pl111.cc revision 7823
17753SWilliam.Wang@arm.com/*
27753SWilliam.Wang@arm.com * Copyright (c) 2010 ARM Limited
37753SWilliam.Wang@arm.com * All rights reserved
47753SWilliam.Wang@arm.com *
57753SWilliam.Wang@arm.com * The license below extends only to copyright in the software and shall
67753SWilliam.Wang@arm.com * not be construed as granting a license to any other intellectual
77753SWilliam.Wang@arm.com * property including but not limited to intellectual property relating
87753SWilliam.Wang@arm.com * to a hardware implementation of the functionality of the software
97753SWilliam.Wang@arm.com * licensed hereunder.  You may use the software subject to the license
107753SWilliam.Wang@arm.com * terms below provided that you ensure that this notice is replicated
117753SWilliam.Wang@arm.com * unmodified and in its entirety in all distributions of the software,
127753SWilliam.Wang@arm.com * modified or unmodified, in source code or in binary form.
137753SWilliam.Wang@arm.com *
147753SWilliam.Wang@arm.com * Redistribution and use in source and binary forms, with or without
157753SWilliam.Wang@arm.com * modification, are permitted provided that the following conditions are
167753SWilliam.Wang@arm.com * met: redistributions of source code must retain the above copyright
177753SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer;
187753SWilliam.Wang@arm.com * redistributions in binary form must reproduce the above copyright
197753SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer in the
207753SWilliam.Wang@arm.com * documentation and/or other materials provided with the distribution;
217753SWilliam.Wang@arm.com * neither the name of the copyright holders nor the names of its
227753SWilliam.Wang@arm.com * contributors may be used to endorse or promote products derived from
237753SWilliam.Wang@arm.com * this software without specific prior written permission.
247753SWilliam.Wang@arm.com *
257753SWilliam.Wang@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
267753SWilliam.Wang@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
277753SWilliam.Wang@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
287753SWilliam.Wang@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
297753SWilliam.Wang@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
307753SWilliam.Wang@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
317753SWilliam.Wang@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
327753SWilliam.Wang@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
337753SWilliam.Wang@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
347753SWilliam.Wang@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
357753SWilliam.Wang@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
367753SWilliam.Wang@arm.com *
377753SWilliam.Wang@arm.com * Authors: William Wang
387753SWilliam.Wang@arm.com */
397753SWilliam.Wang@arm.com
407753SWilliam.Wang@arm.com#include "base/trace.hh"
417753SWilliam.Wang@arm.com#include "dev/arm/amba_device.hh"
427753SWilliam.Wang@arm.com#include "dev/arm/gic.hh"
437753SWilliam.Wang@arm.com#include "dev/arm/pl111.hh"
447753SWilliam.Wang@arm.com#include "mem/packet.hh"
457753SWilliam.Wang@arm.com#include "mem/packet_access.hh"
467753SWilliam.Wang@arm.com
477753SWilliam.Wang@arm.comusing namespace AmbaDev;
487753SWilliam.Wang@arm.com
497753SWilliam.Wang@arm.com// initialize clcd registers
507753SWilliam.Wang@arm.comPl111::Pl111(const Params *p)
517753SWilliam.Wang@arm.com    : AmbaDmaDevice(p), lcdTiming0(0), lcdTiming1(0), lcdTiming2(0),
527753SWilliam.Wang@arm.com      lcdTiming3(0), lcdUpbase(0), lcdLpbase(0), lcdControl(0), lcdImsc(0),
537753SWilliam.Wang@arm.com      lcdRis(0), lcdMis(0), lcdIcr(0), lcdUpcurr(0), lcdLpcurr(0),
547753SWilliam.Wang@arm.com      clcdCrsrCtrl(0), clcdCrsrConfig(0), clcdCrsrPalette0(0),
557753SWilliam.Wang@arm.com      clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0),
567753SWilliam.Wang@arm.com      clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0), clock(p->clock),
577753SWilliam.Wang@arm.com      height(0), width(0), startTime(0), startAddr(0), maxAddr(0), curAddr(0),
587753SWilliam.Wang@arm.com      waterMark(0), dmaPendingNum(0), readEvent(this), fillFifoEvent(this),
597753SWilliam.Wang@arm.com      dmaDoneEvent(maxOutstandingDma, this), intEvent(this)
607753SWilliam.Wang@arm.com{
617753SWilliam.Wang@arm.com    pioSize = 0xFFFF;
627753SWilliam.Wang@arm.com
637753SWilliam.Wang@arm.com    memset(lcdPalette, 0, sizeof(lcdPalette));
647753SWilliam.Wang@arm.com    memset(cursorImage, 0, sizeof(cursorImage));
657753SWilliam.Wang@arm.com    memset(dmaBuffer, 0, sizeof(dmaBuffer));
667753SWilliam.Wang@arm.com    memset(frameBuffer, 0, sizeof(frameBuffer));
677753SWilliam.Wang@arm.com}
687753SWilliam.Wang@arm.com
697753SWilliam.Wang@arm.com// read registers and frame buffer
707753SWilliam.Wang@arm.comTick
717753SWilliam.Wang@arm.comPl111::read(PacketPtr pkt)
727753SWilliam.Wang@arm.com{
737753SWilliam.Wang@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
767753SWilliam.Wang@arm.com    uint32_t data = 0;
777753SWilliam.Wang@arm.com
787753SWilliam.Wang@arm.com    if ((pkt->getAddr()& 0xffff0000) == pioAddr) {
797753SWilliam.Wang@arm.com
807753SWilliam.Wang@arm.com        assert(pkt->getAddr() >= pioAddr &&
817753SWilliam.Wang@arm.com               pkt->getAddr() < pioAddr + pioSize);
827753SWilliam.Wang@arm.com
837753SWilliam.Wang@arm.com        Addr daddr = pkt->getAddr()&0xFFFF;
847753SWilliam.Wang@arm.com        pkt->allocate();
857753SWilliam.Wang@arm.com
867753SWilliam.Wang@arm.com        DPRINTF(PL111, " read register %#x size=%d\n", daddr, pkt->getSize());
877753SWilliam.Wang@arm.com
887753SWilliam.Wang@arm.com        switch (daddr) {
897753SWilliam.Wang@arm.com          case LcdTiming0:
907753SWilliam.Wang@arm.com            data = lcdTiming0;
917753SWilliam.Wang@arm.com            break;
927753SWilliam.Wang@arm.com          case LcdTiming1:
937753SWilliam.Wang@arm.com            data = lcdTiming1;
947753SWilliam.Wang@arm.com            break;
957753SWilliam.Wang@arm.com          case LcdTiming2:
967753SWilliam.Wang@arm.com            data = lcdTiming2;
977753SWilliam.Wang@arm.com            break;
987753SWilliam.Wang@arm.com          case LcdTiming3:
997753SWilliam.Wang@arm.com            data = lcdTiming3;
1007753SWilliam.Wang@arm.com            break;
1017753SWilliam.Wang@arm.com          case LcdUpBase:
1027753SWilliam.Wang@arm.com            data = lcdUpbase;
1037753SWilliam.Wang@arm.com            break;
1047753SWilliam.Wang@arm.com          case LcdLpBase:
1057753SWilliam.Wang@arm.com            data = lcdLpbase;
1067753SWilliam.Wang@arm.com            break;
1077753SWilliam.Wang@arm.com          case LcdControl:
1087753SWilliam.Wang@arm.com            data = lcdControl;
1097753SWilliam.Wang@arm.com            break;
1107753SWilliam.Wang@arm.com          case LcdImsc:
1117753SWilliam.Wang@arm.com            warn("LCD interrupt set/clear function not supported\n");
1127753SWilliam.Wang@arm.com            data = lcdImsc;
1137753SWilliam.Wang@arm.com            break;
1147753SWilliam.Wang@arm.com          case LcdRis:
1157753SWilliam.Wang@arm.com            warn("LCD Raw interrupt status function not supported\n");
1167753SWilliam.Wang@arm.com            data = lcdRis;
1177753SWilliam.Wang@arm.com            break;
1187753SWilliam.Wang@arm.com          case LcdMis:
1197753SWilliam.Wang@arm.com            warn("LCD Masked interrupt status function not supported\n");
1207753SWilliam.Wang@arm.com            data = lcdMis;
1217753SWilliam.Wang@arm.com            break;
1227753SWilliam.Wang@arm.com          case LcdIcr:
1237753SWilliam.Wang@arm.com            panic("LCD register at offset %#x is Write-Only\n", daddr);
1247753SWilliam.Wang@arm.com            break;
1257753SWilliam.Wang@arm.com          case LcdUpCurr:
1267753SWilliam.Wang@arm.com            data = lcdUpcurr;
1277753SWilliam.Wang@arm.com            break;
1287753SWilliam.Wang@arm.com          case LcdLpCurr:
1297753SWilliam.Wang@arm.com            data = lcdLpcurr;
1307753SWilliam.Wang@arm.com            break;
1317753SWilliam.Wang@arm.com          case ClcdCrsrCtrl:
1327753SWilliam.Wang@arm.com            data = clcdCrsrCtrl;
1337753SWilliam.Wang@arm.com            break;
1347753SWilliam.Wang@arm.com          case ClcdCrsrConfig:
1357753SWilliam.Wang@arm.com            data = clcdCrsrConfig;
1367753SWilliam.Wang@arm.com            break;
1377753SWilliam.Wang@arm.com          case ClcdCrsrPalette0:
1387753SWilliam.Wang@arm.com            data = clcdCrsrPalette0;
1397753SWilliam.Wang@arm.com            break;
1407753SWilliam.Wang@arm.com          case ClcdCrsrPalette1:
1417753SWilliam.Wang@arm.com            data = clcdCrsrPalette1;
1427753SWilliam.Wang@arm.com            break;
1437753SWilliam.Wang@arm.com          case ClcdCrsrXY:
1447753SWilliam.Wang@arm.com            data = clcdCrsrXY;
1457753SWilliam.Wang@arm.com            break;
1467753SWilliam.Wang@arm.com          case ClcdCrsrClip:
1477753SWilliam.Wang@arm.com            data = clcdCrsrClip;
1487753SWilliam.Wang@arm.com            break;
1497753SWilliam.Wang@arm.com          case ClcdCrsrImsc:
1507753SWilliam.Wang@arm.com            data = clcdCrsrImsc;
1517753SWilliam.Wang@arm.com            break;
1527753SWilliam.Wang@arm.com          case ClcdCrsrIcr:
1537753SWilliam.Wang@arm.com            panic("CLCD register at offset %#x is Write-Only\n", daddr);
1547753SWilliam.Wang@arm.com            break;
1557753SWilliam.Wang@arm.com          case ClcdCrsrRis:
1567753SWilliam.Wang@arm.com            data = clcdCrsrRis;
1577753SWilliam.Wang@arm.com            break;
1587753SWilliam.Wang@arm.com          case ClcdCrsrMis:
1597753SWilliam.Wang@arm.com            data = clcdCrsrMis;
1607753SWilliam.Wang@arm.com            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
1647753SWilliam.Wang@arm.com                data = pkt->get<uint32_t>();
1657753SWilliam.Wang@arm.com                break;
1667753SWilliam.Wang@arm.com            } else if (daddr >= CrsrImage && daddr <= 0xBFC) {
1677753SWilliam.Wang@arm.com                // CURSOR IMAGE
1687753SWilliam.Wang@arm.com                int index;
1697753SWilliam.Wang@arm.com                index = (daddr - CrsrImage) >> 2;
1707753SWilliam.Wang@arm.com                data= cursorImage[index];
1717753SWilliam.Wang@arm.com                break;
1727753SWilliam.Wang@arm.com            } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
1737753SWilliam.Wang@arm.com                // LCD Palette
1747753SWilliam.Wang@arm.com                int index;
1757753SWilliam.Wang@arm.com                index = (daddr - LcdPalette) >> 2;
1767753SWilliam.Wang@arm.com                data = lcdPalette[index];
1777753SWilliam.Wang@arm.com                break;
1787753SWilliam.Wang@arm.com            } else {
1797753SWilliam.Wang@arm.com                panic("Tried to read CLCD register at offset %#x that \
1807753SWilliam.Wang@arm.com                       doesn't exist\n", daddr);
1817753SWilliam.Wang@arm.com                break;
1827753SWilliam.Wang@arm.com            }
1837753SWilliam.Wang@arm.com        }
1847753SWilliam.Wang@arm.com    }
1857753SWilliam.Wang@arm.com
1867753SWilliam.Wang@arm.com    switch(pkt->getSize()) {
1877753SWilliam.Wang@arm.com      case 1:
1887753SWilliam.Wang@arm.com        pkt->set<uint8_t>(data);
1897753SWilliam.Wang@arm.com        break;
1907753SWilliam.Wang@arm.com      case 2:
1917753SWilliam.Wang@arm.com        pkt->set<uint16_t>(data);
1927753SWilliam.Wang@arm.com        break;
1937753SWilliam.Wang@arm.com      case 4:
1947753SWilliam.Wang@arm.com        pkt->set<uint32_t>(data);
1957753SWilliam.Wang@arm.com        break;
1967753SWilliam.Wang@arm.com      default:
1977753SWilliam.Wang@arm.com        panic("CLCD controller read size too big?\n");
1987753SWilliam.Wang@arm.com        break;
1997753SWilliam.Wang@arm.com    }
2007753SWilliam.Wang@arm.com
2017753SWilliam.Wang@arm.com    pkt->makeAtomicResponse();
2027753SWilliam.Wang@arm.com    return pioDelay;
2037753SWilliam.Wang@arm.com}
2047753SWilliam.Wang@arm.com
2057753SWilliam.Wang@arm.com// write registers and frame buffer
2067753SWilliam.Wang@arm.comTick
2077753SWilliam.Wang@arm.comPl111::write(PacketPtr pkt)
2087753SWilliam.Wang@arm.com{
2097753SWilliam.Wang@arm.com    // use a temporary data since the LCD registers are read/written with
2107753SWilliam.Wang@arm.com    // different size operations
2117753SWilliam.Wang@arm.com    //
2127753SWilliam.Wang@arm.com    uint32_t data = 0;
2137753SWilliam.Wang@arm.com
2147753SWilliam.Wang@arm.com    switch(pkt->getSize()) {
2157753SWilliam.Wang@arm.com      case 1:
2167753SWilliam.Wang@arm.com        data = pkt->get<uint8_t>();
2177753SWilliam.Wang@arm.com        break;
2187753SWilliam.Wang@arm.com      case 2:
2197753SWilliam.Wang@arm.com        data = pkt->get<uint16_t>();
2207753SWilliam.Wang@arm.com        break;
2217753SWilliam.Wang@arm.com      case 4:
2227753SWilliam.Wang@arm.com        data = pkt->get<uint32_t>();
2237753SWilliam.Wang@arm.com        break;
2247753SWilliam.Wang@arm.com      default:
2257753SWilliam.Wang@arm.com        panic("PL111 CLCD controller write size too big?\n");
2267753SWilliam.Wang@arm.com        break;
2277753SWilliam.Wang@arm.com    }
2287753SWilliam.Wang@arm.com
2297753SWilliam.Wang@arm.com    if ((pkt->getAddr()& 0xffff0000) == pioAddr) {
2307753SWilliam.Wang@arm.com
2317753SWilliam.Wang@arm.com        assert(pkt->getAddr() >= pioAddr &&
2327753SWilliam.Wang@arm.com               pkt->getAddr() < pioAddr + pioSize);
2337753SWilliam.Wang@arm.com
2347753SWilliam.Wang@arm.com        Addr daddr = pkt->getAddr() - pioAddr;
2357753SWilliam.Wang@arm.com
2367753SWilliam.Wang@arm.com        DPRINTF(PL111, " write register %#x value %#x size=%d\n", daddr,
2377753SWilliam.Wang@arm.com                pkt->get<uint8_t>(), pkt->getSize());
2387753SWilliam.Wang@arm.com
2397753SWilliam.Wang@arm.com        switch (daddr) {
2407753SWilliam.Wang@arm.com          case LcdTiming0:
2417753SWilliam.Wang@arm.com            lcdTiming0 = data;
2427753SWilliam.Wang@arm.com            // width = 16 * (PPL+1)
2437753SWilliam.Wang@arm.com            width = (lcdTiming0.ppl + 1) << 4;
2447753SWilliam.Wang@arm.com            break;
2457753SWilliam.Wang@arm.com          case LcdTiming1:
2467753SWilliam.Wang@arm.com            lcdTiming1 = data;
2477753SWilliam.Wang@arm.com            // height = LPP + 1
2487753SWilliam.Wang@arm.com            height  = (lcdTiming1.lpp) + 1;
2497753SWilliam.Wang@arm.com            break;
2507753SWilliam.Wang@arm.com          case LcdTiming2:
2517753SWilliam.Wang@arm.com            lcdTiming2 = data;
2527753SWilliam.Wang@arm.com            break;
2537753SWilliam.Wang@arm.com          case LcdTiming3:
2547753SWilliam.Wang@arm.com            lcdTiming3 = data;
2557753SWilliam.Wang@arm.com            break;
2567753SWilliam.Wang@arm.com          case LcdUpBase:
2577753SWilliam.Wang@arm.com            lcdUpbase  = data;
2587753SWilliam.Wang@arm.com            break;
2597753SWilliam.Wang@arm.com          case LcdLpBase:
2607753SWilliam.Wang@arm.com            warn("LCD dual screen mode not supported\n");
2617753SWilliam.Wang@arm.com            lcdLpbase  = data;
2627753SWilliam.Wang@arm.com            break;
2637753SWilliam.Wang@arm.com          case LcdControl:
2647753SWilliam.Wang@arm.com            int old_lcdpwr;
2657753SWilliam.Wang@arm.com            old_lcdpwr = lcdControl.lcdpwr;
2667753SWilliam.Wang@arm.com            lcdControl = data;
2677753SWilliam.Wang@arm.com            // LCD power enable
2687753SWilliam.Wang@arm.com            if (lcdControl.lcdpwr&&!old_lcdpwr) {
2697753SWilliam.Wang@arm.com                DPRINTF(PL111, " lcd size: height %d width %d\n", height, width);
2707753SWilliam.Wang@arm.com                waterMark = lcdControl.watermark ? 8 : 4;
2717753SWilliam.Wang@arm.com                readFramebuffer();
2727753SWilliam.Wang@arm.com            }
2737753SWilliam.Wang@arm.com            break;
2747753SWilliam.Wang@arm.com          case LcdImsc:
2757753SWilliam.Wang@arm.com            warn("LCD interrupt mask set/clear not supported\n");
2767753SWilliam.Wang@arm.com            lcdImsc    = data;
2777753SWilliam.Wang@arm.com            break;
2787753SWilliam.Wang@arm.com          case LcdRis:
2797753SWilliam.Wang@arm.com            warn("LCD register at offset %#x is Read-Only\n", daddr);
2807753SWilliam.Wang@arm.com            break;
2817753SWilliam.Wang@arm.com          case LcdMis:
2827753SWilliam.Wang@arm.com            warn("LCD register at offset %#x is Read-Only\n", daddr);
2837753SWilliam.Wang@arm.com            break;
2847753SWilliam.Wang@arm.com          case LcdIcr:
2857753SWilliam.Wang@arm.com            warn("LCD interrupt clear not supported\n");
2867753SWilliam.Wang@arm.com            lcdIcr     = data;
2877753SWilliam.Wang@arm.com            break;
2887753SWilliam.Wang@arm.com          case LcdUpCurr:
2897753SWilliam.Wang@arm.com            warn("LCD register at offset %#x is Read-Only\n", daddr);
2907753SWilliam.Wang@arm.com            break;
2917753SWilliam.Wang@arm.com          case LcdLpCurr:
2927753SWilliam.Wang@arm.com            warn("LCD register at offset %#x is Read-Only\n", daddr);
2937753SWilliam.Wang@arm.com            break;
2947753SWilliam.Wang@arm.com          case ClcdCrsrCtrl:
2957753SWilliam.Wang@arm.com            clcdCrsrCtrl = data;
2967753SWilliam.Wang@arm.com            break;
2977753SWilliam.Wang@arm.com          case ClcdCrsrConfig:
2987753SWilliam.Wang@arm.com            clcdCrsrConfig = data;
2997753SWilliam.Wang@arm.com            break;
3007753SWilliam.Wang@arm.com          case ClcdCrsrPalette0:
3017753SWilliam.Wang@arm.com            clcdCrsrPalette0 = data;
3027753SWilliam.Wang@arm.com            break;
3037753SWilliam.Wang@arm.com          case ClcdCrsrPalette1:
3047753SWilliam.Wang@arm.com            clcdCrsrPalette1 = data;
3057753SWilliam.Wang@arm.com            break;
3067753SWilliam.Wang@arm.com          case ClcdCrsrXY:
3077753SWilliam.Wang@arm.com            clcdCrsrXY = data;
3087753SWilliam.Wang@arm.com            break;
3097753SWilliam.Wang@arm.com          case ClcdCrsrClip:
3107753SWilliam.Wang@arm.com            clcdCrsrClip = data;
3117753SWilliam.Wang@arm.com            break;
3127753SWilliam.Wang@arm.com          case ClcdCrsrImsc:
3137753SWilliam.Wang@arm.com            clcdCrsrImsc = data;
3147753SWilliam.Wang@arm.com            break;
3157753SWilliam.Wang@arm.com          case ClcdCrsrIcr:
3167753SWilliam.Wang@arm.com            clcdCrsrIcr = data;
3177753SWilliam.Wang@arm.com            break;
3187753SWilliam.Wang@arm.com          case ClcdCrsrRis:
3197753SWilliam.Wang@arm.com            warn("CLCD register at offset %#x is Read-Only\n", daddr);
3207753SWilliam.Wang@arm.com            break;
3217753SWilliam.Wang@arm.com          case ClcdCrsrMis:
3227753SWilliam.Wang@arm.com            warn("CLCD register at offset %#x is Read-Only\n", daddr);
3237753SWilliam.Wang@arm.com            break;
3247753SWilliam.Wang@arm.com          default:
3257753SWilliam.Wang@arm.com            if (daddr >= CrsrImage && daddr <= 0xBFC) {
3267753SWilliam.Wang@arm.com                // CURSOR IMAGE
3277753SWilliam.Wang@arm.com                int index;
3287753SWilliam.Wang@arm.com                index = (daddr - CrsrImage) >> 2;
3297753SWilliam.Wang@arm.com                cursorImage[index] = data;
3307753SWilliam.Wang@arm.com                break;
3317753SWilliam.Wang@arm.com            } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
3327753SWilliam.Wang@arm.com                // LCD Palette
3337753SWilliam.Wang@arm.com                int index;
3347753SWilliam.Wang@arm.com                index = (daddr - LcdPalette) >> 2;
3357753SWilliam.Wang@arm.com                lcdPalette[index] = data;
3367753SWilliam.Wang@arm.com                break;
3377753SWilliam.Wang@arm.com            } else {
3387753SWilliam.Wang@arm.com                panic("Tried to write PL111 register at offset %#x that \
3397753SWilliam.Wang@arm.com                       doesn't exist\n", daddr);
3407753SWilliam.Wang@arm.com                break;
3417753SWilliam.Wang@arm.com            }
3427753SWilliam.Wang@arm.com        }
3437753SWilliam.Wang@arm.com    }
3447753SWilliam.Wang@arm.com
3457753SWilliam.Wang@arm.com    pkt->makeAtomicResponse();
3467753SWilliam.Wang@arm.com    return pioDelay;
3477753SWilliam.Wang@arm.com}
3487753SWilliam.Wang@arm.com
3497753SWilliam.Wang@arm.comvoid
3507753SWilliam.Wang@arm.comPl111::readFramebuffer()
3517753SWilliam.Wang@arm.com{
3527753SWilliam.Wang@arm.com    // initialization for dma read from frame buffer to dma buffer
3537753SWilliam.Wang@arm.com    uint32_t length  = height*width;
3547753SWilliam.Wang@arm.com    if (startAddr != lcdUpbase) {
3557753SWilliam.Wang@arm.com        startAddr = lcdUpbase;
3567753SWilliam.Wang@arm.com    }
3577753SWilliam.Wang@arm.com    curAddr = 0;
3587823Ssteve.reinhardt@amd.com    startTime = curTick();
3597753SWilliam.Wang@arm.com    maxAddr = static_cast<Addr>(length*sizeof(uint32_t));
3607753SWilliam.Wang@arm.com    dmaPendingNum =0 ;
3617753SWilliam.Wang@arm.com
3627753SWilliam.Wang@arm.com    fillFifo();
3637753SWilliam.Wang@arm.com}
3647753SWilliam.Wang@arm.com
3657753SWilliam.Wang@arm.comvoid
3667753SWilliam.Wang@arm.comPl111::fillFifo()
3677753SWilliam.Wang@arm.com{
3687753SWilliam.Wang@arm.com    while ((dmaPendingNum < maxOutstandingDma) && (maxAddr >= curAddr + dmaSize )) {
3697753SWilliam.Wang@arm.com        // concurrent dma reads need different dma done events
3707753SWilliam.Wang@arm.com        // due to assertion in scheduling state
3717753SWilliam.Wang@arm.com        ++dmaPendingNum;
3727753SWilliam.Wang@arm.com        DPRINTF(PL111, " ++ DMA pending number %d read addr %#x\n",
3737753SWilliam.Wang@arm.com                dmaPendingNum, curAddr);
3747753SWilliam.Wang@arm.com        assert(!dmaDoneEvent[dmaPendingNum-1].scheduled());
3757753SWilliam.Wang@arm.com        dmaRead(curAddr + startAddr, dmaSize, &dmaDoneEvent[dmaPendingNum-1],
3767753SWilliam.Wang@arm.com                curAddr + dmaBuffer);
3777753SWilliam.Wang@arm.com        curAddr += dmaSize;
3787753SWilliam.Wang@arm.com    }
3797753SWilliam.Wang@arm.com}
3807753SWilliam.Wang@arm.com
3817753SWilliam.Wang@arm.comvoid
3827753SWilliam.Wang@arm.comPl111::dmaDone()
3837753SWilliam.Wang@arm.com{
3847753SWilliam.Wang@arm.com    Tick maxFrameTime = lcdTiming2.cpl*height*clock;
3857753SWilliam.Wang@arm.com
3867753SWilliam.Wang@arm.com    --dmaPendingNum;
3877753SWilliam.Wang@arm.com
3887753SWilliam.Wang@arm.com    DPRINTF(PL111, " -- DMA pending number %d\n", dmaPendingNum);
3897753SWilliam.Wang@arm.com
3907753SWilliam.Wang@arm.com    if (maxAddr == curAddr && !dmaPendingNum) {
3917823Ssteve.reinhardt@amd.com        if ((curTick() - startTime) > maxFrameTime)
3927753SWilliam.Wang@arm.com            warn("CLCD controller buffer underrun, took %d cycles when should"
3937823Ssteve.reinhardt@amd.com                 " have taken %d\n", curTick() - startTime, maxFrameTime);
3947753SWilliam.Wang@arm.com
3957753SWilliam.Wang@arm.com        // double buffering so the vnc server doesn't see a tear in the screen
3967753SWilliam.Wang@arm.com        memcpy(frameBuffer, dmaBuffer, maxAddr);
3977753SWilliam.Wang@arm.com        assert(!readEvent.scheduled());
3987753SWilliam.Wang@arm.com
3997753SWilliam.Wang@arm.com        DPRINTF(PL111, "-- write out frame buffer into bmp\n");
4007753SWilliam.Wang@arm.com        writeBMP(frameBuffer);
4017753SWilliam.Wang@arm.com
4027753SWilliam.Wang@arm.com        DPRINTF(PL111, "-- schedule next dma read event at %d tick \n",
4037823Ssteve.reinhardt@amd.com                maxFrameTime + curTick());
4047753SWilliam.Wang@arm.com        schedule(readEvent, nextCycle(startTime + maxFrameTime));
4057753SWilliam.Wang@arm.com    }
4067753SWilliam.Wang@arm.com
4077753SWilliam.Wang@arm.com    if (dmaPendingNum > (maxOutstandingDma - waterMark))
4087753SWilliam.Wang@arm.com        return;
4097753SWilliam.Wang@arm.com
4107753SWilliam.Wang@arm.com    if (!fillFifoEvent.scheduled())
4117753SWilliam.Wang@arm.com        schedule(fillFifoEvent, nextCycle());
4127753SWilliam.Wang@arm.com
4137753SWilliam.Wang@arm.com}
4147753SWilliam.Wang@arm.com
4157753SWilliam.Wang@arm.comTick
4167753SWilliam.Wang@arm.comPl111::nextCycle()
4177753SWilliam.Wang@arm.com{
4187823Ssteve.reinhardt@amd.com    Tick nextTick = curTick() + clock - 1;
4197753SWilliam.Wang@arm.com    nextTick -= nextTick%clock;
4207753SWilliam.Wang@arm.com    return nextTick;
4217753SWilliam.Wang@arm.com}
4227753SWilliam.Wang@arm.com
4237753SWilliam.Wang@arm.comTick
4247753SWilliam.Wang@arm.comPl111::nextCycle(Tick beginTick)
4257753SWilliam.Wang@arm.com{
4267753SWilliam.Wang@arm.com    Tick nextTick = beginTick;
4277753SWilliam.Wang@arm.com    if (nextTick%clock!=0)
4287753SWilliam.Wang@arm.com        nextTick = nextTick - (nextTick%clock) + clock;
4297753SWilliam.Wang@arm.com
4307823Ssteve.reinhardt@amd.com    assert(nextTick >= curTick());
4317753SWilliam.Wang@arm.com    return nextTick;
4327753SWilliam.Wang@arm.com}
4337753SWilliam.Wang@arm.com
4347753SWilliam.Wang@arm.com// write out the frame buffer into a bitmap file
4357753SWilliam.Wang@arm.comvoid
4367753SWilliam.Wang@arm.comPl111::writeBMP(uint32_t* frameBuffer)
4377753SWilliam.Wang@arm.com{
4387753SWilliam.Wang@arm.com    fstream pic;
4397753SWilliam.Wang@arm.com
4407753SWilliam.Wang@arm.com    // write out bmp head
4417753SWilliam.Wang@arm.com    std::string filename = "./m5out/frameBuffer.bmp";
4427753SWilliam.Wang@arm.com    pic.open(filename.c_str(), ios::out|ios::binary);
4437753SWilliam.Wang@arm.com    Bitmap bm(pic, height, width);
4447753SWilliam.Wang@arm.com
4457753SWilliam.Wang@arm.com    DPRINTF(PL111, "-- write out data into bmp\n");
4467753SWilliam.Wang@arm.com
4477753SWilliam.Wang@arm.com    // write out frame buffer data
4487753SWilliam.Wang@arm.com    for (int i = height -1; i >= 0; --i) {
4497753SWilliam.Wang@arm.com        for (int j = 0; j< width; ++j) {
4507753SWilliam.Wang@arm.com            uint32_t pixel = frameBuffer[i*width + j];
4517753SWilliam.Wang@arm.com            pic.write(reinterpret_cast<char*>(&pixel),
4527753SWilliam.Wang@arm.com                      sizeof(uint32_t));
4537753SWilliam.Wang@arm.com            DPRINTF(PL111, " write pixel data  %#x at addr %#x\n",
4547753SWilliam.Wang@arm.com                    pixel, i*width + j);
4557753SWilliam.Wang@arm.com        }
4567753SWilliam.Wang@arm.com    }
4577753SWilliam.Wang@arm.com
4587753SWilliam.Wang@arm.com    pic.close();
4597753SWilliam.Wang@arm.com}
4607753SWilliam.Wang@arm.com
4617753SWilliam.Wang@arm.comvoid
4627753SWilliam.Wang@arm.comPl111::serialize(std::ostream &os)
4637753SWilliam.Wang@arm.com{
4647753SWilliam.Wang@arm.com    DPRINTF(PL111, "Serializing ARM PL111\n");
4657753SWilliam.Wang@arm.com
4667753SWilliam.Wang@arm.com    uint32_t lcdTiming0_serial = lcdTiming0;
4677753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdTiming0_serial);
4687753SWilliam.Wang@arm.com
4697753SWilliam.Wang@arm.com    uint32_t lcdTiming1_serial = lcdTiming1;
4707753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdTiming1_serial);
4717753SWilliam.Wang@arm.com
4727753SWilliam.Wang@arm.com    uint32_t lcdTiming2_serial = lcdTiming2;
4737753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdTiming2_serial);
4747753SWilliam.Wang@arm.com
4757753SWilliam.Wang@arm.com    uint32_t lcdTiming3_serial = lcdTiming3;
4767753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdTiming3_serial);
4777753SWilliam.Wang@arm.com
4787753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdUpbase);
4797753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdLpbase);
4807753SWilliam.Wang@arm.com
4817753SWilliam.Wang@arm.com    uint32_t lcdControl_serial = lcdControl;
4827753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdControl_serial);
4837753SWilliam.Wang@arm.com
4847753SWilliam.Wang@arm.com    uint8_t lcdImsc_serial = lcdImsc;
4857753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdImsc_serial);
4867753SWilliam.Wang@arm.com
4877753SWilliam.Wang@arm.com    uint8_t lcdRis_serial = lcdRis;
4887753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdRis_serial);
4897753SWilliam.Wang@arm.com
4907753SWilliam.Wang@arm.com    uint8_t lcdMis_serial = lcdMis;
4917753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdMis_serial);
4927753SWilliam.Wang@arm.com
4937753SWilliam.Wang@arm.com    uint8_t lcdIcr_serial = lcdIcr;
4947753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(lcdIcr_serial);
4957753SWilliam.Wang@arm.com
4967753SWilliam.Wang@arm.com    SERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
4977753SWilliam.Wang@arm.com    SERIALIZE_ARRAY(cursorImage, CrsrImageSize);
4987753SWilliam.Wang@arm.com
4997753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrCtrl);
5007753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrConfig);
5017753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrPalette0);
5027753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrPalette1);
5037753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrXY);
5047753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrClip);
5057753SWilliam.Wang@arm.com
5067753SWilliam.Wang@arm.com    uint8_t clcdCrsrImsc_serial = clcdCrsrImsc;
5077753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrImsc_serial);
5087753SWilliam.Wang@arm.com
5097753SWilliam.Wang@arm.com    uint8_t clcdCrsrIcr_serial = clcdCrsrIcr;
5107753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrIcr_serial);
5117753SWilliam.Wang@arm.com
5127753SWilliam.Wang@arm.com    uint8_t clcdCrsrRis_serial = clcdCrsrRis;
5137753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrRis_serial);
5147753SWilliam.Wang@arm.com
5157753SWilliam.Wang@arm.com    uint8_t clcdCrsrMis_serial = clcdCrsrMis;
5167753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clcdCrsrMis_serial);
5177753SWilliam.Wang@arm.com
5187753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(clock);
5197753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(height);
5207753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(width);
5217753SWilliam.Wang@arm.com
5227753SWilliam.Wang@arm.com    SERIALIZE_ARRAY(dmaBuffer, height*width);
5237753SWilliam.Wang@arm.com    SERIALIZE_ARRAY(frameBuffer, height*width);
5247753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(startTime);
5257753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(startAddr);
5267753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(maxAddr);
5277753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(curAddr);
5287753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(waterMark);
5297753SWilliam.Wang@arm.com    SERIALIZE_SCALAR(dmaPendingNum);
5307753SWilliam.Wang@arm.com}
5317753SWilliam.Wang@arm.com
5327753SWilliam.Wang@arm.comvoid
5337753SWilliam.Wang@arm.comPl111::unserialize(Checkpoint *cp, const std::string &section)
5347753SWilliam.Wang@arm.com{
5357753SWilliam.Wang@arm.com    DPRINTF(PL111, "Unserializing ARM PL111\n");
5367753SWilliam.Wang@arm.com
5377753SWilliam.Wang@arm.com    uint32_t lcdTiming0_serial;
5387753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdTiming0_serial);
5397753SWilliam.Wang@arm.com    lcdTiming0 = lcdTiming0_serial;
5407753SWilliam.Wang@arm.com
5417753SWilliam.Wang@arm.com    uint32_t lcdTiming1_serial;
5427753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdTiming1_serial);
5437753SWilliam.Wang@arm.com    lcdTiming1 = lcdTiming1_serial;
5447753SWilliam.Wang@arm.com
5457753SWilliam.Wang@arm.com    uint32_t lcdTiming2_serial;
5467753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdTiming2_serial);
5477753SWilliam.Wang@arm.com    lcdTiming2 = lcdTiming2_serial;
5487753SWilliam.Wang@arm.com
5497753SWilliam.Wang@arm.com    uint32_t lcdTiming3_serial;
5507753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdTiming3_serial);
5517753SWilliam.Wang@arm.com    lcdTiming3 = lcdTiming3_serial;
5527753SWilliam.Wang@arm.com
5537753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdUpbase);
5547753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdLpbase);
5557753SWilliam.Wang@arm.com
5567753SWilliam.Wang@arm.com    uint32_t lcdControl_serial;
5577753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdControl_serial);
5587753SWilliam.Wang@arm.com    lcdControl = lcdControl_serial;
5597753SWilliam.Wang@arm.com
5607753SWilliam.Wang@arm.com    uint8_t lcdImsc_serial;
5617753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdImsc_serial);
5627753SWilliam.Wang@arm.com    lcdImsc = lcdImsc_serial;
5637753SWilliam.Wang@arm.com
5647753SWilliam.Wang@arm.com    uint8_t lcdRis_serial;
5657753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdRis_serial);
5667753SWilliam.Wang@arm.com    lcdRis = lcdRis_serial;
5677753SWilliam.Wang@arm.com
5687753SWilliam.Wang@arm.com    uint8_t lcdMis_serial;
5697753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdMis_serial);
5707753SWilliam.Wang@arm.com    lcdMis = lcdMis_serial;
5717753SWilliam.Wang@arm.com
5727753SWilliam.Wang@arm.com    uint8_t lcdIcr_serial;
5737753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(lcdIcr_serial);
5747753SWilliam.Wang@arm.com    lcdIcr = lcdIcr_serial;
5757753SWilliam.Wang@arm.com
5767753SWilliam.Wang@arm.com    UNSERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
5777753SWilliam.Wang@arm.com    UNSERIALIZE_ARRAY(cursorImage, CrsrImageSize);
5787753SWilliam.Wang@arm.com
5797753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrCtrl);
5807753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrConfig);
5817753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrPalette0);
5827753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrPalette1);
5837753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrXY);
5847753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrClip);
5857753SWilliam.Wang@arm.com
5867753SWilliam.Wang@arm.com    uint8_t clcdCrsrImsc_serial;
5877753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrImsc_serial);
5887753SWilliam.Wang@arm.com    clcdCrsrImsc = clcdCrsrImsc_serial;
5897753SWilliam.Wang@arm.com
5907753SWilliam.Wang@arm.com    uint8_t clcdCrsrIcr_serial;
5917753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrIcr_serial);
5927753SWilliam.Wang@arm.com    clcdCrsrIcr = clcdCrsrIcr_serial;
5937753SWilliam.Wang@arm.com
5947753SWilliam.Wang@arm.com    uint8_t clcdCrsrRis_serial;
5957753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrRis_serial);
5967753SWilliam.Wang@arm.com    clcdCrsrRis = clcdCrsrRis_serial;
5977753SWilliam.Wang@arm.com
5987753SWilliam.Wang@arm.com    uint8_t clcdCrsrMis_serial;
5997753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clcdCrsrMis_serial);
6007753SWilliam.Wang@arm.com    clcdCrsrMis = clcdCrsrMis_serial;
6017753SWilliam.Wang@arm.com
6027753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(clock);
6037753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(height);
6047753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(width);
6057753SWilliam.Wang@arm.com
6067753SWilliam.Wang@arm.com    UNSERIALIZE_ARRAY(dmaBuffer, height*width);
6077753SWilliam.Wang@arm.com    UNSERIALIZE_ARRAY(frameBuffer, height*width);
6087753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(startTime);
6097753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(startAddr);
6107753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(maxAddr);
6117753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(curAddr);
6127753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(waterMark);
6137753SWilliam.Wang@arm.com    UNSERIALIZE_SCALAR(dmaPendingNum);
6147753SWilliam.Wang@arm.com}
6157753SWilliam.Wang@arm.com
6167753SWilliam.Wang@arm.comvoid
6177753SWilliam.Wang@arm.comPl111::generateInterrupt()
6187753SWilliam.Wang@arm.com{
6197753SWilliam.Wang@arm.com    DPRINTF(PL111, "Generate Interrupt: lcdImsc=0x%x lcdRis=0x%x lcdMis=0x%x\n",
6207753SWilliam.Wang@arm.com            lcdImsc, lcdRis, lcdMis);
6217753SWilliam.Wang@arm.com    lcdMis = lcdImsc & lcdRis;
6227753SWilliam.Wang@arm.com
6237753SWilliam.Wang@arm.com    if (lcdMis.ffufie || lcdMis.nbupie || lcdMis.vtcpie || lcdMis.ahmeie) {
6247753SWilliam.Wang@arm.com        gic->sendInt(intNum);
6257753SWilliam.Wang@arm.com        DPRINTF(PL111, " -- Generated\n");
6267753SWilliam.Wang@arm.com    }
6277753SWilliam.Wang@arm.com}
6287753SWilliam.Wang@arm.com
6297753SWilliam.Wang@arm.comvoid
6307753SWilliam.Wang@arm.comPl111::addressRanges(AddrRangeList& range_list)
6317753SWilliam.Wang@arm.com{
6327753SWilliam.Wang@arm.com    range_list.clear();
6337753SWilliam.Wang@arm.com    range_list.push_back(RangeSize(pioAddr, pioSize));
6347753SWilliam.Wang@arm.com}
6357753SWilliam.Wang@arm.com
6367753SWilliam.Wang@arm.comPl111 *
6377753SWilliam.Wang@arm.comPl111Params::create()
6387753SWilliam.Wang@arm.com{
6397753SWilliam.Wang@arm.com    return new Pl111(this);
6407753SWilliam.Wang@arm.com}
6417753SWilliam.Wang@arm.com
6427753SWilliam.Wang@arm.com// bitmap class ctor
6437753SWilliam.Wang@arm.comBitmap::Bitmap(std::fstream& bmp, uint16_t h, uint16_t w)
6447753SWilliam.Wang@arm.com{
6457753SWilliam.Wang@arm.com    Magic  magic  = {{'B','M'}};
6467753SWilliam.Wang@arm.com    Header header = {sizeof(Color)*w*h , 0, 0, 54};
6477753SWilliam.Wang@arm.com    Info   info   = {sizeof(Info), w, h, 1, sizeof(Color)*8, 0,
6487753SWilliam.Wang@arm.com                     ( sizeof(Color) *(w*h) ), 1, 1, 0, 0};
6497753SWilliam.Wang@arm.com
6507753SWilliam.Wang@arm.com    bmp.write(reinterpret_cast<char*>(&magic),  sizeof(magic));
6517753SWilliam.Wang@arm.com    bmp.write(reinterpret_cast<char*>(&header), sizeof(header));
6527753SWilliam.Wang@arm.com    bmp.write(reinterpret_cast<char*>(&info),   sizeof(info));
6537753SWilliam.Wang@arm.com}
654