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
34 struct DeviceProperty
{
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
)
61 assert(size
>= sizeof(DeviceState
));
63 t
= qemu_mallocz(sizeof(DeviceType
));
64 t
->next
= device_type_list
;
66 t
->name
= qemu_strdup(name
);
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
)
79 for (t
= device_type_list
; t
; t
= t
->next
) {
80 if (strcmp(t
->name
, name
) == 0) {
85 hw_error("Unknown device '%s'\n", name
);
88 dev
= qemu_mallocz(t
->size
);
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
);
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
);
124 static DeviceProperty
*create_prop(DeviceState
*dev
, const char *name
,
127 DeviceProperty
*prop
;
129 /* TODO: Check for duplicate properties. */
130 prop
= qemu_mallocz(sizeof(*prop
));
131 prop
->name
= qemu_strdup(name
);
133 prop
->next
= dev
->props
;
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
)
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
++];
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
,
191 DeviceProperty
*prop
;
193 for (prop
= dev
->props
; prop
; prop
= prop
->next
) {
194 if (strcmp(prop
->name
, name
) == 0) {
195 assert (prop
->type
== type
);
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
);
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
);
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
);
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
,
263 NetReceiveIOV
*receive_iov
,
267 NICInfo
*nd
= dev
->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
284 BlockDriverState
*qdev_init_bdrv(DeviceState
*dev
, BlockInterfaceType type
)
286 int unit
= next_block_unit
[type
]++;
289 index
= drive_get_index(type
, 0, unit
);
293 return drives_table
[index
].bdrv
;
296 BusState
*qdev_get_child_bus(DeviceState
*dev
, const char *name
)
300 LIST_FOREACH(bus
, &dev
->child_bus
, sibling
) {
301 if (strcmp(name
, bus
->name
) == 0) {
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
++;
318 for (unit
= 0; unit
< MAX_SCSI_DEVS
; unit
++) {
319 index
= drive_get_index(IF_SCSI
, bus
, unit
);
323 attach(host
, drives_table
[index
].bdrv
, unit
);
327 BusState
*qbus_create(BusType type
, size_t size
,
328 DeviceState
*parent
, const char *name
)
332 bus
= qemu_mallocz(size
);
334 bus
->parent
= parent
;
335 bus
->name
= qemu_strdup(name
);
336 LIST_INIT(&bus
->children
);
338 LIST_INSERT_HEAD(&parent
->child_bus
, bus
, sibling
);
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
;
358 qdev_printf("dev: %s\n", dev
->type
->name
);
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
) {
369 qdev_printf("prop-int %s 0x%" PRIx64
"\n", prop
->name
,
373 qdev_printf("prop-ptr %s\n", prop
->name
);
376 qdev_printf("prop-dev %s %s\n", prop
->name
,
377 ((DeviceState
*)prop
->value
.ptr
)->type
->name
);
380 qdev_printf("prop-unknown%d %s\n", prop
->type
, prop
->name
);
384 switch (dev
->parent_bus
->type
) {
385 case BUS_TYPE_SYSTEM
:
386 sysbus_dev_print(mon
, dev
, indent
);
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
);
402 qdev_printf("type %s\n", bus_type_names
[bus
->type
]);
403 LIST_FOREACH(dev
, &bus
->children
, sibling
) {
404 qdev_print(mon
, dev
, indent
);
409 void do_info_qtree(Monitor
*mon
)
412 qbus_print(mon
, main_system_bus
, 0);