Statistics
| Branch: | Revision:

root / hw / qdev.c @ 636aa70a

History | View | Annotate | Download (8.6 kB)

1 aae9460e Paul Brook
/*
2 aae9460e Paul Brook
 *  Dynamic device configuration and creation.
3 aae9460e Paul Brook
 *
4 aae9460e Paul Brook
 *  Copyright (c) 2009 CodeSourcery
5 aae9460e Paul Brook
 *
6 aae9460e Paul Brook
 * This library is free software; you can redistribute it and/or
7 aae9460e Paul Brook
 * modify it under the terms of the GNU Lesser General Public
8 aae9460e Paul Brook
 * License as published by the Free Software Foundation; either
9 aae9460e Paul Brook
 * version 2 of the License, or (at your option) any later version.
10 aae9460e Paul Brook
 *
11 aae9460e Paul Brook
 * This library is distributed in the hope that it will be useful,
12 aae9460e Paul Brook
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 aae9460e Paul Brook
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 aae9460e Paul Brook
 * Lesser General Public License for more details.
15 aae9460e Paul Brook
 *
16 aae9460e Paul Brook
 * You should have received a copy of the GNU Lesser General Public
17 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 aae9460e Paul Brook
 */
19 aae9460e Paul Brook
20 aae9460e Paul Brook
/* The theory here is that it should be possible to create a machine without
21 aae9460e Paul Brook
   knowledge of specific devices.  Historically board init routines have
22 aae9460e Paul Brook
   passed a bunch of arguments to each device, requiring the board know
23 aae9460e Paul Brook
   exactly which device it is dealing with.  This file provides an abstract
24 aae9460e Paul Brook
   API for device configuration and initialization.  Devices will generally
25 aae9460e Paul Brook
   inherit from a particular bus (e.g. PCI or I2C) rather than
26 aae9460e Paul Brook
   this API directly.  */
27 aae9460e Paul Brook
28 9d07d757 Paul Brook
#include "net.h"
29 aae9460e Paul Brook
#include "qdev.h"
30 aae9460e Paul Brook
#include "sysemu.h"
31 cae4956e Gerd Hoffmann
#include "monitor.h"
32 aae9460e Paul Brook
33 02e2da45 Paul Brook
/* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
34 b9aaf7f8 Blue Swirl
static BusState *main_system_bus;
35 4d6ae674 Paul Brook
36 042f84d0 Gerd Hoffmann
static DeviceInfo *device_info_list;
37 aae9460e Paul Brook
38 aae9460e Paul Brook
/* Register a new device type.  */
39 074f2fff Gerd Hoffmann
void qdev_register(DeviceInfo *info)
40 aae9460e Paul Brook
{
41 074f2fff Gerd Hoffmann
    assert(info->size >= sizeof(DeviceState));
42 042f84d0 Gerd Hoffmann
    assert(!info->next);
43 aae9460e Paul Brook
44 042f84d0 Gerd Hoffmann
    info->next = device_info_list;
45 042f84d0 Gerd Hoffmann
    device_info_list = info;
46 aae9460e Paul Brook
}
47 aae9460e Paul Brook
48 81ebb98b Gerd Hoffmann
static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
49 81ebb98b Gerd Hoffmann
{
50 81ebb98b Gerd Hoffmann
    DeviceInfo *info;
51 81ebb98b Gerd Hoffmann
52 3320e56e Gerd Hoffmann
    /* first check device names */
53 81ebb98b Gerd Hoffmann
    for (info = device_info_list; info != NULL; info = info->next) {
54 81ebb98b Gerd Hoffmann
        if (bus_info && info->bus_info != bus_info)
55 81ebb98b Gerd Hoffmann
            continue;
56 81ebb98b Gerd Hoffmann
        if (strcmp(info->name, name) != 0)
57 81ebb98b Gerd Hoffmann
            continue;
58 81ebb98b Gerd Hoffmann
        return info;
59 81ebb98b Gerd Hoffmann
    }
60 3320e56e Gerd Hoffmann
61 3320e56e Gerd Hoffmann
    /* failing that check the aliases */
62 3320e56e Gerd Hoffmann
    for (info = device_info_list; info != NULL; info = info->next) {
63 3320e56e Gerd Hoffmann
        if (bus_info && info->bus_info != bus_info)
64 3320e56e Gerd Hoffmann
            continue;
65 3320e56e Gerd Hoffmann
        if (!info->alias)
66 3320e56e Gerd Hoffmann
            continue;
67 3320e56e Gerd Hoffmann
        if (strcmp(info->alias, name) != 0)
68 3320e56e Gerd Hoffmann
            continue;
69 3320e56e Gerd Hoffmann
        return info;
70 3320e56e Gerd Hoffmann
    }
71 81ebb98b Gerd Hoffmann
    return NULL;
72 81ebb98b Gerd Hoffmann
}
73 81ebb98b Gerd Hoffmann
74 aae9460e Paul Brook
/* Create a new device.  This only initializes the device state structure
75 aae9460e Paul Brook
   and allows properties to be set.  qdev_init should be called to
76 aae9460e Paul Brook
   initialize the actual device emulation.  */
77 02e2da45 Paul Brook
DeviceState *qdev_create(BusState *bus, const char *name)
78 aae9460e Paul Brook
{
79 042f84d0 Gerd Hoffmann
    DeviceInfo *info;
80 aae9460e Paul Brook
    DeviceState *dev;
81 aae9460e Paul Brook
82 10c4c98a Gerd Hoffmann
    if (!bus) {
83 10c4c98a Gerd Hoffmann
        if (!main_system_bus) {
84 10c4c98a Gerd Hoffmann
            main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
85 aae9460e Paul Brook
        }
86 10c4c98a Gerd Hoffmann
        bus = main_system_bus;
87 10c4c98a Gerd Hoffmann
    }
88 10c4c98a Gerd Hoffmann
89 81ebb98b Gerd Hoffmann
    info = qdev_find_info(bus->info, name);
90 042f84d0 Gerd Hoffmann
    if (!info) {
91 10c4c98a Gerd Hoffmann
        hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
92 aae9460e Paul Brook
    }
93 aae9460e Paul Brook
94 042f84d0 Gerd Hoffmann
    dev = qemu_mallocz(info->size);
95 042f84d0 Gerd Hoffmann
    dev->info = info;
96 02e2da45 Paul Brook
    dev->parent_bus = bus;
97 ee6847d1 Gerd Hoffmann
    qdev_prop_set_defaults(dev, dev->info->props);
98 ee6847d1 Gerd Hoffmann
    qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
99 b6b61144 Gerd Hoffmann
    qdev_prop_set_compat(dev);
100 02e2da45 Paul Brook
    LIST_INSERT_HEAD(&bus->children, dev, sibling);
101 aae9460e Paul Brook
    return dev;
102 aae9460e Paul Brook
}
103 aae9460e Paul Brook
104 aae9460e Paul Brook
/* Initialize a device.  Device properties should be set before calling
105 aae9460e Paul Brook
   this function.  IRQs and MMIO regions should be connected/mapped after
106 aae9460e Paul Brook
   calling this function.  */
107 aae9460e Paul Brook
void qdev_init(DeviceState *dev)
108 aae9460e Paul Brook
{
109 042f84d0 Gerd Hoffmann
    dev->info->init(dev, dev->info);
110 02e2da45 Paul Brook
}
111 02e2da45 Paul Brook
112 02e2da45 Paul Brook
/* Unlink device from bus and free the structure.  */
113 02e2da45 Paul Brook
void qdev_free(DeviceState *dev)
114 02e2da45 Paul Brook
{
115 02e2da45 Paul Brook
    LIST_REMOVE(dev, sibling);
116 ccb63de3 Gerd Hoffmann
    qemu_free(dev->id);
117 ccb63de3 Gerd Hoffmann
    qemu_free(dev);
118 aae9460e Paul Brook
}
119 aae9460e Paul Brook
120 aae9460e Paul Brook
/* Get a character (serial) device interface.  */
121 aae9460e Paul Brook
CharDriverState *qdev_init_chardev(DeviceState *dev)
122 aae9460e Paul Brook
{
123 aae9460e Paul Brook
    static int next_serial;
124 aae9460e Paul Brook
    static int next_virtconsole;
125 aae9460e Paul Brook
    /* FIXME: This is a nasty hack that needs to go away.  */
126 042f84d0 Gerd Hoffmann
    if (strncmp(dev->info->name, "virtio", 6) == 0) {
127 aae9460e Paul Brook
        return virtcon_hds[next_virtconsole++];
128 aae9460e Paul Brook
    } else {
129 aae9460e Paul Brook
        return serial_hds[next_serial++];
130 aae9460e Paul Brook
    }
131 aae9460e Paul Brook
}
132 aae9460e Paul Brook
133 02e2da45 Paul Brook
BusState *qdev_get_parent_bus(DeviceState *dev)
134 aae9460e Paul Brook
{
135 02e2da45 Paul Brook
    return dev->parent_bus;
136 aae9460e Paul Brook
}
137 aae9460e Paul Brook
138 aae9460e Paul Brook
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
139 aae9460e Paul Brook
{
140 aae9460e Paul Brook
    assert(dev->num_gpio_in == 0);
141 aae9460e Paul Brook
    dev->num_gpio_in = n;
142 aae9460e Paul Brook
    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
143 aae9460e Paul Brook
}
144 aae9460e Paul Brook
145 aae9460e Paul Brook
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
146 aae9460e Paul Brook
{
147 aae9460e Paul Brook
    assert(dev->num_gpio_out == 0);
148 aae9460e Paul Brook
    dev->num_gpio_out = n;
149 aae9460e Paul Brook
    dev->gpio_out = pins;
150 aae9460e Paul Brook
}
151 aae9460e Paul Brook
152 aae9460e Paul Brook
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
153 aae9460e Paul Brook
{
154 aae9460e Paul Brook
    assert(n >= 0 && n < dev->num_gpio_in);
155 aae9460e Paul Brook
    return dev->gpio_in[n];
156 aae9460e Paul Brook
}
157 aae9460e Paul Brook
158 aae9460e Paul Brook
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
159 aae9460e Paul Brook
{
160 aae9460e Paul Brook
    assert(n >= 0 && n < dev->num_gpio_out);
161 aae9460e Paul Brook
    dev->gpio_out[n] = pin;
162 aae9460e Paul Brook
}
163 aae9460e Paul Brook
164 9d07d757 Paul Brook
VLANClientState *qdev_get_vlan_client(DeviceState *dev,
165 cda9046b Mark McLoughlin
                                      NetCanReceive *can_receive,
166 cda9046b Mark McLoughlin
                                      NetReceive *receive,
167 cda9046b Mark McLoughlin
                                      NetReceiveIOV *receive_iov,
168 9d07d757 Paul Brook
                                      NetCleanup *cleanup,
169 9d07d757 Paul Brook
                                      void *opaque)
170 9d07d757 Paul Brook
{
171 9d07d757 Paul Brook
    NICInfo *nd = dev->nd;
172 9d07d757 Paul Brook
    assert(nd);
173 ae50b274 Mark McLoughlin
    nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
174 ae50b274 Mark McLoughlin
                                  receive, receive_iov, cleanup, opaque);
175 ae50b274 Mark McLoughlin
    return nd->vc;
176 9d07d757 Paul Brook
}
177 9d07d757 Paul Brook
178 9d07d757 Paul Brook
179 9d07d757 Paul Brook
void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
180 9d07d757 Paul Brook
{
181 9d07d757 Paul Brook
    memcpy(macaddr, dev->nd->macaddr, 6);
182 9d07d757 Paul Brook
}
183 9d07d757 Paul Brook
184 aae9460e Paul Brook
static int next_block_unit[IF_COUNT];
185 aae9460e Paul Brook
186 aae9460e Paul Brook
/* Get a block device.  This should only be used for single-drive devices
187 aae9460e Paul Brook
   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
188 aae9460e Paul Brook
   appropriate bus.  */
189 aae9460e Paul Brook
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
190 aae9460e Paul Brook
{
191 aae9460e Paul Brook
    int unit = next_block_unit[type]++;
192 aae9460e Paul Brook
    int index;
193 aae9460e Paul Brook
194 aae9460e Paul Brook
    index = drive_get_index(type, 0, unit);
195 aae9460e Paul Brook
    if (index == -1) {
196 aae9460e Paul Brook
        return NULL;
197 aae9460e Paul Brook
    }
198 aae9460e Paul Brook
    return drives_table[index].bdrv;
199 aae9460e Paul Brook
}
200 4d6ae674 Paul Brook
201 02e2da45 Paul Brook
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
202 4d6ae674 Paul Brook
{
203 02e2da45 Paul Brook
    BusState *bus;
204 4d6ae674 Paul Brook
205 02e2da45 Paul Brook
    LIST_FOREACH(bus, &dev->child_bus, sibling) {
206 4d6ae674 Paul Brook
        if (strcmp(name, bus->name) == 0) {
207 02e2da45 Paul Brook
            return bus;
208 4d6ae674 Paul Brook
        }
209 4d6ae674 Paul Brook
    }
210 4d6ae674 Paul Brook
    return NULL;
211 4d6ae674 Paul Brook
}
212 4d6ae674 Paul Brook
213 6f68ecb2 Paul Brook
static int next_scsi_bus;
214 6f68ecb2 Paul Brook
215 6f68ecb2 Paul Brook
/* Create a scsi bus, and attach devices to it.  */
216 6f68ecb2 Paul Brook
/* TODO: Actually create a scsi bus for hotplug to use.  */
217 6f68ecb2 Paul Brook
void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
218 6f68ecb2 Paul Brook
{
219 6f68ecb2 Paul Brook
   int bus = next_scsi_bus++;
220 6f68ecb2 Paul Brook
   int unit;
221 6f68ecb2 Paul Brook
   int index;
222 6f68ecb2 Paul Brook
223 6f68ecb2 Paul Brook
   for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
224 6f68ecb2 Paul Brook
       index = drive_get_index(IF_SCSI, bus, unit);
225 6f68ecb2 Paul Brook
       if (index == -1) {
226 6f68ecb2 Paul Brook
           continue;
227 6f68ecb2 Paul Brook
       }
228 6f68ecb2 Paul Brook
       attach(host, drives_table[index].bdrv, unit);
229 6f68ecb2 Paul Brook
   }
230 6f68ecb2 Paul Brook
}
231 02e2da45 Paul Brook
232 10c4c98a Gerd Hoffmann
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
233 02e2da45 Paul Brook
{
234 02e2da45 Paul Brook
    BusState *bus;
235 02e2da45 Paul Brook
236 10c4c98a Gerd Hoffmann
    bus = qemu_mallocz(info->size);
237 10c4c98a Gerd Hoffmann
    bus->info = info;
238 02e2da45 Paul Brook
    bus->parent = parent;
239 02e2da45 Paul Brook
    bus->name = qemu_strdup(name);
240 02e2da45 Paul Brook
    LIST_INIT(&bus->children);
241 02e2da45 Paul Brook
    if (parent) {
242 02e2da45 Paul Brook
        LIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
243 02e2da45 Paul Brook
    }
244 02e2da45 Paul Brook
    return bus;
245 02e2da45 Paul Brook
}
246 cae4956e Gerd Hoffmann
247 cae4956e Gerd Hoffmann
#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
248 cae4956e Gerd Hoffmann
static void qbus_print(Monitor *mon, BusState *bus, int indent);
249 cae4956e Gerd Hoffmann
250 ee6847d1 Gerd Hoffmann
static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
251 ee6847d1 Gerd Hoffmann
                             const char *prefix, int indent)
252 ee6847d1 Gerd Hoffmann
{
253 ee6847d1 Gerd Hoffmann
    char buf[64];
254 ee6847d1 Gerd Hoffmann
255 ee6847d1 Gerd Hoffmann
    if (!props)
256 ee6847d1 Gerd Hoffmann
        return;
257 ee6847d1 Gerd Hoffmann
    while (props->name) {
258 ee6847d1 Gerd Hoffmann
        if (props->info->print) {
259 ee6847d1 Gerd Hoffmann
            props->info->print(dev, props, buf, sizeof(buf));
260 ee6847d1 Gerd Hoffmann
            qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
261 ee6847d1 Gerd Hoffmann
        }
262 ee6847d1 Gerd Hoffmann
        props++;
263 ee6847d1 Gerd Hoffmann
    }
264 ee6847d1 Gerd Hoffmann
}
265 ee6847d1 Gerd Hoffmann
266 cae4956e Gerd Hoffmann
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
267 cae4956e Gerd Hoffmann
{
268 cae4956e Gerd Hoffmann
    BusState *child;
269 ccb63de3 Gerd Hoffmann
    qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
270 ccb63de3 Gerd Hoffmann
                dev->id ? dev->id : "");
271 cae4956e Gerd Hoffmann
    indent += 2;
272 cae4956e Gerd Hoffmann
    if (dev->num_gpio_in) {
273 cae4956e Gerd Hoffmann
        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
274 cae4956e Gerd Hoffmann
    }
275 cae4956e Gerd Hoffmann
    if (dev->num_gpio_out) {
276 cae4956e Gerd Hoffmann
        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
277 cae4956e Gerd Hoffmann
    }
278 ee6847d1 Gerd Hoffmann
    qdev_print_props(mon, dev, dev->info->props, "dev", indent);
279 ee6847d1 Gerd Hoffmann
    qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
280 10c4c98a Gerd Hoffmann
    if (dev->parent_bus->info->print_dev)
281 10c4c98a Gerd Hoffmann
        dev->parent_bus->info->print_dev(mon, dev, indent);
282 cae4956e Gerd Hoffmann
    LIST_FOREACH(child, &dev->child_bus, sibling) {
283 cae4956e Gerd Hoffmann
        qbus_print(mon, child, indent);
284 cae4956e Gerd Hoffmann
    }
285 cae4956e Gerd Hoffmann
}
286 cae4956e Gerd Hoffmann
287 cae4956e Gerd Hoffmann
static void qbus_print(Monitor *mon, BusState *bus, int indent)
288 cae4956e Gerd Hoffmann
{
289 cae4956e Gerd Hoffmann
    struct DeviceState *dev;
290 cae4956e Gerd Hoffmann
291 cae4956e Gerd Hoffmann
    qdev_printf("bus: %s\n", bus->name);
292 cae4956e Gerd Hoffmann
    indent += 2;
293 10c4c98a Gerd Hoffmann
    qdev_printf("type %s\n", bus->info->name);
294 cae4956e Gerd Hoffmann
    LIST_FOREACH(dev, &bus->children, sibling) {
295 cae4956e Gerd Hoffmann
        qdev_print(mon, dev, indent);
296 cae4956e Gerd Hoffmann
    }
297 cae4956e Gerd Hoffmann
}
298 cae4956e Gerd Hoffmann
#undef qdev_printf
299 cae4956e Gerd Hoffmann
300 cae4956e Gerd Hoffmann
void do_info_qtree(Monitor *mon)
301 cae4956e Gerd Hoffmann
{
302 cae4956e Gerd Hoffmann
    if (main_system_bus)
303 cae4956e Gerd Hoffmann
        qbus_print(mon, main_system_bus, 0);
304 cae4956e Gerd Hoffmann
}