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