pl111.cc revision 7753:d3e613312953
18870SAli.Saidi@ARM.com/* 27090SN/A * Copyright (c) 2010 ARM Limited 37090SN/A * All rights reserved 47090SN/A * 57090SN/A * The license below extends only to copyright in the software and shall 67090SN/A * not be construed as granting a license to any other intellectual 77090SN/A * property including but not limited to intellectual property relating 87090SN/A * to a hardware implementation of the functionality of the software 97090SN/A * licensed hereunder. You may use the software subject to the license 107090SN/A * terms below provided that you ensure that this notice is replicated 117090SN/A * unmodified and in its entirety in all distributions of the software, 127090SN/A * modified or unmodified, in source code or in binary form. 134486SN/A * 144486SN/A * Redistribution and use in source and binary forms, with or without 154486SN/A * modification, are permitted provided that the following conditions are 164486SN/A * met: redistributions of source code must retain the above copyright 174486SN/A * notice, this list of conditions and the following disclaimer; 184486SN/A * redistributions in binary form must reproduce the above copyright 194486SN/A * notice, this list of conditions and the following disclaimer in the 204486SN/A * documentation and/or other materials provided with the distribution; 214486SN/A * neither the name of the copyright holders nor the names of its 224486SN/A * contributors may be used to endorse or promote products derived from 234486SN/A * this software without specific prior written permission. 244486SN/A * 254486SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 264486SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 274486SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 284486SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 294486SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 304486SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 314486SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 324486SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 334486SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 344486SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 354486SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 364486SN/A * 374486SN/A * Authors: William Wang 384486SN/A */ 397584SAli.Saidi@arm.com 407584SAli.Saidi@arm.com#include "base/trace.hh" 417754SWilliam.Wang@arm.com#include "dev/arm/amba_device.hh" 424486SN/A#include "dev/arm/gic.hh" 433630SN/A#include "dev/arm/pl111.hh" 443630SN/A#include "mem/packet.hh" 457587SAli.Saidi@arm.com#include "mem/packet_access.hh" 468525SAli.Saidi@ARM.com 478525SAli.Saidi@ARM.comusing namespace AmbaDev; 488212SAli.Saidi@ARM.com 495478SN/A// initialize clcd registers 505478SN/APl111::Pl111(const Params *p) 517584SAli.Saidi@arm.com : AmbaDmaDevice(p), lcdTiming0(0), lcdTiming1(0), lcdTiming2(0), 528931Sandreas.hansson@arm.com lcdTiming3(0), lcdUpbase(0), lcdLpbase(0), lcdControl(0), lcdImsc(0), 539525SAndreas.Sandberg@ARM.com lcdRis(0), lcdMis(0), lcdIcr(0), lcdUpcurr(0), lcdLpcurr(0), 543630SN/A clcdCrsrCtrl(0), clcdCrsrConfig(0), clcdCrsrPalette0(0), 557584SAli.Saidi@arm.com clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0), 567584SAli.Saidi@arm.com clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0), clock(p->clock), 577584SAli.Saidi@arm.com height(0), width(0), startTime(0), startAddr(0), maxAddr(0), curAddr(0), 589338SAndreas.Sandberg@arm.com waterMark(0), dmaPendingNum(0), readEvent(this), fillFifoEvent(this), 597584SAli.Saidi@arm.com dmaDoneEvent(maxOutstandingDma, this), intEvent(this) 603898SN/A{ 617950SAli.Saidi@ARM.com pioSize = 0xFFFF; 627950SAli.Saidi@ARM.com 637950SAli.Saidi@ARM.com memset(lcdPalette, 0, sizeof(lcdPalette)); 649338SAndreas.Sandberg@arm.com memset(cursorImage, 0, sizeof(cursorImage)); 659525SAndreas.Sandberg@ARM.com memset(dmaBuffer, 0, sizeof(dmaBuffer)); 667950SAli.Saidi@ARM.com memset(frameBuffer, 0, sizeof(frameBuffer)); 677950SAli.Saidi@ARM.com} 687950SAli.Saidi@ARM.com 697950SAli.Saidi@ARM.com// read registers and frame buffer 707587SAli.Saidi@arm.comTick 717587SAli.Saidi@arm.comPl111::read(PacketPtr pkt) 727587SAli.Saidi@arm.com{ 739338SAndreas.Sandberg@arm.com // use a temporary data since the LCD registers are read/written with 747753SWilliam.Wang@arm.com // different size operations 757753SWilliam.Wang@arm.com 769525SAndreas.Sandberg@ARM.com uint32_t data = 0; 777753SWilliam.Wang@arm.com 787587SAli.Saidi@arm.com if ((pkt->getAddr()& 0xffff0000) == pioAddr) { 797587SAli.Saidi@arm.com 808282SAli.Saidi@ARM.com assert(pkt->getAddr() >= pioAddr && 818282SAli.Saidi@ARM.com pkt->getAddr() < pioAddr + pioSize); 829338SAndreas.Sandberg@arm.com 838282SAli.Saidi@ARM.com Addr daddr = pkt->getAddr()&0xFFFF; 847584SAli.Saidi@arm.com pkt->allocate(); 857584SAli.Saidi@arm.com 869338SAndreas.Sandberg@arm.com DPRINTF(PL111, " read register %#x size=%d\n", daddr, pkt->getSize()); 878524SAli.Saidi@ARM.com 888524SAli.Saidi@ARM.com switch (daddr) { 898299Schander.sudanthi@arm.com case LcdTiming0: 907584SAli.Saidi@arm.com data = lcdTiming0; 917584SAli.Saidi@arm.com break; 927584SAli.Saidi@arm.com case LcdTiming1: 939338SAndreas.Sandberg@arm.com data = lcdTiming1; 947584SAli.Saidi@arm.com break; 957584SAli.Saidi@arm.com case LcdTiming2: 967584SAli.Saidi@arm.com data = lcdTiming2; 977584SAli.Saidi@arm.com break; 987584SAli.Saidi@arm.com case LcdTiming3: 999338SAndreas.Sandberg@arm.com data = lcdTiming3; 1009525SAndreas.Sandberg@ARM.com break; 1017584SAli.Saidi@arm.com case LcdUpBase: 1027584SAli.Saidi@arm.com data = lcdUpbase; 1037584SAli.Saidi@arm.com break; 1047584SAli.Saidi@arm.com case LcdLpBase: 1057584SAli.Saidi@arm.com data = lcdLpbase; 1067584SAli.Saidi@arm.com break; 1079338SAndreas.Sandberg@arm.com case LcdControl: 1089525SAndreas.Sandberg@ARM.com data = lcdControl; 1097584SAli.Saidi@arm.com break; 1107584SAli.Saidi@arm.com case LcdImsc: 1117584SAli.Saidi@arm.com warn("LCD interrupt set/clear function not supported\n"); 1127584SAli.Saidi@arm.com data = lcdImsc; 1137584SAli.Saidi@arm.com break; 1147584SAli.Saidi@arm.com case LcdRis: 1158512Sgeoffrey.blake@arm.com warn("LCD Raw interrupt status function not supported\n"); 1168512Sgeoffrey.blake@arm.com data = lcdRis; 1179338SAndreas.Sandberg@arm.com break; 1189525SAndreas.Sandberg@ARM.com case LcdMis: 1198512Sgeoffrey.blake@arm.com warn("LCD Masked interrupt status function not supported\n"); 1208512Sgeoffrey.blake@arm.com data = lcdMis; 1219157Sandreas.hansson@arm.com break; 1229157Sandreas.hansson@arm.com case LcdIcr: 1238512Sgeoffrey.blake@arm.com panic("LCD register at offset %#x is Write-Only\n", daddr); 1248870SAli.Saidi@ARM.com break; 1258870SAli.Saidi@ARM.com case LcdUpCurr: 1269338SAndreas.Sandberg@arm.com data = lcdUpcurr; 1278870SAli.Saidi@ARM.com break; 1288870SAli.Saidi@ARM.com case LcdLpCurr: 1298870SAli.Saidi@ARM.com data = lcdLpcurr; 1307950SAli.Saidi@ARM.com break; 1317754SWilliam.Wang@arm.com case ClcdCrsrCtrl: 1329338SAndreas.Sandberg@arm.com data = clcdCrsrCtrl; 1339330Schander.sudanthi@arm.com break; 1347950SAli.Saidi@ARM.com case ClcdCrsrConfig: 1357950SAli.Saidi@ARM.com data = clcdCrsrConfig; 1367754SWilliam.Wang@arm.com break; 1377754SWilliam.Wang@arm.com case ClcdCrsrPalette0: 1387753SWilliam.Wang@arm.com data = clcdCrsrPalette0; 1397753SWilliam.Wang@arm.com break; 1409338SAndreas.Sandberg@arm.com case ClcdCrsrPalette1: 1419394Sandreas.hansson@arm.com data = clcdCrsrPalette1; 1429330Schander.sudanthi@arm.com break; 1437753SWilliam.Wang@arm.com case ClcdCrsrXY: 1447753SWilliam.Wang@arm.com data = clcdCrsrXY; 1457584SAli.Saidi@arm.com break; 1467584SAli.Saidi@arm.com case ClcdCrsrClip: 1479338SAndreas.Sandberg@arm.com data = clcdCrsrClip; 1483630SN/A break; 1498525SAli.Saidi@ARM.com case ClcdCrsrImsc: 1508870SAli.Saidi@ARM.com data = clcdCrsrImsc; 1518870SAli.Saidi@ARM.com break; 1528870SAli.Saidi@ARM.com case ClcdCrsrIcr: 1538870SAli.Saidi@ARM.com panic("CLCD register at offset %#x is Write-Only\n", daddr); 1548931Sandreas.hansson@arm.com break; 1558931Sandreas.hansson@arm.com case ClcdCrsrRis: 1568931Sandreas.hansson@arm.com data = clcdCrsrRis; 1578870SAli.Saidi@ARM.com break; 1588870SAli.Saidi@ARM.com case ClcdCrsrMis: 1598870SAli.Saidi@ARM.com data = clcdCrsrMis; 1603630SN/A break; 1617753SWilliam.Wang@arm.com default: 1627753SWilliam.Wang@arm.com if (AmbaDev::readId(pkt, AMBA_ID, pioAddr)) { 1637753SWilliam.Wang@arm.com // Hack for variable size accesses 1647584SAli.Saidi@arm.com data = pkt->get<uint32_t>(); 1657584SAli.Saidi@arm.com break; 1667584SAli.Saidi@arm.com } else if (daddr >= CrsrImage && daddr <= 0xBFC) { 1679525SAndreas.Sandberg@ARM.com // CURSOR IMAGE 1687584SAli.Saidi@arm.com int index; 1697584SAli.Saidi@arm.com index = (daddr - CrsrImage) >> 2; 1708512Sgeoffrey.blake@arm.com data= cursorImage[index]; 1717753SWilliam.Wang@arm.com break; 1727754SWilliam.Wang@arm.com } else if (daddr >= LcdPalette && daddr <= 0x3FC) { 1737950SAli.Saidi@ARM.com // LCD Palette 1748282SAli.Saidi@ARM.com int index; 1758525SAli.Saidi@ARM.com index = (daddr - LcdPalette) >> 2; 1768212SAli.Saidi@ARM.com data = lcdPalette[index]; 1778212SAli.Saidi@ARM.com break; 1788212SAli.Saidi@ARM.com } else { 1798212SAli.Saidi@ARM.com panic("Tried to read CLCD register at offset %#x that \ 1808212SAli.Saidi@ARM.com doesn't exist\n", daddr); 1817584SAli.Saidi@arm.com break; 1827731SAli.Saidi@ARM.com } 1838461SAli.Saidi@ARM.com } 1848461SAli.Saidi@ARM.com } 1857696SAli.Saidi@ARM.com 1867696SAli.Saidi@ARM.com switch(pkt->getSize()) { 1877696SAli.Saidi@ARM.com case 1: 1887696SAli.Saidi@ARM.com pkt->set<uint8_t>(data); 1897696SAli.Saidi@ARM.com break; 1907696SAli.Saidi@ARM.com case 2: 1917696SAli.Saidi@ARM.com pkt->set<uint16_t>(data); 1927696SAli.Saidi@ARM.com break; 1937696SAli.Saidi@ARM.com case 4: 1947696SAli.Saidi@ARM.com pkt->set<uint32_t>(data); 1957696SAli.Saidi@ARM.com break; 1967696SAli.Saidi@ARM.com default: 1977696SAli.Saidi@ARM.com panic("CLCD controller read size too big?\n"); 1987696SAli.Saidi@ARM.com break; 1998906Skoansin.tan@gmail.com } 2007696SAli.Saidi@ARM.com 2017696SAli.Saidi@ARM.com pkt->makeAtomicResponse(); 2028713Sandreas.hansson@arm.com return pioDelay; 2038713Sandreas.hansson@arm.com} 2048713Sandreas.hansson@arm.com 2058839Sandreas.hansson@arm.com// write registers and frame buffer 2068839Sandreas.hansson@arm.comTick 2078839Sandreas.hansson@arm.comPl111::write(PacketPtr pkt) 2088839Sandreas.hansson@arm.com{ 2098713Sandreas.hansson@arm.com // use a temporary data since the LCD registers are read/written with 2108713Sandreas.hansson@arm.com // different size operations 2118713Sandreas.hansson@arm.com // 2128713Sandreas.hansson@arm.com uint32_t data = 0; 2138870SAli.Saidi@ARM.com 2148870SAli.Saidi@ARM.com switch(pkt->getSize()) { 2158870SAli.Saidi@ARM.com case 1: 2167696SAli.Saidi@ARM.com data = pkt->get<uint8_t>(); 2177696SAli.Saidi@ARM.com break; 2187696SAli.Saidi@ARM.com case 2: 2197696SAli.Saidi@ARM.com data = pkt->get<uint16_t>(); 2207696SAli.Saidi@ARM.com break; 2218839Sandreas.hansson@arm.com case 4: 2228839Sandreas.hansson@arm.com data = pkt->get<uint32_t>(); 2238839Sandreas.hansson@arm.com break; 2248839Sandreas.hansson@arm.com default: 2258839Sandreas.hansson@arm.com panic("PL111 CLCD controller write size too big?\n"); 2268839Sandreas.hansson@arm.com break; 2278839Sandreas.hansson@arm.com } 2288839Sandreas.hansson@arm.com 2298839Sandreas.hansson@arm.com if ((pkt->getAddr()& 0xffff0000) == pioAddr) { 2308839Sandreas.hansson@arm.com 2318839Sandreas.hansson@arm.com assert(pkt->getAddr() >= pioAddr && 2328839Sandreas.hansson@arm.com pkt->getAddr() < pioAddr + pioSize); 2338839Sandreas.hansson@arm.com 2348839Sandreas.hansson@arm.com Addr daddr = pkt->getAddr() - pioAddr; 2358839Sandreas.hansson@arm.com 2368839Sandreas.hansson@arm.com DPRINTF(PL111, " write register %#x value %#x size=%d\n", daddr, 2378839Sandreas.hansson@arm.com pkt->get<uint8_t>(), pkt->getSize()); 2388839Sandreas.hansson@arm.com 2398839Sandreas.hansson@arm.com switch (daddr) { 2408839Sandreas.hansson@arm.com case LcdTiming0: 2418839Sandreas.hansson@arm.com lcdTiming0 = data; 2428839Sandreas.hansson@arm.com // width = 16 * (PPL+1) 2438839Sandreas.hansson@arm.com width = (lcdTiming0.ppl + 1) << 4; 2448839Sandreas.hansson@arm.com break; 2458839Sandreas.hansson@arm.com case LcdTiming1: 2468906Skoansin.tan@gmail.com lcdTiming1 = data; 2478839Sandreas.hansson@arm.com // height = LPP + 1 2487696SAli.Saidi@ARM.com height = (lcdTiming1.lpp) + 1; 2497754SWilliam.Wang@arm.com break; 2507754SWilliam.Wang@arm.com case LcdTiming2: 2517754SWilliam.Wang@arm.com lcdTiming2 = data; 2527696SAli.Saidi@ARM.com break; 2537696SAli.Saidi@ARM.com case LcdTiming3: 2547696SAli.Saidi@ARM.com lcdTiming3 = data; 2559525SAndreas.Sandberg@ARM.com break; 2567696SAli.Saidi@ARM.com case LcdUpBase: 2577696SAli.Saidi@ARM.com lcdUpbase = data; 2587754SWilliam.Wang@arm.com break; 2597754SWilliam.Wang@arm.com case LcdLpBase: 2607950SAli.Saidi@ARM.com warn("LCD dual screen mode not supported\n"); 2617696SAli.Saidi@ARM.com lcdLpbase = data; 2627696SAli.Saidi@ARM.com break; 2638461SAli.Saidi@ARM.com case LcdControl: 2648461SAli.Saidi@ARM.com int old_lcdpwr; 2657584SAli.Saidi@arm.com old_lcdpwr = lcdControl.lcdpwr; 2667584SAli.Saidi@arm.com lcdControl = data; 2677584SAli.Saidi@arm.com // LCD power enable 2687584SAli.Saidi@arm.com if (lcdControl.lcdpwr&&!old_lcdpwr) { 2698299Schander.sudanthi@arm.com DPRINTF(PL111, " lcd size: height %d width %d\n", height, width); 2707584SAli.Saidi@arm.com waterMark = lcdControl.watermark ? 8 : 4; 2717584SAli.Saidi@arm.com readFramebuffer(); 2727584SAli.Saidi@arm.com } 2737584SAli.Saidi@arm.com break; 2747584SAli.Saidi@arm.com case LcdImsc: 2757584SAli.Saidi@arm.com warn("LCD interrupt mask set/clear not supported\n"); 2767584SAli.Saidi@arm.com lcdImsc = data; 2777584SAli.Saidi@arm.com break; 2787584SAli.Saidi@arm.com case LcdRis: 2797584SAli.Saidi@arm.com warn("LCD register at offset %#x is Read-Only\n", daddr); 2807584SAli.Saidi@arm.com break; 2817584SAli.Saidi@arm.com case LcdMis: 2827584SAli.Saidi@arm.com warn("LCD register at offset %#x is Read-Only\n", daddr); 2837584SAli.Saidi@arm.com break; 2848713Sandreas.hansson@arm.com case LcdIcr: 2858713Sandreas.hansson@arm.com warn("LCD interrupt clear not supported\n"); 2868713Sandreas.hansson@arm.com lcdIcr = data; 2878839Sandreas.hansson@arm.com break; 2888839Sandreas.hansson@arm.com case LcdUpCurr: 2898713Sandreas.hansson@arm.com warn("LCD register at offset %#x is Read-Only\n", daddr); 2908713Sandreas.hansson@arm.com break; 2918713Sandreas.hansson@arm.com case LcdLpCurr: 2928713Sandreas.hansson@arm.com warn("LCD register at offset %#x is Read-Only\n", daddr); 2938713Sandreas.hansson@arm.com break; 2944104SN/A case ClcdCrsrCtrl: 2953630SN/A clcdCrsrCtrl = data; 2963630SN/A break; 2973630SN/A case ClcdCrsrConfig: 2983630SN/A clcdCrsrConfig = data; 2998839Sandreas.hansson@arm.com break; 3008839Sandreas.hansson@arm.com case ClcdCrsrPalette0: 3018839Sandreas.hansson@arm.com clcdCrsrPalette0 = data; 3028839Sandreas.hansson@arm.com break; 3038839Sandreas.hansson@arm.com case ClcdCrsrPalette1: 3048839Sandreas.hansson@arm.com clcdCrsrPalette1 = data; 3058839Sandreas.hansson@arm.com break; 3068839Sandreas.hansson@arm.com case ClcdCrsrXY: 3078839Sandreas.hansson@arm.com clcdCrsrXY = data; 3088839Sandreas.hansson@arm.com break; 3098839Sandreas.hansson@arm.com case ClcdCrsrClip: 3108839Sandreas.hansson@arm.com clcdCrsrClip = data; 3118839Sandreas.hansson@arm.com break; 3128839Sandreas.hansson@arm.com case ClcdCrsrImsc: 3138839Sandreas.hansson@arm.com clcdCrsrImsc = data; 3148839Sandreas.hansson@arm.com break; 3158839Sandreas.hansson@arm.com case ClcdCrsrIcr: 3168839Sandreas.hansson@arm.com clcdCrsrIcr = data; 3178839Sandreas.hansson@arm.com break; 3188839Sandreas.hansson@arm.com case ClcdCrsrRis: 3198839Sandreas.hansson@arm.com warn("CLCD register at offset %#x is Read-Only\n", daddr); 3208839Sandreas.hansson@arm.com break; 3218839Sandreas.hansson@arm.com case ClcdCrsrMis: 3228839Sandreas.hansson@arm.com warn("CLCD register at offset %#x is Read-Only\n", daddr); 3238839Sandreas.hansson@arm.com break; 3247584SAli.Saidi@arm.com default: 3258870SAli.Saidi@ARM.com if (daddr >= CrsrImage && daddr <= 0xBFC) { 3268870SAli.Saidi@ARM.com // CURSOR IMAGE 3278870SAli.Saidi@ARM.com int index; 3289052Sgeoffrey.blake@arm.com index = (daddr - CrsrImage) >> 2; 3298870SAli.Saidi@ARM.com cursorImage[index] = data; 3308870SAli.Saidi@ARM.com break; 3319525SAndreas.Sandberg@ARM.com } else if (daddr >= LcdPalette && daddr <= 0x3FC) { 3328870SAli.Saidi@ARM.com // LCD Palette 3339185SAli.Saidi@ARM.com int index; 3349185SAli.Saidi@ARM.com index = (daddr - LcdPalette) >> 2; 3358870SAli.Saidi@ARM.com lcdPalette[index] = data; 3368870SAli.Saidi@ARM.com break; 3379387SChris.Emmons@arm.com } else { 3388870SAli.Saidi@ARM.com panic("Tried to write PL111 register at offset %#x that \ 3398870SAli.Saidi@ARM.com doesn't exist\n", daddr); 3408870SAli.Saidi@ARM.com break; 3418870SAli.Saidi@ARM.com } 3428870SAli.Saidi@ARM.com } 3439052Sgeoffrey.blake@arm.com } 3449052Sgeoffrey.blake@arm.com 3459052Sgeoffrey.blake@arm.com pkt->makeAtomicResponse(); 3469052Sgeoffrey.blake@arm.com return pioDelay; 3479052Sgeoffrey.blake@arm.com} 3489052Sgeoffrey.blake@arm.com 3499052Sgeoffrey.blake@arm.comvoid 3509052Sgeoffrey.blake@arm.comPl111::readFramebuffer() 3519052Sgeoffrey.blake@arm.com{ 3528931Sandreas.hansson@arm.com // initialization for dma read from frame buffer to dma buffer 3538931Sandreas.hansson@arm.com uint32_t length = height*width; 3548870SAli.Saidi@ARM.com if (startAddr != lcdUpbase) { 3558870SAli.Saidi@ARM.com startAddr = lcdUpbase; 3568870SAli.Saidi@ARM.com } 3578870SAli.Saidi@ARM.com curAddr = 0; 3588870SAli.Saidi@ARM.com startTime = curTick; 3598870SAli.Saidi@ARM.com maxAddr = static_cast<Addr>(length*sizeof(uint32_t)); 3608870SAli.Saidi@ARM.com dmaPendingNum =0 ; 3618870SAli.Saidi@ARM.com 3628870SAli.Saidi@ARM.com fillFifo(); 3638870SAli.Saidi@ARM.com} 3648870SAli.Saidi@ARM.com 3658870SAli.Saidi@ARM.comvoid 3668870SAli.Saidi@ARM.comPl111::fillFifo() 3678870SAli.Saidi@ARM.com{ 3688931Sandreas.hansson@arm.com while ((dmaPendingNum < maxOutstandingDma) && (maxAddr >= curAddr + dmaSize )) { 3698931Sandreas.hansson@arm.com // concurrent dma reads need different dma done events 3708870SAli.Saidi@ARM.com // due to assertion in scheduling state 3718870SAli.Saidi@ARM.com ++dmaPendingNum; 3728870SAli.Saidi@ARM.com DPRINTF(PL111, " ++ DMA pending number %d read addr %#x\n", 3738870SAli.Saidi@ARM.com dmaPendingNum, curAddr); 3748870SAli.Saidi@ARM.com assert(!dmaDoneEvent[dmaPendingNum-1].scheduled()); 3758870SAli.Saidi@ARM.com dmaRead(curAddr + startAddr, dmaSize, &dmaDoneEvent[dmaPendingNum-1], 3768870SAli.Saidi@ARM.com curAddr + dmaBuffer); 3778870SAli.Saidi@ARM.com curAddr += dmaSize; 3788870SAli.Saidi@ARM.com } 3798870SAli.Saidi@ARM.com} 3808870SAli.Saidi@ARM.com 3818870SAli.Saidi@ARM.comvoid 3828870SAli.Saidi@ARM.comPl111::dmaDone() 3839073SAli.Saidi@ARM.com{ 3848870SAli.Saidi@ARM.com Tick maxFrameTime = lcdTiming2.cpl*height*clock; 3858870SAli.Saidi@ARM.com 3868870SAli.Saidi@ARM.com --dmaPendingNum; 3878870SAli.Saidi@ARM.com 3888870SAli.Saidi@ARM.com DPRINTF(PL111, " -- DMA pending number %d\n", dmaPendingNum); 3898870SAli.Saidi@ARM.com 3908870SAli.Saidi@ARM.com if (maxAddr == curAddr && !dmaPendingNum) { 3918870SAli.Saidi@ARM.com if ((curTick - startTime) > maxFrameTime) 3928870SAli.Saidi@ARM.com warn("CLCD controller buffer underrun, took %d cycles when should" 3938870SAli.Saidi@ARM.com " have taken %d\n", curTick - startTime, maxFrameTime); 3948870SAli.Saidi@ARM.com 3958870SAli.Saidi@ARM.com // double buffering so the vnc server doesn't see a tear in the screen 3968870SAli.Saidi@ARM.com memcpy(frameBuffer, dmaBuffer, maxAddr); 3978870SAli.Saidi@ARM.com assert(!readEvent.scheduled()); 3988870SAli.Saidi@ARM.com 3998870SAli.Saidi@ARM.com DPRINTF(PL111, "-- write out frame buffer into bmp\n"); 4008872Ssaidi@eecs.umich.edu writeBMP(frameBuffer); 4018870SAli.Saidi@ARM.com 4028870SAli.Saidi@ARM.com DPRINTF(PL111, "-- schedule next dma read event at %d tick \n", 4038870SAli.Saidi@ARM.com maxFrameTime + curTick); 4048870SAli.Saidi@ARM.com schedule(readEvent, nextCycle(startTime + maxFrameTime)); 4059052Sgeoffrey.blake@arm.com } 4069052Sgeoffrey.blake@arm.com 4079052Sgeoffrey.blake@arm.com if (dmaPendingNum > (maxOutstandingDma - waterMark)) 4089052Sgeoffrey.blake@arm.com return; 4099052Sgeoffrey.blake@arm.com 4109052Sgeoffrey.blake@arm.com if (!fillFifoEvent.scheduled()) 4119052Sgeoffrey.blake@arm.com schedule(fillFifoEvent, nextCycle()); 4128870SAli.Saidi@ARM.com 4138870SAli.Saidi@ARM.com} 4148870SAli.Saidi@ARM.com 4158870SAli.Saidi@ARM.comTick 4168870SAli.Saidi@ARM.comPl111::nextCycle() 4178870SAli.Saidi@ARM.com{ 4188870SAli.Saidi@ARM.com Tick nextTick = curTick + clock - 1; 4198870SAli.Saidi@ARM.com nextTick -= nextTick%clock; 4208870SAli.Saidi@ARM.com return nextTick; 4218870SAli.Saidi@ARM.com} 4228870SAli.Saidi@ARM.com 4238870SAli.Saidi@ARM.comTick 424Pl111::nextCycle(Tick beginTick) 425{ 426 Tick nextTick = beginTick; 427 if (nextTick%clock!=0) 428 nextTick = nextTick - (nextTick%clock) + clock; 429 430 assert(nextTick >= curTick); 431 return nextTick; 432} 433 434// write out the frame buffer into a bitmap file 435void 436Pl111::writeBMP(uint32_t* frameBuffer) 437{ 438 fstream pic; 439 440 // write out bmp head 441 std::string filename = "./m5out/frameBuffer.bmp"; 442 pic.open(filename.c_str(), ios::out|ios::binary); 443 Bitmap bm(pic, height, width); 444 445 DPRINTF(PL111, "-- write out data into bmp\n"); 446 447 // write out frame buffer data 448 for (int i = height -1; i >= 0; --i) { 449 for (int j = 0; j< width; ++j) { 450 uint32_t pixel = frameBuffer[i*width + j]; 451 pic.write(reinterpret_cast<char*>(&pixel), 452 sizeof(uint32_t)); 453 DPRINTF(PL111, " write pixel data %#x at addr %#x\n", 454 pixel, i*width + j); 455 } 456 } 457 458 pic.close(); 459} 460 461void 462Pl111::serialize(std::ostream &os) 463{ 464 DPRINTF(PL111, "Serializing ARM PL111\n"); 465 466 uint32_t lcdTiming0_serial = lcdTiming0; 467 SERIALIZE_SCALAR(lcdTiming0_serial); 468 469 uint32_t lcdTiming1_serial = lcdTiming1; 470 SERIALIZE_SCALAR(lcdTiming1_serial); 471 472 uint32_t lcdTiming2_serial = lcdTiming2; 473 SERIALIZE_SCALAR(lcdTiming2_serial); 474 475 uint32_t lcdTiming3_serial = lcdTiming3; 476 SERIALIZE_SCALAR(lcdTiming3_serial); 477 478 SERIALIZE_SCALAR(lcdUpbase); 479 SERIALIZE_SCALAR(lcdLpbase); 480 481 uint32_t lcdControl_serial = lcdControl; 482 SERIALIZE_SCALAR(lcdControl_serial); 483 484 uint8_t lcdImsc_serial = lcdImsc; 485 SERIALIZE_SCALAR(lcdImsc_serial); 486 487 uint8_t lcdRis_serial = lcdRis; 488 SERIALIZE_SCALAR(lcdRis_serial); 489 490 uint8_t lcdMis_serial = lcdMis; 491 SERIALIZE_SCALAR(lcdMis_serial); 492 493 uint8_t lcdIcr_serial = lcdIcr; 494 SERIALIZE_SCALAR(lcdIcr_serial); 495 496 SERIALIZE_ARRAY(lcdPalette, LcdPaletteSize); 497 SERIALIZE_ARRAY(cursorImage, CrsrImageSize); 498 499 SERIALIZE_SCALAR(clcdCrsrCtrl); 500 SERIALIZE_SCALAR(clcdCrsrConfig); 501 SERIALIZE_SCALAR(clcdCrsrPalette0); 502 SERIALIZE_SCALAR(clcdCrsrPalette1); 503 SERIALIZE_SCALAR(clcdCrsrXY); 504 SERIALIZE_SCALAR(clcdCrsrClip); 505 506 uint8_t clcdCrsrImsc_serial = clcdCrsrImsc; 507 SERIALIZE_SCALAR(clcdCrsrImsc_serial); 508 509 uint8_t clcdCrsrIcr_serial = clcdCrsrIcr; 510 SERIALIZE_SCALAR(clcdCrsrIcr_serial); 511 512 uint8_t clcdCrsrRis_serial = clcdCrsrRis; 513 SERIALIZE_SCALAR(clcdCrsrRis_serial); 514 515 uint8_t clcdCrsrMis_serial = clcdCrsrMis; 516 SERIALIZE_SCALAR(clcdCrsrMis_serial); 517 518 SERIALIZE_SCALAR(clock); 519 SERIALIZE_SCALAR(height); 520 SERIALIZE_SCALAR(width); 521 522 SERIALIZE_ARRAY(dmaBuffer, height*width); 523 SERIALIZE_ARRAY(frameBuffer, height*width); 524 SERIALIZE_SCALAR(startTime); 525 SERIALIZE_SCALAR(startAddr); 526 SERIALIZE_SCALAR(maxAddr); 527 SERIALIZE_SCALAR(curAddr); 528 SERIALIZE_SCALAR(waterMark); 529 SERIALIZE_SCALAR(dmaPendingNum); 530} 531 532void 533Pl111::unserialize(Checkpoint *cp, const std::string §ion) 534{ 535 DPRINTF(PL111, "Unserializing ARM PL111\n"); 536 537 uint32_t lcdTiming0_serial; 538 UNSERIALIZE_SCALAR(lcdTiming0_serial); 539 lcdTiming0 = lcdTiming0_serial; 540 541 uint32_t lcdTiming1_serial; 542 UNSERIALIZE_SCALAR(lcdTiming1_serial); 543 lcdTiming1 = lcdTiming1_serial; 544 545 uint32_t lcdTiming2_serial; 546 UNSERIALIZE_SCALAR(lcdTiming2_serial); 547 lcdTiming2 = lcdTiming2_serial; 548 549 uint32_t lcdTiming3_serial; 550 UNSERIALIZE_SCALAR(lcdTiming3_serial); 551 lcdTiming3 = lcdTiming3_serial; 552 553 UNSERIALIZE_SCALAR(lcdUpbase); 554 UNSERIALIZE_SCALAR(lcdLpbase); 555 556 uint32_t lcdControl_serial; 557 UNSERIALIZE_SCALAR(lcdControl_serial); 558 lcdControl = lcdControl_serial; 559 560 uint8_t lcdImsc_serial; 561 UNSERIALIZE_SCALAR(lcdImsc_serial); 562 lcdImsc = lcdImsc_serial; 563 564 uint8_t lcdRis_serial; 565 UNSERIALIZE_SCALAR(lcdRis_serial); 566 lcdRis = lcdRis_serial; 567 568 uint8_t lcdMis_serial; 569 UNSERIALIZE_SCALAR(lcdMis_serial); 570 lcdMis = lcdMis_serial; 571 572 uint8_t lcdIcr_serial; 573 UNSERIALIZE_SCALAR(lcdIcr_serial); 574 lcdIcr = lcdIcr_serial; 575 576 UNSERIALIZE_ARRAY(lcdPalette, LcdPaletteSize); 577 UNSERIALIZE_ARRAY(cursorImage, CrsrImageSize); 578 579 UNSERIALIZE_SCALAR(clcdCrsrCtrl); 580 UNSERIALIZE_SCALAR(clcdCrsrConfig); 581 UNSERIALIZE_SCALAR(clcdCrsrPalette0); 582 UNSERIALIZE_SCALAR(clcdCrsrPalette1); 583 UNSERIALIZE_SCALAR(clcdCrsrXY); 584 UNSERIALIZE_SCALAR(clcdCrsrClip); 585 586 uint8_t clcdCrsrImsc_serial; 587 UNSERIALIZE_SCALAR(clcdCrsrImsc_serial); 588 clcdCrsrImsc = clcdCrsrImsc_serial; 589 590 uint8_t clcdCrsrIcr_serial; 591 UNSERIALIZE_SCALAR(clcdCrsrIcr_serial); 592 clcdCrsrIcr = clcdCrsrIcr_serial; 593 594 uint8_t clcdCrsrRis_serial; 595 UNSERIALIZE_SCALAR(clcdCrsrRis_serial); 596 clcdCrsrRis = clcdCrsrRis_serial; 597 598 uint8_t clcdCrsrMis_serial; 599 UNSERIALIZE_SCALAR(clcdCrsrMis_serial); 600 clcdCrsrMis = clcdCrsrMis_serial; 601 602 UNSERIALIZE_SCALAR(clock); 603 UNSERIALIZE_SCALAR(height); 604 UNSERIALIZE_SCALAR(width); 605 606 UNSERIALIZE_ARRAY(dmaBuffer, height*width); 607 UNSERIALIZE_ARRAY(frameBuffer, height*width); 608 UNSERIALIZE_SCALAR(startTime); 609 UNSERIALIZE_SCALAR(startAddr); 610 UNSERIALIZE_SCALAR(maxAddr); 611 UNSERIALIZE_SCALAR(curAddr); 612 UNSERIALIZE_SCALAR(waterMark); 613 UNSERIALIZE_SCALAR(dmaPendingNum); 614} 615 616void 617Pl111::generateInterrupt() 618{ 619 DPRINTF(PL111, "Generate Interrupt: lcdImsc=0x%x lcdRis=0x%x lcdMis=0x%x\n", 620 lcdImsc, lcdRis, lcdMis); 621 lcdMis = lcdImsc & lcdRis; 622 623 if (lcdMis.ffufie || lcdMis.nbupie || lcdMis.vtcpie || lcdMis.ahmeie) { 624 gic->sendInt(intNum); 625 DPRINTF(PL111, " -- Generated\n"); 626 } 627} 628 629void 630Pl111::addressRanges(AddrRangeList& range_list) 631{ 632 range_list.clear(); 633 range_list.push_back(RangeSize(pioAddr, pioSize)); 634} 635 636Pl111 * 637Pl111Params::create() 638{ 639 return new Pl111(this); 640} 641 642// bitmap class ctor 643Bitmap::Bitmap(std::fstream& bmp, uint16_t h, uint16_t w) 644{ 645 Magic magic = {{'B','M'}}; 646 Header header = {sizeof(Color)*w*h , 0, 0, 54}; 647 Info info = {sizeof(Info), w, h, 1, sizeof(Color)*8, 0, 648 ( sizeof(Color) *(w*h) ), 1, 1, 0, 0}; 649 650 bmp.write(reinterpret_cast<char*>(&magic), sizeof(magic)); 651 bmp.write(reinterpret_cast<char*>(&header), sizeof(header)); 652 bmp.write(reinterpret_cast<char*>(&info), sizeof(info)); 653} 654