2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1997-1998 Apple Computer, Inc.
28 * sdouglas 22 Oct 97 - first checked in.
29 * sdouglas 24 Jul 98 - start IOKit.
30 * sdouglas 15 Dec 98 - cpp.
34 #include <IOKit/IOLib.h>
35 #include <IOKit/IOPlatformExpert.h>
36 #include <IOKit/IODeviceTreeSupport.h>
37 #include <IOKit/IOLocks.h>
38 #include <IOKit/pwr_mgt/RootDomain.h>
39 #include <IOKit/ndrvsupport/IONDRVFramebuffer.h>
40 #include <IOKit/pci/IOAGPDevice.h>
41 #include <IOKit/assert.h>
43 #include <libkern/c++/OSContainers.h>
49 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
51 class IOATINDRV
: public IONDRVFramebuffer
53 OSDeclareDefaultStructors(IOATINDRV
)
56 virtual IOReturn
getStartupDisplayMode( IODisplayModeID
* displayMode
,
58 virtual IODeviceMemory
* findVRAM( void );
62 class IOATI128NDRV
: public IOATINDRV
64 OSDeclareDefaultStructors(IOATI128NDRV
)
67 virtual void flushCursor( void );
70 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
73 class IONDRVFramebuffer
* framebuffer
;
75 IOFBInterruptProc handler
;
81 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
83 // IONDRVFramebuffer has two power states, off and on
85 enum { kIONDRVFramebufferPowerStateCount
= 2 };
87 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
89 #define super IOFramebuffer
91 OSDefineMetaClassAndStructors(IONDRVFramebuffer
, IOFramebuffer
)
93 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
99 IOService
* IONDRVFramebuffer::probe( IOService
* provider
,
102 IOService
* inst
= this;
103 IOService
* newInst
= 0;
106 if( !super::probe( provider
, score
))
109 if( 0 != provider
->getProperty(kIONDRVIgnoreKey
)) return( 0 );
111 if( /* IONDRV::fromRegistryEntry( provider ) || */ true) {
113 provider
->setProperty(kIONDRVForXKey
, this, sizeof(this) );
115 // temporary for in-kernel acceleration
116 name
= provider
->getName();
117 if( 0 == strncmp("ATY,Rage128", name
, strlen("ATY,Rage128")))
118 newInst
= new IOATI128NDRV
;
119 else if( 0 == strncmp("ATY,", name
, strlen("ATY,")))
120 newInst
= new IOATINDRV
;
123 if( ! newInst
->init( inst
->getPropertyTable())) {
135 IOReturn
IONDRVFramebuffer::setProperties( OSObject
* properties
)
139 IOReturn kr
= kIOReturnUnsupported
;
141 if( !(dict
= OSDynamicCast( OSDictionary
, properties
)))
142 return( kIOReturnBadArgument
);
144 if( (data
= OSDynamicCast(OSData
,
145 dict
->getObject("driver,AAPL,MacOS,PowerPC")))) {
148 return( kIOReturnStillOpen
);
152 nub
->setProperty("driver,AAPL,MacOS,PowerPC", data
);
153 nub
->removeProperty("AAPL,ndrvInst");
154 ndrv
= IONDRV::fromRegistryEntry( nub
, &_undefinedSymbolHandler
, (void *) this );
156 setName( ndrv
->driverName());
158 kr
= kIOReturnSuccess
;
164 static IOPMrootDomain
* gIOPMRootDomain
;
166 bool IONDRVFramebuffer::start( IOService
* provider
)
173 cachedVDResolution
.csDisplayModeID
= kDisplayModeIDInvalid
;
176 ndrv
= IONDRV::fromRegistryEntry( provider
, &_undefinedSymbolHandler
, this );
178 setName( ndrv
->driverName());
180 consoleDevice
= (0 != provider
->getProperty("AAPL,boot-display"));
183 if( 0 == nub
->getDeviceMemoryCount()) {
184 parent
= OSDynamicCast( IOService
, nub
->getParentEntry(gIODTPlane
));
186 parent
->getResources();
187 OSArray
* array
= parent
->getDeviceMemory();
189 nub
->setDeviceMemory( array
);
194 if( false == super::start( nub
))
197 if( !gIOPMRootDomain
)
198 gIOPMRootDomain
= (IOPMrootDomain
*)
199 IORegistryEntry::fromPath("/IOPowerConnection/IOPMrootDomain", gIOPowerPlane
);
201 platformDeepSleep
= (gIOPMRootDomain
->getSleepSupported()
202 & kFrameBufferDeepSleepSupported
) ? 1 : 0;
204 // default flags can be overriden
206 if(0 == strncmp("3Dfx", provider
->getName(), strlen("3Dfx")))
207 accessFlags
|= kFramebufferDisableAltivecAccess
;
209 if( (data
= OSDynamicCast( OSData
, provider
->getProperty(kIOFBHostAccessFlagsKey
))))
210 accessFlags
= *((UInt32
*) data
->getBytesNoCopy());
212 ok
= true; // Success
219 bool IONDRVFramebuffer::isConsoleDevice( void )
221 return( consoleDevice
);
224 // osfmk/ppc/mappings.h
225 extern "C" { extern void ignore_zero_fault(boolean_t
); }
227 IOReturn
IONDRVFramebuffer::enableController( void )
230 const char * logname
;
233 logname
= getProvider()->getName();
235 if( 0 == strcmp( "control", logname
))
236 waitForService( resourceMatching( "IOiic0" ));
239 err
= kIOReturnNotReady
;
241 err
= IONDRVLibrariesInitialize( getProvider() );
243 if( kIOReturnSuccess
== err
) do {
245 ignore_zero_fault( true );
247 ignore_zero_fault( false );
250 IOLog("%s: Not usable\n", logname
);
252 IOLog("%s: driver incompatible.\n", logname
);
255 getCurrentConfiguration();
256 vramMemory
= findVRAM();
258 // disable clamshell sleep on a single head portable
260 && (0 == OSDynamicCast( IOPCIDevice
, getProvider()))
261 && (data
= OSDynamicCast( OSData
,
262 getProvider()->getProperty("ATY,PanelActive")))) {
264 if( 0 == *((UInt32
*) data
->getBytesNoCopy()))
265 gIOPMRootDomain
->receivePowerNotification( kIOPMIgnoreClamshell
);
268 // initialize power management of the device
276 IODeviceMemory
* IONDRVFramebuffer::getVRAMRange( void )
279 vramMemory
->retain();
281 return( vramMemory
);
284 const IOTVector
* IONDRVFramebuffer::_undefinedSymbolHandler( void * self
,
285 const char * libraryName
, const char * symbolName
)
287 return( ((IONDRVFramebuffer
*)self
)->undefinedSymbolHandler( libraryName
, symbolName
) );
290 const IOTVector
* IONDRVFramebuffer::undefinedSymbolHandler( const char * libraryName
,
291 const char * symbolName
)
296 void IONDRVFramebuffer::free( void )
301 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
303 IOReturn
IONDRVFramebuffer::registerForInterruptType( IOSelect interruptType
,
304 IOFBInterruptProc proc
, OSObject
* target
, void * ref
,
305 void ** interruptRef
)
308 _VSLService
* service
;
311 if( (interruptType
== kIOFBVBLInterruptType
)
312 && (getProvider()->getProperty("Ignore VBL")))
313 return( kIOReturnUnsupported
);
315 for( service
= vslServices
;
316 service
&& (service
->type
!= interruptType
);
317 service
= service
->next
) {}
321 if( service
->handler
)
325 service
->target
= target
;
327 service
->handler
= proc
;
328 *interruptRef
= service
;
329 err
= kIOReturnSuccess
;
333 err
= kIOReturnNoResources
;
338 IOReturn
IONDRVFramebuffer::unregisterInterrupt( void * interruptRef
)
340 _VSLService
* service
= (_VSLService
*) interruptRef
;
342 service
->handler
= 0;
344 return( kIOReturnSuccess
);
347 IOReturn
IONDRVFramebuffer::setInterruptState( void * interruptRef
,
350 return( kIOReturnUnsupported
);
353 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
357 OSStatus
IONDRVFramebuffer::VSLNewInterruptService(
359 IOSelect serviceType
,
360 _VSLService
** vslService
)
362 IORegistryEntry
* regEntry
;
363 IONDRVFramebuffer
* fb
;
364 _VSLService
* service
;
365 IOReturn err
= kIOReturnSuccess
;
367 REG_ENTRY_TO_OBJ( (const RegEntryID
*) entryID
, regEntry
)
369 fb
= OSDynamicCast( IONDRVFramebuffer
,
370 regEntry
->getChildEntry( gIOServicePlane
));
374 service
= IONew( _VSLService
, 1 );
377 service
->framebuffer
= fb
;
378 service
->type
= serviceType
;
379 service
->handler
= 0;
380 service
->next
= fb
->vslServices
;
381 fb
->vslServices
= service
;
383 *vslService
= service
;
386 err
= kIOReturnNoMemory
;
389 err
= kIOReturnBadArgument
;
394 OSStatus
IONDRVFramebuffer::VSLDisposeInterruptService(_VSLService
* vslService
)
396 IONDRVFramebuffer
* fb
;
402 fb
= vslService
->framebuffer
;
404 prev
= fb
->vslServices
;
405 if( prev
== vslService
)
406 fb
->vslServices
= vslService
->next
;
408 while( ((next
= prev
->next
) != vslService
) && next
)
411 prev
->next
= vslService
->next
;
414 IODelete( vslService
, _VSLService
, 1 );
417 return( kIOReturnSuccess
);
420 OSStatus
IONDRVFramebuffer::VSLDoInterruptService( _VSLService
* vslService
)
422 IOFBInterruptProc proc
;
425 if( (proc
= vslService
->handler
))
426 (*proc
) (vslService
->target
, vslService
->ref
);
429 return( kIOReturnSuccess
);
432 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
434 struct _VSLCursorRef
{
435 IOFramebuffer
* framebuffer
;
439 Boolean
IONDRVFramebuffer::VSLPrepareCursorForHardwareCursor(
441 IOHardwareCursorDescriptor
* hwDesc
,
442 IOHardwareCursorInfo
* hwCursorInfo
)
444 _VSLCursorRef
* cursor
= (_VSLCursorRef
*) cursorRef
;
447 if( hwCursorInfo
->colorMap
)
448 hwCursorInfo
->colorMap
+= 1;
449 ok
= cursor
->framebuffer
->convertCursorImage(
450 cursor
->cursorImage
, hwDesc
, hwCursorInfo
);
451 if( hwCursorInfo
->colorMap
)
452 hwCursorInfo
->colorMap
-= 1;
457 IOReturn
IONDRVFramebuffer::setCursorImage( void * cursorImage
)
459 _VSLCursorRef cursorRef
;
460 VDSetHardwareCursorRec setCursor
;
464 return( kIOReturnSuccess
);
466 cursorRef
.framebuffer
= this;
467 cursorRef
.cursorImage
= cursorImage
;
469 setCursor
.csCursorRef
= (void *) &cursorRef
;
470 setCursor
.csReserved1
= 0;
471 setCursor
.csReserved2
= 0;
473 err
= doControl( cscSetHardwareCursor
, &setCursor
);
478 IOReturn
IONDRVFramebuffer::setCursorState( SInt32 x
, SInt32 y
, bool visible
)
480 VDDrawHardwareCursorRec drawCursor
;
484 return( kIOReturnSuccess
);
486 if( 0 == OSIncrementAtomic( &ndrvEnter
))
489 drawCursor
.csCursorX
= x
;
490 drawCursor
.csCursorY
= y
;
491 drawCursor
.csCursorVisible
= visible
;
492 drawCursor
.csReserved1
= 0;
493 drawCursor
.csReserved2
= 0;
495 err
= doControl( cscDrawHardwareCursor
, &drawCursor
);
500 OSDecrementAtomic( &ndrvEnter
);
505 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
511 IOReturn
IONDRVFramebuffer::doControl( UInt32 code
, void * params
)
517 return( kIOReturnNotOpen
);
521 pb
.csParams
= params
;
523 OSIncrementAtomic( &ndrvEnter
);
524 err
= ndrv
->doDriverIO( /*ID*/ (UInt32
) &pb
, &pb
,
525 kControlCommand
, kImmediateIOCommandKind
);
526 OSDecrementAtomic( &ndrvEnter
);
531 IOReturn
IONDRVFramebuffer::doStatus( UInt32 code
, void * params
)
537 return( kIOReturnNotOpen
);
541 pb
.csParams
= params
;
543 OSIncrementAtomic( &ndrvEnter
);
544 err
= ndrv
->doDriverIO( /*ID*/ (UInt32
) &pb
, &pb
,
545 kStatusCommand
, kImmediateIOCommandKind
);
546 OSDecrementAtomic( &ndrvEnter
);
552 IOReturn
IONDRVFramebuffer::checkDriver( void )
554 OSStatus err
= noErr
;
555 struct DriverInitInfo initInfo
;
557 VDClutBehavior clutSetting
;
558 VDGammaRecord gammaRec
;
559 VDSwitchInfoRec switchInfo
;
560 IOTimingInformation info
;
563 if( ndrvState
== 0) {
565 initInfo
.refNum
= 0xffcd; // ...sure.
566 MAKE_REG_ENTRY(initInfo
.deviceEntry
, nub
)
568 err
= ndrv
->doDriverIO( 0, &initInfo
,
569 kInitializeCommand
, kImmediateIOCommandKind
);
572 err
= ndrv
->doDriverIO( 0, &pb
,
573 kOpenCommand
, kImmediateIOCommandKind
);
580 // allow calls to ndrv
583 if( (noErr
== doStatus( cscGetCurMode
, &switchInfo
))
584 && (noErr
== getTimingInfoForDisplayMode( switchInfo
.csData
, &info
))
585 && (timingApple_0x0_0hz_Offline
== info
.appleTimingID
)) {
587 IOLog("%s: display offline\n", getName());
588 err
= kIOReturnOffline
;
595 VDCommunicationInfoRec commInfo
;
597 bzero( &commInfo
, sizeof( commInfo
));
598 commInfo
.csBusID
= kVideoDefaultBus
;
600 err
= doStatus( cscGetCommunicationInfo
, &commInfo
);
601 IOLog("%s: cscGetCommunicationInfo: ", getName());
602 if( kIOReturnSuccess
!= err
) {
603 IOLog("fails with %ld\n", err
);
606 if( commInfo
.csSupportedTypes
& (1<<kVideoDDCciReplyType
) )
607 IOLog("supports kVideoDDCciReplyType, ");
608 if( commInfo
.csSupportedTypes
& (1<<kVideoSimpleI2CType
) ) {
609 IOLog("supports kVideoSimpleI2CType");
610 VDCommunicationRec comm
;
612 UInt8 edidRequest
[2];
618 edidData
[128] = 0xAA;
619 edidData
[129] = 0xAA;
620 edidData
[130] = 0xAA;
621 edidData
[131] = 0xAA;
623 memset( edidData
, 0xAA, sizeof( edidData
));
628 comm
.csBusID
= kVideoDefaultBus
;
629 comm
.csReserved0
= 0;
630 comm
.csReserved1
= 0;
631 comm
.csReserved2
= 0;
633 comm
.csSendAddress
= 0xA0;
634 comm
.csSendType
= kVideoSimpleI2CType
;
635 comm
.csSendBuffer
= &edidRequest
[0];
636 comm
.csSendSize
= 0x01;
638 comm
.csReplyAddress
= 0xA1;
639 comm
.csReplyType
= kVideoSimpleI2CType
;
640 comm
.csReplyBuffer
= &edidData
[0];
641 comm
.csReplySize
= 128;
643 comm
.csReserved3
= 0;
644 comm
.csReserved4
= 0;
645 comm
.csReserved5
= 0;
646 comm
.csReserved6
= 0;
649 err
= doControl( cscDoCommunication
, &comm
);
650 IOLog("\nI2C read block[%x](%ld)\n", edidRequest
[0], err
);
651 if( kIOReturnSuccess
!= err
)
653 IOLog(" 0 1 2 3 4 5 6 7 8 9 A B C D E F");
654 for( int i
= 0; i
< 128; i
++) {
656 IOLog("\n%02x: ", i
);
657 IOLog("%02x ", edidData
[i
]);
660 if( edidRequest
[0] || (0 == edidData
[126]))
662 edidRequest
[0] = 0x80;
667 #endif /* IONDRVI2CLOG */
669 // duplicate QD InitGDevice
670 pageInfo
.csMode
= switchInfo
.csMode
;
673 doControl( cscGrayPage
, &pageInfo
);
675 clutSetting
= kSetClutAtSetEntries
;
676 lastClutSetting
= clutSetting
;
677 doControl( cscSetClutBehavior
, &clutSetting
);
680 VDDisplayTimingRangeRec rangeRec
;
682 bzero( &rangeRec
, sizeof( rangeRec
));
683 err
= doStatus( cscGetTimingRanges
, &rangeRec
);
684 if( kIOReturnSuccess
!= err
)
687 setProperty( kIOFBTimingRangeKey
, &rangeRec
, sizeof( rangeRec
));
692 // bogus for ROM control
695 VDGetGammaListRec scan
;
696 VDRetrieveGammaRec get
;
700 scan
.csPreviousGammaTableID
= kGammaTableIDFindFirst
;
701 scan
.csGammaTableName
= name
;
702 err
= doStatus( cscGetGammaInfoList
, &scan
);
703 if( err
|| (scan
.csGammaTableID
== (GammaTableID
) kGammaTableIDNoMoreTables
))
706 table
= (GammaTbl
*)IOMalloc( scan
.csGammaTableSize
);
709 get
.csGammaTableID
= scan
.csGammaTableID
;
710 get
.csGammaTablePtr
= table
;
712 err
= doStatus( cscRetrieveGammaTable
, &get
);
714 kprintf("Setting gamma %s\n", scan
.csGammaTableName
);
715 gammaRec
.csGTable
= (Ptr
) table
;
716 doControl( cscSetGamma
, &gammaRec
);
719 IOFree( table
, scan
.csGammaTableSize
);
728 UInt32
IONDRVFramebuffer::iterateAllModes( IODisplayModeID
* displayModeIDs
)
730 VDResolutionInfoRec info
;
733 info
.csPreviousDisplayModeID
= kDisplayModeIDFindFirstResolution
;
736 (noErr
== doStatus( cscGetNextResolution
, &info
))
737 && ((SInt32
) info
.csDisplayModeID
> 0) ) {
740 displayModeIDs
[ num
] = info
.csDisplayModeID
;
742 info
.csPreviousDisplayModeID
= info
.csDisplayModeID
;
746 if( detailedTimings
) {
747 IOItemCount count
, i
;
749 count
= detailedTimings
->getCount();
750 if( displayModeIDs
) {
751 for( i
= 0; i
< count
; i
++)
752 displayModeIDs
[ num
+ i
] = kDisplayModeIDReservedBase
+ i
;
760 IOReturn
IONDRVFramebuffer::getResInfoForArbMode( IODisplayModeID modeID
,
761 IODisplayModeInformation
* info
)
763 VDVideoParametersInfoRec pixelParams
;
765 VDDetailedTimingRec
* detailed
;
769 err
= validateDisplayMode( modeID
, 0, &detailed
);
771 for( depth
= -1; err
== kIOReturnSuccess
; ) {
772 pixelParams
.csDisplayModeID
= modeID
;
773 pixelParams
.csDepthMode
= ++depth
+ kDepthMode1
;
774 pixelParams
.csVPBlockPtr
= &pixelInfo
;
775 err
= doStatus( cscGetVideoParameters
, &pixelParams
);
779 info
->maxDepthIndex
= depth
- 1;
780 info
->nominalWidth
= pixelInfo
.vpBounds
.right
;
781 info
->nominalHeight
= pixelInfo
.vpBounds
.bottom
;
783 info
->refreshRate
= detailed
->csPixelClock
* 65536ULL /
784 ((detailed
->csVerticalActive
+ detailed
->csVerticalBlanking
)
785 * (detailed
->csHorizontalActive
+ detailed
->csHorizontalBlanking
));
787 info
->refreshRate
= 0;
789 err
= kIOReturnSuccess
;
795 IOReturn
IONDRVFramebuffer::getResInfoForMode( IODisplayModeID modeID
,
796 IODisplayModeInformation
* info
)
799 bzero( info
, sizeof( *info
));
801 if( (UInt32
) modeID
>= (UInt32
) kDisplayModeIDReservedBase
)
802 return( getResInfoForArbMode( modeID
, info
));
804 // unfortunately, there is no "kDisplayModeIDFindSpecific"
805 if( cachedVDResolution
.csDisplayModeID
!= (UInt32
) modeID
) {
807 // try the next after cached mode
808 cachedVDResolution
.csPreviousDisplayModeID
= cachedVDResolution
.csDisplayModeID
;
809 if( (noErr
!= doStatus( cscGetNextResolution
, &cachedVDResolution
))
810 || (cachedVDResolution
.csDisplayModeID
!= (UInt32
) modeID
) ) {
812 // else full blown iterate
813 cachedVDResolution
.csPreviousDisplayModeID
= kDisplayModeIDFindFirstResolution
;
815 (noErr
== doStatus( cscGetNextResolution
, &cachedVDResolution
))
816 && (cachedVDResolution
.csDisplayModeID
!= (UInt32
) modeID
)
817 && ((SInt32
) cachedVDResolution
.csDisplayModeID
> 0)) {
819 cachedVDResolution
.csPreviousDisplayModeID
= cachedVDResolution
.csDisplayModeID
;
824 if( cachedVDResolution
.csDisplayModeID
!= (UInt32
) modeID
) {
825 cachedVDResolution
.csDisplayModeID
= kDisplayModeIDInvalid
;
826 return( kIOReturnUnsupportedMode
);
830 info
->maxDepthIndex
= cachedVDResolution
.csMaxDepthMode
- kDepthMode1
;
831 info
->nominalWidth
= cachedVDResolution
.csHorizontalPixels
;
832 info
->nominalHeight
= cachedVDResolution
.csVerticalLines
;
833 info
->refreshRate
= cachedVDResolution
.csRefreshRate
;
841 kDisplayModeIDPreflight
= kDisplayModeIDReservedBase
+ 1000
844 IOReturn
IONDRVFramebuffer::setDetailedTiming(
845 IODisplayModeID mode
, IOOptionBits options
,
846 void * _desc
, IOByteCount descripSize
)
849 VDResolutionInfoRec info
;
850 VDDetailedTimingRec
* desc
= (VDDetailedTimingRec
*)_desc
;
851 VDDetailedTimingRec look
;
853 bool notPreflight
= (0 == (options
& kModePreflight
));
855 // current must be ok
856 if( mode
== currentDisplayMode
)
857 return( kIOReturnSuccess
);
859 index
= mode
- kDisplayModeIDReservedBase
;
860 bzero( &look
, sizeof( VDDetailedTimingRec
) );
861 look
.csTimingSize
= sizeof( VDDetailedTimingRec
);
863 // look for a programmable
865 info
.csPreviousDisplayModeID
= kDisplayModeIDFindFirstProgrammable
;
866 (noErr
== (err
= doStatus( cscGetNextResolution
, &info
)));
867 info
.csPreviousDisplayModeID
= info
.csDisplayModeID
) {
869 if( (SInt32
) info
.csDisplayModeID
< 0) {
870 err
= kIOReturnNoResources
;
874 look
.csDisplayModeID
= info
.csDisplayModeID
;
875 err
= doStatus( cscGetDetailedTiming
, &look
);
876 if( err
!= kIOReturnSuccess
)
879 // don't toss current
880 if( look
.csDisplayModeAlias
== (UInt32
) currentDisplayMode
)
883 // see if already set to the right timing
884 if( (look
.csDisplayModeAlias
== (UInt32
) mode
)
885 && (look
.csDisplayModeState
== kDMSModeReady
)
887 && (detailedTimingsCurrent
[index
] == detailedTimingsSeed
))
891 if( look
.csDisplayModeState
!= kDMSModeFree
) {
892 look
.csDisplayModeID
= info
.csDisplayModeID
;
893 look
.csDisplayModeAlias
= 0;
894 look
.csDisplayModeState
= kDMSModeFree
;
895 err
= doControl( cscSetDetailedTiming
, &look
);
896 if( err
!= kIOReturnSuccess
)
900 desc
->csDisplayModeID
= info
.csDisplayModeID
;
901 desc
->csDisplayModeAlias
= mode
;
902 desc
->csDisplayModeSeed
= look
.csDisplayModeSeed
;
903 desc
->csDisplayModeState
= kDMSModeReady
;
904 err
= doControl( cscSetDetailedTiming
, desc
);
906 if( kIOReturnSuccess
== err
) {
908 // don't stomp orig record
910 err
= doStatus( cscGetDetailedTiming
, desc
);
912 if( notPreflight
&& (kIOReturnSuccess
== err
))
913 detailedTimingsCurrent
[index
] = detailedTimingsSeed
;
921 IOReturn
IONDRVFramebuffer::validateDisplayMode(
922 IODisplayModeID _mode
, IOOptionBits flags
,
923 VDDetailedTimingRec
** detailed
)
926 IOReturn err
= kIOReturnSuccess
;
931 *detailed
= (VDDetailedTimingRec
*) 0;
933 if( mode
>= (UInt32
) kDisplayModeIDReservedBase
) do {
935 if( mode
== (UInt32
) kDisplayModeIDBootProgrammable
)
938 err
= kIOReturnBadArgument
;
939 if( !detailedTimings
)
942 data
= OSDynamicCast( OSData
, detailedTimings
->getObject(
943 mode
- kDisplayModeIDReservedBase
));
947 bytes
= data
->getBytesNoCopy();
948 err
= setDetailedTiming( mode
, 0, (void *) bytes
, data
->getLength() );
949 if( err
!= kIOReturnSuccess
)
953 *detailed
= (VDDetailedTimingRec
*) bytes
;
960 void IONDRVFramebuffer::getCurrentConfiguration( void )
963 VDSwitchInfoRec switchInfo
;
964 VDGrayRecord grayRec
;
966 grayRec
.csMode
= 0; // turn off luminance map
967 err
= doControl( cscSetGray
, &grayRec
);
968 // driver refused => mono display
969 grayMode
= ((noErr
== err
) && (0 != grayRec
.csMode
));
971 err
= doStatus( cscGetCurMode
, &switchInfo
);
973 currentDisplayMode
= switchInfo
.csData
;
974 currentDepth
= switchInfo
.csMode
- kDepthMode1
;
975 currentPage
= switchInfo
.csPage
;
976 if( 0 == (physicalFramebuffer
= pmap_extract( kernel_pmap
,
977 ((vm_address_t
) switchInfo
.csBaseAddr
) )))
978 physicalFramebuffer
= (UInt32
) switchInfo
.csBaseAddr
;
980 IOLog("%s: cscGetCurMode failed\n", nub
->getName());
983 IODeviceMemory
* IONDRVFramebuffer::makeSubRange(
984 IOPhysicalAddress start
,
985 IOPhysicalLength length
)
987 IODeviceMemory
* mem
= 0;
992 numMaps
= device
->getDeviceMemoryCount();
994 for( i
= 0; (!mem
) && (i
< numMaps
); i
++) {
995 mem
= device
->getDeviceMemoryWithIndex(i
);
998 mem
= IODeviceMemory::withSubRange( mem
,
999 start
- mem
->getPhysicalAddress(), length
);
1002 mem
= IODeviceMemory::withRange( start
, length
);
1007 IODeviceMemory
* IONDRVFramebuffer::getApertureRange( IOPixelAperture aper
)
1010 IOPixelInformation info
;
1013 err
= getPixelInformation( currentDisplayMode
, currentDepth
, aper
,
1018 bytes
= (info
.bytesPerRow
* info
.activeHeight
) + 128;
1020 return( makeSubRange( physicalFramebuffer
, bytes
));
1023 IODeviceMemory
* IONDRVFramebuffer::findVRAM( void )
1025 VDVideoParametersInfoRec pixelParams
;
1027 VDResolutionInfoRec vdRes
;
1029 IOPhysicalAddress vramBase
= physicalFramebuffer
;
1030 IOByteCount vramLength
;
1035 prop
= OSDynamicCast( OSData
, nub
->getProperty("VRAM,memsize"));
1038 vramLength
= *((IOByteCount
*)prop
->getBytesNoCopy());
1040 vramLength
= (vramLength
+ (vramBase
& 0xffff)) & 0xffff0000;
1041 vramBase
&= 0xffff0000;
1047 vdRes
.csPreviousDisplayModeID
= kDisplayModeIDFindFirstResolution
;
1049 (noErr
== doStatus( cscGetNextResolution
, &vdRes
))
1050 && ((SInt32
) vdRes
.csDisplayModeID
> 0) )
1052 pixelParams
.csDisplayModeID
= vdRes
.csDisplayModeID
;
1053 pixelParams
.csDepthMode
= vdRes
.csMaxDepthMode
;
1054 pixelParams
.csVPBlockPtr
= &pixelInfo
;
1055 err
= doStatus( cscGetVideoParameters
, &pixelParams
);
1059 // Control hangs its framebuffer off the end of the aperture to support
1060 // 832 x 624 @ 32bpp. The commented out version will correctly calculate
1061 // the vram length, but DPS needs the full extent to be mapped, so we'll
1062 // end up mapping an extra page that will address vram through the
1063 // little endian aperture. No other drivers like this known.
1065 size
= 0x40 + pixelInfo
.vpBounds
.bottom
*
1066 (pixelInfo
.vpRowBytes
& 0x7fff);
1068 size
= ( (pixelInfo
.vpBounds
.right
* pixelInfo
.vpPixelSize
) / 8) // last line
1069 + (pixelInfo
.vpBounds
.bottom
- 1) *
1070 (pixelInfo
.vpRowBytes
& 0x7fff);
1072 if( size
> vramLength
)
1075 vdRes
.csPreviousDisplayModeID
= vdRes
.csDisplayModeID
;
1078 vramLength
= (vramLength
+ (vramBase
& 0xffff) + 0xffff) & 0xffff0000;
1079 vramBase
&= 0xffff0000;
1082 return( makeSubRange( vramBase
, vramLength
));
1090 const char * IONDRVFramebuffer::getPixelFormats( void )
1092 static const char * ndrvPixelFormats
=
1093 IO1BitIndexedPixels
"\0"
1094 IO2BitIndexedPixels
"\0"
1095 IO4BitIndexedPixels
"\0"
1096 IO8BitIndexedPixels
"\0"
1097 IO16BitDirectPixels
"\0"
1098 IO32BitDirectPixels
"\0"
1101 return( ndrvPixelFormats
);
1104 IOItemCount
IONDRVFramebuffer::getDisplayModeCount( void )
1106 return( iterateAllModes( 0 ));
1109 IOReturn
IONDRVFramebuffer::getDisplayModes( IODisplayModeID
* allDisplayModes
)
1111 iterateAllModes( allDisplayModes
);
1112 return( kIOReturnSuccess
);
1115 IOReturn
IONDRVFramebuffer::validateDetailedTiming(
1116 void * desc
, IOByteCount descripSize
)
1120 err
= setDetailedTiming( kDisplayModeIDPreflight
,
1121 kModePreflight
, desc
, descripSize
);
1126 IOReturn
IONDRVFramebuffer::setDetailedTimings( OSArray
* array
)
1129 UInt32
* newCurrent
;
1130 IOItemCount newCount
;
1132 newCount
= array
->getCount();
1133 newCurrent
= IONew(UInt32
, newCount
);
1135 if( detailedTimings
)
1136 IODelete( detailedTimingsCurrent
, UInt32
, detailedTimings
->getCount());
1137 detailedTimingsCurrent
= newCurrent
;
1138 bzero( newCurrent
, newCount
* sizeof( UInt32
));
1139 setProperty( kIOFBDetailedTimingsKey
, array
); // retains
1140 detailedTimings
= array
;
1141 detailedTimingsSeed
++;
1143 if( currentDisplayMode
== kDisplayModeIDBootProgrammable
) {
1144 VDDetailedTimingRec look
;
1145 VDDetailedTimingRec
* detailed
;
1147 IODisplayModeID newDisplayMode
;
1149 newDisplayMode
= currentDisplayMode
;
1151 bzero( &look
, sizeof( VDDetailedTimingRec
) );
1152 look
.csTimingSize
= sizeof( VDDetailedTimingRec
);
1153 look
.csDisplayModeID
= kDisplayModeIDBootProgrammable
;
1154 err
= doStatus( cscGetDetailedTiming
, &look
);
1156 if( kIOReturnSuccess
== err
)
1158 (data
= OSDynamicCast( OSData
, detailedTimings
->getObject(i
)));
1161 detailed
= (VDDetailedTimingRec
*) data
->getBytesNoCopy();
1162 if( (detailed
->csHorizontalActive
== look
.csHorizontalActive
)
1163 && (detailed
->csVerticalActive
== look
.csVerticalActive
)) {
1165 newDisplayMode
= i
+ kDisplayModeIDReservedBase
;
1169 if( newDisplayMode
!= currentDisplayMode
) {
1170 err
= validateDisplayMode( newDisplayMode
, 0, 0 );
1171 currentDisplayMode
= newDisplayMode
;
1175 err
= kIOReturnSuccess
;
1177 err
= kIOReturnNoMemory
;
1182 IOReturn
IONDRVFramebuffer::getInformationForDisplayMode(
1183 IODisplayModeID displayMode
, IODisplayModeInformation
* info
)
1187 err
= getResInfoForMode( displayMode
, info
);
1189 err
= kIOReturnUnsupportedMode
;
1195 UInt64
IONDRVFramebuffer::getPixelFormatsForDisplayMode(
1196 IODisplayModeID
/* displayMode */, IOIndex depthIndex
)
1198 return( 1 << (depthIndex
+ startAt8
));
1201 IOReturn
IONDRVFramebuffer::getPixelInformation(
1202 IODisplayModeID displayMode
, IOIndex depth
,
1203 IOPixelAperture aperture
, IOPixelInformation
* info
)
1206 VDVideoParametersInfoRec pixelParams
;
1208 const char * formats
;
1212 bzero( info
, sizeof( *info
));
1215 return( kIOReturnUnsupportedMode
);
1217 err
= validateDisplayMode( displayMode
, 0, 0 );
1222 pixelParams
.csDisplayModeID
= displayMode
;
1223 pixelParams
.csDepthMode
= depth
+ kDepthMode1
;
1224 pixelParams
.csVPBlockPtr
= &pixelInfo
;
1225 err
= doStatus( cscGetVideoParameters
, &pixelParams
);
1229 info
->flags
= accessFlags
;
1231 info
->activeWidth
= pixelInfo
.vpBounds
.right
;
1232 info
->activeHeight
= pixelInfo
.vpBounds
.bottom
;
1233 info
->bytesPerRow
= pixelInfo
.vpRowBytes
& 0x7fff;
1234 info
->bytesPerPlane
= pixelInfo
.vpPlaneBytes
;
1235 info
->bitsPerPixel
= pixelInfo
.vpPixelSize
;
1237 formats
= getPixelFormats();
1238 mask
= getPixelFormatsForDisplayMode( displayMode
, depth
);
1240 for( index
= 0; index
< 32; index
++) {
1241 if( (mask
& (1 << index
)) && ((aperture
--) == 0)) {
1242 strcpy( info
->pixelFormat
, formats
);
1245 formats
+= strlen( formats
) + 1;
1248 if( 0 == strcmp("PPPPPPPP", info
->pixelFormat
)) {
1249 info
->pixelType
= kIOCLUTPixels
;
1250 info
->componentMasks
[0] = 0xff;
1251 info
->bitsPerPixel
= 8;
1252 info
->componentCount
= 1;
1253 info
->bitsPerComponent
= 8;
1255 } else if( 0 == strcmp("-RRRRRGGGGGBBBBB", info
->pixelFormat
)) {
1256 info
->pixelType
= kIORGBDirectPixels
;
1257 info
->componentMasks
[0] = 0x7c00;
1258 info
->componentMasks
[1] = 0x03e0;
1259 info
->componentMasks
[2] = 0x001f;
1260 info
->bitsPerPixel
= 16;
1261 info
->componentCount
= 3;
1262 info
->bitsPerComponent
= 5;
1264 } else if( 0 == strcmp("--------RRRRRRRRGGGGGGGGBBBBBBBB",
1265 info
->pixelFormat
)) {
1266 info
->pixelType
= kIORGBDirectPixels
;
1267 info
->componentMasks
[0] = 0x00ff0000;
1268 info
->componentMasks
[1] = 0x0000ff00;
1269 info
->componentMasks
[2] = 0x000000ff;
1270 info
->bitsPerPixel
= 32;
1271 info
->componentCount
= 3;
1272 info
->bitsPerComponent
= 8;
1280 IOReturn
IONDRVFramebuffer::getTimingInfoForDisplayMode(
1281 IODisplayModeID displayMode
, IOTimingInformation
* info
)
1283 VDTimingInfoRec timingInfo
;
1286 err
= validateDisplayMode( displayMode
, 0, 0 );
1290 timingInfo
.csTimingMode
= displayMode
;
1291 // in case the driver doesn't do it:
1292 timingInfo
.csTimingFormat
= kDeclROMtables
;
1293 err
= doStatus( cscGetModeTiming
, &timingInfo
);
1295 if( timingInfo
.csTimingFormat
== kDeclROMtables
)
1296 info
->appleTimingID
= timingInfo
.csTimingData
;
1298 info
->appleTimingID
= timingInvalid
;
1300 return( kIOReturnSuccess
);
1303 return( kIOReturnUnsupportedMode
);
1306 IOReturn
IONDRVFramebuffer::getCurrentDisplayMode(
1307 IODisplayModeID
* displayMode
, IOIndex
* depth
)
1310 *displayMode
= currentDisplayMode
;
1312 *depth
= currentDepth
;
1314 return( kIOReturnSuccess
);
1317 IOReturn
IONDRVFramebuffer::setDisplayMode( IODisplayModeID displayMode
, IOIndex depth
)
1320 VDSwitchInfoRec switchInfo
;
1321 VDPageInfo pageInfo
;
1323 err
= validateDisplayMode( displayMode
, 0, 0 );
1327 ignore_zero_fault( true );
1328 switchInfo
.csData
= displayMode
;
1329 switchInfo
.csMode
= depth
+ kDepthMode1
;
1330 switchInfo
.csPage
= 0;
1331 err
= doControl( cscSwitchMode
, &switchInfo
);
1333 IOLog("%s: cscSwitchMode:%d\n", nub
->getName(), (int)err
);
1335 // duplicate QD InitGDevice
1336 pageInfo
.csMode
= switchInfo
.csMode
;
1337 pageInfo
.csData
= 0;
1338 pageInfo
.csPage
= 0;
1339 doControl( cscSetMode
, &pageInfo
);
1340 doControl( cscGrayPage
, &pageInfo
);
1341 ignore_zero_fault( false );
1343 getCurrentConfiguration();
1348 IOReturn
IONDRVFramebuffer::setStartupDisplayMode(
1349 IODisplayModeID displayMode
, IOIndex depth
)
1352 VDSwitchInfoRec switchInfo
;
1354 err
= validateDisplayMode( displayMode
, 0, 0 );
1358 switchInfo
.csData
= displayMode
;
1359 switchInfo
.csMode
= depth
+ kDepthMode1
;
1360 err
= doControl( cscSavePreferredConfiguration
, &switchInfo
);
1364 IOReturn
IONDRVFramebuffer::getStartupDisplayMode(
1365 IODisplayModeID
* displayMode
, IOIndex
* depth
)
1368 VDSwitchInfoRec switchInfo
;
1370 err
= doStatus( cscGetPreferredConfiguration
, &switchInfo
);
1372 *displayMode
= switchInfo
.csData
;
1373 *depth
= switchInfo
.csMode
- kDepthMode1
;
1378 IOReturn
IONDRVFramebuffer::setApertureEnable( IOPixelAperture
/* aperture */,
1379 IOOptionBits
/* enable */ )
1381 return( kIOReturnSuccess
);
1384 IOReturn
IONDRVFramebuffer::setCLUTWithEntries(
1385 IOColorEntry
* colors
, UInt32 index
, UInt32 numEntries
,
1386 IOOptionBits options
)
1390 VDSetEntryRecord setEntryRec
;
1391 VDClutBehavior clutSetting
;
1392 VDGrayRecord grayRec
;
1394 if( 0 == powerState
)
1395 return( kIOReturnSuccess
);
1397 if( options
& kSetCLUTWithLuminance
)
1398 grayRec
.csMode
= 1; // turn on luminance map
1400 grayRec
.csMode
= 0; // turn off luminance map
1402 if( grayRec
.csMode
!= lastGrayMode
) {
1403 doControl( cscSetGray
, &grayRec
);
1404 lastGrayMode
= grayRec
.csMode
;
1407 if( options
& kSetCLUTImmediately
)
1408 clutSetting
= kSetClutAtSetEntries
;
1410 clutSetting
= kSetClutAtVBL
;
1412 if( clutSetting
!= lastClutSetting
) {
1413 doControl( cscSetClutBehavior
, &clutSetting
);
1414 lastClutSetting
= clutSetting
;
1417 if( options
& kSetCLUTByValue
)
1418 setEntryRec
.csStart
= -1;
1420 setEntryRec
.csStart
= index
;
1422 setEntryRec
.csTable
= (ColorSpec
*) colors
;
1423 setEntryRec
.csCount
= numEntries
- 1;
1425 code
= cscDirectSetEntries
;
1427 code
= cscSetEntries
;
1428 err
= doControl( code
, &setEntryRec
);
1433 IOReturn
IONDRVFramebuffer::setGammaTable( UInt32 channelCount
, UInt32 dataCount
,
1434 UInt32 dataWidth
, void * data
)
1437 VDGammaRecord gammaRec
;
1439 short gVersion
; /*gamma version number*/
1440 short gType
; /*gamma data type*/
1441 short gFormulaSize
; /*Formula data size */
1442 short gChanCnt
; /*number of channels of data */
1443 short gDataCnt
; /*number of values/channel */
1444 short gDataWidth
; /*bits/corrected value */
1445 /* (data packed to next larger byte size) */
1446 UInt8 gFormulaData
[0]; /* data for formulas followed by gamma values */
1448 GammaTbl
* table
= NULL
;
1449 IOByteCount dataLen
= 0;
1451 if( 0 == powerState
)
1452 return( kIOReturnSuccess
);
1455 dataLen
= (dataWidth
+ 7) / 8;
1456 dataLen
*= dataCount
* channelCount
;
1457 table
= (GammaTbl
*) IOMalloc( dataLen
+ sizeof( struct GammaTbl
));
1459 return( kIOReturnNoMemory
);
1461 table
->gVersion
= 0;
1463 table
->gFormulaSize
= 0;
1464 table
->gChanCnt
= channelCount
;
1465 table
->gDataCnt
= dataCount
;
1466 table
->gDataWidth
= dataWidth
;
1467 bcopy( data
, table
->gFormulaData
, dataLen
);
1470 gammaRec
.csGTable
= (Ptr
) table
;
1471 err
= doControl( cscSetGamma
, &gammaRec
);
1473 IOFree( table
, dataLen
+ sizeof( struct GammaTbl
));
1478 IOReturn
IONDRVFramebuffer::getAttribute( IOSelect attribute
, UInt32
* value
)
1480 IOReturn err
= kIOReturnSuccess
;
1481 VDSupportsHardwareCursorRec hwCrsrSupport
;
1483 switch( attribute
) {
1485 case kIOHardwareCursorAttribute
:
1487 *value
= ((kIOReturnSuccess
==
1488 doStatus( cscSupportsHardwareCursor
, &hwCrsrSupport
))
1489 && (hwCrsrSupport
.csSupportsHardwareCursor
));
1493 err
= super::getAttribute( attribute
, value
);
1499 UInt32
IONDRVFramebuffer::getConnectionCount( void )
1501 VDMultiConnectInfoRec theRecord
;
1503 if( doStatus(cscGetMultiConnect
,&theRecord
) == 0 ) {
1504 return theRecord
.csDisplayCountOrNumber
;
1509 IOReturn
IONDRVFramebuffer::setAttributeForConnection( IOIndex connectIndex
,
1510 IOSelect attribute
, UInt32 info
)
1513 VDSyncInfoRec theVDSyncInfoRec
;
1514 VDPowerStateRec sleepInfo
;
1517 switch( attribute
) {
1519 case kConnectionSyncEnable
:
1521 theVDSyncInfoRec
.csMode
= (unsigned char)(info
>>8);
1522 theVDSyncInfoRec
.csFlags
= (unsigned char)(info
& 0xFF);
1523 doControl( cscSetSync
, &theVDSyncInfoRec
);
1525 sleepInfo
.powerState
= ((info
>>8) & 0xff) ? kAVPowerSuspend
: kAVPowerOn
;
1526 sleepInfo
.powerFlags
= 0;
1527 sleepInfo
.powerReserved1
= 0;
1528 sleepInfo
.powerReserved2
= 0;
1529 doControl( cscSetPowerState
, &sleepInfo
);
1531 err
= kIOReturnSuccess
;
1535 err
= super::setAttributeForConnection( connectIndex
,
1543 IOReturn
IONDRVFramebuffer::getAttributeForConnection( IOIndex connectIndex
,
1544 IOSelect attribute
, UInt32
* value
)
1547 VDSyncInfoRec theVDSyncInfoRec
;
1549 switch( attribute
) {
1551 case kConnectionSyncFlags
:
1552 // find out current state of sync lines
1553 theVDSyncInfoRec
.csMode
= 0x00;
1554 doStatus(cscGetSync
,&theVDSyncInfoRec
);
1555 * value
= theVDSyncInfoRec
.csMode
;
1556 ret
= kIOReturnSuccess
;
1558 case kConnectionSyncEnable
:
1559 // what are the sync-controlling capabilities of the ndrv?
1560 theVDSyncInfoRec
.csMode
= 0xFF;
1561 doStatus(cscGetSync
,&theVDSyncInfoRec
);
1562 * value
= (UInt32
)theVDSyncInfoRec
.csMode
;
1563 ret
= kIOReturnSuccess
;
1565 case kConnectionSupportsHLDDCSense
:
1566 case kConnectionSupportsAppleSense
:
1567 ret
= kIOReturnSuccess
;
1570 ret
= super::getAttributeForConnection( connectIndex
,
1578 IOReturn
IONDRVFramebuffer::getAppleSense( IOIndex connectIndex
,
1582 UInt32
* displayType
)
1585 VDMultiConnectInfoRec multiConnect
;
1586 UInt32 sense
, extSense
;
1588 if( connectIndex
== 0 )
1589 err
= doStatus( cscGetConnection
, &multiConnect
.csConnectInfo
);
1592 multiConnect
.csDisplayCountOrNumber
= connectIndex
;
1593 err
= doControl( cscSetMultiConnect
, &multiConnect
);
1598 if( multiConnect
.csConnectInfo
.csConnectFlags
1599 & ((1<<kReportsTagging
) | (1<<kTaggingInfoNonStandard
))
1600 != ((1<<kReportsTagging
)) )
1602 err
= kIOReturnUnsupported
;
1606 sense
= multiConnect
.csConnectInfo
.csConnectTaggedType
;
1607 extSense
= multiConnect
.csConnectInfo
.csConnectTaggedData
;
1608 // bug fixes for really old ATI driver
1610 if( extSense
== 6) {
1612 extSense
= kESCSixStandard
;
1615 if( extSense
== 4) {
1617 extSense
= kESCFourNTSC
;
1623 *extended
= extSense
;
1625 *displayType
= multiConnect
.csConnectInfo
.csDisplayType
;
1632 IOReturn
IONDRVFramebuffer::connectFlags( IOIndex
/* connectIndex */,
1633 IODisplayModeID displayMode
, IOOptionBits
* flags
)
1635 VDTimingInfoRec timingInfo
;
1638 timingInfo
.csTimingMode
= displayMode
;
1639 // in case the driver doesn't do it:
1640 timingInfo
.csTimingFormat
= kDeclROMtables
;
1641 err
= doStatus( cscGetModeTiming
, &timingInfo
);
1643 if( kDetailedTimingFormat
== timingInfo
.csTimingFormat
)
1644 *flags
= kDisplayModeValidFlag
| kDisplayModeSafeFlag
;
1646 *flags
= timingInfo
.csTimingFlags
;
1652 bool IONDRVFramebuffer::hasDDCConnect( IOIndex connectIndex
)
1655 VDMultiConnectInfoRec multiConnect
;
1656 enum { kNeedFlags
= (1<<kReportsDDCConnection
)
1657 | (1<<kHasDDCConnection
) };
1658 if( connectIndex
== 0 )
1659 err
= doStatus( cscGetConnection
, &multiConnect
.csConnectInfo
);
1661 multiConnect
.csDisplayCountOrNumber
= connectIndex
;
1662 err
= doControl( cscSetMultiConnect
, &multiConnect
);
1667 return( (multiConnect
.csConnectInfo
.csConnectFlags
& kNeedFlags
)
1671 IOReturn
IONDRVFramebuffer::getDDCBlock( IOIndex
/* connectIndex */,
1674 IOOptionBits options
,
1675 UInt8
* data
, IOByteCount
* length
)
1679 VDDDCBlockRec ddcRec
;
1680 ByteCount actualLength
= *length
;
1682 ddcRec
.ddcBlockNumber
= blockNumber
;
1683 ddcRec
.ddcBlockType
= blockType
;
1684 ddcRec
.ddcFlags
= options
;
1686 err
= doStatus( cscGetDDCBlock
, &ddcRec
);
1690 if( actualLength
< kDDCBlockSize
)
1691 actualLength
= actualLength
;
1693 actualLength
= kDDCBlockSize
;
1694 bcopy( ddcRec
.ddcBlockData
, data
, actualLength
);
1695 *length
= actualLength
;
1700 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1703 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1705 void IONDRVFramebuffer::initForPM( void )
1707 static const IOPMPowerState powerStates
[ kIONDRVFramebufferPowerStateCount
] = {
1708 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1709 { 1, IOPMDeviceUsable
, IOPMPowerOn
, IOPMPowerOn
, 0, 0, 0, 0, 0, 0, 0, 0 }
1711 // register ourselves with superclass policy-maker
1712 registerPowerDriver( this, (IOPMPowerState
*) powerStates
,
1713 kIONDRVFramebufferPowerStateCount
);
1717 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1718 // maxCapabilityForDomainState
1720 // This simple device needs only power. If the power domain is supplying
1721 // power, the frame buffer can be on. If there is no power it can only be off.
1722 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1724 unsigned long IONDRVFramebuffer::maxCapabilityForDomainState(
1725 IOPMPowerFlags domainState
)
1727 if( domainState
& IOPMPowerOn
)
1728 return( kIONDRVFramebufferPowerStateCount
- 1);
1733 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1734 // initialPowerStateForDomainState
1736 // The power domain may be changing state. If power is on in the new
1737 // state, that will not affect our state at all. If domain power is off,
1738 // we can attain only our lowest state, which is off.
1740 // This implementation is incomplete. It only works in a system where
1741 // the frame buffer is never turned off. When we cross that bridge,
1742 // instead of returning 1, it should return 1 if the frame buffer
1743 // is on, or 0 if it is off.
1744 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1746 unsigned long IONDRVFramebuffer::initialPowerStateForDomainState(
1747 IOPMPowerFlags domainState
)
1749 if( domainState
& IOPMPowerOn
)
1750 return( kIONDRVFramebufferPowerStateCount
- 1);
1756 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1757 // powerStateForDomainState
1759 // The power domain may be changing state. If power is on in the new
1760 // state, that will not affect our state at all. If domain power is off,
1761 // we can attain only our lowest state, which is off.
1762 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1764 unsigned long IONDRVFramebuffer::powerStateForDomainState(
1765 IOPMPowerFlags domainState
)
1767 if( domainState
& IOPMPowerOn
)
1768 return( pm_vars
->myCurrentState
);
1774 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1777 // Called by the superclass to turn the frame buffer on and off.
1778 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1780 IOReturn
IONDRVFramebuffer::setPowerState( unsigned long powerStateOrdinal
,
1781 IOService
* whichDevice
)
1783 static const unsigned long states
[2][2] =
1784 { { kAVPowerOff
, kAVPowerOn
},
1785 { kHardwareSleep
, kHardwareWake
} };
1787 VDPowerStateRec sleepInfo
;
1791 IOAGPDevice
* agpDev
;
1793 if( powerStateOrdinal
== powerState
)
1794 return( IOPMAckImplied
);
1796 if( 0 == powerStateOrdinal
)
1797 super::setPowerState( powerStateOrdinal
, whichDevice
);
1799 sleepInfo
.powerState
= 0;
1800 sleepInfo
.powerFlags
= 0;
1801 sleepInfo
.powerReserved1
= 0;
1802 sleepInfo
.powerReserved2
= 0;
1804 err
= doStatus( cscGetPowerState
, &sleepInfo
);
1805 if( (kIOReturnSuccess
== err
)
1806 && (kPowerStateSleepCanPowerOffMask
& sleepInfo
.powerFlags
))
1807 deepSleep
= platformDeepSleep
;
1809 newState
= states
[deepSleep
& 1][powerStateOrdinal
& 1];
1810 sleepInfo
.powerState
= newState
;
1811 sleepInfo
.powerFlags
= 0;
1812 sleepInfo
.powerReserved1
= 0;
1813 sleepInfo
.powerReserved2
= 0;
1815 ignore_zero_fault( true );
1816 boolean_t ints
= ml_set_interrupts_enabled( false );
1818 err
= doControl( cscSetPowerState
, &sleepInfo
);
1820 ml_set_interrupts_enabled( ints
);
1821 ignore_zero_fault( false );
1823 if( powerStateOrdinal
) {
1824 powerState
= powerStateOrdinal
;
1825 if( kAVPowerOn
== newState
) {
1826 VDPageInfo pageInfo
;
1827 pageInfo
.csData
= 0;
1828 pageInfo
.csPage
= 0;
1829 doControl( cscGrayPage
, &pageInfo
);
1833 setCursorImage( 0 );
1836 agpDev
= OSDynamicCast(IOAGPDevice
, nub
);
1838 agpDev
= OSDynamicCast( IOAGPDevice
, nub
->getParentEntry(gIODTPlane
));
1842 powerState
= powerStateOrdinal
;
1844 if( powerStateOrdinal
)
1845 super::setPowerState( powerStateOrdinal
, whichDevice
);
1847 return( IOPMAckImplied
);
1850 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1853 // Real problem : getStartupMode doesn't.
1855 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1858 #define super IONDRVFramebuffer
1860 OSDefineMetaClassAndStructors(IOATINDRV
, IONDRVFramebuffer
)
1861 OSDefineMetaClassAndStructors(IOATI128NDRV
, IOATINDRV
)
1863 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1865 IOReturn
IOATINDRV::getStartupDisplayMode(
1866 IODisplayModeID
* displayMode
, IOIndex
* depth
)
1871 prop
= OSDynamicCast( OSData
, nub
->getProperty("Sime"));
1873 nvram
= (UInt16
*) prop
->getBytesNoCopy();
1874 *displayMode
= nvram
[ 0 ]; // 1 is physDisplayMode
1875 *depth
= nvram
[ 2 ] - kDepthMode1
;
1876 return( kIOReturnSuccess
);
1878 return(super::getStartupDisplayMode( displayMode
, depth
));
1881 IODeviceMemory
* IOATINDRV::findVRAM( void )
1884 IOByteCount
* lengths
;
1886 IOPhysicalAddress vramBase
;
1887 IOByteCount vramLength
;
1889 prop
= OSDynamicCast( OSData
, nub
->getProperty("ATY,memsize"));
1891 return( super::findVRAM());
1893 lengths
= (IOByteCount
*) prop
->getBytesNoCopy();
1894 count
= prop
->getLength() / sizeof(IOByteCount
);
1896 prop
= OSDynamicCast( OSData
, nub
->getProperty("ATY,Base"));
1898 if( prop
&& (count
> 1)) {
1899 vramBase
= *((IOPhysicalAddress
*)prop
->getBytesNoCopy());
1900 vramLength
= lengths
[1];
1901 vramBase
&= ~(vramLength
- 1);
1903 vramBase
= physicalFramebuffer
;
1904 vramLength
= lengths
[0];
1908 return( super::findVRAM());
1910 vramLength
= (vramLength
+ (vramBase
& 0xffff)) & 0xffff0000;
1911 vramBase
&= 0xffff0000;
1913 return( makeSubRange( vramBase
, vramLength
));
1916 static int g128ExtraCurs
= 8;
1917 static int g128DeltaCurs
= 0x25c0;
1919 void IOATI128NDRV::flushCursor( void )
1921 volatile UInt32
* fb
;
1925 fb
= (volatile UInt32
*) frameBuffer
;
1926 for( i
= 0; i
< g128ExtraCurs
; i
++) {
1928 fb
+= g128DeltaCurs
;
1934 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 0);
1935 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 1);
1936 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 2);
1937 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 3);
1938 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 4);
1939 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 5);
1940 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 6);
1941 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 7);
1942 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 8);
1943 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 9);
1944 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 10);
1945 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 11);
1946 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 12);
1947 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 13);
1948 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 14);
1949 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 15);
1950 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 16);
1951 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 17);
1952 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 18);
1953 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 19);
1954 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 20);
1955 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 21);
1956 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 22);
1957 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 23);
1958 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 24);
1959 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 25);
1960 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 26);
1961 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 27);
1962 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 28);
1963 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 29);
1964 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 30);
1965 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 31);