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 &section)
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