gem5  v21.1.0.2
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 
42 namespace gem5
43 {
44 
45 // The 8042 has a whopping 32 bytes of internal RAM.
46 const uint8_t RamSize = 32;
47 const uint8_t NumOutputBits = 14;
48 
49 
51  : BasicPioDevice(p, 0), // pioSize arg is dummy value... not used
52  latency(p.pio_latency),
53  dataPort(p.data_port), commandPort(p.command_port),
54  statusReg(0), commandByte(0), dataReg(0), lastCommand(NoCommand),
55  mouse(p.mouse), keyboard(p.keyboard)
56 {
57  fatal_if(!mouse, "The i8042 model requires a mouse instance");
58  fatal_if(!keyboard, "The i8042 model requires a keyboard instance");
59 
60  statusReg.passedSelfTest = 1;
61  statusReg.commandLast = 1;
62  statusReg.keyboardUnlocked = 1;
63 
64  commandByte.convertScanCodes = 1;
65  commandByte.passedSelfTest = 1;
66  commandByte.keyboardFullInt = 1;
67 
68  for (int i = 0; i < p.port_keyboard_int_pin_connection_count; i++) {
69  keyboardIntPin.push_back(new IntSourcePin<I8042>(
70  csprintf("%s.keyboard_int_pin[%d]", name(), i), i, this));
71  }
72  for (int i = 0; i < p.port_mouse_int_pin_connection_count; i++) {
73  mouseIntPin.push_back(new IntSourcePin<I8042>(
74  csprintf("%s.mouse_int_pin[%d]", name(), i), i, this));
75  }
76 }
77 
78 
81 {
82  AddrRangeList ranges;
83  // TODO: Are these really supposed to be a single byte and not 4?
84  ranges.push_back(RangeSize(dataPort, 1));
85  ranges.push_back(RangeSize(commandPort, 1));
86  return ranges;
87 }
88 
89 void
90 X86ISA::I8042::writeData(uint8_t newData, bool mouse)
91 {
92  DPRINTF(I8042, "Set data %#02x.\n", newData);
93  dataReg = newData;
94  statusReg.outputFull = 1;
95  statusReg.mouseOutputFull = (mouse ? 1 : 0);
96  if (!mouse && commandByte.keyboardFullInt) {
97  DPRINTF(I8042, "Sending keyboard interrupt.\n");
98  for (auto *wire: keyboardIntPin) {
99  wire->raise();
100  //This is a hack
101  wire->lower();
102  }
103  } else if (mouse && commandByte.mouseFullInt) {
104  DPRINTF(I8042, "Sending mouse interrupt.\n");
105  for (auto *wire: mouseIntPin) {
106  wire->raise();
107  //This is a hack
108  wire->lower();
109  }
110  }
111 }
112 
113 uint8_t
115 {
116  uint8_t data = dataReg;
117  statusReg.outputFull = 0;
118  statusReg.mouseOutputFull = 0;
119  if (keyboard->hostDataAvailable()) {
120  writeData(keyboard->hostRead(), false);
121  } else if (mouse->hostDataAvailable()) {
122  writeData(mouse->hostRead(), true);
123  }
124  return data;
125 }
126 
127 Tick
129 {
130  assert(pkt->getSize() == 1);
131  Addr addr = pkt->getAddr();
132  if (addr == dataPort) {
133  uint8_t data = readDataOut();
134  //DPRINTF(I8042, "Read from data port got %#02x.\n", data);
135  pkt->setLE<uint8_t>(data);
136  } else if (addr == commandPort) {
137  //DPRINTF(I8042, "Read status as %#02x.\n", (uint8_t)statusReg);
138  pkt->setLE<uint8_t>((uint8_t)statusReg);
139  } else {
140  panic("Read from unrecognized port %#x.\n", addr);
141  }
142  pkt->makeAtomicResponse();
143  return latency;
144 }
145 
146 Tick
148 {
149  assert(pkt->getSize() == 1);
150  Addr addr = pkt->getAddr();
151  uint8_t data = pkt->getLE<uint8_t>();
152  if (addr == dataPort) {
153  statusReg.commandLast = 0;
154  switch (lastCommand) {
155  case NoCommand:
156  keyboard->hostWrite(data);
157  if (keyboard->hostDataAvailable())
158  writeData(keyboard->hostRead(), false);
159  break;
160  case WriteToMouse:
161  mouse->hostWrite(data);
162  if (mouse->hostDataAvailable())
163  writeData(mouse->hostRead(), true);
164  break;
165  case WriteCommandByte:
166  commandByte = data;
167  DPRINTF(I8042, "Got data %#02x for \"Write "
168  "command byte\" command.\n", data);
169  statusReg.passedSelfTest = (uint8_t)commandByte.passedSelfTest;
170  break;
171  case WriteMouseOutputBuff:
172  DPRINTF(I8042, "Got data %#02x for \"Write "
173  "mouse output buffer\" command.\n", data);
174  writeData(data, true);
175  break;
176  case WriteKeyboardOutputBuff:
177  DPRINTF(I8042, "Got data %#02x for \"Write "
178  "keyboad output buffer\" command.\n", data);
179  writeData(data, false);
180  break;
181  case WriteOutputPort:
182  DPRINTF(I8042, "Got data %#02x for \"Write "
183  "output port\" command.\n", data);
184  panic_if(bits(data, 0) != 1, "Reset bit should be 1");
185  // Safe to ignore otherwise
186  break;
187  default:
188  panic("Data written for unrecognized "
189  "command %#02x\n", lastCommand);
190  }
191  lastCommand = NoCommand;
192  } else if (addr == commandPort) {
193  DPRINTF(I8042, "Got command %#02x.\n", data);
194  statusReg.commandLast = 1;
195  // These purposefully leave off the first byte of the controller RAM
196  // so it can be handled specially.
197  if (data > ReadControllerRamBase &&
198  data < ReadControllerRamBase + RamSize) {
199  panic("Attempted to use i8042 read controller RAM command to "
200  "get byte %d.\n", data - ReadControllerRamBase);
201  } else if (data > WriteControllerRamBase &&
202  data < WriteControllerRamBase + RamSize) {
203  panic("Attempted to use i8042 read controller RAM command to "
204  "get byte %d.\n", data - ReadControllerRamBase);
205  } else if (data >= PulseOutputBitBase &&
206  data < PulseOutputBitBase + NumOutputBits) {
207  panic("Attempted to use i8042 pulse output bit command to "
208  "to pulse bit %d.\n", data - PulseOutputBitBase);
209  }
210  switch (data) {
211  case GetCommandByte:
212  DPRINTF(I8042, "Getting command byte.\n");
213  writeData(commandByte);
214  break;
215  case WriteCommandByte:
216  DPRINTF(I8042, "Setting command byte.\n");
217  lastCommand = WriteCommandByte;
218  break;
219  case CheckForPassword:
220  panic("i8042 \"Check for password\" command not implemented.\n");
221  case LoadPassword:
222  panic("i8042 \"Load password\" command not implemented.\n");
223  case CheckPassword:
224  panic("i8042 \"Check password\" command not implemented.\n");
225  case DisableMouse:
226  DPRINTF(I8042, "Disabling mouse at controller.\n");
227  commandByte.disableMouse = 1;
228  break;
229  case EnableMouse:
230  DPRINTF(I8042, "Enabling mouse at controller.\n");
231  commandByte.disableMouse = 0;
232  break;
233  case TestMouse:
234  panic("i8042 \"Test mouse\" command not implemented.\n");
235  case SelfTest:
236  panic("i8042 \"Self test\" command not implemented.\n");
237  case InterfaceTest:
238  panic("i8042 \"Interface test\" command not implemented.\n");
239  case DiagnosticDump:
240  panic("i8042 \"Diagnostic dump\" command not implemented.\n");
241  case DisableKeyboard:
242  DPRINTF(I8042, "Disabling keyboard at controller.\n");
243  commandByte.disableKeyboard = 1;
244  break;
245  case EnableKeyboard:
246  DPRINTF(I8042, "Enabling keyboard at controller.\n");
247  commandByte.disableKeyboard = 0;
248  break;
249  case ReadInputPort:
250  panic("i8042 \"Read input port\" command not implemented.\n");
251  case ContinuousPollLow:
252  panic("i8042 \"Continuous poll low\" command not implemented.\n");
253  case ContinuousPollHigh:
254  panic("i8042 \"Continuous poll high\" command not implemented.\n");
255  case ReadOutputPort:
256  panic("i8042 \"Read output port\" command not implemented.\n");
257  case WriteOutputPort:
258  lastCommand = WriteOutputPort;
259  break;
260  case WriteKeyboardOutputBuff:
261  lastCommand = WriteKeyboardOutputBuff;
262  break;
263  case WriteMouseOutputBuff:
264  DPRINTF(I8042, "Got command to write to mouse output buffer.\n");
265  lastCommand = WriteMouseOutputBuff;
266  break;
267  case WriteToMouse:
268  DPRINTF(I8042, "Expecting mouse command.\n");
269  lastCommand = WriteToMouse;
270  break;
271  case DisableA20:
272  panic("i8042 \"Disable A20\" command not implemented.\n");
273  case EnableA20:
274  panic("i8042 \"Enable A20\" command not implemented.\n");
275  case ReadTestInputs:
276  panic("i8042 \"Read test inputs\" command not implemented.\n");
277  case SystemReset:
278  panic("i8042 \"System reset\" command not implemented.\n");
279  default:
280  warn("Write to unknown i8042 "
281  "(keyboard controller) command port.\n");
282  }
283  } else {
284  panic("Write to unrecognized port %#x.\n", addr);
285  }
286  pkt->makeAtomicResponse();
287  return latency;
288 }
289 
290 void
292 {
293  SERIALIZE_SCALAR(dataPort);
294  SERIALIZE_SCALAR(commandPort);
295  SERIALIZE_SCALAR(statusReg);
296  SERIALIZE_SCALAR(commandByte);
297  SERIALIZE_SCALAR(dataReg);
298  SERIALIZE_SCALAR(lastCommand);
299 }
300 
301 void
303 {
304  UNSERIALIZE_SCALAR(dataPort);
305  UNSERIALIZE_SCALAR(commandPort);
306  UNSERIALIZE_SCALAR(statusReg);
307  UNSERIALIZE_SCALAR(commandByte);
308  UNSERIALIZE_SCALAR(dataReg);
309  UNSERIALIZE_SCALAR(lastCommand);
310 }
311 
312 } // namespace gem5
warn
#define warn(...)
Definition: logging.hh:245
gem5::NumOutputBits
const uint8_t NumOutputBits
Definition: i8042.cc:47
data
const char data[]
Definition: circlebuf.test.cc:48
UNSERIALIZE_SCALAR
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:575
gem5::X86ISA::I8042::writeData
void writeData(uint8_t newData, bool mouse=false)
Definition: i8042.cc:90
gem5::RangeSize
AddrRange RangeSize(Addr start, Addr size)
Definition: addr_range.hh:661
gem5::CheckpointIn
Definition: serialize.hh:68
gem5::X86ISA::I8042::mouse
ps2::Device * mouse
Definition: i8042.hh:116
gem5::csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
gem5::Packet::makeAtomicResponse
void makeAtomicResponse()
Definition: packet.hh:1043
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:66
gem5::X86ISA::I8042::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: i8042.cc:291
gem5::X86ISA::I8042::write
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: i8042.cc:147
gem5::X86ISA::I8042::keyboard
ps2::Device * keyboard
Definition: i8042.hh:117
i8042.hh
packet.hh
gem5::PioDevice::Params
PioDeviceParams Params
Definition: io_device.hh:134
gem5::Named::name
virtual std::string name() const
Definition: named.hh:47
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:186
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:283
gem5::MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:326
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
bitunion.hh
gem5::X86ISA::I8042::I8042
I8042(const Params &p)
Definition: i8042.cc:50
gem5::bits
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:76
gem5::X86ISA::I8042::readDataOut
uint8_t readDataOut()
Definition: i8042.cc:114
gem5::X86ISA::I8042::commandByte
CommandByte commandByte
Definition: i8042.hh:106
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::X86ISA::I8042::keyboardIntPin
std::vector< IntSourcePin< I8042 > * > keyboardIntPin
Definition: i8042.hh:114
SERIALIZE_SCALAR
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:568
gem5::X86ISA::I8042::getAddrRanges
AddrRangeList getAddrRanges() const override
Determine the address ranges that this device responds to.
Definition: i8042.cc:80
packet_access.hh
panic_if
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:203
gem5::X86ISA::I8042::read
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: i8042.cc:128
gem5::X86ISA::I8042::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: i8042.cc:302
gem5::X86ISA::I8042::mouseIntPin
std::vector< IntSourcePin< I8042 > * > mouseIntPin
Definition: i8042.hh:113
gem5::Packet::getLE
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Definition: packet_access.hh:78
gem5::X86ISA::p
Bitfield< 0 > p
Definition: pagetable.hh:151
gem5::CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:66
trace.hh
gem5::IntSourcePin
Definition: intpin.hh:112
gem5::Packet::setLE
void setLE(T v)
Set the value in the data pointer to v as little endian.
Definition: packet_access.hh:108
gem5::X86ISA::I8042
Definition: i8042.hh:46
std::list< AddrRange >
gem5::Packet::getAddr
Addr getAddr() const
Definition: packet.hh:781
fatal_if
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:225
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: decoder.cc:40
gem5::BasicPioDevice
Definition: io_device.hh:147
gem5::X86ISA::I8042::statusReg
StatusReg statusReg
Definition: i8042.hh:105
gem5::Packet::getSize
unsigned getSize() const
Definition: packet.hh:791
gem5::RamSize
const uint8_t RamSize
Definition: i8042.cc:46
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:177
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84

Generated on Tue Sep 21 2021 12:25:23 for gem5 by doxygen 1.8.17