pl111.cc revision 8062
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    Tick int_event_time = 0;
591    Tick read_event_time = 0;
592    Tick fill_fifo_event_time = 0;
593
594    if (readEvent.scheduled())
595        read_event_time = readEvent.when();
596    if (fillFifoEvent.scheduled())
597        fill_fifo_event_time = fillFifoEvent.when();
598    if (intEvent.scheduled())
599        int_event_time = intEvent.when();
600
601    SERIALIZE_SCALAR(read_event_time);
602    SERIALIZE_SCALAR(fill_fifo_event_time);
603    SERIALIZE_SCALAR(int_event_time);
604
605    vector<Tick> dma_done_event_tick;
606    dma_done_event_tick.resize(maxOutstandingDma);
607    for (int x = 0; x < maxOutstandingDma; x++) {
608        dma_done_event_tick[x] = dmaDoneEvent[x].scheduled() ?
609            dmaDoneEvent[x].when() : 0;
610    }
611    arrayParamOut(os, "dma_done_event_tick", dma_done_event_tick);
612}
613
614void
615Pl111::unserialize(Checkpoint *cp, const std::string &section)
616{
617    DPRINTF(PL111, "Unserializing ARM PL111\n");
618
619    uint32_t lcdTiming0_serial;
620    UNSERIALIZE_SCALAR(lcdTiming0_serial);
621    lcdTiming0 = lcdTiming0_serial;
622
623    uint32_t lcdTiming1_serial;
624    UNSERIALIZE_SCALAR(lcdTiming1_serial);
625    lcdTiming1 = lcdTiming1_serial;
626
627    uint32_t lcdTiming2_serial;
628    UNSERIALIZE_SCALAR(lcdTiming2_serial);
629    lcdTiming2 = lcdTiming2_serial;
630
631    uint32_t lcdTiming3_serial;
632    UNSERIALIZE_SCALAR(lcdTiming3_serial);
633    lcdTiming3 = lcdTiming3_serial;
634
635    UNSERIALIZE_SCALAR(lcdUpbase);
636    UNSERIALIZE_SCALAR(lcdLpbase);
637
638    uint32_t lcdControl_serial;
639    UNSERIALIZE_SCALAR(lcdControl_serial);
640    lcdControl = lcdControl_serial;
641
642    uint8_t lcdImsc_serial;
643    UNSERIALIZE_SCALAR(lcdImsc_serial);
644    lcdImsc = lcdImsc_serial;
645
646    uint8_t lcdRis_serial;
647    UNSERIALIZE_SCALAR(lcdRis_serial);
648    lcdRis = lcdRis_serial;
649
650    uint8_t lcdMis_serial;
651    UNSERIALIZE_SCALAR(lcdMis_serial);
652    lcdMis = lcdMis_serial;
653
654    UNSERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
655    UNSERIALIZE_ARRAY(cursorImage, CrsrImageSize);
656
657    UNSERIALIZE_SCALAR(clcdCrsrCtrl);
658    UNSERIALIZE_SCALAR(clcdCrsrConfig);
659    UNSERIALIZE_SCALAR(clcdCrsrPalette0);
660    UNSERIALIZE_SCALAR(clcdCrsrPalette1);
661    UNSERIALIZE_SCALAR(clcdCrsrXY);
662    UNSERIALIZE_SCALAR(clcdCrsrClip);
663
664    uint8_t clcdCrsrImsc_serial;
665    UNSERIALIZE_SCALAR(clcdCrsrImsc_serial);
666    clcdCrsrImsc = clcdCrsrImsc_serial;
667
668    uint8_t clcdCrsrIcr_serial;
669    UNSERIALIZE_SCALAR(clcdCrsrIcr_serial);
670    clcdCrsrIcr = clcdCrsrIcr_serial;
671
672    uint8_t clcdCrsrRis_serial;
673    UNSERIALIZE_SCALAR(clcdCrsrRis_serial);
674    clcdCrsrRis = clcdCrsrRis_serial;
675
676    uint8_t clcdCrsrMis_serial;
677    UNSERIALIZE_SCALAR(clcdCrsrMis_serial);
678    clcdCrsrMis = clcdCrsrMis_serial;
679
680    UNSERIALIZE_SCALAR(clock);
681    UNSERIALIZE_SCALAR(height);
682    UNSERIALIZE_SCALAR(width);
683    UNSERIALIZE_SCALAR(bytesPerPixel);
684
685    UNSERIALIZE_ARRAY(dmaBuffer, height * width);
686    UNSERIALIZE_SCALAR(startTime);
687    UNSERIALIZE_SCALAR(startAddr);
688    UNSERIALIZE_SCALAR(maxAddr);
689    UNSERIALIZE_SCALAR(curAddr);
690    UNSERIALIZE_SCALAR(waterMark);
691    UNSERIALIZE_SCALAR(dmaPendingNum);
692
693    Tick int_event_time = 0;
694    Tick read_event_time = 0;
695    Tick fill_fifo_event_time = 0;
696
697    UNSERIALIZE_SCALAR(read_event_time);
698    UNSERIALIZE_SCALAR(fill_fifo_event_time);
699    UNSERIALIZE_SCALAR(int_event_time);
700
701    if (int_event_time)
702        schedule(intEvent, int_event_time);
703    if (read_event_time)
704        schedule(readEvent, read_event_time);
705    if (fill_fifo_event_time)
706        schedule(fillFifoEvent, fill_fifo_event_time);
707
708    vector<Tick> dma_done_event_tick;
709    dma_done_event_tick.resize(maxOutstandingDma);
710    arrayParamIn(cp, section, "dma_done_event_tick", dma_done_event_tick);
711    for (int x = 0; x < maxOutstandingDma; x++) {
712        if (dma_done_event_tick[x])
713            schedule(dmaDoneEvent[x], dma_done_event_tick[x]);
714    }
715
716    updateVideoParams();
717    if (vncserver)
718        vncserver->setDirty();
719}
720
721void
722Pl111::generateInterrupt()
723{
724    DPRINTF(PL111, "Generate Interrupt: lcdImsc=0x%x lcdRis=0x%x lcdMis=0x%x\n",
725            (uint32_t)lcdImsc, (uint32_t)lcdRis, (uint32_t)lcdMis);
726    lcdMis = lcdImsc & lcdRis;
727
728    if (lcdMis.underflow || lcdMis.baseaddr || lcdMis.vcomp || lcdMis.ahbmaster) {
729        gic->sendInt(intNum);
730        DPRINTF(PL111, " -- Generated\n");
731    }
732}
733
734void
735Pl111::addressRanges(AddrRangeList& range_list)
736{
737    range_list.clear();
738    range_list.push_back(RangeSize(pioAddr, pioSize));
739}
740
741Pl111 *
742Pl111Params::create()
743{
744    return new Pl111(this);
745}
746
747
748