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
34struct DeviceProperty {
35    const char *name;
36    DevicePropType type;
37    union {
38        uint64_t i;
39        void *ptr;
40    } value;
41    DeviceProperty *next;
42};
43
44struct DeviceType {
45    DeviceInfo *info;
46    DeviceType *next;
47};
48
49/* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
50static BusState *main_system_bus;
51
52static DeviceType *device_type_list;
53
54/* Register a new device type.  */
55void 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.  */
70DeviceState *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    QLIST_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.  */
108void 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.  */
114void qdev_free(DeviceState *dev)
115{
116    QLIST_REMOVE(dev, sibling);
117    qemu_free(dev);
118}
119
120static 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
135void 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
143void 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
151void 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
159void 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.  */
167CharDriverState *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
179BusState *qdev_get_parent_bus(DeviceState *dev)
180{
181    return dev->parent_bus;
182}
183
184static 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
198uint64_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
210void *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
219DeviceState *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
230void 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
237void 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
244qemu_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
250void 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
256VLANClientState *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
270void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
271{
272    memcpy(macaddr, dev->nd->macaddr, 6);
273}
274
275static 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.  */
280BlockDriverState *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
292BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
293{
294    BusState *bus;
295
296    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
297        if (strcmp(name, bus->name) == 0) {
298            return bus;
299        }
300    }
301    return NULL;
302}
303
304static 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.  */
308void 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
323BusState *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    QLIST_INIT(&bus->children);
333    if (parent) {
334        QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
335    }
336    return bus;
337}
338
339static 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__)
348static void qbus_print(Monitor *mon, BusState *bus, int indent);
349
350static 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    QLIST_FOREACH(child, &dev->child_bus, sibling) {
388        qbus_print(mon, child, indent);
389    }
390}
391
392static 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    QLIST_FOREACH(dev, &bus->children, sibling) {
400        qdev_print(mon, dev, indent);
401    }
402}
403#undef qdev_printf
404
405void do_info_qtree(Monitor *mon)
406{
407    if (main_system_bus)
408        qbus_print(mon, main_system_bus, 0);
409}
410