]>
git.proxmox.com Git - qemu.git/blob - hw/qdev.c
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
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
));
45 info
->next
= device_info_list
;
46 device_info_list
= info
;
49 /* Create a new device. This only initializes the device state structure
50 and allows properties to be set. qdev_init should be called to
51 initialize the actual device emulation. */
52 DeviceState
*qdev_create(BusState
*bus
, const char *name
)
58 if (!main_system_bus
) {
59 main_system_bus
= qbus_create(&system_bus_info
, NULL
, "main-system-bus");
61 bus
= main_system_bus
;
64 for (info
= device_info_list
; info
!= NULL
; info
= info
->next
) {
65 if (info
->bus_info
!= bus
->info
)
67 if (strcmp(info
->name
, name
) != 0)
72 hw_error("Unknown device '%s' for bus '%s'\n", name
, bus
->info
->name
);
75 dev
= qemu_mallocz(info
->size
);
77 dev
->parent_bus
= bus
;
78 qdev_prop_set_defaults(dev
, dev
->info
->props
);
79 qdev_prop_set_defaults(dev
, dev
->parent_bus
->info
->props
);
80 LIST_INSERT_HEAD(&bus
->children
, dev
, sibling
);
84 /* Initialize a device. Device properties should be set before calling
85 this function. IRQs and MMIO regions should be connected/mapped after
86 calling this function. */
87 void qdev_init(DeviceState
*dev
)
89 dev
->info
->init(dev
, dev
->info
);
92 /* Unlink device from bus and free the structure. */
93 void qdev_free(DeviceState
*dev
)
95 LIST_REMOVE(dev
, sibling
);
99 /* Get a character (serial) device interface. */
100 CharDriverState
*qdev_init_chardev(DeviceState
*dev
)
102 static int next_serial
;
103 static int next_virtconsole
;
104 /* FIXME: This is a nasty hack that needs to go away. */
105 if (strncmp(dev
->info
->name
, "virtio", 6) == 0) {
106 return virtcon_hds
[next_virtconsole
++];
108 return serial_hds
[next_serial
++];
112 BusState
*qdev_get_parent_bus(DeviceState
*dev
)
114 return dev
->parent_bus
;
117 void qdev_init_gpio_in(DeviceState
*dev
, qemu_irq_handler handler
, int n
)
119 assert(dev
->num_gpio_in
== 0);
120 dev
->num_gpio_in
= n
;
121 dev
->gpio_in
= qemu_allocate_irqs(handler
, dev
, n
);
124 void qdev_init_gpio_out(DeviceState
*dev
, qemu_irq
*pins
, int n
)
126 assert(dev
->num_gpio_out
== 0);
127 dev
->num_gpio_out
= n
;
128 dev
->gpio_out
= pins
;
131 qemu_irq
qdev_get_gpio_in(DeviceState
*dev
, int n
)
133 assert(n
>= 0 && n
< dev
->num_gpio_in
);
134 return dev
->gpio_in
[n
];
137 void qdev_connect_gpio_out(DeviceState
* dev
, int n
, qemu_irq pin
)
139 assert(n
>= 0 && n
< dev
->num_gpio_out
);
140 dev
->gpio_out
[n
] = pin
;
143 VLANClientState
*qdev_get_vlan_client(DeviceState
*dev
,
144 NetCanReceive
*can_receive
,
146 NetReceiveIOV
*receive_iov
,
150 NICInfo
*nd
= dev
->nd
;
152 nd
->vc
= qemu_new_vlan_client(nd
->vlan
, nd
->model
, nd
->name
, can_receive
,
153 receive
, receive_iov
, cleanup
, opaque
);
158 void qdev_get_macaddr(DeviceState
*dev
, uint8_t *macaddr
)
160 memcpy(macaddr
, dev
->nd
->macaddr
, 6);
163 static int next_block_unit
[IF_COUNT
];
165 /* Get a block device. This should only be used for single-drive devices
166 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
168 BlockDriverState
*qdev_init_bdrv(DeviceState
*dev
, BlockInterfaceType type
)
170 int unit
= next_block_unit
[type
]++;
173 index
= drive_get_index(type
, 0, unit
);
177 return drives_table
[index
].bdrv
;
180 BusState
*qdev_get_child_bus(DeviceState
*dev
, const char *name
)
184 LIST_FOREACH(bus
, &dev
->child_bus
, sibling
) {
185 if (strcmp(name
, bus
->name
) == 0) {
192 static int next_scsi_bus
;
194 /* Create a scsi bus, and attach devices to it. */
195 /* TODO: Actually create a scsi bus for hotplug to use. */
196 void scsi_bus_new(DeviceState
*host
, SCSIAttachFn attach
)
198 int bus
= next_scsi_bus
++;
202 for (unit
= 0; unit
< MAX_SCSI_DEVS
; unit
++) {
203 index
= drive_get_index(IF_SCSI
, bus
, unit
);
207 attach(host
, drives_table
[index
].bdrv
, unit
);
211 BusState
*qbus_create(BusInfo
*info
, DeviceState
*parent
, const char *name
)
215 bus
= qemu_mallocz(info
->size
);
217 bus
->parent
= parent
;
218 bus
->name
= qemu_strdup(name
);
219 LIST_INIT(&bus
->children
);
221 LIST_INSERT_HEAD(&parent
->child_bus
, bus
, sibling
);
226 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
227 static void qbus_print(Monitor
*mon
, BusState
*bus
, int indent
);
229 static void qdev_print_props(Monitor
*mon
, DeviceState
*dev
, Property
*props
,
230 const char *prefix
, int indent
)
236 while (props
->name
) {
237 if (props
->info
->print
) {
238 props
->info
->print(dev
, props
, buf
, sizeof(buf
));
239 qdev_printf("%s-prop: %s = %s\n", prefix
, props
->name
, buf
);
245 static void qdev_print(Monitor
*mon
, DeviceState
*dev
, int indent
)
248 qdev_printf("dev: %s\n", dev
->info
->name
);
250 if (dev
->num_gpio_in
) {
251 qdev_printf("gpio-in %d\n", dev
->num_gpio_in
);
253 if (dev
->num_gpio_out
) {
254 qdev_printf("gpio-out %d\n", dev
->num_gpio_out
);
256 qdev_print_props(mon
, dev
, dev
->info
->props
, "dev", indent
);
257 qdev_print_props(mon
, dev
, dev
->parent_bus
->info
->props
, "bus", indent
);
258 if (dev
->parent_bus
->info
->print_dev
)
259 dev
->parent_bus
->info
->print_dev(mon
, dev
, indent
);
260 LIST_FOREACH(child
, &dev
->child_bus
, sibling
) {
261 qbus_print(mon
, child
, indent
);
265 static void qbus_print(Monitor
*mon
, BusState
*bus
, int indent
)
267 struct DeviceState
*dev
;
269 qdev_printf("bus: %s\n", bus
->name
);
271 qdev_printf("type %s\n", bus
->info
->name
);
272 LIST_FOREACH(dev
, &bus
->children
, sibling
) {
273 qdev_print(mon
, dev
, indent
);
278 void do_info_qtree(Monitor
*mon
)
281 qbus_print(mon
, main_system_bus
, 0);