Statistics
| Branch: | Revision:

root / hw / qdev.c @ ee118d95

History | View | Annotate | Download (8.1 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 aae9460e Paul Brook
 * License along with this library; if not, write to the Free Software
18 aae9460e Paul Brook
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
19 aae9460e Paul Brook
 */
20 aae9460e Paul Brook
21 aae9460e Paul Brook
/* The theory here is that it should be possible to create a machine without
22 aae9460e Paul Brook
   knowledge of specific devices.  Historically board init routines have
23 aae9460e Paul Brook
   passed a bunch of arguments to each device, requiring the board know
24 aae9460e Paul Brook
   exactly which device it is dealing with.  This file provides an abstract
25 aae9460e Paul Brook
   API for device configuration and initialization.  Devices will generally
26 aae9460e Paul Brook
   inherit from a particular bus (e.g. PCI or I2C) rather than
27 aae9460e Paul Brook
   this API directly.  */
28 aae9460e Paul Brook
29 9d07d757 Paul Brook
#include "net.h"
30 aae9460e Paul Brook
#include "qdev.h"
31 aae9460e Paul Brook
#include "sysemu.h"
32 aae9460e Paul Brook
33 aae9460e Paul Brook
struct DeviceProperty {
34 aae9460e Paul Brook
    const char *name;
35 aae9460e Paul Brook
    union {
36 89a740e1 Paul Brook
        uint64_t i;
37 aae9460e Paul Brook
        void *ptr;
38 aae9460e Paul Brook
    } value;
39 aae9460e Paul Brook
    DeviceProperty *next;
40 aae9460e Paul Brook
};
41 aae9460e Paul Brook
42 aae9460e Paul Brook
struct DeviceType {
43 aae9460e Paul Brook
    const char *name;
44 02e2da45 Paul Brook
    DeviceInfo *info;
45 aae9460e Paul Brook
    int size;
46 aae9460e Paul Brook
    DeviceType *next;
47 aae9460e Paul Brook
};
48 aae9460e Paul Brook
49 02e2da45 Paul Brook
/* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
50 02e2da45 Paul Brook
BusState *main_system_bus;
51 4d6ae674 Paul Brook
52 aae9460e Paul Brook
static DeviceType *device_type_list;
53 aae9460e Paul Brook
54 aae9460e Paul Brook
/* Register a new device type.  */
55 02e2da45 Paul Brook
void qdev_register(const char *name, int size, DeviceInfo *info)
56 aae9460e Paul Brook
{
57 aae9460e Paul Brook
    DeviceType *t;
58 aae9460e Paul Brook
59 aae9460e Paul Brook
    assert(size >= sizeof(DeviceState));
60 aae9460e Paul Brook
61 aae9460e Paul Brook
    t = qemu_mallocz(sizeof(DeviceType));
62 aae9460e Paul Brook
    t->next = device_type_list;
63 aae9460e Paul Brook
    device_type_list = t;
64 aae9460e Paul Brook
    t->name = qemu_strdup(name);
65 aae9460e Paul Brook
    t->size = size;
66 02e2da45 Paul Brook
    t->info = info;
67 aae9460e Paul Brook
}
68 aae9460e Paul Brook
69 aae9460e Paul Brook
/* Create a new device.  This only initializes the device state structure
70 aae9460e Paul Brook
   and allows properties to be set.  qdev_init should be called to
71 aae9460e Paul Brook
   initialize the actual device emulation.  */
72 02e2da45 Paul Brook
DeviceState *qdev_create(BusState *bus, const char *name)
73 aae9460e Paul Brook
{
74 aae9460e Paul Brook
    DeviceType *t;
75 aae9460e Paul Brook
    DeviceState *dev;
76 aae9460e Paul Brook
77 aae9460e Paul Brook
    for (t = device_type_list; t; t = t->next) {
78 aae9460e Paul Brook
        if (strcmp(t->name, name) == 0) {
79 aae9460e Paul Brook
            break;
80 aae9460e Paul Brook
        }
81 aae9460e Paul Brook
    }
82 aae9460e Paul Brook
    if (!t) {
83 02e2da45 Paul Brook
        hw_error("Unknown device '%s'\n", name);
84 aae9460e Paul Brook
    }
85 aae9460e Paul Brook
86 aae9460e Paul Brook
    dev = qemu_mallocz(t->size);
87 aae9460e Paul Brook
    dev->name = name;
88 aae9460e Paul Brook
    dev->type = t;
89 02e2da45 Paul Brook
90 02e2da45 Paul Brook
    if (!bus) {
91 02e2da45 Paul Brook
        /* ???: This assumes system busses have no additional state.  */
92 02e2da45 Paul Brook
        if (!main_system_bus) {
93 02e2da45 Paul Brook
            main_system_bus = qbus_create(BUS_TYPE_SYSTEM, sizeof(BusState),
94 02e2da45 Paul Brook
                                          NULL, "main-system-bus");
95 02e2da45 Paul Brook
        }
96 02e2da45 Paul Brook
        bus = main_system_bus;
97 02e2da45 Paul Brook
    }
98 02e2da45 Paul Brook
    if (t->info->bus_type != bus->type) {
99 02e2da45 Paul Brook
        /* TODO: Print bus type names.  */
100 02e2da45 Paul Brook
        hw_error("Device '%s' on wrong bus type (%d/%d)", name,
101 02e2da45 Paul Brook
                 t->info->bus_type, bus->type);
102 02e2da45 Paul Brook
    }
103 02e2da45 Paul Brook
    dev->parent_bus = bus;
104 02e2da45 Paul Brook
    LIST_INSERT_HEAD(&bus->children, dev, sibling);
105 aae9460e Paul Brook
    return dev;
106 aae9460e Paul Brook
}
107 aae9460e Paul Brook
108 aae9460e Paul Brook
/* Initialize a device.  Device properties should be set before calling
109 aae9460e Paul Brook
   this function.  IRQs and MMIO regions should be connected/mapped after
110 aae9460e Paul Brook
   calling this function.  */
111 aae9460e Paul Brook
void qdev_init(DeviceState *dev)
112 aae9460e Paul Brook
{
113 02e2da45 Paul Brook
    dev->type->info->init(dev, dev->type->info);
114 02e2da45 Paul Brook
}
115 02e2da45 Paul Brook
116 02e2da45 Paul Brook
/* Unlink device from bus and free the structure.  */
117 02e2da45 Paul Brook
void qdev_free(DeviceState *dev)
118 02e2da45 Paul Brook
{
119 02e2da45 Paul Brook
    LIST_REMOVE(dev, sibling);
120 02e2da45 Paul Brook
    free(dev);
121 aae9460e Paul Brook
}
122 aae9460e Paul Brook
123 aae9460e Paul Brook
static DeviceProperty *create_prop(DeviceState *dev, const char *name)
124 aae9460e Paul Brook
{
125 aae9460e Paul Brook
    DeviceProperty *prop;
126 aae9460e Paul Brook
127 aae9460e Paul Brook
    /* TODO: Check for duplicate properties.  */
128 aae9460e Paul Brook
    prop = qemu_mallocz(sizeof(*prop));
129 aae9460e Paul Brook
    prop->name = qemu_strdup(name);
130 aae9460e Paul Brook
    prop->next = dev->props;
131 aae9460e Paul Brook
    dev->props = prop;
132 aae9460e Paul Brook
133 aae9460e Paul Brook
    return prop;
134 aae9460e Paul Brook
}
135 aae9460e Paul Brook
136 89a740e1 Paul Brook
void qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value)
137 aae9460e Paul Brook
{
138 aae9460e Paul Brook
    DeviceProperty *prop;
139 aae9460e Paul Brook
140 aae9460e Paul Brook
    prop = create_prop(dev, name);
141 aae9460e Paul Brook
    prop->value.i = value;
142 aae9460e Paul Brook
}
143 aae9460e Paul Brook
144 aae9460e Paul Brook
void qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value)
145 aae9460e Paul Brook
{
146 aae9460e Paul Brook
    DeviceProperty *prop;
147 aae9460e Paul Brook
148 aae9460e Paul Brook
    prop = create_prop(dev, name);
149 aae9460e Paul Brook
    prop->value.ptr = value;
150 aae9460e Paul Brook
}
151 aae9460e Paul Brook
152 9d07d757 Paul Brook
void qdev_set_netdev(DeviceState *dev, NICInfo *nd)
153 9d07d757 Paul Brook
{
154 9d07d757 Paul Brook
    assert(!dev->nd);
155 9d07d757 Paul Brook
    dev->nd = nd;
156 9d07d757 Paul Brook
}
157 9d07d757 Paul Brook
158 aae9460e Paul Brook
159 aae9460e Paul Brook
/* Get a character (serial) device interface.  */
160 aae9460e Paul Brook
CharDriverState *qdev_init_chardev(DeviceState *dev)
161 aae9460e Paul Brook
{
162 aae9460e Paul Brook
    static int next_serial;
163 aae9460e Paul Brook
    static int next_virtconsole;
164 aae9460e Paul Brook
    /* FIXME: This is a nasty hack that needs to go away.  */
165 aae9460e Paul Brook
    if (strncmp(dev->name, "virtio", 6) == 0) {
166 aae9460e Paul Brook
        return virtcon_hds[next_virtconsole++];
167 aae9460e Paul Brook
    } else {
168 aae9460e Paul Brook
        return serial_hds[next_serial++];
169 aae9460e Paul Brook
    }
170 aae9460e Paul Brook
}
171 aae9460e Paul Brook
172 02e2da45 Paul Brook
BusState *qdev_get_parent_bus(DeviceState *dev)
173 aae9460e Paul Brook
{
174 02e2da45 Paul Brook
    return dev->parent_bus;
175 aae9460e Paul Brook
}
176 aae9460e Paul Brook
177 aae9460e Paul Brook
static DeviceProperty *find_prop(DeviceState *dev, const char *name)
178 aae9460e Paul Brook
{
179 aae9460e Paul Brook
    DeviceProperty *prop;
180 aae9460e Paul Brook
181 aae9460e Paul Brook
    for (prop = dev->props; prop; prop = prop->next) {
182 aae9460e Paul Brook
        if (strcmp(prop->name, name) == 0) {
183 aae9460e Paul Brook
            return prop;
184 aae9460e Paul Brook
        }
185 aae9460e Paul Brook
    }
186 aae9460e Paul Brook
    return NULL;
187 aae9460e Paul Brook
}
188 aae9460e Paul Brook
189 aae9460e Paul Brook
uint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def)
190 aae9460e Paul Brook
{
191 aae9460e Paul Brook
    DeviceProperty *prop;
192 aae9460e Paul Brook
193 aae9460e Paul Brook
    prop = find_prop(dev, name);
194 aae9460e Paul Brook
    if (!prop)
195 aae9460e Paul Brook
        return def;
196 aae9460e Paul Brook
197 aae9460e Paul Brook
    return prop->value.i;
198 aae9460e Paul Brook
}
199 aae9460e Paul Brook
200 aae9460e Paul Brook
void *qdev_get_prop_ptr(DeviceState *dev, const char *name)
201 aae9460e Paul Brook
{
202 aae9460e Paul Brook
    DeviceProperty *prop;
203 aae9460e Paul Brook
204 aae9460e Paul Brook
    prop = find_prop(dev, name);
205 aae9460e Paul Brook
    assert(prop);
206 aae9460e Paul Brook
    return prop->value.ptr;
207 aae9460e Paul Brook
}
208 aae9460e Paul Brook
209 aae9460e Paul Brook
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
210 aae9460e Paul Brook
{
211 aae9460e Paul Brook
    assert(dev->num_gpio_in == 0);
212 aae9460e Paul Brook
    dev->num_gpio_in = n;
213 aae9460e Paul Brook
    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
214 aae9460e Paul Brook
}
215 aae9460e Paul Brook
216 aae9460e Paul Brook
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
217 aae9460e Paul Brook
{
218 aae9460e Paul Brook
    assert(dev->num_gpio_out == 0);
219 aae9460e Paul Brook
    dev->num_gpio_out = n;
220 aae9460e Paul Brook
    dev->gpio_out = pins;
221 aae9460e Paul Brook
}
222 aae9460e Paul Brook
223 aae9460e Paul Brook
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
224 aae9460e Paul Brook
{
225 aae9460e Paul Brook
    assert(n >= 0 && n < dev->num_gpio_in);
226 aae9460e Paul Brook
    return dev->gpio_in[n];
227 aae9460e Paul Brook
}
228 aae9460e Paul Brook
229 aae9460e Paul Brook
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
230 aae9460e Paul Brook
{
231 aae9460e Paul Brook
    assert(n >= 0 && n < dev->num_gpio_out);
232 aae9460e Paul Brook
    dev->gpio_out[n] = pin;
233 aae9460e Paul Brook
}
234 aae9460e Paul Brook
235 9d07d757 Paul Brook
VLANClientState *qdev_get_vlan_client(DeviceState *dev,
236 9d07d757 Paul Brook
                                      IOReadHandler *fd_read,
237 9d07d757 Paul Brook
                                      IOCanRWHandler *fd_can_read,
238 9d07d757 Paul Brook
                                      NetCleanup *cleanup,
239 9d07d757 Paul Brook
                                      void *opaque)
240 9d07d757 Paul Brook
{
241 9d07d757 Paul Brook
    NICInfo *nd = dev->nd;
242 9d07d757 Paul Brook
    assert(nd);
243 9d07d757 Paul Brook
    return qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
244 9d07d757 Paul Brook
                                fd_read, fd_can_read, cleanup, opaque);
245 9d07d757 Paul Brook
}
246 9d07d757 Paul Brook
247 9d07d757 Paul Brook
248 9d07d757 Paul Brook
void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
249 9d07d757 Paul Brook
{
250 9d07d757 Paul Brook
    memcpy(macaddr, dev->nd->macaddr, 6);
251 9d07d757 Paul Brook
}
252 9d07d757 Paul Brook
253 aae9460e Paul Brook
static int next_block_unit[IF_COUNT];
254 aae9460e Paul Brook
255 aae9460e Paul Brook
/* Get a block device.  This should only be used for single-drive devices
256 aae9460e Paul Brook
   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
257 aae9460e Paul Brook
   appropriate bus.  */
258 aae9460e Paul Brook
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
259 aae9460e Paul Brook
{
260 aae9460e Paul Brook
    int unit = next_block_unit[type]++;
261 aae9460e Paul Brook
    int index;
262 aae9460e Paul Brook
263 aae9460e Paul Brook
    index = drive_get_index(type, 0, unit);
264 aae9460e Paul Brook
    if (index == -1) {
265 aae9460e Paul Brook
        return NULL;
266 aae9460e Paul Brook
    }
267 aae9460e Paul Brook
    return drives_table[index].bdrv;
268 aae9460e Paul Brook
}
269 4d6ae674 Paul Brook
270 02e2da45 Paul Brook
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
271 4d6ae674 Paul Brook
{
272 02e2da45 Paul Brook
    BusState *bus;
273 4d6ae674 Paul Brook
274 02e2da45 Paul Brook
    LIST_FOREACH(bus, &dev->child_bus, sibling) {
275 4d6ae674 Paul Brook
        if (strcmp(name, bus->name) == 0) {
276 02e2da45 Paul Brook
            return bus;
277 4d6ae674 Paul Brook
        }
278 4d6ae674 Paul Brook
    }
279 4d6ae674 Paul Brook
    return NULL;
280 4d6ae674 Paul Brook
}
281 4d6ae674 Paul Brook
282 6f68ecb2 Paul Brook
static int next_scsi_bus;
283 6f68ecb2 Paul Brook
284 6f68ecb2 Paul Brook
/* Create a scsi bus, and attach devices to it.  */
285 6f68ecb2 Paul Brook
/* TODO: Actually create a scsi bus for hotplug to use.  */
286 6f68ecb2 Paul Brook
void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
287 6f68ecb2 Paul Brook
{
288 6f68ecb2 Paul Brook
   int bus = next_scsi_bus++;
289 6f68ecb2 Paul Brook
   int unit;
290 6f68ecb2 Paul Brook
   int index;
291 6f68ecb2 Paul Brook
292 6f68ecb2 Paul Brook
   for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
293 6f68ecb2 Paul Brook
       index = drive_get_index(IF_SCSI, bus, unit);
294 6f68ecb2 Paul Brook
       if (index == -1) {
295 6f68ecb2 Paul Brook
           continue;
296 6f68ecb2 Paul Brook
       }
297 6f68ecb2 Paul Brook
       attach(host, drives_table[index].bdrv, unit);
298 6f68ecb2 Paul Brook
   }
299 6f68ecb2 Paul Brook
}
300 02e2da45 Paul Brook
301 02e2da45 Paul Brook
BusState *qbus_create(BusType type, size_t size,
302 02e2da45 Paul Brook
                      DeviceState *parent, const char *name)
303 02e2da45 Paul Brook
{
304 02e2da45 Paul Brook
    BusState *bus;
305 02e2da45 Paul Brook
306 02e2da45 Paul Brook
    bus = qemu_mallocz(size);
307 02e2da45 Paul Brook
    bus->type = type;
308 02e2da45 Paul Brook
    bus->parent = parent;
309 02e2da45 Paul Brook
    bus->name = qemu_strdup(name);
310 02e2da45 Paul Brook
    LIST_INIT(&bus->children);
311 02e2da45 Paul Brook
    if (parent) {
312 02e2da45 Paul Brook
        LIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
313 02e2da45 Paul Brook
    }
314 02e2da45 Paul Brook
    return bus;
315 02e2da45 Paul Brook
}