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