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
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)])
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,
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,
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',
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)
/*
- * 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
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
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);
}
}
+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()
{
}
}
-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
{
uint8_t raw_ints = rawInterrupts;
SERIALIZE_SCALAR(raw_ints);
-
- SERIALIZE_SCALAR(ackNext);
- SERIALIZE_SCALAR(shiftDown);
- SERIALIZE_SCALAR(driverInitialized);
-
- SERIALIZE_CONTAINER(rxQueue);
}
void
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()
{
/*
- * 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 "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;
/** 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();
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;
};