includes: sort all includes
[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 "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
51 using namespace AmbaDev;
52
53 // initialize clcd registers
54 Pl111::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
81 Tick
82 Pl111::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
211 Tick
212 Pl111::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
368 void
369 Pl111::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
409 void
410 Pl111::startDma()
411 {
412 if (dmaPendingNum != 0 || readEvent.scheduled())
413 return;
414 readFramebuffer();
415 }
416
417 void
418 Pl111::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
442 void
443 Pl111::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
463 void
464 Pl111::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
504 Tick
505 Pl111::nextCycle()
506 {
507 Tick nextTick = curTick() + clock - 1;
508 nextTick -= nextTick%clock;
509 return nextTick;
510 }
511
512 Tick
513 Pl111::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
523 void
524 Pl111::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
614 void
615 Pl111::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 if (lcdControl.lcdpwr) {
717 updateVideoParams();
718 if (vncserver)
719 vncserver->setDirty();
720 }
721 }
722
723 void
724 Pl111::generateInterrupt()
725 {
726 DPRINTF(PL111, "Generate Interrupt: lcdImsc=0x%x lcdRis=0x%x lcdMis=0x%x\n",
727 (uint32_t)lcdImsc, (uint32_t)lcdRis, (uint32_t)lcdMis);
728 lcdMis = lcdImsc & lcdRis;
729
730 if (lcdMis.underflow || lcdMis.baseaddr || lcdMis.vcomp || lcdMis.ahbmaster) {
731 gic->sendInt(intNum);
732 DPRINTF(PL111, " -- Generated\n");
733 }
734 }
735
736 void
737 Pl111::addressRanges(AddrRangeList& range_list)
738 {
739 range_list.clear();
740 range_list.push_back(RangeSize(pioAddr, pioSize));
741 }
742
743 Pl111 *
744 Pl111Params::create()
745 {
746 return new Pl111(this);
747 }
748
749