diff options
author | Paul Brook <paul@codesourcery.com> | 2009-05-23 00:05:19 +0100 |
---|---|---|
committer | Paul Brook <paul@codesourcery.com> | 2009-05-23 00:13:41 +0100 |
commit | 02e2da45c4601909d5105838323d5c529ec7010b (patch) | |
tree | e9b1099baa55c3f8084110feb28f57ede8d2de3a /hw/qdev.c | |
parent | 4856fcff8af1ba349baaf063af00f5e5d87a99f4 (diff) |
Add common BusState
Implement and use a common device bus state. The main side-effect is
that creating a bus and attaching it to a parent device are no longer
separate operations. For legacy code we allow a NULL parent, but that
should go away eventually.
Also tweak creation code to veriry theat a device in on the right bus.
Signed-off-by: Paul Brook <paul@codesourcery.com>
Diffstat (limited to 'hw/qdev.c')
-rw-r--r-- | hw/qdev.c | 89 |
1 files changed, 53 insertions, 36 deletions
@@ -41,23 +41,18 @@ struct DeviceProperty { struct DeviceType { const char *name; - qdev_initfn init; - void *opaque; + DeviceInfo *info; int size; DeviceType *next; }; -struct ChildBusList { - const char *name; - void *ptr; - ChildBusList *next; -}; +/* This is a nasty hack to allow passing a NULL bus to qdev_create. */ +BusState *main_system_bus; static DeviceType *device_type_list; /* Register a new device type. */ -DeviceType *qdev_register(const char *name, int size, qdev_initfn init, - void *opaque) +void qdev_register(const char *name, int size, DeviceInfo *info) { DeviceType *t; @@ -68,16 +63,13 @@ DeviceType *qdev_register(const char *name, int size, qdev_initfn init, device_type_list = t; t->name = qemu_strdup(name); t->size = size; - t->init = init; - t->opaque = opaque; - - return t; + t->info = info; } /* 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) +DeviceState *qdev_create(BusState *bus, const char *name) { DeviceType *t; DeviceState *dev; @@ -88,14 +80,28 @@ DeviceState *qdev_create(void *bus, const char *name) } } if (!t) { - fprintf(stderr, "Unknown device '%s'\n", name); - exit(1); + hw_error("Unknown device '%s'\n", name); } dev = qemu_mallocz(t->size); dev->name = name; dev->type = t; - dev->bus = bus; + + if (!bus) { + /* ???: This assumes system busses have no additional state. */ + if (!main_system_bus) { + main_system_bus = qbus_create(BUS_TYPE_SYSTEM, sizeof(BusState), + NULL, "main-system-bus"); + } + bus = main_system_bus; + } + if (t->info->bus_type != bus->type) { + /* TODO: Print bus type names. */ + hw_error("Device '%s' on wrong bus type (%d/%d)", name, + t->info->bus_type, bus->type); + } + dev->parent_bus = bus; + LIST_INSERT_HEAD(&bus->children, dev, sibling); return dev; } @@ -104,7 +110,14 @@ DeviceState *qdev_create(void *bus, const char *name) calling this function. */ void qdev_init(DeviceState *dev) { - dev->type->init(dev, dev->type->opaque); + dev->type->info->init(dev, dev->type->info); +} + +/* Unlink device from bus and free the structure. */ +void qdev_free(DeviceState *dev) +{ + LIST_REMOVE(dev, sibling); + free(dev); } static DeviceProperty *create_prop(DeviceState *dev, const char *name) @@ -169,9 +182,9 @@ CharDriverState *qdev_init_chardev(DeviceState *dev) } } -void *qdev_get_bus(DeviceState *dev) +BusState *qdev_get_parent_bus(DeviceState *dev) { - return dev->bus; + return dev->parent_bus; } static DeviceProperty *find_prop(DeviceState *dev, const char *name) @@ -267,30 +280,18 @@ BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type) return drives_table[index].bdrv; } -void *qdev_get_child_bus(DeviceState *dev, const char *name) +BusState *qdev_get_child_bus(DeviceState *dev, const char *name) { - ChildBusList *bus; + BusState *bus; - for (bus = dev->child_bus; bus; bus = bus->next) { + LIST_FOREACH(bus, &dev->child_bus, sibling) { if (strcmp(name, bus->name) == 0) { - return bus->ptr; + return bus; } } return NULL; } -void qdev_attach_child_bus(DeviceState *dev, const char *name, void *bus) -{ - ChildBusList *p; - - assert(!qdev_get_child_bus(dev, name)); - p = qemu_mallocz(sizeof(*p)); - p->name = qemu_strdup(name); - p->ptr = bus; - p->next = dev->child_bus; - dev->child_bus = p; -} - static int next_scsi_bus; /* Create a scsi bus, and attach devices to it. */ @@ -309,3 +310,19 @@ void scsi_bus_new(DeviceState *host, SCSIAttachFn attach) attach(host, drives_table[index].bdrv, unit); } } + +BusState *qbus_create(BusType type, size_t size, + DeviceState *parent, const char *name) +{ + BusState *bus; + + bus = qemu_mallocz(size); + bus->type = type; + bus->parent = parent; + bus->name = qemu_strdup(name); + LIST_INIT(&bus->children); + if (parent) { + LIST_INSERT_HEAD(&parent->child_bus, bus, sibling); + } + return bus; +} |