Revision 02e2da45 hw/qdev.c
b/hw/qdev.c | ||
---|---|---|
41 | 41 |
|
42 | 42 |
struct DeviceType { |
43 | 43 |
const char *name; |
44 |
qdev_initfn init; |
|
45 |
void *opaque; |
|
44 |
DeviceInfo *info; |
|
46 | 45 |
int size; |
47 | 46 |
DeviceType *next; |
48 | 47 |
}; |
49 | 48 |
|
50 |
struct ChildBusList { |
|
51 |
const char *name; |
|
52 |
void *ptr; |
|
53 |
ChildBusList *next; |
|
54 |
}; |
|
49 |
/* This is a nasty hack to allow passing a NULL bus to qdev_create. */ |
|
50 |
BusState *main_system_bus; |
|
55 | 51 |
|
56 | 52 |
static DeviceType *device_type_list; |
57 | 53 |
|
58 | 54 |
/* Register a new device type. */ |
59 |
DeviceType *qdev_register(const char *name, int size, qdev_initfn init, |
|
60 |
void *opaque) |
|
55 |
void qdev_register(const char *name, int size, DeviceInfo *info) |
|
61 | 56 |
{ |
62 | 57 |
DeviceType *t; |
63 | 58 |
|
... | ... | |
68 | 63 |
device_type_list = t; |
69 | 64 |
t->name = qemu_strdup(name); |
70 | 65 |
t->size = size; |
71 |
t->init = init; |
|
72 |
t->opaque = opaque; |
|
73 |
|
|
74 |
return t; |
|
66 |
t->info = info; |
|
75 | 67 |
} |
76 | 68 |
|
77 | 69 |
/* Create a new device. This only initializes the device state structure |
78 | 70 |
and allows properties to be set. qdev_init should be called to |
79 | 71 |
initialize the actual device emulation. */ |
80 |
DeviceState *qdev_create(void *bus, const char *name)
|
|
72 |
DeviceState *qdev_create(BusState *bus, const char *name)
|
|
81 | 73 |
{ |
82 | 74 |
DeviceType *t; |
83 | 75 |
DeviceState *dev; |
... | ... | |
88 | 80 |
} |
89 | 81 |
} |
90 | 82 |
if (!t) { |
91 |
fprintf(stderr, "Unknown device '%s'\n", name); |
|
92 |
exit(1); |
|
83 |
hw_error("Unknown device '%s'\n", name); |
|
93 | 84 |
} |
94 | 85 |
|
95 | 86 |
dev = qemu_mallocz(t->size); |
96 | 87 |
dev->name = name; |
97 | 88 |
dev->type = t; |
98 |
dev->bus = bus; |
|
89 |
|
|
90 |
if (!bus) { |
|
91 |
/* ???: This assumes system busses have no additional state. */ |
|
92 |
if (!main_system_bus) { |
|
93 |
main_system_bus = qbus_create(BUS_TYPE_SYSTEM, sizeof(BusState), |
|
94 |
NULL, "main-system-bus"); |
|
95 |
} |
|
96 |
bus = main_system_bus; |
|
97 |
} |
|
98 |
if (t->info->bus_type != bus->type) { |
|
99 |
/* TODO: Print bus type names. */ |
|
100 |
hw_error("Device '%s' on wrong bus type (%d/%d)", name, |
|
101 |
t->info->bus_type, bus->type); |
|
102 |
} |
|
103 |
dev->parent_bus = bus; |
|
104 |
LIST_INSERT_HEAD(&bus->children, dev, sibling); |
|
99 | 105 |
return dev; |
100 | 106 |
} |
101 | 107 |
|
... | ... | |
104 | 110 |
calling this function. */ |
105 | 111 |
void qdev_init(DeviceState *dev) |
106 | 112 |
{ |
107 |
dev->type->init(dev, dev->type->opaque); |
|
113 |
dev->type->info->init(dev, dev->type->info); |
|
114 |
} |
|
115 |
|
|
116 |
/* Unlink device from bus and free the structure. */ |
|
117 |
void qdev_free(DeviceState *dev) |
|
118 |
{ |
|
119 |
LIST_REMOVE(dev, sibling); |
|
120 |
free(dev); |
|
108 | 121 |
} |
109 | 122 |
|
110 | 123 |
static DeviceProperty *create_prop(DeviceState *dev, const char *name) |
... | ... | |
169 | 182 |
} |
170 | 183 |
} |
171 | 184 |
|
172 |
void *qdev_get_bus(DeviceState *dev)
|
|
185 |
BusState *qdev_get_parent_bus(DeviceState *dev)
|
|
173 | 186 |
{ |
174 |
return dev->bus; |
|
187 |
return dev->parent_bus;
|
|
175 | 188 |
} |
176 | 189 |
|
177 | 190 |
static DeviceProperty *find_prop(DeviceState *dev, const char *name) |
... | ... | |
267 | 280 |
return drives_table[index].bdrv; |
268 | 281 |
} |
269 | 282 |
|
270 |
void *qdev_get_child_bus(DeviceState *dev, const char *name)
|
|
283 |
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
|
|
271 | 284 |
{ |
272 |
ChildBusList *bus;
|
|
285 |
BusState *bus;
|
|
273 | 286 |
|
274 |
for (bus = dev->child_bus; bus; bus = bus->next) {
|
|
287 |
LIST_FOREACH(bus, &dev->child_bus, sibling) {
|
|
275 | 288 |
if (strcmp(name, bus->name) == 0) { |
276 |
return bus->ptr;
|
|
289 |
return bus; |
|
277 | 290 |
} |
278 | 291 |
} |
279 | 292 |
return NULL; |
280 | 293 |
} |
281 | 294 |
|
282 |
void qdev_attach_child_bus(DeviceState *dev, const char *name, void *bus) |
|
283 |
{ |
|
284 |
ChildBusList *p; |
|
285 |
|
|
286 |
assert(!qdev_get_child_bus(dev, name)); |
|
287 |
p = qemu_mallocz(sizeof(*p)); |
|
288 |
p->name = qemu_strdup(name); |
|
289 |
p->ptr = bus; |
|
290 |
p->next = dev->child_bus; |
|
291 |
dev->child_bus = p; |
|
292 |
} |
|
293 |
|
|
294 | 295 |
static int next_scsi_bus; |
295 | 296 |
|
296 | 297 |
/* Create a scsi bus, and attach devices to it. */ |
... | ... | |
309 | 310 |
attach(host, drives_table[index].bdrv, unit); |
310 | 311 |
} |
311 | 312 |
} |
313 |
|
|
314 |
BusState *qbus_create(BusType type, size_t size, |
|
315 |
DeviceState *parent, const char *name) |
|
316 |
{ |
|
317 |
BusState *bus; |
|
318 |
|
|
319 |
bus = qemu_mallocz(size); |
|
320 |
bus->type = type; |
|
321 |
bus->parent = parent; |
|
322 |
bus->name = qemu_strdup(name); |
|
323 |
LIST_INIT(&bus->children); |
|
324 |
if (parent) { |
|
325 |
LIST_INSERT_HEAD(&parent->child_bus, bus, sibling); |
|
326 |
} |
|
327 |
return bus; |
|
328 |
} |
Also available in: Unified diff