qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

isa-bus.c (7136B)


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