]> Git Repo - qemu.git/blame - hw/qdev.c
parallel: convert isa to qdev
[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
02e2da45 33/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
b9aaf7f8 34static BusState *main_system_bus;
4d6ae674 35
042f84d0 36static DeviceInfo *device_info_list;
aae9460e 37
8ffb1bcf
GH
38static BusState *qbus_find_recursive(BusState *bus, const char *name,
39 const BusInfo *info);
40static BusState *qbus_find(const char *path);
41
aae9460e 42/* Register a new device type. */
074f2fff 43void qdev_register(DeviceInfo *info)
aae9460e 44{
074f2fff 45 assert(info->size >= sizeof(DeviceState));
042f84d0 46 assert(!info->next);
aae9460e 47
042f84d0
GH
48 info->next = device_info_list;
49 device_info_list = info;
aae9460e
PB
50}
51
81ebb98b
GH
52static DeviceInfo *qdev_find_info(BusInfo *bus_info, const char *name)
53{
54 DeviceInfo *info;
55
3320e56e 56 /* first check device names */
81ebb98b
GH
57 for (info = device_info_list; info != NULL; info = info->next) {
58 if (bus_info && info->bus_info != bus_info)
59 continue;
60 if (strcmp(info->name, name) != 0)
61 continue;
62 return info;
63 }
3320e56e
GH
64
65 /* failing that check the aliases */
66 for (info = device_info_list; info != NULL; info = info->next) {
67 if (bus_info && info->bus_info != bus_info)
68 continue;
69 if (!info->alias)
70 continue;
71 if (strcmp(info->alias, name) != 0)
72 continue;
73 return info;
74 }
81ebb98b
GH
75 return NULL;
76}
77
aae9460e
PB
78/* Create a new device. This only initializes the device state structure
79 and allows properties to be set. qdev_init should be called to
80 initialize the actual device emulation. */
02e2da45 81DeviceState *qdev_create(BusState *bus, const char *name)
aae9460e 82{
042f84d0 83 DeviceInfo *info;
aae9460e
PB
84 DeviceState *dev;
85
10c4c98a
GH
86 if (!bus) {
87 if (!main_system_bus) {
88 main_system_bus = qbus_create(&system_bus_info, NULL, "main-system-bus");
aae9460e 89 }
10c4c98a
GH
90 bus = main_system_bus;
91 }
92
81ebb98b 93 info = qdev_find_info(bus->info, name);
042f84d0 94 if (!info) {
10c4c98a 95 hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
aae9460e
PB
96 }
97
042f84d0
GH
98 dev = qemu_mallocz(info->size);
99 dev->info = info;
02e2da45 100 dev->parent_bus = bus;
ee6847d1
GH
101 qdev_prop_set_defaults(dev, dev->info->props);
102 qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
b6b61144 103 qdev_prop_set_compat(dev);
72cf2d4f 104 QLIST_INSERT_HEAD(&bus->children, dev, sibling);
aae9460e
PB
105 return dev;
106}
107
1b524b04
GH
108static int qdev_print_devinfo(DeviceInfo *info, char *dest, int len)
109{
110 int pos = 0;
22f2e344
GH
111 int ret;
112
113 ret = snprintf(dest+pos, len-pos, "name \"%s\", bus %s",
114 info->name, info->bus_info->name);
115 pos += MIN(len-pos,ret);
116 if (info->alias) {
117 ret = snprintf(dest+pos, len-pos, ", alias \"%s\"", info->alias);
118 pos += MIN(len-pos,ret);
119 }
120 if (info->desc) {
121 ret = snprintf(dest+pos, len-pos, ", desc \"%s\"", info->desc);
122 pos += MIN(len-pos,ret);
123 }
124 if (info->no_user) {
125 ret = snprintf(dest+pos, len-pos, ", no-user");
126 pos += MIN(len-pos,ret);
127 }
1b524b04
GH
128 return pos;
129}
130
f31d07d1 131static int set_property(const char *name, const char *value, void *opaque)
8ffb1bcf 132{
f31d07d1
GH
133 DeviceState *dev = opaque;
134
135 if (strcmp(name, "driver") == 0)
136 return 0;
137 if (strcmp(name, "bus") == 0)
138 return 0;
139
3df04ac3 140 if (qdev_prop_parse(dev, name, value) == -1) {
286c2321
GH
141 qemu_error("can't set property \"%s\" to \"%s\" for \"%s\"\n",
142 name, value, dev->info->name);
f31d07d1
GH
143 return -1;
144 }
145 return 0;
146}
147
148DeviceState *qdev_device_add(QemuOpts *opts)
149{
150 const char *driver, *path, *id;
8ffb1bcf
GH
151 DeviceInfo *info;
152 DeviceState *qdev;
153 BusState *bus;
8ffb1bcf 154
f31d07d1
GH
155 driver = qemu_opt_get(opts, "driver");
156 if (!driver) {
286c2321 157 qemu_error("-device: no driver specified\n");
8ffb1bcf
GH
158 return NULL;
159 }
160 if (strcmp(driver, "?") == 0) {
1b524b04 161 char msg[256];
8ffb1bcf 162 for (info = device_info_list; info != NULL; info = info->next) {
1b524b04 163 qdev_print_devinfo(info, msg, sizeof(msg));
286c2321 164 qemu_error("%s\n", msg);
8ffb1bcf
GH
165 }
166 return NULL;
167 }
f31d07d1
GH
168
169 /* find driver */
8ffb1bcf
GH
170 info = qdev_find_info(NULL, driver);
171 if (!info) {
286c2321
GH
172 qemu_error("Device \"%s\" not found. Try -device '?' for a list.\n",
173 driver);
8ffb1bcf
GH
174 return NULL;
175 }
176 if (info->no_user) {
286c2321
GH
177 qemu_error("device \"%s\" can't be added via command line\n",
178 info->name);
8ffb1bcf
GH
179 return NULL;
180 }
181
f31d07d1
GH
182 /* find bus */
183 path = qemu_opt_get(opts, "bus");
184 if (path != NULL) {
8ffb1bcf 185 bus = qbus_find(path);
8ffb1bcf
GH
186 } else {
187 bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info);
8ffb1bcf 188 }
75570088
GH
189 if (!bus) {
190 qemu_error("Did not find %s bus for %s\n",
191 path ? path : info->bus_info->name, info->name);
f31d07d1 192 return NULL;
75570088 193 }
8ffb1bcf 194
f31d07d1
GH
195 /* create device, set properties */
196 qdev = qdev_create(bus, driver);
197 id = qemu_opts_id(opts);
198 if (id) {
199 qdev->id = id;
200 }
201 if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
202 qdev_free(qdev);
203 return NULL;
8ffb1bcf 204 }
81a322d4
GH
205 if (qdev_init(qdev) != 0) {
206 qdev_free(qdev);
207 return NULL;
208 }
8ffb1bcf
GH
209 return qdev;
210}
211
aae9460e
PB
212/* Initialize a device. Device properties should be set before calling
213 this function. IRQs and MMIO regions should be connected/mapped after
214 calling this function. */
81a322d4 215int qdev_init(DeviceState *dev)
aae9460e 216{
959f733a
GH
217 int rc;
218
219 rc = dev->info->init(dev, dev->info);
220 if (rc < 0)
221 return rc;
222 if (dev->info->reset)
223 qemu_register_reset(dev->info->reset, dev);
391a079e
GH
224 if (dev->info->vmsd)
225 vmstate_register(-1, dev->info->vmsd, dev);
959f733a 226 return 0;
02e2da45
PB
227}
228
229/* Unlink device from bus and free the structure. */
230void qdev_free(DeviceState *dev)
231{
391a079e
GH
232#if 0 /* FIXME: need sane vmstate_unregister function */
233 if (dev->info->vmsd)
234 vmstate_unregister(dev->info->vmsd, dev);
235#endif
959f733a
GH
236 if (dev->info->reset)
237 qemu_unregister_reset(dev->info->reset, dev);
72cf2d4f 238 QLIST_REMOVE(dev, sibling);
ccb63de3 239 qemu_free(dev);
aae9460e
PB
240}
241
aae9460e
PB
242/* Get a character (serial) device interface. */
243CharDriverState *qdev_init_chardev(DeviceState *dev)
244{
245 static int next_serial;
246 static int next_virtconsole;
247 /* FIXME: This is a nasty hack that needs to go away. */
042f84d0 248 if (strncmp(dev->info->name, "virtio", 6) == 0) {
aae9460e
PB
249 return virtcon_hds[next_virtconsole++];
250 } else {
251 return serial_hds[next_serial++];
252 }
253}
254
02e2da45 255BusState *qdev_get_parent_bus(DeviceState *dev)
aae9460e 256{
02e2da45 257 return dev->parent_bus;
aae9460e
PB
258}
259
aae9460e
PB
260void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n)
261{
262 assert(dev->num_gpio_in == 0);
263 dev->num_gpio_in = n;
264 dev->gpio_in = qemu_allocate_irqs(handler, dev, n);
265}
266
267void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
268{
269 assert(dev->num_gpio_out == 0);
270 dev->num_gpio_out = n;
271 dev->gpio_out = pins;
272}
273
274qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)
275{
276 assert(n >= 0 && n < dev->num_gpio_in);
277 return dev->gpio_in[n];
278}
279
280void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
281{
282 assert(n >= 0 && n < dev->num_gpio_out);
283 dev->gpio_out[n] = pin;
284}
285
9d07d757 286VLANClientState *qdev_get_vlan_client(DeviceState *dev,
cda9046b
MM
287 NetCanReceive *can_receive,
288 NetReceive *receive,
289 NetReceiveIOV *receive_iov,
9d07d757
PB
290 NetCleanup *cleanup,
291 void *opaque)
292{
293 NICInfo *nd = dev->nd;
294 assert(nd);
ae50b274
MM
295 nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
296 receive, receive_iov, cleanup, opaque);
297 return nd->vc;
9d07d757
PB
298}
299
300
301void qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr)
302{
303 memcpy(macaddr, dev->nd->macaddr, 6);
304}
305
aae9460e
PB
306static int next_block_unit[IF_COUNT];
307
308/* Get a block device. This should only be used for single-drive devices
309 (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
310 appropriate bus. */
311BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
312{
313 int unit = next_block_unit[type]++;
751c6a17 314 DriveInfo *dinfo;
aae9460e 315
751c6a17
GH
316 dinfo = drive_get(type, 0, unit);
317 return dinfo ? dinfo->bdrv : NULL;
aae9460e 318}
4d6ae674 319
02e2da45 320BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
4d6ae674 321{
02e2da45 322 BusState *bus;
4d6ae674 323
72cf2d4f 324 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
4d6ae674 325 if (strcmp(name, bus->name) == 0) {
02e2da45 326 return bus;
4d6ae674
PB
327 }
328 }
329 return NULL;
330}
331
8ffb1bcf
GH
332static BusState *qbus_find_recursive(BusState *bus, const char *name,
333 const BusInfo *info)
334{
335 DeviceState *dev;
336 BusState *child, *ret;
337 int match = 1;
338
339 if (name && (strcmp(bus->name, name) != 0)) {
340 match = 0;
341 }
342 if (info && (bus->info != info)) {
343 match = 0;
344 }
345 if (match) {
346 return bus;
347 }
348
72cf2d4f
BS
349 QLIST_FOREACH(dev, &bus->children, sibling) {
350 QLIST_FOREACH(child, &dev->child_bus, sibling) {
8ffb1bcf
GH
351 ret = qbus_find_recursive(child, name, info);
352 if (ret) {
353 return ret;
354 }
355 }
356 }
357 return NULL;
358}
359
360static void qbus_list_bus(DeviceState *dev, char *dest, int len)
361{
362 BusState *child;
363 const char *sep = " ";
364 int pos = 0;
365
366 pos += snprintf(dest+pos, len-pos,"child busses at \"%s\":",
367 dev->id ? dev->id : dev->info->name);
72cf2d4f 368 QLIST_FOREACH(child, &dev->child_bus, sibling) {
8ffb1bcf
GH
369 pos += snprintf(dest+pos, len-pos, "%s\"%s\"", sep, child->name);
370 sep = ", ";
371 }
372}
373
374static void qbus_list_dev(BusState *bus, char *dest, int len)
375{
376 DeviceState *dev;
377 const char *sep = " ";
378 int pos = 0;
379
380 pos += snprintf(dest+pos, len-pos, "devices at \"%s\":",
381 bus->name);
72cf2d4f 382 QLIST_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
383 pos += snprintf(dest+pos, len-pos, "%s\"%s\"",
384 sep, dev->info->name);
385 if (dev->id)
386 pos += snprintf(dest+pos, len-pos, "/\"%s\"", dev->id);
387 sep = ", ";
388 }
389}
390
391static BusState *qbus_find_bus(DeviceState *dev, char *elem)
392{
393 BusState *child;
394
72cf2d4f 395 QLIST_FOREACH(child, &dev->child_bus, sibling) {
8ffb1bcf
GH
396 if (strcmp(child->name, elem) == 0) {
397 return child;
398 }
399 }
400 return NULL;
401}
402
403static DeviceState *qbus_find_dev(BusState *bus, char *elem)
404{
405 DeviceState *dev;
406
407 /*
408 * try to match in order:
409 * (1) instance id, if present
410 * (2) driver name
411 * (3) driver alias, if present
412 */
72cf2d4f 413 QLIST_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
414 if (dev->id && strcmp(dev->id, elem) == 0) {
415 return dev;
416 }
417 }
72cf2d4f 418 QLIST_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
419 if (strcmp(dev->info->name, elem) == 0) {
420 return dev;
421 }
422 }
72cf2d4f 423 QLIST_FOREACH(dev, &bus->children, sibling) {
8ffb1bcf
GH
424 if (dev->info->alias && strcmp(dev->info->alias, elem) == 0) {
425 return dev;
426 }
427 }
428 return NULL;
429}
430
431static BusState *qbus_find(const char *path)
432{
433 DeviceState *dev;
434 BusState *bus;
435 char elem[128], msg[256];
436 int pos, len;
437
438 /* find start element */
439 if (path[0] == '/') {
440 bus = main_system_bus;
441 pos = 0;
442 } else {
443 if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
286c2321 444 qemu_error("path parse error (\"%s\")\n", path);
8ffb1bcf
GH
445 return NULL;
446 }
447 bus = qbus_find_recursive(main_system_bus, elem, NULL);
448 if (!bus) {
286c2321 449 qemu_error("bus \"%s\" not found\n", elem);
8ffb1bcf
GH
450 return NULL;
451 }
452 pos = len;
453 }
454
455 for (;;) {
456 if (path[pos] == '\0') {
457 /* we are done */
458 return bus;
459 }
460
461 /* find device */
462 if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
286c2321 463 qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
8ffb1bcf
GH
464 return NULL;
465 }
466 pos += len;
467 dev = qbus_find_dev(bus, elem);
468 if (!dev) {
469 qbus_list_dev(bus, msg, sizeof(msg));
286c2321 470 qemu_error("device \"%s\" not found\n%s\n", elem, msg);
8ffb1bcf
GH
471 return NULL;
472 }
473 if (path[pos] == '\0') {
474 /* last specified element is a device. If it has exactly
475 * one child bus accept it nevertheless */
476 switch (dev->num_child_bus) {
477 case 0:
286c2321 478 qemu_error("device has no child bus (%s)\n", path);
8ffb1bcf
GH
479 return NULL;
480 case 1:
72cf2d4f 481 return QLIST_FIRST(&dev->child_bus);
8ffb1bcf
GH
482 default:
483 qbus_list_bus(dev, msg, sizeof(msg));
286c2321
GH
484 qemu_error("device has multiple child busses (%s)\n%s\n",
485 path, msg);
8ffb1bcf
GH
486 return NULL;
487 }
488 }
489
490 /* find bus */
491 if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
286c2321 492 qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
8ffb1bcf
GH
493 return NULL;
494 }
495 pos += len;
496 bus = qbus_find_bus(dev, elem);
497 if (!bus) {
498 qbus_list_bus(dev, msg, sizeof(msg));
286c2321 499 qemu_error("child bus \"%s\" not found\n%s\n", elem, msg);
8ffb1bcf
GH
500 return NULL;
501 }
502 }
503}
504
cd739fb6
GH
505void qbus_create_inplace(BusState *bus, BusInfo *info,
506 DeviceState *parent, const char *name)
02e2da45 507{
d271de9f
GH
508 char *buf;
509 int i,len;
02e2da45 510
10c4c98a 511 bus->info = info;
02e2da45 512 bus->parent = parent;
d271de9f
GH
513
514 if (name) {
515 /* use supplied name */
516 bus->name = qemu_strdup(name);
517 } else if (parent && parent->id) {
518 /* parent device has id -> use it for bus name */
519 len = strlen(parent->id) + 16;
520 buf = qemu_malloc(len);
521 snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus);
522 bus->name = buf;
523 } else {
524 /* no id -> use lowercase bus type for bus name */
525 len = strlen(info->name) + 16;
526 buf = qemu_malloc(len);
527 len = snprintf(buf, len, "%s.%d", info->name,
528 parent ? parent->num_child_bus : 0);
529 for (i = 0; i < len; i++)
bb87ece5 530 buf[i] = qemu_tolower(buf[i]);
d271de9f
GH
531 bus->name = buf;
532 }
533
72cf2d4f 534 QLIST_INIT(&bus->children);
02e2da45 535 if (parent) {
72cf2d4f 536 QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling);
d271de9f 537 parent->num_child_bus++;
02e2da45 538 }
cd739fb6
GH
539
540}
541
542BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name)
543{
544 BusState *bus;
545
546 bus = qemu_mallocz(info->size);
547 bus->qdev_allocated = 1;
548 qbus_create_inplace(bus, info, parent, name);
02e2da45
PB
549 return bus;
550}
cae4956e 551
cae4956e
GH
552#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
553static void qbus_print(Monitor *mon, BusState *bus, int indent);
554
ee6847d1
GH
555static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
556 const char *prefix, int indent)
557{
558 char buf[64];
559
560 if (!props)
561 return;
562 while (props->name) {
563 if (props->info->print) {
564 props->info->print(dev, props, buf, sizeof(buf));
565 qdev_printf("%s-prop: %s = %s\n", prefix, props->name, buf);
566 }
567 props++;
568 }
569}
570
cae4956e
GH
571static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
572{
cae4956e 573 BusState *child;
ccb63de3
GH
574 qdev_printf("dev: %s, id \"%s\"\n", dev->info->name,
575 dev->id ? dev->id : "");
cae4956e
GH
576 indent += 2;
577 if (dev->num_gpio_in) {
578 qdev_printf("gpio-in %d\n", dev->num_gpio_in);
579 }
580 if (dev->num_gpio_out) {
581 qdev_printf("gpio-out %d\n", dev->num_gpio_out);
582 }
ee6847d1
GH
583 qdev_print_props(mon, dev, dev->info->props, "dev", indent);
584 qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent);
10c4c98a
GH
585 if (dev->parent_bus->info->print_dev)
586 dev->parent_bus->info->print_dev(mon, dev, indent);
72cf2d4f 587 QLIST_FOREACH(child, &dev->child_bus, sibling) {
cae4956e
GH
588 qbus_print(mon, child, indent);
589 }
590}
591
592static void qbus_print(Monitor *mon, BusState *bus, int indent)
593{
594 struct DeviceState *dev;
595
596 qdev_printf("bus: %s\n", bus->name);
597 indent += 2;
10c4c98a 598 qdev_printf("type %s\n", bus->info->name);
72cf2d4f 599 QLIST_FOREACH(dev, &bus->children, sibling) {
cae4956e
GH
600 qdev_print(mon, dev, indent);
601 }
602}
603#undef qdev_printf
604
605void do_info_qtree(Monitor *mon)
606{
607 if (main_system_bus)
608 qbus_print(mon, main_system_bus, 0);
609}
9316d30f 610
f6c64e0e 611void do_info_qdm(Monitor *mon)
9316d30f
GH
612{
613 DeviceInfo *info;
614 char msg[256];
615
616 for (info = device_info_list; info != NULL; info = info->next) {
617 qdev_print_devinfo(info, msg, sizeof(msg));
618 monitor_printf(mon, "%s\n", msg);
619 }
620}
This page took 0.216299 seconds and 4 git commands to generate.