Deleted Added
sdiff udiff text old ( 11359:b0b976a1ceda ) new ( 11793:ef606668d247 )
full compact
1/*
2 * Copyright (c) 2010-2012, 2015 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 "dev/arm/pl111.hh"
42
43#include "base/output.hh"
44#include "base/trace.hh"
45#include "base/vnc/vncinput.hh"
46#include "debug/PL111.hh"
47#include "debug/Uart.hh"
48#include "dev/arm/amba_device.hh"
49#include "dev/arm/base_gic.hh"
50#include "mem/packet.hh"
51#include "mem/packet_access.hh"
52#include "sim/system.hh"
53
54// clang complains about std::set being overloaded with Packet::set if
55// we open up the entire namespace std
56using std::vector;
57
58// initialize clcd registers
59Pl111::Pl111(const Params *p)
60 : AmbaDmaDevice(p), lcdTiming0(0), lcdTiming1(0), lcdTiming2(0),
61 lcdTiming3(0), lcdUpbase(0), lcdLpbase(0), lcdControl(0), lcdImsc(0),
62 lcdRis(0), lcdMis(0),
63 clcdCrsrCtrl(0), clcdCrsrConfig(0), clcdCrsrPalette0(0),
64 clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0),
65 clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0),
66 pixelClock(p->pixel_clock),
67 converter(PixelConverter::rgba8888_le), fb(LcdMaxWidth, LcdMaxHeight),
68 vnc(p->vnc), bmp(&fb), pic(NULL),
69 width(LcdMaxWidth), height(LcdMaxHeight),
70 bytesPerPixel(4), startTime(0), startAddr(0), maxAddr(0), curAddr(0),
71 waterMark(0), dmaPendingNum(0), readEvent(this), fillFifoEvent(this),
72 dmaDoneEventAll(maxOutstandingDma, this),
73 dmaDoneEventFree(maxOutstandingDma),
74 intEvent(this), enableCapture(p->enable_capture)
75{
76 pioSize = 0xFFFF;
77
78 dmaBuffer = new uint8_t[buffer_size];
79
80 memset(lcdPalette, 0, sizeof(lcdPalette));
81 memset(cursorImage, 0, sizeof(cursorImage));
82 memset(dmaBuffer, 0, buffer_size);
83
84 for (int i = 0; i < maxOutstandingDma; ++i)
85 dmaDoneEventFree[i] = &dmaDoneEventAll[i];
86
87 if (vnc)
88 vnc->setFrameBuffer(&fb);
89}
90
91Pl111::~Pl111()
92{
93 delete[] dmaBuffer;
94}
95
96// read registers and frame buffer
97Tick
98Pl111::read(PacketPtr pkt)
99{
100 // use a temporary data since the LCD registers are read/written with
101 // different size operations
102
103 uint32_t data = 0;
104
105 assert(pkt->getAddr() >= pioAddr &&
106 pkt->getAddr() < pioAddr + pioSize);
107
108 Addr daddr = pkt->getAddr() - pioAddr;
109
110 DPRINTF(PL111, " read register %#x size=%d\n", daddr, pkt->getSize());
111
112 switch (daddr) {
113 case LcdTiming0:
114 data = lcdTiming0;
115 break;
116 case LcdTiming1:
117 data = lcdTiming1;
118 break;
119 case LcdTiming2:
120 data = lcdTiming2;
121 break;
122 case LcdTiming3:
123 data = lcdTiming3;
124 break;
125 case LcdUpBase:
126 data = lcdUpbase;
127 break;
128 case LcdLpBase:
129 data = lcdLpbase;
130 break;
131 case LcdControl:
132 data = lcdControl;
133 break;
134 case LcdImsc:
135 data = lcdImsc;
136 break;
137 case LcdRis:
138 data = lcdRis;
139 break;
140 case LcdMis:
141 data = lcdMis;
142 break;
143 case LcdIcr:
144 panic("LCD register at offset %#x is Write-Only\n", daddr);
145 break;
146 case LcdUpCurr:
147 data = curAddr;
148 break;
149 case LcdLpCurr:
150 data = curAddr;
151 break;
152 case ClcdCrsrCtrl:
153 data = clcdCrsrCtrl;
154 break;
155 case ClcdCrsrConfig:
156 data = clcdCrsrConfig;
157 break;
158 case ClcdCrsrPalette0:
159 data = clcdCrsrPalette0;
160 break;
161 case ClcdCrsrPalette1:
162 data = clcdCrsrPalette1;
163 break;
164 case ClcdCrsrXY:
165 data = clcdCrsrXY;
166 break;
167 case ClcdCrsrClip:
168 data = clcdCrsrClip;
169 break;
170 case ClcdCrsrImsc:
171 data = clcdCrsrImsc;
172 break;
173 case ClcdCrsrIcr:
174 panic("CLCD register at offset %#x is Write-Only\n", daddr);
175 break;
176 case ClcdCrsrRis:
177 data = clcdCrsrRis;
178 break;
179 case ClcdCrsrMis:
180 data = clcdCrsrMis;
181 break;
182 default:
183 if (readId(pkt, AMBA_ID, pioAddr)) {
184 // Hack for variable size accesses
185 data = pkt->get<uint32_t>();
186 break;
187 } else if (daddr >= CrsrImage && daddr <= 0xBFC) {
188 // CURSOR IMAGE
189 int index;
190 index = (daddr - CrsrImage) >> 2;
191 data= cursorImage[index];
192 break;
193 } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
194 // LCD Palette
195 int index;
196 index = (daddr - LcdPalette) >> 2;
197 data = lcdPalette[index];
198 break;
199 } else {
200 panic("Tried to read CLCD register at offset %#x that "
201 "doesn't exist\n", daddr);
202 break;
203 }
204 }
205
206 switch(pkt->getSize()) {
207 case 1:
208 pkt->set<uint8_t>(data);
209 break;
210 case 2:
211 pkt->set<uint16_t>(data);
212 break;
213 case 4:
214 pkt->set<uint32_t>(data);
215 break;
216 default:
217 panic("CLCD controller read size too big?\n");
218 break;
219 }
220
221 pkt->makeAtomicResponse();
222 return pioDelay;
223}
224
225// write registers and frame buffer
226Tick
227Pl111::write(PacketPtr pkt)
228{
229 // use a temporary data since the LCD registers are read/written with
230 // different size operations
231 //
232 uint32_t data = 0;
233
234 switch(pkt->getSize()) {
235 case 1:
236 data = pkt->get<uint8_t>();
237 break;
238 case 2:
239 data = pkt->get<uint16_t>();
240 break;
241 case 4:
242 data = pkt->get<uint32_t>();
243 break;
244 default:
245 panic("PL111 CLCD controller write size too big?\n");
246 break;
247 }
248
249 assert(pkt->getAddr() >= pioAddr &&
250 pkt->getAddr() < pioAddr + pioSize);
251
252 Addr daddr = pkt->getAddr() - pioAddr;
253
254 DPRINTF(PL111, " write register %#x value %#x size=%d\n", daddr,
255 pkt->get<uint8_t>(), pkt->getSize());
256
257 switch (daddr) {
258 case LcdTiming0:
259 lcdTiming0 = data;
260 // width = 16 * (PPL+1)
261 width = (lcdTiming0.ppl + 1) << 4;
262 break;
263 case LcdTiming1:
264 lcdTiming1 = data;
265 // height = LPP + 1
266 height = (lcdTiming1.lpp) + 1;
267 break;
268 case LcdTiming2:
269 lcdTiming2 = data;
270 break;
271 case LcdTiming3:
272 lcdTiming3 = data;
273 break;
274 case LcdUpBase:
275 lcdUpbase = data;
276 DPRINTF(PL111, "####### Upper panel base set to: %#x #######\n", lcdUpbase);
277 break;
278 case LcdLpBase:
279 warn_once("LCD dual screen mode not supported\n");
280 lcdLpbase = data;
281 DPRINTF(PL111, "###### Lower panel base set to: %#x #######\n", lcdLpbase);
282 break;
283 case LcdControl:
284 int old_lcdpwr;
285 old_lcdpwr = lcdControl.lcdpwr;
286 lcdControl = data;
287
288 DPRINTF(PL111, "LCD power is:%d\n", lcdControl.lcdpwr);
289
290 // LCD power enable
291 if (lcdControl.lcdpwr && !old_lcdpwr) {
292 updateVideoParams();
293 DPRINTF(PL111, " lcd size: height %d width %d\n", height, width);
294 waterMark = lcdControl.watermark ? 8 : 4;
295 startDma();
296 }
297 break;
298 case LcdImsc:
299 lcdImsc = data;
300 if (lcdImsc.vcomp)
301 panic("Interrupting on vcomp not supported\n");
302
303 lcdMis = lcdImsc & lcdRis;
304
305 if (!lcdMis)
306 gic->clearInt(intNum);
307
308 break;
309 case LcdRis:
310 panic("LCD register at offset %#x is Read-Only\n", daddr);
311 break;
312 case LcdMis:
313 panic("LCD register at offset %#x is Read-Only\n", daddr);
314 break;
315 case LcdIcr:
316 lcdRis = lcdRis & ~data;
317 lcdMis = lcdImsc & lcdRis;
318
319 if (!lcdMis)
320 gic->clearInt(intNum);
321
322 break;
323 case LcdUpCurr:
324 panic("LCD register at offset %#x is Read-Only\n", daddr);
325 break;
326 case LcdLpCurr:
327 panic("LCD register at offset %#x is Read-Only\n", daddr);
328 break;
329 case ClcdCrsrCtrl:
330 clcdCrsrCtrl = data;
331 break;
332 case ClcdCrsrConfig:
333 clcdCrsrConfig = data;
334 break;
335 case ClcdCrsrPalette0:
336 clcdCrsrPalette0 = data;
337 break;
338 case ClcdCrsrPalette1:
339 clcdCrsrPalette1 = data;
340 break;
341 case ClcdCrsrXY:
342 clcdCrsrXY = data;
343 break;
344 case ClcdCrsrClip:
345 clcdCrsrClip = data;
346 break;
347 case ClcdCrsrImsc:
348 clcdCrsrImsc = data;
349 break;
350 case ClcdCrsrIcr:
351 clcdCrsrIcr = data;
352 break;
353 case ClcdCrsrRis:
354 panic("CLCD register at offset %#x is Read-Only\n", daddr);
355 break;
356 case ClcdCrsrMis:
357 panic("CLCD register at offset %#x is Read-Only\n", daddr);
358 break;
359 default:
360 if (daddr >= CrsrImage && daddr <= 0xBFC) {
361 // CURSOR IMAGE
362 int index;
363 index = (daddr - CrsrImage) >> 2;
364 cursorImage[index] = data;
365 break;
366 } else if (daddr >= LcdPalette && daddr <= 0x3FC) {
367 // LCD Palette
368 int index;
369 index = (daddr - LcdPalette) >> 2;
370 lcdPalette[index] = data;
371 break;
372 } else {
373 panic("Tried to write PL111 register at offset %#x that "
374 "doesn't exist\n", daddr);
375 break;
376 }
377 }
378
379 pkt->makeAtomicResponse();
380 return pioDelay;
381}
382
383PixelConverter
384Pl111::pixelConverter() const
385{
386 unsigned rw, gw, bw;
387 unsigned offsets[3];
388
389 switch (lcdControl.lcdbpp) {
390 case bpp24:
391 rw = gw = bw = 8;
392 offsets[0] = 0;
393 offsets[1] = 8;
394 offsets[2] = 16;
395 break;
396
397 case bpp16m565:
398 rw = 5;
399 gw = 6;
400 bw = 5;
401 offsets[0] = 0;
402 offsets[1] = 5;
403 offsets[2] = 11;
404 break;
405
406 default:
407 panic("Unimplemented video mode\n");
408 }
409
410 if (lcdControl.bgr) {
411 return PixelConverter(
412 bytesPerPixel,
413 offsets[2], offsets[1], offsets[0],
414 rw, gw, bw,
415 LittleEndianByteOrder);
416 } else {
417 return PixelConverter(
418 bytesPerPixel,
419 offsets[0], offsets[1], offsets[2],
420 rw, gw, bw,
421 LittleEndianByteOrder);
422 }
423}
424
425void
426Pl111::updateVideoParams()
427{
428 if (lcdControl.lcdbpp == bpp24) {
429 bytesPerPixel = 4;
430 } else if (lcdControl.lcdbpp == bpp16m565) {
431 bytesPerPixel = 2;
432 }
433
434 fb.resize(width, height);
435 converter = pixelConverter();
436
437 // Workaround configuration bugs where multiple display
438 // controllers are attached to the same VNC server by reattaching
439 // enabled devices. This isn't ideal, but works as long as only
440 // one display controller is active at a time.
441 if (lcdControl.lcdpwr && vnc)
442 vnc->setFrameBuffer(&fb);
443}
444
445void
446Pl111::startDma()
447{
448 if (dmaPendingNum != 0 || readEvent.scheduled())
449 return;
450 readFramebuffer();
451}
452
453void
454Pl111::readFramebuffer()
455{
456 // initialization for dma read from frame buffer to dma buffer
457 uint32_t length = height * width;
458 if (startAddr != lcdUpbase)
459 startAddr = lcdUpbase;
460
461 // Updating base address, interrupt if we're supposed to
462 lcdRis.baseaddr = 1;
463 if (!intEvent.scheduled())
464 schedule(intEvent, clockEdge());
465
466 curAddr = 0;
467 startTime = curTick();
468
469 maxAddr = static_cast<Addr>(length * bytesPerPixel);
470
471 DPRINTF(PL111, " lcd frame buffer size of %d bytes \n", maxAddr);
472
473 fillFifo();
474}
475
476void
477Pl111::fillFifo()
478{
479 while ((dmaPendingNum < maxOutstandingDma) && (maxAddr >= curAddr + dmaSize )) {
480 // concurrent dma reads need different dma done events
481 // due to assertion in scheduling state
482 ++dmaPendingNum;
483
484 assert(!dmaDoneEventFree.empty());
485 DmaDoneEvent *event(dmaDoneEventFree.back());
486 dmaDoneEventFree.pop_back();
487 assert(!event->scheduled());
488
489 // We use a uncachable request here because the requests from the CPU
490 // will be uncacheable as well. If we have uncacheable and cacheable
491 // requests in the memory system for the same address it won't be
492 // pleased
493 dmaPort.dmaAction(MemCmd::ReadReq, curAddr + startAddr, dmaSize,
494 event, curAddr + dmaBuffer,
495 0, Request::UNCACHEABLE);
496 curAddr += dmaSize;
497 }
498}
499
500void
501Pl111::dmaDone()
502{
503 DPRINTF(PL111, "DMA Done\n");
504
505 Tick maxFrameTime = lcdTiming2.cpl * height * pixelClock;
506
507 --dmaPendingNum;
508
509 if (maxAddr == curAddr && !dmaPendingNum) {
510 if ((curTick() - startTime) > maxFrameTime) {
511 warn("CLCD controller buffer underrun, took %d ticks when should"
512 " have taken %d\n", curTick() - startTime, maxFrameTime);
513 lcdRis.underflow = 1;
514 if (!intEvent.scheduled())
515 schedule(intEvent, clockEdge());
516 }
517
518 assert(!readEvent.scheduled());
519 fb.copyIn(dmaBuffer, converter);
520 if (vnc)
521 vnc->setDirty();
522
523 if (enableCapture) {
524 DPRINTF(PL111, "-- write out frame buffer into bmp\n");
525
526 if (!pic)
527 pic = simout.create(csprintf("%s.framebuffer.bmp", sys->name()),
528 true);
529
530 assert(pic);
531 pic->stream()->seekp(0);
532 bmp.write(*pic->stream());
533 }
534
535 // schedule the next read based on when the last frame started
536 // and the desired fps (i.e. maxFrameTime), we turn the
537 // argument into a relative number of cycles in the future
538 if (lcdControl.lcden)
539 schedule(readEvent, clockEdge(ticksToCycles(startTime -
540 curTick() +
541 maxFrameTime)));
542 }
543
544 if (dmaPendingNum > (maxOutstandingDma - waterMark))
545 return;
546
547 if (!fillFifoEvent.scheduled())
548 schedule(fillFifoEvent, clockEdge());
549}
550
551void
552Pl111::serialize(CheckpointOut &cp) const
553{
554 DPRINTF(PL111, "Serializing ARM PL111\n");
555
556 uint32_t lcdTiming0_serial = lcdTiming0;
557 SERIALIZE_SCALAR(lcdTiming0_serial);
558
559 uint32_t lcdTiming1_serial = lcdTiming1;
560 SERIALIZE_SCALAR(lcdTiming1_serial);
561
562 uint32_t lcdTiming2_serial = lcdTiming2;
563 SERIALIZE_SCALAR(lcdTiming2_serial);
564
565 uint32_t lcdTiming3_serial = lcdTiming3;
566 SERIALIZE_SCALAR(lcdTiming3_serial);
567
568 SERIALIZE_SCALAR(lcdUpbase);
569 SERIALIZE_SCALAR(lcdLpbase);
570
571 uint32_t lcdControl_serial = lcdControl;
572 SERIALIZE_SCALAR(lcdControl_serial);
573
574 uint8_t lcdImsc_serial = lcdImsc;
575 SERIALIZE_SCALAR(lcdImsc_serial);
576
577 uint8_t lcdRis_serial = lcdRis;
578 SERIALIZE_SCALAR(lcdRis_serial);
579
580 uint8_t lcdMis_serial = lcdMis;
581 SERIALIZE_SCALAR(lcdMis_serial);
582
583 SERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
584 SERIALIZE_ARRAY(cursorImage, CrsrImageSize);
585
586 SERIALIZE_SCALAR(clcdCrsrCtrl);
587 SERIALIZE_SCALAR(clcdCrsrConfig);
588 SERIALIZE_SCALAR(clcdCrsrPalette0);
589 SERIALIZE_SCALAR(clcdCrsrPalette1);
590 SERIALIZE_SCALAR(clcdCrsrXY);
591 SERIALIZE_SCALAR(clcdCrsrClip);
592
593 uint8_t clcdCrsrImsc_serial = clcdCrsrImsc;
594 SERIALIZE_SCALAR(clcdCrsrImsc_serial);
595
596 uint8_t clcdCrsrIcr_serial = clcdCrsrIcr;
597 SERIALIZE_SCALAR(clcdCrsrIcr_serial);
598
599 uint8_t clcdCrsrRis_serial = clcdCrsrRis;
600 SERIALIZE_SCALAR(clcdCrsrRis_serial);
601
602 uint8_t clcdCrsrMis_serial = clcdCrsrMis;
603 SERIALIZE_SCALAR(clcdCrsrMis_serial);
604
605 SERIALIZE_SCALAR(height);
606 SERIALIZE_SCALAR(width);
607 SERIALIZE_SCALAR(bytesPerPixel);
608
609 SERIALIZE_ARRAY(dmaBuffer, buffer_size);
610 SERIALIZE_SCALAR(startTime);
611 SERIALIZE_SCALAR(startAddr);
612 SERIALIZE_SCALAR(maxAddr);
613 SERIALIZE_SCALAR(curAddr);
614 SERIALIZE_SCALAR(waterMark);
615 SERIALIZE_SCALAR(dmaPendingNum);
616
617 Tick int_event_time = 0;
618 Tick read_event_time = 0;
619 Tick fill_fifo_event_time = 0;
620
621 if (readEvent.scheduled())
622 read_event_time = readEvent.when();
623 if (fillFifoEvent.scheduled())
624 fill_fifo_event_time = fillFifoEvent.when();
625 if (intEvent.scheduled())
626 int_event_time = intEvent.when();
627
628 SERIALIZE_SCALAR(read_event_time);
629 SERIALIZE_SCALAR(fill_fifo_event_time);
630 SERIALIZE_SCALAR(int_event_time);
631
632 vector<Tick> dma_done_event_tick;
633 dma_done_event_tick.resize(maxOutstandingDma);
634 for (int x = 0; x < maxOutstandingDma; x++) {
635 dma_done_event_tick[x] = dmaDoneEventAll[x].scheduled() ?
636 dmaDoneEventAll[x].when() : 0;
637 }
638 SERIALIZE_CONTAINER(dma_done_event_tick);
639}
640
641void
642Pl111::unserialize(CheckpointIn &cp)
643{
644 DPRINTF(PL111, "Unserializing ARM PL111\n");
645
646 uint32_t lcdTiming0_serial;
647 UNSERIALIZE_SCALAR(lcdTiming0_serial);
648 lcdTiming0 = lcdTiming0_serial;
649
650 uint32_t lcdTiming1_serial;
651 UNSERIALIZE_SCALAR(lcdTiming1_serial);
652 lcdTiming1 = lcdTiming1_serial;
653
654 uint32_t lcdTiming2_serial;
655 UNSERIALIZE_SCALAR(lcdTiming2_serial);
656 lcdTiming2 = lcdTiming2_serial;
657
658 uint32_t lcdTiming3_serial;
659 UNSERIALIZE_SCALAR(lcdTiming3_serial);
660 lcdTiming3 = lcdTiming3_serial;
661
662 UNSERIALIZE_SCALAR(lcdUpbase);
663 UNSERIALIZE_SCALAR(lcdLpbase);
664
665 uint32_t lcdControl_serial;
666 UNSERIALIZE_SCALAR(lcdControl_serial);
667 lcdControl = lcdControl_serial;
668
669 uint8_t lcdImsc_serial;
670 UNSERIALIZE_SCALAR(lcdImsc_serial);
671 lcdImsc = lcdImsc_serial;
672
673 uint8_t lcdRis_serial;
674 UNSERIALIZE_SCALAR(lcdRis_serial);
675 lcdRis = lcdRis_serial;
676
677 uint8_t lcdMis_serial;
678 UNSERIALIZE_SCALAR(lcdMis_serial);
679 lcdMis = lcdMis_serial;
680
681 UNSERIALIZE_ARRAY(lcdPalette, LcdPaletteSize);
682 UNSERIALIZE_ARRAY(cursorImage, CrsrImageSize);
683
684 UNSERIALIZE_SCALAR(clcdCrsrCtrl);
685 UNSERIALIZE_SCALAR(clcdCrsrConfig);
686 UNSERIALIZE_SCALAR(clcdCrsrPalette0);
687 UNSERIALIZE_SCALAR(clcdCrsrPalette1);
688 UNSERIALIZE_SCALAR(clcdCrsrXY);
689 UNSERIALIZE_SCALAR(clcdCrsrClip);
690
691 uint8_t clcdCrsrImsc_serial;
692 UNSERIALIZE_SCALAR(clcdCrsrImsc_serial);
693 clcdCrsrImsc = clcdCrsrImsc_serial;
694
695 uint8_t clcdCrsrIcr_serial;
696 UNSERIALIZE_SCALAR(clcdCrsrIcr_serial);
697 clcdCrsrIcr = clcdCrsrIcr_serial;
698
699 uint8_t clcdCrsrRis_serial;
700 UNSERIALIZE_SCALAR(clcdCrsrRis_serial);
701 clcdCrsrRis = clcdCrsrRis_serial;
702
703 uint8_t clcdCrsrMis_serial;
704 UNSERIALIZE_SCALAR(clcdCrsrMis_serial);
705 clcdCrsrMis = clcdCrsrMis_serial;
706
707 UNSERIALIZE_SCALAR(height);
708 UNSERIALIZE_SCALAR(width);
709 UNSERIALIZE_SCALAR(bytesPerPixel);
710
711 UNSERIALIZE_ARRAY(dmaBuffer, buffer_size);
712 UNSERIALIZE_SCALAR(startTime);
713 UNSERIALIZE_SCALAR(startAddr);
714 UNSERIALIZE_SCALAR(maxAddr);
715 UNSERIALIZE_SCALAR(curAddr);
716 UNSERIALIZE_SCALAR(waterMark);
717 UNSERIALIZE_SCALAR(dmaPendingNum);
718
719 Tick int_event_time = 0;
720 Tick read_event_time = 0;
721 Tick fill_fifo_event_time = 0;
722
723 UNSERIALIZE_SCALAR(read_event_time);
724 UNSERIALIZE_SCALAR(fill_fifo_event_time);
725 UNSERIALIZE_SCALAR(int_event_time);
726
727 if (int_event_time)
728 schedule(intEvent, int_event_time);
729 if (read_event_time)
730 schedule(readEvent, read_event_time);
731 if (fill_fifo_event_time)
732 schedule(fillFifoEvent, fill_fifo_event_time);
733
734 vector<Tick> dma_done_event_tick;
735 dma_done_event_tick.resize(maxOutstandingDma);
736 UNSERIALIZE_CONTAINER(dma_done_event_tick);
737 dmaDoneEventFree.clear();
738 for (int x = 0; x < maxOutstandingDma; x++) {
739 if (dma_done_event_tick[x])
740 schedule(dmaDoneEventAll[x], dma_done_event_tick[x]);
741 else
742 dmaDoneEventFree.push_back(&dmaDoneEventAll[x]);
743 }
744 assert(maxOutstandingDma - dmaDoneEventFree.size() == dmaPendingNum);
745
746 if (lcdControl.lcdpwr) {
747 updateVideoParams();
748 fb.copyIn(dmaBuffer, converter);
749 if (vnc)
750 vnc->setDirty();
751 }
752}
753
754void
755Pl111::generateInterrupt()
756{
757 DPRINTF(PL111, "Generate Interrupt: lcdImsc=0x%x lcdRis=0x%x lcdMis=0x%x\n",
758 (uint32_t)lcdImsc, (uint32_t)lcdRis, (uint32_t)lcdMis);
759 lcdMis = lcdImsc & lcdRis;
760
761 if (lcdMis.underflow || lcdMis.baseaddr || lcdMis.vcomp || lcdMis.ahbmaster) {
762 gic->sendInt(intNum);
763 DPRINTF(PL111, " -- Generated\n");
764 }
765}
766
767AddrRangeList
768Pl111::getAddrRanges() const
769{
770 AddrRangeList ranges;
771 ranges.push_back(RangeSize(pioAddr, pioSize));
772 return ranges;
773}
774
775Pl111 *
776Pl111Params::create()
777{
778 return new Pl111(this);
779}
780
781