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