pl111.cc revision 8737
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 55using std::vector; 56 57using namespace AmbaDev; 58 59// initialize clcd registers 60Pl111::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 88Tick 89Pl111::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 218Tick 219Pl111::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 375void 376Pl111::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 416void 417Pl111::startDma() 418{ 419 if (dmaPendingNum != 0 || readEvent.scheduled()) 420 return; 421 readFramebuffer(); 422} 423 424void 425Pl111::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 449void 450Pl111::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 470void 471Pl111::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 511Tick 512Pl111::nextCycle() 513{ 514 Tick nextTick = curTick() + clock - 1; 515 nextTick -= nextTick%clock; 516 return nextTick; 517} 518 519Tick 520Pl111::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 530void 531Pl111::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 621void 622Pl111::unserialize(Checkpoint *cp, const std::string §ion) 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 730void 731Pl111::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 743AddrRangeList 744Pl111::getAddrRanges() 745{ 746 AddrRangeList ranges; 747 ranges.push_back(RangeSize(pioAddr, pioSize)); 748 return ranges; 749} 750 751Pl111 * 752Pl111Params::create() 753{ 754 return new Pl111(this); 755} 756 757 758