net: add qemu_send_packet_async()
[qemu-kvm/markmc.git] / hw / qdev.c
blobbab351c12fdc7e0ddfb411bfdd27d270970baaa7
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, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
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. */
29 #include "net.h"
30 #include "qdev.h"
31 #include "sysemu.h"
32 #include "monitor.h"
34 struct DeviceProperty {
35 const char *name;
36 DevicePropType type;
37 union {
38 uint64_t i;
39 void *ptr;
40 } value;
41 DeviceProperty *next;
44 struct DeviceType {
45 const char *name;
46 DeviceInfo *info;
47 int size;
48 DeviceType *next;
51 /* This is a nasty hack to allow passing a NULL bus to qdev_create. */
52 BusState *main_system_bus;
54 static DeviceType *device_type_list;
56 /* Register a new device type. */
57 void qdev_register(const char *name, int size, DeviceInfo *info)
59 DeviceType *t;
61 assert(size >= sizeof(DeviceState));
63 t = qemu_mallocz(sizeof(DeviceType));
64 t->next = device_type_list;
65 device_type_list = t;
66 t->name = qemu_strdup(name);
67 t->size = size;
68 t->info = info;
71 /* Create a new device. This only initializes the device state structure
72 and allows properties to be set. qdev_init should be called to
73 initialize the actual device emulation. */
74 DeviceState *qdev_create(BusState *bus, const char *name)
76 DeviceType *t;
77 DeviceState *dev;
79 for (t = device_type_list; t; t = t->next) {
80 if (strcmp(t->name, name) == 0) {
81 break;
84 if (!t) {
85 hw_error("Unknown device '%s'\n", name);
88 dev = qemu_mallocz(t->size);
89 dev->type = t;
91 if (!bus) {
92 /* ???: This assumes system busses have no additional state. */
93 if (!main_system_bus) {
94 main_system_bus = qbus_create(BUS_TYPE_SYSTEM, sizeof(BusState),
95 NULL, "main-system-bus");
97 bus = main_system_bus;
99 if (t->info->bus_type != bus->type) {
100 /* TODO: Print bus type names. */
101 hw_error("Device '%s' on wrong bus type (%d/%d)", name,
102 t->info->bus_type, bus->type);
104 dev->parent_bus = bus;
105 LIST_INSERT_HEAD(&bus->children, dev, sibling);
106 return dev;
109 /* Initialize a device. Device properties should be set before calling
110 this function. IRQs and MMIO regions should be connected/mapped after
111 calling this function. */
112 void qdev_init(DeviceState *dev)
114 dev->type->info->init(dev, dev->type->info);
117 /* Unlink device from bus and free the structure. */
118 void qdev_free(DeviceState *dev)
120 LIST_REMOVE(dev, sibling);
121 free(dev);
124 static DeviceProperty *create_prop(DeviceState *dev, const char *name,
125 DevicePropType type)
127 DeviceProperty *prop;
129 /* TODO: Check for duplicate properties. */
130 prop = qemu_mallocz(sizeof(*prop));
131 prop->name = qemu_strdup(name);
132 prop->type = type;
133 prop->next = dev->props;
134 dev->props = prop;
136 return prop;
139 void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value)
141 DeviceProperty *prop;
143 prop = create_prop(dev, name, PROP_TYPE_INT);
144 prop->value.i = value;
147 void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value)
149 DeviceProperty *prop;
151 prop = create_prop(dev, name, PROP_TYPE_DEV);
152 prop->value.ptr = value;
155 void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value)
157 DeviceProperty *prop;
159 prop = create_prop(dev, name, PROP_TYPE_PTR);
160 prop->value.ptr = value;
163 void qdev_set_netdev(DeviceState *dev, NICInfo *nd)
165 assert(!dev->nd);
166 dev->nd = nd;
170 /* Get a character (serial) device interface. */
171 CharDriverState *qdev_init_chardev(DeviceState *dev)
173 static int next_serial;
174 static int next_virtconsole;
175 /* FIXME: This is a nasty hack that needs to go away. */
176 if (strncmp(dev->type->name, "virtio", 6) == 0) {
177 return virtcon_hds[next_virtconsole++];
178 } else {
179 return serial_hds[next_serial++];
183 BusState *qdev_get_parent_bus(DeviceState *dev)
185 return dev->parent_bus;
188 static DeviceProperty *find_prop(DeviceState *dev, const char *name,
189 DevicePropType type)
191 DeviceProperty *prop;
193 for (prop = dev->props; prop; prop = prop->next) {
194 if (strcmp(prop->name, name) == 0) {
195 assert (prop->type == type);
196 return prop;
199 return NULL;
202 uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def)
204 DeviceProperty *prop;
206 prop = find_prop(dev, name, PROP_TYPE_INT);
207 if (!prop) {
208 return def;
211 return prop->value.i;
214 void *qdev_get_prop_ptr(DeviceState *dev, const char *name)
216 DeviceProperty *prop;
218 prop = find_prop(dev, name, PROP_TYPE_PTR);
219 assert(prop);
220 return prop->value.ptr;
223 DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name)
225 DeviceProperty *prop;
227 prop = find_prop(dev, name, PROP_TYPE_DEV);
228 if (!prop) {
229 return NULL;
231 return prop->value.ptr;
234 void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
236 assert(dev->num_gpio_in == 0);
237 dev->num_gpio_in = n;
238 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
241 void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
243 assert(dev->num_gpio_out == 0);
244 dev->num_gpio_out = n;
245 dev->gpio_out = pins;
248 qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
250 assert(n >= 0 && n < dev->num_gpio_in);
251 return dev->gpio_in[n];
254 void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
256 assert(n >= 0 && n < dev->num_gpio_out);
257 dev->gpio_out[n] = pin;
260 VLANClientState *qdev_get_vlan_client(DeviceState *dev,
261 NetCanReceive *can_receive,
262 NetReceive *receive,
263 NetReceiveIOV *receive_iov,
264 NetCleanup *cleanup,
265 void *opaque)
267 NICInfo *nd = dev->nd;
268 assert(nd);
269 return qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
270 receive, receive_iov, cleanup, opaque);
274 void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
276 memcpy(macaddr, dev->nd->macaddr, 6);
279 static int next_block_unit[IF_COUNT];
281 /* Get a block device. This should only be used for single-drive devices
282 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
283 appropriate bus. */
284 BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
286 int unit = next_block_unit[type]++;
287 int index;
289 index = drive_get_index(type, 0, unit);
290 if (index == -1) {
291 return NULL;
293 return drives_table[index].bdrv;
296 BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
298 BusState *bus;
300 LIST_FOREACH(bus, &dev->child_bus, sibling) {
301 if (strcmp(name, bus->name) == 0) {
302 return bus;
305 return NULL;
308 static int next_scsi_bus;
310 /* Create a scsi bus, and attach devices to it. */
311 /* TODO: Actually create a scsi bus for hotplug to use. */
312 void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
314 int bus = next_scsi_bus++;
315 int unit;
316 int index;
318 for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
319 index = drive_get_index(IF_SCSI, bus, unit);
320 if (index == -1) {
321 continue;
323 attach(host, drives_table[index].bdrv, unit);
327 BusState *qbus_create(BusType type, size_t size,
328 DeviceState *parent, const char *name)
330 BusState *bus;
332 bus = qemu_mallocz(size);
333 bus->type = type;
334 bus->parent = parent;
335 bus->name = qemu_strdup(name);
336 LIST_INIT(&bus->children);
337 if (parent) {
338 LIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
340 return bus;
343 static const char *bus_type_names[] = {
344 [ BUS_TYPE_SYSTEM ] = "System",
345 [ BUS_TYPE_PCI ] = "PCI",
346 [ BUS_TYPE_SCSI ] = "SCSI",
347 [ BUS_TYPE_I2C ] = "I2C",
348 [ BUS_TYPE_SSI ] = "SSI",
351 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
352 static void qbus_print(Monitor *mon, BusState *bus, int indent);
354 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
356 DeviceProperty *prop;
357 BusState *child;
358 qdev_printf("dev: %s\n", dev->type->name);
359 indent += 2;
360 if (dev->num_gpio_in) {
361 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
363 if (dev->num_gpio_out) {
364 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
366 for (prop = dev->props; prop; prop = prop->next) {
367 switch (prop->type) {
368 case PROP_TYPE_INT:
369 qdev_printf("prop-int %s 0x%" PRIx64 "\n", prop->name,
370 prop->value.i);
371 break;
372 case PROP_TYPE_PTR:
373 qdev_printf("prop-ptr %s\n", prop->name);
374 break;
375 case PROP_TYPE_DEV:
376 qdev_printf("prop-dev %s %s\n", prop->name,
377 ((DeviceState *)prop->value.ptr)->type->name);
378 break;
379 default:
380 qdev_printf("prop-unknown%d %s\n", prop->type, prop->name);
381 break;
384 switch (dev->parent_bus->type) {
385 case BUS_TYPE_SYSTEM:
386 sysbus_dev_print(mon, dev, indent);
387 break;
388 default:
389 break;
391 LIST_FOREACH(child, &dev->child_bus, sibling) {
392 qbus_print(mon, child, indent);
396 static void qbus_print(Monitor *mon, BusState *bus, int indent)
398 struct DeviceState *dev;
400 qdev_printf("bus: %s\n", bus->name);
401 indent += 2;
402 qdev_printf("type %s\n", bus_type_names[bus->type]);
403 LIST_FOREACH(dev, &bus->children, sibling) {
404 qdev_print(mon, dev, indent);
407 #undef qdev_printf
409 void do_info_qtree(Monitor *mon)
411 if (main_system_bus)
412 qbus_print(mon, main_system_bus, 0);