Statistics
| Branch: | Revision:

root / hw / qdev.c @ d587e078

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