15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Dynamic device configuration and creation. 35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright (c) 2009 CodeSourcery 55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * This library is free software; you can redistribute it and/or 75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * modify it under the terms of the GNU Lesser General Public 85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * License as published by the Free Software Foundation; either 95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * version 2 of the License, or (at your option) any later version. 105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * This library is distributed in the hope that it will be useful, 125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * but WITHOUT ANY WARRANTY; without even the implied warranty of 135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Lesser General Public License for more details. 155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * You should have received a copy of the GNU Lesser General Public 175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * License along with this library; if not, write to the Free Software 185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA 195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* The theory here is that it should be possible to create a machine without 225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner knowledge of specific devices. Historically board init routines have 235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner passed a bunch of arguments to each device, requiring the board know 245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner exactly which device it is dealing with. This file provides an abstract 255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner API for device configuration and initialization. Devices will generally 265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner inherit from a particular bus (e.g. PCI or I2C) rather than 275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner this API directly. */ 285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 29cc330d4169441727fecf1da08aee806fc021c4e2David 'Digit' Turner#include "net/net.h" 302ec695af7284adbedcdbc08a22d818b6bdd8990cDavid 'Digit' Turner#include "hw/qdev.h" 3134c48ff1e3ad5cd2084ca40188754d45f423750bDavid 'Digit' Turner#include "sysemu/sysemu.h" 326af6765e2f3bc930d0dce21d752bea570a1b1362David 'Digit' Turner#include "monitor/monitor.h" 3334c48ff1e3ad5cd2084ca40188754d45f423750bDavid 'Digit' Turner#include "sysemu/blockdev.h" 345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct DeviceProperty { 365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *name; 375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DevicePropType type; 385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner union { 395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint64_t i; 405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner void *ptr; 415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } value; 425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceProperty *next; 435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}; 445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct DeviceType { 465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceInfo *info; 475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceType *next; 485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}; 495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* This is a nasty hack to allow passing a NULL bus to qdev_create. */ 515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BusState *main_system_bus; 525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic DeviceType *device_type_list; 545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Register a new device type. */ 565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qdev_register(DeviceInfo *info) 575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceType *t; 595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner assert(info->size >= sizeof(DeviceState)); 615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 62aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner t = g_malloc0(sizeof(DeviceType)); 635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner t->next = device_type_list; 645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner device_type_list = t; 655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner t->info = info; 665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Create a new device. This only initializes the device state structure 695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner and allows properties to be set. qdev_init should be called to 705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner initialize the actual device emulation. */ 715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerDeviceState *qdev_create(BusState *bus, const char *name) 725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceType *t; 745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceState *dev; 755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (t = device_type_list; t; t = t->next) { 775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strcmp(t->info->name, name) == 0) { 785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!t) { 825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hw_error("Unknown device '%s'\n", name); 835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 85aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner dev = g_malloc0(t->info->size); 865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dev->type = t; 875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!bus) { 895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* ???: This assumes system busses have no additional state. */ 905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!main_system_bus) { 915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner main_system_bus = qbus_create(BUS_TYPE_SYSTEM, sizeof(BusState), 925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NULL, "main-system-bus"); 935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bus = main_system_bus; 955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (t->info->bus_type != bus->type) { 975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* TODO: Print bus type names. */ 985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hw_error("Device '%s' on wrong bus type (%d/%d)", name, 995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner t->info->bus_type, bus->type); 1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dev->parent_bus = bus; 102a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner QLIST_INSERT_HEAD(&bus->children, dev, sibling); 1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return dev; 1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 106cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint qdev_device_help(QemuOpts *opts) 107cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{ 108cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#ifdef CONFIG_ANDROID /* Not ready yet, will remove when we properly integrate upstream qdev */ 109cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return 0; 110cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#else 111cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner const char *driver; 112cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner DeviceInfo *info; 113cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner Property *prop; 114cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner 115cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner driver = qemu_opt_get(opts, "driver"); 116cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (driver && !strcmp(driver, "?")) { 117cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner for (info = device_info_list; info != NULL; info = info->next) { 118cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (info->no_user) { 119cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner continue; /* not available, don't show */ 120cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 121cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner qdev_print_devinfo(info); 122cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 123cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return 1; 124cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 125cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner 126cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (!qemu_opt_get(opts, "?")) { 127cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return 0; 128cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 129cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner 130cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner info = qdev_find_info(NULL, driver); 131cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (!info) { 132cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return 0; 133cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 134cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner 135cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner for (prop = info->props; prop && prop->name; prop++) { 136cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner /* 137cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * TODO Properties without a parser are just for dirty hacks. 138cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * qdev_prop_ptr is the only such PropertyInfo. It's marked 139cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * for removal. This conditional should be removed along with 140cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * it. 141cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */ 142cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (!prop->info->parse) { 143cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner continue; /* no way to set it, don't show */ 144cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 145cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner error_printf("%s.%s=%s\n", info->name, prop->name, prop->info->name); 146cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 147cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return 1; 148cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#endif 149cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner} 150cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner 151cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerDeviceState *qdev_device_add(QemuOpts *opts) 152cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{ 153cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#ifdef CONFIG_ANDROID /* Not ready yet */ 154cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return NULL; 155cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#else 156cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner const char *driver, *path, *id; 157cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner DeviceInfo *info; 158cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner DeviceState *qdev; 159cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner BusState *bus; 160cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner 161cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner driver = qemu_opt_get(opts, "driver"); 162cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (!driver) { 163cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner qerror_report(QERR_MISSING_PARAMETER, "driver"); 164cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return NULL; 165cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 166cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner 167cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner /* find driver */ 168cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner info = qdev_find_info(NULL, driver); 169cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (!info || info->no_user) { 170cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "a driver name"); 171cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner error_printf_unless_qmp("Try with argument '?' for a list.\n"); 172cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return NULL; 173cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 174cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner 175cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner /* find bus */ 176cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner path = qemu_opt_get(opts, "bus"); 177cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (path != NULL) { 178cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner bus = qbus_find(path); 179cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (!bus) { 180cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return NULL; 181cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 182cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (bus->info != info->bus_info) { 183cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner qerror_report(QERR_BAD_BUS_FOR_DEVICE, 184cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner driver, bus->info->name); 185cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return NULL; 186cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 187cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } else { 188cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner bus = qbus_find_recursive(main_system_bus, NULL, info->bus_info); 189cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (!bus) { 190cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner qerror_report(QERR_NO_BUS_FOR_DEVICE, 191cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner info->name, info->bus_info->name); 192cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return NULL; 193cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 194cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 195cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (qdev_hotplug && !bus->allow_hotplug) { 196cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner qerror_report(QERR_BUS_NO_HOTPLUG, bus->name); 197cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return NULL; 198cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 199cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner 200cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner /* create device, set properties */ 201cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner qdev = qdev_create_from_info(bus, info); 202cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner id = qemu_opts_id(opts); 203cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (id) { 204cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner qdev->id = id; 205cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 206cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) { 207cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner qdev_free(qdev); 208cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return NULL; 209cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 210cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (qdev_init(qdev) < 0) { 211cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner qerror_report(QERR_DEVICE_INIT_FAILED, driver); 212cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return NULL; 213cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner } 214cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner qdev->opts = opts; 215cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return qdev; 216cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#endif 217cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner} 218cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner 2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Initialize a device. Device properties should be set before calling 2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner this function. IRQs and MMIO regions should be connected/mapped after 2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner calling this function. */ 2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qdev_init(DeviceState *dev) 2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dev->type->info->init(dev, dev->type->info); 2255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Unlink device from bus and free the structure. */ 2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qdev_free(DeviceState *dev) 2295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 230a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner QLIST_REMOVE(dev, sibling); 231aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner g_free(dev); 2325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic DeviceProperty *create_prop(DeviceState *dev, const char *name, 2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DevicePropType type) 2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceProperty *prop; 2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* TODO: Check for duplicate properties. */ 240aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner prop = g_malloc0(sizeof(*prop)); 241aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner prop->name = g_strdup(name); 2425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner prop->type = type; 2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner prop->next = dev->props; 2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dev->props = prop; 2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return prop; 2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qdev_set_prop_int(DeviceState *dev, const char *name, uint64_t value) 2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceProperty *prop; 2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner prop = create_prop(dev, name, PROP_TYPE_INT); 2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner prop->value.i = value; 2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qdev_set_prop_dev(DeviceState *dev, const char *name, DeviceState *value) 2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceProperty *prop; 2605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner prop = create_prop(dev, name, PROP_TYPE_DEV); 2625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner prop->value.ptr = value; 2635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qdev_set_prop_ptr(DeviceState *dev, const char *name, void *value) 2665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceProperty *prop; 2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner prop = create_prop(dev, name, PROP_TYPE_PTR); 2705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner prop->value.ptr = value; 2715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qdev_set_netdev(DeviceState *dev, NICInfo *nd) 2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner assert(!dev->nd); 2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dev->nd = nd; 2775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Get a character (serial) device interface. */ 2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerCharDriverState *qdev_init_chardev(DeviceState *dev) 2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static int next_serial; 2845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static int next_virtconsole; 2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* FIXME: This is a nasty hack that needs to go away. */ 2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strncmp(dev->type->info->name, "virtio", 6) == 0) { 2875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return virtcon_hds[next_virtconsole++]; 2885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 2895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return serial_hds[next_serial++]; 2905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerBusState *qdev_get_parent_bus(DeviceState *dev) 2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return dev->parent_bus; 2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic DeviceProperty *find_prop(DeviceState *dev, const char *name, 2995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DevicePropType type) 3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceProperty *prop; 3025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (prop = dev->props; prop; prop = prop->next) { 3045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strcmp(prop->name, name) == 0) { 3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner assert (prop->type == type); 3065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return prop; 3075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 3105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneruint64_t qdev_get_prop_int(DeviceState *dev, const char *name, uint64_t def) 3135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceProperty *prop; 3155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner prop = find_prop(dev, name, PROP_TYPE_INT); 3175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!prop) { 3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return def; 3195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return prop->value.i; 3225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid *qdev_get_prop_ptr(DeviceState *dev, const char *name) 3255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceProperty *prop; 3275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner prop = find_prop(dev, name, PROP_TYPE_PTR); 3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner assert(prop); 3305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return prop->value.ptr; 3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerDeviceState *qdev_get_prop_dev(DeviceState *dev, const char *name) 3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceProperty *prop; 3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner prop = find_prop(dev, name, PROP_TYPE_DEV); 3385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!prop) { 3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return prop->value.ptr; 3425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) 3455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner assert(dev->num_gpio_in == 0); 3475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dev->num_gpio_in = n; 3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dev->gpio_in = qemu_allocate_irqs(handler, dev, n); 3495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n) 3525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner assert(dev->num_gpio_out == 0); 3545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dev->num_gpio_out = n; 3555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dev->gpio_out = pins; 3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerqemu_irq qdev_get_gpio_in(DeviceState *dev, int n) 3595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner assert(n >= 0 && n < dev->num_gpio_in); 3615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return dev->gpio_in[n]; 3625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) 3655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner assert(n >= 0 && n < dev->num_gpio_out); 3675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dev->gpio_out[n] = pin; 3685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerVLANClientState *qdev_get_vlan_client(DeviceState *dev, 3715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetCanReceive *can_receive, 3725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetReceive *receive, 3735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetReceiveIOV *receive_iov, 3745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetCleanup *cleanup, 3755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner void *opaque) 3765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NICInfo *nd = dev->nd; 3785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner assert(nd); 3795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive, 3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner receive, receive_iov, cleanup, opaque); 3815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qdev_get_macaddr(DeviceState *dev, uint8_t *macaddr) 3855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(macaddr, dev->nd->macaddr, 6); 3875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int next_block_unit[IF_COUNT]; 3905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Get a block device. This should only be used for single-drive devices 3925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the 3935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner appropriate bus. */ 3945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerBlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type) 3955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int unit = next_block_unit[type]++; 397cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner DriveInfo* info; 3985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 399cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner info = drive_get(type, 0, unit); 400cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (info == NULL) { 4015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 403cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner return info->bdrv; 4045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerBusState *qdev_get_child_bus(DeviceState *dev, const char *name) 4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner BusState *bus; 4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 410a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner QLIST_FOREACH(bus, &dev->child_bus, sibling) { 4115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strcmp(name, bus->name) == 0) { 4125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return bus; 4135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 4165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int next_scsi_bus; 4195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Create a scsi bus, and attach devices to it. */ 4215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* TODO: Actually create a scsi bus for hotplug to use. */ 4225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid scsi_bus_new(DeviceState *host, SCSIAttachFn attach) 4235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int bus = next_scsi_bus++; 4255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int unit; 426cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner DriveInfo* info; 4275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (unit = 0; unit < MAX_SCSI_DEVS; unit++) { 429cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner info = drive_get(IF_SCSI, bus, unit); 430cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner if (info == NULL) { 4315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 4325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 433cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner attach(host, info->bdrv, unit); 4345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerBusState *qbus_create(BusType type, size_t size, 4385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceState *parent, const char *name) 4395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner BusState *bus; 4415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 442aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner bus = g_malloc0(size); 4435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bus->type = type; 4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bus->parent = parent; 445aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner bus->name = g_strdup(name); 446a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner QLIST_INIT(&bus->children); 4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (parent) { 448a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling); 4495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return bus; 4515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const char *bus_type_names[] = { 4545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner [ BUS_TYPE_SYSTEM ] = "System", 4555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner [ BUS_TYPE_PCI ] = "PCI", 4565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner [ BUS_TYPE_SCSI ] = "SCSI", 4575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner [ BUS_TYPE_I2C ] = "I2C", 4585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner [ BUS_TYPE_SSI ] = "SSI", 4595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}; 4605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__) 4625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void qbus_print(Monitor *mon, BusState *bus, int indent); 4635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void qdev_print(Monitor *mon, DeviceState *dev, int indent) 4655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DeviceProperty *prop; 4675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner BusState *child; 4685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qdev_printf("dev: %s\n", dev->type->info->name); 4695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner indent += 2; 4705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (dev->num_gpio_in) { 4715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qdev_printf("gpio-in %d\n", dev->num_gpio_in); 4725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (dev->num_gpio_out) { 4745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qdev_printf("gpio-out %d\n", dev->num_gpio_out); 4755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (prop = dev->props; prop; prop = prop->next) { 4775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (prop->type) { 4785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case PROP_TYPE_INT: 4795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qdev_printf("prop-int %s 0x%" PRIx64 "\n", prop->name, 4805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner prop->value.i); 4815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 4825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case PROP_TYPE_PTR: 4835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qdev_printf("prop-ptr %s\n", prop->name); 4845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 4855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case PROP_TYPE_DEV: 4865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qdev_printf("prop-dev %s %s\n", prop->name, 4875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ((DeviceState *)prop->value.ptr)->type->info->name); 4885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 4895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 4905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qdev_printf("prop-unknown%d %s\n", prop->type, prop->name); 4915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 4925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (dev->parent_bus->type) { 4955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case BUS_TYPE_SYSTEM: 4965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sysbus_dev_print(mon, dev, indent); 4975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 4985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 4995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 5005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 501a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner QLIST_FOREACH(child, &dev->child_bus, sibling) { 5025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qbus_print(mon, child, indent); 5035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 5055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void qbus_print(Monitor *mon, BusState *bus, int indent) 5075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 5085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct DeviceState *dev; 5095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qdev_printf("bus: %s\n", bus->name); 5115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner indent += 2; 5125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qdev_printf("type %s\n", bus_type_names[bus->type]); 513a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner QLIST_FOREACH(dev, &bus->children, sibling) { 5145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qdev_print(mon, dev, indent); 5155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 5175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#undef qdev_printf 5185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid do_info_qtree(Monitor *mon) 5205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 5215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (main_system_bus) 5225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qbus_print(mon, main_system_bus, 0); 5235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 5246234c0bcfcdd730c6815136cf958b240af8f4a7cDavid 'Digit' Turner 5256234c0bcfcdd730c6815136cf958b240af8f4a7cDavid 'Digit' Turnerchar *qdev_get_dev_path(DeviceState *dev) 5266234c0bcfcdd730c6815136cf958b240af8f4a7cDavid 'Digit' Turner{ 5276234c0bcfcdd730c6815136cf958b240af8f4a7cDavid 'Digit' Turner // TODO(digit): Implement this properly. 5286234c0bcfcdd730c6815136cf958b240af8f4a7cDavid 'Digit' Turner return NULL; 5296234c0bcfcdd730c6815136cf958b240af8f4a7cDavid 'Digit' Turner} 5306234c0bcfcdd730c6815136cf958b240af8f4a7cDavid 'Digit' Turner 531