pl111.cc revision 7950:1120b07dd4b0
1/*
2 * Copyright (c) 2010 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: William Wang
38 *          Ali Saidi
39 */
40
41#include "base/bitmap.hh"
42#include "base/output.hh"
43#include "base/trace.hh"
44#include "base/vnc/vncserver.hh"
45#include "dev/arm/amba_device.hh"
46#include "dev/arm/gic.hh"
47#include "dev/arm/pl111.hh"
48#include "mem/packet.hh"
49#include "mem/packet_access.hh"
50
51using namespace AmbaDev;
52
53// initialize clcd registers
54Pl111::Pl111(const Params *p)
55    : AmbaDmaDevice(p), lcdTiming0(0), lcdTiming1(0), lcdTiming2(0),
56      lcdTiming3(0), lcdUpbase(0), lcdLpbase(0), lcdControl(0), lcdImsc(0),
57      lcdRis(0), lcdMis(0),
58      clcdCrsrCtrl(0), clcdCrsrConfig(0), clcdCrsrPalette0(0),
59      clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0),
60      clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0), clock(p->clock),
61      vncserver(p->vnc), bmp(NULL), width(LcdMaxWidth), height(LcdMaxHeight),
62      bytesPerPixel(4), startTime(0), startAddr(0), maxAddr(0), curAddr(0),
63      waterMark(0), dmaPendingNum(0), readEvent(this), fillFifoEvent(this),
64      dmaDoneEvent(maxOutstandingDma, this), intEvent(this)
65{
66    pioSize = 0xFFFF;
67
68    pic = simout.create("framebuffer.bmp", true);
69
70    dmaBuffer = new uint8_t[LcdMaxWidth * LcdMaxHeight * sizeof(uint32_t)];
71
72    memset(lcdPalette, 0, sizeof(lcdPalette));
73    memset(cursorImage, 0, sizeof(cursorImage));
74    memset(dmaBuffer, 0, sizeof(dmaBuffer));
75
76    if (vncserver)
77        vncserver->setFramebufferAddr(dmaBuffer);
78}
79
80// read registers and frame buffer
81Tick
82Pl111::read(PacketPtr pkt)
83{
84    // use a temporary data since the LCD registers are read/written with
85    // different size operations
86
87    uint32_t data = 0;
88
89    assert(pkt->getAddr() >= pioAddr &&
90           pkt->getAddr() < pioAddr + pioSize);
91
92    Addr daddr = pkt->getAddr() - pioAddr;
93    pkt->allocate();
94
95    DPRINTF(PL111, " read register %#x size=%d\n", daddr, pkt->getSize());
96
97    switch (daddr) {
98      case LcdTiming0:
99        data = lcdTiming0;
100        break;
101      case LcdTiming1:
102        data = lcdTiming1;
103        break;
104      case LcdTiming2:
105        data = lcdTiming2;
106        break;
107      case LcdTiming3:
108        data = lcdTiming3;
109        break;
110      case LcdUpBase:
111        data = lcdUpbase;
112        break;
113      case LcdLpBase:
114        data = lcdLpbase;
115        break;
116      case LcdControl:
117        data = lcdControl;
118        break;
119      case LcdImsc:
120        data = lcdImsc;
121        break;
122      case LcdRis:
123        data = lcdRis;
124        break;
125      case LcdMis:
126        data = lcdMis;
127        break;
128      case LcdIcr:
129        panic("LCD register at offset %#x is Write-Only\n", daddr);
130        break;
131      case LcdUpCurr:
132        data = curAddr;
133        break;
134      case LcdLpCurr:
135        data = curAddr;
136        break;
137      case ClcdCrsrCtrl:
138        data = clcdCrsrCtrl;
139        break;
140      case ClcdCrsrConfig:
141        data = clcdCrsrConfig;
142        break;
143      case ClcdCrsrPalette0:
144        data = clcdCrsrPalette0;
145        break;
146      case ClcdCrsrPalette1:
147        data = clcdCrsrPalette1;
148        break;
149      case ClcdCrsrXY:
150        data = clcdCrsrXY;
151        break;
152      case ClcdCrsrClip:
153        data = clcdCrsrClip;
154        break;
155      case ClcdCrsrImsc:
156        data = clcdCrsrImsc;
157        break;
158      case ClcdCrsrIcr:
159        panic("CLCD register at offset %#x is Write-Only\n", daddr);
160        break;
161      case ClcdCrsrRis:
162        data = clcdCrsrRis;
163        break;
164      case ClcdCrsrMis:
165        data = clcdCrsrMis;
166        break;
167      default:
168        if (AmbaDev::readId(pkt, AMBA_ID, pioAddr)) {
169            // Hack for variable size accesses
170            data = pkt->get<uint32_t>();
171            break;
172        } else if (daddr >= CrsrImage && daddr <= 0xBFC) {
173            // CURSOR IMAGE
174            int index;
175            index = (daddr - CrsrImage) >> 2;
176            data= cursorImage[index];
177            break;
178        } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
179            // LCD Palette
180            int index;
181            index = (daddr - LcdPalette) >> 2;
182            data = lcdPalette[index];
183            break;
184        } else {
185            panic("Tried to read CLCD register at offset %#x that \
186                       doesn't exist\n", daddr);
187            break;
188        }
189    }
190
191    switch(pkt->getSize()) {
192      case 1:
193        pkt->set<uint8_t>(data);
194        break;
195      case 2:
196        pkt->set<uint16_t>(data);
197        break;
198      case 4:
199        pkt->set<uint32_t>(data);
200        break;
201      default:
202        panic("CLCD controller read size too big?\n");
203        break;
204    }
205
206    pkt->makeAtomicResponse();
207    return pioDelay;
208}
209
210// write registers and frame buffer
211Tick
212Pl111::write(PacketPtr pkt)
213{
214    // use a temporary data since the LCD registers are read/written with
215    // different size operations
216    //
217    uint32_t data = 0;
218
219    switch(pkt->getSize()) {
220      case 1:
221        data = pkt->get<uint8_t>();
222        break;
223      case 2:
224        data = pkt->get<uint16_t>();
225        break;
226      case 4:
227        data = pkt->get<uint32_t>();
228        break;
229      default:
230        panic("PL111 CLCD controller write size too big?\n");
231        break;
232    }
233
234    assert(pkt->getAddr() >= pioAddr &&
235           pkt->getAddr() < pioAddr + pioSize);
236
237    Addr daddr = pkt->getAddr() - pioAddr;
238
239    DPRINTF(PL111, " write register %#x value %#x size=%d\n", daddr,
240            pkt->get<uint8_t>(), pkt->getSize());
241
242    switch (daddr) {
243      case LcdTiming0:
244        lcdTiming0 = data;
245        // width = 16 * (PPL+1)
246        width = (lcdTiming0.ppl + 1) << 4;
247        break;
248      case LcdTiming1:
249        lcdTiming1 = data;
250        // height = LPP + 1
251        height = (lcdTiming1.lpp) + 1;
252        break;
253      case LcdTiming2:
254        lcdTiming2 = data;
255        break;
256      case LcdTiming3:
257        lcdTiming3 = data;
258        break;
259      case LcdUpBase:
260        lcdUpbase = data;
261        DPRINTF(PL111, "####### Upper panel base set to: %#x #######\n", lcdUpbase);
262        break;
263      case LcdLpBase:
264        warn("LCD dual screen mode not supported\n");
265        lcdLpbase = data;
266        DPRINTF(PL111, "###### Lower panel base set to: %#x #######\n", lcdLpbase);
267        break;
268      case LcdControl:
269        int old_lcdpwr;
270        old_lcdpwr = lcdControl.lcdpwr;
271        lcdControl = data;
272
273        DPRINTF(PL111, "LCD power is:%d\n", lcdControl.lcdpwr);
274
275        // LCD power enable
276        if (lcdControl.lcdpwr && !old_lcdpwr) {
277            updateVideoParams();
278            DPRINTF(PL111, " lcd size: height %d width %d\n", height, width);
279            waterMark = lcdControl.watermark ? 8 : 4;
280            startDma();
281        }
282        break;
283      case LcdImsc:
284        lcdImsc = data;
285        if (lcdImsc.vcomp)
286            panic("Interrupting on vcomp not supported\n");
287
288        lcdMis = lcdImsc & lcdRis;
289
290        if (!lcdMis)
291            gic->clearInt(intNum);
292
293         break;
294      case LcdRis:
295        panic("LCD register at offset %#x is Read-Only\n", daddr);
296        break;
297      case LcdMis:
298        panic("LCD register at offset %#x is Read-Only\n", daddr);
299        break;
300      case LcdIcr:
301        lcdRis = lcdRis & ~data;
302        lcdMis = lcdImsc & lcdRis;
303
304        if (!lcdMis)
305            gic->clearInt(intNum);
306
307        break;
308      case LcdUpCurr:
309        panic("LCD register at offset %#x is Read-Only\n", daddr);
310        break;
311      case LcdLpCurr:
312        panic("LCD register at offset %#x is Read-Only\n", daddr);
313        break;
314      case ClcdCrsrCtrl:
315        clcdCrsrCtrl = data;
316        break;
317      case ClcdCrsrConfig:
318        clcdCrsrConfig = data;
319        break;
320      case ClcdCrsrPalette0:
321        clcdCrsrPalette0 = data;
322        break;
323      case ClcdCrsrPalette1:
324        clcdCrsrPalette1 = data;
325        break;
326      case ClcdCrsrXY:
327        clcdCrsrXY = data;
328        break;
329      case ClcdCrsrClip:
330        clcdCrsrClip = data;
331        break;
332      case ClcdCrsrImsc:
333        clcdCrsrImsc = data;
334        break;
335      case ClcdCrsrIcr:
336        clcdCrsrIcr = data;
337        break;
338      case ClcdCrsrRis:
339        panic("CLCD register at offset %#x is Read-Only\n", daddr);
340        break;
341      case ClcdCrsrMis:
342        panic("CLCD register at offset %#x is Read-Only\n", daddr);
343        break;
344      default:
345        if (daddr >= CrsrImage && daddr <= 0xBFC) {
346            // CURSOR IMAGE
347            int index;
348            index = (daddr - CrsrImage) >> 2;
349            cursorImage[index] = data;
350            break;
351        } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
352            // LCD Palette
353            int index;
354            index = (daddr - LcdPalette) >> 2;
355            lcdPalette[index] = data;
356            break;
357        } else {
358            panic("Tried to write PL111 register at offset %#x that \
359                       doesn't exist\n", daddr);
360            break;
361        }
362    }
363
364    pkt->makeAtomicResponse();
365    return pioDelay;
366}
367
368void
369Pl111::updateVideoParams()
370{
371        if (lcdControl.lcdbpp == bpp24) {
372            bytesPerPixel = 4;
373        } else if (lcdControl.lcdbpp == bpp16m565) {
374            bytesPerPixel = 2;
375        }
376
377        if (vncserver) {
378            if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr)
379                vncserver->setFrameBufferParams(VideoConvert::bgr8888, width,
380                       height);
381            else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr)
382                vncserver->setFrameBufferParams(VideoConvert::rgb8888, width,
383                       height);
384            else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr)
385                vncserver->setFrameBufferParams(VideoConvert::bgr565, width,
386                       height);
387            else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr)
388                vncserver->setFrameBufferParams(VideoConvert::rgb565, width,
389                       height);
390            else
391                panic("Unimplemented video mode\n");
392        }
393
394        if (bmp)
395            delete bmp;
396
397        if (lcdControl.lcdbpp == bpp24 && lcdControl.bgr)
398            bmp = new Bitmap(VideoConvert::bgr8888, width, height, dmaBuffer);
399        else if (lcdControl.lcdbpp == bpp24 && !lcdControl.bgr)
400            bmp = new Bitmap(VideoConvert::rgb8888, width, height, dmaBuffer);
401        else if (lcdControl.lcdbpp == bpp16m565 && lcdControl.bgr)
402            bmp = new Bitmap(VideoConvert::bgr565, width, height, dmaBuffer);
403        else if (lcdControl.lcdbpp == bpp16m565 && !lcdControl.bgr)
404            bmp = new Bitmap(VideoConvert::rgb565, width, height, dmaBuffer);
405        else
406            panic("Unimplemented video mode\n");
407}
408
409void
410Pl111::startDma()
411{
412    if (dmaPendingNum != 0 || readEvent.scheduled())
413        return;
414    readFramebuffer();
415}
416
417void
418Pl111::readFramebuffer()
419{
420    // initialization for dma read from frame buffer to dma buffer
421    uint32_t length = height * width;
422    if (startAddr != lcdUpbase)
423        startAddr = lcdUpbase;
424
425    // Updating base address, interrupt if we're supposed to
426    lcdRis.baseaddr = 1;
427    if (!intEvent.scheduled())
428        schedule(intEvent, nextCycle());
429
430    curAddr = 0;
431    startTime = curTick();
432
433    maxAddr = static_cast<Addr>(length * bytesPerPixel);
434
435    DPRINTF(PL111, " lcd frame buffer size of %d bytes \n", maxAddr);
436
437    dmaPendingNum = 0;
438
439    fillFifo();
440}
441
442void
443Pl111::fillFifo()
444{
445    while ((dmaPendingNum < maxOutstandingDma) && (maxAddr >= curAddr + dmaSize )) {
446        // concurrent dma reads need different dma done events
447        // due to assertion in scheduling state
448        ++dmaPendingNum;
449
450        assert(!dmaDoneEvent[dmaPendingNum-1].scheduled());
451
452        // We use a uncachable request here because the requests from the CPU
453        // will be uncacheable as well. If we have uncacheable and cacheable
454        // requests in the memory system for the same address it won't be
455        // pleased
456        dmaPort->dmaAction(MemCmd::ReadReq, curAddr + startAddr, dmaSize,
457                &dmaDoneEvent[dmaPendingNum-1], curAddr + dmaBuffer, 0,
458                Request::UNCACHEABLE);
459        curAddr += dmaSize;
460    }
461}
462
463void
464Pl111::dmaDone()
465{
466    Tick maxFrameTime = lcdTiming2.cpl * height * clock;
467
468    --dmaPendingNum;
469
470    if (maxAddr == curAddr && !dmaPendingNum) {
471        if ((curTick() - startTime) > maxFrameTime) {
472            warn("CLCD controller buffer underrun, took %d cycles when should"
473                 " have taken %d\n", curTick() - startTime, maxFrameTime);
474            lcdRis.underflow = 1;
475            if (!intEvent.scheduled())
476                schedule(intEvent, nextCycle());
477        }
478
479        assert(!readEvent.scheduled());
480        if (vncserver)
481            vncserver->setDirty();
482
483        DPRINTF(PL111, "-- write out frame buffer into bmp\n");
484
485        assert(bmp);
486        pic->seekp(0);
487        bmp->write(pic);
488
489        DPRINTF(PL111, "-- schedule next dma read event at %d tick \n",
490                maxFrameTime + curTick());
491
492        if (lcdControl.lcden)
493            schedule(readEvent, nextCycle(startTime + maxFrameTime));
494    }
495
496    if (dmaPendingNum > (maxOutstandingDma - waterMark))
497        return;
498
499    if (!fillFifoEvent.scheduled())
500        schedule(fillFifoEvent, nextCycle());
501}
502
503
504Tick
505Pl111::nextCycle()
506{
507    Tick nextTick = curTick() + clock - 1;
508    nextTick -= nextTick%clock;
509    return nextTick;
510}
511
512Tick
513Pl111::nextCycle(Tick beginTick)
514{
515    Tick nextTick = beginTick;
516    if (nextTick%clock!=0)
517        nextTick = nextTick - (nextTick%clock) + clock;
518
519    assert(nextTick >= curTick());
520    return nextTick;
521}
522
523void
524Pl111::serialize(std::ostream &os)
525{
526    DPRINTF(PL111, "Serializing ARM PL111\n");
527
528    uint32_t lcdTiming0_serial = lcdTiming0;
529    SERIALIZE_SCALAR(lcdTiming0_serial);
530
531    uint32_t lcdTiming1_serial = lcdTiming1;
532    SERIALIZE_SCALAR(lcdTiming1_serial);
533
534    uint32_t lcdTiming2_serial = lcdTiming2;
535    SERIALIZE_SCALAR(lcdTiming2_serial);
536
537    uint32_t lcdTiming3_serial = lcdTiming3;
538    SERIALIZE_SCALAR(lcdTiming3_serial);
539
540    SERIALIZE_SCALAR(lcdUpbase);
541    SERIALIZE_SCALAR(lcdLpbase);
542
543    uint32_t lcdControl_serial = lcdControl;
544    SERIALIZE_SCALAR(lcdControl_serial);
545
546    uint8_t lcdImsc_serial = lcdImsc;
547    SERIALIZE_SCALAR(lcdImsc_serial);
548
549    uint8_t lcdRis_serial = lcdRis;
550    SERIALIZE_SCALAR(lcdRis_serial);
551
552    uint8_t lcdMis_serial = lcdMis;
553    SERIALIZE_SCALAR(lcdMis_serial);
554
555    SERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
556    SERIALIZE_ARRAY(cursorImage, CrsrImageSize);
557
558    SERIALIZE_SCALAR(clcdCrsrCtrl);
559    SERIALIZE_SCALAR(clcdCrsrConfig);
560    SERIALIZE_SCALAR(clcdCrsrPalette0);
561    SERIALIZE_SCALAR(clcdCrsrPalette1);
562    SERIALIZE_SCALAR(clcdCrsrXY);
563    SERIALIZE_SCALAR(clcdCrsrClip);
564
565    uint8_t clcdCrsrImsc_serial = clcdCrsrImsc;
566    SERIALIZE_SCALAR(clcdCrsrImsc_serial);
567
568    uint8_t clcdCrsrIcr_serial = clcdCrsrIcr;
569    SERIALIZE_SCALAR(clcdCrsrIcr_serial);
570
571    uint8_t clcdCrsrRis_serial = clcdCrsrRis;
572    SERIALIZE_SCALAR(clcdCrsrRis_serial);
573
574    uint8_t clcdCrsrMis_serial = clcdCrsrMis;
575    SERIALIZE_SCALAR(clcdCrsrMis_serial);
576
577    SERIALIZE_SCALAR(clock);
578    SERIALIZE_SCALAR(height);
579    SERIALIZE_SCALAR(width);
580    SERIALIZE_SCALAR(bytesPerPixel);
581
582    SERIALIZE_ARRAY(dmaBuffer, height * width);
583    SERIALIZE_SCALAR(startTime);
584    SERIALIZE_SCALAR(startAddr);
585    SERIALIZE_SCALAR(maxAddr);
586    SERIALIZE_SCALAR(curAddr);
587    SERIALIZE_SCALAR(waterMark);
588    SERIALIZE_SCALAR(dmaPendingNum);
589}
590
591void
592Pl111::unserialize(Checkpoint *cp, const std::string &section)
593{
594    DPRINTF(PL111, "Unserializing ARM PL111\n");
595
596    uint32_t lcdTiming0_serial;
597    UNSERIALIZE_SCALAR(lcdTiming0_serial);
598    lcdTiming0 = lcdTiming0_serial;
599
600    uint32_t lcdTiming1_serial;
601    UNSERIALIZE_SCALAR(lcdTiming1_serial);
602    lcdTiming1 = lcdTiming1_serial;
603
604    uint32_t lcdTiming2_serial;
605    UNSERIALIZE_SCALAR(lcdTiming2_serial);
606    lcdTiming2 = lcdTiming2_serial;
607
608    uint32_t lcdTiming3_serial;
609    UNSERIALIZE_SCALAR(lcdTiming3_serial);
610    lcdTiming3 = lcdTiming3_serial;
611
612    UNSERIALIZE_SCALAR(lcdUpbase);
613    UNSERIALIZE_SCALAR(lcdLpbase);
614
615    uint32_t lcdControl_serial;
616    UNSERIALIZE_SCALAR(lcdControl_serial);
617    lcdControl = lcdControl_serial;
618
619    uint8_t lcdImsc_serial;
620    UNSERIALIZE_SCALAR(lcdImsc_serial);
621    lcdImsc = lcdImsc_serial;
622
623    uint8_t lcdRis_serial;
624    UNSERIALIZE_SCALAR(lcdRis_serial);
625    lcdRis = lcdRis_serial;
626
627    uint8_t lcdMis_serial;
628    UNSERIALIZE_SCALAR(lcdMis_serial);
629    lcdMis = lcdMis_serial;
630
631    UNSERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
632    UNSERIALIZE_ARRAY(cursorImage, CrsrImageSize);
633
634    UNSERIALIZE_SCALAR(clcdCrsrCtrl);
635    UNSERIALIZE_SCALAR(clcdCrsrConfig);
636    UNSERIALIZE_SCALAR(clcdCrsrPalette0);
637    UNSERIALIZE_SCALAR(clcdCrsrPalette1);
638    UNSERIALIZE_SCALAR(clcdCrsrXY);
639    UNSERIALIZE_SCALAR(clcdCrsrClip);
640
641    uint8_t clcdCrsrImsc_serial;
642    UNSERIALIZE_SCALAR(clcdCrsrImsc_serial);
643    clcdCrsrImsc = clcdCrsrImsc_serial;
644
645    uint8_t clcdCrsrIcr_serial;
646    UNSERIALIZE_SCALAR(clcdCrsrIcr_serial);
647    clcdCrsrIcr = clcdCrsrIcr_serial;
648
649    uint8_t clcdCrsrRis_serial;
650    UNSERIALIZE_SCALAR(clcdCrsrRis_serial);
651    clcdCrsrRis = clcdCrsrRis_serial;
652
653    uint8_t clcdCrsrMis_serial;
654    UNSERIALIZE_SCALAR(clcdCrsrMis_serial);
655    clcdCrsrMis = clcdCrsrMis_serial;
656
657    UNSERIALIZE_SCALAR(clock);
658    UNSERIALIZE_SCALAR(height);
659    UNSERIALIZE_SCALAR(width);
660    UNSERIALIZE_SCALAR(bytesPerPixel);
661
662    UNSERIALIZE_ARRAY(dmaBuffer, height * width);
663    UNSERIALIZE_SCALAR(startTime);
664    UNSERIALIZE_SCALAR(startAddr);
665    UNSERIALIZE_SCALAR(maxAddr);
666    UNSERIALIZE_SCALAR(curAddr);
667    UNSERIALIZE_SCALAR(waterMark);
668    UNSERIALIZE_SCALAR(dmaPendingNum);
669
670    updateVideoParams();
671    if (vncserver)
672        vncserver->setDirty();
673}
674
675void
676Pl111::generateInterrupt()
677{
678    DPRINTF(PL111, "Generate Interrupt: lcdImsc=0x%x lcdRis=0x%x lcdMis=0x%x\n",
679            (uint32_t)lcdImsc, (uint32_t)lcdRis, (uint32_t)lcdMis);
680    lcdMis = lcdImsc & lcdRis;
681
682    if (lcdMis.underflow || lcdMis.baseaddr || lcdMis.vcomp || lcdMis.ahbmaster) {
683        gic->sendInt(intNum);
684        DPRINTF(PL111, " -- Generated\n");
685    }
686}
687
688void
689Pl111::addressRanges(AddrRangeList& range_list)
690{
691    range_list.clear();
692    range_list.push_back(RangeSize(pioAddr, pioSize));
693}
694
695Pl111 *
696Pl111Params::create()
697{
698    return new Pl111(this);
699}
700
701
702