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 "qemu/osdep.h"
  20#include "qapi/error.h"
  21#include "hw/hw.h"
  22#include "monitor/monitor.h"
  23#include "hw/sysbus.h"
  24#include "sysemu/sysemu.h"
  25#include "hw/isa/isa.h"
  26#include "hw/i386/pc.h"
  27
  28static ISABus *isabus;
  29
  30static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent);
  31static char *isabus_get_fw_dev_path(DeviceState *dev);
  32
  33static void isa_bus_class_init(ObjectClass *klass, void *data)
  34{
  35    BusClass *k = BUS_CLASS(klass);
  36
  37    k->print_dev = isabus_dev_print;
  38    k->get_fw_dev_path = isabus_get_fw_dev_path;
  39}
  40
  41static const TypeInfo isa_dma_info = {
  42    .name = TYPE_ISADMA,
  43    .parent = TYPE_INTERFACE,
  44    .class_size = sizeof(IsaDmaClass),
  45};
  46
  47static const TypeInfo isa_bus_info = {
  48    .name = TYPE_ISA_BUS,
  49    .parent = TYPE_BUS,
  50    .instance_size = sizeof(ISABus),
  51    .class_init = isa_bus_class_init,
  52};
  53
  54ISABus *isa_bus_new(DeviceState *dev, MemoryRegion* address_space,
  55                    MemoryRegion *address_space_io, Error **errp)
  56{
  57    if (isabus) {
  58        error_setg(errp, "Can't create a second ISA bus");
  59        return NULL;
  60    }
  61    if (!dev) {
  62        dev = qdev_create(NULL, "isabus-bridge");
  63        qdev_init_nofail(dev);
  64    }
  65
  66    isabus = ISA_BUS(qbus_create(TYPE_ISA_BUS, dev, NULL));
  67    isabus->address_space = address_space;
  68    isabus->address_space_io = address_space_io;
  69    return isabus;
  70}
  71
  72void isa_bus_irqs(ISABus *bus, qemu_irq *irqs)
  73{
  74    bus->irqs = irqs;
  75}
  76
  77/*
  78 * isa_get_irq() returns the corresponding qemu_irq entry for the i8259.
  79 *
  80 * This function is only for special cases such as the 'ferr', and
  81 * temporary use for normal devices until they are converted to qdev.
  82 */
  83qemu_irq isa_get_irq(ISADevice *dev, int isairq)
  84{
  85    assert(!dev || ISA_BUS(qdev_get_parent_bus(DEVICE(dev))) == isabus);
  86    if (isairq < 0 || isairq > 15) {
  87        hw_error("isa irq %d invalid", isairq);
  88    }
  89    return isabus->irqs[isairq];
  90}
  91
  92void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq)
  93{
  94    assert(dev->nirqs < ARRAY_SIZE(dev->isairq));
  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, int 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, uint16_t start,
 135                              const MemoryRegionPortio *pio_start,
 136                              void *opaque, const char *name)
 137{
 138    PortioList piolist;
 139
 140    /* START is how we should treat DEV, regardless of the actual
 141       contents of the portio array.  This is how the old code
 142       actually handled e.g. the FDC device.  */
 143    isa_init_ioport(dev, start);
 144
 145    /* FIXME: the device should store created PortioList in its state.  Note
 146       that DEV can be NULL here and that single device can register several
 147       portio lists.  Current implementation is leaking memory allocated
 148       in portio_list_init.  The leak is not critical because it happens only
 149       at initialization time.  */
 150    portio_list_init(&piolist, OBJECT(dev), pio_start, opaque, name);
 151    portio_list_add(&piolist, isabus->address_space_io, start);
 152}
 153
 154static void isa_device_init(Object *obj)
 155{
 156    ISADevice *dev = ISA_DEVICE(obj);
 157
 158    dev->isairq[0] = -1;
 159    dev->isairq[1] = -1;
 160}
 161
 162ISADevice *isa_create(ISABus *bus, const char *name)
 163{
 164    DeviceState *dev;
 165
 166    dev = qdev_create(BUS(bus), name);
 167    return ISA_DEVICE(dev);
 168}
 169
 170ISADevice *isa_try_create(ISABus *bus, const char *name)
 171{
 172    DeviceState *dev;
 173
 174    dev = qdev_try_create(BUS(bus), name);
 175    return ISA_DEVICE(dev);
 176}
 177
 178ISADevice *isa_create_simple(ISABus *bus, const char *name)
 179{
 180    ISADevice *dev;
 181
 182    dev = isa_create(bus, name);
 183    qdev_init_nofail(DEVICE(dev));
 184    return dev;
 185}
 186
 187ISADevice *isa_vga_init(ISABus *bus)
 188{
 189    switch (vga_interface_type) {
 190    case VGA_CIRRUS:
 191        return isa_create_simple(bus, "isa-cirrus-vga");
 192    case VGA_QXL:
 193        fprintf(stderr, "%s: qxl: no PCI bus\n", __func__);
 194        return NULL;
 195    case VGA_STD:
 196        return isa_create_simple(bus, "isa-vga");
 197    case VGA_VMWARE:
 198        fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __func__);
 199        return NULL;
 200    case VGA_VIRTIO:
 201        fprintf(stderr, "%s: virtio-vga: no PCI bus\n", __func__);
 202        return NULL;
 203    case VGA_NONE:
 204    default:
 205        return NULL;
 206    }
 207}
 208
 209static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent)
 210{
 211    ISADevice *d = ISA_DEVICE(dev);
 212
 213    if (d->isairq[1] != -1) {
 214        monitor_printf(mon, "%*sisa irqs %d,%d\n", indent, "",
 215                       d->isairq[0], d->isairq[1]);
 216    } else if (d->isairq[0] != -1) {
 217        monitor_printf(mon, "%*sisa irq %d\n", indent, "",
 218                       d->isairq[0]);
 219    }
 220}
 221
 222static void isabus_bridge_class_init(ObjectClass *klass, void *data)
 223{
 224    DeviceClass *dc = DEVICE_CLASS(klass);
 225
 226    dc->fw_name = "isa";
 227}
 228
 229static const TypeInfo isabus_bridge_info = {
 230    .name          = "isabus-bridge",
 231    .parent        = TYPE_SYS_BUS_DEVICE,
 232    .instance_size = sizeof(SysBusDevice),
 233    .class_init    = isabus_bridge_class_init,
 234};
 235
 236static void isa_device_class_init(ObjectClass *klass, void *data)
 237{
 238    DeviceClass *k = DEVICE_CLASS(klass);
 239    k->bus_type = TYPE_ISA_BUS;
 240}
 241
 242static const TypeInfo isa_device_type_info = {
 243    .name = TYPE_ISA_DEVICE,
 244    .parent = TYPE_DEVICE,
 245    .instance_size = sizeof(ISADevice),
 246    .instance_init = isa_device_init,
 247    .abstract = true,
 248    .class_size = sizeof(ISADeviceClass),
 249    .class_init = isa_device_class_init,
 250};
 251
 252static void isabus_register_types(void)
 253{
 254    type_register_static(&isa_dma_info);
 255    type_register_static(&isa_bus_info);
 256    type_register_static(&isabus_bridge_info);
 257    type_register_static(&isa_device_type_info);
 258}
 259
 260static char *isabus_get_fw_dev_path(DeviceState *dev)
 261{
 262    ISADevice *d = ISA_DEVICE(dev);
 263    char path[40];
 264    int off;
 265
 266    off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev));
 267    if (d->ioport_id) {
 268        snprintf(path + off, sizeof(path) - off, "@%04x", d->ioport_id);
 269    }
 270
 271    return g_strdup(path);
 272}
 273
 274MemoryRegion *isa_address_space(ISADevice *dev)
 275{
 276    if (dev) {
 277        return isa_bus_from_device(dev)->address_space;
 278    }
 279
 280    return isabus->address_space;
 281}
 282
 283MemoryRegion *isa_address_space_io(ISADevice *dev)
 284{
 285    if (dev) {
 286        return isa_bus_from_device(dev)->address_space_io;
 287    }
 288
 289    return isabus->address_space_io;
 290}
 291
 292type_init(isabus_register_types)
 293
 294static void parallel_init(ISABus *bus, int index, CharDriverState *chr)
 295{
 296    DeviceState *dev;
 297    ISADevice *isadev;
 298
 299    isadev = isa_create(bus, "isa-parallel");
 300    dev = DEVICE(isadev);
 301    qdev_prop_set_uint32(dev, "index", index);
 302    qdev_prop_set_chr(dev, "chardev", chr);
 303    qdev_init_nofail(dev);
 304}
 305
 306void parallel_hds_isa_init(ISABus *bus, int n)
 307{
 308    int i;
 309
 310    assert(n <= MAX_PARALLEL_PORTS);
 311
 312    for (i = 0; i < n; i++) {
 313        if (parallel_hds[i]) {
 314            parallel_init(bus, i, parallel_hds[i]);
 315        }
 316    }
 317}
 318