]> Git Repo - qemu.git/blame - hw/qdev.c
Suppress a Sparse warning
[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;
4d6ae674 35
042f84d0 36static DeviceInfo *device_info_list;
aae9460e
PB
37
38/* Register a new device type. */
074f2fff 39void qdev_register(DeviceInfo *info)
aae9460e 40{
074f2fff 41 assert(info->size >= sizeof(DeviceState));
042f84d0 42 assert(!info->next);
aae9460e 43
042f84d0
GH
44 info->next = device_info_list;
45 device_info_list = info;
aae9460e
PB
46}
47
81ebb98b
GH
48static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
49{
50 DeviceInfo *info;
51
3320e56e 52 /* first check device names */
81ebb98b
GH
53 for (info = device_info_list; info != NULL; info = info->next) {
54 if (bus_info && info->bus_info != bus_info)
55 continue;
56 if (strcmp(info->name, name) != 0)
57 continue;
58 return info;
59 }
3320e56e
GH
60
61 /* failing that check the aliases */
62 for (info = device_info_list; info != NULL; info = info->next) {
63 if (bus_info && info->bus_info != bus_info)
64 continue;
65 if (!info->alias)
66 continue;
67 if (strcmp(info->alias, name) != 0)
68 continue;
69 return info;
70 }
81ebb98b
GH
71 return NULL;
72}
73
aae9460e
PB
74/* Create a new device. This only initializes the device state structure
75 and allows properties to be set. qdev_init should be called to
76 initialize the actual device emulation. */
02e2da45 77DeviceState *qdev_create(BusState *bus, const char *name)
aae9460e 78{
042f84d0 79 DeviceInfo *info;
aae9460e
PB
80 DeviceState *dev;
81
10c4c98a
GH
82 if (!bus) {
83 if (!main_system_bus) {
84 main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
aae9460e 85 }
10c4c98a
GH
86 bus = main_system_bus;
87 }
88
81ebb98b 89 info = qdev_find_info(bus->info, name);
042f84d0 90 if (!info) {
10c4c98a 91 hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
aae9460e
PB
92 }
93
042f84d0
GH
94 dev = qemu_mallocz(info->size);
95 dev->info = info;
02e2da45 96 dev->parent_bus = bus;
ee6847d1
GH
97 qdev_prop_set_defaults(dev, dev->info->props);
98 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
b6b61144 99 qdev_prop_set_compat(dev);
02e2da45 100 LIST_INSERT_HEAD(&bus->children, dev, sibling);
aae9460e
PB
101 return dev;
102}
103
104/* Initialize a device. Device properties should be set before calling
105 this function. IRQs and MMIO regions should be connected/mapped after
106 calling this function. */
107void qdev_init(DeviceState *dev)
108{
042f84d0 109 dev->info->init(dev, dev->info);
02e2da45
PB
110}
111
112/* Unlink device from bus and free the structure. */
113void qdev_free(DeviceState *dev)
114{
115 LIST_REMOVE(dev, sibling);
ccb63de3
GH
116 qemu_free(dev->id);
117 qemu_free(dev);
aae9460e
PB
118}
119
aae9460e
PB
120/* Get a character (serial) device interface. */
121CharDriverState *qdev_init_chardev(DeviceState *dev)
122{
123 static int next_serial;
124 static int next_virtconsole;
125 /* FIXME: This is a nasty hack that needs to go away. */
042f84d0 126 if (strncmp(dev->info->name, "virtio", 6) == 0) {
aae9460e
PB
127 return virtcon_hds[next_virtconsole++];
128 } else {
129 return serial_hds[next_serial++];
130 }
131}
132
02e2da45 133BusState *qdev_get_parent_bus(DeviceState *dev)
aae9460e 134{
02e2da45 135 return dev->parent_bus;
aae9460e
PB
136}
137
aae9460e
PB
138void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
139{
140 assert(dev->num_gpio_in == 0);
141 dev->num_gpio_in = n;
142 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
143}
144
145void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
146{
147 assert(dev->num_gpio_out == 0);
148 dev->num_gpio_out = n;
149 dev->gpio_out = pins;
150}
151
152qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
153{
154 assert(n >= 0 && n < dev->num_gpio_in);
155 return dev->gpio_in[n];
156}
157
158void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
159{
160 assert(n >= 0 && n < dev->num_gpio_out);
161 dev->gpio_out[n] = pin;
162}
163
9d07d757 164VLANClientState *qdev_get_vlan_client(DeviceState *dev,
cda9046b
MM
165 NetCanReceive *can_receive,
166 NetReceive *receive,
167 NetReceiveIOV *receive_iov,
9d07d757
PB
168 NetCleanup *cleanup,
169 void *opaque)
170{
171 NICInfo *nd = dev->nd;
172 assert(nd);
ae50b274
MM
173 nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
174 receive, receive_iov, cleanup, opaque);
175 return nd->vc;
9d07d757
PB
176}
177
178
179void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
180{
181 memcpy(macaddr, dev->nd->macaddr, 6);
182}
183
aae9460e
PB
184static int next_block_unit[IF_COUNT];
185
186/* Get a block device. This should only be used for single-drive devices
187 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
188 appropriate bus. */
189BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
190{
191 int unit = next_block_unit[type]++;
192 int index;
193
194 index = drive_get_index(type, 0, unit);
195 if (index == -1) {
196 return NULL;
197 }
198 return drives_table[index].bdrv;
199}
4d6ae674 200
02e2da45 201BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
4d6ae674 202{
02e2da45 203 BusState *bus;
4d6ae674 204
02e2da45 205 LIST_FOREACH(bus, &dev->child_bus, sibling) {
4d6ae674 206 if (strcmp(name, bus->name) == 0) {
02e2da45 207 return bus;
4d6ae674
PB
208 }
209 }
210 return NULL;
211}
212
6f68ecb2
PB
213static int next_scsi_bus;
214
215/* Create a scsi bus, and attach devices to it. */
216/* TODO: Actually create a scsi bus for hotplug to use. */
217void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
218{
219 int bus = next_scsi_bus++;
220 int unit;
221 int index;
222
223 for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
224 index = drive_get_index(IF_SCSI, bus, unit);
225 if (index == -1) {
226 continue;
227 }
228 attach(host, drives_table[index].bdrv, unit);
229 }
230}
02e2da45 231
10c4c98a 232BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
02e2da45
PB
233{
234 BusState *bus;
235
10c4c98a
GH
236 bus = qemu_mallocz(info->size);
237 bus->info = info;
02e2da45
PB
238 bus->parent = parent;
239 bus->name = qemu_strdup(name);
240 LIST_INIT(&bus->children);
241 if (parent) {
242 LIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
243 }
244 return bus;
245}
cae4956e 246
cae4956e
GH
247#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
248static void qbus_print(Monitor *mon, BusState *bus, int indent);
249
ee6847d1
GH
250static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
251 const char *prefix, int indent)
252{
253 char buf[64];
254
255 if (!props)
256 return;
257 while (props->name) {
258 if (props->info->print) {
259 props->info->print(dev, props, buf, sizeof(buf));
260 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
261 }
262 props++;
263 }
264}
265
cae4956e
GH
266static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
267{
cae4956e 268 BusState *child;
ccb63de3
GH
269 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
270 dev->id ? dev->id : "");
cae4956e
GH
271 indent += 2;
272 if (dev->num_gpio_in) {
273 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
274 }
275 if (dev->num_gpio_out) {
276 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
277 }
ee6847d1
GH
278 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
279 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
10c4c98a
GH
280 if (dev->parent_bus->info->print_dev)
281 dev->parent_bus->info->print_dev(mon, dev, indent);
cae4956e
GH
282 LIST_FOREACH(child, &dev->child_bus, sibling) {
283 qbus_print(mon, child, indent);
284 }
285}
286
287static void qbus_print(Monitor *mon, BusState *bus, int indent)
288{
289 struct DeviceState *dev;
290
291 qdev_printf("bus: %s\n", bus->name);
292 indent += 2;
10c4c98a 293 qdev_printf("type %s\n", bus->info->name);
cae4956e
GH
294 LIST_FOREACH(dev, &bus->children, sibling) {
295 qdev_print(mon, dev, indent);
296 }
297}
298#undef qdev_printf
299
300void do_info_qtree(Monitor *mon)
301{
302 if (main_system_bus)
303 qbus_print(mon, main_system_bus, 0);
304}
This page took 0.08668 seconds and 4 git commands to generate.