]> Git Repo - qemu.git/blame - hw/qdev.c
Avoid allocating TCG resources in non-TCG mode
[qemu.git] / hw / qdev.c
CommitLineData
aae9460e
PB
1/*
2 * Dynamic device configuration and creation.
3 *
4 * Copyright (c) 2009 CodeSourcery
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
aae9460e
PB
18 */
19
20/* The theory here is that it should be possible to create a machine without
21 knowledge of specific devices. Historically board init routines have
22 passed a bunch of arguments to each device, requiring the board know
23 exactly which device it is dealing with. This file provides an abstract
24 API for device configuration and initialization. Devices will generally
25 inherit from a particular bus (e.g. PCI or I2C) rather than
26 this API directly. */
27
9d07d757 28#include "net.h"
aae9460e
PB
29#include "qdev.h"
30#include "sysemu.h"
cae4956e 31#include "monitor.h"
aae9460e 32
3418bd25 33static int qdev_hotplug = 0;
0ac8ef71
AW
34static bool qdev_hot_added = false;
35static bool qdev_hot_removed = false;
3418bd25 36
cdaed7c7 37/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
b9aaf7f8 38static BusState *main_system_bus;
4d6ae674 39
0958b4cc 40DeviceInfo *device_info_list;
aae9460e 41
8ffb1bcf
GH
42static BusState *qbus_find_recursive(BusState *bus, const char *name,
43 const BusInfo *info);
44static BusState *qbus_find(const char *path);
45
aae9460e 46/* Register a new device type. */
074f2fff 47void qdev_register(DeviceInfo *info)
aae9460e 48{
074f2fff 49 assert(info->size >= sizeof(DeviceState));
042f84d0 50 assert(!info->next);
aae9460e 51
042f84d0
GH
52 info->next = device_info_list;
53 device_info_list = info;
aae9460e
PB
54}
55
81ebb98b
GH
56static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
57{
58 DeviceInfo *info;
59
3320e56e 60 /* first check device names */
81ebb98b
GH
61 for (info = device_info_list; info != NULL; info = info->next) {
62 if (bus_info && info->bus_info != bus_info)
63 continue;
64 if (strcmp(info->name, name) != 0)
65 continue;
66 return info;
67 }
3320e56e
GH
68
69 /* failing that check the aliases */
70 for (info = device_info_list; info != NULL; info = info->next) {
71 if (bus_info && info->bus_info != bus_info)
72 continue;
73 if (!info->alias)
74 continue;
75 if (strcmp(info->alias, name) != 0)
76 continue;
77 return info;
78 }
81ebb98b
GH
79 return NULL;
80}
81
0c17542d
MA
82static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
83{
84 DeviceState *dev;
85
86 assert(bus->info == info->bus_info);
87 dev = qemu_mallocz(info->size);
88 dev->info = info;
89 dev->parent_bus = bus;
90 qdev_prop_set_defaults(dev, dev->info->props);
91 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
92 qdev_prop_set_globals(dev);
93 QLIST_INSERT_HEAD(&bus->children, dev, sibling);
94 if (qdev_hotplug) {
95 assert(bus->allow_hotplug);
96 dev->hotplugged = 1;
0ac8ef71 97 qdev_hot_added = true;
0c17542d 98 }
4d2ffa08 99 dev->instance_id_alias = -1;
0c17542d
MA
100 dev->state = DEV_STATE_CREATED;
101 return dev;
102}
103
aae9460e
PB
104/* Create a new device. This only initializes the device state structure
105 and allows properties to be set. qdev_init should be called to
106 initialize the actual device emulation. */
02e2da45 107DeviceState *qdev_create(BusState *bus, const char *name)
0bcdeda7
BS
108{
109 DeviceState *dev;
110
111 dev = qdev_try_create(bus, name);
112 if (!dev) {
113 hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
114 }
115
116 return dev;
117}
118
119DeviceState *qdev_try_create(BusState *bus, const char *name)
aae9460e 120{
042f84d0 121 DeviceInfo *info;
aae9460e 122
10c4c98a 123 if (!bus) {
68694897 124 bus = sysbus_get_default();
10c4c98a
GH
125 }
126
81ebb98b 127 info = qdev_find_info(bus->info, name);
042f84d0 128 if (!info) {
0bcdeda7 129 return NULL;
aae9460e
PB
130 }
131
0c17542d 132 return qdev_create_from_info(bus, info);
aae9460e
PB
133}
134
8a9662ca 135static void qdev_print_devinfo(DeviceInfo *info)
1b524b04 136{
8a9662ca
MA
137 error_printf("name \"%s\", bus %s",
138 info->name, info->bus_info->name);
22f2e344 139 if (info->alias) {
8a9662ca 140 error_printf(", alias \"%s\"", info->alias);
22f2e344
GH
141 }
142 if (info->desc) {
8a9662ca 143 error_printf(", desc \"%s\"", info->desc);
22f2e344
GH
144 }
145 if (info->no_user) {
8a9662ca 146 error_printf(", no-user");
22f2e344 147 }
8a9662ca 148 error_printf("\n");
1b524b04
GH
149}
150
f31d07d1 151static int set_property(const char *name, const char *value, void *opaque)
8ffb1bcf 152{
f31d07d1
GH
153 DeviceState *dev = opaque;
154
155 if (strcmp(name, "driver") == 0)
156 return 0;
157 if (strcmp(name, "bus") == 0)
158 return 0;
159
3df04ac3 160 if (qdev_prop_parse(dev, name, value) == -1) {
f31d07d1
GH
161 return -1;
162 }
163 return 0;
164}
165
ff952ba2
MA
166int qdev_device_help(QemuOpts *opts)
167{
168 const char *driver;
169 DeviceInfo *info;
08350cf0 170 Property *prop;
ff952ba2
MA
171
172 driver = qemu_opt_get(opts, "driver");
173 if (driver && !strcmp(driver, "?")) {
174 for (info = device_info_list; info != NULL; info = info->next) {
c64eafaf
MA
175 if (info->no_user) {
176 continue; /* not available, don't show */
177 }
8a9662ca 178 qdev_print_devinfo(info);
ff952ba2
MA
179 }
180 return 1;
181 }
182
08350cf0
MA
183 if (!qemu_opt_get(opts, "?")) {
184 return 0;
185 }
186
187 info = qdev_find_info(NULL, driver);
188 if (!info) {
189 return 0;
190 }
191
192 for (prop = info->props; prop && prop->name; prop++) {
036f7166
MA
193 /*
194 * TODO Properties without a parser are just for dirty hacks.
195 * qdev_prop_ptr is the only such PropertyInfo. It's marked
196 * for removal. This conditional should be removed along with
197 * it.
198 */
199 if (!prop->info->parse) {
200 continue; /* no way to set it, don't show */
201 }
8a9662ca 202 error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name);
08350cf0
MA
203 }
204 return 1;
ff952ba2
MA
205}
206
f31d07d1
GH
207DeviceState *qdev_device_add(QemuOpts *opts)
208{
209 const char *driver, *path, *id;
8ffb1bcf
GH
210 DeviceInfo *info;
211 DeviceState *qdev;
212 BusState *bus;
8ffb1bcf 213
f31d07d1
GH
214 driver = qemu_opt_get(opts, "driver");
215 if (!driver) {
0204276b 216 qerror_report(QERR_MISSING_PARAMETER, "driver");
8ffb1bcf
GH
217 return NULL;
218 }
f31d07d1
GH
219
220 /* find driver */
8ffb1bcf 221 info = qdev_find_info(NULL, driver);
c64eafaf 222 if (!info || info->no_user) {
e17ba87c 223 qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name");
0204276b 224 error_printf_unless_qmp("Try with argument '?' for a list.\n");
8ffb1bcf
GH
225 return NULL;
226 }
8ffb1bcf 227
f31d07d1
GH
228 /* find bus */
229 path = qemu_opt_get(opts, "bus");
230 if (path != NULL) {
8ffb1bcf 231 bus = qbus_find(path);
ac8dae67
MA
232 if (!bus) {
233 return NULL;
234 }
235 if (bus->info != info->bus_info) {
0204276b
MA
236 qerror_report(QERR_BAD_BUS_FOR_DEVICE,
237 driver, bus->info->name);
327867b6
MA
238 return NULL;
239 }
8ffb1bcf
GH
240 } else {
241 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
ac8dae67 242 if (!bus) {
0204276b
MA
243 qerror_report(QERR_NO_BUS_FOR_DEVICE,
244 info->name, info->bus_info->name);
ac8dae67
MA
245 return NULL;
246 }
75570088 247 }
3418bd25 248 if (qdev_hotplug && !bus->allow_hotplug) {
0204276b 249 qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
3418bd25
GH
250 return NULL;
251 }
8ffb1bcf 252
f31d07d1 253 /* create device, set properties */
0c17542d 254 qdev = qdev_create_from_info(bus, info);
f31d07d1
GH
255 id = qemu_opts_id(opts);
256 if (id) {
257 qdev->id = id;
258 }
259 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
260 qdev_free(qdev);
261 return NULL;
8ffb1bcf 262 }
5c17ca25 263 if (qdev_init(qdev) < 0) {
0204276b 264 qerror_report(QERR_DEVICE_INIT_FAILED, driver);
81a322d4
GH
265 return NULL;
266 }
ef80b466 267 qdev->opts = opts;
8ffb1bcf
GH
268 return qdev;
269}
270
aae9460e
PB
271/* Initialize a device. Device properties should be set before calling
272 this function. IRQs and MMIO regions should be connected/mapped after
18cfeb52
MA
273 calling this function.
274 On failure, destroy the device and return negative value.
275 Return 0 on success. */
81a322d4 276int qdev_init(DeviceState *dev)
aae9460e 277{
959f733a
GH
278 int rc;
279
131ec1bd 280 assert(dev->state == DEV_STATE_CREATED);
959f733a 281 rc = dev->info->init(dev, dev->info);
18cfeb52
MA
282 if (rc < 0) {
283 qdev_free(dev);
959f733a 284 return rc;
18cfeb52 285 }
4d2ffa08 286 if (dev->info->vmsd) {
0be71e32 287 vmstate_register_with_alias_id(dev, -1, dev->info->vmsd, dev,
4d2ffa08
JK
288 dev->instance_id_alias,
289 dev->alias_required_for_version);
290 }
131ec1bd 291 dev->state = DEV_STATE_INITIALIZED;
5ab28c83
JK
292 if (dev->hotplugged && dev->info->reset) {
293 dev->info->reset(dev);
294 }
959f733a 295 return 0;
02e2da45
PB
296}
297
4d2ffa08
JK
298void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
299 int required_for_version)
300{
301 assert(dev->state == DEV_STATE_CREATED);
302 dev->instance_id_alias = alias_id;
303 dev->alias_required_for_version = required_for_version;
304}
305
3418bd25
GH
306int qdev_unplug(DeviceState *dev)
307{
308 if (!dev->parent_bus->allow_hotplug) {
cc601cb7 309 qerror_report(QERR_BUS_NO_HOTPLUG, dev->parent_bus->name);
3418bd25
GH
310 return -1;
311 }
593831de
AS
312 assert(dev->info->unplug != NULL);
313
0ac8ef71
AW
314 qdev_hot_removed = true;
315
3418bd25
GH
316 return dev->info->unplug(dev);
317}
318
ec990eb6
AL
319static int qdev_reset_one(DeviceState *dev, void *opaque)
320{
321 if (dev->info->reset) {
322 dev->info->reset(dev);
323 }
324
325 return 0;
326}
327
328BusState *sysbus_get_default(void)
329{
68694897
SW
330 if (!main_system_bus) {
331 main_system_bus = qbus_create(&system_bus_info, NULL,
332 "main-system-bus");
333 }
ec990eb6
AL
334 return main_system_bus;
335}
336
b4694b7c
IY
337static int qbus_reset_one(BusState *bus, void *opaque)
338{
339 if (bus->info->reset) {
340 return bus->info->reset(bus);
341 }
342 return 0;
343}
344
5af0a04b
IY
345void qdev_reset_all(DeviceState *dev)
346{
347 qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
348}
349
80376c3f
IY
350void qbus_reset_all_fn(void *opaque)
351{
352 BusState *bus = opaque;
f530cce3 353 qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
80376c3f
IY
354}
355
3418bd25
GH
356/* can be used as ->unplug() callback for the simple cases */
357int qdev_simple_unplug_cb(DeviceState *dev)
358{
359 /* just zap it */
360 qdev_free(dev);
361 return 0;
362}
363
3b29a101
MT
364
365/* Like qdev_init(), but terminate program via error_report() instead of
e23a1b33
MA
366 returning an error value. This is okay during machine creation.
367 Don't use for hotplug, because there callers need to recover from
368 failure. Exception: if you know the device's init() callback can't
369 fail, then qdev_init_nofail() can't fail either, and is therefore
370 usable even then. But relying on the device implementation that
371 way is somewhat unclean, and best avoided. */
372void qdev_init_nofail(DeviceState *dev)
373{
374 DeviceInfo *info = dev->info;
375
bd6c9a61 376 if (qdev_init(dev) < 0) {
6daf194d 377 error_report("Initialization of device %s failed", info->name);
bd6c9a61
MA
378 exit(1);
379 }
e23a1b33
MA
380}
381
02e2da45
PB
382/* Unlink device from bus and free the structure. */
383void qdev_free(DeviceState *dev)
384{
131ec1bd 385 BusState *bus;
d21357df 386 Property *prop;
131ec1bd
GH
387
388 if (dev->state == DEV_STATE_INITIALIZED) {
389 while (dev->num_child_bus) {
390 bus = QLIST_FIRST(&dev->child_bus);
391 qbus_free(bus);
392 }
131ec1bd 393 if (dev->info->vmsd)
0be71e32 394 vmstate_unregister(dev, dev->info->vmsd, dev);
d29275f1
GH
395 if (dev->info->exit)
396 dev->info->exit(dev);
ef80b466
GH
397 if (dev->opts)
398 qemu_opts_del(dev->opts);
131ec1bd 399 }
72cf2d4f 400 QLIST_REMOVE(dev, sibling);
d21357df
MA
401 for (prop = dev->info->props; prop && prop->name; prop++) {
402 if (prop->info->free) {
403 prop->info->free(dev, prop);
404 }
405 }
ccb63de3 406 qemu_free(dev);
aae9460e
PB
407}
408
3418bd25
GH
409void qdev_machine_creation_done(void)
410{
411 /*
412 * ok, initial machine setup is done, starting from now we can
413 * only create hotpluggable devices
414 */
415 qdev_hotplug = 1;
416}
417
0ac8ef71
AW
418bool qdev_machine_modified(void)
419{
420 return qdev_hot_added || qdev_hot_removed;
421}
422
aae9460e
PB
423/* Get a character (serial) device interface. */
424CharDriverState *qdev_init_chardev(DeviceState *dev)
425{
426 static int next_serial;
98b19252
AS
427
428 /* FIXME: This function needs to go away: use chardev properties! */
429 return serial_hds[next_serial++];
aae9460e
PB
430}
431
02e2da45 432BusState *qdev_get_parent_bus(DeviceState *dev)
aae9460e 433{
02e2da45 434 return dev->parent_bus;
aae9460e
PB
435}
436
aae9460e
PB
437void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
438{
439 assert(dev->num_gpio_in == 0);
440 dev->num_gpio_in = n;
441 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
442}
443
444void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
445{
446 assert(dev->num_gpio_out == 0);
447 dev->num_gpio_out = n;
448 dev->gpio_out = pins;
449}
450
451qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
452{
453 assert(n >= 0 && n < dev->num_gpio_in);
454 return dev->gpio_in[n];
455}
456
457void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
458{
459 assert(n >= 0 && n < dev->num_gpio_out);
460 dev->gpio_out[n] = pin;
461}
462
ed16ab5a
GH
463void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
464{
6eed1856 465 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
ed16ab5a
GH
466 if (nd->vlan)
467 qdev_prop_set_vlan(dev, "vlan", nd->vlan);
468 if (nd->netdev)
469 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
75422b0d 470 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
97b15621
GH
471 qdev_prop_exists(dev, "vectors")) {
472 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
473 }
48e2faf2 474 nd->instantiated = 1;
ed16ab5a
GH
475}
476
02e2da45 477BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
4d6ae674 478{
02e2da45 479 BusState *bus;
4d6ae674 480
72cf2d4f 481 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
4d6ae674 482 if (strcmp(name, bus->name) == 0) {
02e2da45 483 return bus;
4d6ae674
PB
484 }
485 }
486 return NULL;
487}
488
81699d8a
AL
489int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
490 qbus_walkerfn *busfn, void *opaque)
491{
492 DeviceState *dev;
493 int err;
494
495 if (busfn) {
496 err = busfn(bus, opaque);
497 if (err) {
498 return err;
499 }
500 }
501
502 QLIST_FOREACH(dev, &bus->children, sibling) {
503 err = qdev_walk_children(dev, devfn, busfn, opaque);
504 if (err < 0) {
505 return err;
506 }
507 }
508
509 return 0;
510}
511
512int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
513 qbus_walkerfn *busfn, void *opaque)
514{
515 BusState *bus;
516 int err;
517
518 if (devfn) {
519 err = devfn(dev, opaque);
520 if (err) {
521 return err;
522 }
523 }
524
525 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
526 err = qbus_walk_children(bus, devfn, busfn, opaque);
527 if (err < 0) {
528 return err;
529 }
530 }
531
532 return 0;
533}
534
8ffb1bcf
GH
535static BusState *qbus_find_recursive(BusState *bus, const char *name,
536 const BusInfo *info)
537{
538 DeviceState *dev;
539 BusState *child, *ret;
540 int match = 1;
541
542 if (name && (strcmp(bus->name, name) != 0)) {
543 match = 0;
544 }
545 if (info && (bus->info != info)) {
546 match = 0;
547 }
548 if (match) {
549 return bus;
550 }
551
72cf2d4f
BS
552 QLIST_FOREACH(dev, &bus->children, sibling) {
553 QLIST_FOREACH(child, &dev->child_bus, sibling) {
8ffb1bcf
GH
554 ret = qbus_find_recursive(child, name, info);
555 if (ret) {
556 return ret;
557 }
558 }
559 }
560 return NULL;
561}
562
a2ee6b4f 563DeviceState *qdev_find_recursive(BusState *bus, const char *id)
3418bd25
GH
564{
565 DeviceState *dev, *ret;
566 BusState *child;
567
568 QLIST_FOREACH(dev, &bus->children, sibling) {
569 if (dev->id && strcmp(dev->id, id) == 0)
570 return dev;
571 QLIST_FOREACH(child, &dev->child_bus, sibling) {
572 ret = qdev_find_recursive(child, id);
573 if (ret) {
574 return ret;
575 }
576 }
577 }
578 return NULL;
579}
580
53db16b5 581static void qbus_list_bus(DeviceState *dev)
8ffb1bcf
GH
582{
583 BusState *child;
584 const char *sep = " ";
8ffb1bcf 585
53db16b5
MA
586 error_printf("child busses at \"%s\":",
587 dev->id ? dev->id : dev->info->name);
72cf2d4f 588 QLIST_FOREACH(child, &dev->child_bus, sibling) {
53db16b5 589 error_printf("%s\"%s\"", sep, child->name);
8ffb1bcf
GH
590 sep = ", ";
591 }
53db16b5 592 error_printf("\n");
8ffb1bcf
GH
593}
594
53db16b5 595static void qbus_list_dev(BusState *bus)
8ffb1bcf
GH
596{
597 DeviceState *dev;
598 const char *sep = " ";
8ffb1bcf 599
53db16b5 600 error_printf("devices at \"%s\":", bus->name);
72cf2d4f 601 QLIST_FOREACH(dev, &bus->children, sibling) {
53db16b5 602 error_printf("%s\"%s\"", sep, dev->info->name);
8ffb1bcf 603 if (dev->id)
53db16b5 604 error_printf("/\"%s\"", dev->id);
8ffb1bcf
GH
605 sep = ", ";
606 }
53db16b5 607 error_printf("\n");
8ffb1bcf
GH
608}
609
610static BusState *qbus_find_bus(DeviceState *dev, char *elem)
611{
612 BusState *child;
613
72cf2d4f 614 QLIST_FOREACH(child, &dev->child_bus, sibling) {
8ffb1bcf
GH
615 if (strcmp(child->name, elem) == 0) {
616 return child;
617 }
618 }
619 return NULL;
620}
621
622static DeviceState *qbus_find_dev(BusState *bus, char *elem)
623{
624 DeviceState *dev;
625
626 /*
627 * try to match in order:
628 * (1) instance id, if present
629 * (2) driver name
630 * (3) driver alias, if present
631 */
72cf2d4f 632 QLIST_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
633 if (dev->id && strcmp(dev->id, elem) == 0) {
634 return dev;
635 }
636 }
72cf2d4f 637 QLIST_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
638 if (strcmp(dev->info->name, elem) == 0) {
639 return dev;
640 }
641 }
72cf2d4f 642 QLIST_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
643 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
644 return dev;
645 }
646 }
647 return NULL;
648}
649
650static BusState *qbus_find(const char *path)
651{
652 DeviceState *dev;
653 BusState *bus;
53db16b5 654 char elem[128];
8ffb1bcf
GH
655 int pos, len;
656
657 /* find start element */
658 if (path[0] == '/') {
659 bus = main_system_bus;
660 pos = 0;
661 } else {
662 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
fc98eb43
MA
663 assert(!path[0]);
664 elem[0] = len = 0;
8ffb1bcf
GH
665 }
666 bus = qbus_find_recursive(main_system_bus, elem, NULL);
667 if (!bus) {
ac8dae67 668 qerror_report(QERR_BUS_NOT_FOUND, elem);
8ffb1bcf
GH
669 return NULL;
670 }
671 pos = len;
672 }
673
674 for (;;) {
fc98eb43
MA
675 assert(path[pos] == '/' || !path[pos]);
676 while (path[pos] == '/') {
677 pos++;
678 }
8ffb1bcf 679 if (path[pos] == '\0') {
8ffb1bcf
GH
680 return bus;
681 }
682
683 /* find device */
fc98eb43
MA
684 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
685 assert(0);
686 elem[0] = len = 0;
8ffb1bcf
GH
687 }
688 pos += len;
689 dev = qbus_find_dev(bus, elem);
690 if (!dev) {
ac8dae67 691 qerror_report(QERR_DEVICE_NOT_FOUND, elem);
8bc27249
MA
692 if (!monitor_cur_is_qmp()) {
693 qbus_list_dev(bus);
694 }
8ffb1bcf
GH
695 return NULL;
696 }
fc98eb43
MA
697
698 assert(path[pos] == '/' || !path[pos]);
699 while (path[pos] == '/') {
700 pos++;
701 }
8ffb1bcf
GH
702 if (path[pos] == '\0') {
703 /* last specified element is a device. If it has exactly
704 * one child bus accept it nevertheless */
705 switch (dev->num_child_bus) {
706 case 0:
ac8dae67 707 qerror_report(QERR_DEVICE_NO_BUS, elem);
8ffb1bcf
GH
708 return NULL;
709 case 1:
72cf2d4f 710 return QLIST_FIRST(&dev->child_bus);
8ffb1bcf 711 default:
ac8dae67 712 qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
8bc27249
MA
713 if (!monitor_cur_is_qmp()) {
714 qbus_list_bus(dev);
715 }
8ffb1bcf
GH
716 return NULL;
717 }
718 }
719
720 /* find bus */
fc98eb43
MA
721 if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
722 assert(0);
723 elem[0] = len = 0;
8ffb1bcf
GH
724 }
725 pos += len;
726 bus = qbus_find_bus(dev, elem);
727 if (!bus) {
ac8dae67 728 qerror_report(QERR_BUS_NOT_FOUND, elem);
8bc27249
MA
729 if (!monitor_cur_is_qmp()) {
730 qbus_list_bus(dev);
731 }
8ffb1bcf
GH
732 return NULL;
733 }
734 }
735}
736
cd739fb6
GH
737void qbus_create_inplace(BusState *bus, BusInfo *info,
738 DeviceState *parent, const char *name)
02e2da45 739{
d271de9f
GH
740 char *buf;
741 int i,len;
02e2da45 742
10c4c98a 743 bus->info = info;
02e2da45 744 bus->parent = parent;
d271de9f
GH
745
746 if (name) {
747 /* use supplied name */
748 bus->name = qemu_strdup(name);
749 } else if (parent && parent->id) {
750 /* parent device has id -> use it for bus name */
751 len = strlen(parent->id) + 16;
752 buf = qemu_malloc(len);
753 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
754 bus->name = buf;
755 } else {
756 /* no id -> use lowercase bus type for bus name */
757 len = strlen(info->name) + 16;
758 buf = qemu_malloc(len);
759 len = snprintf(buf, len, "%s.%d", info->name,
760 parent ? parent->num_child_bus : 0);
761 for (i = 0; i < len; i++)
bb87ece5 762 buf[i] = qemu_tolower(buf[i]);
d271de9f
GH
763 bus->name = buf;
764 }
765
72cf2d4f 766 QLIST_INIT(&bus->children);
02e2da45 767 if (parent) {
72cf2d4f 768 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
d271de9f 769 parent->num_child_bus++;
80376c3f
IY
770 } else if (bus != main_system_bus) {
771 /* TODO: once all bus devices are qdevified,
772 only reset handler for main_system_bus should be registered here. */
773 qemu_register_reset(qbus_reset_all_fn, bus);
02e2da45 774 }
cd739fb6
GH
775}
776
777BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
778{
779 BusState *bus;
780
781 bus = qemu_mallocz(info->size);
782 bus->qdev_allocated = 1;
783 qbus_create_inplace(bus, info, parent, name);
02e2da45
PB
784 return bus;
785}
cae4956e 786
131ec1bd
GH
787void qbus_free(BusState *bus)
788{
789 DeviceState *dev;
790
791 while ((dev = QLIST_FIRST(&bus->children)) != NULL) {
792 qdev_free(dev);
793 }
794 if (bus->parent) {
795 QLIST_REMOVE(bus, sibling);
796 bus->parent->num_child_bus--;
80376c3f
IY
797 } else {
798 assert(bus != main_system_bus); /* main_system_bus is never freed */
799 qemu_unregister_reset(qbus_reset_all_fn, bus);
131ec1bd 800 }
e163ae7b 801 qemu_free((void*)bus->name);
131ec1bd
GH
802 if (bus->qdev_allocated) {
803 qemu_free(bus);
804 }
805}
806
cae4956e
GH
807#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
808static void qbus_print(Monitor *mon, BusState *bus, int indent);
809
ee6847d1
GH
810static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
811 const char *prefix, int indent)
812{
813 char buf[64];
814
815 if (!props)
816 return;
817 while (props->name) {
036f7166
MA
818 /*
819 * TODO Properties without a print method are just for dirty
820 * hacks. qdev_prop_ptr is the only such PropertyInfo. It's
821 * marked for removal. The test props->info->print should be
822 * removed along with it.
823 */
ee6847d1
GH
824 if (props->info->print) {
825 props->info->print(dev, props, buf, sizeof(buf));
826 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
827 }
828 props++;
829 }
830}
831
cae4956e
GH
832static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
833{
cae4956e 834 BusState *child;
ccb63de3
GH
835 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
836 dev->id ? dev->id : "");
cae4956e
GH
837 indent += 2;
838 if (dev->num_gpio_in) {
839 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
840 }
841 if (dev->num_gpio_out) {
842 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
843 }
ee6847d1
GH
844 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
845 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
10c4c98a
GH
846 if (dev->parent_bus->info->print_dev)
847 dev->parent_bus->info->print_dev(mon, dev, indent);
72cf2d4f 848 QLIST_FOREACH(child, &dev->child_bus, sibling) {
cae4956e
GH
849 qbus_print(mon, child, indent);
850 }
851}
852
853static void qbus_print(Monitor *mon, BusState *bus, int indent)
854{
855 struct DeviceState *dev;
856
857 qdev_printf("bus: %s\n", bus->name);
858 indent += 2;
10c4c98a 859 qdev_printf("type %s\n", bus->info->name);
72cf2d4f 860 QLIST_FOREACH(dev, &bus->children, sibling) {
cae4956e
GH
861 qdev_print(mon, dev, indent);
862 }
863}
864#undef qdev_printf
865
866void do_info_qtree(Monitor *mon)
867{
868 if (main_system_bus)
869 qbus_print(mon, main_system_bus, 0);
870}
9316d30f 871
f6c64e0e 872void do_info_qdm(Monitor *mon)
9316d30f
GH
873{
874 DeviceInfo *info;
9316d30f
GH
875
876 for (info = device_info_list; info != NULL; info = info->next) {
8a9662ca 877 qdev_print_devinfo(info);
9316d30f
GH
878 }
879}
3418bd25 880
8bc27249 881int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
3418bd25
GH
882{
883 QemuOpts *opts;
884
3329f07b 885 opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
8bc27249
MA
886 if (!opts) {
887 return -1;
888 }
889 if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
890 qemu_opts_del(opts);
891 return 0;
0f853a38 892 }
8bc27249
MA
893 if (!qdev_device_add(opts)) {
894 qemu_opts_del(opts);
895 return -1;
896 }
897 return 0;
3418bd25
GH
898}
899
17a38eaa 900int do_device_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
3418bd25
GH
901{
902 const char *id = qdict_get_str(qdict, "id");
903 DeviceState *dev;
904
905 dev = qdev_find_recursive(main_system_bus, id);
906 if (NULL == dev) {
17a38eaa
MA
907 qerror_report(QERR_DEVICE_NOT_FOUND, id);
908 return -1;
3418bd25 909 }
17a38eaa 910 return qdev_unplug(dev);
3418bd25 911}
1ca4d09a
GN
912
913static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size)
914{
915 int l = 0;
916
917 if (dev && dev->parent_bus) {
918 char *d;
919 l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size);
920 if (dev->parent_bus->info->get_fw_dev_path) {
921 d = dev->parent_bus->info->get_fw_dev_path(dev);
922 l += snprintf(p + l, size - l, "%s", d);
923 qemu_free(d);
924 } else {
925 l += snprintf(p + l, size - l, "%s", dev->info->name);
926 }
927 }
928 l += snprintf(p + l , size - l, "/");
929
930 return l;
931}
932
933char* qdev_get_fw_dev_path(DeviceState *dev)
934{
935 char path[128];
936 int l;
937
938 l = qdev_get_fw_dev_path_helper(dev, path, 128);
939
940 path[l-1] = '\0';
941
942 return strdup(path);
943}
This page took 0.474325 seconds and 4 git commands to generate.