diff -r 67af516e5cbd -r 6620791e63ad src/dev/arm/RealView.py --- a/src/dev/arm/RealView.py Thu Sep 16 10:48:40 2010 +0300 +++ b/src/dev/arm/RealView.py Thu Sep 16 10:49:06 2010 +0300 @@ -54,6 +54,10 @@ 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,24 @@ clock1 = Param.Clock('1MHz', "Clock speed of the input") amba_id = 0x00141804 +class Pl111(AmbaDmaDevice): + type = 'Pl111' + 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, warn_access="1") dmac_fake = AmbaFake(pio_addr=0x10030000) @@ -106,7 +118,6 @@ 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) @@ -135,12 +146,12 @@ 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 @@ -154,12 +165,14 @@ self.kmi1_fake.pio = bus.port self.rtc_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) @@ -167,7 +180,6 @@ 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) @@ -196,12 +208,12 @@ 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 diff -r 67af516e5cbd -r 6620791e63ad src/dev/arm/SConscript --- a/src/dev/arm/SConscript Thu Sep 16 10:48:40 2010 +0300 +++ b/src/dev/arm/SConscript Thu Sep 16 10:49:06 2010 +0300 @@ -46,8 +46,10 @@ 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') \ No newline at end of file diff -r 67af516e5cbd -r 6620791e63ad src/dev/arm/amba_device.hh --- a/src/dev/arm/amba_device.hh Thu Sep 16 10:48:40 2010 +0300 +++ b/src/dev/arm/amba_device.hh Thu Sep 16 10:49:06 2010 +0300 @@ -55,6 +55,7 @@ #include "dev/io_device.hh" #include "params/AmbaDevice.hh" #include "params/AmbaDmaDevice.hh" +#include "dev/arm/gic.hh" namespace AmbaDev { @@ -84,6 +85,11 @@ { protected: uint64_t ambaId; + Addr pioAddr; + Addr pioSize; + Tick pioDelay; + int intNum; + Gic *gic; public: typedef AmbaDmaDeviceParams Params; diff -r 67af516e5cbd -r 6620791e63ad src/dev/arm/amba_device.cc --- a/src/dev/arm/amba_device.cc Thu Sep 16 10:48:40 2010 +0300 +++ b/src/dev/arm/amba_device.cc Thu Sep 16 10:49:06 2010 +0300 @@ -44,6 +44,7 @@ #include "dev/arm/amba_fake.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" +#include "amba_device.hh" AmbaDevice::AmbaDevice(const Params *p) : BasicPioDevice(p), ambaId(ULL(0xb105f00d00000000) | p->amba_id) @@ -51,11 +52,12 @@ } AmbaDmaDevice::AmbaDmaDevice(const Params *p) - : DmaDevice(p), ambaId(ULL(0xb105f00d00000000) | p->amba_id) + : DmaDevice(p), ambaId(ULL(0xb105f00d00000000) | 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) diff -r 67af516e5cbd -r 6620791e63ad src/dev/arm/pl111.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dev/arm/pl111.hh Thu Sep 16 10:49:06 2010 +0300 @@ -0,0 +1,256 @@ +/* + * 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_H__ +#define __DEV_ARM_PL111_H__ + +#include "base/range.hh" +#include "params/Pl111.hh" +#include "dev/arm/amba_device.hh" +#include + +using namespace std; + +class Gic; + +class Pl111: public AmbaDmaDevice +{ + protected: + //Frame buffer + static const int FB_ADDR = 0X08000000; + static const int FB_SIZE = 0X001D4C00; // 800x600x4 + static const int FB_LEN = 0X00075300; // 800x600 + static const uint16_t HEIGHT = 600; + static const uint16_t WIDTH = 800; + + protected: + static const uint64_t AMBA_ID = ULL(0xb105f00d00141111); + /* ARM PL111 register map*/ + static const int LCD_TIMING0 = 0x000; + static const int LCD_TIMING1 = 0x004; + static const int LCD_TIMING2 = 0x008; + static const int LCD_TIMING3 = 0x00C; + static const int LCD_UPBASE = 0x010; + static const int LCD_LPBASE = 0x014; + static const int LCD_CONTROL = 0x018; + static const int LCD_IMSC = 0x01C; + static const int LCD_RIS = 0x020; + static const int LCD_MIS = 0x024; + static const int LCD_ICR = 0x028; + static const int LCD_UPCURR = 0x02C; + static const int LCD_LPCURR = 0x030; + static const int LCD_PALETTE = 0x200; + static const int CRSR_IMAGE = 0x800; + static const int CLCD_CRSR_CTRL = 0xC00; + static const int CLCD_CRSR_CONFIG = 0xC04; + static const int CLCD_CRSR_PALETTE0 = 0xC08; + static const int CLCD_CRSR_PALETTE1 = 0xC0C; + static const int CLCD_CRSR_XY = 0xC10; + static const int CLCD_CRSR_CLIP = 0xC14; + static const int CLCD_CRSR_IMSC = 0xC20; + static const int CLCD_CRSR_ICR = 0xC24; + static const int CLCD_CRSR_RIS = 0xC28; + static const int CLCD_CRSR_MIS = 0xC2C; + + static const int LCD_PALETTE_SIZE = 128; + static const int CRSR_IMAGE_SIZE = 256; + + BitUnion8(INTREG_PL111) + Bitfield<1> ffufie; + Bitfield<2> nbupie; + Bitfield<3> vtcpie; + Bitfield<4> ahmeie; + EndBitUnion(INTREG_PL111) + + // frame buffer + uint32_t frameBuffer[FB_LEN]; + fstream pic; + + //Horizontal axis panel control register + int lcdTiming0; + + //Vertical axis panel control register + int lcdTiming1; + + //Clock and signal polarity control register + int lcdTiming2; + + //Line end control register + int lcdTiming3; + + //Upper panel frame base address register + int lcdUpbase; + + //Lower panel frame base address register + int lcdLpbase; + + // Control register + int lcdControl; + + /** interrupt mask set/clear register. */ + INTREG_PL111 lcdImsc; + + /** raw interrupt status register */ + const INTREG_PL111 lcdRis; + + /** Masked interrupt status register */ + INTREG_PL111 lcdMis; + + // Interrupt clear register + INTREG_PL111 lcdIcr; + + //Upper panel current address value register + const int lcdUpcurr; + + //Lower panel current address value register + const int lcdLpcurr; + + //256x16-bit color palette registers + //256 palette entries organized as 128 locations of two entries per word + int lcdPalette[LCD_PALETTE_SIZE]; + + //Cursor image RAM register + //256-word wide values defining images overlaid by the hw cursor mechanism + int cursorImage[CRSR_IMAGE_SIZE]; + + //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 + INTREG_PL111 clcdCrsrImsc; + + //Cursor interrupt clear register + INTREG_PL111 clcdCrsrIcr; + + //Cursor raw interrupt status register + const INTREG_PL111 clcdCrsrRis; + + //Cursor masked interrupt status register + const INTREG_PL111 clcdCrsrMis; + + /** Function to generate interrupt */ + void generateInterrupt(); + + /** Wrapper to create an event out of the thing */ + EventWrapper intEvent; + + public: + typedef Pl111Params Params; + + const Params * + params() const + { + return dynamic_cast(_params); + } + Pl111(const Params *p); + + virtual Tick read(PacketPtr pkt); + virtual Tick write(PacketPtr pkt); + + /** 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 diff -r 67af516e5cbd -r 6620791e63ad src/dev/arm/pl111.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dev/arm/pl111.cc Thu Sep 16 10:49:06 2010 +0300 @@ -0,0 +1,404 @@ +/* + * 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),intEvent(this) +{ + pioSize = 0xFFFF; + + for(int i = 0; i < LCD_PALETTE_SIZE ; ++i) + lcdPalette[i] = 0x00000000; + + for(int i = 0; i < CRSR_IMAGE_SIZE ; ++i) + cursorImage[i] = 0x00000000; +} + +// read registers and frame buffer +Tick +Pl111::read(PacketPtr pkt) +{ + // use a temporary data since the CLCD 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 LCD_TIMING0: + data = lcdTiming0; + break; + case LCD_TIMING1: + data = lcdTiming1; + break; + case LCD_TIMING2: + data = lcdTiming2; + break; + case LCD_TIMING3: + data = lcdTiming3; + break; + case LCD_UPBASE: + data = lcdUpbase; + break; + case LCD_LPBASE: + data = lcdLpbase; + break; + case LCD_CONTROL: + data = lcdControl; + break; + case LCD_IMSC: + data = lcdImsc; + break; + case LCD_RIS: + data = lcdRis; + break; + case LCD_MIS: + data = lcdMis; + break; + case LCD_ICR: + panic("LCD Interrupt Clear Register at offset %#x is Write-Only\n", daddr); + break; + case LCD_UPCURR: + data = lcdUpcurr; + break; + case LCD_LPCURR: + data = lcdLpcurr; + break; + case CLCD_CRSR_CTRL: + data = clcdCrsrCtrl; + break; + case CLCD_CRSR_CONFIG: + data = clcdCrsrConfig; + break; + case CLCD_CRSR_PALETTE0: + data = clcdCrsrPalette0; + break; + case CLCD_CRSR_PALETTE1: + data = clcdCrsrPalette1; + break; + case CLCD_CRSR_XY: + data = clcdCrsrXY; + break; + case CLCD_CRSR_CLIP: + data = clcdCrsrClip; + break; + case CLCD_CRSR_IMSC: + data = clcdCrsrImsc; + break; + case CLCD_CRSR_ICR: + panic("Cursor Interrupt Clear Register at offset %#x is Write-Only\n", daddr); + break; + case CLCD_CRSR_RIS: + data = clcdCrsrRis; + break; + case CLCD_CRSR_MIS: + data = clcdCrsrMis; + break; + default: + if (AmbaDev::readId(pkt, AMBA_ID, pioAddr)) { + // Hack for variable size accesses + data = pkt->get(); + break; + } + + else if (daddr >= CRSR_IMAGE && daddr <= 0xBFC) { + // CURSOR IMAGE + int index; + index = (daddr - CRSR_IMAGE) >> 2; + data= cursorImage[index]; + break; + } + + else if (daddr >= LCD_PALETTE && daddr <= 0x3FC) { + // LCD Palette + int index; + index = (daddr - LCD_PALETTE) >> 2; + data = lcdPalette[index]; + break; + } + + else{ + panic("Tried to read CLCD controller PL111 at offset %#x that doesn't exist\n", daddr); + break; + } + } + } + + else if((pkt->getAddr() >= lcdUpbase) && (pkt->getAddr() < (lcdUpbase + FB_SIZE))){ + int index; + index = (pkt->getAddr() - lcdUpbase) >> 2; + data = frameBuffer[index]; + DPRINTF(PL111, " read frame buffer %#x value %#x\n", index, data); + + // write out the frame buffer into a bitmap file + std::string filename = "./m5out/frameBuffer.bmp"; + pic.open(filename.c_str(), ios::out|ios::binary); + Bitmap bm(pic, HEIGHT, WIDTH); + + // read the frame buffer base address when frame buffer is full + // act as the end of frame buffer signal that triggers + // this frame buffer write out + if (index==0){ + for(int i = (FB_LEN/WIDTH) -1; i >= 0; --i){ + for(int j = 0; j(&pixel), sizeof(uint32_t)); + } + } + } + + pic.close(); + } + + switch(pkt->getSize()) { + case 1: + pkt->set(data); + break; + case 2: + pkt->set(data); + break; + case 4: + pkt->set(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 uart registers are read/written with + // different size operations + // + uint32_t data = 0; + + switch(pkt->getSize()) { + case 1: + data = pkt->get(); + break; + case 2: + data = pkt->get(); + break; + case 4: + data = pkt->get(); + 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(), pkt->getSize()); + + switch (daddr) { + case LCD_TIMING0: + lcdTiming0 = data; + break; + case LCD_TIMING1: + lcdTiming1 = data; + break; + case LCD_TIMING2: + lcdTiming2 = data; + break; + case LCD_TIMING3: + lcdTiming3 = data; + break; + case LCD_UPBASE: + lcdUpbase = data; + break; + case LCD_LPBASE: + lcdLpbase = data; + break; + case LCD_CONTROL: + lcdControl = data; + break; + case LCD_IMSC: + lcdImsc = data; + break; + case LCD_RIS: + warn("LCD Raw Interrupt Status Register at offset %#x is Read-Only\n", daddr); + break; + case LCD_MIS: + warn("LCD Masked Interrupt Status Register at offset %#x is Read-Only\n", daddr); + break; + case LCD_ICR: + lcdIcr = data; + break; + case LCD_UPCURR: + warn("LCD Upper Panel Current Address Value Register at offset %#x is Read-Only\n", daddr); + break; + case LCD_LPCURR: + warn("LCD Upper Panel Current Address Value Register at offset %#x is Read-Only\n", daddr); + break; + case CLCD_CRSR_CTRL: + clcdCrsrCtrl = data; + break; + case CLCD_CRSR_CONFIG: + clcdCrsrConfig = data; + break; + case CLCD_CRSR_PALETTE0: + clcdCrsrPalette0 = data; + break; + case CLCD_CRSR_PALETTE1: + clcdCrsrPalette1 = data; + break; + case CLCD_CRSR_XY: + clcdCrsrXY = data; + break; + case CLCD_CRSR_CLIP: + clcdCrsrClip = data; + break; + case CLCD_CRSR_IMSC: + clcdCrsrImsc = data; + break; + case CLCD_CRSR_ICR: + clcdCrsrIcr = data; + break; + case CLCD_CRSR_RIS: + warn("Cursor Raw Interrupt Status Register at offset %#x is Read-Only\n", daddr); + break; + case CLCD_CRSR_MIS: + warn("Cursor Masked Interrupt Status Register at offset %#x is Read-Only\n", daddr); + break; + default: + if (daddr >= CRSR_IMAGE && daddr <= 0xBFC) { + // CURSOR IMAGE + int index; + index = (daddr - CRSR_IMAGE) >> 2; + cursorImage[index] = data; + break; + } + + else if (daddr >= LCD_PALETTE && daddr <= 0x3FC) { + // LCD Palette + int index; + index = (daddr - LCD_PALETTE) >> 2; + lcdPalette[index] = data; + break; + } + + else{ + panic("Tried to write PL111 at offset %#x that doesn't exist\n", daddr); + break; + } + } + } + + else if((pkt->getAddr() >= lcdUpbase) && (pkt->getAddr() < (lcdUpbase + FB_SIZE))){ + + int index; + index = (pkt->getAddr() - lcdUpbase) >> 2; + frameBuffer[index] = data; + DPRINTF(PL111, " write frame buffer %#x value %#x\n", index, data); + } + pkt->makeAtomicResponse(); + return pioDelay; +} + +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(FB_ADDR, FB_SIZE)); + 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(&magic), sizeof(magic)); + bmp.write(reinterpret_cast(&header), sizeof(header)); + bmp.write(reinterpret_cast(&info), sizeof(info)); +}