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 17 OBJECT_DECLARE_SIMPLE_TYPE(Port92State, PORT92) 18 19 struct Port92State { 20 ISADevice parent_obj; 21 22 MemoryRegion io; 23 uint8_t outport; 24 qemu_irq a20_out; 25 }; 26 27 static 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 41 static 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 53 static 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 63 static void port92_reset(DeviceState *d) 64 { 65 Port92State *s = PORT92(d); 66 67 s->outport &= ~1; 68 } 69 70 static 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 80 static 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 91 static 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 99 static 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 114 static 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 122 static void port92_register_types(void) 123 { 124 type_register_static(&port92_info); 125 } 126 127 type_init(port92_register_types) 128