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