]> git.proxmox.com Git - qemu.git/blame - hw/qdev.c
Sparc32: use hex for version numbers
[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
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
aae9460e
PB
18 */
19
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. */
27
9d07d757 28#include "net.h"
aae9460e
PB
29#include "qdev.h"
30#include "sysemu.h"
cae4956e 31#include "monitor.h"
aae9460e 32
02e2da45 33/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
b9aaf7f8 34static BusState *main_system_bus;
10c4c98a 35extern struct BusInfo system_bus_info;
4d6ae674 36
042f84d0 37static DeviceInfo *device_info_list;
aae9460e
PB
38
39/* Register a new device type. */
074f2fff 40void qdev_register(DeviceInfo *info)
aae9460e 41{
074f2fff 42 assert(info->size >= sizeof(DeviceState));
042f84d0 43 assert(!info->next);
aae9460e 44
042f84d0
GH
45 info->next = device_info_list;
46 device_info_list = info;
aae9460e
PB
47}
48
81ebb98b
GH
49static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
50{
51 DeviceInfo *info;
52
3320e56e 53 /* first check device names */
81ebb98b
GH
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;
60 }
3320e56e
GH
61
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;
71 }
81ebb98b
GH
72 return NULL;
73}
74
aae9460e
PB
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. */
02e2da45 78DeviceState *qdev_create(BusState *bus, const char *name)
aae9460e 79{
042f84d0 80 DeviceInfo *info;
aae9460e
PB
81 DeviceState *dev;
82
10c4c98a
GH
83 if (!bus) {
84 if (!main_system_bus) {
85 main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
aae9460e 86 }
10c4c98a
GH
87 bus = main_system_bus;
88 }
89
81ebb98b 90 info = qdev_find_info(bus->info, name);
042f84d0 91 if (!info) {
10c4c98a 92 hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
aae9460e
PB
93 }
94
042f84d0
GH
95 dev = qemu_mallocz(info->size);
96 dev->info = info;
02e2da45 97 dev->parent_bus = bus;
ee6847d1
GH
98 qdev_prop_set_defaults(dev, dev->info->props);
99 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
b6b61144 100 qdev_prop_set_compat(dev);
02e2da45 101 LIST_INSERT_HEAD(&bus->children, dev, sibling);
aae9460e
PB
102 return dev;
103}
104
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. */
108void qdev_init(DeviceState *dev)
109{
042f84d0 110 dev->info->init(dev, dev->info);
02e2da45
PB
111}
112
113/* Unlink device from bus and free the structure. */
114void qdev_free(DeviceState *dev)
115{
116 LIST_REMOVE(dev, sibling);
ccb63de3
GH
117 qemu_free(dev->id);
118 qemu_free(dev);
aae9460e
PB
119}
120
aae9460e
PB
121/* Get a character (serial) device interface. */
122CharDriverState *qdev_init_chardev(DeviceState *dev)
123{
124 static int next_serial;
125 static int next_virtconsole;
126 /* FIXME: This is a nasty hack that needs to go away. */
042f84d0 127 if (strncmp(dev->info->name, "virtio", 6) == 0) {
aae9460e
PB
128 return virtcon_hds[next_virtconsole++];
129 } else {
130 return serial_hds[next_serial++];
131 }
132}
133
02e2da45 134BusState *qdev_get_parent_bus(DeviceState *dev)
aae9460e 135{
02e2da45 136 return dev->parent_bus;
aae9460e
PB
137}
138
aae9460e
PB
139void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
140{
141 assert(dev->num_gpio_in == 0);
142 dev->num_gpio_in = n;
143 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
144}
145
146void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
147{
148 assert(dev->num_gpio_out == 0);
149 dev->num_gpio_out = n;
150 dev->gpio_out = pins;
151}
152
153qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
154{
155 assert(n >= 0 && n < dev->num_gpio_in);
156 return dev->gpio_in[n];
157}
158
159void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
160{
161 assert(n >= 0 && n < dev->num_gpio_out);
162 dev->gpio_out[n] = pin;
163}
164
9d07d757 165VLANClientState *qdev_get_vlan_client(DeviceState *dev,
cda9046b
MM
166 NetCanReceive *can_receive,
167 NetReceive *receive,
168 NetReceiveIOV *receive_iov,
9d07d757
PB
169 NetCleanup *cleanup,
170 void *opaque)
171{
172 NICInfo *nd = dev->nd;
173 assert(nd);
ae50b274
MM
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;
9d07d757
PB
177}
178
179
180void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
181{
182 memcpy(macaddr, dev->nd->macaddr, 6);
183}
184
aae9460e
PB
185static int next_block_unit[IF_COUNT];
186
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. */
190BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
191{
192 int unit = next_block_unit[type]++;
193 int index;
194
195 index = drive_get_index(type, 0, unit);
196 if (index == -1) {
197 return NULL;
198 }
199 return drives_table[index].bdrv;
200}
4d6ae674 201
02e2da45 202BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
4d6ae674 203{
02e2da45 204 BusState *bus;
4d6ae674 205
02e2da45 206 LIST_FOREACH(bus, &dev->child_bus, sibling) {
4d6ae674 207 if (strcmp(name, bus->name) == 0) {
02e2da45 208 return bus;
4d6ae674
PB
209 }
210 }
211 return NULL;
212}
213
6f68ecb2
PB
214static int next_scsi_bus;
215
216/* Create a scsi bus, and attach devices to it. */
217/* TODO: Actually create a scsi bus for hotplug to use. */
218void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
219{
220 int bus = next_scsi_bus++;
221 int unit;
222 int index;
223
224 for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
225 index = drive_get_index(IF_SCSI, bus, unit);
226 if (index == -1) {
227 continue;
228 }
229 attach(host, drives_table[index].bdrv, unit);
230 }
231}
02e2da45 232
10c4c98a 233BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
02e2da45
PB
234{
235 BusState *bus;
236
10c4c98a
GH
237 bus = qemu_mallocz(info->size);
238 bus->info = info;
02e2da45
PB
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);
244 }
245 return bus;
246}
cae4956e 247
cae4956e
GH
248#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
249static void qbus_print(Monitor *mon, BusState *bus, int indent);
250
ee6847d1
GH
251static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
252 const char *prefix, int indent)
253{
254 char buf[64];
255
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);
262 }
263 props++;
264 }
265}
266
cae4956e
GH
267static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
268{
cae4956e 269 BusState *child;
ccb63de3
GH
270 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
271 dev->id ? dev->id : "");
cae4956e
GH
272 indent += 2;
273 if (dev->num_gpio_in) {
274 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
275 }
276 if (dev->num_gpio_out) {
277 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
278 }
ee6847d1
GH
279 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
280 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
10c4c98a
GH
281 if (dev->parent_bus->info->print_dev)
282 dev->parent_bus->info->print_dev(mon, dev, indent);
cae4956e
GH
283 LIST_FOREACH(child, &dev->child_bus, sibling) {
284 qbus_print(mon, child, indent);
285 }
286}
287
288static void qbus_print(Monitor *mon, BusState *bus, int indent)
289{
290 struct DeviceState *dev;
291
292 qdev_printf("bus: %s\n", bus->name);
293 indent += 2;
10c4c98a 294 qdev_printf("type %s\n", bus->info->name);
cae4956e
GH
295 LIST_FOREACH(dev, &bus->children, sibling) {
296 qdev_print(mon, dev, indent);
297 }
298}
299#undef qdev_printf
300
301void do_info_qtree(Monitor *mon)
302{
303 if (main_system_bus)
304 qbus_print(mon, main_system_bus, 0);
305}