Statistics
| Branch: | Revision:

root / hw / qdev.c @ 18cfeb52

History | View | Annotate | Download (19.9 kB)

1 aae9460e Paul Brook
/*
2 aae9460e Paul Brook
 *  Dynamic device configuration and creation.
3 aae9460e Paul Brook
 *
4 aae9460e Paul Brook
 *  Copyright (c) 2009 CodeSourcery
5 aae9460e Paul Brook
 *
6 aae9460e Paul Brook
 * This library is free software; you can redistribute it and/or
7 aae9460e Paul Brook
 * modify it under the terms of the GNU Lesser General Public
8 aae9460e Paul Brook
 * License as published by the Free Software Foundation; either
9 aae9460e Paul Brook
 * version 2 of the License, or (at your option) any later version.
10 aae9460e Paul Brook
 *
11 aae9460e Paul Brook
 * This library is distributed in the hope that it will be useful,
12 aae9460e Paul Brook
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 aae9460e Paul Brook
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 aae9460e Paul Brook
 * Lesser General Public License for more details.
15 aae9460e Paul Brook
 *
16 aae9460e Paul Brook
 * You should have received a copy of the GNU Lesser General Public
17 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 aae9460e Paul Brook
 */
19 aae9460e Paul Brook
20 aae9460e Paul Brook
/* The theory here is that it should be possible to create a machine without
21 aae9460e Paul Brook
   knowledge of specific devices.  Historically board init routines have
22 aae9460e Paul Brook
   passed a bunch of arguments to each device, requiring the board know
23 aae9460e Paul Brook
   exactly which device it is dealing with.  This file provides an abstract
24 aae9460e Paul Brook
   API for device configuration and initialization.  Devices will generally
25 aae9460e Paul Brook
   inherit from a particular bus (e.g. PCI or I2C) rather than
26 aae9460e Paul Brook
   this API directly.  */
27 aae9460e Paul Brook
28 9d07d757 Paul Brook
#include "net.h"
29 aae9460e Paul Brook
#include "qdev.h"
30 aae9460e Paul Brook
#include "sysemu.h"
31 cae4956e Gerd Hoffmann
#include "monitor.h"
32 aae9460e Paul Brook
33 3418bd25 Gerd Hoffmann
static int qdev_hotplug = 0;
34 3418bd25 Gerd Hoffmann
35 cdaed7c7 Gerd Hoffmann
/* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
36 b9aaf7f8 Blue Swirl
static BusState *main_system_bus;
37 4d6ae674 Paul Brook
38 042f84d0 Gerd Hoffmann
static DeviceInfo *device_info_list;
39 aae9460e Paul Brook
40 8ffb1bcf Gerd Hoffmann
static BusState *qbus_find_recursive(BusState *bus, const char *name,
41 8ffb1bcf Gerd Hoffmann
                                     const BusInfo *info);
42 8ffb1bcf Gerd Hoffmann
static BusState *qbus_find(const char *path);
43 8ffb1bcf Gerd Hoffmann
44 aae9460e Paul Brook
/* Register a new device type.  */
45 074f2fff Gerd Hoffmann
void qdev_register(DeviceInfo *info)
46 aae9460e Paul Brook
{
47 074f2fff Gerd Hoffmann
    assert(info->size >= sizeof(DeviceState));
48 042f84d0 Gerd Hoffmann
    assert(!info->next);
49 aae9460e Paul Brook
50 042f84d0 Gerd Hoffmann
    info->next = device_info_list;
51 042f84d0 Gerd Hoffmann
    device_info_list = info;
52 aae9460e Paul Brook
}
53 aae9460e Paul Brook
54 81ebb98b Gerd Hoffmann
static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
55 81ebb98b Gerd Hoffmann
{
56 81ebb98b Gerd Hoffmann
    DeviceInfo *info;
57 81ebb98b Gerd Hoffmann
58 3320e56e Gerd Hoffmann
    /* first check device names */
59 81ebb98b Gerd Hoffmann
    for (info = device_info_list; info != NULL; info = info->next) {
60 81ebb98b Gerd Hoffmann
        if (bus_info && info->bus_info != bus_info)
61 81ebb98b Gerd Hoffmann
            continue;
62 81ebb98b Gerd Hoffmann
        if (strcmp(info->name, name) != 0)
63 81ebb98b Gerd Hoffmann
            continue;
64 81ebb98b Gerd Hoffmann
        return info;
65 81ebb98b Gerd Hoffmann
    }
66 3320e56e Gerd Hoffmann
67 3320e56e Gerd Hoffmann
    /* failing that check the aliases */
68 3320e56e Gerd Hoffmann
    for (info = device_info_list; info != NULL; info = info->next) {
69 3320e56e Gerd Hoffmann
        if (bus_info && info->bus_info != bus_info)
70 3320e56e Gerd Hoffmann
            continue;
71 3320e56e Gerd Hoffmann
        if (!info->alias)
72 3320e56e Gerd Hoffmann
            continue;
73 3320e56e Gerd Hoffmann
        if (strcmp(info->alias, name) != 0)
74 3320e56e Gerd Hoffmann
            continue;
75 3320e56e Gerd Hoffmann
        return info;
76 3320e56e Gerd Hoffmann
    }
77 81ebb98b Gerd Hoffmann
    return NULL;
78 81ebb98b Gerd Hoffmann
}
79 81ebb98b Gerd Hoffmann
80 aae9460e Paul Brook
/* Create a new device.  This only initializes the device state structure
81 aae9460e Paul Brook
   and allows properties to be set.  qdev_init should be called to
82 aae9460e Paul Brook
   initialize the actual device emulation.  */
83 02e2da45 Paul Brook
DeviceState *qdev_create(BusState *bus, const char *name)
84 aae9460e Paul Brook
{
85 042f84d0 Gerd Hoffmann
    DeviceInfo *info;
86 aae9460e Paul Brook
    DeviceState *dev;
87 aae9460e Paul Brook
88 10c4c98a Gerd Hoffmann
    if (!bus) {
89 10c4c98a Gerd Hoffmann
        if (!main_system_bus) {
90 10c4c98a Gerd Hoffmann
            main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
91 aae9460e Paul Brook
        }
92 10c4c98a Gerd Hoffmann
        bus = main_system_bus;
93 10c4c98a Gerd Hoffmann
    }
94 10c4c98a Gerd Hoffmann
95 81ebb98b Gerd Hoffmann
    info = qdev_find_info(bus->info, name);
96 042f84d0 Gerd Hoffmann
    if (!info) {
97 10c4c98a Gerd Hoffmann
        hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
98 aae9460e Paul Brook
    }
99 aae9460e Paul Brook
100 042f84d0 Gerd Hoffmann
    dev = qemu_mallocz(info->size);
101 042f84d0 Gerd Hoffmann
    dev->info = info;
102 02e2da45 Paul Brook
    dev->parent_bus = bus;
103 ee6847d1 Gerd Hoffmann
    qdev_prop_set_defaults(dev, dev->info->props);
104 ee6847d1 Gerd Hoffmann
    qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
105 b6b61144 Gerd Hoffmann
    qdev_prop_set_compat(dev);
106 72cf2d4f Blue Swirl
    QLIST_INSERT_HEAD(&bus->children, dev, sibling);
107 3418bd25 Gerd Hoffmann
    if (qdev_hotplug) {
108 3418bd25 Gerd Hoffmann
        assert(bus->allow_hotplug);
109 3418bd25 Gerd Hoffmann
        dev->hotplugged = 1;
110 3418bd25 Gerd Hoffmann
    }
111 131ec1bd Gerd Hoffmann
    dev->state = DEV_STATE_CREATED;
112 aae9460e Paul Brook
    return dev;
113 aae9460e Paul Brook
}
114 aae9460e Paul Brook
115 1b524b04 Gerd Hoffmann
static int qdev_print_devinfo(DeviceInfo *info, char *dest, int len)
116 1b524b04 Gerd Hoffmann
{
117 1b524b04 Gerd Hoffmann
    int pos = 0;
118 22f2e344 Gerd Hoffmann
    int ret;
119 22f2e344 Gerd Hoffmann
120 22f2e344 Gerd Hoffmann
    ret = snprintf(dest+pos, len-pos, "name \"%s\", bus %s",
121 22f2e344 Gerd Hoffmann
                   info->name, info->bus_info->name);
122 22f2e344 Gerd Hoffmann
    pos += MIN(len-pos,ret);
123 22f2e344 Gerd Hoffmann
    if (info->alias) {
124 22f2e344 Gerd Hoffmann
        ret = snprintf(dest+pos, len-pos, ", alias \"%s\"", info->alias);
125 22f2e344 Gerd Hoffmann
        pos += MIN(len-pos,ret);
126 22f2e344 Gerd Hoffmann
    }
127 22f2e344 Gerd Hoffmann
    if (info->desc) {
128 22f2e344 Gerd Hoffmann
        ret = snprintf(dest+pos, len-pos, ", desc \"%s\"", info->desc);
129 22f2e344 Gerd Hoffmann
        pos += MIN(len-pos,ret);
130 22f2e344 Gerd Hoffmann
    }
131 22f2e344 Gerd Hoffmann
    if (info->no_user) {
132 22f2e344 Gerd Hoffmann
        ret = snprintf(dest+pos, len-pos, ", no-user");
133 22f2e344 Gerd Hoffmann
        pos += MIN(len-pos,ret);
134 22f2e344 Gerd Hoffmann
    }
135 1b524b04 Gerd Hoffmann
    return pos;
136 1b524b04 Gerd Hoffmann
}
137 1b524b04 Gerd Hoffmann
138 f31d07d1 Gerd Hoffmann
static int set_property(const char *name, const char *value, void *opaque)
139 8ffb1bcf Gerd Hoffmann
{
140 f31d07d1 Gerd Hoffmann
    DeviceState *dev = opaque;
141 f31d07d1 Gerd Hoffmann
142 f31d07d1 Gerd Hoffmann
    if (strcmp(name, "driver") == 0)
143 f31d07d1 Gerd Hoffmann
        return 0;
144 f31d07d1 Gerd Hoffmann
    if (strcmp(name, "bus") == 0)
145 f31d07d1 Gerd Hoffmann
        return 0;
146 f31d07d1 Gerd Hoffmann
147 3df04ac3 Mark McLoughlin
    if (qdev_prop_parse(dev, name, value) == -1) {
148 286c2321 Gerd Hoffmann
        qemu_error("can't set property \"%s\" to \"%s\" for \"%s\"\n",
149 286c2321 Gerd Hoffmann
                   name, value, dev->info->name);
150 f31d07d1 Gerd Hoffmann
        return -1;
151 f31d07d1 Gerd Hoffmann
    }
152 f31d07d1 Gerd Hoffmann
    return 0;
153 f31d07d1 Gerd Hoffmann
}
154 f31d07d1 Gerd Hoffmann
155 f31d07d1 Gerd Hoffmann
DeviceState *qdev_device_add(QemuOpts *opts)
156 f31d07d1 Gerd Hoffmann
{
157 f31d07d1 Gerd Hoffmann
    const char *driver, *path, *id;
158 8ffb1bcf Gerd Hoffmann
    DeviceInfo *info;
159 8ffb1bcf Gerd Hoffmann
    DeviceState *qdev;
160 8ffb1bcf Gerd Hoffmann
    BusState *bus;
161 8ffb1bcf Gerd Hoffmann
162 f31d07d1 Gerd Hoffmann
    driver = qemu_opt_get(opts, "driver");
163 f31d07d1 Gerd Hoffmann
    if (!driver) {
164 286c2321 Gerd Hoffmann
        qemu_error("-device: no driver specified\n");
165 8ffb1bcf Gerd Hoffmann
        return NULL;
166 8ffb1bcf Gerd Hoffmann
    }
167 8ffb1bcf Gerd Hoffmann
    if (strcmp(driver, "?") == 0) {
168 1b524b04 Gerd Hoffmann
        char msg[256];
169 8ffb1bcf Gerd Hoffmann
        for (info = device_info_list; info != NULL; info = info->next) {
170 1b524b04 Gerd Hoffmann
            qdev_print_devinfo(info, msg, sizeof(msg));
171 286c2321 Gerd Hoffmann
            qemu_error("%s\n", msg);
172 8ffb1bcf Gerd Hoffmann
        }
173 8ffb1bcf Gerd Hoffmann
        return NULL;
174 8ffb1bcf Gerd Hoffmann
    }
175 f31d07d1 Gerd Hoffmann
176 f31d07d1 Gerd Hoffmann
    /* find driver */
177 8ffb1bcf Gerd Hoffmann
    info = qdev_find_info(NULL, driver);
178 8ffb1bcf Gerd Hoffmann
    if (!info) {
179 286c2321 Gerd Hoffmann
        qemu_error("Device \"%s\" not found.  Try -device '?' for a list.\n",
180 286c2321 Gerd Hoffmann
                   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 81a322d4 Gerd Hoffmann
    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 3418bd25 Gerd Hoffmann
    return dev->info->unplug(dev);
262 3418bd25 Gerd Hoffmann
}
263 3418bd25 Gerd Hoffmann
264 3418bd25 Gerd Hoffmann
/* can be used as ->unplug() callback for the simple cases */
265 3418bd25 Gerd Hoffmann
int qdev_simple_unplug_cb(DeviceState *dev)
266 3418bd25 Gerd Hoffmann
{
267 3418bd25 Gerd Hoffmann
    /* just zap it */
268 3418bd25 Gerd Hoffmann
    qdev_free(dev);
269 3418bd25 Gerd Hoffmann
    return 0;
270 3418bd25 Gerd Hoffmann
}
271 3418bd25 Gerd Hoffmann
272 02e2da45 Paul Brook
/* Unlink device from bus and free the structure.  */
273 02e2da45 Paul Brook
void qdev_free(DeviceState *dev)
274 02e2da45 Paul Brook
{
275 131ec1bd Gerd Hoffmann
    BusState *bus;
276 131ec1bd Gerd Hoffmann
277 131ec1bd Gerd Hoffmann
    if (dev->state == DEV_STATE_INITIALIZED) {
278 131ec1bd Gerd Hoffmann
        while (dev->num_child_bus) {
279 131ec1bd Gerd Hoffmann
            bus = QLIST_FIRST(&dev->child_bus);
280 131ec1bd Gerd Hoffmann
            qbus_free(bus);
281 131ec1bd Gerd Hoffmann
        }
282 391a079e Gerd Hoffmann
#if 0 /* FIXME: need sane vmstate_unregister function */
283 131ec1bd Gerd Hoffmann
        if (dev->info->vmsd)
284 131ec1bd Gerd Hoffmann
            vmstate_unregister(dev->info->vmsd, dev);
285 391a079e Gerd Hoffmann
#endif
286 d29275f1 Gerd Hoffmann
        if (dev->info->exit)
287 d29275f1 Gerd Hoffmann
            dev->info->exit(dev);
288 ef80b466 Gerd Hoffmann
        if (dev->opts)
289 ef80b466 Gerd Hoffmann
            qemu_opts_del(dev->opts);
290 131ec1bd Gerd Hoffmann
    }
291 7f23f812 Michael S. Tsirkin
    qemu_unregister_reset(qdev_reset, dev);
292 72cf2d4f Blue Swirl
    QLIST_REMOVE(dev, sibling);
293 ccb63de3 Gerd Hoffmann
    qemu_free(dev);
294 aae9460e Paul Brook
}
295 aae9460e Paul Brook
296 3418bd25 Gerd Hoffmann
void qdev_machine_creation_done(void)
297 3418bd25 Gerd Hoffmann
{
298 3418bd25 Gerd Hoffmann
    /*
299 3418bd25 Gerd Hoffmann
     * ok, initial machine setup is done, starting from now we can
300 3418bd25 Gerd Hoffmann
     * only create hotpluggable devices
301 3418bd25 Gerd Hoffmann
     */
302 3418bd25 Gerd Hoffmann
    qdev_hotplug = 1;
303 3418bd25 Gerd Hoffmann
}
304 3418bd25 Gerd Hoffmann
305 aae9460e Paul Brook
/* Get a character (serial) device interface.  */
306 aae9460e Paul Brook
CharDriverState *qdev_init_chardev(DeviceState *dev)
307 aae9460e Paul Brook
{
308 aae9460e Paul Brook
    static int next_serial;
309 aae9460e Paul Brook
    static int next_virtconsole;
310 aae9460e Paul Brook
    /* FIXME: This is a nasty hack that needs to go away.  */
311 042f84d0 Gerd Hoffmann
    if (strncmp(dev->info->name, "virtio", 6) == 0) {
312 aae9460e Paul Brook
        return virtcon_hds[next_virtconsole++];
313 aae9460e Paul Brook
    } else {
314 aae9460e Paul Brook
        return serial_hds[next_serial++];
315 aae9460e Paul Brook
    }
316 aae9460e Paul Brook
}
317 aae9460e Paul Brook
318 02e2da45 Paul Brook
BusState *qdev_get_parent_bus(DeviceState *dev)
319 aae9460e Paul Brook
{
320 02e2da45 Paul Brook
    return dev->parent_bus;
321 aae9460e Paul Brook
}
322 aae9460e Paul Brook
323 aae9460e Paul Brook
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
324 aae9460e Paul Brook
{
325 aae9460e Paul Brook
    assert(dev->num_gpio_in == 0);
326 aae9460e Paul Brook
    dev->num_gpio_in = n;
327 aae9460e Paul Brook
    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
328 aae9460e Paul Brook
}
329 aae9460e Paul Brook
330 aae9460e Paul Brook
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
331 aae9460e Paul Brook
{
332 aae9460e Paul Brook
    assert(dev->num_gpio_out == 0);
333 aae9460e Paul Brook
    dev->num_gpio_out = n;
334 aae9460e Paul Brook
    dev->gpio_out = pins;
335 aae9460e Paul Brook
}
336 aae9460e Paul Brook
337 aae9460e Paul Brook
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
338 aae9460e Paul Brook
{
339 aae9460e Paul Brook
    assert(n >= 0 && n < dev->num_gpio_in);
340 aae9460e Paul Brook
    return dev->gpio_in[n];
341 aae9460e Paul Brook
}
342 aae9460e Paul Brook
343 aae9460e Paul Brook
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
344 aae9460e Paul Brook
{
345 aae9460e Paul Brook
    assert(n >= 0 && n < dev->num_gpio_out);
346 aae9460e Paul Brook
    dev->gpio_out[n] = pin;
347 aae9460e Paul Brook
}
348 aae9460e Paul Brook
349 9d07d757 Paul Brook
VLANClientState *qdev_get_vlan_client(DeviceState *dev,
350 cda9046b Mark McLoughlin
                                      NetCanReceive *can_receive,
351 cda9046b Mark McLoughlin
                                      NetReceive *receive,
352 cda9046b Mark McLoughlin
                                      NetReceiveIOV *receive_iov,
353 9d07d757 Paul Brook
                                      NetCleanup *cleanup,
354 9d07d757 Paul Brook
                                      void *opaque)
355 9d07d757 Paul Brook
{
356 9d07d757 Paul Brook
    NICInfo *nd = dev->nd;
357 9d07d757 Paul Brook
    assert(nd);
358 ae50b274 Mark McLoughlin
    nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
359 ae50b274 Mark McLoughlin
                                  receive, receive_iov, cleanup, opaque);
360 ae50b274 Mark McLoughlin
    return nd->vc;
361 9d07d757 Paul Brook
}
362 9d07d757 Paul Brook
363 9d07d757 Paul Brook
364 9d07d757 Paul Brook
void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
365 9d07d757 Paul Brook
{
366 9d07d757 Paul Brook
    memcpy(macaddr, dev->nd->macaddr, 6);
367 9d07d757 Paul Brook
}
368 9d07d757 Paul Brook
369 aae9460e Paul Brook
static int next_block_unit[IF_COUNT];
370 aae9460e Paul Brook
371 aae9460e Paul Brook
/* Get a block device.  This should only be used for single-drive devices
372 aae9460e Paul Brook
   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
373 aae9460e Paul Brook
   appropriate bus.  */
374 aae9460e Paul Brook
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
375 aae9460e Paul Brook
{
376 aae9460e Paul Brook
    int unit = next_block_unit[type]++;
377 751c6a17 Gerd Hoffmann
    DriveInfo *dinfo;
378 aae9460e Paul Brook
379 751c6a17 Gerd Hoffmann
    dinfo = drive_get(type, 0, unit);
380 751c6a17 Gerd Hoffmann
    return dinfo ? dinfo->bdrv : NULL;
381 aae9460e Paul Brook
}
382 4d6ae674 Paul Brook
383 02e2da45 Paul Brook
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
384 4d6ae674 Paul Brook
{
385 02e2da45 Paul Brook
    BusState *bus;
386 4d6ae674 Paul Brook
387 72cf2d4f Blue Swirl
    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
388 4d6ae674 Paul Brook
        if (strcmp(name, bus->name) == 0) {
389 02e2da45 Paul Brook
            return bus;
390 4d6ae674 Paul Brook
        }
391 4d6ae674 Paul Brook
    }
392 4d6ae674 Paul Brook
    return NULL;
393 4d6ae674 Paul Brook
}
394 4d6ae674 Paul Brook
395 8ffb1bcf Gerd Hoffmann
static BusState *qbus_find_recursive(BusState *bus, const char *name,
396 8ffb1bcf Gerd Hoffmann
                                     const BusInfo *info)
397 8ffb1bcf Gerd Hoffmann
{
398 8ffb1bcf Gerd Hoffmann
    DeviceState *dev;
399 8ffb1bcf Gerd Hoffmann
    BusState *child, *ret;
400 8ffb1bcf Gerd Hoffmann
    int match = 1;
401 8ffb1bcf Gerd Hoffmann
402 8ffb1bcf Gerd Hoffmann
    if (name && (strcmp(bus->name, name) != 0)) {
403 8ffb1bcf Gerd Hoffmann
        match = 0;
404 8ffb1bcf Gerd Hoffmann
    }
405 8ffb1bcf Gerd Hoffmann
    if (info && (bus->info != info)) {
406 8ffb1bcf Gerd Hoffmann
        match = 0;
407 8ffb1bcf Gerd Hoffmann
    }
408 8ffb1bcf Gerd Hoffmann
    if (match) {
409 8ffb1bcf Gerd Hoffmann
        return bus;
410 8ffb1bcf Gerd Hoffmann
    }
411 8ffb1bcf Gerd Hoffmann
412 72cf2d4f Blue Swirl
    QLIST_FOREACH(dev, &bus->children, sibling) {
413 72cf2d4f Blue Swirl
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
414 8ffb1bcf Gerd Hoffmann
            ret = qbus_find_recursive(child, name, info);
415 8ffb1bcf Gerd Hoffmann
            if (ret) {
416 8ffb1bcf Gerd Hoffmann
                return ret;
417 8ffb1bcf Gerd Hoffmann
            }
418 8ffb1bcf Gerd Hoffmann
        }
419 8ffb1bcf Gerd Hoffmann
    }
420 8ffb1bcf Gerd Hoffmann
    return NULL;
421 8ffb1bcf Gerd Hoffmann
}
422 8ffb1bcf Gerd Hoffmann
423 3418bd25 Gerd Hoffmann
static DeviceState *qdev_find_recursive(BusState *bus, const char *id)
424 3418bd25 Gerd Hoffmann
{
425 3418bd25 Gerd Hoffmann
    DeviceState *dev, *ret;
426 3418bd25 Gerd Hoffmann
    BusState *child;
427 3418bd25 Gerd Hoffmann
428 3418bd25 Gerd Hoffmann
    QLIST_FOREACH(dev, &bus->children, sibling) {
429 3418bd25 Gerd Hoffmann
        if (dev->id && strcmp(dev->id, id) == 0)
430 3418bd25 Gerd Hoffmann
            return dev;
431 3418bd25 Gerd Hoffmann
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
432 3418bd25 Gerd Hoffmann
            ret = qdev_find_recursive(child, id);
433 3418bd25 Gerd Hoffmann
            if (ret) {
434 3418bd25 Gerd Hoffmann
                return ret;
435 3418bd25 Gerd Hoffmann
            }
436 3418bd25 Gerd Hoffmann
        }
437 3418bd25 Gerd Hoffmann
    }
438 3418bd25 Gerd Hoffmann
    return NULL;
439 3418bd25 Gerd Hoffmann
}
440 3418bd25 Gerd Hoffmann
441 8ffb1bcf Gerd Hoffmann
static void qbus_list_bus(DeviceState *dev, char *dest, int len)
442 8ffb1bcf Gerd Hoffmann
{
443 8ffb1bcf Gerd Hoffmann
    BusState *child;
444 8ffb1bcf Gerd Hoffmann
    const char *sep = " ";
445 8ffb1bcf Gerd Hoffmann
    int pos = 0;
446 8ffb1bcf Gerd Hoffmann
447 8ffb1bcf Gerd Hoffmann
    pos += snprintf(dest+pos, len-pos,"child busses at \"%s\":",
448 8ffb1bcf Gerd Hoffmann
                    dev->id ? dev->id : dev->info->name);
449 72cf2d4f Blue Swirl
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
450 8ffb1bcf Gerd Hoffmann
        pos += snprintf(dest+pos, len-pos, "%s\"%s\"", sep, child->name);
451 8ffb1bcf Gerd Hoffmann
        sep = ", ";
452 8ffb1bcf Gerd Hoffmann
    }
453 8ffb1bcf Gerd Hoffmann
}
454 8ffb1bcf Gerd Hoffmann
455 8ffb1bcf Gerd Hoffmann
static void qbus_list_dev(BusState *bus, char *dest, int len)
456 8ffb1bcf Gerd Hoffmann
{
457 8ffb1bcf Gerd Hoffmann
    DeviceState *dev;
458 8ffb1bcf Gerd Hoffmann
    const char *sep = " ";
459 8ffb1bcf Gerd Hoffmann
    int pos = 0;
460 8ffb1bcf Gerd Hoffmann
461 8ffb1bcf Gerd Hoffmann
    pos += snprintf(dest+pos, len-pos, "devices at \"%s\":",
462 8ffb1bcf Gerd Hoffmann
                    bus->name);
463 72cf2d4f Blue Swirl
    QLIST_FOREACH(dev, &bus->children, sibling) {
464 8ffb1bcf Gerd Hoffmann
        pos += snprintf(dest+pos, len-pos, "%s\"%s\"",
465 8ffb1bcf Gerd Hoffmann
                        sep, dev->info->name);
466 8ffb1bcf Gerd Hoffmann
        if (dev->id)
467 8ffb1bcf Gerd Hoffmann
            pos += snprintf(dest+pos, len-pos, "/\"%s\"", dev->id);
468 8ffb1bcf Gerd Hoffmann
        sep = ", ";
469 8ffb1bcf Gerd Hoffmann
    }
470 8ffb1bcf Gerd Hoffmann
}
471 8ffb1bcf Gerd Hoffmann
472 8ffb1bcf Gerd Hoffmann
static BusState *qbus_find_bus(DeviceState *dev, char *elem)
473 8ffb1bcf Gerd Hoffmann
{
474 8ffb1bcf Gerd Hoffmann
    BusState *child;
475 8ffb1bcf Gerd Hoffmann
476 72cf2d4f Blue Swirl
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
477 8ffb1bcf Gerd Hoffmann
        if (strcmp(child->name, elem) == 0) {
478 8ffb1bcf Gerd Hoffmann
            return child;
479 8ffb1bcf Gerd Hoffmann
        }
480 8ffb1bcf Gerd Hoffmann
    }
481 8ffb1bcf Gerd Hoffmann
    return NULL;
482 8ffb1bcf Gerd Hoffmann
}
483 8ffb1bcf Gerd Hoffmann
484 8ffb1bcf Gerd Hoffmann
static DeviceState *qbus_find_dev(BusState *bus, char *elem)
485 8ffb1bcf Gerd Hoffmann
{
486 8ffb1bcf Gerd Hoffmann
    DeviceState *dev;
487 8ffb1bcf Gerd Hoffmann
488 8ffb1bcf Gerd Hoffmann
    /*
489 8ffb1bcf Gerd Hoffmann
     * try to match in order:
490 8ffb1bcf Gerd Hoffmann
     *   (1) instance id, if present
491 8ffb1bcf Gerd Hoffmann
     *   (2) driver name
492 8ffb1bcf Gerd Hoffmann
     *   (3) driver alias, if present
493 8ffb1bcf Gerd Hoffmann
     */
494 72cf2d4f Blue Swirl
    QLIST_FOREACH(dev, &bus->children, sibling) {
495 8ffb1bcf Gerd Hoffmann
        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
496 8ffb1bcf Gerd Hoffmann
            return dev;
497 8ffb1bcf Gerd Hoffmann
        }
498 8ffb1bcf Gerd Hoffmann
    }
499 72cf2d4f Blue Swirl
    QLIST_FOREACH(dev, &bus->children, sibling) {
500 8ffb1bcf Gerd Hoffmann
        if (strcmp(dev->info->name, elem) == 0) {
501 8ffb1bcf Gerd Hoffmann
            return dev;
502 8ffb1bcf Gerd Hoffmann
        }
503 8ffb1bcf Gerd Hoffmann
    }
504 72cf2d4f Blue Swirl
    QLIST_FOREACH(dev, &bus->children, sibling) {
505 8ffb1bcf Gerd Hoffmann
        if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
506 8ffb1bcf Gerd Hoffmann
            return dev;
507 8ffb1bcf Gerd Hoffmann
        }
508 8ffb1bcf Gerd Hoffmann
    }
509 8ffb1bcf Gerd Hoffmann
    return NULL;
510 8ffb1bcf Gerd Hoffmann
}
511 8ffb1bcf Gerd Hoffmann
512 8ffb1bcf Gerd Hoffmann
static BusState *qbus_find(const char *path)
513 8ffb1bcf Gerd Hoffmann
{
514 8ffb1bcf Gerd Hoffmann
    DeviceState *dev;
515 8ffb1bcf Gerd Hoffmann
    BusState *bus;
516 8ffb1bcf Gerd Hoffmann
    char elem[128], msg[256];
517 8ffb1bcf Gerd Hoffmann
    int pos, len;
518 8ffb1bcf Gerd Hoffmann
519 8ffb1bcf Gerd Hoffmann
    /* find start element */
520 8ffb1bcf Gerd Hoffmann
    if (path[0] == '/') {
521 8ffb1bcf Gerd Hoffmann
        bus = main_system_bus;
522 8ffb1bcf Gerd Hoffmann
        pos = 0;
523 8ffb1bcf Gerd Hoffmann
    } else {
524 8ffb1bcf Gerd Hoffmann
        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
525 286c2321 Gerd Hoffmann
            qemu_error("path parse error (\"%s\")\n", path);
526 8ffb1bcf Gerd Hoffmann
            return NULL;
527 8ffb1bcf Gerd Hoffmann
        }
528 8ffb1bcf Gerd Hoffmann
        bus = qbus_find_recursive(main_system_bus, elem, NULL);
529 8ffb1bcf Gerd Hoffmann
        if (!bus) {
530 286c2321 Gerd Hoffmann
            qemu_error("bus \"%s\" not found\n", elem);
531 8ffb1bcf Gerd Hoffmann
            return NULL;
532 8ffb1bcf Gerd Hoffmann
        }
533 8ffb1bcf Gerd Hoffmann
        pos = len;
534 8ffb1bcf Gerd Hoffmann
    }
535 8ffb1bcf Gerd Hoffmann
536 8ffb1bcf Gerd Hoffmann
    for (;;) {
537 8ffb1bcf Gerd Hoffmann
        if (path[pos] == '\0') {
538 8ffb1bcf Gerd Hoffmann
            /* we are done */
539 8ffb1bcf Gerd Hoffmann
            return bus;
540 8ffb1bcf Gerd Hoffmann
        }
541 8ffb1bcf Gerd Hoffmann
542 8ffb1bcf Gerd Hoffmann
        /* find device */
543 8ffb1bcf Gerd Hoffmann
        if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
544 286c2321 Gerd Hoffmann
            qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
545 8ffb1bcf Gerd Hoffmann
            return NULL;
546 8ffb1bcf Gerd Hoffmann
        }
547 8ffb1bcf Gerd Hoffmann
        pos += len;
548 8ffb1bcf Gerd Hoffmann
        dev = qbus_find_dev(bus, elem);
549 8ffb1bcf Gerd Hoffmann
        if (!dev) {
550 8ffb1bcf Gerd Hoffmann
            qbus_list_dev(bus, msg, sizeof(msg));
551 286c2321 Gerd Hoffmann
            qemu_error("device \"%s\" not found\n%s\n", elem, msg);
552 8ffb1bcf Gerd Hoffmann
            return NULL;
553 8ffb1bcf Gerd Hoffmann
        }
554 8ffb1bcf Gerd Hoffmann
        if (path[pos] == '\0') {
555 8ffb1bcf Gerd Hoffmann
            /* last specified element is a device.  If it has exactly
556 8ffb1bcf Gerd Hoffmann
             * one child bus accept it nevertheless */
557 8ffb1bcf Gerd Hoffmann
            switch (dev->num_child_bus) {
558 8ffb1bcf Gerd Hoffmann
            case 0:
559 286c2321 Gerd Hoffmann
                qemu_error("device has no child bus (%s)\n", path);
560 8ffb1bcf Gerd Hoffmann
                return NULL;
561 8ffb1bcf Gerd Hoffmann
            case 1:
562 72cf2d4f Blue Swirl
                return QLIST_FIRST(&dev->child_bus);
563 8ffb1bcf Gerd Hoffmann
            default:
564 8ffb1bcf Gerd Hoffmann
                qbus_list_bus(dev, msg, sizeof(msg));
565 286c2321 Gerd Hoffmann
                qemu_error("device has multiple child busses (%s)\n%s\n",
566 286c2321 Gerd Hoffmann
                           path, msg);
567 8ffb1bcf Gerd Hoffmann
                return NULL;
568 8ffb1bcf Gerd Hoffmann
            }
569 8ffb1bcf Gerd Hoffmann
        }
570 8ffb1bcf Gerd Hoffmann
571 8ffb1bcf Gerd Hoffmann
        /* find bus */
572 8ffb1bcf Gerd Hoffmann
        if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
573 286c2321 Gerd Hoffmann
            qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
574 8ffb1bcf Gerd Hoffmann
            return NULL;
575 8ffb1bcf Gerd Hoffmann
        }
576 8ffb1bcf Gerd Hoffmann
        pos += len;
577 8ffb1bcf Gerd Hoffmann
        bus = qbus_find_bus(dev, elem);
578 8ffb1bcf Gerd Hoffmann
        if (!bus) {
579 8ffb1bcf Gerd Hoffmann
            qbus_list_bus(dev, msg, sizeof(msg));
580 286c2321 Gerd Hoffmann
            qemu_error("child bus \"%s\" not found\n%s\n", elem, msg);
581 8ffb1bcf Gerd Hoffmann
            return NULL;
582 8ffb1bcf Gerd Hoffmann
        }
583 8ffb1bcf Gerd Hoffmann
    }
584 8ffb1bcf Gerd Hoffmann
}
585 8ffb1bcf Gerd Hoffmann
586 cd739fb6 Gerd Hoffmann
void qbus_create_inplace(BusState *bus, BusInfo *info,
587 cd739fb6 Gerd Hoffmann
                         DeviceState *parent, const char *name)
588 02e2da45 Paul Brook
{
589 d271de9f Gerd Hoffmann
    char *buf;
590 d271de9f Gerd Hoffmann
    int i,len;
591 02e2da45 Paul Brook
592 10c4c98a Gerd Hoffmann
    bus->info = info;
593 02e2da45 Paul Brook
    bus->parent = parent;
594 d271de9f Gerd Hoffmann
595 d271de9f Gerd Hoffmann
    if (name) {
596 d271de9f Gerd Hoffmann
        /* use supplied name */
597 d271de9f Gerd Hoffmann
        bus->name = qemu_strdup(name);
598 d271de9f Gerd Hoffmann
    } else if (parent && parent->id) {
599 d271de9f Gerd Hoffmann
        /* parent device has id -> use it for bus name */
600 d271de9f Gerd Hoffmann
        len = strlen(parent->id) + 16;
601 d271de9f Gerd Hoffmann
        buf = qemu_malloc(len);
602 d271de9f Gerd Hoffmann
        snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
603 d271de9f Gerd Hoffmann
        bus->name = buf;
604 d271de9f Gerd Hoffmann
    } else {
605 d271de9f Gerd Hoffmann
        /* no id -> use lowercase bus type for bus name */
606 d271de9f Gerd Hoffmann
        len = strlen(info->name) + 16;
607 d271de9f Gerd Hoffmann
        buf = qemu_malloc(len);
608 d271de9f Gerd Hoffmann
        len = snprintf(buf, len, "%s.%d", info->name,
609 d271de9f Gerd Hoffmann
                       parent ? parent->num_child_bus : 0);
610 d271de9f Gerd Hoffmann
        for (i = 0; i < len; i++)
611 bb87ece5 Christoph Egger
            buf[i] = qemu_tolower(buf[i]);
612 d271de9f Gerd Hoffmann
        bus->name = buf;
613 d271de9f Gerd Hoffmann
    }
614 d271de9f Gerd Hoffmann
615 72cf2d4f Blue Swirl
    QLIST_INIT(&bus->children);
616 02e2da45 Paul Brook
    if (parent) {
617 72cf2d4f Blue Swirl
        QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
618 d271de9f Gerd Hoffmann
        parent->num_child_bus++;
619 02e2da45 Paul Brook
    }
620 cd739fb6 Gerd Hoffmann
621 cd739fb6 Gerd Hoffmann
}
622 cd739fb6 Gerd Hoffmann
623 cd739fb6 Gerd Hoffmann
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
624 cd739fb6 Gerd Hoffmann
{
625 cd739fb6 Gerd Hoffmann
    BusState *bus;
626 cd739fb6 Gerd Hoffmann
627 cd739fb6 Gerd Hoffmann
    bus = qemu_mallocz(info->size);
628 cd739fb6 Gerd Hoffmann
    bus->qdev_allocated = 1;
629 cd739fb6 Gerd Hoffmann
    qbus_create_inplace(bus, info, parent, name);
630 02e2da45 Paul Brook
    return bus;
631 02e2da45 Paul Brook
}
632 cae4956e Gerd Hoffmann
633 131ec1bd Gerd Hoffmann
void qbus_free(BusState *bus)
634 131ec1bd Gerd Hoffmann
{
635 131ec1bd Gerd Hoffmann
    DeviceState *dev;
636 131ec1bd Gerd Hoffmann
637 131ec1bd Gerd Hoffmann
    while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
638 131ec1bd Gerd Hoffmann
        qdev_free(dev);
639 131ec1bd Gerd Hoffmann
    }
640 131ec1bd Gerd Hoffmann
    if (bus->parent) {
641 131ec1bd Gerd Hoffmann
        QLIST_REMOVE(bus, sibling);
642 131ec1bd Gerd Hoffmann
        bus->parent->num_child_bus--;
643 131ec1bd Gerd Hoffmann
    }
644 131ec1bd Gerd Hoffmann
    if (bus->qdev_allocated) {
645 131ec1bd Gerd Hoffmann
        qemu_free(bus);
646 131ec1bd Gerd Hoffmann
    }
647 131ec1bd Gerd Hoffmann
}
648 131ec1bd Gerd Hoffmann
649 cae4956e Gerd Hoffmann
#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
650 cae4956e Gerd Hoffmann
static void qbus_print(Monitor *mon, BusState *bus, int indent);
651 cae4956e Gerd Hoffmann
652 ee6847d1 Gerd Hoffmann
static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
653 ee6847d1 Gerd Hoffmann
                             const char *prefix, int indent)
654 ee6847d1 Gerd Hoffmann
{
655 ee6847d1 Gerd Hoffmann
    char buf[64];
656 ee6847d1 Gerd Hoffmann
657 ee6847d1 Gerd Hoffmann
    if (!props)
658 ee6847d1 Gerd Hoffmann
        return;
659 ee6847d1 Gerd Hoffmann
    while (props->name) {
660 ee6847d1 Gerd Hoffmann
        if (props->info->print) {
661 ee6847d1 Gerd Hoffmann
            props->info->print(dev, props, buf, sizeof(buf));
662 ee6847d1 Gerd Hoffmann
            qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
663 ee6847d1 Gerd Hoffmann
        }
664 ee6847d1 Gerd Hoffmann
        props++;
665 ee6847d1 Gerd Hoffmann
    }
666 ee6847d1 Gerd Hoffmann
}
667 ee6847d1 Gerd Hoffmann
668 cae4956e Gerd Hoffmann
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
669 cae4956e Gerd Hoffmann
{
670 cae4956e Gerd Hoffmann
    BusState *child;
671 ccb63de3 Gerd Hoffmann
    qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
672 ccb63de3 Gerd Hoffmann
                dev->id ? dev->id : "");
673 cae4956e Gerd Hoffmann
    indent += 2;
674 cae4956e Gerd Hoffmann
    if (dev->num_gpio_in) {
675 cae4956e Gerd Hoffmann
        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
676 cae4956e Gerd Hoffmann
    }
677 cae4956e Gerd Hoffmann
    if (dev->num_gpio_out) {
678 cae4956e Gerd Hoffmann
        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
679 cae4956e Gerd Hoffmann
    }
680 ee6847d1 Gerd Hoffmann
    qdev_print_props(mon, dev, dev->info->props, "dev", indent);
681 ee6847d1 Gerd Hoffmann
    qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
682 10c4c98a Gerd Hoffmann
    if (dev->parent_bus->info->print_dev)
683 10c4c98a Gerd Hoffmann
        dev->parent_bus->info->print_dev(mon, dev, indent);
684 72cf2d4f Blue Swirl
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
685 cae4956e Gerd Hoffmann
        qbus_print(mon, child, indent);
686 cae4956e Gerd Hoffmann
    }
687 cae4956e Gerd Hoffmann
}
688 cae4956e Gerd Hoffmann
689 cae4956e Gerd Hoffmann
static void qbus_print(Monitor *mon, BusState *bus, int indent)
690 cae4956e Gerd Hoffmann
{
691 cae4956e Gerd Hoffmann
    struct DeviceState *dev;
692 cae4956e Gerd Hoffmann
693 cae4956e Gerd Hoffmann
    qdev_printf("bus: %s\n", bus->name);
694 cae4956e Gerd Hoffmann
    indent += 2;
695 10c4c98a Gerd Hoffmann
    qdev_printf("type %s\n", bus->info->name);
696 72cf2d4f Blue Swirl
    QLIST_FOREACH(dev, &bus->children, sibling) {
697 cae4956e Gerd Hoffmann
        qdev_print(mon, dev, indent);
698 cae4956e Gerd Hoffmann
    }
699 cae4956e Gerd Hoffmann
}
700 cae4956e Gerd Hoffmann
#undef qdev_printf
701 cae4956e Gerd Hoffmann
702 cae4956e Gerd Hoffmann
void do_info_qtree(Monitor *mon)
703 cae4956e Gerd Hoffmann
{
704 cae4956e Gerd Hoffmann
    if (main_system_bus)
705 cae4956e Gerd Hoffmann
        qbus_print(mon, main_system_bus, 0);
706 cae4956e Gerd Hoffmann
}
707 9316d30f Gerd Hoffmann
708 f6c64e0e Gerd Hoffmann
void do_info_qdm(Monitor *mon)
709 9316d30f Gerd Hoffmann
{
710 9316d30f Gerd Hoffmann
    DeviceInfo *info;
711 9316d30f Gerd Hoffmann
    char msg[256];
712 9316d30f Gerd Hoffmann
713 9316d30f Gerd Hoffmann
    for (info = device_info_list; info != NULL; info = info->next) {
714 9316d30f Gerd Hoffmann
        qdev_print_devinfo(info, msg, sizeof(msg));
715 9316d30f Gerd Hoffmann
        monitor_printf(mon, "%s\n", msg);
716 9316d30f Gerd Hoffmann
    }
717 9316d30f Gerd Hoffmann
}
718 3418bd25 Gerd Hoffmann
719 3418bd25 Gerd Hoffmann
void do_device_add(Monitor *mon, const QDict *qdict)
720 3418bd25 Gerd Hoffmann
{
721 3418bd25 Gerd Hoffmann
    QemuOpts *opts;
722 3418bd25 Gerd Hoffmann
723 3418bd25 Gerd Hoffmann
    opts = qemu_opts_parse(&qemu_device_opts,
724 3418bd25 Gerd Hoffmann
                           qdict_get_str(qdict, "config"), "driver");
725 3418bd25 Gerd Hoffmann
    if (opts)
726 3418bd25 Gerd Hoffmann
        qdev_device_add(opts);
727 3418bd25 Gerd Hoffmann
}
728 3418bd25 Gerd Hoffmann
729 3418bd25 Gerd Hoffmann
void do_device_del(Monitor *mon, const QDict *qdict)
730 3418bd25 Gerd Hoffmann
{
731 3418bd25 Gerd Hoffmann
    const char *id = qdict_get_str(qdict, "id");
732 3418bd25 Gerd Hoffmann
    DeviceState *dev;
733 3418bd25 Gerd Hoffmann
734 3418bd25 Gerd Hoffmann
    dev = qdev_find_recursive(main_system_bus, id);
735 3418bd25 Gerd Hoffmann
    if (NULL == dev) {
736 3418bd25 Gerd Hoffmann
        qemu_error("Device '%s' not found\n", id);
737 3418bd25 Gerd Hoffmann
        return;
738 3418bd25 Gerd Hoffmann
    }
739 3418bd25 Gerd Hoffmann
    qdev_unplug(dev);
740 3418bd25 Gerd Hoffmann
}