]> git.proxmox.com Git - qemu.git/blame - hw/qdev.c
net: re-name vc->fd_read() to vc->receive()
[qemu.git] / hw / qdev.c
CommitLineData
aae9460e
PB
1/*
2 * Dynamic device configuration and creation.
3 *
4 * Copyright (c) 2009 CodeSourcery
5 *
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.
10 *
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.
15 *
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
19 */
20
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. */
28
9d07d757 29#include "net.h"
aae9460e
PB
30#include "qdev.h"
31#include "sysemu.h"
cae4956e 32#include "monitor.h"
aae9460e
PB
33
34struct DeviceProperty {
35 const char *name;
1431b6a1 36 DevicePropType type;
aae9460e 37 union {
89a740e1 38 uint64_t i;
aae9460e
PB
39 void *ptr;
40 } value;
41 DeviceProperty *next;
42};
43
44struct DeviceType {
45 const char *name;
02e2da45 46 DeviceInfo *info;
aae9460e
PB
47 int size;
48 DeviceType *next;
49};
50
02e2da45
PB
51/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
52BusState *main_system_bus;
4d6ae674 53
aae9460e
PB
54static DeviceType *device_type_list;
55
56/* Register a new device type. */
02e2da45 57void qdev_register(const char *name, int size, DeviceInfo *info)
aae9460e
PB
58{
59 DeviceType *t;
60
61 assert(size >= sizeof(DeviceState));
62
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;
02e2da45 68 t->info = info;
aae9460e
PB
69}
70
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. */
02e2da45 74DeviceState *qdev_create(BusState *bus, const char *name)
aae9460e
PB
75{
76 DeviceType *t;
77 DeviceState *dev;
78
79 for (t = device_type_list; t; t = t->next) {
80 if (strcmp(t->name, name) == 0) {
81 break;
82 }
83 }
84 if (!t) {
02e2da45 85 hw_error("Unknown device '%s'\n", name);
aae9460e
PB
86 }
87
88 dev = qemu_mallocz(t->size);
aae9460e 89 dev->type = t;
02e2da45
PB
90
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");
96 }
97 bus = main_system_bus;
98 }
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);
103 }
104 dev->parent_bus = bus;
105 LIST_INSERT_HEAD(&bus->children, dev, sibling);
aae9460e
PB
106 return dev;
107}
108
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. */
112void qdev_init(DeviceState *dev)
113{
02e2da45
PB
114 dev->type->info->init(dev, dev->type->info);
115}
116
117/* Unlink device from bus and free the structure. */
118void qdev_free(DeviceState *dev)
119{
120 LIST_REMOVE(dev, sibling);
121 free(dev);
aae9460e
PB
122}
123
1431b6a1
PB
124static DeviceProperty *create_prop(DeviceState *dev, const char *name,
125 DevicePropType type)
aae9460e
PB
126{
127 DeviceProperty *prop;
128
129 /* TODO: Check for duplicate properties. */
130 prop = qemu_mallocz(sizeof(*prop));
131 prop->name = qemu_strdup(name);
1431b6a1 132 prop->type = type;
aae9460e
PB
133 prop->next = dev->props;
134 dev->props = prop;
135
136 return prop;
137}
138
89a740e1 139void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value)
aae9460e
PB
140{
141 DeviceProperty *prop;
142
1431b6a1 143 prop = create_prop(dev, name, PROP_TYPE_INT);
aae9460e
PB
144 prop->value.i = value;
145}
146
1431b6a1
PB
147void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value)
148{
149 DeviceProperty *prop;
150
151 prop = create_prop(dev, name, PROP_TYPE_DEV);
152 prop->value.ptr = value;
153}
154
aae9460e
PB
155void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value)
156{
157 DeviceProperty *prop;
158
db241f40 159 prop = create_prop(dev, name, PROP_TYPE_PTR);
aae9460e
PB
160 prop->value.ptr = value;
161}
162
9d07d757
PB
163void qdev_set_netdev(DeviceState *dev, NICInfo *nd)
164{
165 assert(!dev->nd);
166 dev->nd = nd;
167}
168
aae9460e 169
aae9460e
PB
170/* Get a character (serial) device interface. */
171CharDriverState *qdev_init_chardev(DeviceState *dev)
172{
173 static int next_serial;
174 static int next_virtconsole;
175 /* FIXME: This is a nasty hack that needs to go away. */
aca312af 176 if (strncmp(dev->type->name, "virtio", 6) == 0) {
aae9460e
PB
177 return virtcon_hds[next_virtconsole++];
178 } else {
179 return serial_hds[next_serial++];
180 }
181}
182
02e2da45 183BusState *qdev_get_parent_bus(DeviceState *dev)
aae9460e 184{
02e2da45 185 return dev->parent_bus;
aae9460e
PB
186}
187
1431b6a1
PB
188static DeviceProperty *find_prop(DeviceState *dev, const char *name,
189 DevicePropType type)
aae9460e
PB
190{
191 DeviceProperty *prop;
192
193 for (prop = dev->props; prop; prop = prop->next) {
194 if (strcmp(prop->name, name) == 0) {
1431b6a1 195 assert (prop->type == type);
aae9460e
PB
196 return prop;
197 }
198 }
199 return NULL;
200}
201
202uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def)
203{
204 DeviceProperty *prop;
205
1431b6a1
PB
206 prop = find_prop(dev, name, PROP_TYPE_INT);
207 if (!prop) {
aae9460e 208 return def;
1431b6a1 209 }
aae9460e
PB
210
211 return prop->value.i;
212}
213
214void *qdev_get_prop_ptr(DeviceState *dev, const char *name)
215{
216 DeviceProperty *prop;
217
1431b6a1 218 prop = find_prop(dev, name, PROP_TYPE_PTR);
aae9460e
PB
219 assert(prop);
220 return prop->value.ptr;
221}
222
1431b6a1
PB
223DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name)
224{
225 DeviceProperty *prop;
226
227 prop = find_prop(dev, name, PROP_TYPE_DEV);
228 if (!prop) {
229 return NULL;
230 }
231 return prop->value.ptr;
232}
233
aae9460e
PB
234void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
235{
236 assert(dev->num_gpio_in == 0);
237 dev->num_gpio_in = n;
238 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
239}
240
241void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
242{
243 assert(dev->num_gpio_out == 0);
244 dev->num_gpio_out = n;
245 dev->gpio_out = pins;
246}
247
248qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
249{
250 assert(n >= 0 && n < dev->num_gpio_in);
251 return dev->gpio_in[n];
252}
253
254void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
255{
256 assert(n >= 0 && n < dev->num_gpio_out);
257 dev->gpio_out[n] = pin;
258}
259
9d07d757 260VLANClientState *qdev_get_vlan_client(DeviceState *dev,
cda9046b
MM
261 NetCanReceive *can_receive,
262 NetReceive *receive,
263 NetReceiveIOV *receive_iov,
9d07d757
PB
264 NetCleanup *cleanup,
265 void *opaque)
266{
267 NICInfo *nd = dev->nd;
268 assert(nd);
cda9046b
MM
269 return qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
270 receive, receive_iov, cleanup, opaque);
9d07d757
PB
271}
272
273
274void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
275{
276 memcpy(macaddr, dev->nd->macaddr, 6);
277}
278
aae9460e
PB
279static int next_block_unit[IF_COUNT];
280
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. */
284BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
285{
286 int unit = next_block_unit[type]++;
287 int index;
288
289 index = drive_get_index(type, 0, unit);
290 if (index == -1) {
291 return NULL;
292 }
293 return drives_table[index].bdrv;
294}
4d6ae674 295
02e2da45 296BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
4d6ae674 297{
02e2da45 298 BusState *bus;
4d6ae674 299
02e2da45 300 LIST_FOREACH(bus, &dev->child_bus, sibling) {
4d6ae674 301 if (strcmp(name, bus->name) == 0) {
02e2da45 302 return bus;
4d6ae674
PB
303 }
304 }
305 return NULL;
306}
307
6f68ecb2
PB
308static int next_scsi_bus;
309
310/* Create a scsi bus, and attach devices to it. */
311/* TODO: Actually create a scsi bus for hotplug to use. */
312void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
313{
314 int bus = next_scsi_bus++;
315 int unit;
316 int index;
317
318 for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
319 index = drive_get_index(IF_SCSI, bus, unit);
320 if (index == -1) {
321 continue;
322 }
323 attach(host, drives_table[index].bdrv, unit);
324 }
325}
02e2da45
PB
326
327BusState *qbus_create(BusType type, size_t size,
328 DeviceState *parent, const char *name)
329{
330 BusState *bus;
331
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);
339 }
340 return bus;
341}
cae4956e
GH
342
343static const char *bus_type_names[] = {
98ba2632
GH
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",
cae4956e
GH
349};
350
351#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
352static void qbus_print(Monitor *mon, BusState *bus, int indent);
353
354static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
355{
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);
362 }
363 if (dev->num_gpio_out) {
364 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
365 }
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;
382 }
383 }
384 switch (dev->parent_bus->type) {
385 case BUS_TYPE_SYSTEM:
386 sysbus_dev_print(mon, dev, indent);
387 break;
388 default:
389 break;
390 }
391 LIST_FOREACH(child, &dev->child_bus, sibling) {
392 qbus_print(mon, child, indent);
393 }
394}
395
396static void qbus_print(Monitor *mon, BusState *bus, int indent)
397{
398 struct DeviceState *dev;
399
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);
405 }
406}
407#undef qdev_printf
408
409void do_info_qtree(Monitor *mon)
410{
411 if (main_system_bus)
412 qbus_print(mon, main_system_bus, 0);
413}