pl111.cc revision 7950
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/bitmap.hh" 42#include "base/output.hh" 43#include "base/trace.hh" 44#include "base/vnc/vncserver.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 51using namespace AmbaDev; 52 53// initialize clcd registers 54Pl111::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 81Tick 82Pl111::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 211Tick 212Pl111::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 368void 369Pl111::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 409void 410Pl111::startDma() 411{ 412 if (dmaPendingNum != 0 || readEvent.scheduled()) 413 return; 414 readFramebuffer(); 415} 416 417void 418Pl111::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 442void 443Pl111::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 463void 464Pl111::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 504Tick 505Pl111::nextCycle() 506{ 507 Tick nextTick = curTick() + clock - 1; 508 nextTick -= nextTick%clock; 509 return nextTick; 510} 511 512Tick 513Pl111::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 523void 524Pl111::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 591void 592Pl111::unserialize(Checkpoint *cp, const std::string §ion) 593{ 594 DPRINTF(PL111, "Unserializing ARM PL111\n"); 595 596 uint32_t lcdTiming0_serial; 597 UNSERIALIZE_SCALAR(lcdTiming0_serial); 598 lcdTiming0 = lcdTiming0_serial; 599 600 uint32_t lcdTiming1_serial; 601 UNSERIALIZE_SCALAR(lcdTiming1_serial); 602 lcdTiming1 = lcdTiming1_serial; 603 604 uint32_t lcdTiming2_serial; 605 UNSERIALIZE_SCALAR(lcdTiming2_serial); 606 lcdTiming2 = lcdTiming2_serial; 607 608 uint32_t lcdTiming3_serial; 609 UNSERIALIZE_SCALAR(lcdTiming3_serial); 610 lcdTiming3 = lcdTiming3_serial; 611 612 UNSERIALIZE_SCALAR(lcdUpbase); 613 UNSERIALIZE_SCALAR(lcdLpbase); 614 615 uint32_t lcdControl_serial; 616 UNSERIALIZE_SCALAR(lcdControl_serial); 617 lcdControl = lcdControl_serial; 618 619 uint8_t lcdImsc_serial; 620 UNSERIALIZE_SCALAR(lcdImsc_serial); 621 lcdImsc = lcdImsc_serial; 622 623 uint8_t lcdRis_serial; 624 UNSERIALIZE_SCALAR(lcdRis_serial); 625 lcdRis = lcdRis_serial; 626 627 uint8_t lcdMis_serial; 628 UNSERIALIZE_SCALAR(lcdMis_serial); 629 lcdMis = lcdMis_serial; 630 631 UNSERIALIZE_ARRAY(lcdPalette, LcdPaletteSize); 632 UNSERIALIZE_ARRAY(cursorImage, CrsrImageSize); 633 634 UNSERIALIZE_SCALAR(clcdCrsrCtrl); 635 UNSERIALIZE_SCALAR(clcdCrsrConfig); 636 UNSERIALIZE_SCALAR(clcdCrsrPalette0); 637 UNSERIALIZE_SCALAR(clcdCrsrPalette1); 638 UNSERIALIZE_SCALAR(clcdCrsrXY); 639 UNSERIALIZE_SCALAR(clcdCrsrClip); 640 641 uint8_t clcdCrsrImsc_serial; 642 UNSERIALIZE_SCALAR(clcdCrsrImsc_serial); 643 clcdCrsrImsc = clcdCrsrImsc_serial; 644 645 uint8_t clcdCrsrIcr_serial; 646 UNSERIALIZE_SCALAR(clcdCrsrIcr_serial); 647 clcdCrsrIcr = clcdCrsrIcr_serial; 648 649 uint8_t clcdCrsrRis_serial; 650 UNSERIALIZE_SCALAR(clcdCrsrRis_serial); 651 clcdCrsrRis = clcdCrsrRis_serial; 652 653 uint8_t clcdCrsrMis_serial; 654 UNSERIALIZE_SCALAR(clcdCrsrMis_serial); 655 clcdCrsrMis = clcdCrsrMis_serial; 656 657 UNSERIALIZE_SCALAR(clock); 658 UNSERIALIZE_SCALAR(height); 659 UNSERIALIZE_SCALAR(width); 660 UNSERIALIZE_SCALAR(bytesPerPixel); 661 662 UNSERIALIZE_ARRAY(dmaBuffer, height * width); 663 UNSERIALIZE_SCALAR(startTime); 664 UNSERIALIZE_SCALAR(startAddr); 665 UNSERIALIZE_SCALAR(maxAddr); 666 UNSERIALIZE_SCALAR(curAddr); 667 UNSERIALIZE_SCALAR(waterMark); 668 UNSERIALIZE_SCALAR(dmaPendingNum); 669 670 updateVideoParams(); 671 if (vncserver) 672 vncserver->setDirty(); 673} 674 675void 676Pl111::generateInterrupt() 677{ 678 DPRINTF(PL111, "Generate Interrupt: lcdImsc=0x%x lcdRis=0x%x lcdMis=0x%x\n", 679 (uint32_t)lcdImsc, (uint32_t)lcdRis, (uint32_t)lcdMis); 680 lcdMis = lcdImsc & lcdRis; 681 682 if (lcdMis.underflow || lcdMis.baseaddr || lcdMis.vcomp || lcdMis.ahbmaster) { 683 gic->sendInt(intNum); 684 DPRINTF(PL111, " -- Generated\n"); 685 } 686} 687 688void 689Pl111::addressRanges(AddrRangeList& range_list) 690{ 691 range_list.clear(); 692 range_list.push_back(RangeSize(pioAddr, pioSize)); 693} 694 695Pl111 * 696Pl111Params::create() 697{ 698 return new Pl111(this); 699} 700 701 702