gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
i8042.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "dev/x86/i8042.hh"
30
31#include "base/bitunion.hh"
32#include "base/trace.hh"
33#include "debug/I8042.hh"
34#include "mem/packet.hh"
35#include "mem/packet_access.hh"
36
41
42namespace gem5
43{
44
45// The 8042 has a whopping 32 bytes of internal RAM.
46const uint8_t RamSize = 32;
47const uint8_t NumOutputBits = 14;
48
49
51 : PioDevice(p), latency(p.pio_latency),
52 dataPort(p.data_port), commandPort(p.command_port),
54{
55 fatal_if(!mouse, "The i8042 model requires a mouse instance");
56 fatal_if(!keyboard, "The i8042 model requires a keyboard instance");
57
58 statusReg.keyboardUnlocked = 1;
59
60 commandByte.convertScanCodes = 1;
61 commandByte.disableMouse = 1;
62 commandByte.disableKeyboard = 1;
63
64 for (int i = 0; i < p.port_keyboard_int_pin_connection_count; i++) {
66 csprintf("%s.keyboard_int_pin[%d]", name(), i), i, this));
67 }
68 for (int i = 0; i < p.port_mouse_int_pin_connection_count; i++) {
69 mouseIntPin.push_back(new IntSourcePin<I8042>(
70 csprintf("%s.mouse_int_pin[%d]", name(), i), i, this));
71 }
72}
73
74
77{
78 AddrRangeList ranges;
79 ranges.push_back(RangeSize(dataPort, 1));
80 ranges.push_back(RangeSize(commandPort, 1));
81 return ranges;
82}
83
84void
85X86ISA::I8042::writeData(uint8_t newData, bool mouse)
86{
87 DPRINTF(I8042, "Set data %#02x.\n", newData);
88 dataReg = newData;
89 statusReg.outputFull = 1;
90 statusReg.mouseOutputFull = (mouse ? 1 : 0);
91 if (!mouse && commandByte.keyboardFullInt) {
92 DPRINTF(I8042, "Sending keyboard interrupt.\n");
93 for (auto *wire: keyboardIntPin) {
94 wire->raise();
95 //This is a hack
96 wire->lower();
97 }
98 } else if (mouse && commandByte.mouseFullInt) {
99 DPRINTF(I8042, "Sending mouse interrupt.\n");
100 for (auto *wire: mouseIntPin) {
101 wire->raise();
102 //This is a hack
103 wire->lower();
104 }
105 }
106}
107
108uint8_t
110{
111 uint8_t data = dataReg;
112 statusReg.outputFull = 0;
113 statusReg.mouseOutputFull = 0;
114 if (keyboard->hostDataAvailable()) {
115 writeData(keyboard->hostRead(), false);
116 } else if (mouse->hostDataAvailable()) {
117 writeData(mouse->hostRead(), true);
118 }
119 return data;
120}
121
122Tick
124{
125 assert(pkt->getSize() == 1);
126 Addr addr = pkt->getAddr();
127 if (addr == dataPort) {
128 uint8_t data = readDataOut();
129 //DPRINTF(I8042, "Read from data port got %#02x.\n", data);
130 pkt->setLE<uint8_t>(data);
131 } else if (addr == commandPort) {
132 //DPRINTF(I8042, "Read status as %#02x.\n", (uint8_t)statusReg);
133 pkt->setLE<uint8_t>((uint8_t)statusReg);
134 } else {
135 panic("Read from unrecognized port %#x.\n", addr);
136 }
137 pkt->makeAtomicResponse();
138 return latency;
139}
140
141Tick
143{
144 assert(pkt->getSize() == 1);
145 Addr addr = pkt->getAddr();
146 uint8_t data = pkt->getLE<uint8_t>();
147 if (addr == dataPort) {
148 statusReg.commandLast = 0;
149 switch (lastCommand) {
150 case NoCommand:
151 keyboard->hostWrite(data);
152 if (keyboard->hostDataAvailable())
153 writeData(keyboard->hostRead(), false);
154 break;
155 case WriteToMouse:
156 mouse->hostWrite(data);
157 if (mouse->hostDataAvailable())
158 writeData(mouse->hostRead(), true);
159 break;
160 case WriteCommandByte:
162 DPRINTF(I8042, "Got data %#02x for \"Write "
163 "command byte\" command.\n", data);
164 statusReg.passedSelfTest = (uint8_t)commandByte.passedSelfTest;
165 break;
167 DPRINTF(I8042, "Got data %#02x for \"Write "
168 "mouse output buffer\" command.\n", data);
169 writeData(data, true);
170 break;
172 DPRINTF(I8042, "Got data %#02x for \"Write "
173 "keyboad output buffer\" command.\n", data);
174 writeData(data, false);
175 break;
176 case WriteOutputPort:
177 DPRINTF(I8042, "Got data %#02x for \"Write "
178 "output port\" command.\n", data);
179 panic_if(bits(data, 0) != 1, "Reset bit should be 1");
180 // Safe to ignore otherwise
181 break;
182 default:
183 panic("Data written for unrecognized "
184 "command %#02x\n", lastCommand);
185 }
187 } else if (addr == commandPort) {
188 DPRINTF(I8042, "Got command %#02x.\n", data);
189 statusReg.commandLast = 1;
190 // These purposefully leave off the first byte of the controller RAM
191 // so it can be handled specially.
194 panic("Attempted to use i8042 read controller RAM command to "
195 "get byte %d.\n", data - ReadControllerRamBase);
196 } else if (data > WriteControllerRamBase &&
198 panic("Attempted to use i8042 write controller RAM command to "
199 "get byte %d.\n", data - WriteControllerRamBase);
200 } else if (data >= PulseOutputBitBase &&
202 panic("Attempted to use i8042 pulse output bit command to "
203 "to pulse bit %d.\n", data - PulseOutputBitBase);
204 }
205 switch (data) {
206 case GetCommandByte:
207 DPRINTF(I8042, "Getting command byte.\n");
209 break;
210 case WriteCommandByte:
211 DPRINTF(I8042, "Setting command byte.\n");
213 break;
214 case CheckForPassword:
215 panic("i8042 \"Check for password\" command not implemented.\n");
216 case LoadPassword:
217 panic("i8042 \"Load password\" command not implemented.\n");
218 case CheckPassword:
219 panic("i8042 \"Check password\" command not implemented.\n");
220 case DisableMouse:
221 DPRINTF(I8042, "Disabling mouse at controller.\n");
222 commandByte.disableMouse = 1;
223 break;
224 case EnableMouse:
225 DPRINTF(I8042, "Enabling mouse at controller.\n");
226 commandByte.disableMouse = 0;
227 break;
228 case TestMouse:
229 // The response to this is from the 8042, not the mouse.
230 // Hard code no errors detected.
231 writeData(0x00);
232 break;
233 case SelfTest:
234 // Exactly what this does is essentially undocumented, but this:
235 // https://www.os2museum.com/wp/
236 // ibm-pcat-8042-keyboard-controller-commands/
237 // says that this should essentially reset some values.
238 commandByte.convertScanCodes = 1;
239 commandByte.disableMouse = 1;
240 commandByte.disableKeyboard = 1;
241 commandByte.passedSelfTest = 1;
242 statusReg.passedSelfTest = 1;
243 writeData(0x55); // Self test passed.
244 break;
245 case InterfaceTest:
246 // Hard code no errors detected.
247 writeData(0x00);
248 break;
249 case DiagnosticDump:
250 panic("i8042 \"Diagnostic dump\" command not implemented.\n");
251 case DisableKeyboard:
252 DPRINTF(I8042, "Disabling keyboard at controller.\n");
253 commandByte.disableKeyboard = 1;
254 break;
255 case EnableKeyboard:
256 DPRINTF(I8042, "Enabling keyboard at controller.\n");
257 commandByte.disableKeyboard = 0;
258 break;
259 case ReadInputPort:
260 panic("i8042 \"Read input port\" command not implemented.\n");
262 panic("i8042 \"Continuous poll low\" command not implemented.\n");
264 panic("i8042 \"Continuous poll high\" command not implemented.\n");
265 case ReadOutputPort:
266 panic("i8042 \"Read output port\" command not implemented.\n");
267 case WriteOutputPort:
269 break;
272 break;
274 DPRINTF(I8042, "Got command to write to mouse output buffer.\n");
276 break;
277 case WriteToMouse:
278 DPRINTF(I8042, "Expecting mouse command.\n");
280 break;
281 case DisableA20:
282 panic("i8042 \"Disable A20\" command not implemented.\n");
283 case EnableA20:
284 panic("i8042 \"Enable A20\" command not implemented.\n");
285 case ReadTestInputs:
286 panic("i8042 \"Read test inputs\" command not implemented.\n");
287 case SystemReset:
288 panic("i8042 \"System reset\" command not implemented.\n");
289 default:
290 warn("Write to unknown i8042 "
291 "(keyboard controller) command port.\n");
292 }
293 } else {
294 panic("Write to unrecognized port %#x.\n", addr);
295 }
296 pkt->makeAtomicResponse();
297 return latency;
298}
299
300void
310
311void
321
322} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
const char data[]
virtual std::string name() const
Definition named.hh:60
Addr getAddr() const
Definition packet.hh:807
void setLE(T v)
Set the value in the data pointer to v as little endian.
unsigned getSize() const
Definition packet.hh:817
void makeAtomicResponse()
Definition packet.hh:1074
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
PioDevice(const Params &p)
Definition io_device.cc:50
uint8_t readDataOut()
Definition i8042.cc:109
ps2::Device * mouse
Definition i8042.hh:116
void writeData(uint8_t newData, bool mouse=false)
Definition i8042.cc:85
uint16_t lastCommand
Definition i8042.hh:111
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition i8042.cc:312
ps2::Device * keyboard
Definition i8042.hh:117
static const uint16_t NoCommand
Definition i8042.hh:110
StatusReg statusReg
Definition i8042.hh:105
I8042(const Params &p)
Definition i8042.cc:50
std::vector< IntSourcePin< I8042 > * > keyboardIntPin
Definition i8042.hh:114
I8042Params Params
Definition i8042.hh:123
std::vector< IntSourcePin< I8042 > * > mouseIntPin
Definition i8042.hh:113
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition i8042.cc:142
CommandByte commandByte
Definition i8042.hh:106
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition i8042.cc:301
AddrRangeList getAddrRanges() const override
Every PIO device is obliged to provide an implementation that returns the address ranges the device r...
Definition i8042.cc:76
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition i8042.cc:123
AddrRange RangeSize(Addr start, Addr size)
std::list< AddrRange > AddrRangeList
Convenience typedef for a collection of address ranges.
Definition addr_range.hh:64
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:268
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:246
#define warn(...)
Definition logging.hh:288
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 3 > addr
Definition types.hh:84
Bitfield< 0 > p
Definition pagetable.hh:151
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
IntSourcePinBase IntSourcePin
Definition intpin.hh:102
const uint8_t NumOutputBits
Definition i8042.cc:47
std::ostream CheckpointOut
Definition serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
const uint8_t RamSize
Definition i8042.cc:46
uint64_t Tick
Tick count type.
Definition types.hh:58
Packet * PacketPtr
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
Declaration of the Packet class.
#define UNSERIALIZE_SCALAR(scalar)
Definition serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition serialize.hh:568

Generated on Mon May 26 2025 09:19:10 for gem5 by doxygen 1.13.2