Statistics
| Branch: | Revision:

root / hw / qdev.c @ cafe5bdb

History | View | Annotate | Download (38.5 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 0ac8ef71 Alex Williamson
static bool qdev_hot_added = false;
35 0ac8ef71 Alex Williamson
static bool qdev_hot_removed = false;
36 3418bd25 Gerd Hoffmann
37 cdaed7c7 Gerd Hoffmann
/* This is a nasty hack to allow passing a NULL bus to qdev_create.  */
38 b9aaf7f8 Blue Swirl
static BusState *main_system_bus;
39 2da8bb92 Isaku Yamahata
static void main_system_bus_create(void);
40 4d6ae674 Paul Brook
41 0958b4cc Gerd Hoffmann
DeviceInfo *device_info_list;
42 aae9460e Paul Brook
43 8ffb1bcf Gerd Hoffmann
static BusState *qbus_find_recursive(BusState *bus, const char *name,
44 8ffb1bcf Gerd Hoffmann
                                     const BusInfo *info);
45 8ffb1bcf Gerd Hoffmann
static BusState *qbus_find(const char *path);
46 8ffb1bcf Gerd Hoffmann
47 aae9460e Paul Brook
/* Register a new device type.  */
48 074f2fff Gerd Hoffmann
void qdev_register(DeviceInfo *info)
49 aae9460e Paul Brook
{
50 074f2fff Gerd Hoffmann
    assert(info->size >= sizeof(DeviceState));
51 042f84d0 Gerd Hoffmann
    assert(!info->next);
52 aae9460e Paul Brook
53 042f84d0 Gerd Hoffmann
    info->next = device_info_list;
54 042f84d0 Gerd Hoffmann
    device_info_list = info;
55 aae9460e Paul Brook
}
56 aae9460e Paul Brook
57 81ebb98b Gerd Hoffmann
static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
58 81ebb98b Gerd Hoffmann
{
59 81ebb98b Gerd Hoffmann
    DeviceInfo *info;
60 81ebb98b Gerd Hoffmann
61 3320e56e Gerd Hoffmann
    /* first check device names */
62 81ebb98b Gerd Hoffmann
    for (info = device_info_list; info != NULL; info = info->next) {
63 81ebb98b Gerd Hoffmann
        if (bus_info && info->bus_info != bus_info)
64 81ebb98b Gerd Hoffmann
            continue;
65 81ebb98b Gerd Hoffmann
        if (strcmp(info->name, name) != 0)
66 81ebb98b Gerd Hoffmann
            continue;
67 81ebb98b Gerd Hoffmann
        return info;
68 81ebb98b Gerd Hoffmann
    }
69 3320e56e Gerd Hoffmann
70 3320e56e Gerd Hoffmann
    /* failing that check the aliases */
71 3320e56e Gerd Hoffmann
    for (info = device_info_list; info != NULL; info = info->next) {
72 3320e56e Gerd Hoffmann
        if (bus_info && info->bus_info != bus_info)
73 3320e56e Gerd Hoffmann
            continue;
74 3320e56e Gerd Hoffmann
        if (!info->alias)
75 3320e56e Gerd Hoffmann
            continue;
76 3320e56e Gerd Hoffmann
        if (strcmp(info->alias, name) != 0)
77 3320e56e Gerd Hoffmann
            continue;
78 3320e56e Gerd Hoffmann
        return info;
79 3320e56e Gerd Hoffmann
    }
80 81ebb98b Gerd Hoffmann
    return NULL;
81 81ebb98b Gerd Hoffmann
}
82 81ebb98b Gerd Hoffmann
83 0c17542d Markus Armbruster
static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
84 0c17542d Markus Armbruster
{
85 0c17542d Markus Armbruster
    DeviceState *dev;
86 a5296ca9 Anthony Liguori
    Property *prop;
87 0c17542d Markus Armbruster
88 0c17542d Markus Armbruster
    assert(bus->info == info->bus_info);
89 7267c094 Anthony Liguori
    dev = g_malloc0(info->size);
90 0c17542d Markus Armbruster
    dev->info = info;
91 0c17542d Markus Armbruster
    dev->parent_bus = bus;
92 0c17542d Markus Armbruster
    qdev_prop_set_defaults(dev, dev->info->props);
93 0c17542d Markus Armbruster
    qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
94 0c17542d Markus Armbruster
    qdev_prop_set_globals(dev);
95 d8bb00d6 Paolo Bonzini
    QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
96 0c17542d Markus Armbruster
    if (qdev_hotplug) {
97 0c17542d Markus Armbruster
        assert(bus->allow_hotplug);
98 0c17542d Markus Armbruster
        dev->hotplugged = 1;
99 0ac8ef71 Alex Williamson
        qdev_hot_added = true;
100 0c17542d Markus Armbruster
    }
101 4d2ffa08 Jan Kiszka
    dev->instance_id_alias = -1;
102 44677ded Anthony Liguori
    QTAILQ_INIT(&dev->properties);
103 0c17542d Markus Armbruster
    dev->state = DEV_STATE_CREATED;
104 a5296ca9 Anthony Liguori
105 a5296ca9 Anthony Liguori
    for (prop = dev->info->props; prop && prop->name; prop++) {
106 a5296ca9 Anthony Liguori
        qdev_property_add_legacy(dev, prop, NULL);
107 a5296ca9 Anthony Liguori
    }
108 a5296ca9 Anthony Liguori
109 a5296ca9 Anthony Liguori
    for (prop = dev->info->bus_info->props; prop && prop->name; prop++) {
110 a5296ca9 Anthony Liguori
        qdev_property_add_legacy(dev, prop, NULL);
111 a5296ca9 Anthony Liguori
    }
112 a5296ca9 Anthony Liguori
113 cd34d667 Anthony Liguori
    qdev_property_add_str(dev, "type", qdev_get_type, NULL, NULL);
114 cd34d667 Anthony Liguori
115 0c17542d Markus Armbruster
    return dev;
116 0c17542d Markus Armbruster
}
117 0c17542d Markus Armbruster
118 aae9460e Paul Brook
/* Create a new device.  This only initializes the device state structure
119 aae9460e Paul Brook
   and allows properties to be set.  qdev_init should be called to
120 aae9460e Paul Brook
   initialize the actual device emulation.  */
121 02e2da45 Paul Brook
DeviceState *qdev_create(BusState *bus, const char *name)
122 aae9460e Paul Brook
{
123 0bcdeda7 Blue Swirl
    DeviceState *dev;
124 0bcdeda7 Blue Swirl
125 0bcdeda7 Blue Swirl
    dev = qdev_try_create(bus, name);
126 0bcdeda7 Blue Swirl
    if (!dev) {
127 e92714c7 Peter Maydell
        if (bus) {
128 e92714c7 Peter Maydell
            hw_error("Unknown device '%s' for bus '%s'\n", name,
129 e92714c7 Peter Maydell
                     bus->info->name);
130 e92714c7 Peter Maydell
        } else {
131 e92714c7 Peter Maydell
            hw_error("Unknown device '%s' for default sysbus\n", name);
132 e92714c7 Peter Maydell
        }
133 0bcdeda7 Blue Swirl
    }
134 0bcdeda7 Blue Swirl
135 0bcdeda7 Blue Swirl
    return dev;
136 0bcdeda7 Blue Swirl
}
137 0bcdeda7 Blue Swirl
138 0bcdeda7 Blue Swirl
DeviceState *qdev_try_create(BusState *bus, const char *name)
139 0bcdeda7 Blue Swirl
{
140 042f84d0 Gerd Hoffmann
    DeviceInfo *info;
141 aae9460e Paul Brook
142 10c4c98a Gerd Hoffmann
    if (!bus) {
143 68694897 Stefan Weil
        bus = sysbus_get_default();
144 10c4c98a Gerd Hoffmann
    }
145 10c4c98a Gerd Hoffmann
146 81ebb98b Gerd Hoffmann
    info = qdev_find_info(bus->info, name);
147 042f84d0 Gerd Hoffmann
    if (!info) {
148 0bcdeda7 Blue Swirl
        return NULL;
149 aae9460e Paul Brook
    }
150 aae9460e Paul Brook
151 0c17542d Markus Armbruster
    return qdev_create_from_info(bus, info);
152 aae9460e Paul Brook
}
153 aae9460e Paul Brook
154 8a9662ca Markus Armbruster
static void qdev_print_devinfo(DeviceInfo *info)
155 1b524b04 Gerd Hoffmann
{
156 8a9662ca Markus Armbruster
    error_printf("name \"%s\", bus %s",
157 8a9662ca Markus Armbruster
                 info->name, info->bus_info->name);
158 22f2e344 Gerd Hoffmann
    if (info->alias) {
159 8a9662ca Markus Armbruster
        error_printf(", alias \"%s\"", info->alias);
160 22f2e344 Gerd Hoffmann
    }
161 22f2e344 Gerd Hoffmann
    if (info->desc) {
162 8a9662ca Markus Armbruster
        error_printf(", desc \"%s\"", info->desc);
163 22f2e344 Gerd Hoffmann
    }
164 22f2e344 Gerd Hoffmann
    if (info->no_user) {
165 8a9662ca Markus Armbruster
        error_printf(", no-user");
166 22f2e344 Gerd Hoffmann
    }
167 8a9662ca Markus Armbruster
    error_printf("\n");
168 1b524b04 Gerd Hoffmann
}
169 1b524b04 Gerd Hoffmann
170 f31d07d1 Gerd Hoffmann
static int set_property(const char *name, const char *value, void *opaque)
171 8ffb1bcf Gerd Hoffmann
{
172 f31d07d1 Gerd Hoffmann
    DeviceState *dev = opaque;
173 f31d07d1 Gerd Hoffmann
174 f31d07d1 Gerd Hoffmann
    if (strcmp(name, "driver") == 0)
175 f31d07d1 Gerd Hoffmann
        return 0;
176 f31d07d1 Gerd Hoffmann
    if (strcmp(name, "bus") == 0)
177 f31d07d1 Gerd Hoffmann
        return 0;
178 f31d07d1 Gerd Hoffmann
179 3df04ac3 Mark McLoughlin
    if (qdev_prop_parse(dev, name, value) == -1) {
180 f31d07d1 Gerd Hoffmann
        return -1;
181 f31d07d1 Gerd Hoffmann
    }
182 f31d07d1 Gerd Hoffmann
    return 0;
183 f31d07d1 Gerd Hoffmann
}
184 f31d07d1 Gerd Hoffmann
185 ff952ba2 Markus Armbruster
int qdev_device_help(QemuOpts *opts)
186 ff952ba2 Markus Armbruster
{
187 ff952ba2 Markus Armbruster
    const char *driver;
188 ff952ba2 Markus Armbruster
    DeviceInfo *info;
189 08350cf0 Markus Armbruster
    Property *prop;
190 ff952ba2 Markus Armbruster
191 ff952ba2 Markus Armbruster
    driver = qemu_opt_get(opts, "driver");
192 ff952ba2 Markus Armbruster
    if (driver && !strcmp(driver, "?")) {
193 ff952ba2 Markus Armbruster
        for (info = device_info_list; info != NULL; info = info->next) {
194 c64eafaf Markus Armbruster
            if (info->no_user) {
195 c64eafaf Markus Armbruster
                continue;       /* not available, don't show */
196 c64eafaf Markus Armbruster
            }
197 8a9662ca Markus Armbruster
            qdev_print_devinfo(info);
198 ff952ba2 Markus Armbruster
        }
199 ff952ba2 Markus Armbruster
        return 1;
200 ff952ba2 Markus Armbruster
    }
201 ff952ba2 Markus Armbruster
202 542379f4 Markus Armbruster
    if (!driver || !qemu_opt_get(opts, "?")) {
203 08350cf0 Markus Armbruster
        return 0;
204 08350cf0 Markus Armbruster
    }
205 08350cf0 Markus Armbruster
206 08350cf0 Markus Armbruster
    info = qdev_find_info(NULL, driver);
207 08350cf0 Markus Armbruster
    if (!info) {
208 08350cf0 Markus Armbruster
        return 0;
209 08350cf0 Markus Armbruster
    }
210 08350cf0 Markus Armbruster
211 08350cf0 Markus Armbruster
    for (prop = info->props; prop && prop->name; prop++) {
212 036f7166 Markus Armbruster
        /*
213 036f7166 Markus Armbruster
         * TODO Properties without a parser are just for dirty hacks.
214 036f7166 Markus Armbruster
         * qdev_prop_ptr is the only such PropertyInfo.  It's marked
215 036f7166 Markus Armbruster
         * for removal.  This conditional should be removed along with
216 036f7166 Markus Armbruster
         * it.
217 036f7166 Markus Armbruster
         */
218 036f7166 Markus Armbruster
        if (!prop->info->parse) {
219 036f7166 Markus Armbruster
            continue;           /* no way to set it, don't show */
220 036f7166 Markus Armbruster
        }
221 cafe5bdb Paolo Bonzini
        error_printf("%s.%s=%s\n", info->name, prop->name,
222 cafe5bdb Paolo Bonzini
                     prop->info->legacy_name ?: prop->info->name);
223 a8467c7a Gerd Hoffmann
    }
224 a8467c7a Gerd Hoffmann
    for (prop = info->bus_info->props; prop && prop->name; prop++) {
225 a8467c7a Gerd Hoffmann
        if (!prop->info->parse) {
226 a8467c7a Gerd Hoffmann
            continue;           /* no way to set it, don't show */
227 a8467c7a Gerd Hoffmann
        }
228 cafe5bdb Paolo Bonzini
        error_printf("%s.%s=%s\n", info->name, prop->name,
229 cafe5bdb Paolo Bonzini
                     prop->info->legacy_name ?: prop->info->name);
230 08350cf0 Markus Armbruster
    }
231 08350cf0 Markus Armbruster
    return 1;
232 ff952ba2 Markus Armbruster
}
233 ff952ba2 Markus Armbruster
234 1bdaacb1 Anthony Liguori
static DeviceState *qdev_get_peripheral(void)
235 1bdaacb1 Anthony Liguori
{
236 1bdaacb1 Anthony Liguori
    static DeviceState *dev;
237 1bdaacb1 Anthony Liguori
238 1bdaacb1 Anthony Liguori
    if (dev == NULL) {
239 1bdaacb1 Anthony Liguori
        dev = qdev_create(NULL, "container");
240 1bdaacb1 Anthony Liguori
        qdev_property_add_child(qdev_get_root(), "peripheral", dev, NULL);
241 1bdaacb1 Anthony Liguori
        qdev_init_nofail(dev);
242 1bdaacb1 Anthony Liguori
    }
243 1bdaacb1 Anthony Liguori
244 1bdaacb1 Anthony Liguori
    return dev;
245 1bdaacb1 Anthony Liguori
}
246 1bdaacb1 Anthony Liguori
247 8eb02831 Anthony Liguori
static DeviceState *qdev_get_peripheral_anon(void)
248 8eb02831 Anthony Liguori
{
249 8eb02831 Anthony Liguori
    static DeviceState *dev;
250 8eb02831 Anthony Liguori
251 8eb02831 Anthony Liguori
    if (dev == NULL) {
252 8eb02831 Anthony Liguori
        dev = qdev_create(NULL, "container");
253 8eb02831 Anthony Liguori
        qdev_property_add_child(qdev_get_root(), "peripheral-anon", dev, NULL);
254 8eb02831 Anthony Liguori
        qdev_init_nofail(dev);
255 8eb02831 Anthony Liguori
    }
256 8eb02831 Anthony Liguori
257 8eb02831 Anthony Liguori
    return dev;
258 8eb02831 Anthony Liguori
}
259 8eb02831 Anthony Liguori
260 f31d07d1 Gerd Hoffmann
DeviceState *qdev_device_add(QemuOpts *opts)
261 f31d07d1 Gerd Hoffmann
{
262 f31d07d1 Gerd Hoffmann
    const char *driver, *path, *id;
263 8ffb1bcf Gerd Hoffmann
    DeviceInfo *info;
264 8ffb1bcf Gerd Hoffmann
    DeviceState *qdev;
265 8ffb1bcf Gerd Hoffmann
    BusState *bus;
266 8ffb1bcf Gerd Hoffmann
267 f31d07d1 Gerd Hoffmann
    driver = qemu_opt_get(opts, "driver");
268 f31d07d1 Gerd Hoffmann
    if (!driver) {
269 0204276b Markus Armbruster
        qerror_report(QERR_MISSING_PARAMETER, "driver");
270 8ffb1bcf Gerd Hoffmann
        return NULL;
271 8ffb1bcf Gerd Hoffmann
    }
272 f31d07d1 Gerd Hoffmann
273 f31d07d1 Gerd Hoffmann
    /* find driver */
274 8ffb1bcf Gerd Hoffmann
    info = qdev_find_info(NULL, driver);
275 c64eafaf Markus Armbruster
    if (!info || info->no_user) {
276 e17ba87c Markus Armbruster
        qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
277 0204276b Markus Armbruster
        error_printf_unless_qmp("Try with argument '?' for a list.\n");
278 8ffb1bcf Gerd Hoffmann
        return NULL;
279 8ffb1bcf Gerd Hoffmann
    }
280 8ffb1bcf Gerd Hoffmann
281 f31d07d1 Gerd Hoffmann
    /* find bus */
282 f31d07d1 Gerd Hoffmann
    path = qemu_opt_get(opts, "bus");
283 f31d07d1 Gerd Hoffmann
    if (path != NULL) {
284 8ffb1bcf Gerd Hoffmann
        bus = qbus_find(path);
285 ac8dae67 Markus Armbruster
        if (!bus) {
286 ac8dae67 Markus Armbruster
            return NULL;
287 ac8dae67 Markus Armbruster
        }
288 ac8dae67 Markus Armbruster
        if (bus->info != info->bus_info) {
289 0204276b Markus Armbruster
            qerror_report(QERR_BAD_BUS_FOR_DEVICE,
290 0204276b Markus Armbruster
                           driver, bus->info->name);
291 327867b6 Markus Armbruster
            return NULL;
292 327867b6 Markus Armbruster
        }
293 8ffb1bcf Gerd Hoffmann
    } else {
294 8ffb1bcf Gerd Hoffmann
        bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
295 ac8dae67 Markus Armbruster
        if (!bus) {
296 0204276b Markus Armbruster
            qerror_report(QERR_NO_BUS_FOR_DEVICE,
297 0204276b Markus Armbruster
                           info->name, info->bus_info->name);
298 ac8dae67 Markus Armbruster
            return NULL;
299 ac8dae67 Markus Armbruster
        }
300 75570088 Gerd Hoffmann
    }
301 3418bd25 Gerd Hoffmann
    if (qdev_hotplug && !bus->allow_hotplug) {
302 0204276b Markus Armbruster
        qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
303 3418bd25 Gerd Hoffmann
        return NULL;
304 3418bd25 Gerd Hoffmann
    }
305 8ffb1bcf Gerd Hoffmann
306 f31d07d1 Gerd Hoffmann
    /* create device, set properties */
307 0c17542d Markus Armbruster
    qdev = qdev_create_from_info(bus, info);
308 f31d07d1 Gerd Hoffmann
    id = qemu_opts_id(opts);
309 f31d07d1 Gerd Hoffmann
    if (id) {
310 f31d07d1 Gerd Hoffmann
        qdev->id = id;
311 1bdaacb1 Anthony Liguori
        qdev_property_add_child(qdev_get_peripheral(), qdev->id, qdev, NULL);
312 8eb02831 Anthony Liguori
    } else {
313 8eb02831 Anthony Liguori
        static int anon_count;
314 8eb02831 Anthony Liguori
        gchar *name = g_strdup_printf("device[%d]", anon_count++);
315 8eb02831 Anthony Liguori
        qdev_property_add_child(qdev_get_peripheral_anon(), name,
316 8eb02831 Anthony Liguori
                                qdev, NULL);
317 8eb02831 Anthony Liguori
        g_free(name);
318 8eb02831 Anthony Liguori
    }        
319 f31d07d1 Gerd Hoffmann
    if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
320 f31d07d1 Gerd Hoffmann
        qdev_free(qdev);
321 f31d07d1 Gerd Hoffmann
        return NULL;
322 8ffb1bcf Gerd Hoffmann
    }
323 5c17ca25 Markus Armbruster
    if (qdev_init(qdev) < 0) {
324 0204276b Markus Armbruster
        qerror_report(QERR_DEVICE_INIT_FAILED, driver);
325 81a322d4 Gerd Hoffmann
        return NULL;
326 81a322d4 Gerd Hoffmann
    }
327 ef80b466 Gerd Hoffmann
    qdev->opts = opts;
328 8ffb1bcf Gerd Hoffmann
    return qdev;
329 8ffb1bcf Gerd Hoffmann
}
330 8ffb1bcf Gerd Hoffmann
331 aae9460e Paul Brook
/* Initialize a device.  Device properties should be set before calling
332 aae9460e Paul Brook
   this function.  IRQs and MMIO regions should be connected/mapped after
333 18cfeb52 Markus Armbruster
   calling this function.
334 18cfeb52 Markus Armbruster
   On failure, destroy the device and return negative value.
335 18cfeb52 Markus Armbruster
   Return 0 on success.  */
336 81a322d4 Gerd Hoffmann
int qdev_init(DeviceState *dev)
337 aae9460e Paul Brook
{
338 959f733a Gerd Hoffmann
    int rc;
339 959f733a Gerd Hoffmann
340 131ec1bd Gerd Hoffmann
    assert(dev->state == DEV_STATE_CREATED);
341 959f733a Gerd Hoffmann
    rc = dev->info->init(dev, dev->info);
342 18cfeb52 Markus Armbruster
    if (rc < 0) {
343 18cfeb52 Markus Armbruster
        qdev_free(dev);
344 959f733a Gerd Hoffmann
        return rc;
345 18cfeb52 Markus Armbruster
    }
346 4d2ffa08 Jan Kiszka
    if (dev->info->vmsd) {
347 0be71e32 Alex Williamson
        vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
348 4d2ffa08 Jan Kiszka
                                       dev->instance_id_alias,
349 4d2ffa08 Jan Kiszka
                                       dev->alias_required_for_version);
350 4d2ffa08 Jan Kiszka
    }
351 131ec1bd Gerd Hoffmann
    dev->state = DEV_STATE_INITIALIZED;
352 5ab28c83 Jan Kiszka
    if (dev->hotplugged && dev->info->reset) {
353 5ab28c83 Jan Kiszka
        dev->info->reset(dev);
354 5ab28c83 Jan Kiszka
    }
355 959f733a Gerd Hoffmann
    return 0;
356 02e2da45 Paul Brook
}
357 02e2da45 Paul Brook
358 4d2ffa08 Jan Kiszka
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
359 4d2ffa08 Jan Kiszka
                                 int required_for_version)
360 4d2ffa08 Jan Kiszka
{
361 4d2ffa08 Jan Kiszka
    assert(dev->state == DEV_STATE_CREATED);
362 4d2ffa08 Jan Kiszka
    dev->instance_id_alias = alias_id;
363 4d2ffa08 Jan Kiszka
    dev->alias_required_for_version = required_for_version;
364 4d2ffa08 Jan Kiszka
}
365 4d2ffa08 Jan Kiszka
366 3418bd25 Gerd Hoffmann
int qdev_unplug(DeviceState *dev)
367 3418bd25 Gerd Hoffmann
{
368 3418bd25 Gerd Hoffmann
    if (!dev->parent_bus->allow_hotplug) {
369 cc601cb7 Markus Armbruster
        qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
370 3418bd25 Gerd Hoffmann
        return -1;
371 3418bd25 Gerd Hoffmann
    }
372 593831de Amit Shah
    assert(dev->info->unplug != NULL);
373 593831de Amit Shah
374 85ed303b Anthony Liguori
    if (dev->ref != 0) {
375 85ed303b Anthony Liguori
        qerror_report(QERR_DEVICE_IN_USE, dev->id?:"");
376 85ed303b Anthony Liguori
        return -1;
377 85ed303b Anthony Liguori
    }
378 85ed303b Anthony Liguori
379 0ac8ef71 Alex Williamson
    qdev_hot_removed = true;
380 0ac8ef71 Alex Williamson
381 3418bd25 Gerd Hoffmann
    return dev->info->unplug(dev);
382 3418bd25 Gerd Hoffmann
}
383 3418bd25 Gerd Hoffmann
384 ec990eb6 Anthony Liguori
static int qdev_reset_one(DeviceState *dev, void *opaque)
385 ec990eb6 Anthony Liguori
{
386 ec990eb6 Anthony Liguori
    if (dev->info->reset) {
387 ec990eb6 Anthony Liguori
        dev->info->reset(dev);
388 ec990eb6 Anthony Liguori
    }
389 ec990eb6 Anthony Liguori
390 ec990eb6 Anthony Liguori
    return 0;
391 ec990eb6 Anthony Liguori
}
392 ec990eb6 Anthony Liguori
393 ec990eb6 Anthony Liguori
BusState *sysbus_get_default(void)
394 ec990eb6 Anthony Liguori
{
395 68694897 Stefan Weil
    if (!main_system_bus) {
396 2da8bb92 Isaku Yamahata
        main_system_bus_create();
397 68694897 Stefan Weil
    }
398 ec990eb6 Anthony Liguori
    return main_system_bus;
399 ec990eb6 Anthony Liguori
}
400 ec990eb6 Anthony Liguori
401 b4694b7c Isaku Yamahata
static int qbus_reset_one(BusState *bus, void *opaque)
402 b4694b7c Isaku Yamahata
{
403 b4694b7c Isaku Yamahata
    if (bus->info->reset) {
404 b4694b7c Isaku Yamahata
        return bus->info->reset(bus);
405 b4694b7c Isaku Yamahata
    }
406 b4694b7c Isaku Yamahata
    return 0;
407 b4694b7c Isaku Yamahata
}
408 b4694b7c Isaku Yamahata
409 5af0a04b Isaku Yamahata
void qdev_reset_all(DeviceState *dev)
410 5af0a04b Isaku Yamahata
{
411 5af0a04b Isaku Yamahata
    qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
412 5af0a04b Isaku Yamahata
}
413 5af0a04b Isaku Yamahata
414 80376c3f Isaku Yamahata
void qbus_reset_all_fn(void *opaque)
415 80376c3f Isaku Yamahata
{
416 80376c3f Isaku Yamahata
    BusState *bus = opaque;
417 f530cce3 Michael S. Tsirkin
    qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
418 80376c3f Isaku Yamahata
}
419 80376c3f Isaku Yamahata
420 3418bd25 Gerd Hoffmann
/* can be used as ->unplug() callback for the simple cases */
421 3418bd25 Gerd Hoffmann
int qdev_simple_unplug_cb(DeviceState *dev)
422 3418bd25 Gerd Hoffmann
{
423 3418bd25 Gerd Hoffmann
    /* just zap it */
424 3418bd25 Gerd Hoffmann
    qdev_free(dev);
425 3418bd25 Gerd Hoffmann
    return 0;
426 3418bd25 Gerd Hoffmann
}
427 3418bd25 Gerd Hoffmann
428 3b29a101 Michael Tokarev
429 3b29a101 Michael Tokarev
/* Like qdev_init(), but terminate program via error_report() instead of
430 e23a1b33 Markus Armbruster
   returning an error value.  This is okay during machine creation.
431 e23a1b33 Markus Armbruster
   Don't use for hotplug, because there callers need to recover from
432 e23a1b33 Markus Armbruster
   failure.  Exception: if you know the device's init() callback can't
433 e23a1b33 Markus Armbruster
   fail, then qdev_init_nofail() can't fail either, and is therefore
434 e23a1b33 Markus Armbruster
   usable even then.  But relying on the device implementation that
435 e23a1b33 Markus Armbruster
   way is somewhat unclean, and best avoided.  */
436 e23a1b33 Markus Armbruster
void qdev_init_nofail(DeviceState *dev)
437 e23a1b33 Markus Armbruster
{
438 e23a1b33 Markus Armbruster
    DeviceInfo *info = dev->info;
439 e23a1b33 Markus Armbruster
440 bd6c9a61 Markus Armbruster
    if (qdev_init(dev) < 0) {
441 6daf194d Markus Armbruster
        error_report("Initialization of device %s failed", info->name);
442 bd6c9a61 Markus Armbruster
        exit(1);
443 bd6c9a61 Markus Armbruster
    }
444 e23a1b33 Markus Armbruster
}
445 e23a1b33 Markus Armbruster
446 44677ded Anthony Liguori
static void qdev_property_del_all(DeviceState *dev)
447 44677ded Anthony Liguori
{
448 44677ded Anthony Liguori
    while (!QTAILQ_EMPTY(&dev->properties)) {
449 44677ded Anthony Liguori
        DeviceProperty *prop = QTAILQ_FIRST(&dev->properties);
450 44677ded Anthony Liguori
451 44677ded Anthony Liguori
        QTAILQ_REMOVE(&dev->properties, prop, node);
452 44677ded Anthony Liguori
453 44677ded Anthony Liguori
        if (prop->release) {
454 44677ded Anthony Liguori
            prop->release(dev, prop->name, prop->opaque);
455 44677ded Anthony Liguori
        }
456 44677ded Anthony Liguori
457 44677ded Anthony Liguori
        g_free(prop->name);
458 44677ded Anthony Liguori
        g_free(prop->type);
459 44677ded Anthony Liguori
        g_free(prop);
460 44677ded Anthony Liguori
    }
461 44677ded Anthony Liguori
}
462 44677ded Anthony Liguori
463 02e2da45 Paul Brook
/* Unlink device from bus and free the structure.  */
464 02e2da45 Paul Brook
void qdev_free(DeviceState *dev)
465 02e2da45 Paul Brook
{
466 131ec1bd Gerd Hoffmann
    BusState *bus;
467 d21357df Markus Armbruster
    Property *prop;
468 131ec1bd Gerd Hoffmann
469 44677ded Anthony Liguori
    qdev_property_del_all(dev);
470 44677ded Anthony Liguori
471 131ec1bd Gerd Hoffmann
    if (dev->state == DEV_STATE_INITIALIZED) {
472 131ec1bd Gerd Hoffmann
        while (dev->num_child_bus) {
473 131ec1bd Gerd Hoffmann
            bus = QLIST_FIRST(&dev->child_bus);
474 131ec1bd Gerd Hoffmann
            qbus_free(bus);
475 131ec1bd Gerd Hoffmann
        }
476 131ec1bd Gerd Hoffmann
        if (dev->info->vmsd)
477 0be71e32 Alex Williamson
            vmstate_unregister(dev, dev->info->vmsd, dev);
478 d29275f1 Gerd Hoffmann
        if (dev->info->exit)
479 d29275f1 Gerd Hoffmann
            dev->info->exit(dev);
480 ef80b466 Gerd Hoffmann
        if (dev->opts)
481 ef80b466 Gerd Hoffmann
            qemu_opts_del(dev->opts);
482 131ec1bd Gerd Hoffmann
    }
483 d8bb00d6 Paolo Bonzini
    QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
484 d21357df Markus Armbruster
    for (prop = dev->info->props; prop && prop->name; prop++) {
485 d21357df Markus Armbruster
        if (prop->info->free) {
486 d21357df Markus Armbruster
            prop->info->free(dev, prop);
487 d21357df Markus Armbruster
        }
488 d21357df Markus Armbruster
    }
489 7267c094 Anthony Liguori
    g_free(dev);
490 aae9460e Paul Brook
}
491 aae9460e Paul Brook
492 3418bd25 Gerd Hoffmann
void qdev_machine_creation_done(void)
493 3418bd25 Gerd Hoffmann
{
494 3418bd25 Gerd Hoffmann
    /*
495 3418bd25 Gerd Hoffmann
     * ok, initial machine setup is done, starting from now we can
496 3418bd25 Gerd Hoffmann
     * only create hotpluggable devices
497 3418bd25 Gerd Hoffmann
     */
498 3418bd25 Gerd Hoffmann
    qdev_hotplug = 1;
499 3418bd25 Gerd Hoffmann
}
500 3418bd25 Gerd Hoffmann
501 0ac8ef71 Alex Williamson
bool qdev_machine_modified(void)
502 0ac8ef71 Alex Williamson
{
503 0ac8ef71 Alex Williamson
    return qdev_hot_added || qdev_hot_removed;
504 0ac8ef71 Alex Williamson
}
505 0ac8ef71 Alex Williamson
506 aae9460e Paul Brook
/* Get a character (serial) device interface.  */
507 aae9460e Paul Brook
CharDriverState *qdev_init_chardev(DeviceState *dev)
508 aae9460e Paul Brook
{
509 aae9460e Paul Brook
    static int next_serial;
510 98b19252 Amit Shah
511 98b19252 Amit Shah
    /* FIXME: This function needs to go away: use chardev properties!  */
512 98b19252 Amit Shah
    return serial_hds[next_serial++];
513 aae9460e Paul Brook
}
514 aae9460e Paul Brook
515 02e2da45 Paul Brook
BusState *qdev_get_parent_bus(DeviceState *dev)
516 aae9460e Paul Brook
{
517 02e2da45 Paul Brook
    return dev->parent_bus;
518 aae9460e Paul Brook
}
519 aae9460e Paul Brook
520 aae9460e Paul Brook
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
521 aae9460e Paul Brook
{
522 aae9460e Paul Brook
    assert(dev->num_gpio_in == 0);
523 aae9460e Paul Brook
    dev->num_gpio_in = n;
524 aae9460e Paul Brook
    dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
525 aae9460e Paul Brook
}
526 aae9460e Paul Brook
527 aae9460e Paul Brook
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
528 aae9460e Paul Brook
{
529 aae9460e Paul Brook
    assert(dev->num_gpio_out == 0);
530 aae9460e Paul Brook
    dev->num_gpio_out = n;
531 aae9460e Paul Brook
    dev->gpio_out = pins;
532 aae9460e Paul Brook
}
533 aae9460e Paul Brook
534 aae9460e Paul Brook
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
535 aae9460e Paul Brook
{
536 aae9460e Paul Brook
    assert(n >= 0 && n < dev->num_gpio_in);
537 aae9460e Paul Brook
    return dev->gpio_in[n];
538 aae9460e Paul Brook
}
539 aae9460e Paul Brook
540 aae9460e Paul Brook
void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
541 aae9460e Paul Brook
{
542 aae9460e Paul Brook
    assert(n >= 0 && n < dev->num_gpio_out);
543 aae9460e Paul Brook
    dev->gpio_out[n] = pin;
544 aae9460e Paul Brook
}
545 aae9460e Paul Brook
546 ed16ab5a Gerd Hoffmann
void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
547 ed16ab5a Gerd Hoffmann
{
548 6eed1856 Jan Kiszka
    qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
549 ed16ab5a Gerd Hoffmann
    if (nd->vlan)
550 ed16ab5a Gerd Hoffmann
        qdev_prop_set_vlan(dev, "vlan", nd->vlan);
551 ed16ab5a Gerd Hoffmann
    if (nd->netdev)
552 ed16ab5a Gerd Hoffmann
        qdev_prop_set_netdev(dev, "netdev", nd->netdev);
553 75422b0d Amit Shah
    if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
554 97b15621 Gerd Hoffmann
        qdev_prop_exists(dev, "vectors")) {
555 97b15621 Gerd Hoffmann
        qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
556 97b15621 Gerd Hoffmann
    }
557 48e2faf2 Peter Maydell
    nd->instantiated = 1;
558 ed16ab5a Gerd Hoffmann
}
559 ed16ab5a Gerd Hoffmann
560 02e2da45 Paul Brook
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
561 4d6ae674 Paul Brook
{
562 02e2da45 Paul Brook
    BusState *bus;
563 4d6ae674 Paul Brook
564 72cf2d4f Blue Swirl
    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
565 4d6ae674 Paul Brook
        if (strcmp(name, bus->name) == 0) {
566 02e2da45 Paul Brook
            return bus;
567 4d6ae674 Paul Brook
        }
568 4d6ae674 Paul Brook
    }
569 4d6ae674 Paul Brook
    return NULL;
570 4d6ae674 Paul Brook
}
571 4d6ae674 Paul Brook
572 81699d8a Anthony Liguori
int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
573 81699d8a Anthony Liguori
                       qbus_walkerfn *busfn, void *opaque)
574 81699d8a Anthony Liguori
{
575 81699d8a Anthony Liguori
    DeviceState *dev;
576 81699d8a Anthony Liguori
    int err;
577 81699d8a Anthony Liguori
578 81699d8a Anthony Liguori
    if (busfn) {
579 81699d8a Anthony Liguori
        err = busfn(bus, opaque);
580 81699d8a Anthony Liguori
        if (err) {
581 81699d8a Anthony Liguori
            return err;
582 81699d8a Anthony Liguori
        }
583 81699d8a Anthony Liguori
    }
584 81699d8a Anthony Liguori
585 d8bb00d6 Paolo Bonzini
    QTAILQ_FOREACH(dev, &bus->children, sibling) {
586 81699d8a Anthony Liguori
        err = qdev_walk_children(dev, devfn, busfn, opaque);
587 81699d8a Anthony Liguori
        if (err < 0) {
588 81699d8a Anthony Liguori
            return err;
589 81699d8a Anthony Liguori
        }
590 81699d8a Anthony Liguori
    }
591 81699d8a Anthony Liguori
592 81699d8a Anthony Liguori
    return 0;
593 81699d8a Anthony Liguori
}
594 81699d8a Anthony Liguori
595 81699d8a Anthony Liguori
int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
596 81699d8a Anthony Liguori
                       qbus_walkerfn *busfn, void *opaque)
597 81699d8a Anthony Liguori
{
598 81699d8a Anthony Liguori
    BusState *bus;
599 81699d8a Anthony Liguori
    int err;
600 81699d8a Anthony Liguori
601 81699d8a Anthony Liguori
    if (devfn) {
602 81699d8a Anthony Liguori
        err = devfn(dev, opaque);
603 81699d8a Anthony Liguori
        if (err) {
604 81699d8a Anthony Liguori
            return err;
605 81699d8a Anthony Liguori
        }
606 81699d8a Anthony Liguori
    }
607 81699d8a Anthony Liguori
608 81699d8a Anthony Liguori
    QLIST_FOREACH(bus, &dev->child_bus, sibling) {
609 81699d8a Anthony Liguori
        err = qbus_walk_children(bus, devfn, busfn, opaque);
610 81699d8a Anthony Liguori
        if (err < 0) {
611 81699d8a Anthony Liguori
            return err;
612 81699d8a Anthony Liguori
        }
613 81699d8a Anthony Liguori
    }
614 81699d8a Anthony Liguori
615 81699d8a Anthony Liguori
    return 0;
616 81699d8a Anthony Liguori
}
617 81699d8a Anthony Liguori
618 8ffb1bcf Gerd Hoffmann
static BusState *qbus_find_recursive(BusState *bus, const char *name,
619 8ffb1bcf Gerd Hoffmann
                                     const BusInfo *info)
620 8ffb1bcf Gerd Hoffmann
{
621 8ffb1bcf Gerd Hoffmann
    DeviceState *dev;
622 8ffb1bcf Gerd Hoffmann
    BusState *child, *ret;
623 8ffb1bcf Gerd Hoffmann
    int match = 1;
624 8ffb1bcf Gerd Hoffmann
625 8ffb1bcf Gerd Hoffmann
    if (name && (strcmp(bus->name, name) != 0)) {
626 8ffb1bcf Gerd Hoffmann
        match = 0;
627 8ffb1bcf Gerd Hoffmann
    }
628 8ffb1bcf Gerd Hoffmann
    if (info && (bus->info != info)) {
629 8ffb1bcf Gerd Hoffmann
        match = 0;
630 8ffb1bcf Gerd Hoffmann
    }
631 8ffb1bcf Gerd Hoffmann
    if (match) {
632 8ffb1bcf Gerd Hoffmann
        return bus;
633 8ffb1bcf Gerd Hoffmann
    }
634 8ffb1bcf Gerd Hoffmann
635 d8bb00d6 Paolo Bonzini
    QTAILQ_FOREACH(dev, &bus->children, sibling) {
636 72cf2d4f Blue Swirl
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
637 8ffb1bcf Gerd Hoffmann
            ret = qbus_find_recursive(child, name, info);
638 8ffb1bcf Gerd Hoffmann
            if (ret) {
639 8ffb1bcf Gerd Hoffmann
                return ret;
640 8ffb1bcf Gerd Hoffmann
            }
641 8ffb1bcf Gerd Hoffmann
        }
642 8ffb1bcf Gerd Hoffmann
    }
643 8ffb1bcf Gerd Hoffmann
    return NULL;
644 8ffb1bcf Gerd Hoffmann
}
645 8ffb1bcf Gerd Hoffmann
646 a2ee6b4f Isaku Yamahata
DeviceState *qdev_find_recursive(BusState *bus, const char *id)
647 3418bd25 Gerd Hoffmann
{
648 3418bd25 Gerd Hoffmann
    DeviceState *dev, *ret;
649 3418bd25 Gerd Hoffmann
    BusState *child;
650 3418bd25 Gerd Hoffmann
651 d8bb00d6 Paolo Bonzini
    QTAILQ_FOREACH(dev, &bus->children, sibling) {
652 3418bd25 Gerd Hoffmann
        if (dev->id && strcmp(dev->id, id) == 0)
653 3418bd25 Gerd Hoffmann
            return dev;
654 3418bd25 Gerd Hoffmann
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
655 3418bd25 Gerd Hoffmann
            ret = qdev_find_recursive(child, id);
656 3418bd25 Gerd Hoffmann
            if (ret) {
657 3418bd25 Gerd Hoffmann
                return ret;
658 3418bd25 Gerd Hoffmann
            }
659 3418bd25 Gerd Hoffmann
        }
660 3418bd25 Gerd Hoffmann
    }
661 3418bd25 Gerd Hoffmann
    return NULL;
662 3418bd25 Gerd Hoffmann
}
663 3418bd25 Gerd Hoffmann
664 53db16b5 Markus Armbruster
static void qbus_list_bus(DeviceState *dev)
665 8ffb1bcf Gerd Hoffmann
{
666 8ffb1bcf Gerd Hoffmann
    BusState *child;
667 8ffb1bcf Gerd Hoffmann
    const char *sep = " ";
668 8ffb1bcf Gerd Hoffmann
669 53db16b5 Markus Armbruster
    error_printf("child busses at \"%s\":",
670 53db16b5 Markus Armbruster
                 dev->id ? dev->id : dev->info->name);
671 72cf2d4f Blue Swirl
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
672 53db16b5 Markus Armbruster
        error_printf("%s\"%s\"", sep, child->name);
673 8ffb1bcf Gerd Hoffmann
        sep = ", ";
674 8ffb1bcf Gerd Hoffmann
    }
675 53db16b5 Markus Armbruster
    error_printf("\n");
676 8ffb1bcf Gerd Hoffmann
}
677 8ffb1bcf Gerd Hoffmann
678 53db16b5 Markus Armbruster
static void qbus_list_dev(BusState *bus)
679 8ffb1bcf Gerd Hoffmann
{
680 8ffb1bcf Gerd Hoffmann
    DeviceState *dev;
681 8ffb1bcf Gerd Hoffmann
    const char *sep = " ";
682 8ffb1bcf Gerd Hoffmann
683 53db16b5 Markus Armbruster
    error_printf("devices at \"%s\":", bus->name);
684 d8bb00d6 Paolo Bonzini
    QTAILQ_FOREACH(dev, &bus->children, sibling) {
685 53db16b5 Markus Armbruster
        error_printf("%s\"%s\"", sep, dev->info->name);
686 8ffb1bcf Gerd Hoffmann
        if (dev->id)
687 53db16b5 Markus Armbruster
            error_printf("/\"%s\"", dev->id);
688 8ffb1bcf Gerd Hoffmann
        sep = ", ";
689 8ffb1bcf Gerd Hoffmann
    }
690 53db16b5 Markus Armbruster
    error_printf("\n");
691 8ffb1bcf Gerd Hoffmann
}
692 8ffb1bcf Gerd Hoffmann
693 8ffb1bcf Gerd Hoffmann
static BusState *qbus_find_bus(DeviceState *dev, char *elem)
694 8ffb1bcf Gerd Hoffmann
{
695 8ffb1bcf Gerd Hoffmann
    BusState *child;
696 8ffb1bcf Gerd Hoffmann
697 72cf2d4f Blue Swirl
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
698 8ffb1bcf Gerd Hoffmann
        if (strcmp(child->name, elem) == 0) {
699 8ffb1bcf Gerd Hoffmann
            return child;
700 8ffb1bcf Gerd Hoffmann
        }
701 8ffb1bcf Gerd Hoffmann
    }
702 8ffb1bcf Gerd Hoffmann
    return NULL;
703 8ffb1bcf Gerd Hoffmann
}
704 8ffb1bcf Gerd Hoffmann
705 8ffb1bcf Gerd Hoffmann
static DeviceState *qbus_find_dev(BusState *bus, char *elem)
706 8ffb1bcf Gerd Hoffmann
{
707 8ffb1bcf Gerd Hoffmann
    DeviceState *dev;
708 8ffb1bcf Gerd Hoffmann
709 8ffb1bcf Gerd Hoffmann
    /*
710 8ffb1bcf Gerd Hoffmann
     * try to match in order:
711 8ffb1bcf Gerd Hoffmann
     *   (1) instance id, if present
712 8ffb1bcf Gerd Hoffmann
     *   (2) driver name
713 8ffb1bcf Gerd Hoffmann
     *   (3) driver alias, if present
714 8ffb1bcf Gerd Hoffmann
     */
715 d8bb00d6 Paolo Bonzini
    QTAILQ_FOREACH(dev, &bus->children, sibling) {
716 8ffb1bcf Gerd Hoffmann
        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
717 8ffb1bcf Gerd Hoffmann
            return dev;
718 8ffb1bcf Gerd Hoffmann
        }
719 8ffb1bcf Gerd Hoffmann
    }
720 d8bb00d6 Paolo Bonzini
    QTAILQ_FOREACH(dev, &bus->children, sibling) {
721 8ffb1bcf Gerd Hoffmann
        if (strcmp(dev->info->name, elem) == 0) {
722 8ffb1bcf Gerd Hoffmann
            return dev;
723 8ffb1bcf Gerd Hoffmann
        }
724 8ffb1bcf Gerd Hoffmann
    }
725 d8bb00d6 Paolo Bonzini
    QTAILQ_FOREACH(dev, &bus->children, sibling) {
726 8ffb1bcf Gerd Hoffmann
        if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
727 8ffb1bcf Gerd Hoffmann
            return dev;
728 8ffb1bcf Gerd Hoffmann
        }
729 8ffb1bcf Gerd Hoffmann
    }
730 8ffb1bcf Gerd Hoffmann
    return NULL;
731 8ffb1bcf Gerd Hoffmann
}
732 8ffb1bcf Gerd Hoffmann
733 8ffb1bcf Gerd Hoffmann
static BusState *qbus_find(const char *path)
734 8ffb1bcf Gerd Hoffmann
{
735 8ffb1bcf Gerd Hoffmann
    DeviceState *dev;
736 8ffb1bcf Gerd Hoffmann
    BusState *bus;
737 53db16b5 Markus Armbruster
    char elem[128];
738 8ffb1bcf Gerd Hoffmann
    int pos, len;
739 8ffb1bcf Gerd Hoffmann
740 8ffb1bcf Gerd Hoffmann
    /* find start element */
741 8ffb1bcf Gerd Hoffmann
    if (path[0] == '/') {
742 8ffb1bcf Gerd Hoffmann
        bus = main_system_bus;
743 8ffb1bcf Gerd Hoffmann
        pos = 0;
744 8ffb1bcf Gerd Hoffmann
    } else {
745 8ffb1bcf Gerd Hoffmann
        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
746 fc98eb43 Markus Armbruster
            assert(!path[0]);
747 fc98eb43 Markus Armbruster
            elem[0] = len = 0;
748 8ffb1bcf Gerd Hoffmann
        }
749 8ffb1bcf Gerd Hoffmann
        bus = qbus_find_recursive(main_system_bus, elem, NULL);
750 8ffb1bcf Gerd Hoffmann
        if (!bus) {
751 ac8dae67 Markus Armbruster
            qerror_report(QERR_BUS_NOT_FOUND, elem);
752 8ffb1bcf Gerd Hoffmann
            return NULL;
753 8ffb1bcf Gerd Hoffmann
        }
754 8ffb1bcf Gerd Hoffmann
        pos = len;
755 8ffb1bcf Gerd Hoffmann
    }
756 8ffb1bcf Gerd Hoffmann
757 8ffb1bcf Gerd Hoffmann
    for (;;) {
758 fc98eb43 Markus Armbruster
        assert(path[pos] == '/' || !path[pos]);
759 fc98eb43 Markus Armbruster
        while (path[pos] == '/') {
760 fc98eb43 Markus Armbruster
            pos++;
761 fc98eb43 Markus Armbruster
        }
762 8ffb1bcf Gerd Hoffmann
        if (path[pos] == '\0') {
763 8ffb1bcf Gerd Hoffmann
            return bus;
764 8ffb1bcf Gerd Hoffmann
        }
765 8ffb1bcf Gerd Hoffmann
766 8ffb1bcf Gerd Hoffmann
        /* find device */
767 fc98eb43 Markus Armbruster
        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
768 fc98eb43 Markus Armbruster
            assert(0);
769 fc98eb43 Markus Armbruster
            elem[0] = len = 0;
770 8ffb1bcf Gerd Hoffmann
        }
771 8ffb1bcf Gerd Hoffmann
        pos += len;
772 8ffb1bcf Gerd Hoffmann
        dev = qbus_find_dev(bus, elem);
773 8ffb1bcf Gerd Hoffmann
        if (!dev) {
774 ac8dae67 Markus Armbruster
            qerror_report(QERR_DEVICE_NOT_FOUND, elem);
775 8bc27249 Markus Armbruster
            if (!monitor_cur_is_qmp()) {
776 8bc27249 Markus Armbruster
                qbus_list_dev(bus);
777 8bc27249 Markus Armbruster
            }
778 8ffb1bcf Gerd Hoffmann
            return NULL;
779 8ffb1bcf Gerd Hoffmann
        }
780 fc98eb43 Markus Armbruster
781 fc98eb43 Markus Armbruster
        assert(path[pos] == '/' || !path[pos]);
782 fc98eb43 Markus Armbruster
        while (path[pos] == '/') {
783 fc98eb43 Markus Armbruster
            pos++;
784 fc98eb43 Markus Armbruster
        }
785 8ffb1bcf Gerd Hoffmann
        if (path[pos] == '\0') {
786 8ffb1bcf Gerd Hoffmann
            /* last specified element is a device.  If it has exactly
787 8ffb1bcf Gerd Hoffmann
             * one child bus accept it nevertheless */
788 8ffb1bcf Gerd Hoffmann
            switch (dev->num_child_bus) {
789 8ffb1bcf Gerd Hoffmann
            case 0:
790 ac8dae67 Markus Armbruster
                qerror_report(QERR_DEVICE_NO_BUS, elem);
791 8ffb1bcf Gerd Hoffmann
                return NULL;
792 8ffb1bcf Gerd Hoffmann
            case 1:
793 72cf2d4f Blue Swirl
                return QLIST_FIRST(&dev->child_bus);
794 8ffb1bcf Gerd Hoffmann
            default:
795 ac8dae67 Markus Armbruster
                qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
796 8bc27249 Markus Armbruster
                if (!monitor_cur_is_qmp()) {
797 8bc27249 Markus Armbruster
                    qbus_list_bus(dev);
798 8bc27249 Markus Armbruster
                }
799 8ffb1bcf Gerd Hoffmann
                return NULL;
800 8ffb1bcf Gerd Hoffmann
            }
801 8ffb1bcf Gerd Hoffmann
        }
802 8ffb1bcf Gerd Hoffmann
803 8ffb1bcf Gerd Hoffmann
        /* find bus */
804 fc98eb43 Markus Armbruster
        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
805 fc98eb43 Markus Armbruster
            assert(0);
806 fc98eb43 Markus Armbruster
            elem[0] = len = 0;
807 8ffb1bcf Gerd Hoffmann
        }
808 8ffb1bcf Gerd Hoffmann
        pos += len;
809 8ffb1bcf Gerd Hoffmann
        bus = qbus_find_bus(dev, elem);
810 8ffb1bcf Gerd Hoffmann
        if (!bus) {
811 ac8dae67 Markus Armbruster
            qerror_report(QERR_BUS_NOT_FOUND, elem);
812 8bc27249 Markus Armbruster
            if (!monitor_cur_is_qmp()) {
813 8bc27249 Markus Armbruster
                qbus_list_bus(dev);
814 8bc27249 Markus Armbruster
            }
815 8ffb1bcf Gerd Hoffmann
            return NULL;
816 8ffb1bcf Gerd Hoffmann
        }
817 8ffb1bcf Gerd Hoffmann
    }
818 8ffb1bcf Gerd Hoffmann
}
819 8ffb1bcf Gerd Hoffmann
820 cd739fb6 Gerd Hoffmann
void qbus_create_inplace(BusState *bus, BusInfo *info,
821 cd739fb6 Gerd Hoffmann
                         DeviceState *parent, const char *name)
822 02e2da45 Paul Brook
{
823 d271de9f Gerd Hoffmann
    char *buf;
824 d271de9f Gerd Hoffmann
    int i,len;
825 02e2da45 Paul Brook
826 10c4c98a Gerd Hoffmann
    bus->info = info;
827 02e2da45 Paul Brook
    bus->parent = parent;
828 d271de9f Gerd Hoffmann
829 d271de9f Gerd Hoffmann
    if (name) {
830 d271de9f Gerd Hoffmann
        /* use supplied name */
831 7267c094 Anthony Liguori
        bus->name = g_strdup(name);
832 d271de9f Gerd Hoffmann
    } else if (parent && parent->id) {
833 d271de9f Gerd Hoffmann
        /* parent device has id -> use it for bus name */
834 d271de9f Gerd Hoffmann
        len = strlen(parent->id) + 16;
835 7267c094 Anthony Liguori
        buf = g_malloc(len);
836 d271de9f Gerd Hoffmann
        snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
837 d271de9f Gerd Hoffmann
        bus->name = buf;
838 d271de9f Gerd Hoffmann
    } else {
839 d271de9f Gerd Hoffmann
        /* no id -> use lowercase bus type for bus name */
840 d271de9f Gerd Hoffmann
        len = strlen(info->name) + 16;
841 7267c094 Anthony Liguori
        buf = g_malloc(len);
842 d271de9f Gerd Hoffmann
        len = snprintf(buf, len, "%s.%d", info->name,
843 d271de9f Gerd Hoffmann
                       parent ? parent->num_child_bus : 0);
844 d271de9f Gerd Hoffmann
        for (i = 0; i < len; i++)
845 bb87ece5 Christoph Egger
            buf[i] = qemu_tolower(buf[i]);
846 d271de9f Gerd Hoffmann
        bus->name = buf;
847 d271de9f Gerd Hoffmann
    }
848 d271de9f Gerd Hoffmann
849 d8bb00d6 Paolo Bonzini
    QTAILQ_INIT(&bus->children);
850 02e2da45 Paul Brook
    if (parent) {
851 72cf2d4f Blue Swirl
        QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
852 d271de9f Gerd Hoffmann
        parent->num_child_bus++;
853 80376c3f Isaku Yamahata
    } else if (bus != main_system_bus) {
854 80376c3f Isaku Yamahata
        /* TODO: once all bus devices are qdevified,
855 80376c3f Isaku Yamahata
           only reset handler for main_system_bus should be registered here. */
856 80376c3f Isaku Yamahata
        qemu_register_reset(qbus_reset_all_fn, bus);
857 02e2da45 Paul Brook
    }
858 cd739fb6 Gerd Hoffmann
}
859 cd739fb6 Gerd Hoffmann
860 cd739fb6 Gerd Hoffmann
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
861 cd739fb6 Gerd Hoffmann
{
862 cd739fb6 Gerd Hoffmann
    BusState *bus;
863 cd739fb6 Gerd Hoffmann
864 7267c094 Anthony Liguori
    bus = g_malloc0(info->size);
865 cd739fb6 Gerd Hoffmann
    bus->qdev_allocated = 1;
866 cd739fb6 Gerd Hoffmann
    qbus_create_inplace(bus, info, parent, name);
867 02e2da45 Paul Brook
    return bus;
868 02e2da45 Paul Brook
}
869 cae4956e Gerd Hoffmann
870 2da8bb92 Isaku Yamahata
static void main_system_bus_create(void)
871 2da8bb92 Isaku Yamahata
{
872 2da8bb92 Isaku Yamahata
    /* assign main_system_bus before qbus_create_inplace()
873 2da8bb92 Isaku Yamahata
     * in order to make "if (bus != main_system_bus)" work */
874 7267c094 Anthony Liguori
    main_system_bus = g_malloc0(system_bus_info.size);
875 2da8bb92 Isaku Yamahata
    main_system_bus->qdev_allocated = 1;
876 2da8bb92 Isaku Yamahata
    qbus_create_inplace(main_system_bus, &system_bus_info, NULL,
877 2da8bb92 Isaku Yamahata
                        "main-system-bus");
878 2da8bb92 Isaku Yamahata
}
879 2da8bb92 Isaku Yamahata
880 131ec1bd Gerd Hoffmann
void qbus_free(BusState *bus)
881 131ec1bd Gerd Hoffmann
{
882 131ec1bd Gerd Hoffmann
    DeviceState *dev;
883 131ec1bd Gerd Hoffmann
884 d8bb00d6 Paolo Bonzini
    while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
885 131ec1bd Gerd Hoffmann
        qdev_free(dev);
886 131ec1bd Gerd Hoffmann
    }
887 131ec1bd Gerd Hoffmann
    if (bus->parent) {
888 131ec1bd Gerd Hoffmann
        QLIST_REMOVE(bus, sibling);
889 131ec1bd Gerd Hoffmann
        bus->parent->num_child_bus--;
890 80376c3f Isaku Yamahata
    } else {
891 80376c3f Isaku Yamahata
        assert(bus != main_system_bus); /* main_system_bus is never freed */
892 80376c3f Isaku Yamahata
        qemu_unregister_reset(qbus_reset_all_fn, bus);
893 131ec1bd Gerd Hoffmann
    }
894 7267c094 Anthony Liguori
    g_free((void*)bus->name);
895 131ec1bd Gerd Hoffmann
    if (bus->qdev_allocated) {
896 7267c094 Anthony Liguori
        g_free(bus);
897 131ec1bd Gerd Hoffmann
    }
898 131ec1bd Gerd Hoffmann
}
899 131ec1bd Gerd Hoffmann
900 cae4956e Gerd Hoffmann
#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
901 cae4956e Gerd Hoffmann
static void qbus_print(Monitor *mon, BusState *bus, int indent);
902 cae4956e Gerd Hoffmann
903 ee6847d1 Gerd Hoffmann
static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
904 ee6847d1 Gerd Hoffmann
                             const char *prefix, int indent)
905 ee6847d1 Gerd Hoffmann
{
906 ee6847d1 Gerd Hoffmann
    char buf[64];
907 ee6847d1 Gerd Hoffmann
908 ee6847d1 Gerd Hoffmann
    if (!props)
909 ee6847d1 Gerd Hoffmann
        return;
910 ee6847d1 Gerd Hoffmann
    while (props->name) {
911 036f7166 Markus Armbruster
        /*
912 036f7166 Markus Armbruster
         * TODO Properties without a print method are just for dirty
913 036f7166 Markus Armbruster
         * hacks.  qdev_prop_ptr is the only such PropertyInfo.  It's
914 036f7166 Markus Armbruster
         * marked for removal.  The test props->info->print should be
915 036f7166 Markus Armbruster
         * removed along with it.
916 036f7166 Markus Armbruster
         */
917 ee6847d1 Gerd Hoffmann
        if (props->info->print) {
918 ee6847d1 Gerd Hoffmann
            props->info->print(dev, props, buf, sizeof(buf));
919 ee6847d1 Gerd Hoffmann
            qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
920 ee6847d1 Gerd Hoffmann
        }
921 ee6847d1 Gerd Hoffmann
        props++;
922 ee6847d1 Gerd Hoffmann
    }
923 ee6847d1 Gerd Hoffmann
}
924 ee6847d1 Gerd Hoffmann
925 cae4956e Gerd Hoffmann
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
926 cae4956e Gerd Hoffmann
{
927 cae4956e Gerd Hoffmann
    BusState *child;
928 ccb63de3 Gerd Hoffmann
    qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
929 ccb63de3 Gerd Hoffmann
                dev->id ? dev->id : "");
930 cae4956e Gerd Hoffmann
    indent += 2;
931 cae4956e Gerd Hoffmann
    if (dev->num_gpio_in) {
932 cae4956e Gerd Hoffmann
        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
933 cae4956e Gerd Hoffmann
    }
934 cae4956e Gerd Hoffmann
    if (dev->num_gpio_out) {
935 cae4956e Gerd Hoffmann
        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
936 cae4956e Gerd Hoffmann
    }
937 ee6847d1 Gerd Hoffmann
    qdev_print_props(mon, dev, dev->info->props, "dev", indent);
938 ee6847d1 Gerd Hoffmann
    qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
939 10c4c98a Gerd Hoffmann
    if (dev->parent_bus->info->print_dev)
940 10c4c98a Gerd Hoffmann
        dev->parent_bus->info->print_dev(mon, dev, indent);
941 72cf2d4f Blue Swirl
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
942 cae4956e Gerd Hoffmann
        qbus_print(mon, child, indent);
943 cae4956e Gerd Hoffmann
    }
944 cae4956e Gerd Hoffmann
}
945 cae4956e Gerd Hoffmann
946 cae4956e Gerd Hoffmann
static void qbus_print(Monitor *mon, BusState *bus, int indent)
947 cae4956e Gerd Hoffmann
{
948 cae4956e Gerd Hoffmann
    struct DeviceState *dev;
949 cae4956e Gerd Hoffmann
950 cae4956e Gerd Hoffmann
    qdev_printf("bus: %s\n", bus->name);
951 cae4956e Gerd Hoffmann
    indent += 2;
952 10c4c98a Gerd Hoffmann
    qdev_printf("type %s\n", bus->info->name);
953 d8bb00d6 Paolo Bonzini
    QTAILQ_FOREACH(dev, &bus->children, sibling) {
954 cae4956e Gerd Hoffmann
        qdev_print(mon, dev, indent);
955 cae4956e Gerd Hoffmann
    }
956 cae4956e Gerd Hoffmann
}
957 cae4956e Gerd Hoffmann
#undef qdev_printf
958 cae4956e Gerd Hoffmann
959 cae4956e Gerd Hoffmann
void do_info_qtree(Monitor *mon)
960 cae4956e Gerd Hoffmann
{
961 cae4956e Gerd Hoffmann
    if (main_system_bus)
962 cae4956e Gerd Hoffmann
        qbus_print(mon, main_system_bus, 0);
963 cae4956e Gerd Hoffmann
}
964 9316d30f Gerd Hoffmann
965 f6c64e0e Gerd Hoffmann
void do_info_qdm(Monitor *mon)
966 9316d30f Gerd Hoffmann
{
967 9316d30f Gerd Hoffmann
    DeviceInfo *info;
968 9316d30f Gerd Hoffmann
969 9316d30f Gerd Hoffmann
    for (info = device_info_list; info != NULL; info = info->next) {
970 8a9662ca Markus Armbruster
        qdev_print_devinfo(info);
971 9316d30f Gerd Hoffmann
    }
972 9316d30f Gerd Hoffmann
}
973 3418bd25 Gerd Hoffmann
974 8bc27249 Markus Armbruster
int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
975 3418bd25 Gerd Hoffmann
{
976 3418bd25 Gerd Hoffmann
    QemuOpts *opts;
977 3418bd25 Gerd Hoffmann
978 3329f07b Gerd Hoffmann
    opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
979 8bc27249 Markus Armbruster
    if (!opts) {
980 8bc27249 Markus Armbruster
        return -1;
981 8bc27249 Markus Armbruster
    }
982 8bc27249 Markus Armbruster
    if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
983 8bc27249 Markus Armbruster
        qemu_opts_del(opts);
984 8bc27249 Markus Armbruster
        return 0;
985 0f853a38 Kevin Wolf
    }
986 8bc27249 Markus Armbruster
    if (!qdev_device_add(opts)) {
987 8bc27249 Markus Armbruster
        qemu_opts_del(opts);
988 8bc27249 Markus Armbruster
        return -1;
989 8bc27249 Markus Armbruster
    }
990 8bc27249 Markus Armbruster
    return 0;
991 3418bd25 Gerd Hoffmann
}
992 3418bd25 Gerd Hoffmann
993 17a38eaa Markus Armbruster
int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
994 3418bd25 Gerd Hoffmann
{
995 3418bd25 Gerd Hoffmann
    const char *id = qdict_get_str(qdict, "id");
996 3418bd25 Gerd Hoffmann
    DeviceState *dev;
997 3418bd25 Gerd Hoffmann
998 3418bd25 Gerd Hoffmann
    dev = qdev_find_recursive(main_system_bus, id);
999 3418bd25 Gerd Hoffmann
    if (NULL == dev) {
1000 17a38eaa Markus Armbruster
        qerror_report(QERR_DEVICE_NOT_FOUND, id);
1001 17a38eaa Markus Armbruster
        return -1;
1002 3418bd25 Gerd Hoffmann
    }
1003 17a38eaa Markus Armbruster
    return qdev_unplug(dev);
1004 3418bd25 Gerd Hoffmann
}
1005 1ca4d09a Gleb Natapov
1006 1ca4d09a Gleb Natapov
static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
1007 1ca4d09a Gleb Natapov
{
1008 1ca4d09a Gleb Natapov
    int l = 0;
1009 1ca4d09a Gleb Natapov
1010 1ca4d09a Gleb Natapov
    if (dev && dev->parent_bus) {
1011 1ca4d09a Gleb Natapov
        char *d;
1012 1ca4d09a Gleb Natapov
        l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
1013 1ca4d09a Gleb Natapov
        if (dev->parent_bus->info->get_fw_dev_path) {
1014 1ca4d09a Gleb Natapov
            d = dev->parent_bus->info->get_fw_dev_path(dev);
1015 1ca4d09a Gleb Natapov
            l += snprintf(p + l, size - l, "%s", d);
1016 7267c094 Anthony Liguori
            g_free(d);
1017 1ca4d09a Gleb Natapov
        } else {
1018 1ca4d09a Gleb Natapov
            l += snprintf(p + l, size - l, "%s", dev->info->name);
1019 1ca4d09a Gleb Natapov
        }
1020 1ca4d09a Gleb Natapov
    }
1021 1ca4d09a Gleb Natapov
    l += snprintf(p + l , size - l, "/");
1022 1ca4d09a Gleb Natapov
1023 1ca4d09a Gleb Natapov
    return l;
1024 1ca4d09a Gleb Natapov
}
1025 1ca4d09a Gleb Natapov
1026 1ca4d09a Gleb Natapov
char* qdev_get_fw_dev_path(DeviceState *dev)
1027 1ca4d09a Gleb Natapov
{
1028 1ca4d09a Gleb Natapov
    char path[128];
1029 1ca4d09a Gleb Natapov
    int l;
1030 1ca4d09a Gleb Natapov
1031 1ca4d09a Gleb Natapov
    l = qdev_get_fw_dev_path_helper(dev, path, 128);
1032 1ca4d09a Gleb Natapov
1033 1ca4d09a Gleb Natapov
    path[l-1] = '\0';
1034 1ca4d09a Gleb Natapov
1035 1ca4d09a Gleb Natapov
    return strdup(path);
1036 1ca4d09a Gleb Natapov
}
1037 85ed303b Anthony Liguori
1038 cd34d667 Anthony Liguori
char *qdev_get_type(DeviceState *dev, Error **errp)
1039 cd34d667 Anthony Liguori
{
1040 cd34d667 Anthony Liguori
    return g_strdup(dev->info->name);
1041 cd34d667 Anthony Liguori
}
1042 cd34d667 Anthony Liguori
1043 85ed303b Anthony Liguori
void qdev_ref(DeviceState *dev)
1044 85ed303b Anthony Liguori
{
1045 85ed303b Anthony Liguori
    dev->ref++;
1046 85ed303b Anthony Liguori
}
1047 85ed303b Anthony Liguori
1048 85ed303b Anthony Liguori
void qdev_unref(DeviceState *dev)
1049 85ed303b Anthony Liguori
{
1050 85ed303b Anthony Liguori
    g_assert(dev->ref > 0);
1051 85ed303b Anthony Liguori
    dev->ref--;
1052 85ed303b Anthony Liguori
}
1053 44677ded Anthony Liguori
1054 44677ded Anthony Liguori
void qdev_property_add(DeviceState *dev, const char *name, const char *type,
1055 44677ded Anthony Liguori
                       DevicePropertyAccessor *get, DevicePropertyAccessor *set,
1056 44677ded Anthony Liguori
                       DevicePropertyRelease *release,
1057 44677ded Anthony Liguori
                       void *opaque, Error **errp)
1058 44677ded Anthony Liguori
{
1059 44677ded Anthony Liguori
    DeviceProperty *prop = g_malloc0(sizeof(*prop));
1060 44677ded Anthony Liguori
1061 44677ded Anthony Liguori
    prop->name = g_strdup(name);
1062 44677ded Anthony Liguori
    prop->type = g_strdup(type);
1063 44677ded Anthony Liguori
1064 44677ded Anthony Liguori
    prop->get = get;
1065 44677ded Anthony Liguori
    prop->set = set;
1066 44677ded Anthony Liguori
    prop->release = release;
1067 44677ded Anthony Liguori
    prop->opaque = opaque;
1068 44677ded Anthony Liguori
1069 44677ded Anthony Liguori
    QTAILQ_INSERT_TAIL(&dev->properties, prop, node);
1070 44677ded Anthony Liguori
}
1071 44677ded Anthony Liguori
1072 44677ded Anthony Liguori
static DeviceProperty *qdev_property_find(DeviceState *dev, const char *name)
1073 44677ded Anthony Liguori
{
1074 44677ded Anthony Liguori
    DeviceProperty *prop;
1075 44677ded Anthony Liguori
1076 44677ded Anthony Liguori
    QTAILQ_FOREACH(prop, &dev->properties, node) {
1077 44677ded Anthony Liguori
        if (strcmp(prop->name, name) == 0) {
1078 44677ded Anthony Liguori
            return prop;
1079 44677ded Anthony Liguori
        }
1080 44677ded Anthony Liguori
    }
1081 44677ded Anthony Liguori
1082 44677ded Anthony Liguori
    return NULL;
1083 44677ded Anthony Liguori
}
1084 44677ded Anthony Liguori
1085 44677ded Anthony Liguori
void qdev_property_get(DeviceState *dev, Visitor *v, const char *name,
1086 44677ded Anthony Liguori
                       Error **errp)
1087 44677ded Anthony Liguori
{
1088 44677ded Anthony Liguori
    DeviceProperty *prop = qdev_property_find(dev, name);
1089 44677ded Anthony Liguori
1090 44677ded Anthony Liguori
    if (prop == NULL) {
1091 44677ded Anthony Liguori
        error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1092 44677ded Anthony Liguori
        return;
1093 44677ded Anthony Liguori
    }
1094 44677ded Anthony Liguori
1095 44677ded Anthony Liguori
    if (!prop->get) {
1096 44677ded Anthony Liguori
        error_set(errp, QERR_PERMISSION_DENIED);
1097 44677ded Anthony Liguori
    } else {
1098 44677ded Anthony Liguori
        prop->get(dev, v, prop->opaque, name, errp);
1099 44677ded Anthony Liguori
    }
1100 44677ded Anthony Liguori
}
1101 44677ded Anthony Liguori
1102 44677ded Anthony Liguori
void qdev_property_set(DeviceState *dev, Visitor *v, const char *name,
1103 44677ded Anthony Liguori
                       Error **errp)
1104 44677ded Anthony Liguori
{
1105 44677ded Anthony Liguori
    DeviceProperty *prop = qdev_property_find(dev, name);
1106 44677ded Anthony Liguori
1107 44677ded Anthony Liguori
    if (prop == NULL) {
1108 44677ded Anthony Liguori
        error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1109 44677ded Anthony Liguori
        return;
1110 44677ded Anthony Liguori
    }
1111 44677ded Anthony Liguori
1112 44677ded Anthony Liguori
    if (!prop->set) {
1113 44677ded Anthony Liguori
        error_set(errp, QERR_PERMISSION_DENIED);
1114 44677ded Anthony Liguori
    } else {
1115 0d41d9aa Paolo Bonzini
        prop->set(dev, v, prop->opaque, name, errp);
1116 44677ded Anthony Liguori
    }
1117 44677ded Anthony Liguori
}
1118 44677ded Anthony Liguori
1119 44677ded Anthony Liguori
const char *qdev_property_get_type(DeviceState *dev, const char *name, Error **errp)
1120 44677ded Anthony Liguori
{
1121 44677ded Anthony Liguori
    DeviceProperty *prop = qdev_property_find(dev, name);
1122 44677ded Anthony Liguori
1123 44677ded Anthony Liguori
    if (prop == NULL) {
1124 44677ded Anthony Liguori
        error_set(errp, QERR_PROPERTY_NOT_FOUND, dev->id?:"", name);
1125 44677ded Anthony Liguori
        return NULL;
1126 44677ded Anthony Liguori
    }
1127 44677ded Anthony Liguori
1128 44677ded Anthony Liguori
    return prop->type;
1129 44677ded Anthony Liguori
}
1130 a5296ca9 Anthony Liguori
1131 a5296ca9 Anthony Liguori
/**
1132 a5296ca9 Anthony Liguori
 * Legacy property handling
1133 a5296ca9 Anthony Liguori
 */
1134 a5296ca9 Anthony Liguori
1135 a5296ca9 Anthony Liguori
static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1136 a5296ca9 Anthony Liguori
                                     const char *name, Error **errp)
1137 a5296ca9 Anthony Liguori
{
1138 a5296ca9 Anthony Liguori
    Property *prop = opaque;
1139 a5296ca9 Anthony Liguori
1140 e3cb6ba6 Paolo Bonzini
    char buffer[1024];
1141 e3cb6ba6 Paolo Bonzini
    char *ptr = buffer;
1142 a5296ca9 Anthony Liguori
1143 e3cb6ba6 Paolo Bonzini
    prop->info->print(dev, prop, buffer, sizeof(buffer));
1144 e3cb6ba6 Paolo Bonzini
    visit_type_str(v, &ptr, name, errp);
1145 a5296ca9 Anthony Liguori
}
1146 a5296ca9 Anthony Liguori
1147 a5296ca9 Anthony Liguori
static void qdev_set_legacy_property(DeviceState *dev, Visitor *v, void *opaque,
1148 a5296ca9 Anthony Liguori
                                     const char *name, Error **errp)
1149 a5296ca9 Anthony Liguori
{
1150 a5296ca9 Anthony Liguori
    Property *prop = opaque;
1151 e3cb6ba6 Paolo Bonzini
    Error *local_err = NULL;
1152 e3cb6ba6 Paolo Bonzini
    char *ptr = NULL;
1153 e3cb6ba6 Paolo Bonzini
    int ret;
1154 a5296ca9 Anthony Liguori
1155 a5296ca9 Anthony Liguori
    if (dev->state != DEV_STATE_CREATED) {
1156 a5296ca9 Anthony Liguori
        error_set(errp, QERR_PERMISSION_DENIED);
1157 a5296ca9 Anthony Liguori
        return;
1158 a5296ca9 Anthony Liguori
    }
1159 a5296ca9 Anthony Liguori
1160 e3cb6ba6 Paolo Bonzini
    visit_type_str(v, &ptr, name, &local_err);
1161 e3cb6ba6 Paolo Bonzini
    if (local_err) {
1162 e3cb6ba6 Paolo Bonzini
        error_propagate(errp, local_err);
1163 e3cb6ba6 Paolo Bonzini
        return;
1164 e3cb6ba6 Paolo Bonzini
    }
1165 a5296ca9 Anthony Liguori
1166 e3cb6ba6 Paolo Bonzini
    ret = prop->info->parse(dev, prop, ptr);
1167 7db4c4e8 Paolo Bonzini
    error_set_from_qdev_prop_error(errp, ret, dev, prop, ptr);
1168 e3cb6ba6 Paolo Bonzini
    g_free(ptr);
1169 a5296ca9 Anthony Liguori
}
1170 a5296ca9 Anthony Liguori
1171 a5296ca9 Anthony Liguori
/**
1172 a5296ca9 Anthony Liguori
 * @qdev_add_legacy_property - adds a legacy property
1173 a5296ca9 Anthony Liguori
 *
1174 a5296ca9 Anthony Liguori
 * Do not use this is new code!  Properties added through this interface will
1175 a5296ca9 Anthony Liguori
 * be given types in the "legacy<>" type namespace.
1176 a5296ca9 Anthony Liguori
 *
1177 a5296ca9 Anthony Liguori
 * Legacy properties are always processed as strings.  The format of the string
1178 a5296ca9 Anthony Liguori
 * depends on the property type.
1179 a5296ca9 Anthony Liguori
 */
1180 a5296ca9 Anthony Liguori
void qdev_property_add_legacy(DeviceState *dev, Property *prop,
1181 a5296ca9 Anthony Liguori
                              Error **errp)
1182 a5296ca9 Anthony Liguori
{
1183 a5296ca9 Anthony Liguori
    gchar *type;
1184 a5296ca9 Anthony Liguori
1185 cafe5bdb Paolo Bonzini
    type = g_strdup_printf("legacy<%s>",
1186 cafe5bdb Paolo Bonzini
                           prop->info->legacy_name ?: prop->info->name);
1187 a5296ca9 Anthony Liguori
1188 a5296ca9 Anthony Liguori
    qdev_property_add(dev, prop->name, type,
1189 e3cb6ba6 Paolo Bonzini
                      prop->info->print ? qdev_get_legacy_property : NULL,
1190 e3cb6ba6 Paolo Bonzini
                      prop->info->parse ? qdev_set_legacy_property : NULL,
1191 a5296ca9 Anthony Liguori
                      NULL,
1192 a5296ca9 Anthony Liguori
                      prop, errp);
1193 a5296ca9 Anthony Liguori
1194 a5296ca9 Anthony Liguori
    g_free(type);
1195 a5296ca9 Anthony Liguori
}
1196 a10f07a7 Anthony Liguori
1197 a10f07a7 Anthony Liguori
DeviceState *qdev_get_root(void)
1198 a10f07a7 Anthony Liguori
{
1199 a10f07a7 Anthony Liguori
    static DeviceState *qdev_root;
1200 a10f07a7 Anthony Liguori
1201 a10f07a7 Anthony Liguori
    if (!qdev_root) {
1202 a10f07a7 Anthony Liguori
        qdev_root = qdev_create(NULL, "container");
1203 a10f07a7 Anthony Liguori
        qdev_init_nofail(qdev_root);
1204 a10f07a7 Anthony Liguori
    }
1205 a10f07a7 Anthony Liguori
1206 a10f07a7 Anthony Liguori
    return qdev_root;
1207 a10f07a7 Anthony Liguori
}
1208 f9fbd2fd Anthony Liguori
1209 3de1c3e8 Anthony Liguori
static void qdev_get_child_property(DeviceState *dev, Visitor *v, void *opaque,
1210 3de1c3e8 Anthony Liguori
                                    const char *name, Error **errp)
1211 3de1c3e8 Anthony Liguori
{
1212 3de1c3e8 Anthony Liguori
    DeviceState *child = opaque;
1213 3de1c3e8 Anthony Liguori
    gchar *path;
1214 3de1c3e8 Anthony Liguori
1215 3de1c3e8 Anthony Liguori
    path = qdev_get_canonical_path(child);
1216 3de1c3e8 Anthony Liguori
    visit_type_str(v, &path, name, errp);
1217 3de1c3e8 Anthony Liguori
    g_free(path);
1218 3de1c3e8 Anthony Liguori
}
1219 3de1c3e8 Anthony Liguori
1220 3de1c3e8 Anthony Liguori
void qdev_property_add_child(DeviceState *dev, const char *name,
1221 3de1c3e8 Anthony Liguori
                             DeviceState *child, Error **errp)
1222 3de1c3e8 Anthony Liguori
{
1223 3de1c3e8 Anthony Liguori
    gchar *type;
1224 3de1c3e8 Anthony Liguori
1225 3de1c3e8 Anthony Liguori
    type = g_strdup_printf("child<%s>", child->info->name);
1226 3de1c3e8 Anthony Liguori
1227 3de1c3e8 Anthony Liguori
    qdev_property_add(dev, name, type, qdev_get_child_property,
1228 3de1c3e8 Anthony Liguori
                      NULL, NULL, child, errp);
1229 3de1c3e8 Anthony Liguori
1230 3de1c3e8 Anthony Liguori
    qdev_ref(child);
1231 b2b6c39a Anthony Liguori
    g_assert(child->parent == NULL);
1232 b2b6c39a Anthony Liguori
    child->parent = dev;
1233 3de1c3e8 Anthony Liguori
1234 3de1c3e8 Anthony Liguori
    g_free(type);
1235 3de1c3e8 Anthony Liguori
}
1236 3de1c3e8 Anthony Liguori
1237 83e94fb8 Anthony Liguori
static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
1238 83e94fb8 Anthony Liguori
                                   const char *name, Error **errp)
1239 83e94fb8 Anthony Liguori
{
1240 83e94fb8 Anthony Liguori
    DeviceState **child = opaque;
1241 83e94fb8 Anthony Liguori
    gchar *path;
1242 83e94fb8 Anthony Liguori
1243 83e94fb8 Anthony Liguori
    if (*child) {
1244 83e94fb8 Anthony Liguori
        path = qdev_get_canonical_path(*child);
1245 83e94fb8 Anthony Liguori
        visit_type_str(v, &path, name, errp);
1246 83e94fb8 Anthony Liguori
        g_free(path);
1247 83e94fb8 Anthony Liguori
    } else {
1248 83e94fb8 Anthony Liguori
        path = (gchar *)"";
1249 83e94fb8 Anthony Liguori
        visit_type_str(v, &path, name, errp);
1250 83e94fb8 Anthony Liguori
    }
1251 83e94fb8 Anthony Liguori
}
1252 83e94fb8 Anthony Liguori
1253 83e94fb8 Anthony Liguori
static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
1254 83e94fb8 Anthony Liguori
                                   const char *name, Error **errp)
1255 83e94fb8 Anthony Liguori
{
1256 83e94fb8 Anthony Liguori
    DeviceState **child = opaque;
1257 83e94fb8 Anthony Liguori
    bool ambiguous = false;
1258 83e94fb8 Anthony Liguori
    const char *type;
1259 83e94fb8 Anthony Liguori
    char *path;
1260 83e94fb8 Anthony Liguori
1261 83e94fb8 Anthony Liguori
    type = qdev_property_get_type(dev, name, NULL);
1262 83e94fb8 Anthony Liguori
1263 83e94fb8 Anthony Liguori
    visit_type_str(v, &path, name, errp);
1264 83e94fb8 Anthony Liguori
1265 83e94fb8 Anthony Liguori
    if (*child) {
1266 83e94fb8 Anthony Liguori
        qdev_unref(*child);
1267 83e94fb8 Anthony Liguori
    }
1268 83e94fb8 Anthony Liguori
1269 83e94fb8 Anthony Liguori
    if (strcmp(path, "") != 0) {
1270 83e94fb8 Anthony Liguori
        DeviceState *target;
1271 83e94fb8 Anthony Liguori
1272 83e94fb8 Anthony Liguori
        target = qdev_resolve_path(path, &ambiguous);
1273 83e94fb8 Anthony Liguori
        if (target) {
1274 83e94fb8 Anthony Liguori
            gchar *target_type;
1275 83e94fb8 Anthony Liguori
1276 83e94fb8 Anthony Liguori
            target_type = g_strdup_printf("link<%s>", target->info->name);
1277 83e94fb8 Anthony Liguori
            if (strcmp(target_type, type) == 0) {
1278 83e94fb8 Anthony Liguori
                *child = target;
1279 83e94fb8 Anthony Liguori
                qdev_ref(target);
1280 83e94fb8 Anthony Liguori
            } else {
1281 83e94fb8 Anthony Liguori
                error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
1282 83e94fb8 Anthony Liguori
            }
1283 83e94fb8 Anthony Liguori
1284 83e94fb8 Anthony Liguori
            g_free(target_type);
1285 83e94fb8 Anthony Liguori
        } else {
1286 83e94fb8 Anthony Liguori
            error_set(errp, QERR_DEVICE_NOT_FOUND, path);
1287 83e94fb8 Anthony Liguori
        }
1288 83e94fb8 Anthony Liguori
    } else {
1289 83e94fb8 Anthony Liguori
        *child = NULL;
1290 83e94fb8 Anthony Liguori
    }
1291 83e94fb8 Anthony Liguori
1292 83e94fb8 Anthony Liguori
    g_free(path);
1293 83e94fb8 Anthony Liguori
}
1294 83e94fb8 Anthony Liguori
1295 83e94fb8 Anthony Liguori
void qdev_property_add_link(DeviceState *dev, const char *name,
1296 83e94fb8 Anthony Liguori
                            const char *type, DeviceState **child,
1297 83e94fb8 Anthony Liguori
                            Error **errp)
1298 83e94fb8 Anthony Liguori
{
1299 83e94fb8 Anthony Liguori
    gchar *full_type;
1300 83e94fb8 Anthony Liguori
1301 83e94fb8 Anthony Liguori
    full_type = g_strdup_printf("link<%s>", type);
1302 83e94fb8 Anthony Liguori
1303 83e94fb8 Anthony Liguori
    qdev_property_add(dev, name, full_type,
1304 83e94fb8 Anthony Liguori
                      qdev_get_link_property,
1305 83e94fb8 Anthony Liguori
                      qdev_set_link_property,
1306 83e94fb8 Anthony Liguori
                      NULL, child, errp);
1307 83e94fb8 Anthony Liguori
1308 83e94fb8 Anthony Liguori
    g_free(full_type);
1309 83e94fb8 Anthony Liguori
}
1310 83e94fb8 Anthony Liguori
1311 b2b6c39a Anthony Liguori
gchar *qdev_get_canonical_path(DeviceState *dev)
1312 f9fbd2fd Anthony Liguori
{
1313 b2b6c39a Anthony Liguori
    DeviceState *root = qdev_get_root();
1314 b2b6c39a Anthony Liguori
    char *newpath = NULL, *path = NULL;
1315 f9fbd2fd Anthony Liguori
1316 b2b6c39a Anthony Liguori
    while (dev != root) {
1317 b2b6c39a Anthony Liguori
        DeviceProperty *prop = NULL;
1318 f9fbd2fd Anthony Liguori
1319 b2b6c39a Anthony Liguori
        g_assert(dev->parent != NULL);
1320 f9fbd2fd Anthony Liguori
1321 b2b6c39a Anthony Liguori
        QTAILQ_FOREACH(prop, &dev->parent->properties, node) {
1322 b2b6c39a Anthony Liguori
            if (!strstart(prop->type, "child<", NULL)) {
1323 b2b6c39a Anthony Liguori
                continue;
1324 b2b6c39a Anthony Liguori
            }
1325 f9fbd2fd Anthony Liguori
1326 b2b6c39a Anthony Liguori
            if (prop->opaque == dev) {
1327 b2b6c39a Anthony Liguori
                if (path) {
1328 b2b6c39a Anthony Liguori
                    newpath = g_strdup_printf("%s/%s", prop->name, path);
1329 b2b6c39a Anthony Liguori
                    g_free(path);
1330 b2b6c39a Anthony Liguori
                    path = newpath;
1331 b2b6c39a Anthony Liguori
                } else {
1332 b2b6c39a Anthony Liguori
                    path = g_strdup(prop->name);
1333 b2b6c39a Anthony Liguori
                }
1334 b2b6c39a Anthony Liguori
                break;
1335 b2b6c39a Anthony Liguori
            }
1336 f9fbd2fd Anthony Liguori
        }
1337 f9fbd2fd Anthony Liguori
1338 b2b6c39a Anthony Liguori
        g_assert(prop != NULL);
1339 f9fbd2fd Anthony Liguori
1340 b2b6c39a Anthony Liguori
        dev = dev->parent;
1341 f9fbd2fd Anthony Liguori
    }
1342 f9fbd2fd Anthony Liguori
1343 f9fbd2fd Anthony Liguori
    newpath = g_strdup_printf("/%s", path);
1344 f9fbd2fd Anthony Liguori
    g_free(path);
1345 f9fbd2fd Anthony Liguori
1346 f9fbd2fd Anthony Liguori
    return newpath;
1347 f9fbd2fd Anthony Liguori
}
1348 dc45c21f Anthony Liguori
1349 dc45c21f Anthony Liguori
static DeviceState *qdev_resolve_abs_path(DeviceState *parent,
1350 dc45c21f Anthony Liguori
                                          gchar **parts,
1351 dc45c21f Anthony Liguori
                                          int index)
1352 dc45c21f Anthony Liguori
{
1353 dc45c21f Anthony Liguori
    DeviceProperty *prop;
1354 dc45c21f Anthony Liguori
    DeviceState *child;
1355 dc45c21f Anthony Liguori
1356 dc45c21f Anthony Liguori
    if (parts[index] == NULL) {
1357 dc45c21f Anthony Liguori
        return parent;
1358 dc45c21f Anthony Liguori
    }
1359 dc45c21f Anthony Liguori
1360 dc45c21f Anthony Liguori
    if (strcmp(parts[index], "") == 0) {
1361 dc45c21f Anthony Liguori
        return qdev_resolve_abs_path(parent, parts, index + 1);
1362 dc45c21f Anthony Liguori
    }
1363 dc45c21f Anthony Liguori
1364 dc45c21f Anthony Liguori
    prop = qdev_property_find(parent, parts[index]);
1365 dc45c21f Anthony Liguori
    if (prop == NULL) {
1366 dc45c21f Anthony Liguori
        return NULL;
1367 dc45c21f Anthony Liguori
    }
1368 dc45c21f Anthony Liguori
1369 dc45c21f Anthony Liguori
    child = NULL;
1370 dc45c21f Anthony Liguori
    if (strstart(prop->type, "link<", NULL)) {
1371 dc45c21f Anthony Liguori
        DeviceState **pchild = prop->opaque;
1372 dc45c21f Anthony Liguori
        if (*pchild) {
1373 dc45c21f Anthony Liguori
            child = *pchild;
1374 dc45c21f Anthony Liguori
        }
1375 dc45c21f Anthony Liguori
    } else if (strstart(prop->type, "child<", NULL)) {
1376 dc45c21f Anthony Liguori
        child = prop->opaque;
1377 dc45c21f Anthony Liguori
    }
1378 dc45c21f Anthony Liguori
1379 dc45c21f Anthony Liguori
    if (!child) {
1380 dc45c21f Anthony Liguori
        return NULL;
1381 dc45c21f Anthony Liguori
    }
1382 dc45c21f Anthony Liguori
1383 dc45c21f Anthony Liguori
    return qdev_resolve_abs_path(child, parts, index + 1);
1384 dc45c21f Anthony Liguori
}
1385 dc45c21f Anthony Liguori
1386 dc45c21f Anthony Liguori
static DeviceState *qdev_resolve_partial_path(DeviceState *parent,
1387 dc45c21f Anthony Liguori
                                              gchar **parts,
1388 dc45c21f Anthony Liguori
                                              bool *ambiguous)
1389 dc45c21f Anthony Liguori
{
1390 dc45c21f Anthony Liguori
    DeviceState *dev;
1391 dc45c21f Anthony Liguori
    DeviceProperty *prop;
1392 dc45c21f Anthony Liguori
1393 dc45c21f Anthony Liguori
    dev = qdev_resolve_abs_path(parent, parts, 0);
1394 dc45c21f Anthony Liguori
1395 dc45c21f Anthony Liguori
    QTAILQ_FOREACH(prop, &parent->properties, node) {
1396 dc45c21f Anthony Liguori
        DeviceState *found;
1397 dc45c21f Anthony Liguori
1398 dc45c21f Anthony Liguori
        if (!strstart(prop->type, "child<", NULL)) {
1399 dc45c21f Anthony Liguori
            continue;
1400 dc45c21f Anthony Liguori
        }
1401 dc45c21f Anthony Liguori
1402 dc45c21f Anthony Liguori
        found = qdev_resolve_partial_path(prop->opaque, parts, ambiguous);
1403 dc45c21f Anthony Liguori
        if (found) {
1404 dc45c21f Anthony Liguori
            if (dev) {
1405 dc45c21f Anthony Liguori
                if (ambiguous) {
1406 dc45c21f Anthony Liguori
                    *ambiguous = true;
1407 dc45c21f Anthony Liguori
                }
1408 dc45c21f Anthony Liguori
                return NULL;
1409 dc45c21f Anthony Liguori
            }
1410 dc45c21f Anthony Liguori
            dev = found;
1411 dc45c21f Anthony Liguori
        }
1412 dc45c21f Anthony Liguori
1413 dc45c21f Anthony Liguori
        if (ambiguous && *ambiguous) {
1414 dc45c21f Anthony Liguori
            return NULL;
1415 dc45c21f Anthony Liguori
        }
1416 dc45c21f Anthony Liguori
    }
1417 dc45c21f Anthony Liguori
1418 dc45c21f Anthony Liguori
    return dev;
1419 dc45c21f Anthony Liguori
}
1420 dc45c21f Anthony Liguori
1421 dc45c21f Anthony Liguori
DeviceState *qdev_resolve_path(const char *path, bool *ambiguous)
1422 dc45c21f Anthony Liguori
{
1423 dc45c21f Anthony Liguori
    bool partial_path = true;
1424 dc45c21f Anthony Liguori
    DeviceState *dev;
1425 dc45c21f Anthony Liguori
    gchar **parts;
1426 dc45c21f Anthony Liguori
1427 dc45c21f Anthony Liguori
    parts = g_strsplit(path, "/", 0);
1428 dc45c21f Anthony Liguori
    if (parts == NULL || parts[0] == NULL) {
1429 dc45c21f Anthony Liguori
        g_strfreev(parts);
1430 dc45c21f Anthony Liguori
        return qdev_get_root();
1431 dc45c21f Anthony Liguori
    }
1432 dc45c21f Anthony Liguori
1433 dc45c21f Anthony Liguori
    if (strcmp(parts[0], "") == 0) {
1434 dc45c21f Anthony Liguori
        partial_path = false;
1435 dc45c21f Anthony Liguori
    }
1436 dc45c21f Anthony Liguori
1437 dc45c21f Anthony Liguori
    if (partial_path) {
1438 dc45c21f Anthony Liguori
        if (ambiguous) {
1439 dc45c21f Anthony Liguori
            *ambiguous = false;
1440 dc45c21f Anthony Liguori
        }
1441 dc45c21f Anthony Liguori
        dev = qdev_resolve_partial_path(qdev_get_root(), parts, ambiguous);
1442 dc45c21f Anthony Liguori
    } else {
1443 dc45c21f Anthony Liguori
        dev = qdev_resolve_abs_path(qdev_get_root(), parts, 1);
1444 dc45c21f Anthony Liguori
    }
1445 dc45c21f Anthony Liguori
1446 dc45c21f Anthony Liguori
    g_strfreev(parts);
1447 dc45c21f Anthony Liguori
1448 dc45c21f Anthony Liguori
    return dev;
1449 dc45c21f Anthony Liguori
}
1450 dc45c21f Anthony Liguori
1451 6a146eba Anthony Liguori
typedef struct StringProperty
1452 6a146eba Anthony Liguori
{
1453 6a146eba Anthony Liguori
    char *(*get)(DeviceState *, Error **);
1454 6a146eba Anthony Liguori
    void (*set)(DeviceState *, const char *, Error **);
1455 6a146eba Anthony Liguori
} StringProperty;
1456 6a146eba Anthony Liguori
1457 6a146eba Anthony Liguori
static void qdev_property_get_str(DeviceState *dev, Visitor *v, void *opaque,
1458 6a146eba Anthony Liguori
                                  const char *name, Error **errp)
1459 6a146eba Anthony Liguori
{
1460 6a146eba Anthony Liguori
    StringProperty *prop = opaque;
1461 6a146eba Anthony Liguori
    char *value;
1462 6a146eba Anthony Liguori
1463 6a146eba Anthony Liguori
    value = prop->get(dev, errp);
1464 6a146eba Anthony Liguori
    if (value) {
1465 6a146eba Anthony Liguori
        visit_type_str(v, &value, name, errp);
1466 6a146eba Anthony Liguori
        g_free(value);
1467 6a146eba Anthony Liguori
    }
1468 6a146eba Anthony Liguori
}
1469 6a146eba Anthony Liguori
1470 6a146eba Anthony Liguori
static void qdev_property_set_str(DeviceState *dev, Visitor *v, void *opaque,
1471 6a146eba Anthony Liguori
                                  const char *name, Error **errp)
1472 6a146eba Anthony Liguori
{
1473 6a146eba Anthony Liguori
    StringProperty *prop = opaque;
1474 6a146eba Anthony Liguori
    char *value;
1475 6a146eba Anthony Liguori
    Error *local_err = NULL;
1476 6a146eba Anthony Liguori
1477 6a146eba Anthony Liguori
    visit_type_str(v, &value, name, &local_err);
1478 6a146eba Anthony Liguori
    if (local_err) {
1479 6a146eba Anthony Liguori
        error_propagate(errp, local_err);
1480 6a146eba Anthony Liguori
        return;
1481 6a146eba Anthony Liguori
    }
1482 6a146eba Anthony Liguori
1483 6a146eba Anthony Liguori
    prop->set(dev, value, errp);
1484 6a146eba Anthony Liguori
    g_free(value);
1485 6a146eba Anthony Liguori
}
1486 6a146eba Anthony Liguori
1487 6a146eba Anthony Liguori
static void qdev_property_release_str(DeviceState *dev, const char *name,
1488 6a146eba Anthony Liguori
                                      void *opaque)
1489 6a146eba Anthony Liguori
{
1490 6a146eba Anthony Liguori
    StringProperty *prop = opaque;
1491 6a146eba Anthony Liguori
    g_free(prop);
1492 6a146eba Anthony Liguori
}
1493 6a146eba Anthony Liguori
1494 6a146eba Anthony Liguori
void qdev_property_add_str(DeviceState *dev, const char *name,
1495 6a146eba Anthony Liguori
                           char *(*get)(DeviceState *, Error **),
1496 6a146eba Anthony Liguori
                           void (*set)(DeviceState *, const char *, Error **),
1497 6a146eba Anthony Liguori
                           Error **errp)
1498 6a146eba Anthony Liguori
{
1499 6a146eba Anthony Liguori
    StringProperty *prop = g_malloc0(sizeof(*prop));
1500 6a146eba Anthony Liguori
1501 6a146eba Anthony Liguori
    prop->get = get;
1502 6a146eba Anthony Liguori
    prop->set = set;
1503 6a146eba Anthony Liguori
1504 6a146eba Anthony Liguori
    qdev_property_add(dev, name, "string",
1505 6a146eba Anthony Liguori
                      get ? qdev_property_get_str : NULL,
1506 6a146eba Anthony Liguori
                      set ? qdev_property_set_str : NULL,
1507 6a146eba Anthony Liguori
                      qdev_property_release_str,
1508 6a146eba Anthony Liguori
                      prop, errp);
1509 6a146eba Anthony Liguori
}