Refactor common code using a list
[qemu-kvm/fedora.git] / hw / qdev.c
blob001c74ce0e69a72264c13019b6a4cbb2e7140a81
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 /* first check device names */
54 for (info = device_info_list; info != NULL; info = info->next) {
55 if (bus_info && info->bus_info != bus_info)
56 continue;
57 if (strcmp(info->name, name) != 0)
58 continue;
59 return info;
62 /* failing that check the aliases */
63 for (info = device_info_list; info != NULL; info = info->next) {
64 if (bus_info && info->bus_info != bus_info)
65 continue;
66 if (!info->alias)
67 continue;
68 if (strcmp(info->alias, name) != 0)
69 continue;
70 return info;
72 return NULL;
75 /* Create a new device. This only initializes the device state structure
76 and allows properties to be set. qdev_init should be called to
77 initialize the actual device emulation. */
78 DeviceState *qdev_create(BusState *bus, const char *name)
80 DeviceInfo *info;
81 DeviceState *dev;
83 if (!bus) {
84 if (!main_system_bus) {
85 main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
87 bus = main_system_bus;
90 info = qdev_find_info(bus->info, name);
91 if (!info) {
92 hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
95 dev = qemu_mallocz(info->size);
96 dev->info = info;
97 dev->parent_bus = bus;
98 qdev_prop_set_defaults(dev, dev->info->props);
99 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
100 qdev_prop_set_compat(dev);
101 LIST_INSERT_HEAD(&bus->children, dev, sibling);
102 return dev;
105 /* Initialize a device. Device properties should be set before calling
106 this function. IRQs and MMIO regions should be connected/mapped after
107 calling this function. */
108 void qdev_init(DeviceState *dev)
110 dev->info->init(dev, dev->info);
113 /* Unlink device from bus and free the structure. */
114 void qdev_free(DeviceState *dev)
116 LIST_REMOVE(dev, sibling);
117 qemu_free(dev->id);
118 qemu_free(dev);
121 /* Get a character (serial) device interface. */
122 CharDriverState *qdev_init_chardev(DeviceState *dev)
124 static int next_serial;
125 static int next_virtconsole;
126 /* FIXME: This is a nasty hack that needs to go away. */
127 if (strncmp(dev->info->name, "virtio", 6) == 0) {
128 return virtcon_hds[next_virtconsole++];
129 } else {
130 return serial_hds[next_serial++];
134 BusState *qdev_get_parent_bus(DeviceState *dev)
136 return dev->parent_bus;
139 void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
141 assert(dev->num_gpio_in == 0);
142 dev->num_gpio_in = n;
143 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
146 void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
148 assert(dev->num_gpio_out == 0);
149 dev->num_gpio_out = n;
150 dev->gpio_out = pins;
153 qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
155 assert(n >= 0 && n < dev->num_gpio_in);
156 return dev->gpio_in[n];
159 void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
161 assert(n >= 0 && n < dev->num_gpio_out);
162 dev->gpio_out[n] = pin;
165 VLANClientState *qdev_get_vlan_client(DeviceState *dev,
166 NetCanReceive *can_receive,
167 NetReceive *receive,
168 NetReceiveIOV *receive_iov,
169 NetCleanup *cleanup,
170 void *opaque)
172 NICInfo *nd = dev->nd;
173 assert(nd);
174 nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
175 receive, receive_iov, cleanup, opaque);
176 return nd->vc;
180 void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
182 memcpy(macaddr, dev->nd->macaddr, 6);
185 static int next_block_unit[IF_COUNT];
187 /* Get a block device. This should only be used for single-drive devices
188 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
189 appropriate bus. */
190 BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
192 int unit = next_block_unit[type]++;
193 int index;
195 index = drive_get_index(type, 0, unit);
196 if (index == -1) {
197 return NULL;
199 return drives_table[index].bdrv;
202 BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
204 BusState *bus;
206 LIST_FOREACH(bus, &dev->child_bus, sibling) {
207 if (strcmp(name, bus->name) == 0) {
208 return bus;
211 return NULL;
214 static int next_scsi_bus;
216 /* Create a scsi bus, and attach devices to it. */
217 /* TODO: Actually create a scsi bus for hotplug to use. */
218 void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
220 int bus = next_scsi_bus++;
221 int unit;
222 int index;
224 for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
225 index = drive_get_index(IF_SCSI, bus, unit);
226 if (index == -1) {
227 continue;
229 attach(host, drives_table[index].bdrv, unit);
233 BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
235 BusState *bus;
237 bus = qemu_mallocz(info->size);
238 bus->info = info;
239 bus->parent = parent;
240 bus->name = qemu_strdup(name);
241 LIST_INIT(&bus->children);
242 if (parent) {
243 LIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
245 return bus;
248 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
249 static void qbus_print(Monitor *mon, BusState *bus, int indent);
251 static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
252 const char *prefix, int indent)
254 char buf[64];
256 if (!props)
257 return;
258 while (props->name) {
259 if (props->info->print) {
260 props->info->print(dev, props, buf, sizeof(buf));
261 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
263 props++;
267 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
269 BusState *child;
270 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
271 dev->id ? dev->id : "");
272 indent += 2;
273 if (dev->num_gpio_in) {
274 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
276 if (dev->num_gpio_out) {
277 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
279 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
280 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
281 if (dev->parent_bus->info->print_dev)
282 dev->parent_bus->info->print_dev(mon, dev, indent);
283 LIST_FOREACH(child, &dev->child_bus, sibling) {
284 qbus_print(mon, child, indent);
288 static void qbus_print(Monitor *mon, BusState *bus, int indent)
290 struct DeviceState *dev;
292 qdev_printf("bus: %s\n", bus->name);
293 indent += 2;
294 qdev_printf("type %s\n", bus->info->name);
295 LIST_FOREACH(dev, &bus->children, sibling) {
296 qdev_print(mon, dev, indent);
299 #undef qdev_printf
301 void do_info_qtree(Monitor *mon)
303 if (main_system_bus)
304 qbus_print(mon, main_system_bus, 0);