Statistics
| Branch: | Revision:

root / hw / qdev.c @ 3d0f4b9b

History | View | Annotate | Download (20.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 3ced9f7a Luiz Capitulino
#include "qerror.h"
33 aae9460e Paul Brook
34 3418bd25 Gerd Hoffmann
static int qdev_hotplug = 0;
35 3418bd25 Gerd Hoffmann
36 cdaed7c7 Gerd Hoffmann
/* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
37 b9aaf7f8 Blue Swirl
static BusState *main_system_bus;
38 4d6ae674 Paul Brook
39 0958b4cc Gerd Hoffmann
DeviceInfo *device_info_list;
40 aae9460e Paul Brook
41 8ffb1bcf Gerd Hoffmann
static BusState *qbus_find_recursive(BusState *bus, const char *name,
42 8ffb1bcf Gerd Hoffmann
                                     const BusInfo *info);
43 8ffb1bcf Gerd Hoffmann
static BusState *qbus_find(const char *path);
44 8ffb1bcf Gerd Hoffmann
45 aae9460e Paul Brook
/* Register a new device type.  */
46 074f2fff Gerd Hoffmann
void qdev_register(DeviceInfo *info)
47 aae9460e Paul Brook
{
48 074f2fff Gerd Hoffmann
    assert(info->size >= sizeof(DeviceState));
49 042f84d0 Gerd Hoffmann
    assert(!info->next);
50 aae9460e Paul Brook
51 042f84d0 Gerd Hoffmann
    info->next = device_info_list;
52 042f84d0 Gerd Hoffmann
    device_info_list = info;
53 aae9460e Paul Brook
}
54 aae9460e Paul Brook
55 81ebb98b Gerd Hoffmann
static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
56 81ebb98b Gerd Hoffmann
{
57 81ebb98b Gerd Hoffmann
    DeviceInfo *info;
58 81ebb98b Gerd Hoffmann
59 3320e56e Gerd Hoffmann
    /* first check device names */
60 81ebb98b Gerd Hoffmann
    for (info = device_info_list; info != NULL; info = info->next) {
61 81ebb98b Gerd Hoffmann
        if (bus_info && info->bus_info != bus_info)
62 81ebb98b Gerd Hoffmann
            continue;
63 81ebb98b Gerd Hoffmann
        if (strcmp(info->name, name) != 0)
64 81ebb98b Gerd Hoffmann
            continue;
65 81ebb98b Gerd Hoffmann
        return info;
66 81ebb98b Gerd Hoffmann
    }
67 3320e56e Gerd Hoffmann
68 3320e56e Gerd Hoffmann
    /* failing that check the aliases */
69 3320e56e Gerd Hoffmann
    for (info = device_info_list; info != NULL; info = info->next) {
70 3320e56e Gerd Hoffmann
        if (bus_info && info->bus_info != bus_info)
71 3320e56e Gerd Hoffmann
            continue;
72 3320e56e Gerd Hoffmann
        if (!info->alias)
73 3320e56e Gerd Hoffmann
            continue;
74 3320e56e Gerd Hoffmann
        if (strcmp(info->alias, name) != 0)
75 3320e56e Gerd Hoffmann
            continue;
76 3320e56e Gerd Hoffmann
        return info;
77 3320e56e Gerd Hoffmann
    }
78 81ebb98b Gerd Hoffmann
    return NULL;
79 81ebb98b Gerd Hoffmann
}
80 81ebb98b Gerd Hoffmann
81 aae9460e Paul Brook
/* Create a new device.  This only initializes the device state structure
82 aae9460e Paul Brook
   and allows properties to be set.  qdev_init should be called to
83 aae9460e Paul Brook
   initialize the actual device emulation.  */
84 02e2da45 Paul Brook
DeviceState *qdev_create(BusState *bus, const char *name)
85 aae9460e Paul Brook
{
86 042f84d0 Gerd Hoffmann
    DeviceInfo *info;
87 aae9460e Paul Brook
    DeviceState *dev;
88 aae9460e Paul Brook
89 10c4c98a Gerd Hoffmann
    if (!bus) {
90 10c4c98a Gerd Hoffmann
        if (!main_system_bus) {
91 10c4c98a Gerd Hoffmann
            main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
92 aae9460e Paul Brook
        }
93 10c4c98a Gerd Hoffmann
        bus = main_system_bus;
94 10c4c98a Gerd Hoffmann
    }
95 10c4c98a Gerd Hoffmann
96 81ebb98b Gerd Hoffmann
    info = qdev_find_info(bus->info, name);
97 042f84d0 Gerd Hoffmann
    if (!info) {
98 10c4c98a Gerd Hoffmann
        hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
99 aae9460e Paul Brook
    }
100 aae9460e Paul Brook
101 042f84d0 Gerd Hoffmann
    dev = qemu_mallocz(info->size);
102 042f84d0 Gerd Hoffmann
    dev->info = info;
103 02e2da45 Paul Brook
    dev->parent_bus = bus;
104 ee6847d1 Gerd Hoffmann
    qdev_prop_set_defaults(dev, dev->info->props);
105 ee6847d1 Gerd Hoffmann
    qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
106 458fb679 Gerd Hoffmann
    qdev_prop_set_globals(dev);
107 72cf2d4f Blue Swirl
    QLIST_INSERT_HEAD(&bus->children, dev, sibling);
108 3418bd25 Gerd Hoffmann
    if (qdev_hotplug) {
109 3418bd25 Gerd Hoffmann
        assert(bus->allow_hotplug);
110 3418bd25 Gerd Hoffmann
        dev->hotplugged = 1;
111 3418bd25 Gerd Hoffmann
    }
112 131ec1bd Gerd Hoffmann
    dev->state = DEV_STATE_CREATED;
113 aae9460e Paul Brook
    return dev;
114 aae9460e Paul Brook
}
115 aae9460e Paul Brook
116 1b524b04 Gerd Hoffmann
static int qdev_print_devinfo(DeviceInfo *info, char *dest, int len)
117 1b524b04 Gerd Hoffmann
{
118 1b524b04 Gerd Hoffmann
    int pos = 0;
119 22f2e344 Gerd Hoffmann
    int ret;
120 22f2e344 Gerd Hoffmann
121 22f2e344 Gerd Hoffmann
    ret = snprintf(dest+pos, len-pos, "name \"%s\", bus %s",
122 22f2e344 Gerd Hoffmann
                   info->name, info->bus_info->name);
123 22f2e344 Gerd Hoffmann
    pos += MIN(len-pos,ret);
124 22f2e344 Gerd Hoffmann
    if (info->alias) {
125 22f2e344 Gerd Hoffmann
        ret = snprintf(dest+pos, len-pos, ", alias \"%s\"", info->alias);
126 22f2e344 Gerd Hoffmann
        pos += MIN(len-pos,ret);
127 22f2e344 Gerd Hoffmann
    }
128 22f2e344 Gerd Hoffmann
    if (info->desc) {
129 22f2e344 Gerd Hoffmann
        ret = snprintf(dest+pos, len-pos, ", desc \"%s\"", info->desc);
130 22f2e344 Gerd Hoffmann
        pos += MIN(len-pos,ret);
131 22f2e344 Gerd Hoffmann
    }
132 22f2e344 Gerd Hoffmann
    if (info->no_user) {
133 22f2e344 Gerd Hoffmann
        ret = snprintf(dest+pos, len-pos, ", no-user");
134 22f2e344 Gerd Hoffmann
        pos += MIN(len-pos,ret);
135 22f2e344 Gerd Hoffmann
    }
136 1b524b04 Gerd Hoffmann
    return pos;
137 1b524b04 Gerd Hoffmann
}
138 1b524b04 Gerd Hoffmann
139 f31d07d1 Gerd Hoffmann
static int set_property(const char *name, const char *value, void *opaque)
140 8ffb1bcf Gerd Hoffmann
{
141 f31d07d1 Gerd Hoffmann
    DeviceState *dev = opaque;
142 f31d07d1 Gerd Hoffmann
143 f31d07d1 Gerd Hoffmann
    if (strcmp(name, "driver") == 0)
144 f31d07d1 Gerd Hoffmann
        return 0;
145 f31d07d1 Gerd Hoffmann
    if (strcmp(name, "bus") == 0)
146 f31d07d1 Gerd Hoffmann
        return 0;
147 f31d07d1 Gerd Hoffmann
148 3df04ac3 Mark McLoughlin
    if (qdev_prop_parse(dev, name, value) == -1) {
149 286c2321 Gerd Hoffmann
        qemu_error("can't set property \"%s\" to \"%s\" for \"%s\"\n",
150 286c2321 Gerd Hoffmann
                   name, value, dev->info->name);
151 f31d07d1 Gerd Hoffmann
        return -1;
152 f31d07d1 Gerd Hoffmann
    }
153 f31d07d1 Gerd Hoffmann
    return 0;
154 f31d07d1 Gerd Hoffmann
}
155 f31d07d1 Gerd Hoffmann
156 ff952ba2 Markus Armbruster
int qdev_device_help(QemuOpts *opts)
157 ff952ba2 Markus Armbruster
{
158 ff952ba2 Markus Armbruster
    const char *driver;
159 ff952ba2 Markus Armbruster
    DeviceInfo *info;
160 ff952ba2 Markus Armbruster
    char msg[256];
161 08350cf0 Markus Armbruster
    Property *prop;
162 ff952ba2 Markus Armbruster
163 ff952ba2 Markus Armbruster
    driver = qemu_opt_get(opts, "driver");
164 ff952ba2 Markus Armbruster
    if (driver && !strcmp(driver, "?")) {
165 ff952ba2 Markus Armbruster
        for (info = device_info_list; info != NULL; info = info->next) {
166 ff952ba2 Markus Armbruster
            qdev_print_devinfo(info, msg, sizeof(msg));
167 ff952ba2 Markus Armbruster
            qemu_error("%s\n", msg);
168 ff952ba2 Markus Armbruster
        }
169 ff952ba2 Markus Armbruster
        return 1;
170 ff952ba2 Markus Armbruster
    }
171 ff952ba2 Markus Armbruster
172 08350cf0 Markus Armbruster
    if (!qemu_opt_get(opts, "?")) {
173 08350cf0 Markus Armbruster
        return 0;
174 08350cf0 Markus Armbruster
    }
175 08350cf0 Markus Armbruster
176 08350cf0 Markus Armbruster
    info = qdev_find_info(NULL, driver);
177 08350cf0 Markus Armbruster
    if (!info) {
178 08350cf0 Markus Armbruster
        return 0;
179 08350cf0 Markus Armbruster
    }
180 08350cf0 Markus Armbruster
181 08350cf0 Markus Armbruster
    for (prop = info->props; prop && prop->name; prop++) {
182 117f8eb8 Markus Armbruster
        qemu_error("%s.%s=%s\n", info->name, prop->name, prop->info->name);
183 08350cf0 Markus Armbruster
    }
184 08350cf0 Markus Armbruster
    return 1;
185 ff952ba2 Markus Armbruster
}
186 ff952ba2 Markus Armbruster
187 f31d07d1 Gerd Hoffmann
DeviceState *qdev_device_add(QemuOpts *opts)
188 f31d07d1 Gerd Hoffmann
{
189 f31d07d1 Gerd Hoffmann
    const char *driver, *path, *id;
190 8ffb1bcf Gerd Hoffmann
    DeviceInfo *info;
191 8ffb1bcf Gerd Hoffmann
    DeviceState *qdev;
192 8ffb1bcf Gerd Hoffmann
    BusState *bus;
193 8ffb1bcf Gerd Hoffmann
194 f31d07d1 Gerd Hoffmann
    driver = qemu_opt_get(opts, "driver");
195 f31d07d1 Gerd Hoffmann
    if (!driver) {
196 286c2321 Gerd Hoffmann
        qemu_error("-device: no driver specified\n");
197 8ffb1bcf Gerd Hoffmann
        return NULL;
198 8ffb1bcf Gerd Hoffmann
    }
199 f31d07d1 Gerd Hoffmann
200 f31d07d1 Gerd Hoffmann
    /* find driver */
201 8ffb1bcf Gerd Hoffmann
    info = qdev_find_info(NULL, driver);
202 8ffb1bcf Gerd Hoffmann
    if (!info) {
203 3ced9f7a Luiz Capitulino
        qemu_error_new(QERR_DEVICE_NOT_FOUND, driver);
204 8ffb1bcf Gerd Hoffmann
        return NULL;
205 8ffb1bcf Gerd Hoffmann
    }
206 8ffb1bcf Gerd Hoffmann
    if (info->no_user) {
207 286c2321 Gerd Hoffmann
        qemu_error("device \"%s\" can't be added via command line\n",
208 286c2321 Gerd Hoffmann
                   info->name);
209 8ffb1bcf Gerd Hoffmann
        return NULL;
210 8ffb1bcf Gerd Hoffmann
    }
211 8ffb1bcf Gerd Hoffmann
212 f31d07d1 Gerd Hoffmann
    /* find bus */
213 f31d07d1 Gerd Hoffmann
    path = qemu_opt_get(opts, "bus");
214 f31d07d1 Gerd Hoffmann
    if (path != NULL) {
215 8ffb1bcf Gerd Hoffmann
        bus = qbus_find(path);
216 8ffb1bcf Gerd Hoffmann
    } else {
217 8ffb1bcf Gerd Hoffmann
        bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
218 8ffb1bcf Gerd Hoffmann
    }
219 75570088 Gerd Hoffmann
    if (!bus) {
220 75570088 Gerd Hoffmann
        qemu_error("Did not find %s bus for %s\n",
221 75570088 Gerd Hoffmann
                   path ? path : info->bus_info->name, info->name);
222 f31d07d1 Gerd Hoffmann
        return NULL;
223 75570088 Gerd Hoffmann
    }
224 3418bd25 Gerd Hoffmann
    if (qdev_hotplug && !bus->allow_hotplug) {
225 3418bd25 Gerd Hoffmann
        qemu_error("Bus %s does not support hotplugging\n",
226 3418bd25 Gerd Hoffmann
                   bus->name);
227 3418bd25 Gerd Hoffmann
        return NULL;
228 3418bd25 Gerd Hoffmann
    }
229 8ffb1bcf Gerd Hoffmann
230 f31d07d1 Gerd Hoffmann
    /* create device, set properties */
231 f31d07d1 Gerd Hoffmann
    qdev = qdev_create(bus, driver);
232 f31d07d1 Gerd Hoffmann
    id = qemu_opts_id(opts);
233 f31d07d1 Gerd Hoffmann
    if (id) {
234 f31d07d1 Gerd Hoffmann
        qdev->id = id;
235 f31d07d1 Gerd Hoffmann
    }
236 f31d07d1 Gerd Hoffmann
    if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
237 f31d07d1 Gerd Hoffmann
        qdev_free(qdev);
238 f31d07d1 Gerd Hoffmann
        return NULL;
239 8ffb1bcf Gerd Hoffmann
    }
240 5c17ca25 Markus Armbruster
    if (qdev_init(qdev) < 0) {
241 c8cd1fcd Amit Shah
        qemu_error("Error initializing device %s\n", driver);
242 81a322d4 Gerd Hoffmann
        return NULL;
243 81a322d4 Gerd Hoffmann
    }
244 ef80b466 Gerd Hoffmann
    qdev->opts = opts;
245 8ffb1bcf Gerd Hoffmann
    return qdev;
246 8ffb1bcf Gerd Hoffmann
}
247 8ffb1bcf Gerd Hoffmann
248 7f23f812 Michael S. Tsirkin
static void qdev_reset(void *opaque)
249 7f23f812 Michael S. Tsirkin
{
250 7f23f812 Michael S. Tsirkin
    DeviceState *dev = opaque;
251 7f23f812 Michael S. Tsirkin
    if (dev->info->reset)
252 7f23f812 Michael S. Tsirkin
        dev->info->reset(dev);
253 7f23f812 Michael S. Tsirkin
}
254 7f23f812 Michael S. Tsirkin
255 aae9460e Paul Brook
/* Initialize a device.  Device properties should be set before calling
256 aae9460e Paul Brook
   this function.  IRQs and MMIO regions should be connected/mapped after
257 18cfeb52 Markus Armbruster
   calling this function.
258 18cfeb52 Markus Armbruster
   On failure, destroy the device and return negative value.
259 18cfeb52 Markus Armbruster
   Return 0 on success.  */
260 81a322d4 Gerd Hoffmann
int qdev_init(DeviceState *dev)
261 aae9460e Paul Brook
{
262 959f733a Gerd Hoffmann
    int rc;
263 959f733a Gerd Hoffmann
264 131ec1bd Gerd Hoffmann
    assert(dev->state == DEV_STATE_CREATED);
265 959f733a Gerd Hoffmann
    rc = dev->info->init(dev, dev->info);
266 18cfeb52 Markus Armbruster
    if (rc < 0) {
267 18cfeb52 Markus Armbruster
        qdev_free(dev);
268 959f733a Gerd Hoffmann
        return rc;
269 18cfeb52 Markus Armbruster
    }
270 7f23f812 Michael S. Tsirkin
    qemu_register_reset(qdev_reset, dev);
271 391a079e Gerd Hoffmann
    if (dev->info->vmsd)
272 391a079e Gerd Hoffmann
        vmstate_register(-1, dev->info->vmsd, dev);
273 131ec1bd Gerd Hoffmann
    dev->state = DEV_STATE_INITIALIZED;
274 959f733a Gerd Hoffmann
    return 0;
275 02e2da45 Paul Brook
}
276 02e2da45 Paul Brook
277 3418bd25 Gerd Hoffmann
int qdev_unplug(DeviceState *dev)
278 3418bd25 Gerd Hoffmann
{
279 3418bd25 Gerd Hoffmann
    if (!dev->parent_bus->allow_hotplug) {
280 3418bd25 Gerd Hoffmann
        qemu_error("Bus %s does not support hotplugging\n",
281 3418bd25 Gerd Hoffmann
                   dev->parent_bus->name);
282 3418bd25 Gerd Hoffmann
        return -1;
283 3418bd25 Gerd Hoffmann
    }
284 593831de Amit Shah
    assert(dev->info->unplug != NULL);
285 593831de Amit Shah
286 3418bd25 Gerd Hoffmann
    return dev->info->unplug(dev);
287 3418bd25 Gerd Hoffmann
}
288 3418bd25 Gerd Hoffmann
289 3418bd25 Gerd Hoffmann
/* can be used as ->unplug() callback for the simple cases */
290 3418bd25 Gerd Hoffmann
int qdev_simple_unplug_cb(DeviceState *dev)
291 3418bd25 Gerd Hoffmann
{
292 3418bd25 Gerd Hoffmann
    /* just zap it */
293 3418bd25 Gerd Hoffmann
    qdev_free(dev);
294 3418bd25 Gerd Hoffmann
    return 0;
295 3418bd25 Gerd Hoffmann
}
296 3418bd25 Gerd Hoffmann
297 e23a1b33 Markus Armbruster
/* Like qdev_init(), but terminate program via hw_error() instead of
298 e23a1b33 Markus Armbruster
   returning an error value.  This is okay during machine creation.
299 e23a1b33 Markus Armbruster
   Don't use for hotplug, because there callers need to recover from
300 e23a1b33 Markus Armbruster
   failure.  Exception: if you know the device's init() callback can't
301 e23a1b33 Markus Armbruster
   fail, then qdev_init_nofail() can't fail either, and is therefore
302 e23a1b33 Markus Armbruster
   usable even then.  But relying on the device implementation that
303 e23a1b33 Markus Armbruster
   way is somewhat unclean, and best avoided.  */
304 e23a1b33 Markus Armbruster
void qdev_init_nofail(DeviceState *dev)
305 e23a1b33 Markus Armbruster
{
306 e23a1b33 Markus Armbruster
    DeviceInfo *info = dev->info;
307 e23a1b33 Markus Armbruster
308 e23a1b33 Markus Armbruster
    if (qdev_init(dev) < 0)
309 e23a1b33 Markus Armbruster
        hw_error("Initialization of device %s failed\n", info->name);
310 e23a1b33 Markus Armbruster
}
311 e23a1b33 Markus Armbruster
312 02e2da45 Paul Brook
/* Unlink device from bus and free the structure.  */
313 02e2da45 Paul Brook
void qdev_free(DeviceState *dev)
314 02e2da45 Paul Brook
{
315 131ec1bd Gerd Hoffmann
    BusState *bus;
316 131ec1bd Gerd Hoffmann
317 131ec1bd Gerd Hoffmann
    if (dev->state == DEV_STATE_INITIALIZED) {
318 131ec1bd Gerd Hoffmann
        while (dev->num_child_bus) {
319 131ec1bd Gerd Hoffmann
            bus = QLIST_FIRST(&dev->child_bus);
320 131ec1bd Gerd Hoffmann
            qbus_free(bus);
321 131ec1bd Gerd Hoffmann
        }
322 131ec1bd Gerd Hoffmann
        if (dev->info->vmsd)
323 131ec1bd Gerd Hoffmann
            vmstate_unregister(dev->info->vmsd, dev);
324 d29275f1 Gerd Hoffmann
        if (dev->info->exit)
325 d29275f1 Gerd Hoffmann
            dev->info->exit(dev);
326 ef80b466 Gerd Hoffmann
        if (dev->opts)
327 ef80b466 Gerd Hoffmann
            qemu_opts_del(dev->opts);
328 131ec1bd Gerd Hoffmann
    }
329 7f23f812 Michael S. Tsirkin
    qemu_unregister_reset(qdev_reset, dev);
330 72cf2d4f Blue Swirl
    QLIST_REMOVE(dev, sibling);
331 ccb63de3 Gerd Hoffmann
    qemu_free(dev);
332 aae9460e Paul Brook
}
333 aae9460e Paul Brook
334 3418bd25 Gerd Hoffmann
void qdev_machine_creation_done(void)
335 3418bd25 Gerd Hoffmann
{
336 3418bd25 Gerd Hoffmann
    /*
337 3418bd25 Gerd Hoffmann
     * ok, initial machine setup is done, starting from now we can
338 3418bd25 Gerd Hoffmann
     * only create hotpluggable devices
339 3418bd25 Gerd Hoffmann
     */
340 3418bd25 Gerd Hoffmann
    qdev_hotplug = 1;
341 3418bd25 Gerd Hoffmann
}
342 3418bd25 Gerd Hoffmann
343 aae9460e Paul Brook
/* Get a character (serial) device interface.  */
344 aae9460e Paul Brook
CharDriverState *qdev_init_chardev(DeviceState *dev)
345 aae9460e Paul Brook
{
346 aae9460e Paul Brook
    static int next_serial;
347 98b19252 Amit Shah
348 98b19252 Amit Shah
    /* FIXME: This function needs to go away: use chardev properties!  */
349 98b19252 Amit Shah
    return serial_hds[next_serial++];
350 aae9460e Paul Brook
}
351 aae9460e Paul Brook
352 02e2da45 Paul Brook
BusState *qdev_get_parent_bus(DeviceState *dev)
353 aae9460e Paul Brook
{
354 02e2da45 Paul Brook
    return dev->parent_bus;
355 aae9460e Paul Brook
}
356 aae9460e Paul Brook
357 aae9460e Paul Brook
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
358 aae9460e Paul Brook
{
359 aae9460e Paul Brook
    assert(dev->num_gpio_in == 0);
360 aae9460e Paul Brook
    dev->num_gpio_in = n;
361 aae9460e Paul Brook
    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
362 aae9460e Paul Brook
}
363 aae9460e Paul Brook
364 aae9460e Paul Brook
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
365 aae9460e Paul Brook
{
366 aae9460e Paul Brook
    assert(dev->num_gpio_out == 0);
367 aae9460e Paul Brook
    dev->num_gpio_out = n;
368 aae9460e Paul Brook
    dev->gpio_out = pins;
369 aae9460e Paul Brook
}
370 aae9460e Paul Brook
371 aae9460e Paul Brook
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
372 aae9460e Paul Brook
{
373 aae9460e Paul Brook
    assert(n >= 0 && n < dev->num_gpio_in);
374 aae9460e Paul Brook
    return dev->gpio_in[n];
375 aae9460e Paul Brook
}
376 aae9460e Paul Brook
377 aae9460e Paul Brook
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
378 aae9460e Paul Brook
{
379 aae9460e Paul Brook
    assert(n >= 0 && n < dev->num_gpio_out);
380 aae9460e Paul Brook
    dev->gpio_out[n] = pin;
381 aae9460e Paul Brook
}
382 aae9460e Paul Brook
383 ed16ab5a Gerd Hoffmann
void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
384 ed16ab5a Gerd Hoffmann
{
385 ed16ab5a Gerd Hoffmann
    qdev_prop_set_macaddr(dev, "mac", nd->macaddr);
386 ed16ab5a Gerd Hoffmann
    if (nd->vlan)
387 ed16ab5a Gerd Hoffmann
        qdev_prop_set_vlan(dev, "vlan", nd->vlan);
388 ed16ab5a Gerd Hoffmann
    if (nd->netdev)
389 ed16ab5a Gerd Hoffmann
        qdev_prop_set_netdev(dev, "netdev", nd->netdev);
390 97b15621 Gerd Hoffmann
    if (nd->nvectors != NIC_NVECTORS_UNSPECIFIED &&
391 97b15621 Gerd Hoffmann
        qdev_prop_exists(dev, "vectors")) {
392 97b15621 Gerd Hoffmann
        qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
393 97b15621 Gerd Hoffmann
    }
394 ed16ab5a Gerd Hoffmann
}
395 ed16ab5a Gerd Hoffmann
396 aae9460e Paul Brook
static int next_block_unit[IF_COUNT];
397 aae9460e Paul Brook
398 aae9460e Paul Brook
/* Get a block device.  This should only be used for single-drive devices
399 aae9460e Paul Brook
   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
400 aae9460e Paul Brook
   appropriate bus.  */
401 aae9460e Paul Brook
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
402 aae9460e Paul Brook
{
403 aae9460e Paul Brook
    int unit = next_block_unit[type]++;
404 751c6a17 Gerd Hoffmann
    DriveInfo *dinfo;
405 aae9460e Paul Brook
406 751c6a17 Gerd Hoffmann
    dinfo = drive_get(type, 0, unit);
407 751c6a17 Gerd Hoffmann
    return dinfo ? dinfo->bdrv : NULL;
408 aae9460e Paul Brook
}
409 4d6ae674 Paul Brook
410 02e2da45 Paul Brook
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
411 4d6ae674 Paul Brook
{
412 02e2da45 Paul Brook
    BusState *bus;
413 4d6ae674 Paul Brook
414 72cf2d4f Blue Swirl
    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
415 4d6ae674 Paul Brook
        if (strcmp(name, bus->name) == 0) {
416 02e2da45 Paul Brook
            return bus;
417 4d6ae674 Paul Brook
        }
418 4d6ae674 Paul Brook
    }
419 4d6ae674 Paul Brook
    return NULL;
420 4d6ae674 Paul Brook
}
421 4d6ae674 Paul Brook
422 8ffb1bcf Gerd Hoffmann
static BusState *qbus_find_recursive(BusState *bus, const char *name,
423 8ffb1bcf Gerd Hoffmann
                                     const BusInfo *info)
424 8ffb1bcf Gerd Hoffmann
{
425 8ffb1bcf Gerd Hoffmann
    DeviceState *dev;
426 8ffb1bcf Gerd Hoffmann
    BusState *child, *ret;
427 8ffb1bcf Gerd Hoffmann
    int match = 1;
428 8ffb1bcf Gerd Hoffmann
429 8ffb1bcf Gerd Hoffmann
    if (name && (strcmp(bus->name, name) != 0)) {
430 8ffb1bcf Gerd Hoffmann
        match = 0;
431 8ffb1bcf Gerd Hoffmann
    }
432 8ffb1bcf Gerd Hoffmann
    if (info && (bus->info != info)) {
433 8ffb1bcf Gerd Hoffmann
        match = 0;
434 8ffb1bcf Gerd Hoffmann
    }
435 8ffb1bcf Gerd Hoffmann
    if (match) {
436 8ffb1bcf Gerd Hoffmann
        return bus;
437 8ffb1bcf Gerd Hoffmann
    }
438 8ffb1bcf Gerd Hoffmann
439 72cf2d4f Blue Swirl
    QLIST_FOREACH(dev, &bus->children, sibling) {
440 72cf2d4f Blue Swirl
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
441 8ffb1bcf Gerd Hoffmann
            ret = qbus_find_recursive(child, name, info);
442 8ffb1bcf Gerd Hoffmann
            if (ret) {
443 8ffb1bcf Gerd Hoffmann
                return ret;
444 8ffb1bcf Gerd Hoffmann
            }
445 8ffb1bcf Gerd Hoffmann
        }
446 8ffb1bcf Gerd Hoffmann
    }
447 8ffb1bcf Gerd Hoffmann
    return NULL;
448 8ffb1bcf Gerd Hoffmann
}
449 8ffb1bcf Gerd Hoffmann
450 3418bd25 Gerd Hoffmann
static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
451 3418bd25 Gerd Hoffmann
{
452 3418bd25 Gerd Hoffmann
    DeviceState *dev, *ret;
453 3418bd25 Gerd Hoffmann
    BusState *child;
454 3418bd25 Gerd Hoffmann
455 3418bd25 Gerd Hoffmann
    QLIST_FOREACH(dev, &bus->children, sibling) {
456 3418bd25 Gerd Hoffmann
        if (dev->id && strcmp(dev->id, id) == 0)
457 3418bd25 Gerd Hoffmann
            return dev;
458 3418bd25 Gerd Hoffmann
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
459 3418bd25 Gerd Hoffmann
            ret = qdev_find_recursive(child, id);
460 3418bd25 Gerd Hoffmann
            if (ret) {
461 3418bd25 Gerd Hoffmann
                return ret;
462 3418bd25 Gerd Hoffmann
            }
463 3418bd25 Gerd Hoffmann
        }
464 3418bd25 Gerd Hoffmann
    }
465 3418bd25 Gerd Hoffmann
    return NULL;
466 3418bd25 Gerd Hoffmann
}
467 3418bd25 Gerd Hoffmann
468 8ffb1bcf Gerd Hoffmann
static void qbus_list_bus(DeviceState *dev, char *dest, int len)
469 8ffb1bcf Gerd Hoffmann
{
470 8ffb1bcf Gerd Hoffmann
    BusState *child;
471 8ffb1bcf Gerd Hoffmann
    const char *sep = " ";
472 8ffb1bcf Gerd Hoffmann
    int pos = 0;
473 8ffb1bcf Gerd Hoffmann
474 8ffb1bcf Gerd Hoffmann
    pos += snprintf(dest+pos, len-pos,"child busses at \"%s\":",
475 8ffb1bcf Gerd Hoffmann
                    dev->id ? dev->id : dev->info->name);
476 72cf2d4f Blue Swirl
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
477 8ffb1bcf Gerd Hoffmann
        pos += snprintf(dest+pos, len-pos, "%s\"%s\"", sep, child->name);
478 8ffb1bcf Gerd Hoffmann
        sep = ", ";
479 8ffb1bcf Gerd Hoffmann
    }
480 8ffb1bcf Gerd Hoffmann
}
481 8ffb1bcf Gerd Hoffmann
482 8ffb1bcf Gerd Hoffmann
static void qbus_list_dev(BusState *bus, char *dest, int len)
483 8ffb1bcf Gerd Hoffmann
{
484 8ffb1bcf Gerd Hoffmann
    DeviceState *dev;
485 8ffb1bcf Gerd Hoffmann
    const char *sep = " ";
486 8ffb1bcf Gerd Hoffmann
    int pos = 0;
487 8ffb1bcf Gerd Hoffmann
488 8ffb1bcf Gerd Hoffmann
    pos += snprintf(dest+pos, len-pos, "devices at \"%s\":",
489 8ffb1bcf Gerd Hoffmann
                    bus->name);
490 72cf2d4f Blue Swirl
    QLIST_FOREACH(dev, &bus->children, sibling) {
491 8ffb1bcf Gerd Hoffmann
        pos += snprintf(dest+pos, len-pos, "%s\"%s\"",
492 8ffb1bcf Gerd Hoffmann
                        sep, dev->info->name);
493 8ffb1bcf Gerd Hoffmann
        if (dev->id)
494 8ffb1bcf Gerd Hoffmann
            pos += snprintf(dest+pos, len-pos, "/\"%s\"", dev->id);
495 8ffb1bcf Gerd Hoffmann
        sep = ", ";
496 8ffb1bcf Gerd Hoffmann
    }
497 8ffb1bcf Gerd Hoffmann
}
498 8ffb1bcf Gerd Hoffmann
499 8ffb1bcf Gerd Hoffmann
static BusState *qbus_find_bus(DeviceState *dev, char *elem)
500 8ffb1bcf Gerd Hoffmann
{
501 8ffb1bcf Gerd Hoffmann
    BusState *child;
502 8ffb1bcf Gerd Hoffmann
503 72cf2d4f Blue Swirl
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
504 8ffb1bcf Gerd Hoffmann
        if (strcmp(child->name, elem) == 0) {
505 8ffb1bcf Gerd Hoffmann
            return child;
506 8ffb1bcf Gerd Hoffmann
        }
507 8ffb1bcf Gerd Hoffmann
    }
508 8ffb1bcf Gerd Hoffmann
    return NULL;
509 8ffb1bcf Gerd Hoffmann
}
510 8ffb1bcf Gerd Hoffmann
511 8ffb1bcf Gerd Hoffmann
static DeviceState *qbus_find_dev(BusState *bus, char *elem)
512 8ffb1bcf Gerd Hoffmann
{
513 8ffb1bcf Gerd Hoffmann
    DeviceState *dev;
514 8ffb1bcf Gerd Hoffmann
515 8ffb1bcf Gerd Hoffmann
    /*
516 8ffb1bcf Gerd Hoffmann
     * try to match in order:
517 8ffb1bcf Gerd Hoffmann
     *   (1) instance id, if present
518 8ffb1bcf Gerd Hoffmann
     *   (2) driver name
519 8ffb1bcf Gerd Hoffmann
     *   (3) driver alias, if present
520 8ffb1bcf Gerd Hoffmann
     */
521 72cf2d4f Blue Swirl
    QLIST_FOREACH(dev, &bus->children, sibling) {
522 8ffb1bcf Gerd Hoffmann
        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
523 8ffb1bcf Gerd Hoffmann
            return dev;
524 8ffb1bcf Gerd Hoffmann
        }
525 8ffb1bcf Gerd Hoffmann
    }
526 72cf2d4f Blue Swirl
    QLIST_FOREACH(dev, &bus->children, sibling) {
527 8ffb1bcf Gerd Hoffmann
        if (strcmp(dev->info->name, elem) == 0) {
528 8ffb1bcf Gerd Hoffmann
            return dev;
529 8ffb1bcf Gerd Hoffmann
        }
530 8ffb1bcf Gerd Hoffmann
    }
531 72cf2d4f Blue Swirl
    QLIST_FOREACH(dev, &bus->children, sibling) {
532 8ffb1bcf Gerd Hoffmann
        if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
533 8ffb1bcf Gerd Hoffmann
            return dev;
534 8ffb1bcf Gerd Hoffmann
        }
535 8ffb1bcf Gerd Hoffmann
    }
536 8ffb1bcf Gerd Hoffmann
    return NULL;
537 8ffb1bcf Gerd Hoffmann
}
538 8ffb1bcf Gerd Hoffmann
539 8ffb1bcf Gerd Hoffmann
static BusState *qbus_find(const char *path)
540 8ffb1bcf Gerd Hoffmann
{
541 8ffb1bcf Gerd Hoffmann
    DeviceState *dev;
542 8ffb1bcf Gerd Hoffmann
    BusState *bus;
543 8ffb1bcf Gerd Hoffmann
    char elem[128], msg[256];
544 8ffb1bcf Gerd Hoffmann
    int pos, len;
545 8ffb1bcf Gerd Hoffmann
546 8ffb1bcf Gerd Hoffmann
    /* find start element */
547 8ffb1bcf Gerd Hoffmann
    if (path[0] == '/') {
548 8ffb1bcf Gerd Hoffmann
        bus = main_system_bus;
549 8ffb1bcf Gerd Hoffmann
        pos = 0;
550 8ffb1bcf Gerd Hoffmann
    } else {
551 8ffb1bcf Gerd Hoffmann
        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
552 286c2321 Gerd Hoffmann
            qemu_error("path parse error (\"%s\")\n", path);
553 8ffb1bcf Gerd Hoffmann
            return NULL;
554 8ffb1bcf Gerd Hoffmann
        }
555 8ffb1bcf Gerd Hoffmann
        bus = qbus_find_recursive(main_system_bus, elem, NULL);
556 8ffb1bcf Gerd Hoffmann
        if (!bus) {
557 286c2321 Gerd Hoffmann
            qemu_error("bus \"%s\" not found\n", elem);
558 8ffb1bcf Gerd Hoffmann
            return NULL;
559 8ffb1bcf Gerd Hoffmann
        }
560 8ffb1bcf Gerd Hoffmann
        pos = len;
561 8ffb1bcf Gerd Hoffmann
    }
562 8ffb1bcf Gerd Hoffmann
563 8ffb1bcf Gerd Hoffmann
    for (;;) {
564 8ffb1bcf Gerd Hoffmann
        if (path[pos] == '\0') {
565 8ffb1bcf Gerd Hoffmann
            /* we are done */
566 8ffb1bcf Gerd Hoffmann
            return bus;
567 8ffb1bcf Gerd Hoffmann
        }
568 8ffb1bcf Gerd Hoffmann
569 8ffb1bcf Gerd Hoffmann
        /* find device */
570 8ffb1bcf Gerd Hoffmann
        if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
571 286c2321 Gerd Hoffmann
            qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
572 8ffb1bcf Gerd Hoffmann
            return NULL;
573 8ffb1bcf Gerd Hoffmann
        }
574 8ffb1bcf Gerd Hoffmann
        pos += len;
575 8ffb1bcf Gerd Hoffmann
        dev = qbus_find_dev(bus, elem);
576 8ffb1bcf Gerd Hoffmann
        if (!dev) {
577 8ffb1bcf Gerd Hoffmann
            qbus_list_dev(bus, msg, sizeof(msg));
578 286c2321 Gerd Hoffmann
            qemu_error("device \"%s\" not found\n%s\n", elem, msg);
579 8ffb1bcf Gerd Hoffmann
            return NULL;
580 8ffb1bcf Gerd Hoffmann
        }
581 8ffb1bcf Gerd Hoffmann
        if (path[pos] == '\0') {
582 8ffb1bcf Gerd Hoffmann
            /* last specified element is a device.  If it has exactly
583 8ffb1bcf Gerd Hoffmann
             * one child bus accept it nevertheless */
584 8ffb1bcf Gerd Hoffmann
            switch (dev->num_child_bus) {
585 8ffb1bcf Gerd Hoffmann
            case 0:
586 286c2321 Gerd Hoffmann
                qemu_error("device has no child bus (%s)\n", path);
587 8ffb1bcf Gerd Hoffmann
                return NULL;
588 8ffb1bcf Gerd Hoffmann
            case 1:
589 72cf2d4f Blue Swirl
                return QLIST_FIRST(&dev->child_bus);
590 8ffb1bcf Gerd Hoffmann
            default:
591 8ffb1bcf Gerd Hoffmann
                qbus_list_bus(dev, msg, sizeof(msg));
592 286c2321 Gerd Hoffmann
                qemu_error("device has multiple child busses (%s)\n%s\n",
593 286c2321 Gerd Hoffmann
                           path, msg);
594 8ffb1bcf Gerd Hoffmann
                return NULL;
595 8ffb1bcf Gerd Hoffmann
            }
596 8ffb1bcf Gerd Hoffmann
        }
597 8ffb1bcf Gerd Hoffmann
598 8ffb1bcf Gerd Hoffmann
        /* find bus */
599 8ffb1bcf Gerd Hoffmann
        if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
600 286c2321 Gerd Hoffmann
            qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
601 8ffb1bcf Gerd Hoffmann
            return NULL;
602 8ffb1bcf Gerd Hoffmann
        }
603 8ffb1bcf Gerd Hoffmann
        pos += len;
604 8ffb1bcf Gerd Hoffmann
        bus = qbus_find_bus(dev, elem);
605 8ffb1bcf Gerd Hoffmann
        if (!bus) {
606 8ffb1bcf Gerd Hoffmann
            qbus_list_bus(dev, msg, sizeof(msg));
607 286c2321 Gerd Hoffmann
            qemu_error("child bus \"%s\" not found\n%s\n", elem, msg);
608 8ffb1bcf Gerd Hoffmann
            return NULL;
609 8ffb1bcf Gerd Hoffmann
        }
610 8ffb1bcf Gerd Hoffmann
    }
611 8ffb1bcf Gerd Hoffmann
}
612 8ffb1bcf Gerd Hoffmann
613 cd739fb6 Gerd Hoffmann
void qbus_create_inplace(BusState *bus, BusInfo *info,
614 cd739fb6 Gerd Hoffmann
                         DeviceState *parent, const char *name)
615 02e2da45 Paul Brook
{
616 d271de9f Gerd Hoffmann
    char *buf;
617 d271de9f Gerd Hoffmann
    int i,len;
618 02e2da45 Paul Brook
619 10c4c98a Gerd Hoffmann
    bus->info = info;
620 02e2da45 Paul Brook
    bus->parent = parent;
621 d271de9f Gerd Hoffmann
622 d271de9f Gerd Hoffmann
    if (name) {
623 d271de9f Gerd Hoffmann
        /* use supplied name */
624 d271de9f Gerd Hoffmann
        bus->name = qemu_strdup(name);
625 d271de9f Gerd Hoffmann
    } else if (parent && parent->id) {
626 d271de9f Gerd Hoffmann
        /* parent device has id -> use it for bus name */
627 d271de9f Gerd Hoffmann
        len = strlen(parent->id) + 16;
628 d271de9f Gerd Hoffmann
        buf = qemu_malloc(len);
629 d271de9f Gerd Hoffmann
        snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
630 d271de9f Gerd Hoffmann
        bus->name = buf;
631 d271de9f Gerd Hoffmann
    } else {
632 d271de9f Gerd Hoffmann
        /* no id -> use lowercase bus type for bus name */
633 d271de9f Gerd Hoffmann
        len = strlen(info->name) + 16;
634 d271de9f Gerd Hoffmann
        buf = qemu_malloc(len);
635 d271de9f Gerd Hoffmann
        len = snprintf(buf, len, "%s.%d", info->name,
636 d271de9f Gerd Hoffmann
                       parent ? parent->num_child_bus : 0);
637 d271de9f Gerd Hoffmann
        for (i = 0; i < len; i++)
638 bb87ece5 Christoph Egger
            buf[i] = qemu_tolower(buf[i]);
639 d271de9f Gerd Hoffmann
        bus->name = buf;
640 d271de9f Gerd Hoffmann
    }
641 d271de9f Gerd Hoffmann
642 72cf2d4f Blue Swirl
    QLIST_INIT(&bus->children);
643 02e2da45 Paul Brook
    if (parent) {
644 72cf2d4f Blue Swirl
        QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
645 d271de9f Gerd Hoffmann
        parent->num_child_bus++;
646 02e2da45 Paul Brook
    }
647 cd739fb6 Gerd Hoffmann
648 cd739fb6 Gerd Hoffmann
}
649 cd739fb6 Gerd Hoffmann
650 cd739fb6 Gerd Hoffmann
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
651 cd739fb6 Gerd Hoffmann
{
652 cd739fb6 Gerd Hoffmann
    BusState *bus;
653 cd739fb6 Gerd Hoffmann
654 cd739fb6 Gerd Hoffmann
    bus = qemu_mallocz(info->size);
655 cd739fb6 Gerd Hoffmann
    bus->qdev_allocated = 1;
656 cd739fb6 Gerd Hoffmann
    qbus_create_inplace(bus, info, parent, name);
657 02e2da45 Paul Brook
    return bus;
658 02e2da45 Paul Brook
}
659 cae4956e Gerd Hoffmann
660 131ec1bd Gerd Hoffmann
void qbus_free(BusState *bus)
661 131ec1bd Gerd Hoffmann
{
662 131ec1bd Gerd Hoffmann
    DeviceState *dev;
663 131ec1bd Gerd Hoffmann
664 131ec1bd Gerd Hoffmann
    while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
665 131ec1bd Gerd Hoffmann
        qdev_free(dev);
666 131ec1bd Gerd Hoffmann
    }
667 131ec1bd Gerd Hoffmann
    if (bus->parent) {
668 131ec1bd Gerd Hoffmann
        QLIST_REMOVE(bus, sibling);
669 131ec1bd Gerd Hoffmann
        bus->parent->num_child_bus--;
670 131ec1bd Gerd Hoffmann
    }
671 131ec1bd Gerd Hoffmann
    if (bus->qdev_allocated) {
672 131ec1bd Gerd Hoffmann
        qemu_free(bus);
673 131ec1bd Gerd Hoffmann
    }
674 131ec1bd Gerd Hoffmann
}
675 131ec1bd Gerd Hoffmann
676 cae4956e Gerd Hoffmann
#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
677 cae4956e Gerd Hoffmann
static void qbus_print(Monitor *mon, BusState *bus, int indent);
678 cae4956e Gerd Hoffmann
679 ee6847d1 Gerd Hoffmann
static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
680 ee6847d1 Gerd Hoffmann
                             const char *prefix, int indent)
681 ee6847d1 Gerd Hoffmann
{
682 ee6847d1 Gerd Hoffmann
    char buf[64];
683 ee6847d1 Gerd Hoffmann
684 ee6847d1 Gerd Hoffmann
    if (!props)
685 ee6847d1 Gerd Hoffmann
        return;
686 ee6847d1 Gerd Hoffmann
    while (props->name) {
687 ee6847d1 Gerd Hoffmann
        if (props->info->print) {
688 ee6847d1 Gerd Hoffmann
            props->info->print(dev, props, buf, sizeof(buf));
689 ee6847d1 Gerd Hoffmann
            qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
690 ee6847d1 Gerd Hoffmann
        }
691 ee6847d1 Gerd Hoffmann
        props++;
692 ee6847d1 Gerd Hoffmann
    }
693 ee6847d1 Gerd Hoffmann
}
694 ee6847d1 Gerd Hoffmann
695 cae4956e Gerd Hoffmann
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
696 cae4956e Gerd Hoffmann
{
697 cae4956e Gerd Hoffmann
    BusState *child;
698 ccb63de3 Gerd Hoffmann
    qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
699 ccb63de3 Gerd Hoffmann
                dev->id ? dev->id : "");
700 cae4956e Gerd Hoffmann
    indent += 2;
701 cae4956e Gerd Hoffmann
    if (dev->num_gpio_in) {
702 cae4956e Gerd Hoffmann
        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
703 cae4956e Gerd Hoffmann
    }
704 cae4956e Gerd Hoffmann
    if (dev->num_gpio_out) {
705 cae4956e Gerd Hoffmann
        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
706 cae4956e Gerd Hoffmann
    }
707 ee6847d1 Gerd Hoffmann
    qdev_print_props(mon, dev, dev->info->props, "dev", indent);
708 ee6847d1 Gerd Hoffmann
    qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
709 10c4c98a Gerd Hoffmann
    if (dev->parent_bus->info->print_dev)
710 10c4c98a Gerd Hoffmann
        dev->parent_bus->info->print_dev(mon, dev, indent);
711 72cf2d4f Blue Swirl
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
712 cae4956e Gerd Hoffmann
        qbus_print(mon, child, indent);
713 cae4956e Gerd Hoffmann
    }
714 cae4956e Gerd Hoffmann
}
715 cae4956e Gerd Hoffmann
716 cae4956e Gerd Hoffmann
static void qbus_print(Monitor *mon, BusState *bus, int indent)
717 cae4956e Gerd Hoffmann
{
718 cae4956e Gerd Hoffmann
    struct DeviceState *dev;
719 cae4956e Gerd Hoffmann
720 cae4956e Gerd Hoffmann
    qdev_printf("bus: %s\n", bus->name);
721 cae4956e Gerd Hoffmann
    indent += 2;
722 10c4c98a Gerd Hoffmann
    qdev_printf("type %s\n", bus->info->name);
723 72cf2d4f Blue Swirl
    QLIST_FOREACH(dev, &bus->children, sibling) {
724 cae4956e Gerd Hoffmann
        qdev_print(mon, dev, indent);
725 cae4956e Gerd Hoffmann
    }
726 cae4956e Gerd Hoffmann
}
727 cae4956e Gerd Hoffmann
#undef qdev_printf
728 cae4956e Gerd Hoffmann
729 cae4956e Gerd Hoffmann
void do_info_qtree(Monitor *mon)
730 cae4956e Gerd Hoffmann
{
731 cae4956e Gerd Hoffmann
    if (main_system_bus)
732 cae4956e Gerd Hoffmann
        qbus_print(mon, main_system_bus, 0);
733 cae4956e Gerd Hoffmann
}
734 9316d30f Gerd Hoffmann
735 f6c64e0e Gerd Hoffmann
void do_info_qdm(Monitor *mon)
736 9316d30f Gerd Hoffmann
{
737 9316d30f Gerd Hoffmann
    DeviceInfo *info;
738 9316d30f Gerd Hoffmann
    char msg[256];
739 9316d30f Gerd Hoffmann
740 9316d30f Gerd Hoffmann
    for (info = device_info_list; info != NULL; info = info->next) {
741 9316d30f Gerd Hoffmann
        qdev_print_devinfo(info, msg, sizeof(msg));
742 9316d30f Gerd Hoffmann
        monitor_printf(mon, "%s\n", msg);
743 9316d30f Gerd Hoffmann
    }
744 9316d30f Gerd Hoffmann
}
745 3418bd25 Gerd Hoffmann
746 3418bd25 Gerd Hoffmann
void do_device_add(Monitor *mon, const QDict *qdict)
747 3418bd25 Gerd Hoffmann
{
748 3418bd25 Gerd Hoffmann
    QemuOpts *opts;
749 3418bd25 Gerd Hoffmann
750 3418bd25 Gerd Hoffmann
    opts = qemu_opts_parse(&qemu_device_opts,
751 3418bd25 Gerd Hoffmann
                           qdict_get_str(qdict, "config"), "driver");
752 0f853a38 Kevin Wolf
    if (opts) {
753 0f853a38 Kevin Wolf
        if (qdev_device_help(opts) || qdev_device_add(opts) == NULL) {
754 0f853a38 Kevin Wolf
            qemu_opts_del(opts);
755 0f853a38 Kevin Wolf
        }
756 0f853a38 Kevin Wolf
    }
757 3418bd25 Gerd Hoffmann
}
758 3418bd25 Gerd Hoffmann
759 3418bd25 Gerd Hoffmann
void do_device_del(Monitor *mon, const QDict *qdict)
760 3418bd25 Gerd Hoffmann
{
761 3418bd25 Gerd Hoffmann
    const char *id = qdict_get_str(qdict, "id");
762 3418bd25 Gerd Hoffmann
    DeviceState *dev;
763 3418bd25 Gerd Hoffmann
764 3418bd25 Gerd Hoffmann
    dev = qdev_find_recursive(main_system_bus, id);
765 3418bd25 Gerd Hoffmann
    if (NULL == dev) {
766 3418bd25 Gerd Hoffmann
        qemu_error("Device '%s' not found\n", id);
767 3418bd25 Gerd Hoffmann
        return;
768 3418bd25 Gerd Hoffmann
    }
769 3418bd25 Gerd Hoffmann
    qdev_unplug(dev);
770 3418bd25 Gerd Hoffmann
}