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