VNC/ARM: Use VNC server and add support to boot into X11
authorAli Saidi <Ali.Saidi@ARM.com>
Sat, 12 Feb 2011 00:29:36 +0000 (18:29 -0600)
committerAli Saidi <Ali.Saidi@ARM.com>
Sat, 12 Feb 2011 00:29:36 +0000 (18:29 -0600)
12 files changed:
src/dev/SConscript
src/dev/arm/RealView.py
src/dev/arm/amba_device.cc
src/dev/arm/amba_device.hh
src/dev/arm/kmi.cc
src/dev/arm/kmi.hh
src/dev/arm/pl111.cc
src/dev/arm/pl111.hh
src/dev/arm/rv_ctrl.cc
src/dev/arm/rv_ctrl.hh
src/dev/ps2.cc [new file with mode: 0644]
src/dev/ps2.hh [new file with mode: 0644]

index 7cdea7961fea5d40b2e4ddd7aeaa35e7c8724f43..5243da683c9ddbe98822b51b255abf2276d6e758 100644 (file)
@@ -69,6 +69,7 @@ if env['FULL_SYSTEM']:
     Source('pcidev.cc')
     Source('pktfifo.cc')
     Source('platform.cc')
+    Source('ps2.cc')
     Source('simple_disk.cc')
     Source('sinic.cc')
     Source('terminal.cc')
index cdc06e4ef75f6784cd621dbefc8d639ea6b7e5fb..ef3f68a8848317076f95974cd129b5317bcc095f 100644 (file)
@@ -52,6 +52,14 @@ class AmbaDevice(BasicPioDevice):
     abstract = True
     amba_id = Param.UInt32("ID of AMBA device for kernel detection")
 
+class AmbaIntDevice(AmbaDevice):
+    type = 'AmbaIntDevice'
+    abstract = True
+    gic = Param.Gic(Parent.any, "Gic to use for interrupting")
+    int_num = Param.UInt32("Interrupt number that connects to GIC")
+    int_delay = Param.Latency("100ns",
+            "Time between action and interrupt generation by device")
+
 class AmbaDmaDevice(DmaDevice):
     type = 'AmbaDmaDevice'
     abstract = True
@@ -94,16 +102,17 @@ class Sp804(AmbaDevice):
     clock1 = Param.Clock('1MHz', "Clock speed of the input")
     amba_id = 0x00141804
 
-class Pl050(AmbaDevice):
+class Pl050(AmbaIntDevice):
     type = 'Pl050'
-    gic = Param.Gic(Parent.any, "Gic to use for interrupting")
-    int_num = Param.UInt32("Interrupt number that connects to GIC")
-    int_delay = Param.Latency("100ns", "Time between action and interrupt generation by UART")
+    vnc = Param.VncServer(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
 
 class Pl111(AmbaDmaDevice):
     type = 'Pl111'
     clock = Param.Clock('24MHz', "Clock speed of the input")
+    vnc   = Param.VncServer(Parent.any, "Vnc server for remote frame buffer display")
     amba_id = 0x00141111
 
 class RealView(Platform):
@@ -121,7 +130,7 @@ class RealViewPBX(RealView):
     timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000)
     clcd = Pl111(pio_addr=0x10020000, int_num=55)
     kmi0   = Pl050(pio_addr=0x10006000, int_num=52)
-    kmi1   = Pl050(pio_addr=0x10007000, int_num=53)
+    kmi1   = Pl050(pio_addr=0x10007000, int_num=53, is_mouse=True)
 
     l2x0_fake     = IsaFake(pio_addr=0x1f002000, pio_size=0xfff)
     flash_fake    = IsaFake(pio_addr=0x40000000, pio_size=0x4000000)
@@ -140,7 +149,7 @@ class RealViewPBX(RealView):
     aaci_fake     = AmbaFake(pio_addr=0x10004000)
     mmc_fake      = AmbaFake(pio_addr=0x10005000)
     rtc_fake      = AmbaFake(pio_addr=0x10017000, amba_id=0x41031)
-
+    cf0_fake      = IsaFake(pio_addr=0x18000000, pio_size=0xfff)
 
 
     # Attach I/O devices that are on chip
@@ -175,6 +184,7 @@ class RealViewPBX(RealView):
        self.mmc_fake.pio      = bus.port
        self.rtc_fake.pio      = bus.port
        self.flash_fake.pio    = bus.port
+       self.cf0_fake.pio      = bus.port
 
 # Reference for memory map and interrupt number
 # RealView Emulation Baseboard User Guide (ARM DUI 0143B)
@@ -187,7 +197,7 @@ class RealViewEB(RealView):
     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)
+    kmi1   = Pl050(pio_addr=0x10007000, int_num=21, is_mouse=True)
 
     l2x0_fake     = IsaFake(pio_addr=0x1f002000, pio_size=0xfff, warn_access="1")
     dmac_fake     = AmbaFake(pio_addr=0x10030000)
index e5d53d6a38b3b33929bc8a93c5ecc43e49bd140b..37eb77ae1b1d8f1418618a83b176a56e1ac88494 100644 (file)
 #include "mem/packet_access.hh"
 
 const uint64_t AmbaVendor = ULL(0xb105f00d00000000);
+
 AmbaDevice::AmbaDevice(const Params *p)
     : BasicPioDevice(p), ambaId(AmbaVendor | p->amba_id)
 {
 }
 
+AmbaIntDevice::AmbaIntDevice(const Params *p)
+    : AmbaDevice(p), intNum(p->int_num), gic(p->gic), intDelay(p->int_delay)
+{
+}
+
+
+
 AmbaDmaDevice::AmbaDmaDevice(const Params *p)
     : DmaDevice(p), ambaId(AmbaVendor | p->amba_id),
       pioAddr(p->pio_addr), pioSize(0),
index 1782fb003fbf49413e9b41e022b902fceb66c2b0..297a78f8278f1de7c7154a10e104e16aeb79a26c 100644 (file)
@@ -55,6 +55,7 @@
 #include "mem/packet.hh"
 #include "mem/packet_access.hh"
 #include "params/AmbaDevice.hh"
+#include "params/AmbaIntDevice.hh"
 #include "params/AmbaDmaDevice.hh"
 
 namespace AmbaDev {
@@ -81,6 +82,18 @@ class AmbaDevice : public BasicPioDevice
     AmbaDevice(const Params *p);
 };
 
+class AmbaIntDevice : public AmbaDevice
+{
+  protected:
+    int intNum;
+    Gic *gic;
+    Tick intDelay;
+
+  public:
+    typedef AmbaIntDeviceParams Params;
+    AmbaIntDevice(const Params *p);
+};
+
 class AmbaDmaDevice : public DmaDevice
 {
   protected:
index 6cd61fd090b88fe294da77fd569f89f3475fca35..adf1439b3b3a0a66349072241cf4ce0d269177b3 100644 (file)
  * (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: William Wang
+ * Authors: Ali Saidi
+ *          William Wang
  */
 
 #include "base/trace.hh"
+#include "base/vnc/vncserver.hh"
 #include "dev/arm/amba_device.hh"
 #include "dev/arm/kmi.hh"
+#include "dev/ps2.hh"
 #include "mem/packet.hh"
 #include "mem/packet_access.hh"
 
 Pl050::Pl050(const Params *p)
-    : AmbaDevice(p), control(0x00), status(0x43), kmidata(0x00), clkdiv(0x00),
-      intreg(0x00), intNum(p->int_num), gic(p->gic), intDelay(p->int_delay),
-      intEvent(this)
+    : AmbaIntDevice(p), control(0), status(0x43), clkdiv(0), interrupts(0),
+      rawInterrupts(0), ackNext(false), shiftDown(false), vnc(p->vnc),
+      driverInitialized(false), intEvent(this)
 {
     pioSize = 0xfff;
+
+    if (vnc) {
+        if (!p->is_mouse)
+            vnc->setKeyboard(this);
+        else
+            vnc->setMouse(this);
+    }
 }
 
 Tick
@@ -62,28 +72,39 @@ Pl050::read(PacketPtr pkt)
     Addr daddr = pkt->getAddr() - pioAddr;
     pkt->allocate();
 
-    DPRINTF(Pl050, " read register %#x size=%d\n", daddr, pkt->getSize());
 
-    // use a temporary data since the KMI registers are read/written with
-    // different size operations
-    //
     uint32_t data = 0;
 
     switch (daddr) {
       case kmiCr:
+        DPRINTF(Pl050, "Read Commmand: %#x\n", (uint32_t)control);
         data = control;
         break;
       case kmiStat:
+        if (rxQueue.empty())
+            status.rxfull = 0;
+        else
+            status.rxfull = 1;
+
+        DPRINTF(Pl050, "Read Status: %#x\n", (uint32_t)status);
         data = status;
         break;
       case kmiData:
-        data = kmidata;
+        if (rxQueue.empty()) {
+            data = 0;
+        } else {
+            data = rxQueue.front();
+            rxQueue.pop_front();
+        }
+        DPRINTF(Pl050, "Read Data: %#x\n", (uint32_t)data);
+        updateIntStatus();
         break;
       case kmiClkDiv:
         data = clkdiv;
         break;
       case kmiISR:
-        data = intreg;
+        data = interrupts;
+        DPRINTF(Pl050, "Read Interrupts: %#x\n", (uint32_t)interrupts);
         break;
       default:
         if (AmbaDev::readId(pkt, ambaId, pioAddr)) {
@@ -123,65 +144,224 @@ Pl050::write(PacketPtr pkt)
 
     Addr daddr = pkt->getAddr() - pioAddr;
 
-    DPRINTF(Pl050, " write register %#x value %#x size=%d\n", daddr,
-            pkt->get<uint8_t>(), pkt->getSize());
+    assert(pkt->getSize() == sizeof(uint8_t));
 
-    // use a temporary data since the KMI registers are read/written with
-    // different size operations
-    //
-    uint32_t data = 0;
 
-    switch (pkt->getSize()) {
-      case 1:
-        data = pkt->get<uint8_t>();
+    switch (daddr) {
+      case kmiCr:
+        DPRINTF(Pl050, "Write Commmand: %#x\n", (uint32_t)pkt->get<uint8_t>());
+        control = pkt->get<uint8_t>();
+        updateIntStatus();
         break;
-      case 2:
-        data = pkt->get<uint16_t>();
+      case kmiData:
+        DPRINTF(Pl050, "Write Data: %#x\n", (uint32_t)pkt->get<uint8_t>());
+        processCommand(pkt->get<uint8_t>());
+        updateIntStatus();
         break;
-      case 4:
-        data = pkt->get<uint32_t>();
+      case kmiClkDiv:
+        clkdiv = pkt->get<uint8_t>();
         break;
       default:
-        panic("KMI write size too big?\n");
+        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;
 
-    switch (daddr) {
-      case kmiCr:
-        control = data;
+    if (ackNext) {
+        ackNext--;
+        rxQueue.push_back(Ack);
+        updateIntStatus();
+        return;
+    }
+
+    switch (byte) {
+      case Ps2Reset:
+        rxQueue.push_back(Ack);
+        rxQueue.push_back(SelfTestPass);
         break;
-      case kmiStat:
-        panic("Tried to write PL050 register(read only) at offset %#x\n",
-              daddr);
+      case SetResolution:
+      case SetRate:
+      case SetStatusLed:
+      case SetScaling1_1:
+      case SetScaling1_2:
+        rxQueue.push_back(Ack);
+        ackNext = 1;
         break;
-      case kmiData:
-        kmidata = data;
+      case ReadId:
+        rxQueue.push_back(Ack);
+        if (params()->is_mouse)
+            rxQueue.push_back(MouseId);
+        else
+            rxQueue.push_back(KeyboardId);
         break;
-      case kmiClkDiv:
-        clkdiv = data;
+      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:
+        rxQueue.push_back(Ack);
         break;
-      case kmiISR:
-        panic("Tried to write PL050 register(read only) at offset %#x\n",
-              daddr);
+      case StatusRequest:
+        rxQueue.push_back(Ack);
+        rxQueue.push_back(0);
+        rxQueue.push_back(2); // default resolution
+        rxQueue.push_back(100); // default sample rate
         break;
-      default:
-        warn("Tried to write PL050 at offset %#x that doesn't exist\n", daddr);
+      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);
     }
-    pkt->makeAtomicResponse();
-    return pioDelay;
+
+    updateIntStatus();
+}
+
+
+void
+Pl050::updateIntStatus()
+{
+    if (!rxQueue.empty())
+        rawInterrupts.rx = 1;
+    else
+        rawInterrupts.rx = 0;
+
+    interrupts.tx = rawInterrupts.tx & control.txint_enable;
+    interrupts.rx = rawInterrupts.rx & control.rxint_enable;
+
+    DPRINTF(Pl050, "rawInterupts=%#x control=%#x interrupts=%#x\n",
+            (uint32_t)rawInterrupts, (uint32_t)control, (uint32_t)interrupts);
+
+    if (interrupts && !intEvent.scheduled())
+        schedule(intEvent, curTick() + intDelay);
 }
 
 void
 Pl050::generateInterrupt()
 {
-    if (intreg.rxintr || intreg.txintr) {
+
+    if (interrupts) {
         gic->sendInt(intNum);
-        DPRINTF(Pl050, " -- Generated\n");
+        DPRINTF(Pl050, "Generated interrupt\n");
     }
 }
 
+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(std::ostream &os)
+{
+    uint8_t ctrlreg = control;
+    SERIALIZE_SCALAR(ctrlreg);
+
+    uint8_t stsreg = status;
+    SERIALIZE_SCALAR(stsreg);
+    SERIALIZE_SCALAR(clkdiv);
+
+    uint8_t ints = interrupts;
+    SERIALIZE_SCALAR(ints);
+
+    uint8_t raw_ints = rawInterrupts;
+    SERIALIZE_SCALAR(raw_ints);
+
+    SERIALIZE_SCALAR(ackNext);
+    SERIALIZE_SCALAR(shiftDown);
+    SERIALIZE_SCALAR(driverInitialized);
+
+    arrayParamOut(os, "rxQueue", rxQueue);
+}
+
+void
+Pl050::unserialize(Checkpoint *cp, const std::string &section)
+{
+    uint8_t ctrlreg;
+    UNSERIALIZE_SCALAR(ctrlreg);
+    control = ctrlreg;
+
+    uint8_t stsreg;
+    UNSERIALIZE_SCALAR(stsreg);
+    status = stsreg;
+
+    UNSERIALIZE_SCALAR(clkdiv);
+
+    uint8_t ints;
+    UNSERIALIZE_SCALAR(ints);
+    interrupts = ints;
+
+    uint8_t raw_ints;
+    UNSERIALIZE_SCALAR(raw_ints);
+    rawInterrupts = raw_ints;
+
+    UNSERIALIZE_SCALAR(ackNext);
+    UNSERIALIZE_SCALAR(shiftDown);
+    UNSERIALIZE_SCALAR(driverInitialized);
+
+    arrayParamIn(cp, section, "rxQueue", rxQueue);
+}
+
+
+
 Pl050 *
 Pl050Params::create()
 {
index c96dd55a976683281523e7da0e474474e1bf238f..1e25f8974832938de435a8288a43c966b4fdf465 100644 (file)
 #ifndef __DEV_ARM_PL050_HH__
 #define __DEV_ARM_PL050_HH__
 
+#include <list>
+
 #include "base/range.hh"
-#include "dev/io_device.hh"
+#include "base/vnc/vncserver.hh"
+#include "dev/arm/amba_device.hh"
 #include "params/Pl050.hh"
 
 class Gic;
 
-class Pl050 : public AmbaDevice
+class Pl050 : public AmbaIntDevice, public VncKeyboard, public VncMouse
 {
   protected:
     static const int kmiCr       = 0x000;
@@ -63,34 +66,68 @@ class Pl050 : public AmbaDevice
     static const int kmiClkDiv   = 0x00C;
     static const int kmiISR      = 0x010;
 
-    // control register
-    uint8_t control;
+    BitUnion8(ControlReg)
+        Bitfield<0> force_clock_low;
+        Bitfield<1> force_data_low;
+        Bitfield<2> enable;
+        Bitfield<3> txint_enable;
+        Bitfield<4> rxint_enable;
+        Bitfield<5> type;
+    EndBitUnion(ControlReg)
 
-    // status register
-    uint8_t status;
+    /** control register
+     */
+    ControlReg control;
+
+    /** KMI status register */
+    BitUnion8(StatusReg)
+        Bitfield<0> data_in;
+        Bitfield<1> clk_in;
+        Bitfield<2> rxparity;
+        Bitfield<3> rxbusy;
+        Bitfield<4> rxfull;
+        Bitfield<5> txbusy;
+        Bitfield<6> txempty;
+    EndBitUnion(StatusReg)
+
+    StatusReg status;
+
+    /** clock divisor register
+     * This register is just kept around to satisfy reads after driver does
+     * writes. The divsor does nothing, as we're not actually signaling ps2
+     * serial commands to anything.
+     */
+    uint8_t clkdiv;
 
-    // received data (read) or data to be transmitted (write)
-    uint8_t kmidata;
+    BitUnion8(InterruptReg)
+        Bitfield<0> rx;
+        Bitfield<1> tx;
+    EndBitUnion(InterruptReg)
 
-    // clock divisor register
-    uint8_t clkdiv;
+    /** interrupt status register. */
+    InterruptReg interrupts;
+
+    /** raw interrupt register (unmasked) */
+    InterruptReg rawInterrupts;
 
-    BitUnion8(IntReg)
-    Bitfield<0> txintr;
-    Bitfield<1> rxintr;
-    EndBitUnion(IntReg)
+    /** 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;
 
-    /** interrupt mask register. */
-    IntReg intreg;
+    /** is the shift key currently down */
+    bool shiftDown;
 
-    /** Interrupt number to generate */
-    int intNum;
+    /** The vnc server we're connected to (if any) */
+    VncServer *vnc;
 
-    /** Gic to use for interrupting */
-    Gic *gic;
+    /** If the linux driver has initialized the device yet and thus can we send
+     * mouse data */
+    bool driverInitialized;
 
-    /** Delay before interrupting */
-    Tick intDelay;
+    /** Update the status of the interrupt registers and schedule an interrupt
+     * if required */
+    void updateIntStatus();
 
     /** Function to generate interrupt */
     void generateInterrupt();
@@ -98,6 +135,15 @@ class Pl050 : public AmbaDevice
     /** Wrapper to create an event out of the thing */
     EventWrapper<Pl050, &Pl050::generateInterrupt> 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);
+
   public:
     typedef Pl050Params Params;
     const Params *
@@ -111,12 +157,11 @@ class Pl050 : public AmbaDevice
     virtual Tick read(PacketPtr pkt);
     virtual Tick write(PacketPtr pkt);
 
-    /**
-     * Return if we have an interrupt pending
-     * @return interrupt status
-     * @todo fix me when implementation improves
-     */
-    virtual bool intStatus() { return false; }
+    virtual void mouseAt(uint16_t x, uint16_t y, uint8_t buttons);
+    virtual void keyPress(uint32_t key, bool down);
+
+    virtual void serialize(std::ostream &os);
+    virtual void unserialize(Checkpoint *cp, const std::string &section);
 };
 
-#endif
+#endif // __DEV_ARM_PL050_HH__
index e597bf27242de2bf40c49a93c77e530d8f09d526..e884d9b58f494a5001791a35628a3a95b5b85217 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: William Wang
+ *          Ali Saidi
  */
 
+#include "base/bitmap.hh"
+#include "base/output.hh"
 #include "base/trace.hh"
+#include "base/vnc/vncserver.hh"
 #include "dev/arm/amba_device.hh"
 #include "dev/arm/gic.hh"
 #include "dev/arm/pl111.hh"
@@ -50,20 +54,27 @@ using namespace AmbaDev;
 Pl111::Pl111(const Params *p)
     : AmbaDmaDevice(p), lcdTiming0(0), lcdTiming1(0), lcdTiming2(0),
       lcdTiming3(0), lcdUpbase(0), lcdLpbase(0), lcdControl(0), lcdImsc(0),
-      lcdRis(0), lcdMis(0), lcdIcr(0), lcdUpcurr(0), lcdLpcurr(0),
+      lcdRis(0), lcdMis(0),
       clcdCrsrCtrl(0), clcdCrsrConfig(0), clcdCrsrPalette0(0),
       clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0),
       clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0), clock(p->clock),
-      height(0), width(0), startTime(0), startAddr(0), maxAddr(0), curAddr(0),
+      vncserver(p->vnc), bmp(NULL), width(LcdMaxWidth), height(LcdMaxHeight),
+      bytesPerPixel(4), startTime(0), startAddr(0), maxAddr(0), curAddr(0),
       waterMark(0), dmaPendingNum(0), readEvent(this), fillFifoEvent(this),
       dmaDoneEvent(maxOutstandingDma, this), intEvent(this)
 {
     pioSize = 0xFFFF;
 
+    pic = simout.create("framebuffer.bmp", true);
+
+    dmaBuffer = new uint8_t[LcdMaxWidth * LcdMaxHeight * sizeof(uint32_t)];
+
     memset(lcdPalette, 0, sizeof(lcdPalette));
     memset(cursorImage, 0, sizeof(cursorImage));
     memset(dmaBuffer, 0, sizeof(dmaBuffer));
-    memset(frameBuffer, 0, sizeof(frameBuffer));
+
+    if (vncserver)
+        vncserver->setFramebufferAddr(dmaBuffer);
 }
 
 // read registers and frame buffer
@@ -75,111 +86,105 @@ Pl111::read(PacketPtr pkt)
 
     uint32_t data = 0;
 
-    if ((pkt->getAddr()& 0xffff0000) == pioAddr) {
+    assert(pkt->getAddr() >= pioAddr &&
+           pkt->getAddr() < pioAddr + pioSize);
 
-        assert(pkt->getAddr() >= pioAddr &&
-               pkt->getAddr() < pioAddr + pioSize);
+    Addr daddr = pkt->getAddr() - pioAddr;
+    pkt->allocate();
 
-        Addr daddr = pkt->getAddr()&0xFFFF;
-        pkt->allocate();
+    DPRINTF(PL111, " read register %#x size=%d\n", daddr, pkt->getSize());
 
-        DPRINTF(PL111, " read register %#x size=%d\n", daddr, pkt->getSize());
-
-        switch (daddr) {
-          case LcdTiming0:
-            data = lcdTiming0;
-            break;
-          case LcdTiming1:
-            data = lcdTiming1;
-            break;
-          case LcdTiming2:
-            data = lcdTiming2;
-            break;
-          case LcdTiming3:
-            data = lcdTiming3;
-            break;
-          case LcdUpBase:
-            data = lcdUpbase;
-            break;
-          case LcdLpBase:
-            data = lcdLpbase;
-            break;
-          case LcdControl:
-            data = lcdControl;
-            break;
-          case LcdImsc:
-            warn("LCD interrupt set/clear function not supported\n");
-            data = lcdImsc;
-            break;
-          case LcdRis:
-            warn("LCD Raw interrupt status function not supported\n");
-            data = lcdRis;
-            break;
-          case LcdMis:
-            warn("LCD Masked interrupt status function not supported\n");
-            data = lcdMis;
-            break;
-          case LcdIcr:
-            panic("LCD register at offset %#x is Write-Only\n", daddr);
-            break;
-          case LcdUpCurr:
-            data = lcdUpcurr;
-            break;
-          case LcdLpCurr:
-            data = lcdLpcurr;
-            break;
-          case ClcdCrsrCtrl:
-            data = clcdCrsrCtrl;
-            break;
-          case ClcdCrsrConfig:
-            data = clcdCrsrConfig;
-            break;
-          case ClcdCrsrPalette0:
-            data = clcdCrsrPalette0;
-            break;
-          case ClcdCrsrPalette1:
-            data = clcdCrsrPalette1;
-            break;
-          case ClcdCrsrXY:
-            data = clcdCrsrXY;
-            break;
-          case ClcdCrsrClip:
-            data = clcdCrsrClip;
-            break;
-          case ClcdCrsrImsc:
-            data = clcdCrsrImsc;
-            break;
-          case ClcdCrsrIcr:
-            panic("CLCD register at offset %#x is Write-Only\n", daddr);
-            break;
-          case ClcdCrsrRis:
-            data = clcdCrsrRis;
-            break;
-          case ClcdCrsrMis:
-            data = clcdCrsrMis;
-            break;
-          default:
-            if (AmbaDev::readId(pkt, AMBA_ID, pioAddr)) {
-                // Hack for variable size accesses
-                data = pkt->get<uint32_t>();
-                break;
-            } else if (daddr >= CrsrImage && daddr <= 0xBFC) {
-                // CURSOR IMAGE
-                int index;
-                index = (daddr - CrsrImage) >> 2;
-                data= cursorImage[index];
-                break;
-            } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
-                // LCD Palette
-                int index;
-                index = (daddr - LcdPalette) >> 2;
-                data = lcdPalette[index];
-                break;
-            } else {
-                panic("Tried to read CLCD register at offset %#x that \
+    switch (daddr) {
+      case LcdTiming0:
+        data = lcdTiming0;
+        break;
+      case LcdTiming1:
+        data = lcdTiming1;
+        break;
+      case LcdTiming2:
+        data = lcdTiming2;
+        break;
+      case LcdTiming3:
+        data = lcdTiming3;
+        break;
+      case LcdUpBase:
+        data = lcdUpbase;
+        break;
+      case LcdLpBase:
+        data = lcdLpbase;
+        break;
+      case LcdControl:
+        data = lcdControl;
+        break;
+      case LcdImsc:
+        data = lcdImsc;
+        break;
+      case LcdRis:
+        data = lcdRis;
+        break;
+      case LcdMis:
+        data = lcdMis;
+        break;
+      case LcdIcr:
+        panic("LCD register at offset %#x is Write-Only\n", daddr);
+        break;
+      case LcdUpCurr:
+        data = curAddr;
+        break;
+      case LcdLpCurr:
+        data = curAddr;
+        break;
+      case ClcdCrsrCtrl:
+        data = clcdCrsrCtrl;
+        break;
+      case ClcdCrsrConfig:
+        data = clcdCrsrConfig;
+        break;
+      case ClcdCrsrPalette0:
+        data = clcdCrsrPalette0;
+        break;
+      case ClcdCrsrPalette1:
+        data = clcdCrsrPalette1;
+        break;
+      case ClcdCrsrXY:
+        data = clcdCrsrXY;
+        break;
+      case ClcdCrsrClip:
+        data = clcdCrsrClip;
+        break;
+      case ClcdCrsrImsc:
+        data = clcdCrsrImsc;
+        break;
+      case ClcdCrsrIcr:
+        panic("CLCD register at offset %#x is Write-Only\n", daddr);
+        break;
+      case ClcdCrsrRis:
+        data = clcdCrsrRis;
+        break;
+      case ClcdCrsrMis:
+        data = clcdCrsrMis;
+        break;
+      default:
+        if (AmbaDev::readId(pkt, AMBA_ID, pioAddr)) {
+            // Hack for variable size accesses
+            data = pkt->get<uint32_t>();
+            break;
+        } else if (daddr >= CrsrImage && daddr <= 0xBFC) {
+            // CURSOR IMAGE
+            int index;
+            index = (daddr - CrsrImage) >> 2;
+            data= cursorImage[index];
+            break;
+        } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
+            // LCD Palette
+            int index;
+            index = (daddr - LcdPalette) >> 2;
+            data = lcdPalette[index];
+            break;
+        } else {
+            panic("Tried to read CLCD register at offset %#x that \
                        doesn't exist\n", daddr);
-                break;
-            }
+            break;
         }
     }
 
@@ -226,119 +231,133 @@ Pl111::write(PacketPtr pkt)
         break;
     }
 
-    if ((pkt->getAddr()& 0xffff0000) == pioAddr) {
+    assert(pkt->getAddr() >= pioAddr &&
+           pkt->getAddr() < pioAddr + pioSize);
 
-        assert(pkt->getAddr() >= pioAddr &&
-               pkt->getAddr() < pioAddr + pioSize);
+    Addr daddr = pkt->getAddr() - pioAddr;
 
-        Addr daddr = pkt->getAddr() - pioAddr;
+    DPRINTF(PL111, " write register %#x value %#x size=%d\n", daddr,
+            pkt->get<uint8_t>(), pkt->getSize());
 
-        DPRINTF(PL111, " write register %#x value %#x size=%d\n", daddr,
-                pkt->get<uint8_t>(), pkt->getSize());
+    switch (daddr) {
+      case LcdTiming0:
+        lcdTiming0 = data;
+        // width = 16 * (PPL+1)
+        width = (lcdTiming0.ppl + 1) << 4;
+        break;
+      case LcdTiming1:
+        lcdTiming1 = data;
+        // height = LPP + 1
+        height = (lcdTiming1.lpp) + 1;
+        break;
+      case LcdTiming2:
+        lcdTiming2 = data;
+        break;
+      case LcdTiming3:
+        lcdTiming3 = data;
+        break;
+      case LcdUpBase:
+        lcdUpbase = data;
+        DPRINTF(PL111, "####### Upper panel base set to: %#x #######\n", lcdUpbase);
+        break;
+      case LcdLpBase:
+        warn("LCD dual screen mode not supported\n");
+        lcdLpbase = data;
+        DPRINTF(PL111, "###### Lower panel base set to: %#x #######\n", lcdLpbase);
+        break;
+      case LcdControl:
+        int old_lcdpwr;
+        old_lcdpwr = lcdControl.lcdpwr;
+        lcdControl = data;
+
+        DPRINTF(PL111, "LCD power is:%d\n", lcdControl.lcdpwr);
+
+        // LCD power enable
+        if (lcdControl.lcdpwr && !old_lcdpwr) {
+            updateVideoParams();
+            DPRINTF(PL111, " lcd size: height %d width %d\n", height, width);
+            waterMark = lcdControl.watermark ? 8 : 4;
+            startDma();
+        }
+        break;
+      case LcdImsc:
+        lcdImsc = data;
+        if (lcdImsc.vcomp)
+            panic("Interrupting on vcomp not supported\n");
 
-        switch (daddr) {
-          case LcdTiming0:
-            lcdTiming0 = data;
-            // width = 16 * (PPL+1)
-            width = (lcdTiming0.ppl + 1) << 4;
-            break;
-          case LcdTiming1:
-            lcdTiming1 = data;
-            // height = LPP + 1
-            height  = (lcdTiming1.lpp) + 1;
-            break;
-          case LcdTiming2:
-            lcdTiming2 = data;
-            break;
-          case LcdTiming3:
-            lcdTiming3 = data;
-            break;
-          case LcdUpBase:
-            lcdUpbase  = data;
-            break;
-          case LcdLpBase:
-            warn("LCD dual screen mode not supported\n");
-            lcdLpbase  = data;
-            break;
-          case LcdControl:
-            int old_lcdpwr;
-            old_lcdpwr = lcdControl.lcdpwr;
-            lcdControl = data;
-            // LCD power enable
-            if (lcdControl.lcdpwr&&!old_lcdpwr) {
-                DPRINTF(PL111, " lcd size: height %d width %d\n", height, width);
-                waterMark = lcdControl.watermark ? 8 : 4;
-                readFramebuffer();
-            }
-            break;
-          case LcdImsc:
-            warn("LCD interrupt mask set/clear not supported\n");
-            lcdImsc    = data;
-            break;
-          case LcdRis:
-            warn("LCD register at offset %#x is Read-Only\n", daddr);
-            break;
-          case LcdMis:
-            warn("LCD register at offset %#x is Read-Only\n", daddr);
-            break;
-          case LcdIcr:
-            warn("LCD interrupt clear not supported\n");
-            lcdIcr     = data;
-            break;
-          case LcdUpCurr:
-            warn("LCD register at offset %#x is Read-Only\n", daddr);
-            break;
-          case LcdLpCurr:
-            warn("LCD register at offset %#x is Read-Only\n", daddr);
-            break;
-          case ClcdCrsrCtrl:
-            clcdCrsrCtrl = data;
-            break;
-          case ClcdCrsrConfig:
-            clcdCrsrConfig = data;
-            break;
-          case ClcdCrsrPalette0:
-            clcdCrsrPalette0 = data;
-            break;
-          case ClcdCrsrPalette1:
-            clcdCrsrPalette1 = data;
-            break;
-          case ClcdCrsrXY:
-            clcdCrsrXY = data;
-            break;
-          case ClcdCrsrClip:
-            clcdCrsrClip = data;
-            break;
-          case ClcdCrsrImsc:
-            clcdCrsrImsc = data;
-            break;
-          case ClcdCrsrIcr:
-            clcdCrsrIcr = data;
-            break;
-          case ClcdCrsrRis:
-            warn("CLCD register at offset %#x is Read-Only\n", daddr);
-            break;
-          case ClcdCrsrMis:
-            warn("CLCD register at offset %#x is Read-Only\n", daddr);
-            break;
-          default:
-            if (daddr >= CrsrImage && daddr <= 0xBFC) {
-                // CURSOR IMAGE
-                int index;
-                index = (daddr - CrsrImage) >> 2;
-                cursorImage[index] = data;
-                break;
-            } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
-                // LCD Palette
-                int index;
-                index = (daddr - LcdPalette) >> 2;
-                lcdPalette[index] = data;
-                break;
-            } else {
-                panic("Tried to write PL111 register at offset %#x that \
+        lcdMis = lcdImsc & lcdRis;
+
+        if (!lcdMis)
+            gic->clearInt(intNum);
+
+         break;
+      case LcdRis:
+        panic("LCD register at offset %#x is Read-Only\n", daddr);
+        break;
+      case LcdMis:
+        panic("LCD register at offset %#x is Read-Only\n", daddr);
+        break;
+      case LcdIcr:
+        lcdRis = lcdRis & ~data;
+        lcdMis = lcdImsc & lcdRis;
+
+        if (!lcdMis)
+            gic->clearInt(intNum);
+
+        break;
+      case LcdUpCurr:
+        panic("LCD register at offset %#x is Read-Only\n", daddr);
+        break;
+      case LcdLpCurr:
+        panic("LCD register at offset %#x is Read-Only\n", daddr);
+        break;
+      case ClcdCrsrCtrl:
+        clcdCrsrCtrl = data;
+        break;
+      case ClcdCrsrConfig:
+        clcdCrsrConfig = data;
+        break;
+      case ClcdCrsrPalette0:
+        clcdCrsrPalette0 = data;
+        break;
+      case ClcdCrsrPalette1:
+        clcdCrsrPalette1 = data;
+        break;
+      case ClcdCrsrXY:
+        clcdCrsrXY = data;
+        break;
+      case ClcdCrsrClip:
+        clcdCrsrClip = data;
+        break;
+      case ClcdCrsrImsc:
+        clcdCrsrImsc = data;
+        break;
+      case ClcdCrsrIcr:
+        clcdCrsrIcr = data;
+        break;
+      case ClcdCrsrRis:
+        panic("CLCD register at offset %#x is Read-Only\n", daddr);
+        break;
+      case ClcdCrsrMis:
+        panic("CLCD register at offset %#x is Read-Only\n", daddr);
+        break;
+      default:
+        if (daddr >= CrsrImage && daddr <= 0xBFC) {
+            // CURSOR IMAGE
+            int index;
+            index = (daddr - CrsrImage) >> 2;
+            cursorImage[index] = data;
+            break;
+        } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
+            // LCD Palette
+            int index;
+            index = (daddr - LcdPalette) >> 2;
+            lcdPalette[index] = data;
+            break;
+        } else {
+            panic("Tried to write PL111 register at offset %#x that \
                        doesn't exist\n", daddr);
-                break;
-            }
+            break;
         }
     }
 
@@ -346,18 +365,76 @@ Pl111::write(PacketPtr pkt)
     return pioDelay;
 }
 
+void
+Pl111::updateVideoParams()
+{
+        if (lcdControl.lcdbpp == bpp24) {
+            bytesPerPixel = 4;
+        } else if (lcdControl.lcdbpp == bpp16m565) {
+            bytesPerPixel = 2;
+        }
+
+        if (vncserver) {
+            if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr)
+                vncserver->setFrameBufferParams(VideoConvert::bgr8888, width,
+                       height);
+            else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr)
+                vncserver->setFrameBufferParams(VideoConvert::rgb8888, width,
+                       height);
+            else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr)
+                vncserver->setFrameBufferParams(VideoConvert::bgr565, width,
+                       height);
+            else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr)
+                vncserver->setFrameBufferParams(VideoConvert::rgb565, width,
+                       height);
+            else
+                panic("Unimplemented video mode\n");
+        }
+
+        if (bmp)
+            delete bmp;
+
+        if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr)
+            bmp = new Bitmap(VideoConvert::bgr8888, width, height, dmaBuffer);
+        else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr)
+            bmp = new Bitmap(VideoConvert::rgb8888, width, height, dmaBuffer);
+        else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr)
+            bmp = new Bitmap(VideoConvert::bgr565, width, height, dmaBuffer);
+        else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr)
+            bmp = new Bitmap(VideoConvert::rgb565, width, height, dmaBuffer);
+        else
+            panic("Unimplemented video mode\n");
+}
+
+void
+Pl111::startDma()
+{
+    if (dmaPendingNum != 0 || readEvent.scheduled())
+        return;
+    readFramebuffer();
+}
+
 void
 Pl111::readFramebuffer()
 {
     // initialization for dma read from frame buffer to dma buffer
-    uint32_t length  = height*width;
-    if (startAddr != lcdUpbase) {
+    uint32_t length = height * width;
+    if (startAddr != lcdUpbase)
         startAddr = lcdUpbase;
-    }
+
+    // Updating base address, interrupt if we're supposed to
+    lcdRis.baseaddr = 1;
+    if (!intEvent.scheduled())
+        schedule(intEvent, nextCycle());
+
     curAddr = 0;
     startTime = curTick();
-    maxAddr = static_cast<Addr>(length*sizeof(uint32_t));
-    dmaPendingNum =0 ;
+
+    maxAddr = static_cast<Addr>(length * bytesPerPixel);
+
+    DPRINTF(PL111, " lcd frame buffer size of %d bytes \n", maxAddr);
+
+    dmaPendingNum = 0;
 
     fillFifo();
 }
@@ -369,11 +446,16 @@ Pl111::fillFifo()
         // concurrent dma reads need different dma done events
         // due to assertion in scheduling state
         ++dmaPendingNum;
-        DPRINTF(PL111, " ++ DMA pending number %d read addr %#x\n",
-                dmaPendingNum, curAddr);
+
         assert(!dmaDoneEvent[dmaPendingNum-1].scheduled());
-        dmaRead(curAddr + startAddr, dmaSize, &dmaDoneEvent[dmaPendingNum-1],
-                curAddr + dmaBuffer);
+
+        // We use a uncachable request here because the requests from the CPU
+        // will be uncacheable as well. If we have uncacheable and cacheable
+        // requests in the memory system for the same address it won't be
+        // pleased
+        dmaPort->dmaAction(MemCmd::ReadReq, curAddr + startAddr, dmaSize,
+                &dmaDoneEvent[dmaPendingNum-1], curAddr + dmaBuffer, 0,
+                Request::UNCACHEABLE);
         curAddr += dmaSize;
     }
 }
@@ -381,27 +463,34 @@ Pl111::fillFifo()
 void
 Pl111::dmaDone()
 {
-    Tick maxFrameTime = lcdTiming2.cpl*height*clock;
+    Tick maxFrameTime = lcdTiming2.cpl * height * clock;
 
     --dmaPendingNum;
 
-    DPRINTF(PL111, " -- DMA pending number %d\n", dmaPendingNum);
-
     if (maxAddr == curAddr && !dmaPendingNum) {
-        if ((curTick() - startTime) > maxFrameTime)
+        if ((curTick() - startTime) > maxFrameTime) {
             warn("CLCD controller buffer underrun, took %d cycles when should"
                  " have taken %d\n", curTick() - startTime, maxFrameTime);
+            lcdRis.underflow = 1;
+            if (!intEvent.scheduled())
+                schedule(intEvent, nextCycle());
+        }
 
-        // double buffering so the vnc server doesn't see a tear in the screen
-        memcpy(frameBuffer, dmaBuffer, maxAddr);
         assert(!readEvent.scheduled());
+        if (vncserver)
+            vncserver->setDirty();
 
         DPRINTF(PL111, "-- write out frame buffer into bmp\n");
-        writeBMP(frameBuffer);
+
+        assert(bmp);
+        pic->seekp(0);
+        bmp->write(pic);
 
         DPRINTF(PL111, "-- schedule next dma read event at %d tick \n",
                 maxFrameTime + curTick());
-        schedule(readEvent, nextCycle(startTime + maxFrameTime));
+
+        if (lcdControl.lcden)
+            schedule(readEvent, nextCycle(startTime + maxFrameTime));
     }
 
     if (dmaPendingNum > (maxOutstandingDma - waterMark))
@@ -409,9 +498,9 @@ Pl111::dmaDone()
 
     if (!fillFifoEvent.scheduled())
         schedule(fillFifoEvent, nextCycle());
-
 }
 
+
 Tick
 Pl111::nextCycle()
 {
@@ -431,33 +520,6 @@ Pl111::nextCycle(Tick beginTick)
     return nextTick;
 }
 
-// write out the frame buffer into a bitmap file
-void
-Pl111::writeBMP(uint32_t* frameBuffer)
-{
-    fstream pic;
-
-    // write out bmp head
-    std::string filename = "./m5out/frameBuffer.bmp";
-    pic.open(filename.c_str(), ios::out|ios::binary);
-    Bitmap bm(pic, height, width);
-
-    DPRINTF(PL111, "-- write out data into bmp\n");
-
-    // write out frame buffer data
-    for (int i = height -1; i >= 0; --i) {
-        for (int j = 0; j< width; ++j) {
-            uint32_t pixel = frameBuffer[i*width + j];
-            pic.write(reinterpret_cast<char*>(&pixel),
-                      sizeof(uint32_t));
-            DPRINTF(PL111, " write pixel data  %#x at addr %#x\n",
-                    pixel, i*width + j);
-        }
-    }
-
-    pic.close();
-}
-
 void
 Pl111::serialize(std::ostream &os)
 {
@@ -490,9 +552,6 @@ Pl111::serialize(std::ostream &os)
     uint8_t lcdMis_serial = lcdMis;
     SERIALIZE_SCALAR(lcdMis_serial);
 
-    uint8_t lcdIcr_serial = lcdIcr;
-    SERIALIZE_SCALAR(lcdIcr_serial);
-
     SERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
     SERIALIZE_ARRAY(cursorImage, CrsrImageSize);
 
@@ -518,9 +577,9 @@ Pl111::serialize(std::ostream &os)
     SERIALIZE_SCALAR(clock);
     SERIALIZE_SCALAR(height);
     SERIALIZE_SCALAR(width);
+    SERIALIZE_SCALAR(bytesPerPixel);
 
-    SERIALIZE_ARRAY(dmaBuffer, height*width);
-    SERIALIZE_ARRAY(frameBuffer, height*width);
+    SERIALIZE_ARRAY(dmaBuffer, height * width);
     SERIALIZE_SCALAR(startTime);
     SERIALIZE_SCALAR(startAddr);
     SERIALIZE_SCALAR(maxAddr);
@@ -569,10 +628,6 @@ Pl111::unserialize(Checkpoint *cp, const std::string &section)
     UNSERIALIZE_SCALAR(lcdMis_serial);
     lcdMis = lcdMis_serial;
 
-    uint8_t lcdIcr_serial;
-    UNSERIALIZE_SCALAR(lcdIcr_serial);
-    lcdIcr = lcdIcr_serial;
-
     UNSERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
     UNSERIALIZE_ARRAY(cursorImage, CrsrImageSize);
 
@@ -602,25 +657,29 @@ Pl111::unserialize(Checkpoint *cp, const std::string &section)
     UNSERIALIZE_SCALAR(clock);
     UNSERIALIZE_SCALAR(height);
     UNSERIALIZE_SCALAR(width);
+    UNSERIALIZE_SCALAR(bytesPerPixel);
 
-    UNSERIALIZE_ARRAY(dmaBuffer, height*width);
-    UNSERIALIZE_ARRAY(frameBuffer, height*width);
+    UNSERIALIZE_ARRAY(dmaBuffer, height * width);
     UNSERIALIZE_SCALAR(startTime);
     UNSERIALIZE_SCALAR(startAddr);
     UNSERIALIZE_SCALAR(maxAddr);
     UNSERIALIZE_SCALAR(curAddr);
     UNSERIALIZE_SCALAR(waterMark);
     UNSERIALIZE_SCALAR(dmaPendingNum);
+
+    updateVideoParams();
+    if (vncserver)
+        vncserver->setDirty();
 }
 
 void
 Pl111::generateInterrupt()
 {
     DPRINTF(PL111, "Generate Interrupt: lcdImsc=0x%x lcdRis=0x%x lcdMis=0x%x\n",
-            lcdImsc, lcdRis, lcdMis);
+            (uint32_t)lcdImsc, (uint32_t)lcdRis, (uint32_t)lcdMis);
     lcdMis = lcdImsc & lcdRis;
 
-    if (lcdMis.ffufie || lcdMis.nbupie || lcdMis.vtcpie || lcdMis.ahmeie) {
+    if (lcdMis.underflow || lcdMis.baseaddr || lcdMis.vcomp || lcdMis.ahbmaster) {
         gic->sendInt(intNum);
         DPRINTF(PL111, " -- Generated\n");
     }
@@ -639,15 +698,4 @@ Pl111Params::create()
     return new Pl111(this);
 }
 
-// bitmap class ctor
-Bitmap::Bitmap(std::fstream& bmp, uint16_t h, uint16_t w)
-{
-    Magic  magic  = {{'B','M'}};
-    Header header = {sizeof(Color)*w*h , 0, 0, 54};
-    Info   info   = {sizeof(Info), w, h, 1, sizeof(Color)*8, 0,
-                     ( sizeof(Color) *(w*h) ), 1, 1, 0, 0};
-
-    bmp.write(reinterpret_cast<char*>(&magic),  sizeof(magic));
-    bmp.write(reinterpret_cast<char*>(&header), sizeof(header));
-    bmp.write(reinterpret_cast<char*>(&info),   sizeof(info));
-}
+
index 4e75af4e8486cbd811939ad8382b75ff493abfbb..f36dc681030e02392a4cb8276b163f35aff2dbf9 100644 (file)
@@ -35,6 +35,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: William Wang
+ *          Ali Saidi
  */
 
 
@@ -55,6 +56,8 @@
 using namespace std;
 
 class Gic;
+class VncServer;
+class Bitmap;
 
 class Pl111: public AmbaDmaDevice
 {
@@ -96,58 +99,69 @@ class Pl111: public AmbaDmaDevice
     static const int dmaSize            = 8;    // 64 bits
     static const int maxOutstandingDma  = 16;   // 16 deep FIFO of 64 bits
 
+    enum LcdMode {
+        bpp1 = 0,
+        bpp2,
+        bpp4,
+        bpp8,
+        bpp16,
+        bpp24,
+        bpp16m565,
+        bpp12
+    };
+
     BitUnion8(InterruptReg)
-    Bitfield<1> ffufie;
-    Bitfield<2> nbupie;
-    Bitfield<3> vtcpie;
-    Bitfield<4> ahmeie;
+        Bitfield<1> underflow;
+        Bitfield<2> baseaddr;
+        Bitfield<3> vcomp;
+        Bitfield<4> ahbmaster;
     EndBitUnion(InterruptReg)
 
     BitUnion32(TimingReg0)
-    Bitfield<7,2> ppl;
-    Bitfield<15,8> hsw;
-    Bitfield<23,16> hfp;
-    Bitfield<31,24> hbp;
+        Bitfield<7,2> ppl;
+        Bitfield<15,8> hsw;
+        Bitfield<23,16> hfp;
+        Bitfield<31,24> hbp;
     EndBitUnion(TimingReg0)
 
     BitUnion32(TimingReg1)
-    Bitfield<9,0> lpp;
-    Bitfield<15,10> vsw;
-    Bitfield<23,16> vfp;
-    Bitfield<31,24> vbp;
+        Bitfield<9,0> lpp;
+        Bitfield<15,10> vsw;
+        Bitfield<23,16> vfp;
+        Bitfield<31,24> vbp;
     EndBitUnion(TimingReg1)
 
     BitUnion32(TimingReg2)
-    Bitfield<4,0> pcdlo;
-    Bitfield<5> clksel;
-    Bitfield<10,6> acb;
-    Bitfield<11> avs;
-    Bitfield<12> ihs;
-    Bitfield<13> ipc;
-    Bitfield<14> ioe;
-    Bitfield<25,16> cpl;
-    Bitfield<26> bcd;
-    Bitfield<31,27> pcdhi;
+        Bitfield<4,0> pcdlo;
+        Bitfield<5> clksel;
+        Bitfield<10,6> acb;
+        Bitfield<11> avs;
+        Bitfield<12> ihs;
+        Bitfield<13> ipc;
+        Bitfield<14> ioe;
+        Bitfield<25,16> cpl;
+        Bitfield<26> bcd;
+        Bitfield<31,27> pcdhi;
     EndBitUnion(TimingReg2)
 
     BitUnion32(TimingReg3)
-    Bitfield<6,0> led;
-    Bitfield<16> lee;
+        Bitfield<6,0> led;
+        Bitfield<16> lee;
     EndBitUnion(TimingReg3)
 
     BitUnion32(ControlReg)
-    Bitfield<0> lcden;
-    Bitfield<3,1> lcdbpp;
-    Bitfield<4> lcdbw;
-    Bitfield<5> lcdtft;
-    Bitfield<6> lcdmono8;
-    Bitfield<7> lcddual;
-    Bitfield<8> bgr;
-    Bitfield<9> bebo;
-    Bitfield<10> bepo;
-    Bitfield<11> lcdpwr;
-    Bitfield<13,12> lcdvcomp;
-    Bitfield<16> watermark;
+        Bitfield<0> lcden;
+        Bitfield<3,1> lcdbpp;
+        Bitfield<4> lcdbw;
+        Bitfield<5> lcdtft;
+        Bitfield<6> lcdmono8;
+        Bitfield<7> lcddual;
+        Bitfield<8> bgr;
+        Bitfield<9> bebo;
+        Bitfield<10> bepo;
+        Bitfield<11> lcdpwr;
+        Bitfield<13,12> lcdvcomp;
+        Bitfield<16> watermark;
     EndBitUnion(ControlReg)
 
     /** Horizontal axis panel control register */
@@ -180,15 +194,6 @@ class Pl111: public AmbaDmaDevice
     /** Masked interrupt status register */
     InterruptReg lcdMis;
 
-    /** Interrupt clear register */
-    InterruptReg lcdIcr;
-
-    /** Upper panel current address value register - ro */
-    int lcdUpcurr;
-
-    /** Lower panel current address value register - ro */
-    int lcdLpcurr;
-
     /** 256x16-bit color palette registers
      * 256 palette entries organized as 128 locations of two entries per word */
     int lcdPalette[LcdPaletteSize];
@@ -228,17 +233,26 @@ class Pl111: public AmbaDmaDevice
     /** Clock speed */
     Tick clock;
 
-    /** Frame buffer height - lines per panel */
-    uint16_t height;
+    /** VNC server */
+    VncServer *vncserver;
+
+    /** Helper to write out bitmaps */
+    Bitmap *bmp;
+
+    /** Picture of what the current frame buffer looks like */
+    std::ostream *pic;
 
     /** Frame buffer width - pixels per line */
     uint16_t width;
 
-    /** CLCDC supports up to 1024x768 */
-    uint8_t dmaBuffer[LcdMaxWidth * LcdMaxHeight * sizeof(uint32_t)];
+    /** Frame buffer height - lines per panel */
+    uint16_t height;
 
-    /** Double buffering */
-    uint32_t frameBuffer[LcdMaxWidth * LcdMaxHeight];
+    /** Bytes per pixel */
+    uint8_t bytesPerPixel;
+
+    /** CLCDC supports up to 1024x768 */
+    uint8_t *dmaBuffer;
 
     /** Start time for frame buffer dma read */
     Tick startTime;
@@ -258,12 +272,12 @@ class Pl111: public AmbaDmaDevice
     /** Number of pending dma reads */
     int dmaPendingNum;
 
+    /** Send updated parameters to the vnc server */
+    void updateVideoParams();
+
     /** DMA framebuffer read */
     void readFramebuffer();
 
-    /** Write framebuffer to a bmp file */
-    void writeBMP(uint32_t*);
-
     /** Generate dma framebuffer read event */
     void generateReadEvent();
 
@@ -273,6 +287,9 @@ class Pl111: public AmbaDmaDevice
     /** fillFIFO event */
     void fillFifo();
 
+    /** start the dmas off after power is enabled */
+    void startDma();
+
     /** DMA done event */
     void dmaDone();
 
@@ -289,7 +306,7 @@ class Pl111: public AmbaDmaDevice
     /** DMA done event */
     vector<EventWrapper<Pl111, &Pl111::dmaDone> > dmaDoneEvent;
 
-    /** Wrapper to create an event out of the thing */
+    /** Wrapper to create an event out of the interrupt */
     EventWrapper<Pl111, &Pl111::generateInterrupt> intEvent;
 
   public:
@@ -312,57 +329,6 @@ class Pl111: public AmbaDmaDevice
      * @param range_list range list to populate with ranges
      */
     void addressRanges(AddrRangeList &range_list);
-
-    /**
-     * Return if we have an interrupt pending
-     * @return interrupt status
-     * @todo fix me when implementation improves
-     */
-    virtual bool intStatus() { return false; }
-};
-
-// write frame buffer into a bitmap picture
-class  Bitmap
-{
-  public:
-    Bitmap(std::fstream& bmp, uint16_t h, uint16_t w);
-
-  private:
-    struct Magic
-    {
-        unsigned char magic_number[2];
-    } magic;
-
-    struct Header
-    {
-        uint32_t size;
-        uint16_t reserved1;
-        uint16_t reserved2;
-        uint32_t offset;
-    } header;
-
-    struct Info
-    {
-        uint32_t Size;
-        uint32_t Width;
-        uint32_t Height;
-        uint16_t Planes;
-        uint16_t BitCount;
-        uint32_t Compression;
-        uint32_t SizeImage;
-        uint32_t XPelsPerMeter;
-        uint32_t YPelsPerMeter;
-        uint32_t ClrUsed;
-        uint32_t ClrImportant;
-    } info;
-
-    struct Color
-    {
-        unsigned char b;
-        unsigned char g;
-        unsigned char r;
-        unsigned char a;
-    } color;
 };
 
 #endif
index c0ba4c7aa13b7681bf296276b112739ff3982f3a..b1bbc065b44e005330085674d11d59af0d60179c 100644 (file)
@@ -68,6 +68,27 @@ RealViewCtrl::read(PacketPtr pkt)
       case Flash:
         pkt->set<uint32_t>(0);
         break;
+      case Clcd:
+        pkt->set<uint32_t>(0x00001F00);
+        break;
+      case Osc0:
+        pkt->set<uint32_t>(0x00012C5C);
+        break;
+      case Osc1:
+        pkt->set<uint32_t>(0x00002CC0);
+        break;
+      case Osc2:
+        pkt->set<uint32_t>(0x00002C75);
+        break;
+      case Osc3:
+        pkt->set<uint32_t>(0x00020211);
+        break;
+      case Osc4:
+        pkt->set<uint32_t>(0x00002C75);
+        break;
+      case Lock:
+        pkt->set<uint32_t>(sysLock);
+        break;
       default:
         panic("Tried to read RealView I/O at offset %#x that doesn't exist\n", daddr);
         break;
@@ -85,6 +106,15 @@ RealViewCtrl::write(PacketPtr pkt)
     Addr daddr = pkt->getAddr() - pioAddr;
     switch (daddr) {
       case Flash:
+      case Clcd:
+      case Osc0:
+      case Osc1:
+      case Osc2:
+      case Osc3:
+      case Osc4:
+        break;
+      case Lock:
+        sysLock.lockVal = pkt->get<uint16_t>();
         break;
       default:
         panic("Tried to write RVIO at offset %#x that doesn't exist\n", daddr);
index 00a19d7158517237a84330587783952004675991..ceed5ef2f437560b7f4ea1d0f4af77454f94b686 100644 (file)
@@ -40,6 +40,7 @@
 #ifndef __DEV_ARM_RV_HH__
 #define __DEV_ARM_RV_HH__
 
+#include "base/bitunion.hh"
 #include "base/range.hh"
 #include "dev/io_device.hh"
 #include "params/RealViewCtrl.hh"
@@ -86,6 +87,14 @@ class RealViewCtrl : public BasicPioDevice
         TestOsc4   = 0xD0
     };
 
+    // system lock value
+    BitUnion32(SysLockReg)
+        Bitfield<15,0> lockVal;
+        Bitfield<16> locked;
+    EndBitUnion(SysLockReg)
+
+    SysLockReg sysLock;
+
   public:
     typedef RealViewCtrlParams Params;
     const Params *
@@ -120,4 +129,3 @@ class RealViewCtrl : public BasicPioDevice
 
 
 #endif // __DEV_ARM_RV_HH__
-
diff --git a/src/dev/ps2.cc b/src/dev/ps2.cc
new file mode 100644 (file)
index 0000000..fe90ce6
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2011 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: Ali Saidi
+ */
+
+#include <list>
+#include "x11keysym/keysym.h"
+
+#include "base/misc.hh"
+#include "dev/ps2.hh"
+
+
+namespace Ps2 {
+
+/** Table to convert simple key symbols (0x00XX) into ps2 bytes. Lower byte
+ * is the scan code to send and upper byte is if a modifier is required to
+ * generate it. The table generates us keyboard codes, (e.g. the guest is
+ * supposed to recognize the keyboard as en_US). A new table would be required
+ * for another locale.
+ */
+
+static const uint16_t keySymToPs2Byte[128] = {
+// 0 / 8   1 / 9   2 / A   3 / B   4 / C   5 / D   6 / E   7 / F
+   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00-0x07
+   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x08-0x0f
+   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x10-0x17
+   0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x18-0x1f
+   0x0029, 0x0116, 0x0152, 0x0126, 0x0125, 0x012e, 0x013d, 0x0052, // 0x20-0x27
+   0x0146, 0x0145, 0x013e, 0x0155, 0x0041, 0x004e, 0x0049, 0x004a, // 0x28-0x2f
+   0x0045, 0x0016, 0x001e, 0x0026, 0x0025, 0x002e, 0x0036, 0x003d, // 0x30-0x37
+   0x003e, 0x0046, 0x014c, 0x004c, 0x0141, 0x0055, 0x0149, 0x014a, // 0x38-0x3f
+   0x011e, 0x011c, 0x0132, 0x0121, 0x0123, 0x0124, 0x012b, 0x0134, // 0x40-0x47
+   0x0133, 0x0143, 0x013b, 0x0142, 0x014b, 0x013a, 0x0131, 0x0144, // 0x48-0x4f
+   0x014d, 0x0115, 0x012d, 0x011b, 0x012c, 0x013c, 0x012a, 0x011d, // 0x50-0x57
+   0x0122, 0x0135, 0x011a, 0x0054, 0x005d, 0x005b, 0x0136, 0x014e, // 0x58-0x5f
+   0x000e, 0x001c, 0x0032, 0x0021, 0x0023, 0x0024, 0x002b, 0x0034, // 0x60-0x67
+   0x0033, 0x0043, 0x003b, 0x0042, 0x004b, 0x003a, 0x0031, 0x0044, // 0x68-0x6f
+   0x004d, 0x0015, 0x002d, 0x001b, 0x002c, 0x003c, 0x002a, 0x001d, // 0x70-0x77
+   0x0022, 0x0035, 0x001a, 0x0154, 0x015d, 0x015b, 0x010e, 0x0000  // 0x78-0x7f
+};
+
+const uint8_t ShiftKey = 0x12;
+const uint8_t BreakKey = 0xf0;
+const uint8_t ExtendedKey = 0xe0;
+const uint32_t UpperKeys = 0xff00;
+
+void
+keySymToPs2(uint32_t key, bool down, bool &cur_shift,
+        std::list<uint8_t> &keys)
+{
+    if (key <= XK_asciitilde) {
+        uint16_t tmp = keySymToPs2Byte[key];
+        uint8_t code = tmp & 0xff;
+        bool shift = tmp >> 8;
+
+        if (down) {
+            if (!cur_shift && shift) {
+                keys.push_back(ShiftKey);
+                cur_shift = true;
+            }
+            keys.push_back(code);
+        } else {
+            if (cur_shift && !shift) {
+                keys.push_back(BreakKey);
+                keys.push_back(ShiftKey);
+                cur_shift = false;
+            }
+            keys.push_back(BreakKey);
+            keys.push_back(code);
+        }
+    } else {
+        if ((key & UpperKeys) == UpperKeys) {
+            bool extended = false;
+            switch (key) {
+              case XK_BackSpace:
+                keys.push_back(0x66);
+                break;
+              case XK_Tab:
+                keys.push_back(0x0d);
+                break;
+              case XK_Return:
+                keys.push_back(0x5a);
+                break;
+             case XK_Escape:
+                keys.push_back(0x76);
+                break;
+             case XK_Delete:
+                extended = true;
+                keys.push_back(0x71);
+                break;
+             case XK_Home:
+                extended = true;
+                keys.push_back(0x6c);
+                break;
+             case XK_Left:
+                extended = true;
+                keys.push_back(0x6b);
+                break;
+             case XK_Right:
+                extended = true;
+                keys.push_back(0x74);
+                break;
+             case XK_Down:
+                extended = true;
+                keys.push_back(0x72);
+                break;
+             case XK_Up:
+                extended = true;
+                keys.push_back(0x75);
+                break;
+             case XK_Page_Up:
+                extended = true;
+                keys.push_back(0x7d);
+                break;
+             case XK_Page_Down:
+                extended = true;
+                keys.push_back(0x7a);
+                break;
+             case XK_End:
+                extended = true;
+                keys.push_back(0x69);
+                break;
+             case XK_Shift_L:
+                keys.push_back(0x12);
+                if (down)
+                    cur_shift = true;
+                else
+                    cur_shift = false;
+                break;
+             case XK_Shift_R:
+                keys.push_back(0x59);
+                if (down)
+                    cur_shift = true;
+                else
+                    cur_shift = false;
+                break;
+             case XK_Control_L:
+                keys.push_back(0x14);
+                break;
+             case XK_Control_R:
+                extended = true;
+                keys.push_back(0x14);
+                break;
+             default:
+               warn("Unknown extended key %#x\n", key);
+               return;
+            }
+
+            if (extended) {
+                if (down) {
+                    keys.push_front(ExtendedKey);
+                } else {
+                    keys.push_front(BreakKey);
+                    keys.push_front(ExtendedKey);
+                }
+            } else {
+                if (!down)
+                    keys.push_front(BreakKey);
+            }
+        } // upper keys
+    } // extended keys
+    return;
+}
+
+} /* namespace Ps2 */
+
diff --git a/src/dev/ps2.hh b/src/dev/ps2.hh
new file mode 100644 (file)
index 0000000..73f3f9c
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2011 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: Ali Saidi
+ */
+
+#ifndef __DEV_PS2_HH__
+#define __DEV_PS2_HH__
+
+#include <stdint.h>
+
+#include "base/bitunion.hh"
+
+/** @file misc functions and constants required to interface with or emulate ps2
+ * devices
+ */
+
+namespace Ps2 {
+enum {
+    Ps2Reset        = 0xff,
+    SelfTestPass    = 0xAA,
+    SetStatusLed    = 0xed,
+    SetResolution   = 0xe8,
+    StatusRequest   = 0xe9,
+    SetScaling1_2   = 0xe7,
+    SetScaling1_1   = 0xe6,
+    ReadId          = 0xf2,
+    TpReadId        = 0xe1,
+    Ack             = 0xfa,
+    SetRate         = 0xf3,
+    Enable          = 0xf4,
+    Disable         = 0xf6,
+    KeyboardId      = 0xab,
+    TouchKitId      = 0x0a,
+    MouseId         = 0x00,
+};
+
+/** A bitfield that represents the first byte of a mouse movement packet
+ */
+BitUnion8(Ps2MouseMovement)
+    Bitfield<0> leftButton;
+    Bitfield<1> rightButton;
+    Bitfield<2> middleButton;
+    Bitfield<3> one;
+    Bitfield<4> xSign;
+    Bitfield<5> ySign;
+    Bitfield<6> xOverflow;
+    Bitfield<7> yOverflow;
+EndBitUnion(Ps2MouseMovement)
+
+/** Convert an x11 key symbol into a set of ps2 charecters.
+ * @param key x11 key symbol
+ * @param down if the key is being pressed or released
+ * @param cur_shift if device has already sent a shift
+ * @param keys list of keys command to send to emulate the x11 key symbol
+ */
+void keySymToPs2(uint32_t key, bool down, bool &cur_shift,
+        std::list<uint8_t> &keys);
+
+} /* namespace Ps2 */
+#endif // __DEV_PS2_HH__