pl111.cc revision 9090:e4e22240398f
19646SChris.Emmons@arm.com/*
211897Ssudhanshu.jha@arm.com * Copyright (c) 2010 ARM Limited
39646SChris.Emmons@arm.com * All rights reserved
49646SChris.Emmons@arm.com *
59646SChris.Emmons@arm.com * The license below extends only to copyright in the software and shall
69646SChris.Emmons@arm.com * not be construed as granting a license to any other intellectual
79646SChris.Emmons@arm.com * property including but not limited to intellectual property relating
89646SChris.Emmons@arm.com * to a hardware implementation of the functionality of the software
99646SChris.Emmons@arm.com * licensed hereunder.  You may use the software subject to the license
109646SChris.Emmons@arm.com * terms below provided that you ensure that this notice is replicated
119646SChris.Emmons@arm.com * unmodified and in its entirety in all distributions of the software,
129646SChris.Emmons@arm.com * modified or unmodified, in source code or in binary form.
139646SChris.Emmons@arm.com *
149646SChris.Emmons@arm.com * Redistribution and use in source and binary forms, with or without
159646SChris.Emmons@arm.com * modification, are permitted provided that the following conditions are
169646SChris.Emmons@arm.com * met: redistributions of source code must retain the above copyright
179646SChris.Emmons@arm.com * notice, this list of conditions and the following disclaimer;
189646SChris.Emmons@arm.com * redistributions in binary form must reproduce the above copyright
199646SChris.Emmons@arm.com * notice, this list of conditions and the following disclaimer in the
209646SChris.Emmons@arm.com * documentation and/or other materials provided with the distribution;
219646SChris.Emmons@arm.com * neither the name of the copyright holders nor the names of its
229646SChris.Emmons@arm.com * contributors may be used to endorse or promote products derived from
239646SChris.Emmons@arm.com * this software without specific prior written permission.
249646SChris.Emmons@arm.com *
259646SChris.Emmons@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
269646SChris.Emmons@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
279646SChris.Emmons@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
289646SChris.Emmons@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
299646SChris.Emmons@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
309646SChris.Emmons@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
319646SChris.Emmons@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
329646SChris.Emmons@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
339646SChris.Emmons@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
349646SChris.Emmons@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
359646SChris.Emmons@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
369646SChris.Emmons@arm.com *
379646SChris.Emmons@arm.com * Authors: William Wang
3811090Sandreas.sandberg@arm.com *          Ali Saidi
399646SChris.Emmons@arm.com */
409646SChris.Emmons@arm.com
4110839Sandreas.sandberg@arm.com#include "base/vnc/vncserver.hh"
4210839Sandreas.sandberg@arm.com#include "base/bitmap.hh"
439646SChris.Emmons@arm.com#include "base/output.hh"
449646SChris.Emmons@arm.com#include "base/trace.hh"
4511793Sbrandon.potter@amd.com#include "debug/PL111.hh"
4611090Sandreas.sandberg@arm.com#include "debug/Uart.hh"
479646SChris.Emmons@arm.com#include "dev/arm/amba_device.hh"
489646SChris.Emmons@arm.com#include "dev/arm/gic.hh"
499646SChris.Emmons@arm.com#include "dev/arm/pl111.hh"
509646SChris.Emmons@arm.com#include "mem/packet.hh"
519646SChris.Emmons@arm.com#include "mem/packet_access.hh"
5211090Sandreas.sandberg@arm.com
539646SChris.Emmons@arm.com// clang complains about std::set being overloaded with Packet::set if
549646SChris.Emmons@arm.com// we open up the entire namespace std
559646SChris.Emmons@arm.comusing std::vector;
569646SChris.Emmons@arm.com
579646SChris.Emmons@arm.comusing namespace AmbaDev;
589646SChris.Emmons@arm.com
5911090Sandreas.sandberg@arm.com// initialize clcd registers
6011090Sandreas.sandberg@arm.comPl111::Pl111(const Params *p)
6111090Sandreas.sandberg@arm.com    : AmbaDmaDevice(p), lcdTiming0(0), lcdTiming1(0), lcdTiming2(0),
6211090Sandreas.sandberg@arm.com      lcdTiming3(0), lcdUpbase(0), lcdLpbase(0), lcdControl(0), lcdImsc(0),
6311090Sandreas.sandberg@arm.com      lcdRis(0), lcdMis(0),
6411090Sandreas.sandberg@arm.com      clcdCrsrCtrl(0), clcdCrsrConfig(0), clcdCrsrPalette0(0),
6511090Sandreas.sandberg@arm.com      clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0),
6611090Sandreas.sandberg@arm.com      clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0), clock(p->clock),
6711090Sandreas.sandberg@arm.com      vncserver(p->vnc), bmp(NULL), width(LcdMaxWidth), height(LcdMaxHeight),
6811898Ssudhanshu.jha@arm.com      bytesPerPixel(4), startTime(0), startAddr(0), maxAddr(0), curAddr(0),
6911090Sandreas.sandberg@arm.com      waterMark(0), dmaPendingNum(0), readEvent(this), fillFifoEvent(this),
7011090Sandreas.sandberg@arm.com      dmaDoneEvent(maxOutstandingDma, this), intEvent(this)
7111090Sandreas.sandberg@arm.com{
7211090Sandreas.sandberg@arm.com    pioSize = 0xFFFF;
7311090Sandreas.sandberg@arm.com
749646SChris.Emmons@arm.com    pic = simout.create(csprintf("%s.framebuffer.bmp", sys->name()), true);
759646SChris.Emmons@arm.com
7611090Sandreas.sandberg@arm.com    const int buffer_size = LcdMaxWidth * LcdMaxHeight * sizeof(uint32_t);
779646SChris.Emmons@arm.com    dmaBuffer = new uint8_t[buffer_size];
789646SChris.Emmons@arm.com
7911090Sandreas.sandberg@arm.com    memset(lcdPalette, 0, sizeof(lcdPalette));
8011090Sandreas.sandberg@arm.com    memset(cursorImage, 0, sizeof(cursorImage));
8111090Sandreas.sandberg@arm.com    memset(dmaBuffer, 0, buffer_size);
8211090Sandreas.sandberg@arm.com
8311090Sandreas.sandberg@arm.com    if (vncserver)
849646SChris.Emmons@arm.com        vncserver->setFramebufferAddr(dmaBuffer);
8511090Sandreas.sandberg@arm.com}
8611898Ssudhanshu.jha@arm.com
8711090Sandreas.sandberg@arm.comPl111::~Pl111()
8811090Sandreas.sandberg@arm.com{
8911090Sandreas.sandberg@arm.com    delete[] dmaBuffer;
909646SChris.Emmons@arm.com}
919646SChris.Emmons@arm.com
9211090Sandreas.sandberg@arm.com// read registers and frame buffer
939646SChris.Emmons@arm.comTick
949646SChris.Emmons@arm.comPl111::read(PacketPtr pkt)
959646SChris.Emmons@arm.com{
969646SChris.Emmons@arm.com    // use a temporary data since the LCD registers are read/written with
979646SChris.Emmons@arm.com    // different size operations
989646SChris.Emmons@arm.com
9911090Sandreas.sandberg@arm.com    uint32_t data = 0;
10011091Sandreas.sandberg@arm.com
10111091Sandreas.sandberg@arm.com    assert(pkt->getAddr() >= pioAddr &&
10211523Sdavid.guillen@arm.com           pkt->getAddr() < pioAddr + pioSize);
10311523Sdavid.guillen@arm.com
10411091Sandreas.sandberg@arm.com    Addr daddr = pkt->getAddr() - pioAddr;
10511091Sandreas.sandberg@arm.com    pkt->allocate();
10611091Sandreas.sandberg@arm.com
10711091Sandreas.sandberg@arm.com    DPRINTF(PL111, " read register %#x size=%d\n", daddr, pkt->getSize());
10811091Sandreas.sandberg@arm.com
10911091Sandreas.sandberg@arm.com    switch (daddr) {
11011091Sandreas.sandberg@arm.com      case LcdTiming0:
11111091Sandreas.sandberg@arm.com        data = lcdTiming0;
11211091Sandreas.sandberg@arm.com        break;
11311091Sandreas.sandberg@arm.com      case LcdTiming1:
11411090Sandreas.sandberg@arm.com        data = lcdTiming1;
11511090Sandreas.sandberg@arm.com        break;
11611090Sandreas.sandberg@arm.com      case LcdTiming2:
11711090Sandreas.sandberg@arm.com        data = lcdTiming2;
11811090Sandreas.sandberg@arm.com        break;
11911090Sandreas.sandberg@arm.com      case LcdTiming3:
12011090Sandreas.sandberg@arm.com        data = lcdTiming3;
12111090Sandreas.sandberg@arm.com        break;
12211090Sandreas.sandberg@arm.com      case LcdUpBase:
12311090Sandreas.sandberg@arm.com        data = lcdUpbase;
12411090Sandreas.sandberg@arm.com        break;
12511090Sandreas.sandberg@arm.com      case LcdLpBase:
12611090Sandreas.sandberg@arm.com        data = lcdLpbase;
12711090Sandreas.sandberg@arm.com        break;
12811090Sandreas.sandberg@arm.com      case LcdControl:
12911090Sandreas.sandberg@arm.com        data = lcdControl;
13011090Sandreas.sandberg@arm.com        break;
13111090Sandreas.sandberg@arm.com      case LcdImsc:
13211090Sandreas.sandberg@arm.com        data = lcdImsc;
13311090Sandreas.sandberg@arm.com        break;
13411090Sandreas.sandberg@arm.com      case LcdRis:
13511090Sandreas.sandberg@arm.com        data = lcdRis;
13611090Sandreas.sandberg@arm.com        break;
13711090Sandreas.sandberg@arm.com      case LcdMis:
13811090Sandreas.sandberg@arm.com        data = lcdMis;
13911090Sandreas.sandberg@arm.com        break;
14011090Sandreas.sandberg@arm.com      case LcdIcr:
14111090Sandreas.sandberg@arm.com        panic("LCD register at offset %#x is Write-Only\n", daddr);
14211090Sandreas.sandberg@arm.com        break;
14311090Sandreas.sandberg@arm.com      case LcdUpCurr:
14411090Sandreas.sandberg@arm.com        data = curAddr;
14511090Sandreas.sandberg@arm.com        break;
14611090Sandreas.sandberg@arm.com      case LcdLpCurr:
14711090Sandreas.sandberg@arm.com        data = curAddr;
14811090Sandreas.sandberg@arm.com        break;
14911090Sandreas.sandberg@arm.com      case ClcdCrsrCtrl:
15011090Sandreas.sandberg@arm.com        data = clcdCrsrCtrl;
15111090Sandreas.sandberg@arm.com        break;
15211090Sandreas.sandberg@arm.com      case ClcdCrsrConfig:
15311090Sandreas.sandberg@arm.com        data = clcdCrsrConfig;
15411090Sandreas.sandberg@arm.com        break;
15511090Sandreas.sandberg@arm.com      case ClcdCrsrPalette0:
15611090Sandreas.sandberg@arm.com        data = clcdCrsrPalette0;
15711090Sandreas.sandberg@arm.com        break;
15811090Sandreas.sandberg@arm.com      case ClcdCrsrPalette1:
15911090Sandreas.sandberg@arm.com        data = clcdCrsrPalette1;
16011090Sandreas.sandberg@arm.com        break;
16111090Sandreas.sandberg@arm.com      case ClcdCrsrXY:
16211090Sandreas.sandberg@arm.com        data = clcdCrsrXY;
16311090Sandreas.sandberg@arm.com        break;
16411090Sandreas.sandberg@arm.com      case ClcdCrsrClip:
16511090Sandreas.sandberg@arm.com        data = clcdCrsrClip;
16611090Sandreas.sandberg@arm.com        break;
16711090Sandreas.sandberg@arm.com      case ClcdCrsrImsc:
16811090Sandreas.sandberg@arm.com        data = clcdCrsrImsc;
16911090Sandreas.sandberg@arm.com        break;
17011090Sandreas.sandberg@arm.com      case ClcdCrsrIcr:
17111090Sandreas.sandberg@arm.com        panic("CLCD register at offset %#x is Write-Only\n", daddr);
17211090Sandreas.sandberg@arm.com        break;
17311090Sandreas.sandberg@arm.com      case ClcdCrsrRis:
17411090Sandreas.sandberg@arm.com        data = clcdCrsrRis;
17511090Sandreas.sandberg@arm.com        break;
17611090Sandreas.sandberg@arm.com      case ClcdCrsrMis:
17711090Sandreas.sandberg@arm.com        data = clcdCrsrMis;
17811090Sandreas.sandberg@arm.com        break;
17911090Sandreas.sandberg@arm.com      default:
18011090Sandreas.sandberg@arm.com        if (AmbaDev::readId(pkt, AMBA_ID, pioAddr)) {
18111090Sandreas.sandberg@arm.com            // Hack for variable size accesses
18211090Sandreas.sandberg@arm.com            data = pkt->get<uint32_t>();
18311090Sandreas.sandberg@arm.com            break;
18411090Sandreas.sandberg@arm.com        } else if (daddr >= CrsrImage && daddr <= 0xBFC) {
18511090Sandreas.sandberg@arm.com            // CURSOR IMAGE
18611090Sandreas.sandberg@arm.com            int index;
18711090Sandreas.sandberg@arm.com            index = (daddr - CrsrImage) >> 2;
18811090Sandreas.sandberg@arm.com            data= cursorImage[index];
18911090Sandreas.sandberg@arm.com            break;
19011090Sandreas.sandberg@arm.com        } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
19111090Sandreas.sandberg@arm.com            // LCD Palette
19211090Sandreas.sandberg@arm.com            int index;
19311090Sandreas.sandberg@arm.com            index = (daddr - LcdPalette) >> 2;
19411090Sandreas.sandberg@arm.com            data = lcdPalette[index];
19511090Sandreas.sandberg@arm.com            break;
19611090Sandreas.sandberg@arm.com        } else {
19711090Sandreas.sandberg@arm.com            panic("Tried to read CLCD register at offset %#x that \
19811090Sandreas.sandberg@arm.com                       doesn't exist\n", daddr);
19911090Sandreas.sandberg@arm.com            break;
20011090Sandreas.sandberg@arm.com        }
20111090Sandreas.sandberg@arm.com    }
20211090Sandreas.sandberg@arm.com
20311090Sandreas.sandberg@arm.com    switch(pkt->getSize()) {
20411090Sandreas.sandberg@arm.com      case 1:
20511090Sandreas.sandberg@arm.com        pkt->set<uint8_t>(data);
20611898Ssudhanshu.jha@arm.com        break;
20711898Ssudhanshu.jha@arm.com      case 2:
20811898Ssudhanshu.jha@arm.com        pkt->set<uint16_t>(data);
20911898Ssudhanshu.jha@arm.com        break;
21011898Ssudhanshu.jha@arm.com      case 4:
21111898Ssudhanshu.jha@arm.com        pkt->set<uint32_t>(data);
21211898Ssudhanshu.jha@arm.com        break;
21311898Ssudhanshu.jha@arm.com      default:
21411898Ssudhanshu.jha@arm.com        panic("CLCD controller read size too big?\n");
21511898Ssudhanshu.jha@arm.com        break;
21611898Ssudhanshu.jha@arm.com    }
21711898Ssudhanshu.jha@arm.com
21811898Ssudhanshu.jha@arm.com    pkt->makeAtomicResponse();
21911897Ssudhanshu.jha@arm.com    return pioDelay;
22011090Sandreas.sandberg@arm.com}
22111090Sandreas.sandberg@arm.com
22211090Sandreas.sandberg@arm.com// write registers and frame buffer
22311090Sandreas.sandberg@arm.comTick
22411090Sandreas.sandberg@arm.comPl111::write(PacketPtr pkt)
22511090Sandreas.sandberg@arm.com{
22611898Ssudhanshu.jha@arm.com    // use a temporary data since the LCD registers are read/written with
22711898Ssudhanshu.jha@arm.com    // different size operations
22811898Ssudhanshu.jha@arm.com    //
22911898Ssudhanshu.jha@arm.com    uint32_t data = 0;
23011898Ssudhanshu.jha@arm.com
23111898Ssudhanshu.jha@arm.com    switch(pkt->getSize()) {
23211898Ssudhanshu.jha@arm.com      case 1:
2339646SChris.Emmons@arm.com        data = pkt->get<uint8_t>();
2349646SChris.Emmons@arm.com        break;
2359646SChris.Emmons@arm.com      case 2:
2369646SChris.Emmons@arm.com        data = pkt->get<uint16_t>();
23711090Sandreas.sandberg@arm.com        break;
23811090Sandreas.sandberg@arm.com      case 4:
2399646SChris.Emmons@arm.com        data = pkt->get<uint32_t>();
24011090Sandreas.sandberg@arm.com        break;
24111090Sandreas.sandberg@arm.com      default:
24211090Sandreas.sandberg@arm.com        panic("PL111 CLCD controller write size too big?\n");
24311090Sandreas.sandberg@arm.com        break;
2449646SChris.Emmons@arm.com    }
24511090Sandreas.sandberg@arm.com
24611090Sandreas.sandberg@arm.com    assert(pkt->getAddr() >= pioAddr &&
2479646SChris.Emmons@arm.com           pkt->getAddr() < pioAddr + pioSize);
2489646SChris.Emmons@arm.com
2499646SChris.Emmons@arm.com    Addr daddr = pkt->getAddr() - pioAddr;
2509646SChris.Emmons@arm.com
2519646SChris.Emmons@arm.com    DPRINTF(PL111, " write register %#x value %#x size=%d\n", daddr,
2529646SChris.Emmons@arm.com            pkt->get<uint8_t>(), pkt->getSize());
2539646SChris.Emmons@arm.com
2549646SChris.Emmons@arm.com    switch (daddr) {
2559646SChris.Emmons@arm.com      case LcdTiming0:
2569646SChris.Emmons@arm.com        lcdTiming0 = data;
2579646SChris.Emmons@arm.com        // width = 16 * (PPL+1)
25811090Sandreas.sandberg@arm.com        width = (lcdTiming0.ppl + 1) << 4;
2599646SChris.Emmons@arm.com        break;
26011090Sandreas.sandberg@arm.com      case LcdTiming1:
26111090Sandreas.sandberg@arm.com        lcdTiming1 = data;
26211090Sandreas.sandberg@arm.com        // height = LPP + 1
26311090Sandreas.sandberg@arm.com        height = (lcdTiming1.lpp) + 1;
26411090Sandreas.sandberg@arm.com        break;
26511090Sandreas.sandberg@arm.com      case LcdTiming2:
2669646SChris.Emmons@arm.com        lcdTiming2 = data;
26711090Sandreas.sandberg@arm.com        break;
2689646SChris.Emmons@arm.com      case LcdTiming3:
2699646SChris.Emmons@arm.com        lcdTiming3 = data;
2709646SChris.Emmons@arm.com        break;
2719646SChris.Emmons@arm.com      case LcdUpBase:
2729646SChris.Emmons@arm.com        lcdUpbase = data;
27311090Sandreas.sandberg@arm.com        DPRINTF(PL111, "####### Upper panel base set to: %#x #######\n", lcdUpbase);
27411090Sandreas.sandberg@arm.com        break;
2759646SChris.Emmons@arm.com      case LcdLpBase:
27611090Sandreas.sandberg@arm.com        warn_once("LCD dual screen mode not supported\n");
27711090Sandreas.sandberg@arm.com        lcdLpbase = data;
27810839Sandreas.sandberg@arm.com        DPRINTF(PL111, "###### Lower panel base set to: %#x #######\n", lcdLpbase);
27911090Sandreas.sandberg@arm.com        break;
28011090Sandreas.sandberg@arm.com      case LcdControl:
28111090Sandreas.sandberg@arm.com        int old_lcdpwr;
28211090Sandreas.sandberg@arm.com        old_lcdpwr = lcdControl.lcdpwr;
28311090Sandreas.sandberg@arm.com        lcdControl = data;
2849646SChris.Emmons@arm.com
28511090Sandreas.sandberg@arm.com        DPRINTF(PL111, "LCD power is:%d\n", lcdControl.lcdpwr);
28611090Sandreas.sandberg@arm.com
28711090Sandreas.sandberg@arm.com        // LCD power enable
28811090Sandreas.sandberg@arm.com        if (lcdControl.lcdpwr && !old_lcdpwr) {
28911090Sandreas.sandberg@arm.com            updateVideoParams();
2909646SChris.Emmons@arm.com            DPRINTF(PL111, " lcd size: height %d width %d\n", height, width);
29111090Sandreas.sandberg@arm.com            waterMark = lcdControl.watermark ? 8 : 4;
29211090Sandreas.sandberg@arm.com            startDma();
29311090Sandreas.sandberg@arm.com        }
29411090Sandreas.sandberg@arm.com        break;
29511090Sandreas.sandberg@arm.com      case LcdImsc:
29611090Sandreas.sandberg@arm.com        lcdImsc = data;
29711090Sandreas.sandberg@arm.com        if (lcdImsc.vcomp)
29811090Sandreas.sandberg@arm.com            panic("Interrupting on vcomp not supported\n");
29911090Sandreas.sandberg@arm.com
30010839Sandreas.sandberg@arm.com        lcdMis = lcdImsc & lcdRis;
30111090Sandreas.sandberg@arm.com
30211090Sandreas.sandberg@arm.com        if (!lcdMis)
30311090Sandreas.sandberg@arm.com            gic->clearInt(intNum);
30411090Sandreas.sandberg@arm.com
30511090Sandreas.sandberg@arm.com         break;
30610839Sandreas.sandberg@arm.com      case LcdRis:
30711090Sandreas.sandberg@arm.com        panic("LCD register at offset %#x is Read-Only\n", daddr);
30811090Sandreas.sandberg@arm.com        break;
3099646SChris.Emmons@arm.com      case LcdMis:
3109646SChris.Emmons@arm.com        panic("LCD register at offset %#x is Read-Only\n", daddr);
3119646SChris.Emmons@arm.com        break;
3129646SChris.Emmons@arm.com      case LcdIcr:
31311090Sandreas.sandberg@arm.com        lcdRis = lcdRis & ~data;
3149646SChris.Emmons@arm.com        lcdMis = lcdImsc & lcdRis;
31511090Sandreas.sandberg@arm.com
31611090Sandreas.sandberg@arm.com        if (!lcdMis)
31711090Sandreas.sandberg@arm.com            gic->clearInt(intNum);
3189646SChris.Emmons@arm.com
31911090Sandreas.sandberg@arm.com        break;
32011090Sandreas.sandberg@arm.com      case LcdUpCurr:
32111090Sandreas.sandberg@arm.com        panic("LCD register at offset %#x is Read-Only\n", daddr);
32211090Sandreas.sandberg@arm.com        break;
32311090Sandreas.sandberg@arm.com      case LcdLpCurr:
32411090Sandreas.sandberg@arm.com        panic("LCD register at offset %#x is Read-Only\n", daddr);
32511090Sandreas.sandberg@arm.com        break;
32611090Sandreas.sandberg@arm.com      case ClcdCrsrCtrl:
32711090Sandreas.sandberg@arm.com        clcdCrsrCtrl = data;
32811090Sandreas.sandberg@arm.com        break;
32911090Sandreas.sandberg@arm.com      case ClcdCrsrConfig:
33011090Sandreas.sandberg@arm.com        clcdCrsrConfig = data;
33111090Sandreas.sandberg@arm.com        break;
33211090Sandreas.sandberg@arm.com      case ClcdCrsrPalette0:
33311090Sandreas.sandberg@arm.com        clcdCrsrPalette0 = data;
33411090Sandreas.sandberg@arm.com        break;
33511090Sandreas.sandberg@arm.com      case ClcdCrsrPalette1:
33611090Sandreas.sandberg@arm.com        clcdCrsrPalette1 = data;
33711090Sandreas.sandberg@arm.com        break;
33811090Sandreas.sandberg@arm.com      case ClcdCrsrXY:
33911090Sandreas.sandberg@arm.com        clcdCrsrXY = data;
34011090Sandreas.sandberg@arm.com        break;
34111090Sandreas.sandberg@arm.com      case ClcdCrsrClip:
34211090Sandreas.sandberg@arm.com        clcdCrsrClip = data;
34311090Sandreas.sandberg@arm.com        break;
34411090Sandreas.sandberg@arm.com      case ClcdCrsrImsc:
34511090Sandreas.sandberg@arm.com        clcdCrsrImsc = data;
34611090Sandreas.sandberg@arm.com        break;
34711090Sandreas.sandberg@arm.com      case ClcdCrsrIcr:
34811090Sandreas.sandberg@arm.com        clcdCrsrIcr = data;
34911090Sandreas.sandberg@arm.com        break;
35011090Sandreas.sandberg@arm.com      case ClcdCrsrRis:
35111090Sandreas.sandberg@arm.com        panic("CLCD register at offset %#x is Read-Only\n", daddr);
35211090Sandreas.sandberg@arm.com        break;
35311090Sandreas.sandberg@arm.com      case ClcdCrsrMis:
35411090Sandreas.sandberg@arm.com        panic("CLCD register at offset %#x is Read-Only\n", daddr);
35511090Sandreas.sandberg@arm.com        break;
35611090Sandreas.sandberg@arm.com      default:
35711090Sandreas.sandberg@arm.com        if (daddr >= CrsrImage && daddr <= 0xBFC) {
35811090Sandreas.sandberg@arm.com            // CURSOR IMAGE
35911090Sandreas.sandberg@arm.com            int index;
36011090Sandreas.sandberg@arm.com            index = (daddr - CrsrImage) >> 2;
36111090Sandreas.sandberg@arm.com            cursorImage[index] = data;
36211090Sandreas.sandberg@arm.com            break;
36311090Sandreas.sandberg@arm.com        } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
36411090Sandreas.sandberg@arm.com            // LCD Palette
36511090Sandreas.sandberg@arm.com            int index;
36611090Sandreas.sandberg@arm.com            index = (daddr - LcdPalette) >> 2;
36711090Sandreas.sandberg@arm.com            lcdPalette[index] = data;
36811090Sandreas.sandberg@arm.com            break;
36911090Sandreas.sandberg@arm.com        } else {
37011090Sandreas.sandberg@arm.com            panic("Tried to write PL111 register at offset %#x that \
37111090Sandreas.sandberg@arm.com                       doesn't exist\n", daddr);
37211090Sandreas.sandberg@arm.com            break;
37311090Sandreas.sandberg@arm.com        }
37411090Sandreas.sandberg@arm.com    }
37511090Sandreas.sandberg@arm.com
37611090Sandreas.sandberg@arm.com    pkt->makeAtomicResponse();
37711090Sandreas.sandberg@arm.com    return pioDelay;
37811090Sandreas.sandberg@arm.com}
37911090Sandreas.sandberg@arm.com
38011090Sandreas.sandberg@arm.comvoid
38111090Sandreas.sandberg@arm.comPl111::updateVideoParams()
38211090Sandreas.sandberg@arm.com{
38311090Sandreas.sandberg@arm.com        if (lcdControl.lcdbpp == bpp24) {
38411090Sandreas.sandberg@arm.com            bytesPerPixel = 4;
38511090Sandreas.sandberg@arm.com        } else if (lcdControl.lcdbpp == bpp16m565) {
38611090Sandreas.sandberg@arm.com            bytesPerPixel = 2;
38711090Sandreas.sandberg@arm.com        }
38811090Sandreas.sandberg@arm.com
38911090Sandreas.sandberg@arm.com        if (vncserver) {
39011090Sandreas.sandberg@arm.com            if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr)
39111090Sandreas.sandberg@arm.com                vncserver->setFrameBufferParams(VideoConvert::bgr8888, width,
39211090Sandreas.sandberg@arm.com                       height);
39311090Sandreas.sandberg@arm.com            else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr)
39411090Sandreas.sandberg@arm.com                vncserver->setFrameBufferParams(VideoConvert::rgb8888, width,
39511090Sandreas.sandberg@arm.com                       height);
39611090Sandreas.sandberg@arm.com            else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr)
39711090Sandreas.sandberg@arm.com                vncserver->setFrameBufferParams(VideoConvert::bgr565, width,
39811090Sandreas.sandberg@arm.com                       height);
39911090Sandreas.sandberg@arm.com            else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr)
40011090Sandreas.sandberg@arm.com                vncserver->setFrameBufferParams(VideoConvert::rgb565, width,
40111090Sandreas.sandberg@arm.com                       height);
40211090Sandreas.sandberg@arm.com            else
40311090Sandreas.sandberg@arm.com                panic("Unimplemented video mode\n");
40411090Sandreas.sandberg@arm.com        }
40511090Sandreas.sandberg@arm.com
40611090Sandreas.sandberg@arm.com        if (bmp)
40711090Sandreas.sandberg@arm.com            delete bmp;
40811090Sandreas.sandberg@arm.com
40911090Sandreas.sandberg@arm.com        if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr)
41011090Sandreas.sandberg@arm.com            bmp = new Bitmap(VideoConvert::bgr8888, width, height, dmaBuffer);
41111090Sandreas.sandberg@arm.com        else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr)
41211090Sandreas.sandberg@arm.com            bmp = new Bitmap(VideoConvert::rgb8888, width, height, dmaBuffer);
41311090Sandreas.sandberg@arm.com        else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr)
41411090Sandreas.sandberg@arm.com            bmp = new Bitmap(VideoConvert::bgr565, width, height, dmaBuffer);
41511090Sandreas.sandberg@arm.com        else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr)
41611090Sandreas.sandberg@arm.com            bmp = new Bitmap(VideoConvert::rgb565, width, height, dmaBuffer);
41711090Sandreas.sandberg@arm.com        else
41811090Sandreas.sandberg@arm.com            panic("Unimplemented video mode\n");
41911090Sandreas.sandberg@arm.com}
42011090Sandreas.sandberg@arm.com
42111090Sandreas.sandberg@arm.comvoid
42211090Sandreas.sandberg@arm.comPl111::startDma()
42311090Sandreas.sandberg@arm.com{
42411090Sandreas.sandberg@arm.com    if (dmaPendingNum != 0 || readEvent.scheduled())
42511090Sandreas.sandberg@arm.com        return;
42611090Sandreas.sandberg@arm.com    readFramebuffer();
42711090Sandreas.sandberg@arm.com}
42811090Sandreas.sandberg@arm.com
42911090Sandreas.sandberg@arm.comvoid
4309646SChris.Emmons@arm.comPl111::readFramebuffer()
4319646SChris.Emmons@arm.com{
4329646SChris.Emmons@arm.com    // initialization for dma read from frame buffer to dma buffer
43310839Sandreas.sandberg@arm.com    uint32_t length = height * width;
43410839Sandreas.sandberg@arm.com    if (startAddr != lcdUpbase)
43510839Sandreas.sandberg@arm.com        startAddr = lcdUpbase;
43610840Sandreas.sandberg@arm.com
43710839Sandreas.sandberg@arm.com    // Updating base address, interrupt if we're supposed to
43810840Sandreas.sandberg@arm.com    lcdRis.baseaddr = 1;
43910840Sandreas.sandberg@arm.com    if (!intEvent.scheduled())
44010840Sandreas.sandberg@arm.com        schedule(intEvent, nextCycle());
44111090Sandreas.sandberg@arm.com
44210840Sandreas.sandberg@arm.com    curAddr = 0;
44311090Sandreas.sandberg@arm.com    startTime = curTick();
44410840Sandreas.sandberg@arm.com
44510840Sandreas.sandberg@arm.com    maxAddr = static_cast<Addr>(length * bytesPerPixel);
44610840Sandreas.sandberg@arm.com
44710840Sandreas.sandberg@arm.com    DPRINTF(PL111, " lcd frame buffer size of %d bytes \n", maxAddr);
44810840Sandreas.sandberg@arm.com
44911090Sandreas.sandberg@arm.com    dmaPendingNum = 0;
45010840Sandreas.sandberg@arm.com
45110840Sandreas.sandberg@arm.com    fillFifo();
45210840Sandreas.sandberg@arm.com}
45310840Sandreas.sandberg@arm.com
45410839Sandreas.sandberg@arm.comvoid
45510839Sandreas.sandberg@arm.comPl111::fillFifo()
45611090Sandreas.sandberg@arm.com{
45711090Sandreas.sandberg@arm.com    while ((dmaPendingNum < maxOutstandingDma) && (maxAddr >= curAddr + dmaSize )) {
45811090Sandreas.sandberg@arm.com        // concurrent dma reads need different dma done events
45911090Sandreas.sandberg@arm.com        // due to assertion in scheduling state
46011090Sandreas.sandberg@arm.com        ++dmaPendingNum;
46111090Sandreas.sandberg@arm.com
46211090Sandreas.sandberg@arm.com        assert(!dmaDoneEvent[dmaPendingNum-1].scheduled());
46311090Sandreas.sandberg@arm.com
46411090Sandreas.sandberg@arm.com        // We use a uncachable request here because the requests from the CPU
4659646SChris.Emmons@arm.com        // will be uncacheable as well. If we have uncacheable and cacheable
46611090Sandreas.sandberg@arm.com        // requests in the memory system for the same address it won't be
46711090Sandreas.sandberg@arm.com        // pleased
46811090Sandreas.sandberg@arm.com        dmaPort.dmaAction(MemCmd::ReadReq, curAddr + startAddr, dmaSize,
46911090Sandreas.sandberg@arm.com                          &dmaDoneEvent[dmaPendingNum-1], curAddr + dmaBuffer,
47011090Sandreas.sandberg@arm.com                          0, Request::UNCACHEABLE);
47111090Sandreas.sandberg@arm.com        curAddr += dmaSize;
4729646SChris.Emmons@arm.com    }
47311090Sandreas.sandberg@arm.com}
47411090Sandreas.sandberg@arm.com
47511090Sandreas.sandberg@arm.comvoid
47611090Sandreas.sandberg@arm.comPl111::dmaDone()
47711090Sandreas.sandberg@arm.com{
47811090Sandreas.sandberg@arm.com    Tick maxFrameTime = lcdTiming2.cpl * height * clock;
47911090Sandreas.sandberg@arm.com
48011090Sandreas.sandberg@arm.com    --dmaPendingNum;
48111090Sandreas.sandberg@arm.com
48211090Sandreas.sandberg@arm.com    if (maxAddr == curAddr && !dmaPendingNum) {
48311090Sandreas.sandberg@arm.com        if ((curTick() - startTime) > maxFrameTime) {
48411090Sandreas.sandberg@arm.com            warn("CLCD controller buffer underrun, took %d cycles when should"
48511090Sandreas.sandberg@arm.com                 " have taken %d\n", curTick() - startTime, maxFrameTime);
48611090Sandreas.sandberg@arm.com            lcdRis.underflow = 1;
48711090Sandreas.sandberg@arm.com            if (!intEvent.scheduled())
48811090Sandreas.sandberg@arm.com                schedule(intEvent, nextCycle());
48911090Sandreas.sandberg@arm.com        }
49011090Sandreas.sandberg@arm.com
49111090Sandreas.sandberg@arm.com        assert(!readEvent.scheduled());
49211090Sandreas.sandberg@arm.com        if (vncserver)
49311090Sandreas.sandberg@arm.com            vncserver->setDirty();
49411090Sandreas.sandberg@arm.com
49511090Sandreas.sandberg@arm.com        DPRINTF(PL111, "-- write out frame buffer into bmp\n");
49611090Sandreas.sandberg@arm.com
49711897Ssudhanshu.jha@arm.com        assert(bmp);
49811897Ssudhanshu.jha@arm.com        pic->seekp(0);
49911897Ssudhanshu.jha@arm.com        bmp->write(pic);
50011898Ssudhanshu.jha@arm.com
50111898Ssudhanshu.jha@arm.com        DPRINTF(PL111, "-- schedule next dma read event at %d tick \n",
50211898Ssudhanshu.jha@arm.com                maxFrameTime + curTick());
50311898Ssudhanshu.jha@arm.com
50411898Ssudhanshu.jha@arm.com        if (lcdControl.lcden)
50511898Ssudhanshu.jha@arm.com            schedule(readEvent, nextCycle(startTime + maxFrameTime));
50611090Sandreas.sandberg@arm.com    }
50711090Sandreas.sandberg@arm.com
50811090Sandreas.sandberg@arm.com    if (dmaPendingNum > (maxOutstandingDma - waterMark))
50911090Sandreas.sandberg@arm.com        return;
51011090Sandreas.sandberg@arm.com
51111090Sandreas.sandberg@arm.com    if (!fillFifoEvent.scheduled())
51211898Ssudhanshu.jha@arm.com        schedule(fillFifoEvent, nextCycle());
51311898Ssudhanshu.jha@arm.com}
51411898Ssudhanshu.jha@arm.com
51511898Ssudhanshu.jha@arm.com
51611898Ssudhanshu.jha@arm.comTick
51711090Sandreas.sandberg@arm.comPl111::nextCycle()
51811090Sandreas.sandberg@arm.com{
51911090Sandreas.sandberg@arm.com    Tick nextTick = curTick() + clock - 1;
52011090Sandreas.sandberg@arm.com    nextTick -= nextTick%clock;
52111090Sandreas.sandberg@arm.com    return nextTick;
52211090Sandreas.sandberg@arm.com}
52311090Sandreas.sandberg@arm.com
52411090Sandreas.sandberg@arm.comTick
52511090Sandreas.sandberg@arm.comPl111::nextCycle(Tick beginTick)
52611090Sandreas.sandberg@arm.com{
52711090Sandreas.sandberg@arm.com    Tick nextTick = beginTick;
52811090Sandreas.sandberg@arm.com    if (nextTick%clock!=0)
52911090Sandreas.sandberg@arm.com        nextTick = nextTick - (nextTick%clock) + clock;
53011090Sandreas.sandberg@arm.com
53111090Sandreas.sandberg@arm.com    assert(nextTick >= curTick());
53211090Sandreas.sandberg@arm.com    return nextTick;
53311090Sandreas.sandberg@arm.com}
53411090Sandreas.sandberg@arm.com
53511090Sandreas.sandberg@arm.comvoid
53611090Sandreas.sandberg@arm.comPl111::serialize(std::ostream &os)
53711090Sandreas.sandberg@arm.com{
53811090Sandreas.sandberg@arm.com    DPRINTF(PL111, "Serializing ARM PL111\n");
53911090Sandreas.sandberg@arm.com
54011090Sandreas.sandberg@arm.com    uint32_t lcdTiming0_serial = lcdTiming0;
54111090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(lcdTiming0_serial);
54211090Sandreas.sandberg@arm.com
54311090Sandreas.sandberg@arm.com    uint32_t lcdTiming1_serial = lcdTiming1;
54411090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(lcdTiming1_serial);
54511090Sandreas.sandberg@arm.com
54611090Sandreas.sandberg@arm.com    uint32_t lcdTiming2_serial = lcdTiming2;
54711090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(lcdTiming2_serial);
54811090Sandreas.sandberg@arm.com
54911090Sandreas.sandberg@arm.com    uint32_t lcdTiming3_serial = lcdTiming3;
55011090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(lcdTiming3_serial);
55111091Sandreas.sandberg@arm.com
55211090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(lcdUpbase);
55311090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(lcdLpbase);
55411090Sandreas.sandberg@arm.com
55511090Sandreas.sandberg@arm.com    uint32_t lcdControl_serial = lcdControl;
55611090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(lcdControl_serial);
55711090Sandreas.sandberg@arm.com
55811090Sandreas.sandberg@arm.com    uint8_t lcdImsc_serial = lcdImsc;
55911090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(lcdImsc_serial);
56011090Sandreas.sandberg@arm.com
56111090Sandreas.sandberg@arm.com    uint8_t lcdRis_serial = lcdRis;
56211090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(lcdRis_serial);
56311090Sandreas.sandberg@arm.com
56411090Sandreas.sandberg@arm.com    uint8_t lcdMis_serial = lcdMis;
56511090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(lcdMis_serial);
56611090Sandreas.sandberg@arm.com
56711090Sandreas.sandberg@arm.com    SERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
56810839Sandreas.sandberg@arm.com    SERIALIZE_ARRAY(cursorImage, CrsrImageSize);
5699646SChris.Emmons@arm.com
5709646SChris.Emmons@arm.com    SERIALIZE_SCALAR(clcdCrsrCtrl);
5719646SChris.Emmons@arm.com    SERIALIZE_SCALAR(clcdCrsrConfig);
5729939Sdam.sunwoo@arm.com    SERIALIZE_SCALAR(clcdCrsrPalette0);
57311090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(clcdCrsrPalette1);
57411090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(clcdCrsrXY);
57511090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(clcdCrsrClip);
57611090Sandreas.sandberg@arm.com
57711090Sandreas.sandberg@arm.com    uint8_t clcdCrsrImsc_serial = clcdCrsrImsc;
5789646SChris.Emmons@arm.com    SERIALIZE_SCALAR(clcdCrsrImsc_serial);
5799939Sdam.sunwoo@arm.com
58011359Sandreas@sandberg.pp.se    uint8_t clcdCrsrIcr_serial = clcdCrsrIcr;
58111359Sandreas@sandberg.pp.se    SERIALIZE_SCALAR(clcdCrsrIcr_serial);
5829939Sdam.sunwoo@arm.com
5839646SChris.Emmons@arm.com    uint8_t clcdCrsrRis_serial = clcdCrsrRis;
5849646SChris.Emmons@arm.com    SERIALIZE_SCALAR(clcdCrsrRis_serial);
5859646SChris.Emmons@arm.com
58611090Sandreas.sandberg@arm.com    uint8_t clcdCrsrMis_serial = clcdCrsrMis;
5879646SChris.Emmons@arm.com    SERIALIZE_SCALAR(clcdCrsrMis_serial);
58811090Sandreas.sandberg@arm.com
5899646SChris.Emmons@arm.com    SERIALIZE_SCALAR(clock);
59011090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(height);
59111090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(width);
5929646SChris.Emmons@arm.com    SERIALIZE_SCALAR(bytesPerPixel);
59311090Sandreas.sandberg@arm.com
59411090Sandreas.sandberg@arm.com    SERIALIZE_ARRAY(dmaBuffer, height * width);
59511090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(startTime);
59611090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(startAddr);
5979646SChris.Emmons@arm.com    SERIALIZE_SCALAR(maxAddr);
5989646SChris.Emmons@arm.com    SERIALIZE_SCALAR(curAddr);
5999646SChris.Emmons@arm.com    SERIALIZE_SCALAR(waterMark);
60011090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(dmaPendingNum);
60111090Sandreas.sandberg@arm.com
60211090Sandreas.sandberg@arm.com    Tick int_event_time = 0;
60311090Sandreas.sandberg@arm.com    Tick read_event_time = 0;
60411090Sandreas.sandberg@arm.com    Tick fill_fifo_event_time = 0;
60511090Sandreas.sandberg@arm.com
60611090Sandreas.sandberg@arm.com    if (readEvent.scheduled())
60711090Sandreas.sandberg@arm.com        read_event_time = readEvent.when();
60811090Sandreas.sandberg@arm.com    if (fillFifoEvent.scheduled())
6099646SChris.Emmons@arm.com        fill_fifo_event_time = fillFifoEvent.when();
6109646SChris.Emmons@arm.com    if (intEvent.scheduled())
6119646SChris.Emmons@arm.com        int_event_time = intEvent.when();
6129646SChris.Emmons@arm.com
61311090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(read_event_time);
6149646SChris.Emmons@arm.com    SERIALIZE_SCALAR(fill_fifo_event_time);
61511090Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(int_event_time);
6169646SChris.Emmons@arm.com
61711090Sandreas.sandberg@arm.com    vector<Tick> dma_done_event_tick;
61811090Sandreas.sandberg@arm.com    dma_done_event_tick.resize(maxOutstandingDma);
6199646SChris.Emmons@arm.com    for (int x = 0; x < maxOutstandingDma; x++) {
6209646SChris.Emmons@arm.com        dma_done_event_tick[x] = dmaDoneEvent[x].scheduled() ?
6219646SChris.Emmons@arm.com            dmaDoneEvent[x].when() : 0;
62211090Sandreas.sandberg@arm.com    }
6239646SChris.Emmons@arm.com    arrayParamOut(os, "dma_done_event_tick", dma_done_event_tick);
62411090Sandreas.sandberg@arm.com}
6259646SChris.Emmons@arm.com
62611090Sandreas.sandberg@arm.comvoid
62711090Sandreas.sandberg@arm.comPl111::unserialize(Checkpoint *cp, const std::string &section)
6289646SChris.Emmons@arm.com{
6299646SChris.Emmons@arm.com    DPRINTF(PL111, "Unserializing ARM PL111\n");
63011090Sandreas.sandberg@arm.com
63111090Sandreas.sandberg@arm.com    uint32_t lcdTiming0_serial;
6329646SChris.Emmons@arm.com    UNSERIALIZE_SCALAR(lcdTiming0_serial);
63311090Sandreas.sandberg@arm.com    lcdTiming0 = lcdTiming0_serial;
63411090Sandreas.sandberg@arm.com
63511090Sandreas.sandberg@arm.com    uint32_t lcdTiming1_serial;
63611090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(lcdTiming1_serial);
6379646SChris.Emmons@arm.com    lcdTiming1 = lcdTiming1_serial;
6389646SChris.Emmons@arm.com
63911090Sandreas.sandberg@arm.com    uint32_t lcdTiming2_serial;
64011090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(lcdTiming2_serial);
64111090Sandreas.sandberg@arm.com    lcdTiming2 = lcdTiming2_serial;
64211090Sandreas.sandberg@arm.com
64311090Sandreas.sandberg@arm.com    uint32_t lcdTiming3_serial;
64411090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(lcdTiming3_serial);
64511090Sandreas.sandberg@arm.com    lcdTiming3 = lcdTiming3_serial;
64611090Sandreas.sandberg@arm.com
64711090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(lcdUpbase);
64811090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(lcdLpbase);
64911090Sandreas.sandberg@arm.com
65011090Sandreas.sandberg@arm.com    uint32_t lcdControl_serial;
65111090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(lcdControl_serial);
65211090Sandreas.sandberg@arm.com    lcdControl = lcdControl_serial;
65311090Sandreas.sandberg@arm.com
65411090Sandreas.sandberg@arm.com    uint8_t lcdImsc_serial;
65511090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(lcdImsc_serial);
65611090Sandreas.sandberg@arm.com    lcdImsc = lcdImsc_serial;
65711090Sandreas.sandberg@arm.com
65811090Sandreas.sandberg@arm.com    uint8_t lcdRis_serial;
65911090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(lcdRis_serial);
66011090Sandreas.sandberg@arm.com    lcdRis = lcdRis_serial;
66111090Sandreas.sandberg@arm.com
66211090Sandreas.sandberg@arm.com    uint8_t lcdMis_serial;
66311090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(lcdMis_serial);
66411090Sandreas.sandberg@arm.com    lcdMis = lcdMis_serial;
66511090Sandreas.sandberg@arm.com
66611090Sandreas.sandberg@arm.com    UNSERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
66711090Sandreas.sandberg@arm.com    UNSERIALIZE_ARRAY(cursorImage, CrsrImageSize);
66811090Sandreas.sandberg@arm.com
66911090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(clcdCrsrCtrl);
67011090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(clcdCrsrConfig);
67111090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(clcdCrsrPalette0);
67211090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(clcdCrsrPalette1);
67311090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(clcdCrsrXY);
67411090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(clcdCrsrClip);
67511090Sandreas.sandberg@arm.com
67611090Sandreas.sandberg@arm.com    uint8_t clcdCrsrImsc_serial;
67711090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(clcdCrsrImsc_serial);
67811090Sandreas.sandberg@arm.com    clcdCrsrImsc = clcdCrsrImsc_serial;
67911090Sandreas.sandberg@arm.com
68011090Sandreas.sandberg@arm.com    uint8_t clcdCrsrIcr_serial;
68111090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(clcdCrsrIcr_serial);
68211090Sandreas.sandberg@arm.com    clcdCrsrIcr = clcdCrsrIcr_serial;
68311090Sandreas.sandberg@arm.com
68411090Sandreas.sandberg@arm.com    uint8_t clcdCrsrRis_serial;
68511090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(clcdCrsrRis_serial);
68611090Sandreas.sandberg@arm.com    clcdCrsrRis = clcdCrsrRis_serial;
68711090Sandreas.sandberg@arm.com
68811090Sandreas.sandberg@arm.com    uint8_t clcdCrsrMis_serial;
68911090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(clcdCrsrMis_serial);
69011090Sandreas.sandberg@arm.com    clcdCrsrMis = clcdCrsrMis_serial;
69111090Sandreas.sandberg@arm.com
69211090Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(clock);
6939646SChris.Emmons@arm.com    UNSERIALIZE_SCALAR(height);
6949646SChris.Emmons@arm.com    UNSERIALIZE_SCALAR(width);
6959646SChris.Emmons@arm.com    UNSERIALIZE_SCALAR(bytesPerPixel);
6969646SChris.Emmons@arm.com
6979646SChris.Emmons@arm.com    UNSERIALIZE_ARRAY(dmaBuffer, height * width);
698    UNSERIALIZE_SCALAR(startTime);
699    UNSERIALIZE_SCALAR(startAddr);
700    UNSERIALIZE_SCALAR(maxAddr);
701    UNSERIALIZE_SCALAR(curAddr);
702    UNSERIALIZE_SCALAR(waterMark);
703    UNSERIALIZE_SCALAR(dmaPendingNum);
704
705    Tick int_event_time = 0;
706    Tick read_event_time = 0;
707    Tick fill_fifo_event_time = 0;
708
709    UNSERIALIZE_SCALAR(read_event_time);
710    UNSERIALIZE_SCALAR(fill_fifo_event_time);
711    UNSERIALIZE_SCALAR(int_event_time);
712
713    if (int_event_time)
714        schedule(intEvent, int_event_time);
715    if (read_event_time)
716        schedule(readEvent, read_event_time);
717    if (fill_fifo_event_time)
718        schedule(fillFifoEvent, fill_fifo_event_time);
719
720    vector<Tick> dma_done_event_tick;
721    dma_done_event_tick.resize(maxOutstandingDma);
722    arrayParamIn(cp, section, "dma_done_event_tick", dma_done_event_tick);
723    for (int x = 0; x < maxOutstandingDma; x++) {
724        if (dma_done_event_tick[x])
725            schedule(dmaDoneEvent[x], dma_done_event_tick[x]);
726    }
727
728    if (lcdControl.lcdpwr) {
729        updateVideoParams();
730        if (vncserver)
731            vncserver->setDirty();
732    }
733}
734
735void
736Pl111::generateInterrupt()
737{
738    DPRINTF(PL111, "Generate Interrupt: lcdImsc=0x%x lcdRis=0x%x lcdMis=0x%x\n",
739            (uint32_t)lcdImsc, (uint32_t)lcdRis, (uint32_t)lcdMis);
740    lcdMis = lcdImsc & lcdRis;
741
742    if (lcdMis.underflow || lcdMis.baseaddr || lcdMis.vcomp || lcdMis.ahbmaster) {
743        gic->sendInt(intNum);
744        DPRINTF(PL111, " -- Generated\n");
745    }
746}
747
748AddrRangeList
749Pl111::getAddrRanges() const
750{
751    AddrRangeList ranges;
752    ranges.push_back(RangeSize(pioAddr, pioSize));
753    return ranges;
754}
755
756Pl111 *
757Pl111Params::create()
758{
759    return new Pl111(this);
760}
761
762
763