CRIS: Prettify sizes for the internal disasm.
[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     DeviceInfo *info;
46     DeviceType *next;
47 };
48
49 /* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
50 static BusState *main_system_bus;
51
52 static DeviceType *device_type_list;
53
54 /* Register a new device type.  */
55 void qdev_register(DeviceInfo *info)
56 {
57     DeviceType *t;
58
59     assert(info->size >= sizeof(DeviceState));
60
61     t = qemu_mallocz(sizeof(DeviceType));
62     t->next = device_type_list;
63     device_type_list = t;
64     t->info = info;
65 }
66
67 /* Create a new device.  This only initializes the device state structure
68    and allows properties to be set.  qdev_init should be called to
69    initialize the actual device emulation.  */
70 DeviceState *qdev_create(BusState *bus, const char *name)
71 {
72     DeviceType *t;
73     DeviceState *dev;
74
75     for (t = device_type_list; t; t = t->next) {
76         if (strcmp(t->info->name, name) == 0) {
77             break;
78         }
79     }
80     if (!t) {
81         hw_error("Unknown device '%s'\n", name);
82     }
83
84     dev = qemu_mallocz(t->info->size);
85     dev->type = t;
86
87     if (!bus) {
88         /* ???: This assumes system busses have no additional state.  */
89         if (!main_system_bus) {
90             main_system_bus = qbus_create(BUS_TYPE_SYSTEM, sizeof(BusState),
91                                           NULL, "main-system-bus");
92         }
93         bus = main_system_bus;
94     }
95     if (t->info->bus_type != bus->type) {
96         /* TODO: Print bus type names.  */
97         hw_error("Device '%s' on wrong bus type (%d/%d)", name,
98                  t->info->bus_type, bus->type);
99     }
100     dev->parent_bus = bus;
101     LIST_INSERT_HEAD(&bus->children, dev, sibling);
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.  */
108 void qdev_init(DeviceState *dev)
109 {
110     dev->type->info->init(dev, dev->type->info);
111 }
112
113 /* Unlink device from bus and free the structure.  */
114 void qdev_free(DeviceState *dev)
115 {
116     LIST_REMOVE(dev, sibling);
117     free(dev);
118 }
119
120 static DeviceProperty *create_prop(DeviceState *dev, const char *name,
121                                    DevicePropType type)
122 {
123     DeviceProperty *prop;
124
125     /* TODO: Check for duplicate properties.  */
126     prop = qemu_mallocz(sizeof(*prop));
127     prop->name = qemu_strdup(name);
128     prop->type = type;
129     prop->next = dev->props;
130     dev->props = prop;
131
132     return prop;
133 }
134
135 void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value)
136 {
137     DeviceProperty *prop;
138
139     prop = create_prop(dev, name, PROP_TYPE_INT);
140     prop->value.i = value;
141 }
142
143 void qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value)
144 {
145     DeviceProperty *prop;
146
147     prop = create_prop(dev, name, PROP_TYPE_DEV);
148     prop->value.ptr = value;
149 }
150
151 void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value)
152 {
153     DeviceProperty *prop;
154
155     prop = create_prop(dev, name, PROP_TYPE_PTR);
156     prop->value.ptr = value;
157 }
158
159 void qdev_set_netdev(DeviceState *dev, NICInfo *nd)
160 {
161     assert(!dev->nd);
162     dev->nd = nd;
163 }
164
165
166 /* Get a character (serial) device interface.  */
167 CharDriverState *qdev_init_chardev(DeviceState *dev)
168 {
169     static int next_serial;
170     static int next_virtconsole;
171     /* FIXME: This is a nasty hack that needs to go away.  */
172     if (strncmp(dev->type->info->name, "virtio", 6) == 0) {
173         return virtcon_hds[next_virtconsole++];
174     } else {
175         return serial_hds[next_serial++];
176     }
177 }
178
179 BusState *qdev_get_parent_bus(DeviceState *dev)
180 {
181     return dev->parent_bus;
182 }
183
184 static DeviceProperty *find_prop(DeviceState *dev, const char *name,
185                                  DevicePropType type)
186 {
187     DeviceProperty *prop;
188
189     for (prop = dev->props; prop; prop = prop->next) {
190         if (strcmp(prop->name, name) == 0) {
191             assert (prop->type == type);
192             return prop;
193         }
194     }
195     return NULL;
196 }
197
198 uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def)
199 {
200     DeviceProperty *prop;
201
202     prop = find_prop(dev, name, PROP_TYPE_INT);
203     if (!prop) {
204         return def;
205     }
206
207     return prop->value.i;
208 }
209
210 void *qdev_get_prop_ptr(DeviceState *dev, const char *name)
211 {
212     DeviceProperty *prop;
213
214     prop = find_prop(dev, name, PROP_TYPE_PTR);
215     assert(prop);
216     return prop->value.ptr;
217 }
218
219 DeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name)
220 {
221     DeviceProperty *prop;
222
223     prop = find_prop(dev, name, PROP_TYPE_DEV);
224     if (!prop) {
225         return NULL;
226     }
227     return prop->value.ptr;
228 }
229
230 void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
231 {
232     assert(dev->num_gpio_in == 0);
233     dev->num_gpio_in = n;
234     dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
235 }
236
237 void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
238 {
239     assert(dev->num_gpio_out == 0);
240     dev->num_gpio_out = n;
241     dev->gpio_out = pins;
242 }
243
244 qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
245 {
246     assert(n >= 0 && n < dev->num_gpio_in);
247     return dev->gpio_in[n];
248 }
249
250 void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
251 {
252     assert(n >= 0 && n < dev->num_gpio_out);
253     dev->gpio_out[n] = pin;
254 }
255
256 VLANClientState *qdev_get_vlan_client(DeviceState *dev,
257                                       NetCanReceive *can_receive,
258                                       NetReceive *receive,
259                                       NetReceiveIOV *receive_iov,
260                                       NetCleanup *cleanup,
261                                       void *opaque)
262 {
263     NICInfo *nd = dev->nd;
264     assert(nd);
265     return qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
266                                 receive, receive_iov, cleanup, opaque);
267 }
268
269
270 void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
271 {
272     memcpy(macaddr, dev->nd->macaddr, 6);
273 }
274
275 static int next_block_unit[IF_COUNT];
276
277 /* Get a block device.  This should only be used for single-drive devices
278    (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
279    appropriate bus.  */
280 BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
281 {
282     int unit = next_block_unit[type]++;
283     int index;
284
285     index = drive_get_index(type, 0, unit);
286     if (index == -1) {
287         return NULL;
288     }
289     return drives_table[index].bdrv;
290 }
291
292 BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
293 {
294     BusState *bus;
295
296     LIST_FOREACH(bus, &dev->child_bus, sibling) {
297         if (strcmp(name, bus->name) == 0) {
298             return bus;
299         }
300     }
301     return NULL;
302 }
303
304 static int next_scsi_bus;
305
306 /* Create a scsi bus, and attach devices to it.  */
307 /* TODO: Actually create a scsi bus for hotplug to use.  */
308 void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
309 {
310    int bus = next_scsi_bus++;
311    int unit;
312    int index;
313
314    for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
315        index = drive_get_index(IF_SCSI, bus, unit);
316        if (index == -1) {
317            continue;
318        }
319        attach(host, drives_table[index].bdrv, unit);
320    }
321 }
322
323 BusState *qbus_create(BusType type, size_t size,
324                       DeviceState *parent, const char *name)
325 {
326     BusState *bus;
327
328     bus = qemu_mallocz(size);
329     bus->type = type;
330     bus->parent = parent;
331     bus->name = qemu_strdup(name);
332     LIST_INIT(&bus->children);
333     if (parent) {
334         LIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
335     }
336     return bus;
337 }
338
339 static const char *bus_type_names[] = {
340     [ BUS_TYPE_SYSTEM ] = "System",
341     [ BUS_TYPE_PCI ]    = "PCI",
342     [ BUS_TYPE_SCSI ]   = "SCSI",
343     [ BUS_TYPE_I2C ]    = "I2C",
344     [ BUS_TYPE_SSI ]    = "SSI",
345 };
346
347 #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
348 static void qbus_print(Monitor *mon, BusState *bus, int indent);
349
350 static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
351 {
352     DeviceProperty *prop;
353     BusState *child;
354     qdev_printf("dev: %s\n", dev->type->info->name);
355     indent += 2;
356     if (dev->num_gpio_in) {
357         qdev_printf("gpio-in %d\n", dev->num_gpio_in);
358     }
359     if (dev->num_gpio_out) {
360         qdev_printf("gpio-out %d\n", dev->num_gpio_out);
361     }
362     for (prop = dev->props; prop; prop = prop->next) {
363         switch (prop->type) {
364         case PROP_TYPE_INT:
365             qdev_printf("prop-int %s 0x%" PRIx64 "\n", prop->name,
366                         prop->value.i);
367             break;
368         case PROP_TYPE_PTR:
369             qdev_printf("prop-ptr %s\n", prop->name);
370             break;
371         case PROP_TYPE_DEV:
372             qdev_printf("prop-dev %s %s\n", prop->name,
373                         ((DeviceState *)prop->value.ptr)->type->info->name);
374             break;
375         default:
376             qdev_printf("prop-unknown%d %s\n", prop->type, prop->name);
377             break;
378         }
379     }
380     switch (dev->parent_bus->type) {
381     case BUS_TYPE_SYSTEM:
382         sysbus_dev_print(mon, dev, indent);
383         break;
384     default:
385         break;
386     }
387     LIST_FOREACH(child, &dev->child_bus, sibling) {
388         qbus_print(mon, child, indent);
389     }
390 }
391
392 static void qbus_print(Monitor *mon, BusState *bus, int indent)
393 {
394     struct DeviceState *dev;
395
396     qdev_printf("bus: %s\n", bus->name);
397     indent += 2;
398     qdev_printf("type %s\n", bus_type_names[bus->type]);
399     LIST_FOREACH(dev, &bus->children, sibling) {
400         qdev_print(mon, dev, indent);
401     }
402 }
403 #undef qdev_printf
404
405 void do_info_qtree(Monitor *mon)
406 {
407     if (main_system_bus)
408         qbus_print(mon, main_system_bus, 0);
409 }