Statistics
| Branch: | Revision:

root / hw / qdev.c @ df0db221

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