port92.c (2880B)
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)