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 23#include <IOKit/IOLib.h> 24#include <IOKit/platform/ApplePlatformExpert.h> 25#include <IOKit/IODeviceTreeSupport.h> 26#include <IOKit/IOSubMemoryDescriptor.h> 27#include <IOKit/IOLocks.h> 28#include <IOKit/IOMessage.h> 29#include <IOKit/pwr_mgt/RootDomain.h> 30#include <IOKit/IOHibernatePrivate.h> 31#include <IOKit/graphics/IOGraphicsPrivate.h> 32#include <IOKit/graphics/IOGraphicsInterfaceTypes.h> 33#include <IOKit/ndrvsupport/IONDRVFramebuffer.h> 34#include <IOKit/i2c/IOI2CInterface.h> 35#include <IOKit/pci/IOAGPDevice.h> 36#include <IOKit/IOTimerEventSource.h> 37#include <IOKit/assert.h> 38 39#include <libkern/c++/OSContainers.h> 40#include <string.h> 41 42#include "IONDRV.h" 43#include "IONDRVFramebufferPrivate.h" 44 45#define sizeof32(x) ((int)sizeof(x)) 46 47/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 48 49extern "C" IOReturn _IONDRVLibrariesInitialize( IOService * provider ); 50extern "C" IOReturn _IONDRVLibrariesFinalize( IOService * provider ); 51 52#if RLOG 53#define IONDRVCHECK 1 54#endif 55#define IONDRVCHECK 1 56#define IONDRVI2CLOG 0 57#define TIME_LOGS 0 58 59#define kFirstDepth kDepthMode1 60 61enum 62{ 63 kModePreflight = 1, 64 kDisplayModeIDPreflight = kDisplayModeIDReservedBase + 1000 65}; 66 67#define arbMode2Index(index) \ 68 (index & 0x3ff) 69 70#if TIME_LOGS 71 72#define TIMESTART() \ 73{ \ 74 AbsoluteTime startTime, endTime; \ 75 uint64_t nsec; \ 76 AbsoluteTime_to_scalar(&startTime) = mach_absolute_time(); 77 78#define TIMEEND(name, fmt, args...) \ 79 AbsoluteTime_to_scalar(&endTime) = mach_absolute_time(); \ 80 absolutetime_to_nanoseconds(endTime, &nsec); \ 81 kprintf("%08d [%s]: ", (uint32_t) (nsec / 1000000ULL), name); \ 82 SUB_ABSOLUTETIME(&endTime, &startTime); \ 83 absolutetime_to_nanoseconds(endTime, &nsec); \ 84 nsec /= 1000000ULL; \ 85 kprintf(fmt, ## args , nsec); \ 86} 87 88 89#else /* !TIME_LOGS */ 90 91#define TIMESTART() 92#define TIMEEND(name, fmt, args...) 93 94#endif 95 96 97/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 98 99struct IONDRVFramebufferPrivate 100{ 101 IOOptionBits displayConnectFlags; 102 unsigned int ackConnectChange:1; 103 unsigned int postWakeProbe:1; 104 unsigned int i2cPowerState:1; 105 unsigned int deferCLUTSet:1; 106 unsigned int removable:1; 107 unsigned int pad1:27; 108 UInt32 desiredGammaWidth; 109 UInt32 desiredGammaCount; 110 IOTimerEventSource * probeInterrupt; 111 UInt32 currentModeTiming; 112 UInt32 reducedSpeed; 113 IODisplayModeID depthMapModeID; 114 UInt8 indexToDepthMode[kDepthMode6 - kDepthMode1 + 1]; 115 UInt8 depthModeToIndex[kDepthMode6 - kDepthMode1 + 1]; 116 IOPhysicalAddress64 physicalFramebuffer; 117 118}; 119 120/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 121 122class IOBootNDRV : public IONDRV 123{ 124 OSDeclareDefaultStructors(IOBootNDRV) 125 126public: 127 enum { kIOBootNDRVDisplayMode = 100 }; 128 129 IOMemoryDescriptor * fVRAMDesc; 130 UInt32 fRowBytes; 131 UInt32 fWidth; 132 UInt32 fHeight; 133 UInt32 fBitsPerPixel; 134 135 static IONDRV * fromRegistryEntry( IORegistryEntry * regEntry ); 136 137 virtual void free( void ); 138 139 virtual IOReturn getSymbol( const char * symbolName, 140 IOLogicalAddress * address ); 141 142 virtual const char * driverName( void ); 143 144 virtual IOReturn doDriverIO( UInt32 commandID, void * contents, 145 UInt32 commandCode, UInt32 commandKind ); 146 147private: 148 149 static bool getUInt32Property( IORegistryEntry * regEntry, const char * name, 150 UInt32 * result ); 151 IOReturn doControl( UInt32 code, void * params ); 152 IOReturn doStatus( UInt32 code, void * params ); 153}; 154 155/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 156 157/* generic nub for multihead devices */ 158 159class IONDRVDevice : public IOPlatformDevice 160{ 161 OSDeclareDefaultStructors(IONDRVDevice) 162 163public: 164 virtual bool compareName( OSString * name, OSString ** matched = 0 ) const; 165 virtual IOService * matchLocation( IOService * client ); 166 virtual IOReturn getResources( void ); 167 virtual void joinPMtree( IOService * driver ); 168}; 169 170#undef super 171#define super IOPlatformDevice 172 173OSDefineMetaClassAndStructors(IONDRVDevice, IOPlatformDevice) 174 175void IONDRVDevice::joinPMtree( IOService * driver ) 176{ 177 IOService * realDevice; 178 realDevice = OSDynamicCast( IOService, getParentEntry(gIODTPlane) ); 179 if (realDevice) 180 realDevice->addPowerChild(driver); 181 else 182 super::joinPMtree( driver ); 183} 184 185bool IONDRVDevice::compareName( OSString * name, 186 OSString ** matched ) const 187{ 188 return (IODTCompareNubName(this, name, matched) 189 || IORegistryEntry::compareName(name, matched)); 190} 191 192IOService * IONDRVDevice::matchLocation( IOService * client ) 193{ 194 return (this); 195} 196 197IOReturn IONDRVDevice::getResources( void ) 198{ 199 if (getDeviceMemory()) 200 return (kIOReturnSuccess); 201 202 IODTResolveAddressing(this, "reg", 0); 203 204 return (kIOReturnSuccess); 205} 206 207/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 208 209struct _VSLService 210{ 211 class IONDRVFramebuffer * framebuffer; 212 IOSelect type; 213 IOFBInterruptProc handler; 214 OSObject * target; 215 void * ref; 216 _VSLService * next; 217}; 218 219/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 220 221// IONDRVFramebuffer has three power states: sleep, doze, wake. 222 223enum { 224 kNDRVFramebufferSleepState = 0, 225 kNDRVFramebufferDozeState = 1, 226 kNDRVFramebufferWakeState = 2, 227 kIONDRVFramebufferPowerStateCount = 3, 228 kIONDRVFramebufferPowerStateMax = kIONDRVFramebufferPowerStateCount - 1 229}; 230 231/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 232 233#undef super 234#define super IOFramebuffer 235 236OSDefineMetaClassAndStructors(IONDRVFramebuffer, IOFramebuffer) 237 238static int gIONDRVFramebufferGeneration[2] = { 0, 0 }; 239 240/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 241 242IOService * IONDRVFramebuffer::probe( IOService * provider, SInt32 * score ) 243{ 244 IOService * inst; 245 246 if (0 != provider->getProperty(kIONDRVIgnoreKey)) 247 return (0); 248 249 inst = super::probe(provider, score); 250 if (!inst) 251 return (0); 252 253 if (getProperty(gIONameMatchedKey)) 254 { 255 // matched 256 provider->setProperty(kIONDRVForXKey, gIOFBOne32Data); 257 } 258 259 return (inst); 260} 261 262IOReturn IONDRVFramebuffer::setProperties( OSObject * properties ) 263{ 264 OSDictionary * dict; 265 OSData * data; 266 IOReturn kr = kIOReturnUnsupported; 267 268 if (!(dict = OSDynamicCast(OSDictionary, properties))) 269 return (kIOReturnBadArgument); 270 271 if ((data = OSDynamicCast(OSData, 272 dict->getObject("driver,AAPL,MacOS,PowerPC")))) 273 { 274 gIONDRVFramebufferGeneration[1] = gIONDRVFramebufferGeneration[0]; 275 if (ndrvState) 276 return (kIOReturnStillOpen); 277 278 if (ndrv) 279 ndrv->release(); 280 ndrv = NULL; 281 if (ndrv) 282 { 283 setName( ndrv->driverName()); 284 setProperty("driver,AAPL,MacOS,PowerPC", nub->getProperty("driver,AAPL,MacOS,PowerPC")); 285 } 286 kr = kIOReturnSuccess; 287 } 288 else 289 kr = super::setProperties(properties); 290 291 return (kr); 292} 293 294void IONDRVFramebuffer::stop( IOService * provider ) 295{ 296 UInt32 state = ndrvState; 297 298 super::stop( provider ); 299 300 if (state) 301 { 302 IOMemoryDescriptor * vram; 303 if ((vram = getVRAMRange())) 304 { 305 vram->redirect( kernel_task, false ); 306 vram->release(); 307 } 308 online = false; 309 device = 0; 310 nub = 0; 311 _IONDRVLibrariesFinalize(provider); 312 } 313 provider->removeProperty(kIONDRVForXKey); 314} 315 316bool IONDRVFramebuffer::start( IOService * provider ) 317{ 318 bool ok = false; 319 IOService * parent = 0; 320 OSData * data; 321 322 if (0 == getProperty(gIONameMatchedKey)) 323 { 324 // !matched 325 IORegistryIterator * iter; 326 IORegistryEntry * next; 327 IOService * nub; 328 OSArray * toDo = 0; 329 bool firstLevel; 330 331 if (0 == provider->getProperty("AAPL,ndrv-dev")) 332 { 333 provider->setProperty("AAPL,ndrv-dev", kOSBooleanTrue); 334 335 if (provider->getProperty("@0,name")) 336 { 337 OSDictionary * dict; 338 OSCollectionIterator * keys; 339 const OSSymbol * key; 340 char buffer[80]; 341 const char * keyChrs; 342 size_t len; 343 char c; 344 345 dict = provider->dictionaryWithProperties(); 346 keys = OSCollectionIterator::withCollection(dict); 347 if (dict) 348 dict->release(); 349 if (keys) 350 { 351 while ((key = OSDynamicCast(OSSymbol, keys->getNextObject()))) 352 { 353 keyChrs = key->getCStringNoCopy(); 354 if ('@' != keyChrs[0]) 355 continue; 356 357 len = 0; 358 do 359 { 360 c = keyChrs[len]; 361 if (!c || (c == ',')) 362 break; 363 buffer[len] = c; 364 len++; 365 } 366 while (len < (sizeof(buffer) - 1)); 367 if (!c) 368 continue; 369 370 buffer[len] = 0; 371 keyChrs += len + 1; 372 373 next = provider->childFromPath(buffer, gIODTPlane); 374 if (!next) 375 { 376 next = new IOService; 377 if (next && !next->init()) 378 { 379 next->release(); 380 next = 0; 381 } 382 if (!next) 383 continue; 384 next->setLocation(&buffer[1]); 385 if (!next->attachToParent(provider, gIODTPlane)) 386 continue; 387 } 388 389 OSObject * obj = dict->getObject(key); 390 next->setProperty(keyChrs, dict->getObject(key)); 391 if (!strcmp(keyChrs, "name")) 392 { 393 OSData * data = OSDynamicCast(OSData, obj); 394 if (data) 395 next->setName((const char *) data->getBytesNoCopy()); 396 } 397 next->release(); 398 provider->removeProperty(key); 399 } 400 keys->release(); 401 } 402 } 403 404 iter = IORegistryIterator::iterateOver( provider, gIODTPlane, 0 ); 405 toDo = OSArray::withCapacity(2); 406 407 if (iter && toDo) 408 { 409 bool haveDoneLibInit = false; 410 UInt32 index = 0; 411 do 412 { 413 while ((next = (IORegistryEntry *) iter->getNextObject())) 414 { 415 firstLevel = (provider == next->getParentEntry(gIODTPlane)); 416 if (firstLevel) 417 { 418 data = OSDynamicCast( OSData, next->getProperty("device_type")); 419 if (!data || (0 != strcmp("display", (char *) data->getBytesNoCopy()))) 420 continue; 421 422 if (!haveDoneLibInit) 423 { 424 haveDoneLibInit = (kIOReturnSuccess == _IONDRVLibrariesInitialize(provider)); 425 if (!haveDoneLibInit) 426 continue; 427 } 428 next->setProperty( kIOFBDependentIDKey, provider->getRegistryEntryID(), 64 ); 429 next->setProperty( kIOFBDependentIndexKey, index, 32 ); 430 index++; 431 } 432 433 toDo->setObject( next ); 434 iter->enterEntry(); 435 } 436 } 437 while (iter->exitEntry()); 438 } 439 if (iter) 440 iter->release(); 441 442 if (toDo) 443 { 444 OSObject * obj; 445 OSArray * deviceMemory; 446 obj = provider->copyProperty(gIODeviceMemoryKey); 447 deviceMemory = OSDynamicCast(OSArray, obj); 448 449 for (unsigned int i = 0; 450 (next = (IORegistryEntry *) toDo->getObject(i)); 451 i++) 452 { 453 nub = new IONDRVDevice; 454 if (!nub) 455 continue; 456 if (!nub->init(next, gIODTPlane)) 457 { 458 nub->free(); 459 nub = 0; 460 continue; 461 } 462 if (deviceMemory) 463 nub->setDeviceMemory(deviceMemory); 464 nub->attach(provider); 465 nub->registerService(kIOServiceSynchronous); 466 } 467 if (obj) 468 obj->release(); 469 toDo->release(); 470 } 471 } 472 return (false); 473 } 474 475 data = OSDynamicCast(OSData, provider->getProperty("device_type")); 476 if (data && (0 != strcmp("display", (char *) data->getBytesNoCopy()))) 477 return (false); 478 479 do 480 { 481 cachedVDResolution.csDisplayModeID = kDisplayModeIDInvalid; 482 483 if (!__private) 484 { 485 __private = IONew( IONDRVFramebufferPrivate, 1 ); 486 if (!__private) 487 continue; 488 bzero( __private, sizeof(IONDRVFramebufferPrivate) ); 489 } 490 491 __private->depthMapModeID = kDisplayModeIDInvalid; 492 493 nub = provider; 494 495 gIONDRVFramebufferGeneration[0]++; 496 data = OSData::withBytesNoCopy(&gIONDRVFramebufferGeneration, sizeof32(gIONDRVFramebufferGeneration)); 497 if (data) 498 { 499 setProperty(kIONDRVFramebufferGenerationKey, data); 500 getRegistryRoot()->setProperty(kIONDRVFramebufferGenerationKey, data); 501 data->release(); 502 } 503 504 if ((data = OSDynamicCast(OSData, getProperty("driver,AAPL,MacOS,PowerPC")))) 505 nub->setProperty("driver,AAPL,MacOS,PowerPC", data); 506 507 ndrv = NULL; 508 if (ndrv) 509 setName( ndrv->driverName()); 510 consoleDevice = (0 != provider->getProperty("AAPL,boot-display")); 511 512 powerState = kIONDRVFramebufferPowerStateMax; 513 514 if (OSDynamicCast(IONDRVDevice, nub)) 515 parent = OSDynamicCast(IOService, nub->getParentEntry(gIODTPlane)); 516 if (parent) 517 device = parent; 518 else 519 device = nub; 520 521 RegEntryID regEntry; 522 MAKE_REG_ENTRY( ®Entry, nub); 523 nub->setProperty( kAAPLRegEntryIDKey, ®Entry, sizeof32(regEntry) ); 524 525 if (false == super::start(nub)) 526 continue; 527 528 OSObject * obj; 529 if ((obj = nub->getProperty(kIOFBDependentIDKey))) 530 setProperty( kIOFBDependentIDKey, obj ); 531 if ((obj = nub->getProperty(kIOFBDependentIndexKey))) 532 setProperty( kIOFBDependentIndexKey, obj ); 533 534 platformSleep = false; 535 __private->removable = (0 != device->metaCast("IOCardBusDevice")); 536 537 IOOptionBits flags = getPMRootDomain()->getSleepSupported(); 538 getPMRootDomain()->setSleepSupported(flags & ~kFrameBufferDeepSleepSupported); 539 540 // default flags can be overriden 541 accessFlags = 0; 542 if (0 == strncmp("3Dfx", provider->getName(), strlen("3Dfx"))) 543 accessFlags |= kFramebufferDisableAltivecAccess; 544 545 if ((data = OSDynamicCast(OSData, provider->getProperty(kIOFBHostAccessFlagsKey)))) 546 accessFlags = *((UInt32 *) data->getBytesNoCopy()); 547 548 ok = true; // Success 549 } 550 while (false); 551 552 return (ok); 553} 554 555bool IONDRVFramebuffer::isConsoleDevice( void ) 556{ 557 return (consoleDevice); 558} 559 560IOReturn IONDRVFramebuffer::enableController( void ) 561{ 562 IOReturn err; 563 const char * logname; 564 565 logname = getProvider()->getName(); 566 do 567 { 568 gIONDRVFramebufferGeneration[1] = gIONDRVFramebufferGeneration[0]; 569 570 getProvider()->setProperty("AAPL,ndrv-dev", kOSBooleanTrue); 571 572 // wait for accelerator module, display parameter drivers 573 // device->waitQuiet(); 574 // find out about onboard audio/video jack state 575 // OSObject * notify = 576 addMatchingNotification( gIOPublishNotification, 577 resourceMatching(kAppleAudioVideoJackStateKey), 578 _videoJackStateChangeHandler, this, 0 ); 579 580 err = checkDriver(); 581 if (err) 582 { 583 IOLog("%s: Not usable\n", logname ); 584 if (err == -999) 585 IOLog("%s: driver incompatible.\n", logname ); 586 continue; 587 } 588 uintptr_t isOnline = true; 589 if ((kIOReturnSuccess != getAttributeForConnection(0, kConnectionCheckEnable, &isOnline)) 590 || isOnline || true) 591 { 592 getCurrentConfiguration(); 593 594 if (!device->getProperty("IONVRAMProperty")) 595 setStartupDisplayMode( currentDisplayMode, currentDepth ); 596 597 if (currentDisplayMode == kDisplayModeIDBootProgrammable) 598 { 599 VDScalerRec scaler; 600 601 bzero( &scaler, sizeof( VDScalerRec) ); 602 scaler.csScalerSize = sizeof32(VDScalerRec); 603 scaler.csDisplayModeID = kDisplayModeIDBootProgrammable; 604 if (noErr == _doStatus(this, cscGetScaler, &scaler)) 605 { 606 DEBG(thisName, " boot scalerFlags 0x%x\n", (uint32_t) scaler.csScalerFlags); 607 if (kIOScaleRotateFlags & scaler.csScalerFlags) 608 setProperty(kIOFBTransformKey, kIOScaleRotateFlags & scaler.csScalerFlags, 64); 609 } 610 } 611 } 612 online = isOnline; 613// vramMemory = findVRAM(); 614 615 OSData * data; 616 if ((data = OSDynamicCast(OSData, device->getProperty(kIOAGPCommandValueKey)))) 617 accessFlags |= (kIOAGPFastWrite & (*((UInt32 *) data->getBytesNoCopy()))) 618 ? kFramebufferAGPFastWriteAccess : 0; 619 620 // initialize power management of the device 621 initForPM(); 622 device->setProperty(kIOPMIsPowerManagedKey, true); 623 624 if ((data = OSDynamicCast(OSData, getPMRootDomain()->getProperty(kIOHibernateStateKey)))) 625 device->setProperty(kIOHibernateStateKey, gIOFBZero32Data); 626 } 627 while (false); 628 629 return (err); 630} 631 632bool IONDRVFramebuffer::_videoJackStateChangeHandler( void * target, void * ref, 633 IOService * resourceService, IONotifier * notifier ) 634{ 635 IONDRVFramebuffer * self = (IONDRVFramebuffer *) target; 636 uint32_t jackData; 637 638 OSObject * jackValue = resourceService->getProperty(kAppleAudioVideoJackStateKey); 639 if (!jackValue) 640 return (true); 641 642 jackData = (jackValue == kOSBooleanTrue); 643 IOLog(kAppleAudioVideoJackStateKey " %d\n", jackData); 644 645 self->nub->setProperty( kAppleAudioVideoJackStateKey, &jackData, sizeof32(jackData) ); 646 resourceService->removeProperty(kAppleAudioVideoJackStateKey); 647 648 if (!self->__private->probeInterrupt) 649 { 650 self->__private->probeInterrupt = IOTimerEventSource::timerEventSource( 651 self, &IONDRVFramebuffer::_avProbeAction); 652 if (self->__private->probeInterrupt) 653 self->getControllerWorkLoop()->addEventSource(self->__private->probeInterrupt); 654 } 655 if (self->__private->probeInterrupt && (self->avJackState != jackData)) 656 { 657 self->avJackState = jackData; 658 self->__private->probeInterrupt->setTimeoutMS(kIONDRVAVJackProbeDelayMS); 659 } 660 661 return (true); 662} 663 664void IONDRVFramebuffer::_avProbeAction( OSObject * p0, IOTimerEventSource * evtSrc ) 665{ 666 _probeAction( (IONDRVFramebuffer *) p0, kIOFBAVProbe ); 667} 668 669IOReturn IONDRVFramebuffer::_probeAction( IONDRVFramebuffer * self, IOOptionBits options ) 670{ 671 IOReturn err = kIOReturnSuccess; 672 673 if (self->captured) 674 { 675 err = kIOReturnBusy; 676 } 677 else if (options & (kIOFBUserRequestProbe | kIOFBAVProbe)) 678 { 679 if ((options & kIOFBUserRequestProbe) && !self->supportsProbe) 680 { 681 err = kIOReturnUnsupported; 682 } 683 else 684 { 685#if 1 686 err = self->_doControl( self, cscProbeConnection, 0 ); 687#else 688 do 689 { 690 OSNumber * num = OSDynamicCast(OSNumber, self->getProperty(kIOFBDependentIndexKey)); 691 if (num && (0 != num->unsigned32BitValue())) 692 continue; 693 694 IONDRVFramebuffer * next = self; 695 do 696 { 697 next->_doControl( next, cscProbeConnection, 0 ); 698 next = OSDynamicCast(IONDRVFramebuffer, next->nextDependent); 699 } 700 while (next && (next != self)); 701 } 702 while (false); 703#endif 704 } 705 } 706 else if (options & kIOFBForceReadEDID) 707 { 708 if (!self->forceReadEDID) 709 { 710 _VSLService * service; 711 IOFBInterruptProc proc; 712 713 self->forceReadEDID = 1; 714 715 for (service = self->vslServices; 716 service && (kIOFBConnectInterruptType != service->type); 717 service = service->next) 718 {} 719 if (service && (proc = service->handler)) 720 (*proc) (service->target, service->ref); 721 } 722 err = kIOReturnSuccess; 723 } 724 else 725 err = kIOReturnBadArgument; 726 727 return (err); 728} 729 730IOReturn IONDRVFramebuffer::requestProbe( IOOptionBits options ) 731{ 732 IOReturn err; 733 734 err = super::requestProbe(options); 735 736 return (err); 737} 738 739IODeviceMemory * IONDRVFramebuffer::getVRAMRange( void ) 740{ 741 if (ndrvState && !vramMemory) 742 vramMemory = findVRAM(); 743 744 if (vramMemory) 745 vramMemory->retain(); 746 747 return (vramMemory); 748} 749 750const IOTVector * IONDRVFramebuffer::_undefinedSymbolHandler( void * self, 751 const char * libraryName, const char * symbolName ) 752{ 753 return (((IONDRVFramebuffer *)self)->undefinedSymbolHandler(libraryName, symbolName)); 754} 755 756const IOTVector * IONDRVFramebuffer::undefinedSymbolHandler( const char * libraryName, 757 const char * symbolName ) 758{ 759 return (0); 760} 761 762void IONDRVFramebuffer::free( void ) 763{ 764 if (__private) 765 { 766 IODelete( __private, IONDRVFramebufferPrivate, 1 ); 767 __private = 0; 768 } 769 super::free(); 770} 771 772/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 773 774IOReturn IONDRVFramebuffer::registerForInterruptType( IOSelect interruptType, 775 IOFBInterruptProc proc, OSObject * target, void * ref, 776 void ** interruptRef ) 777 778{ 779 _VSLService * service; 780 IOReturn err; 781 782 if ((interruptType == kIOFBVBLInterruptType) 783 && (getProvider()->getProperty("Ignore VBL"))) 784 return (kIOReturnUnsupported); 785 786 for (service = vslServices; 787 service && (service->type != interruptType); 788 service = service->next) 789 {} 790 791 if (service) 792 { 793 if (service->handler) 794 err = kIOReturnBusy; 795 else 796 { 797 service->target = target; 798 service->ref = ref; 799 service->handler = proc; 800 *interruptRef = service; 801 err = kIOReturnSuccess; 802 } 803 } 804 else 805 { 806 err = super::registerForInterruptType(interruptType, proc, target, ref, interruptRef); 807 } 808 809 return (err); 810} 811 812IOReturn IONDRVFramebuffer::unregisterInterrupt( void * interruptRef ) 813{ 814 _VSLService * service; 815 IOReturn err; 816 817 for (service = vslServices; 818 service && (service != interruptRef); 819 service = service->next) 820 {} 821 822 if (service) 823 { 824 service->handler = 0; 825 err = kIOReturnSuccess; 826 } 827 else 828 { 829 err = super::unregisterInterrupt(interruptRef); 830 } 831 832 return (err); 833} 834 835IOReturn IONDRVFramebuffer::setInterruptState( void * interruptRef, 836 UInt32 state ) 837{ 838 _VSLService * service; 839 IOReturn err; 840 841 for (service = vslServices; 842 service && (service != interruptRef); 843 service = service->next) 844 {} 845 846 if (service) 847 { 848 err = kIOReturnUnsupported; 849 } 850 else 851 { 852 err = super::setInterruptState(interruptRef, state); 853 } 854 855 return (err); 856} 857 858/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 859 860//// VSL calls 861 862OSStatus IONDRVFramebuffer::VSLNewInterruptService( 863 void * entryID, 864 IOSelect serviceType, 865 _VSLService ** vslService ) 866{ 867 IORegistryEntry * regEntry; 868 IOService * device; 869 IOService * client = NULL; 870 IONDRVFramebuffer * fb = NULL; 871 _VSLService * service; 872 IOReturn err = kIOReturnSuccess; 873 874 REG_ENTRY_TO_OBJ( (const RegEntryID *) entryID, regEntry) 875 876 if ((device = OSDynamicCast(IOService, regEntry))) 877 client = device->copyClientWithCategory(gIOFramebufferKey); 878 879 if ((fb = OSDynamicCast(IONDRVFramebuffer, client))) 880 { 881 service = IONew( _VSLService, 1 ); 882 883 if (service) 884 { 885 service->framebuffer = fb; 886 service->type = serviceType; 887 service->handler = 0; 888 service->next = fb->vslServices; 889 fb->vslServices = service; 890 891 *vslService = service; 892 } 893 else 894 err = kIOReturnNoMemory; 895 } 896 else 897 err = kIOReturnBadArgument; 898 899 if (client) 900 client->release(); 901 902 return (err); 903} 904 905OSStatus IONDRVFramebuffer::VSLDisposeInterruptService(_VSLService * vslService) 906{ 907 IONDRVFramebuffer * fb; 908 _VSLService * next; 909 _VSLService * prev; 910 911 if (vslService) 912 { 913 fb = vslService->framebuffer; 914 915 prev = fb->vslServices; 916 if (prev == vslService) 917 fb->vslServices = vslService->next; 918 else 919 { 920 while (((next = prev->next) != vslService) && next) 921 prev = next; 922 if (next) 923 prev->next = vslService->next; 924 } 925 926 IODelete( vslService, _VSLService, 1 ); 927 } 928 929 return (kIOReturnSuccess); 930} 931 932OSStatus IONDRVFramebuffer::VSLDoInterruptService( _VSLService * vslService ) 933{ 934 IOReturn ret = kIOReturnSuccess; 935 IOFBInterruptProc proc; 936 937 if (vslService) 938 { 939 if (kIOFBConnectInterruptType == vslService->type) 940 vslService->framebuffer->__private->ackConnectChange = true; 941 else if (kIOFBWakeInterruptType == vslService->type) 942 ret = vslService->framebuffer->handleEvent(kIOFBNotifyVRAMReady); 943 944 if ((proc = vslService->handler)) 945 (*proc) (vslService->target, vslService->ref); 946 } 947 948 return (ret); 949} 950 951/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 952 953struct _VSLCursorRef 954{ 955 IOFramebuffer * framebuffer; 956 void * cursorImage; 957}; 958 959Boolean IONDRVFramebuffer::VSLPrepareCursorForHardwareCursor( 960 void * cursorRef, 961 IOHardwareCursorDescriptor * hwDesc, 962 IOHardwareCursorInfo * hwCursorInfo ) 963{ 964 _VSLCursorRef * cursor = (_VSLCursorRef *) cursorRef; 965 bool ok; 966 967 if (hwCursorInfo->colorMap) 968 hwCursorInfo->colorMap += 1; 969 ok = cursor->framebuffer->convertCursorImage( 970 cursor->cursorImage, hwDesc, hwCursorInfo ); 971 if (hwCursorInfo->colorMap) 972 hwCursorInfo->colorMap -= 1; 973 974 return (ok); 975} 976 977IOReturn IONDRVFramebuffer::setCursorImage( void * cursorImage ) 978{ 979 _VSLCursorRef cursorRef; 980 VDSetHardwareCursorRec setCursor; 981 IOReturn err; 982 983 if (0 == powerState) 984 return (kIOReturnSuccess); 985 if (!online) 986 return (kIOReturnSuccess); 987 988 cursorRef.framebuffer = this; 989 cursorRef.cursorImage = cursorImage; 990 991 setCursor.csCursorRef = (void *) &cursorRef; 992 setCursor.csReserved1 = 0; 993 setCursor.csReserved2 = 0; 994 995 err = _doControl( this, cscSetHardwareCursor, &setCursor ); 996 997 mirrorSWCursor = (mirrored && !mirrorPrimary && (kIOReturnSuccess != err)); 998 if (mirrorSWCursor) 999 err = kIOReturnSuccess; 1000 1001 return (err); 1002} 1003 1004IOReturn IONDRVFramebuffer::setCursorState( SInt32 x, SInt32 y, bool visible ) 1005{ 1006 VDDrawHardwareCursorRec drawCursor; 1007 IOReturn err; 1008 1009 if (mirrorSWCursor || !online) 1010 return (kIOReturnSuccess); 1011 1012 if (0 == powerState) 1013 return (kIOReturnSuccess); 1014 1015 if (0 == OSIncrementAtomic(&ndrvEnter)) 1016 { 1017 drawCursor.csCursorX = x; 1018 drawCursor.csCursorY = y; 1019 drawCursor.csCursorVisible = visible; 1020 drawCursor.csReserved1 = 0; 1021 drawCursor.csReserved2 = 0; 1022 1023 err = _doControl( this, cscDrawHardwareCursor, &drawCursor ); 1024 } 1025 else 1026 { 1027 err = kIOReturnBusy; 1028 } 1029 1030 OSDecrementAtomic( &ndrvEnter ); 1031 1032 return (err); 1033} 1034 1035/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1036 1037IOReturn IONDRVFramebuffer::doDriverIO( UInt32 commandID, void * contents, 1038 UInt32 commandCode, UInt32 commandKind ) 1039{ 1040 IOReturn err; 1041 1042 if (kIONDRVInitializeCommand == commandCode) 1043 { 1044 if (!ndrv) 1045 { 1046 uint32_t debugFlags; 1047 if (PE_parse_boot_argn("iog", &debugFlags, sizeof(debugFlags)) 1048 && (kIOGDbgDumbPanic & debugFlags)) 1049 { 1050 panic("dumb FB start"); 1051 } 1052 ndrv = IOBootNDRV::fromRegistryEntry( nub ); 1053 if (ndrv) 1054 setName( ndrv->driverName()); 1055 } 1056 } 1057 1058 if (ndrv) 1059 { 1060 OSIncrementAtomic( &ndrvEnter ); 1061 err = ndrv->doDriverIO( commandID, contents, commandCode, commandKind ); 1062 OSDecrementAtomic( &ndrvEnter ); 1063 } 1064 else 1065 err = kIOReturnUnsupported; 1066 1067 return (err); 1068} 1069 1070/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1071 1072IOReturn IONDRVFramebuffer::_doControl( IONDRVFramebuffer * self, UInt32 code, void * params ) 1073{ 1074 IOReturn err; 1075 IONDRVControlParameters pb; 1076 1077#if IONDRVCHECK 1078 IOWorkLoop * wl; 1079 if (!ml_at_interrupt_context() && (wl = self->getControllerWorkLoop()) && !wl->inGate()) 1080 OSReportWithBacktrace("%s::_doControl(%d) not gated\n", self->thisName, code); 1081#endif 1082 1083 if (self->ndrvState == 0) 1084 return (kIOReturnNotOpen); 1085 1086 pb.code = code; 1087 pb.params = params; 1088 1089 err = self->doDriverIO( /*ID*/ 1, &pb, 1090 kIONDRVControlCommand, kIONDRVImmediateIOCommandKind ); 1091 1092#if FORCE_CONNECT_CHANGE 1093 if (cscProbeConnection == code) 1094 { 1095 _VSLService * vslService = self->vslServices; 1096 while (vslService && (kIOFBConnectInterruptType != vslService->type)) 1097 vslService = vslService->next; 1098 if (vslService) 1099 VSLDoInterruptService(vslService); 1100 } 1101#endif 1102 1103 return (err); 1104} 1105 1106IOReturn IONDRVFramebuffer::_doStatus( IONDRVFramebuffer * self, UInt32 code, void * params ) 1107{ 1108 IOReturn err; 1109 IONDRVControlParameters pb; 1110 1111 if (self->ndrvState == 0) 1112 return (kIOReturnNotOpen); 1113 1114#if IONDRVCHECK 1115 IOWorkLoop * wl; 1116 if (!ml_at_interrupt_context() && (wl = self->getControllerWorkLoop()) && !wl->inGate()) 1117 OSReportWithBacktrace("%s::_doStatus(%d) not gated\n", self->thisName, code); 1118#endif 1119 1120 pb.code = code; 1121 pb.params = params; 1122 1123 err = self->doDriverIO( /*ID*/ 1, &pb, 1124 kIONDRVStatusCommand, kIONDRVImmediateIOCommandKind ); 1125 1126 return (err); 1127} 1128 1129IOReturn IONDRVFramebuffer::extControl( OSObject * owner, void * code, void * params ) 1130{ 1131 IONDRVFramebuffer * self = (IONDRVFramebuffer *) owner; 1132 IOReturn err; 1133 1134 if (self->powerState) 1135 err = _doControl( self, (UInt32)(uintptr_t) code, params ); 1136 else 1137 err = kIOReturnNotReady; 1138 1139 return (err); 1140} 1141 1142IOReturn IONDRVFramebuffer::extStatus( OSObject * owner, void * code, void * params ) 1143{ 1144 IONDRVFramebuffer * self = (IONDRVFramebuffer *) owner; 1145 IOReturn err; 1146 1147 if (self->powerState) 1148 err = _doStatus( self, (UInt32)(uintptr_t) code, params ); 1149 else 1150 err = kIOReturnNotReady; 1151 1152 return (err); 1153} 1154 1155IOReturn IONDRVFramebuffer::doControl( UInt32 code, void * params ) 1156{ 1157 return (getControllerWorkLoop()->runAction((IOWorkLoop::Action) &extControl, this, (void *)(uintptr_t) code, params)); 1158} 1159 1160IOReturn IONDRVFramebuffer::doStatus( UInt32 code, void * params ) 1161{ 1162 return (getControllerWorkLoop()->runAction((IOWorkLoop::Action) &extStatus, this, (void *)(uintptr_t) code, params)); 1163} 1164 1165/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1166 1167IOReturn IONDRVFramebuffer::checkDriver( void ) 1168{ 1169 OSStatus err = noErr; 1170 IONDRVControlParameters pb; 1171 VDClutBehavior clutSetting; 1172 VDGammaRecord gammaRec; 1173 VDSwitchInfoRec switchInfo; 1174 VDPageInfo pageInfo; 1175 1176 if (ndrvState == 0) 1177 { 1178 do 1179 { 1180 err = doDriverIO( 0, nub, 1181 kIONDRVInitializeCommand, kIONDRVImmediateIOCommandKind ); 1182 if (err) 1183 continue; 1184 err = doDriverIO( 0, &pb, 1185 kIONDRVOpenCommand, kIONDRVImmediateIOCommandKind ); 1186 } 1187 while (false); 1188 if (err) 1189 return (err); 1190 1191 // allow calls to ndrv 1192 ndrvState = 2; 1193 1194 createI2C(); 1195 1196#if IONDRVI2CLOG 1197 do 1198 { 1199 VDCommunicationInfoRec commInfo; 1200 1201 bzero( &commInfo, sizeof( commInfo)); 1202 commInfo.csBusID = kVideoDefaultBus; 1203 1204 err = _doStatus( this, cscGetCommunicationInfo, &commInfo ); 1205 IOLog("%s: cscGetCommunicationInfo: ", getName()); 1206 if (kIOReturnSuccess != err) 1207 { 1208 IOLog("fails with %ld\n", err); 1209 continue; 1210 } 1211 IOLog("csBusType %lx, csMinBus %lx, csMaxBus %lx\n" 1212 "csSupportedTypes %lx, csSupportedCommFlags %lx\n", 1213 commInfo.csBusType, 1214 commInfo.csMinBus, commInfo.csMaxBus, 1215 commInfo.csSupportedTypes, commInfo.csSupportedCommFlags); 1216 1217 if (commInfo.csSupportedTypes & (1<<kVideoDDCciReplyType)) 1218 IOLog("supports kVideoDDCciReplyType, "); 1219 if (commInfo.csSupportedTypes & (1<<kVideoSimpleI2CType)) 1220 { 1221 IOLog("supports kVideoSimpleI2CType"); 1222 VDCommunicationRec comm; 1223 UInt8 edidData[132]; 1224 UInt8 edidRequest[2]; 1225 1226 memset( edidData, 0xAA, sizeof( edidData)); 1227 1228 edidRequest[0] = 0; 1229 edidRequest[1] = 0; 1230 1231 comm.csBusID = kVideoDefaultBus; 1232 comm.csCommFlags = 0; 1233 comm.csMinReplyDelay = 0; 1234 comm.csReserved2 = 0; 1235 1236 comm.csSendAddress = 0xA0; 1237 comm.csSendType = kVideoSimpleI2CType; 1238 comm.csSendBuffer = &edidRequest[0]; 1239 comm.csSendSize = 0x01; 1240 1241 comm.csReplyAddress = 0xA1; 1242 comm.csReplyType = kVideoSimpleI2CType; 1243 comm.csReplyBuffer = &edidData[0]; 1244 comm.csReplySize = 128; 1245 1246 comm.csReserved3 = 0; 1247 comm.csReserved4 = 0; 1248 comm.csReserved5 = 0; 1249 comm.csReserved6 = 0; 1250 1251 do 1252 { 1253 err = _doControl( this, cscDoCommunication, &comm ); 1254 IOLog("\nI2C read block[%x](%ld)\n", edidRequest[0], err); 1255 if (kIOReturnSuccess != err) 1256 break; 1257 IOLog(" 0 1 2 3 4 5 6 7 8 9 A B C D E F"); 1258 for (int i = 0; i < 128; i++) 1259 { 1260 if (0 == (i & 15)) 1261 IOLog("\n%02x: ", i); 1262 IOLog("%02x ", edidData[i]); 1263 } 1264 IOLog("\n"); 1265 if (edidRequest[0] || (0 == edidData[126])) 1266 break; 1267 edidRequest[0] = 0x80; 1268 } 1269 while (true); 1270 } 1271 } 1272 while (false); 1273#endif /* IONDRVI2CLOG */ 1274 1275 // duplicate QD InitGDevice 1276 _doStatus( this, cscGetCurMode, &switchInfo ); 1277 pageInfo.csMode = switchInfo.csMode; 1278 pageInfo.csData = 0; 1279 pageInfo.csPage = 0; 1280 _doControl( this, cscGrayPage, &pageInfo); 1281 1282 clutSetting = kSetClutAtSetEntries; 1283 lastClutSetting = clutSetting; 1284 __private->deferCLUTSet = (kIOReturnSuccess == 1285 _doControl( this, cscSetClutBehavior, &clutSetting)); 1286 1287 setInfoProperties(); 1288 1289 VDGetGammaListRec scan; 1290 GammaTbl * table; 1291 1292 err = _doStatus( this, cscGetGamma, &gammaRec ); 1293 table = (GammaTbl *) gammaRec.csGTable; 1294 if (table && (err == kIOReturnSuccess)) 1295 { 1296 __private->desiredGammaWidth = table->gDataWidth; 1297 __private->desiredGammaCount = table->gDataCnt; 1298 } 1299 else 1300 { 1301 __private->desiredGammaWidth = 8; 1302 __private->desiredGammaCount = (1 << 8); 1303 } 1304 1305 for (scan.csPreviousGammaTableID = kGammaTableIDFindFirst; 1306 ; 1307 scan.csPreviousGammaTableID = scan.csGammaTableID) 1308 { 1309 VDRetrieveGammaRec get; 1310 char name[ 64 ]; 1311 1312 scan.csGammaTableName = name; 1313 err = _doStatus( this, cscGetGammaInfoList, &scan); 1314 if (err || (scan.csGammaTableID == (GammaTableID) kGammaTableIDNoMoreTables)) 1315 break; 1316 1317 table = (GammaTbl *) IOMalloc(scan.csGammaTableSize); 1318 if (0 == table) 1319 continue; 1320 get.csGammaTableID = scan.csGammaTableID; 1321 get.csGammaTablePtr = table; 1322 1323 err = _doStatus( this, cscRetrieveGammaTable, &get ); 1324 if (noErr == err) 1325 { 1326 DEBG(thisName, " gamma %s: %d * %d\n", scan.csGammaTableName, 1327 table->gDataWidth, table->gDataCnt); 1328 if (((UInt32) table->gDataWidth) > __private->desiredGammaWidth) 1329 { 1330 __private->desiredGammaWidth = table->gDataWidth; 1331 __private->desiredGammaCount = table->gDataCnt; 1332 } 1333 } 1334 1335 IOFree( table, scan.csGammaTableSize); 1336 } 1337 1338 setProperty(kIOFBGammaWidthKey, __private->desiredGammaWidth, 32); 1339 setProperty(kIOFBGammaCountKey, __private->desiredGammaCount, 32); 1340 setProperty(kIOFBGammaHeaderSizeKey, sizeof32(GammaTbl) - sizeof32(table->gFormulaData), 32); 1341 } 1342 return (noErr); 1343} 1344 1345void IONDRVFramebuffer::setInfoProperties( void ) 1346{ 1347 IOReturn err; 1348 VDDisplayTimingRangeRec rangeRec; 1349 VDScalerInfoRec scalerRec; 1350 UInt32 probeOptions = 0; 1351 1352// UInt8 probeType[32]; 1353// if (noErr == _doStatus(this, cscProbeConnection, &probeType)) 1354 { 1355 probeOptions |= kIOFBUserRequestProbe; 1356 supportsProbe = true; 1357 } 1358 1359 removeProperty( kIOFBTimingRangeKey ); 1360 bzero( &rangeRec, sizeof( rangeRec)); 1361 rangeRec.csRangeSize = sizeof32( rangeRec); 1362 err = _doStatus( this, cscGetTimingRanges, &rangeRec ); 1363 if (kIOReturnSuccess == err) 1364 setProperty( kIOFBTimingRangeKey, &rangeRec, sizeof32( rangeRec)); 1365 1366 removeProperty( kIOFBScalerInfoKey ); 1367 bzero( &scalerRec, sizeof( scalerRec)); 1368 scalerRec.csScalerInfoSize = sizeof32( scalerRec); 1369 err = _doStatus( this, cscGetScalerInfo, &scalerRec ); 1370 if (kIOReturnSuccess == err) 1371 { 1372 setProperty( kIOFBScalerInfoKey, &scalerRec, sizeof32( scalerRec)); 1373 if (kScaleCanRotateMask & scalerRec.csScalerFeatures) 1374 probeOptions |= kIOFBSetTransform; 1375 } 1376 1377 if (probeOptions) 1378 setProperty( kIOFBProbeOptionsKey, probeOptions, 32); 1379 1380 nub->setProperty(kIONDRVDisplayConnectFlagsKey, 1381 &__private->displayConnectFlags, sizeof32(__private->displayConnectFlags)); 1382} 1383 1384UInt32 IONDRVFramebuffer::iterateAllModes( IODisplayModeID * displayModeIDs ) 1385{ 1386 VDResolutionInfoRec info; 1387 UInt32 num = 0; 1388 1389 info.csPreviousDisplayModeID = kDisplayModeIDFindFirstResolution; 1390 1391 while ( 1392 (noErr == _doStatus(this, cscGetNextResolution, &info)) 1393 && ((SInt32) info.csDisplayModeID > 0)) 1394 { 1395 if (displayModeIDs) 1396 displayModeIDs[ num ] = info.csDisplayModeID; 1397 1398 info.csPreviousDisplayModeID = info.csDisplayModeID; 1399 num++; 1400 } 1401 1402 return (num); 1403} 1404 1405IOIndex IONDRVFramebuffer::mapDepthIndex( 1406 IODisplayModeID modeID, IOIndex depth, bool fromDepthMode ) 1407{ 1408 VDVideoParametersInfoRec pixelParams; 1409 VPBlock pixelInfo; 1410 IOIndex mapped, index, lastDepth, lastIndex; 1411 IOReturn err; 1412 1413 if ((modeID == kDisplayModeIDPreflight) 1414 || (modeID != __private->depthMapModeID)) 1415 { 1416 lastDepth = kDepthMode1; 1417 lastIndex = 0; 1418 for (mapped = kDepthMode1, index = 0; mapped <= kDepthMode6; mapped++) 1419 { 1420 pixelParams.csDisplayModeID = modeID; 1421 pixelParams.csDepthMode = mapped; 1422 pixelParams.csVPBlockPtr = &pixelInfo; 1423 err = _doStatus( this, cscGetVideoParameters, &pixelParams ); 1424 if (kIOReturnSuccess == err) 1425 { 1426 __private->indexToDepthMode[index] = mapped; 1427 lastDepth = mapped; 1428 lastIndex = index; 1429 index++; 1430 } 1431 __private->depthModeToIndex[mapped - kDepthMode1] = lastIndex; 1432 } 1433 1434 for (; index <= (kDepthMode6 - kDepthMode1); index++) 1435 __private->indexToDepthMode[index] = lastDepth; 1436 1437 __private->depthMapModeID = modeID; 1438// DEBG(thisName, " cache miss for %08lx\n", modeID); 1439 } 1440 1441 if (fromDepthMode) 1442 { 1443 if (depth > kDepthMode6) 1444 depth = kDepthMode6; 1445 mapped = __private->depthModeToIndex[depth - kDepthMode1]; 1446 1447// DEBG(thisName, " mode %x -> index %x\n", depth, mapped); 1448 } 1449 else 1450 { 1451 if (depth > (kDepthMode6 - kDepthMode1)) 1452 depth = (kDepthMode6 - kDepthMode1); 1453 mapped = __private->indexToDepthMode[depth]; 1454 1455// DEBG(thisName, " index %x -> mode %x\n", depth, mapped); 1456 } 1457 1458 return (mapped); 1459} 1460 1461static IOFixed1616 1462DetailedRefreshRate(IODetailedTimingInformationV2 * detailed) 1463{ 1464 UInt64 pixelCount; 1465 pixelCount = ((detailed->verticalActive + detailed->verticalBlanking) 1466 * (detailed->horizontalActive + detailed->horizontalBlanking)); 1467 return (pixelCount ? ((detailed->pixelClock * 65536ULL) / pixelCount) : 0); 1468} 1469 1470IOReturn IONDRVFramebuffer::getResInfoForDetailed( 1471 IODisplayModeID modeID, 1472 VDDetailedTimingRec * detailed, 1473 IODisplayModeInformation * info ) 1474{ 1475 IODetailedTimingInformationV2 * desc = (IODetailedTimingInformationV2 *) detailed; 1476 1477 info->maxDepthIndex = mapDepthIndex(modeID, kDepthMode6, true); 1478// DEBG(thisName, " %x maxDepthIndex %x\n", modeID, info->maxDepthIndex); 1479 1480 if (desc->horizontalScaled && desc->verticalScaled) 1481 { 1482 info->nominalWidth = desc->horizontalScaled; 1483 info->nominalHeight = desc->verticalScaled; 1484 } 1485 else 1486 { 1487 info->nominalWidth = detailed->csHorizontalActive; 1488 info->nominalHeight = detailed->csVerticalActive; 1489 } 1490 info->refreshRate = DetailedRefreshRate(desc); 1491 1492 if (kIOInterlacedCEATiming & detailed->csSignalConfig) 1493 info->refreshRate *= 2; 1494 1495 return (kIOReturnSuccess); 1496} 1497 1498IOReturn IONDRVFramebuffer::getResInfoForArbMode( IODisplayModeID modeID, 1499 IODisplayModeInformation * info ) 1500{ 1501 IOReturn err; 1502 VDDetailedTimingRec * detailed; 1503 VDDetailedTimingRec _detailed; 1504 1505 if (modeID == kDisplayModeIDBootProgrammable) 1506 { 1507 detailed = &_detailed; 1508 bzero(detailed, sizeof(VDDetailedTimingRec)); 1509 detailed->csTimingSize = sizeof32(VDDetailedTimingRec); 1510 detailed->csDisplayModeID = kDisplayModeIDBootProgrammable; 1511 err = _doStatus(this, cscGetDetailedTiming, detailed); 1512 } 1513 else 1514 err = validateDisplayMode( modeID, 0, &detailed ); 1515 1516 if (kIOReturnSuccess == err) 1517 err = getResInfoForDetailed(modeID, detailed, info); 1518 1519 return (err); 1520} 1521 1522IOReturn IONDRVFramebuffer::getResInfoForMode( IODisplayModeID modeID, 1523 IODisplayModeInformation * info ) 1524{ 1525 bzero( info, sizeof( *info)); 1526 1527 if ((UInt32) modeID >= (UInt32) kDisplayModeIDReservedBase) 1528 return (getResInfoForArbMode(modeID, info)); 1529 1530 // unfortunately, there is no "kDisplayModeIDFindSpecific" 1531 if (cachedVDResolution.csDisplayModeID != modeID) 1532 { 1533 // try the next after cached mode 1534 cachedVDResolution.csPreviousDisplayModeID = cachedVDResolution.csDisplayModeID; 1535 if ((noErr != _doStatus(this, cscGetNextResolution, &cachedVDResolution)) 1536 || (cachedVDResolution.csDisplayModeID != modeID)) 1537 { 1538 // else full blown iterate 1539 cachedVDResolution.csPreviousDisplayModeID = kDisplayModeIDFindFirstResolution; 1540 while ( 1541 (noErr == _doStatus(this, cscGetNextResolution, &cachedVDResolution)) 1542 && (cachedVDResolution.csDisplayModeID != modeID) 1543 && ((SInt32) cachedVDResolution.csDisplayModeID > 0)) 1544 { 1545 cachedVDResolution.csPreviousDisplayModeID = cachedVDResolution.csDisplayModeID; 1546 } 1547 } 1548 } 1549 1550 if (cachedVDResolution.csDisplayModeID != modeID) 1551 { 1552 cachedVDResolution.csDisplayModeID = kDisplayModeIDInvalid; 1553 return (kIOReturnUnsupportedMode); 1554 } 1555 else 1556 { 1557 info->nominalWidth = cachedVDResolution.csHorizontalPixels; 1558 info->nominalHeight = cachedVDResolution.csVerticalLines; 1559 info->refreshRate = cachedVDResolution.csRefreshRate; 1560 1561 info->maxDepthIndex = mapDepthIndex(modeID, kDepthMode6, true); 1562// DEBG(thisName, " %x maxDepthIndex %x\n", modeID, info->maxDepthIndex); 1563 1564 return (noErr); 1565 } 1566} 1567 1568IOReturn IONDRVFramebuffer::setDetailedTiming( 1569 IODisplayModeID mode, IOOptionBits options, 1570 void * _desc, IOByteCount descripSize ) 1571{ 1572 IOReturn err; 1573 VDResolutionInfoRec info; 1574 IODetailedTimingInformationV2 * desc = (IODetailedTimingInformationV2 *)_desc; 1575 VDDetailedTimingRec look; 1576 VDDetailedTimingRec newTiming; 1577 VDSwitchInfoRec switchInfo; 1578 IOIndex index; 1579 UInt32 checkCurrent; 1580 UInt32 checkBoot; 1581 bool notPreflight = (0 == (options & kModePreflight)); 1582 bool hasScale; 1583 1584 index = arbMode2Index(mode); 1585 1586 bzero( &look, sizeof( VDDetailedTimingRec) ); 1587 look.csTimingSize = sizeof32( VDDetailedTimingRec); 1588 1589 // current must be ok 1590 if ((mode == currentDisplayMode) 1591 && notPreflight 1592 && (detailedTimingsCurrent[index] == detailedTimingsSeed)) 1593 { 1594 return (kIOReturnSuccess); 1595 } 1596 1597 err = _doStatus( this, cscGetCurMode, &switchInfo ); 1598 if ((err == noErr) && (switchInfo.csData == kDisplayModeIDBootProgrammable)) 1599 checkBoot = (UInt32) kDisplayModeIDBootProgrammable; 1600 else 1601 checkBoot = 0xffffffff; 1602 checkCurrent = (UInt32) currentDisplayMode; 1603 1604 // look for a programmable 1605 for ( 1606 info.csPreviousDisplayModeID = kDisplayModeIDFindFirstProgrammable; 1607 (noErr == (err = _doStatus(this, cscGetNextResolution, &info))); 1608 info.csPreviousDisplayModeID = info.csDisplayModeID) 1609 { 1610 if ((SInt32) info.csDisplayModeID < 0) 1611 { 1612 err = kIOReturnNoResources; 1613 break; 1614 } 1615 1616 look.csDisplayModeID = info.csDisplayModeID; 1617 err = _doStatus( this, cscGetDetailedTiming, &look ); 1618 if (err != kIOReturnSuccess) 1619 continue; 1620 1621 // don't toss current 1622 if (look.csDisplayModeAlias == checkCurrent) 1623 { 1624 checkCurrent = 0xffffffff; 1625 continue; 1626 } 1627 // don't toss kDisplayModeIDBootProgrammable if the driver is in that mode 1628 if (look.csDisplayModeAlias == checkBoot) 1629 { 1630 checkBoot = 0xffffffff; 1631 continue; 1632 } 1633 1634 // see if already set to the right timing 1635 if ((look.csDisplayModeAlias == (UInt32) mode) 1636 && (look.csDisplayModeState == kDMSModeReady) 1637 && (notPreflight) 1638 && (detailedTimingsCurrent[index] == detailedTimingsSeed)) 1639 break; 1640 1641 // set it free 1642 if (look.csDisplayModeState != kDMSModeFree) 1643 { 1644 look.csDisplayModeID = info.csDisplayModeID; 1645 look.csDisplayModeAlias = 0; 1646 look.csDisplayModeState = kDMSModeFree; 1647 err = _doControl( this, cscSetDetailedTiming, &look ); 1648 if (err != kIOReturnSuccess) 1649 continue; 1650 } 1651 1652 // set it 1653 hasScale = (desc->horizontalScaled && desc->verticalScaled); 1654 1655 1656 newTiming = *((VDDetailedTimingRec *) desc); 1657 newTiming.csTimingSize = sizeof32(VDDetailedTimingRec); 1658 newTiming.csDisplayModeID = info.csDisplayModeID; 1659 newTiming.csDisplayModeAlias = mode; 1660 newTiming.csDisplayModeSeed = look.csDisplayModeSeed; 1661 newTiming.csDisplayModeState = hasScale ? kDMSModeNotReady : kDMSModeReady; 1662 err = _doControl( this, cscSetDetailedTiming, &newTiming ); 1663 1664 if (hasScale && (kIOReturnSuccess == err)) 1665 { 1666 VDScalerRec scaler; 1667 1668 // set scale 1669 bzero( &scaler, sizeof( scaler)); 1670 scaler.csScalerSize = sizeof32( scaler); 1671 scaler.csScalerFlags = desc->scalerFlags; 1672 scaler.csHorizontalPixels = desc->horizontalScaled; 1673 scaler.csVerticalPixels = desc->verticalScaled; 1674 scaler.csHorizontalInset = desc->horizontalScaledInset; 1675 scaler.csVerticalInset = desc->verticalScaledInset; 1676 scaler.csDisplayModeID = info.csDisplayModeID; 1677 scaler.csDisplayModeSeed = newTiming.csDisplayModeSeed; 1678 scaler.csDisplayModeState = kDMSModeReady; 1679 1680 err = _doControl( this, cscSetScaler, &scaler ); 1681 1682 newTiming.csDisplayModeSeed = scaler.csDisplayModeSeed; 1683 } 1684 1685 if (kIOReturnSuccess == err) 1686 { 1687 err = _doStatus( this, cscGetDetailedTiming, &newTiming ); 1688 1689 if (!notPreflight && (kIOReturnSuccess == err)) 1690 { 1691 desc->signalConfig = newTiming.csSignalConfig; 1692 desc->signalLevels = newTiming.csSignalLevels; 1693 1694 desc->pixelClock = newTiming.csPixelClock; 1695 desc->minPixelClock = newTiming.csMinPixelClock; 1696 desc->maxPixelClock = newTiming.csMaxPixelClock; 1697 1698 desc->horizontalActive = newTiming.csHorizontalActive; 1699 desc->horizontalBlanking = newTiming.csHorizontalBlanking; 1700 desc->horizontalSyncOffset = newTiming.csHorizontalSyncOffset; 1701 desc->horizontalSyncPulseWidth = newTiming.csHorizontalSyncPulseWidth; 1702 1703 desc->verticalActive = newTiming.csVerticalActive; 1704 desc->verticalBlanking = newTiming.csVerticalBlanking; 1705 desc->verticalSyncOffset = newTiming.csVerticalSyncOffset; 1706 desc->verticalSyncPulseWidth = newTiming.csVerticalSyncPulseWidth; 1707 1708 desc->horizontalBorderLeft = newTiming.csHorizontalBorderLeft; 1709 desc->horizontalBorderRight = newTiming.csHorizontalBorderRight; 1710 desc->verticalBorderTop = newTiming.csVerticalBorderTop; 1711 desc->verticalBorderBottom = newTiming.csVerticalBorderBottom; 1712 1713 desc->horizontalSyncConfig = newTiming.csHorizontalSyncConfig; 1714 desc->horizontalSyncLevel = newTiming.csHorizontalSyncLevel; 1715 desc->verticalSyncConfig = newTiming.csVerticalSyncConfig; 1716 desc->verticalSyncLevel = newTiming.csVerticalSyncLevel; 1717 } 1718 } 1719 if (notPreflight && (kIOReturnSuccess == err)) 1720 detailedTimingsCurrent[index] = detailedTimingsSeed; 1721 1722 break; 1723 } 1724 1725 return (err); 1726} 1727 1728IOReturn IONDRVFramebuffer::validateDisplayMode( 1729 IODisplayModeID _mode, IOOptionBits flags, 1730 VDDetailedTimingRec ** detailed ) 1731{ 1732 UInt32 mode = _mode; 1733 IOReturn err = kIOReturnSuccess; 1734 OSData * data; 1735 const void * bytes; 1736 1737 if (detailed) 1738 *detailed = (VDDetailedTimingRec *) 0; 1739 1740 if (mode >= (UInt32) kDisplayModeIDReservedBase) 1741 { 1742 do 1743 { 1744 if (mode == (UInt32) kDisplayModeIDBootProgrammable) 1745 continue; 1746 1747 err = kIOReturnBadArgument; 1748 if (!detailedTimings) 1749 continue; 1750 1751 data = OSDynamicCast( OSData, detailedTimings->getObject( 1752 arbMode2Index(mode))); 1753 if (!data) 1754 continue; 1755 1756 bytes = data->getBytesNoCopy(); 1757 err = setDetailedTiming( mode, 0, (void *) bytes, data->getLength() ); 1758 if (err != kIOReturnSuccess) 1759 continue; 1760 1761 if (detailed) 1762 *detailed = (VDDetailedTimingRec *) bytes; 1763 } 1764 while (false); 1765 } 1766 1767 if (err) 1768 DEBG(thisName, " failed (%x) %x\n", (int32_t) mode, err); 1769 1770 return (err); 1771} 1772 1773void IONDRVFramebuffer::getCurrentConfiguration( void ) 1774{ 1775 IOReturn err; 1776 VDSwitchInfoRec switchInfo; 1777 VDTimingInfoRec timingInfo; 1778 VDGrayRecord grayRec; 1779 1780 grayRec.csMode = 0; // turn off luminance map 1781 err = _doControl( this, cscSetGray, &grayRec ); 1782 // driver refused => mono display 1783 grayMode = ((noErr == err) && (0 != grayRec.csMode)); 1784 1785#if 0 1786 VDPageInfo pageInfo; 1787 if (noErr == _doStatus(this, cscGetMode, &pageInfo)) 1788 { 1789 _doControl( this, cscSetMode, &pageInfo); 1790 _doControl( this, cscGrayPage, &pageInfo); 1791 } 1792#endif 1793 1794 err = _doStatus( this, cscGetCurMode, &switchInfo ); 1795 if (err != noErr) 1796 { 1797 DEBG(thisName, " cscGetCurMode failed\n"); 1798 } 1799 else 1800 { 1801 if ((kDisplayModeIDBootProgrammable != switchInfo.csData) || !currentDisplayMode) 1802 { 1803 currentDisplayMode = switchInfo.csData; 1804 } 1805 currentDepth = mapDepthIndex(currentDisplayMode, (IOIndex) switchInfo.csMode, true); 1806 currentPage = switchInfo.csPage; 1807 1808 timingInfo.csTimingMode = currentDisplayMode; 1809 timingInfo.csTimingFormat = kDeclROMtables; 1810 err = _doStatus( this, cscGetModeTiming, &timingInfo ); 1811 if ((noErr == err) && (kDeclROMtables == timingInfo.csTimingFormat)) 1812 __private->currentModeTiming = timingInfo.csTimingData; 1813 else 1814 __private->currentModeTiming = timingInvalid; 1815 1816 mach_vm_address_t vAddr = (mach_vm_address_t) switchInfo.csBaseAddr; 1817 ppnum_t page = 0; 1818 1819 1820 if (!vramMemory) 1821 vramMemory = getVRAMRange(); 1822 1823 if (vAddr) 1824 { 1825 if (vAddr & 1) page = atop_64(vAddr); 1826 else page = pmap_find_phys(kernel_pmap, vAddr); 1827 if (!page) panic("pmap_find_phys %qx", vAddr); 1828 __private->physicalFramebuffer = ptoa_64(page) + (PAGE_MASK & vAddr & ~1); 1829 } 1830 } 1831} 1832 1833IOReturn IONDRVFramebuffer::setupForCurrentConfig( void ) 1834{ 1835 getCurrentConfiguration(); 1836 return (super::setupForCurrentConfig()); 1837} 1838 1839IODeviceMemory * IONDRVFramebuffer::makeSubRange( 1840 IOPhysicalAddress64 start, 1841 IOPhysicalLength64 length ) 1842{ 1843 IOMemoryDescriptor * mem = 0; 1844 UInt32 numMaps, i; 1845 IOService * device; 1846 1847 device = nub; 1848 numMaps = device->getDeviceMemoryCount(); 1849 1850 for (i = 0; (!mem) && (i < numMaps); i++) 1851 { 1852 mem = device->getDeviceMemoryWithIndex(i); 1853 if (!mem) 1854 continue; 1855 1856 mem = IOSubMemoryDescriptor::withSubRange( 1857 mem, 1858 start - mem->getPhysicalSegment(0, 0, kIOMemoryMapperNone), 1859 length, kIODirectionNone); 1860 } 1861 if (!mem) 1862 mem = IOMemoryDescriptor::withAddressRange( 1863 start, length, kIODirectionNone | kIOMemoryMapperNone, NULL); 1864 1865 return ((IODeviceMemory *) mem); 1866} 1867 1868IODeviceMemory * IONDRVFramebuffer::getApertureRange( IOPixelAperture aper ) 1869{ 1870 IOReturn err; 1871 IOPixelInformation info; 1872 IOByteCount bytes; 1873 1874 if (!__private->physicalFramebuffer) 1875 return (NULL); 1876 1877 err = getPixelInformation( currentDisplayMode, currentDepth, aper, 1878 &info ); 1879 if (err) 1880 { 1881 DEBG(thisName, " getPixelInformation(%x) 0x%x\n", err, (uint32_t )currentDisplayMode); 1882 return (NULL); 1883 } 1884 1885 bytes = (info.bytesPerRow * info.activeHeight) + 128; 1886 1887 return (makeSubRange(__private->physicalFramebuffer, bytes)); 1888} 1889 1890IODeviceMemory * IONDRVFramebuffer::findVRAM( void ) 1891{ 1892 IOBootNDRV * bootndrv; 1893 if ((bootndrv = OSDynamicCast(IOBootNDRV, ndrv))) 1894 { 1895 bootndrv->fVRAMDesc->retain(); 1896 return ((IODeviceMemory *) bootndrv->fVRAMDesc); 1897 } 1898 1899 return (NULL); 1900} 1901 1902const char * IONDRVFramebuffer::getPixelFormats( void ) 1903{ 1904 static const char * ndrvPixelFormats = 1905 IO1BitIndexedPixels "\0" 1906 IO2BitIndexedPixels "\0" 1907 IO4BitIndexedPixels "\0" 1908 IO8BitIndexedPixels "\0" 1909 IO16BitDirectPixels "\0" 1910 IO32BitDirectPixels "\0" 1911 "\0"; 1912 1913 return (ndrvPixelFormats); 1914} 1915 1916IOItemCount IONDRVFramebuffer::getDisplayModeCount( void ) 1917{ 1918 return (iterateAllModes(0)); 1919} 1920 1921IOReturn IONDRVFramebuffer::getDisplayModes( IODisplayModeID * allDisplayModes ) 1922{ 1923 iterateAllModes( allDisplayModes ); 1924 return (kIOReturnSuccess); 1925} 1926 1927IOReturn IONDRVFramebuffer::validateDetailedTiming( 1928 void * _desc, IOByteCount descripSize ) 1929{ 1930 IOReturn err; 1931 1932 if (descripSize == sizeof(IOFBDisplayModeDescription)) 1933 { 1934 IOFBDisplayModeDescription * desc = (IOFBDisplayModeDescription *) _desc; 1935 VDDetailedTimingRec * detailed = (VDDetailedTimingRec *) &desc->timingInfo.detailedInfo.v2; 1936 1937 err = setDetailedTiming( kDisplayModeIDPreflight, 1938 kModePreflight, detailed, sizeof(VDDetailedTimingRec)); 1939 1940 if (kIOReturnSuccess == err) 1941 err = getResInfoForDetailed(kDisplayModeIDPreflight, detailed, &desc->info); 1942 } 1943 else 1944 err = setDetailedTiming( kDisplayModeIDPreflight, 1945 kModePreflight, _desc, descripSize); 1946 1947 return (err); 1948} 1949 1950IOReturn IONDRVFramebuffer::setDetailedTimings( OSArray * array ) 1951{ 1952 IOReturn err; 1953 UInt32 * newCurrent; 1954 IOItemCount newCount; 1955 1956 if (!array) 1957 { 1958 if (detailedTimings) 1959 { 1960 IODelete( detailedTimingsCurrent, UInt32, detailedTimings->getCount()); 1961 detailedTimingsCurrent = 0; 1962 } 1963 removeProperty( kIOFBDetailedTimingsKey ); 1964 detailedTimings = 0; 1965 detailedTimingsSeed++; 1966 return (kIOReturnSuccess); 1967 } 1968 1969 newCount = array->getCount(); 1970 newCurrent = IONew(UInt32, newCount); 1971 if (newCurrent) 1972 { 1973 if (detailedTimings) 1974 IODelete( detailedTimingsCurrent, UInt32, detailedTimings->getCount()); 1975 detailedTimingsCurrent = newCurrent; 1976 bzero( newCurrent, newCount * sizeof( UInt32)); 1977 setProperty( kIOFBDetailedTimingsKey, array ); // retains 1978 detailedTimings = array; 1979 detailedTimingsSeed++; 1980 1981// if (((UInt32) currentDisplayMode) >= ((UInt32) kDisplayModeIDReservedBase)) 1982 if (currentDisplayMode == kDisplayModeIDBootProgrammable) 1983 { 1984 VDDetailedTimingRec look; 1985 VDScalerRec scaler; 1986 IODetailedTimingInformationV2 * detailed; 1987 OSData * data; 1988 IODisplayModeID newDisplayMode; 1989 bool bootScaled; 1990 1991 newDisplayMode = currentDisplayMode; 1992 1993 bzero( &look, sizeof( VDDetailedTimingRec) ); 1994 look.csTimingSize = sizeof32( VDDetailedTimingRec); 1995 look.csDisplayModeID = currentDisplayMode; 1996 err = _doStatus( this, cscGetDetailedTiming, &look ); 1997 1998 bzero( &scaler, sizeof( VDScalerRec) ); 1999 scaler.csScalerSize = sizeof32( VDScalerRec); 2000 scaler.csDisplayModeID = currentDisplayMode; 2001 bootScaled = (noErr == _doStatus( this, cscGetScaler, &scaler )); 2002 2003 if (bootScaled 2004 && (scaler.csHorizontalPixels == look.csHorizontalActive) 2005 && (scaler.csVerticalPixels == look.csVerticalActive) 2006 && (!(kIOScaleRotateFlags & scaler.csScalerFlags)) 2007 && (!scaler.csHorizontalInset) 2008 && (!scaler.csVerticalInset)) 2009 { 2010 scaler.csHorizontalPixels = 0; 2011 scaler.csVerticalPixels = 0; 2012 scaler.csScalerFlags = 0; 2013 } 2014 2015 if (kIOReturnSuccess == err) 2016 { 2017 for (int i = 0; 2018 (data = OSDynamicCast(OSData, detailedTimings->getObject(i))); 2019 i++) 2020 { 2021 detailed = (IODetailedTimingInformationV2 *) data->getBytesNoCopy(); 2022 2023 if ((detailed->horizontalActive != look.csHorizontalActive) 2024 || (detailed->verticalActive != look.csVerticalActive)) 2025 continue; 2026 2027 if (!bootScaled || (!scaler.csHorizontalPixels && !scaler.csVerticalPixels)) 2028 { 2029 IOFixed1616 refreshRate1, refreshRate2; 2030 refreshRate1 = DetailedRefreshRate(detailed); 2031 refreshRate2 = DetailedRefreshRate((IODetailedTimingInformationV2 *) &look); 2032 refreshRate1 = (refreshRate1 + 0x8000) >> 16; 2033 refreshRate2 = (refreshRate2 + 0x8000) >> 16; 2034 if (refreshRate1 != refreshRate2) 2035 continue; 2036 } 2037 2038 if (bootScaled 2039 && ((detailed->horizontalScaled != scaler.csHorizontalPixels) 2040 || (detailed->verticalScaled != scaler.csVerticalPixels) 2041 || (detailed->horizontalScaledInset != scaler.csHorizontalInset) 2042 || (detailed->verticalScaledInset != scaler.csVerticalInset) 2043 || (detailed->scalerFlags != scaler.csScalerFlags))) 2044 continue; 2045 2046 newDisplayMode = detailed->detailedTimingModeID; 2047 break; 2048 } 2049 } 2050 2051 if (newDisplayMode != currentDisplayMode) 2052 { 2053 err = validateDisplayMode( newDisplayMode, 0, 0 ); 2054 currentDisplayMode = newDisplayMode; 2055 } 2056 } 2057 2058 err = kIOReturnSuccess; 2059 } 2060 else 2061 err = kIOReturnNoMemory; 2062 2063 return (err); 2064} 2065 2066IOReturn IONDRVFramebuffer::getInformationForDisplayMode( 2067 IODisplayModeID displayMode, IODisplayModeInformation * info ) 2068{ 2069 IOReturn err; 2070 2071 err = getResInfoForMode( displayMode, info ); 2072 if (err) 2073 err = kIOReturnUnsupportedMode; 2074 2075 return (err); 2076} 2077 2078 2079UInt64 IONDRVFramebuffer::getPixelFormatsForDisplayMode( 2080 IODisplayModeID /* displayMode */, IOIndex depthIndex ) 2081{ 2082 return (1 << depthIndex); 2083} 2084 2085IOReturn IONDRVFramebuffer::getPixelInformation( 2086 IODisplayModeID displayMode, IOIndex depth, 2087 IOPixelAperture aperture, IOPixelInformation * info ) 2088{ 2089 SInt32 err; 2090 VDVideoParametersInfoRec pixelParams; 2091 VPBlock pixelInfo; 2092 UInt32 pixelType; 2093 const char * pixelFormat; 2094 2095 2096 bzero( info, sizeof( *info)); 2097 2098 if (aperture) 2099 return (kIOReturnUnsupportedMode); 2100 2101 err = validateDisplayMode( displayMode, 0, 0 ); 2102 if (err) 2103 return (err); 2104 2105 do 2106 { 2107 pixelParams.csDisplayModeID = displayMode; 2108 pixelParams.csDepthMode = mapDepthIndex(displayMode, depth, false); 2109 pixelParams.csVPBlockPtr = &pixelInfo; 2110 err = _doStatus( this, cscGetVideoParameters, &pixelParams ); 2111 if (err) 2112 continue; 2113 2114 info->flags = accessFlags; 2115 2116 info->activeWidth = pixelInfo.vpBounds.right; 2117 info->activeHeight = pixelInfo.vpBounds.bottom; 2118#if __LP64__ 2119 info->bytesPerRow = pixelInfo.vpRowBytes; 2120#else 2121 info->bytesPerRow = pixelInfo.vpRowBytes & 0x7fff; 2122#endif 2123 info->bytesPerPlane = pixelInfo.vpPlaneBytes; 2124 info->bitsPerPixel = pixelInfo.vpPixelSize; 2125 2126 switch (pixelInfo.vpPixelSize / 8) 2127 { 2128 default: 2129 pixelInfo.vpPixelSize = 8; 2130 case 0: 2131 case 1: 2132 strlcpy(info->pixelFormat, IO8BitIndexedPixels, sizeof(info->pixelFormat)); 2133 info->pixelType = kIOCLUTPixels; 2134 info->componentMasks[0] = (1 << pixelInfo.vpPixelSize) - 1; 2135 info->bitsPerPixel = pixelInfo.vpPixelSize; 2136 info->componentCount = 1; 2137 info->bitsPerComponent = pixelInfo.vpPixelSize; 2138 break; 2139 2140 case 2: 2141 strlcpy(info->pixelFormat, IO16BitDirectPixels, sizeof(info->pixelFormat)); 2142 info->pixelType = kIORGBDirectPixels; 2143 info->componentMasks[0] = 0x7c00; 2144 info->componentMasks[1] = 0x03e0; 2145 info->componentMasks[2] = 0x001f; 2146 info->bitsPerPixel = 16; 2147 info->componentCount = 3; 2148 info->bitsPerComponent = 5; 2149 break; 2150 2151 case 4: 2152 case 8: 2153 info->bitsPerPixel = pixelInfo.vpPixelSize; 2154 info->componentCount = pixelInfo.vpCmpCount; 2155 info->bitsPerComponent = pixelInfo.vpCmpSize; 2156 2157 pixelType = kIORGBDirectPixels; 2158 switch (pixelInfo.vpPixelType) 2159 { 2160 case kIORGBSignedFloatingPointPixels: 2161 pixelType = pixelInfo.vpPixelType; 2162 if (info->bitsPerComponent == 16) 2163 pixelFormat = kIO16BitFloatPixels; 2164 else 2165 pixelFormat = kIO32BitFloatPixels; 2166 break; 2167 2168 case kIORGBSignedDirectPixels: 2169 pixelType = pixelInfo.vpPixelType; 2170 // fall thru 2171 default: 2172 if (info->bitsPerComponent == 10) 2173 pixelFormat = kIO30BitDirectPixels; 2174 else if (info->bitsPerComponent == 16) 2175 pixelFormat = kIO64BitDirectPixels; 2176 else 2177 pixelFormat = IO32BitDirectPixels; 2178 break; 2179 } 2180 2181 strlcpy(info->pixelFormat, pixelFormat, sizeof(info->pixelFormat)); 2182 info->pixelType = pixelType; 2183 2184 switch (info->bitsPerComponent) 2185 { 2186 default: 2187 case 8: 2188 info->componentMasks[0] = 0x00ff0000; 2189 info->componentMasks[1] = 0x0000ff00; 2190 info->componentMasks[2] = 0x000000ff; 2191 break; 2192 2193 case 10: 2194 info->componentMasks[0] = 0x3ff00000; 2195 info->componentMasks[1] = 0x000ffc00; 2196 info->componentMasks[2] = 0x000003ff; 2197 break; 2198 2199 case 16: 2200 info->componentMasks[0] = 0x0000ffff; 2201// info->componentMasks[1] = 0x00000000; 2202 2203// info->componentMasks[2] = 0x00000000; 2204 info->componentMasks[3] = 0xffff0000; 2205 2206// info->componentMasks[4] = 0x00000000; 2207 info->componentMasks[5] = 0x0000ffff; 2208 break; 2209 2210 case 32: 2211// info->componentMasks[0] = 0x00000000; 2212 info->componentMasks[1] = 0xffffffff; 2213// info->componentMasks[2] = 0x00000000; 2214// info->componentMasks[3] = 0x00000000; 2215 2216// info->componentMasks[4] = 0x00000000; 2217// info->componentMasks[5] = 0x00000000; 2218 info->componentMasks[6] = 0xffffffff; 2219// info->componentMasks[7] = 0x00000000; 2220 2221// info->componentMasks[8] = 0x00000000; 2222// info->componentMasks[9] = 0x00000000; 2223// info->componentMasks[10] = 0x00000000; 2224 info->componentMasks[11] = 0xffffffff; 2225 break; 2226 } 2227 break; 2228 } 2229 } 2230 while (false); 2231 2232 return (err); 2233} 2234 2235IOReturn IONDRVFramebuffer::getTimingInfoForDisplayMode( 2236 IODisplayModeID displayMode, IOTimingInformation * info ) 2237{ 2238 VDTimingInfoRec timingInfo; 2239 2240 OSStatus err; 2241 2242 err = validateDisplayMode( displayMode, 0, 0 ); 2243 if (err) 2244 return (err); 2245 2246 timingInfo.csTimingMode = displayMode; 2247 // in case the driver doesn't do it: 2248 timingInfo.csTimingFormat = kDeclROMtables; 2249 err = _doStatus( this, cscGetModeTiming, &timingInfo); 2250 if (err == noErr) 2251 { 2252 if (timingInfo.csTimingFormat == kDeclROMtables) 2253 info->appleTimingID = timingInfo.csTimingData; 2254 else 2255 info->appleTimingID = timingInvalid; 2256 2257 if (info->flags & kIODetailedTimingValid) 2258 { 2259 VDDetailedTimingRec * look = (VDDetailedTimingRec *) &info->detailedInfo.v2; 2260 VDScalerRec scaler; 2261 2262 bzero( look, sizeof( VDDetailedTimingRec) ); 2263 look->csTimingSize = sizeof32( VDDetailedTimingRec); 2264 look->csDisplayModeID = displayMode; 2265 err = _doStatus( this, cscGetDetailedTiming, look ); 2266 if (kIOReturnSuccess != err) 2267 info->flags &= ~kIODetailedTimingValid; 2268 else 2269 { 2270 bzero( &info->detailedInfo.v2.__reservedA[0], sizeof( info->detailedInfo.v2.__reservedA)); 2271 bzero( &info->detailedInfo.v2.__reservedB[0], sizeof( info->detailedInfo.v2.__reservedB)); 2272 2273 bzero( &scaler, sizeof( VDScalerRec) ); 2274 scaler.csScalerSize = sizeof32( VDScalerRec); 2275 scaler.csDisplayModeID = displayMode; 2276 err = _doStatus( this, cscGetScaler, &scaler ); 2277 if (kIOReturnSuccess == err) 2278 { 2279 info->flags |= kIOScalingInfoValid; 2280 info->detailedInfo.v2.scalerFlags = scaler.csScalerFlags; 2281 info->detailedInfo.v2.horizontalScaled = scaler.csHorizontalPixels; 2282 info->detailedInfo.v2.verticalScaled = scaler.csVerticalPixels; 2283 info->detailedInfo.v2.horizontalScaledInset = scaler.csHorizontalInset; 2284 info->detailedInfo.v2.verticalScaledInset = scaler.csVerticalInset; 2285 } 2286 else 2287 { 2288 info->detailedInfo.v2.scalerFlags = 0; 2289 info->detailedInfo.v2.horizontalScaled = 0; 2290 info->detailedInfo.v2.verticalScaled = 0; 2291 } 2292 } 2293 } 2294 2295 return (kIOReturnSuccess); 2296 } 2297 2298 return (kIOReturnUnsupportedMode); 2299} 2300 2301IOReturn IONDRVFramebuffer::getCurrentDisplayMode( 2302 IODisplayModeID * displayMode, IOIndex * depth ) 2303{ 2304 if (displayMode) 2305 *displayMode = currentDisplayMode; 2306 if (depth) 2307 *depth = currentDepth; 2308 2309 return (kIOReturnSuccess); 2310} 2311 2312IOReturn IONDRVFramebuffer::setDisplayMode( IODisplayModeID displayMode, IOIndex depth ) 2313{ 2314 SInt32 err; 2315 VDSwitchInfoRec switchInfo; 2316 VDPageInfo pageInfo; 2317 VDTimingInfoRec timingInfo; 2318 UInt32 timingID; 2319 2320 if (0 == powerState) 2321 return (kIOReturnNotReady); 2322 2323 timingInfo.csTimingMode = displayMode; 2324 timingInfo.csTimingFormat = kDeclROMtables; 2325 err = _doStatus( this, cscGetModeTiming, &timingInfo ); 2326 if ((noErr == err) && (kDeclROMtables == timingInfo.csTimingFormat)) 2327 timingID = timingInfo.csTimingData; 2328 else 2329 timingID = timingInvalid; 2330 2331#if 1 2332 if (!online && (timingApple_0x0_0hz_Offline != timingID)) 2333 { 2334 DEBG(thisName, " offline\n"); 2335 return (kIOReturnSuccess); 2336 } 2337#endif 2338 2339 err = validateDisplayMode( displayMode, 0, 0 ); 2340 if (err) 2341 return (err); 2342 2343 switchInfo.csData = displayMode; 2344 switchInfo.csMode = mapDepthIndex(displayMode, depth, false); 2345 switchInfo.csPage = 0; 2346 err = _doControl( this, cscSwitchMode, &switchInfo); 2347 if (err) 2348 DEBG(thisName, " %d: cscSwitchMode(0x%08x) %d\n", 2349 online, (int32_t) displayMode, (int) err); 2350 2351 // duplicate QD InitGDevice 2352 pageInfo.csMode = switchInfo.csMode; 2353 pageInfo.csData = 0; 2354 pageInfo.csPage = 0; 2355 _doControl( this, cscSetMode, &pageInfo); 2356 2357#if 0 2358 if (mirrored) 2359 { 2360 VDGammaRecord gammaRec; 2361 OSStatus gammaErr; 2362 2363 gammaErr = _doStatus( this, cscGetGamma, &gammaRec ); 2364 if (noErr == gammaErr) 2365 _doControl( this, cscSetGamma, &gammaRec ); 2366 else 2367 _doControl( this, cscGrayPage, &pageInfo); 2368 } 2369 else 2370 _doControl( this, cscGrayPage, &pageInfo); 2371#endif 2372 2373 return (err); 2374} 2375 2376IOReturn IONDRVFramebuffer::setStartupDisplayMode( 2377 IODisplayModeID displayMode, IOIndex depth ) 2378{ 2379 SInt32 err; 2380 VDSwitchInfoRec switchInfo; 2381 2382 err = validateDisplayMode( displayMode, 0, 0 ); 2383 if (err) 2384 return (err); 2385 2386 switchInfo.csData = displayMode; 2387 switchInfo.csMode = mapDepthIndex(displayMode, depth, false); 2388 err = _doControl( this, cscSavePreferredConfiguration, &switchInfo); 2389 return (err); 2390} 2391 2392IOReturn IONDRVFramebuffer::getStartupDisplayMode( 2393 IODisplayModeID * displayMode, IOIndex * depth ) 2394{ 2395 SInt32 err; 2396 VDSwitchInfoRec switchInfo; 2397 2398 err = _doStatus( this, cscGetPreferredConfiguration, &switchInfo); 2399 if (err == noErr) 2400 { 2401 *displayMode = switchInfo.csData; 2402 *depth = mapDepthIndex(switchInfo.csData, (IOIndex) switchInfo.csMode, true); 2403 } 2404 return (err); 2405} 2406 2407IOReturn IONDRVFramebuffer::setApertureEnable( IOPixelAperture /* aperture */, 2408 IOOptionBits /* enable */ ) 2409{ 2410 return (kIOReturnSuccess); 2411} 2412 2413IOReturn IONDRVFramebuffer::setCLUTWithEntries( 2414 IOColorEntry * colors, UInt32 index, UInt32 numEntries, 2415 IOOptionBits options ) 2416{ 2417 IOReturn err; 2418 VDSetEntryRecord setEntryRec; 2419 VDClutBehavior clutSetting; 2420 VDGrayRecord grayRec; 2421 2422 if (0 == powerState) 2423 return (kIOReturnSuccess); 2424 2425 if (options & kSetCLUTWithLuminance) 2426 grayRec.csMode = 1; // turn on luminance map 2427 else 2428 grayRec.csMode = 0; // turn off luminance map 2429 2430 if (grayRec.csMode != lastGrayMode) 2431 { 2432 _doControl( this, cscSetGray, &grayRec); 2433 lastGrayMode = grayRec.csMode; 2434 } 2435 2436 if (options & kSetCLUTImmediately) 2437 clutSetting = kSetClutAtSetEntries; 2438 else 2439 clutSetting = kSetClutAtVBL; 2440 2441 if (clutSetting != lastClutSetting) 2442 { 2443 _doControl( this, cscSetClutBehavior, &clutSetting); 2444 lastClutSetting = clutSetting; 2445 } 2446 2447 if (options & kSetCLUTByValue) 2448 setEntryRec.csStart = -1; 2449 else 2450 setEntryRec.csStart = index; 2451 2452 setEntryRec.csTable = (ColorSpec *) colors; 2453 setEntryRec.csCount = numEntries - 1; 2454 err = _doControl( this, cscSetEntries, &setEntryRec); 2455 2456 return (err); 2457} 2458 2459IOReturn IONDRVFramebuffer::setGammaTable( 2460 UInt32 channelCount, UInt32 dataCount, 2461 UInt32 dataWidth, void * data ) 2462{ 2463 IOReturn err; 2464 VDClutBehavior clutSetting; 2465 VDGammaRecord gammaRec; 2466 GammaTbl * table = (GammaTbl *) data; 2467 2468 if (0 == powerState) 2469 return (kIOReturnSuccess); 2470 if (!data) 2471 return (kIOReturnBadArgument); 2472 2473 if (__private->deferCLUTSet) 2474 { 2475 clutSetting = kSetClutAtSetEntries; 2476 if (clutSetting != lastClutSetting) 2477 { 2478 _doControl( this, cscSetClutBehavior, &clutSetting); 2479 lastClutSetting = clutSetting; 2480 } 2481 } 2482 2483 table->gVersion = 0; 2484 table->gType = 0; 2485 table->gFormulaSize = 0; 2486 table->gChanCnt = channelCount; 2487 table->gDataCnt = dataCount; 2488 table->gDataWidth = dataWidth; 2489 2490 gammaRec.csGTable = (Ptr) table; 2491 err = _doControl( this, cscSetGamma, &gammaRec ); 2492 2493 if (kIOReturnSuccess != err) 2494 DEBG(thisName, " cscSetGamma(%d, %d, %d) set: %d\n", 2495 (uint32_t) channelCount, (uint32_t) dataCount, (uint32_t) dataWidth, err); 2496 2497 return (err); 2498} 2499 2500IOReturn IONDRVFramebuffer::setMirror( IONDRVFramebuffer * other ) 2501{ 2502 IOReturn err = kIOReturnSuccess; 2503// IONDRVFramebuffer * next; 2504 VDMirrorRec mirror; 2505 2506 if (mirrored == (other != 0)) 2507 return (kIOReturnSuccess); 2508 2509 if (!nextDependent) 2510 return (kIOReturnUnsupported); 2511// if (other && (other != nextDependent)) 2512// return (kIOReturnUnsupported); 2513 2514 do 2515 { 2516 bzero( &mirror, sizeof( mirror)); 2517 mirror.csMirrorSize = sizeof32(VDMirrorRec); 2518 mirror.csMirrorFlags = 0 2519 | kMirrorCanMirrorMask 2520 | kMirrorAreMirroredMask 2521 | kMirrorUnclippedMirrorMask 2522 | kMirrorClippedMirrorMask 2523 | kMirrorHAlignCenterMirrorMask 2524 | kMirrorVAlignCenterMirrorMask; 2525 MAKE_REG_ENTRY( (RegEntryID *)&mirror.csMirrorResultID, 0 ); 2526 if (0 == other) 2527 { 2528 MAKE_REG_ENTRY( ((RegEntryID *)&mirror.csMirrorRequestID), 0 ); 2529 } 2530 else 2531 { 2532 MAKE_REG_ENTRY( ((RegEntryID *)&mirror.csMirrorRequestID), other->getProvider() ); 2533 } 2534 2535 err = _doControl( this, cscSetMirror, &mirror ); 2536 if (err) 2537 continue; 2538 2539 mirrored = (other != 0); 2540// if ((next = OSDynamicCast(IONDRVFramebuffer, nextDependent))) 2541// next->setMirror( (other != 0) ? this : 0 ); 2542 } 2543 while (false); 2544 2545 return (err); 2546} 2547 2548 2549IOReturn IONDRVFramebuffer::setAttribute( IOSelect attribute, uintptr_t _value ) 2550{ 2551 IOReturn err = kIOReturnSuccess; 2552 IONDRVFramebuffer * other = 0; 2553 uintptr_t * data = (uintptr_t *) _value; 2554 UInt32 value; 2555 2556 switch (attribute) 2557 { 2558 case kIOPowerStateAttribute: 2559 err = ndrvSetPowerState( (UInt32)_value ); 2560 break; 2561 2562 case kIODriverPowerAttribute: 2563 err = ndrvSetPowerState( (UInt32)_value ); 2564 break; 2565 2566 case kIOSystemPowerAttribute: 2567 switch (_value) 2568 { 2569 case kIOMessageSystemWillPowerOff: 2570 if ((kIODVIPowerEnableFlag & __private->displayConnectFlags) && powerState) 2571 { 2572 err = ndrvGetSetFeature( kDVIPowerSwitchFeature, 0, NULL ); 2573 if (kIOReturnSuccess == err) 2574 IOSleep( kDVIPowerSwitchPowerOffDelay ); 2575 } 2576 /* fall thru */ 2577 case kIOMessageSystemWillRestart: 2578 if (ndrvState && powerState) 2579 { 2580 IONDRVControlParameters pb; 2581 2582 err = doDriverIO( 0, &pb, 2583 kIONDRVCloseCommand, kIONDRVImmediateIOCommandKind ); 2584 err = doDriverIO( 0, nub, 2585 kIONDRVFinalizeCommand, kIONDRVImmediateIOCommandKind ); 2586 ndrvState = 0; 2587 2588 DEBG(thisName, " kIOSystemPowerAttribute finalize(%d)\n", err); 2589 } 2590 } 2591 err = kIOReturnSuccess; 2592 break; 2593 2594 case kIOFBSpeedAttribute: 2595 __private->reducedSpeed = (UInt32) _value; 2596 if (powerState) 2597 err = ndrvUpdatePowerState(); 2598 break; 2599 2600 case kIOMirrorAttribute: 2601 2602 do 2603 { 2604 value = data[0] & 1; 2605 if (value) 2606 { 2607 other = OSDynamicCast( IONDRVFramebuffer, (OSObject *) data[1] ); 2608 if (!other) 2609 { 2610 err = kIOReturnBadArgument; 2611 continue; 2612 } 2613 } 2614 2615 err = setMirror( other ); 2616 if (kIOReturnSuccess != err) 2617 continue; 2618 2619 OSNumber * num = OSDynamicCast(OSNumber, getProperty(kIOFBDependentIndexKey)); 2620 mirrorPrimary = mirrored && (!num || (1 == num->unsigned32BitValue())); 2621 2622// (void) setDisplayMode( currentDisplayMode, currentDepth ); 2623 } 2624 while (false); 2625 2626 break; 2627 2628 default: 2629 err = super::setAttribute( attribute, _value ); 2630 } 2631 2632 return (err); 2633} 2634 2635IOReturn IONDRVFramebuffer::getAttribute( IOSelect attribute, uintptr_t * value ) 2636{ 2637 IOReturn err = kIOReturnSuccess; 2638 VDSupportsHardwareCursorRec hwCrsrSupport; 2639 VDMirrorRec mirror; 2640 IONDRVFramebuffer * other; 2641 2642 switch (attribute) 2643 { 2644 case kIOHardwareCursorAttribute: 2645 2646 UInt32 flags; 2647 2648 hwCrsrSupport.csReserved1 = 0; 2649 hwCrsrSupport.csReserved2 = 0; 2650 flags = ((kIOReturnSuccess == _doStatus( this, cscSupportsHardwareCursor, &hwCrsrSupport)) 2651 && true && (hwCrsrSupport.csSupportsHardwareCursor)) 2652 ? kIOFBHWCursorSupported : 0; 2653 if (flags) 2654 flags |= (hwCrsrSupport.csReserved1 & ~kIOFBHWCursorSupported); 2655 *value = flags; 2656 break; 2657 2658 case kIODeferCLUTSetAttribute: 2659 2660 *value = __private->deferCLUTSet; 2661 break; 2662 2663 case kIOMirrorAttribute: 2664 2665 bzero( &mirror, sizeof( mirror)); 2666 mirror.csMirrorSize = sizeof32(VDMirrorRec); 2667 2668 other = OSDynamicCast( IONDRVFramebuffer, (OSObject *) value[0] ); 2669 if (other) 2670 { 2671 MAKE_REG_ENTRY( ((RegEntryID *)&mirror.csMirrorRequestID), other->getProvider() ); 2672 } 2673 else 2674 { 2675 MAKE_REG_ENTRY( ((RegEntryID *)&mirror.csMirrorRequestID), 0 ); 2676 } 2677 err = _doStatus( this, cscGetMirror, &mirror ); 2678 value[0] = mirror.csMirrorSupportedFlags; 2679 2680 if (kIOReturnSuccess == err) 2681 { 2682 OSNumber * num = OSDynamicCast(OSNumber, getProperty(kIOFBDependentIndexKey)); 2683 if (!num || (1 == num->unsigned32BitValue())) 2684 value[0] |= kIOMirrorIsPrimary; 2685 2686 if (kMirrorClippedMirrorMask & mirror.csMirrorSupportedFlags) 2687 value[0] |= kIOMirrorHWClipped; 2688 2689 do 2690 { 2691 VDVideoParametersInfoRec pixelParams; 2692 VPBlock pixelInfo; 2693 IODisplayModeInformation modeInfo; 2694 IOReturn err; 2695 2696 pixelParams.csDisplayModeID = currentDisplayMode; 2697 pixelParams.csDepthMode = mapDepthIndex(currentDisplayMode, currentDepth, false); 2698 pixelParams.csVPBlockPtr = &pixelInfo; 2699 err = _doStatus( this, cscGetVideoParameters, &pixelParams ); 2700 if (err) 2701 continue; 2702 err = getResInfoForMode( currentDisplayMode, &modeInfo ); 2703 if (err) 2704 continue; 2705 if ((modeInfo.nominalWidth != (UInt32) pixelInfo.vpBounds.right) 2706 || (modeInfo.nominalHeight != (UInt32) pixelInfo.vpBounds.bottom)) 2707 value[0] |= kIOMirrorHWClipped; 2708 } 2709 while (false); 2710 2711 DEBG(thisName, " kIOMirrorAttribute %08lx csMirrorSupportedFlags %08x, csMirrorFeatures %08x\n", 2712 value[0], (uint32_t) mirror.csMirrorSupportedFlags, (uint32_t) mirror.csMirrorFeatures); 2713 2714 err = kIOReturnSuccess; 2715 } 2716 break; 2717 2718 case kIOMirrorDefaultAttribute: 2719 { 2720 IORegistryEntry * entry; 2721 IORegistryEntry * root; 2722 IONDRVFramebuffer * next; 2723 OSNumber * num; 2724 OSData * data = 0; 2725 enum { kIOMirrorHint = 0x10000 }; 2726 2727 num = OSDynamicCast(OSNumber, getProperty("graphic-options")); 2728 if (num) 2729 value[0] = num->unsigned32BitValue(); 2730 else 2731 { 2732 value[0] = 0; 2733 2734 data = OSDynamicCast(OSData, nub->getProperty("graphic-options")); 2735 if (!data && (root = IORegistryEntry::fromPath("/", gIODTPlane))) 2736 { 2737 data = OSDynamicCast(OSData, root->getProperty("graphic-options")); 2738 root->release(); 2739 } 2740 2741 if (data) 2742 value[0] = *((UInt32 *) data->getBytesNoCopy()); 2743 else if ((entry = IORegistryEntry::fromPath("mac-io/battery", gIODTPlane)) 2744 || (entry = IORegistryEntry::fromPath("mac-io/via-pmu/battery", gIODTPlane))) 2745 { 2746 value[0] &= ~kIOMirrorDefault; 2747 entry->release(); 2748 } 2749 setProperty("graphic-options", value[0], 32); 2750 } 2751 2752 if (online 2753 && (kIOMirrorDefault & value[0]) 2754 && (next = OSDynamicCast(IONDRVFramebuffer, nextDependent)) 2755 && next->getOnlineState()) 2756 value[0] |= kIOMirrorHint; 2757 err = kIOReturnSuccess; 2758 break; 2759 } 2760 2761 case kIOVRAMSaveAttribute: 2762 DEBG1(thisName, " kIOVRAMSaveAttribute on(%d), mirr(%d), prim(%d)\n", 2763 online, mirrored, mirrorPrimary ); 2764 *value = (online && (!mirrored || !mirrorPrimary)); 2765 break; 2766 2767 default: 2768 err = super::getAttribute( attribute, value ); 2769 } 2770 2771 return (err); 2772} 2773 2774UInt32 IONDRVFramebuffer::getConnectionCount( void ) 2775{ 2776 VDMultiConnectInfoRec multiConnection; 2777 2778 multiConnection.csDisplayCountOrNumber = kGetConnectionCount; 2779 if (noErr == _doStatus(this, cscGetMultiConnect, &multiConnection)) 2780 return (multiConnection.csDisplayCountOrNumber); 2781 else 2782 return (1); 2783} 2784 2785/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2786 2787IOReturn IONDRVFramebuffer::createI2C( void ) 2788{ 2789 IOReturn err; 2790 VDCommunicationInfoRec commInfo; 2791 SInt32 busID, minBus, maxBus; 2792 OSArray * array; 2793 OSDictionary * dict; 2794 bool ok = false; 2795 2796 array = OSArray::withCapacity(1); 2797 if (!array) 2798 return (kIOReturnNoMemory); 2799 2800 do 2801 { 2802 bzero( &commInfo, sizeof( commInfo)); 2803 commInfo.csBusID = kVideoDefaultBus; 2804 2805 err = _doStatus( this, cscGetCommunicationInfo, &commInfo ); 2806 DEBG(thisName, " cscGetCommunicationInfo(%d): csBusType %x, csMinBus %x, csMaxBus %x\n" 2807 "csSupportedTypes %x, csSupportedCommFlags %x\n", 2808 err, (uint32_t) commInfo.csBusType, 2809 (uint32_t) commInfo.csMinBus, (uint32_t) commInfo.csMaxBus, 2810 (uint32_t) commInfo.csSupportedTypes, (uint32_t) commInfo.csSupportedCommFlags); 2811 2812 if (kIOReturnSuccess != err) 2813 continue; 2814 2815 minBus = commInfo.csMinBus; 2816 maxBus = commInfo.csMaxBus; 2817 if (maxBus < minBus) 2818 continue; 2819 for (busID = minBus; 2820 busID <= maxBus; 2821 busID++) 2822 { 2823 bzero(&commInfo, sizeof(commInfo)); 2824 commInfo.csBusID = busID; 2825 err = _doStatus(this, cscGetCommunicationInfo, &commInfo); 2826 if (kIOReturnSuccess != err) 2827 break; 2828 2829 dict = OSDictionary::withCapacity(4); 2830 if (!dict) 2831 break; 2832 2833 setNumber(dict, kIOI2CInterfaceIDKey, busID); 2834 setNumber(dict, kIOI2CBusTypeKey, commInfo.csBusType); 2835 setNumber(dict, kIOI2CTransactionTypesKey, commInfo.csSupportedTypes); 2836 setNumber(dict, kIOI2CSupportedCommFlagsKey, commInfo.csSupportedCommFlags); 2837 array->setObject(dict); 2838 dict->release(); 2839 } 2840 2841 ok = (busID > maxBus); 2842 } 2843 while (false); 2844 2845 if (ok) 2846 setProperty(kIOFBI2CInterfaceInfoKey, array); 2847 2848 array->release(); 2849 2850 return (kIOReturnSuccess); 2851} 2852 2853IOReturn IONDRVFramebuffer::doI2CRequest( UInt32 bus, IOI2CBusTiming * timing, IOI2CRequest * request ) 2854{ 2855 IOReturn err; 2856 VDCommunicationRec comm; 2857 2858 bzero( &comm, sizeof( comm)); 2859 2860 do 2861 { 2862 comm.csBusID = bus; 2863 comm.csCommFlags = request->commFlags; 2864 2865 comm.csMinReplyDelay = request->minReplyDelay * 1000; // ms -> us 2866 if (comm.csMinReplyDelay) 2867 comm.csCommFlags |= kVideoReplyMicroSecDelayMask; 2868 2869 if (kIOI2CUseSubAddressCommFlag & request->commFlags) 2870 comm.csSendAddress = (request->sendAddress << 8) | request->sendSubAddress; 2871 else 2872 comm.csSendAddress = request->sendAddress; 2873 2874 comm.csSendType = request->sendTransactionType; 2875 comm.csSendBuffer = (LogicalAddress) request->sendBuffer; 2876 comm.csSendSize = request->sendBytes; 2877 2878 if (kIOI2CUseSubAddressCommFlag & request->commFlags) 2879 comm.csReplyAddress = (request->replyAddress << 8) | request->replySubAddress; 2880 else 2881 comm.csReplyAddress = request->replyAddress; 2882 2883 comm.csReplyType = request->replyTransactionType; 2884 comm.csReplyBuffer = (LogicalAddress) request->replyBuffer; 2885 comm.csReplySize = request->replyBytes; 2886 2887 err = _doControl(this, cscDoCommunication, &comm); 2888 } 2889 while (false); 2890 2891 switch (err) 2892 { 2893 case kVideoI2CReplyPendingErr: 2894 err = kIOReturnNoCompletion; 2895 break; 2896 case kVideoI2CTransactionErr: 2897 err = kIOReturnNoDevice; 2898 break; 2899 case kVideoI2CBusyErr: 2900 err = kIOReturnBusy; 2901 break; 2902 case kVideoI2CTransactionTypeErr: 2903 err = kIOReturnUnsupportedMode; 2904 break; 2905 case kVideoBufferSizeErr: 2906 err = kIOReturnOverrun; 2907 break; 2908 } 2909 2910 request->result = err; 2911 if (request->completion) 2912 (*request->completion)(request); 2913 2914 err = kIOReturnSuccess; 2915 2916 return (err); 2917} 2918 2919/* 2920 File: DDCPowerOnOffUtils.c <CS3> 2921*/ 2922 2923enum{ 2924 kVCPSendSize = 8, 2925 kVCPReplySize = 64, 2926 kI2CDisplayWriteAddress = 0x6E, 2927 kI2CDisplayReadAddress = 0x6F, 2928 // Messed up specification says checksum should be calculated with ACCESS.bus value of 50. 2929 kI2CDisplayReadHostCheckSumAddress = 0x50, 2930 // Messed up specification says checksum should be calculated with ACCESS.bus value of 50. 2931 kI2CDisplayReadHostAddress = 0x51, 2932 2933 kI2CVCPGetCode = 0x01, 2934 kI2CVCPGetLength = 0x82, 2935 kI2CVCPGetMessageSize = 0x05, 2936 2937 kI2CVCPReplyLength = 0x88, 2938 kI2CNullReplyLength = 0x80, 2939 kI2CNullReplyCheckSum = 0xBE, 2940 2941 kI2CVCPSetCode = 0x03, 2942 kI2CVCPSetLength = 0x84, 2943 kI2CVCPReplyCode = 0x02, 2944 2945 kDDCPowerOn = 0x01, 2946 kDDCPowerOff = 0x04 2947}; 2948enum { 2949 kBasicI2CCommTransactionsMask = ( (1<<kVideoNoTransactionType) | (1<<kVideoSimpleI2CType) 2950 | (1<<kVideoDDCciReplyType) ) 2951}; 2952 2953void IONDRVFramebuffer::displayI2CPower( bool enable ) 2954{ 2955 VDCommunicationRec i2CRecord; 2956 VDCommunicationInfoRec i2cInfoRecord; 2957 Byte sendBuffer[8]; 2958 Byte replyBuffer[kVCPReplySize]; 2959 UInt32 supportedCommFlags = 0; 2960 // Don't do it if we're told it's not supported 2961 bool setThisDisplay = true; 2962 2963 if (enable == __private->i2cPowerState) 2964 return; 2965 2966 __private->i2cPowerState = enable; 2967 2968 // 2969 // Some displays (like Fiji) do not support the reading 2970 // of the current power state. Others (like Mitsubishi 2971 // Diamond Pro 710) report that they do not support 2972 // power management calls. 2973 // 2974 // I'll avoid sending the power command only in the 2975 // case that I get a valid reply that does says 2976 // it does not support the power selector. 2977 // 2978 2979 bzero( &i2cInfoRecord, sizeof(i2cInfoRecord) ); 2980 if (noErr != _doStatus(this, cscGetCommunicationInfo, &i2cInfoRecord)) 2981 return ; 2982 if (kBasicI2CCommTransactionsMask != (i2cInfoRecord.csSupportedTypes & kBasicI2CCommTransactionsMask)) 2983 return ; 2984 2985 supportedCommFlags = i2cInfoRecord.csSupportedCommFlags; 2986 bzero( &i2CRecord, sizeof(i2CRecord) ); 2987 bzero( &sendBuffer, sizeof(sendBuffer) ); 2988 bzero( &replyBuffer, sizeof(replyBuffer) ); 2989 2990 sendBuffer[0] = kI2CDisplayReadHostAddress; 2991 sendBuffer[1] = kI2CVCPGetLength; 2992 sendBuffer[2] = kI2CVCPGetCode; // GetVCP command 2993 sendBuffer[3] = 0xD6; 2994 sendBuffer[4] = kI2CDisplayWriteAddress ^ 2995 sendBuffer[0] ^ sendBuffer[1] ^ 2996 sendBuffer[2] ^ sendBuffer[3]; 2997 2998 i2CRecord.csBusID = kVideoDefaultBus; 2999 i2CRecord.csSendType = kVideoSimpleI2CType; 3000 i2CRecord.csSendAddress = kI2CDisplayWriteAddress; 3001 i2CRecord.csSendBuffer = &sendBuffer; 3002 i2CRecord.csSendSize = 7; 3003 i2CRecord.csReplyType = kVideoDDCciReplyType; 3004 i2CRecord.csReplyAddress = kI2CDisplayReadAddress; 3005 i2CRecord.csReplyBuffer = &replyBuffer; 3006 i2CRecord.csReplySize = kVCPReplySize; 3007 3008 if (supportedCommFlags & kVideoReplyMicroSecDelayMask) 3009 { 3010 // We know some displays are slow, this is an important call to get right 3011 i2CRecord.csCommFlags |= kVideoReplyMicroSecDelayMask; 3012 // 50 milliseconds should be enough time for the display to respond. 3013 i2CRecord.csMinReplyDelay = 50 * 1000; 3014 } 3015 3016 if ((noErr == _doControl(this, cscDoCommunication, &i2CRecord)) 3017 && (kI2CDisplayWriteAddress == replyBuffer[0]) 3018 && (kI2CVCPReplyLength == replyBuffer[1]) 3019 && (kI2CVCPReplyCode == replyBuffer[2])) 3020 { 3021 Byte checkSum = kI2CDisplayReadHostCheckSumAddress ^ // host address 3022 replyBuffer[0] ^ // source address 3023 replyBuffer[1] ^ // message length (0x88) 3024 replyBuffer[2] ^ // VCP type code 3025 replyBuffer[3] ^ // result code 3026 replyBuffer[4] ^ // VCP op code 3027 replyBuffer[5] ^ // VCP type code 3028 replyBuffer[6] ^ // Max value MSB 3029 replyBuffer[7] ^ // Max value LSB 3030 replyBuffer[8] ^ // Current value MSB 3031 replyBuffer[9]; // Current value LSB 3032 3033 if ((checkSum == replyBuffer[10]) && // Did the check sum match AND 3034 (0 != replyBuffer[3])) // Are we not supposed to support this feature? 3035 setThisDisplay = false; // Don't do it if we're told it's not supported 3036 } 3037 3038 if (setThisDisplay) 3039 { 3040 bzero( &i2CRecord, sizeof(i2CRecord) ); 3041 bzero( &sendBuffer, sizeof(sendBuffer) ); 3042 bzero( &replyBuffer, sizeof(replyBuffer) ); 3043 3044 sendBuffer[0] = kI2CDisplayReadHostAddress; 3045 sendBuffer[1] = kI2CVCPSetLength; 3046 sendBuffer[2] = kI2CVCPSetCode; // SetVCP command 3047 sendBuffer[3] = 0xD6; 3048 sendBuffer[4] = 0; // MSB 3049 sendBuffer[5] = enable ? kDDCPowerOn : kDDCPowerOff; // LSB 3050 sendBuffer[6] = kI2CDisplayWriteAddress ^ 3051 sendBuffer[0] ^ sendBuffer[1] ^ 3052 sendBuffer[2] ^ sendBuffer[3] ^ 3053 sendBuffer[4] ^ sendBuffer[5]; 3054 3055 i2CRecord.csBusID = kVideoDefaultBus; 3056 i2CRecord.csSendAddress = kI2CDisplayWriteAddress; 3057 i2CRecord.csSendType = kVideoSimpleI2CType; 3058 i2CRecord.csSendBuffer = &sendBuffer; 3059 i2CRecord.csSendSize = 7; 3060 i2CRecord.csReplyType = kVideoNoTransactionType; 3061 i2CRecord.csReplyAddress = 0; 3062 i2CRecord.csReplyBuffer = 0; 3063 i2CRecord.csReplySize = 0; 3064 3065 if (supportedCommFlags & kVideoReplyMicroSecDelayMask) 3066 { 3067 // We know some displays are slow, this is an important call to get right 3068 i2CRecord.csCommFlags |= kVideoReplyMicroSecDelayMask; 3069 // 50 milliseconds should be enough time for the display to respond. 3070 i2CRecord.csMinReplyDelay = 50 * 1000; 3071 } 3072 3073 _doControl(this, cscDoCommunication, &i2CRecord); 3074 } 3075} 3076 3077bool IONDRVFramebuffer::getOnlineState( void ) 3078{ 3079 return (online); 3080} 3081 3082IOReturn IONDRVFramebuffer::ndrvGetSetFeature( UInt32 feature, 3083 uintptr_t newValue, uintptr_t * currentValue ) 3084{ 3085#define CHAR(c) ((c) ? (char) (c) : '0') 3086#define FEAT(f) CHAR(f>>24), CHAR(f>>16), CHAR(f>>8), CHAR(f>>0) 3087 3088 IOReturn err; 3089 VDConfigurationRec configRec; 3090 3091 bzero( &configRec, sizeof( configRec)); 3092 configRec.csConfigFeature = feature; 3093 3094 DEBG(thisName, "(0x%08x '%c%c%c%c')\n", (int) feature, FEAT(feature)); 3095 3096 TIMESTART(); 3097 err = _doStatus( this, cscGetFeatureConfiguration, &configRec ); 3098 TIMEEND(thisName, "cscGetFeatureConfiguration: '%c%c%c%c' %qd ms\n", FEAT(feature)); 3099 3100 DEBG1(thisName, " cscGetFeatureConfiguration(%d), %08x %08lx %08lx %08lx\n", err, 3101 (uint32_t) configRec.csConfigSupport, configRec.csConfigValue, configRec.csReserved1, configRec.csReserved2); 3102 3103 if ((kIOReturnSuccess != err) || !configRec.csConfigSupport) 3104 err = kIOReturnUnsupported; 3105 3106 if (kIOReturnSuccess == err) 3107 { 3108 if (currentValue) 3109 { 3110 currentValue[0] = configRec.csConfigValue; 3111 currentValue[1] = configRec.csReserved1; 3112 currentValue[2] = configRec.csReserved2; 3113 } 3114 else if (configRec.csConfigValue != newValue) 3115 { 3116 configRec.csConfigFeature = feature; 3117 configRec.csConfigValue = newValue; 3118 TIMESTART(); 3119 err = _doControl( this, cscSetFeatureConfiguration, &configRec ); 3120 TIMEEND(thisName, "cscSetFeatureConfiguration: '%c%c%c%c' = 0x%lx %qd ms\n", 3121 FEAT(feature), newValue); 3122 3123 DEBG1(thisName, " cscSetFeatureConfiguration(%d) %08lx\n", err, configRec.csConfigValue); 3124 } 3125 else 3126 DEBG1(thisName, " skipped cscSetFeatureConfiguration(%d) %08lx\n", err, configRec.csConfigValue); 3127 } 3128 3129 return (err); 3130} 3131 3132IOReturn IONDRVFramebuffer::setConnectionFlags( void ) 3133{ 3134 if (kIODVIPowerEnableFlag & __private->displayConnectFlags) 3135 ndrvGetSetFeature( kDVIPowerSwitchFeature, kDVIPowerSwitchActiveMask, NULL ); 3136 3137 shouldDoI2CPower |= (0 != ( kIOI2CPowerEnableFlag & __private->displayConnectFlags)); 3138 3139 if (shouldDoI2CPower) 3140 displayI2CPower( (powerState == kIONDRVFramebufferPowerStateMax) ); 3141 3142 return (kIOReturnSuccess); 3143} 3144 3145IOReturn IONDRVFramebuffer::setAttributeForConnection( IOIndex connectIndex, 3146 IOSelect attribute, uintptr_t value ) 3147{ 3148 IOReturn err; 3149 VDSyncInfoRec syncInfo; 3150 3151 // -- temp 3152 if (ndrvState == 0) 3153 return (kIOReturnNotOpen); 3154 if (!getControllerWorkLoop()->inGate()) 3155 { 3156 if ((attribute != kConnectionProbe) && (attribute != 0x696772)) 3157 { 3158 OSReportWithBacktrace("%s::setAttributeForConnection(0x%x) not gated\n", 3159 thisName, (int) attribute); 3160 } 3161 return (super::setAttributeForConnectionExt(connectIndex, attribute, value)); 3162 } 3163 // -- 3164 3165 switch (attribute) 3166 { 3167 case kConnectionPower: 3168 err = kIOReturnSuccess; 3169 break; 3170 3171 case kConnectionSyncEnable: 3172 syncInfo.csMode = (UInt8) (value >> 8); 3173 syncInfo.csFlags = (UInt8) (value & 0xFF); 3174 _doControl( this, cscSetSync, &syncInfo); 3175 err = kIOReturnSuccess; 3176 break; 3177 3178 case kConnectionFlags: 3179 __private->displayConnectFlags |= (UInt32) value; 3180 nub->setProperty(kIONDRVDisplayConnectFlagsKey, 3181 &__private->displayConnectFlags, sizeof32(__private->displayConnectFlags)); 3182 err = setConnectionFlags(); 3183 break; 3184 3185 case kConnectionProbe: 3186 DEBG1(thisName, " kConnectionProbe\n"); 3187 err = _probeAction(this, (IOOptionBits) value); 3188 break; 3189 3190 default: 3191 3192 err = super::setAttributeForConnection( connectIndex, 3193 attribute, value ); 3194 if (kIOReturnUnsupported == err) 3195 err = ndrvGetSetFeature(attribute, value, NULL); 3196 break; 3197 } 3198 3199 return (err); 3200} 3201 3202bool IONDRVFramebuffer::searchOfflineMode( IODisplayModeID * offlineMode ) 3203{ 3204 VDResolutionInfoRec info; 3205 VDTimingInfoRec timingInfo; 3206 bool ret = false; 3207 3208 info.csPreviousDisplayModeID = kDisplayModeIDFindFirstResolution; 3209 while ( 3210 (noErr == _doStatus(this, cscGetNextResolution, &info)) 3211 && ((SInt32) info.csDisplayModeID > 0)) 3212 { 3213 timingInfo.csTimingMode = info.csDisplayModeID; 3214 timingInfo.csTimingFormat = kDeclROMtables; 3215 ret = _doStatus( this, cscGetModeTiming, &timingInfo); 3216 3217 if ((noErr == ret) 3218 && (kDeclROMtables == timingInfo.csTimingFormat) 3219 && (timingApple_0x0_0hz_Offline == timingInfo.csTimingData) 3220 && (kDisplayModeSafeFlag & timingInfo.csTimingFlags)) 3221 { 3222 if (offlineMode) 3223 *offlineMode = info.csDisplayModeID; 3224 ret = true; 3225 break; 3226 } 3227 info.csPreviousDisplayModeID = info.csDisplayModeID; 3228 } 3229 3230 return (ret); 3231} 3232 3233IOReturn IONDRVFramebuffer::processConnectChange( uintptr_t * value ) 3234{ 3235 IOReturn ret; 3236 uintptr_t connectEnabled; 3237 3238 DEBG(thisName, "\n"); 3239 3240 ret = getAttributeForConnection( 0, kConnectionCheckEnable, &connectEnabled ); 3241 3242 setDetailedTimings( 0 ); 3243 removeProperty( kIOFBConfigKey ); 3244 __private->displayConnectFlags = 0; 3245 __private->i2cPowerState = 0; 3246 shouldDoI2CPower = 0; 3247 cachedVDResolution.csDisplayModeID = kDisplayModeIDInvalid; 3248 __private->depthMapModeID = kDisplayModeIDInvalid; 3249 3250 setInfoProperties(); 3251 if (mirrored) 3252 setMirror( 0 ); 3253 3254 IODisplayModeID offlineMode; 3255 if (!online 3256 && searchOfflineMode(&offlineMode) 3257 && (offlineMode != currentDisplayMode)) 3258 { 3259 setDisplayMode( offlineMode, currentDepth ); 3260 } 3261 3262 __private->ackConnectChange = false; 3263 3264 ret = kIOReturnSuccess; 3265 3266 return (ret); 3267} 3268 3269IOReturn IONDRVFramebuffer::getAttributeForConnection( IOIndex connectIndex, 3270 IOSelect attribute, uintptr_t * value ) 3271{ 3272 IOReturn ret, thisRet; 3273 UInt32 thisCount = 0; 3274 VDSyncInfoRec syncInfo; 3275 VDConfigurationFeatureListRec featureList; 3276 3277 switch (attribute) 3278 { 3279 case kConnectionSyncFlags: 3280 // find out current state of sync lines 3281 syncInfo.csMode = 0x00; 3282 _doStatus( this, cscGetSync, &syncInfo); 3283 *value = syncInfo.csMode; 3284 ret = kIOReturnSuccess; 3285 break; 3286 3287 case kConnectionSyncEnable: 3288 // what are the sync-controlling capabilities of the ndrv? 3289 syncInfo.csMode = 0xFF; 3290 _doStatus( this, cscGetSync, &syncInfo); 3291 *value = (UInt32) syncInfo.csMode; 3292 ret = kIOReturnSuccess; 3293 break; 3294 3295 case kConnectionSupportsHLDDCSense: 3296 case kConnectionSupportsAppleSense: 3297 ret = kIOReturnSuccess; 3298 break; 3299 3300 case kConnectionFlags: 3301 VDMultiConnectInfoRec multiConnect; 3302 if (connectIndex == 0) 3303 ret = _doStatus( this, cscGetConnection, &multiConnect.csConnectInfo); 3304 else 3305 { 3306 multiConnect.csDisplayCountOrNumber = connectIndex; 3307 ret = _doStatus( this, cscGetMultiConnect, &multiConnect); 3308 } 3309 if (__private->removable) 3310 multiConnect.csConnectInfo.csConnectFlags &= ~(1<<kBuiltInConnection); 3311 3312 if (kIOReturnSuccess == ret) 3313 *value = multiConnect.csConnectInfo.csConnectFlags; 3314 else 3315 *value = 0; 3316 break; 3317 3318 case kConnectionCheckEnable: 3319 3320 if (connectIndex == 0) 3321 ret = _doStatus( this, cscGetConnection, &multiConnect.csConnectInfo); 3322 else 3323 { 3324 multiConnect.csDisplayCountOrNumber = connectIndex; 3325 ret = _doStatus( this, cscGetMultiConnect, &multiConnect); 3326 } 3327 if ((kIOReturnSuccess == ret) 3328 && ((1 << kConnectionInactive) & multiConnect.csConnectInfo.csConnectFlags)) 3329 { 3330 online = false; 3331 *value = online; 3332 break; 3333 } 3334 online = !searchOfflineMode( 0 ); 3335 /* fall thru */ 3336 3337 case kConnectionEnable: 3338 3339 *value = online; 3340 ret = kIOReturnSuccess; 3341 break; 3342 3343 case kConnectionPostWake: 3344 ret = kIOReturnSuccess; 3345 break; 3346 3347 case kConnectionChanged: 3348 if (value) 3349 ret = processConnectChange(value); 3350 else if (__private->postWakeProbe) 3351 { 3352 DEBG1(thisName, " kConnectionPostWake\n"); 3353 ret = _doControl( this, cscProbeConnection, 0 ); 3354 __private->postWakeProbe = false; 3355 if (!__private->ackConnectChange) 3356 setConnectionFlags(); 3357 } else 3358 ret = kIOReturnSuccess; 3359 break; 3360 3361 case kConnectionInTVMode: 3362 3363 switch (__private->currentModeTiming) 3364 { 3365 case timingAppleNTSC_ST: 3366 case timingAppleNTSC_FF: 3367 case timingAppleNTSC_STconv: 3368 case timingAppleNTSC_FFconv: 3369 *value = kConnectionNTSCMode; 3370 break; 3371 case timingApplePAL_ST: 3372 case timingApplePAL_FF: 3373 case timingApplePAL_STconv: 3374 case timingApplePAL_FFconv: 3375 *value = kConnectionPALMode; 3376 break; 3377 3378 default: 3379 *value = kConnectionNonTVMode; 3380 break; 3381 } 3382 ret = kIOReturnSuccess; 3383 break; 3384 3385 case kConnectionDisplayParameterCount: 3386 3387 bzero(&featureList, sizeof(featureList)); 3388 TIMESTART(); 3389 thisRet = _doStatus(this, cscGetFeatureList, &featureList); 3390 TIMEEND(thisName, "cscGetFeatureList: %qd ms\n"); 3391 if (kIOReturnSuccess == thisRet) 3392 thisCount = featureList.csNumConfigFeatures; 3393 3394 ret = super::getAttributeForConnection( connectIndex, attribute, value ); 3395 if (kIOReturnSuccess != ret) 3396 { 3397 *value = thisCount; 3398 ret = thisRet; 3399 } 3400 else 3401 *value += thisCount; 3402 break; 3403 3404 case kConnectionDisplayParameters: 3405 3406 bzero(&featureList, sizeof(featureList)); 3407 featureList.csConfigFeatureList = (OSType *) value; 3408 featureList.csNumConfigFeatures = 0x7fff; 3409 thisRet = _doStatus(this, cscGetFeatureList, &featureList); 3410 if (kIOReturnSuccess == thisRet) 3411 { 3412 thisCount = featureList.csNumConfigFeatures; 3413 for (uint32_t idx = thisCount; idx > 0; idx--) 3414 value[idx - 1] = ((OSType *)value)[idx - 1]; 3415 } 3416 3417 ret = super::getAttributeForConnection( connectIndex, 3418 attribute, value + thisCount ); 3419 if (kIOReturnSuccess != ret) 3420 ret = thisRet; 3421 break; 3422 3423 default: 3424 3425 ret = super::getAttributeForConnection( connectIndex, 3426 attribute, value ); 3427 if (kIOReturnUnsupported == ret) 3428 ret = ndrvGetSetFeature(attribute, 0, value); 3429 break; 3430 } 3431 3432 return (ret); 3433} 3434 3435IOReturn IONDRVFramebuffer::getAppleSense( IOIndex connectIndex, 3436 UInt32 * senseType, 3437 UInt32 * primary, 3438 UInt32 * extended, 3439 UInt32 * displayType ) 3440{ 3441 OSStatus err; 3442 VDMultiConnectInfoRec multiConnect; 3443 UInt32 sense, extSense; 3444 3445 if (connectIndex == 0) 3446 err = _doStatus( this, cscGetConnection, &multiConnect.csConnectInfo); 3447 else 3448 { 3449 multiConnect.csDisplayCountOrNumber = connectIndex; 3450 err = _doStatus( this, cscGetMultiConnect, &multiConnect); 3451 } 3452 if (err) 3453 return (err); 3454 3455 if ((primary || extended) 3456 && (0 == ((1<<kReportsTagging) & multiConnect.csConnectInfo.csConnectFlags))) 3457 3458 err = kIOReturnUnsupported; 3459 3460 else 3461 { 3462 sense = multiConnect.csConnectInfo.csConnectTaggedType; 3463 extSense = multiConnect.csConnectInfo.csConnectTaggedData; 3464 // bug fixes for really old ATI driver 3465 if (sense == 0) 3466 { 3467 if (extSense == 6) 3468 { 3469 sense = kRSCSix; 3470 extSense = kESCSixStandard; 3471 } 3472 else if (extSense == 4) 3473 { 3474 sense = kRSCFour; 3475 extSense = kESCFourNTSC; 3476 } 3477 } 3478 if (primary) 3479 *primary = sense; 3480 if (extended) 3481 *extended = extSense; 3482 if (senseType) 3483 *senseType = (0 != ((1<<kTaggingInfoNonStandard) & multiConnect.csConnectInfo.csConnectFlags)); 3484 if (displayType) 3485 *displayType = multiConnect.csConnectInfo.csDisplayType; 3486 } 3487 return (err); 3488} 3489 3490IOReturn IONDRVFramebuffer::connectFlags( IOIndex /* connectIndex */, 3491 IODisplayModeID displayMode, IOOptionBits * flags ) 3492{ 3493 VDTimingInfoRec timingInfo; 3494 OSStatus err; 3495 3496 timingInfo.csTimingMode = displayMode; 3497 // in case the driver doesn't do it: 3498 timingInfo.csTimingFormat = kDeclROMtables; 3499 err = _doStatus( this, cscGetModeTiming, &timingInfo); 3500 3501 if (kDetailedTimingFormat == timingInfo.csTimingFormat) 3502 *flags = kDisplayModeValidFlag | kDisplayModeSafeFlag; 3503 else 3504 *flags = timingInfo.csTimingFlags; 3505 3506 return (err); 3507} 3508 3509 3510bool IONDRVFramebuffer::hasDDCConnect( IOIndex connectIndex ) 3511{ 3512 OSStatus err; 3513 VDMultiConnectInfoRec multiConnect; 3514 enum { kNeedFlags = (1<<kReportsDDCConnection) | (1<<kHasDDCConnection) }; 3515 3516 if (connectIndex == 0) 3517 err = _doStatus( this, cscGetConnection, &multiConnect.csConnectInfo); 3518 else 3519 { 3520 multiConnect.csDisplayCountOrNumber = connectIndex; 3521 err = _doStatus( this, cscGetMultiConnect, &multiConnect); 3522 } 3523 if (err) 3524 return (err); 3525 3526 return (forceReadEDID 3527 || (kNeedFlags == (multiConnect.csConnectInfo.csConnectFlags & kNeedFlags))); 3528} 3529 3530// I2C first year for Apple displays. 3531// Apple monitors older than this (and Manta) 3532// are never called with I2C commands 3533enum { 3534 kFirstAppleI2CYear = 1999, 3535 kAppleVESAVendorID = 0x0610 3536}; 3537 3538struct EDID 3539{ 3540 UInt8 header[8]; 3541 UInt8 vendorProduct[4]; 3542 UInt8 serialNumber[4]; 3543 UInt8 weekOfManufacture; 3544 UInt8 yearOfManufacture; 3545 UInt8 version; 3546 UInt8 revision; 3547 UInt8 displayParams[5]; 3548 UInt8 colorCharacteristics[10]; 3549 UInt8 establishedTimings[3]; 3550 UInt16 standardTimings[8]; 3551 UInt8 descriptors[4][18]; 3552 UInt8 extension; 3553 UInt8 checksum; 3554}; 3555 3556static bool IsApplePowerBlock(UInt8 * theBlock) 3557{ 3558 return (theBlock && 3559 0x00000000 == *(UInt32 *)&theBlock[0] && 3560 0x00 == theBlock[4] && 3561 0x06 == theBlock[5] && 3562 0x10 == theBlock[6]); 3563} 3564 3565IOReturn IONDRVFramebuffer::getDDCBlock( IOIndex /* connectIndex */, 3566 UInt32 blockNumber, 3567 IOSelect blockType, 3568 IOOptionBits options, 3569 UInt8 * data, IOByteCount * length ) 3570 3571{ 3572 OSStatus err = 0; 3573 VDDDCBlockRec ddcRec; 3574 IOByteCount actualLength = *length; 3575 3576 if (forceReadEDID) 3577 { 3578 forceReadEDID = 0; 3579 options |= kDDCForceReadMask; 3580 } 3581 3582 ddcRec.ddcBlockNumber = blockNumber; 3583 ddcRec.ddcBlockType = blockType; 3584 ddcRec.ddcFlags = options; 3585 3586 err = _doStatus( this, cscGetDDCBlock, &ddcRec); 3587 3588 if (err == noErr) 3589 { 3590 if (actualLength > kDDCBlockSize) 3591 actualLength = kDDCBlockSize; 3592 bcopy( ddcRec.ddcBlockData, data, actualLength); 3593 *length = actualLength; 3594 3595 if ((1 == blockNumber) && (kIODDCBlockTypeEDID == blockType) 3596 && (actualLength >= sizeof(EDID))) 3597 do 3598 { 3599 EDID * edid; 3600 UInt32 vendor; 3601 UInt32 product; 3602 3603 edid = (EDID *) data; 3604 vendor = (edid->vendorProduct[0] << 8) | edid->vendorProduct[1]; 3605 product = (edid->vendorProduct[3] << 8) | edid->vendorProduct[2]; 3606 if (kAppleVESAVendorID == vendor) 3607 { 3608 if ((0x01F4 == product) || (0x9D02 == product) || (0x9216 == product)) 3609 continue; 3610 if (edid->yearOfManufacture && ((edid->yearOfManufacture + 1990) < kFirstAppleI2CYear)) 3611 continue; 3612 } 3613 shouldDoI2CPower = (IsApplePowerBlock( &edid->descriptors[1][0]) 3614 || IsApplePowerBlock( &edid->descriptors[2][0]) 3615 || IsApplePowerBlock( &edid->descriptors[3][0])); 3616 3617 if (shouldDoI2CPower) 3618 __private->displayConnectFlags |= kIODVIPowerEnableFlag; 3619 3620 err = kIOReturnSuccess; 3621 } 3622 while (false); 3623 } 3624 3625 if (1 == blockNumber) 3626 DEBG(thisName, " i2cPower %d\n", shouldDoI2CPower); 3627 3628 return (err); 3629} 3630 3631/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3632// initForPM 3633// 3634/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3635 3636void IONDRVFramebuffer::initForPM( void ) 3637{ 3638 IOPMPowerState powerStates[ kIONDRVFramebufferPowerStateCount ] = 3639 { 3640 // version, 3641 // capabilityFlags, outputPowerCharacter, inputPowerRequirement, 3642 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 3643 { 1, 0, 0, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 }, 3644 { 1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 } 3645 // staticPower, unbudgetedPower, powerToAttain, timeToAttain, settleUpTime, 3646 // timeToLower, settleDownTime, powerDomainBudget 3647 }; 3648 VDPowerStateRec sleepInfo; 3649 IOReturn err; 3650 bool dozeOnly; 3651 3652 dozeOnly = false; 3653 { 3654 sleepInfo.powerState = 0; 3655 sleepInfo.powerFlags = 0; 3656 sleepInfo.powerReserved1 = 0; 3657 sleepInfo.powerReserved2 = 0; 3658 // can this ndrv power off? 3659 err = _doStatus( this, cscGetPowerState, &sleepInfo); 3660 dozeOnly = ((kIOReturnSuccess != err) 3661 || (0 == (kPowerStateSleepCanPowerOffMask & sleepInfo.powerFlags))); 3662 } 3663 3664 if (OSDynamicCast(IOBootNDRV, ndrv)) 3665 dozeOnly = true; 3666 3667 if (dozeOnly) 3668 { 3669 powerStates[kNDRVFramebufferSleepState].capabilityFlags |= kIOPMPreventSystemSleep; 3670 powerStates[kNDRVFramebufferDozeState].capabilityFlags |= kIOPMPreventSystemSleep; 3671 powerStates[kNDRVFramebufferWakeState].capabilityFlags |= kIOPMPreventSystemSleep; 3672 } 3673 3674 // register ourselves with superclass policy-maker 3675 registerPowerDriver( this, powerStates, kIONDRVFramebufferPowerStateCount ); 3676 // no sleep until children 3677 temporaryPowerClampOn(); 3678 // not below doze until system sleep 3679 changePowerStateTo( kNDRVFramebufferDozeState ); 3680} 3681 3682 3683/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3684// maxCapabilityForDomainState 3685// 3686// This simple device needs only power. If the power domain is supplying 3687// power, the frame buffer can be on. If there is no power it can only be off. 3688/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3689 3690unsigned long IONDRVFramebuffer::maxCapabilityForDomainState( 3691 IOPMPowerFlags domainState ) 3692{ 3693 if (domainState & IOPMPowerOn) 3694 return (kIONDRVFramebufferPowerStateMax); 3695 else 3696 return (kNDRVFramebufferSleepState); 3697} 3698 3699/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3700// initialPowerStateForDomainState 3701// 3702// The power domain may be changing state. If power is on in the new 3703// state, that will not affect our state at all. If domain power is off, 3704// we can attain only our lowest state, which is off. 3705/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3706 3707unsigned long IONDRVFramebuffer::initialPowerStateForDomainState( 3708 IOPMPowerFlags domainState ) 3709{ 3710 if (domainState & IOPMPowerOn) 3711 return (kIONDRVFramebufferPowerStateMax); 3712 else 3713 return (kNDRVFramebufferSleepState); 3714} 3715 3716 3717/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3718// powerStateForDomainState 3719// 3720// The power domain may be changing state. If power is on in the new 3721// state, that will not affect our state at all. If domain power is off, 3722// we can attain only our lowest state, which is off. 3723/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3724 3725unsigned long IONDRVFramebuffer::powerStateForDomainState( 3726 IOPMPowerFlags domainState ) 3727{ 3728 if (domainState & IOPMPowerOn) 3729 return (getPowerState()); 3730 else 3731 return (kNDRVFramebufferSleepState); 3732} 3733 3734/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3735 3736IOReturn IONDRVFramebuffer::ndrvSetDisplayPowerState( UInt32 state ) 3737{ 3738 IOReturn err; 3739 VDSyncInfoRec syncInfo; 3740 3741 state = state ? true : false; 3742 3743 // what are the sync-controlling capabilities of the ndrv? 3744 syncInfo.csMode = 0xff; 3745 err = _doStatus( this, cscGetSync, &syncInfo ); 3746 if (kIOReturnSuccess == err) 3747 { 3748 // pick new sync state 3749 if (state) 3750 syncInfo.csMode = kDPMSSyncOn; 3751 else 3752 syncInfo.csMode = kDPMSSyncOff; 3753 syncInfo.csFlags = kDPMSSyncMask; 3754 _doControl( this, cscSetSync, &syncInfo); 3755 3756 DEBG(thisName, " sync->%02x\n", syncInfo.csMode); 3757 } 3758 3759 if (shouldDoI2CPower) 3760 { 3761 displayI2CPower( state ); 3762 DEBG(thisName, " i2c->%02x\n", state ? true : false); 3763 } 3764 3765 err = kIOReturnSuccess; 3766 3767 return (err); 3768} 3769 3770/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3771// ndrvSetPowerState 3772// 3773// Called by the superclass to turn the frame buffer on and off. 3774/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3775 3776IOReturn IONDRVFramebuffer::ndrvUpdatePowerState( void ) 3777{ 3778 IOReturn err; 3779 VDPowerStateRec sleepInfo; 3780 bool supportsReducedPower; 3781 3782 super::handleEvent( kIOFBNotifyWillChangeSpeed, (void *)(uintptr_t) __private->reducedSpeed ); 3783 3784 sleepInfo.powerState = 0; 3785 sleepInfo.powerFlags = 0; 3786 sleepInfo.powerReserved1 = 0; 3787 sleepInfo.powerReserved2 = 0; 3788 3789 err = _doStatus( this, cscGetPowerState, &sleepInfo); 3790 3791 supportsReducedPower = (kIOReturnSuccess == err) && (0 != 3792 (( kPowerStateSupportsReducedPower1BitMask 3793 | kPowerStateSupportsReducedPower2BitMask 3794 | kPowerStateSupportsReducedPower3BitMask) & sleepInfo.powerFlags)); 3795 3796 if (supportsReducedPower) 3797 { 3798 sleepInfo.powerFlags = (__private->reducedSpeed << 8); 3799 sleepInfo.powerReserved1 = kPowerStateSleepWakeNeedsProbeMask; 3800 sleepInfo.powerReserved2 = 0; 3801 3802 err = _doControl(this, cscSetPowerState, &sleepInfo); 3803 } 3804 else 3805 err = kIOReturnUnsupported; 3806 3807 super::handleEvent( kIOFBNotifyDidChangeSpeed, (void *)(uintptr_t) __private->reducedSpeed ); 3808 3809 return (err); 3810} 3811 3812IOReturn IONDRVFramebuffer::ndrvSetPowerState( UInt32 newState ) 3813{ 3814 static const UInt32 3815 // [sleep][fromState][toState] 3816 states[2][kIONDRVFramebufferPowerStateCount][kIONDRVFramebufferPowerStateCount] = 3817 { 3818 { 3819 { 0, kAVPowerOff, kAVPowerOn }, 3820 { kAVPowerOff, 0, kAVPowerOn }, 3821 { kAVPowerOff, kAVPowerOff, 0 }, 3822 }, { 3823 { 0, kHardwareWakeToDoze, kHardwareWake }, 3824 { kHardwareSleep, 0, kAVPowerOn }, 3825 { kHardwareSleep, kAVPowerSuspend, 0 } 3826 } 3827 }; 3828 3829 IOReturn err; 3830 UInt32 sleep = 0; 3831 UInt32 ndrvPowerState; 3832 UInt32 oldState; 3833 IOIndex postEvent = 0; 3834 IOAGPDevice * agpDev; 3835 IODTPlatformExpert * pe; 3836 bool supportsReducedPower; 3837 3838 if (newState == powerState) 3839 return (kIOReturnSuccess); 3840 3841 if (newState > kIONDRVFramebufferPowerStateMax) 3842 newState = kIONDRVFramebufferPowerStateMax; 3843 3844 oldState = powerState; 3845 3846 if (kIONDRVFramebufferPowerStateMax == oldState) 3847 { 3848 super::handleEvent( kIOFBNotifyWillPowerOff ); 3849 postEvent = kIOFBNotifyDidPowerOff; 3850 ndrvSetDisplayPowerState( false ); 3851 } 3852 else if (kIONDRVFramebufferPowerStateMax == newState) 3853 { 3854 super::handleEvent( kIOFBNotifyWillPowerOn ); 3855 postEvent = kIOFBNotifyDidPowerOn; 3856 } 3857 3858 if (kNDRVFramebufferSleepState == newState) 3859 { 3860 if (kIODVIPowerEnableFlag & __private->displayConnectFlags) 3861 { 3862 err = ndrvGetSetFeature( kDVIPowerSwitchFeature, 0, 0 ); 3863 if (kIOReturnSuccess == err) 3864 IOSleep( kDVIPowerSwitchPowerOffDelay ); 3865 } 3866 3867 IOMemoryDescriptor * vram; 3868 if ((vram = getVRAMRange())) 3869 { 3870 vram->redirect( kernel_task, true ); 3871 vram->release(); 3872 } 3873 // tell accelerators to protect HW also 3874 super::handleEvent( kIOFBNotifyWillSleep, (void *) true ); 3875 } 3876 3877 if (platformSleep 3878 && !__private->removable 3879 && (pe = OSDynamicCast(IODTPlatformExpert, getPlatform())) 3880 && (pe->getChipSetType() < kChipSetTypeCore99)) 3881 { 3882 VDSleepWakeInfo sleepInfo; 3883 3884 ndrvPowerState = newState ? vdWakeState : vdSleepState; 3885 3886 err = _doStatus( this, cscSleepWake, &sleepInfo); 3887 3888 powerState = newState; 3889 3890 if ((kIOReturnSuccess == err) && (sleepWakeSig == sleepInfo.csData) 3891 && (ndrvPowerState != sleepInfo.csMode)) 3892 { 3893 sleepInfo.csMode = ndrvPowerState; 3894 3895 err = _doControl( this, cscSleepWake, &sleepInfo); 3896 } 3897 } 3898 else 3899 { 3900 VDPowerStateRec sleepInfo; 3901 3902 sleepInfo.powerState = 0; 3903 sleepInfo.powerFlags = 0; 3904 sleepInfo.powerReserved1 = 0; 3905 sleepInfo.powerReserved2 = 0; 3906 3907 err = _doStatus( this, cscGetPowerState, &sleepInfo); 3908 3909 if (((kIOReturnSuccess == err) && (kPowerStateSleepCanPowerOffMask & sleepInfo.powerFlags)) 3910 || (platformSleep && !__private->removable)) 3911 sleep = 1; 3912 3913 supportsReducedPower = (kIOReturnSuccess == err) && (0 != 3914 (( kPowerStateSupportsReducedPower1BitMask 3915 | kPowerStateSupportsReducedPower2BitMask 3916 | kPowerStateSupportsReducedPower3BitMask) & sleepInfo.powerFlags)); 3917 3918 ndrvPowerState = states[sleep][oldState][newState]; 3919 3920 if ((kHardwareWakeToDoze == ndrvPowerState) 3921 && (0 == (kPowerStateSleepWaketoDozeMask & sleepInfo.powerFlags))) 3922 { 3923 DEBG1(thisName, " no kHardwareWakeToDoze support\n"); 3924 ndrvPowerState = kHardwareWake; 3925 } 3926 else if (kAVPowerSuspend == ndrvPowerState) 3927 { 3928 } 3929 3930 3931 DEBG1(thisName, " idx %d powerFlags %08x, state->%02x\n", 3932 (uint32_t) newState, (uint32_t) sleepInfo.powerFlags, (uint32_t) ndrvPowerState); 3933 3934 powerState = newState; 3935 3936 if ((kIOReturnSuccess != err) || (sleepInfo.powerState != ndrvPowerState)) 3937 { 3938 sleepInfo.powerState = ndrvPowerState; 3939 3940 if (supportsReducedPower) 3941 sleepInfo.powerFlags = (__private->reducedSpeed << 8); 3942 else 3943 sleepInfo.powerFlags = 0; 3944 sleepInfo.powerReserved1 = kPowerStateSleepWakeNeedsProbeMask; 3945 sleepInfo.powerReserved2 = 0; 3946 3947 err = _doControl( this, cscSetPowerState, &sleepInfo); 3948 3949 DEBG(thisName, " done powerFlags %08x\n", (uint32_t) sleepInfo.powerFlags); 3950 3951 if (kNDRVFramebufferSleepState == oldState) 3952 __private->postWakeProbe = (0 != (kPowerStateSleepWakeNeedsProbeMask & sleepInfo.powerFlags)); 3953 else if (kNDRVFramebufferSleepState == newState) 3954 __private->postWakeProbe = false; 3955 } 3956 } 3957 3958 agpDev = OSDynamicCast(IOAGPDevice, device); 3959 3960 if (kNDRVFramebufferSleepState == oldState) 3961 { 3962 uintptr_t isOnline, wasOnline = online; 3963 if (__private->postWakeProbe) 3964 isOnline = wasOnline; 3965 else if (kIOReturnSuccess != getAttributeForConnection(0, kConnectionCheckEnable, &isOnline)) 3966 isOnline = true; 3967 if (isOnline != wasOnline) 3968 { 3969 online = isOnline; 3970 // vramMemory = findVRAM(); 3971 if (isOnline) 3972 getCurrentConfiguration(); 3973 } 3974 if (agpDev) 3975 agpDev->resetAGP(); 3976 } 3977 3978 if (kNDRVFramebufferSleepState == oldState) 3979 { 3980 IOMemoryDescriptor * vram; 3981 if ((vram = getVRAMRange())) 3982 { 3983 vram->redirect( kernel_task, false ); 3984 vram->release(); 3985 } 3986 // tell accelerators to unprotect HW also 3987 super::handleEvent( kIOFBNotifyDidWake, (void *) true ); 3988 } 3989 3990 if (postEvent) 3991 { 3992 super::handleEvent( postEvent ); 3993 if (kIOFBNotifyDidPowerOn == postEvent) 3994 { 3995 ndrvSetDisplayPowerState( true ); 3996 } 3997 } 3998 3999 IONDRVFramebuffer * next; 4000 next = OSDynamicCast(IONDRVFramebuffer, nextDependent); 4001 if (true && next 4002 && ((newState > oldState))) 4003// /*|| ((newState == kNDRVFramebufferDozeState)&& !other->getOnlineState()*/))) 4004 { 4005 while (next && (next != this)) 4006 { 4007 next->ndrvSetPowerState( newState ); 4008 next = OSDynamicCast(IONDRVFramebuffer, next->nextDependent); 4009 } 4010 } 4011 4012 if ((kNDRVFramebufferSleepState == oldState) 4013 && !__private->ackConnectChange 4014 && !__private->postWakeProbe) 4015 setConnectionFlags(); 4016 4017 return (kIOReturnSuccess); 4018} 4019 4020/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4021 4022#undef super 4023#define super IONDRV 4024OSDefineMetaClassAndStructors(IOBootNDRV, IONDRV) 4025 4026/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4027 4028bool IOBootNDRV::getUInt32Property( IORegistryEntry * regEntry, const char * name, 4029 UInt32 * result ) 4030{ 4031 OSData * data; 4032 4033 data = OSDynamicCast(OSData, regEntry->getProperty(name)); 4034 if (data) 4035 *result = *((UInt32 *) data->getBytesNoCopy()); 4036 4037 return (data != 0); 4038} 4039 4040IONDRV * IOBootNDRV::fromRegistryEntry( IORegistryEntry * regEntry ) 4041{ 4042 IOBootNDRV * inst; 4043 IOBootNDRV * result = NULL; 4044 IOService * device; 4045 IOByteCount bytes; 4046 4047 inst = new IOBootNDRV; 4048 if (inst && !inst->init()) 4049 { 4050 inst->release(); 4051 inst = NULL; 4052 } 4053 4054 if (inst && (device = OSDynamicCast(IOService, regEntry))) 4055 do 4056 { 4057 PE_Video bootDisplay; 4058 UInt32 bpp; 4059 4060 IOService::getPlatform()->getConsoleInfo( &bootDisplay); 4061 4062 IOPhysicalAddress64 consolePhysAddress = bootDisplay.v_baseAddr & ~3; 4063#ifndef __LP64__ 4064 consolePhysAddress |= (((uint64_t) bootDisplay.v_baseAddrHigh) << 32); 4065#endif 4066 4067 IOMemoryDescriptor * mem = NULL; 4068 IOPCIDevice * pciDevice; 4069 UInt32 numMaps, i; 4070 4071 OSNumber * num = OSDynamicCast(OSNumber, device->getProperty(kIOFBDependentIndexKey)); 4072 if (num && (0 != num->unsigned32BitValue())) 4073 break; 4074 else if ((pciDevice = OSDynamicCast(IOPCIDevice, device)) 4075 && pciDevice->getFunctionNumber()) 4076 break; 4077 4078 bytes = (bootDisplay.v_rowBytes * bootDisplay.v_height); 4079 numMaps = device->getDeviceMemoryCount(); 4080 for (i = 0; (!mem) && (i < numMaps); i++) 4081 { 4082 addr64_t pa; 4083 mem = device->getDeviceMemoryWithIndex(i); 4084 if (!mem) 4085 continue; 4086 pa = mem->getPhysicalSegment(0, 0, kIOMemoryMapperNone); 4087 if ((consolePhysAddress < pa) || (consolePhysAddress >= (pa + mem->getLength()))) 4088 mem = NULL; 4089 else 4090 { 4091 mem = IOSubMemoryDescriptor::withSubRange(mem, 4092 consolePhysAddress - pa, 4093 bytes, kIODirectionNone); 4094 } 4095 } 4096 4097 if (mem) 4098 { 4099 inst->fVRAMDesc = mem; 4100 inst->fRowBytes = (UInt32) bootDisplay.v_rowBytes; 4101 inst->fWidth = (UInt32) bootDisplay.v_width; 4102 inst->fHeight = (UInt32) bootDisplay.v_height; 4103 bpp = (UInt32) bootDisplay.v_depth; 4104 if (bpp == 15) 4105 bpp = 16; 4106 else if (bpp == 24) 4107 bpp = 32; 4108 inst->fBitsPerPixel = bpp; 4109 4110 result = inst; 4111 } 4112 } 4113 while (false); 4114 4115 if (inst && !result) 4116 inst->release(); 4117 4118 return (result); 4119} 4120 4121void IOBootNDRV::free( void ) 4122{ 4123 super::free(); 4124} 4125 4126IOReturn IOBootNDRV::getSymbol( const char * symbolName, 4127 IOLogicalAddress * address ) 4128{ 4129 return (kIOReturnUnsupported); 4130} 4131 4132const char * IOBootNDRV::driverName( void ) 4133{ 4134 return (".Display_boot"); 4135} 4136 4137IOReturn IOBootNDRV::doDriverIO( UInt32 commandID, void * contents, 4138 UInt32 commandCode, UInt32 commandKind ) 4139{ 4140 IONDRVControlParameters * pb = (IONDRVControlParameters *) contents; 4141 IOReturn ret; 4142 4143 switch (commandCode) 4144 { 4145 case kIONDRVInitializeCommand: 4146 case kIONDRVOpenCommand: 4147 ret = kIOReturnSuccess; 4148 break; 4149 4150 case kIONDRVControlCommand: 4151 ret = doControl( pb->code, pb->params ); 4152 break; 4153 case kIONDRVStatusCommand: 4154 ret = doStatus( pb->code, pb->params ); 4155 break; 4156 4157 default: 4158 ret = kIOReturnUnsupported; 4159 break; 4160 } 4161 4162 return (ret); 4163} 4164 4165IOReturn IOBootNDRV::doControl( UInt32 code, void * params ) 4166{ 4167 IOReturn ret; 4168 4169 switch (code) 4170 { 4171 case cscSetEntries: 4172 case cscSetGamma: 4173 ret = kIOReturnSuccess; 4174 break; 4175 4176 default: 4177 ret = kIOReturnUnsupported; 4178 break; 4179 } 4180 4181 return (ret); 4182} 4183 4184IOReturn IOBootNDRV::doStatus( UInt32 code, void * params ) 4185{ 4186 IOReturn ret; 4187 4188 switch (code) 4189 { 4190 case cscGetCurMode: 4191 { 4192 VDSwitchInfoRec * switchInfo = (VDSwitchInfoRec *) params; 4193 4194 switchInfo->csData = kIOBootNDRVDisplayMode; 4195 switchInfo->csMode = kDepthMode1; 4196 switchInfo->csPage = 1; 4197 switchInfo->csBaseAddr = (char *)(1 | fVRAMDesc->getPhysicalSegment(0, NULL, kIOMemoryMapperNone)); 4198 ret = kIOReturnSuccess; 4199 } 4200 break; 4201 4202 case cscGetNextResolution: 4203 { 4204 VDResolutionInfoRec * resInfo = (VDResolutionInfoRec *) params; 4205 4206 if ((kDisplayModeIDFindFirstResolution == (SInt32) resInfo->csPreviousDisplayModeID) 4207 || (kDisplayModeIDCurrent == (SInt32) resInfo->csPreviousDisplayModeID)) 4208 { 4209 resInfo->csDisplayModeID = kIOBootNDRVDisplayMode; 4210 resInfo->csMaxDepthMode = kDepthMode1; 4211 resInfo->csHorizontalPixels = fWidth; 4212 resInfo->csVerticalLines = fHeight; 4213 resInfo->csRefreshRate = 0 << 16; 4214 ret = kIOReturnSuccess; 4215 } 4216 else if (kIOBootNDRVDisplayMode == resInfo->csPreviousDisplayModeID) 4217 { 4218 resInfo->csDisplayModeID = kDisplayModeIDNoMoreResolutions; 4219 ret = kIOReturnSuccess; 4220 } 4221 else 4222 { 4223 resInfo->csDisplayModeID = kDisplayModeIDInvalid; 4224 ret = kIOReturnBadArgument; 4225 } 4226 } 4227 break; 4228 4229 case cscGetVideoParameters: 4230 { 4231 VDVideoParametersInfoRec * pixelParams = (VDVideoParametersInfoRec *) params; 4232 4233 if ((kIOBootNDRVDisplayMode != pixelParams->csDisplayModeID) 4234 || (kDepthMode1 != pixelParams->csDepthMode)) 4235 { 4236 ret = kIOReturnBadArgument; 4237 break; 4238 } 4239 VPBlock * pixelInfo = pixelParams->csVPBlockPtr; 4240 4241 bzero(pixelInfo, sizeof(VPBlock)); 4242 pixelInfo->vpBounds.right = fWidth; 4243 pixelInfo->vpBounds.bottom = fHeight; 4244 pixelInfo->vpRowBytes = fRowBytes; 4245 pixelInfo->vpPixelSize = fBitsPerPixel; 4246 pixelInfo->vpPixelType = kIORGBDirectPixels; 4247 pixelInfo->vpCmpCount = 3; 4248 pixelInfo->vpCmpSize = (fBitsPerPixel <= 16) ? 5 : 8; 4249 ret = kIOReturnSuccess; 4250 } 4251 break; 4252 4253 case cscGetModeTiming: 4254 { 4255 VDTimingInfoRec * timingInfo = (VDTimingInfoRec *) params; 4256 4257 if (kIOBootNDRVDisplayMode != timingInfo->csTimingMode) 4258 { 4259 ret = kIOReturnBadArgument; 4260 break; 4261 } 4262 timingInfo->csTimingFormat = kDeclROMtables; 4263 timingInfo->csTimingFlags = kDisplayModeValidFlag | kDisplayModeSafeFlag; 4264 ret = kIOReturnSuccess; 4265 } 4266 break; 4267 4268 default: 4269 ret = kIOReturnUnsupported; 4270 break; 4271 } 4272 4273 return (ret); 4274} 4275 4276/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4277 4278OSMetaClassDefineReservedUsed(IONDRVFramebuffer, 0); 4279 4280OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 1); 4281OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 2); 4282OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 3); 4283OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 4); 4284OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 5); 4285OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 6); 4286OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 7); 4287OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 8); 4288OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 9); 4289OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 10); 4290OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 11); 4291OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 12); 4292OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 13); 4293OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 14); 4294OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 15); 4295OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 16); 4296OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 17); 4297OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 18); 4298OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 19); 4299OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 20); 4300OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 21); 4301OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 22); 4302OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 23); 4303OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 24); 4304OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 25); 4305OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 26); 4306OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 27); 4307OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 28); 4308OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 29); 4309OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 30); 4310OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 31); 4311