Andreas Sandberg has submitted this change and it was merged. ( https://gem5-review.googlesource.com/9762 )

Change subject: ps2: Factor out PS/2 devices into their own subsystem
......................................................................

ps2: Factor out PS/2 devices into their own subsystem

PS/2 devices are currently emulated both in the i8042 model and the
Arm KMI model. This is undesirable since it leads to code duplication.

This change introduces a common PS/2 device interface and factor out
the x86 keyboard and mouse model. A subsequent commit will implement
support for this interface in the Arm KMI model.

Change-Id: I440e83517fd9dce362fdc1676db477cc6eee5211
Signed-off-by: Andreas Sandberg <andreas.sandb...@arm.com>
Reviewed-by: Giacomo Travaglini <giacomo.travagl...@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/9762
Reviewed-by: Gabe Black <gabebl...@google.com>
Maintainer: Gabe Black <gabebl...@google.com>
---
M src/dev/ps2.hh
A src/dev/ps2/PS2.py
A src/dev/ps2/SConscript
A src/dev/ps2/device.cc
A src/dev/ps2/device.hh
A src/dev/ps2/keyboard.cc
A src/dev/ps2/keyboard.hh
A src/dev/ps2/mouse.cc
A src/dev/ps2/mouse.hh
M src/dev/x86/I8042.py
M src/dev/x86/i8042.cc
M src/dev/x86/i8042.hh
12 files changed, 912 insertions(+), 382 deletions(-)

Approvals:
  Gabe Black: Looks good to me, approved; Looks good to me, approved



diff --git a/src/dev/ps2.hh b/src/dev/ps2.hh
index 9e99867..7b57835 100644
--- a/src/dev/ps2.hh
+++ b/src/dev/ps2.hh
@@ -61,6 +61,7 @@
     ReadId          = 0xf2,
     TpReadId        = 0xe1,
     Ack             = 0xfa,
+    Resend          = 0xfe,
     SetRate         = 0xf3,
     Enable          = 0xf4,
     Disable         = 0xf5,
diff --git a/src/dev/ps2/PS2.py b/src/dev/ps2/PS2.py
new file mode 100644
index 0000000..5db3b6e
--- /dev/null
+++ b/src/dev/ps2/PS2.py
@@ -0,0 +1,53 @@
+# Copyright (c) 2017-2018 ARM Limited
+# All rights reserved
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder.  You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
+# 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: Andreas Sandberg
+
+from m5.SimObject import SimObject
+from m5.params import *
+from m5.proxy import *
+
+class PS2Device(SimObject):
+    type = 'PS2Device'
+    cxx_header = "dev/ps2/device.hh"
+    abstract = True
+
+class PS2Keyboard(PS2Device):
+    type = 'PS2Keyboard'
+    cxx_header = "dev/ps2/keyboard.hh"
+
+class PS2Mouse(PS2Device):
+    type = 'PS2Mouse'
+    cxx_header = "dev/ps2/mouse.hh"
diff --git a/src/dev/ps2/SConscript b/src/dev/ps2/SConscript
new file mode 100644
index 0000000..acce7be
--- /dev/null
+++ b/src/dev/ps2/SConscript
@@ -0,0 +1,50 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2017-2018 ARM Limited
+# All rights reserved.
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder.  You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
+# 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: Andreas Sandberg
+
+Import('*')
+
+if env['TARGET_ISA'] == 'null':
+    Return()
+
+SimObject('PS2.py')
+Source('device.cc')
+Source('keyboard.cc')
+Source('mouse.cc')
+
+DebugFlag('PS2')
diff --git a/src/dev/ps2/device.cc b/src/dev/ps2/device.cc
new file mode 100644
index 0000000..deedb49
--- /dev/null
+++ b/src/dev/ps2/device.cc
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2017-2018 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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
+ *          Andreas Sandberg
+ */
+
+#include "dev/ps2/device.hh"
+
+#include "base/logging.hh"
+#include "dev/ps2.hh"
+#include "params/PS2Device.hh"
+
+PS2Device::PS2Device(const PS2DeviceParams *p)
+    : SimObject(p)
+{
+}
+
+void
+PS2Device::serialize(CheckpointOut &cp) const
+{
+    std::vector<uint8_t> buffer(outBuffer.size());
+    std::copy(outBuffer.begin(), outBuffer.end(), buffer.begin());
+    arrayParamOut(cp, "outBuffer", buffer);
+}
+
+void
+PS2Device::unserialize(CheckpointIn &cp)
+{
+    std::vector<uint8_t> buffer;
+    arrayParamIn(cp, "outBuffer", buffer);
+    for (auto c : buffer)
+        outBuffer.push_back(c);
+}
+
+void
+PS2Device::hostRegDataAvailable(const std::function<void()> &c)
+{
+    fatal_if(dataAvailableCallback,
+ "A data pending callback has already been associated with this "
+             "PS/2 device.\n");
+
+    dataAvailableCallback = c;
+}
+
+uint8_t
+PS2Device::hostRead()
+{
+    uint8_t data = outBuffer.front();
+    outBuffer.pop_front();
+    return data;
+}
+
+void
+PS2Device::hostWrite(uint8_t c)
+{
+    recv(c);
+}
+
+void
+PS2Device::send(const uint8_t *data, size_t size)
+{
+    assert(data || size == 0);
+    while (size) {
+        outBuffer.push_back(*(data++));
+        size--;
+    }
+
+    // Registering a callback is optional.
+    if (dataAvailableCallback)
+        dataAvailableCallback();
+}
+
+void
+PS2Device::sendAck()
+{
+    send(Ps2::Ack);
+}
diff --git a/src/dev/ps2/device.hh b/src/dev/ps2/device.hh
new file mode 100644
index 0000000..5252ac8
--- /dev/null
+++ b/src/dev/ps2/device.hh
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2017-2018 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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
+ *          Andreas Sandberg
+ */
+
+#ifndef __DEV_PS2_DEVICE_HH__
+#define __DEV_PS2_DEVICE_HH__
+
+#include <deque>
+
+#include "sim/sim_object.hh"
+
+struct PS2DeviceParams;
+
+class PS2Device : public SimObject
+{
+  public:
+    PS2Device(const PS2DeviceParams *p);
+
+    void serialize(CheckpointOut &cp) const override;
+    void unserialize(CheckpointIn &cp) override;
+
+  public: /* Host interface */
+    /**
+     * Register a data available callback into the PS/2 interface
+     *
+     * @param c Callback instance from host interface
+     */
+    void hostRegDataAvailable(const std::function<void()> &c);
+
+    /**
+     * Check if there is pending data from the PS/2 device.
+     *
+     * @return true if there is data pending that can be read using
+     * the readData() method.
+     */
+    bool hostDataAvailable() const  { return !outBuffer.empty(); }
+
+    /**
+     * Read a character from the device.
+     *
+     * @return Character from the device's output buffer, undefined if
+     * no data is pending.
+     */
+    uint8_t hostRead();
+
+    /**
+     * Transmit a character from the host interface to the device.
+     *
+     * @param c Received data.
+     */
+    void hostWrite(uint8_t c);
+
+  protected: /* Device interface */
+    /**
+     * Data received from host.
+     */
+    virtual void recv(uint8_t data) = 0;
+
+    /**
+     * Send data from a PS/2 device to a host
+     *
+     * @param data Pointer to data array
+     * @param size Size of the data array
+     */
+    void send(const uint8_t *data, size_t size);
+    void send(const std::vector<uint8_t> &data) {
+        send(data.data(), data.size());
+    }
+
+    /**
+     * Send a byte of data from a PS/2 device to a host
+     *
+     * @param data Byte to send
+     */
+    void send(uint8_t data) { send(&data, 1); }
+
+    /** Send an ACK byte to the host */
+    void sendAck();
+
+    /**
+     * Output buffer size
+     *
+     * Device models may use this method to query the size of the
+     * output buffer to do rate limiting.
+     */
+    size_t sendPending() const { return outBuffer.size(); }
+
+  private:
+    /** Device -> host FIFO */
+    std::deque<uint8_t> outBuffer;
+
+    std::function<void()> dataAvailableCallback;
+};
+
+#endif // __DEV_PS2_HOUSE_HH__
diff --git a/src/dev/ps2/keyboard.cc b/src/dev/ps2/keyboard.cc
new file mode 100644
index 0000000..a942d34
--- /dev/null
+++ b/src/dev/ps2/keyboard.cc
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2017-2018 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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
+ *          Andreas Sandberg
+ */
+
+#include "dev/ps2/keyboard.hh"
+
+#include "base/logging.hh"
+#include "debug/PS2.hh"
+#include "params/PS2Keyboard.hh"
+
+const uint8_t PS2Keyboard::ID[] = {0xab, 0x83};
+
+PS2Keyboard::PS2Keyboard(const PS2KeyboardParams *p)
+    : PS2Device(p),
+      lastCommand(NoCommand)
+{
+}
+
+void
+PS2Keyboard::serialize(CheckpointOut &cp) const
+{
+    PS2Device::serialize(cp);
+    SERIALIZE_SCALAR(lastCommand);
+}
+
+void
+PS2Keyboard::unserialize(CheckpointIn &cp)
+{
+    PS2Device::unserialize(cp);
+    UNSERIALIZE_SCALAR(lastCommand);
+}
+
+void
+PS2Keyboard::recv(uint8_t data)
+{
+    if (lastCommand != NoCommand) {
+        switch (lastCommand) {
+          case LEDWrite:
+            DPRINTF(PS2, "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");
+            sendAck();
+            lastCommand = NoCommand;
+            break;
+          case TypematicInfo:
+            DPRINTF(PS2, "Setting typematic info to %#02x.\n", data);
+            sendAck();
+            lastCommand = NoCommand;
+            break;
+        }
+        return;
+    }
+
+    switch (data) {
+      case LEDWrite:
+        DPRINTF(PS2, "Got LED write command.\n");
+        sendAck();
+        lastCommand = LEDWrite;
+        break;
+      case DiagnosticEcho:
+        panic("Keyboard diagnostic echo unimplemented.\n");
+      case AlternateScanCodes:
+        panic("Accessing alternate scan codes unimplemented.\n");
+      case ReadID:
+        DPRINTF(PS2, "Got keyboard read ID command.\n");
+        sendAck();
+        send((uint8_t *)&ID, sizeof(ID));
+        break;
+      case TypematicInfo:
+        DPRINTF(PS2, "Setting typematic info.\n");
+        sendAck();
+        lastCommand = TypematicInfo;
+        break;
+      case Enable:
+        DPRINTF(PS2, "Enabling the keyboard.\n");
+        sendAck();
+        break;
+      case Disable:
+        DPRINTF(PS2, "Disabling the keyboard.\n");
+        sendAck();
+        break;
+      case DefaultsAndDisable:
+        DPRINTF(PS2, "Disabling and resetting the keyboard.\n");
+        sendAck();
+        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 Reset:
+        panic("Keyboard reset unimplemented.\n");
+      default:
+        panic("Unknown keyboard command %#02x.\n", data);
+    }
+}
+
+PS2Keyboard *
+PS2KeyboardParams::create()
+{
+    return new PS2Keyboard(this);
+}
diff --git a/src/dev/ps2/keyboard.hh b/src/dev/ps2/keyboard.hh
new file mode 100644
index 0000000..8943e7f
--- /dev/null
+++ b/src/dev/ps2/keyboard.hh
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2017-2018 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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
+ *          Andreas Sandberg
+ */
+
+#ifndef __DEV_PS2_KEYBOARD_HH__
+#define __DEV_PS2_KEYBOARD_HH__
+
+#include "dev/ps2/device.hh"
+
+struct PS2KeyboardParams;
+
+class PS2Keyboard : public PS2Device
+{
+  protected:
+    static const uint8_t ID[];
+
+    enum Command
+    {
+        LEDWrite = 0xED,
+        DiagnosticEcho = 0xEE,
+        AlternateScanCodes = 0xF0,
+        ReadID = 0xF2,
+        TypematicInfo = 0xF3,
+        Enable = 0xF4,
+        Disable = 0xF5,
+        DefaultsAndDisable = 0xF6,
+        AllKeysToTypematic = 0xF7,
+        AllKeysToMakeRelease = 0xF8,
+        AllKeysToMake = 0xF9,
+        AllKeysToTypematicMakeRelease = 0xFA,
+        KeyToTypematic = 0xFB,
+        KeyToMakeRelease = 0xFC,
+        KeyToMakeOnly = 0xFD,
+        Resend = 0xFE,
+        Reset = 0xFF
+    };
+    static const uint16_t NoCommand = (uint16_t)(-1);
+
+
+    uint16_t lastCommand;
+
+  public:
+    PS2Keyboard(const PS2KeyboardParams *p);
+
+    void serialize(CheckpointOut &cp) const override;
+    void unserialize(CheckpointIn &cp) override;
+
+  protected: // PS2Device
+    void recv(uint8_t data) override;
+};
+
+#endif // __DEV_PS2_KEYBOARD_hH__
+
diff --git a/src/dev/ps2/mouse.cc b/src/dev/ps2/mouse.cc
new file mode 100644
index 0000000..1bdf39c
--- /dev/null
+++ b/src/dev/ps2/mouse.cc
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2017-2018 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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
+ *          Andreas Sandberg
+ */
+
+#include "dev/ps2/mouse.hh"
+
+#include "base/logging.hh"
+#include "debug/PS2.hh"
+#include "params/PS2Mouse.hh"
+
+const uint8_t PS2Mouse::ID[] = {0x00};
+const uint8_t BatSuccessful = 0xaa;
+
+PS2Mouse::PS2Mouse(const PS2MouseParams *p)
+    : PS2Device(p),
+      lastCommand(NoCommand),
+      status(0), resolution(4), sampleRate(100)
+{
+}
+
+void
+PS2Mouse::recv(uint8_t data)
+{
+    if (lastCommand != NoCommand) {
+        switch(lastCommand) {
+          case SetResolution:
+            DPRINTF(PS2, "Mouse resolution set to %d.\n", data);
+            resolution = data;
+            sendAck();
+            lastCommand = NoCommand;
+            break;
+          case SampleRate:
+            DPRINTF(PS2, "Mouse sample rate %d samples "
+                    "per second.\n", data);
+            sampleRate = data;
+            sendAck();
+            lastCommand = NoCommand;
+            break;
+          default:
+            panic("Not expecting data for a mouse command.\n");
+        }
+        return;
+    }
+    switch (data) {
+      case Scale1to1:
+        DPRINTF(PS2, "Setting mouse scale to 1:1.\n");
+        status.twoToOne = 0;
+        sendAck();
+        break;
+      case Scale2to1:
+        DPRINTF(PS2, "Setting mouse scale to 2:1.\n");
+        status.twoToOne = 1;
+        sendAck();
+        break;
+      case SetResolution:
+        DPRINTF(PS2, "Setting mouse resolution.\n");
+        lastCommand = SetResolution;
+        sendAck();
+        break;
+      case GetStatus:
+        DPRINTF(PS2, "Getting mouse status.\n");
+        sendAck();
+        send((uint8_t *)&(status), 1);
+        send(&resolution, sizeof(resolution));
+        send(&sampleRate, sizeof(sampleRate));
+        break;
+      case ReadData:
+        panic("Reading mouse data unimplemented.\n");
+      case ResetWrapMode:
+        panic("Resetting mouse wrap mode unimplemented.\n");
+      case WrapMode:
+        panic("Setting mouse wrap mode unimplemented.\n");
+      case RemoteMode:
+        panic("Setting mouse remote mode unimplemented.\n");
+      case ReadID:
+        DPRINTF(PS2, "Mouse ID requested.\n");
+        sendAck();
+        send(ID, sizeof(ID));
+        break;
+      case SampleRate:
+        DPRINTF(PS2, "Setting mouse sample rate.\n");
+        lastCommand = SampleRate;
+        sendAck();
+        break;
+      case DisableReporting:
+        DPRINTF(PS2, "Disabling data reporting.\n");
+        status.enabled = 0;
+        sendAck();
+        break;
+      case EnableReporting:
+        DPRINTF(PS2, "Enabling data reporting.\n");
+        status.enabled = 1;
+        sendAck();
+        break;
+      case DefaultsAndDisable:
+        DPRINTF(PS2, "Disabling and resetting mouse.\n");
+        sampleRate = 100;
+        resolution = 4;
+        status.twoToOne = 0;
+        status.enabled = 0;
+        sendAck();
+        break;
+      case Resend:
+        panic("Mouse resend unimplemented.\n");
+      case Reset:
+        DPRINTF(PS2, "Resetting the mouse.\n");
+        sampleRate = 100;
+        resolution = 4;
+        status.twoToOne = 0;
+        status.enabled = 0;
+        sendAck();
+        send(&BatSuccessful, sizeof(BatSuccessful));
+        send(ID, sizeof(ID));
+        break;
+      default:
+        warn("Unknown mouse command %#02x.\n", data);
+        send(Resend);
+        break;
+    }
+}
+
+void
+PS2Mouse::serialize(CheckpointOut &cp) const
+{
+    PS2Device::serialize(cp);
+
+    SERIALIZE_SCALAR(lastCommand);
+
+    SERIALIZE_SCALAR(status);
+    SERIALIZE_SCALAR(resolution);
+    SERIALIZE_SCALAR(sampleRate);
+}
+
+void
+PS2Mouse::unserialize(CheckpointIn &cp)
+{
+    PS2Device::unserialize(cp);
+
+    UNSERIALIZE_SCALAR(lastCommand);
+
+    UNSERIALIZE_SCALAR(status);
+    UNSERIALIZE_SCALAR(resolution);
+    UNSERIALIZE_SCALAR(sampleRate);
+}
+
+PS2Mouse *
+PS2MouseParams::create()
+{
+    return new PS2Mouse(this);
+}
diff --git a/src/dev/ps2/mouse.hh b/src/dev/ps2/mouse.hh
new file mode 100644
index 0000000..e0b4c53
--- /dev/null
+++ b/src/dev/ps2/mouse.hh
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017-2018 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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
+ *          Andreas Sandberg
+ */
+
+#ifndef __DEV_PS2_MOUSE_HH__
+#define __DEV_PS2_MOUSE_HH__
+
+#include "dev/ps2/device.hh"
+
+struct PS2MouseParams;
+
+class PS2Mouse : public PS2Device
+{
+  protected:
+    static const uint8_t ID[];
+
+    enum Command
+    {
+        Scale1to1 = 0xE6,
+        Scale2to1 = 0xE7,
+        SetResolution = 0xE8,
+        GetStatus = 0xE9,
+        ReadData = 0xEB,
+        ResetWrapMode = 0xEC,
+        WrapMode = 0xEE,
+        RemoteMode = 0xF0,
+        ReadID = 0xF2,
+        SampleRate = 0xF3,
+        EnableReporting = 0xF4,
+        DisableReporting = 0xF5,
+        DefaultsAndDisable = 0xF6,
+        Resend = 0xFE,
+        Reset = 0xFF
+    };
+    static const uint16_t NoCommand = (uint16_t)(-1);
+
+    BitUnion8(Status)
+        Bitfield<6> remote;
+        Bitfield<5> enabled;
+        Bitfield<4> twoToOne;
+        Bitfield<2> leftButton;
+        Bitfield<0> rightButton;
+    EndBitUnion(Status)
+
+    uint16_t lastCommand;
+
+    Status status;
+    uint8_t resolution;
+    uint8_t sampleRate;
+
+  public:
+    PS2Mouse(const PS2MouseParams *p);
+
+    void serialize(CheckpointOut &cp) const override;
+    void unserialize(CheckpointIn &cp) override;
+
+  protected: // PS2Device
+    void recv(uint8_t data) override;
+};
+
+#endif // __DEV_PS2_MOUSE_hH__
+
diff --git a/src/dev/x86/I8042.py b/src/dev/x86/I8042.py
index d13a133..9203f40 100644
--- a/src/dev/x86/I8042.py
+++ b/src/dev/x86/I8042.py
@@ -30,6 +30,7 @@
 from m5.proxy import *
 from Device import BasicPioDevice
 from X86IntPin import X86IntSourcePin
+from PS2 import *

 class I8042(BasicPioDevice):
     type = 'I8042'
@@ -43,3 +44,6 @@
             'Pin to signal the mouse has data')
     keyboard_int_pin = Param.X86IntSourcePin(X86IntSourcePin(),
             'Pin to signal the keyboard has data')
+
+    keyboard = Param.PS2Device(PS2Keyboard(), "PS/2 keyboard device")
+    mouse = Param.PS2Device(PS2Mouse(), "PS/2 mouse device")
diff --git a/src/dev/x86/i8042.cc b/src/dev/x86/i8042.cc
index c884f71..8ab0d40 100644
--- a/src/dev/x86/i8042.cc
+++ b/src/dev/x86/i8042.cc
@@ -43,11 +43,6 @@
 // The 8042 has a whopping 32 bytes of internal RAM.
 const uint8_t RamSize = 32;
 const uint8_t NumOutputBits = 14;
-const uint8_t X86ISA::PS2Keyboard::ID[] = {0xab, 0x83};
-const uint8_t X86ISA::PS2Mouse::ID[] = {0x00};
-const uint8_t CommandAck = 0xfa;
-const uint8_t CommandNack = 0xfe;
-const uint8_t BatSuccessful = 0xaa;


 X86ISA::I8042::I8042(Params *p)
@@ -55,8 +50,12 @@
       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), keyboardIntPin(p->keyboard_int_pin)
+      mouseIntPin(p->mouse_int_pin), keyboardIntPin(p->keyboard_int_pin),
+      mouse(p->mouse), keyboard(p->keyboard)
 {
+    fatal_if(!mouse, "The i8042 model requires a mouse instance");
+    fatal_if(!keyboard, "The i8042 model requires a keyboard instance");
+
     statusReg.passedSelfTest = 1;
     statusReg.commandLast = 1;
     statusReg.keyboardUnlocked = 1;
@@ -97,247 +96,20 @@
     }
 }

-void
-X86ISA::PS2Device::serialize(const std::string &base, CheckpointOut &cp) const
-{
-    paramOut(cp, base + ".lastCommand", lastCommand);
-
-    std::vector<uint8_t> buffer(outBuffer.size());
-    std::copy(outBuffer.begin(), outBuffer.end(), buffer.begin());
-    arrayParamOut(cp, base + ".outBuffer.elts", buffer);
-}
-
-void
-X86ISA::PS2Device::unserialize(const std::string &base, CheckpointIn &cp)
-{
-    paramIn(cp, base + ".lastCommand", lastCommand);
-
-    std::vector<uint8_t> buffer;
-    arrayParamIn(cp, base + ".outBuffer.elts", buffer);
-    assert(outBuffer.empty());
-    for (auto c : buffer)
-        outBuffer.push_back(c);
-}
-
-
-void
-X86ISA::PS2Device::ack()
-{
-    bufferData(&CommandAck, sizeof(CommandAck));
-}
-
-void
-X86ISA::PS2Device::nack()
-{
-    bufferData(&CommandNack, sizeof(CommandNack));
-}
-
-void
-X86ISA::PS2Device::bufferData(const uint8_t *data, int size)
-{
-    assert(data || size == 0);
-    while (size) {
-        outBuffer.push_back(*(data++));
-        size--;
-    }
-}
-
 uint8_t
 X86ISA::I8042::readDataOut()
 {
     uint8_t data = dataReg;
     statusReg.outputFull = 0;
     statusReg.mouseOutputFull = 0;
-    if (keyboard.hasData()) {
-        writeData(keyboard.getData(), false);
-    } else if (mouse.hasData()) {
-        writeData(mouse.getData(), true);
+    if (keyboard->hostDataAvailable()) {
+        writeData(keyboard->hostRead(), false);
+    } else if (mouse->hostDataAvailable()) {
+        writeData(mouse->hostRead(), true);
     }
     return data;
 }

-bool
-X86ISA::PS2Keyboard::processData(uint8_t data)
-{
-    if (lastCommand != NoCommand) {
-        switch (lastCommand) {
-          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");
-            ack();
-            lastCommand = NoCommand;
-            break;
-          case TypematicInfo:
-            DPRINTF(I8042, "Setting typematic info to %#02x.\n", data);
-            ack();
-            lastCommand = NoCommand;
-            break;
-        }
-        return hasData();
-    }
-    switch (data) {
-      case LEDWrite:
-        DPRINTF(I8042, "Got LED write command.\n");
-        ack();
-        lastCommand = LEDWrite;
-        break;
-      case DiagnosticEcho:
-        panic("Keyboard diagnostic echo unimplemented.\n");
-      case AlternateScanCodes:
-        panic("Accessing alternate scan codes unimplemented.\n");
-      case ReadID:
-        DPRINTF(I8042, "Got keyboard read ID command.\n");
-        ack();
-        bufferData((uint8_t *)&ID, sizeof(ID));
-        break;
-      case TypematicInfo:
-        DPRINTF(I8042, "Setting typematic info.\n");
-        ack();
-        lastCommand = TypematicInfo;
-        break;
-      case Enable:
-        DPRINTF(I8042, "Enabling the keyboard.\n");
-        ack();
-        break;
-      case Disable:
-        DPRINTF(I8042, "Disabling the keyboard.\n");
-        ack();
-        break;
-      case DefaultsAndDisable:
-        DPRINTF(I8042, "Disabling and resetting the keyboard.\n");
-        ack();
-        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 Reset:
-        panic("Keyboard reset unimplemented.\n");
-      default:
-        panic("Unknown keyboard command %#02x.\n", data);
-    }
-    return hasData();
-}
-
-bool
-X86ISA::PS2Mouse::processData(uint8_t data)
-{
-    if (lastCommand != NoCommand) {
-        switch(lastCommand) {
-          case SetResolution:
-            DPRINTF(I8042, "Mouse resolution set to %d.\n", data);
-            resolution = data;
-            ack();
-            lastCommand = NoCommand;
-            break;
-          case SampleRate:
-            DPRINTF(I8042, "Mouse sample rate %d samples "
-                    "per second.\n", data);
-            sampleRate = data;
-            ack();
-            lastCommand = NoCommand;
-            break;
-          default:
-            panic("Not expecting data for a mouse command.\n");
-        }
-        return hasData();
-    }
-    switch (data) {
-      case Scale1to1:
-        DPRINTF(I8042, "Setting mouse scale to 1:1.\n");
-        status.twoToOne = 0;
-        ack();
-        break;
-      case Scale2to1:
-        DPRINTF(I8042, "Setting mouse scale to 2:1.\n");
-        status.twoToOne = 1;
-        ack();
-        break;
-      case SetResolution:
-        DPRINTF(I8042, "Setting mouse resolution.\n");
-        lastCommand = SetResolution;
-        ack();
-        break;
-      case GetStatus:
-        DPRINTF(I8042, "Getting mouse status.\n");
-        ack();
-        bufferData((uint8_t *)&(status), 1);
-        bufferData(&resolution, sizeof(resolution));
-        bufferData(&sampleRate, sizeof(sampleRate));
-        break;
-      case ReadData:
-        panic("Reading mouse data unimplemented.\n");
-      case ResetWrapMode:
-        panic("Resetting mouse wrap mode unimplemented.\n");
-      case WrapMode:
-        panic("Setting mouse wrap mode unimplemented.\n");
-      case RemoteMode:
-        panic("Setting mouse remote mode unimplemented.\n");
-      case ReadID:
-        DPRINTF(I8042, "Mouse ID requested.\n");
-        ack();
-        bufferData(ID, sizeof(ID));
-        break;
-      case SampleRate:
-        DPRINTF(I8042, "Setting mouse sample rate.\n");
-        lastCommand = SampleRate;
-        ack();
-        break;
-      case DisableReporting:
-        DPRINTF(I8042, "Disabling data reporting.\n");
-        status.enabled = 0;
-        ack();
-        break;
-      case EnableReporting:
-        DPRINTF(I8042, "Enabling data reporting.\n");
-        status.enabled = 1;
-        ack();
-        break;
-      case DefaultsAndDisable:
-        DPRINTF(I8042, "Disabling and resetting mouse.\n");
-        sampleRate = 100;
-        resolution = 4;
-        status.twoToOne = 0;
-        status.enabled = 0;
-        ack();
-        break;
-      case Resend:
-        panic("Mouse resend unimplemented.\n");
-      case Reset:
-        DPRINTF(I8042, "Resetting the mouse.\n");
-        sampleRate = 100;
-        resolution = 4;
-        status.twoToOne = 0;
-        status.enabled = 0;
-        ack();
-        bufferData(&BatSuccessful, sizeof(BatSuccessful));
-        bufferData(ID, sizeof(ID));
-        break;
-      default:
-        warn("Unknown mouse command %#02x.\n", data);
-        nack();
-        break;
-    }
-    return hasData();
-}
-
-
 Tick
 X86ISA::I8042::read(PacketPtr pkt)
 {
@@ -367,14 +139,14 @@
         statusReg.commandLast = 0;
         switch (lastCommand) {
           case NoCommand:
-            if (keyboard.processData(data)) {
-                writeData(keyboard.getData(), false);
-            }
+            keyboard->hostWrite(data);
+            if (keyboard->hostDataAvailable())
+                writeData(keyboard->hostRead(), false);
             break;
           case WriteToMouse:
-            if (mouse.processData(data)) {
-                writeData(mouse.getData(), true);
-            }
+            mouse->hostWrite(data);
+            if (mouse->hostDataAvailable())
+                writeData(mouse->hostRead(), true);
             break;
           case WriteCommandByte:
             commandByte = data;
@@ -510,8 +282,6 @@
     SERIALIZE_SCALAR(commandByte);
     SERIALIZE_SCALAR(dataReg);
     SERIALIZE_SCALAR(lastCommand);
-    mouse.serialize("mouse", cp);
-    keyboard.serialize("keyboard", cp);
 }

 void
@@ -523,28 +293,6 @@
     UNSERIALIZE_SCALAR(commandByte);
     UNSERIALIZE_SCALAR(dataReg);
     UNSERIALIZE_SCALAR(lastCommand);
-    mouse.unserialize("mouse", cp);
-    keyboard.unserialize("keyboard", cp);
-}
-
-void
-X86ISA::PS2Mouse::serialize(const std::string &base, CheckpointOut &cp) const
-{
-    PS2Device::serialize(base, cp);
-
-    paramOut(cp, base + ".status", status);
-    paramOut(cp, base + ".resolution", resolution);
-    paramOut(cp, base + ".sampleRate", sampleRate);
-}
-
-void
-X86ISA::PS2Mouse::unserialize(const std::string &base, CheckpointIn &cp)
-{
-    PS2Device::unserialize(base, cp);
-
-    paramIn(cp, base + ".status", status);
-    paramIn(cp, base + ".resolution", resolution);
-    paramIn(cp, base + ".sampleRate", sampleRate);
 }

 X86ISA::I8042 *
diff --git a/src/dev/x86/i8042.hh b/src/dev/x86/i8042.hh
index 82d07e9..0f38da9 100644
--- a/src/dev/x86/i8042.hh
+++ b/src/dev/x86/i8042.hh
@@ -33,8 +33,9 @@

 #include <deque>

-#include "dev/x86/intdev.hh"
 #include "dev/io_device.hh"
+#include "dev/ps2/device.hh"
+#include "dev/x86/intdev.hh"
 #include "params/I8042.hh"

 namespace X86ISA
@@ -42,118 +43,6 @@

 class IntPin;

-class PS2Device
-{
-  protected:
-    std::deque<uint8_t> outBuffer;
-
-    static const uint16_t NoCommand = (uint16_t)(-1);
-
-    uint16_t lastCommand;
-    void bufferData(const uint8_t *data, int size);
-    void ack();
-    void nack();
-
-  public:
-    virtual ~PS2Device()
-    {};
-
-    PS2Device() : lastCommand(NoCommand)
-    {}
-
- virtual void serialize(const std::string &base, CheckpointOut &cp) const;
-    virtual void unserialize(const std::string &base, CheckpointIn &cp);
-
-    bool hasData()
-    {
-        return !outBuffer.empty();
-    }
-
-    uint8_t getData()
-    {
-        uint8_t data = outBuffer.front();
-        outBuffer.pop_front();
-        return data;
-    }
-
-    virtual bool processData(uint8_t data) = 0;
-};
-
-class PS2Mouse : public PS2Device
-{
-  protected:
-    static const uint8_t ID[];
-
-    enum Command
-    {
-        Scale1to1 = 0xE6,
-        Scale2to1 = 0xE7,
-        SetResolution = 0xE8,
-        GetStatus = 0xE9,
-        ReadData = 0xEB,
-        ResetWrapMode = 0xEC,
-        WrapMode = 0xEE,
-        RemoteMode = 0xF0,
-        ReadID = 0xF2,
-        SampleRate = 0xF3,
-        EnableReporting = 0xF4,
-        DisableReporting = 0xF5,
-        DefaultsAndDisable = 0xF6,
-        Resend = 0xFE,
-        Reset = 0xFF
-    };
-
-    BitUnion8(Status)
-        Bitfield<6> remote;
-        Bitfield<5> enabled;
-        Bitfield<4> twoToOne;
-        Bitfield<2> leftButton;
-        Bitfield<0> rightButton;
-    EndBitUnion(Status)
-
-    Status status;
-    uint8_t resolution;
-    uint8_t sampleRate;
-  public:
-    PS2Mouse() : PS2Device(), status(0), resolution(4), sampleRate(100)
-    {}
-
-    bool processData(uint8_t data) override;
-
- void serialize(const std::string &base, CheckpointOut &cp) const override;
-    void unserialize(const std::string &base, CheckpointIn &cp) override;
-};
-
-class PS2Keyboard : public PS2Device
-{
-  protected:
-    static const uint8_t ID[];
-
-    enum Command
-    {
-        LEDWrite = 0xED,
-        DiagnosticEcho = 0xEE,
-        AlternateScanCodes = 0xF0,
-        ReadID = 0xF2,
-        TypematicInfo = 0xF3,
-        Enable = 0xF4,
-        Disable = 0xF5,
-        DefaultsAndDisable = 0xF6,
-        AllKeysToTypematic = 0xF7,
-        AllKeysToMakeRelease = 0xF8,
-        AllKeysToMake = 0xF9,
-        AllKeysToTypematicMakeRelease = 0xFA,
-        KeyToTypematic = 0xFB,
-        KeyToMakeRelease = 0xFC,
-        KeyToMakeOnly = 0xFD,
-        Resend = 0xFE,
-        Reset = 0xFF
-    };
-
-  public:
-    bool processData(uint8_t data) override;
-};
-
 class I8042 : public BasicPioDevice
 {
   protected:
@@ -224,8 +113,8 @@
     IntSourcePin *mouseIntPin;
     IntSourcePin *keyboardIntPin;

-    PS2Mouse mouse;
-    PS2Keyboard keyboard;
+    PS2Device *mouse;
+    PS2Device *keyboard;

     void writeData(uint8_t newData, bool mouse = false);
     uint8_t readDataOut();

--
To view, visit https://gem5-review.googlesource.com/9762
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I440e83517fd9dce362fdc1676db477cc6eee5211
Gerrit-Change-Number: 9762
Gerrit-PatchSet: 3
Gerrit-Owner: Andreas Sandberg <andreas.sandb...@arm.com>
Gerrit-Reviewer: Andreas Sandberg <andreas.sandb...@arm.com>
Gerrit-Reviewer: Gabe Black <gabebl...@google.com>
Gerrit-Reviewer: Giacomo Travaglini <giacomo.travagl...@arm.com>
Gerrit-Reviewer: Jason Lowe-Power <ja...@lowepower.com>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to