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.1 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
  20#include "qemu/osdep.h"
  21#include "qemu/error-report.h"
  22#include "qemu/module.h"
  23#include "qapi/error.h"
  24#include "monitor/monitor.h"
  25#include "hw/sysbus.h"
  26#include "sysemu/sysemu.h"
  27#include "hw/isa/isa.h"
  28
  29static ISABus *isabus;
  30
  31static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent);
  32static char *isabus_get_fw_dev_path(DeviceState *dev);
  33
  34static void isa_bus_class_init(ObjectClass *klass, void *data)
  35{
  36    BusClass *k = BUS_CLASS(klass);
  37
  38    k->print_dev = isabus_dev_print;
  39    k->get_fw_dev_path = isabus_get_fw_dev_path;
  40}
  41
  42static const TypeInfo isa_dma_info = {
  43    .name = TYPE_ISADMA,
  44    .parent = TYPE_INTERFACE,
  45    .class_size = sizeof(IsaDmaClass),
  46};
  47
  48static const TypeInfo isa_bus_info = {
  49    .name = TYPE_ISA_BUS,
  50    .parent = TYPE_BUS,
  51    .instance_size = sizeof(ISABus),
  52    .class_init = isa_bus_class_init,
  53};
  54
  55ISABus *isa_bus_new(DeviceState *dev, MemoryRegion* address_space,
  56                    MemoryRegion *address_space_io, Error **errp)
  57{
  58    if (isabus) {
  59        error_setg(errp, "Can't create a second ISA bus");
  60        return NULL;
  61    }
  62    if (!dev) {
  63        dev = qdev_new("isabus-bridge");
  64        sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
  65    }
  66
  67    isabus = ISA_BUS(qbus_create(TYPE_ISA_BUS, dev, NULL));
  68    isabus->address_space = address_space;
  69    isabus->address_space_io = address_space_io;
  70    return isabus;
  71}
  72
  73void isa_bus_irqs(ISABus *bus, qemu_irq *irqs)
  74{
  75    bus->irqs = irqs;
  76}
  77
  78/*
  79 * isa_get_irq() returns the corresponding qemu_irq entry for the i8259.
  80 *
  81 * This function is only for special cases such as the 'ferr', and
  82 * temporary use for normal devices until they are converted to qdev.
  83 */
  84qemu_irq isa_get_irq(ISADevice *dev, unsigned isairq)
  85{
  86    assert(!dev || ISA_BUS(qdev_get_parent_bus(DEVICE(dev))) == isabus);
  87    assert(isairq < ISA_NUM_IRQS);
  88    return isabus->irqs[isairq];
  89}
  90
  91void isa_init_irq(ISADevice *dev, qemu_irq *p, unsigned isairq)
  92{
  93    assert(dev->nirqs < ARRAY_SIZE(dev->isairq));
  94    assert(isairq < ISA_NUM_IRQS);
  95    dev->isairq[dev->nirqs] = isairq;
  96    *p = isa_get_irq(dev, isairq);
  97    dev->nirqs++;
  98}
  99
 100void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, unsigned isairq)
 101{
 102    qemu_irq irq;
 103    isa_init_irq(isadev, &irq, isairq);
 104    qdev_connect_gpio_out(DEVICE(isadev), gpioirq, irq);
 105}
 106
 107void isa_bus_dma(ISABus *bus, IsaDma *dma8, IsaDma *dma16)
 108{
 109    assert(bus && dma8 && dma16);
 110    assert(!bus->dma[0] && !bus->dma[1]);
 111    bus->dma[0] = dma8;
 112    bus->dma[1] = dma16;
 113}
 114
 115IsaDma *isa_get_dma(ISABus *bus, int nchan)
 116{
 117    assert(bus);
 118    return bus->dma[nchan > 3 ? 1 : 0];
 119}
 120
 121static inline void isa_init_ioport(ISADevice *dev, uint16_t ioport)
 122{
 123    if (dev && (dev->ioport_id == 0 || ioport < dev->ioport_id)) {
 124        dev->ioport_id = ioport;
 125    }
 126}
 127
 128void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start)
 129{
 130    memory_region_add_subregion(isabus->address_space_io, start, io);
 131    isa_init_ioport(dev, start);
 132}
 133
 134void isa_register_portio_list(ISADevice *dev,
 135                              PortioList *piolist, uint16_t start,
 136                              const MemoryRegionPortio *pio_start,
 137                              void *opaque, const char *name)
 138{
 139    assert(piolist && !piolist->owner);
 140
 141    /* START is how we should treat DEV, regardless of the actual
 142       contents of the portio array.  This is how the old code
 143       actually handled e.g. the FDC device.  */
 144    isa_init_ioport(dev, start);
 145
 146    portio_list_init(piolist, OBJECT(dev), pio_start, opaque, name);
 147    portio_list_add(piolist, isabus->address_space_io, start);
 148}
 149
 150static void isa_device_init(Object *obj)
 151{
 152    ISADevice *dev = ISA_DEVICE(obj);
 153
 154    dev->isairq[0] = -1;
 155    dev->isairq[1] = -1;
 156}
 157
 158ISADevice *isa_new(const char *name)
 159{
 160    return ISA_DEVICE(qdev_new(name));
 161}
 162
 163ISADevice *isa_try_new(const char *name)
 164{
 165    return ISA_DEVICE(qdev_try_new(name));
 166}
 167
 168ISADevice *isa_create_simple(ISABus *bus, const char *name)
 169{
 170    ISADevice *dev;
 171
 172    dev = isa_new(name);
 173    isa_realize_and_unref(dev, bus, &error_fatal);
 174    return dev;
 175}
 176
 177bool isa_realize_and_unref(ISADevice *dev, ISABus *bus, Error **errp)
 178{
 179    return qdev_realize_and_unref(&dev->parent_obj, &bus->parent_obj, errp);
 180}
 181
 182ISADevice *isa_vga_init(ISABus *bus)
 183{
 184    switch (vga_interface_type) {
 185    case VGA_CIRRUS:
 186        return isa_create_simple(bus, "isa-cirrus-vga");
 187    case VGA_QXL:
 188        error_report("%s: qxl: no PCI bus", __func__);
 189        return NULL;
 190    case VGA_STD:
 191        return isa_create_simple(bus, "isa-vga");
 192    case VGA_VMWARE:
 193        error_report("%s: vmware_vga: no PCI bus", __func__);
 194        return NULL;
 195    case VGA_VIRTIO:
 196        error_report("%s: virtio-vga: no PCI bus", __func__);
 197        return NULL;
 198    case VGA_NONE:
 199    default:
 200        return NULL;
 201    }
 202}
 203
 204void isa_build_aml(ISABus *bus, Aml *scope)
 205{
 206    BusChild *kid;
 207    ISADevice *dev;
 208    ISADeviceClass *dc;
 209
 210    QTAILQ_FOREACH(kid, &bus->parent_obj.children, sibling) {
 211        dev = ISA_DEVICE(kid->child);
 212        dc = ISA_DEVICE_GET_CLASS(dev);
 213        if (dc->build_aml) {
 214            dc->build_aml(dev, scope);
 215        }
 216    }
 217}
 218
 219static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent)
 220{
 221    ISADevice *d = ISA_DEVICE(dev);
 222
 223    if (d->isairq[1] != -1) {
 224        monitor_printf(mon, "%*sisa irqs %d,%d\n", indent, "",
 225                       d->isairq[0], d->isairq[1]);
 226    } else if (d->isairq[0] != -1) {
 227        monitor_printf(mon, "%*sisa irq %d\n", indent, "",
 228                       d->isairq[0]);
 229    }
 230}
 231
 232static void isabus_bridge_class_init(ObjectClass *klass, void *data)
 233{
 234    DeviceClass *dc = DEVICE_CLASS(klass);
 235
 236    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 237    dc->fw_name = "isa";
 238}
 239
 240static const TypeInfo isabus_bridge_info = {
 241    .name          = "isabus-bridge",
 242    .parent        = TYPE_SYS_BUS_DEVICE,
 243    .instance_size = sizeof(SysBusDevice),
 244    .class_init    = isabus_bridge_class_init,
 245};
 246
 247static void isa_device_class_init(ObjectClass *klass, void *data)
 248{
 249    DeviceClass *k = DEVICE_CLASS(klass);
 250    k->bus_type = TYPE_ISA_BUS;
 251}
 252
 253static const TypeInfo isa_device_type_info = {
 254    .name = TYPE_ISA_DEVICE,
 255    .parent = TYPE_DEVICE,
 256    .instance_size = sizeof(ISADevice),
 257    .instance_init = isa_device_init,
 258    .abstract = true,
 259    .class_size = sizeof(ISADeviceClass),
 260    .class_init = isa_device_class_init,
 261};
 262
 263static void isabus_register_types(void)
 264{
 265    type_register_static(&isa_dma_info);
 266    type_register_static(&isa_bus_info);
 267    type_register_static(&isabus_bridge_info);
 268    type_register_static(&isa_device_type_info);
 269}
 270
 271static char *isabus_get_fw_dev_path(DeviceState *dev)
 272{
 273    ISADevice *d = ISA_DEVICE(dev);
 274    char path[40];
 275    int off;
 276
 277    off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
 278    if (d->ioport_id) {
 279        snprintf(path + off, sizeof(path) - off, "@%04x", d->ioport_id);
 280    }
 281
 282    return g_strdup(path);
 283}
 284
 285MemoryRegion *isa_address_space(ISADevice *dev)
 286{
 287    if (dev) {
 288        return isa_bus_from_device(dev)->address_space;
 289    }
 290
 291    return isabus->address_space;
 292}
 293
 294MemoryRegion *isa_address_space_io(ISADevice *dev)
 295{
 296    if (dev) {
 297        return isa_bus_from_device(dev)->address_space_io;
 298    }
 299
 300    return isabus->address_space_io;
 301}
 302
 303type_init(isabus_register_types)
 304