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