qemu/hw/isa/isa-bus.c
<<
>>
Prefs
   1/*
   2 * isa bus support for qdev.
   3 *
   4 * Copyright (c) 2009 Gerd Hoffmann <kraxel@redhat.com>
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19#include "hw/hw.h"
  20#include "monitor/monitor.h"
  21#include "hw/sysbus.h"
  22#include "sysemu/sysemu.h"
  23#include "hw/isa/isa.h"
  24#include "exec/address-spaces.h"
  25
  26static ISABus *isabus;
  27hwaddr isa_mem_base = 0;
  28
  29static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent);
  30static char *isabus_get_fw_dev_path(DeviceState *dev);
  31
  32static void isa_bus_class_init(ObjectClass *klass, void *data)
  33{
  34    BusClass *k = BUS_CLASS(klass);
  35
  36    k->print_dev = isabus_dev_print;
  37    k->get_fw_dev_path = isabus_get_fw_dev_path;
  38}
  39
  40static const TypeInfo isa_bus_info = {
  41    .name = TYPE_ISA_BUS,
  42    .parent = TYPE_BUS,
  43    .instance_size = sizeof(ISABus),
  44    .class_init = isa_bus_class_init,
  45};
  46
  47ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io)
  48{
  49    if (isabus) {
  50        fprintf(stderr, "Can't create a second ISA bus\n");
  51        return NULL;
  52    }
  53    if (!dev) {
  54        dev = qdev_create(NULL, "isabus-bridge");
  55        qdev_init_nofail(dev);
  56    }
  57
  58    isabus = ISA_BUS(qbus_create(TYPE_ISA_BUS, dev, NULL));
  59    isabus->address_space_io = address_space_io;
  60    return isabus;
  61}
  62
  63void isa_bus_irqs(ISABus *bus, qemu_irq *irqs)
  64{
  65    if (!bus) {
  66        hw_error("Can't set isa irqs with no isa bus present.");
  67    }
  68    bus->irqs = irqs;
  69}
  70
  71/*
  72 * isa_get_irq() returns the corresponding qemu_irq entry for the i8259.
  73 *
  74 * This function is only for special cases such as the 'ferr', and
  75 * temporary use for normal devices until they are converted to qdev.
  76 */
  77qemu_irq isa_get_irq(ISADevice *dev, int isairq)
  78{
  79    assert(!dev || ISA_BUS(qdev_get_parent_bus(DEVICE(dev))) == isabus);
  80    if (isairq < 0 || isairq > 15) {
  81        hw_error("isa irq %d invalid", isairq);
  82    }
  83    return isabus->irqs[isairq];
  84}
  85
  86void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq)
  87{
  88    assert(dev->nirqs < ARRAY_SIZE(dev->isairq));
  89    dev->isairq[dev->nirqs] = isairq;
  90    *p = isa_get_irq(dev, isairq);
  91    dev->nirqs++;
  92}
  93
  94static inline void isa_init_ioport(ISADevice *dev, uint16_t ioport)
  95{
  96    if (dev && (dev->ioport_id == 0 || ioport < dev->ioport_id)) {
  97        dev->ioport_id = ioport;
  98    }
  99}
 100
 101void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start)
 102{
 103    memory_region_add_subregion(isabus->address_space_io, start, io);
 104    isa_init_ioport(dev, start);
 105}
 106
 107void isa_register_portio_list(ISADevice *dev, uint16_t start,
 108                              const MemoryRegionPortio *pio_start,
 109                              void *opaque, const char *name)
 110{
 111    PortioList piolist;
 112
 113    /* START is how we should treat DEV, regardless of the actual
 114       contents of the portio array.  This is how the old code
 115       actually handled e.g. the FDC device.  */
 116    isa_init_ioport(dev, start);
 117
 118    /* FIXME: the device should store created PortioList in its state.  Note
 119       that DEV can be NULL here and that single device can register several
 120       portio lists.  Current implementation is leaking memory allocated
 121       in portio_list_init.  The leak is not critical because it happens only
 122       at initialization time.  */
 123    portio_list_init(&piolist, OBJECT(dev), pio_start, opaque, name);
 124    portio_list_add(&piolist, isabus->address_space_io, start);
 125}
 126
 127static void isa_device_init(Object *obj)
 128{
 129    ISADevice *dev = ISA_DEVICE(obj);
 130
 131    dev->isairq[0] = -1;
 132    dev->isairq[1] = -1;
 133}
 134
 135ISADevice *isa_create(ISABus *bus, const char *name)
 136{
 137    DeviceState *dev;
 138
 139    if (!bus) {
 140        hw_error("Tried to create isa device %s with no isa bus present.",
 141                 name);
 142    }
 143    dev = qdev_create(BUS(bus), name);
 144    return ISA_DEVICE(dev);
 145}
 146
 147ISADevice *isa_try_create(ISABus *bus, const char *name)
 148{
 149    DeviceState *dev;
 150
 151    if (!bus) {
 152        hw_error("Tried to create isa device %s with no isa bus present.",
 153                 name);
 154    }
 155    dev = qdev_try_create(BUS(bus), name);
 156    return ISA_DEVICE(dev);
 157}
 158
 159ISADevice *isa_create_simple(ISABus *bus, const char *name)
 160{
 161    ISADevice *dev;
 162
 163    dev = isa_create(bus, name);
 164    qdev_init_nofail(DEVICE(dev));
 165    return dev;
 166}
 167
 168ISADevice *isa_vga_init(ISABus *bus)
 169{
 170    switch (vga_interface_type) {
 171    case VGA_CIRRUS:
 172        return isa_create_simple(bus, "isa-cirrus-vga");
 173    case VGA_QXL:
 174        fprintf(stderr, "%s: qxl: no PCI bus\n", __func__);
 175        return NULL;
 176    case VGA_STD:
 177        return isa_create_simple(bus, "isa-vga");
 178    case VGA_VMWARE:
 179        fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __func__);
 180        return NULL;
 181    case VGA_NONE:
 182    default:
 183        return NULL;
 184    }
 185}
 186
 187static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent)
 188{
 189    ISADevice *d = ISA_DEVICE(dev);
 190
 191    if (d->isairq[1] != -1) {
 192        monitor_printf(mon, "%*sisa irqs %d,%d\n", indent, "",
 193                       d->isairq[0], d->isairq[1]);
 194    } else if (d->isairq[0] != -1) {
 195        monitor_printf(mon, "%*sisa irq %d\n", indent, "",
 196                       d->isairq[0]);
 197    }
 198}
 199
 200static void isabus_bridge_class_init(ObjectClass *klass, void *data)
 201{
 202    DeviceClass *dc = DEVICE_CLASS(klass);
 203
 204    dc->fw_name = "isa";
 205}
 206
 207static const TypeInfo isabus_bridge_info = {
 208    .name          = "isabus-bridge",
 209    .parent        = TYPE_SYS_BUS_DEVICE,
 210    .instance_size = sizeof(SysBusDevice),
 211    .class_init    = isabus_bridge_class_init,
 212};
 213
 214static void isa_device_class_init(ObjectClass *klass, void *data)
 215{
 216    DeviceClass *k = DEVICE_CLASS(klass);
 217    k->bus_type = TYPE_ISA_BUS;
 218}
 219
 220static const TypeInfo isa_device_type_info = {
 221    .name = TYPE_ISA_DEVICE,
 222    .parent = TYPE_DEVICE,
 223    .instance_size = sizeof(ISADevice),
 224    .instance_init = isa_device_init,
 225    .abstract = true,
 226    .class_size = sizeof(ISADeviceClass),
 227    .class_init = isa_device_class_init,
 228};
 229
 230static void isabus_register_types(void)
 231{
 232    type_register_static(&isa_bus_info);
 233    type_register_static(&isabus_bridge_info);
 234    type_register_static(&isa_device_type_info);
 235}
 236
 237static char *isabus_get_fw_dev_path(DeviceState *dev)
 238{
 239    ISADevice *d = ISA_DEVICE(dev);
 240    char path[40];
 241    int off;
 242
 243    off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
 244    if (d->ioport_id) {
 245        snprintf(path + off, sizeof(path) - off, "@%04x", d->ioport_id);
 246    }
 247
 248    return g_strdup(path);
 249}
 250
 251MemoryRegion *isa_address_space(ISADevice *dev)
 252{
 253    return get_system_memory();
 254}
 255
 256MemoryRegion *isa_address_space_io(ISADevice *dev)
 257{
 258    if (dev) {
 259        return isa_bus_from_device(dev)->address_space_io;
 260    }
 261
 262    return isabus->address_space_io;
 263}
 264
 265type_init(isabus_register_types)
 266