qdev: add monitor command to dump the tree.
[qemu] / hw / qdev.c
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
29 #include "net.h"
30 #include "qdev.h"
31 #include "sysemu.h"
32 #include "monitor.h"
33
34 struct DeviceProperty {
35     const char *name;
36     DevicePropType type;
37     union {
38         uint64_t i;
39         void *ptr;
40     } value;
41     DeviceProperty *next;
42 };
43
44 struct DeviceType {
45     const char *name;
46     DeviceInfo *info;
47     int size;
48     DeviceType *next;
49 };
50
51 /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
52 BusState *main_system_bus;
53
54 static DeviceType *device_type_list;
55
56 /* Register a new device type.  */
57 void qdev_register(const char *name, int size, DeviceInfo *info)
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;
68     t->info = info;
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.  */
74 DeviceState *qdev_create(BusState *bus, const char *name)
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) {
85         hw_error("Unknown device '%s'\n", name);
86     }
87
88     dev = qemu_mallocz(t->size);
89     dev->type = t;
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);
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.  */
112 void qdev_init(DeviceState *dev)
113 {
114     dev->type->info->init(dev, dev->type->info);
115 }
116
117 /* Unlink device from bus and free the structure.  */
118 void qdev_free(DeviceState *dev)
119 {
120     LIST_REMOVE(dev, sibling);
121     free(dev);
122 }
123
124 static DeviceProperty *create_prop(DeviceState *dev, const char *name,
125                                    DevicePropType type)
126 {
127     DeviceProperty *prop;
128
129     /* TODO: Check for duplicate properties.  */
130     prop = qemu_mallocz(sizeof(*prop));
131     prop->name = qemu_strdup(name);
132     prop->type = type;
133     prop->next = dev->props;
134     dev->props = prop;
135
136     return prop;
137 }
138
139 void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value)
140 {
141     DeviceProperty *prop;
142
143     prop = create_prop(dev, name, PROP_TYPE_INT);
144     prop->value.i = value;
145 }
146
147 void 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
155 void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value)
156 {
157     DeviceProperty *prop;
158
159     prop = create_prop(dev, name, PROP_TYPE_INT);
160     prop->value.ptr = value;
161 }
162
163 void qdev_set_netdev(DeviceState *dev, NICInfo *nd)
164 {
165     assert(!dev->nd);
166     dev->nd = nd;
167 }
168
169
170 /* Get a character (serial) device interface.  */
171 CharDriverState *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.  */
176     if (strncmp(dev->type->name, "virtio", 6) == 0) {
177         return virtcon_hds[next_virtconsole++];
178     } else {
179         return serial_hds[next_serial++];
180     }
181 }
182
183 BusState *qdev_get_parent_bus(DeviceState *dev)
184 {
185     return dev->parent_bus;
186 }
187
188 static DeviceProperty *find_prop(DeviceState *dev, const char *name,
189                                  DevicePropType type)
190 {
191     DeviceProperty *prop;
192
193     for (prop = dev->props; prop; prop = prop->next) {
194         if (strcmp(prop->name, name) == 0) {
195             assert (prop->type == type);
196             return prop;
197         }
198     }
199     return NULL;
200 }
201
202 uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def)
203 {
204     DeviceProperty *prop;
205
206     prop = find_prop(dev, name, PROP_TYPE_INT);
207     if (!prop) {
208         return def;
209     }
210
211     return prop->value.i;
212 }
213
214 void *qdev_get_prop_ptr(DeviceState *dev, const char *name)
215 {
216     DeviceProperty *prop;
217
218     prop = find_prop(dev, name, PROP_TYPE_PTR);
219     assert(prop);
220     return prop->value.ptr;
221 }
222
223 DeviceState *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
234 void 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
241 void 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
248 qemu_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
254 void 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
260 VLANClientState *qdev_get_vlan_client(DeviceState *dev,
261                                       IOReadHandler *fd_read,
262                                       IOCanRWHandler *fd_can_read,
263                                       NetCleanup *cleanup,
264                                       void *opaque)
265 {
266     NICInfo *nd = dev->nd;
267     assert(nd);
268     return qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
269                                 fd_read, fd_can_read, cleanup, opaque);
270 }
271
272
273 void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
274 {
275     memcpy(macaddr, dev->nd->macaddr, 6);
276 }
277
278 static int next_block_unit[IF_COUNT];
279
280 /* Get a block device.  This should only be used for single-drive devices
281    (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
282    appropriate bus.  */
283 BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
284 {
285     int unit = next_block_unit[type]++;
286     int index;
287
288     index = drive_get_index(type, 0, unit);
289     if (index == -1) {
290         return NULL;
291     }
292     return drives_table[index].bdrv;
293 }
294
295 BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
296 {
297     BusState *bus;
298
299     LIST_FOREACH(bus, &dev->child_bus, sibling) {
300         if (strcmp(name, bus->name) == 0) {
301             return bus;
302         }
303     }
304     return NULL;
305 }
306
307 static int next_scsi_bus;
308
309 /* Create a scsi bus, and attach devices to it.  */
310 /* TODO: Actually create a scsi bus for hotplug to use.  */
311 void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
312 {
313    int bus = next_scsi_bus++;
314    int unit;
315    int index;
316
317    for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
318        index = drive_get_index(IF_SCSI, bus, unit);
319        if (index == -1) {
320            continue;
321        }
322        attach(host, drives_table[index].bdrv, unit);
323    }
324 }
325
326 BusState *qbus_create(BusType type, size_t size,
327                       DeviceState *parent, const char *name)
328 {
329     BusState *bus;
330
331     bus = qemu_mallocz(size);
332     bus->type = type;
333     bus->parent = parent;
334     bus->name = qemu_strdup(name);
335     LIST_INIT(&bus->children);
336     if (parent) {
337         LIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
338     }
339     return bus;
340 }
341
342 static const char *bus_type_names[] = {
343     "System",
344     "PCI",
345     "SCSI",
346     "I2C",
347     "SSI"
348 };
349
350 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
351 static void qbus_print(Monitor *mon, BusState *bus, int indent);
352
353 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
354 {
355     DeviceProperty *prop;
356     BusState *child;
357     qdev_printf("dev: %s\n", dev->type->name);
358     indent += 2;
359     if (dev->num_gpio_in) {
360         qdev_printf("gpio-in %d\n", dev->num_gpio_in);
361     }
362     if (dev->num_gpio_out) {
363         qdev_printf("gpio-out %d\n", dev->num_gpio_out);
364     }
365     for (prop = dev->props; prop; prop = prop->next) {
366         switch (prop->type) {
367         case PROP_TYPE_INT:
368             qdev_printf("prop-int %s 0x%" PRIx64 "\n", prop->name,
369                         prop->value.i);
370             break;
371         case PROP_TYPE_PTR:
372             qdev_printf("prop-ptr %s\n", prop->name);
373             break;
374         case PROP_TYPE_DEV:
375             qdev_printf("prop-dev %s %s\n", prop->name,
376                         ((DeviceState *)prop->value.ptr)->type->name);
377             break;
378         default:
379             qdev_printf("prop-unknown%d %s\n", prop->type, prop->name);
380             break;
381         }
382     }
383     switch (dev->parent_bus->type) {
384     case BUS_TYPE_SYSTEM:
385         sysbus_dev_print(mon, dev, indent);
386         break;
387     default:
388         break;
389     }
390     LIST_FOREACH(child, &dev->child_bus, sibling) {
391         qbus_print(mon, child, indent);
392     }
393 }
394
395 static void qbus_print(Monitor *mon, BusState *bus, int indent)
396 {
397     struct DeviceState *dev;
398
399     qdev_printf("bus: %s\n", bus->name);
400     indent += 2;
401     qdev_printf("type %s\n", bus_type_names[bus->type]);
402     LIST_FOREACH(dev, &bus->children, sibling) {
403         qdev_print(mon, dev, indent);
404     }
405 }
406 #undef qdev_printf
407
408 void do_info_qtree(Monitor *mon)
409 {
410     if (main_system_bus)
411         qbus_print(mon, main_system_bus, 0);
412 }