summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-01-31 23:59:01 -0800
committerGabe Black <gblack@eecs.umich.edu>2009-01-31 23:59:01 -0800
commit7cf276bed34c2ed1f8f86bbf46497aab3f8ebc6c (patch)
treedb3e3f8f53e93f7ea60e68236e09484bf756104f
parent0287f19edecd317a139d2ff809901b9c91eb0c2e (diff)
downloadgem5-7cf276bed34c2ed1f8f86bbf46497aab3f8ebc6c.tar.xz
X86: Add a keyboard controller device.
-rw-r--r--src/dev/x86/I8042.py43
-rw-r--r--src/dev/x86/SConscript4
-rw-r--r--src/dev/x86/SouthBridge.py13
-rw-r--r--src/dev/x86/i8042.cc529
-rw-r--r--src/dev/x86/i8042.hh142
5 files changed, 731 insertions, 0 deletions
diff --git a/src/dev/x86/I8042.py b/src/dev/x86/I8042.py
new file mode 100644
index 000000000..1f6a48410
--- /dev/null
+++ b/src/dev/x86/I8042.py
@@ -0,0 +1,43 @@
+# Copyright (c) 2008 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Gabe Black
+
+from m5.params import *
+from m5.proxy import *
+from Device import BasicPioDevice
+from X86IntPin import X86IntSourcePin
+
+class I8042(BasicPioDevice):
+ type = 'I8042'
+ cxx_class = 'X86ISA::I8042'
+ pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks")
+ data_port = Param.Addr('Data port address')
+ command_port = Param.Addr('Command/status port address')
+ mouse_int_pin = Param.X86IntSourcePin(X86IntSourcePin(),
+ 'Pin to signal the mouse has data')
+ keyboard_int_pin = Param.X86IntSourcePin(X86IntSourcePin(),
+ 'Pin to signal the keyboard has data')
diff --git a/src/dev/x86/SConscript b/src/dev/x86/SConscript
index 167b14a84..e7543dfdf 100644
--- a/src/dev/x86/SConscript
+++ b/src/dev/x86/SConscript
@@ -53,6 +53,10 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'x86':
Source('i8237.cc')
TraceFlag('I8237', 'The I8237 dma controller');
+ SimObject('I8042.py')
+ Source('i8042.cc')
+ TraceFlag('I8042', 'The I8042 keyboard controller');
+
SimObject('PcSpeaker.py')
Source('speaker.cc')
TraceFlag('PcSpeaker')
diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py
index ba9aaf2b4..a3db83610 100644
--- a/src/dev/x86/SouthBridge.py
+++ b/src/dev/x86/SouthBridge.py
@@ -29,6 +29,7 @@
from m5.params import *
from m5.proxy import *
from Cmos import Cmos
+from I8042 import I8042
from I82094AA import I82094AA
from I8237 import I8237
from I8254 import I8254
@@ -50,6 +51,8 @@ class SouthBridge(SimObject):
_pic2 = I8259(pio_addr=x86IOAddress(0xA0), mode='I8259Slave')
_cmos = Cmos(pio_addr=x86IOAddress(0x70))
_dma1 = I8237(pio_addr=x86IOAddress(0x0))
+ _keyboard = I8042(data_port=x86IOAddress(0x60), \
+ command_port=x86IOAddress(0x64))
_pit = I8254(pio_addr=x86IOAddress(0x40))
_speaker = PcSpeaker(pio_addr=x86IOAddress(0x61))
_io_apic = I82094AA(pio_addr=0xFEC00000)
@@ -61,6 +64,7 @@ class SouthBridge(SimObject):
pic2 = Param.I8259(_pic2, "Slave PIC")
cmos = Param.Cmos(_cmos, "CMOS memory and real time clock device")
dma1 = Param.I8237(_dma1, "The first dma controller")
+ keyboard = Param.I8042(_keyboard, "The keyboard controller")
pit = Param.I8254(_pit, "Programmable interval timer")
speaker = Param.PcSpeaker(_speaker, "PC speaker")
io_apic = Param.I82094AA(_io_apic, "I/O APIC")
@@ -75,6 +79,14 @@ class SouthBridge(SimObject):
self.connectPins(self.cmos.int_pin, self.pic2.pin(0))
self.connectPins(self.pit.int_pin, self.pic1.pin(0))
self.connectPins(self.pit.int_pin, self.io_apic.pin(2))
+# self.connectPins(self.keyboard.keyboard_int_pin,
+# self.pic1.pin(1))
+ self.connectPins(self.keyboard.keyboard_int_pin,
+ self.io_apic.pin(1))
+# self.connectPins(self.keyboard.mouse_int_pin,
+# self.pic2.pin(4))
+ self.connectPins(self.keyboard.mouse_int_pin,
+ self.io_apic.pin(12))
# Tell the devices about each other
self.pic1.slave = self.pic2
self.speaker.i8254 = self.pit
@@ -82,6 +94,7 @@ class SouthBridge(SimObject):
# Connect to the bus
self.cmos.pio = bus.port
self.dma1.pio = bus.port
+ self.keyboard.pio = bus.port
self.pic1.pio = bus.port
self.pic2.pio = bus.port
self.pit.pio = bus.port
diff --git a/src/dev/x86/i8042.cc b/src/dev/x86/i8042.cc
new file mode 100644
index 000000000..7dff49823
--- /dev/null
+++ b/src/dev/x86/i8042.cc
@@ -0,0 +1,529 @@
+/*
+ * Copyright (c) 2008 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include "base/bitunion.hh"
+#include "dev/x86/i8042.hh"
+#include "mem/packet.hh"
+#include "mem/packet_access.hh"
+
+// The 8042 has a whopping 32 bytes of internal RAM.
+const uint8_t RamSize = 32;
+const uint8_t NumOutputBits = 14;
+const uint8_t KeyboardID[] = {0xab, 0x83};
+const uint8_t MouseID[] = {0x00};
+const uint8_t CommandAck = 0xfa;
+const uint8_t CommandNack = 0xfe;
+const uint8_t BatSuccessful = 0xaa;
+
+enum Port64Command
+{
+ GetCommandByte = 0x20,
+ ReadControllerRamBase = 0x20,
+ WriteCommandByte = 0x60,
+ WriteControllerRamBase = 0x60,
+ CheckForPassword = 0xA4,
+ LoadPassword = 0xA5,
+ CheckPassword = 0xA6,
+ DisableMouse = 0xA7,
+ EnableMouse = 0xA8,
+ TestMouse = 0xA9,
+ SelfTest = 0xAA,
+ InterfaceTest = 0xAB,
+ DiagnosticDump = 0xAC,
+ DisableKeyboard = 0xAD,
+ EnableKeyboard = 0xAE,
+ ReadInputPort = 0xC0,
+ ContinuousPollLow = 0xC1,
+ ContinuousPollHigh = 0xC2,
+ ReadOutputPort = 0xD0,
+ WriteOutputPort = 0xD1,
+ WriteKeyboardOutputBuff = 0xD2,
+ WriteMouseOutputBuff = 0xD3,
+ WriteToMouse = 0xD4,
+ DisableA20 = 0xDD,
+ EnableA20 = 0xDF,
+ ReadTestInputs = 0xE0,
+ PulseOutputBitBase = 0xF0,
+ SystemReset = 0xFE
+};
+
+enum Port60Command
+{
+ MouseScale1to1 = 0xE6,
+ MouseScale2to1 = 0xE7,
+ SetMouseResolution = 0xE8,
+ MouseGetStatus = 0xE9,
+ MouseReadData = 0xEB,
+ MouseResetWrapMode = 0xEC,
+ LEDWrite = 0xED,
+ DiagnosticEcho = 0xEE,
+ MouseWrapMode = 0xEE,
+ AlternateScanCodes = 0xF0,
+ MouseRemoteMode = 0xF0,
+ ReadKeyboardID = 0xF2,
+ ReadMouseID = 0xF2,
+ TypematicInfo = 0xF3,
+ MouseSampleRate = 0xF3,
+ KeyboardEnable = 0xF4,
+ MouseEnableReporting = 0xF4,
+ KeyboardDisable = 0xF5,
+ MouseDisableReporting = 0xF5,
+ DefaultsAndDisableKeyboard = 0xF6,
+ DefaultsAndDisableMouse = 0xF6,
+ AllKeysToTypematic = 0xF7,
+ AllKeysToMakeRelease = 0xF8,
+ AllKeysToMake = 0xF9,
+ AllKeysToTypematicMakeRelease = 0xFA,
+ KeyToTypematic = 0xFB,
+ KeyToMakeRelease = 0xFC,
+ KeyToMakeOnly = 0xFD,
+ Resend = 0xFE,
+ KeyboardReset = 0xFF,
+ MouseReset = 0xFF
+};
+
+void
+X86ISA::I8042::addressRanges(AddrRangeList &range_list)
+{
+ range_list.clear();
+ range_list.push_back(RangeSize(dataPort, 1));
+ range_list.push_back(RangeSize(commandPort, 1));
+}
+
+bool
+X86ISA::I8042::writeData(uint8_t newData, bool mouse)
+{
+ if (!statusReg.outputFull) {
+ DPRINTF(I8042, "Set data %#02x.\n", newData);
+ dataReg = newData;
+ statusReg.outputFull = 1;
+ statusReg.mouseOutputFull = (mouse ? 1 : 0);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void
+X86ISA::I8042::keyboardAck()
+{
+ while (!keyboardBuffer.empty())
+ keyboardBuffer.pop();
+ writeKeyboardData(&CommandAck, sizeof(CommandAck));
+}
+
+void
+X86ISA::I8042::writeKeyboardData(const uint8_t *data, int size)
+{
+ assert(data || size == 0);
+ while (size) {
+ keyboardBuffer.push(*(data++));
+ size--;
+ }
+ if (writeData(keyboardBuffer.front())) {
+ keyboardBuffer.pop();
+ if (commandByte.keyboardFullInt) {
+ DPRINTF(I8042, "Sending keyboard interrupt.\n");
+ keyboardIntPin->raise();
+ //XXX This is a hack.
+ keyboardIntPin->lower();
+ }
+ }
+}
+
+void
+X86ISA::I8042::mouseAck()
+{
+ while (!mouseBuffer.empty())
+ mouseBuffer.pop();
+ writeMouseData(&CommandAck, sizeof(CommandAck));
+}
+
+void
+X86ISA::I8042::mouseNack()
+{
+ while (!mouseBuffer.empty())
+ mouseBuffer.pop();
+ writeMouseData(&CommandNack, sizeof(CommandAck));
+}
+
+void
+X86ISA::I8042::writeMouseData(const uint8_t *data, int size)
+{
+ assert(data || size == 0);
+ while (size) {
+ mouseBuffer.push(*(data++));
+ size--;
+ }
+ if (writeData(mouseBuffer.front(), true)) {
+ mouseBuffer.pop();
+ if (commandByte.mouseFullInt) {
+ DPRINTF(I8042, "Sending mouse interrupt.\n");
+ mouseIntPin->raise();
+ //XXX This is a hack
+ mouseIntPin->lower();
+ }
+ }
+}
+
+uint8_t
+X86ISA::I8042::readDataOut()
+{
+ uint8_t data = dataReg;
+ statusReg.outputFull = 0;
+ statusReg.mouseOutputFull = 0;
+ if (!keyboardBuffer.empty()) {
+ writeKeyboardData(NULL, 0);
+ }
+ if (!mouseBuffer.empty()) {
+ writeMouseData(NULL, 0);
+ }
+ return data;
+}
+
+Tick
+X86ISA::I8042::read(PacketPtr pkt)
+{
+ assert(pkt->getSize() == 1);
+ Addr addr = pkt->getAddr();
+ if (addr == dataPort) {
+ uint8_t data = readDataOut();
+ //DPRINTF(I8042, "Read from data port got %#02x.\n", data);
+ pkt->set<uint8_t>(data);
+ } else if (addr == commandPort) {
+ //DPRINTF(I8042, "Read status as %#02x.\n", (uint8_t)statusReg);
+ pkt->set<uint8_t>((uint8_t)statusReg);
+ } else {
+ panic("Read from unrecognized port %#x.\n", addr);
+ }
+ return latency;
+}
+
+Tick
+X86ISA::I8042::write(PacketPtr pkt)
+{
+ assert(pkt->getSize() == 1);
+ Addr addr = pkt->getAddr();
+ uint8_t data = pkt->get<uint8_t>();
+ if (addr == dataPort) {
+ statusReg.commandLast = 0;
+ switch (lastCommand) {
+ case NoCommand:
+ if (lastKeyboardCommand != NoCommand) {
+ switch (lastKeyboardCommand) {
+ case LEDWrite:
+ DPRINTF(I8042, "Setting LEDs: "
+ "caps lock %s, num lock %s, scroll lock %s\n",
+ bits(data, 2) ? "on" : "off",
+ bits(data, 1) ? "on" : "off",
+ bits(data, 0) ? "on" : "off");
+ keyboardAck();
+ lastKeyboardCommand = NoCommand;
+ break;
+ case TypematicInfo:
+ DPRINTF(I8042,
+ "Setting typematic info to %#02x.\n", data);
+ keyboardAck();
+ lastKeyboardCommand = NoCommand;
+ break;
+ }
+ break;
+ }
+ DPRINTF(I8042, "Got port 0x60 command %#02x.\n", data);
+ switch (data) {
+ case LEDWrite:
+ DPRINTF(I8042, "Got LED write command.\n");
+ keyboardAck();
+ lastKeyboardCommand = LEDWrite;
+ break;
+ case DiagnosticEcho:
+ panic("Keyboard diagnostic echo unimplemented.\n");
+ case AlternateScanCodes:
+ panic("Accessing alternate scan codes unimplemented.\n");
+ case ReadKeyboardID:
+ DPRINTF(I8042, "Got keyboard read ID command.\n");
+ keyboardAck();
+ writeKeyboardData((uint8_t *)&KeyboardID, sizeof(KeyboardID));
+ break;
+ case TypematicInfo:
+ DPRINTF(I8042, "Setting typematic info.\n");
+ keyboardAck();
+ lastKeyboardCommand = TypematicInfo;
+ break;
+ case KeyboardEnable:
+ DPRINTF(I8042, "Enabling the keyboard.\n");
+ keyboardAck();
+ break;
+ case KeyboardDisable:
+ DPRINTF(I8042, "Disabling the keyboard.\n");
+ keyboardAck();
+ break;
+ case DefaultsAndDisableKeyboard:
+ DPRINTF(I8042, "Disabling and resetting the keyboard.\n");
+ keyboardAck();
+ break;
+ case AllKeysToTypematic:
+ panic("Setting all keys to typemantic unimplemented.\n");
+ case AllKeysToMakeRelease:
+ panic("Setting all keys to make/release unimplemented.\n");
+ case AllKeysToMake:
+ panic("Setting all keys to make unimplemented.\n");
+ case AllKeysToTypematicMakeRelease:
+ panic("Setting all keys to "
+ "typematic/make/release unimplemented.\n");
+ case KeyToTypematic:
+ panic("Setting a key to typematic unimplemented.\n");
+ case KeyToMakeRelease:
+ panic("Setting a key to make/release unimplemented.\n");
+ case KeyToMakeOnly:
+ panic("Setting key to make only unimplemented.\n");
+ case Resend:
+ panic("Keyboard resend unimplemented.\n");
+ case KeyboardReset:
+ panic("Keyboard reset unimplemented.\n");
+ default:
+ panic("Unknown keyboard command %#02x.\n", data);
+ }
+ break;
+ case WriteToMouse:
+ if (lastMouseCommand != NoCommand) {
+ switch(lastMouseCommand) {
+ case SetMouseResolution:
+ DPRINTF(I8042, "Mouse resolution set to %d.\n", data);
+ mouseResolution = data;
+ mouseAck();
+ lastMouseCommand = NoCommand;
+ break;
+ case MouseSampleRate:
+ DPRINTF(I8042, "Mouse sample rate %d samples "
+ "per second.\n", data);
+ mouseSampleRate = data;
+ mouseAck();
+ lastMouseCommand = NoCommand;
+ break;
+ default:
+ panic("Not expecting data for a mouse command.\n");
+ }
+ break;
+ }
+ switch (data) {
+ case MouseScale1to1:
+ DPRINTF(I8042, "Setting mouse scale to 1:1.\n");
+ mouseStatus.twoToOne = 0;
+ mouseAck();
+ break;
+ case MouseScale2to1:
+ DPRINTF(I8042, "Setting mouse scale to 2:1.\n");
+ mouseStatus.twoToOne = 1;
+ mouseAck();
+ break;
+ case SetMouseResolution:
+ DPRINTF(I8042, "Setting mouse resolution.\n");
+ lastMouseCommand = SetMouseResolution;
+ mouseAck();
+ break;
+ case MouseGetStatus:
+ DPRINTF(I8042, "Getting mouse status.\n");
+ mouseAck();
+ writeMouseData((uint8_t *)&(mouseStatus), 1);
+ writeMouseData(&mouseResolution, sizeof(mouseResolution));
+ writeMouseData(&mouseSampleRate, sizeof(mouseSampleRate));
+ break;
+ case MouseReadData:
+ panic("Reading mouse data unimplemented.\n");
+ case MouseResetWrapMode:
+ panic("Resetting mouse wrap mode unimplemented.\n");
+ case MouseWrapMode:
+ panic("Setting mouse wrap mode unimplemented.\n");
+ case MouseRemoteMode:
+ panic("Setting mouse remote mode unimplemented.\n");
+ case ReadMouseID:
+ DPRINTF(I8042, "Mouse ID requested.\n");
+ mouseAck();
+ writeMouseData(MouseID, sizeof(MouseID));
+ break;
+ case MouseSampleRate:
+ DPRINTF(I8042, "Setting mouse sample rate.\n");
+ lastMouseCommand = MouseSampleRate;
+ mouseAck();
+ break;
+ case MouseDisableReporting:
+ DPRINTF(I8042, "Disabling data reporting.\n");
+ mouseStatus.enabled = 0;
+ mouseAck();
+ break;
+ case MouseEnableReporting:
+ DPRINTF(I8042, "Enabling data reporting.\n");
+ mouseStatus.enabled = 1;
+ mouseAck();
+ break;
+ case DefaultsAndDisableMouse:
+ DPRINTF(I8042, "Disabling and resetting mouse.\n");
+ mouseSampleRate = 100;
+ mouseResolution = 4;
+ mouseStatus.twoToOne = 0;
+ mouseStatus.enabled = 0;
+ mouseAck();
+ break;
+ case Resend:
+ panic("Keyboard resent unimplemented.\n");
+ case MouseReset:
+ DPRINTF(I8042, "Resetting the mouse.\n");
+ mouseSampleRate = 100;
+ mouseResolution = 4;
+ mouseStatus.twoToOne = 0;
+ mouseStatus.enabled = 0;
+ mouseAck();
+ writeMouseData(&BatSuccessful, sizeof(BatSuccessful));
+ writeMouseData(MouseID, sizeof(MouseID));
+ break;
+ default:
+ warn("Unknown mouse command %#02x.\n", data);
+ mouseNack();
+ break;
+ }
+ break;
+ case WriteCommandByte:
+ commandByte = data;
+ DPRINTF(I8042, "Got data %#02x for \"Write "
+ "command byte\" command.\n", data);
+ statusReg.passedSelfTest = (uint8_t)commandByte.passedSelfTest;
+ break;
+ case WriteMouseOutputBuff:
+ DPRINTF(I8042, "Got data %#02x for \"Write "
+ "mouse output buffer\" command.\n", data);
+ writeMouseData(&data, sizeof(data));
+ break;
+ default:
+ panic("Data written for unrecognized "
+ "command %#02x\n", lastCommand);
+ }
+ lastCommand = NoCommand;
+ } else if (addr == commandPort) {
+ DPRINTF(I8042, "Got command %#02x.\n", data);
+ statusReg.commandLast = 1;
+ // These purposefully leave off the first byte of the controller RAM
+ // so it can be handled specially.
+ if (data > ReadControllerRamBase &&
+ data < ReadControllerRamBase + RamSize) {
+ panic("Attempted to use i8042 read controller RAM command to "
+ "get byte %d.\n", data - ReadControllerRamBase);
+ } else if (data > WriteControllerRamBase &&
+ data < WriteControllerRamBase + RamSize) {
+ panic("Attempted to use i8042 read controller RAM command to "
+ "get byte %d.\n", data - ReadControllerRamBase);
+ } else if (data >= PulseOutputBitBase &&
+ data < PulseOutputBitBase + NumOutputBits) {
+ panic("Attempted to use i8042 pulse output bit command to "
+ "to pulse bit %d.\n", data - PulseOutputBitBase);
+ }
+ switch (data) {
+ case GetCommandByte:
+ DPRINTF(I8042, "Getting command byte.\n");
+ writeData(commandByte);
+ break;
+ case WriteCommandByte:
+ DPRINTF(I8042, "Setting command byte.\n");
+ lastCommand = WriteCommandByte;
+ break;
+ case CheckForPassword:
+ panic("i8042 \"Check for password\" command not implemented.\n");
+ case LoadPassword:
+ panic("i8042 \"Load password\" command not implemented.\n");
+ case CheckPassword:
+ panic("i8042 \"Check password\" command not implemented.\n");
+ case DisableMouse:
+ DPRINTF(I8042, "Disabling mouse at controller.\n");
+ commandByte.disableMouse = 1;
+ break;
+ case EnableMouse:
+ DPRINTF(I8042, "Enabling mouse at controller.\n");
+ commandByte.disableMouse = 0;
+ break;
+ case TestMouse:
+ panic("i8042 \"Test mouse\" command not implemented.\n");
+ case SelfTest:
+ panic("i8042 \"Self test\" command not implemented.\n");
+ case InterfaceTest:
+ panic("i8042 \"Interface test\" command not implemented.\n");
+ case DiagnosticDump:
+ panic("i8042 \"Diagnostic dump\" command not implemented.\n");
+ case DisableKeyboard:
+ DPRINTF(I8042, "Disabling keyboard at controller.\n");
+ commandByte.disableKeyboard = 1;
+ break;
+ case EnableKeyboard:
+ DPRINTF(I8042, "Enabling keyboard at controller.\n");
+ commandByte.disableKeyboard = 0;
+ break;
+ case ReadInputPort:
+ panic("i8042 \"Read input port\" command not implemented.\n");
+ case ContinuousPollLow:
+ panic("i8042 \"Continuous poll low\" command not implemented.\n");
+ case ContinuousPollHigh:
+ panic("i8042 \"Continuous poll high\" command not implemented.\n");
+ case ReadOutputPort:
+ panic("i8042 \"Read output port\" command not implemented.\n");
+ case WriteOutputPort:
+ panic("i8042 \"Write output port\" command not implemented.\n");
+ case WriteKeyboardOutputBuff:
+ panic("i8042 \"Write keyboard output buffer\" "
+ "command not implemented.\n");
+ case WriteMouseOutputBuff:
+ DPRINTF(I8042, "Got command to write to mouse output buffer.\n");
+ lastCommand = WriteMouseOutputBuff;
+ break;
+ case WriteToMouse:
+ DPRINTF(I8042, "Expecting mouse command.\n");
+ lastCommand = WriteToMouse;
+ break;
+ case DisableA20:
+ panic("i8042 \"Disable A20\" command not implemented.\n");
+ case EnableA20:
+ panic("i8042 \"Enable A20\" command not implemented.\n");
+ case ReadTestInputs:
+ panic("i8042 \"Read test inputs\" command not implemented.\n");
+ case SystemReset:
+ panic("i8042 \"System reset\" command not implemented.\n");
+ default:
+ panic("Write to unknown i8042 "
+ "(keyboard controller) command port.\n");
+ }
+ } else {
+ panic("Write to unrecognized port %#x.\n", addr);
+ }
+ return latency;
+}
+
+X86ISA::I8042 *
+I8042Params::create()
+{
+ return new X86ISA::I8042(this);
+}
diff --git a/src/dev/x86/i8042.hh b/src/dev/x86/i8042.hh
new file mode 100644
index 000000000..7eeb5f7e0
--- /dev/null
+++ b/src/dev/x86/i8042.hh
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2008 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef __DEV_X86_I8042_HH__
+#define __DEV_X86_I8042_HH__
+
+#include "dev/io_device.hh"
+#include "dev/x86/intdev.hh"
+#include "params/I8042.hh"
+
+#include <queue>
+
+namespace X86ISA
+{
+
+class IntPin;
+
+class I8042 : public BasicPioDevice
+{
+ protected:
+ BitUnion8(StatusReg)
+ Bitfield<7> parityError;
+ Bitfield<6> timeout;
+ Bitfield<5> mouseOutputFull;
+ Bitfield<4> keyboardUnlocked;
+ Bitfield<3> commandLast;
+ Bitfield<2> passedSelfTest;
+ Bitfield<1> inputFull;
+ Bitfield<0> outputFull;
+ EndBitUnion(StatusReg)
+
+ BitUnion8(CommandByte)
+ Bitfield<6> convertScanCodes;
+ Bitfield<5> disableMouse;
+ Bitfield<4> disableKeyboard;
+ Bitfield<2> passedSelfTest;
+ Bitfield<1> mouseFullInt;
+ Bitfield<0> keyboardFullInt;
+ EndBitUnion(CommandByte)
+
+ Tick latency;
+ Addr dataPort;
+ Addr commandPort;
+
+ StatusReg statusReg;
+ CommandByte commandByte;
+
+ uint8_t dataReg;
+
+ static const uint16_t NoCommand = (uint16_t)(-1);
+ uint16_t lastCommand;
+
+ BitUnion8(MouseStatus)
+ Bitfield<6> remote;
+ Bitfield<5> enabled;
+ Bitfield<4> twoToOne;
+ Bitfield<2> leftButton;
+ Bitfield<0> rightButton;
+ EndBitUnion(MouseStatus)
+
+ IntSourcePin *mouseIntPin;
+ std::queue<uint8_t> mouseBuffer;
+ uint16_t lastMouseCommand;
+ uint8_t mouseResolution;
+ uint8_t mouseSampleRate;
+ MouseStatus mouseStatus;
+
+
+ IntSourcePin *keyboardIntPin;
+ std::queue<uint8_t> keyboardBuffer;
+ uint16_t lastKeyboardCommand;
+
+ bool writeData(uint8_t newData, bool mouse = false);
+ void keyboardAck();
+ void writeKeyboardData(const uint8_t *data, int size);
+ void mouseAck();
+ void mouseNack();
+ void writeMouseData(const uint8_t *data, int size);
+ uint8_t readDataOut();
+
+ public:
+ typedef I8042Params Params;
+
+ const Params *
+ params() const
+ {
+ return dynamic_cast<const Params *>(_params);
+ }
+
+ I8042(Params *p) : BasicPioDevice(p), latency(p->pio_latency),
+ dataPort(p->data_port), commandPort(p->command_port),
+ statusReg(0), commandByte(0), dataReg(0), lastCommand(NoCommand),
+ mouseIntPin(p->mouse_int_pin), lastMouseCommand(NoCommand),
+ keyboardIntPin(p->keyboard_int_pin),
+ lastKeyboardCommand(NoCommand)
+ {
+ statusReg.passedSelfTest = 1;
+ statusReg.commandLast = 1;
+ statusReg.keyboardUnlocked = 1;
+
+ commandByte.convertScanCodes = 1;
+ commandByte.passedSelfTest = 1;
+ commandByte.keyboardFullInt = 1;
+ }
+
+ void addressRanges(AddrRangeList &range_list);
+
+ Tick read(PacketPtr pkt);
+
+ Tick write(PacketPtr pkt);
+};
+
+}; // namespace X86ISA
+
+#endif //__DEV_X86_I8042_HH__