]>
Commit | Line | Data |
---|---|---|
d3e07dc8 PMD |
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" | |
db1015e9 | 15 | #include "qom/object.h" |
d3e07dc8 | 16 | |
8063396b | 17 | OBJECT_DECLARE_SIMPLE_TYPE(Port92State, PORT92) |
d3e07dc8 | 18 | |
db1015e9 | 19 | struct Port92State { |
d3e07dc8 PMD |
20 | ISADevice parent_obj; |
21 | ||
22 | MemoryRegion io; | |
23 | uint8_t outport; | |
24 | qemu_irq a20_out; | |
db1015e9 | 25 | }; |
d3e07dc8 PMD |
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) |