qemu/hw/i386/port92.c
<<
>>
Prefs
   1/*
   2 * QEMU I/O port 0x92 (System Control Port A, to handle Fast Gate A20)
   3 *
   4 * Copyright (c) 2003-2004 Fabrice Bellard
   5 *
   6 * SPDX-License-Identifier: MIT
   7 */
   8
   9#include "qemu/osdep.h"
  10#include "sysemu/runstate.h"
  11#include "migration/vmstate.h"
  12#include "hw/irq.h"
  13#include "hw/i386/pc.h"
  14#include "trace.h"
  15#include "qom/object.h"
  16
  17OBJECT_DECLARE_SIMPLE_TYPE(Port92State, PORT92)
  18
  19struct Port92State {
  20    ISADevice parent_obj;
  21
  22    MemoryRegion io;
  23    uint8_t outport;
  24    qemu_irq a20_out;
  25};
  26
  27static void port92_write(void *opaque, hwaddr addr, uint64_t val,
  28                         unsigned size)
  29{
  30    Port92State *s = opaque;
  31    int oldval = s->outport;
  32
  33    trace_port92_write(val);
  34    s->outport = val;
  35    qemu_set_irq(s->a20_out, (val >> 1) & 1);
  36    if ((val & 1) && !(oldval & 1)) {
  37        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
  38    }
  39}
  40
  41static uint64_t port92_read(void *opaque, hwaddr addr,
  42                            unsigned size)
  43{
  44    Port92State *s = opaque;
  45    uint32_t ret;
  46
  47    ret = s->outport;
  48    trace_port92_read(ret);
  49
  50    return ret;
  51}
  52
  53static const VMStateDescription vmstate_port92_isa = {
  54    .name = "port92",
  55    .version_id = 1,
  56    .minimum_version_id = 1,
  57    .fields = (VMStateField[]) {
  58        VMSTATE_UINT8(outport, Port92State),
  59        VMSTATE_END_OF_LIST()
  60    }
  61};
  62
  63static void port92_reset(DeviceState *d)
  64{
  65    Port92State *s = PORT92(d);
  66
  67    s->outport &= ~1;
  68}
  69
  70static const MemoryRegionOps port92_ops = {
  71    .read = port92_read,
  72    .write = port92_write,
  73    .impl = {
  74        .min_access_size = 1,
  75        .max_access_size = 1,
  76    },
  77    .endianness = DEVICE_LITTLE_ENDIAN,
  78};
  79
  80static void port92_initfn(Object *obj)
  81{
  82    Port92State *s = PORT92(obj);
  83
  84    memory_region_init_io(&s->io, OBJECT(s), &port92_ops, s, "port92", 1);
  85
  86    s->outport = 0;
  87
  88    qdev_init_gpio_out_named(DEVICE(obj), &s->a20_out, PORT92_A20_LINE, 1);
  89}
  90
  91static void port92_realizefn(DeviceState *dev, Error **errp)
  92{
  93    ISADevice *isadev = ISA_DEVICE(dev);
  94    Port92State *s = PORT92(dev);
  95
  96    isa_register_ioport(isadev, &s->io, 0x92);
  97}
  98
  99static void port92_class_initfn(ObjectClass *klass, void *data)
 100{
 101    DeviceClass *dc = DEVICE_CLASS(klass);
 102
 103    dc->realize = port92_realizefn;
 104    dc->reset = port92_reset;
 105    dc->vmsd = &vmstate_port92_isa;
 106    /*
 107     * Reason: unlike ordinary ISA devices, this one needs additional
 108     * wiring: its A20 output line needs to be wired up with
 109     * qdev_connect_gpio_out_named().
 110     */
 111    dc->user_creatable = false;
 112}
 113
 114static const TypeInfo port92_info = {
 115    .name          = TYPE_PORT92,
 116    .parent        = TYPE_ISA_DEVICE,
 117    .instance_size = sizeof(Port92State),
 118    .instance_init = port92_initfn,
 119    .class_init    = port92_class_initfn,
 120};
 121
 122static void port92_register_types(void)
 123{
 124    type_register_static(&port92_info);
 125}
 126
 127type_init(port92_register_types)
 128