dev, arm: Use the PS/2 framework in the Pl050 model
authorAndreas Sandberg <andreas.sandberg@arm.com>
Mon, 9 Apr 2018 17:42:28 +0000 (18:42 +0100)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Tue, 17 Apr 2018 12:24:17 +0000 (12:24 +0000)
The Pl050 KMI model currently has its own keyboard and mouse
models. Use the generic PS/2 interface instead.

Change-Id: I6523d26f8e38bcc8ba399d4d1a131723645d36c7
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/9767
Reviewed-by: Gabe Black <gabeblack@google.com>
src/dev/arm/RealView.py
src/dev/arm/kmi.cc
src/dev/arm/kmi.hh

index a59e1713f7a8d5db5e2eb726b5066e5dfd9db856..7661db15a2afce5c862de4b90655589a85de9a4f 100644 (file)
@@ -62,6 +62,7 @@ from ClockDomain import SrcClockDomain
 from SubSystem import SubSystem
 from Graphics import ImageFormat
 from ClockedObject import ClockedObject
+from PS2 import *
 
 # Platforms with KVM support should generally use in-kernel GIC
 # emulation. Use a GIC model that automatically switches between
@@ -465,11 +466,11 @@ class PL031(AmbaIntDevice):
 class Pl050(AmbaIntDevice):
     type = 'Pl050'
     cxx_header = "dev/arm/kmi.hh"
-    vnc = Param.VncInput(Parent.any, "Vnc server for remote frame buffer display")
-    is_mouse = Param.Bool(False, "Is this interface a mouse, if not a keyboard")
     int_delay = '1us'
     amba_id = 0x00141050
 
+    ps2 = Param.PS2Device("PS/2 device")
+
     def generateDeviceTree(self, state):
         node = self.generateBasicPioDeviceNode(state, 'kmi', self.pio_addr,
                                                0x1000, [int(self.int_num)])
@@ -624,8 +625,8 @@ class RealViewPBX(RealView):
     local_cpu_timer = CpuLocalTimer(int_num_timer=29, int_num_watchdog=30,
                                     pio_addr=0x1f000600)
     clcd = Pl111(pio_addr=0x10020000, int_num=55)
-    kmi0   = Pl050(pio_addr=0x10006000, int_num=52)
-    kmi1   = Pl050(pio_addr=0x10007000, int_num=53, is_mouse=True)
+    kmi0   = Pl050(pio_addr=0x10006000, int_num=52, ps2=PS2Keyboard())
+    kmi1   = Pl050(pio_addr=0x10007000, int_num=53, ps2=PS2TouchKit())
     a9scu  = A9SCU(pio_addr=0x1f000000)
     cf_ctrl = IdeController(disks=[], pci_func=0, pci_dev=7, pci_bus=2,
                             io_shift = 1, ctrl_offset = 2, Command = 0x1,
@@ -753,8 +754,8 @@ class RealViewEB(RealView):
     timer0 = Sp804(int_num0=36, int_num1=36, pio_addr=0x10011000)
     timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000)
     clcd   = Pl111(pio_addr=0x10020000, int_num=23)
-    kmi0   = Pl050(pio_addr=0x10006000, int_num=20)
-    kmi1   = Pl050(pio_addr=0x10007000, int_num=21, is_mouse=True)
+    kmi0   = Pl050(pio_addr=0x10006000, int_num=20, ps2=PS2Keyboard())
+    kmi1   = Pl050(pio_addr=0x10007000, int_num=21, ps2=PS2TouchKit())
 
     l2x0_fake     = IsaFake(pio_addr=0x1f002000, pio_size=0xfff, warn_access="1")
     flash_fake    = IsaFake(pio_addr=0x40000000, pio_size=0x20000000-1,
@@ -904,8 +905,8 @@ class VExpress_EMM(RealView):
     timer0 = Sp804(int_num0=34, int_num1=34, pio_addr=0x1C110000, clock0='1MHz', clock1='1MHz')
     timer1 = Sp804(int_num0=35, int_num1=35, pio_addr=0x1C120000, clock0='1MHz', clock1='1MHz')
     clcd   = Pl111(pio_addr=0x1c1f0000, int_num=46)
-    kmi0   = Pl050(pio_addr=0x1c060000, int_num=44)
-    kmi1   = Pl050(pio_addr=0x1c070000, int_num=45, is_mouse=True)
+    kmi0   = Pl050(pio_addr=0x1c060000, int_num=44, ps2=PS2Keyboard())
+    kmi1   = Pl050(pio_addr=0x1c070000, int_num=45, ps2=PS2TouchKit())
     cf_ctrl = IdeController(disks=[], pci_func=0, pci_dev=0, pci_bus=2,
                             io_shift = 2, ctrl_offset = 2, Command = 0x1,
                             BAR0 = 0x1C1A0000, BAR0Size = '256B',
@@ -1136,8 +1137,8 @@ Interrupts:
 
     uart0 = Pl011(pio_addr=0x1c090000, int_num=37)
 
-    kmi0 = Pl050(pio_addr=0x1c060000, int_num=44)
-    kmi1 = Pl050(pio_addr=0x1c070000, int_num=45, is_mouse=True)
+    kmi0 = Pl050(pio_addr=0x1c060000, int_num=44, ps2=PS2Keyboard())
+    kmi1 = Pl050(pio_addr=0x1c070000, int_num=45, ps2=PS2TouchKit())
 
     rtc = PL031(pio_addr=0x1c170000, int_num=36)
 
index 8b373b8194e58c872227ee2cea505d126f788ed3..d80bc14e98414a3e87450d02f044bc6357aa29ef 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2017 ARM Limited
+ * Copyright (c) 2010, 2017-2018 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
 #include "debug/Pl050.hh"
 #include "dev/arm/amba_device.hh"
 #include "dev/ps2.hh"
+#include "dev/ps2/device.hh"
 #include "mem/packet.hh"
 #include "mem/packet_access.hh"
 
-Pl050::Pl050(const Params *p)
+Pl050::Pl050(const Pl050Params *p)
     : AmbaIntDevice(p, 0xfff), control(0), status(0x43), clkdiv(0),
-      rawInterrupts(0), ackNext(false), shiftDown(false),
-      vnc(p->vnc), driverInitialized(false),
-      intEvent([this]{ generateInterrupt(); }, name())
+      rawInterrupts(0),
+      intEvent([this]{ generateInterrupt(); }, name()),
+      ps2(p->ps2)
 {
-    if (vnc) {
-        if (!p->is_mouse)
-            vnc->setKeyboard(this);
-        else
-            vnc->setMouse(this);
-    }
+    ps2->hostRegDataAvailable([this]() { this->updateIntStatus(); });
 }
 
 Tick
@@ -79,32 +75,28 @@ Pl050::read(PacketPtr pkt)
         DPRINTF(Pl050, "Read Commmand: %#x\n", (uint32_t)control);
         data = control;
         break;
-      case kmiStat:
-        if (rxQueue.empty())
-            status.rxfull = 0;
-        else
-            status.rxfull = 1;
 
+      case kmiStat:
+        status.rxfull = ps2->hostDataAvailable() ? 1 : 0;
         DPRINTF(Pl050, "Read Status: %#x\n", (uint32_t)status);
         data = status;
         break;
+
       case kmiData:
-        if (rxQueue.empty()) {
-            data = 0;
-        } else {
-            data = rxQueue.front();
-            rxQueue.pop_front();
-        }
+        data = ps2->hostDataAvailable() ? ps2->hostRead() : 0;
         DPRINTF(Pl050, "Read Data: %#x\n", (uint32_t)data);
         updateIntStatus();
         break;
+
       case kmiClkDiv:
         data = clkdiv;
         break;
+
       case kmiISR:
         data = getInterrupt();
         DPRINTF(Pl050, "Read Interrupts: %#x\n", getInterrupt());
         break;
+
       default:
         if (readId(pkt, ambaId, pioAddr)) {
             // Hack for variable size accesses
@@ -152,99 +144,33 @@ Pl050::write(PacketPtr pkt)
         control = pkt->get<uint8_t>();
         updateIntStatus();
         break;
+
       case kmiData:
         DPRINTF(Pl050, "Write Data: %#x\n", (uint32_t)pkt->get<uint8_t>());
-        processCommand(pkt->get<uint8_t>());
+        ps2->hostWrite(pkt->get<uint8_t>());
         updateIntStatus();
         break;
+
       case kmiClkDiv:
         clkdiv = pkt->get<uint8_t>();
         break;
+
       default:
         warn("Tried to write PL050 at offset %#x that doesn't exist\n", daddr);
         break;
     }
+
     pkt->makeAtomicResponse();
     return pioDelay;
 }
 
-void
-Pl050::processCommand(uint8_t byte)
-{
-    using namespace Ps2;
-
-    if (ackNext) {
-        ackNext--;
-        rxQueue.push_back(Ack);
-        updateIntStatus();
-        return;
-    }
-
-    switch (byte) {
-      case Ps2Reset:
-        rxQueue.push_back(Ack);
-        rxQueue.push_back(SelfTestPass);
-        break;
-      case SetResolution:
-      case SetRate:
-      case SetStatusLed:
-        rxQueue.push_back(Ack);
-        ackNext = 1;
-        break;
-      case ReadId:
-        rxQueue.push_back(Ack);
-        if (params()->is_mouse)
-            rxQueue.push_back(MouseId);
-        else
-            rxQueue.push_back(KeyboardId);
-        break;
-      case TpReadId:
-        if (!params()->is_mouse)
-            break;
-        // We're not a trackpoint device, this should make the probe go away
-        rxQueue.push_back(Ack);
-        rxQueue.push_back(0);
-        rxQueue.push_back(0);
-        // fall through
-      case Disable:
-      case Enable:
-      case SetDefaults:
-      case SetScaling1_1:
-      case SetScaling1_2:
-        rxQueue.push_back(Ack);
-        break;
-      case StatusRequest:
-        rxQueue.push_back(Ack);
-        rxQueue.push_back(0);
-        rxQueue.push_back(2); // default resolution
-        rxQueue.push_back(100); // default sample rate
-        break;
-      case TouchKitId:
-        ackNext = 2;
-        rxQueue.push_back(Ack);
-        rxQueue.push_back(TouchKitId);
-        rxQueue.push_back(1);
-        rxQueue.push_back('A');
-
-        driverInitialized = true;
-        break;
-      default:
-        panic("Unknown byte received: %d\n", byte);
-    }
-
-    updateIntStatus();
-}
-
 
 void
 Pl050::updateIntStatus()
 {
     const bool old_interrupt(getInterrupt());
 
-    if (!rxQueue.empty())
-        rawInterrupts.rx = 1;
-    else
-        rawInterrupts.rx = 0;
+    rawInterrupts.rx = ps2->hostDataAvailable() ? 1 : 0;
 
     if ((!old_interrupt && getInterrupt()) && !intEvent.scheduled()) {
         schedule(intEvent, curTick() + intDelay);
@@ -253,6 +179,17 @@ Pl050::updateIntStatus()
     }
 }
 
+Pl050::InterruptReg
+Pl050::getInterrupt() const
+{
+    InterruptReg tmp_interrupt(0);
+
+    tmp_interrupt.tx = rawInterrupts.tx & control.txint_enable;
+    tmp_interrupt.rx = rawInterrupts.rx & control.rxint_enable;
+
+    return tmp_interrupt;
+}
+
 void
 Pl050::generateInterrupt()
 {
@@ -265,51 +202,6 @@ Pl050::generateInterrupt()
     }
 }
 
-void
-Pl050::mouseAt(uint16_t x, uint16_t y, uint8_t buttons)
-{
-    using namespace Ps2;
-
-    // If the driver hasn't initialized the device yet, no need to try and send
-    // it anything. Similarly we can get vnc mouse events orders of maginture
-    // faster than m5 can process them. Only queue up two sets mouse movements
-    // and don't add more until those are processed.
-    if (!driverInitialized || rxQueue.size() > 10)
-        return;
-
-    // We shouldn't be here unless a vnc server called us in which case
-    // we should have a pointer to it
-    assert(vnc);
-
-    // Convert screen coordinates to touchpad coordinates
-    uint16_t _x = (2047.0/vnc->videoWidth()) * x;
-    uint16_t _y = (2047.0/vnc->videoHeight()) * y;
-
-    rxQueue.push_back(buttons);
-    rxQueue.push_back(_x >> 7);
-    rxQueue.push_back(_x & 0x7f);
-    rxQueue.push_back(_y >> 7);
-    rxQueue.push_back(_y & 0x7f);
-
-    updateIntStatus();
-}
-
-
-void
-Pl050::keyPress(uint32_t key, bool down)
-{
-    using namespace Ps2;
-
-    std::list<uint8_t> keys;
-
-    // convert the X11 keysym into ps2 codes
-    keySymToPs2(key, down, shiftDown, keys);
-
-    // Insert into our queue of charecters
-    rxQueue.splice(rxQueue.end(), keys);
-    updateIntStatus();
-}
-
 void
 Pl050::serialize(CheckpointOut &cp) const
 {
@@ -322,12 +214,6 @@ Pl050::serialize(CheckpointOut &cp) const
 
     uint8_t raw_ints = rawInterrupts;
     SERIALIZE_SCALAR(raw_ints);
-
-    SERIALIZE_SCALAR(ackNext);
-    SERIALIZE_SCALAR(shiftDown);
-    SERIALIZE_SCALAR(driverInitialized);
-
-    SERIALIZE_CONTAINER(rxQueue);
 }
 
 void
@@ -346,16 +232,8 @@ Pl050::unserialize(CheckpointIn &cp)
     uint8_t raw_ints;
     UNSERIALIZE_SCALAR(raw_ints);
     rawInterrupts = raw_ints;
-
-    UNSERIALIZE_SCALAR(ackNext);
-    UNSERIALIZE_SCALAR(shiftDown);
-    UNSERIALIZE_SCALAR(driverInitialized);
-
-    UNSERIALIZE_CONTAINER(rxQueue);
 }
 
-
-
 Pl050 *
 Pl050Params::create()
 {
index 0593165c0949440304c1ee3d9dad63d243cd51a6..16a61a18162c1dcb4994221baa3702c8311fbcad 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2017 ARM Limited
+ * Copyright (c) 2010, 2017-2018 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -54,7 +54,9 @@
 #include "dev/arm/amba_device.hh"
 #include "params/Pl050.hh"
 
-class Pl050 : public AmbaIntDevice, public VncKeyboard, public VncMouse
+class PS2Device;
+
+class Pl050 : public AmbaIntDevice
 {
   protected:
     static const int kmiCr       = 0x000;
@@ -104,21 +106,6 @@ class Pl050 : public AmbaIntDevice, public VncKeyboard, public VncMouse
     /** raw interrupt register (unmasked) */
     InterruptReg rawInterrupts;
 
-    /** If the controller should ignore the next data byte and acknowledge it.
-     * The driver is attempting to setup some feature we don't care about
-     */
-    int ackNext;
-
-    /** is the shift key currently down */
-    bool shiftDown;
-
-    /** The vnc server we're connected to (if any) */
-    VncInput *vnc;
-
-    /** If the linux driver has initialized the device yet and thus can we send
-     * mouse data */
-    bool driverInitialized;
-
     /** Update the status of the interrupt registers and schedule an interrupt
      * if required */
     void updateIntStatus();
@@ -127,40 +114,20 @@ class Pl050 : public AmbaIntDevice, public VncKeyboard, public VncMouse
     void generateInterrupt();
 
     /** Get interrupt value */
-    InterruptReg getInterrupt() const {
-        InterruptReg tmp_interrupt(0);
-        tmp_interrupt.tx = rawInterrupts.tx & control.txint_enable;
-        tmp_interrupt.rx = rawInterrupts.rx & control.rxint_enable;
-        return tmp_interrupt;
-    }
+    InterruptReg getInterrupt() const;
+
     /** Wrapper to create an event out of the thing */
     EventFunctionWrapper intEvent;
 
-    /** Receive queue. This list contains all the pending commands that
-     * need to be sent to the driver
-     */
-    std::list<uint8_t> rxQueue;
-
-    /** Handle a command sent to the kmi and respond appropriately
-     */
-    void processCommand(uint8_t byte);
+    /** PS2 device connected to this KMI interface */
+    PS2Device *ps2;
 
   public:
-    typedef Pl050Params Params;
-    const Params *
-    params() const
-    {
-        return dynamic_cast<const Params *>(_params);
-    }
-
-    Pl050(const Params *p);
+    Pl050(const Pl050Params *p);
 
     Tick read(PacketPtr pkt) override;
     Tick write(PacketPtr pkt) override;
 
-    void mouseAt(uint16_t x, uint16_t y, uint8_t buttons) override;
-    void keyPress(uint32_t key, bool down) override;
-
     void serialize(CheckpointOut &cp) const override;
     void unserialize(CheckpointIn &cp) override;
 };