Source('pcidev.cc')
Source('pktfifo.cc')
Source('platform.cc')
+ Source('ps2.cc')
Source('simple_disk.cc')
Source('sinic.cc')
Source('terminal.cc')
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
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):
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)
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
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)
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)
#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),
#include "mem/packet.hh"
#include "mem/packet_access.hh"
#include "params/AmbaDevice.hh"
+#include "params/AmbaIntDevice.hh"
#include "params/AmbaDmaDevice.hh"
namespace AmbaDev {
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:
* (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
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)) {
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 §ion)
+{
+ 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()
{
#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;
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();
/** 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 *
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 §ion);
};
-#endif
+#endif // __DEV_ARM_PL050_HH__
* 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"
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
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;
}
}
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;
}
}
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();
}
// 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;
}
}
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))
if (!fillFifoEvent.scheduled())
schedule(fillFifoEvent, nextCycle());
-
}
+
Tick
Pl111::nextCycle()
{
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)
{
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);
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);
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);
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");
}
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));
-}
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: William Wang
+ * Ali Saidi
*/
using namespace std;
class Gic;
+class VncServer;
+class Bitmap;
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 */
/** 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];
/** 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;
/** 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();
/** fillFIFO event */
void fillFifo();
+ /** start the dmas off after power is enabled */
+ void startDma();
+
/** DMA done event */
void dmaDone();
/** 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:
* @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
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;
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);
#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"
TestOsc4 = 0xD0
};
+ // system lock value
+ BitUnion32(SysLockReg)
+ Bitfield<15,0> lockVal;
+ Bitfield<16> locked;
+ EndBitUnion(SysLockReg)
+
+ SysLockReg sysLock;
+
public:
typedef RealViewCtrlParams Params;
const Params *
#endif // __DEV_ARM_RV_HH__
-
--- /dev/null
+/*
+ * 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 */
+
--- /dev/null
+/*
+ * 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__