qdev: factor out driver search to qdev_find_info()
[qemu/aliguori-queue.git] / hw / qdev.c
bloba53125dd8889efa0bcb3871c69e37286f5490a9e
1 /*
2 * Dynamic device configuration and creation.
4 * Copyright (c) 2009 CodeSourcery
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.
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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 /* The theory here is that it should be possible to create a machine without
21 knowledge of specific devices. Historically board init routines have
22 passed a bunch of arguments to each device, requiring the board know
23 exactly which device it is dealing with. This file provides an abstract
24 API for device configuration and initialization. Devices will generally
25 inherit from a particular bus (e.g. PCI or I2C) rather than
26 this API directly. */
28 #include "net.h"
29 #include "qdev.h"
30 #include "sysemu.h"
31 #include "monitor.h"
33 /* This is a nasty hack to allow passing a NULL bus to qdev_create. */
34 static BusState *main_system_bus;
35 extern struct BusInfo system_bus_info;
37 static DeviceInfo *device_info_list;
39 /* Register a new device type. */
40 void qdev_register(DeviceInfo *info)
42 assert(info->size >= sizeof(DeviceState));
43 assert(!info->next);
45 info->next = device_info_list;
46 device_info_list = info;
49 static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
51 DeviceInfo *info;
53 for (info = device_info_list; info != NULL; info = info->next) {
54 if (bus_info && info->bus_info != bus_info)
55 continue;
56 if (strcmp(info->name, name) != 0)
57 continue;
58 return info;
60 return NULL;
63 /* Create a new device. This only initializes the device state structure
64 and allows properties to be set. qdev_init should be called to
65 initialize the actual device emulation. */
66 DeviceState *qdev_create(BusState *bus, const char *name)
68 DeviceInfo *info;
69 DeviceState *dev;
71 if (!bus) {
72 if (!main_system_bus) {
73 main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
75 bus = main_system_bus;
78 info = qdev_find_info(bus->info, name);
79 if (!info) {
80 hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
83 dev = qemu_mallocz(info->size);
84 dev->info = info;
85 dev->parent_bus = bus;
86 qdev_prop_set_defaults(dev, dev->info->props);
87 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
88 LIST_INSERT_HEAD(&bus->children, dev, sibling);
89 return dev;
92 /* Initialize a device. Device properties should be set before calling
93 this function. IRQs and MMIO regions should be connected/mapped after
94 calling this function. */
95 void qdev_init(DeviceState *dev)
97 dev->info->init(dev, dev->info);
100 /* Unlink device from bus and free the structure. */
101 void qdev_free(DeviceState *dev)
103 LIST_REMOVE(dev, sibling);
104 free(dev);
107 /* Get a character (serial) device interface. */
108 CharDriverState *qdev_init_chardev(DeviceState *dev)
110 static int next_serial;
111 static int next_virtconsole;
112 /* FIXME: This is a nasty hack that needs to go away. */
113 if (strncmp(dev->info->name, "virtio", 6) == 0) {
114 return virtcon_hds[next_virtconsole++];
115 } else {
116 return serial_hds[next_serial++];
120 BusState *qdev_get_parent_bus(DeviceState *dev)
122 return dev->parent_bus;
125 void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
127 assert(dev->num_gpio_in == 0);
128 dev->num_gpio_in = n;
129 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
132 void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
134 assert(dev->num_gpio_out == 0);
135 dev->num_gpio_out = n;
136 dev->gpio_out = pins;
139 qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
141 assert(n >= 0 && n < dev->num_gpio_in);
142 return dev->gpio_in[n];
145 void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
147 assert(n >= 0 && n < dev->num_gpio_out);
148 dev->gpio_out[n] = pin;
151 VLANClientState *qdev_get_vlan_client(DeviceState *dev,
152 NetCanReceive *can_receive,
153 NetReceive *receive,
154 NetReceiveIOV *receive_iov,
155 NetCleanup *cleanup,
156 void *opaque)
158 NICInfo *nd = dev->nd;
159 assert(nd);
160 nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
161 receive, receive_iov, cleanup, opaque);
162 return nd->vc;
166 void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
168 memcpy(macaddr, dev->nd->macaddr, 6);
171 static int next_block_unit[IF_COUNT];
173 /* Get a block device. This should only be used for single-drive devices
174 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
175 appropriate bus. */
176 BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
178 int unit = next_block_unit[type]++;
179 int index;
181 index = drive_get_index(type, 0, unit);
182 if (index == -1) {
183 return NULL;
185 return drives_table[index].bdrv;
188 BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
190 BusState *bus;
192 LIST_FOREACH(bus, &dev->child_bus, sibling) {
193 if (strcmp(name, bus->name) == 0) {
194 return bus;
197 return NULL;
200 static int next_scsi_bus;
202 /* Create a scsi bus, and attach devices to it. */
203 /* TODO: Actually create a scsi bus for hotplug to use. */
204 void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
206 int bus = next_scsi_bus++;
207 int unit;
208 int index;
210 for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
211 index = drive_get_index(IF_SCSI, bus, unit);
212 if (index == -1) {
213 continue;
215 attach(host, drives_table[index].bdrv, unit);
219 BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
221 BusState *bus;
223 bus = qemu_mallocz(info->size);
224 bus->info = info;
225 bus->parent = parent;
226 bus->name = qemu_strdup(name);
227 LIST_INIT(&bus->children);
228 if (parent) {
229 LIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
231 return bus;
234 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
235 static void qbus_print(Monitor *mon, BusState *bus, int indent);
237 static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
238 const char *prefix, int indent)
240 char buf[64];
242 if (!props)
243 return;
244 while (props->name) {
245 if (props->info->print) {
246 props->info->print(dev, props, buf, sizeof(buf));
247 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
249 props++;
253 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
255 BusState *child;
256 qdev_printf("dev: %s\n", dev->info->name);
257 indent += 2;
258 if (dev->num_gpio_in) {
259 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
261 if (dev->num_gpio_out) {
262 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
264 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
265 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
266 if (dev->parent_bus->info->print_dev)
267 dev->parent_bus->info->print_dev(mon, dev, indent);
268 LIST_FOREACH(child, &dev->child_bus, sibling) {
269 qbus_print(mon, child, indent);
273 static void qbus_print(Monitor *mon, BusState *bus, int indent)
275 struct DeviceState *dev;
277 qdev_printf("bus: %s\n", bus->name);
278 indent += 2;
279 qdev_printf("type %s\n", bus->info->name);
280 LIST_FOREACH(dev, &bus->children, sibling) {
281 qdev_print(mon, dev, indent);
284 #undef qdev_printf
286 void do_info_qtree(Monitor *mon)
288 if (main_system_bus)
289 qbus_print(mon, main_system_bus, 0);