ARM: Implement a CLCD Frame buffer
This commit is contained in:
parent
80db6a5ecb
commit
fc1eeafc94
6 changed files with 1056 additions and 11 deletions
|
@ -54,6 +54,10 @@ class AmbaDevice(BasicPioDevice):
|
|||
class AmbaDmaDevice(DmaDevice):
|
||||
type = 'AmbaDmaDevice'
|
||||
abstract = True
|
||||
pio_addr = Param.Addr("Address for AMBA slave interface")
|
||||
pio_latency = Param.Latency("10ns", "Time between action and write/read result by AMBA DMA Device")
|
||||
gic = Param.Gic(Parent.any, "Gic to use for interrupting")
|
||||
int_num = Param.UInt32("Interrupt number that connects to GIC")
|
||||
amba_id = Param.UInt32("ID of AMBA device for kernel detection")
|
||||
|
||||
class RealViewCtrl(BasicPioDevice):
|
||||
|
@ -89,16 +93,25 @@ class Sp804(AmbaDevice):
|
|||
clock1 = Param.Clock('1MHz', "Clock speed of the input")
|
||||
amba_id = 0x00141804
|
||||
|
||||
class Pl111(AmbaDmaDevice):
|
||||
type = 'Pl111'
|
||||
clock = Param.Clock('24MHz', "Clock speed of the input")
|
||||
amba_id = 0x00141111
|
||||
|
||||
class RealView(Platform):
|
||||
type = 'RealView'
|
||||
system = Param.System(Parent.any, "system")
|
||||
|
||||
# Reference for memory map and interrupt number
|
||||
# RealView Platform Baseboard Explore for Cortex-A9 User Guide(ARM DUI 0440A)
|
||||
# Chapter 4: Programmer's Reference
|
||||
class RealViewPBX(RealView):
|
||||
uart = Pl011(pio_addr=0x10009000, int_num=44)
|
||||
realview_io = RealViewCtrl(pio_addr=0x10000000)
|
||||
gic = Gic()
|
||||
timer0 = Sp804(int_num0=36, int_num1=36, pio_addr=0x10011000)
|
||||
timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000)
|
||||
clcd = Pl111(pio_addr=0x10020000, int_num=55)
|
||||
|
||||
l2x0_fake = IsaFake(pio_addr=0x1f002000, pio_size=0xfff)
|
||||
flash_fake = IsaFake(pio_addr=0x40000000, pio_size=0x4000000)
|
||||
|
@ -107,7 +120,6 @@ class RealViewPBX(RealView):
|
|||
uart2_fake = AmbaFake(pio_addr=0x1000b000)
|
||||
uart3_fake = AmbaFake(pio_addr=0x1000c000)
|
||||
smc_fake = AmbaFake(pio_addr=0x100e1000)
|
||||
clcd_fake = AmbaFake(pio_addr=0x10020000)
|
||||
sp810_fake = AmbaFake(pio_addr=0x10001000, ignore_access=True)
|
||||
watchdog_fake = AmbaFake(pio_addr=0x10010000)
|
||||
gpio0_fake = AmbaFake(pio_addr=0x10013000)
|
||||
|
@ -136,12 +148,12 @@ class RealViewPBX(RealView):
|
|||
self.realview_io.pio = bus.port
|
||||
self.timer0.pio = bus.port
|
||||
self.timer1.pio = bus.port
|
||||
self.clcd.pio = bus.port
|
||||
self.dmac_fake.pio = bus.port
|
||||
self.uart1_fake.pio = bus.port
|
||||
self.uart2_fake.pio = bus.port
|
||||
self.uart3_fake.pio = bus.port
|
||||
self.smc_fake.pio = bus.port
|
||||
self.clcd_fake.pio = bus.port
|
||||
self.sp810_fake.pio = bus.port
|
||||
self.watchdog_fake.pio = bus.port
|
||||
self.gpio0_fake.pio = bus.port
|
||||
|
@ -156,12 +168,14 @@ class RealViewPBX(RealView):
|
|||
self.rtc_fake.pio = bus.port
|
||||
self.flash_fake.pio = bus.port
|
||||
|
||||
# Interrupt numbers are wrong here
|
||||
class RealViewEB(RealView):
|
||||
uart = Pl011(pio_addr=0x10009000, int_num=44)
|
||||
realview_io = RealViewCtrl(pio_addr=0x10000000)
|
||||
gic = Gic(dist_addr=0x10041000, cpu_addr=0x10040000)
|
||||
timer0 = Sp804(int_num0=36, int_num1=36, pio_addr=0x10011000)
|
||||
timer1 = Sp804(int_num0=37, int_num1=37, pio_addr=0x10012000)
|
||||
clcd = Pl111(pio_addr=0x10020000, int_num=55)
|
||||
|
||||
l2x0_fake = IsaFake(pio_addr=0x1f002000, pio_size=0xfff, warn_access="1")
|
||||
dmac_fake = AmbaFake(pio_addr=0x10030000)
|
||||
|
@ -169,7 +183,6 @@ class RealViewEB(RealView):
|
|||
uart2_fake = AmbaFake(pio_addr=0x1000b000)
|
||||
uart3_fake = AmbaFake(pio_addr=0x1000c000)
|
||||
smc_fake = AmbaFake(pio_addr=0x100e1000)
|
||||
clcd_fake = AmbaFake(pio_addr=0x10020000)
|
||||
sp810_fake = AmbaFake(pio_addr=0x10001000, ignore_access=True)
|
||||
watchdog_fake = AmbaFake(pio_addr=0x10010000)
|
||||
gpio0_fake = AmbaFake(pio_addr=0x10013000)
|
||||
|
@ -198,12 +211,12 @@ class RealViewEB(RealView):
|
|||
self.realview_io.pio = bus.port
|
||||
self.timer0.pio = bus.port
|
||||
self.timer1.pio = bus.port
|
||||
self.clcd.pio = bus.port
|
||||
self.dmac_fake.pio = bus.port
|
||||
self.uart1_fake.pio = bus.port
|
||||
self.uart2_fake.pio = bus.port
|
||||
self.uart3_fake.pio = bus.port
|
||||
self.smc_fake.pio = bus.port
|
||||
self.clcd_fake.pio = bus.port
|
||||
self.sp810_fake.pio = bus.port
|
||||
self.watchdog_fake.pio = bus.port
|
||||
self.gpio0_fake.pio = bus.port
|
||||
|
|
|
@ -46,9 +46,11 @@ if env['FULL_SYSTEM'] and env['TARGET_ISA'] == 'arm':
|
|||
Source('amba_fake.cc')
|
||||
Source('gic.cc')
|
||||
Source('pl011.cc')
|
||||
Source('pl111.cc')
|
||||
Source('timer_sp804.cc')
|
||||
Source('rv_ctrl.cc')
|
||||
Source('realview.cc')
|
||||
|
||||
TraceFlag('AMBA')
|
||||
TraceFlag('PL111')
|
||||
TraceFlag('GIC')
|
||||
|
|
|
@ -42,20 +42,23 @@
|
|||
|
||||
#include "base/trace.hh"
|
||||
#include "dev/arm/amba_fake.hh"
|
||||
#include "dev/arm/amba_device.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
|
||||
const uint64_t AmbaVendor = ULL(0xb105f00d00000000);
|
||||
AmbaDevice::AmbaDevice(const Params *p)
|
||||
: BasicPioDevice(p), ambaId(ULL(0xb105f00d00000000) | p->amba_id)
|
||||
: BasicPioDevice(p), ambaId(AmbaVendor | p->amba_id)
|
||||
{
|
||||
}
|
||||
|
||||
AmbaDmaDevice::AmbaDmaDevice(const Params *p)
|
||||
: DmaDevice(p), ambaId(ULL(0xb105f00d00000000) | p->amba_id)
|
||||
: DmaDevice(p), ambaId(AmbaVendor | p->amba_id),
|
||||
pioAddr(p->pio_addr), pioSize(0),
|
||||
pioDelay(p->pio_latency),intNum(p->int_num), gic(p->gic)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
namespace AmbaDev {
|
||||
bool
|
||||
readId(PacketPtr pkt, uint64_t amba_id, Addr pio_addr)
|
||||
|
|
|
@ -46,13 +46,14 @@
|
|||
* Implementer ID calls.
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_AMBA_DEVICE_H__
|
||||
#define __DEV_ARM_AMBA_DEVICE_H__
|
||||
#ifndef __DEV_ARM_AMBA_DEVICE_HH__
|
||||
#define __DEV_ARM_AMBA_DEVICE_HH__
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "dev/arm/gic.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
#include "dev/io_device.hh"
|
||||
#include "params/AmbaDevice.hh"
|
||||
#include "params/AmbaDmaDevice.hh"
|
||||
|
||||
|
@ -84,6 +85,11 @@ class AmbaDmaDevice : public DmaDevice
|
|||
{
|
||||
protected:
|
||||
uint64_t ambaId;
|
||||
Addr pioAddr;
|
||||
Addr pioSize;
|
||||
Tick pioDelay;
|
||||
int intNum;
|
||||
Gic *gic;
|
||||
|
||||
public:
|
||||
typedef AmbaDmaDeviceParams Params;
|
||||
|
@ -91,4 +97,4 @@ class AmbaDmaDevice : public DmaDevice
|
|||
};
|
||||
|
||||
|
||||
#endif //__DEV_ARM_AMBA_DEVICE_H__
|
||||
#endif //__DEV_ARM_AMBA_DEVICE_HH__
|
||||
|
|
653
src/dev/arm/pl111.cc
Normal file
653
src/dev/arm/pl111.cc
Normal file
|
@ -0,0 +1,653 @@
|
|||
/*
|
||||
* Copyright (c) 2010 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: William Wang
|
||||
*/
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "dev/arm/amba_device.hh"
|
||||
#include "dev/arm/gic.hh"
|
||||
#include "dev/arm/pl111.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/packet_access.hh"
|
||||
|
||||
using namespace AmbaDev;
|
||||
|
||||
// initialize clcd registers
|
||||
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),
|
||||
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),
|
||||
waterMark(0), dmaPendingNum(0), readEvent(this), fillFifoEvent(this),
|
||||
dmaDoneEvent(maxOutstandingDma, this), intEvent(this)
|
||||
{
|
||||
pioSize = 0xFFFF;
|
||||
|
||||
memset(lcdPalette, 0, sizeof(lcdPalette));
|
||||
memset(cursorImage, 0, sizeof(cursorImage));
|
||||
memset(dmaBuffer, 0, sizeof(dmaBuffer));
|
||||
memset(frameBuffer, 0, sizeof(frameBuffer));
|
||||
}
|
||||
|
||||
// read registers and frame buffer
|
||||
Tick
|
||||
Pl111::read(PacketPtr pkt)
|
||||
{
|
||||
// use a temporary data since the LCD registers are read/written with
|
||||
// different size operations
|
||||
|
||||
uint32_t data = 0;
|
||||
|
||||
if ((pkt->getAddr()& 0xffff0000) == pioAddr) {
|
||||
|
||||
assert(pkt->getAddr() >= pioAddr &&
|
||||
pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
Addr daddr = pkt->getAddr()&0xFFFF;
|
||||
pkt->allocate();
|
||||
|
||||
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 \
|
||||
doesn't exist\n", daddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(pkt->getSize()) {
|
||||
case 1:
|
||||
pkt->set<uint8_t>(data);
|
||||
break;
|
||||
case 2:
|
||||
pkt->set<uint16_t>(data);
|
||||
break;
|
||||
case 4:
|
||||
pkt->set<uint32_t>(data);
|
||||
break;
|
||||
default:
|
||||
panic("CLCD controller read size too big?\n");
|
||||
break;
|
||||
}
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
// write registers and frame buffer
|
||||
Tick
|
||||
Pl111::write(PacketPtr pkt)
|
||||
{
|
||||
// use a temporary data since the LCD registers are read/written with
|
||||
// different size operations
|
||||
//
|
||||
uint32_t data = 0;
|
||||
|
||||
switch(pkt->getSize()) {
|
||||
case 1:
|
||||
data = pkt->get<uint8_t>();
|
||||
break;
|
||||
case 2:
|
||||
data = pkt->get<uint16_t>();
|
||||
break;
|
||||
case 4:
|
||||
data = pkt->get<uint32_t>();
|
||||
break;
|
||||
default:
|
||||
panic("PL111 CLCD controller write size too big?\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if ((pkt->getAddr()& 0xffff0000) == pioAddr) {
|
||||
|
||||
assert(pkt->getAddr() >= pioAddr &&
|
||||
pkt->getAddr() < pioAddr + pioSize);
|
||||
|
||||
Addr daddr = pkt->getAddr() - pioAddr;
|
||||
|
||||
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;
|
||||
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 \
|
||||
doesn't exist\n", daddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pkt->makeAtomicResponse();
|
||||
return pioDelay;
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::readFramebuffer()
|
||||
{
|
||||
// initialization for dma read from frame buffer to dma buffer
|
||||
uint32_t length = height*width;
|
||||
if (startAddr != lcdUpbase) {
|
||||
startAddr = lcdUpbase;
|
||||
}
|
||||
curAddr = 0;
|
||||
startTime = curTick;
|
||||
maxAddr = static_cast<Addr>(length*sizeof(uint32_t));
|
||||
dmaPendingNum =0 ;
|
||||
|
||||
fillFifo();
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::fillFifo()
|
||||
{
|
||||
while ((dmaPendingNum < maxOutstandingDma) && (maxAddr >= curAddr + dmaSize )) {
|
||||
// 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);
|
||||
curAddr += dmaSize;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::dmaDone()
|
||||
{
|
||||
Tick maxFrameTime = lcdTiming2.cpl*height*clock;
|
||||
|
||||
--dmaPendingNum;
|
||||
|
||||
DPRINTF(PL111, " -- DMA pending number %d\n", dmaPendingNum);
|
||||
|
||||
if (maxAddr == curAddr && !dmaPendingNum) {
|
||||
if ((curTick - startTime) > maxFrameTime)
|
||||
warn("CLCD controller buffer underrun, took %d cycles when should"
|
||||
" have taken %d\n", curTick - startTime, maxFrameTime);
|
||||
|
||||
// double buffering so the vnc server doesn't see a tear in the screen
|
||||
memcpy(frameBuffer, dmaBuffer, maxAddr);
|
||||
assert(!readEvent.scheduled());
|
||||
|
||||
DPRINTF(PL111, "-- write out frame buffer into bmp\n");
|
||||
writeBMP(frameBuffer);
|
||||
|
||||
DPRINTF(PL111, "-- schedule next dma read event at %d tick \n",
|
||||
maxFrameTime + curTick);
|
||||
schedule(readEvent, nextCycle(startTime + maxFrameTime));
|
||||
}
|
||||
|
||||
if (dmaPendingNum > (maxOutstandingDma - waterMark))
|
||||
return;
|
||||
|
||||
if (!fillFifoEvent.scheduled())
|
||||
schedule(fillFifoEvent, nextCycle());
|
||||
|
||||
}
|
||||
|
||||
Tick
|
||||
Pl111::nextCycle()
|
||||
{
|
||||
Tick nextTick = curTick + clock - 1;
|
||||
nextTick -= nextTick%clock;
|
||||
return nextTick;
|
||||
}
|
||||
|
||||
Tick
|
||||
Pl111::nextCycle(Tick beginTick)
|
||||
{
|
||||
Tick nextTick = beginTick;
|
||||
if (nextTick%clock!=0)
|
||||
nextTick = nextTick - (nextTick%clock) + clock;
|
||||
|
||||
assert(nextTick >= curTick);
|
||||
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)
|
||||
{
|
||||
DPRINTF(PL111, "Serializing ARM PL111\n");
|
||||
|
||||
uint32_t lcdTiming0_serial = lcdTiming0;
|
||||
SERIALIZE_SCALAR(lcdTiming0_serial);
|
||||
|
||||
uint32_t lcdTiming1_serial = lcdTiming1;
|
||||
SERIALIZE_SCALAR(lcdTiming1_serial);
|
||||
|
||||
uint32_t lcdTiming2_serial = lcdTiming2;
|
||||
SERIALIZE_SCALAR(lcdTiming2_serial);
|
||||
|
||||
uint32_t lcdTiming3_serial = lcdTiming3;
|
||||
SERIALIZE_SCALAR(lcdTiming3_serial);
|
||||
|
||||
SERIALIZE_SCALAR(lcdUpbase);
|
||||
SERIALIZE_SCALAR(lcdLpbase);
|
||||
|
||||
uint32_t lcdControl_serial = lcdControl;
|
||||
SERIALIZE_SCALAR(lcdControl_serial);
|
||||
|
||||
uint8_t lcdImsc_serial = lcdImsc;
|
||||
SERIALIZE_SCALAR(lcdImsc_serial);
|
||||
|
||||
uint8_t lcdRis_serial = lcdRis;
|
||||
SERIALIZE_SCALAR(lcdRis_serial);
|
||||
|
||||
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(clcdCrsrCtrl);
|
||||
SERIALIZE_SCALAR(clcdCrsrConfig);
|
||||
SERIALIZE_SCALAR(clcdCrsrPalette0);
|
||||
SERIALIZE_SCALAR(clcdCrsrPalette1);
|
||||
SERIALIZE_SCALAR(clcdCrsrXY);
|
||||
SERIALIZE_SCALAR(clcdCrsrClip);
|
||||
|
||||
uint8_t clcdCrsrImsc_serial = clcdCrsrImsc;
|
||||
SERIALIZE_SCALAR(clcdCrsrImsc_serial);
|
||||
|
||||
uint8_t clcdCrsrIcr_serial = clcdCrsrIcr;
|
||||
SERIALIZE_SCALAR(clcdCrsrIcr_serial);
|
||||
|
||||
uint8_t clcdCrsrRis_serial = clcdCrsrRis;
|
||||
SERIALIZE_SCALAR(clcdCrsrRis_serial);
|
||||
|
||||
uint8_t clcdCrsrMis_serial = clcdCrsrMis;
|
||||
SERIALIZE_SCALAR(clcdCrsrMis_serial);
|
||||
|
||||
SERIALIZE_SCALAR(clock);
|
||||
SERIALIZE_SCALAR(height);
|
||||
SERIALIZE_SCALAR(width);
|
||||
|
||||
SERIALIZE_ARRAY(dmaBuffer, height*width);
|
||||
SERIALIZE_ARRAY(frameBuffer, height*width);
|
||||
SERIALIZE_SCALAR(startTime);
|
||||
SERIALIZE_SCALAR(startAddr);
|
||||
SERIALIZE_SCALAR(maxAddr);
|
||||
SERIALIZE_SCALAR(curAddr);
|
||||
SERIALIZE_SCALAR(waterMark);
|
||||
SERIALIZE_SCALAR(dmaPendingNum);
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
DPRINTF(PL111, "Unserializing ARM PL111\n");
|
||||
|
||||
uint32_t lcdTiming0_serial;
|
||||
UNSERIALIZE_SCALAR(lcdTiming0_serial);
|
||||
lcdTiming0 = lcdTiming0_serial;
|
||||
|
||||
uint32_t lcdTiming1_serial;
|
||||
UNSERIALIZE_SCALAR(lcdTiming1_serial);
|
||||
lcdTiming1 = lcdTiming1_serial;
|
||||
|
||||
uint32_t lcdTiming2_serial;
|
||||
UNSERIALIZE_SCALAR(lcdTiming2_serial);
|
||||
lcdTiming2 = lcdTiming2_serial;
|
||||
|
||||
uint32_t lcdTiming3_serial;
|
||||
UNSERIALIZE_SCALAR(lcdTiming3_serial);
|
||||
lcdTiming3 = lcdTiming3_serial;
|
||||
|
||||
UNSERIALIZE_SCALAR(lcdUpbase);
|
||||
UNSERIALIZE_SCALAR(lcdLpbase);
|
||||
|
||||
uint32_t lcdControl_serial;
|
||||
UNSERIALIZE_SCALAR(lcdControl_serial);
|
||||
lcdControl = lcdControl_serial;
|
||||
|
||||
uint8_t lcdImsc_serial;
|
||||
UNSERIALIZE_SCALAR(lcdImsc_serial);
|
||||
lcdImsc = lcdImsc_serial;
|
||||
|
||||
uint8_t lcdRis_serial;
|
||||
UNSERIALIZE_SCALAR(lcdRis_serial);
|
||||
lcdRis = lcdRis_serial;
|
||||
|
||||
uint8_t lcdMis_serial;
|
||||
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(clcdCrsrCtrl);
|
||||
UNSERIALIZE_SCALAR(clcdCrsrConfig);
|
||||
UNSERIALIZE_SCALAR(clcdCrsrPalette0);
|
||||
UNSERIALIZE_SCALAR(clcdCrsrPalette1);
|
||||
UNSERIALIZE_SCALAR(clcdCrsrXY);
|
||||
UNSERIALIZE_SCALAR(clcdCrsrClip);
|
||||
|
||||
uint8_t clcdCrsrImsc_serial;
|
||||
UNSERIALIZE_SCALAR(clcdCrsrImsc_serial);
|
||||
clcdCrsrImsc = clcdCrsrImsc_serial;
|
||||
|
||||
uint8_t clcdCrsrIcr_serial;
|
||||
UNSERIALIZE_SCALAR(clcdCrsrIcr_serial);
|
||||
clcdCrsrIcr = clcdCrsrIcr_serial;
|
||||
|
||||
uint8_t clcdCrsrRis_serial;
|
||||
UNSERIALIZE_SCALAR(clcdCrsrRis_serial);
|
||||
clcdCrsrRis = clcdCrsrRis_serial;
|
||||
|
||||
uint8_t clcdCrsrMis_serial;
|
||||
UNSERIALIZE_SCALAR(clcdCrsrMis_serial);
|
||||
clcdCrsrMis = clcdCrsrMis_serial;
|
||||
|
||||
UNSERIALIZE_SCALAR(clock);
|
||||
UNSERIALIZE_SCALAR(height);
|
||||
UNSERIALIZE_SCALAR(width);
|
||||
|
||||
UNSERIALIZE_ARRAY(dmaBuffer, height*width);
|
||||
UNSERIALIZE_ARRAY(frameBuffer, height*width);
|
||||
UNSERIALIZE_SCALAR(startTime);
|
||||
UNSERIALIZE_SCALAR(startAddr);
|
||||
UNSERIALIZE_SCALAR(maxAddr);
|
||||
UNSERIALIZE_SCALAR(curAddr);
|
||||
UNSERIALIZE_SCALAR(waterMark);
|
||||
UNSERIALIZE_SCALAR(dmaPendingNum);
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::generateInterrupt()
|
||||
{
|
||||
DPRINTF(PL111, "Generate Interrupt: lcdImsc=0x%x lcdRis=0x%x lcdMis=0x%x\n",
|
||||
lcdImsc, lcdRis, lcdMis);
|
||||
lcdMis = lcdImsc & lcdRis;
|
||||
|
||||
if (lcdMis.ffufie || lcdMis.nbupie || lcdMis.vtcpie || lcdMis.ahmeie) {
|
||||
gic->sendInt(intNum);
|
||||
DPRINTF(PL111, " -- Generated\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Pl111::addressRanges(AddrRangeList& range_list)
|
||||
{
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeSize(pioAddr, pioSize));
|
||||
}
|
||||
|
||||
Pl111 *
|
||||
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));
|
||||
}
|
368
src/dev/arm/pl111.hh
Normal file
368
src/dev/arm/pl111.hh
Normal file
|
@ -0,0 +1,368 @@
|
|||
/*
|
||||
* Copyright (c) 2010 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: William Wang
|
||||
*/
|
||||
|
||||
|
||||
/** @file
|
||||
* Implementiation of a PL111 CLCD controller
|
||||
*/
|
||||
|
||||
#ifndef __DEV_ARM_PL111_HH__
|
||||
#define __DEV_ARM_PL111_HH__
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "base/range.hh"
|
||||
#include "dev/arm/amba_device.hh"
|
||||
#include "params/Pl111.hh"
|
||||
#include "sim/serialize.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Gic;
|
||||
|
||||
class Pl111: public AmbaDmaDevice
|
||||
{
|
||||
protected:
|
||||
static const uint64_t AMBA_ID = ULL(0xb105f00d00141111);
|
||||
/** ARM PL111 register map*/
|
||||
static const int LcdTiming0 = 0x000;
|
||||
static const int LcdTiming1 = 0x004;
|
||||
static const int LcdTiming2 = 0x008;
|
||||
static const int LcdTiming3 = 0x00C;
|
||||
static const int LcdUpBase = 0x010;
|
||||
static const int LcdLpBase = 0x014;
|
||||
static const int LcdControl = 0x018;
|
||||
static const int LcdImsc = 0x01C;
|
||||
static const int LcdRis = 0x020;
|
||||
static const int LcdMis = 0x024;
|
||||
static const int LcdIcr = 0x028;
|
||||
static const int LcdUpCurr = 0x02C;
|
||||
static const int LcdLpCurr = 0x030;
|
||||
static const int LcdPalette = 0x200;
|
||||
static const int CrsrImage = 0x800;
|
||||
static const int ClcdCrsrCtrl = 0xC00;
|
||||
static const int ClcdCrsrConfig = 0xC04;
|
||||
static const int ClcdCrsrPalette0 = 0xC08;
|
||||
static const int ClcdCrsrPalette1 = 0xC0C;
|
||||
static const int ClcdCrsrXY = 0xC10;
|
||||
static const int ClcdCrsrClip = 0xC14;
|
||||
static const int ClcdCrsrImsc = 0xC20;
|
||||
static const int ClcdCrsrIcr = 0xC24;
|
||||
static const int ClcdCrsrRis = 0xC28;
|
||||
static const int ClcdCrsrMis = 0xC2C;
|
||||
|
||||
static const int LcdPaletteSize = 128;
|
||||
static const int CrsrImageSize = 256;
|
||||
|
||||
static const int LcdMaxWidth = 1024; // pixels per line
|
||||
static const int LcdMaxHeight = 768; // lines per panel
|
||||
|
||||
static const int dmaSize = 8; // 64 bits
|
||||
static const int maxOutstandingDma = 16; // 16 deep FIFO of 64 bits
|
||||
|
||||
BitUnion8(InterruptReg)
|
||||
Bitfield<1> ffufie;
|
||||
Bitfield<2> nbupie;
|
||||
Bitfield<3> vtcpie;
|
||||
Bitfield<4> ahmeie;
|
||||
EndBitUnion(InterruptReg)
|
||||
|
||||
BitUnion32(TimingReg0)
|
||||
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;
|
||||
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;
|
||||
EndBitUnion(TimingReg2)
|
||||
|
||||
BitUnion32(TimingReg3)
|
||||
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;
|
||||
EndBitUnion(ControlReg)
|
||||
|
||||
/** Horizontal axis panel control register */
|
||||
TimingReg0 lcdTiming0;
|
||||
|
||||
/** Vertical axis panel control register */
|
||||
TimingReg1 lcdTiming1;
|
||||
|
||||
/** Clock and signal polarity control register */
|
||||
TimingReg2 lcdTiming2;
|
||||
|
||||
/** Line end control register */
|
||||
TimingReg3 lcdTiming3;
|
||||
|
||||
/** Upper panel frame base address register */
|
||||
int lcdUpbase;
|
||||
|
||||
/** Lower panel frame base address register */
|
||||
int lcdLpbase;
|
||||
|
||||
/** Control register */
|
||||
ControlReg lcdControl;
|
||||
|
||||
/** Interrupt mask set/clear register */
|
||||
InterruptReg lcdImsc;
|
||||
|
||||
/** Raw interrupt status register - const */
|
||||
InterruptReg lcdRis;
|
||||
|
||||
/** 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];
|
||||
|
||||
/** Cursor image RAM register
|
||||
* 256-word wide values defining images overlaid by the hw cursor mechanism */
|
||||
int cursorImage[CrsrImageSize];
|
||||
|
||||
/** Cursor control register */
|
||||
int clcdCrsrCtrl;
|
||||
|
||||
/** Cursor configuration register */
|
||||
int clcdCrsrConfig;
|
||||
|
||||
/** Cursor palette registers */
|
||||
int clcdCrsrPalette0;
|
||||
int clcdCrsrPalette1;
|
||||
|
||||
/** Cursor XY position register */
|
||||
int clcdCrsrXY;
|
||||
|
||||
/** Cursor clip position register */
|
||||
int clcdCrsrClip;
|
||||
|
||||
/** Cursor interrupt mask set/clear register */
|
||||
InterruptReg clcdCrsrImsc;
|
||||
|
||||
/** Cursor interrupt clear register */
|
||||
InterruptReg clcdCrsrIcr;
|
||||
|
||||
/** Cursor raw interrupt status register - const */
|
||||
InterruptReg clcdCrsrRis;
|
||||
|
||||
/** Cursor masked interrupt status register - const */
|
||||
InterruptReg clcdCrsrMis;
|
||||
|
||||
/** Clock speed */
|
||||
Tick clock;
|
||||
|
||||
/** Frame buffer height - lines per panel */
|
||||
uint16_t height;
|
||||
|
||||
/** Frame buffer width - pixels per line */
|
||||
uint16_t width;
|
||||
|
||||
/** CLCDC supports up to 1024x768 */
|
||||
uint8_t dmaBuffer[LcdMaxWidth * LcdMaxHeight * sizeof(uint32_t)];
|
||||
|
||||
/** Double buffering */
|
||||
uint32_t frameBuffer[LcdMaxWidth * LcdMaxHeight];
|
||||
|
||||
/** Start time for frame buffer dma read */
|
||||
Tick startTime;
|
||||
|
||||
/** Frame buffer base address */
|
||||
Addr startAddr;
|
||||
|
||||
/** Frame buffer max address */
|
||||
Addr maxAddr;
|
||||
|
||||
/** Frame buffer current address */
|
||||
Addr curAddr;
|
||||
|
||||
/** DMA FIFO watermark */
|
||||
int waterMark;
|
||||
|
||||
/** Number of pending dma reads */
|
||||
int dmaPendingNum;
|
||||
|
||||
/** DMA framebuffer read */
|
||||
void readFramebuffer();
|
||||
|
||||
/** Write framebuffer to a bmp file */
|
||||
void writeBMP(uint32_t*);
|
||||
|
||||
/** Generate dma framebuffer read event */
|
||||
void generateReadEvent();
|
||||
|
||||
/** Function to generate interrupt */
|
||||
void generateInterrupt();
|
||||
|
||||
/** fillFIFO event */
|
||||
void fillFifo();
|
||||
|
||||
/** DMA done event */
|
||||
void dmaDone();
|
||||
|
||||
/** Next cycle event */
|
||||
Tick nextCycle();
|
||||
Tick nextCycle(Tick beginTick);
|
||||
|
||||
/** DMA framebuffer read event */
|
||||
EventWrapper<Pl111, &Pl111::readFramebuffer> readEvent;
|
||||
|
||||
/** Fill fifo */
|
||||
EventWrapper<Pl111, &Pl111::fillFifo> fillFifoEvent;
|
||||
|
||||
/** DMA done event */
|
||||
vector<EventWrapper<Pl111, &Pl111::dmaDone> > dmaDoneEvent;
|
||||
|
||||
/** Wrapper to create an event out of the thing */
|
||||
EventWrapper<Pl111, &Pl111::generateInterrupt> intEvent;
|
||||
|
||||
public:
|
||||
typedef Pl111Params Params;
|
||||
|
||||
const Params *
|
||||
params() const
|
||||
{
|
||||
return dynamic_cast<const Params *>(_params);
|
||||
}
|
||||
Pl111(const Params *p);
|
||||
|
||||
virtual Tick read(PacketPtr pkt);
|
||||
virtual Tick write(PacketPtr pkt);
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
/** return the address ranges that this device responds to.
|
||||
* @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
|
Loading…
Reference in a new issue