1/* 2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22//#define IOFB_DISABLEFB 1 23 24#include <IOKit/IOLib.h> 25#include <libkern/c++/OSContainers.h> 26#include <libkern/OSByteOrder.h> 27 28#include <IOKit/IOWorkLoop.h> 29#include <IOKit/IOTimerEventSource.h> 30#include <IOKit/IOCommandGate.h> 31#include <IOKit/IOMessage.h> 32#include <IOKit/IOPlatformExpert.h> 33#include <IOKit/IOBufferMemoryDescriptor.h> 34#include <IOKit/IOHibernatePrivate.h> 35#include <IOKit/IOUserClient.h> 36#include <IOKit/IOKitKeysPrivate.h> 37#include <IOKit/IODeviceTreeSupport.h> 38 39#define IOFRAMEBUFFER_PRIVATE 40#include <IOKit/graphics/IOGraphicsPrivate.h> 41#include <IOKit/graphics/IOFramebuffer.h> 42#include <IOKit/graphics/IODisplay.h> 43#include <IOKit/i2c/IOI2CInterface.h> 44#if defined(__ppc__) && !defined(OSTYPES_K64_REV) 45#include <IOKit/i2c/PPCI2CInterface.h> 46#endif 47#include <IOKit/acpi/IOACPIPlatformExpert.h> 48 49#include "IOFramebufferUserClient.h" 50#include "IODisplayWrangler.h" 51#include "IOFramebufferReallyPrivate.h" 52#include <IOKit/pwr_mgt/RootDomain.h> 53#include <IOKit/pwr_mgt/IOPMPrivate.h> 54 55#include <string.h> 56#include <IOKit/assert.h> 57#include <sys/kdebug.h> 58 59/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 60 61#ifndef VERSION_MAJOR 62#error no VERSION_MAJOR 63#endif 64 65#define SINGLE_THREAD 0 66#define TIME_LOGS RLOG1 67#define TIME_CURSOR RLOG1 68#define ASYNC_GAMMA 1 69 70#define GAMMA_ADJ 0 71 72#define DOANIO 0 73#define VRAM_SAVE 1 74#define VRAM_COMPRESS 1 75 76enum { kIOFBVRAMCompressSpeed = 0 }; 77enum { kVBLThrottleTimeMS = 5000 }; 78enum { kInitFBTimeoutNS = 1000000000ULL }; 79 80enum { k2xDPI = (150*10) }; 81 82//#define AUTO_COLOR_MODE kIODisplayColorModeRGB 83#define AUTO_COLOR_MODE kIODisplayColorModeYCbCr444 84 85 86#if defined(__i386__) || defined(__x86_64__) 87enum { kIOFBMapCacheMode = kIOMapWriteCombineCache }; 88#else 89enum { kIOFBMapCacheMode = kIOMapInhibitCache }; 90#endif 91 92#ifndef kBootArgsFlagBlack 93#define kBootArgsFlagBlack (1 << 2) 94#endif 95 96#ifndef kIOPMUserTriggeredFullWakeKey 97#define kIOPMUserTriggeredFullWakeKey "IOPMUserTriggeredFullWake" 98#endif 99 100#if VRAM_COMPRESS 101#include "bmcompress.h" 102#endif 103 104#if DOANIO 105#include <sys/uio.h> 106#include <sys/conf.h> 107#endif 108 109enum { 110 kIOFBClamshellProbeDelayMS = 1*1000 111}; 112enum { 113 kIOFBClamshellEnableDelayMS = 15*1000 114}; 115 116enum 117{ 118 // all seconds: 119 kSystemWillSleepTimeout = 90, // 90 120 kServerAckTimeout = 25, // 25 121 kPowerStateTimeout = 45, 122 kDarkWokeTimeout = 5, 123}; 124 125enum 126{ 127 kIOFBEventCaptureSetting = 0x00000001, 128 kIOFBEventDisplayDimsSetting = 0x00000002, 129 kIOFBEventReadClamshell = 0x00000004, 130 kIOFBEventResetClamshell = 0x00000008, 131 kIOFBEventEnableClamshell = 0x00000010, 132 kIOFBEventProbeAll = 0x00000020, 133 kIOFBEventDisplaysPowerState = 0x00000040, 134 kIOFBEventSystemPowerOn = 0x00000080 135}; 136 137enum 138{ 139 fg = 1, 140 bg = 2, 141 fgOff = 3, 142 bgOff = 4, 143}; 144 145#if RLOG1 146static const char * processConnectChangeModeNames[] = 147 { "", "fg", "bg", "fgOff", "bgOff" }; 148#endif 149 150#define CHAR(c) ((c) ? ((char) (c)) : '0') 151#define FEAT(f) CHAR(f>>24), CHAR(f>>16), CHAR(f>>8), CHAR(f>>0) 152 153/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 154 155static class IOGraphicsWorkLoop * gIOFBSystemWorkLoop; 156static struct IOFBController * gIOFBAllControllers; 157static struct IOFBController * gIOFBLastController; 158 159static OSArray * gAllFramebuffers; 160static OSArray * gStartedFramebuffers; 161static OSArray * gRunawayFramebuffers; 162static IOWorkLoop * gIOFBHIDWorkLoop; 163static IOTimerEventSource * gIOFBDelayedPrefsEvent; 164static IOTimerEventSource * gIOFBServerAckTimer; 165static IONotifier * gIOFBRootNotifier; 166static IONotifier * gIOFBClamshellNotify; 167static IONotifier * gIOFBGCNotifier; 168static IOInterruptEventSource * gIOFBWorkES; 169static volatile UInt32 gIOFBGlobalEvents; 170static IORegistryEntry * gChosenEntry; 171static IOService * gIOFBSystemPowerAckTo; 172static void * gIOFBSystemPowerAckRef; 173static IOService * gIOFBSystemPowerMuxAckTo; 174static uint32_t gIOFBSystemPowerMuxAckRef; 175static UInt32 gIOFBLastMuxMessage = kIOMessageSystemHasPoweredOn; 176static bool gIOFBSwitching; 177bool gIOFBSystemPower = true; 178bool gIOFBSystemDark; 179static bool gIOFBServerInit; 180static bool gIOFBWSState = true; 181static bool gIOFBPostWakeNeeded; 182static bool gIOFBProbeCaptured; 183static uint32_t gIOFBCaptureState; 184bool gIOGraphicsSystemPower = true; 185static thread_call_t gIOFBClamshellCallout; 186static SInt32 gIOFBDisplayCount; 187static SInt32 gIOFBBacklightDisplayCount; 188static IOOptionBits gIOFBClamshellState; 189static IOFramebuffer * gIOFBConsoleFramebuffer; 190static bool gIOFBDesktopModeAllowed = true; 191IOOptionBits gIOFBCurrentClamshellState; 192static IOOptionBits gIOFBLastClamshellState; 193int32_t gIOFBHaveBacklight = -1; 194static IOOptionBits gIOFBLastReadClamshellState; 195const OSSymbol * gIOFBGetSensorValueKey; 196const OSSymbol * gIOFramebufferKey; 197const OSSymbol * gIOFBRotateKey; 198const OSSymbol * gIOFBStartupModeTimingKey; 199const OSSymbol * gIOFBPMSettingDisplaySleepUsesDimKey; 200const OSSymbol * gIOFBConfigKey; 201const OSSymbol * gIOFBModesKey; 202const OSSymbol * gIOFBModeIDKey; 203const OSSymbol * gIOFBModeDMKey; 204static OSDictionary * gIOFBPrefs; 205static OSDictionary * gIOFBPrefsParameters; 206static OSDictionary * gIOFBIgnoreParameters; 207static OSSerializer * gIOFBPrefsSerializer; 208static IOService * gIOGraphicsControl; 209static OSObject * gIOResourcesAppleClamshellState; 210static AbsoluteTime gIOFBNextProbeAllTime; 211static AbsoluteTime gIOFBMaxVBLDelta; 212OSData * gIOFBZero32Data; 213OSData * gIOFBOne32Data; 214uint32_t gIOFBGrayValue = kIOFBBootGrayValue; 215OSData * gIOFBGray32Data; 216static uint8_t gIOFBBlackBoot; 217static const OSSymbol * gIOGraphicsPrefsVersionKey; 218static OSNumber * gIOGraphicsPrefsVersionValue; 219static uint8_t gIOFBLidOpenMode; 220static uint8_t gIOFBVBLThrottle; 221static uint8_t gIOFBVBLDrift; 222uint32_t gIOGDebugFlags; 223uint32_t gIOGNotifyTO; 224static bool gIOGFades; 225 226#define kIOFBGetSensorValueKey "getSensorValue" 227 228enum { kIOFBDefaultScalerUnderscan = 0*kIOFBScalerUnderscan }; 229 230// console clut 231extern UInt8 appleClut8[256 * 3]; 232 233/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 234 235enum { kIOFBControllerMaxFBs = 32 }; 236 237struct IOFBController 238{ 239 IOFBController * nextController; 240 IOFramebuffer * fbs[kIOFBControllerMaxFBs + 1]; 241 class IOGraphicsWorkLoop * wl; 242 IOInterruptEventSource * workES; 243 IOService * device; 244 const char * name; 245 AbsoluteTime initTime; 246 247 thread_t powerThread; 248 249 uint32_t vendorID; 250 uint32_t maxFB; 251 uint32_t onlineMask; 252 253 int32_t connectChange; 254 int32_t lastForceRetrain; 255 int32_t lastMessagedChange; 256 int32_t lastFinishedChange; 257 int32_t postWakeChange; 258 259 uint8_t mute; 260 261 uint8_t wsWait; 262 263 uint8_t needsWork; 264 uint8_t didWork; 265 uint8_t asyncWork; 266 uint8_t pendingMuxPowerChange; 267 uint8_t integrated; 268 269 uint32_t state; 270 uint32_t aliasID; 271#if IOFB_DISABLEFB 272 uintptr_t saveGAR; 273#endif 274}; 275 276struct IOFBInterruptRegister 277{ 278 IOFBInterruptProc handler; 279 OSObject * target; 280 void * ref; 281 UInt32 state; 282}; 283enum 284{ 285 kIOFBMCCSInterruptRegister = 0, 286 kIOFBNumInterruptRegister = 1 287}; 288 289struct IOFramebufferPrivate 290{ 291 IOFBController * controller; 292 IODisplay * display; 293 IOFramebuffer * nextMirror; 294 uint64_t regID; 295 uint32_t displayOptions; 296 uint32_t controllerIndex; 297 IOGSize maxWaitCursorSize; 298 UInt32 numCursorFrames; 299 uint32_t cursorBytesPerPixel; 300 UInt8 * cursorFlags; 301 volatile unsigned char ** cursorImages; 302 volatile unsigned char ** cursorMasks; 303 IOMemoryDescriptor * saveBitsMD[kIOPreviewImageCount]; 304 305 IOGBounds screenBounds[2]; // phys & virtual bounds 306 307 class IOFramebufferParameterHandler * paramHandler; 308 309 void * vblInterrupt; 310 void * connectInterrupt; 311 IOTimerEventSource * vblUpdateTimer; 312 IOTimerEventSource * deferredCLUTSetTimerEvent; 313 IOInterruptEventSource * deferredVBLDisableEvent; 314 uint64_t actualVBLCount; 315 OSObject * displayAttributes; 316 317 IOFBInterruptRegister interruptRegisters[kIOFBNumInterruptRegister]; 318 319 OSArray * cursorAttributes; 320 IOFBCursorControlAttribute cursorControl; 321 IOInterruptEventSource * cursorThread; 322 IOOptionBits cursorToDo; 323 UInt32 framePending; 324 SInt32 xPending; 325 SInt32 yPending; 326 IOGPoint cursorHotSpotAdjust[2]; 327 IOGPoint lastHotSpot; 328 void * waitVBLEvent; 329 330 IOByteCount gammaHeaderSize; 331 UInt32 desiredGammaDataWidth; 332 UInt32 desiredGammaDataCount; 333 334 IOInterruptEventSource * deferredCLUTSetEvent; 335 IOInterruptEventSource * deferredSpeedChangeEvent; 336 IOTimerEventSource * delayedConnectInterrupt; 337 UInt32 delayedConnectTime; 338 339 IOTimerEventSource * dpInterruptES; 340 void * dpInterruptRef; 341 UInt32 dpInterrupDelayTime; 342 343 const OSSymbol * displayPrefKey; 344 345 IOByteCount gammaDataLen; 346 UInt8 * gammaData; 347 UInt32 gammaChannelCount; 348 UInt32 gammaDataCount; 349 UInt32 gammaDataWidth; 350 351 IOByteCount rawGammaDataLen; 352 UInt8 * rawGammaData; 353 UInt32 rawGammaChannelCount; 354 UInt32 rawGammaDataCount; 355 UInt32 rawGammaDataWidth; 356 357 IOByteCount clutDataLen; 358 UInt8 * clutData; 359 UInt32 clutIndex; 360 UInt32 clutOptions; 361 362 uint32_t framebufferWidth; 363 uint32_t framebufferHeight; 364 uint32_t consoleDepth; 365 uint32_t restoreType; 366 uint32_t hibernateGfxStatus; 367 uint32_t saveLength; 368 void * saveFramebuffer; 369 370 UInt8 needGammaRestore; 371 UInt8 vblThrottle; 372 UInt8 vblEnabled; 373 UInt8 gammaNeedSet; 374 UInt8 gammaScaleChange; 375 UInt8 scaledMode; 376 UInt8 visiblePending; 377 UInt8 testingCursor; 378 UInt8 index; 379 UInt8 gammaSet; 380 UInt8 cursorSlept; 381 UInt8 cursorPanning; 382 UInt8 pendingSpeedChange; 383 384 UInt8 lli2c; 385 UInt8 cursorClutDependent; 386 UInt8 allowSpeedChanges; 387 UInt8 dimDisable; 388 389 UInt8 enableScalerUnderscan; 390 UInt8 userSetTransform; 391 UInt8 closed; 392 UInt8 online; 393 UInt8 displaysOnline; 394 UInt8 lastNotifyOnline; 395 UInt8 modeUpdate; 396 UInt8 dpInterrupts; 397 SInt8 dpSupported; 398 UInt8 dpDongle; 399 UInt8 dpDongleSinkCount; 400 UInt8 dpBusID; 401 UInt8 colorModesAllowed; 402 UInt8 needsInit; 403 UInt8 audioStreaming; 404 uint32_t uiScale; 405 406 uint32_t colorModesSupported; 407 408 UInt64 transform; 409 UInt64 selectedTransform; 410 UInt32 reducedSpeed; 411 IOService * temperatureSensor; 412 IOI2CBusTiming defaultI2CTiming; 413 414 uintptr_t gammaScale[4]; 415 416 IOPixelInformation pixelInfo; 417 IOTimingInformation timingInfo; 418 IODisplayModeID offlineMode; 419 IODisplayModeID aliasMode; 420 IODisplayModeID matchedMode; 421 IODisplayModeID setupMode; 422 IOIndex currentDepth; 423 424 int32_t lastProcessedChange; 425}; 426 427/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 428 429#define GetShmem(instance) ((StdFBShmem_t *)(instance->priv)) 430 431#define KICK_CURSOR(thread) \ 432 thread->interruptOccurred(0, 0, 0); 433 434#define CLEARSEMA(shmem, inst) \ 435 if( inst->__private->cursorToDo ) { \ 436 KICK_CURSOR(inst->__private->cursorThread); \ 437 } \ 438 OSSpinLockUnlock(&shmem->cursorSema) 439 440#define SETSEMA(shmem) \ 441 if (!OSSpinLockTry(&shmem->cursorSema)) return; 442#define TOUCHBOUNDS(one, two) \ 443 (((one.minx < two.maxx) && (two.minx < one.maxx)) && \ 444 ((one.miny < two.maxy) && (two.miny < one.maxy))) 445 446/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 447 448class IOGraphicsWorkLoop : public IOWorkLoop 449{ 450 OSDeclareDefaultStructors(IOGraphicsWorkLoop) 451public: 452 typedef void GateFunction(IOWorkLoop * wl, OSObject * obj, void * reference, bool gate); 453 454 IOLock * gateMutex; 455 thread_t gateThread; 456 uint32_t gateCount; 457 458 IOOptionBits options; 459 GateFunction * func; 460 OSObject * obj; 461 void * reference; 462 463 static IOGraphicsWorkLoop * workLoop(IOOptionBits options = 0, 464 GateFunction * func = NULL, 465 OSObject * obj = NULL, void * reference = NULL); 466 virtual bool init(); 467 virtual void free(); 468 469 virtual void signalWorkAvailable() { IOWorkLoop::signalWorkAvailable(); } 470 virtual bool inGate() const; 471 virtual void closeGate(); 472 virtual void openGate(); 473 virtual bool tryCloseGate(); 474 virtual int sleepGate(void *event, UInt32 interuptibleType); 475 virtual int sleepGate(void *event, AbsoluteTime deadline, UInt32 interuptibleType); 476 virtual void wakeupGate(void *event, bool oneThread); 477}; 478 479OSDefineMetaClassAndStructors(IOGraphicsWorkLoop, IOWorkLoop) 480 481IOGraphicsWorkLoop * IOGraphicsWorkLoop::workLoop(IOOptionBits options, 482 GateFunction * func, OSObject * obj, void * reference) 483{ 484 IOGraphicsWorkLoop *me = new IOGraphicsWorkLoop; 485 486 if (!me) 487 return (NULL); 488 489 me->options = options; 490 me->func = func; 491 me->obj = obj; 492 me->reference = reference; 493 if (!me->init()) 494 { 495 me->release(); 496 me = NULL; 497 } 498 499 return (me); 500} 501 502bool IOGraphicsWorkLoop::init() 503{ 504 bool ok; 505 506 gateMutex = IOLockAlloc(); 507 if (!gateMutex) return (false); 508 509 ok = IOWorkLoop::init(); 510 511 if (gateLock) 512 { 513 IORecursiveLockFree(gateLock); 514 gateLock = NULL; 515 } 516 517 return (ok); 518} 519 520void IOGraphicsWorkLoop::free() 521{ 522 if (gateMutex && !workThread) 523 { 524 IOLockFree(gateMutex); 525 gateMutex = NULL; 526 } 527 IOWorkLoop::free(); 528} 529 530bool IOGraphicsWorkLoop::inGate() const 531{ 532 return (gateThread == IOThreadSelf()); 533} 534 535void IOGraphicsWorkLoop::closeGate() 536{ 537 if (gateThread == IOThreadSelf()) 538 { 539 if (!gateCount) panic("gateCount"); 540 gateCount++; 541 } 542 else 543 { 544#if 0 545 AbsoluteTime startTime, endTime; 546 uint64_t nsec; 547 AbsoluteTime_to_scalar(&startTime) = mach_absolute_time(); 548#endif 549 IOLockLock(gateMutex); 550#if 0 551 AbsoluteTime_to_scalar(&endTime) = mach_absolute_time(); 552 SUB_ABSOLUTETIME(&endTime, &startTime); 553 absolutetime_to_nanoseconds(endTime, &nsec); 554 nsec /= 1000000ULL; 555 if (nsec >= 50) 556 OSReportWithBacktrace("wsloow %qd ms\n", nsec); 557#endif 558 assert (gateThread == 0); 559 assert (gateCount == 0); 560 if (gateThread) panic("gateThread"); 561 if (gateCount) panic("gateCount"); 562 563 gateThread = IOThreadSelf(); 564 gateCount = 1; 565 if (func) (*func)(this, obj, reference, true); 566 } 567} 568 569void IOGraphicsWorkLoop::openGate() 570{ 571 assert (gateThread == IOThreadSelf()); 572 if (gateThread != IOThreadSelf()) panic("gateThread"); 573 if (1 == gateCount) 574 { 575 if (func) (*func)(this, obj, reference, false); 576 if (gateThread != IOThreadSelf()) panic("gateThread"); 577 if (gateCount != 1) panic("gateCount"); 578 gateThread = NULL; 579 gateCount = 0; 580 IOLockUnlock(gateMutex); 581 return; 582 } 583 gateCount--; 584} 585 586bool IOGraphicsWorkLoop::tryCloseGate() 587{ 588 bool gotit = true; 589 590 if (gateThread == IOThreadSelf()) gateCount++; 591 else 592 { 593 if (!IOLockTryLock(gateMutex)) gotit = false; 594 else 595 { 596 assert (gateThread == 0); 597 assert (gateCount == 0); 598 if (gateThread) panic("gateThread"); 599 if (gateCount) panic("gateCount"); 600 gateThread = IOThreadSelf(); 601 gateCount = 1; 602 if (func) (*func)(this, obj, reference, true); 603 } 604 } 605 return (gotit); 606} 607 608int IOGraphicsWorkLoop::sleepGate(void *event, UInt32 interuptibleType) 609{ 610 int result; 611 uint32_t count; 612 613 assert(gateThread == IOThreadSelf()); 614 if (gateThread != IOThreadSelf()) panic("gateThread"); 615 616 count = gateCount; 617 gateCount = 0; 618 if (func) (*func)(this, obj, reference, false); 619 620 gateThread = NULL; 621 result = IOLockSleep(gateMutex, event, interuptibleType); 622 623 assert (gateThread == 0); 624 assert (gateCount == 0); 625 if (gateThread) panic("gateThread"); 626 if (gateCount) panic("gateCount"); 627 gateThread = IOThreadSelf(); 628 gateCount = count; 629 630 if (func) (*func)(this, obj, reference, true); 631 return (result); 632} 633 634int IOGraphicsWorkLoop::sleepGate(void *event, AbsoluteTime deadline, UInt32 interuptibleType) 635{ 636 int result; 637 uint32_t count; 638 639 assert(gateThread == IOThreadSelf()); 640 641 count = gateCount; 642 gateCount = 0; 643 if (func) (*func)(this, obj, reference, false); 644 645 gateThread = NULL; 646 result = IOLockSleepDeadline(gateMutex, event, deadline, interuptibleType); 647 648 assert (gateThread == 0); 649 assert (gateCount == 0); 650 gateThread = IOThreadSelf(); 651 gateCount = count; 652 653 if (func) (*func)(this, obj, reference, true); 654 655 return (result); 656} 657 658void IOGraphicsWorkLoop::wakeupGate(void *event, bool oneThread) 659{ 660 return (IOLockWakeup(gateMutex, event, oneThread)); 661} 662 663/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 664 665#define SYSLOCK() \ 666 gIOFBSystemWorkLoop->closeGate() 667#define SYSUNLOCK() \ 668 gIOFBSystemWorkLoop->openGate() 669 670#define FCLOCK(fc) \ 671 fc->wl->closeGate() 672#define FCUNLOCK(fc) \ 673 fc->wl->openGate() 674 675#define FBWL(fb) \ 676 fb->__private->controller->wl 677 678#define _FBLOCK(fb) \ 679 FBWL(fb)->closeGate() 680 681#define FBUNLOCK(fb) \ 682 FBWL(fb)->openGate() \ 683 684#if TIME_LOGS 685 686static void TIMELOCK(IOGraphicsWorkLoop * wl, const char * name, const char * fn) 687{ 688 AbsoluteTime startTime, endTime; 689 uint64_t nsec; 690 691 AbsoluteTime_to_scalar(&startTime) = mach_absolute_time(); 692 693 wl->closeGate(); 694 695 AbsoluteTime_to_scalar(&endTime) = mach_absolute_time(); 696 SUB_ABSOLUTETIME(&endTime, &startTime); 697 absolutetime_to_nanoseconds(endTime, &nsec); 698 nsec /= 1000000ULL; 699 if (nsec >= 5) 700 IOLog("%s: %s: sloow %qd ms\n", name, fn, nsec); 701} 702#define FBLOCK(fb) TIMELOCK(FBWL(fb), fb->thisName, __FUNCTION__) 703 704 705#define TIMESTART() \ 706{ \ 707 AbsoluteTime startTime, endTime; \ 708 uint64_t nsec; \ 709 AbsoluteTime_to_scalar(&startTime) = mach_absolute_time(); 710 711#define TIMEEND(name, fmt, args...) \ 712 AbsoluteTime_to_scalar(&endTime) = mach_absolute_time(); \ 713 absolutetime_to_nanoseconds(endTime, &nsec); \ 714 kprintf("%08d [%s]: ", (uint32_t) (nsec / 1000000ULL), name); \ 715 SUB_ABSOLUTETIME(&endTime, &startTime); \ 716 absolutetime_to_nanoseconds(endTime, &nsec); \ 717 nsec /= 1000000ULL; \ 718 kprintf(fmt, ## args , nsec); \ 719} 720 721#else /* !TIME_LOGS */ 722 723#define FBLOCK(fb) _FBLOCK(fb) 724#define TIMELOCK(wl, name, fn) wl->closeGate() 725#define TIMESTART() 726#define TIMEEND(name, fmt, args...) 727 728#endif 729 730#if TIME_CURSOR 731 732#define CURSORLOCK(fb) \ 733 if (!cursorEnable) return; \ 734 AbsoluteTime startTime, endTime; \ 735 uint64_t nsec; \ 736 AbsoluteTime_to_scalar(&startTime) = mach_absolute_time(); \ 737 \ 738 StdFBShmem_t *shmem = GetShmem(fb); \ 739 bool __checkTime = (2 == fb->getPowerState()); \ 740 SETSEMA(shmem); \ 741 FBLOCK(this); \ 742 \ 743 AbsoluteTime_to_scalar(&endTime) = mach_absolute_time(); \ 744 SUB_ABSOLUTETIME(&endTime, &startTime); \ 745 absolutetime_to_nanoseconds(endTime, &nsec); \ 746 nsec /= 1000000ULL; \ 747 if (__checkTime && (nsec >= 20)) \ 748 IOLog("%s: %s: cursor lock stall %qd ms\n", fb->thisName, __FUNCTION__, nsec); 749 750#else /* TIME_CURSOR */ 751 752#define CURSORLOCK(fb) \ 753 if (!cursorEnable) return; \ 754 StdFBShmem_t *shmem = GetShmem(fb); \ 755 SETSEMA(shmem); \ 756 FBLOCK(this); \ 757 758#endif /* TIME_CURSOR */ 759 760#define CURSORUNLOCK(fb) \ 761 FBUNLOCK(fb); \ 762 CLEARSEMA(shmem, fb); 763 764 765/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 766 767#define extEntry(allowOffline) _extEntry(false, allowOffline, __FUNCTION__) 768#define extExit(result) _extExit (false, result, __FUNCTION__) 769#define extEntrySys(allowOffline) _extEntry(true, allowOffline, __FUNCTION__) 770#define extExitSys(result) _extExit (true, result, __FUNCTION__) 771 772/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 773 774class IOFramebufferParameterHandler : public IODisplayParameterHandler 775{ 776 OSDeclareDefaultStructors(IOFramebufferParameterHandler) 777 778 OSDictionary * fDisplayParams; 779 IOFramebuffer * fFramebuffer; 780 IODisplay * fDisplay; 781 782public: 783 static IOFramebufferParameterHandler * withFramebuffer( IOFramebuffer * framebuffer ); 784 virtual void free(); 785 786 virtual bool setDisplay( IODisplay * display ); 787 virtual bool doIntegerSet( OSDictionary * params, 788 const OSSymbol * paramName, UInt32 value ); 789 virtual bool doDataSet( const OSSymbol * paramName, OSData * value ); 790 virtual bool doUpdate( void ); 791 792 void displayModeChange( void ); 793}; 794 795class IOFramebufferSensor : public IOService 796{ 797 OSDeclareDefaultStructors(IOFramebufferSensor) 798 799 IOFramebuffer * fFramebuffer; 800 801public: 802 static IOFramebufferSensor * withFramebuffer( IOFramebuffer * framebuffer ); 803 virtual void free(); 804 805 virtual IOReturn callPlatformFunction( const OSSymbol * functionName, 806 bool waitForFunction, 807 void *param1, void *param2, 808 void *param3, void *param4 ); 809 810 virtual IOReturn callPlatformFunction( const char * functionName, 811 bool waitForFunction, 812 void *param1, void *param2, 813 void *param3, void *param4 ); 814}; 815 816/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 817 818class IOFramebufferI2CInterface : public IOI2CInterface 819{ 820 OSDeclareDefaultStructors(IOFramebufferI2CInterface) 821 822 IOFramebuffer * fFramebuffer; 823 SInt32 fBusID; 824 UInt32 fSupportedTypes; 825 UInt32 fSupportedCommFlags; 826 827public: 828 virtual bool start( IOService * provider ); 829 virtual IOReturn startIO( IOI2CRequest * request ); 830 831 static IOFramebufferI2CInterface * withFramebuffer( IOFramebuffer * framebuffer, 832 OSDictionary * info ); 833 static IOReturn create( IOFramebuffer * framebuffer ); 834}; 835 836/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 837 838#undef super 839#define super IOGraphicsDevice 840 841OSDefineMetaClass( IOFramebuffer, IOGraphicsDevice ) 842OSDefineAbstractStructors( IOFramebuffer, IOGraphicsDevice ) 843 844/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 845 846void IOFramebuffer::fbLock( void ) 847{ 848 FBLOCK(this); 849} 850 851void IOFramebuffer::fbUnlock( void ) 852{ 853 FBUNLOCK(this); 854} 855 856/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 857 858/* 859 * Cursor rendering 860 */ 861 862#include "IOCursorBlits.h" 863 864inline void IOFramebuffer::StdFBDisplayCursor( IOFramebuffer * inst ) 865{ 866 StdFBShmem_t *shmem; 867 IOGBounds saveRect; 868 volatile unsigned char *vramPtr; /* screen data pointer */ 869 unsigned int cursStart; 870 unsigned int cursorWidth; 871 int width; 872 int height; 873 874 shmem = GetShmem(inst); 875 saveRect = shmem->cursorRect; 876 /* Clip saveRect vertical within screen bounds */ 877 if (saveRect.miny < shmem->screenBounds.miny) 878 saveRect.miny = shmem->screenBounds.miny; 879 if (saveRect.maxy > shmem->screenBounds.maxy) 880 saveRect.maxy = shmem->screenBounds.maxy; 881 if (saveRect.minx < shmem->screenBounds.minx) 882 saveRect.minx = shmem->screenBounds.minx; 883 if (saveRect.maxx > shmem->screenBounds.maxx) 884 saveRect.maxx = shmem->screenBounds.maxx; 885 shmem->saveRect = saveRect; /* Remember save rect for RemoveCursor */ 886 887 vramPtr = inst->frameBuffer + 888 (inst->rowBytes * (saveRect.miny - shmem->screenBounds.miny)) + 889 (inst->bytesPerPixel * (saveRect.minx - shmem->screenBounds.minx)); 890 891 width = saveRect.maxx - saveRect.minx; 892 height = saveRect.maxy - saveRect.miny; 893 cursorWidth = shmem->cursorSize[0 != shmem->frame].width; 894 895 cursStart = (saveRect.miny - shmem->cursorRect.miny) * cursorWidth + 896 (saveRect.minx - shmem->cursorRect.minx); 897 898 if (inst->cursorBlitProc) 899 inst->cursorBlitProc( inst, 900 (void *) shmem, 901 vramPtr, 902 cursStart, 903 inst->totalWidth - width, /* vramRow */ 904 cursorWidth - width, /* cursRow */ 905 width, 906 height); 907} 908 909// Description: RemoveCursor erases the cursor by replacing the background 910// image that was saved by the previous call to DisplayCursor. 911// If the frame buffer is cacheable, flush at the end of the 912// drawing operation. 913 914inline void IOFramebuffer::StdFBRemoveCursor( IOFramebuffer * inst ) 915{ 916 StdFBShmem_t *shmem; 917 volatile unsigned char *vramPtr; /* screen data pointer */ 918 unsigned int vramRow; 919 int width; 920 int height; 921 922 shmem = GetShmem(inst); 923 924 /* Clip saveRect vertical within screen bounds */ 925 if ((shmem->saveRect.miny < shmem->screenBounds.miny) 926 || (shmem->saveRect.maxy > shmem->screenBounds.maxy) 927 || (shmem->saveRect.minx < shmem->screenBounds.minx) 928 || (shmem->saveRect.maxx > shmem->screenBounds.maxx)) 929 { 930 IOLog("%s: bad crsr saverect (%d, %d), (%d, %d) - (%d, %d), (%d, %d)\n", 931 inst->thisName, 932 shmem->saveRect.minx, shmem->saveRect.miny, 933 shmem->saveRect.maxx, shmem->saveRect.maxy, 934 shmem->screenBounds.minx, shmem->screenBounds.miny, 935 shmem->screenBounds.maxx, shmem->screenBounds.maxy); 936 return; 937 } 938 939 vramRow = inst->totalWidth; /* Scanline width in pixels */ 940 941 vramPtr = inst->frameBuffer + 942 (inst->rowBytes * (shmem->saveRect.miny - shmem->screenBounds.miny)) 943 + (inst->bytesPerPixel * 944 (shmem->saveRect.minx - shmem->screenBounds.minx)); 945 946 width = shmem->saveRect.maxx - shmem->saveRect.minx; 947 height = shmem->saveRect.maxy - shmem->saveRect.miny; 948 vramRow -= width; 949 950 if (inst->cursorRemoveProc) 951 inst->cursorRemoveProc( inst, (void *)shmem, 952 vramPtr, vramRow, width, height); 953} 954 955inline void IOFramebuffer::RemoveCursor( IOFramebuffer * inst ) 956{ 957 StdFBShmem_t * shmem = GetShmem(inst); 958 959 if (!inst->pagingState) 960 return; 961 962 if (shmem->hardwareCursorActive) 963 { 964 IOGPoint * hs; 965 966 hs = &shmem->hotSpot[0 != shmem->frame]; 967 inst->_setCursorState( 968 shmem->cursorLoc.x - hs->x - shmem->screenBounds.minx, 969 shmem->cursorLoc.y - hs->y - shmem->screenBounds.miny, false ); 970 } 971 else 972 StdFBRemoveCursor(inst); 973} 974 975inline void IOFramebuffer::DisplayCursor( IOFramebuffer * inst ) 976{ 977 IOGPoint * hs; 978 StdFBShmem_t * shmem = GetShmem(inst); 979 SInt32 x, y; 980 981 if (!inst->pagingState) 982 return; 983 984 hs = &shmem->hotSpot[0 != shmem->frame]; 985 x = shmem->cursorLoc.x - hs->x; 986 y = shmem->cursorLoc.y - hs->y; 987 988 if (shmem->hardwareCursorActive) 989 inst->_setCursorState( x - shmem->screenBounds.minx, 990 y - shmem->screenBounds.miny, true ); 991 else 992 { 993 shmem->cursorRect.maxx = (shmem->cursorRect.minx = x) 994 + shmem->cursorSize[0 != shmem->frame].width; 995 shmem->cursorRect.maxy = (shmem->cursorRect.miny = y) 996 + shmem->cursorSize[0 != shmem->frame].height; 997 StdFBDisplayCursor(inst); 998 shmem->oldCursorRect = shmem->cursorRect; 999 } 1000} 1001 1002inline void IOFramebuffer::SysHideCursor( IOFramebuffer * inst ) 1003{ 1004 if (!GetShmem(inst)->cursorShow++) 1005 RemoveCursor(inst); 1006} 1007 1008inline void IOFramebuffer::SysShowCursor( IOFramebuffer * inst ) 1009{ 1010 StdFBShmem_t *shmem; 1011 1012 shmem = GetShmem(inst); 1013 1014 if (shmem->cursorShow) 1015 if (!--(shmem->cursorShow)) 1016 DisplayCursor(inst); 1017} 1018 1019inline void IOFramebuffer::CheckShield( IOFramebuffer * inst ) 1020{ 1021 IOGPoint * hs; 1022 int intersect; 1023 IOGBounds tempRect; 1024 StdFBShmem_t * shmem = GetShmem(inst); 1025 1026 /* Calculate temp cursorRect */ 1027 hs = &shmem->hotSpot[0 != shmem->frame]; 1028 tempRect.maxx = (tempRect.minx = (shmem->cursorLoc).x - hs->x) 1029 + shmem->cursorSize[0 != shmem->frame].width; 1030 tempRect.maxy = (tempRect.miny = (shmem->cursorLoc).y - hs->y) 1031 + shmem->cursorSize[0 != shmem->frame].height; 1032 1033 intersect = TOUCHBOUNDS(tempRect, shmem->shieldRect); 1034 if (intersect != shmem->shielded) 1035 (shmem->shielded = intersect) ? 1036 SysHideCursor(inst) : SysShowCursor(inst); 1037} 1038 1039#include "AppleLogo.h" 1040#include "AppleLogo2x.h" 1041 1042/************************************************************** 1043 LZSS.C -- A Data Compression Program 1044*************************************************************** 1045 4/6/1989 Haruhiko Okumura 1046 Use, distribute, and modify this program freely. 1047 Please send me your improved versions. 1048 PC-VAN SCIENCE 1049 NIFTY-Serve PAF01022 1050 CompuServe 74050,1022 1051 1052**************************************************************/ 1053#define N 4096 /* size of ring buffer - must be power of 2 */ 1054#define F 18 /* upper limit for match_length */ 1055#define THRESHOLD 2 /* encode string into position and length 1056 if match_length is greater than this */ 1057 1058static void IOFramebufferBootInitFB(IOVirtualAddress frameBuffer, 1059 uint32_t framebufferWidth, uint32_t framebufferHeight, 1060 uint32_t totalWidth, uint32_t consoleDepth, uint8_t logo) 1061{ 1062 const uint8_t * src; 1063 uint32_t * out; 1064 uint32_t gray, data, x, y, ox, oy, sx, lw, lh; 1065 1066 if (gIOFBBlackBoot) 1067 gray = logo = 0; 1068 else if (32 == consoleDepth) 1069 gray = 0xbfbfbf; 1070 else if (30 == consoleDepth) 1071#define g10 ((0xbf << 2) | (0xbf >> 6)) 1072 gray = (g10 | (g10 << 10 ) | (g10 << 20)); 1073 else 1074 return; 1075 1076 src = (2 == logo) ? &gAppleLogo2XPacked[0] : &gAppleLogoPacked[0]; 1077 lw = (2 == logo) ? kAppleLogo2XWidth : kAppleLogoWidth; 1078 lh = (2 == logo) ? kAppleLogo2XHeight : kAppleLogoHeight; 1079 1080 ox = (framebufferWidth - lw) / 2; 1081 oy = (framebufferHeight - lh) / 2; 1082 1083 out = (uint32_t *) frameBuffer; 1084 1085 /* ring buffer of size N, with extra F-1 bytes to aid string comparison */ 1086 uint8_t text_buf[N + F - 1]; 1087 int32_t i, j, k, r; 1088 uint32_t flags; 1089 1090 for (i = 0; i < N - F; i++) text_buf[i] = ' '; 1091 r = N - F; 1092 flags = 0; 1093 j = 0; 1094 k = INT32_MAX; 1095 1096 for (y = 0; y < framebufferHeight; y++) 1097 { 1098 if ((!logo) || (y < oy) || (y >= (oy + lh))) 1099 { 1100 for (x = 0; x < framebufferWidth; x++) out[x] = gray; 1101 } 1102 else 1103 { 1104 for (x = 0; x < ox; x++) out[x] = gray; 1105 for (sx = 0; sx < lw; sx++) 1106 { 1107 if (k > j) { 1108 if (((flags >>= 1) & 0x100) == 0) { 1109 data = *src++; 1110 flags = data | 0xFF00; /* uses higher byte cleverly */ 1111 } /* to count eight */ 1112 if (flags & 1) data = *src++; 1113 else { 1114 i = *src++; 1115 j = *src++; 1116 i |= ((j & 0xF0) << 4); 1117 j = (j & 0x0F) + THRESHOLD; 1118 k = 0; 1119 } 1120 } 1121 if (k <= j) { 1122 data = text_buf[(i + k) & (N - 1)]; 1123 k++; 1124 } 1125 text_buf[r++] = data; 1126 r &= (N - 1); 1127 1128 if (32 == consoleDepth) 1129 data |= (data << 8) | (data << 16); 1130 else if (30 == consoleDepth) 1131 data |= (data << 10) | (data << 20); 1132 out[x++] = data; 1133 } 1134 for (; x < framebufferWidth; x++) out[x] = gray; 1135 } 1136 out += totalWidth; 1137 } 1138} 1139 1140void IOFramebuffer::setupCursor(void) 1141{ 1142 StdFBShmem_t * shmem = GetShmem(this); 1143 IOPixelInformation * info = &__private->pixelInfo; 1144 volatile unsigned char * bits; 1145 IOByteCount cursorImageBytes, waitCursorImageBytes; 1146 1147 rowBytes = info->bytesPerRow; 1148 totalWidth = (rowBytes * 8) / info->bitsPerPixel; 1149 bytesPerPixel = info->bitsPerPixel / 8; 1150 if (bytesPerPixel > 4) 1151 __private->cursorBytesPerPixel = 4; 1152 else 1153 __private->cursorBytesPerPixel = bytesPerPixel; 1154 1155 frameBuffer = (volatile unsigned char *) (vramMap ? vramMap->getVirtualAddress() : NULL); 1156 __private->framebufferWidth = info->activeWidth; 1157 __private->framebufferHeight = info->activeHeight; 1158 if (info->bitsPerComponent > 8) 1159 __private->consoleDepth = info->componentCount * info->bitsPerComponent; 1160 else 1161 __private->consoleDepth = info->bitsPerPixel; 1162 1163 if (shmem) 1164 { 1165 DEBG1(thisName, " setupCursor online %d, (%d, %d) - (%d, %d)\n", 1166 __private->online, 1167 shmem->screenBounds.minx, shmem->screenBounds.miny, 1168 shmem->screenBounds.maxx, shmem->screenBounds.maxy); 1169 if (__private->online && 1170 ((shmem->screenBounds.maxx == shmem->screenBounds.minx) 1171 || (shmem->screenBounds.maxy == shmem->screenBounds.miny))) 1172 { 1173 // a default if no one calls IOFBSetBounds() 1174 shmem->screenBounds.minx = 0; 1175 shmem->screenBounds.miny = 0; 1176 shmem->screenBounds.maxx = info->activeWidth; 1177 shmem->screenBounds.maxy = info->activeHeight; 1178 __private->screenBounds[0] = shmem->screenBounds; 1179 __private->screenBounds[1] = shmem->screenBounds; 1180 1181 shmem->cursorSize[0] = maxCursorSize; 1182 shmem->cursorSize[1] = __private->maxWaitCursorSize; 1183 shmem->cursorSize[2] = __private->maxWaitCursorSize; 1184 shmem->cursorSize[3] = __private->maxWaitCursorSize; 1185 } 1186 __private->actualVBLCount = 0; 1187 1188 cursorImageBytes = maxCursorSize.width * maxCursorSize.height 1189 * __private->cursorBytesPerPixel; 1190 waitCursorImageBytes = __private->maxWaitCursorSize.width * __private->maxWaitCursorSize.height 1191 * __private->cursorBytesPerPixel; 1192 bits = shmem->cursor; 1193 1194 for (UInt32 i = 0; i < __private->numCursorFrames; i++) 1195 { 1196 __private->cursorFlags[i] = kIOFBCursorImageNew; 1197 __private->cursorImages[i] = bits; 1198 bits += i ? waitCursorImageBytes : cursorImageBytes; 1199 } 1200 if (info->bitsPerPixel <= 8) 1201 { 1202 for (UInt32 i = 0; i < __private->numCursorFrames; i++) 1203 { 1204 __private->cursorMasks[i] = bits; 1205 bits += i ? waitCursorImageBytes : cursorImageBytes; 1206 } 1207 } 1208 cursorSave = bits; 1209 cursorEnable = true; 1210 } 1211 1212 cursorBlitProc = (CursorBlitProc) NULL; 1213 cursorRemoveProc = (CursorRemoveProc) NULL; 1214 if (vramMap) switch (info->bitsPerPixel) 1215 { 1216 case 8: 1217 if (colorConvert.t._bm256To38SampleTable 1218 && colorConvert.t._bm38To256SampleTable) 1219 { 1220 cursorBlitProc = (CursorBlitProc) StdFBDisplayCursor8P; 1221 cursorRemoveProc = (CursorRemoveProc) StdFBRemoveCursor8; 1222 } 1223 break; 1224 case 16: 1225 if (colorConvert.t._bm34To35SampleTable 1226 && colorConvert.t._bm35To34SampleTable) 1227 { 1228 cursorBlitProc = (CursorBlitProc) StdFBDisplayCursor555; 1229 cursorRemoveProc = (CursorRemoveProc) StdFBRemoveCursor16; 1230 } 1231 break; 1232 case 32: 1233 case 64: 1234 if (10 == info->bitsPerComponent) 1235 cursorBlitProc = (CursorBlitProc) StdFBDisplayCursor30Axxx; 1236 else 1237 cursorBlitProc = (CursorBlitProc) StdFBDisplayCursor32Axxx; 1238 cursorRemoveProc = (CursorRemoveProc) StdFBRemoveCursor32; 1239 break; 1240 default: 1241 break; 1242 } 1243 1244 if (!cursorBlitProc) DEBG1(thisName, " can't do sw cursor at depth %d\n", 1245 (uint32_t) info->bitsPerPixel); 1246} 1247 1248void IOFramebuffer::stopCursor( void ) 1249{ 1250 cursorEnable = false; 1251 cursorBlitProc = (CursorBlitProc) NULL; 1252 cursorRemoveProc = (CursorRemoveProc) NULL; 1253} 1254 1255IOReturn IOFramebuffer::extCreateSharedCursor( 1256 OSObject * target, void * reference, IOExternalMethodArguments * args) 1257{ 1258 IOFramebuffer * inst = (IOFramebuffer *) target; 1259 int version = args->scalarInput[0]; 1260 int maxWidth = args->scalarInput[1]; 1261 int maxWaitWidth = args->scalarInput[2]; 1262 1263 IOReturn err; 1264 1265 if ((err = inst->extEntry(true))) 1266 return (err); 1267 1268 err = inst->createSharedCursor( version, maxWidth, maxWaitWidth ); 1269 1270 inst->extExit(err); 1271 1272 return (err); 1273} 1274 1275bool IOFramebuffer::deepFramebuffer(IOPixelInformation * pixelInfo) 1276{ 1277 if ((pixelInfo->pixelType == kIORGBSignedFloatingPointPixels) 1278 || (pixelInfo->bitsPerComponent > 8)) 1279 return (true); 1280 else 1281 return (false); 1282} 1283 1284bool IOFramebuffer::validFramebuffer(IOPixelInformation * pixelInfo) 1285{ 1286 if (pixelInfo->pixelType == kIORGBSignedDirectPixels) 1287 return (false); 1288 1289 if (deepFramebuffer(pixelInfo)) 1290 return (true); 1291 1292 return (true); 1293} 1294 1295IOIndex IOFramebuffer::closestDepth(IODisplayModeID mode, IOPixelInformation * matchInfo) 1296{ 1297 IOReturn err; 1298 IOIndex depth; 1299 IOPixelInformation pixelInfo; 1300 1301 depth = 0; 1302 for (depth = 0;; depth++) 1303 { 1304 err = getPixelInformation(mode, depth, kIOFBSystemAperture, &pixelInfo); 1305 if (kIOReturnSuccess != err) 1306 { 1307 depth = 0; 1308 break; 1309 } 1310 if ((pixelInfo.bitsPerPixel == matchInfo->bitsPerPixel) 1311 && (pixelInfo.pixelType == matchInfo->pixelType) 1312 && (pixelInfo.componentCount == matchInfo->componentCount) 1313 && (pixelInfo.bitsPerComponent == matchInfo->bitsPerComponent)) 1314 break; 1315 } 1316 return (depth); 1317} 1318 1319IOReturn IOFramebuffer::extGetPixelInformation( 1320 OSObject * target, void * reference, IOExternalMethodArguments * args) 1321{ 1322 IOFramebuffer * inst = (IOFramebuffer *) target; 1323 IODisplayModeID displayMode = args->scalarInput[0]; 1324 IOIndex depth = args->scalarInput[1]; 1325 IOPixelAperture aperture = args->scalarInput[2]; 1326 IOPixelInformation * pixelInfo = (IOPixelInformation *) args->structureOutput; 1327 1328 IOReturn err; 1329 1330 if ((err = inst->extEntry(false))) 1331 return (err); 1332 1333 err = inst->getPixelInformation(displayMode, depth, aperture, pixelInfo); 1334 1335 inst->extExit(err); 1336 1337 return (err); 1338} 1339 1340IOReturn IOFramebuffer::extGetCurrentDisplayMode( 1341 OSObject * target, void * reference, IOExternalMethodArguments * args) 1342{ 1343 IOFramebuffer * inst = (IOFramebuffer *) target; 1344 IODisplayModeID displayMode; 1345 IOIndex depth; 1346 1347 IOReturn err; 1348 1349 if ((err = inst->extEntry(false))) 1350 return (err); 1351 1352 if (kIODisplayModeIDInvalid != inst->__private->aliasMode) 1353 { 1354 displayMode = inst->__private->aliasMode; 1355 depth = inst->__private->currentDepth; 1356 } 1357 else 1358 { 1359 err = inst->getCurrentDisplayMode(&displayMode, &depth); 1360 } 1361 1362 inst->extExit(err); 1363 1364 args->scalarOutput[0] = displayMode; 1365 args->scalarOutput[1] = depth; 1366 1367 return (err); 1368} 1369 1370IOReturn IOFramebuffer::extSetStartupDisplayMode( 1371 OSObject * target, void * reference, IOExternalMethodArguments * args) 1372{ 1373 IOFramebuffer * inst = (IOFramebuffer *) target; 1374 IODisplayModeID displayMode = args->scalarInput[0]; 1375 IOIndex depth = args->scalarInput[1]; 1376 1377 IOReturn err; 1378 1379 if ((err = inst->extEntry(false))) 1380 return (err); 1381 1382 err = inst->setStartupDisplayMode( displayMode, depth ); 1383 1384 if (inst->__private->online && (kIODetailedTimingValid & inst->__private->timingInfo.flags)) 1385 { 1386 OSData * data = OSData::withBytes( 1387 &inst->__private->timingInfo, sizeof(inst->__private->timingInfo)); 1388 if (data) 1389 { 1390 inst->setPreference(NULL, gIOFBStartupModeTimingKey, data); 1391 data->release(); 1392 } 1393 } 1394 1395 inst->extExit(err); 1396 1397 return (err); 1398} 1399 1400#if 0 1401static void IOFBLogGamma( 1402 uint32_t channelCount, uint32_t srcDataCount, 1403 uint32_t dataWidth, const void * data) 1404{ 1405 uint32_t c, i; 1406 uint16_t * words; 1407 words = ((uint16_t *)data); 1408 kprintf("/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */"); 1409 for (c = 0; c < channelCount; c++) 1410 { 1411 for (i = 0; i < srcDataCount; i++) 1412 { 1413 if( 0 == (i & 15)) 1414 kprintf("\n "); 1415 kprintf("0x%04x,", words[i]); 1416 } 1417 words += i; 1418 kprintf("\n\n\n"); 1419 } 1420} 1421#endif 1422 1423enum { kIOFBGammaPointCountMax = 256 }; 1424enum { kIOFBGammaDesiredError = 127 }; 1425 1426struct IOFBLineSeg 1427{ 1428 // [start end] 1429 uint16_t start; 1430 uint16_t end; 1431 uint16_t dist; 1432 uint16_t split; 1433}; 1434typedef struct IOFBLineSeg IOFBLineSeg; 1435 1436static void 1437IOFBSegDist(const uint16_t data[], IOFBLineSeg * seg) 1438{ 1439 uint16_t start; 1440 uint16_t end; 1441 uint16_t idx; 1442 uint16_t interp; 1443 int16_t dist; 1444 1445 seg->dist = 0; 1446 start = seg->start; 1447 end = seg->end; 1448 for (idx = start + 1; idx < end; idx++) 1449 { 1450 interp = data[start] + ((data[end] - data[start]) * (idx - start)) / (end - start); 1451 dist = data[idx] - interp; 1452 if (dist < 0) dist = -dist; 1453 if (dist > seg->dist) 1454 { 1455 seg->dist = dist; 1456 seg->split = idx; 1457 } 1458 } 1459} 1460 1461static void 1462IOFBSegInit(const uint16_t data[], IOFBLineSeg * seg, uint16_t start, uint16_t end) 1463{ 1464 seg->start = start; 1465 seg->end = end; 1466 IOFBSegDist(data, seg); 1467} 1468 1469static void 1470IOFBSimplifySegs(const uint16_t data[], uint16_t srcDataCount, 1471 uint16_t desiredError, uint16_t * maxError, 1472 IOFBLineSeg * segs, uint16_t count, uint16_t maxCount, 1473 IOFBBootGamma * bootGamma) 1474{ 1475 IOFBGamma * channelGamma; 1476 uint16_t idx; 1477 uint16_t furthest; 1478 uint16_t start; 1479 1480 while (count < maxCount) 1481 { 1482 furthest = 0; 1483 for (idx = 1; idx < count; idx++) 1484 { 1485 if (segs[idx].dist > segs[furthest].dist) furthest = idx; 1486 } 1487 if (segs[furthest].dist <= desiredError) break; 1488 bcopy(&segs[furthest+1], &segs[furthest+2], (count - furthest - 1) * sizeof(IOFBLineSeg)); 1489 count++; 1490 IOFBSegInit(data, &segs[furthest+1], segs[furthest].split, segs[furthest].end); 1491 segs[furthest].end = segs[furthest].split; 1492 IOFBSegDist(data, &segs[furthest]); 1493 } 1494 1495 *maxError = 0; 1496 channelGamma = &bootGamma->gamma.red; 1497 for (idx = 0; idx < count; idx++) 1498 { 1499 if (segs[idx].dist > *maxError) 1500 { 1501 *maxError = segs[idx].dist; 1502 //IOLog("max error seg 0x%x, 0x%x count %d, target %d\n", segs[idx].start, segs[idx].end, count, maxCount); 1503 } 1504 start = segs[idx].start % srcDataCount; 1505 if (!start) 1506 { 1507 if (segs[idx].start) 1508 { 1509 channelGamma = (typeof(channelGamma)) &channelGamma->points[channelGamma->pointCount]; 1510 } 1511 channelGamma->pointCount = 0; 1512 continue; 1513 } 1514 channelGamma->points[channelGamma->pointCount].in = 1515 (start * 65536 / srcDataCount) 1516 | (start * 65536 / srcDataCount / srcDataCount); 1517 channelGamma->points[channelGamma->pointCount].out = data[segs[idx].start]; 1518 channelGamma->pointCount++; 1519 } 1520} 1521 1522static bool 1523IOFBCompressGamma( 1524 IOFBBootGamma * bootGamma, 1525 uint16_t channelCount, uint16_t srcDataCount, 1526 uint16_t dataWidth, const void * _data, 1527 uint16_t desiredError, uint16_t maxCount, 1528 uint16_t * maxError) 1529{ 1530 IOFBGamma * channelGamma; 1531 const uint16_t * data = (typeof(data)) _data; 1532 IOFBLineSeg * segs; 1533 uint16_t idx; 1534 1535 if ((3 != channelCount) || (16 != dataWidth)) return (false); 1536 1537 maxCount += 3; 1538 segs = IONew(IOFBLineSeg, maxCount); 1539 if (!segs) return (false); 1540 1541 data = (typeof(data)) _data; 1542 1543 for (idx = 0; idx < 3; idx++) IOFBSegInit(data, &segs[idx], idx * srcDataCount, ((idx + 1) * srcDataCount) - 1); 1544 1545 IOFBSimplifySegs(data, srcDataCount, desiredError, maxError, 1546 segs, 3, maxCount, 1547 bootGamma); 1548 1549 IODelete(segs, IOFBLineSeg, maxCount); 1550 1551 channelGamma = &bootGamma->gamma.red; 1552 for (idx = 0; idx < channelCount; idx++) 1553 { 1554 channelGamma = (typeof(channelGamma)) &channelGamma->points[channelGamma->pointCount]; 1555 } 1556 bootGamma->length = ((uintptr_t) channelGamma) - ((uintptr_t) bootGamma); 1557 1558 return (true); 1559} 1560 1561 1562static void __unused 1563IOFBDecompressGamma(const IOFBBootGamma * bootGamma, uint16_t * data, uint16_t count) 1564{ 1565 const IOFBGamma * channelGamma; 1566 uint16_t channel, idx, maxIdx, seg; 1567 uint16_t startIn, startOut, point; 1568 uint16_t endIn, endOut; 1569 1570 maxIdx = count - 1; 1571 channelGamma = &bootGamma->gamma.red; 1572 for (channel = 0; channel < 3; channel++) 1573 { 1574 seg = 0; 1575 startIn = 0; 1576 startOut = 0x0000; 1577 endIn = 0; 1578 endOut = 0; 1579 for (idx = 0; idx <= maxIdx; idx++) 1580 { 1581 point = idx * 65535 / maxIdx; 1582 if ((point >= endIn) && (idx != maxIdx)) 1583 { 1584 startIn = endIn; 1585 startOut = endOut; 1586 if (seg < channelGamma->pointCount) 1587 { 1588 endIn = channelGamma->points[seg].in; 1589 endOut = channelGamma->points[seg].out; 1590 seg++; 1591 } 1592 else endIn = endOut = 0xFFFF; 1593 } 1594 data[channel * count + idx] = startOut + ((endOut - startOut) * (point - startIn)) / (endIn - startIn); 1595 } 1596 channelGamma = (typeof(channelGamma)) &channelGamma->points[channelGamma->pointCount]; 1597 } 1598} 1599 1600void IOFramebuffer::saveGammaTables(void) 1601{ 1602 IORegistryEntry * options; 1603 const OSSymbol * sym; 1604 IOFBBootGamma * bootGamma; 1605 IOFramebuffer * fb; 1606 OSNumber * num; 1607 OSData * data; 1608 uint32_t maxCount; 1609 uint16_t maxError; 1610 1611 options = IORegistryEntry::fromPath("/options", gIODTPlane); 1612 if (!options) return; 1613 1614 maxCount = (gIOFBBacklightDisplayCount + gIOFBDisplayCount); 1615 if (!maxCount) return; 1616 maxCount = ((0x700 - (maxCount * sizeof(IOFBBootGamma))) / sizeof(IOFBGammaPoint) / maxCount); 1617 if (maxCount > kIOFBGammaPointCountMax) maxCount = kIOFBGammaPointCountMax; 1618 1619 bootGamma = (typeof(bootGamma)) IOMalloc(sizeof(IOFBBootGamma) 1620 + maxCount * sizeof(IOFBGammaPoint)); 1621 if (!bootGamma) return; 1622 1623 data = OSData::withCapacity(512); 1624 if (!data) return; 1625 1626 for (UInt32 index = 0; 1627 (fb = (IOFramebuffer *) gAllFramebuffers->getObject(index)); 1628 index++) 1629 { 1630 FBLOCK(fb); 1631 if (fb->__private->display) do 1632 { 1633 bootGamma->vendor = 0; 1634 bootGamma->product = 0; 1635 bootGamma->serial = 0; 1636 bootGamma->length = 0; 1637 bootGamma->resvA = 0; 1638 bootGamma->resvB = 0; 1639 1640 if ((num = OSDynamicCast(OSNumber, fb->__private->display->getProperty(kDisplayVendorID)))) 1641 bootGamma->vendor = num->unsigned32BitValue(); 1642 if ((num = OSDynamicCast(OSNumber, fb->__private->display->getProperty(kDisplayProductID)))) 1643 bootGamma->product = num->unsigned32BitValue(); 1644 if ((num = OSDynamicCast(OSNumber, fb->__private->display->getProperty(kDisplaySerialNumber)))) 1645 bootGamma->serial = num->unsigned32BitValue(); 1646#if 0 1647 IOFBLogGamma(fb->__private->rawGammaChannelCount, 1648 fb->__private->rawGammaDataCount, 1649 fb->__private->rawGammaDataWidth, 1650 fb->__private->rawGammaData); 1651#endif 1652 if (IOFBCompressGamma(bootGamma, 1653 fb->__private->rawGammaChannelCount, 1654 fb->__private->rawGammaDataCount, 1655 fb->__private->rawGammaDataWidth, 1656 fb->__private->rawGammaData, 1657 kIOFBGammaDesiredError, maxCount, 1658 &maxError)) 1659 { 1660 DEBG1(fb->thisName, " compressed gamma %d max error 0x%04x\n", bootGamma->length, maxError); 1661 if (bootGamma->gamma.red.pointCount) 1662 { 1663 data->appendBytes(bootGamma, bootGamma->length); 1664 } 1665 } 1666 } 1667 while (false); 1668 FBUNLOCK(fb); 1669 } 1670 IOFree(bootGamma, sizeof(IOFBBootGamma) 1671 + maxCount * sizeof(IOFBGammaPoint)); 1672 sym = OSSymbol::withCStringNoCopy(kIOFBBootGammaKey); 1673 if (sym && data->getLength()) 1674 { 1675 options->setProperty(sym, data); 1676 sym->release(); 1677 } 1678 data->release(); 1679 options->release(); 1680} 1681 1682IOReturn IOFramebuffer::extSetGammaTable( 1683 OSObject * target, void * reference, IOExternalMethodArguments * args) 1684{ 1685 IOFramebuffer * inst = (IOFramebuffer *) target; 1686 UInt32 channelCount = args->scalarInput[0]; 1687 UInt32 dataCount = args->scalarInput[1]; 1688 UInt32 dataWidth = args->scalarInput[2]; 1689 IOReturn err; 1690 IOByteCount dataLen; 1691 1692 if ((err = inst->extEntry(true))) 1693 return (err); 1694 1695 dataLen = (dataWidth + 7) / 8; 1696 dataLen *= dataCount * channelCount; 1697 1698 if (dataLen != inst->__private->rawGammaDataLen) 1699 { 1700 if (inst->__private->rawGammaDataLen) 1701 IODelete(inst->__private->rawGammaData, UInt8, inst->__private->rawGammaDataLen); 1702 inst->__private->rawGammaData = IONew(UInt8, dataLen); 1703 inst->__private->rawGammaDataLen = dataLen; 1704 } 1705 1706 if (!inst->__private->rawGammaData) 1707 err = kIOReturnNoMemory; 1708 else 1709 { 1710 inst->__private->rawGammaChannelCount = channelCount; 1711 inst->__private->rawGammaDataCount = dataCount; 1712 inst->__private->rawGammaDataWidth = dataWidth; 1713 1714 if (args->structureInputDescriptor) 1715 { 1716 if (dataLen != args->structureInputDescriptor->getLength()) 1717 err = kIOReturnBadArgument; 1718 else 1719 { 1720 err = args->structureInputDescriptor->prepare(kIODirectionOut); 1721 if ((kIOReturnSuccess == err) 1722 && (dataLen != args->structureInputDescriptor->readBytes( 1723 0, inst->__private->rawGammaData, dataLen))) 1724 { 1725 err = kIOReturnVMError; 1726 } 1727 args->structureInputDescriptor->complete(); 1728 } 1729 } 1730 else 1731 { 1732 if (dataLen == args->structureInputSize) 1733 bcopy(args->structureInput, inst->__private->rawGammaData, dataLen); 1734 else 1735 err = kIOReturnBadArgument; 1736 } 1737 if (kIOReturnSuccess == err) 1738 { 1739#if 0 1740 IOFBLogGamma(inst->__private->rawGammaChannelCount, 1741 inst->__private->rawGammaDataCount, 1742 inst->__private->rawGammaDataWidth, 1743 inst->__private->rawGammaData); 1744#endif 1745 err = inst->updateGammaTable(channelCount, dataCount, dataWidth, inst->__private->rawGammaData); 1746 } 1747 } 1748#if 0 1749DEBG1(inst->thisName, " extSetGammaTable(%x) online %d %ld %ld data %x\n", 1750 err, inst->__private->online, 1751 channelCount, dataCount, 1752 *((uint32_t *) inst->__private->rawGammaData)); 1753#endif 1754 1755 if (!inst->__private->gammaSet) 1756 { 1757 gIOFBGrayValue = kIOFBGrayValue; 1758 inst->__private->gammaSet = 1; 1759 } 1760 1761 inst->extExit(err); 1762 1763 return (err); 1764} 1765 1766IOReturn IOFramebuffer::updateGammaTable( 1767 UInt32 channelCount, UInt32 srcDataCount, 1768 UInt32 dataWidth, const void * data, 1769 bool immediate) 1770{ 1771 IOReturn err = kIOReturnBadArgument; 1772 IOByteCount dataLen; 1773 UInt16 * channelData; 1774 UInt32 dataCount; 1775 UInt32 tryWidth; 1776 UInt8 * table = NULL; 1777 bool needAlloc; 1778 bool gammaHaveScale = ((1 << 16) != __private->gammaScale[0]) 1779 || ((1 << 16) != __private->gammaScale[1]) 1780 || ((1 << 16) != __private->gammaScale[2]) 1781 || ((1 << 16) != __private->gammaScale[3]); 1782 const uint32_t * adjustParams = NULL; 1783 const uint32_t * adjustNext = NULL; 1784 uint32_t gammaThresh; 1785 uint32_t gammaAdjust; 1786 1787 if (GAMMA_ADJ && gIOGraphicsControl && (__private->desiredGammaDataWidth <= 8)) 1788 { 1789 static const uint32_t _params[] = { 138, 3, 256, 4 }; 1790 adjustParams = &_params[0]; 1791 } 1792 else 1793 { 1794 gammaThresh = -1U; 1795 gammaAdjust = 0; 1796 } 1797 do 1798 { 1799 if (!__private->online) 1800 { 1801 DEBG1(thisName, " offline updateGammaTable\n"); 1802 err = kIOReturnOffline; 1803 break; 1804 } 1805 if (dataWidth != 16) 1806 break; 1807 1808 if (!__private->desiredGammaDataWidth) 1809 { 1810 __private->desiredGammaDataWidth = dataWidth; 1811 __private->desiredGammaDataCount = srcDataCount; 1812 } 1813 1814 dataCount = __private->desiredGammaDataCount; 1815 dataLen = (__private->desiredGammaDataWidth + 7) / 8; 1816 dataLen *= dataCount * channelCount; 1817 dataLen += __private->gammaHeaderSize; 1818 1819 needAlloc = (0 == __private->gammaDataLen); 1820 if (!needAlloc) 1821 { 1822 table = __private->gammaData; 1823 if (__private->gammaDataLen != dataLen) 1824 { 1825 IODelete(table, UInt8, __private->gammaDataLen); 1826 __private->gammaData = NULL; 1827 needAlloc = true; 1828 } 1829 __private->gammaDataLen = 0; 1830 __private->gammaNeedSet = false; 1831 } 1832 1833 if (needAlloc) 1834 { 1835 table = IONew(UInt8, dataLen); 1836 if (!table) 1837 { 1838 err = kIOReturnNoMemory; 1839 continue; 1840 } 1841 __private->gammaData = table; 1842 } 1843 1844 __private->gammaChannelCount = channelCount; 1845 __private->gammaDataCount = dataCount; 1846 1847 table += __private->gammaHeaderSize; 1848 1849 tryWidth = __private->desiredGammaDataWidth; 1850 1851#if 0 1852 OSData * ddata; 1853 if (data) 1854 { 1855 ddata = OSData::withBytes((void *)data, srcDataCount*channelCount*sizeof(UInt16)); 1856 if (ddata) 1857 { 1858 setProperty("GammaIn", ddata); 1859 ddata->release(); 1860 } 1861 } 1862 ddata = OSData::withBytesNoCopy(table, dataLen - __private->gammaHeaderSize); 1863 if (ddata) 1864 { 1865 setProperty("GammaOut", ddata); 1866 ddata->release(); 1867 } 1868#endif 1869 1870 if ((__private->desiredGammaDataCount == dataCount) 1871 && (tryWidth == dataWidth) 1872 && !gammaHaveScale 1873 && data 1874 && !adjustParams) 1875 bcopy(data, table, dataLen - __private->gammaHeaderSize); 1876 else 1877 { 1878 uint32_t pin, pt5, in, out, channel, idx, maxSrc, maxDst, interpCount; 1879 int64_t value, value2; 1880 1881 pin = (1 << tryWidth) - 1; 1882 pt5 = 0; //(1 << (tryWidth - 1)); // truncate not round 1883 if (gammaHaveScale) 1884 dataWidth += 32; 1885 1886 channelData = (UInt16 *) data; 1887 maxSrc = (srcDataCount - 1); 1888 maxDst = (__private->desiredGammaDataCount - 1); 1889 if ((srcDataCount < __private->desiredGammaDataCount) 1890 && (0 == (__private->desiredGammaDataCount % srcDataCount))) 1891 interpCount = __private->desiredGammaDataCount / srcDataCount; 1892 else 1893 interpCount = 0; 1894 1895 for (out = 0, channel = 0; channel < channelCount; channel++) 1896 { 1897 if (adjustParams) 1898 { 1899 gammaThresh = 0; 1900 adjustNext = adjustParams; 1901 } 1902 for (idx = 0; idx <= maxDst; idx++) 1903 { 1904 if (idx >= gammaThresh) 1905 { 1906 gammaThresh = *adjustNext++; 1907 gammaAdjust = *adjustNext++; 1908 } 1909 if (channelData) 1910 { 1911 in = ((idx * maxSrc) + (idx ? (idx - 1) : 0)) / maxDst; 1912 value = (channelData[in] /*+ pt5*/); 1913 if (interpCount && (in < maxSrc)) 1914 { 1915 value2 = (channelData[in+1] /*+ pt5*/); 1916 value += ((value2 - value) * (idx % interpCount) + (interpCount - 1)) / interpCount; 1917 } 1918 } 1919 else 1920 value = (idx * ((1 << dataWidth) - 1)) / maxDst; 1921 if (gammaHaveScale) 1922 { 1923 value = ((value * __private->gammaScale[channel] * __private->gammaScale[3]) + (1U << 31)); 1924 } 1925 value = (value >> (dataWidth - tryWidth)); 1926 if (value) 1927 value += gammaAdjust; 1928 if (value > pin) 1929 value = pin; 1930 1931 if (tryWidth <= 8) 1932 ((UInt8 *) table)[out] = (value & 0xff); 1933 else 1934 ((UInt16 *) table)[out] = value; 1935 out++; 1936 } 1937 if (channelData) channelData += srcDataCount; 1938 } 1939 } 1940 __private->gammaDataWidth = tryWidth; 1941 __private->gammaDataLen = dataLen; 1942 1943 if (ASYNC_GAMMA && !immediate) 1944 { 1945 if (__private->vblThrottle && __private->deferredCLUTSetTimerEvent) 1946 { 1947 AbsoluteTime deadline; 1948 getTimeOfVBL(&deadline, 1); 1949 __private->deferredCLUTSetTimerEvent->wakeAtTime(deadline); 1950 __private->gammaNeedSet = true; 1951 err = kIOReturnSuccess; 1952 } 1953 else if (__private->deferredCLUTSetEvent) 1954 { 1955 __private->gammaNeedSet = true; 1956 err = kIOReturnSuccess; 1957 } 1958 } 1959 if (!__private->gammaNeedSet) 1960 { 1961 err = setGammaTable( __private->gammaChannelCount, __private->gammaDataCount, 1962 __private->gammaDataWidth, __private->gammaData ); 1963 updateCursorForCLUTSet(); 1964 } 1965 } 1966 while (false); 1967 1968 return (err); 1969} 1970 1971 1972IOReturn IOFramebuffer::extSetCLUTWithEntries( 1973 OSObject * target, void * reference, IOExternalMethodArguments * args) 1974{ 1975 IOFramebuffer * inst = (IOFramebuffer *) target; 1976 UInt32 index = args->scalarInput[0]; 1977 IOOptionBits options = args->scalarInput[1]; 1978 IOColorEntry * colors = (IOColorEntry *) args->structureInput; 1979 IOByteCount dataLen = args->structureInputSize; 1980 1981 IOReturn err; 1982 UInt8 * table; 1983 bool needAlloc; 1984 1985 if ((err = inst->extEntry(false))) 1986 return (err); 1987 1988 err = kIOReturnBadArgument; 1989 if (inst->__private->deferredCLUTSetEvent) 1990 { 1991 do 1992 { 1993 needAlloc = (0 == inst->__private->clutDataLen); 1994 if (!needAlloc) 1995 { 1996 if (index || (inst->__private->clutDataLen != dataLen)) 1997 { 1998 inst->checkDeferredCLUTSet(); 1999 needAlloc = true; 2000 } 2001 inst->__private->clutDataLen = 0; 2002 } 2003 2004 if (needAlloc) 2005 { 2006 table = IONew(UInt8, dataLen); 2007 if (!table) 2008 { 2009 err = kIOReturnNoMemory; 2010 continue; 2011 } 2012 inst->__private->clutData = table; 2013 } 2014 else 2015 table = inst->__private->clutData; 2016 2017 inst->__private->clutIndex = index; 2018 inst->__private->clutOptions = options; 2019 inst->__private->clutDataLen = dataLen; 2020 2021 bcopy(colors, table, dataLen); 2022 2023 if (inst->__private->vblThrottle && inst->__private->deferredCLUTSetTimerEvent) 2024 { 2025 AbsoluteTime deadline; 2026 inst->getTimeOfVBL(&deadline, 1); 2027 inst->__private->deferredCLUTSetTimerEvent->wakeAtTime(deadline); 2028 } 2029 2030 err = kIOReturnSuccess; 2031 } 2032 while (false); 2033 } 2034 else 2035 { 2036 err = inst->setCLUTWithEntries( colors, index, 2037 dataLen / sizeof( IOColorEntry), options ); 2038 inst->updateCursorForCLUTSet(); 2039 } 2040 2041 if (inst == gIOFBConsoleFramebuffer) 2042 { 2043 UInt32 count = index + dataLen / sizeof(IOColorEntry); 2044 if (count > 256) 2045 count = 256; 2046 for (; index < count; index++) 2047 { 2048 appleClut8[index * 3 + 0] = colors[index].red >> 8; 2049 appleClut8[index * 3 + 1] = colors[index].green >> 8; 2050 appleClut8[index * 3 + 2] = colors[index].blue >> 8; 2051 } 2052 } 2053 2054 inst->extExit(err); 2055 2056 return (err); 2057} 2058 2059void IOFramebuffer::updateCursorForCLUTSet( void ) 2060{ 2061 if (__private->cursorClutDependent) 2062 { 2063 StdFBShmem_t *shmem = GetShmem(this); 2064 2065 SETSEMA(shmem); 2066 if ((kIOFBHardwareCursorActive == shmem->hardwareCursorActive) 2067 && !shmem->cursorShow) 2068 { 2069 RemoveCursor(this); 2070 setCursorImage( (void *)(uintptr_t) shmem->frame ); 2071 DisplayCursor(this); 2072 } 2073 CLEARSEMA(shmem, this); 2074 } 2075} 2076 2077void IOFramebuffer::deferredCLUTSetInterrupt( OSObject * owner, 2078 IOInterruptEventSource * evtSrc, int intCount ) 2079{ 2080 IOFramebuffer * self = (IOFramebuffer *) owner; 2081 2082 if (self->__private->waitVBLEvent) 2083 { 2084 FBWL(self)->wakeupGate(self->__private->waitVBLEvent, true); 2085 self->__private->waitVBLEvent = 0; 2086 } 2087 2088 self->checkDeferredCLUTSet(); 2089} 2090 2091void IOFramebuffer::deferredCLUTSetTimer(OSObject * owner, IOTimerEventSource * source) 2092{ 2093 IOFramebuffer * self = (IOFramebuffer *) owner; 2094 self->checkDeferredCLUTSet(); 2095} 2096 2097void IOFramebuffer::checkDeferredCLUTSet( void ) 2098{ 2099 IOReturn ret; 2100 bool gammaNeedSet = __private->gammaNeedSet; 2101 IOByteCount clutLen = __private->clutDataLen; 2102 2103 if( !gammaNeedSet && !clutLen) 2104 return; 2105 2106 __private->gammaNeedSet = false; 2107 __private->clutDataLen = 0; 2108 2109 if (gammaNeedSet) 2110 { 2111 ret = setGammaTable( __private->gammaChannelCount, __private->gammaDataCount, 2112 __private->gammaDataWidth, __private->gammaData ); 2113 } 2114 2115 if (clutLen) 2116 { 2117 ret = setCLUTWithEntries( (IOColorEntry *) __private->clutData, __private->clutIndex, 2118 clutLen / sizeof( IOColorEntry), __private->clutOptions ); 2119 2120 IODelete(__private->clutData, UInt8, clutLen); 2121 } 2122 2123 updateCursorForCLUTSet(); 2124} 2125 2126IOReturn IOFramebuffer::createSharedCursor( 2127 int version, int maxWidth, int maxWaitWidth ) 2128{ 2129 StdFBShmem_t * shmem; 2130 UInt32 shmemVersion; 2131 IOByteCount size, maxImageSize, maxWaitImageSize; 2132 UInt32 numCursorFrames; 2133 2134 DEBG(thisName, " vers = %08x, %d x %d\n", 2135 version, maxWidth, maxWaitWidth); 2136 2137 shmemVersion = version & kIOFBShmemVersionMask; 2138 2139 if (shmemVersion == kIOFBTenPtTwoShmemVersion) 2140 { 2141 numCursorFrames = (kIOFBShmemCursorNumFramesMask & version) >> kIOFBShmemCursorNumFramesShift; 2142 2143 setProperty(kIOFBWaitCursorFramesKey, (numCursorFrames - 1), 32); 2144 setProperty(kIOFBWaitCursorPeriodKey, 33333333, 32); /* 30 fps */ 2145 } 2146 else if (shmemVersion == kIOFBTenPtOneShmemVersion) 2147 { 2148 numCursorFrames = 4; 2149 } 2150 else 2151 return (kIOReturnUnsupported); 2152 2153 shmemClientVersion = shmemVersion; 2154 2155 if (__private->cursorFlags) 2156 { 2157 IODelete( __private->cursorFlags, UInt8, __private->numCursorFrames ); 2158 __private->cursorFlags = 0; 2159 } 2160 if (__private->cursorImages) 2161 { 2162 IODelete( __private->cursorImages, volatile unsigned char *, __private->numCursorFrames ); 2163 __private->cursorImages = 0; 2164 } 2165 if (__private->cursorMasks) 2166 { 2167 IODelete( __private->cursorMasks, volatile unsigned char *, __private->numCursorFrames ); 2168 __private->cursorMasks = 0; 2169 } 2170 __private->numCursorFrames = numCursorFrames; 2171 __private->cursorFlags = IONew( UInt8, numCursorFrames ); 2172 __private->cursorImages = IONew( volatile unsigned char *, numCursorFrames ); 2173 __private->cursorMasks = IONew( volatile unsigned char *, numCursorFrames ); 2174 2175 if (!__private->cursorFlags || !__private->cursorImages || !__private->cursorMasks) 2176 return (kIOReturnNoMemory); 2177 2178 bzero(__private->cursorFlags, numCursorFrames * sizeof(UInt8)); 2179 bzero(__private->cursorImages, numCursorFrames * sizeof(volatile unsigned char *)); 2180 bzero(__private->cursorMasks, numCursorFrames * sizeof(volatile unsigned char *)); 2181 2182 maxImageSize = (maxWidth * maxWidth * kIOFBMaxCursorDepth) / 8; 2183 maxWaitImageSize = (maxWaitWidth * maxWaitWidth * kIOFBMaxCursorDepth) / 8; 2184 2185 size = sizeof( StdFBShmem_t) 2186 + maxImageSize 2187 + max(maxImageSize, maxWaitImageSize) 2188 + ((numCursorFrames - 1) * maxWaitImageSize); 2189 2190 if (!sharedCursor || (size != sharedCursor->getLength())) 2191 { 2192 IOBufferMemoryDescriptor * newDesc; 2193 2194 priv = 0; 2195 newDesc = IOBufferMemoryDescriptor::withOptions( 2196 kIODirectionNone | kIOMemoryKernelUserShared, size ); 2197 if (!newDesc) 2198 return (kIOReturnNoMemory); 2199 2200 if (sharedCursor) 2201 sharedCursor->release(); 2202 sharedCursor = newDesc; 2203 } 2204 shmem = (StdFBShmem_t *) sharedCursor->getBytesNoCopy(); 2205 priv = shmem; 2206 2207 // Init shared memory area 2208 bzero( shmem, size ); 2209 shmem->version = shmemClientVersion; 2210 shmem->structSize = size; 2211 shmem->cursorShow = 1; 2212 shmem->hardwareCursorCapable = haveHWCursor; 2213 for (UInt32 i = 0; i < numCursorFrames; i++) 2214 __private->cursorFlags[i] = kIOFBCursorImageNew; 2215 2216 maxCursorSize.width = maxWidth; 2217 maxCursorSize.height = maxWidth; 2218 __private->maxWaitCursorSize.width = maxWaitWidth; 2219 __private->maxWaitCursorSize.height = maxWaitWidth; 2220 2221 doSetup( false ); 2222 2223 return (kIOReturnSuccess); 2224} 2225 2226IOReturn IOFramebuffer::setBoundingRect( IOGBounds * bounds ) 2227{ 2228 return (kIOReturnUnsupported); 2229} 2230 2231/** 2232 ** IOUserClient methods 2233 **/ 2234 2235IOReturn IOFramebuffer::newUserClient( task_t owningTask, 2236 void * security_id, 2237 UInt32 type, 2238 IOUserClient ** handler ) 2239 2240{ 2241 IOReturn err = kIOReturnSuccess; 2242 IOUserClient * newConnect = 0; 2243 IOUserClient * theConnect = 0; 2244 2245 switch (type) 2246 { 2247 case kIOFBServerConnectType: 2248 if (serverConnect) 2249 err = kIOReturnExclusiveAccess; 2250 else 2251 { 2252 if ((this == gIOFBConsoleFramebuffer) || !gIOFBConsoleFramebuffer) 2253 getPlatform()->setConsoleInfo( 0, kPEReleaseScreen); 2254 2255 err = open(); 2256 if (kIOReturnSuccess == err) 2257 newConnect = IOFramebufferUserClient::withTask(owningTask); 2258 } 2259 break; 2260 2261 case kIOFBSharedConnectType: 2262 if (sharedConnect) 2263 { 2264 theConnect = sharedConnect; 2265 theConnect->retain(); 2266 } 2267 else if (serverConnect) 2268 { 2269 newConnect = IOFramebufferSharedUserClient::withTask(owningTask); 2270 if (newConnect) 2271 newConnect->retain(); 2272 } 2273 else 2274 err = kIOReturnNotOpen; 2275 break; 2276 2277 default: 2278 err = kIOReturnBadArgument; 2279 } 2280 2281 if (newConnect) 2282 { 2283 if ((false == newConnect->attach(this)) 2284 || (false == newConnect->start(this))) 2285 { 2286 newConnect->detach( this ); 2287 newConnect->release(); 2288 } 2289 else 2290 theConnect = newConnect; 2291 } 2292 2293 *handler = theConnect; 2294 return (err); 2295} 2296 2297IOReturn IOFramebuffer::extGetDisplayModeCount( 2298 OSObject * target, void * reference, IOExternalMethodArguments * args) 2299{ 2300 IOFramebuffer * inst = (IOFramebuffer *) target; 2301 uint64_t * count = &args->scalarOutput[0]; 2302 2303 IOReturn err; 2304 2305 if ((err = inst->extEntry(false))) 2306 return (err); 2307 2308 *count = inst->dead ? 0 : inst->getDisplayModeCount(); 2309 2310 inst->extExit(err); 2311 2312 return (kIOReturnSuccess); 2313} 2314 2315IOReturn IOFramebuffer::extGetDisplayModes( 2316 OSObject * target, void * reference, IOExternalMethodArguments * args) 2317{ 2318 IOFramebuffer * inst = (IOFramebuffer *) target; 2319 IODisplayModeID * allModes = (IODisplayModeID *) args->structureOutput; 2320 uint32_t * size = &args->structureOutputSize; 2321 2322 IOReturn err; 2323 IOByteCount outSize; 2324 2325 if ((err = inst->extEntry(false))) 2326 return (err); 2327 2328 outSize = inst->getDisplayModeCount() * sizeof( IODisplayModeID); 2329 if (*size >= outSize) 2330 { 2331 *size = outSize; 2332 err = inst->getDisplayModes( allModes ); 2333 } 2334 else 2335 err = kIOReturnBadArgument; 2336 2337 inst->extExit(err); 2338 2339 return (err); 2340} 2341 2342IOReturn IOFramebuffer::extGetVRAMMapOffset( 2343 OSObject * target, void * reference, IOExternalMethodArguments * args) 2344{ 2345 IOFramebuffer * inst = (IOFramebuffer *) target; 2346 // IOPixelAperture aperture = args->scalarInput[0]; 2347 uint64_t * offset = &args->scalarOutput[0]; 2348 2349 IOReturn err; 2350 2351 if ((err = inst->extEntry(false))) 2352 return (err); 2353 2354 if (inst->vramMap) *offset = inst->vramMapOffset; 2355 else 2356 { 2357 *offset = 0; 2358 err = kIOReturnNoSpace; 2359 } 2360 2361 inst->extExit(err); 2362 2363 return (err); 2364} 2365 2366IOReturn IOFramebuffer::_extEntry(bool system, bool allowOffline, const char * where) 2367{ 2368 IOReturn err = kIOReturnSuccess; 2369 2370 if (system) 2371 { 2372 TIMELOCK(gIOFBSystemWorkLoop, thisName, where); 2373 } 2374 2375 TIMELOCK(FBWL(this), thisName, where); 2376 2377 while (!pagingState && !gIOFBSystemPowerAckTo) 2378 { 2379// IODisplayWrangler::activityChange(this); 2380 if (system) 2381 { 2382 FBUNLOCK(this); 2383 err = gIOFBSystemWorkLoop->sleepGate(&serverConnect, false); 2384 FBLOCK(this); 2385 } 2386 else 2387 err = FBWL(this)->sleepGate(&serverConnect, false); 2388 2389 if (kIOReturnSuccess != err) 2390 break; 2391 } 2392 2393 if ((kIOReturnSuccess == err) && !__private->online && !allowOffline) err = kIOReturnOffline; 2394 2395 if (kIOReturnSuccess != err) DEBG1(thisName, " %s: err 0x%x\n", where, err); 2396 2397 if (kIOReturnSuccess != err) 2398 _extExit(system, err, where); 2399 2400 return (err); 2401} 2402 2403void IOFramebuffer::_extExit(bool system, IOReturn result, const char * where) 2404{ 2405 FBUNLOCK(this); 2406 if (system) 2407 SYSUNLOCK(); 2408} 2409 2410 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2411 2412IOReturn IOFramebuffer::extSetBounds( 2413 OSObject * target, void * reference, IOExternalMethodArguments * args) 2414{ 2415 IOFramebuffer * inst = (IOFramebuffer *) target; 2416 IOGBounds * bounds = (IOGBounds *) args->structureInput; 2417 uint32_t inSize = args->structureInputSize; 2418 uint32_t virtIdx = 0; 2419 SInt16 ox, oy; 2420 2421 IOReturn err; 2422 StdFBShmem_t * shmem; 2423 2424 if (inSize < sizeof(IOGBounds)) 2425 return (kIOReturnBadArgument); 2426 if (inSize >= (2 * sizeof(IOGBounds))) 2427 virtIdx = 1; 2428 2429 DEBG1(inst->thisName, " (%d, %d), (%d, %d)\n", 2430 bounds->minx, bounds->miny, 2431 bounds->maxx, bounds->maxy); 2432 2433 if (true && 2434 (1 == (bounds->maxx - bounds->minx)) 2435 && (1 == (bounds->maxy - bounds->miny))) 2436 { 2437 shmem = GetShmem(inst); 2438 if (shmem) 2439 { 2440 ox = shmem->screenBounds.minx; 2441 oy = shmem->screenBounds.miny; 2442 2443 shmem->screenBounds = *bounds; 2444 inst->__private->screenBounds[0] = bounds[0]; 2445 inst->__private->screenBounds[1] = bounds[virtIdx]; 2446 2447 ox = bounds->minx - ox; 2448 oy = bounds->miny - oy; 2449 shmem->saveRect.minx += ox; 2450 shmem->saveRect.maxx += ox; 2451 shmem->saveRect.miny += oy; 2452 shmem->saveRect.maxy += oy; 2453 } 2454 2455 return (kIOReturnSuccess); 2456 } 2457 2458 if ((err = inst->extEntry(true))) 2459 return (err); 2460 2461 shmem = GetShmem(inst); 2462 if (shmem) 2463 { 2464 ox = shmem->screenBounds.minx; 2465 oy = shmem->screenBounds.miny; 2466 2467 if ((kIOFBHardwareCursorActive == shmem->hardwareCursorActive) && inst->__private->online) 2468 { 2469 IOReturn err; 2470 IOGPoint * hs; 2471 hs = &shmem->hotSpot[0 != shmem->frame]; 2472 err = inst->_setCursorState( 2473 shmem->cursorLoc.x - hs->x - ox, 2474 shmem->cursorLoc.y - hs->y - oy, false ); 2475 } 2476 2477 shmem->screenBounds = *bounds; 2478 inst->__private->screenBounds[0] = bounds[0]; 2479 inst->__private->screenBounds[1] = bounds[virtIdx]; 2480 2481 ox = bounds->minx - ox; 2482 oy = bounds->miny - oy; 2483 shmem->saveRect.minx += ox; 2484 shmem->saveRect.maxx += ox; 2485 shmem->saveRect.miny += oy; 2486 shmem->saveRect.maxy += oy; 2487 } 2488 2489 inst->extExit(err); 2490 2491 return (kIOReturnSuccess); 2492} 2493 2494IOReturn IOFramebuffer::extValidateDetailedTiming( 2495 OSObject * target, void * reference, IOExternalMethodArguments * args) 2496{ 2497 IOFramebuffer * inst = (IOFramebuffer *) target; 2498 void * description = const_cast<void *>(args->structureInput); 2499 void * outDescription = args->structureOutput; 2500 uint32_t inSize = args->structureInputSize; 2501 uint32_t * outSize = &args->structureOutputSize; 2502 2503 IOReturn err; 2504 2505 if (*outSize != inSize) 2506 return (kIOReturnBadArgument); 2507 2508 if ((err = inst->extEntry(false))) 2509 return (err); 2510 2511 err = inst->validateDetailedTiming( description, inSize ); 2512 2513 if (kIOReturnSuccess == err) 2514 bcopy( description, outDescription, inSize ); 2515 2516 inst->extExit(err); 2517 2518 return (err); 2519} 2520 2521 2522IOReturn IOFramebuffer::extSetColorConvertTable( 2523 OSObject * target, void * reference, IOExternalMethodArguments * args) 2524{ 2525 IOFramebuffer * inst = (IOFramebuffer *) target; 2526 UInt32 select = args->scalarInput[0]; 2527 UInt8 * data = (UInt8 *) args->structureInput; 2528 IOByteCount length = args->structureInputSize; 2529 2530 static const IOByteCount checkLength[] = { 2531 16 * sizeof( UInt8), 2532 32 * sizeof( UInt8), 2533 256 * sizeof( UInt32), 2534 5 * 256 * sizeof( UInt8) }; 2535 2536 IOReturn err; 2537 UInt8 * table; 2538 2539 if (select > 3) 2540 return (kIOReturnBadArgument); 2541 2542 if (length != checkLength[select]) 2543 return (kIOReturnBadArgument); 2544 2545 if ((err = inst->extEntry(true))) 2546 return (err); 2547 2548 do 2549 { 2550 err = kIOReturnNoMemory; 2551 table = inst->colorConvert.tables[select]; 2552 if (0 == table) 2553 { 2554 table = (UInt8 *) IOMalloc( length ); 2555 inst->colorConvert.tables[select] = table; 2556 } 2557 if (!table) 2558 continue; 2559 2560 bcopy( data, table, length ); 2561 if (select == 3) 2562 inst->white = data[data[255] + data[511] + data[767] + 1024]; 2563 2564 if ((false == inst->cursorEnable) 2565 && inst->__private->online 2566 && inst->colorConvert.tables[0] && inst->colorConvert.tables[1] 2567 && inst->colorConvert.tables[2] && inst->colorConvert.tables[3] 2568// && inst->vramMap 2569 && (inst->__private->pixelInfo.activeWidth >= 128)) 2570 inst->setupCursor(); 2571 2572 err = kIOReturnSuccess; 2573 } 2574 while (false); 2575 2576 inst->extExit(err); 2577 2578 return (err); 2579} 2580 2581/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2582 2583bool IOFramebuffer::requestTerminate( IOService * provider, IOOptionBits options ) 2584{ 2585 SYSLOCK(); 2586 2587 if (opened) 2588 { 2589 if (!gRunawayFramebuffers) 2590 gRunawayFramebuffers = OSArray::withCapacity(4); 2591 if (gRunawayFramebuffers) 2592 gRunawayFramebuffers->setObject(this); 2593 } 2594 2595 SYSUNLOCK(); 2596 2597 return (false); 2598} 2599 2600void IOFramebuffer::stop( IOService * provider ) 2601{ 2602 2603 if (opened) 2604 { 2605 SYSLOCK(); 2606 2607 dead = true; 2608 2609 setAttribute( kIOSystemPowerAttribute, kIOMessageSystemWillPowerOff ); 2610 2611 SYSUNLOCK(); 2612 2613 temporaryPowerClampOn(); // only to clear out kIOPMPreventSystemSleep 2614 PMstop(); 2615 initialized = false; 2616 2617 connectChangeInterrupt(this, 0); 2618 } 2619 2620 return (super::stop(provider)); 2621} 2622 2623void IOFramebuffer::free() 2624{ 2625 if (vblSemaphore) 2626 semaphore_destroy(kernel_task, vblSemaphore); 2627 if (__private) 2628 { 2629 IODelete( __private, IOFramebufferPrivate, 1 ); 2630 __private = 0; 2631 } 2632 super::free(); 2633} 2634 2635IOService * IOFramebuffer::probe( IOService * provider, SInt32 * score ) 2636{ 2637 IOFramebuffer * replace = 0; 2638 2639 if (gRunawayFramebuffers) 2640 { 2641 SYSLOCK(); 2642 2643 replace = (IOFramebuffer *) gRunawayFramebuffers->getObject(0); 2644 gRunawayFramebuffers->removeObject(0); 2645 2646 SYSUNLOCK(); 2647 } 2648 2649 return (replace ? replace : this); 2650} 2651 2652 2653__private_extern__ "C" kern_return_t IOGraphicsFamilyModuleStart(kmod_info_t *ki, void *data) 2654{ 2655 gIOFBSystemWorkLoop = IOGraphicsWorkLoop::workLoop(0, NULL, NULL, NULL); 2656 if (!gIOFBSystemWorkLoop) panic("gIOFBSystemWorkLoop"); 2657 gAllFramebuffers = OSArray::withCapacity(1); 2658 gStartedFramebuffers = OSArray::withCapacity(1); 2659 gIOFramebufferKey = OSSymbol::withCStringNoCopy("IOFramebuffer"); 2660 2661 if (PE_parse_boot_argn("iog", &gIOGDebugFlags, sizeof(gIOGDebugFlags))) 2662 { 2663 DEBG1("IOGraphics", " flags 0x%x\n", gIOGDebugFlags); 2664 gIOFBLidOpenMode = (0 != (kIOGDbgLidOpen & gIOGDebugFlags)); 2665 gIOFBVBLThrottle = (0 != (kIOGDbgVBLThrottle & gIOGDebugFlags)); 2666 gIOFBVBLDrift = (0 != (kIOGDbgVBLDrift & gIOGDebugFlags)); 2667 } 2668 else 2669 { 2670 gIOFBLidOpenMode = (version_major >= 11); 2671 gIOFBVBLThrottle = (version_major >= 11); 2672 } 2673 gIOGFades = (version_major >= 14); 2674 if (!PE_parse_boot_argn("iognotifyto", &gIOGNotifyTO, sizeof(gIOGNotifyTO)) 2675 || !gIOGNotifyTO) 2676 { 2677 gIOGNotifyTO = kSystemWillSleepTimeout; 2678 } 2679 DEBG1("IOGraphics", " notify timeout %ds\n", gIOGNotifyTO); 2680 2681 return (kIOReturnSuccess); 2682} 2683 2684static bool 2685IOFramebufferLockedSerialize(void * target, void * ref, OSSerialize * s) 2686{ 2687 bool ok; 2688 SYSLOCK(); 2689 ok = ((OSObject *) target)->serialize(s); 2690 SYSUNLOCK(); 2691 return (ok); 2692} 2693 2694void IOFramebuffer::initialize() 2695{ 2696 OSDictionary * matching; 2697 OSIterator * iter; 2698 2699 gIOFBServerInit = true; 2700 gIOFBBlackBoot = (0 != (kBootArgsFlagBlack & ((boot_args *) PE_state.bootArgs)->flags)); 2701 if (gIOFBBlackBoot) gIOFBGrayValue = 0; 2702 2703 gIOFBGetSensorValueKey = OSSymbol::withCStringNoCopy(kIOFBGetSensorValueKey); 2704 gIOFBRotateKey = OSSymbol::withCStringNoCopy(kIOFBRotatePrefsKey); 2705 gIOFBStartupModeTimingKey = OSSymbol::withCStringNoCopy(kIOFBStartupTimingPrefsKey); 2706 gIOFBPMSettingDisplaySleepUsesDimKey = OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey); 2707 2708 gIOFBConfigKey = OSSymbol::withCString(kIOFBConfigKey); 2709 gIOFBModesKey = OSSymbol::withCString(kIOFBModesKey); 2710 gIOFBModeIDKey = OSSymbol::withCString(kIOFBModeIDKey); 2711 gIOFBModeDMKey = OSSymbol::withCString(kIOFBModeDMKey); 2712 2713 matching = serviceMatching("AppleGraphicsControl"); 2714 if ((gIOGraphicsControl = copyMatchingService(matching))) 2715 { 2716 gIOFBGCNotifier = gIOGraphicsControl->registerInterest( 2717 gIOGeneralInterest, &agcMessage, 0, 0 ); 2718 } 2719 if (matching) matching->release(); 2720 2721 matching = serviceMatching("IOAccelerator"); 2722 if ((iter = getMatchingServices(matching))) 2723 { 2724 IOService * accel; 2725 while ((accel = OSDynamicCast(IOService, iter->getNextObject()))) 2726 accel->requestProbe(kIOFBUserRequestProbe); 2727 2728 iter->release(); 2729 } 2730 if (matching) matching->release(); 2731 2732 if (gIOFBPrefs) 2733 gIOFBPrefsSerializer = OSSerializer::forTarget(gIOFBPrefs, 2734 &IOFramebufferLockedSerialize, 0); 2735 2736 clock_interval_to_absolutetime_interval(20, kMillisecondScale, &gIOFBMaxVBLDelta); 2737 2738 gIOFBRootNotifier = getPMRootDomain()->registerInterest( 2739 gIOPriorityPowerStateInterest, &systemPowerChange, 0, 0 ); 2740 gIOFBClamshellCallout = thread_call_allocate(&delayedEvent, (thread_call_param_t) 0); 2741 static uint32_t zero = 0; 2742 static uint32_t one = 1; 2743 gIOFBZero32Data = OSData::withBytesNoCopy(&zero, sizeof(zero)); 2744 gIOFBOne32Data = OSData::withBytesNoCopy(&one, sizeof(one)); 2745 gIOFBGray32Data = OSData::withBytesNoCopy(&gIOFBGrayValue, sizeof(gIOFBGrayValue)); 2746 2747 gIOGraphicsPrefsVersionKey = OSSymbol::withCStringNoCopy(kIOGraphicsPrefsVersionKey); 2748 gIOGraphicsPrefsVersionValue = OSNumber::withNumber(kIOGraphicsPrefsCurrentVersion, 32); 2749 2750 matching = nameMatching("IOHIDSystem"); 2751 IOService * hidsystem = copyMatchingService(matching); 2752 if (hidsystem) 2753 { 2754 gIOFBHIDWorkLoop = hidsystem->getWorkLoop(); 2755 if (gIOFBHIDWorkLoop) gIOFBHIDWorkLoop->retain(); 2756 hidsystem->release(); 2757 } 2758 if (matching) matching->release(); 2759 2760 // system work 2761 gIOFBWorkES = IOInterruptEventSource::interruptEventSource(gIOFBSystemWorkLoop, &systemWork); 2762 if (gIOFBWorkES) 2763 gIOFBSystemWorkLoop->addEventSource(gIOFBWorkES); 2764 2765 gIOFBDelayedPrefsEvent = IOTimerEventSource::timerEventSource( 2766 gAllFramebuffers, &writePrefs); 2767 if (gIOFBDelayedPrefsEvent) 2768 gIOFBSystemWorkLoop->addEventSource(gIOFBDelayedPrefsEvent); 2769 2770 gIOFBServerAckTimer = IOTimerEventSource::timerEventSource( 2771 gAllFramebuffers, &serverAckTimeout); 2772 if (gIOFBServerAckTimer) 2773 gIOFBSystemWorkLoop->addEventSource(gIOFBServerAckTimer); 2774} 2775 2776bool IOFramebuffer::start( IOService * provider ) 2777{ 2778 bool runaway; 2779 2780 if (!super::start(provider)) return (false); 2781 2782 runaway = (__private != 0); 2783 2784 if (!__private) 2785 { 2786 __private = IONew( IOFramebufferPrivate, 1 ); 2787 if (!__private) 2788 return (false); 2789 bzero( __private, sizeof(IOFramebufferPrivate) ); 2790 __private->lastNotifyOnline = 0xdd; 2791 __private->regID = getRegistryEntryID(); 2792 2793 userAccessRanges = OSArray::withCapacity( 1 ); 2794 if (!userAccessRanges) 2795 return (false); 2796 2797 serverMsg = IOMalloc( sizeof (mach_msg_header_t) ); 2798 if (!serverMsg) 2799 return (false); 2800 bzero( serverMsg, sizeof (mach_msg_header_t)); 2801 } 2802 if (!thisName) 2803 thisName = "IOFB?"; 2804 2805 // initialize superclass power management variables 2806 PMinit(); 2807 // attach into the power management hierarchy 2808 setProperty("IOPMStrictTreeOrder", kOSBooleanTrue); 2809 provider->joinPMtree(this); 2810 2811 SYSLOCK(); 2812 if (!runaway && !gIOFBServerInit) do 2813 { 2814 IOFramebuffer * fb; 2815 char * path; 2816 char * pathThis; 2817 int pathLen; 2818 2819 pathLen = 1024; 2820 path = IONew(char, pathLen); 2821 pathThis = IONew(char, pathLen); 2822 if (!path || !pathThis) continue; 2823 2824 if (!getPath(pathThis, &pathLen, gIOServicePlane)) pathThis[0] = 0; 2825 for (thisIndex = 0; (fb = (IOFramebuffer *) gStartedFramebuffers->getObject(thisIndex)); thisIndex++) 2826 { 2827 pathLen = 1024; 2828 if (!fb->getPath(path, &pathLen, gIOServicePlane)) path[0] = 0; 2829 if (0 > strcmp(pathThis, path)) break; 2830 } 2831 gStartedFramebuffers->setObject(thisIndex, this); 2832 2833 IODelete(path, char, 1024); 2834 IODelete(pathThis, char, 1024); 2835 } 2836 while (false); 2837 SYSUNLOCK(); 2838 2839 if (!runaway) registerService(); 2840 else 2841 { 2842 IOReturn err; 2843 2844 SYSLOCK(); 2845 err = enableController(); 2846 if (kIOReturnSuccess == err) 2847 { 2848 opened = true; 2849 dead = false; 2850 isUsable = true; 2851 connectChangeInterrupt(this, 0); 2852 } 2853 SYSUNLOCK(); 2854 } 2855 2856 return (true); 2857} 2858 2859/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2860 2861// 2862// BEGIN: Implementation of the evScreen protocol 2863// 2864 2865void IOFramebuffer::deferredMoveCursor( IOFramebuffer * inst ) 2866{ 2867 StdFBShmem_t * shmem = GetShmem(inst); 2868 IOReturn err = kIOReturnSuccess; 2869 2870 if (shmem->hardwareCursorActive) 2871 { 2872 if (shmem->cursorObscured) 2873 { 2874 shmem->cursorObscured = 0; 2875 if (shmem->cursorShow) 2876 --shmem->cursorShow; 2877 } 2878 if (shmem->hardwareCursorShields && shmem->shieldFlag) 2879 CheckShield(inst); 2880 if (!shmem->cursorShow) 2881 { 2882 IOGPoint * hs; 2883 hs = &shmem->hotSpot[0 != shmem->frame]; 2884 err = inst->_setCursorState( 2885 shmem->cursorLoc.x - hs->x - shmem->screenBounds.minx, 2886 shmem->cursorLoc.y - hs->y - shmem->screenBounds.miny, true ); 2887#if 0 2888 // debug 2889 shmem->cursorRect.minx = shmem->cursorLoc.x - hs->x - shmem->screenBounds.minx; 2890 shmem->cursorRect.miny = shmem->cursorLoc.y - hs->y - shmem->screenBounds.miny; 2891 shmem->cursorRect.maxx = 0; 2892 shmem->cursorRect.maxy = 0; 2893#endif 2894 } 2895 } 2896 else 2897 { 2898 if (!shmem->cursorShow++) 2899 RemoveCursor(inst); 2900 if (shmem->cursorObscured) 2901 { 2902 shmem->cursorObscured = 0; 2903 if (shmem->cursorShow) 2904 --shmem->cursorShow; 2905 } 2906 if (shmem->shieldFlag) 2907 CheckShield(inst); 2908 if (shmem->cursorShow) 2909 if (!--shmem->cursorShow) 2910 DisplayCursor(inst); 2911 2912 inst->flushCursor(); 2913 2914 if (inst->__private->cursorPanning) 2915 { 2916 IOGPoint * hs; 2917 hs = &shmem->hotSpot[0 != shmem->frame]; 2918 err = inst->setCursorState( 2919 shmem->cursorLoc.x - hs->x - shmem->screenBounds.minx, 2920 shmem->cursorLoc.y - hs->y - shmem->screenBounds.miny, false ); 2921 } 2922 } 2923} 2924 2925void IOFramebuffer::cursorWork( OSObject * p0, IOInterruptEventSource * evtSrc, int intCount ) 2926{ 2927 IOFramebuffer * inst = (IOFramebuffer *) p0; 2928 StdFBShmem_t * shmem = GetShmem(inst); 2929 struct IOFramebufferPrivate * __private = inst->__private; 2930 IOFBCursorControlAttribute * cursorControl = &__private->cursorControl; 2931 IOReturn ret; 2932 IOHardwareCursorDescriptor desc; 2933 2934 IOOptionBits todo = inst->__private->cursorToDo; 2935 2936 while (todo) 2937 { 2938 if (2 & todo) 2939 { 2940 desc.majorVersion = kHardwareCursorDescriptorMajorVersion; 2941 desc.minorVersion = kHardwareCursorDescriptorMinorVersion; 2942 desc.height = shmem->cursorSize[0 != __private->framePending].height; 2943 desc.width = shmem->cursorSize[0 != __private->framePending].width; 2944 desc.bitDepth = inst->__private->cursorBytesPerPixel * 8; 2945 desc.maskBitDepth = 0; 2946 desc.colorEncodings = 0; 2947 desc.flags = 0; 2948 desc.supportedSpecialEncodings = kTransparentEncodedPixel; 2949 2950 ret = (*cursorControl->callouts->setCursorImage) ( 2951 cursorControl->self, cursorControl->ref, 2952 &desc, (void *)(uintptr_t) __private->framePending ); 2953 } 2954 if (1 & todo) 2955 ret = (*cursorControl->callouts->setCursorState) ( 2956 cursorControl->self, cursorControl->ref, 2957 __private->xPending, __private->yPending, __private->visiblePending ); 2958 2959 todo = __private->cursorToDo & ~todo; 2960 __private->cursorToDo = todo; 2961 } 2962} 2963 2964IOOptionBits IOFramebuffer::_setCursorImage( UInt32 frame ) 2965{ 2966 StdFBShmem_t * shmem = GetShmem(this); 2967 IOGPoint * hs; 2968 IOOptionBits flags; 2969 bool animation = (((int) frame) != shmem->frame); 2970 2971 hs = &shmem->hotSpot[0 != frame]; 2972 if (false && ((hs->x != __private->lastHotSpot.x) || (hs->y != __private->lastHotSpot.y))) 2973 { 2974 __private->lastHotSpot = *hs; 2975 if (GetShmem(this) && __private->deferredCLUTSetEvent && shmem->vblCount && !__private->cursorSlept && !suspended) 2976 { 2977 if (false) 2978 { 2979 __private->waitVBLEvent = hs; 2980 FBWL(this)->sleepGate(hs, THREAD_UNINT); 2981 } 2982 else if (CMP_ABSOLUTETIME(&shmem->vblDelta, &gIOFBMaxVBLDelta) < 0) 2983 { 2984 AbsoluteTime deadline = shmem->vblTime; 2985 ADD_ABSOLUTETIME(&deadline, &shmem->vblDelta); 2986 clock_delay_until(deadline); 2987 } 2988 } 2989 } 2990 2991 if (!animation && ((kIOFBHardwareCursorActive == shmem->hardwareCursorActive) || !shmem->cursorShow)) 2992 { 2993 RemoveCursor(this); 2994 } 2995 flags = (kIOReturnSuccess == setCursorImage( (void *)(uintptr_t) frame )) 2996 ? kIOFBHardwareCursorActive : 0; 2997 if (!animation && !shmem->cursorShow) 2998 { 2999 DisplayCursor(this); 3000 } 3001 if (!flags && __private->cursorThread && (__private->cursorBytesPerPixel >= 2)) 3002 { 3003 __private->framePending = frame; 3004 __private->cursorToDo |= 2; 3005 flags = kIOFBHardwareCursorActive | kIOFBHardwareCursorInVRAM; 3006 } 3007 3008 return (flags); 3009} 3010 3011IOReturn IOFramebuffer::_setCursorState( SInt32 x, SInt32 y, bool visible ) 3012{ 3013 StdFBShmem_t *shmem = GetShmem(this); 3014 IOReturn ret = kIOReturnUnsupported; 3015 3016 x -= __private->cursorHotSpotAdjust[0].x; 3017 y -= __private->cursorHotSpotAdjust[0].y; 3018 3019 if (kIOFBHardwareCursorActive == shmem->hardwareCursorActive) 3020 { 3021 ret = setCursorState( x, y, visible ); 3022 } 3023 else if (__private->cursorThread) 3024 { 3025 __private->cursorToDo |= 1; 3026 __private->xPending = x; 3027 __private->yPending = y; 3028 __private->visiblePending = visible; 3029 } 3030 3031 return (ret); 3032} 3033 3034void IOFramebuffer::transformLocation(StdFBShmem_t * shmem, 3035 IOGPoint * cursorLoc, IOGPoint * transformLoc) 3036{ 3037 SInt32 x, y; 3038 3039 x = cursorLoc->x - shmem->screenBounds.minx; 3040 y = cursorLoc->y - shmem->screenBounds.miny; 3041 3042 if (__private->transform & kIOFBSwapAxes) 3043 { 3044 SInt32 t = x; 3045 x = y; 3046 y = t; 3047 } 3048 if (__private->transform & kIOFBInvertX) 3049 x = __private->framebufferWidth - x - 1; 3050 if (__private->transform & kIOFBInvertY) 3051 y = __private->framebufferHeight - y - 1; 3052 3053 transformLoc->x = x + shmem->screenBounds.minx; 3054 transformLoc->y = y + shmem->screenBounds.miny; 3055} 3056 3057void IOFramebuffer::moveCursor( IOGPoint * cursorLoc, int frame ) 3058{ 3059 UInt32 hwCursorActive; 3060 3061 nextCursorLoc = *cursorLoc; 3062 nextCursorFrame = frame; 3063 3064 CURSORLOCK(this); 3065 3066 if (frame != shmem->frame) 3067 { 3068 if (__private->cursorFlags[frame] && pagingState) 3069 { 3070 hwCursorActive = _setCursorImage( frame ); 3071 __private->cursorFlags[frame] = hwCursorActive ? kIOFBCursorHWCapable : 0; 3072 } 3073 else 3074 hwCursorActive = 0; 3075 3076 shmem->frame = frame; 3077 if (shmem->hardwareCursorActive != hwCursorActive) 3078 { 3079 SysHideCursor( this ); 3080 shmem->hardwareCursorActive = hwCursorActive; 3081 if (shmem->shieldFlag 3082 && ((0 == hwCursorActive) || (shmem->hardwareCursorShields))) 3083 CheckShield(this); 3084 SysShowCursor( this ); 3085 } 3086 } 3087 3088 if (kIOFBRotateFlags & __private->transform) 3089 transformLocation(shmem, &nextCursorLoc, &shmem->cursorLoc); 3090 else 3091 shmem->cursorLoc = nextCursorLoc; 3092 shmem->frame = frame; 3093 deferredMoveCursor( this ); 3094 3095 CURSORUNLOCK(this); 3096} 3097 3098void IOFramebuffer::hideCursor( void ) 3099{ 3100 CURSORLOCK(this); 3101 3102 SysHideCursor(this); 3103 3104 CURSORUNLOCK(this); 3105} 3106 3107void IOFramebuffer::showCursor( IOGPoint * cursorLoc, int frame ) 3108{ 3109 UInt32 hwCursorActive; 3110 3111 CURSORLOCK(this); 3112 3113 if (frame != shmem->frame) 3114 { 3115 if (__private->cursorFlags[frame]) 3116 { 3117 hwCursorActive = _setCursorImage( frame ); 3118 __private->cursorFlags[frame] = hwCursorActive ? kIOFBCursorHWCapable : 0; 3119 } 3120 else 3121 hwCursorActive = 0; 3122 shmem->frame = frame; 3123 shmem->hardwareCursorActive = hwCursorActive; 3124 } 3125 3126 shmem->cursorLoc = *cursorLoc; 3127 if (shmem->shieldFlag 3128 && ((0 == shmem->hardwareCursorActive) || (shmem->hardwareCursorShields))) 3129 CheckShield(this); 3130 3131 SysShowCursor(this); 3132 3133 CURSORUNLOCK(this); 3134} 3135 3136void IOFramebuffer::updateVBL(OSObject * owner, IOTimerEventSource * sender) 3137{ 3138 IOFramebuffer * inst = (IOFramebuffer *) owner; 3139 3140 if (inst->__private->vblInterrupt 3141 && inst->__private->vblThrottle 3142 && inst->__private->displaysOnline 3143 && inst->pagingState) 3144 { 3145 inst->setInterruptState(inst->__private->vblInterrupt, kEnabledInterruptState); 3146 inst->__private->vblEnabled = true; 3147 } 3148} 3149 3150void IOFramebuffer::deferredVBLDisable(OSObject * owner, 3151 IOInterruptEventSource * evtSrc, int intCount) 3152{ 3153 IOFramebuffer * inst = (IOFramebuffer *) owner; 3154 3155 if (inst->__private->vblInterrupt && inst->__private->vblThrottle) 3156 { 3157 inst->setInterruptState(inst->__private->vblInterrupt, kDisabledInterruptState); 3158 } 3159} 3160 3161bool IOFramebuffer::getTimeOfVBL(AbsoluteTime * deadline, uint32_t frames) 3162{ 3163 uint64_t last, now; 3164 uint64_t delta; 3165 3166 StdFBShmem_t * shmem = GetShmem(this); 3167 if (!shmem) 3168 return (false); 3169 3170 do 3171 { 3172 last = AbsoluteTime_to_scalar(&shmem->vblTime); 3173 now = mach_absolute_time(); 3174 } 3175 while (last != AbsoluteTime_to_scalar(&shmem->vblTime)); 3176 3177 delta = AbsoluteTime_to_scalar(&shmem->vblDelta); 3178 if (delta) 3179 { 3180 now += frames * delta - ((now - last) % delta); 3181 } 3182 AbsoluteTime_to_scalar(deadline) = now; 3183 3184 return (true); 3185} 3186 3187void IOFramebuffer::handleVBL(IOFramebuffer * inst, void * ref) 3188{ 3189 StdFBShmem_t * shmem = GetShmem(inst); 3190 AbsoluteTime now; 3191 uint64_t _now, calculatedDelta, drift; 3192 3193 if (!shmem) return; 3194 inst->__private->actualVBLCount++; 3195 if (!inst->__private->vblEnabled) return; 3196 3197 _now = mach_absolute_time(); 3198 AbsoluteTime_to_scalar(&now) = _now; 3199 AbsoluteTime delta = now; 3200 SUB_ABSOLUTETIME(&delta, &shmem->vblTime); 3201 calculatedDelta = AbsoluteTime_to_scalar(&shmem->vblDelta); 3202 3203 if (calculatedDelta && inst->__private->vblThrottle) 3204 { 3205 // round up to deal with scheduling noise. 3206 uint64_t timeCount = ((AbsoluteTime_to_scalar(&delta) * 2 / calculatedDelta) + 1) / 2; 3207 shmem->vblCount += timeCount; 3208 timeCount = (timeCount > inst->__private->actualVBLCount) 3209 ? (timeCount - inst->__private->actualVBLCount) 3210 : (inst->__private->actualVBLCount - timeCount); 3211 if (gIOFBVBLDrift && (timeCount <= 1)) 3212 { 3213 drift = (AbsoluteTime_to_scalar(&shmem->vblTime) 3214 + inst->__private->actualVBLCount * calculatedDelta); 3215 drift = (drift < _now) ? (_now - drift) : (drift - _now); 3216 shmem->vblDrift = drift; 3217 shmem->vblDeltaMeasured = (AbsoluteTime_to_scalar(&delta) / inst->__private->actualVBLCount); 3218// shmem->vblDeltaMeasured = IOMappedRead32(0xb0070000); 3219 } 3220 } 3221 else 3222 { 3223 shmem->vblCount++; 3224 shmem->vblDelta = delta; 3225 } 3226 shmem->vblTime = now; 3227 inst->__private->actualVBLCount = 0; 3228 3229 KERNEL_DEBUG(0xc000030 | DBG_FUNC_NONE, 3230 (uint32_t)(AbsoluteTime_to_scalar(&shmem->vblDelta) >> 32), 3231 (uint32_t)(AbsoluteTime_to_scalar(&shmem->vblDelta)), 0, 0, 0); 3232 3233 if (inst->vblSemaphore) 3234 semaphore_signal_all(inst->vblSemaphore); 3235 3236 if (inst->__private->vblThrottle) 3237 { 3238 inst->__private->vblEnabled = false; 3239 if (!gIOFBVBLDrift) inst->__private->deferredVBLDisableEvent->interruptOccurred(0, 0, 0); 3240 inst->__private->vblUpdateTimer->setTimeoutMS(kVBLThrottleTimeMS); 3241 } 3242 else if (inst->__private->deferredCLUTSetEvent 3243 && (inst->__private->gammaNeedSet || inst->__private->clutDataLen || inst->__private->waitVBLEvent)) 3244 { 3245 inst->__private->deferredCLUTSetEvent->interruptOccurred(0, 0, 0); 3246 } 3247} 3248 3249void IOFramebuffer::resetCursor( void ) 3250{ 3251 StdFBShmem_t * shmem; 3252 int frame; 3253 3254 shmem = GetShmem(this); 3255 // hwCursorLoaded = false; 3256 if (!shmem) 3257 return; 3258 3259 shmem->hardwareCursorActive = 0; 3260 frame = shmem->frame; 3261 shmem->frame = frame ^ 1; 3262 showCursor( &shmem->cursorLoc, frame ); 3263} 3264 3265void IOFramebuffer::getVBLTime( AbsoluteTime * time, AbsoluteTime * delta ) 3266{ 3267 StdFBShmem_t *shmem; 3268 3269 shmem = GetShmem(this); 3270 if (shmem) 3271 { 3272 getTimeOfVBL(time, 0); 3273 *delta = shmem->vblDelta; 3274 } 3275 else 3276 { 3277 AbsoluteTime_to_scalar(time) = 0; 3278 AbsoluteTime_to_scalar(delta) = 0; 3279 } 3280} 3281 3282void IOFramebuffer::getBoundingRect( IOGBounds ** bounds ) 3283{ 3284 StdFBShmem_t *shmem; 3285 3286 shmem = GetShmem(this); 3287 if (NULL == shmem) 3288 *bounds = NULL; 3289 else 3290 *bounds = &__private->screenBounds[0]; 3291} 3292 3293// 3294// END: Implementation of the evScreen protocol 3295// 3296 3297/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3298 3299IOReturn IOFramebuffer::getNotificationSemaphore( 3300 IOSelect interruptType, semaphore_t * semaphore ) 3301{ 3302 kern_return_t kr; 3303 semaphore_t sema; 3304 3305 if (interruptType != kIOFBVBLInterruptType) 3306 return (kIOReturnUnsupported); 3307 3308 if (!haveVBLService) 3309 return (kIOReturnNoResources); 3310 3311 if (MACH_PORT_NULL == vblSemaphore) 3312 { 3313 kr = semaphore_create(kernel_task, &sema, SYNC_POLICY_FIFO, 0); 3314 if (kr == KERN_SUCCESS) 3315 vblSemaphore = sema; 3316 } 3317 else 3318 kr = KERN_SUCCESS; 3319 3320 if (kr == KERN_SUCCESS) 3321 *semaphore = vblSemaphore; 3322 3323 return (kr); 3324} 3325 3326IOReturn IOFramebuffer::extSetCursorVisible( 3327 OSObject * target, void * reference, IOExternalMethodArguments * args) 3328{ 3329 IOFramebuffer * inst = (IOFramebuffer *) target; 3330 bool visible = args->scalarInput[0]; 3331 3332 IOReturn err; 3333 IOGPoint * hs; 3334 StdFBShmem_t * shmem; 3335 3336 if ((err = inst->extEntry(true))) 3337 return (err); 3338 3339 shmem = GetShmem(inst); 3340 if (shmem->hardwareCursorActive && inst->__private->online) 3341 { 3342 hs = &shmem->hotSpot[0 != shmem->frame]; 3343 err = inst->_setCursorState( 3344 shmem->cursorLoc.x - hs->x - shmem->screenBounds.minx, 3345 shmem->cursorLoc.y - hs->y - shmem->screenBounds.miny, 3346 visible ); 3347 3348 if (inst->__private->cursorToDo) 3349 KICK_CURSOR(inst->__private->cursorThread); 3350 } 3351 else 3352 err = kIOReturnBadArgument; 3353 3354 inst->extExit(err); 3355 3356 return (err); 3357} 3358 3359IOReturn IOFramebuffer::extSetCursorPosition( 3360 OSObject * target, void * reference, IOExternalMethodArguments * args) 3361{ 3362// IOFramebuffer * inst = (IOFramebuffer *) target; 3363// SInt32 x = args->scalarInput[0]; 3364// SInt32 y = args->scalarInput[1]; 3365 3366 return (kIOReturnUnsupported); 3367} 3368 3369void IOFramebuffer::transformCursor( StdFBShmem_t * shmem, IOIndex frame ) 3370{ 3371 void * buf; 3372 unsigned int * out; 3373 volatile unsigned int * cursPtr32 = 0; 3374 volatile unsigned short * cursPtr16 = 0; 3375 SInt32 x, y, dw, dh, sx, sy, sw, sh; 3376 3377 if (__private->cursorBytesPerPixel == 4) 3378 { 3379 cursPtr32 = (volatile unsigned int *) __private->cursorImages[frame]; 3380 cursPtr16 = 0; 3381 } 3382 else if (__private->cursorBytesPerPixel == 2) 3383 { 3384 cursPtr32 = 0; 3385 cursPtr16 = (volatile unsigned short *) __private->cursorImages[frame]; 3386 } 3387 3388 sw = shmem->cursorSize[0 != frame].width; 3389 sh = shmem->cursorSize[0 != frame].height; 3390 3391 if (kIOFBSwapAxes & __private->transform) 3392 { 3393 dw = sh; 3394 dh = sw; 3395 } 3396 else 3397 { 3398 dw = sw; 3399 dh = sh; 3400 } 3401 3402 buf = IOMalloc(dw * dh * __private->cursorBytesPerPixel); 3403 out = (unsigned int *) buf; 3404 3405 for (y = 0; y < dh; y++) 3406 { 3407 for (x = 0; x < dw; x++) 3408 { 3409 if (kIOFBSwapAxes & __private->transform) 3410 { 3411 sx = y; 3412 sy = x; 3413 } 3414 else 3415 { 3416 sx = x; 3417 sy = y; 3418 } 3419 if (__private->transform & kIOFBInvertY) 3420 sx = sw - sx - 1; 3421 if (__private->transform & kIOFBInvertX) 3422 sy = sh - sy - 1; 3423 3424 if (cursPtr32) 3425 *out++ = cursPtr32[sx + sy * sw]; 3426 else 3427 STOREINC(out, cursPtr16[sx + sy * sw], UInt16) 3428 } 3429 } 3430 3431 bcopy(buf, (void *) __private->cursorImages[frame], dw * dh * __private->cursorBytesPerPixel); 3432 IOFree(buf, dw * dh * __private->cursorBytesPerPixel); 3433 3434 shmem->cursorSize[0 != frame].width = dw; 3435 shmem->cursorSize[0 != frame].height = dh; 3436 3437 if (kIOFBSwapAxes & __private->transform) 3438 { 3439 x = shmem->hotSpot[0 != frame].y; 3440 y = shmem->hotSpot[0 != frame].x; 3441 } 3442 else 3443 { 3444 x = shmem->hotSpot[0 != frame].x; 3445 y = shmem->hotSpot[0 != frame].y; 3446 } 3447 if (__private->transform & kIOFBInvertX) 3448 x = dw - x - 1; 3449 if (__private->transform & kIOFBInvertY) 3450 y = dh - y - 1; 3451 shmem->hotSpot[0 != frame].x = x; 3452 shmem->hotSpot[0 != frame].y = y; 3453} 3454 3455IOReturn IOFramebuffer::extSetNewCursor( 3456 OSObject * target, void * reference, IOExternalMethodArguments * args) 3457{ 3458 IOFramebuffer * inst = (IOFramebuffer *) target; 3459 IOIndex cursor = args->scalarInput[0]; 3460 IOIndex frame = args->scalarInput[1]; 3461 IOOptionBits options = args->scalarInput[2]; 3462 3463 StdFBShmem_t * shmem; 3464 IOReturn err; 3465 UInt32 hwCursorActive; 3466 3467 if ((err = inst->extEntry(false))) 3468 return (err); 3469 3470 shmem = GetShmem(inst); 3471 // assumes called with cursorSema held 3472 if (cursor || options || (((UInt32) frame) >= inst->__private->numCursorFrames)) 3473 err = kIOReturnBadArgument; 3474 else 3475 { 3476 if (kIOFBRotateFlags & inst->__private->transform) 3477 inst->transformCursor(shmem, frame); 3478 3479 if ((shmem->cursorSize[0 != frame].width > inst->maxCursorSize.width) 3480 || (shmem->cursorSize[0 != frame].height > inst->maxCursorSize.height)) 3481 err = kIOReturnBadArgument; 3482 3483 else if (inst->haveHWCursor) 3484 { 3485 if (frame == shmem->frame) 3486 { 3487 hwCursorActive = inst->_setCursorImage( frame ); 3488 shmem->hardwareCursorActive = hwCursorActive; 3489 inst->__private->cursorFlags[frame] = hwCursorActive ? kIOFBCursorHWCapable : 0; 3490 } 3491 else 3492 { 3493 inst->__private->cursorFlags[frame] = kIOFBCursorImageNew; 3494 } 3495 err = kIOReturnSuccess; // I guess 3496 } 3497 else 3498 err = kIOReturnUnsupported; 3499 } 3500 if (inst->__private->cursorToDo) 3501 KICK_CURSOR(inst->__private->cursorThread); 3502 3503 inst->extExit(err); 3504 3505 return (err); 3506} 3507 3508bool IOFramebuffer::convertCursorImage( void * cursorImage, 3509 IOHardwareCursorDescriptor * hwDesc, 3510 IOHardwareCursorInfo * hwCursorInfo ) 3511{ 3512 StdFBShmem_t * shmem = GetShmem(this); 3513 UInt8 * dataOut = hwCursorInfo->hardwareCursorData; 3514 IOColorEntry * clut = hwCursorInfo->colorMap; 3515 UInt32 maxColors = hwDesc->numColors; 3516 int frame = (uintptr_t) cursorImage; 3517 3518 volatile unsigned short * cursPtr16; 3519 volatile unsigned int * cursPtr32; 3520 SInt32 x, lastx, y, lasty; 3521 UInt32 width, height, lineBytes = 0; 3522 UInt32 index, numColors = 0; 3523 UInt32 alpha, red, green, blue; 3524 UInt16 s16; 3525 UInt32 s32; 3526 UInt32 pixel = 0; 3527 UInt32 data = 0; 3528 UInt32 bits = 0; 3529 bool ok = true; 3530 bool isDirect; 3531 3532 if (__private->testingCursor) 3533 { 3534 IOHardwareCursorDescriptor copy; 3535 3536 if ((hwDesc->numColors == 0) && (hwDesc->bitDepth > 8) && (hwDesc->bitDepth < 32)) 3537 { 3538 copy = *hwDesc; 3539 hwDesc = © 3540 copy.bitDepth = 32; 3541 } 3542 3543 OSData * data = OSData::withBytes( hwDesc, sizeof(IOHardwareCursorDescriptor) ); 3544 if (data) 3545 { 3546 __private->cursorAttributes->setObject( data ); 3547 data->release(); 3548 } 3549 3550 return (false); 3551 } 3552 else if (!hwCursorInfo || !hwCursorInfo->hardwareCursorData) 3553 return (false); 3554 3555 assert( frame < __private->numCursorFrames ); 3556 3557 if (__private->cursorBytesPerPixel == 4) 3558 { 3559 cursPtr32 = (volatile unsigned int *) __private->cursorImages[frame]; 3560 cursPtr16 = 0; 3561 } 3562 else if (__private->cursorBytesPerPixel == 2) 3563 { 3564 cursPtr32 = 0; 3565 cursPtr16 = (volatile unsigned short *) __private->cursorImages[frame]; 3566 } 3567 else 3568 return (false); 3569 3570 if (!cursPtr32 && !cursPtr16) return (false); 3571 3572 x = shmem->cursorSize[0 != frame].width; 3573 y = shmem->cursorSize[0 != frame].height; 3574 if ((x > (SInt32) hwDesc->width) || (y > (SInt32) hwDesc->height)) 3575 return (false); 3576 isDirect = (hwDesc->bitDepth > 8); 3577 if (isDirect && (hwDesc->bitDepth != 32) && (hwDesc->bitDepth != 16)) 3578 return (false); 3579 3580 width = hwDesc->width; 3581 height = hwDesc->height; 3582 3583 // matrox workaround - 2979661 3584 if ((maxColors > 1) && (&clut[1] == (IOColorEntry *) hwCursorInfo)) 3585 width = height = 16; 3586 // -- 3587 3588 SInt32 adjX = 4 - shmem->hotSpot[0 != frame].x; 3589 SInt32 adjY = 4 - shmem->hotSpot[0 != frame].y; 3590 if ((adjX < 0) || ((UInt32)(x + adjX) > width)) 3591 adjX = 0; 3592 else 3593 x += adjX; 3594 if ((adjY < 0) || ((UInt32)(y + adjY) > height)) 3595 adjY = 0; 3596 3597 __private->cursorHotSpotAdjust[0 != frame].x = adjX; 3598 __private->cursorHotSpotAdjust[0 != frame].y = adjY; 3599 3600 while ((width >> 1) >= (UInt32) x) 3601 width >>= 1; 3602 while ((UInt32)(height >> 1) >= (UInt32)(y + adjY)) 3603 height >>= 1; 3604 3605 hwCursorInfo->cursorWidth = width; 3606 hwCursorInfo->cursorHeight = height; 3607 hwCursorInfo->cursorHotSpotX = shmem->hotSpot[0 != frame].x 3608 + __private->cursorHotSpotAdjust[0 != frame].x; 3609 hwCursorInfo->cursorHotSpotY = shmem->hotSpot[0 != frame].y 3610 + __private->cursorHotSpotAdjust[0 != frame].y; 3611 lastx = x - width - 1; 3612 3613 if (isDirect && adjY) 3614 { 3615 lineBytes = width * (hwDesc->bitDepth >> 3); 3616 // top lines 3617 bzero_nc( dataOut, adjY * lineBytes ); 3618 dataOut += adjY * lineBytes; 3619 // bottom lines 3620 adjY = height - shmem->cursorSize[0 != frame].height - adjY; 3621 lasty = -1; 3622 } 3623 else 3624 { 3625 y += adjY; 3626 lasty = y - height - 1; 3627 } 3628 3629 while (ok && (--y != lasty)) 3630 { 3631 x = shmem->cursorSize[0 != frame].width + adjX; 3632 while (ok && (--x != lastx)) 3633 { 3634 if ((x < 0) 3635 || (y < 0) 3636 || (x >= shmem->cursorSize[0 != frame].width) 3637 || (y >= shmem->cursorSize[0 != frame].height)) 3638 alpha = red = green = blue = 0; 3639 3640 else if (cursPtr32) 3641 { 3642 s32 = *(cursPtr32++); 3643 alpha = (s32 >> 24) & 0xff; 3644 red = (s32 >> 16) & 0xff; 3645 green = (s32 >> 8) & 0xff; 3646 blue = (s32) & 0xff; 3647 } 3648 else 3649 { 3650#define RMASK16 0xF000 3651#define GMASK16 0x0F00 3652#define BMASK16 0x00F0 3653#define AMASK16 0x000F 3654 s16 = *(cursPtr16++); 3655 alpha = s16 & AMASK16; 3656 alpha |= (alpha << 4); 3657 red = (s16 & RMASK16) >> 8; 3658 red |= (red >> 4); 3659 green = (s16 & GMASK16) >> 4; 3660 green |= (green >> 4); 3661 blue = s16 & BMASK16; 3662 blue |= (blue >> 4); 3663 } 3664 3665 if (isDirect) 3666 { 3667 if (alpha == 0) 3668 { 3669 if (0xff == (red & green & blue)) 3670 { 3671 /* Transparent white area. Invert dst. */ 3672 if (kInvertingEncodedPixel 3673 & hwDesc->supportedSpecialEncodings) 3674 pixel = hwDesc->specialEncodings[kInvertingEncoding]; 3675 else 3676 ok = false; 3677 } 3678 else 3679 pixel = 0; 3680 3681 if (hwDesc->bitDepth == 32) 3682 STOREINC(dataOut, pixel, UInt32) 3683 else 3684 STOREINC(dataOut, pixel, UInt16) 3685 } 3686 else 3687 { 3688 if (0xff != alpha) 3689 { 3690 red = 0xff * red / alpha; 3691 green = 0xff * green / alpha; 3692 blue = 0xff * blue / alpha; 3693 } 3694 if (hwDesc->bitDepth == 32) 3695 { 3696 pixel = (alpha << 24) 3697 | ((red & 0xff) << 16) 3698 | ((green & 0xff) << 8) 3699 | (blue & 0xff); 3700 3701 STOREINC(dataOut, pixel, UInt32) 3702 } 3703 else 3704 { 3705 pixel = ((alpha & 0xf0) << 8) 3706 | ((red & 0xf0) << 4) 3707 | ((green & 0xf0) << 0) 3708 | ((blue & 0xf0) >> 4); 3709 3710 STOREINC(dataOut, pixel, UInt16) 3711 } 3712 } 3713 } 3714 else 3715 { 3716 /* Indexed pixels */ 3717 3718 if (alpha == 0) 3719 { 3720 if (0 == (red | green | blue)) 3721 { 3722 /* Transparent black area. Leave dst as is. */ 3723 if (kTransparentEncodedPixel 3724 & hwDesc->supportedSpecialEncodings) 3725 pixel = hwDesc->specialEncodings[kTransparentEncoding]; 3726 else 3727 ok = false; 3728 } 3729 else if (0xff == (red & green & blue)) 3730 { 3731 /* Transparent white area. Invert dst. */ 3732 if (kInvertingEncodedPixel 3733 & hwDesc->supportedSpecialEncodings) 3734 pixel = hwDesc->specialEncodings[kInvertingEncoding]; 3735 else 3736 ok = false; 3737 } 3738 else 3739 ok = false; 3740 } 3741 else if (alpha == 0xff) 3742 { 3743 red |= (red << 8); 3744 green |= (green << 8); 3745 blue |= (blue << 8); 3746 3747 /* Opaque cursor pixel. Mark it. */ 3748 for (index = 0; index < numColors; index++) 3749 { 3750 if ((red == clut[index].red) 3751 && (green == clut[index].green) 3752 && (blue == clut[index].blue)) 3753 { 3754 pixel = clut[index].index; 3755 break; 3756 } 3757 } 3758 if (index == numColors) 3759 { 3760 ok = (numColors < maxColors); 3761 if (ok) 3762 { 3763 pixel = hwDesc->colorEncodings[numColors++]; 3764 clut[index].red = red; 3765 clut[index].green = green; 3766 clut[index].blue = blue; 3767 clut[index].index = pixel; 3768 } 3769 } 3770 } 3771 else 3772 { 3773 /* Alpha is not 0 or 1.0. Sover the cursor. */ 3774 ok = false; 3775 break; 3776 } 3777 data <<= hwDesc->bitDepth; 3778 data |= pixel; 3779 bits += hwDesc->bitDepth; 3780 if (0 == (bits & 31)) 3781 { 3782 OSWriteBigInt32(dataOut, 0, data); 3783 dataOut += sizeof(UInt32); 3784 } 3785 } 3786 } /* x */ 3787 } /* y */ 3788 3789 if (ok && isDirect && adjY) 3790 { 3791 // bottom lines 3792 bzero_nc( dataOut, adjY * lineBytes ); 3793 dataOut += adjY * lineBytes; 3794 } 3795 3796 __private->cursorClutDependent = (ok && !isDirect); 3797 3798#if 0 3799 if (ok) 3800 { 3801 static UInt32 lastWidth; 3802 static UInt32 lastHeight; 3803 3804 if ((width != lastWidth) || (height != lastHeight)) 3805 { 3806 lastWidth = width; 3807 lastHeight = height; 3808 IOLog("[%d,%d]", width, height); 3809 } 3810 3811 if (((UInt32)(dataOut - hwCursorInfo->hardwareCursorData) 3812 != ((hwCursorInfo->cursorHeight * hwCursorInfo->cursorWidth * hwDesc->bitDepth) >> 3))) 3813 IOLog("dataOut %p, %p @ %d\n", dataOut, hwCursorInfo->hardwareCursorData, hwDesc->bitDepth ); 3814 } 3815#endif 3816 3817 return (ok); 3818} 3819 3820/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3821 3822// Apple standard 8-bit CLUT 3823 3824#if 0 3825UInt8 appleClut8[256 * 3] = 3826{ 3827 // 00 3828 0xFF,0xFF,0xFF, 0xFF,0xFF,0xCC, 0xFF,0xFF,0x99, 0xFF,0xFF,0x66, 3829 0xFF,0xFF,0x33, 0xFF,0xFF,0x00, 0xFF,0xCC,0xFF, 0xFF,0xCC,0xCC, 3830 0xFF,0xCC,0x99, 0xFF,0xCC,0x66, 0xFF,0xCC,0x33, 0xFF,0xCC,0x00, 3831 0xFF,0x99,0xFF, 0xFF,0x99,0xCC, 0xFF,0x99,0x99, 0xFF,0x99,0x66, 3832 // 10 3833 0xFF,0x99,0x33, 0xFF,0x99,0x00, 0xFF,0x66,0xFF, 0xFF,0x66,0xCC, 3834 0xFF,0x66,0x99, 0xFF,0x66,0x66, 0xFF,0x66,0x33, 0xFF,0x66,0x00, 3835 0xFF,0x33,0xFF, 0xFF,0x33,0xCC, 0xFF,0x33,0x99, 0xFF,0x33,0x66, 3836 0xFF,0x33,0x33, 0xFF,0x33,0x00, 0xFF,0x00,0xFF, 0xFF,0x00,0xCC, 3837 // 20 3838 0xFF,0x00,0x99, 0xFF,0x00,0x66, 0xFF,0x00,0x33, 0xFF,0x00,0x00, 3839 0xCC,0xFF,0xFF, 0xCC,0xFF,0xCC, 0xCC,0xFF,0x99, 0xCC,0xFF,0x66, 3840 0xCC,0xFF,0x33, 0xCC,0xFF,0x00, 0xCC,0xCC,0xFF, 0xCC,0xCC,0xCC, 3841 0xCC,0xCC,0x99, 0xCC,0xCC,0x66, 0xCC,0xCC,0x33, 0xCC,0xCC,0x00, 3842 // 30 3843 0xCC,0x99,0xFF, 0xCC,0x99,0xCC, 0xCC,0x99,0x99, 0xCC,0x99,0x66, 3844 0xCC,0x99,0x33, 0xCC,0x99,0x00, 0xCC,0x66,0xFF, 0xCC,0x66,0xCC, 3845 0xCC,0x66,0x99, 0xCC,0x66,0x66, 0xCC,0x66,0x33, 0xCC,0x66,0x00, 3846 0xCC,0x33,0xFF, 0xCC,0x33,0xCC, 0xCC,0x33,0x99, 0xCC,0x33,0x66, 3847 // 40 3848 0xCC,0x33,0x33, 0xCC,0x33,0x00, 0xCC,0x00,0xFF, 0xCC,0x00,0xCC, 3849 0xCC,0x00,0x99, 0xCC,0x00,0x66, 0xCC,0x00,0x33, 0xCC,0x00,0x00, 3850 0x99,0xFF,0xFF, 0x99,0xFF,0xCC, 0x99,0xFF,0x99, 0x99,0xFF,0x66, 3851 0x99,0xFF,0x33, 0x99,0xFF,0x00, 0x99,0xCC,0xFF, 0x99,0xCC,0xCC, 3852 // 50 3853 0x99,0xCC,0x99, 0x99,0xCC,0x66, 0x99,0xCC,0x33, 0x99,0xCC,0x00, 3854 0x99,0x99,0xFF, 0x99,0x99,0xCC, 0x99,0x99,0x99, 0x99,0x99,0x66, 3855 0x99,0x99,0x33, 0x99,0x99,0x00, 0x99,0x66,0xFF, 0x99,0x66,0xCC, 3856 0x99,0x66,0x99, 0x99,0x66,0x66, 0x99,0x66,0x33, 0x99,0x66,0x00, 3857 // 60 3858 0x99,0x33,0xFF, 0x99,0x33,0xCC, 0x99,0x33,0x99, 0x99,0x33,0x66, 3859 0x99,0x33,0x33, 0x99,0x33,0x00, 0x99,0x00,0xFF, 0x99,0x00,0xCC, 3860 0x99,0x00,0x99, 0x99,0x00,0x66, 0x99,0x00,0x33, 0x99,0x00,0x00, 3861 0x66,0xFF,0xFF, 0x66,0xFF,0xCC, 0x66,0xFF,0x99, 0x66,0xFF,0x66, 3862 // 70 3863 0x66,0xFF,0x33, 0x66,0xFF,0x00, 0x66,0xCC,0xFF, 0x66,0xCC,0xCC, 3864 0x66,0xCC,0x99, 0x66,0xCC,0x66, 0x66,0xCC,0x33, 0x66,0xCC,0x00, 3865 0x66,0x99,0xFF, 0x66,0x99,0xCC, 0x66,0x99,0x99, 0x66,0x99,0x66, 3866 0x66,0x99,0x33, 0x66,0x99,0x00, 0x66,0x66,0xFF, 0x66,0x66,0xCC, 3867 // 80 3868 0x66,0x66,0x99, 0x66,0x66,0x66, 0x66,0x66,0x33, 0x66,0x66,0x00, 3869 0x66,0x33,0xFF, 0x66,0x33,0xCC, 0x66,0x33,0x99, 0x66,0x33,0x66, 3870 0x66,0x33,0x33, 0x66,0x33,0x00, 0x66,0x00,0xFF, 0x66,0x00,0xCC, 3871 0x66,0x00,0x99, 0x66,0x00,0x66, 0x66,0x00,0x33, 0x66,0x00,0x00, 3872 // 90 3873 0x33,0xFF,0xFF, 0x33,0xFF,0xCC, 0x33,0xFF,0x99, 0x33,0xFF,0x66, 3874 0x33,0xFF,0x33, 0x33,0xFF,0x00, 0x33,0xCC,0xFF, 0x33,0xCC,0xCC, 3875 0x33,0xCC,0x99, 0x33,0xCC,0x66, 0x33,0xCC,0x33, 0x33,0xCC,0x00, 3876 0x33,0x99,0xFF, 0x33,0x99,0xCC, 0x33,0x99,0x99, 0x33,0x99,0x66, 3877 // a0 3878 0x33,0x99,0x33, 0x33,0x99,0x00, 0x33,0x66,0xFF, 0x33,0x66,0xCC, 3879 0x33,0x66,0x99, 0x33,0x66,0x66, 0x33,0x66,0x33, 0x33,0x66,0x00, 3880 0x33,0x33,0xFF, 0x33,0x33,0xCC, 0x33,0x33,0x99, 0x33,0x33,0x66, 3881 0x33,0x33,0x33, 0x33,0x33,0x00, 0x33,0x00,0xFF, 0x33,0x00,0xCC, 3882 // b0 3883 0x33,0x00,0x99, 0x33,0x00,0x66, 0x33,0x00,0x33, 0x33,0x00,0x00, 3884 0x00,0xFF,0xFF, 0x00,0xFF,0xCC, 0x00,0xFF,0x99, 0x00,0xFF,0x66, 3885 0x00,0xFF,0x33, 0x00,0xFF,0x00, 0x00,0xCC,0xFF, 0x00,0xCC,0xCC, 3886 0x00,0xCC,0x99, 0x00,0xCC,0x66, 0x00,0xCC,0x33, 0x00,0xCC,0x00, 3887 // c0 3888 0x00,0x99,0xFF, 0x00,0x99,0xCC, 0x00,0x99,0x99, 0x00,0x99,0x66, 3889 0x00,0x99,0x33, 0x00,0x99,0x00, 0x00,0x66,0xFF, 0x00,0x66,0xCC, 3890 0x00,0x66,0x99, 0x00,0x66,0x66, 0x00,0x66,0x33, 0x00,0x66,0x00, 3891 0x00,0x33,0xFF, 0x00,0x33,0xCC, 0x00,0x33,0x99, 0x00,0x33,0x66, 3892 // d0 3893 0x00,0x33,0x33, 0x00,0x33,0x00, 0x00,0x00,0xFF, 0x00,0x00,0xCC, 3894 0x00,0x00,0x99, 0x00,0x00,0x66, 0x00,0x00,0x33, 0xEE,0x00,0x00, 3895 0xDD,0x00,0x00, 0xBB,0x00,0x00, 0xAA,0x00,0x00, 0x88,0x00,0x00, 3896 0x77,0x00,0x00, 0x55,0x00,0x00, 0x44,0x00,0x00, 0x22,0x00,0x00, 3897 // e0 3898 0x11,0x00,0x00, 0x00,0xEE,0x00, 0x00,0xDD,0x00, 0x00,0xBB,0x00, 3899 0x00,0xAA,0x00, 0x00,0x88,0x00, 0x00,0x77,0x00, 0x00,0x55,0x00, 3900 0x00,0x44,0x00, 0x00,0x22,0x00, 0x00,0x11,0x00, 0x00,0x00,0xEE, 3901 0x00,0x00,0xDD, 0x00,0x00,0xBB, 0x00,0x00,0xAA, 0x00,0x00,0x88, 3902 // f0 3903 0x00,0x00,0x77, 0x00,0x00,0x55, 0x00,0x00,0x44, 0x00,0x00,0x22, 3904 0x00,0x00,0x11, 0xEE,0xEE,0xEE, 0xDD,0xDD,0xDD, 0xBB,0xBB,0xBB, 3905 0xAA,0xAA,0xAA, 0x88,0x88,0x88, 0x77,0x77,0x77, 0x55,0x55,0x55, 3906 0x44,0x44,0x44, 0x22,0x22,0x22, 0x11,0x11,0x11, 0x00,0x00,0x00 3907}; 3908#endif 3909 3910/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3911 3912#ifdef __ppc__ 3913extern 3914#endif 3915 int killprint; 3916extern "C" 3917{ 3918 int kmputc( int c ); 3919} 3920 3921#if DOANIO 3922 3923#warning ** DO AN IO ** 3924 3925static unsigned long doaniobuf[256]; 3926 3927static void doanio( void ) 3928{ 3929 struct uio uio; 3930 struct iovec iovec; 3931 int err; 3932 dev_t device = makedev( 14, 0 ); 3933 3934 iovec.iov_base = (char *) &doaniobuf[0]; 3935 iovec.iov_len = 1024; 3936 3937 uio.uio_iov = &iovec; 3938 uio.uio_iovcnt = 1; 3939 uio.uio_rw = UIO_READ; 3940 uio.uio_segflg = UIO_SYSSPACE; 3941 uio.uio_offset = 0; 3942 uio.uio_resid = 1024; 3943 3944 DEBG("", "\n"); 3945 err = ((*cdevsw[major(device)].d_read)(device, &uio, 0)); 3946 DEBG("", " done(%08lx)\n", doaniobuf[0]); 3947} 3948 3949#endif 3950 3951IOReturn IOFramebuffer::deliverDisplayModeDidChangeNotification( void ) 3952{ 3953 IOReturn 3954 ret = deliverFramebufferNotification( kIOFBNotifyDisplayModeDidChange ); 3955 3956 if (__private->lastNotifyOnline != __private->online) 3957 { 3958 __private->lastNotifyOnline = __private->online; 3959 deliverFramebufferNotification( kIOFBNotifyOnlineChange, (void *)(uintptr_t) __private->online); 3960 } 3961 3962 return (ret); 3963} 3964 3965void IOFramebuffer::saveFramebuffer(void) 3966{ 3967#if VRAM_SAVE 3968 // vram content is being lost 3969 uintptr_t value; 3970 if (true 3971 && !dead 3972 && !__private->saveLength 3973 && __private->online 3974 && __private->framebufferHeight 3975 && __private->framebufferWidth 3976 && rowBytes 3977 && (kIOReturnSuccess == getAttribute(kIOVRAMSaveAttribute, &value)) 3978 && value) 3979 { 3980 vm_size_t sLen; 3981 sLen = __private->framebufferHeight * rowBytes; 3982 3983 /* 3984 * dLen should account for possible growth. (e.g. run-length encoding noise) 3985 * Add 5 bytes for header, 3986 * 12% for RLE growth 3987 * 2 bytes per line for line spans, 3988 * 1 additional escape code byte for trailing pixel in each line 3989 */ 3990#if VRAM_COMPRESS 3991 vm_size_t dLen; 3992 uint32_t idx; 3993 3994 dLen = 5 + sLen + ((sLen + 7) >> 3) + (__private->framebufferHeight * 3) + rowBytes; 3995 3996 for (idx = 0; 3997 (idx < kIOPreviewImageCount) && __private->saveBitsMD[idx]; 3998 idx++) {} 3999 4000 dLen *= (idx + 1); 4001 DEBG1(thisName, " dLen 0x%x\n", (int) dLen); 4002 4003 dLen = round_page(dLen); 4004 if (dLen >= 96*1024*1024) dLen = 95*1024*1024; 4005 __private->saveLength = dLen; 4006#else 4007 __private->saveLength = round_page(sLen); 4008#endif 4009 __private->saveFramebuffer = IOMallocPageable( __private->saveLength, page_size ); 4010 if (!__private->saveFramebuffer) 4011 __private->saveLength = 0; 4012 else 4013 { 4014#if VRAM_COMPRESS 4015 UInt8 * bits[kIOPreviewImageCount] = { 0 }; 4016 IOByteCount bitsLen = 0; 4017 IOMemoryMap * map[kIOPreviewImageCount] = { 0 }; 4018 4019 for (idx = 0; 4020 (idx < kIOPreviewImageCount) && __private->saveBitsMD[idx]; 4021 idx++) 4022 { 4023 map[idx] = __private->saveBitsMD[idx]->map(kIOMapReadOnly); 4024 if (map[idx]) 4025 { 4026 bits[idx] = (UInt8 *) map[idx]->getVirtualAddress(); 4027 if (!idx) bitsLen = map[idx]->getLength(); 4028 else if (bitsLen != map[idx]->getLength()) 4029 { 4030 bits[idx] = NULL; 4031 map[idx]->release(); 4032 map[idx] = 0; 4033 } 4034 } 4035 __private->saveBitsMD[idx]->release(); 4036 __private->saveBitsMD[idx] = 0; 4037 } 4038 4039 if (!bits[0]) 4040 { 4041 IOLog("%s: no save bits\n", thisName); 4042 dLen = 0; 4043 } 4044 else if ((((__private->framebufferHeight - 1) * rowBytes) 4045 + __private->framebufferWidth * bytesPerPixel) > bitsLen) 4046 { 4047 IOLog("%s: bad pixel parameters %d x %d x %d > 0x%x\n", thisName, 4048 (int) __private->framebufferWidth, (int) __private->framebufferHeight, (int) rowBytes, (int) bitsLen); 4049 dLen = 0; 4050 } 4051 else 4052 { 4053 uint8_t * gammaData = __private->gammaData; 4054 if (gammaData) gammaData += __private->gammaHeaderSize; 4055 dLen = CompressData( bits, kIOPreviewImageCount, bytesPerPixel, 4056 __private->framebufferWidth, __private->framebufferHeight, rowBytes, 4057 (UInt8 *) __private->saveFramebuffer, __private->saveLength, 4058 __private->gammaChannelCount, __private->gammaDataCount, 4059 __private->gammaDataWidth, gammaData); 4060 } 4061 DEBG1(thisName, " compressed to %d%%\n", (int) ((dLen * 100) / sLen)); 4062 4063 for (idx = 0; (idx < kIOPreviewImageCount); idx++) 4064 { 4065 if (map[idx]) map[idx]->release(); 4066 } 4067 4068 dLen = round_page( dLen ); 4069 if (__private->saveLength > dLen) 4070 { 4071 IOFreePageable( (void *) (((uintptr_t) __private->saveFramebuffer) + dLen), 4072 __private->saveLength - dLen ); 4073 __private->saveLength = dLen; 4074 } 4075#else 4076 if (frameBuffer) bcopy_nc( (void *) frameBuffer, __private->saveFramebuffer, sLen ); 4077#endif 4078 if (__private->saveLength) 4079 { 4080#if RLOG 4081 kern_return_t kr = 4082#endif 4083 vm_map_wire( IOPageableMapForAddress( (vm_address_t) __private->saveFramebuffer ), 4084 (vm_address_t) __private->saveFramebuffer, 4085 ((vm_address_t) __private->saveFramebuffer) + __private->saveLength, 4086 VM_PROT_READ | VM_PROT_WRITE, FALSE ); 4087 DEBG(thisName, " vm_map_wire(%x)\n", kr); 4088 4089 if (this == gIOFBConsoleFramebuffer) 4090 { 4091 IOMemoryDescriptor * 4092 previewBuffer = IOMemoryDescriptor::withAddress( 4093 __private->saveFramebuffer, 4094 __private->saveLength, 4095 kIODirectionInOut); 4096 if (previewBuffer) 4097 { 4098 getPMRootDomain()->setProperty(kIOHibernatePreviewBufferKey, previewBuffer); 4099 previewBuffer->release(); 4100 4101 OSNumber * num; 4102 if (false 4103 && frameBuffer 4104 && (num = OSDynamicCast(OSNumber, getPMRootDomain()->getProperty(kIOHibernateModeKey))) 4105 && (kIOHibernateModeOn == ((kIOHibernateModeSleep | kIOHibernateModeOn) & num->unsigned32BitValue())) 4106 && !gIOFBCurrentClamshellState) 4107 { 4108 // hibernate enabled, will power off, clamshell open - do preview 4109 UInt32 flags = 0; 4110 getProvider()->setProperty(kIOHibernatePreviewActiveKey, &flags, sizeof(flags)); 4111 PreviewDecompressData(&__private->saveFramebuffer, 0, (void *)frameBuffer, 4112 __private->framebufferWidth, __private->framebufferHeight, 4113 bytesPerPixel, rowBytes); 4114 } 4115 } 4116 } 4117 } 4118 } 4119 } 4120#endif /* VRAM_SAVE */ 4121} 4122 4123IOReturn IOFramebuffer::restoreFramebuffer(IOIndex event) 4124{ 4125 IOReturn ret = kIOReturnNotReady; 4126 uint32_t restoreType; 4127 4128 if (2 == pendingPowerState) 4129 { 4130 restoreType = 4131 (kOSBooleanFalse == getPMRootDomain()->getProperty(kIOPMUserTriggeredFullWakeKey)) 4132 ? kIOScreenRestoreStateDark : kIOScreenRestoreStateNormal; 4133 } 4134 else restoreType = kIOScreenRestoreStateDark; 4135 4136 if (__private->hibernateGfxStatus) restoreType = kIOScreenRestoreStateDark; 4137 4138#if VRAM_SAVE 4139 // restore vram content 4140 if (restoreType != __private->restoreType) 4141 { 4142 thread_t saveThread = NULL; 4143 4144 if (kIOFBNotifyVRAMReady == event) 4145 { 4146 IOMemoryDescriptor * vram; 4147 if ((vram = getVRAMRange())) 4148 { 4149 vram->redirect( kernel_task, false ); 4150 vram->release(); 4151 } 4152 } 4153 else 4154 { 4155 saveThread = __private->controller->powerThread; 4156 __private->controller->powerThread = current_thread(); 4157 setAttribute(kIOFBSpeedAttribute, kIOFBVRAMCompressSpeed); 4158 } 4159 4160 if (!__private->saveLength) restoreType = kIOScreenRestoreStateDark; 4161 4162 if (frameBuffer) 4163 { 4164 if (kIOScreenRestoreStateDark == restoreType) 4165 { 4166 volatile unsigned char * line = frameBuffer; 4167 for (uint32_t y = 0; y < __private->framebufferHeight; y++) 4168 { 4169 bzero((void *) line, __private->framebufferWidth * __private->cursorBytesPerPixel); 4170 line += rowBytes; 4171 } 4172 } 4173 else 4174 { 4175 KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_IOGRAPHICS, DBG_IOG_VRAM_RESTORE) | DBG_FUNC_START, 4176 0, (uintptr_t) __private->regID, (uintptr_t) (__private->regID >> 32), 0, 0); 4177 #if VRAM_COMPRESS 4178 uint32_t image = (kOSBooleanTrue == 4179 IORegistryEntry::getRegistryRoot()->getProperty(kIOConsoleLockedKey)); 4180 if (image >= kIOPreviewImageCount) image = 0; 4181 DecompressData((UInt8 *) __private->saveFramebuffer, image, (UInt8 *) frameBuffer, 4182 0, 0, __private->framebufferWidth, __private->framebufferHeight, rowBytes); 4183 #else 4184 bcopy_nc( __private->saveFramebuffer, (void *) frameBuffer, __private->saveLength ); 4185 #endif 4186 KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_IOGRAPHICS, DBG_IOG_VRAM_RESTORE) | DBG_FUNC_END, 4187 0, (uintptr_t) __private->regID, (uintptr_t) (__private->regID >> 32), 0, 0); 4188 DEBG1(thisName, " screen drawn\n"); 4189 } 4190 } 4191 DEBG1(thisName, " restoretype %d->%d\n", __private->restoreType, restoreType); 4192 __private->needGammaRestore = (0 == __private->restoreType); 4193 __private->restoreType = restoreType; 4194 4195 if (kIOFBNotifyVRAMReady != event) 4196 { 4197 setAttribute(kIOFBSpeedAttribute, __private->reducedSpeed); 4198 __private->controller->powerThread = saveThread; 4199 } 4200 4201 ret = kIOReturnSuccess; 4202 } 4203 4204 if ((kIOFBNotifyVRAMReady != event) && __private->restoreType && __private->needGammaRestore) 4205 { 4206 if (__private->gammaDataLen && __private->gammaData && !__private->scaledMode) 4207 { 4208 DEBG1(thisName, " set gamma\n"); 4209 setGammaTable( __private->gammaChannelCount, __private->gammaDataCount, 4210 __private->gammaDataWidth, __private->gammaData ); 4211 } 4212 __private->needGammaRestore = false; 4213 } 4214#endif /* VRAM_SAVE */ 4215 4216 return (ret); 4217} 4218 4219IOReturn IOFramebuffer::handleEvent( IOIndex event, void * info ) 4220{ 4221 IOReturn ret = kIOReturnSuccess; 4222 bool sendEvent = true; 4223 4224 DEBG1(thisName, "(%d, %d)\n", (uint32_t) event, 4225 current_thread() != __private->controller->powerThread); 4226 4227 if (current_thread() != __private->controller->powerThread) 4228 { 4229 sendEvent = false; 4230 } 4231 else switch (event) 4232 { 4233 case kIOFBNotifyWillSleep: 4234 if (!info) 4235 break; 4236 4237 if (this == gIOFBConsoleFramebuffer) 4238 { 4239// getPlatform()->setConsoleInfo( 0, kPEDisableScreen); 4240 killprint = 1; 4241 } 4242 __private->restoreType = kIOScreenRestoreStateNone; 4243 // notification sent early at system sleep 4244 sendEvent = false; 4245 ret = kIOReturnSuccess; 4246 break; 4247 4248 case kIOFBNotifyDidWake: 4249 if (!info) 4250 break; 4251 4252 restoreFramebuffer(event); 4253 4254 if (this == gIOFBConsoleFramebuffer) 4255 { 4256// getPlatform()->setConsoleInfo( 0, kPEEnableScreen); 4257 killprint = 0; 4258 kmputc( 033 ); 4259 kmputc( 'c' ); 4260 } 4261 4262 sleepConnectCheck = true; 4263 4264#if DOANIO 4265 doanio(); 4266#endif 4267 pagingState = true; 4268 __private->actualVBLCount = 0; 4269 updateVBL(this, NULL); 4270 ret = deliverFramebufferNotification(kIOFBNotifyDidWake, (void *) true); 4271 info = (void *) false; 4272 break; 4273 4274 case kIOFBNotifyDidPowerOn: 4275 pagingState = true; 4276 ret = kIOReturnSuccess; 4277 break; 4278 4279 case kIOFBNotifyVRAMReady: 4280 ret = restoreFramebuffer(event); 4281 sendEvent = false; 4282 break; 4283 } 4284 4285 if (sendEvent) 4286 ret = deliverFramebufferNotification(event, info); 4287 4288 return (ret); 4289} 4290 4291IOReturn IOFramebuffer::notifyServer( UInt8 state ) 4292{ 4293 mach_msg_header_t * msgh = (mach_msg_header_t *) serverMsg; 4294 IOReturn err = kIOReturnSuccess; 4295 4296 if (serverNotified != state) 4297 { 4298 if (!gChosenEntry) gChosenEntry = IORegistryEntry::fromPath("/chosen", gIODTPlane); 4299 if (gChosenEntry && !state) gChosenEntry->removeProperty(kIOScreenLockStateKey); 4300 if (state) 4301 { 4302 if (this == gIOFBConsoleFramebuffer) 4303 { 4304 getPMRootDomain()->removeProperty(kIOHibernatePreviewBufferKey); 4305 getProvider()->removeProperty(kIOHibernatePreviewActiveKey); 4306 } 4307 if (__private->saveFramebuffer && __private->saveLength) 4308 { 4309 IOFreePageable( __private->saveFramebuffer, __private->saveLength ); 4310 } 4311 __private->saveFramebuffer = 0; 4312 __private->saveLength = 0; 4313 setProperty(kIOScreenRestoreStateKey, 4314 &__private->restoreType, sizeof(__private->restoreType)); 4315 DEBG1(thisName, " kIOScreenRestoreStateKey %d\n", __private->restoreType); 4316 __private->restoreType = kIOScreenRestoreStateNone; 4317 __private->needGammaRestore = false; 4318 } 4319 4320 serverNotified = state; 4321 4322 DEBG1(thisName, "(%p, wait %d, %d->%d)\n", msgh->msgh_remote_port, 4323 __private->controller->wsWait, serverState, serverNotified); 4324 4325 KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_IOGRAPHICS, DBG_IOG_NOTIFYSERVER) | DBG_FUNC_NONE, 4326 state, (uintptr_t) __private->regID, (uintptr_t) (__private->regID >> 32), 0, 0); 4327 4328 msgh->msgh_id = state; 4329 if ((MACH_PORT_NULL == msgh->msgh_remote_port) 4330 || (KERN_SUCCESS != mach_msg_send_from_kernel(msgh, msgh->msgh_size))) 4331 { 4332 // failed to send 4333 serverState = serverNotified; 4334 } 4335 else 4336 { 4337 // start ack timeout 4338 gIOFBServerAckTimer->setTimeoutMS(kServerAckTimeout * 1000); 4339 } 4340 } 4341 4342 if (serverNotified) 4343 { 4344 // wakeup is not gate specific 4345 FBWL(this)->wakeupGate(&serverConnect, true); 4346 } 4347 4348 return (err); 4349} 4350 4351bool IOFramebuffer::getIsUsable( void ) 4352{ 4353 return (dead || (0 != isUsable)); 4354} 4355 4356IOReturn IOFramebuffer::postWake(void) 4357{ 4358 IOReturn ret; 4359 uintptr_t value; 4360 bool probeDP; 4361 4362 DEBG1(thisName, " post wake from sleep %d\n", sleepConnectCheck); 4363 4364 probeDP = (__private->dpDongle && !sleepConnectCheck); 4365 4366 ret = getAttributeForConnection(0, kConnectionPostWake, &value); 4367 4368 if (captured) 4369 gIOFBProbeCaptured = true; 4370 else 4371 { 4372 getAttributeForConnection(0, kConnectionChanged, 0); 4373 if (probeDP) 4374 { 4375#if RLOG 4376 IOReturn probeErr = 4377#endif 4378 setAttributeForConnection(0, kConnectionProbe, kIOFBUserRequestProbe); 4379 DEBG(thisName, " dp probe wake result %x\n", probeErr); 4380 } 4381 } 4382 4383 __private->controller->postWakeChange = __private->controller->connectChange; 4384 if (sleepConnectCheck) 4385 { 4386 gIOFBLastReadClamshellState = gIOFBCurrentClamshellState; 4387 sleepConnectCheck = false; 4388 } 4389 4390 resetClamshell(kIOFBClamshellProbeDelayMS); 4391 4392 return (ret); 4393} 4394 4395/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4396 4397IOReturn IOFramebuffer::pmSettingsChange(OSObject * target, const OSSymbol * type, 4398 OSObject * val, uintptr_t refcon) 4399{ 4400 if (type == gIOFBPMSettingDisplaySleepUsesDimKey) 4401 { 4402 OSBitOrAtomic(kIOFBEventDisplayDimsSetting, &gIOFBGlobalEvents); 4403 startThread(false); 4404 } 4405 return (kIOReturnSuccess); 4406} 4407 4408/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4409 4410void IOFramebuffer::startAsync(IOFBController * controller, uint32_t asyncWork) 4411{ 4412 if (!gIOFBSystemWorkLoop->inGate()) panic("!sys"); 4413 if (!controller->wl->inGate()) panic("!gate\n"); 4414 if (controller->asyncWork) panic("asyncWork"); 4415 if (controller->didWork) panic("didWork"); 4416 4417 controller->asyncWork = asyncWork; 4418 controller->workES->interruptOccurred(0, 0, 0); 4419} 4420 4421// system WL 4422 4423enum 4424{ 4425 kIOFBDidWork = 0x00000001, 4426 kIOFBWorking = 0x00000002, 4427 kIOFBPaging = 0x00000004, 4428 kIOFBWsWait = 0x00000008, 4429 kIOFBDimmed = 0x00000010, 4430 kIOFBServerSlept = 0x00000020, // any fb ws notified asleep 4431 kIOFBServerUp = 0x00000040, // any fb ws state awake 4432 kIOFBServerDown = 0x00000080, // any fb ws state asleep 4433 kIOFBCaptured = 0x00000100, 4434 kIOFBDimDisable = 0x00000200, 4435 kIOFBDisplaysChanging = 0x00001000 4436}; 4437 4438enum 4439{ 4440 kWorkStateChange = 0x00000001, 4441 kWorkPower = 0x00000002, 4442 kWorkSuspend = 0x00000004, 4443}; 4444 4445void IOFramebuffer::systemWork(OSObject * owner, 4446 IOInterruptEventSource * evtSrc, int intCount) 4447{ 4448 UInt32 events; 4449 uint32_t index; 4450 IOFBController * controller; 4451 IOFramebuffer * fb; 4452 uint32_t allState; 4453 4454 allState = 0; 4455 4456 controller = gIOFBAllControllers; 4457 if (controller) do 4458 { 4459 allState |= controllerState(controller); 4460 controller = controller->nextController; 4461 } 4462 while (controller != gIOFBAllControllers); 4463 4464 DEBG1("S1", " state 0x%x\n", allState); 4465 4466 controller = gIOFBAllControllers; 4467 if (controller) do 4468 { 4469 if (controller->needsWork) 4470 { 4471 uint32_t state = allState; 4472 DEBG1(controller->name, " working %x\n", state); 4473 4474 FCLOCK(controller); 4475 if (!controller->didWork) 4476 { 4477 if (kIOFBEventSystemPowerOn & gIOFBGlobalEvents) 4478 { 4479 OSBitAndAtomic(~kIOFBEventSystemPowerOn, &gIOFBGlobalEvents); 4480 muxPowerMessage(kIOMessageDeviceWillPowerOn); 4481 } 4482 4483 state |= checkPowerWork(controller, state); 4484 4485 if (kIOFBServerSlept & state) 4486 { 4487 if ((controller->lastFinishedChange != controller->connectChange) 4488 && !controller->fbs[0]->messaged 4489 && gIOFBSwitching) 4490 { 4491 IODisplayWrangler::activityChange(controller->fbs[0]); 4492 } 4493 } 4494 else if (!(kIOFBServerDown & state)) 4495 { 4496 state |= checkConnectionWork(controller, state); 4497 controller->needsWork = false; 4498 } 4499 } 4500 FCUNLOCK(controller); 4501 } 4502 controller = controller->nextController; 4503 } 4504 while (controller != gIOFBAllControllers); 4505 4506 DEBG1("S2", " state 0x%x\n", allState); 4507 4508 if (kIOFBWorking & allState) 4509 return; 4510 4511 if (!(kIOFBWsWait & allState)) 4512 { 4513 bool wsState = ((gIOFBSystemPower || gIOFBSwitching) && !(kIOFBDimmed & allState)); 4514 if (wsState != gIOFBWSState) 4515 { 4516 if (wsState && (kIOFBServerUp & allState)) 4517 { 4518 DEBG1("S", " notifyServer wait ack\n"); 4519 } 4520 else 4521 { 4522 DEBG1("S", " notifyServer(%d)\n", wsState); 4523 gIOFBWSState = wsState; 4524 if (wsState) 4525 gIOFBPostWakeNeeded = true; 4526 for (index = 0; 4527 (fb = (IOFramebuffer *) gAllFramebuffers->getObject(index)); 4528 index++) 4529 { 4530 FBLOCK(fb); 4531 fb->notifyServer(wsState); 4532 FBUNLOCK(fb); 4533 } 4534 } 4535 } 4536 } 4537 4538 if (!(kIOFBServerUp & allState) && gIOFBSystemPowerAckTo 4539 && !(kIOFBDisplaysChanging & allState) 4540 && !gIOFBSwitching) 4541 { 4542 uintptr_t notiArg; 4543 // tell accelerators to disable, then protect HW 4544 for(notiArg = 0; notiArg < 2; notiArg++) 4545 { 4546 for (index = 0; 4547 (fb = (IOFramebuffer *) gAllFramebuffers->getObject(index)); 4548 index++) 4549 { 4550 FBLOCK(fb); 4551 fb->deliverFramebufferNotification(kIOFBNotifyWillSleep, (void *) notiArg); 4552 if (notiArg) 4553 { 4554 fb->saveFramebuffer(); 4555 fb->pagingState = false; 4556 } 4557 FBUNLOCK(fb); 4558 } 4559 } 4560 4561 DEBG("S", " allowPowerChange(%p)\n", gIOFBSystemPowerAckRef); 4562 4563 IOService * ackTo = gIOFBSystemPowerAckTo; 4564 void * ackRef = gIOFBSystemPowerAckRef; 4565 gIOFBSystemPowerAckTo = 0; 4566 4567 ackTo->allowPowerChange( (uintptr_t) ackRef ); 4568 4569 DEBG("S", " did allowPowerChange()\n"); 4570 } 4571 4572 if (!(kIOFBServerDown & allState) && gIOFBPostWakeNeeded) 4573 { 4574 gIOFBPostWakeNeeded = false; 4575 for (index = 0; 4576 (fb = (IOFramebuffer *) gAllFramebuffers->getObject(index)); 4577 index++) 4578 { 4579 FBLOCK(fb); 4580 fb->postWake(); 4581 FBUNLOCK(fb); 4582 } 4583 } 4584 4585 events = gIOFBGlobalEvents; 4586 4587 if (kIOFBEventCaptureSetting & events) 4588 { 4589 bool wasCaptured, wasDimDisable; 4590 bool newCaptured, newDimDisable; 4591 4592 OSBitAndAtomic(~kIOFBEventCaptureSetting, &gIOFBGlobalEvents); 4593 4594 wasCaptured = (0 != (kIOFBCaptured & allState)); 4595 wasDimDisable = (0 != (kIOFBDimDisable & allState)); 4596 newCaptured = (0 != (kIOCaptureDisableDisplayChange & gIOFBCaptureState)); 4597 newDimDisable = (0 != (kIOCaptureDisableDisplayDimming & gIOFBCaptureState)); 4598 4599 for (index = 0; 4600 (fb = (IOFramebuffer *) gAllFramebuffers->getObject(index)); 4601 index++) 4602 { 4603 FBLOCK(fb); 4604 fb->setCaptured(newCaptured); 4605 fb->setDimDisable(newDimDisable); 4606 FBUNLOCK(fb); 4607 } 4608 if (wasCaptured != newCaptured) gIOFBGrayValue = newCaptured ? 0 : kIOFBGrayValue; 4609 4610 if (newDimDisable != wasDimDisable) 4611 { 4612 getPMRootDomain()->setAggressiveness(kIOFBCaptureAggressiveness, newDimDisable); 4613 } 4614 4615 if (gIOFBProbeCaptured && wasCaptured && !newCaptured) 4616 { 4617 gIOFBProbeCaptured = false; 4618 OSBitOrAtomic(kIOFBEventProbeAll, &gIOFBGlobalEvents); 4619 startThread(false); 4620 DEBG1("S", " capt probe all\n"); 4621 } 4622 } 4623 4624 if (kIOFBEventDisplayDimsSetting & events) 4625 { 4626 OSNumber * num; 4627 uintptr_t value = true; 4628 OSObject * obj; 4629 4630 OSBitAndAtomic(~kIOFBEventDisplayDimsSetting, &gIOFBGlobalEvents); 4631 obj = getPMRootDomain()->copyPMSetting(const_cast<OSSymbol *> 4632 (gIOFBPMSettingDisplaySleepUsesDimKey)); 4633 if ((num = OSDynamicCast(OSNumber, obj))) 4634 value = num->unsigned32BitValue(); 4635 if (obj) 4636 obj->release(); 4637 4638 if (num) for (uint32_t index = 0; 4639 (fb = (IOFramebuffer *) gAllFramebuffers->getObject(index)); 4640 index++) 4641 { 4642 FBLOCK(fb); 4643 fb->deliverFramebufferNotification(kIOFBNotifyDisplayDimsChange, (void *) value); 4644 FBUNLOCK(fb); 4645 } 4646 } 4647 4648 if ((kIOFBEventReadClamshell & events) 4649 && !gIOFBSwitching 4650 && !(kIOFBWsWait & allState)) 4651 { 4652 OSObject * clamshellProperty; 4653 4654 OSBitAndAtomic(~kIOFBEventReadClamshell, &gIOFBGlobalEvents); 4655 clamshellProperty = gIOResourcesAppleClamshellState; 4656 if (clamshellProperty) 4657 { 4658 gIOFBLastClamshellState = 4659 gIOFBCurrentClamshellState = (kOSBooleanTrue == clamshellProperty); 4660 DEBG1("S", " clamshell read %d\n", (int) gIOFBCurrentClamshellState); 4661 4662 for (uint32_t index = 0; 4663 (fb = (IOFramebuffer *) gAllFramebuffers->getObject(index)); 4664 index++) 4665 { 4666 FBLOCK(fb); 4667 fb->deliverFramebufferNotification(kIOFBNotifyClamshellChange, clamshellProperty); 4668 FBUNLOCK(fb); 4669 } 4670 4671 bool desktopMode; 4672 if (gIOFBLidOpenMode) 4673 desktopMode = gIOFBDesktopModeAllowed && (gIOFBDisplayCount > 0); 4674 else 4675 desktopMode = gIOFBDesktopModeAllowed && (gIOFBBacklightDisplayCount <= 0); 4676 4677 if (desktopMode) 4678 { 4679 // lid change, desktop mode 4680 DEBG1("S", " desktop will reprobe\n"); 4681 resetClamshell(kIOFBClamshellProbeDelayMS); 4682 } 4683 } 4684 } 4685 4686 if ((kIOFBEventResetClamshell & events) && gIOFBSystemPower 4687 && !(kIOFBWsWait & allState) 4688 && !(kIOFBDisplaysChanging & allState)) 4689 { 4690 OSBitAndAtomic(~kIOFBEventResetClamshell, &gIOFBGlobalEvents); 4691 4692 DEBG1("S", " kIOFBEventResetClamshell %d, %d\n", gIOFBCurrentClamshellState, gIOFBLastReadClamshellState); 4693 4694 if ((gIOFBLidOpenMode && (gIOFBCurrentClamshellState != gIOFBLastReadClamshellState)) 4695 // clamshell changed since last probe 4696 || (!gIOFBLidOpenMode && (gIOFBBacklightDisplayCount && gIOFBLastReadClamshellState && !gIOFBCurrentClamshellState))) 4697 // clamshell was closed during last probe, now open => reprobe 4698 { 4699 DEBG1("S", " clamshell caused reprobe\n"); 4700 events |= kIOFBEventProbeAll; 4701 OSBitOrAtomic(kIOFBEventProbeAll, &gIOFBGlobalEvents); 4702 } 4703 else 4704 { 4705 AbsoluteTime deadline; 4706 clock_interval_to_deadline(kIOFBClamshellEnableDelayMS, kMillisecondScale, &deadline ); 4707 thread_call_enter1_delayed(gIOFBClamshellCallout, 4708 (thread_call_param_t) kIOFBEventEnableClamshell, deadline ); 4709 } 4710 } 4711 4712 if ((kIOFBEventEnableClamshell & events) && gIOFBSystemPower 4713 && !(kIOFBWsWait & allState) 4714 && !(kIOFBDisplaysChanging & allState)) 4715 { 4716 UInt32 change; 4717 bool desktopMode; 4718 4719 OSBitAndAtomic(~kIOFBEventEnableClamshell, &gIOFBGlobalEvents); 4720 4721 if (gIOFBLidOpenMode) 4722 desktopMode = gIOFBDesktopModeAllowed && (gIOFBDisplayCount > 0); 4723 else 4724 desktopMode = gIOFBDesktopModeAllowed && (gIOFBBacklightDisplayCount <= 0); 4725 4726 change = kIOPMEnableClamshell | kIOPMSetDesktopMode | (desktopMode ? kIOPMSetValue : 0); 4727 if (change != gIOFBClamshellState) 4728 { 4729 gIOFBClamshellState = change; 4730 DEBG1("S", " clamshell ena desktopMode %d\n", desktopMode); 4731 getPMRootDomain()->receivePowerNotification(change); 4732 } 4733 } 4734 4735 if (kIOFBEventDisplaysPowerState & events) 4736 { 4737 unsigned long state = IODisplayWrangler::getDisplaysPowerState(); 4738 4739 if (gIOFBSwitching && (state < kIODisplayNumPowerStates)) 4740 { 4741 state = kIODisplayNumPowerStates; 4742 } 4743 else 4744 { 4745 OSBitAndAtomic(~kIOFBEventDisplaysPowerState, &gIOFBGlobalEvents); 4746 } 4747 DEBG1("S", " displays pstate %ld\n", state); 4748 4749 for (uint32_t index = 0; 4750 (fb = (IOFramebuffer *) gAllFramebuffers->getObject(index)); 4751 index++) 4752 { 4753 FBLOCK(fb); 4754 if (fb->__private->display) 4755 fb->__private->display->setDisplayPowerState(state); 4756 FBUNLOCK(fb); 4757 } 4758 } 4759 4760 if ((kIOFBEventProbeAll & events) 4761 && gIOFBSystemPower 4762 && (kIOMessageSystemHasPoweredOn == gIOFBLastMuxMessage) 4763 && !(kIOFBWsWait & allState) 4764 && !(kIOFBCaptured & allState) 4765 && !(kIOFBDisplaysChanging & allState)) 4766 { 4767 OSBitAndAtomic(~kIOFBEventProbeAll, &gIOFBGlobalEvents); 4768 4769 DEBG1("S", " probeAll clam %d -> %d\n", 4770 (int) gIOFBLastClamshellState, (int) gIOFBCurrentClamshellState); 4771 4772 gIOFBLastClamshellState = gIOFBCurrentClamshellState; 4773 gIOFBLastReadClamshellState = gIOFBCurrentClamshellState; 4774 4775 probeAll(kIOFBUserRequestProbe); 4776 for (uint32_t index = 0; 4777 (fb = (IOFramebuffer *) gAllFramebuffers->getObject(index)); 4778 index++) 4779 { 4780 FBLOCK(fb); 4781 fb->deliverFramebufferNotification(kIOFBNotifyProbed, NULL); 4782 FBUNLOCK(fb); 4783 } 4784 resetClamshell(kIOFBClamshellProbeDelayMS); 4785 } 4786} 4787 4788void IOFramebuffer::serverAckTimeout(OSObject * null, IOTimerEventSource * sender) 4789{ 4790 uint32_t index; 4791 IOFramebuffer * fb; 4792 4793 for (index = 0; 4794 (fb = (IOFramebuffer *) gAllFramebuffers->getObject(index)); 4795 index++) 4796 { 4797 FBLOCK(fb); 4798 if (fb->serverState != fb->serverNotified) 4799 { 4800 DEBG1(fb->thisName, " (%d->%d) server ack timeout\n", 4801 fb->serverState, fb->serverNotified); 4802 fb->serverAcknowledgeNotification(); 4803 } 4804 FBUNLOCK(fb); 4805 } 4806} 4807 4808IOFBController * IOFramebuffer::aliasController(IOFBController * controller) 4809{ 4810 IOFBController * result = controller; 4811 do 4812 { 4813 result = result->nextController; 4814 if (result->aliasID == controller->aliasID) 4815 break; 4816 } 4817 while (result != controller); 4818 4819 if (result == controller) 4820 result = controller->nextController; 4821 4822 return (result); 4823} 4824 4825uint32_t IOFramebuffer::controllerState(IOFBController * controller) 4826{ 4827 IOFramebuffer * fb; 4828 uint32_t idx; 4829 uint32_t state; 4830 4831 state = controller->state; 4832 4833 if (controller->didWork || controller->connectChange) 4834 { 4835 FCLOCK(controller); 4836 4837 if (controller->connectChange) 4838 controller->needsWork = true; 4839 4840 if (controller->didWork & ~kWorkStateChange) 4841 { 4842 controller->asyncWork = false; 4843 4844 for (idx = 0; (fb = controller->fbs[idx]); idx++) 4845 { 4846 if (kWorkPower & controller->didWork) 4847 { 4848 if (fb->pendingPowerState) 4849 { 4850 fb->deliverFramebufferNotification( kIOFBNotifyDidWake, (void *) true); 4851 fb->deliverFramebufferNotification( kIOFBNotifyDidPowerOn, (void *) false); 4852// fb->deliverFramebufferNotification( kIOFBNotifyDidWake, (void *) false); 4853 } 4854 else 4855 fb->deliverFramebufferNotification( kIOFBNotifyDidPowerOff, (void *) false); 4856 } 4857 if (kWorkSuspend & controller->didWork) 4858 { 4859 fb->suspend(false); 4860 } 4861 } 4862 4863 if (kWorkSuspend & controller->didWork) 4864 { 4865 if (controller->onlineMask) // bgOn 4866 { 4867 IOFBController * oldController; 4868 4869 oldController = aliasController(controller); 4870 FCLOCK(oldController); 4871 if (oldController->lastFinishedChange == oldController->connectChange) 4872 { 4873 DEBG1(controller->name, " mute exit\n"); 4874 } 4875 FCUNLOCK(oldController); 4876 messageConnectionChange(controller); 4877 } 4878 } 4879 } 4880 4881 state = 0; 4882 if (controller->wsWait) 4883 state |= kIOFBWsWait; 4884 4885 for (idx = 0; (fb = controller->fbs[idx]); idx++) 4886 { 4887 if (fb->pagingState) 4888 state |= kIOFBPaging; 4889 if (fb->messaged) 4890 state |= kIOFBDisplaysChanging; 4891 if (!fb->getIsUsable()) 4892 state |= kIOFBDimmed; 4893 if (!fb->serverNotified) 4894 state |= kIOFBServerSlept; 4895 if (fb->serverState) 4896 state |= kIOFBServerUp; 4897 else 4898 state |= kIOFBServerDown; 4899 if (fb->captured) 4900 state |= kIOFBCaptured; 4901 if (fb->getDimDisable()) 4902 state |= kIOFBDimDisable; 4903 } 4904 4905 controller->state = state; 4906 controller->didWork = false; 4907 state |= kIOFBDidWork; 4908 4909 FCUNLOCK(controller); 4910 } 4911 4912 DEBG1(controller->name, " state %x\n", state); 4913 4914 return (state); 4915} 4916 4917void IOFramebuffer::startThread(bool highPri) 4918{ 4919 gIOFBWorkES->interruptOccurred(0, 0, 0); 4920} 4921 4922// controller WL 4923 4924void IOFramebuffer::startControllerThread(IOFBController * controller) 4925{ 4926 controller->needsWork = true; 4927 4928 controller->didWork |= kWorkStateChange; 4929 4930 startThread(false); 4931} 4932 4933void IOFramebuffer::controllerDidWork(IOFBController * controller, IOOptionBits work) 4934{ 4935 if (controller->asyncWork && !work) OSReportWithBacktrace("asyncWork+did"); 4936 4937 controller->didWork |= work; 4938 4939 startThread(false); 4940} 4941 4942void IOFramebuffer::controllerAsyncWork(OSObject * owner, 4943 IOInterruptEventSource * evtSrc, int intCount) 4944{ 4945 IOFramebuffer * fb = (IOFramebuffer *) owner; 4946 IOFBController * controller = fb->__private->controller; 4947 uint32_t idx; 4948 uint32_t asyncWork; 4949 4950 asyncWork = controller->asyncWork; 4951 controller->asyncWork = true; 4952 4953 DEBG1(controller->name, " (%d)\n", asyncWork); 4954 4955 if (kWorkPower & asyncWork) 4956 { 4957 uint32_t newState = controller->fbs[0]->pendingPowerState; 4958 DEBG1(controller->name, " async kIODriverPowerAttribute(%d, %d)\n", 4959 newState, controller->fbs[0]->pendingPowerState); 4960 for (idx = 0; (fb = controller->fbs[idx]); idx++) 4961 fb->setAttribute(kIODriverPowerAttribute, newState); 4962 controllerDidWork(controller, kWorkPower); 4963 } 4964 else if (kWorkSuspend & asyncWork) 4965 { 4966 for (idx = 0; (fb = controller->fbs[idx]); idx++) 4967 fb->setAttributeForConnection(0, kConnectionPanelTimingDisable, false); 4968 4969 processConnectChange(controller, bg); 4970 if (controller->onlineMask) 4971 matchController(controller); 4972 else 4973 { 4974 DEBG1(controller->name, " bg offline\n"); 4975 controller->lastFinishedChange = controller->connectChange; 4976 } 4977 4978 for (idx = 0; (fb = controller->fbs[idx]); idx++) 4979 fb->setAttributeForConnection(0, kConnectionPanelTimingDisable, true); 4980 4981 controllerDidWork(controller, kWorkSuspend); 4982 } 4983} 4984 4985IOOptionBits IOFramebuffer::checkPowerWork(IOFBController * controller, IOOptionBits state) 4986{ 4987 IOFramebuffer * fb; 4988 uint32_t idx; 4989 4990 if (controller->pendingMuxPowerChange) 4991 { 4992 uint32_t newState = controller->fbs[0]->pendingPowerState; 4993 DEBG1(controller->name, " async checkPowerWork(%d)\n", newState); 4994 if (!newState) 4995 { 4996 for (idx = 0; (fb = controller->fbs[idx]); idx++) 4997 { 4998// fb->deliverFramebufferNotification(kIOFBNotifyWillSleep, (void *) false); 4999 fb->deliverFramebufferNotification(kIOFBNotifyWillPowerOff, (void *) false); 5000 fb->deliverFramebufferNotification(kIOFBNotifyWillSleep, (void *) true); 5001 } 5002 } 5003 controller->pendingMuxPowerChange = false; 5004 startAsync(controller, kWorkPower); 5005 } 5006 else for (idx = 0; (fb = controller->fbs[idx]); idx++) 5007 { 5008 state |= fb->checkPowerWork(state); 5009 } 5010 5011 return (state); 5012} 5013 5014IOOptionBits IOFramebuffer::checkPowerWork(IOOptionBits state) 5015{ 5016 IOOptionBits ourState = kIOFBPaging; 5017 IOService * device = 0; 5018 OSData * stateData = 0; 5019 5020 if (pendingPowerChange) 5021 { 5022 uintptr_t newState = pendingPowerState; 5023 5024 DEBG1(thisName, " pendingPowerState(%ld)\n", newState); 5025 5026 __private->controller->powerThread = current_thread(); 5027 __private->hibernateGfxStatus = 0; 5028 if (!pagingState) 5029 { 5030 device = __private->controller->device; 5031 if (device 5032 && (stateData = OSDynamicCast(OSData, getPMRootDomain()->getProperty(kIOHibernateStateKey)))) 5033 { 5034 if (kIOHibernateStateWakingFromHibernate == ((uint32_t *) stateData->getBytesNoCopy())[0]) 5035 { 5036 OSNumber * 5037 num = OSDynamicCast(OSNumber, getPMRootDomain()->getProperty(kIOHibernateOptionsKey)); 5038 uint32_t options = 0; 5039 if (num) options = num->unsigned32BitValue(); 5040 DEBG1(thisName, " kIOHibernateOptionsKey %p (0x%x)\n", num, options); 5041 if (kIOHibernateOptionDarkWake & options) 5042 { 5043 stateData = 0; 5044 } 5045 else 5046 { 5047 device->setProperty(kIOHibernateStateKey, stateData); 5048 5049 5050 OSData * 5051 data = OSDynamicCast(OSData, getPMRootDomain()->getProperty(kIOHibernateGfxStatusKey)); 5052 if (data) 5053 { 5054 __private->hibernateGfxStatus = ((uint32_t *)data->getBytesNoCopy())[0]; 5055 device->setProperty(kIOHibernateEFIGfxStatusKey, data); 5056 } 5057 if (newState == 1) newState = 2; 5058 } 5059 } 5060 } 5061 } 5062 5063 // online-online test 5064 // if (newState && __private->controllerIndex) connectChangeInterrupt(this, 0); 5065 5066 if ((newState == 1) 5067 && (kIODisplayOptionDimDisable & __private->displayOptions) 5068// 9564372 && __private->audioStreaming 5069 && !gIOFBSystemDark) 5070 { 5071 newState = 2; 5072 } 5073 5074 setAttribute(kIOPowerStateAttribute, newState); 5075 DEBG1(thisName, " did kIOPowerStateAttribute(%ld)\n", newState); 5076 if (device && stateData) 5077 { 5078 device->setProperty(kIOHibernateStateKey, gIOFBZero32Data); 5079 device->removeProperty(kIOHibernateEFIGfxStatusKey); 5080 } 5081 5082 __private->controller->powerThread = NULL; 5083 5084 OSObject * obj; 5085 if ((this == gIOFBConsoleFramebuffer) 5086 && (obj = copyProperty(kIOHibernatePreviewActiveKey, gIOServicePlane))) 5087 { 5088 getPMRootDomain()->setProperty(kIOHibernatePreviewActiveKey, obj); 5089 obj->release(); 5090 } 5091 5092 DEBG(thisName, " acknowledgeSetPowerState\n"); 5093 pendingPowerChange = false; 5094 acknowledgeSetPowerState(); 5095 } 5096 5097 if (__private->allowSpeedChanges && __private->pendingSpeedChange) 5098 { 5099 __private->pendingSpeedChange = false; 5100 __private->controller->powerThread = current_thread(); 5101 setAttribute(kIOFBSpeedAttribute, __private->reducedSpeed); 5102 __private->controller->powerThread = NULL; 5103 } 5104 5105 return (ourState); 5106} 5107 5108IOOptionBits IOFramebuffer::checkConnectionWork( IOFBController * controller, IOOptionBits state ) 5109{ 5110 IOFramebuffer * fb; 5111 uint32_t idx; 5112 5113 DEBG1(controller->name, " count(%d, msg %d, fin %d, proc %d, wake %d), capt(%d) wsWait(%d)\n", 5114 controller->connectChange, 5115 controller->lastMessagedChange, controller->lastFinishedChange, 5116 controller->fbs[0]->__private->lastProcessedChange, 5117 controller->postWakeChange, 5118 (0 != (kIOFBCaptured & state)), controller->wsWait); 5119 5120 if (kIOFBCaptured & state) 5121 { 5122 if (controller->connectChange != controller->lastForceRetrain) 5123 { 5124 controller->lastForceRetrain = controller->connectChange; 5125 for (idx = 0; (fb = controller->fbs[idx]); idx++) 5126 { 5127 if (!fb->__private->dpSupported) 5128 { 5129 IOReturn err; 5130 uintptr_t value[16]; 5131 err = fb->getAttributeForConnection(0, kConnectionHandleDisplayPortEvent, &value[0]); 5132 fb->__private->dpSupported = (kIOReturnSuccess == err) ? true : -1; 5133 DEBG1(fb->thisName, " dpSupported(%d)\n", fb->__private->dpSupported); 5134 } 5135 5136 if (fb->__private->dpSupported > 0) 5137 { 5138 IOReturn err; 5139 uintptr_t sel = kIODPEventForceRetrain; 5140 err = fb->setAttributeForConnection(0, kConnectionHandleDisplayPortEvent, (uintptr_t) &sel); 5141 DEBG1(fb->thisName, " kIODPEventForceRetrain(0x%x)\n", err); 5142 } 5143 } 5144 } 5145 return (state); 5146 } 5147 5148 if (gIOGraphicsControl 5149 && (controller->fbs[0]->__private->lastProcessedChange != controller->connectChange) 5150 && !controller->asyncWork) 5151 { 5152 bool needAsync = false; 5153 if ((!controller->onlineMask) 5154 && (controller->lastFinishedChange == controller->connectChange)) 5155 { 5156 // bgOff 5157 needAsync = true; 5158 } 5159 else if ((!controller->onlineMask) 5160 && (!controller->mute) 5161 && (controller->connectChange != controller->postWakeChange)) 5162 { 5163 // bgOn 5164 IOFBController * oldController; 5165 IOFramebuffer * oldfb; 5166 oldController = aliasController(controller); 5167 FCLOCK(oldController); 5168 5169 DEBG1(controller->name, " copy from %s\n", oldController->name); 5170 5171 for (idx = 0; (fb = controller->fbs[idx]) && (oldfb = oldController->fbs[idx]); idx++) 5172 { 5173 DEBG1(oldfb->thisName, " copy %d x %d\n", 5174 (int) oldfb->__private->pixelInfo.activeWidth, 5175 (int) oldfb->__private->pixelInfo.activeHeight); 5176 5177 fb->__private->pixelInfo = oldfb->__private->pixelInfo; 5178 fb->__private->timingInfo = oldfb->__private->timingInfo; 5179 fb->__private->uiScale = oldfb->__private->uiScale; 5180 fb->__private->matchedMode = oldfb->__private->setupMode; 5181 5182 if (oldfb->__private->displayAttributes) oldfb->__private->displayAttributes->retain(); 5183 if (fb->__private->displayAttributes) fb->__private->displayAttributes->release(); 5184 fb->__private->displayAttributes = oldfb->__private->displayAttributes; 5185 5186 if (oldfb->__private->rawGammaDataLen != fb->__private->rawGammaDataLen) 5187 { 5188 if (fb->__private->rawGammaDataLen) 5189 IODelete(fb->__private->rawGammaData, UInt8, fb->__private->rawGammaDataLen); 5190 fb->__private->rawGammaData = IONew(UInt8, oldfb->__private->rawGammaDataLen); 5191 } 5192 if (!fb->__private->rawGammaData) 5193 { 5194 fb->__private->rawGammaDataLen = 0; 5195 break; 5196 } 5197 fb->__private->rawGammaDataLen = oldfb->__private->rawGammaDataLen; 5198 fb->__private->rawGammaChannelCount = oldfb->__private->rawGammaChannelCount; 5199 fb->__private->rawGammaDataCount = oldfb->__private->rawGammaDataCount; 5200 fb->__private->rawGammaDataWidth = oldfb->__private->rawGammaDataWidth; 5201 5202 bcopy(oldfb->__private->rawGammaData, fb->__private->rawGammaData, 5203 fb->__private->rawGammaDataLen); 5204 5205 } 5206 FCUNLOCK(oldController); 5207 needAsync = true; 5208 } 5209 5210 if (needAsync) 5211 { 5212 for (idx = 0; (fb = controller->fbs[idx]); idx++) 5213 fb->suspend(true); 5214 startAsync(controller, kWorkSuspend); 5215 state |= kIOFBDisplaysChanging; 5216 } 5217 } 5218 5219 if (!controller->asyncWork) 5220 { 5221 messageConnectionChange(controller); 5222 } 5223 5224 return (state); 5225} 5226 5227void IOFramebuffer::messageConnectionChange( IOFBController * controller ) 5228{ 5229 IOReturn err; 5230 bool discard = false; 5231 IOFramebuffer * fb; 5232 uint32_t idx; 5233 5234 if ((controller->lastMessagedChange != controller->connectChange) 5235 && !controller->fbs[0]->messaged 5236 && !controller->wsWait) 5237 { 5238 controller->lastMessagedChange = controller->connectChange; 5239 if (gIOGraphicsControl) 5240 { 5241 err = gIOGraphicsControl->message(kIOFBMessageConnectChange, controller->fbs[0], NULL); 5242 if (kIOReturnOffline == err) 5243 { 5244 DEBG1(controller->name, " AGC discard\n"); 5245 discard = true; 5246 } 5247 } 5248 if (discard) 5249 { 5250 controller->lastFinishedChange = controller->lastMessagedChange; 5251 for (idx = 0; (fb = controller->fbs[idx]); idx++) 5252 fb->__private->lastProcessedChange = controller->lastMessagedChange; 5253 } 5254 else 5255 { 5256 DEBG1(controller->name, " messaged\n"); 5257 controller->fbs[0]->messaged = true; 5258 controller->fbs[0]->messageClients(kIOMessageServiceIsSuspended, (void *) true); 5259 } 5260 } 5261} 5262 5263 5264IOReturn IOFramebuffer::extEndConnectionChange(void) 5265{ 5266 IOFBController * controller = __private->controller; 5267 5268 DEBG1(controller->name, " WS done msg %d, onl %x, count(%d, msg %d, fin %d, proc %d, wake %d)\n", 5269 controller->fbs[0]->messaged, __private->controller->onlineMask, 5270 controller->connectChange, 5271 controller->lastMessagedChange, controller->lastFinishedChange, 5272 controller->fbs[0]->__private->lastProcessedChange, 5273 controller->postWakeChange); 5274 5275 if (!controller->fbs[0]->messaged) 5276 return (kIOReturnSuccess); 5277 5278 controller->fbs[0]->messaged = false; 5279 __private->controller->lastFinishedChange = __private->controller->lastMessagedChange; 5280 5281 if (gIOGraphicsControl) 5282 { 5283 IOReturn err; 5284 err = gIOGraphicsControl->message(kIOFBMessageEndConnectChange, controller->fbs[0], NULL); 5285 } 5286 5287 resetClamshell(kIOFBClamshellProbeDelayMS); 5288 startControllerThread(controller); 5289 5290 return (kIOReturnSuccess); 5291} 5292 5293IOReturn IOFramebuffer::processConnectChange(IOFBController * controller, IOOptionBits mode) 5294{ 5295 IOFramebuffer * fb; 5296 uint32_t idx; 5297 5298 for (idx = 0; (fb = controller->fbs[idx]); idx++) 5299 { 5300 fb->processConnectChange(mode); 5301 } 5302 return (kIOReturnSuccess); 5303} 5304 5305IOReturn IOFramebuffer::extProcessConnectionChange(void) 5306{ 5307 IOFBController * controller = __private->controller; 5308 IOReturn err = kIOReturnSuccess; 5309 IOOptionBits mode = 0; 5310 5311 TIMELOCK(gIOFBSystemWorkLoop, thisName, __FUNCTION__); 5312 5313 if ((err = extEntry(true))) 5314 { 5315 SYSUNLOCK(); 5316 return (err); 5317 } 5318 5319 if (controller->fbs[0]->messaged) 5320 { 5321 if (controller->mute) 5322 mode = fgOff; 5323 else if (__private->lastProcessedChange != __private->controller->connectChange) 5324 mode = fg; 5325 else if (kIODisplayModeIDInvalid != __private->aliasMode) 5326 { 5327 IOFBController * oldController; 5328 IOFramebuffer * oldfb; 5329 bool rematch = false; 5330 5331 oldController = aliasController(controller); 5332 FCLOCK(oldController); 5333 oldfb = oldController->fbs[__private->controllerIndex]; 5334 if (oldfb) 5335 { 5336 DEBG1(thisName, " check copy from %s: 0x%x==0x%x?\n", oldfb->thisName, 5337 (int) __private->matchedMode, (int) oldfb->__private->setupMode); 5338 rematch = (__private->matchedMode != oldfb->__private->setupMode); 5339 if (rematch) 5340 { 5341 DEBG1(thisName, " rematch using %d x %d\n", 5342 (int) oldfb->__private->pixelInfo.activeWidth, 5343 (int) oldfb->__private->pixelInfo.activeHeight); 5344 __private->pixelInfo = oldfb->__private->pixelInfo; 5345 __private->timingInfo = oldfb->__private->timingInfo; 5346 __private->uiScale = oldfb->__private->uiScale; 5347 __private->matchedMode = oldfb->__private->setupMode; 5348 } 5349 } 5350 FCUNLOCK(oldController); 5351 if (rematch) 5352 { 5353 suspend(true); 5354 matchFramebuffer(); 5355 suspend(false); 5356 } 5357 } 5358 } 5359 extExit(err); 5360 5361 if (mode) 5362 { 5363 temporaryPowerClampOn(); 5364 IODisplayWrangler::destroyDisplayConnects(this); 5365 5366 err = extEntry(true); 5367 if (kIOReturnSuccess == err) 5368 { 5369 err = processConnectChange(mode); 5370 extExit(err); 5371 } 5372 } 5373 5374 SYSUNLOCK(); 5375 5376 return (err); 5377} 5378 5379 5380IOReturn IOFramebuffer::processConnectChange(IOOptionBits mode) 5381{ 5382 IOReturn err; 5383 uintptr_t unused; 5384 bool nowOnline; 5385 5386 DEBG1(thisName, " (%d==%s) curr %d\n", 5387 (uint32_t) mode, processConnectChangeModeNames[mode], __private->lastProcessedChange); 5388 5389 if (fgOff == mode) 5390 { 5391 displaysOnline(false); 5392 __private->online = false; 5393 return (kIOReturnSuccess); 5394 } 5395 if (__private->lastProcessedChange == __private->controller->connectChange) 5396 return (kIOReturnSuccess); 5397 5398 if (fg == mode) suspend(true); 5399 5400 { 5401 // connect change vars here 5402 __private->enableScalerUnderscan = false; 5403 __private->audioStreaming = false; 5404 __private->colorModesSupported = 0; 5405 } 5406 5407 TIMESTART(); 5408 err = getAttributeForConnection(0, kConnectionChanged, &unused); 5409 TIMEEND(thisName, "kConnectionChanged time: %qd ms\n"); 5410 5411 __private->lastProcessedChange = __private->controller->connectChange; 5412 extSetMirrorOne(0, 0); 5413 if (fg == mode) suspend(true); 5414 5415 nowOnline = updateOnline(); 5416 if (false && nowOnline) 5417 { 5418 DEBG1(thisName, " bgOff forced\n"); 5419 nowOnline = false; 5420 } 5421 5422 displaysOnline(false); 5423 __private->online = nowOnline; 5424 __private->transform = __private->selectedTransform; 5425 setProperty(kIOFBTransformKey, __private->transform, 64); 5426 if (nowOnline) 5427 displaysOnline(true); 5428 5429 if (nowOnline) 5430 { 5431 if (__private->cursorAttributes && !__private->cursorAttributes->getCount()) 5432 { 5433 __private->cursorAttributes->release(); 5434 __private->cursorAttributes = 0; 5435 } 5436 5437 if (!__private->cursorAttributes) 5438 { 5439 if ((__private->cursorAttributes = OSArray::withCapacity(2))) 5440 { 5441 __private->testingCursor = true; 5442 setCursorImage( (void *) 0 ); 5443 __private->testingCursor = false; 5444 5445 setProperty( kIOFBCursorInfoKey, __private->cursorAttributes ); 5446 } 5447 } 5448 } 5449 else 5450 { 5451 if (kIODisplayModeIDInvalid != __private->offlineMode) 5452 { 5453 IOPixelInformation pixelInfo; 5454 5455 pixelInfo.bitsPerPixel = 32; 5456 pixelInfo.pixelType = kIORGBDirectPixels; 5457 pixelInfo.componentCount = 3; 5458 pixelInfo.bitsPerComponent = 8; 5459 __private->currentDepth = closestDepth(__private->offlineMode, &pixelInfo); 5460 5461 err = setDisplayMode(__private->offlineMode, __private->currentDepth); 5462 DEBG1(thisName, " offline setDisplayMode(0x%x, %d) err %x msg %d susp %d\n", 5463 (int32_t) __private->offlineMode, (int32_t) __private->currentDepth, 5464 err, messaged, suspended); 5465 } 5466 if (fg == mode) suspend(false); 5467 } 5468 5469 err = kIOReturnSuccess; 5470 return (err); 5471} 5472 5473bool IOFramebuffer::updateOnline(void) 5474{ 5475 IOReturn err; 5476 uintptr_t connectEnabled; 5477 bool nowOnline; 5478 IOTimingInformation info; 5479 IODisplayModeID * modeIDs; 5480 IOItemCount modeCount, modeNum; 5481 5482 TIMESTART(); 5483 err = getAttributeForConnection(0, kConnectionCheckEnable, &connectEnabled); 5484 TIMEEND(thisName, "kConnectionCheckEnable == %ld, time: %qd ms\n", connectEnabled); 5485 5486 nowOnline = (!dead && ((kIOReturnSuccess != err) || connectEnabled)); 5487 5488 __private->gammaScale[0] = __private->gammaScale[1] 5489 = __private->gammaScale[2] = __private->gammaScale[3] = (1 << 16); 5490 __private->aliasMode = kIODisplayModeIDInvalid; 5491 __private->offlineMode = kIODisplayModeIDInvalid; 5492 5493 if (!nowOnline) do 5494 { 5495 TIMESTART(); 5496 modeCount = getDisplayModeCount(); 5497 modeIDs = IONew(IODisplayModeID, modeCount); 5498 if (!modeIDs) 5499 break; 5500 err = getDisplayModes(modeIDs); 5501 if (kIOReturnSuccess == err) 5502 { 5503 for (modeNum = 0; modeNum < modeCount; modeNum++) 5504 { 5505 info.flags = 0; 5506 err = getTimingInfoForDisplayMode(modeIDs[modeNum], &info); 5507 if (kIOReturnSuccess != err) 5508 continue; 5509 if (kIOTimingIDApple_0x0_0hz_Offline != info.appleTimingID) 5510 continue; 5511 __private->offlineMode = modeIDs[modeNum]; 5512 break; 5513 } 5514 } 5515 IODelete(modeIDs, IODisplayModeID, modeCount); 5516 TIMEEND(thisName, "offline mode %x time: %qd ms\n", (int32_t) __private->offlineMode); 5517 } 5518 while (false); 5519 5520 return (nowOnline); 5521} 5522 5523void IOFramebuffer::displaysOnline(bool nowOnline) 5524{ 5525 if (nowOnline == __private->displaysOnline) 5526 return; 5527 5528 if (nowOnline) 5529 { 5530 TIMESTART(); 5531 IODisplayWrangler::makeDisplayConnects(this); 5532 TIMEEND(thisName, "makeDisplayConnects time: %qd ms\n"); 5533 } 5534 else 5535 { 5536 if (__private->displayPrefKey) 5537 { 5538 __private->displayPrefKey->release(); 5539 __private->displayPrefKey = NULL; 5540 } 5541 5542 TIMESTART(); 5543 if (__private->paramHandler) 5544 __private->paramHandler->setDisplay(0); 5545 TIMEEND(thisName, "setDisplay time: %qd ms\n"); 5546 5547 TIMESTART(); 5548 stopCursor(); 5549// temporaryPowerClampOn(); 5550 // FCUNLOCK(controller); 5551// IODisplayWrangler::destroyDisplayConnects(this); 5552 // FCLOCK(controller); 5553 TIMEEND(thisName, "destroyDisplayConnects time: %qd ms\n"); 5554 } 5555 __private->displaysOnline = nowOnline; 5556 5557 __private->actualVBLCount = 0; 5558 StdFBShmem_t * shmem = GetShmem(this); 5559 if (shmem) 5560 { 5561 shmem->vblDrift = 0; 5562 shmem->vblDeltaMeasured = 0; 5563 } 5564 if (nowOnline) 5565 { 5566 __private->controller->onlineMask |= (1 << __private->controllerIndex); 5567 updateVBL(this, NULL); 5568 } 5569 else 5570 { 5571 __private->controller->onlineMask &= ~(1 << __private->controllerIndex); 5572 } 5573} 5574 5575IOReturn IOFramebuffer::matchFramebuffer(void) 5576{ 5577 IOFBDisplayModeDescription modeInfo; 5578 IOReturn err; 5579 IODisplayModeID mode; 5580 IOIndex depth = 0; 5581 OSData * data; 5582 OSArray * array; 5583 5584 modeInfo.timingInfo = __private->timingInfo; 5585 mode = kIODisplayModeIDInvalid; 5586 if (kIODetailedTimingValid & modeInfo.timingInfo.flags) do 5587 { 5588 modeInfo.timingInfo.detailedInfo.v2.detailedTimingModeID 5589 = (kIODisplayModeIDReservedBase | kIODisplayModeIDAliasBase); 5590 modeInfo.timingInfo.detailedInfo.v2.minPixelClock 5591 = modeInfo.timingInfo.detailedInfo.v2.pixelClock; 5592 modeInfo.timingInfo.detailedInfo.v2.maxPixelClock 5593 = modeInfo.timingInfo.detailedInfo.v2.pixelClock; 5594 5595 err = validateDetailedTiming(&modeInfo, sizeof(modeInfo)); 5596 if (kIOReturnSuccess != err) 5597 { 5598 DEBG1(thisName, " validateDetailedTiming(%x)\n", err); 5599 break; 5600 } 5601 data = OSData::withBytes(&modeInfo.timingInfo.detailedInfo.v2, 5602 sizeof(modeInfo.timingInfo.detailedInfo.v2)); 5603 array = OSArray::withObjects((const OSObject**) &data, 1, 1); 5604 data->release(); 5605 err = setDetailedTimings(array); 5606 array->release(); 5607 if (kIOReturnSuccess != err) 5608 { 5609 DEBG1(thisName, " setDetailedTimings(%x)\n", err); 5610 break; 5611 } 5612 mode = kIODisplayModeIDReservedBase | kIODisplayModeIDAliasBase; 5613 } 5614 while (false); 5615 if (kIODisplayModeIDInvalid != mode) 5616 { 5617 setDisplayAttributes(__private->displayAttributes); 5618 5619 depth = closestDepth(mode, &__private->pixelInfo); 5620 TIMESTART(); 5621 err = setDisplayMode(mode, depth); 5622 TIMEEND(thisName, "matching setDisplayMode(0x%x, %d) err %x time: %qd ms\n", 5623 (int32_t) mode, (int32_t) depth, err); 5624 5625 if (__private->rawGammaData) 5626 { 5627 TIMESTART(); 5628 updateGammaTable(__private->rawGammaChannelCount, 5629 __private->rawGammaDataCount, 5630 __private->rawGammaDataWidth, 5631 __private->rawGammaData, 5632 true); 5633 TIMEEND(thisName, "match updateGammaTable time: %qd ms\n"); 5634 } 5635 } 5636 __private->aliasMode = mode; 5637 __private->currentDepth = depth; 5638 return (err); 5639} 5640 5641IOReturn IOFramebuffer::matchController(IOFBController * controller) 5642{ 5643 IOFramebuffer * fb; 5644 uint32_t idx; 5645 5646 for (idx = 0; (fb = controller->fbs[idx]); idx++) 5647 { 5648 if (!fb->__private->online) 5649 continue; 5650 fb->matchFramebuffer(); 5651 } 5652 return (kIOReturnSuccess); 5653} 5654 5655IOReturn IOFramebuffer::setPowerState( unsigned long powerStateOrdinal, 5656 IOService * whichDevice ) 5657{ 5658 IOReturn ret = kIOPMAckImplied; 5659 5660 DEBG1(thisName, " (%ld) mute %d, now %d\n", 5661 powerStateOrdinal, __private->controller->mute, (int)getPowerState()); 5662 5663 if (gIOFBSystemPowerAckTo && !powerStateOrdinal) 5664 IOLog("graphics notify timeout (%d, %d)", serverState, serverNotified); 5665 5666 FBLOCK(this); 5667 if (!__private->closed) 5668 { 5669 pendingPowerState = powerStateOrdinal; 5670 pendingPowerChange = true; 5671 5672 startControllerThread(__private->controller); 5673 ret = kPowerStateTimeout * 1000 * 1000; 5674 } 5675 FBUNLOCK(this); 5676 5677 return (ret); 5678} 5679 5680IOReturn IOFramebuffer::powerStateWillChangeTo( IOPMPowerFlags flags, 5681 unsigned long state, IOService * whatDevice ) 5682{ 5683 DEBG1(thisName, " (%08lx)\n", flags); 5684 5685 FBLOCK(this); 5686 if (isUsable && !(IOPMDeviceUsable & flags)) 5687 { 5688 isUsable = false; 5689 controllerDidWork(__private->controller, kWorkStateChange); 5690 } 5691 FBUNLOCK(this); 5692 5693 return (kIOReturnSuccess); 5694} 5695 5696IOReturn IOFramebuffer::powerStateDidChangeTo( IOPMPowerFlags flags, 5697 unsigned long, IOService* whatDevice ) 5698{ 5699 DEBG1(thisName, " (%08lx)\n", flags); 5700 5701 FBLOCK(this); 5702 if ((IOPMDeviceUsable & flags) && !isUsable) 5703 { 5704 isUsable = true; 5705 controllerDidWork(__private->controller, kWorkStateChange); 5706 } 5707 FBUNLOCK(this); 5708 5709 return (kIOReturnSuccess); 5710} 5711 5712void IOFramebuffer::updateDisplaysPowerState(void) 5713{ 5714 OSBitOrAtomic(kIOFBEventDisplaysPowerState, &gIOFBGlobalEvents); 5715 startThread(false); 5716} 5717 5718void IOFramebuffer::delayedEvent(thread_call_param_t p0, thread_call_param_t p1) 5719{ 5720 OSBitOrAtomic((uintptr_t) p1, &gIOFBGlobalEvents); 5721 startThread(false); 5722} 5723 5724void IOFramebuffer::resetClamshell(uint32_t delay) 5725{ 5726 AbsoluteTime deadline; 5727 clock_interval_to_deadline(delay, kMillisecondScale, &deadline ); 5728 thread_call_enter1_delayed(gIOFBClamshellCallout, 5729 (thread_call_param_t) kIOFBEventResetClamshell, deadline ); 5730} 5731 5732void IOFramebuffer::displayOnline(IODisplay * display, SInt32 delta, uint32_t options) 5733{ 5734 if (delta <= 0) 5735 { 5736 options = __private->displayOptions; 5737 } 5738 if (kIODisplayOptionBacklight & options) 5739 OSAddAtomic(delta, &gIOFBBacklightDisplayCount); 5740 else 5741 OSAddAtomic(delta, &gIOFBDisplayCount); 5742 5743 if (delta < 0) 5744 { 5745// if (display != __private->display) panic("(display != __private->display)"); 5746 __private->display = NULL; 5747 __private->displayOptions = 0; 5748 if (kIODisplayOptionBacklight & options) 5749 { 5750 OSBitAndAtomic(~kIOFBEventEnableClamshell, &gIOFBGlobalEvents); 5751 gIOFBClamshellState = kIOPMDisableClamshell; 5752 getPMRootDomain()->receivePowerNotification(kIOPMDisableClamshell); 5753 DEBG1("S", " clamshell disable\n"); 5754 } 5755 } 5756 else 5757 { 5758// if (__private->display) panic("(__private->display)"); 5759 __private->display = display; 5760 __private->displayOptions = options; 5761 } 5762} 5763 5764IOOptionBits IOFramebuffer::clamshellState( void ) 5765{ 5766 return (gIOFBClamshellState); 5767} 5768 5769IOReturn IOFramebuffer::agcMessage( void * target, void * refCon, 5770 UInt32 messageType, IOService * service, 5771 void * messageArgument, vm_size_t argSize ) 5772{ 5773 IOReturn ret = kIOReturnSuccess; 5774 enum 5775 { 5776 gMux_Message = 'gMUX', 5777 gMux_WillSwitch = 0, 5778 gMux_DidSwitch = 1, 5779 gMux_DidNotSwitch = 2, 5780 }; 5781 5782 IOService * ackTo = NULL; 5783 uint32_t ackRef = NULL; 5784 uintptr_t param = (uintptr_t) messageArgument; 5785 5786 if (gMux_Message != messageType) 5787 return (ret); 5788 5789 DEBG1("AGC", " %p\n", messageArgument); 5790 5791 SYSLOCK(); 5792 if (gMux_WillSwitch == param) 5793 { 5794 gIOFBSwitching = true; 5795 } 5796 else if (gIOFBSwitching && ((gMux_DidSwitch == param) || (gMux_DidNotSwitch == param))) 5797 { 5798 gIOFBSwitching = false; 5799 5800 ackTo = gIOFBSystemPowerMuxAckTo; 5801 ackRef = gIOFBSystemPowerMuxAckRef; 5802 gIOFBSystemPowerMuxAckTo = 0; 5803 5804 startThread(false); 5805 } 5806 5807 SYSUNLOCK(); 5808 5809 if (ackTo) 5810 { 5811 DEBG("S", " mux allowPowerChange()\n"); 5812 ackTo->allowPowerChange(ackRef); 5813 } 5814 5815 return (ret); 5816} 5817 5818 5819IOReturn IOFramebuffer::muxPowerMessage(UInt32 messageType) 5820{ 5821 IOReturn ret = kIOReturnSuccess; 5822 5823 DEBG1("PWR", " muxPowerMessage(%x->%x)\n", (int) gIOFBLastMuxMessage, (int) messageType); 5824 5825 if (messageType == gIOFBLastMuxMessage) 5826 return (kIOReturnSuccess); 5827 5828 if (kIOMessageSystemWillPowerOn == messageType) 5829 { 5830 OSBitOrAtomic(kIOFBEventSystemPowerOn, &gIOFBGlobalEvents); 5831 return (kIOReturnSuccess); 5832 } 5833 if (kIOMessageDeviceWillPowerOn == messageType) messageType = kIOMessageSystemWillPowerOn; 5834 5835 if ((kIOMessageSystemHasPoweredOn == messageType) 5836 && (kIOMessageSystemWillPowerOn != gIOFBLastMuxMessage)) 5837 { 5838 DEBG1("PWR", " muxPowerMessage(%x)\n", (int) kIOMessageSystemWillPowerOn); 5839 if (gIOGraphicsControl) (void) gIOGraphicsControl->message(kIOMessageSystemWillPowerOn, NULL, NULL); 5840 } 5841 5842 gIOFBLastMuxMessage = messageType; 5843 DEBG1("PWR", " muxPowerMessage(%x)\n", (int) messageType); 5844 if (gIOGraphicsControl) ret = gIOGraphicsControl->message(messageType, NULL, NULL); 5845 5846 return (ret); 5847} 5848 5849IOReturn IOFramebuffer::systemPowerChange( void * target, void * refCon, 5850 UInt32 messageType, IOService * service, 5851 void * messageArgument, vm_size_t argSize ) 5852{ 5853 IOReturn ret = kIOReturnSuccess; 5854 5855 DEBG1("PWR", "(%08x)\n", (uint32_t) messageType); 5856 5857 if (gIOGraphicsControl) switch (messageType) 5858 { 5859#if VERSION_MAJOR >= 11 5860 case kIOMessageSystemCapabilityChange: 5861#endif 5862 case kIOMessageSystemWillSleep: 5863 case kIOMessageSystemWillPowerOn: 5864 case kIOMessageSystemHasPoweredOn: 5865 break; 5866 5867 default: 5868 ret = gIOGraphicsControl->message(messageType, service, messageArgument); 5869 break; 5870 } 5871 5872 switch (messageType) 5873 { 5874 case kIOMessageSystemCapabilityChange: 5875 { 5876 IOPMSystemCapabilityChangeParameters * params = (typeof params) messageArgument; 5877 5878 // root domain won't overlap capability changes with pstate changes 5879 5880 DEBG1("DARK", " %s%s 0x%x->0x%x\n", 5881 params->changeFlags & kIOPMSystemCapabilityWillChange ? "will" : "", 5882 params->changeFlags & kIOPMSystemCapabilityDidChange ? "did" : "", 5883 params->fromCapabilities, 5884 params->toCapabilities); 5885 5886 if ((params->changeFlags & kIOPMSystemCapabilityWillChange) && 5887 (params->fromCapabilities & kIOPMSystemCapabilityGraphics) && 5888 ((params->toCapabilities & kIOPMSystemCapabilityGraphics) == 0)) 5889 { 5890 ret = muxPowerMessage(kIOMessageSystemWillSleep); 5891 if (kIOReturnNotReady == ret) 5892 { 5893 SYSLOCK(); 5894 gIOFBSwitching = true; 5895 gIOFBSystemPowerMuxAckRef = params->notifyRef; 5896 gIOFBSystemPowerMuxAckTo = service; 5897 SYSUNLOCK(); 5898 params->maxWaitForReply = gIOGNotifyTO * 1000 * 1000; 5899 } 5900 } 5901 else if ((params->changeFlags & kIOPMSystemCapabilityWillChange) && 5902 ((params->fromCapabilities & kIOPMSystemCapabilityGraphics) == 0) && 5903 (params->toCapabilities & kIOPMSystemCapabilityGraphics)) 5904 { 5905 if (kIOMessageSystemHasPoweredOn != gIOFBLastMuxMessage) 5906 muxPowerMessage(kIOMessageSystemWillPowerOn); 5907 } 5908 else if ((params->changeFlags & kIOPMSystemCapabilityDidChange) && 5909 ((params->fromCapabilities & kIOPMSystemCapabilityGraphics) == 0) && 5910 (params->toCapabilities & kIOPMSystemCapabilityGraphics)) 5911 { 5912 muxPowerMessage(kIOMessageSystemHasPoweredOn); 5913 } 5914 5915 else if ((params->changeFlags & kIOPMSystemCapabilityDidChange) && 5916 ((params->fromCapabilities & kIOPMSystemCapabilityCPU) == 0) && 5917 (params->toCapabilities & kIOPMSystemCapabilityCPU)) 5918 { 5919 muxPowerMessage(kIOMessageSystemHasPoweredOn); 5920 } 5921 else if ((params->changeFlags & kIOPMSystemCapabilityWillChange) && 5922 ((params->fromCapabilities & kIOPMSystemCapabilityCPU) == 0) && 5923 (params->toCapabilities & kIOPMSystemCapabilityCPU)) 5924 { 5925 muxPowerMessage(kIOMessageSystemWillPowerOn); 5926 SYSLOCK(); 5927 gIOFBSystemPower = true; 5928 gIOGraphicsSystemPower = true; 5929 gIOFBSystemDark = true; 5930 SYSUNLOCK(); 5931 } 5932 else if ((params->changeFlags & kIOPMSystemCapabilityWillChange) && 5933 (params->fromCapabilities & kIOPMSystemCapabilityCPU) && 5934 ((params->toCapabilities & kIOPMSystemCapabilityCPU) == 0)) 5935 { 5936 if (gIOFBSystemPower) 5937 { 5938 ret = muxPowerMessage(kIOMessageSystemWillSleep); 5939 5940 SYSLOCK(); 5941 5942// gIOFBClamshellState = kIOPMDisableClamshell; 5943// getPMRootDomain()->receivePowerNotification(kIOPMDisableClamshell); 5944 5945 gIOFBSystemPower = false; 5946 gIOFBSystemPowerAckRef = (void *)(uintptr_t) params->notifyRef; 5947 gIOFBSystemPowerAckTo = service; 5948 startThread(false); 5949 gIOGraphicsSystemPower = false; 5950 5951 SYSUNLOCK(); 5952 5953 // We will ack within gIOGNotifyTO seconds 5954 params->maxWaitForReply = gIOGNotifyTO * 1000 * 1000; 5955 ret = kIOReturnSuccess; 5956 } 5957 } 5958 ret = kIOReturnSuccess; 5959 break; 5960 } 5961 5962 case kIOMessageSystemWillSleep: 5963 { 5964 IOPowerStateChangeNotification * params = (typeof params) messageArgument; 5965 5966 ret = muxPowerMessage(kIOMessageSystemWillSleep); 5967 5968 SYSLOCK(); 5969 gIOFBClamshellState = kIOPMDisableClamshell; 5970 getPMRootDomain()->receivePowerNotification(kIOPMDisableClamshell); 5971 5972 gIOFBSystemPower = false; 5973 gIOFBSystemPowerAckRef = params->powerRef; 5974 gIOFBSystemPowerAckTo = service; 5975 gIOFBSwitching = (kIOReturnNotReady == ret); 5976 if (gIOFBSwitching) 5977 { 5978 DEBG1("PWR", " agc not ready\n"); 5979 } 5980 startThread(false); 5981 gIOGraphicsSystemPower = false; 5982 SYSUNLOCK(); 5983 5984 // We will ack within gIOGNotifyTO seconds 5985 params->returnValue = gIOGNotifyTO * 1000 * 1000; 5986 ret = kIOReturnSuccess; 5987 break; 5988 } 5989 5990 case kIOMessageSystemWillPowerOn: 5991 { 5992 IOPowerStateChangeNotification * params = (typeof params) messageArgument; 5993 5994 gIOFBSystemDark = false; 5995 5996 if (!gIOFBSystemPower) 5997 { 5998 muxPowerMessage(kIOMessageSystemWillPowerOn); 5999 6000 SYSLOCK(); 6001 6002 readClamshellState(); 6003 OSBitAndAtomic(~(kIOFBEventResetClamshell | kIOFBEventEnableClamshell), 6004 &gIOFBGlobalEvents); 6005 gIOFBSystemPower = true; 6006 gIOGraphicsSystemPower = true; 6007 6008 SYSUNLOCK(); 6009 } 6010 params->returnValue = 0; 6011 ret = kIOReturnSuccess; 6012 break; 6013 } 6014 6015 case kIOMessageSystemHasPoweredOn: 6016 { 6017 IOPowerStateChangeNotification * params = (typeof params) messageArgument; 6018 6019 muxPowerMessage(kIOMessageSystemHasPoweredOn); 6020 6021 SYSLOCK(); 6022 startThread(false); 6023 SYSUNLOCK(); 6024 6025 params->returnValue = 0; 6026 ret = kIOReturnSuccess; 6027 break; 6028 } 6029 6030 case kIOMessageSystemWillRestart: 6031 case kIOMessageSystemWillPowerOff: 6032 case kIOMessageSystemPagingOff: 6033 { 6034 IOPowerStateChangeNotification * params = (typeof params) messageArgument; 6035 6036 SYSLOCK(); 6037 if (gAllFramebuffers) 6038 { 6039 IOFramebuffer * fb; 6040 for (UInt32 index = 0; 6041 (fb = (IOFramebuffer *) gAllFramebuffers->getObject(index)); 6042 index++) 6043 { 6044 FBLOCK(fb); 6045 fb->deliverFramebufferNotification( kIOFBNotifyDisplayModeWillChange ); 6046 if (kIOMessageSystemPagingOff != messageType) 6047 { 6048 fb->setAttribute( kIOSystemPowerAttribute, messageType ); 6049 fb->__private->closed = true; 6050 } 6051 FBUNLOCK(fb); 6052 } 6053 if (kIOMessageSystemPagingOff == messageType) saveGammaTables(); 6054 } 6055 SYSUNLOCK(); 6056 6057 params->returnValue = 0; 6058 ret = kIOReturnSuccess; 6059 break; 6060 } 6061 6062 default: 6063 ret = kIOReturnUnsupported; 6064 break; 6065 } 6066 6067 return (ret); 6068} 6069 6070void IOFramebuffer::deferredSpeedChangeEvent( OSObject * owner, 6071 IOInterruptEventSource * evtSrc, int intCount ) 6072{ 6073 IOFramebuffer * self = (IOFramebuffer *) owner; 6074 6075 if (self->__private->pendingSpeedChange) 6076 { 6077 self->__private->pendingSpeedChange = false; 6078 self->__private->controller->powerThread = current_thread(); 6079 self->setAttribute(kIOFBSpeedAttribute, self->__private->reducedSpeed); 6080 self->__private->controller->powerThread = NULL; 6081 6082 } 6083} 6084 6085IOReturn IOFramebuffer::setAggressiveness( unsigned long type, unsigned long newLevel ) 6086{ 6087 UInt32 reducedSpeed = newLevel; 6088 6089 if (__private 6090 && (type == (unsigned long) kIOFBLowPowerAggressiveness) 6091// && (reducedSpeed != __private->reducedSpeed) 6092 ) 6093 { 6094 __private->reducedSpeed = reducedSpeed; 6095 __private->pendingSpeedChange = true; 6096 if (__private->allowSpeedChanges && __private->deferredSpeedChangeEvent) 6097 { 6098 FBLOCK(this); 6099 startControllerThread(__private->controller); 6100 FBUNLOCK(this); 6101// __private->deferredSpeedChangeEvent->interruptOccurred(0, 0, 0); 6102 } 6103 } 6104 6105 super::setAggressiveness(type, newLevel); 6106 6107 return (kIOReturnSuccess); 6108} 6109 6110IOReturn 6111IOFramebuffer::getAggressiveness( unsigned long type, unsigned long * currentLevel ) 6112{ 6113 IOReturn ret; 6114 6115 if (gIOFBSystemWorkLoop && (type == (unsigned long) kIOFBLowPowerAggressiveness)) 6116 { 6117 SYSLOCK(); 6118 *currentLevel = __private->reducedSpeed; 6119 SYSUNLOCK(); 6120 ret = kIOReturnSuccess; 6121 } 6122 else 6123 ret = super::getAggressiveness(type, currentLevel); 6124 6125 return (ret); 6126} 6127 6128void 6129IOFramebuffer::serverAcknowledgeNotification(void) 6130{ 6131 bool nowOn; 6132 6133 nowOn = (serverNotified && (serverState != serverNotified)); 6134 serverState = serverNotified; 6135 6136 if (serverState && __private->cursorSlept) 6137 { 6138 resetCursor(); 6139 __private->cursorSlept = false; 6140 } 6141 else if (!serverState && !__private->cursorSlept) 6142 { 6143 hideCursor(); 6144 __private->cursorSlept = true; 6145 } 6146 6147 controllerDidWork(__private->controller, kWorkStateChange); 6148} 6149 6150IOReturn 6151IOFramebuffer::extAcknowledgeNotification( 6152 OSObject * target, void * reference, IOExternalMethodArguments * args) 6153{ 6154 IOFramebuffer * inst = (IOFramebuffer *) target; 6155 IOReturn err; 6156 uint32_t idx; 6157 uint32_t countIn; 6158 6159 if ((err = inst->extEntry(true))) 6160 return (err); 6161 6162 countIn = args->scalarInputCount / 2; 6163 for (idx = 0; (idx < kIOPreviewImageCount); idx++) 6164 { 6165 mach_vm_address_t address; 6166 mach_vm_size_t length; 6167 if (inst->__private->saveBitsMD[idx]) 6168 { 6169 inst->__private->saveBitsMD[idx]->release(); 6170 inst->__private->saveBitsMD[idx] = 0; 6171 } 6172 if ((idx < countIn) 6173 && (address = args->scalarInput[idx]) 6174 && (length = args->scalarInput[countIn + idx])) 6175 { 6176 inst->__private->saveBitsMD[idx] = IOMemoryDescriptor::withAddressRange( 6177 address, length, 6178 kIODirectionOut | kIOMemoryPersistent, current_task()); 6179 DEBG1(inst->thisName, " (%d->%d) save bits [0x%llx, 0x%llx] md %p\n", 6180 inst->serverState, inst->serverNotified, 6181 address, length, 6182 inst->__private->saveBitsMD[idx]); 6183 } 6184 } 6185 6186 inst->serverAcknowledgeNotification(); 6187 6188 inst->extExit(err); 6189 6190 return (err); 6191} 6192 6193IOReturn IOFramebuffer::extRegisterNotificationPort( 6194 mach_port_t port, 6195 UInt32 type, 6196 UInt32 refCon ) 6197{ 6198 mach_msg_header_t * msgh; 6199 UInt8 currentState; 6200 6201 FBLOCK(this); 6202 6203 msgh = (mach_msg_header_t *) serverMsg; 6204 bzero( msgh, sizeof(mach_msg_header_t) ); 6205 6206 msgh->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); 6207 msgh->msgh_size = sizeof(mach_msg_header_t); 6208 msgh->msgh_remote_port = port; 6209 6210 msgh->msgh_id = 0x87654321; 6211 mach_msg_send_from_kernel( msgh, msgh->msgh_size ); 6212 6213 currentState = serverNotified; 6214 serverNotified = true; // server assumes so at startup 6215 notifyServer( currentState ); 6216 6217 FBUNLOCK(this); 6218 6219 return (kIOReturnSuccess); 6220} 6221 6222/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 6223 6224#if IOFB_DISABLEFB 6225IODeviceMemory * IOFramebuffer::_getApertureRange(IOFramebuffer * fb, IOPixelAperture aperture) 6226{ 6227 typedef IODeviceMemory * (*Proc)(IOFramebuffer * fb, IOPixelAperture aperture); 6228 Proc proc = (Proc) fb->__private->controller->saveGAR; 6229 IODeviceMemory * mem; 6230 6231 mem = (*proc)(fb, aperture); 6232// kprintf("%s: zorch GAR(%d) %p\n", fb->thisName, aperture, mem); 6233 if (kIOFBSystemAperture == aperture) mem = 0; 6234 6235 return (mem); 6236} 6237#endif 6238 6239/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 6240 6241void IOFramebuffer::writePrefs( OSObject * null, IOTimerEventSource * sender ) 6242{ 6243 IOFramebuffer * fb = (IOFramebuffer *) gAllFramebuffers->getObject(0); 6244 if (fb) 6245 { 6246 DEBG(fb->thisName, "\n"); 6247 fb->messageClients( kIOMessageServicePropertyChange, (void *) 'pref' ); 6248 } 6249} 6250 6251void IOFramebuffer::connectChangeInterrupt( IOFramebuffer * inst, void * delay ) 6252{ 6253 OSIncrementAtomic( &inst->__private->controller->connectChange); 6254 6255 DEBG1(inst->thisName, "(%d)\n", inst->__private->controller->connectChange); 6256 6257 startThread(false); 6258} 6259 6260IOReturn IOFramebuffer::open( void ) 6261{ 6262 IOReturn err = kIOReturnSuccess; 6263 uintptr_t value; 6264 IOFramebuffer * next; 6265 OSNumber * depIDProp; 6266 OSNumber * depIDMatch; 6267 OSNumber * num; 6268 OSData * data; 6269 OSObject * obj; 6270 bool newController; 6271 bool openAllDependents; 6272 6273 do 6274 { 6275 if (!gIOFBSystemWorkLoop) panic("gIOFBSystemWorkLoop"); 6276 SYSLOCK(); 6277 6278 if (opened) continue; 6279 if (dead) 6280 { 6281 err = kIOReturnNotOpen; 6282 continue; 6283 } 6284 6285 if (!gIOFBServerInit) IOFramebuffer::initialize(); 6286 if (!gAllFramebuffers) continue; 6287 if (!gIOFBRootNotifier) continue; 6288 if (!gIOFBHIDWorkLoop) continue; 6289 if (!gIOFBWorkES) continue; 6290 6291 if (!IODisplayWrangler::serverStart()) continue; 6292 6293 if (!gIOFBClamshellNotify) 6294 gIOFBClamshellNotify = addMatchingNotification( gIOPublishNotification, 6295 resourceMatching(kAppleClamshellStateKey), 6296 &clamshellHandler, NULL, 0, 10000 ); 6297 readClamshellState(); 6298 6299 if (-1 == gIOFBHaveBacklight) do 6300 { 6301 OSDictionary * matching = nameMatching("backlight"); 6302 OSIterator * iter = NULL; 6303 bool haveBacklight = false; 6304 if (matching) 6305 { 6306 iter = getMatchingServices(matching); 6307 matching->release(); 6308 } 6309 if (iter) 6310 { 6311 haveBacklight = (0 != iter->getNextObject()); 6312 iter->release(); 6313 } 6314 gIOFBHaveBacklight = haveBacklight; 6315 6316 if (!haveBacklight) 6317 continue; 6318 6319 const OSSymbol * settingsArray[2]; 6320 getPMRootDomain()->publishFeature("DisplayDims"); 6321 // Register to manage the "DisplaySleepUsesDim" setting 6322 settingsArray[0] = gIOFBPMSettingDisplaySleepUsesDimKey; 6323 settingsArray[1] = NULL; 6324 OSObject * pmSettingNotificationHandle; 6325 getPMRootDomain()->registerPMSettingController(settingsArray, 6326 &pmSettingsChange, 6327 NULL, 6328 (uintptr_t) NULL, 6329 &pmSettingNotificationHandle); 6330 } 6331 while (false); 6332 6333 serverNotified = true; 6334 serverState = true; 6335 6336 newController = (!__private->controller); 6337 if (newController) 6338 { 6339 __private->controller = IONew(IOFBController, 1); 6340 if (!__private->controller) 6341 panic("IOFBController"); 6342 bzero(__private->controller, sizeof(IOFBController)); 6343 IOService * service = this; 6344 while ((service = service->getProvider()) && !OSDynamicCast(IOPCIDevice, service)) 6345 {} 6346 if (service) 6347 { 6348 __private->controller->device = service; 6349 __private->controller->name = service->getName(); 6350 if ((data = OSDynamicCast(OSData, service->getProperty("vendor-id")))) 6351 __private->controller->vendorID = ((uint32_t *) data->getBytesNoCopy())[0]; 6352 __private->controller->integrated = (0 == ((IOPCIDevice *)service)->getBusNumber()); 6353 } 6354 else 6355 __private->controller->name = "FB??"; 6356#if SINGLE_THREAD 6357 __private->controller->wl = gIOFBSystemWorkLoop; 6358#else 6359 __private->controller->wl = IOGraphicsWorkLoop::workLoop(0, 6360 NULL, NULL, __private->controller); 6361#endif 6362 if (!__private->controller->wl) 6363 panic("controller->wl"); 6364 __private->controller->workES = IOInterruptEventSource::interruptEventSource( 6365 this, &controllerAsyncWork); 6366 if (!__private->controller->workES) 6367 panic("controller->workES"); 6368 __private->controller->wl->addEventSource(__private->controller->workES); 6369 __private->controller->didWork = true; 6370 } 6371 if (__private->controller->integrated) setProperty(kIOFBIntegratedKey, kOSBooleanTrue); 6372 6373 FBLOCK(this); 6374 6375 uint32_t depIdx; 6376 depIDProp = OSDynamicCast(OSNumber, getProperty(kIOFBDependentIDKey)); 6377 openAllDependents = depIDProp && !nextDependent; 6378 num = OSDynamicCast(OSNumber, getProperty(kIOFBDependentIndexKey)); 6379 depIdx = num ? num->unsigned32BitValue() : 0; 6380 if (depIdx >= kIOFBControllerMaxFBs) 6381 panic("%s: bad " kIOFBDependentIndexKey "\n", getName()); 6382 else 6383 { 6384 __private->controller->fbs[depIdx] = this; 6385 if (depIdx >= __private->controller->maxFB) 6386 __private->controller->maxFB = depIdx; 6387 __private->controllerIndex = depIdx; 6388 } 6389 6390 __private->controller->wsWait |= (1 << __private->controllerIndex); 6391 isUsable = true; 6392 6393 size_t len = strlen(__private->controller->name) + 3; 6394 char * logName = IONew(char, len); 6395 if (logName) 6396 snprintf(logName, len, "%s-%c", __private->controller->name, 'A' + depIdx); 6397 thisName = logName; 6398 6399 if (openAllDependents) 6400 { 6401 do 6402 { 6403 IOFramebuffer * first = 0; 6404 IOFramebuffer * last = 0; 6405 for (thisIndex = 0; (next = (IOFramebuffer *) gStartedFramebuffers->getObject(thisIndex)); thisIndex++) 6406 { 6407 depIDMatch = OSDynamicCast(OSNumber, next->getProperty(kIOFBDependentIDKey)); 6408 if (!depIDMatch || !depIDMatch->isEqualTo(depIDProp)) continue; 6409 next->__private->controller = __private->controller; 6410 if (!first) 6411 first = next; 6412 else if (last) 6413 last->setNextDependent( next ); 6414 last = next; 6415 } 6416 if (first && last && (first != last)) 6417 last->setNextDependent( first ); 6418 } 6419 while (false); 6420 } 6421 6422 // tell the console if it's on this display, it's going away 6423 if (isConsoleDevice() /*&& !gIOFBConsoleFramebuffer*/) 6424 gIOFBConsoleFramebuffer = this; 6425 if ((this == gIOFBConsoleFramebuffer) || !gIOFBConsoleFramebuffer) 6426 getPlatform()->setConsoleInfo( 0, kPEDisableScreen); 6427 6428 deliverFramebufferNotification( kIOFBNotifyDisplayModeWillChange ); 6429 6430 IOService * provider = getProvider(); 6431 provider->setProperty("AAPL,gray-value", gIOFBGray32Data); 6432 provider->setProperty("AAPL,gray-page", gIOFBOne32Data); 6433 data = OSData::withBytesNoCopy(&__private->uiScale, sizeof(__private->uiScale)); 6434 if (data) 6435 { 6436 setProperty(kIOFBUIScaleKey, data); 6437 data->release(); 6438 } 6439 6440 if (!AbsoluteTime_to_scalar(&__private->controller->initTime)) 6441 AbsoluteTime_to_scalar(&__private->controller->initTime) = mach_absolute_time(); 6442 6443 err = enableController(); 6444 6445 if (kIOReturnSuccess != err) 6446 { 6447 dead = true; 6448 if (nextDependent) 6449 { 6450 nextDependent->setNextDependent( NULL ); 6451 nextDependent = NULL; 6452 } 6453 deliverDisplayModeDidChangeNotification(); 6454 FBUNLOCK(this); 6455 continue; 6456 } 6457 6458#if IOFB_DISABLEFB 6459 if (newController) 6460 { 6461 // getApertureRange 2472 6462 // getVRAMRange 2480 6463 uintptr_t * vt; 6464 addr64_t v; 6465 ppnum_t phys; 6466 vt = ((uintptr_t **)this)[0]; 6467 __private->controller->saveGAR = vt[2472/sizeof(uintptr_t)]; 6468 v = (addr64_t) &vt[2472/sizeof(uintptr_t)]; 6469 phys = pmap_find_phys(kernel_pmap, v); 6470 ml_phys_write_double_64(ptoa_64(phys) | (v & page_mask), (uint64_t) &IOFramebuffer::_getApertureRange); 6471 } 6472#endif 6473 6474 if (newController) 6475 { 6476 if (gIOFBLastController) 6477 gIOFBLastController->nextController = __private->controller; 6478 else 6479 gIOFBAllControllers = __private->controller; 6480 __private->controller->nextController = gIOFBAllControllers; 6481 gIOFBLastController = __private->controller; 6482 6483 if ((obj = copyProperty("AAPL,display-alias", gIOServicePlane))) 6484 { 6485 if ((data = OSDynamicCast(OSData, obj))) 6486 __private->controller->aliasID = (0x80000000 | ((uint32_t *) data->getBytesNoCopy())[0]); 6487 obj->release(); 6488 } 6489 } 6490 6491 thisIndex = gStartedFramebuffers->getNextIndexOfObject(this, 0); 6492 if (-1U == thisIndex) 6493 { 6494 thisIndex = gStartedFramebuffers->getCount(); 6495 gStartedFramebuffers->setObject(this); 6496 } 6497 setProperty(kIOFramebufferOpenGLIndexKey, thisIndex, 64); 6498 gAllFramebuffers->setObject(this); 6499 6500 DEBG(thisName, " this %p \"%s\" \"%s\"\n", this, getName(), getProvider()->getName()); 6501 DEBG1(thisName, " singleth %d, this %p controller %p\n", 6502 SINGLE_THREAD, this, __private->controller); 6503 DEBG1(thisName, " init time now %lld start %lld\n", 6504 mach_absolute_time(), AbsoluteTime_to_scalar(&__private->controller->initTime)); 6505 6506 pagingState = true; 6507 6508 obj = copyProperty("graphic-options", gIOServicePlane); 6509 if (obj) 6510 { 6511 data = OSDynamicCast(OSData, obj); 6512 uint32_t gOpts = ((UInt32 *) data->getBytesNoCopy())[0]; 6513 __private->colorModesAllowed = (data && (0 != (kIOGPlatformYCbCr & gOpts))); 6514 obj->release(); 6515 } 6516 6517 if ((num = OSDynamicCast(OSNumber, getProperty(kIOFBTransformKey)))) 6518 __private->selectedTransform = num->unsigned64BitValue(); 6519 __private->selectedTransform |= kIOFBDefaultScalerUnderscan; 6520 6521 // vbl events 6522 err = registerForInterruptType( kIOFBVBLInterruptType, 6523 (IOFBInterruptProc) &handleVBL, 6524 this, priv, &__private->vblInterrupt ); 6525 haveVBLService = (err == kIOReturnSuccess ); 6526 __private->vblEnabled = haveVBLService; 6527 if (haveVBLService) 6528 { 6529 __private->deferredVBLDisableEvent = IOInterruptEventSource::interruptEventSource( 6530 this, &deferredVBLDisable); 6531 if (__private->deferredVBLDisableEvent) 6532 __private->controller->wl->addEventSource(__private->deferredVBLDisableEvent); 6533 __private->vblUpdateTimer = IOTimerEventSource::timerEventSource(this, &updateVBL); 6534 if (__private->vblUpdateTimer) 6535 __private->controller->wl->addEventSource(__private->vblUpdateTimer); 6536 } 6537 6538 if (haveVBLService 6539 && (kIOReturnSuccess == getAttribute( kIODeferCLUTSetAttribute, &value )) 6540 && value) 6541 { 6542 __private->deferredCLUTSetEvent = IOInterruptEventSource::interruptEventSource( 6543 this, &deferredCLUTSetInterrupt); 6544 if (__private->deferredCLUTSetEvent) 6545 __private->controller->wl->addEventSource(__private->deferredCLUTSetEvent); 6546 6547 __private->deferredCLUTSetTimerEvent = IOTimerEventSource::timerEventSource( 6548 this, &deferredCLUTSetTimer); 6549 if (__private->deferredCLUTSetTimerEvent) 6550 __private->controller->wl->addEventSource(__private->deferredCLUTSetTimerEvent); 6551 6552 if (__private->deferredCLUTSetEvent || __private->deferredCLUTSetTimerEvent) 6553 setProperty(kIOFBCLUTDeferKey, kOSBooleanTrue); 6554 } 6555 6556 // connect events 6557 obj = copyProperty(kIOFBConnectInterruptDelayKey, gIOServicePlane); 6558 if (obj) 6559 { 6560 OSData * data; 6561 if ((data = OSDynamicCast(OSData, obj))) 6562 __private->delayedConnectTime = *((UInt32 *) data->getBytesNoCopy()); 6563 obj->release(); 6564 } 6565 6566 err = registerForInterruptType( kIOFBConnectInterruptType, 6567 (IOFBInterruptProc) &connectChangeInterrupt, 6568 this, (void *)(uintptr_t) __private->delayedConnectTime, 6569 &__private->connectInterrupt ); 6570 // dp events 6571 __private->dpInterrupDelayTime = 2; 6572 __private->dpInterruptES = IOTimerEventSource::timerEventSource(this, &dpInterrupt); 6573 if (__private->dpInterruptES) 6574 __private->controller->wl->addEventSource(__private->dpInterruptES); 6575 6576 err = registerForInterruptType( kIOFBDisplayPortInterruptType, 6577 (IOFBInterruptProc) &dpInterruptProc, 6578 this, (void *)(uintptr_t) __private->dpInterrupDelayTime, 6579 &__private->dpInterruptRef ); 6580 __private->dpInterrupts = (kIOReturnSuccess == err); 6581 __private->dpSupported = __private->dpInterrupts; 6582 // 6583 6584 err = getAttribute( kIOHardwareCursorAttribute, &value ); 6585 haveHWCursor = ((err == kIOReturnSuccess) && (0 != (kIOFBHWCursorSupported & value))); 6586 6587 clock_interval_to_deadline(40, kMicrosecondScale, 6588 &__private->defaultI2CTiming.bitTimeout); 6589 clock_interval_to_deadline(40, kMicrosecondScale, 6590 &__private->defaultI2CTiming.byteTimeout); 6591 clock_interval_to_deadline(40, kMicrosecondScale, 6592 &__private->defaultI2CTiming.acknowledgeTimeout); 6593 clock_interval_to_deadline(40, kMicrosecondScale, 6594 &__private->defaultI2CTiming.startTimeout); 6595 6596 __private->lli2c = (kIOReturnSuccess == getAttributeForConnection( 6597 0, kConnectionSupportsLLDDCSense, 6598 (uintptr_t *) &__private->defaultI2CTiming)); 6599 6600 if ((num = OSDynamicCast(OSNumber, getProperty(kIOFBGammaWidthKey)))) 6601 __private->desiredGammaDataWidth = num->unsigned32BitValue(); 6602 if ((num = OSDynamicCast(OSNumber, getProperty(kIOFBGammaCountKey)))) 6603 __private->desiredGammaDataCount = num->unsigned32BitValue(); 6604 if ((num = OSDynamicCast(OSNumber, getProperty(kIOFBGammaHeaderSizeKey)))) 6605 __private->gammaHeaderSize = num->unsigned32BitValue(); 6606 6607 __private->deferredSpeedChangeEvent = IOInterruptEventSource::interruptEventSource( 6608 this, deferredSpeedChangeEvent); 6609 if (__private->deferredSpeedChangeEvent) 6610 __private->controller->wl->addEventSource(__private->deferredSpeedChangeEvent); 6611 6612 opened = true; 6613 6614 bool nowOnline; 6615 nowOnline = updateOnline(); 6616 if (nowOnline) 6617 { 6618 if (!gIOFBConsoleFramebuffer) gIOFBConsoleFramebuffer = this; 6619 } 6620 else 6621 { 6622 if (this == gIOFBConsoleFramebuffer) gIOFBConsoleFramebuffer = NULL; 6623 } 6624 6625 __private->paramHandler = IOFramebufferParameterHandler::withFramebuffer(this); 6626 if (__private->paramHandler) 6627 setProperty(gIODisplayParametersKey, __private->paramHandler); 6628 6629 IOFramebufferI2CInterface::create( this ); 6630 6631 __private->online = nowOnline; 6632 if (nowOnline) 6633 displaysOnline(nowOnline); 6634 else 6635 IODisplayUpdateNVRAM(this, 0); 6636 6637 __private->transform = __private->selectedTransform; 6638 setProperty(kIOFBTransformKey, __private->transform, 64); 6639 6640 if (openAllDependents) 6641 { 6642 next = this; 6643 while ((next = next->getNextDependent()) && (next != this)) 6644 { 6645 next->open(); 6646 } 6647 } 6648 6649 if (nowOnline) 6650 { 6651 deliverDisplayModeDidChangeNotification(); 6652 err = kIOReturnSuccess; 6653 } 6654 else 6655 { 6656 findConsole(); 6657 deliverDisplayModeDidChangeNotification(); 6658 dpUpdateConnect(); 6659 } 6660 6661 if (openAllDependents) 6662 { 6663 next = this; 6664 do 6665 { 6666 next->postOpen(); 6667 } 6668 while ((next = next->getNextDependent()) && (next != this)); 6669 } 6670 6671 FBUNLOCK(this); 6672 } 6673 while (false); 6674 6675 if (__private->controller) 6676 { 6677 FBLOCK(this); 6678 __private->allowSpeedChanges = true; 6679 if (__private->pendingSpeedChange) 6680 { 6681 __private->pendingSpeedChange = false; 6682 __private->controller->powerThread = current_thread(); 6683 setAttribute(kIOFBSpeedAttribute, __private->reducedSpeed); 6684 __private->controller->powerThread = NULL; 6685 } 6686 FBUNLOCK(this); 6687 } 6688 6689 SYSUNLOCK(); 6690 6691 return (err); 6692} 6693 6694void IOFramebuffer::setTransform( UInt64 newTransform, bool generateChange ) 6695{ 6696 newTransform |= (kIOFBScalerUnderscan & __private->selectedTransform); 6697 6698 if (newTransform != __private->selectedTransform) 6699 { 6700 __private->userSetTransform = generateChange; 6701 __private->selectedTransform = newTransform; 6702 if (generateChange) 6703 connectChangeInterrupt(this, 0); 6704 else 6705 { 6706 __private->transform = newTransform; 6707 setProperty(kIOFBTransformKey, newTransform, 64); 6708 } 6709 } 6710} 6711 6712UInt64 IOFramebuffer::getTransform( void ) 6713{ 6714 return (__private->transform); 6715} 6716 6717IOReturn IOFramebuffer::selectTransform( UInt64 transform, bool generateChange ) 6718{ 6719 IOFramebuffer * next; 6720 next = this; 6721// do 6722 { 6723 next->setTransform(transform, generateChange); 6724 } 6725// while ((next = next->getNextDependent()) && (next != this)); 6726 6727 return (kIOReturnSuccess); 6728} 6729 6730IOReturn IOFramebuffer::probeAll( IOOptionBits options ) 6731{ 6732 IOReturn err = kIOReturnSuccess; 6733 6734 do 6735 { 6736 unsigned int index; 6737 IOFramebuffer * fb; 6738 6739 if (gIOGraphicsControl) 6740 { 6741 err = gIOGraphicsControl->requestProbe(options); 6742 break; 6743 } 6744 for (index = 0; 6745 (fb = (IOFramebuffer *) gAllFramebuffers->getObject(index)); 6746 index++) 6747 { 6748 FBLOCK(fb); 6749 if (!fb->captured) 6750 { 6751 IOReturn 6752 thisErr = fb->setAttributeForConnection(0, kConnectionProbe, options); 6753 if (kIOReturnSuccess == err) 6754 err = thisErr; 6755 } 6756 FBUNLOCK(fb); 6757 } 6758 } 6759 while (false); 6760 6761 return (err); 6762} 6763 6764IOReturn IOFramebuffer::requestProbe( IOOptionBits options ) 6765{ 6766 IOReturn err; 6767 6768 if (!gIOFBSystemWorkLoop || gIOFBSystemWorkLoop->inGate()) 6769 return (kIOReturnNotReady); 6770 6771 if ((err = extEntry(true))) 6772 return (err); 6773 6774#if 0 6775 if (!__private->online) 6776 { 6777 inst->extExit(err); 6778 return (kIOReturnSuccess); 6779 } 6780#endif 6781 if (kIOFBSetTransform & options) 6782 { 6783 options >>= 16; 6784 selectTransform(options, true); 6785 } 6786 else 6787 { 6788 if (captured) 6789 { 6790 err = kIOReturnBusy; 6791 } 6792 else 6793 { 6794 AbsoluteTime now; 6795 AbsoluteTime_to_scalar(&now) = mach_absolute_time(); 6796 if (CMP_ABSOLUTETIME(&now, &gIOFBNextProbeAllTime) >= 0) 6797 { 6798 OSBitOrAtomic(kIOFBEventProbeAll, &gIOFBGlobalEvents); 6799 startThread(false); 6800 clock_interval_to_deadline(10, kSecondScale, &gIOFBNextProbeAllTime); 6801 } 6802 } 6803 } 6804 6805 extExit(err); 6806 6807 return (kIOReturnSuccess); 6808} 6809 6810void IOFramebuffer::initFB(void) 6811{ 6812 AbsoluteTime now; 6813 uint64_t nsec; 6814 6815 if (!__private->online) 6816 { 6817 __private->needsInit = false; 6818 return; 6819 } 6820 if (!frameBuffer) return; 6821 6822 do 6823 { 6824 IOReturn err; 6825 IODisplayModeID mode; 6826 IOIndex depth; 6827 IOPixelInformation pixelInfo; 6828 IOMemoryDescriptor * fbRange; 6829 uint32_t totalWidth, consoleDepth; 6830 uint8_t logo; 6831 bool timeout = false; 6832 6833 err = getCurrentDisplayMode(&mode, &depth); 6834 if (kIOReturnSuccess != err) 6835 break; 6836 err = getPixelInformation(mode, depth, kIOFBSystemAperture, &pixelInfo); 6837 if (kIOReturnSuccess != err) 6838 break; 6839 if (pixelInfo.activeWidth < 128) 6840 break; 6841 6842 if (!vramMap) 6843 { 6844 fbRange = getApertureRange(kIOFBSystemAperture); 6845 if (!fbRange) 6846 break; 6847 vramMap = fbRange->map(kIOFBMapCacheMode); 6848 fbRange->release(); 6849 if (!vramMap) 6850 break; 6851 } 6852 if (pixelInfo.bitsPerComponent > 8) 6853 consoleDepth = pixelInfo.componentCount * pixelInfo.bitsPerComponent; 6854 else 6855 consoleDepth = pixelInfo.bitsPerPixel; 6856 totalWidth = (pixelInfo.bytesPerRow * 8) / pixelInfo.bitsPerPixel; 6857 6858 if (false && __private->needsInit == 1) 6859 { 6860 AbsoluteTime_to_scalar(&now) = mach_absolute_time(); 6861 SUB_ABSOLUTETIME(&now, &__private->controller->initTime); 6862 absolutetime_to_nanoseconds(now, &nsec); 6863 timeout = (nsec > kInitFBTimeoutNS); 6864 if (timeout) DEBG1(thisName, " init timeout\n"); 6865 } 6866 // timeout = false; 6867 logo = ((!timeout) 6868 && (NULL != getProperty("AAPL,boot-display", gIOServicePlane)) 6869 && (__private->needsInit != 3)); 6870 // logo = 1; 6871 if (logo) 6872 { 6873 PE_Video consoleInfo; 6874 IOService::getPlatform()->getConsoleInfo(&consoleInfo); 6875 if ((consoleInfo.v_width == pixelInfo.activeWidth) 6876 && (consoleInfo.v_height == pixelInfo.activeHeight)) 6877 { 6878 if (2 == consoleInfo.v_scale) logo = 2; 6879 } 6880 else logo = 0; 6881 } 6882 DEBG1(thisName, " initFB: needsInit %d logo %d\n", 6883 __private->needsInit, logo); 6884 IOFramebufferBootInitFB( 6885 vramMap->getVirtualAddress(), 6886 pixelInfo.activeWidth, pixelInfo.activeHeight, 6887 totalWidth, consoleDepth, 6888 logo); 6889 DEBG1(thisName, " initFB: done\n"); 6890 if (logo && !getProperty(kIOFBBootGammaRestoredKey, gIOServicePlane)) updateGammaTable(3, 256, 16, NULL, false); 6891 __private->needsInit = false; 6892 setProperty(kIOFBNeedsRefreshKey, (0 == logo)); 6893 } 6894 while (false); 6895} 6896 6897IOReturn IOFramebuffer::postOpen( void ) 6898{ 6899 __private->needsInit = true; 6900 __private->needsInit += (kOSBooleanFalse == getProperty(kIOFBNeedsRefreshKey)); 6901 setProperty(kIOFBNeedsRefreshKey, true); 6902 initFB(); 6903 6904 if (__private->cursorAttributes) 6905 { 6906 __private->cursorAttributes->release(); 6907 __private->cursorAttributes = 0; 6908 } 6909 6910 __private->cursorAttributes = OSArray::withCapacity(2); 6911 if (!__private->cursorAttributes) 6912 return (kIOReturnNoMemory); 6913 6914 __private->testingCursor = true; 6915 6916 setCursorImage( (void *) 0 ); 6917 6918 if (__private->cursorThread) 6919 { 6920 IOHardwareCursorDescriptor desc; 6921 6922 desc.majorVersion = kHardwareCursorDescriptorMajorVersion; 6923 desc.minorVersion = kHardwareCursorDescriptorMinorVersion; 6924 desc.height = 256; 6925 desc.width = 256; 6926 desc.bitDepth = 32; 6927 desc.maskBitDepth = 0; 6928 desc.colorEncodings = 0; 6929 desc.flags = 0; 6930 desc.supportedSpecialEncodings = kTransparentEncodedPixel; 6931 6932 (*__private->cursorControl.callouts->setCursorImage) ( 6933 __private->cursorControl.self, __private->cursorControl.ref, 6934 &desc, (void *) 0 ); 6935 6936 if (__private->controller->wl) 6937 __private->controller->wl->addEventSource(__private->cursorThread); 6938 } 6939 6940 __private->testingCursor = false; 6941 6942 setProperty( kIOFBCursorInfoKey, __private->cursorAttributes ); 6943 6944 IOService * sensor = 0; 6945 uintptr_t value[16]; 6946 6947//#define kTempAttribute kConnectionWSSB 6948#define kTempAttribute 'thrm' 6949 6950 if (!__private->temperatureSensor 6951 && (kIOReturnSuccess == getAttributeForConnection(0, kTempAttribute, &value[0]))) 6952 do 6953 { 6954 UInt32 data; 6955 OSNumber * num; 6956 6957 num = OSDynamicCast(OSNumber, getProperty(kIOFBDependentIDKey)); 6958 if (num && num->unsigned32BitValue()) 6959 continue; 6960 6961 sensor = new IOService; 6962 if (!sensor) 6963 continue; 6964 if (!sensor->init()) 6965 continue; 6966 6967#define kTempSensorName "temp-sensor" 6968 sensor->setName(kTempSensorName); 6969 sensor->setProperty("name", (void *) kTempSensorName, strlen(kTempSensorName) + 1); 6970 sensor->setProperty("compatible", (void *) kTempSensorName, strlen(kTempSensorName) + 1); 6971 sensor->setProperty("device_type", (void *) kTempSensorName, strlen(kTempSensorName) + 1); 6972 sensor->setProperty("type", "temperature"); 6973 sensor->setProperty("location", "GPU"); 6974 data = 0xff000002; 6975 sensor->setProperty("zone", &data, sizeof(data)); 6976 data = 0x00000001; 6977 sensor->setProperty("version", &data, sizeof(data)); 6978 6979 OSData * prop; 6980 IOService * device; 6981 data = 0x12345678; 6982 if ((device = getProvider()) 6983 && (prop = OSDynamicCast(OSData, device->getProperty("AAPL,phandle")))) 6984 data = (*((UInt32 *) prop->getBytesNoCopy())) << 8; 6985 sensor->setProperty("sensor-id", &data, sizeof(data)); 6986 6987 if (!sensor->attach(this)) 6988 continue; 6989 6990 sensor->registerService(); 6991 __private->temperatureSensor = sensor; 6992 } 6993 while (false); 6994 6995 if (sensor) 6996 sensor->release(); 6997 6998 return (kIOReturnSuccess); 6999} 7000 7001IOReturn IOFramebuffer::callPlatformFunction( const OSSymbol * functionName, 7002 bool waitForFunction, 7003 void *p1, void *p2, 7004 void *p3, void *p4 ) 7005{ 7006 uintptr_t value[16]; 7007 IOReturn ret; 7008 7009 if (functionName != gIOFBGetSensorValueKey) 7010 return (super::callPlatformFunction(functionName, waitForFunction, p1, p2, p3, p4)); 7011 7012 FBLOCK(this); 7013 ret = getAttributeForConnection(0, kTempAttribute, &value[0]); 7014 FBUNLOCK(this); 7015 7016 if (kIOReturnSuccess == ret) 7017 *((UInt32 *)p2) = ((value[0] & 0xffff) << 16); 7018 7019 return (ret); 7020} 7021 7022IOWorkLoop * IOFramebuffer::getControllerWorkLoop() const 7023{ 7024 return (__private->controller->wl); 7025} 7026 7027IOWorkLoop * IOFramebuffer::getGraphicsSystemWorkLoop() const 7028{ 7029 return (gIOFBSystemWorkLoop); 7030} 7031 7032IOWorkLoop * IOFramebuffer::getWorkLoop() const 7033{ 7034 if (__private && __private->controller) 7035 return (__private->controller->wl); 7036 else 7037 return (NULL); 7038} 7039 7040void IOFramebuffer::setCaptured( bool isCaptured ) 7041{ 7042 bool wasCaptured = captured; 7043 7044 captured = isCaptured; 7045 7046 DEBG1(thisName, " captured %d -> %d\n", wasCaptured, captured); 7047 7048 if (wasCaptured != isCaptured) 7049 { 7050 if (isCaptured) 7051 setProperty(kIOFBCapturedKey, kOSBooleanTrue); 7052 else 7053 removeProperty(kIOFBCapturedKey); 7054 deliverFramebufferNotification(kIOFBNotifyCaptureChange, (void *) isCaptured); 7055 7056 startControllerThread(__private->controller); 7057 } 7058} 7059 7060void IOFramebuffer::setDimDisable( bool dimDisable ) 7061{ 7062 __private->dimDisable = dimDisable; 7063} 7064 7065bool IOFramebuffer::getDimDisable( void ) 7066{ 7067 return (__private->dimDisable); 7068} 7069 7070void IOFramebuffer::setNextDependent( IOFramebuffer * dependent ) 7071{ 7072 nextDependent = dependent; 7073} 7074 7075IOFramebuffer * IOFramebuffer::getNextDependent( void ) 7076{ 7077 return (nextDependent); 7078} 7079 7080void IOFramebuffer::close( void ) // called by the user client when 7081{ // the window server exits 7082 IOReturn err; 7083 unsigned int idx; 7084 mach_msg_header_t * msgh; 7085 7086 if ((err = extEntrySys(true))) 7087 return; 7088 7089 if ((this == gIOFBConsoleFramebuffer) && getPowerState()) 7090 getPlatform()->setConsoleInfo( 0, kPEAcquireScreen); 7091 7092 msgh = (mach_msg_header_t *) serverMsg; 7093 if (msgh) 7094 msgh->msgh_remote_port = MACH_PORT_NULL; 7095 7096 __private->controller->wsWait |= (1 << __private->controllerIndex); 7097 serverConnect = 0; 7098 captured = false; 7099 setProperty(kIOFBNeedsRefreshKey, true); 7100 7101 for (idx = 0; 7102 (idx < kIOPreviewImageCount) && __private->saveBitsMD[idx]; 7103 idx++) 7104 { 7105 __private->saveBitsMD[idx]->release(); 7106 __private->saveBitsMD[idx] = 0; 7107 } 7108 7109 if (gRunawayFramebuffers) 7110 { 7111 idx = gAllFramebuffers->getNextIndexOfObject( this, 0 ); 7112 if (idx != (unsigned int) -1) 7113 gAllFramebuffers->removeObject(idx); 7114 7115 idx = gRunawayFramebuffers->getNextIndexOfObject( this, 0 ); 7116 if (idx != (unsigned int) -1) 7117 gRunawayFramebuffers->removeObject(idx); 7118 7119 if (idx != (unsigned int) -1) 7120 { 7121 terminate(); 7122 } 7123 } 7124 7125 extExitSys(err); 7126} 7127 7128IODeviceMemory * IOFramebuffer::getVRAMRange( void ) 7129{ 7130 return (getApertureRange(kIOFBSystemAperture)); 7131} 7132 7133IOReturn IOFramebuffer::setUserRanges( void ) 7134{ 7135#if RLOG 7136 // print ranges 7137 uint32_t i, numRanges; 7138 IOMemoryDescriptor * mem; 7139 numRanges = userAccessRanges->getCount(); 7140 DEBG(thisName, " ranges num:%d\n", numRanges); 7141 for (i = 0; i < numRanges; i++) 7142 { 7143 mem = (IOMemoryDescriptor *) userAccessRanges->getObject( i ); 7144 if (0 == mem) 7145 continue; 7146 DEBG(thisName, " start:%llx size:%lx\n", 7147 mem->getPhysicalSegment(0, 0, kIOMemoryMapperNone), (long) mem->getLength() ); 7148 } 7149#endif 7150 7151 return (kIOReturnSuccess); 7152} 7153 7154IOReturn IOFramebuffer::setBackingFramebuffer(const IOPixelInformation * info, 7155 uint32_t bufferCount, 7156 void * mappedAddress[]) 7157{ 7158 return (kIOReturnSuccess); 7159} 7160 7161IOReturn IOFramebuffer::switchBackingFramebuffer(uint32_t bufferIndex) 7162{ 7163 return (kIOReturnSuccess); 7164} 7165 7166void IOFramebuffer::findConsole(void) 7167{ 7168 PE_Video newConsole; 7169 IOFramebuffer * look; 7170 IOFramebuffer * fb = NULL; 7171 uintptr_t value; 7172 7173 for (uint32_t index = 0; 7174 (look = (IOFramebuffer *) gAllFramebuffers->getObject(index)); 7175 index++) 7176 { 7177 if (!look->__private 7178 || !look->frameBuffer 7179 || !look->__private->framebufferWidth 7180 || !look->__private->framebufferHeight 7181 || !look->__private->online 7182 || !look->__private->controller 7183 || !look->__private->controller->device 7184 || !look->__private->consoleDepth 7185 || (look->__private->consoleDepth > 32)) 7186 continue; 7187 7188 if ((kIOReturnSuccess == look->getAttribute(kIOVRAMSaveAttribute, &value)) 7189 && !value) 7190 continue; 7191 7192 if (kIODisplayOptionBacklight & look->__private->displayOptions) 7193 { 7194 fb = look; 7195 break; 7196 } 7197 if (!fb || (look == gIOFBConsoleFramebuffer)) 7198 { 7199 fb = look; 7200 } 7201 } 7202 7203 if (fb) 7204 { 7205 DEBG1(fb->thisName, " console set 0x%x000 %d x %d\n", 7206 pmap_find_phys(kernel_pmap, (addr64_t) fb->frameBuffer), 7207 fb->__private->framebufferWidth, 7208 fb->__private->framebufferHeight); 7209 bzero(&newConsole, sizeof(newConsole)); 7210 newConsole.v_baseAddr = (unsigned long) fb->frameBuffer; 7211 newConsole.v_rowBytes = fb->rowBytes; 7212 newConsole.v_width = fb->__private->framebufferWidth; 7213 newConsole.v_height = fb->__private->framebufferHeight; 7214 newConsole.v_depth = fb->__private->consoleDepth; 7215 newConsole.v_scale = fb->__private->uiScale; 7216 newConsole.v_display = 1; // graphics mode for i386 7217 // strcpy( consoleInfo->v_pixelFormat, "PPPPPPPP"); 7218 getPlatform()->setConsoleInfo( &newConsole, kPEReleaseScreen ); 7219 getPlatform()->setConsoleInfo( &newConsole, kPEEnableScreen ); 7220 gIOFBConsoleFramebuffer = fb; 7221 DEBG1(fb->thisName, " now console\n"); 7222 } 7223} 7224 7225IOReturn IOFramebuffer::setupForCurrentConfig( void ) 7226{ 7227 TIMESTART(); 7228 if (__private->paramHandler) 7229 __private->paramHandler->displayModeChange(); 7230 TIMEEND(thisName, "paramHandler->displayModeChange time: %qd ms\n"); 7231 7232 return (doSetup(true)); 7233} 7234 7235OSData * IOFramebuffer::getConfigMode(IODisplayModeID mode, const OSSymbol * sym) 7236{ 7237 OSDictionary * dict; 7238 OSArray * array; 7239 OSNumber * num; 7240 unsigned int idx; 7241 7242 dict = OSDynamicCast(OSDictionary, getProperty(gIOFBConfigKey)); 7243 if (!dict) return (0); 7244 array = OSDynamicCast(OSArray, dict->getObject(gIOFBModesKey)); 7245 if (!array) return (0); 7246 for (idx = 0; (dict = OSDynamicCast(OSDictionary, array->getObject(idx))); idx++) 7247 { 7248 if (!(num = OSDynamicCast(OSNumber, dict->getObject(gIOFBModeIDKey)))) continue; 7249 if (num->unsigned32BitValue() == (UInt32) mode) break; 7250 } 7251 if (!dict) return (0); 7252 return (OSDynamicCast(OSData, dict->getObject(sym))); 7253} 7254 7255IOReturn IOFramebuffer::doSetup( bool full ) 7256{ 7257 StdFBShmem_t * shmem = GetShmem(this); 7258 IOReturn err; 7259 IODisplayModeID mode; 7260 IOIndex depth; 7261 IOMemoryDescriptor * mem; 7262 IOMemoryDescriptor * fbRange; 7263 OSData * data; 7264 IOPhysicalAddress64 base; 7265 uintptr_t value; 7266 bool haveFB = __private->online; 7267 7268 bzero(&__private->pixelInfo, sizeof(__private->pixelInfo)); 7269 if (haveFB) 7270 { 7271 err = getAttribute( kIOHardwareCursorAttribute, &value ); 7272 __private->cursorPanning = ((err == kIOReturnSuccess) && (0 != (kIOFBCursorPans & value))); 7273 7274 err = getCurrentDisplayMode( &mode, &depth ); 7275 if (kIOReturnSuccess == err) 7276 err = getPixelInformation( mode, depth, kIOFBSystemAperture, &__private->pixelInfo ); 7277 if (kIOReturnSuccess != err) 7278 bzero(&__private->pixelInfo, sizeof(__private->pixelInfo)); 7279 if (__private->pixelInfo.activeWidth < 128) 7280 haveFB = false; 7281 else if ((data = getConfigMode(mode, gIOFBModeDMKey))) 7282 { 7283 IODisplayModeInformation * info = (typeof(info)) data->getBytesNoCopy(); 7284 if (info->imageWidth) 7285 { 7286 if ((__private->pixelInfo.activeWidth >= 2048) 7287 && (__private->pixelInfo.activeHeight >= 1280) 7288 && (((254 * __private->pixelInfo.activeWidth) / info->imageWidth) > k2xDPI)) 7289 __private->uiScale = 2; 7290 else __private->uiScale = 1; 7291 } 7292 else __private->uiScale = 0; 7293 } 7294 } 7295 7296 __private->timingInfo.flags = kIODetailedTimingValid; 7297 if (haveFB 7298 && (kIOReturnSuccess == getTimingInfoForDisplayMode(mode, &__private->timingInfo))) 7299 { 7300 if (kIODetailedTimingValid & __private->timingInfo.flags) 7301 { 7302 uint64_t count = ((uint64_t)(__private->timingInfo.detailedInfo.v2.horizontalActive 7303 + __private->timingInfo.detailedInfo.v2.horizontalBlanking)); 7304 count *= ((uint64_t)(__private->timingInfo.detailedInfo.v2.verticalActive 7305 + __private->timingInfo.detailedInfo.v2.verticalBlanking)); 7306 if (kIOInterlacedCEATiming & __private->timingInfo.detailedInfo.v2.signalConfig) 7307 count >>= 1; 7308 7309 uint64_t clock = __private->timingInfo.detailedInfo.v2.pixelClock; 7310 uint64_t actual = __private->timingInfo.detailedInfo.v2.minPixelClock; 7311 7312 DEBG1(thisName, " minPixelClock %qd maxPixelClock %qd\n", 7313 __private->timingInfo.detailedInfo.v2.maxPixelClock, 7314 __private->timingInfo.detailedInfo.v2.minPixelClock); 7315 7316 if (actual != __private->timingInfo.detailedInfo.v2.maxPixelClock) 7317 actual = 0; 7318 bool throttleEnable = (gIOFBVBLThrottle && clock && actual && shmem); 7319 DEBG1(thisName, " vblthrottle(%d) clk %qd act %qd\n", throttleEnable, clock, actual); 7320 if (throttleEnable) 7321 clock = actual; 7322 setProperty(kIOFBCurrentPixelClockKey, clock, 64); 7323 setProperty(kIOFBCurrentPixelCountKey, count, 64); 7324 if (shmem && throttleEnable) 7325 { 7326 mach_timebase_info_data_t timebaseInfo; 7327 clock_timebase_info(&timebaseInfo); 7328 AbsoluteTime_to_scalar(&shmem->vblDelta) 7329 = (count * kSecondScale * timebaseInfo.numer / clock / timebaseInfo.denom); 7330 } 7331 __private->vblThrottle = throttleEnable; 7332 __private->setupMode = mode; 7333 } 7334 else 7335 { 7336 removeProperty(kIOFBCurrentPixelClockKey); 7337 removeProperty(kIOFBCurrentPixelCountKey); 7338 if (shmem && __private->vblThrottle) 7339 AbsoluteTime_to_scalar(&shmem->vblDelta) = 0; 7340 } 7341 7342 __private->scaledMode = false; 7343 if (kIOScalingInfoValid & __private->timingInfo.flags) 7344 { 7345 __private->scaledMode = 7346 (__private->timingInfo.detailedInfo.v2.scalerFlags 7347 || __private->timingInfo.detailedInfo.v2.horizontalScaledInset 7348 || __private->timingInfo.detailedInfo.v2.verticalScaledInset 7349 || (__private->timingInfo.detailedInfo.v2.horizontalScaled 7350 && (__private->timingInfo.detailedInfo.v2.horizontalScaled != __private->timingInfo.detailedInfo.v2.horizontalActive)) 7351 || (__private->timingInfo.detailedInfo.v2.verticalScaled 7352 && (__private->timingInfo.detailedInfo.v2.verticalScaled != __private->timingInfo.detailedInfo.v2.verticalActive))); 7353 } 7354 } 7355 else 7356 __private->timingInfo.flags = 0; 7357 7358 if (full) 7359 { 7360 frameBuffer = NULL; 7361 if ((fbRange = getApertureRange(kIOFBSystemAperture))) 7362 { 7363 userAccessRanges->removeObject( kIOFBSystemAperture ); 7364 userAccessRanges->setObject( kIOFBSystemAperture, fbRange ); 7365 err = setUserRanges(); 7366 7367 base = fbRange->getPhysicalSegment(0, 0, kIOMemoryMapperNone); 7368 if ((mem = getVRAMRange())) 7369 { 7370 vramMapOffset = base - mem->getPhysicalSegment(0, 0, kIOMemoryMapperNone); 7371 if (vramMapOffset > mem->getLength()) 7372 vramMapOffset &= (mem->getLength() - 1); 7373 setProperty( kIOFBMemorySizeKey, mem->getLength(), 32 ); 7374 mem->release(); 7375 } 7376 7377 IOMemoryMap * oldMap = vramMap; 7378 vramMap = fbRange->map( kIOFBMapCacheMode ); 7379 if (oldMap) 7380 oldMap->release(); 7381 assert( vramMap ); 7382 if (vramMap) 7383 { 7384 base = vramMap->getVirtualAddress(); 7385 frameBuffer = (volatile unsigned char *) base; 7386 } 7387 7388 DEBG1(thisName, " using (%dx%d,%d bpp)\n", 7389 (uint32_t) __private->pixelInfo.activeWidth, (uint32_t) __private->pixelInfo.activeHeight, 7390 (uint32_t) __private->pixelInfo.bitsPerPixel ); 7391 7392 if (fbRange) 7393 fbRange->release(); 7394 } 7395 } 7396 7397 if (full) 7398 { 7399 deliverDisplayModeDidChangeNotification(); 7400 7401 dpUpdateConnect(); 7402 } 7403 7404DEBG1(thisName, " doSetup vram %d, fb %d\n", vramMap != NULL, haveFB); 7405 if (haveFB) 7406 { 7407 if (__private->needsInit) initFB(); 7408 setupCursor(); 7409 } 7410 else 7411 { 7412 cursorBlitProc = (CursorBlitProc) NULL; 7413 cursorRemoveProc = (CursorRemoveProc) NULL; 7414 __private->framebufferWidth = 0; 7415 __private->framebufferHeight = 0; 7416 } 7417 7418 // reset console 7419 if (full && (haveFB || !gIOFBConsoleFramebuffer)) 7420 findConsole(); 7421 7422 return (kIOReturnSuccess); 7423} 7424 7425bool IOFramebuffer::suspend(bool now) 7426{ 7427 if (now == suspended) 7428 return (true); 7429 7430 if (now) 7431 { 7432 stopCursor(); 7433 checkDeferredCLUTSet(); 7434 if (this == gIOFBConsoleFramebuffer) 7435 { 7436 getPlatform()->setConsoleInfo( 0, kPEDisableScreen); 7437 gIOFBConsoleFramebuffer = 0; 7438 } 7439 deliverFramebufferNotification( kIOFBNotifyDisplayModeWillChange ); 7440 suspended = true; 7441 } 7442 else 7443 { 7444 TIMESTART(); 7445 setupForCurrentConfig(); 7446 TIMEEND(thisName, "exit suspend setupForCurrentConfig time: %qd ms\n"); 7447 7448 suspended = false; 7449 __private->modeUpdate = false; 7450 } 7451 7452 return (false); 7453} 7454 7455IOReturn IOFramebuffer::extSetDisplayMode( 7456 OSObject * target, void * reference, IOExternalMethodArguments * args) 7457{ 7458 IOFramebuffer * inst = (IOFramebuffer *) target; 7459 IODisplayModeID displayMode = args->scalarInput[0]; 7460 IOIndex depth = args->scalarInput[1]; 7461 IOReturn err; 7462 7463 err = inst->doSetDisplayMode(displayMode, depth); 7464 7465 return (err); 7466} 7467 7468IOReturn IOFramebuffer::doSetDisplayMode( 7469 IODisplayModeID displayMode, IOIndex depth) 7470{ 7471 IOReturn err; 7472 7473 DEBG1(thisName, " extSetDisplayMode(0x%x, %d) susp %d online %d\n", 7474 (int32_t) displayMode, (uint32_t) depth, suspended, 7475 __private->online); 7476 7477 if (kIODisplayModeIDAliasBase & displayMode) 7478 { 7479 // && (depth == __private->currentDepth)) 7480 7481 if ((err = extEntry(false))) 7482 return (err); 7483 7484 DEBG(thisName, " nop set mode\n"); 7485 __private->aliasMode = displayMode & ~kIODisplayModeIDAliasBase; 7486 __private->modeUpdate = false; 7487 extExit(err); 7488 7489 return (kIOReturnSuccess); 7490 } 7491 7492 if ((err = extEntrySys(false))) 7493 return (err); 7494 7495 if ((kIODisplayModeIDCurrent == displayMode) 7496 && __private->modeUpdate) 7497 { 7498 getCurrentDisplayMode(&displayMode, &depth); 7499 } 7500 7501 suspend(true); 7502 7503 if (kIODisplayModeIDCurrent != displayMode) 7504 { 7505 TIMESTART(); 7506 err = setDisplayMode( displayMode, depth ); 7507 TIMEEND(thisName, "setDisplayMode time: %qd ms\n"); 7508 __private->aliasMode = kIODisplayModeIDInvalid; 7509 __private->currentDepth = depth; 7510 } 7511 7512 suspend(false); 7513 7514 extExitSys(err); 7515 7516 return (err); 7517} 7518 7519IOReturn IOFramebuffer::checkMirrorSafe( UInt32 value, IOFramebuffer * other ) 7520{ 7521 IOReturn err = kIOReturnSuccess; 7522 IOFramebuffer * next = this; 7523 7524 while ((next = next->getNextDependent()) && (next != this)) 7525 { 7526 DEBG1(next->thisName, " transform 0x%llx \n", __private->transform); 7527 if (~kIOFBScalerUnderscan & (__private->transform ^ next->getTransform())) 7528 { 7529 err = kIOReturnUnsupported; 7530 break; 7531 } 7532 } 7533 7534 return (err); 7535} 7536 7537IOReturn IOFramebuffer::extSetMirrorOne(uint32_t value, IOFramebuffer * other) 7538{ 7539 IOReturn err; 7540 IOFramebuffer * next; 7541 uintptr_t data[2]; 7542 bool was; 7543 7544 if (value && __private->nextMirror) return (kIOReturnBusy); 7545 if (value && !other) return (kIOReturnBadArgument); 7546 if (!value && !__private->nextMirror) return (kIOReturnSuccess); 7547 if (!value && __private->nextMirror) 7548 { 7549 next = this; 7550 do 7551 { 7552 next->suspend(true); 7553 data[0] = value; 7554 data[1] = (uintptr_t) next->__private->nextMirror; 7555 DEBG1(next->thisName, " kIOMirrorAttribute(0)\n"); 7556 err = next->setAttribute(kIOMirrorAttribute, (uintptr_t) &data); 7557 DEBG1(next->thisName, " kIOMirrorAttribute(%d) ret 0x%x\n", value, err); 7558 } 7559 while ((next = next->__private->nextMirror) && (next != this)); 7560 7561 next = this; 7562 do 7563 { 7564 IOFramebuffer * prev; 7565 prev = next; 7566 next = next->__private->nextMirror; 7567 prev->__private->nextMirror = 0; 7568 prev->suspend(false); 7569 } 7570 while (next && (next != this)); 7571 7572 return (kIOReturnSuccess); 7573 } 7574 7575 was = suspend(true); 7576 data[0] = value; 7577 data[1] = (uintptr_t) other; 7578 err = setAttribute(kIOMirrorAttribute, (uintptr_t) &data); 7579 DEBG1(thisName, " kIOMirrorAttribute(%d) ret 0x%x\n", value, err); 7580 if (kIOReturnSuccess != err) 7581 { 7582 if (!was) suspend(false); 7583 } 7584 else 7585 { 7586 __private->nextMirror = other; 7587 if (other->__private->nextMirror) 7588 { 7589 next = other; 7590 do next->suspend(false); 7591 while ((next = next->__private->nextMirror) && (next != other)); 7592 } 7593 } 7594 return (err); 7595} 7596 7597IOReturn IOFramebuffer::extSetAttribute( 7598 OSObject * target, void * reference, IOExternalMethodArguments * args) 7599{ 7600 IOFramebuffer * inst = (IOFramebuffer *) target; 7601 IOSelect attribute = args->scalarInput[0]; 7602 uint32_t value = args->scalarInput[1]; 7603 IOFramebuffer * other = (IOFramebuffer *) reference; 7604 7605 IOReturn err; 7606 7607 if ((err = inst->extEntry(false))) 7608 return (err); 7609 7610 switch (attribute) 7611 { 7612 case kIOMirrorAttribute: 7613 7614 DEBG1(inst->thisName, " kIOMirrorAttribute(%d) susp(%d), curr(%d)\n", 7615 value, inst->suspended, (inst->__private->nextMirror != 0)); 7616 value = (value != 0); 7617 if (value) 7618 { 7619 err = inst->checkMirrorSafe(value, other); 7620 if (kIOReturnSuccess != err) 7621 break; 7622 } 7623 err = inst->extSetMirrorOne(value, other); 7624 break; 7625 7626 default: 7627 err = inst->setAttribute( attribute, value ); 7628 break; 7629 } 7630 7631 inst->extExit(err); 7632 7633 return (err); 7634} 7635 7636IOReturn IOFramebuffer::extGetAttribute( 7637 OSObject * target, void * reference, IOExternalMethodArguments * args) 7638{ 7639 IOFramebuffer * inst = (IOFramebuffer *) target; 7640 IOSelect attribute = args->scalarInput[0]; 7641 uint64_t * value = &args->scalarOutput[0]; 7642 IOFramebuffer * other = (IOFramebuffer *) reference; 7643 7644 IOReturn err = kIOReturnSuccess; 7645 7646 *value = 0; 7647 7648 switch (attribute) 7649 { 7650 case kIOFBProcessConnectChangeAttribute: 7651 err = inst->extProcessConnectionChange(); 7652 break; 7653 7654 case kIOFBEndConnectChangeAttribute: 7655 if ((err = inst->extEntrySys(true))) 7656 return (err); 7657 err = inst->extEndConnectionChange(); 7658 inst->extExitSys(err); 7659 break; 7660 7661 case kIOFBWSStartAttribute: 7662 if ((err = inst->extEntrySys(true))) 7663 return (err); 7664 if (inst->__private->controller->wsWait) 7665 { 7666 DEBG1(inst->thisName, " kIOFBWSStartAttribute wsWait %d\n", inst->__private->controller->wsWait); 7667 inst->__private->controller->wsWait &= ~(1 << inst->__private->controllerIndex); 7668 if (!inst->__private->controller->wsWait) 7669 { 7670 DEBG1(inst->thisName, " wsWait done remsg %d\n", inst->messaged); 7671 if (inst->messaged) 7672 { 7673 inst->messageClients(kIOMessageServiceIsSuspended, (void *) true); 7674 } 7675 resetClamshell(kIOFBClamshellProbeDelayMS); 7676 startControllerThread(inst->__private->controller); 7677 } 7678 } 7679 inst->extExitSys(err); 7680 break; 7681 7682 default: 7683 7684 if ((err = inst->extEntry(false))) 7685 return (err); 7686 7687 uintptr_t result = (uintptr_t) other; 7688 err = inst->getAttribute( attribute, &result ); 7689 *value = (UInt32) result; 7690 7691 inst->extExit(err); 7692 break; 7693 } 7694 7695 7696 return (err); 7697} 7698 7699IOReturn IOFramebuffer::extGetInformationForDisplayMode( 7700 OSObject * target, void * reference, IOExternalMethodArguments * args) 7701{ 7702 IOFramebuffer * inst = (IOFramebuffer *) target; 7703 IODisplayModeID mode = args->scalarInput[0]; 7704 void * info = args->structureOutput; 7705 IOByteCount length = args->structureOutputSize; 7706 7707 UInt32 flags = 0; 7708 IOReturn err; 7709 bool getTiming; 7710 IOFBDisplayModeDescription * out = (IOFBDisplayModeDescription *) info; 7711 7712 if (length < sizeof(IODisplayModeInformation)) 7713 return (kIOReturnBadArgument); 7714 7715 if ((err = inst->extEntry(false))) 7716 return (err); 7717 7718 err = inst->getInformationForDisplayMode( mode, &out->info ); 7719 if (kIOReturnSuccess == err) 7720 { 7721 err = IODisplayWrangler::getFlagsForDisplayMode( inst, mode, &flags); 7722 if (kIOReturnSuccess == err) 7723 { 7724 out->info.flags &= ~kDisplayModeSafetyFlags; 7725 out->info.flags |= flags; 7726 } 7727 getTiming = (length >= sizeof(IOFBDisplayModeDescription)); 7728 out->timingInfo.flags = getTiming ? kIODetailedTimingValid : 0; 7729 if (kIOReturnSuccess != inst->getTimingInfoForDisplayMode(mode, &out->timingInfo)) 7730 { 7731 out->timingInfo.flags &= ~kIODetailedTimingValid; 7732 out->timingInfo.appleTimingID = 0; 7733 } 7734 } 7735 7736 inst->extExit(err); 7737 7738 return (err); 7739} 7740 7741IOReturn IOFramebuffer::setDisplayAttributes(OSObject * obj) 7742{ 7743 IOReturn r, ret = kIOReturnSuccess; 7744 OSData * data; 7745 OSDictionary * dict; 7746 uint32_t * attributes; 7747 uint32_t idx, max; 7748 uint32_t attr, attrValue, value, mask; 7749 uint32_t controllerDepths, ditherMask = 0; 7750 uintptr_t lvalue[16]; 7751 bool found = false; 7752 bool skip = false; 7753 bool updatesMode = false; 7754 7755 if (!obj) return (kIOReturnSuccess); 7756 7757 obj->retain(); 7758 if (__private->displayAttributes) __private->displayAttributes->release(); 7759 __private->displayAttributes = obj; 7760 7761 if (__private->display) __private->display->setProperty(kIODisplayAttributesKey, obj); 7762 7763 dict = OSDynamicCast(OSDictionary, obj); 7764 data = dict ? OSDynamicCast(OSData, dict->getObject(kIODisplayAttributesKey)) 7765 : OSDynamicCast(OSData, obj); 7766 7767 if (!data) return (kIOReturnSuccess); 7768 7769 attributes = (uint32_t *) data->getBytesNoCopy(); 7770 max = data->getLength() / sizeof(attributes[0]); 7771 7772 for (idx = 0; idx < max; idx += 2) 7773 { 7774 attr = attributes[idx]; 7775 attrValue = attributes[idx + 1]; 7776 7777 if (kConnectionVendorTag == attr) 7778 { 7779 if (found) 7780 break; 7781 skip = (attrValue && (attrValue != __private->controller->vendorID)); 7782 found = !skip; 7783 continue; 7784 } 7785 if (skip) 7786 continue; 7787 7788 DEBG1(thisName, " (0x%08x '%c%c%c%c')(%x)\n", attr, FEAT(attr), attrValue); 7789 7790 updatesMode = false; 7791 switch (attr) 7792 { 7793 case kConnectionColorModesSupported: 7794 attrValue |= kIODisplayColorModeAuto; 7795 attrValue |= kIODisplayColorModeRGBLimited; 7796 __private->colorModesSupported = attrValue; 7797 break; 7798 7799 case kConnectionColorDepthsSupported: 7800 7801 r = getAttributeForConnection(0, kConnectionControllerDepthsSupported, &lvalue[0]); 7802 if (kIOReturnSuccess != r) 7803 { 7804 lvalue[0] = kIODisplayRGBColorComponentBits6 7805 | kIODisplayRGBColorComponentBits8; 7806 if (10 == __private->desiredGammaDataWidth) 7807 lvalue[0] |= kIODisplayRGBColorComponentBits10; 7808 } 7809 7810 controllerDepths = lvalue[0]; 7811 7812#define COLRMASK(n) ((n ## 16) | (n ## 14) | (n ## 12) | (n ## 10) | (n ## 8) | (n ## 6)) 7813#define HIGHBIT(v) (1 << (31 - __builtin_clz(v))) 7814 7815 value = controllerDepths & attrValue; 7816 if (!value) 7817 value = kIODisplayRGBColorComponentBits8; 7818 7819 mask = COLRMASK(kIODisplayRGBColorComponentBits); 7820 if (value & mask) 7821 { 7822 value = (value & ~mask) | HIGHBIT(value & mask); 7823 if (!(value & HIGHBIT(controllerDepths & mask))) 7824 ditherMask |= (kIODisplayDitherAll << kIODisplayDitherRGBShift); 7825 } 7826 7827 mask = COLRMASK(kIODisplayYCbCr444ColorComponentBits); 7828 if (value & mask) 7829 { 7830 value = (value & ~mask) | HIGHBIT(value & mask); 7831 if (!(value & HIGHBIT(controllerDepths & mask))) 7832 ditherMask |= (kIODisplayDitherAll << kIODisplayDitherYCbCr444Shift); 7833 } 7834 7835 mask = COLRMASK(kIODisplayYCbCr422ColorComponentBits); 7836 if (value & mask) 7837 { 7838 value = (value & ~mask) | HIGHBIT(value & mask); 7839 if (!(value & HIGHBIT(controllerDepths & mask))) 7840 ditherMask |= (kIODisplayDitherAll << kIODisplayDitherYCbCr422Shift); 7841 } 7842 7843 // pass thru kConnectionColorDepthsSupported 7844 DEBG1(thisName, " (0x%08x '%c%c%c%c')(%x)\n", attr, FEAT(attr), attrValue); 7845 r = setAttributeForConnection(0, attr, attrValue); 7846 if (kIOReturnSuccess != r) 7847 ret = r; 7848 7849 attr = kConnectionControllerColorDepth; 7850 attrValue = value; 7851 updatesMode = true; 7852 break; 7853 7854 case kConnectionControllerDitherControl: 7855 7856 attrValue &= ditherMask; 7857 updatesMode = true; 7858 break; 7859 } 7860 7861 DEBG1(thisName, " (0x%08x '%c%c%c%c')(%x)\n", attr, FEAT(attr), attrValue); 7862 7863 if (updatesMode) 7864 { 7865 r = getAttributeForConnection(0, attr, &lvalue[0]); 7866 if (kIOReturnSuccess != r) 7867 continue; 7868 if (lvalue[0] == attrValue) 7869 continue; 7870 } 7871 r = setAttributeForConnection(0, attr, attrValue); 7872 if (kIOReturnSuccess == r) 7873 __private->modeUpdate |= updatesMode; 7874 else 7875 ret = r; 7876 } 7877 7878 return (ret); 7879} 7880 7881IOReturn IOFramebuffer::extSetProperties( OSDictionary * props ) 7882{ 7883 OSDictionary * dict; 7884 OSArray * array; 7885 IOReturn err = kIOReturnUnsupported; 7886 7887 if ((err = extEntry(true))) 7888 return (err); 7889 7890 err = kIOReturnUnsupported; 7891 if ((dict = OSDynamicCast(OSDictionary, props->getObject(gIOFBConfigKey)))) do 7892 { 7893 setProperty( gIOFBConfigKey, dict ); 7894 if (!__private->online) 7895 { 7896 err = kIOReturnSuccess; 7897 break; 7898 } 7899 if (dict->getObject("IOFBScalerUnderscan")) 7900 { 7901 __private->enableScalerUnderscan = true; 7902 } 7903 if ((array = OSDynamicCast(OSArray, 7904 dict->getObject(kIOFBDetailedTimingsKey)))) 7905 err = setDetailedTimings( array ); 7906 else 7907 err = kIOReturnSuccess; 7908 } 7909 while (false); 7910 7911 setDisplayAttributes(props->getObject(kIODisplayAttributesKey)); 7912 7913 extExit(err); 7914 7915 return (err); 7916} 7917 7918//// Controller attributes 7919 7920IOReturn IOFramebuffer::setAttribute( IOSelect attribute, uintptr_t value ) 7921{ 7922 IOReturn ret; 7923 7924 switch (attribute) 7925 { 7926 case kIOCapturedAttribute: 7927 { 7928 DEBG(thisName, " kIOCapturedAttribute(%ld)\n", value); 7929 if (value != gIOFBCaptureState) 7930 { 7931 gIOFBCaptureState = value; 7932 OSBitOrAtomic(kIOFBEventCaptureSetting, &gIOFBGlobalEvents); 7933 controllerDidWork(__private->controller, kWorkStateChange); 7934 } 7935 ret = kIOReturnSuccess; 7936 break; 7937 } 7938 7939 case kIOCursorControlAttribute: 7940 { 7941 IOFBCursorControlAttribute * crsrControl; 7942 7943 crsrControl = (IOFBCursorControlAttribute *) value; 7944 7945 if (__private->cursorThread) 7946 { 7947 __private->cursorThread->release(); 7948 __private->cursorThread = 0; 7949 } 7950 7951 if (crsrControl && crsrControl->callouts) 7952 { 7953 __private->cursorControl = *((IOFBCursorControlAttribute *) value); 7954 __private->cursorThread = IOInterruptEventSource::interruptEventSource(this, &cursorWork); 7955 if (__private->controller->wl && __private->cursorThread) 7956 __private->controller->wl->addEventSource(__private->cursorThread); 7957 } 7958 ret = kIOReturnSuccess; 7959 break; 7960 } 7961 7962 case kIOPowerStateAttribute: 7963 ret = setAttribute(kIOPowerAttribute, value); 7964 break; 7965 7966 case kIOPowerAttribute: 7967 ret = setAttributeExt(attribute, value); 7968 break; 7969 7970 default: 7971 ret = kIOReturnUnsupported; 7972 break; 7973 } 7974 7975 return (ret); 7976} 7977 7978/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 7979 7980#if __ppc__ 7981static IOReturn 7982ApplePMUSendMiscCommand( UInt32 command, 7983 IOByteCount sendLength, UInt8 * sendBuffer, 7984 IOByteCount * readLength, UInt8 * readBuffer ) 7985{ 7986 struct SendMiscCommandParameterBlock 7987 { 7988 int command; 7989 IOByteCount sLength; 7990 UInt8 *sBuffer; 7991 IOByteCount *rLength; 7992 UInt8 *rBuffer; 7993 }; 7994 IOReturn ret = kIOReturnError; 7995 static IOService * pmu; 7996 7997 // See if ApplePMU exists 7998 if (!pmu) 7999 { 8000 OSIterator * iter; 8001 iter = IOService::getMatchingServices(IOService::serviceMatching("ApplePMU")); 8002 if (iter) 8003 { 8004 pmu = (IOService *) iter->getNextObject(); 8005 iter->release(); 8006 } 8007 } 8008 8009 SendMiscCommandParameterBlock params = { command, sendLength, sendBuffer, 8010 readLength, readBuffer }; 8011 if (pmu) 8012 ret = pmu->callPlatformFunction( "sendMiscCommand", true, 8013 (void*)¶ms, NULL, NULL, NULL ); 8014 return (ret); 8015} 8016#endif 8017 8018/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 8019 8020void IOFramebuffer::readClamshellState() 8021{ 8022 // zero -> lid open 8023 8024#if __ppc__ 8025 8026#define readExtSwitches 0xDC 8027 8028 UInt8 bootEnvIntData[32]; 8029 IOByteCount iLen = sizeof(UInt8); 8030 8031 ret = ApplePMUSendMiscCommand(readExtSwitches, 0, NULL, &iLen, &bootEnvIntData[0]); 8032 if (kIOReturnSuccess == ret) 8033 { 8034 gIOFBLastClamshellState = bootEnvIntData[0]; 8035 } 8036 8037#elif defined(__i386__) || defined(__x86_64__) 8038 static IOACPIPlatformDevice * lidDevice; 8039 UInt32 lidState; 8040 8041 if (!lidDevice) 8042 { 8043 OSIterator * iter; 8044 IOService * service; 8045 OSDictionary * matching; 8046 8047 matching = IOService::nameMatching("PNP0C0D"); 8048 iter = IOService::getMatchingServices(matching); 8049 if (matching) matching->release(); 8050 if (iter) 8051 { 8052 service = (IOService *)iter->getNextObject(); 8053 if (service->metaCast("IOACPIPlatformDevice")) 8054 { 8055 lidDevice = (IOACPIPlatformDevice *) service; 8056 lidDevice->retain(); 8057 } 8058 iter->release(); 8059 } 8060 } 8061 8062 if (lidDevice) 8063 { 8064 IOReturn ret; 8065 ret = lidDevice->evaluateInteger("_LID", &lidState); 8066 if (kIOReturnSuccess == ret) 8067 gIOFBLastClamshellState = (lidState == 0); 8068 } 8069#endif 8070 8071 DEBG1("S", " %d\n", (int) gIOFBLastClamshellState); 8072} 8073 8074extern "C" IOReturn 8075IOGetHardwareClamshellState( IOOptionBits * result ) 8076{ 8077 // zero -> lid open 8078 if (gIOFBDesktopModeAllowed) 8079 *result = gIOFBLastClamshellState; 8080 else 8081 *result = 0; 8082 8083// gIOFBLastReadClamshellState = gIOFBLastClamshellState; 8084 8085 DEBG1("S", " %d\n", (int) *result); 8086 8087 return (kIOReturnSuccess); 8088} 8089 8090/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 8091 8092bool IOFramebuffer::clamshellHandler(void * target, void * ref, 8093 IOService * resourceService, IONotifier * notifier) 8094{ 8095 gIOResourcesAppleClamshellState = resourceService->getProperty(kAppleClamshellStateKey); 8096 resourceService->removeProperty(kAppleClamshellStateKey); 8097 OSBitOrAtomic(kIOFBEventReadClamshell, &gIOFBGlobalEvents); 8098 startThread(false); 8099 return (true); 8100} 8101 8102/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 8103 8104IOReturn IOFramebuffer::getAttribute( IOSelect attribute, uintptr_t * value ) 8105{ 8106 IOReturn ret = kIOReturnUnsupported; 8107 8108 switch (attribute) 8109 { 8110 case kIOClamshellStateAttribute: 8111 IOOptionBits result; 8112 ret = IOGetHardwareClamshellState( &result ); 8113 *value = result; 8114 break; 8115 8116 default: 8117 break; 8118 } 8119 8120 return (ret); 8121} 8122 8123/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 8124 8125bool IOFramebuffer::setNumber( OSDictionary * dict, const char * key, 8126 UInt32 value ) 8127{ 8128 OSNumber * num; 8129 bool ok; 8130 8131 num = OSNumber::withNumber( value, 32 ); 8132 if (!num) 8133 return (false); 8134 8135 ok = dict->setObject( key, num ); 8136 num->release(); 8137 8138 return (ok); 8139} 8140 8141bool IOFramebuffer::serializeInfo( OSSerialize * s ) 8142{ 8143 IOReturn err; 8144 IODisplayModeInformation info; 8145 IOPixelInformation pixelInfo; 8146 IODisplayModeID * modeIDs; 8147 IOItemCount modeCount, modeNum, aperture; 8148 IOIndex depthNum; 8149 OSDictionary * infoDict; 8150 OSDictionary * modeDict; 8151 OSDictionary * pixelDict; 8152 char keyBuf[12]; 8153 bool ok = true; 8154 8155 modeCount = getDisplayModeCount(); 8156 modeIDs = IONew( IODisplayModeID, modeCount ); 8157 if (!modeIDs) 8158 return (false); 8159 8160 err = getDisplayModes( modeIDs ); 8161 if (err) 8162 return (false); 8163 8164 infoDict = OSDictionary::withCapacity( 10 ); 8165 if (!infoDict) 8166 return (false); 8167 8168 for (modeNum = 0; modeNum < modeCount; modeNum++) 8169 { 8170 err = getInformationForDisplayMode( modeIDs[modeNum], &info ); 8171 if (err) 8172 continue; 8173 8174 modeDict = OSDictionary::withCapacity( 10 ); 8175 if (!modeDict) 8176 break; 8177 8178 ok = setNumber( modeDict, kIOFBWidthKey, 8179 info.nominalWidth ) 8180 && setNumber( modeDict, kIOFBHeightKey, 8181 info.nominalHeight ) 8182 && setNumber( modeDict, kIOFBRefreshRateKey, 8183 info.refreshRate ) 8184 && setNumber( modeDict, kIOFBFlagsKey, 8185 info.flags ); 8186 if (!ok) 8187 break; 8188 8189 for (depthNum = 0; depthNum < info.maxDepthIndex; depthNum++) 8190 { 8191 for (aperture = 0; ; aperture++) 8192 { 8193 err = getPixelInformation( modeIDs[modeNum], depthNum, 8194 aperture, &pixelInfo ); 8195 if (err) 8196 break; 8197 8198 pixelDict = OSDictionary::withCapacity( 10 ); 8199 if (!pixelDict) 8200 continue; 8201 8202 ok = setNumber( pixelDict, kIOFBBytesPerRowKey, 8203 pixelInfo.bytesPerRow ) 8204 && setNumber( pixelDict, kIOFBBytesPerPlaneKey, 8205 pixelInfo.bytesPerPlane ) 8206 && setNumber( pixelDict, kIOFBBitsPerPixelKey, 8207 pixelInfo.bitsPerPixel ) 8208 && setNumber( pixelDict, kIOFBComponentCountKey, 8209 pixelInfo.componentCount ) 8210 && setNumber( pixelDict, kIOFBBitsPerComponentKey, 8211 pixelInfo.bitsPerComponent ) 8212 && setNumber( pixelDict, kIOFBFlagsKey, 8213 pixelInfo.flags ) 8214 && setNumber( pixelDict, kIOFBWidthKey, 8215 pixelInfo.activeWidth ) 8216 && setNumber( pixelDict, kIOFBHeightKey, 8217 pixelInfo.activeHeight ); 8218 if (!ok) 8219 break; 8220 8221 snprintf(keyBuf, sizeof(keyBuf), "%x", (int) (depthNum + (aperture << 16))); 8222 modeDict->setObject( keyBuf, pixelDict ); 8223 pixelDict->release(); 8224 } 8225 } 8226 8227 snprintf(keyBuf, sizeof(keyBuf), "%x", (int) modeIDs[modeNum]); 8228 infoDict->setObject( keyBuf, modeDict ); 8229 modeDict->release(); 8230 } 8231 8232 IODelete( modeIDs, IODisplayModeID, modeCount ); 8233 8234 ok &= infoDict->serialize( s ); 8235 infoDict->release(); 8236 8237 return (ok); 8238} 8239 8240/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 8241 8242OSDefineMetaClassAndStructors(_IOFramebufferNotifier, IONotifier) 8243#define LOCKNOTIFY() 8244#define UNLOCKNOTIFY() 8245 8246void _IOFramebufferNotifier::remove() 8247{ 8248 LOCKNOTIFY(); 8249 8250 if (whence) 8251 { 8252 whence->removeObject( (OSObject *) this ); 8253 whence = 0; 8254 } 8255 8256 fEnable = false; 8257 8258 UNLOCKNOTIFY(); 8259 8260 release(); 8261} 8262 8263bool _IOFramebufferNotifier::disable() 8264{ 8265 bool ret; 8266 8267 LOCKNOTIFY(); 8268 ret = fEnable; 8269 fEnable = false; 8270 UNLOCKNOTIFY(); 8271 8272 return (ret); 8273} 8274 8275void _IOFramebufferNotifier::enable( bool was ) 8276{ 8277 LOCKNOTIFY(); 8278 fEnable = was; 8279 UNLOCKNOTIFY(); 8280} 8281 8282IONotifier * IOFramebuffer::addFramebufferNotification( 8283 IOFramebufferNotificationHandler handler, 8284 OSObject * self, void * ref) 8285{ 8286 _IOFramebufferNotifier * notify = 0; 8287 8288 notify = new _IOFramebufferNotifier; 8289 if (notify && !notify->init()) 8290 { 8291 notify->release(); 8292 notify = 0; 8293 } 8294 8295 if (notify) 8296 { 8297 notify->handler = handler; 8298 notify->self = self; 8299 notify->ref = ref; 8300 notify->fEnable = true; 8301 8302 if (__private && __private->controller) 8303 FBLOCK(this); 8304 else 8305 SYSLOCK(); 8306 if (0 == fbNotifications) 8307 fbNotifications = OSSet::withCapacity(1); 8308 8309 notify->whence = fbNotifications; 8310 if (fbNotifications) 8311 fbNotifications->setObject( notify ); 8312 if (__private && __private->controller) 8313 FBUNLOCK(this); 8314 else 8315 SYSUNLOCK(); 8316 } 8317 8318 return (notify); 8319} 8320 8321IOReturn IOFramebuffer::deliverFramebufferNotification( 8322 IOIndex event, void * info ) 8323{ 8324 OSIterator * iter; 8325 _IOFramebufferNotifier * notify; 8326 IOReturn ret = kIOReturnSuccess; 8327 IOReturn r; 8328 8329#if RLOG1 8330 const char * name = NULL; 8331 switch (event) 8332 { 8333 case kIOFBNotifyDisplayModeWillChange: 8334 name = "kIOFBNotifyDisplayModeWillChange"; 8335 break; 8336 case kIOFBNotifyDisplayModeDidChange: 8337 name = "kIOFBNotifyDisplayModeDidChange"; 8338 break; 8339 case kIOFBNotifyWillSleep: 8340 name = "kIOFBNotifyWillSleep"; 8341 break; 8342 case kIOFBNotifyDidWake: 8343 name = "kIOFBNotifyDidWake"; 8344 break; 8345 case kIOFBNotifyDidPowerOff: 8346 name = "kIOFBNotifyDidPowerOff"; 8347 break; 8348 case kIOFBNotifyWillPowerOn: 8349 name = "kIOFBNotifyWillPowerOn"; 8350 break; 8351 case kIOFBNotifyWillPowerOff: 8352 name = "kIOFBNotifyWillPowerOff"; 8353 break; 8354 case kIOFBNotifyDidPowerOn: 8355 name = "kIOFBNotifyDidPowerOn"; 8356 break; 8357#if 0 8358 case kIOFBNotifyWillChangeSpeed: 8359 name = "kIOFBNotifyWillChangeSpeed"; 8360 break; 8361 case kIOFBNotifyDidChangeSpeed: 8362 name = "kIOFBNotifyDidChangeSpeed"; 8363 break; 8364 case kIOFBNotifyDisplayDimsChange: 8365 name = "kIOFBNotifyDisplayDimsChange"; 8366 break; 8367#endif 8368 case kIOFBNotifyClamshellChange: 8369 name = "kIOFBNotifyClamshellChange"; 8370 break; 8371 case kIOFBNotifyCaptureChange: 8372 name = "kIOFBNotifyCaptureChange"; 8373 break; 8374 case kIOFBNotifyOnlineChange: 8375 name = "kIOFBNotifyOnlineChange"; 8376 break; 8377 } 8378#endif 8379 8380 LOCKNOTIFY(); 8381 8382#if RLOG1 8383 AbsoluteTime startTime, endTime; 8384 uint64_t nsec; 8385 AbsoluteTime_to_scalar(&startTime) = mach_absolute_time(); 8386#endif 8387 8388 iter = OSCollectionIterator::withCollection( fbNotifications ); 8389 8390 if (iter) 8391 { 8392 while ((notify = (_IOFramebufferNotifier *) iter->getNextObject())) 8393 { 8394 if (notify->fEnable) 8395 { 8396 r = (*notify->handler)( notify->self, notify->ref, this, 8397 event, info ); 8398 if (kIOReturnSuccess != r) 8399 ret = r; 8400 } 8401 } 8402 iter->release(); 8403 } 8404 8405#if RLOG1 8406 AbsoluteTime_to_scalar(&endTime) = mach_absolute_time(); 8407 SUB_ABSOLUTETIME(&endTime, &startTime); 8408 absolutetime_to_nanoseconds(endTime, &nsec); 8409 8410 bool notGated = (!gIOFBSystemWorkLoop->inGate() || !FBWL(this)->inGate()); 8411 8412 if (name || notGated) 8413 { 8414 DEBG1(thisName, " %s(%s(%d), %p) %qd ms\n", 8415 notGated ? "not gated " : "", 8416 name ? name : "", (uint32_t) event, info, 8417 nsec / 1000000ULL); 8418 } 8419#endif 8420 8421 UNLOCKNOTIFY(); 8422 8423 return (ret); 8424} 8425 8426/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 8427 8428// Some stubs 8429 8430IOReturn IOFramebuffer::enableController ( void ) 8431{ 8432 return (kIOReturnSuccess); 8433} 8434 8435bool IOFramebuffer::isConsoleDevice( void ) 8436{ 8437 return (false); 8438} 8439 8440// Set display mode and depth 8441IOReturn IOFramebuffer::setDisplayMode( IODisplayModeID /* displayMode */, 8442 IOIndex /* depth */ ) 8443{ 8444 return (kIOReturnUnsupported); 8445} 8446 8447// For pages 8448IOReturn IOFramebuffer::setApertureEnable( 8449 IOPixelAperture /* aperture */, IOOptionBits /* enable */ ) 8450{ 8451 return (kIOReturnUnsupported); 8452} 8453 8454// Display mode and depth for startup 8455IOReturn IOFramebuffer::setStartupDisplayMode( 8456 IODisplayModeID /* displayMode */, IOIndex /* depth */ ) 8457{ 8458 return (kIOReturnUnsupported); 8459} 8460 8461IOReturn IOFramebuffer::getStartupDisplayMode( 8462 IODisplayModeID * /* displayMode */, IOIndex * /* depth */ ) 8463{ 8464 return (kIOReturnUnsupported); 8465} 8466 8467//// CLUTs 8468 8469IOReturn IOFramebuffer::setCLUTWithEntries( 8470 IOColorEntry * /* colors */, UInt32 /* index */, 8471 UInt32 /* numEntries */, IOOptionBits /* options */ ) 8472{ 8473 return (kIOReturnUnsupported); 8474} 8475 8476//// Gamma 8477 8478IOReturn IOFramebuffer::setGammaTable( UInt32 /* channelCount */, 8479 UInt32 /* dataCount */, UInt32 /* dataWidth */, void * /* data */ ) 8480{ 8481 return (kIOReturnUnsupported); 8482} 8483 8484 8485//// Display mode timing information 8486 8487IOReturn IOFramebuffer::getTimingInfoForDisplayMode( 8488 IODisplayModeID /* displayMode */, 8489 IOTimingInformation * /* info */ ) 8490{ 8491 return (kIOReturnUnsupported); 8492} 8493 8494IOReturn IOFramebuffer::validateDetailedTiming( 8495 void * description, IOByteCount descripSize ) 8496{ 8497 return (kIOReturnUnsupported); 8498} 8499 8500IOReturn IOFramebuffer::setDetailedTimings( OSArray * array ) 8501{ 8502 return (kIOReturnUnsupported); 8503} 8504 8505//// Connections 8506 8507IOItemCount IOFramebuffer::getConnectionCount( void ) 8508{ 8509 return (1); 8510} 8511 8512/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 8513 8514IOReturn IOFramebuffer::setAttributeExt( IOSelect attribute, uintptr_t value ) 8515{ 8516 IOReturn err; 8517 8518 FBLOCK(this); 8519 8520 switch (attribute) 8521 { 8522 case kIOPowerAttribute: 8523 8524 DEBG1(thisName, " mux power change %d->%ld, gated %d, thread %d\n", 8525 pendingPowerState, value, 8526 gIOFBSystemWorkLoop->inGate(), gIOFBSystemWorkLoop->onThread()); 8527 8528 if (value != pendingPowerState) 8529 { 8530 pendingPowerState = value; 8531 if (!__private->controllerIndex) 8532 { 8533 __private->controller->pendingMuxPowerChange = true; 8534 startControllerThread(__private->controller); 8535 } 8536 } 8537 err = kIOReturnSuccess; 8538 break; 8539 8540 default: 8541 err = setAttribute(attribute, value); 8542 break; 8543 } 8544 8545 FBUNLOCK(this); 8546 return (err); 8547} 8548 8549IOReturn IOFramebuffer::getAttributeExt( IOSelect attribute, uintptr_t * value ) 8550{ 8551 IOReturn err; 8552 8553 FBLOCK(this); 8554 err = getAttribute(attribute, value); 8555 switch (attribute) 8556 { 8557 case kIOMirrorAttribute: 8558 if (kIOReturnSuccess != err) *value = 0; 8559 if (__private->nextMirror) *value |= kIOMirrorIsMirrored; 8560 err = kIOReturnSuccess; 8561 break; 8562 8563 default: 8564 break; 8565 } 8566 FBUNLOCK(this); 8567 return (err); 8568} 8569 8570IOReturn IOFramebuffer::setAttributeForConnectionExt( IOIndex connectIndex, 8571 IOSelect attribute, uintptr_t value ) 8572{ 8573 IOReturn err; 8574 8575 if (opened) 8576 FBLOCK(this); 8577 else 8578 return (kIOReturnNotReady); 8579 8580 if ('\0igr' == attribute) 8581 { 8582 DEBG1(thisName, " 0igr ->0x%lx, gated %d, thread %d\n", value, 8583 gIOFBSystemWorkLoop->inGate(), gIOFBSystemWorkLoop->onThread()); 8584 __private->controller->mute = (0 != (value & (1 << 31))); 8585 } 8586 8587 err = setAttributeForConnection(connectIndex, attribute, value); 8588 8589 if (opened) 8590 FBUNLOCK(this); 8591 8592 return (err); 8593} 8594 8595IOReturn IOFramebuffer::getAttributeForConnectionExt( IOIndex connectIndex, 8596 IOSelect attribute, uintptr_t * value ) 8597{ 8598 IOReturn err; 8599 8600 FBLOCK(this); 8601 err = getAttributeForConnection(connectIndex, attribute, value); 8602 FBUNLOCK(this); 8603 8604 return (err); 8605} 8606 8607/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 8608 8609IOReturn IOFramebuffer::getAttributeForConnectionParam( IOIndex connectIndex, 8610 IOSelect attribute, uintptr_t * value ) 8611{ 8612 IOReturn err; 8613 8614 if (!__private->colorModesAllowed) 8615 { 8616 if (kConnectionColorMode == attribute) 8617 return (kIOReturnUnsupported); 8618 if (kConnectionColorModesSupported == attribute) 8619 return (kIOReturnUnsupported); 8620 } 8621 8622 err = getAttributeForConnection(connectIndex, attribute, value); 8623 8624 return (err); 8625} 8626 8627IOReturn IOFramebuffer::setAttributeForConnectionParam( IOIndex connectIndex, 8628 IOSelect attribute, uintptr_t value ) 8629{ 8630 IOReturn err; 8631 8632 err = setAttributeForConnection(connectIndex, attribute, value); 8633 8634 return (err); 8635} 8636 8637/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 8638 8639IOReturn IOFramebuffer::setAttributeForConnection( IOIndex connectIndex, 8640 IOSelect attribute, uintptr_t info ) 8641{ 8642 IOReturn err; 8643 8644 switch( attribute ) 8645 { 8646 case kConnectionRedGammaScale: 8647 if (info != __private->gammaScale[0]) 8648 { 8649 __private->gammaScale[0] = info; 8650 __private->gammaScaleChange = true; 8651 } 8652 err = kIOReturnSuccess; 8653 break; 8654 8655 case kConnectionGreenGammaScale: 8656 if (info != __private->gammaScale[1]) 8657 { 8658 __private->gammaScale[1] = info; 8659 __private->gammaScaleChange = true; 8660 } 8661 err = kIOReturnSuccess; 8662 break; 8663 8664 case kConnectionBlueGammaScale: 8665 if (info != __private->gammaScale[2]) 8666 { 8667 __private->gammaScale[2] = info; 8668 __private->gammaScaleChange = true; 8669 } 8670 err = kIOReturnSuccess; 8671 break; 8672 8673 case kConnectionGammaScale: 8674 if (info != __private->gammaScale[3]) 8675 { 8676 __private->gammaScale[3] = info; 8677 __private->gammaScaleChange = true; 8678 } 8679 err = kIOReturnSuccess; 8680 break; 8681 8682 case kConnectionFlushParameters: 8683 if (__private->gammaScaleChange) 8684 { 8685 __private->gammaScaleChange = false; 8686 updateGammaTable(__private->rawGammaChannelCount, __private->rawGammaDataCount, 8687 __private->rawGammaDataWidth, __private->rawGammaData); 8688 } 8689 err = kIOReturnSuccess; 8690 break; 8691 8692 case kConnectionAudioStreaming: 8693 __private->audioStreaming = info; 8694 pendingPowerChange = true; 8695 startControllerThread(__private->controller); 8696 err = kIOReturnSuccess; 8697 break; 8698 8699 case kConnectionOverscan: 8700 8701 UInt64 newTransform; 8702 DEBG(thisName, " set oscn %ld, ena %d\n", info, __private->enableScalerUnderscan); 8703 if (info) 8704 newTransform = __private->selectedTransform & ~kIOFBScalerUnderscan; 8705 else 8706 newTransform = __private->selectedTransform | kIOFBScalerUnderscan; 8707 if (__private->enableScalerUnderscan) 8708 { 8709 if (newTransform != __private->selectedTransform) 8710 { 8711 __private->selectedTransform = newTransform; 8712 if (!suspended) 8713 connectChangeInterrupt(this, 0); 8714 else 8715 { 8716 __private->transform = newTransform; 8717 setProperty(kIOFBTransformKey, newTransform, 64); 8718 } 8719 } 8720 err = kIOReturnSuccess; 8721 break; 8722 } 8723 8724 /* fall thru */ 8725 8726 default: 8727 err = kIOReturnUnsupported; 8728 break; 8729 } 8730 8731 return( err ); 8732} 8733 8734IOReturn IOFramebuffer::getAttributeForConnection( IOIndex connectIndex, 8735 IOSelect attribute, uintptr_t * value ) 8736{ 8737 IOReturn err; 8738 uintptr_t result; 8739 8740 switch( attribute ) 8741 { 8742 case kConnectionDisplayParameterCount: 8743 result = 3; // 3 gamma rgb scales 8744 if (gIOGFades) result++; // 1 gamma scale 8745 if (__private->enableScalerUnderscan) 8746 result++; 8747 *value = result; 8748 err = kIOReturnSuccess; 8749 break; 8750 8751 case kConnectionDisplayParameters: 8752 result = 0; 8753 value[result++] = kConnectionRedGammaScale; 8754 value[result++] = kConnectionGreenGammaScale; 8755 value[result++] = kConnectionBlueGammaScale; 8756 if (gIOGFades) value[result++] = kConnectionGammaScale; 8757 if (__private->enableScalerUnderscan) 8758 value[result++] = kConnectionOverscan; 8759 err = kIOReturnSuccess; 8760 break; 8761 8762 case kConnectionOverscan: 8763 if (__private->enableScalerUnderscan) 8764 { 8765 value[0] = (0 == (kIOFBScalerUnderscan & __private->selectedTransform)); 8766 DEBG(thisName, " oscn %ld (%qx)\n", value[0], __private->selectedTransform); 8767 value[1] = 0; 8768 value[2] = 1; 8769 err = kIOReturnSuccess; 8770 } 8771 else 8772 err = kIOReturnUnsupported; 8773 break; 8774 8775 case kConnectionRedGammaScale: 8776 value[0] = __private->gammaScale[0]; 8777 value[1] = 0; 8778 value[2] = (1 << 16); 8779 err = kIOReturnSuccess; 8780 break; 8781 8782 case kConnectionGreenGammaScale: 8783 value[0] = __private->gammaScale[1]; 8784 value[1] = 0; 8785 value[2] = (1 << 16); 8786 err = kIOReturnSuccess; 8787 break; 8788 8789 case kConnectionBlueGammaScale: 8790 value[0] = __private->gammaScale[2]; 8791 value[1] = 0; 8792 value[2] = (1 << 16); 8793 err = kIOReturnSuccess; 8794 break; 8795 8796 case kConnectionGammaScale: 8797 value[0] = __private->gammaScale[3]; 8798 value[1] = 0; 8799 value[2] = (1 << 16); 8800 err = kIOReturnSuccess; 8801 break; 8802 8803 case kConnectionCheckEnable: 8804 err = getAttributeForConnection(connectIndex, kConnectionEnable, value); 8805 break; 8806 8807 case kConnectionSupportsHLDDCSense: 8808 if (__private->lli2c) 8809 { 8810 err = kIOReturnSuccess; 8811 break; 8812 } 8813 // fall thru 8814 default: 8815 err = kIOReturnUnsupported; 8816 break; 8817 } 8818 8819 return( err ); 8820} 8821 8822//// HW Cursors 8823 8824IOReturn IOFramebuffer::setCursorImage( void * cursorImage ) 8825{ 8826 return (kIOReturnUnsupported); 8827} 8828 8829IOReturn IOFramebuffer::setCursorState( SInt32 x, SInt32 y, bool visible ) 8830{ 8831 return (kIOReturnUnsupported); 8832} 8833 8834void IOFramebuffer::flushCursor( void ) 8835{} 8836 8837//// Interrupts 8838 8839IOReturn IOFramebuffer::registerForInterruptType( IOSelect interruptType, 8840 IOFBInterruptProc proc, OSObject * target, void * ref, 8841 void ** interruptRef ) 8842{ 8843 if ((interruptType != kIOFBMCCSInterruptType) || !__private->dpInterrupts) 8844 return (kIOReturnNoResources); 8845 8846 interruptType = kIOFBMCCSInterruptRegister; 8847 __private->interruptRegisters[interruptType].handler = proc; 8848 __private->interruptRegisters[interruptType].target = target; 8849 __private->interruptRegisters[interruptType].ref = ref; 8850 __private->interruptRegisters[interruptType].state = true; 8851 *interruptRef = &__private->interruptRegisters[interruptType]; 8852 8853 return (kIOReturnSuccess); 8854} 8855 8856IOReturn IOFramebuffer::unregisterInterrupt(void * interruptRef) 8857{ 8858 uintptr_t index; 8859 IOReturn err; 8860 8861 index = ((IOFBInterruptRegister *) interruptRef) - &__private->interruptRegisters[0]; 8862 if (interruptRef == &__private->interruptRegisters[index]) 8863 { 8864 __private->interruptRegisters[index].handler = 0; 8865 err = kIOReturnSuccess; 8866 } 8867 else 8868 { 8869 err = kIOReturnUnsupported; 8870 } 8871 8872 return (err); 8873} 8874 8875IOReturn IOFramebuffer::setInterruptState(void * interruptRef, UInt32 state) 8876{ 8877 uintptr_t index; 8878 IOReturn err; 8879 8880 index = ((IOFBInterruptRegister *) interruptRef) - &__private->interruptRegisters[0]; 8881 if (interruptRef == &__private->interruptRegisters[index]) 8882 { 8883 __private->interruptRegisters[index].state = state; 8884 err = kIOReturnSuccess; 8885 } 8886 else 8887 { 8888 err = kIOReturnUnsupported; 8889 } 8890 8891 return (err); 8892} 8893 8894// Apple sensing 8895 8896IOReturn IOFramebuffer::getAppleSense( 8897 IOIndex /* connectIndex */, 8898 UInt32 * /* senseType */, 8899 UInt32 * /* primary */, 8900 UInt32 * /* extended */, 8901 UInt32 * /* displayType */ ) 8902{ 8903 return (kIOReturnUnsupported); 8904} 8905 8906IOReturn IOFramebuffer::connectFlags( IOIndex /* connectIndex */, 8907 IODisplayModeID /* displayMode */, IOOptionBits * /* flags */ ) 8908{ 8909 return (kIOReturnUnsupported); 8910} 8911 8912//// IOLowLevelDDCSense 8913 8914void IOFramebuffer::setDDCClock( IOIndex /* connectIndex */, UInt32 /* value */ ) 8915{} 8916 8917void IOFramebuffer::setDDCData( IOIndex /* connectIndex */, UInt32 /* value */ ) 8918{} 8919 8920bool IOFramebuffer::readDDCClock( IOIndex /* connectIndex */ ) 8921{ 8922 return (false); 8923} 8924 8925bool IOFramebuffer::readDDCData( IOIndex /* connectIndex */ ) 8926{ 8927 return (false); 8928} 8929 8930IOReturn IOFramebuffer::enableDDCRaster( bool /* enable */ ) 8931{ 8932 return (kIOReturnUnsupported); 8933} 8934 8935/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 8936 8937//// IOHighLevelDDCSense 8938 8939enum { kDDCBlockSize = 128 }; 8940 8941bool IOFramebuffer::hasDDCConnect( IOIndex connectIndex ) 8942{ 8943 return (__private->lli2c); 8944} 8945 8946IOReturn IOFramebuffer::getDDCBlock( IOIndex bus, UInt32 blockNumber, 8947 IOSelect blockType, IOOptionBits options, 8948 UInt8 * data, IOByteCount * length ) 8949{ 8950 UInt8 startAddress; 8951 IOReturn err; 8952 UInt32 badsums, timeouts; 8953 IOI2CBusTiming * timing = &__private->defaultI2CTiming; 8954 8955 if (!__private->lli2c) 8956 return (kIOReturnUnsupported); 8957 8958 // Assume that we have already attempted to stop DDC1 8959 8960 // Read the requested block (Block 1 is at 0x0, each additional block is at 0x80 offset) 8961 startAddress = kDDCBlockSize * (blockNumber - 1); 8962 if (length) 8963 *length = kDDCBlockSize; 8964 8965 // Attempt to read the DDC data 8966 // 1. If the error is a timeout, then it will attempt one more time. If it gets another timeout, then 8967 // it will return a timeout error to the caller. 8968 // 8969 // 2. If the error is a bad checksum error, it will attempt to read the block up to 2 more times. 8970 // If it still gets an error, then it will return a bad checksum error to the caller. 8971 i2cSend9Stops(bus, timing); 8972 badsums = timeouts = 0; 8973 do 8974 { 8975 err = readDDCBlock(bus, timing, 0xa0, startAddress, data); 8976 if (kIOReturnSuccess == err) 8977 break; 8978 IOLog("readDDCBlock returned error\n"); 8979 i2cSend9Stops(bus, timing); 8980 8981 // We got an error. Determine what kind 8982 if (kIOReturnNotResponding == err) 8983 { 8984 IOLog("timeout\n"); 8985 timeouts++; 8986 } 8987 else if (kIOReturnUnformattedMedia == err) 8988 { 8989 IOLog("bad sum\n"); 8990 badsums++; 8991 } 8992 else 8993 break; 8994 } 8995 while ((timeouts < 2) && (badsums < 4)); 8996 8997 return (err); 8998} 8999 9000/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9001// 9002// doI2CRequest(), 9003// 9004 9005IOReturn IOFramebuffer::doI2CRequest( UInt32 bus, IOI2CBusTiming * timing, IOI2CRequest * request ) 9006{ 9007 IOReturn err = kIOReturnError; // Assume failure 9008 9009 if (!__private->lli2c) 9010 return (kIOReturnUnsupported); 9011 9012 if (!timing) 9013 timing = &__private->defaultI2CTiming; 9014 9015 if (request->sendTransactionType == kIOI2CSimpleTransactionType) 9016 { 9017 if ( request->sendAddress & 0x01 ) 9018 { 9019 // Read Transaction 9020 // 9021 err = i2cReadData(bus, timing, request->sendAddress, request->sendBytes, (UInt8 *) request->sendBuffer); 9022 } 9023 else 9024 { 9025 // Read Transaction 9026 // 9027 err = i2cWriteData(bus, timing, request->sendAddress, request->sendBytes, (UInt8 *) request->sendBuffer); 9028 } 9029 } 9030 9031 // Now, let's check to see if there is a csReplyType 9032 // 9033 if (request->replyTransactionType == kIOI2CDDCciReplyTransactionType ) 9034 { 9035 err = i2cReadDDCciData(bus, timing, request->replyAddress, request->replyBytes, (UInt8 *) request->replyBuffer); 9036 } 9037 else if (request->replyTransactionType == kIOI2CSimpleTransactionType ) 9038 { 9039 err = i2cReadData(bus, timing, request->replyAddress, request->replyBytes, (UInt8 *) request->replyBuffer); 9040 } 9041 9042 request->result = err; 9043 if (request->completion) 9044 (*request->completion)(request); 9045 9046 err = kIOReturnSuccess; 9047 9048 return (err); 9049} 9050 9051/* 9052 with thanks to: 9053 File: GraphicsCoreUtils.c 9054 Written by: Sean Williams, Kevin Williams, Fernando Urbina 9055*/ 9056 9057/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9058// 9059// stopDDC1SendCommand(), 9060// 9061// The VESA spec for DDC says a display in DDC1 will transition from DDC1 to DDC2 when a valid DDC2 9062// command is received. 9063// DDC1 constantly spews data on the data line if syncs are active...bad for macintosh sensing 9064// DDC2 only sends data when requested. 9065// The VESA spec illustrates the manner to do this. 9066// Read the first byte of data, send a Nack and a Stop. 9067// This routine does that. 9068// 9069// There is a delay of two vertical clock periods where the clock line is forced low. The 9070// NEC XE15 monitor has a controller that sometimes pulls the clockline low and never releases it. 9071// This is bad, DDC will fail, and the monitor sensing algorithim will think a mono 1152x870 display 9072// is attached. This isn't part of the spec but it fixes the NEC XE15. 9073// 9074 9075IOReturn IOFramebuffer::stopDDC1SendCommand(IOIndex bus, IOI2CBusTiming * timing) 9076{ 9077 UInt8 data; 9078 IOReturn err = kIOReturnSuccess; 9079 UInt8 address; 9080 9081 // keep clock line low for 2 vclocks....keeps NEC XE15 from locking clock line low 9082 // 640x480@67hz has a veritcal frequency of 15 ms 9083 // 640x480@60hz has a vertical frequency of 16.7 ms 9084 // Lower the clock line for 34 milliseconds 9085 9086 setDDCClock(bus, kIODDCLow); 9087 IOSleep( 34 ); 9088 9089 address = 0; 9090 err = i2cWrite(bus, timing, 0xa0, 1, &address); 9091 9092 if (kIOReturnSuccess == err) 9093 { 9094 i2cStart(bus, timing); 9095 9096 i2cSendByte(bus, timing, 0xa1 ); 9097 9098 err = i2cWaitForAck(bus, timing); 9099 if (kIOReturnSuccess == err) 9100 err = i2cReadByte(bus, timing, &data); 9101 } 9102 9103 i2cSendNack(bus, timing); 9104 i2cStop(bus, timing); 9105 9106 return (err); 9107} 9108 9109/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9110// 9111// i2cReadData() 9112// 9113// The parameters are described as follows: 9114// 9115// -> deviceAddress device's I2C address 9116// -> count # of bytes to read 9117// <- buffer buffer for the data 9118 9119IOReturn IOFramebuffer::i2cReadData(IOIndex bus, IOI2CBusTiming * timing, 9120 UInt8 deviceAddress, UInt8 count, UInt8 * buffer) 9121{ 9122 IOReturn err = kIOReturnError; 9123 UInt32 attempts = 10; 9124 9125 while ((kIOReturnSuccess != err) && (attempts-- > 0)) 9126 { 9127 // Attempt to read the I2C data 9128 i2cSend9Stops(bus, timing); 9129 err = i2cRead(bus, timing, deviceAddress, count, buffer); 9130 } 9131 9132 return (err); 9133} 9134 9135/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9136// 9137// i2cWriteData() 9138// 9139// The parameters are described as follows: 9140// 9141// -> deviceAddress device's I2C address 9142// -> count # of bytes to read 9143// -> buffer buffer for the data 9144 9145IOReturn IOFramebuffer::i2cWriteData(IOIndex bus, IOI2CBusTiming * timing, UInt8 deviceAddress, UInt8 count, UInt8 * buffer) 9146{ 9147 IOReturn err = kIOReturnError; 9148 UInt32 attempts = 10; 9149 9150 while ((kIOReturnSuccess != err) && (attempts-- > 0)) 9151 { 9152 // Attempt to write the I2C data 9153 i2cSend9Stops(bus, timing); 9154 err = i2cWrite(bus, timing, deviceAddress, count, buffer); 9155 } 9156 9157 return (err); 9158} 9159 9160/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9161// 9162// WaitForDDCDataLine() 9163// 9164// Watch the DDC data line and see if it is toggling. If the data line is toggling, it means 9165// 1) DDC display is connected 9166// 2) DDC controller in the display is ready to receive commands. 9167// 9168// -> waitTime max duration that the DDC data line should be watched 9169 9170void IOFramebuffer::waitForDDCDataLine(IOIndex bus, IOI2CBusTiming * timing, UInt32 waitTime) 9171{ 9172 AbsoluteTime now, expirationTime; 9173 UInt32 dataLine; 9174 9175 setDDCData(bus, kIODDCTristate); // make sure data line is tristated 9176 9177 // Set up the timeout timer...watch DDC data line for waitTime, see if it changes 9178 clock_interval_to_deadline(waitTime, kMillisecondScale, &expirationTime); 9179 9180 dataLine = readDDCData(bus); // read present state of dataline 9181 9182 while (true) 9183 { 9184 if (dataLine != readDDCData(bus)) 9185 break; 9186 9187 AbsoluteTime_to_scalar(&now) = mach_absolute_time(); 9188 if (CMP_ABSOLUTETIME(&now, &expirationTime) > 0) 9189 break; 9190 } 9191} 9192 9193/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9194// 9195// readDDCBlock() 9196// Read one block of DDC data 9197// 9198// The parameters are described as follows: 9199// 9200// -> deviceAddress device's I2C address 9201// -> startAddress start address to get data from 9202// <- data a block of EDID data 9203 9204IOReturn IOFramebuffer::readDDCBlock(IOIndex bus, IOI2CBusTiming * timing, UInt8 deviceAddress, UInt8 startAddress, UInt8 * data) 9205{ 9206 IOReturn err; 9207 UInt32 i; 9208 UInt8 sum = 0; 9209 9210 // First, send the address/data as a write 9211 err = i2cWrite(bus, timing, deviceAddress, 1, &startAddress); 9212 if (kIOReturnSuccess != err) 9213 goto ErrorExit; 9214 9215 // Now, read the I2C data 9216 err = i2cRead(bus, timing, deviceAddress, kDDCBlockSize, data); 9217 if (kIOReturnSuccess != err) 9218 goto ErrorExit; 9219 9220 for (i = 0; i < kDDCBlockSize; i++) 9221 sum += data[i]; 9222 9223 if (sum) 9224 err = kIOReturnUnformattedMedia; 9225 9226ErrorExit: 9227 9228 return (err); 9229} 9230 9231/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9232// 9233// i2cStart() 9234// Start a I2C transaction 9235 9236void IOFramebuffer::i2cStart(IOIndex bus, IOI2CBusTiming * timing) 9237{ 9238 // Generates a Start condition: 9239 9240 // Set DATA and CLK high and enabled 9241 setDDCData(bus, kIODDCHigh); 9242 setDDCClock(bus, kIODDCHigh); 9243 9244 IODelay( 100 ); 9245 9246 // Bring DATA low 9247 setDDCData(bus, kIODDCLow); 9248 IODelay( 100 ); 9249 9250 // Bring CLK low 9251 setDDCClock(bus, kIODDCLow); 9252 IODelay( 100 ); 9253} 9254 9255/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9256// 9257// i2cStop() 9258 9259void IOFramebuffer::i2cStop(IOIndex bus, IOI2CBusTiming * timing) 9260{ 9261 // Generate a low to high transition on DATA 9262 // while SCL is high 9263 9264 // Bring DATA and CLK low 9265 IODelay( 200 ); 9266 setDDCData(bus, kIODDCLow); 9267 setDDCClock(bus, kIODDCLow); 9268 9269 IODelay( 100 ); 9270 9271 // Bring CLK High 9272 setDDCClock(bus, kIODDCHigh); 9273 IODelay( 200 ); 9274 9275 // Bring DATA High 9276 setDDCData(bus, kIODDCHigh); 9277 IODelay( 100 ); 9278 9279 // Release Bus 9280 9281 setDDCData(bus, kIODDCTristate); 9282 setDDCClock(bus, kIODDCTristate); 9283} 9284 9285/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9286// 9287// i2cSendAck() 9288// Send an ACK to acknowledge we received the data 9289 9290void IOFramebuffer::i2cSendAck(IOIndex bus, IOI2CBusTiming * timing) 9291{ 9292 // Here, we have to make sure that the CLK is low while 9293 // we bring DATA low and pulse CLK 9294 setDDCClock(bus, kIODDCLow); 9295 9296 // This routine will release the bus by 9297 // tristating the CLK and DATA lines 9298 IODelay(20); 9299 9300 // should we wait for the SDA to be high before going on??? 9301 9302 IODelay( 40 ); 9303 9304 // Bring SDA low 9305 setDDCData(bus, kIODDCLow); 9306 IODelay( 100 ); 9307 9308 // pulse the CLK 9309 setDDCClock(bus, kIODDCHigh); 9310 IODelay( 200 ); 9311 setDDCClock(bus, kIODDCLow); 9312 IODelay( 40 ); 9313 9314 // Release SDA, 9315 setDDCData(bus, kIODDCTristate); 9316} 9317 9318/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9319// 9320// i2cSendNack() 9321// Send an ACK to acknowledge we received the data 9322 9323void IOFramebuffer::i2cSendNack(IOIndex bus, IOI2CBusTiming * timing) 9324{ 9325 // Here, we have to make sure that the CLK is low while 9326 // we bring DATA high and pulse CLK 9327 setDDCClock(bus, kIODDCLow); 9328 9329 // This routine will release the bus by 9330 // tristating the CLK and DATA lines 9331 IODelay( 20 ); 9332 // should we wait for the SDA to be high before going on??? 9333 9334 IODelay( 40 ); 9335 9336 // Bring SDA high 9337 setDDCData(bus, kIODDCHigh); 9338 IODelay( 100 ); 9339 9340 // pulse the CLK 9341 setDDCClock(bus, kIODDCHigh); 9342 IODelay( 200 ); 9343 setDDCClock(bus, kIODDCLow); 9344 IODelay( 40 ); 9345 9346 // Release SDA, 9347 setDDCData(bus, kIODDCTristate); 9348 IODelay( 100 ); 9349 IODelay( 100 ); 9350} 9351 9352/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9353// 9354// i2cWaitForAck() 9355// This routine will poll the SDA line looking for a LOW value and when it finds it, it will pulse 9356// the CLK. 9357 9358IOReturn IOFramebuffer::i2cWaitForAck(IOIndex bus, IOI2CBusTiming * timing) 9359{ 9360 AbsoluteTime now, expirationTime; 9361 IOReturn err = kIOReturnSuccess; 9362 9363 IODelay( 40 ); 9364 9365 // Set up a watchdog timer that will time us out, in case we never see the SDA LOW. 9366 clock_interval_to_deadline(1, kMillisecondScale, &expirationTime); 9367 9368 while ((0 != readDDCData(bus)) && (kIOReturnSuccess == err)) 9369 { 9370 AbsoluteTime_to_scalar(&now) = mach_absolute_time(); 9371 if (CMP_ABSOLUTETIME(&now, &expirationTime) > 0) 9372 err = kIOReturnNotResponding; // Timed Out 9373 } 9374 9375 // OK, now pulse the clock (SDA is not enabled), the CLK 9376 // should be low here. 9377 IODelay( 40 ); 9378 setDDCClock(bus, kIODDCHigh); 9379 IODelay( 200 ); 9380 setDDCClock(bus, kIODDCLow); 9381 IODelay( 40 ); 9382 9383 return (err); 9384} 9385 9386/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9387// 9388// i2cSendByte() 9389// Send a byte of data 9390// 9391 9392void IOFramebuffer::i2cSendByte(IOIndex bus, IOI2CBusTiming * timing, UInt8 data) 9393{ 9394 UInt8 valueToSend; 9395 int i; 9396 9397 // CLK should be low when entering this routine 9398 // and will be low when exiting 9399 9400 for ( i = 0 ; i < 8; i++ ) 9401 { 9402 // Wait a bit 9403 IODelay( 100 ); 9404 9405 // Get the bit 9406 valueToSend = ( data >> (7 - i)) & 0x01; 9407 9408 // Send it out 9409 setDDCData(bus, valueToSend); 9410 9411 // Wait for 40 us and then pulse the clock 9412 9413 IODelay( 40 ); 9414 // Raise the CLK line 9415 setDDCClock(bus, kIODDCHigh); 9416 9417 IODelay( 200 ); 9418 // Lower the clock line 9419 setDDCClock(bus, kIODDCLow); 9420 9421 // Wait a bit 9422 IODelay( 40 ); 9423 } 9424 9425 // Tristate the DATA while keeping CLK low 9426 setDDCData(bus, kIODDCTristate); 9427} 9428 9429/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9430// 9431// i2cReadByte() 9432// Read a byte of data 9433 9434IOReturn IOFramebuffer::i2cReadByte(IOIndex bus, IOI2CBusTiming * timing, UInt8 *data) 9435{ 9436 AbsoluteTime now, expirationTime; 9437 IOReturn err = kIOReturnSuccess; 9438 UInt32 i; 9439 UInt32 value; 9440 9441 // Make sure that DATA is Tristated and that Clock is low 9442 setDDCClock(bus, kIODDCLow); 9443 setDDCData(bus, kIODDCTristate); 9444 9445 for (i = 0 ; (kIOReturnSuccess == err) && (i < 8); i++) 9446 { 9447 // Wait for 1 msec and then pulse the clock 9448 IODelay( 100 ); 9449 // Release the CLK line 9450 setDDCClock(bus, kIODDCTristate); 9451 9452 // Wait for a slow device by reading the SCL line until it is high 9453 // (A slow device will keep it low). The DDC spec suggests a timeout 9454 // of 2ms here. 9455 // Setup for a timeout 9456 clock_interval_to_deadline(2, kMillisecondScale, &expirationTime); 9457 9458 while ((0 == readDDCClock(bus)) && (kIOReturnSuccess == err)) 9459 { 9460 AbsoluteTime_to_scalar(&now) = mach_absolute_time(); 9461 if (CMP_ABSOLUTETIME(&now, &expirationTime) > 0) 9462 err = kIOReturnNotResponding; // Timed Out 9463 } 9464 9465 // Read the data 9466 value = readDDCData(bus); 9467 *data |= (value << (7-i)); 9468 9469 //we keep clock high for when sending bits....so do same here. Ensures display sees clock. 9470 // reach 100% success rate with NEC XE15 9471 9472 IODelay( 200 ); 9473 // Lower the clock line 9474 setDDCClock(bus, kIODDCLow); 9475 IODelay( 40 ); 9476 } 9477 9478 return (err); 9479} 9480 9481/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9482// 9483// i2cWaitForBus() 9484// Tristate DDC Clk and DDC Data lines 9485 9486IOReturn IOFramebuffer::i2cWaitForBus(IOIndex bus, IOI2CBusTiming * timing) 9487{ 9488 // should we wait for the bus here? 9489 9490 setDDCClock(bus, kIODDCTristate); 9491 setDDCData(bus, kIODDCTristate); 9492 IODelay( 200 ); 9493 9494 return kIOReturnSuccess; 9495} 9496 9497/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9498// 9499// i2cReadDDCciData() 9500// 9501// The parameters are described as follows: 9502// 9503// -> deviceAddress device's I2C address 9504// -> count # of bytes to read 9505// <- buffer buffer for the data 9506// 9507 9508IOReturn IOFramebuffer::i2cReadDDCciData(IOIndex bus, IOI2CBusTiming * timing, UInt8 deviceAddress, UInt8 count, UInt8 *buffer) 9509{ 9510 // This is a funky call that encodes the length of the transaction in the response. 9511 // According to the VESA DDC/ci spec, the low 7 bits of second byte returned by the display 9512 // will contain the length of the message less the checksum. The card should then attempt to read 9513 // that length plus the checksum but should not exceed "count" bytes. 9514 // If the size exceeds "count", then the buffer should be filled with "count" bytes and the 9515 // transaction should be completed without copying more bytes into the buffer. 9516 9517 IOReturn err = kIOReturnSuccess; 9518 UInt32 i; 9519 UInt8 readLength; 9520 UInt32 bufferSize; 9521 Boolean reportShortRead = false; 9522 9523 // Assume that the bufferSize == count 9524 bufferSize = count; 9525 9526 err = i2cWaitForBus(bus, timing); 9527 if( kIOReturnSuccess != err ) goto ErrorExit; 9528 9529 i2cStart(bus, timing); 9530 9531 i2cSendByte(bus, timing, deviceAddress | 0x01 ); 9532 9533 err = i2cWaitForAck(bus, timing); 9534 if( kIOReturnSuccess != err ) goto ErrorExit; 9535 9536 for ( i = 0; i < bufferSize; i++ ) 9537 { 9538 err = i2cReadByte(bus, timing, &buffer[i] ); 9539 if( kIOReturnSuccess != err ) goto ErrorExit; 9540 9541 i2cSendAck(bus, timing); 9542 9543 if ( i == 1 ) 9544 { 9545 // We have read the 2nd byte, so adjust the 9546 // bufferSize accordingly 9547 // 9548 readLength = buffer[i] & 0x07; 9549 if ( (readLength + 1) <= count ) 9550 { 9551 // The read amount is less than our bufferSize, so 9552 // adjust that size 9553 // 9554 bufferSize = (readLength + 1); 9555 } 9556 else 9557 { 9558 // The amount to read > than our bufferSize 9559 // so only read up to our buffer size and remember to 9560 // report that we didn't read all the data 9561 // 9562 reportShortRead = true; 9563 } 9564 } 9565 } 9566 9567 9568ErrorExit: 9569 i2cSendNack(bus, timing); 9570 i2cStop(bus, timing); 9571 9572 if ( reportShortRead ) 9573 err = kIOReturnOverrun; 9574 9575 return (err); 9576 9577} 9578 9579/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9580// 9581// i2cRead() 9582// Read a bunch of data via I2C 9583// 9584// The parameters are described as follows: 9585// 9586// -> deviceAddress device's I2C address 9587// -> numberOfBytes number of bytes to read 9588// <- data the requested number of bytes of data 9589 9590IOReturn IOFramebuffer::i2cRead(IOIndex bus, IOI2CBusTiming * timing, UInt8 deviceAddress, UInt8 numberOfBytes, UInt8 * data) 9591{ 9592 IOReturn err = kIOReturnSuccess; 9593 int i; 9594 9595 err = i2cWaitForBus(bus, timing); 9596 if (kIOReturnSuccess != err) 9597 goto ErrorExit; 9598 9599 i2cStart(bus, timing); 9600 9601 i2cSendByte(bus, timing, deviceAddress | 0x01 ); 9602 9603 err = i2cWaitForAck(bus, timing); 9604 if (kIOReturnSuccess != err) 9605 goto ErrorExit; 9606 9607 for (i = 0; i < numberOfBytes; i++) 9608 { 9609 data[i] = 0; 9610 err = i2cReadByte(bus, timing, &data[i] ); 9611 if (kIOReturnSuccess != err) 9612 break; 9613 if (i != (numberOfBytes - 1)) 9614 i2cSendAck(bus, timing); 9615 } 9616 9617ErrorExit: 9618 i2cSendNack(bus, timing); 9619 i2cStop(bus, timing); 9620 9621 return (err); 9622} 9623 9624 9625/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9626// 9627// i2cWrite() 9628// Write a bunch of data via I2C 9629// 9630// The parameters are described as follows: 9631// 9632// -> deviceAddress device's I2C address 9633// -> numberOfBytes number of bytes to write 9634// -> data the number of bytes of data 9635 9636IOReturn IOFramebuffer::i2cWrite(IOIndex bus, IOI2CBusTiming * timing, UInt8 deviceAddress, UInt8 numberOfBytes, UInt8 * data) 9637{ 9638 IOReturn err = kIOReturnSuccess; 9639 UInt32 i; 9640 9641 err = i2cWaitForBus(bus, timing); 9642 if (kIOReturnSuccess != err) 9643 goto ErrorExit; 9644 9645 i2cStart(bus, timing); 9646 9647 i2cSendByte(bus, timing, deviceAddress); 9648 9649 err = i2cWaitForAck(bus, timing); 9650 if (kIOReturnSuccess != err) 9651 goto ErrorExit; 9652 9653 for (i = 0; i < numberOfBytes; i++) 9654 { 9655 i2cSendByte(bus, timing, data[i] ); 9656 err = i2cWaitForAck(bus, timing); 9657 if (kIOReturnSuccess != err) 9658 break; 9659 } 9660 9661 9662ErrorExit: 9663 9664 if (kIOReturnSuccess != err) 9665 i2cStop(bus, timing); 9666 9667 return (err); 9668} 9669 9670/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9671 9672// 9673// i2cSend9Stops() 9674// 9675// Assume we are reading the DDC data, and display misses a few clocks, we send ack, display misses ack 9676// The display might still be holding down the data line. Whenever we get an error, send nine stops. 9677// If the display is waiting for a clock before going to the next bit, the stop will be interpreted 9678// as a clock. It will go onto the next bit. Whenever it has finished writing the eigth bit, the 9679// next stop will look like a stop....the display will release the bus. 9680// 8 bits, 9 stops. The display should see at least one stop.... 9681 9682void IOFramebuffer::i2cSend9Stops(IOIndex bus, IOI2CBusTiming * timing) 9683{ 9684 for (UInt32 i = 0; i < 9; i++) 9685 i2cStop(bus, timing); 9686} 9687 9688/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9689/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9690 9691IOReturn IOFramebuffer::setPreferences( IOService * props, OSDictionary * prefs ) 9692{ 9693 if (!gIOFBPrefs) 9694 { 9695 prefs->retain(); 9696 gIOFBPrefs = prefs; 9697 gIOFBPrefsParameters = OSDynamicCast(OSDictionary, 9698 props->getProperty(kIOGraphicsPrefsParametersKey)); 9699 gIOFBIgnoreParameters = OSDynamicCast(OSDictionary, 9700 props->getProperty(kIOGraphicsIgnoreParametersKey)); 9701 9702 } 9703 return (kIOReturnSuccess); 9704} 9705 9706OSObject * IOFramebuffer::copyPreferences( void ) 9707{ 9708 if (gIOFBPrefsSerializer) 9709 gIOFBPrefsSerializer->retain(); 9710 return (gIOFBPrefsSerializer); 9711} 9712 9713OSObject * IOFramebuffer::copyPreference( IODisplay * display, const OSSymbol * key ) 9714{ 9715 OSDictionary * dict; 9716 OSObject * value = 0; 9717 9718 if (!gIOFBPrefs) 9719 return (value); 9720 9721 if (!__private->displayPrefKey && display) 9722 __private->displayPrefKey = (const OSSymbol *) display->copyProperty(kIODisplayPrefKeyKey); 9723 if (!__private->displayPrefKey) 9724 return (value); 9725 9726 if ((dict = OSDynamicCast(OSDictionary, gIOFBPrefs->getObject(__private->displayPrefKey)))) 9727 { 9728 value = dict->getObject(key); 9729 if (value) 9730 value->retain(); 9731 } 9732 9733 return (value); 9734} 9735 9736bool IOFramebuffer::getIntegerPreference( IODisplay * display, const OSSymbol * key, UInt32 * value ) 9737{ 9738 bool found = false; 9739 OSObject * 9740 pref = copyPreference(display, key); 9741 if (pref) 9742 { 9743 OSNumber * num; 9744 if ((num = OSDynamicCast(OSNumber, pref))) 9745 { 9746 value[0] = num->unsigned32BitValue(); 9747 DEBG1(thisName, " found(%s) %s = %d\n", __private->displayPrefKey->getCStringNoCopy(), 9748 key->getCStringNoCopy(), (uint32_t) value[0]); 9749 found = true; 9750 } 9751 pref->release(); 9752 } 9753 return (found); 9754} 9755 9756bool IOFramebuffer::setPreference( IODisplay * display, const OSSymbol * key, OSObject * value ) 9757{ 9758 OSDictionary * dict; 9759 OSObject * oldValue = 0; 9760 bool madeChanges = false; 9761 9762 if (!gIOFBPrefs) 9763 return (false); 9764 9765 if (!__private->displayPrefKey && display) 9766 __private->displayPrefKey = (const OSSymbol *) display->copyProperty(kIODisplayPrefKeyKey); 9767 9768 if (!__private->displayPrefKey) 9769 return (false); 9770 9771 dict = OSDynamicCast(OSDictionary, gIOFBPrefs->getObject(__private->displayPrefKey)); 9772 if (!dict) 9773 { 9774 dict = OSDictionary::withCapacity(4); 9775 if (dict) 9776 { 9777 gIOFBPrefs->setObject(__private->displayPrefKey, dict); 9778 dict->release(); 9779 madeChanges = true; 9780 } 9781 } 9782 else if (key) 9783 oldValue = dict->getObject(key); 9784 9785 if (dict 9786 && !gIOGraphicsPrefsVersionValue->isEqualTo(dict->getObject(gIOGraphicsPrefsVersionKey))) 9787 { 9788 dict->setObject(gIOGraphicsPrefsVersionKey, gIOGraphicsPrefsVersionValue); 9789 madeChanges = true; 9790 } 9791 9792 if (key && dict) 9793 { 9794 if (!oldValue || (!oldValue->isEqualTo(value))) 9795 { 9796 dict->setObject(key, value); 9797 madeChanges = true; 9798 } 9799 } 9800 9801 if (madeChanges) 9802 { 9803 DEBG(thisName, " sched prefs\n"); 9804 gIOFBDelayedPrefsEvent->setTimeoutMS((UInt32) 2000); 9805 } 9806 9807 return (true); 9808} 9809 9810bool IOFramebuffer::setIntegerPreference( IODisplay * display, const OSSymbol * key, UInt32 value ) 9811{ 9812 bool ok = false; 9813 OSNumber * 9814 num = OSNumber::withNumber(value, 32); 9815 if (num) 9816 { 9817 ok = setPreference(display, key, num); 9818 num->release(); 9819 } 9820 DEBG("", " %s = %d\n", key->getCStringNoCopy(), (uint32_t) value); 9821 return (ok); 9822} 9823 9824void IOFramebuffer::getTransformPrefs( IODisplay * display ) 9825{ 9826 OSObject * obj; 9827 UInt32 value; 9828 9829 if ((obj = copyPreference(display, gIOFBStartupModeTimingKey))) 9830 setProperty(gIOFBStartupModeTimingKey, obj); 9831 9832 if (getIntegerPreference(display, gIODisplayOverscanKey, &value)) 9833 { 9834 if (value) 9835 __private->selectedTransform = __private->selectedTransform & ~kIOFBScalerUnderscan; 9836 else 9837 __private->selectedTransform = __private->selectedTransform | kIOFBScalerUnderscan; 9838 } 9839 9840 if (__private->userSetTransform) 9841 { 9842 __private->userSetTransform = false; 9843 setIntegerPreference(display, gIOFBRotateKey, __private->selectedTransform & ~kIOFBScalerUnderscan); 9844 } 9845 else if (getIntegerPreference(display, gIOFBRotateKey, &value)) 9846 selectTransform(value, false); 9847 else if (__private->transform & ~kIOFBScalerUnderscan) 9848 selectTransform(0, false); 9849} 9850 9851/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9852/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9853 9854#undef super 9855#define super IODisplayParameterHandler 9856 9857OSDefineMetaClassAndStructors(IOFramebufferParameterHandler, IODisplayParameterHandler) 9858 9859/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9860 9861IOFramebufferParameterHandler * IOFramebufferParameterHandler::withFramebuffer( IOFramebuffer * framebuffer ) 9862{ 9863 IOFramebufferParameterHandler * handler; 9864 uintptr_t count = 0; 9865 9866 if ((kIOReturnSuccess != framebuffer->getAttributeForConnection( 9867 0, kConnectionDisplayParameterCount, &count))) 9868 return (0); 9869 9870 handler = new IOFramebufferParameterHandler; 9871 if (handler && !handler->init()) 9872 { 9873 handler->release(); 9874 handler = 0; 9875 } 9876 if (handler) 9877 handler->fFramebuffer = framebuffer; 9878 9879 return (handler); 9880} 9881 9882void IOFramebufferParameterHandler::free() 9883{ 9884 if (fDisplayParams) 9885 fDisplayParams->release(); 9886 9887 super::free(); 9888} 9889 9890bool IOFramebufferParameterHandler::setDisplay( IODisplay * display ) 9891{ 9892 fDisplay = display; 9893 9894 fFramebuffer->setPreference(display, 0, 0); // register display 9895 9896 if (!display) 9897 return (false); 9898 9899 fFramebuffer->getTransformPrefs(display); 9900 9901 return (true); 9902} 9903 9904void IOFramebufferParameterHandler::displayModeChange( void ) 9905{ 9906 IODisplay * display = fDisplay; 9907 IOReturn ret; 9908 uintptr_t count = 0; 9909 UInt32 str[2]; 9910 const OSSymbol * sym; 9911 uintptr_t value[16]; 9912 uintptr_t * attributes; 9913 OSDictionary * allParams; 9914 OSDictionary * newDict = 0; 9915 OSDictionary * oldParams; 9916 const OSSymbol * key; 9917 OSIterator * iter; 9918 9919 if (!display) 9920 return; 9921 9922 allParams = OSDynamicCast(OSDictionary, display->copyProperty(gIODisplayParametersKey)); 9923 if (allParams) 9924 { 9925 newDict = OSDictionary::withDictionary(allParams); 9926 allParams->release(); 9927 } 9928 9929 ret = fFramebuffer->getAttributeForConnectionParam( 9930 0, kConnectionDisplayParameterCount, &count); 9931 if (kIOReturnSuccess != ret) 9932 count = 0; 9933 9934 DEBG(fFramebuffer->thisName, " (%x) count %ld\n", ret, count); 9935 9936 oldParams = fDisplayParams; 9937 do 9938 { 9939 if (count) 9940 fDisplayParams = OSDictionary::withCapacity(count); 9941 else 9942 fDisplayParams = 0; 9943 if (!fDisplayParams) 9944 continue; 9945 9946 attributes = IONew(uintptr_t, count); 9947 if (!attributes) 9948 continue; 9949 9950 if (kIOReturnSuccess != fFramebuffer->getAttributeForConnection( 9951 0, kConnectionDisplayParameters, attributes)) 9952 continue; 9953 9954 str[1] = 0; 9955 for (uint32_t i = 0; i < count; i++) 9956 { 9957 DEBG1(fFramebuffer->thisName, " [%d] 0x%08lx '%c%c%c%c'\n", i, attributes[i], FEAT(attributes[i])); 9958 9959 if (attributes[i] < 0x00ffffff) 9960 continue; 9961 9962 OSWriteBigInt32(str, 0, attributes[i]); 9963 sym = OSSymbol::withCString((const char *) str); 9964 if (!sym) 9965 continue; 9966 9967 if ((!gIOFBIgnoreParameters || !gIOFBIgnoreParameters->getObject(sym)) 9968 && (kIOReturnSuccess == fFramebuffer->getAttributeForConnectionParam(0, attributes[i], &value[0]))) 9969 { 9970 OSObject * obj; 9971 9972 DEBG1(fFramebuffer->thisName, " [%d] drvr %s = %ld, (%ld - %ld)\n", i, (const char *) str, value[0], value[1], value[2]); 9973 9974 if (gIOFBPrefsParameters && (obj = gIOFBPrefsParameters->getObject(sym))) 9975 { 9976 OSNumber * prefDefault = NULL; 9977 UInt32 pref; 9978 9979 if ((fFramebuffer->getIntegerPreference(display, sym, &pref)) 9980 || (prefDefault = OSDynamicCast(OSNumber, obj))) 9981 { 9982 if (prefDefault) 9983 pref = prefDefault->unsigned32BitValue(); 9984 if (pref < value[1]) 9985 pref = value[1]; 9986 if (pref > value[2]) 9987 pref = value[2]; 9988 value[0] = pref; 9989 } 9990 } 9991 if (kConnectionColorMode == attributes[i]) 9992 { 9993 IODisplay::addParameter(fDisplayParams, gIODisplaySelectedColorModeKey, 0, kIODisplayColorModeRGBLimited); 9994 IODisplay::setParameter(fDisplayParams, gIODisplaySelectedColorModeKey, kIODisplayColorModeRGB); 9995 } 9996 IODisplay::addParameter(fDisplayParams, sym, value[1], value[2]); 9997 IODisplay::setParameter(fDisplayParams, sym, value[0]); 9998 } 9999 DEBG1(fFramebuffer->thisName, " [%d] added %s = %ld, (%ld - %ld)\n", i, (const char *) str, value[0], value[1], value[2]); 10000 sym->release(); 10001 } 10002 10003 IODelete(attributes, uintptr_t, count); 10004 } 10005 while (false); 10006 10007 if (oldParams) 10008 { 10009 if (newDict) 10010 { 10011 iter = OSCollectionIterator::withCollection(oldParams); 10012 if (iter) 10013 { 10014 while ((key = (const OSSymbol *) iter->getNextObject())) 10015 { 10016 if (!fDisplayParams || !fDisplayParams->getObject(key)) 10017 newDict->removeObject(key); 10018 } 10019 iter->release(); 10020 } 10021 } 10022 oldParams->release(); 10023 } 10024 10025 if (newDict) 10026 { 10027 if (fDisplayParams) 10028 newDict->merge(fDisplayParams); 10029 display->setProperty(gIODisplayParametersKey, newDict); 10030 newDict->release(); 10031 } 10032 else if (fDisplayParams) 10033 display->setProperty(gIODisplayParametersKey, fDisplayParams); 10034} 10035 10036bool IOFramebufferParameterHandler::doIntegerSet( OSDictionary * params, 10037 const OSSymbol * paramName, UInt32 value ) 10038{ 10039 UInt32 attribute; 10040 bool ok; 10041 SInt32 min, max; 10042 10043 fFramebuffer->fbLock(); 10044 10045 if (fDisplayParams && fDisplayParams->getObject(paramName)) 10046 { 10047 if (fDisplay 10048 && gIOFBPrefsParameters 10049 && gIOFBPrefsParameters->getObject(paramName) 10050 && (params = IODisplay::getIntegerRange(fDisplayParams, paramName, 0, &min, &max)) 10051 && (min != max)) 10052 { 10053 fFramebuffer->setIntegerPreference(fDisplay, paramName, value); 10054 } 10055 10056 attribute = OSReadBigInt32(paramName->getCStringNoCopy(), 0); 10057 10058 if (kConnectionColorMode == attribute) 10059 { 10060 if ((kIODisplayColorModeAuto == value) 10061 && (AUTO_COLOR_MODE != kIODisplayColorModeRGB) 10062 && fFramebuffer->__private->colorModesAllowed 10063 && (AUTO_COLOR_MODE & fFramebuffer->__private->colorModesSupported)) 10064 { 10065 value = AUTO_COLOR_MODE; 10066 } 10067 else 10068 { 10069 value = kIODisplayColorModeRGB; 10070 } 10071 IODisplay::setParameter(fDisplayParams, gIODisplaySelectedColorModeKey, value); 10072 } 10073 10074 ok = (kIOReturnSuccess == fFramebuffer->setAttributeForConnectionParam( 10075 0, attribute, value)); 10076 10077 DEBG1(fFramebuffer->thisName, "(%d) %s = %d\n", ok, paramName->getCStringNoCopy(), (int) value); 10078 } 10079 else 10080 ok = false; 10081 10082 if (gIODisplayParametersFlushKey == paramName) 10083 { 10084 fFramebuffer->setAttributeForConnectionParam(0, kConnectionFlushParameters, true); 10085 } 10086 10087 fFramebuffer->fbUnlock(); 10088 10089 return (ok); 10090} 10091 10092bool IOFramebufferParameterHandler::doDataSet( const OSSymbol * paramName, OSData * value ) 10093{ 10094 return (false); 10095} 10096 10097bool IOFramebufferParameterHandler::doUpdate( void ) 10098{ 10099 bool ok = true; 10100 10101 return (ok); 10102} 10103 10104/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 10105 10106void IOFramebuffer::dpInterruptProc(OSObject * target, void * ref) 10107{ 10108 IOFramebuffer * self = (IOFramebuffer *) target; 10109 uintptr_t delay = (uintptr_t) ref; 10110 10111 if (delay && self->__private->dpInterruptES) 10112 self->__private->dpInterruptES->setTimeoutMS(delay); 10113} 10114 10115void IOFramebuffer::dpInterrupt(OSObject * owner, IOTimerEventSource * sender) 10116{ 10117 IOFramebuffer * self = (IOFramebuffer *) owner; 10118 self->dpProcessInterrupt(); 10119} 10120 10121void IOFramebuffer::dpProcessInterrupt(void) 10122{ 10123 IOReturn err; 10124 IOI2CRequest request; 10125 UInt8 data[6]; 10126 uintptr_t bits, sel; 10127 10128 if (__private->closed || !pagingState) 10129 return; 10130 10131 sel = kIODPEventStart; 10132 err = setAttributeForConnection(0, kConnectionHandleDisplayPortEvent, (uintptr_t) &sel); 10133 10134 bzero(&data[0], sizeof(data)); 10135 do 10136 { 10137 bzero( &request, sizeof(request) ); 10138 10139 request.commFlags = 0; 10140 request.sendAddress = 0; 10141 request.sendTransactionType = kIOI2CNoTransactionType; 10142 request.sendBuffer = NULL; 10143 request.sendBytes = 0; 10144 10145 request.replyAddress = kDPRegisterLinkStatus; 10146 request.replyTransactionType = kIOI2CDisplayPortNativeTransactionType; 10147 request.replyBuffer = (vm_address_t) &data[0]; 10148 request.replyBytes = sizeof(data); 10149 10150 err = doI2CRequest(__private->dpBusID, 0, &request); 10151 if( (kIOReturnSuccess != err) || (kIOReturnSuccess != request.result)) 10152 break; 10153 10154 bits = data[1]; 10155 if (!bits) 10156 break; 10157 DEBG1(thisName, "dp events: 0x%02lx\n", bits); 10158 10159 if (kDPIRQRemoteControlCommandPending & bits) 10160 { 10161 sel = kIODPEventRemoteControlCommandPending; 10162 err = setAttributeForConnection(0, kConnectionHandleDisplayPortEvent, (uintptr_t) &sel); 10163 } 10164 if (kDPIRQAutomatedTestRequest & bits) 10165 { 10166 sel = kIODPEventAutomatedTestRequest; 10167 err = setAttributeForConnection(0, kConnectionHandleDisplayPortEvent, (uintptr_t) &sel); 10168 } 10169 if (kDPIRQContentProtection & bits) 10170 { 10171 sel = kIODPEventContentProtection; 10172 err = setAttributeForConnection(0, kConnectionHandleDisplayPortEvent, (uintptr_t) &sel); 10173 } 10174 if (kDPIRQMCCS & bits) 10175 { 10176 sel = kIODPEventMCCS; 10177 err = setAttributeForConnection(0, kConnectionHandleDisplayPortEvent, (uintptr_t) &sel); 10178 10179 IOFBInterruptProc proc; 10180 if ((proc = __private->interruptRegisters[kIOFBMCCSInterruptRegister].handler) 10181 && __private->interruptRegisters[kIOFBMCCSInterruptRegister].state) 10182 { 10183 (*proc)(__private->interruptRegisters[kIOFBMCCSInterruptRegister].target, 10184 __private->interruptRegisters[kIOFBMCCSInterruptRegister].ref); 10185 } 10186 } 10187 if (kDPIRQSinkSpecific & bits) 10188 { 10189 sel = kIODPEventSinkSpecific; 10190 err = setAttributeForConnection(0, kConnectionHandleDisplayPortEvent, (uintptr_t) &sel); 10191 } 10192 10193 request.sendAddress = kDPRegisterServiceIRQ; 10194 request.sendTransactionType = kIOI2CDisplayPortNativeTransactionType; 10195 request.sendBuffer = (vm_address_t) &data[1]; 10196 request.sendBytes = sizeof(data[1]); 10197 10198 request.replyAddress = kDPRegisterLinkStatus; 10199 request.replyTransactionType = kIOI2CDisplayPortNativeTransactionType; 10200 request.replyBuffer = (vm_address_t) &data[0]; 10201 request.replyBytes = sizeof(data); 10202 10203 err = doI2CRequest(__private->dpBusID, 0, &request); 10204 if( (kIOReturnSuccess != err) || (kIOReturnSuccess != request.result)) 10205 break; 10206 10207 if (data[1] == bits) 10208 { 10209 DEBG("dp events not cleared: 0x%02x\n", thisName, data[1]); 10210 break; 10211 } 10212 } 10213 while (false); 10214 10215 sel = kIODPEventIdle; 10216 err = setAttributeForConnection(0, kConnectionHandleDisplayPortEvent, (uintptr_t) &sel); 10217 10218 DEBG(thisName, "dp sinkCount %d\n", (kDPLinkStatusSinkCountMask & data[0])); 10219 10220 if (__private->dpDongle) 10221 { 10222 UInt8 sinkCount = (kDPLinkStatusSinkCountMask & data[0]); 10223 if (sinkCount != __private->dpDongleSinkCount) do 10224 { 10225 __private->dpDongleSinkCount = sinkCount; 10226 if (captured) 10227 continue; 10228 OSBitOrAtomic(kIOFBEventProbeAll, &gIOFBGlobalEvents); 10229 startThread(false); 10230 DEBG(thisName, "dp dongle hpd probeDP\n"); 10231 } 10232 while (false); 10233 } 10234 10235 return; 10236} 10237 10238void IOFramebuffer::dpUpdateConnect(void) 10239{ 10240 OSObject * obj; 10241 OSData * data; 10242 10243 __private->dpDongle = false; 10244 if (getProvider()->getProperty(kIOFBDPDeviceIDKey) 10245 && (obj = getProvider()->copyProperty(kIOFBDPDeviceTypeKey))) 10246 { 10247 data = OSDynamicCast(OSData, obj); 10248 __private->dpDongle = 10249 (data && data->isEqualTo(kIOFBDPDeviceTypeDongleKey, strlen(kIOFBDPDeviceTypeDongleKey))); 10250 obj->release(); 10251 10252 if (__private->dpDongle) 10253 { 10254 IOReturn err; 10255 IOI2CRequest request; 10256 UInt8 data[6]; 10257 10258 bzero(&data[0], sizeof(data)); 10259 do 10260 { 10261 bzero( &request, sizeof(request) ); 10262 10263 request.commFlags = 0; 10264 request.sendAddress = 0; 10265 request.sendTransactionType = kIOI2CNoTransactionType; 10266 request.sendBuffer = NULL; 10267 request.sendBytes = 0; 10268 10269 request.replyAddress = kDPRegisterLinkStatus; 10270 request.replyTransactionType = kIOI2CDisplayPortNativeTransactionType; 10271 request.replyBuffer = (vm_address_t) &data[0]; 10272 request.replyBytes = sizeof(data); 10273 10274 err = doI2CRequest(__private->dpBusID, 0, &request); 10275 if( (kIOReturnSuccess != err) || (kIOReturnSuccess != request.result)) 10276 break; 10277 10278 __private->dpDongleSinkCount = (kDPLinkStatusSinkCountMask & data[0]); 10279 } 10280 while (false); 10281 } 10282 } 10283 DEBG(thisName, "dp dongle %d, sinks %d\n", __private->dpDongle, __private->dpDongleSinkCount); 10284} 10285 10286/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 10287/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 10288 10289#undef super 10290#define super IOI2CInterface 10291 10292OSDefineMetaClassAndStructors(IOFramebufferI2CInterface, IOI2CInterface) 10293 10294/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 10295 10296IOFramebufferI2CInterface * IOFramebufferI2CInterface::withFramebuffer( 10297 IOFramebuffer * framebuffer, OSDictionary * info ) 10298{ 10299 IOFramebufferI2CInterface * interface; 10300 10301 interface = new IOFramebufferI2CInterface; 10302 info = OSDictionary::withDictionary(info); 10303 10304 if (interface && info) 10305 { 10306 interface->fFramebuffer = framebuffer; 10307 if (!interface->init(info) 10308 || !interface->attach(framebuffer) 10309 || !interface->start(framebuffer) 10310 ) 10311 { 10312 interface->detach( framebuffer ); 10313 interface->release(); 10314 interface = 0; 10315 } 10316 } 10317 if (info) 10318 info->release(); 10319 10320 return (interface); 10321} 10322 10323bool IOFramebufferI2CInterface::start( IOService * provider ) 10324{ 10325 bool ok = false; 10326 OSNumber * num; 10327 10328 if (!super::start(provider)) 10329 return (false); 10330 10331 do 10332 { 10333 num = OSDynamicCast(OSNumber, getProperty(kIOI2CInterfaceIDKey)); 10334 if (!num) 10335 break; 10336 fBusID = num->unsigned32BitValue(); 10337 10338 num = OSDynamicCast(OSNumber, getProperty(kIOI2CBusTypeKey)); 10339 if (!num) 10340 setProperty(kIOI2CBusTypeKey, (UInt64) kIOI2CBusTypeI2C, 32); 10341 10342 num = OSDynamicCast(OSNumber, getProperty(kIOI2CTransactionTypesKey)); 10343 if (num) 10344 fSupportedTypes = num->unsigned32BitValue(); 10345 else 10346 { 10347 fSupportedTypes = ((1 << kIOI2CNoTransactionType) 10348 | (1 << kIOI2CSimpleTransactionType) 10349 | (1 << kIOI2CDDCciReplyTransactionType) 10350 | (1 << kIOI2CCombinedTransactionType)); 10351 setProperty(kIOI2CTransactionTypesKey, (UInt64) fSupportedTypes, 32); 10352 } 10353 10354 num = OSDynamicCast(OSNumber, getProperty(kIOI2CSupportedCommFlagsKey)); 10355 if (num) 10356 fSupportedCommFlags = num->unsigned32BitValue(); 10357 else 10358 { 10359 fSupportedCommFlags = kIOI2CUseSubAddressCommFlag; 10360 setProperty(kIOI2CSupportedCommFlagsKey, (UInt64) fSupportedCommFlags, 32); 10361 } 10362 10363 UInt64 id = (((UInt64) (uintptr_t) fFramebuffer) << 32) | fBusID; 10364 registerI2C(id); 10365 10366 ok = true; 10367 } 10368 while (false); 10369 10370 return (ok); 10371} 10372 10373IOReturn IOFramebufferI2CInterface::startIO( IOI2CRequest * request ) 10374{ 10375 IOReturn err; 10376 10377 fFramebuffer->fbLock(); 10378 10379 do 10380 { 10381 if (0 == ((1 << request->sendTransactionType) & fSupportedTypes)) 10382 { 10383 err = kIOReturnUnsupportedMode; 10384 continue; 10385 } 10386 if (0 == ((1 << request->replyTransactionType) & fSupportedTypes)) 10387 { 10388 err = kIOReturnUnsupportedMode; 10389 continue; 10390 } 10391 if (request->commFlags != (request->commFlags & fSupportedCommFlags)) 10392 { 10393 err = kIOReturnUnsupportedMode; 10394 continue; 10395 } 10396 10397 err = fFramebuffer->doI2CRequest( fBusID, 0, request ); 10398 } 10399 while (false); 10400 10401 if (kIOReturnSuccess != err) 10402 { 10403 request->result = err; 10404 if (request->completion) 10405 (*request->completion)(request); 10406 10407 err = kIOReturnSuccess; 10408 } 10409 10410 fFramebuffer->fbUnlock(); 10411 10412 return (err); 10413} 10414 10415/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 10416 10417#if defined(__ppc__) && !defined(OSTYPES_K64_REV) 10418 10419class AppleOnboardI2CInterface : public IOI2CInterface 10420{ 10421 OSDeclareDefaultStructors(AppleOnboardI2CInterface) 10422 10423 class PPCI2CInterface * fInterface; 10424 SInt32 fPort; 10425 10426public: 10427 virtual bool start( IOService * provider ); 10428 virtual IOReturn startIO( IOI2CRequest * request ); 10429 10430 static AppleOnboardI2CInterface * withInterface( PPCI2CInterface * interface, SInt32 port ); 10431}; 10432 10433#undef super 10434#define super IOI2CInterface 10435 10436OSDefineMetaClassAndStructors(AppleOnboardI2CInterface, IOI2CInterface) 10437 10438/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 10439 10440AppleOnboardI2CInterface * AppleOnboardI2CInterface::withInterface( 10441 PPCI2CInterface * onboardInterface, SInt32 port ) 10442{ 10443 AppleOnboardI2CInterface * interface; 10444 UInt64 id = (((UInt64) (UInt32) onboardInterface) << 32) | port; 10445 10446 interface = new AppleOnboardI2CInterface; 10447 if (interface) 10448 { 10449 interface->fInterface = onboardInterface; 10450 interface->fPort = port; 10451 if (!interface->init() 10452 || !interface->attach(onboardInterface) 10453 || !interface->start(onboardInterface) 10454 ) 10455 { 10456 interface->detach( onboardInterface ); 10457 interface->release(); 10458 interface = 0; 10459 } 10460 else 10461 interface->registerI2C(id); 10462 } 10463 return (interface); 10464} 10465 10466bool AppleOnboardI2CInterface::start( IOService * provider ) 10467{ 10468 if (!super::start(provider)) 10469 return (false); 10470 10471 setProperty(kIOI2CBusTypeKey, 10472 (UInt64) kIOI2CBusTypeI2C, 32); 10473 setProperty(kIOI2CTransactionTypesKey, 10474 (UInt64) ((1 << kIOI2CNoTransactionType) 10475 | (1 << kIOI2CSimpleTransactionType) 10476 | (1 << kIOI2CDDCciReplyTransactionType) 10477 | (1 << kIOI2CCombinedTransactionType)), 32); 10478 setProperty(kIOI2CSupportedCommFlagsKey, 10479 (UInt64) kIOI2CUseSubAddressCommFlag, 32); 10480 10481 return (true); 10482} 10483 10484IOReturn AppleOnboardI2CInterface::startIO( IOI2CRequest * request ) 10485{ 10486 IOReturn err = kIOReturnSuccess; 10487 10488 do 10489 { 10490 // Open the interface and sets it in the wanted mode: 10491 10492 fInterface->openI2CBus(fPort); 10493 10494 // the i2c driver does not support well read in interrupt mode 10495 // so it is better to "go polling" (read does not timeout on errors 10496 // in interrupt mode). 10497 fInterface->setPollingMode(true); 10498 10499 if (request->sendBytes && (kIOI2CNoTransactionType != request->sendTransactionType)) 10500 { 10501 if (kIOI2CCombinedTransactionType == request->sendTransactionType) 10502 fInterface->setCombinedMode(); 10503 else if (kIOI2CUseSubAddressCommFlag & request->commFlags) 10504 fInterface->setStandardSubMode(); 10505 else 10506 fInterface->setStandardMode(); 10507 10508 if (!fInterface->writeI2CBus(request->sendAddress >> 1, request->sendSubAddress, 10509 (UInt8 *) request->sendBuffer, request->sendBytes)) 10510 err = kIOReturnNotWritable; 10511 } 10512 10513 if (request->replyBytes && (kIOI2CNoTransactionType != request->replyTransactionType)) 10514 { 10515 if (kIOI2CCombinedTransactionType == request->replyTransactionType) 10516 fInterface->setCombinedMode(); 10517 else if (kIOI2CUseSubAddressCommFlag & request->commFlags) 10518 fInterface->setStandardSubMode(); 10519 else 10520 fInterface->setStandardMode(); 10521 10522 if (!fInterface->readI2CBus(request->replyAddress >> 1, request->replySubAddress, 10523 (UInt8 *) request->replyBuffer, request->replyBytes)) 10524 err = kIOReturnNotReadable; 10525 } 10526 10527 fInterface->closeI2CBus(); 10528 } 10529 while (false); 10530 10531 request->result = err; 10532 10533 err = kIOReturnSuccess; 10534 10535 return (err); 10536} 10537 10538#endif /* __ppc__ && !defined(OSTYPES_K64_REV) */ 10539 10540/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 10541 10542IOReturn IOFramebufferI2CInterface::create( IOFramebuffer * framebuffer ) 10543{ 10544 IOReturn err = kIOReturnSuccess; 10545 IOI2CInterface * interface; 10546 UInt32 idx; 10547 OSArray * busArray; 10548 OSArray * interfaceIDArray; 10549 OSDictionary * dict; 10550 OSObject * num; 10551 bool ok = true; 10552 10553 interfaceIDArray = OSArray::withCapacity(1); 10554 if (!interfaceIDArray) 10555 return (kIOReturnNoMemory); 10556 10557 busArray = OSDynamicCast(OSArray, framebuffer->getProperty(kIOFBI2CInterfaceInfoKey)); 10558 do 10559 { 10560 if (!busArray) 10561 continue; 10562 for (idx = 0; (dict = OSDynamicCast(OSDictionary, busArray->getObject(idx))); idx++) 10563 { 10564 interface = IOFramebufferI2CInterface::withFramebuffer(framebuffer, dict); 10565 if (!interface) 10566 break; 10567 num = interface->getProperty(kIOI2CInterfaceIDKey); 10568 if (num) 10569 interfaceIDArray->setObject(num); 10570 else 10571 break; 10572 } 10573 10574 ok = (idx == busArray->getCount()); 10575 } 10576 while (false); 10577 10578#if defined(__ppc__) && !defined(OSTYPES_K64_REV) 10579 10580 OSData * data = OSDynamicCast( OSData, framebuffer->getProvider()->getProperty("iic-address")); 10581 if (data && (!framebuffer->getProperty(kIOFBDependentIDKey)) 10582 && (0x8c == *((UInt32 *) data->getBytesNoCopy())) /*iMac*/) 10583 { 10584 do 10585 { 10586 PPCI2CInterface * onboardInterface = 10587 (PPCI2CInterface*) getResourceService()->getProperty("PPCI2CInterface.i2c-uni-n"); 10588 if (!onboardInterface) 10589 continue; 10590 10591 interface = AppleOnboardI2CInterface::withInterface( onboardInterface, 1 ); 10592 if (!interface) 10593 break; 10594 num = interface->getProperty(kIOI2CInterfaceIDKey); 10595 if (num) 10596 interfaceIDArray->setObject(num); 10597 else 10598 break; 10599 } 10600 while (false); 10601 } 10602#endif /* defined(__ppc__) && !defined(OSTYPES_K64_REV) */ 10603 10604 if (ok && interfaceIDArray->getCount()) 10605 framebuffer->setProperty(kIOFBI2CInterfaceIDsKey, interfaceIDArray); 10606 10607 interfaceIDArray->release(); 10608 10609 return (err); 10610} 10611 10612/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 10613 10614OSMetaClassDefineReservedUsed(IOFramebuffer, 0); 10615 10616OSMetaClassDefineReservedUnused(IOFramebuffer, 1); 10617OSMetaClassDefineReservedUnused(IOFramebuffer, 2); 10618OSMetaClassDefineReservedUnused(IOFramebuffer, 3); 10619OSMetaClassDefineReservedUnused(IOFramebuffer, 4); 10620OSMetaClassDefineReservedUnused(IOFramebuffer, 5); 10621OSMetaClassDefineReservedUnused(IOFramebuffer, 6); 10622OSMetaClassDefineReservedUnused(IOFramebuffer, 7); 10623OSMetaClassDefineReservedUnused(IOFramebuffer, 8); 10624OSMetaClassDefineReservedUnused(IOFramebuffer, 9); 10625OSMetaClassDefineReservedUnused(IOFramebuffer, 10); 10626OSMetaClassDefineReservedUnused(IOFramebuffer, 11); 10627OSMetaClassDefineReservedUnused(IOFramebuffer, 12); 10628OSMetaClassDefineReservedUnused(IOFramebuffer, 13); 10629OSMetaClassDefineReservedUnused(IOFramebuffer, 14); 10630OSMetaClassDefineReservedUnused(IOFramebuffer, 15); 10631OSMetaClassDefineReservedUnused(IOFramebuffer, 16); 10632OSMetaClassDefineReservedUnused(IOFramebuffer, 17); 10633OSMetaClassDefineReservedUnused(IOFramebuffer, 18); 10634OSMetaClassDefineReservedUnused(IOFramebuffer, 19); 10635OSMetaClassDefineReservedUnused(IOFramebuffer, 20); 10636OSMetaClassDefineReservedUnused(IOFramebuffer, 21); 10637OSMetaClassDefineReservedUnused(IOFramebuffer, 22); 10638OSMetaClassDefineReservedUnused(IOFramebuffer, 23); 10639OSMetaClassDefineReservedUnused(IOFramebuffer, 24); 10640OSMetaClassDefineReservedUnused(IOFramebuffer, 25); 10641OSMetaClassDefineReservedUnused(IOFramebuffer, 26); 10642OSMetaClassDefineReservedUnused(IOFramebuffer, 27); 10643OSMetaClassDefineReservedUnused(IOFramebuffer, 28); 10644OSMetaClassDefineReservedUnused(IOFramebuffer, 29); 10645OSMetaClassDefineReservedUnused(IOFramebuffer, 30); 10646OSMetaClassDefineReservedUnused(IOFramebuffer, 31); 10647 10648 10649