]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IONDRVSupport/IONDRVFramebuffer.cpp
472e54d9ec7efd66872f422a4c09423cd8e3c332
[apple/xnu.git] / iokit / Families / IONDRVSupport / IONDRVFramebuffer.cpp
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 * Copyright (c) 1997-1998 Apple Computer, Inc.
24 *
25 *
26 * HISTORY
27 *
28 * sdouglas 22 Oct 97 - first checked in.
29 * sdouglas 24 Jul 98 - start IOKit.
30 * sdouglas 15 Dec 98 - cpp.
31 *
32 */
33
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>
42
43 #include <libkern/c++/OSContainers.h>
44
45 #include "IONDRV.h"
46
47 #include <string.h>
48
49 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
50
51 class IOATINDRV : public IONDRVFramebuffer
52 {
53 OSDeclareDefaultStructors(IOATINDRV)
54
55 public:
56 virtual IOReturn getStartupDisplayMode( IODisplayModeID * displayMode,
57 IOIndex * depth );
58 virtual IODeviceMemory * findVRAM( void );
59
60 };
61
62 class IOATI128NDRV : public IOATINDRV
63 {
64 OSDeclareDefaultStructors(IOATI128NDRV)
65
66 public:
67 virtual void flushCursor( void );
68 };
69
70 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
71
72 struct _VSLService {
73 class IONDRVFramebuffer * framebuffer;
74 IOSelect type;
75 IOFBInterruptProc handler;
76 OSObject * target;
77 void * ref;
78 _VSLService * next;
79 };
80
81 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
82
83 // IONDRVFramebuffer has two power states, off and on
84
85 enum { kIONDRVFramebufferPowerStateCount = 2 };
86
87 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
88
89 #define super IOFramebuffer
90
91 OSDefineMetaClassAndStructors(IONDRVFramebuffer, IOFramebuffer)
92
93 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
94
95 //============
96 //= External =
97 //============
98
99 IOService * IONDRVFramebuffer::probe( IOService * provider,
100 SInt32 * score )
101 {
102 IOService * inst = this;
103 IOService * newInst = 0;
104 const char * name;
105
106 if( !super::probe( provider, score ))
107 return( 0 );
108
109 if( 0 != provider->getProperty(kIONDRVIgnoreKey)) return( 0 );
110
111 if( /* IONDRV::fromRegistryEntry( provider ) || */ true) {
112
113 provider->setProperty(kIONDRVForXKey, this, sizeof(this) );
114
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;
121
122 if( newInst) {
123 if( ! newInst->init( inst->getPropertyTable())) {
124 newInst->release();
125 newInst = 0;
126 }
127 inst = newInst;
128 }
129 } else
130 inst = 0;
131
132 return( inst );
133 }
134
135 IOReturn IONDRVFramebuffer::setProperties( OSObject * properties )
136 {
137 OSDictionary * dict;
138 OSData * data;
139 IOReturn kr = kIOReturnUnsupported;
140
141 if( !(dict = OSDynamicCast( OSDictionary, properties)))
142 return( kIOReturnBadArgument);
143
144 if( (data = OSDynamicCast(OSData,
145 dict->getObject("driver,AAPL,MacOS,PowerPC")))) {
146
147 if( ndrvState)
148 return( kIOReturnStillOpen );
149
150 if( ndrv)
151 ndrv->release();
152 nub->setProperty("driver,AAPL,MacOS,PowerPC", data);
153 nub->removeProperty("AAPL,ndrvInst");
154 ndrv = IONDRV::fromRegistryEntry( nub, &_undefinedSymbolHandler, (void *) this );
155 if( ndrv)
156 setName( ndrv->driverName());
157
158 kr = kIOReturnSuccess;
159 }
160
161 return( kr );
162 }
163
164 static IOPMrootDomain * gIOPMRootDomain;
165
166 bool IONDRVFramebuffer::start( IOService * provider )
167 {
168 bool ok = false;
169 IOService * parent;
170 OSData * data;
171
172 do {
173 cachedVDResolution.csDisplayModeID = kDisplayModeIDInvalid;
174
175 nub = provider;
176 ndrv = IONDRV::fromRegistryEntry( provider, &_undefinedSymbolHandler, this );
177 if( ndrv)
178 setName( ndrv->driverName());
179 startAt8 = 3;
180 consoleDevice = (0 != provider->getProperty("AAPL,boot-display"));
181 powerState = 1;
182
183 if( 0 == nub->getDeviceMemoryCount()) {
184 parent = OSDynamicCast( IOService, nub->getParentEntry(gIODTPlane));
185 if( parent) {
186 parent->getResources();
187 OSArray * array = parent->getDeviceMemory();
188 array->retain();
189 nub->setDeviceMemory( array);
190 array->release();
191 }
192 }
193
194 if( false == super::start( nub ))
195 continue;
196
197 if( !gIOPMRootDomain)
198 gIOPMRootDomain = (IOPMrootDomain *)
199 IORegistryEntry::fromPath("/IOPowerConnection/IOPMrootDomain", gIOPowerPlane);
200 if( gIOPMRootDomain)
201 platformDeepSleep = (gIOPMRootDomain->getSleepSupported()
202 & kFrameBufferDeepSleepSupported) ? 1 : 0;
203
204 // default flags can be overriden
205 accessFlags = 0;
206 if(0 == strncmp("3Dfx", provider->getName(), strlen("3Dfx")))
207 accessFlags |= kFramebufferDisableAltivecAccess;
208
209 if( (data = OSDynamicCast( OSData, provider->getProperty(kIOFBHostAccessFlagsKey))))
210 accessFlags = *((UInt32 *) data->getBytesNoCopy());
211
212 ok = true; // Success
213
214 } while( false);
215
216 return( ok);
217 }
218
219 bool IONDRVFramebuffer::isConsoleDevice( void )
220 {
221 return( consoleDevice );
222 }
223
224 // osfmk/ppc/mappings.h
225 extern "C" { extern void ignore_zero_fault(boolean_t); }
226
227 IOReturn IONDRVFramebuffer::enableController( void )
228 {
229 IOReturn err;
230 const char * logname;
231 OSData * data;
232
233 logname = getProvider()->getName();
234
235 if( 0 == strcmp( "control", logname))
236 waitForService( resourceMatching( "IOiic0" ));
237
238 if( 0 == ndrv)
239 err = kIOReturnNotReady;
240 else
241 err = IONDRVLibrariesInitialize( getProvider() );
242
243 if( kIOReturnSuccess == err) do {
244
245 ignore_zero_fault( true );
246 err = checkDriver();
247 ignore_zero_fault( false );
248
249 if( err) {
250 IOLog("%s: Not usable\n", logname );
251 if( err == -999)
252 IOLog("%s: driver incompatible.\n", logname );
253 continue;
254 }
255 getCurrentConfiguration();
256 vramMemory = findVRAM();
257
258 // disable clamshell sleep on a single head portable
259 if( gIOPMRootDomain
260 && (0 == OSDynamicCast( IOPCIDevice, getProvider()))
261 && (data = OSDynamicCast( OSData,
262 getProvider()->getProperty("ATY,PanelActive")))) {
263
264 if( 0 == *((UInt32 *) data->getBytesNoCopy()))
265 gIOPMRootDomain->receivePowerNotification( kIOPMIgnoreClamshell);
266 }
267
268 // initialize power management of the device
269 initForPM();
270
271 } while( false);
272
273 return( err);
274 }
275
276 IODeviceMemory * IONDRVFramebuffer::getVRAMRange( void )
277 {
278 if( vramMemory)
279 vramMemory->retain();
280
281 return( vramMemory );
282 }
283
284 const IOTVector * IONDRVFramebuffer::_undefinedSymbolHandler( void * self,
285 const char * libraryName, const char * symbolName )
286 {
287 return( ((IONDRVFramebuffer *)self)->undefinedSymbolHandler( libraryName, symbolName) );
288 }
289
290 const IOTVector * IONDRVFramebuffer::undefinedSymbolHandler( const char * libraryName,
291 const char * symbolName )
292 {
293 return( 0 );
294 }
295
296 void IONDRVFramebuffer::free( void )
297 {
298 super::free();
299 }
300
301 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
302
303 IOReturn IONDRVFramebuffer::registerForInterruptType( IOSelect interruptType,
304 IOFBInterruptProc proc, OSObject * target, void * ref,
305 void ** interruptRef )
306
307 {
308 _VSLService * service;
309 IOReturn err;
310
311 if( (interruptType == kIOFBVBLInterruptType)
312 && (getProvider()->getProperty("Ignore VBL")))
313 return( kIOReturnUnsupported );
314
315 for( service = vslServices;
316 service && (service->type != interruptType);
317 service = service->next ) {}
318
319 if( service) {
320
321 if( service->handler)
322 err = kIOReturnBusy;
323
324 else {
325 service->target = target;
326 service->ref = ref;
327 service->handler = proc;
328 *interruptRef = service;
329 err = kIOReturnSuccess;
330 }
331
332 } else
333 err = kIOReturnNoResources;
334
335 return( err );
336 }
337
338 IOReturn IONDRVFramebuffer::unregisterInterrupt( void * interruptRef )
339 {
340 _VSLService * service = (_VSLService *) interruptRef;
341
342 service->handler = 0;
343
344 return( kIOReturnSuccess );
345 }
346
347 IOReturn IONDRVFramebuffer::setInterruptState( void * interruptRef,
348 UInt32 state )
349 {
350 return( kIOReturnUnsupported );
351 }
352
353 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
354
355 //// VSL calls
356
357 OSStatus IONDRVFramebuffer::VSLNewInterruptService(
358 void * entryID,
359 IOSelect serviceType,
360 _VSLService ** vslService )
361 {
362 IORegistryEntry * regEntry;
363 IONDRVFramebuffer * fb;
364 _VSLService * service;
365 IOReturn err = kIOReturnSuccess;
366
367 REG_ENTRY_TO_OBJ( (const RegEntryID *) entryID, regEntry)
368
369 fb = OSDynamicCast( IONDRVFramebuffer,
370 regEntry->getChildEntry( gIOServicePlane ));
371 assert( fb );
372
373 if( fb) {
374 service = IONew( _VSLService, 1 );
375
376 if( service) {
377 service->framebuffer = fb;
378 service->type = serviceType;
379 service->handler = 0;
380 service->next = fb->vslServices;
381 fb->vslServices = service;
382
383 *vslService = service;
384
385 } else
386 err = kIOReturnNoMemory;
387
388 } else
389 err = kIOReturnBadArgument;
390
391 return( err );
392 }
393
394 OSStatus IONDRVFramebuffer::VSLDisposeInterruptService(_VSLService * vslService)
395 {
396 IONDRVFramebuffer * fb;
397 _VSLService * next;
398 _VSLService * prev;
399
400 if( vslService) {
401
402 fb = vslService->framebuffer;
403
404 prev = fb->vslServices;
405 if( prev == vslService)
406 fb->vslServices = vslService->next;
407 else {
408 while( ((next = prev->next) != vslService) && next)
409 prev = next;
410 if( next)
411 prev->next = vslService->next;
412 }
413
414 IODelete( vslService, _VSLService, 1 );
415 }
416
417 return( kIOReturnSuccess );
418 }
419
420 OSStatus IONDRVFramebuffer::VSLDoInterruptService( _VSLService * vslService )
421 {
422 IOFBInterruptProc proc;
423
424 if( vslService) {
425 if( (proc = vslService->handler))
426 (*proc) (vslService->target, vslService->ref);
427 }
428
429 return( kIOReturnSuccess );
430 }
431
432 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
433
434 struct _VSLCursorRef {
435 IOFramebuffer * framebuffer;
436 void * cursorImage;
437 };
438
439 Boolean IONDRVFramebuffer::VSLPrepareCursorForHardwareCursor(
440 void * cursorRef,
441 IOHardwareCursorDescriptor * hwDesc,
442 IOHardwareCursorInfo * hwCursorInfo )
443 {
444 _VSLCursorRef * cursor = (_VSLCursorRef *) cursorRef;
445 bool ok;
446
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;
453
454 return( ok );
455 }
456
457 IOReturn IONDRVFramebuffer::setCursorImage( void * cursorImage )
458 {
459 _VSLCursorRef cursorRef;
460 VDSetHardwareCursorRec setCursor;
461 IOReturn err;
462
463 if( 0 == powerState)
464 return( kIOReturnSuccess );
465
466 cursorRef.framebuffer = this;
467 cursorRef.cursorImage = cursorImage;
468
469 setCursor.csCursorRef = (void *) &cursorRef;
470 setCursor.csReserved1 = 0;
471 setCursor.csReserved2 = 0;
472
473 err = doControl( cscSetHardwareCursor, &setCursor );
474
475 return( err );
476 }
477
478 IOReturn IONDRVFramebuffer::setCursorState( SInt32 x, SInt32 y, bool visible )
479 {
480 VDDrawHardwareCursorRec drawCursor;
481 IOReturn err;
482
483 if( 0 == powerState)
484 return( kIOReturnSuccess );
485
486 if( 0 == OSIncrementAtomic( &ndrvEnter))
487 {
488
489 drawCursor.csCursorX = x;
490 drawCursor.csCursorY = y;
491 drawCursor.csCursorVisible = visible;
492 drawCursor.csReserved1 = 0;
493 drawCursor.csReserved2 = 0;
494
495 err = doControl( cscDrawHardwareCursor, &drawCursor );
496
497 } else
498 err = kIOReturnBusy;
499
500 OSDecrementAtomic( &ndrvEnter );
501
502 return( err );
503 }
504
505 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
506
507 //============
508 //= Internal =
509 //============
510
511 IOReturn IONDRVFramebuffer::doControl( UInt32 code, void * params )
512 {
513 IOReturn err;
514 CntrlParam pb;
515
516 if( ndrvState == 0)
517 return( kIOReturnNotOpen);
518
519 pb.qLink = 0;
520 pb.csCode = code;
521 pb.csParams = params;
522
523 OSIncrementAtomic( &ndrvEnter );
524 err = ndrv->doDriverIO( /*ID*/ (UInt32) &pb, &pb,
525 kControlCommand, kImmediateIOCommandKind );
526 OSDecrementAtomic( &ndrvEnter );
527
528 return( err);
529 }
530
531 IOReturn IONDRVFramebuffer::doStatus( UInt32 code, void * params )
532 {
533 IOReturn err;
534 CntrlParam pb;
535
536 if( ndrvState == 0)
537 return( kIOReturnNotOpen);
538
539 pb.qLink = 0;
540 pb.csCode = code;
541 pb.csParams = params;
542
543 OSIncrementAtomic( &ndrvEnter );
544 err = ndrv->doDriverIO( /*ID*/ (UInt32) &pb, &pb,
545 kStatusCommand, kImmediateIOCommandKind );
546 OSDecrementAtomic( &ndrvEnter );
547
548 return( err);
549 }
550
551
552 IOReturn IONDRVFramebuffer::checkDriver( void )
553 {
554 OSStatus err = noErr;
555 struct DriverInitInfo initInfo;
556 CntrlParam pb;
557 VDClutBehavior clutSetting;
558 VDGammaRecord gammaRec;
559 VDSwitchInfoRec switchInfo;
560 IOTimingInformation info;
561 VDPageInfo pageInfo;
562
563 if( ndrvState == 0) {
564 do {
565 initInfo.refNum = 0xffcd; // ...sure.
566 MAKE_REG_ENTRY(initInfo.deviceEntry, nub )
567
568 err = ndrv->doDriverIO( 0, &initInfo,
569 kInitializeCommand, kImmediateIOCommandKind );
570 if( err) continue;
571
572 err = ndrv->doDriverIO( 0, &pb,
573 kOpenCommand, kImmediateIOCommandKind );
574
575 } while( false);
576
577 if( err)
578 return( err);
579
580 // allow calls to ndrv
581 ndrvState = 1;
582
583 if( (noErr == doStatus( cscGetCurMode, &switchInfo ))
584 && (noErr == getTimingInfoForDisplayMode( switchInfo.csData, &info))
585 && (timingApple_0x0_0hz_Offline == info.appleTimingID)) {
586
587 IOLog("%s: display offline\n", getName());
588 err = kIOReturnOffline;
589 return( err);
590 } else
591 ndrvState = 2;
592
593 #if IONDRVI2CLOG
594 do {
595 VDCommunicationInfoRec commInfo;
596
597 bzero( &commInfo, sizeof( commInfo));
598 commInfo.csBusID = kVideoDefaultBus;
599
600 err = doStatus( cscGetCommunicationInfo, &commInfo );
601 IOLog("%s: cscGetCommunicationInfo: ", getName());
602 if( kIOReturnSuccess != err) {
603 IOLog("fails with %ld\n", err);
604 continue;
605 }
606 if( commInfo.csSupportedTypes & (1<<kVideoDDCciReplyType) )
607 IOLog("supports kVideoDDCciReplyType, ");
608 if( commInfo.csSupportedTypes & (1<<kVideoSimpleI2CType) ) {
609 IOLog("supports kVideoSimpleI2CType");
610 VDCommunicationRec comm;
611 UInt8 edidData[132];
612 UInt8 edidRequest[2];
613
614 edidData[0] = 0xAA;
615 edidData[1] = 0xAA;
616 edidData[2] = 0xAA;
617 edidData[3] = 0xAA;
618 edidData[128] = 0xAA;
619 edidData[129] = 0xAA;
620 edidData[130] = 0xAA;
621 edidData[131] = 0xAA;
622
623 memset( edidData, 0xAA, sizeof( edidData));
624
625 edidRequest[0] = 0;
626 edidRequest[1] = 0;
627
628 comm.csBusID = kVideoDefaultBus;
629 comm.csReserved0 = 0;
630 comm.csReserved1 = 0;
631 comm.csReserved2 = 0;
632
633 comm.csSendAddress = 0xA0;
634 comm.csSendType = kVideoSimpleI2CType;
635 comm.csSendBuffer = &edidRequest[0];
636 comm.csSendSize = 0x01;
637
638 comm.csReplyAddress = 0xA1;
639 comm.csReplyType = kVideoSimpleI2CType;
640 comm.csReplyBuffer = &edidData[0];
641 comm.csReplySize = 128;
642
643 comm.csReserved3 = 0;
644 comm.csReserved4 = 0;
645 comm.csReserved5 = 0;
646 comm.csReserved6 = 0;
647
648 do {
649 err = doControl( cscDoCommunication, &comm );
650 IOLog("\nI2C read block[%x](%ld)\n", edidRequest[0], err);
651 if( kIOReturnSuccess != err)
652 break;
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++) {
655 if( 0 == (i & 15))
656 IOLog("\n%02x: ", i);
657 IOLog("%02x ", edidData[i]);
658 }
659 IOLog("\n");
660 if( edidRequest[0] || (0 == edidData[126]))
661 break;
662 edidRequest[0] = 0x80;
663 } while( true );
664 }
665
666 } while( false );
667 #endif /* IONDRVI2CLOG */
668
669 // duplicate QD InitGDevice
670 pageInfo.csMode = switchInfo.csMode;
671 pageInfo.csData = 0;
672 pageInfo.csPage = 0;
673 doControl( cscGrayPage, &pageInfo);
674
675 clutSetting = kSetClutAtSetEntries;
676 lastClutSetting = clutSetting;
677 doControl( cscSetClutBehavior, &clutSetting);
678
679 do {
680 VDDisplayTimingRangeRec rangeRec;
681
682 bzero( &rangeRec, sizeof( rangeRec));
683 err = doStatus( cscGetTimingRanges, &rangeRec );
684 if( kIOReturnSuccess != err)
685 continue;
686
687 setProperty( kIOFBTimingRangeKey, &rangeRec, sizeof( rangeRec));
688
689 } while( false );
690
691 #if 1
692 // bogus for ROM control
693 do {
694
695 VDGetGammaListRec scan;
696 VDRetrieveGammaRec get;
697 GammaTbl * table;
698 char name[ 64 ];
699
700 scan.csPreviousGammaTableID = kGammaTableIDFindFirst;
701 scan.csGammaTableName = name;
702 err = doStatus( cscGetGammaInfoList, &scan);
703 if( err || (scan.csGammaTableID == (GammaTableID) kGammaTableIDNoMoreTables))
704 continue;
705
706 table = (GammaTbl *)IOMalloc( scan.csGammaTableSize);
707 if( 0 == table)
708 continue;
709 get.csGammaTableID = scan.csGammaTableID;
710 get.csGammaTablePtr = table;
711
712 err = doStatus( cscRetrieveGammaTable, &get );
713 if( noErr == err) {
714 kprintf("Setting gamma %s\n", scan.csGammaTableName);
715 gammaRec.csGTable = (Ptr) table;
716 doControl( cscSetGamma, &gammaRec );
717 }
718
719 IOFree( table, scan.csGammaTableSize);
720
721 } while( false);
722 #endif
723 }
724 return( noErr);
725 }
726
727
728 UInt32 IONDRVFramebuffer::iterateAllModes( IODisplayModeID * displayModeIDs )
729 {
730 VDResolutionInfoRec info;
731 UInt32 num = 0;
732
733 info.csPreviousDisplayModeID = kDisplayModeIDFindFirstResolution;
734
735 while(
736 (noErr == doStatus( cscGetNextResolution, &info))
737 && ((SInt32) info.csDisplayModeID > 0) ) {
738
739 if( displayModeIDs)
740 displayModeIDs[ num ] = info.csDisplayModeID;
741
742 info.csPreviousDisplayModeID = info.csDisplayModeID;
743 num++;
744 }
745
746 if( detailedTimings) {
747 IOItemCount count, i;
748
749 count = detailedTimings->getCount();
750 if( displayModeIDs) {
751 for( i = 0; i < count; i++)
752 displayModeIDs[ num + i ] = kDisplayModeIDReservedBase + i;
753 }
754 num += count;
755 }
756
757 return( num);
758 }
759
760 IOReturn IONDRVFramebuffer::getResInfoForArbMode( IODisplayModeID modeID,
761 IODisplayModeInformation * info )
762 {
763 VDVideoParametersInfoRec pixelParams;
764 VPBlock pixelInfo;
765 VDDetailedTimingRec * detailed;
766 IOIndex depth;
767 IOReturn err;
768
769 err = validateDisplayMode( modeID, 0, &detailed );
770
771 for( depth = -1; err == kIOReturnSuccess; ) {
772 pixelParams.csDisplayModeID = modeID;
773 pixelParams.csDepthMode = ++depth + kDepthMode1;
774 pixelParams.csVPBlockPtr = &pixelInfo;
775 err = doStatus( cscGetVideoParameters, &pixelParams );
776 }
777
778 if( depth) {
779 info->maxDepthIndex = depth - 1;
780 info->nominalWidth = pixelInfo.vpBounds.right;
781 info->nominalHeight = pixelInfo.vpBounds.bottom;
782 if( detailed)
783 info->refreshRate = detailed->csPixelClock * 65536ULL /
784 ((detailed->csVerticalActive + detailed->csVerticalBlanking)
785 * (detailed->csHorizontalActive + detailed->csHorizontalBlanking));
786 else
787 info->refreshRate = 0;
788
789 err = kIOReturnSuccess;
790 }
791
792 return( err );
793 }
794
795 IOReturn IONDRVFramebuffer::getResInfoForMode( IODisplayModeID modeID,
796 IODisplayModeInformation * info )
797 {
798
799 bzero( info, sizeof( *info));
800
801 if( (UInt32) modeID >= (UInt32) kDisplayModeIDReservedBase)
802 return( getResInfoForArbMode( modeID, info ));
803
804 // unfortunately, there is no "kDisplayModeIDFindSpecific"
805 if( cachedVDResolution.csDisplayModeID != (UInt32) modeID) {
806
807 // try the next after cached mode
808 cachedVDResolution.csPreviousDisplayModeID = cachedVDResolution.csDisplayModeID;
809 if( (noErr != doStatus( cscGetNextResolution, &cachedVDResolution))
810 || (cachedVDResolution.csDisplayModeID != (UInt32) modeID) ) {
811
812 // else full blown iterate
813 cachedVDResolution.csPreviousDisplayModeID = kDisplayModeIDFindFirstResolution;
814 while(
815 (noErr == doStatus( cscGetNextResolution, &cachedVDResolution))
816 && (cachedVDResolution.csDisplayModeID != (UInt32) modeID)
817 && ((SInt32) cachedVDResolution.csDisplayModeID > 0)) {
818
819 cachedVDResolution.csPreviousDisplayModeID = cachedVDResolution.csDisplayModeID;
820 }
821 }
822 }
823
824 if( cachedVDResolution.csDisplayModeID != (UInt32) modeID) {
825 cachedVDResolution.csDisplayModeID = kDisplayModeIDInvalid;
826 return( kIOReturnUnsupportedMode);
827
828 } else {
829
830 info->maxDepthIndex = cachedVDResolution.csMaxDepthMode - kDepthMode1;
831 info->nominalWidth = cachedVDResolution.csHorizontalPixels;
832 info->nominalHeight = cachedVDResolution.csVerticalLines;
833 info->refreshRate = cachedVDResolution.csRefreshRate;
834
835 return( noErr);
836 }
837 }
838
839 enum {
840 kModePreflight = 1,
841 kDisplayModeIDPreflight = kDisplayModeIDReservedBase + 1000
842 };
843
844 IOReturn IONDRVFramebuffer::setDetailedTiming(
845 IODisplayModeID mode, IOOptionBits options,
846 void * _desc, IOByteCount descripSize )
847 {
848 IOReturn err;
849 VDResolutionInfoRec info;
850 VDDetailedTimingRec * desc = (VDDetailedTimingRec *)_desc;
851 VDDetailedTimingRec look;
852 IOIndex index;
853 bool notPreflight = (0 == (options & kModePreflight));
854
855 // current must be ok
856 if( mode == currentDisplayMode)
857 return( kIOReturnSuccess );
858
859 index = mode - kDisplayModeIDReservedBase;
860 bzero( &look, sizeof( VDDetailedTimingRec) );
861 look.csTimingSize = sizeof( VDDetailedTimingRec);
862
863 // look for a programmable
864 for(
865 info.csPreviousDisplayModeID = kDisplayModeIDFindFirstProgrammable;
866 (noErr == (err = doStatus( cscGetNextResolution, &info)));
867 info.csPreviousDisplayModeID = info.csDisplayModeID) {
868
869 if( (SInt32) info.csDisplayModeID < 0) {
870 err = kIOReturnNoResources;
871 break;
872 }
873
874 look.csDisplayModeID = info.csDisplayModeID;
875 err = doStatus( cscGetDetailedTiming, &look );
876 if( err != kIOReturnSuccess)
877 continue;
878
879 // don't toss current
880 if( look.csDisplayModeAlias == (UInt32) currentDisplayMode)
881 continue;
882
883 // see if already set to the right timing
884 if( (look.csDisplayModeAlias == (UInt32) mode)
885 && (look.csDisplayModeState == kDMSModeReady)
886 && (notPreflight)
887 && (detailedTimingsCurrent[index] == detailedTimingsSeed))
888 break;
889
890 // set it free
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)
897 continue;
898 }
899 // set it ready
900 desc->csDisplayModeID = info.csDisplayModeID;
901 desc->csDisplayModeAlias = mode;
902 desc->csDisplayModeSeed = look.csDisplayModeSeed;
903 desc->csDisplayModeState = kDMSModeReady;
904 err = doControl( cscSetDetailedTiming, desc );
905
906 if( kIOReturnSuccess == err) {
907 if( notPreflight)
908 // don't stomp orig record
909 desc = &look;
910 err = doStatus( cscGetDetailedTiming, desc );
911 }
912 if( notPreflight && (kIOReturnSuccess == err))
913 detailedTimingsCurrent[index] = detailedTimingsSeed;
914
915 break;
916 }
917
918 return( err );
919 }
920
921 IOReturn IONDRVFramebuffer::validateDisplayMode(
922 IODisplayModeID _mode, IOOptionBits flags,
923 VDDetailedTimingRec ** detailed )
924 {
925 UInt32 mode = _mode;
926 IOReturn err = kIOReturnSuccess;
927 OSData * data;
928 const void * bytes;
929
930 if( detailed)
931 *detailed = (VDDetailedTimingRec *) 0;
932
933 if( mode >= (UInt32) kDisplayModeIDReservedBase) do {
934
935 if( mode == (UInt32) kDisplayModeIDBootProgrammable)
936 continue;
937
938 err = kIOReturnBadArgument;
939 if( !detailedTimings)
940 continue;
941
942 data = OSDynamicCast( OSData, detailedTimings->getObject(
943 mode - kDisplayModeIDReservedBase));
944 if( !data)
945 continue;
946
947 bytes = data->getBytesNoCopy();
948 err = setDetailedTiming( mode, 0, (void *) bytes, data->getLength() );
949 if( err != kIOReturnSuccess)
950 continue;
951
952 if( detailed)
953 *detailed = (VDDetailedTimingRec *) bytes;
954
955 } while( false );
956
957 return( err );
958 }
959
960 void IONDRVFramebuffer::getCurrentConfiguration( void )
961 {
962 IOReturn err;
963 VDSwitchInfoRec switchInfo;
964 VDGrayRecord grayRec;
965
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));
970
971 err = doStatus( cscGetCurMode, &switchInfo );
972 if( err == noErr) {
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;
979 } else
980 IOLog("%s: cscGetCurMode failed\n", nub->getName());
981 }
982
983 IODeviceMemory * IONDRVFramebuffer::makeSubRange(
984 IOPhysicalAddress start,
985 IOPhysicalLength length )
986 {
987 IODeviceMemory * mem = 0;
988 UInt32 numMaps, i;
989 IOService * device;
990
991 device = nub;
992 numMaps = device->getDeviceMemoryCount();
993
994 for( i = 0; (!mem) && (i < numMaps); i++) {
995 mem = device->getDeviceMemoryWithIndex(i);
996 if( !mem)
997 continue;
998 mem = IODeviceMemory::withSubRange( mem,
999 start - mem->getPhysicalAddress(), length );
1000 }
1001 if( !mem)
1002 mem = IODeviceMemory::withRange( start, length );
1003
1004 return( mem );
1005 }
1006
1007 IODeviceMemory * IONDRVFramebuffer::getApertureRange( IOPixelAperture aper )
1008 {
1009 IOReturn err;
1010 IOPixelInformation info;
1011 IOByteCount bytes;
1012
1013 err = getPixelInformation( currentDisplayMode, currentDepth, aper,
1014 &info );
1015 if( err)
1016 return( 0 );
1017
1018 bytes = (info.bytesPerRow * info.activeHeight) + 128;
1019
1020 return( makeSubRange( physicalFramebuffer, bytes ));
1021 }
1022
1023 IODeviceMemory * IONDRVFramebuffer::findVRAM( void )
1024 {
1025 VDVideoParametersInfoRec pixelParams;
1026 VPBlock pixelInfo;
1027 VDResolutionInfoRec vdRes;
1028 UInt32 size;
1029 IOPhysicalAddress vramBase = physicalFramebuffer;
1030 IOByteCount vramLength;
1031 IOReturn err;
1032 OSData * prop;
1033
1034 vramLength = 0;
1035 prop = OSDynamicCast( OSData, nub->getProperty("VRAM,memsize"));
1036
1037 if( prop) {
1038 vramLength = *((IOByteCount *)prop->getBytesNoCopy());
1039 if( vramLength) {
1040 vramLength = (vramLength + (vramBase & 0xffff)) & 0xffff0000;
1041 vramBase &= 0xffff0000;
1042 }
1043 }
1044
1045 if( !vramLength) {
1046
1047 vdRes.csPreviousDisplayModeID = kDisplayModeIDFindFirstResolution;
1048 while(
1049 (noErr == doStatus( cscGetNextResolution, &vdRes))
1050 && ((SInt32) vdRes.csDisplayModeID > 0) )
1051 {
1052 pixelParams.csDisplayModeID = vdRes.csDisplayModeID;
1053 pixelParams.csDepthMode = vdRes.csMaxDepthMode;
1054 pixelParams.csVPBlockPtr = &pixelInfo;
1055 err = doStatus( cscGetVideoParameters, &pixelParams);
1056 if( err)
1057 continue;
1058
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.
1064 #if 1
1065 size = 0x40 + pixelInfo.vpBounds.bottom *
1066 (pixelInfo.vpRowBytes & 0x7fff);
1067 #else
1068 size = ( (pixelInfo.vpBounds.right * pixelInfo.vpPixelSize) / 8) // last line
1069 + (pixelInfo.vpBounds.bottom - 1) *
1070 (pixelInfo.vpRowBytes & 0x7fff);
1071 #endif
1072 if( size > vramLength)
1073 vramLength = size;
1074
1075 vdRes.csPreviousDisplayModeID = vdRes.csDisplayModeID;
1076 }
1077
1078 vramLength = (vramLength + (vramBase & 0xffff) + 0xffff) & 0xffff0000;
1079 vramBase &= 0xffff0000;
1080 }
1081
1082 return( makeSubRange( vramBase, vramLength ));
1083 }
1084
1085
1086 //============
1087 //= External =
1088 //============
1089
1090 const char * IONDRVFramebuffer::getPixelFormats( void )
1091 {
1092 static const char * ndrvPixelFormats =
1093 IO1BitIndexedPixels "\0"
1094 IO2BitIndexedPixels "\0"
1095 IO4BitIndexedPixels "\0"
1096 IO8BitIndexedPixels "\0"
1097 IO16BitDirectPixels "\0"
1098 IO32BitDirectPixels "\0"
1099 "\0";
1100
1101 return( ndrvPixelFormats);
1102 }
1103
1104 IOItemCount IONDRVFramebuffer::getDisplayModeCount( void )
1105 {
1106 return( iterateAllModes( 0 ));
1107 }
1108
1109 IOReturn IONDRVFramebuffer::getDisplayModes( IODisplayModeID * allDisplayModes )
1110 {
1111 iterateAllModes( allDisplayModes );
1112 return( kIOReturnSuccess );
1113 }
1114
1115 IOReturn IONDRVFramebuffer::validateDetailedTiming(
1116 void * desc, IOByteCount descripSize )
1117 {
1118 IOReturn err;
1119
1120 err = setDetailedTiming( kDisplayModeIDPreflight,
1121 kModePreflight, desc, descripSize);
1122
1123 return( err );
1124 }
1125
1126 IOReturn IONDRVFramebuffer::setDetailedTimings( OSArray * array )
1127 {
1128 IOReturn err;
1129 UInt32 * newCurrent;
1130 IOItemCount newCount;
1131
1132 newCount = array->getCount();
1133 newCurrent = IONew(UInt32, newCount);
1134 if( newCurrent) {
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++;
1142
1143 if( currentDisplayMode == kDisplayModeIDBootProgrammable) {
1144 VDDetailedTimingRec look;
1145 VDDetailedTimingRec * detailed;
1146 OSData * data;
1147 IODisplayModeID newDisplayMode;
1148
1149 newDisplayMode = currentDisplayMode;
1150
1151 bzero( &look, sizeof( VDDetailedTimingRec) );
1152 look.csTimingSize = sizeof( VDDetailedTimingRec);
1153 look.csDisplayModeID = kDisplayModeIDBootProgrammable;
1154 err = doStatus( cscGetDetailedTiming, &look );
1155
1156 if( kIOReturnSuccess == err)
1157 for( int i = 0;
1158 (data = OSDynamicCast( OSData, detailedTimings->getObject(i)));
1159 i++) {
1160
1161 detailed = (VDDetailedTimingRec *) data->getBytesNoCopy();
1162 if( (detailed->csHorizontalActive == look.csHorizontalActive)
1163 && (detailed->csVerticalActive == look.csVerticalActive)) {
1164
1165 newDisplayMode = i + kDisplayModeIDReservedBase;
1166 break;
1167 }
1168 }
1169 if( newDisplayMode != currentDisplayMode) {
1170 err = validateDisplayMode( newDisplayMode, 0, 0 );
1171 currentDisplayMode = newDisplayMode;
1172 }
1173 }
1174
1175 err = kIOReturnSuccess;
1176 } else
1177 err = kIOReturnNoMemory;
1178
1179 return( err );
1180 }
1181
1182 IOReturn IONDRVFramebuffer::getInformationForDisplayMode(
1183 IODisplayModeID displayMode, IODisplayModeInformation * info )
1184 {
1185 IOReturn err;
1186
1187 err = getResInfoForMode( displayMode, info );
1188 if( err)
1189 err = kIOReturnUnsupportedMode;
1190
1191 return( err );
1192 }
1193
1194
1195 UInt64 IONDRVFramebuffer::getPixelFormatsForDisplayMode(
1196 IODisplayModeID /* displayMode */, IOIndex depthIndex )
1197 {
1198 return( 1 << (depthIndex + startAt8));
1199 }
1200
1201 IOReturn IONDRVFramebuffer::getPixelInformation(
1202 IODisplayModeID displayMode, IOIndex depth,
1203 IOPixelAperture aperture, IOPixelInformation * info )
1204 {
1205 SInt32 err;
1206 VDVideoParametersInfoRec pixelParams;
1207 VPBlock pixelInfo;
1208 const char * formats;
1209 UInt32 mask;
1210 int index;
1211
1212 bzero( info, sizeof( *info));
1213
1214 if( aperture)
1215 return( kIOReturnUnsupportedMode);
1216
1217 err = validateDisplayMode( displayMode, 0, 0 );
1218 if( err)
1219 return( err );
1220
1221 do {
1222 pixelParams.csDisplayModeID = displayMode;
1223 pixelParams.csDepthMode = depth + kDepthMode1;
1224 pixelParams.csVPBlockPtr = &pixelInfo;
1225 err = doStatus( cscGetVideoParameters, &pixelParams );
1226 if( err)
1227 continue;
1228
1229 info->flags = accessFlags;
1230
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;
1236
1237 formats = getPixelFormats();
1238 mask = getPixelFormatsForDisplayMode( displayMode, depth );
1239
1240 for( index = 0; index < 32; index++) {
1241 if( (mask & (1 << index)) && ((aperture--) == 0)) {
1242 strcpy( info->pixelFormat, formats);
1243 break;
1244 }
1245 formats += strlen( formats) + 1;
1246 }
1247
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;
1254
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;
1263
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;
1273 }
1274
1275 } while( false);
1276
1277 return( err);
1278 }
1279
1280 IOReturn IONDRVFramebuffer::getTimingInfoForDisplayMode(
1281 IODisplayModeID displayMode, IOTimingInformation * info )
1282 {
1283 VDTimingInfoRec timingInfo;
1284 OSStatus err;
1285
1286 err = validateDisplayMode( displayMode, 0, 0 );
1287 if( err)
1288 return( err );
1289
1290 timingInfo.csTimingMode = displayMode;
1291 // in case the driver doesn't do it:
1292 timingInfo.csTimingFormat = kDeclROMtables;
1293 err = doStatus( cscGetModeTiming, &timingInfo);
1294 if( err == noErr) {
1295 if( timingInfo.csTimingFormat == kDeclROMtables)
1296 info->appleTimingID = timingInfo.csTimingData;
1297 else
1298 info->appleTimingID = timingInvalid;
1299
1300 return( kIOReturnSuccess);
1301 }
1302
1303 return( kIOReturnUnsupportedMode);
1304 }
1305
1306 IOReturn IONDRVFramebuffer::getCurrentDisplayMode(
1307 IODisplayModeID * displayMode, IOIndex * depth )
1308 {
1309 if( displayMode)
1310 *displayMode = currentDisplayMode;
1311 if( depth)
1312 *depth = currentDepth;
1313
1314 return( kIOReturnSuccess);
1315 }
1316
1317 IOReturn IONDRVFramebuffer::setDisplayMode( IODisplayModeID displayMode, IOIndex depth )
1318 {
1319 SInt32 err;
1320 VDSwitchInfoRec switchInfo;
1321 VDPageInfo pageInfo;
1322
1323 err = validateDisplayMode( displayMode, 0, 0 );
1324 if( err)
1325 return( err );
1326
1327 ignore_zero_fault( true );
1328 switchInfo.csData = displayMode;
1329 switchInfo.csMode = depth + kDepthMode1;
1330 switchInfo.csPage = 0;
1331 err = doControl( cscSwitchMode, &switchInfo);
1332 if(err)
1333 IOLog("%s: cscSwitchMode:%d\n", nub->getName(), (int)err);
1334
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 );
1342
1343 getCurrentConfiguration();
1344
1345 return( err);
1346 }
1347
1348 IOReturn IONDRVFramebuffer::setStartupDisplayMode(
1349 IODisplayModeID displayMode, IOIndex depth )
1350 {
1351 SInt32 err;
1352 VDSwitchInfoRec switchInfo;
1353
1354 err = validateDisplayMode( displayMode, 0, 0 );
1355 if( err)
1356 return( err );
1357
1358 switchInfo.csData = displayMode;
1359 switchInfo.csMode = depth + kDepthMode1;
1360 err = doControl( cscSavePreferredConfiguration, &switchInfo);
1361 return( err);
1362 }
1363
1364 IOReturn IONDRVFramebuffer::getStartupDisplayMode(
1365 IODisplayModeID * displayMode, IOIndex * depth )
1366 {
1367 SInt32 err;
1368 VDSwitchInfoRec switchInfo;
1369
1370 err = doStatus( cscGetPreferredConfiguration, &switchInfo);
1371 if( err == noErr) {
1372 *displayMode = switchInfo.csData;
1373 *depth = switchInfo.csMode - kDepthMode1;
1374 }
1375 return( err);
1376 }
1377
1378 IOReturn IONDRVFramebuffer::setApertureEnable( IOPixelAperture /* aperture */,
1379 IOOptionBits /* enable */ )
1380 {
1381 return( kIOReturnSuccess);
1382 }
1383
1384 IOReturn IONDRVFramebuffer::setCLUTWithEntries(
1385 IOColorEntry * colors, UInt32 index, UInt32 numEntries,
1386 IOOptionBits options )
1387 {
1388 IOReturn err;
1389 UInt32 code;
1390 VDSetEntryRecord setEntryRec;
1391 VDClutBehavior clutSetting;
1392 VDGrayRecord grayRec;
1393
1394 if( 0 == powerState)
1395 return( kIOReturnSuccess );
1396
1397 if( options & kSetCLUTWithLuminance)
1398 grayRec.csMode = 1; // turn on luminance map
1399 else
1400 grayRec.csMode = 0; // turn off luminance map
1401
1402 if( grayRec.csMode != lastGrayMode) {
1403 doControl( cscSetGray, &grayRec);
1404 lastGrayMode = grayRec.csMode;
1405 }
1406
1407 if( options & kSetCLUTImmediately)
1408 clutSetting = kSetClutAtSetEntries;
1409 else
1410 clutSetting = kSetClutAtVBL;
1411
1412 if( clutSetting != lastClutSetting) {
1413 doControl( cscSetClutBehavior, &clutSetting);
1414 lastClutSetting = clutSetting;
1415 }
1416
1417 if( options & kSetCLUTByValue)
1418 setEntryRec.csStart = -1;
1419 else
1420 setEntryRec.csStart = index;
1421
1422 setEntryRec.csTable = (ColorSpec *) colors;
1423 setEntryRec.csCount = numEntries - 1;
1424 if( directMode)
1425 code = cscDirectSetEntries;
1426 else
1427 code = cscSetEntries;
1428 err = doControl( code, &setEntryRec);
1429
1430 return( err);
1431 }
1432
1433 IOReturn IONDRVFramebuffer::setGammaTable( UInt32 channelCount, UInt32 dataCount,
1434 UInt32 dataWidth, void * data )
1435 {
1436 IOReturn err;
1437 VDGammaRecord gammaRec;
1438 struct GammaTbl {
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 */
1447 };
1448 GammaTbl * table = NULL;
1449 IOByteCount dataLen = 0;
1450
1451 if( 0 == powerState)
1452 return( kIOReturnSuccess );
1453
1454 if( data) {
1455 dataLen = (dataWidth + 7) / 8;
1456 dataLen *= dataCount * channelCount;
1457 table = (GammaTbl *) IOMalloc( dataLen + sizeof( struct GammaTbl));
1458 if( NULL == table)
1459 return( kIOReturnNoMemory);
1460
1461 table->gVersion = 0;
1462 table->gType = 0;
1463 table->gFormulaSize = 0;
1464 table->gChanCnt = channelCount;
1465 table->gDataCnt = dataCount;
1466 table->gDataWidth = dataWidth;
1467 bcopy( data, table->gFormulaData, dataLen);
1468 }
1469
1470 gammaRec.csGTable = (Ptr) table;
1471 err = doControl( cscSetGamma, &gammaRec);
1472 if( table)
1473 IOFree( table, dataLen + sizeof( struct GammaTbl));
1474
1475 return( err);
1476 }
1477
1478 IOReturn IONDRVFramebuffer::getAttribute( IOSelect attribute, UInt32 * value )
1479 {
1480 IOReturn err = kIOReturnSuccess;
1481 VDSupportsHardwareCursorRec hwCrsrSupport;
1482
1483 switch( attribute ) {
1484
1485 case kIOHardwareCursorAttribute:
1486
1487 *value = ((kIOReturnSuccess ==
1488 doStatus( cscSupportsHardwareCursor, &hwCrsrSupport))
1489 && (hwCrsrSupport.csSupportsHardwareCursor));
1490 break;
1491
1492 default:
1493 err = super::getAttribute( attribute, value );
1494 }
1495
1496 return( err );
1497 }
1498
1499 UInt32 IONDRVFramebuffer::getConnectionCount( void )
1500 {
1501 VDMultiConnectInfoRec theRecord;
1502
1503 if( doStatus(cscGetMultiConnect,&theRecord) == 0 ) {
1504 return theRecord.csDisplayCountOrNumber;
1505 }
1506 return 1;
1507 }
1508
1509 /*
1510 File: DDCPowerOnOffUtils.c <CS3>
1511 */
1512
1513 enum{
1514 kVCPSendSize = 8,
1515 kVCPReplySize = 64,
1516 kI2CDisplayWriteAddress = 0x6E,
1517 kI2CDisplayReadAddress = 0x6F,
1518 // Messed up specification says checksum should be calculated with ACCESS.bus value of 50.
1519 kI2CDisplayReadHostCheckSumAddress = 0x50,
1520 // Messed up specification says checksum should be calculated with ACCESS.bus value of 50.
1521 kI2CDisplayReadHostAddress = 0x51,
1522
1523 kI2CVCPGetCode = 0x01,
1524 kI2CVCPGetLength = 0x82,
1525 kI2CVCPGetMessageSize = 0x05,
1526
1527 kI2CVCPReplyLength = 0x88,
1528 kI2CNullReplyLength = 0x80,
1529 kI2CNullReplyCheckSum = 0xBE,
1530
1531 kI2CVCPSetCode = 0x03,
1532 kI2CVCPSetLength = 0x84,
1533 kI2CVCPReplyCode = 0x02,
1534
1535 kDDCPowerOn = 0x01,
1536 kDDCPowerOff = 0x04
1537 };
1538 enum {
1539 kBasicI2CCommTransactionsMask = ( (1<<kVideoNoTransactionType) | (1<<kVideoSimpleI2CType)
1540 | (1<<kVideoDDCciReplyType) )
1541 };
1542
1543 void IONDRVFramebuffer::displayI2CPower( bool enable )
1544 {
1545 VDCommunicationRec i2CRecord;
1546 VDCommunicationInfoRec i2cInfoRecord;
1547 Byte sendBuffer[8];
1548 Byte replyBuffer[kVCPReplySize];
1549 UInt32 supportedCommFlags = 0;
1550 // Don't do it if we're told it's not supported
1551 bool setThisDisplay = true;
1552
1553 //
1554 // Some displays (like Fiji) do not support the reading
1555 // of the current power state. Others (like Mitsubishi
1556 // Diamond Pro 710) report that they do not support
1557 // power management calls.
1558 //
1559 // I'll avoid sending the power command only in the
1560 // case that I get a valid reply that does says
1561 // it does not support the power selector.
1562 //
1563
1564 bzero( &i2cInfoRecord, sizeof(i2cInfoRecord) );
1565 if( noErr != doStatus( cscGetCommunicationInfo, &i2cInfoRecord))
1566 return;
1567 if( kBasicI2CCommTransactionsMask != (i2cInfoRecord.csSupportedTypes & kBasicI2CCommTransactionsMask))
1568 return;
1569 if( !shouldDoI2CPower)
1570 return;
1571
1572 supportedCommFlags = i2cInfoRecord.csSupportedCommFlags;
1573 bzero( &i2CRecord, sizeof(i2CRecord) );
1574 bzero( &sendBuffer, sizeof(sendBuffer) );
1575 bzero( &replyBuffer, sizeof(replyBuffer) );
1576
1577 sendBuffer[0] = kI2CDisplayReadHostAddress;
1578 sendBuffer[1] = kI2CVCPGetLength;
1579 sendBuffer[2] = kI2CVCPGetCode; // GetVCP command
1580 sendBuffer[3] = 0xD6;
1581 sendBuffer[4] = kI2CDisplayWriteAddress ^
1582 sendBuffer[0] ^ sendBuffer[1] ^
1583 sendBuffer[2] ^ sendBuffer[3];
1584
1585 i2CRecord.csBusID = kVideoDefaultBus;
1586 i2CRecord.csSendType = kVideoSimpleI2CType;
1587 i2CRecord.csSendAddress = kI2CDisplayWriteAddress;
1588 i2CRecord.csSendBuffer = &sendBuffer;
1589 i2CRecord.csSendSize = 7;
1590 i2CRecord.csReplyType = kVideoDDCciReplyType;
1591 i2CRecord.csReplyAddress = kI2CDisplayReadAddress;
1592 i2CRecord.csReplyBuffer = &replyBuffer;
1593 i2CRecord.csReplySize = kVCPReplySize;
1594
1595 if( supportedCommFlags & kVideoReplyMicroSecDelayMask )
1596 {
1597 // We know some displays are slow, this is an important call to get right
1598 i2CRecord.csCommFlags |= kVideoReplyMicroSecDelayMask;
1599 // 50 milliseconds should be enough time for the display to respond.
1600 i2CRecord.csMinReplyDelay = 50 * 1000;
1601 }
1602
1603 if( (noErr == doControl( cscDoCommunication, &i2CRecord))
1604 && (kI2CDisplayWriteAddress == replyBuffer[0])
1605 && (kI2CVCPReplyLength == replyBuffer[1])
1606 && (kI2CVCPReplyCode == replyBuffer[2])) {
1607 Byte checkSum = kI2CDisplayReadHostCheckSumAddress ^ // host address
1608 replyBuffer[0] ^ // source address
1609 replyBuffer[1] ^ // message length (0x88)
1610 replyBuffer[2] ^ // VCP type code
1611 replyBuffer[3] ^ // result code
1612 replyBuffer[4] ^ // VCP op code
1613 replyBuffer[5] ^ // VCP type code
1614 replyBuffer[6] ^ // Max value MSB
1615 replyBuffer[7] ^ // Max value LSB
1616 replyBuffer[8] ^ // Current value MSB
1617 replyBuffer[9]; // Current value LSB
1618
1619 if( (checkSum == replyBuffer[10]) && // Did the check sum match AND
1620 (0 != replyBuffer[3])) // Are we not supposed to support this feature?
1621 setThisDisplay = false; // Don't do it if we're told it's not supported
1622 }
1623
1624 if( setThisDisplay) {
1625
1626 bzero( &i2CRecord, sizeof(i2CRecord) );
1627 bzero( &sendBuffer, sizeof(sendBuffer) );
1628 bzero( &replyBuffer, sizeof(replyBuffer) );
1629
1630 sendBuffer[0] = kI2CDisplayReadHostAddress;
1631 sendBuffer[1] = kI2CVCPSetLength;
1632 sendBuffer[2] = kI2CVCPSetCode; // SetVCP command
1633 sendBuffer[3] = 0xD6;
1634 sendBuffer[4] = 0; // MSB
1635 sendBuffer[5] = enable ? kDDCPowerOn : kDDCPowerOff; // LSB
1636 sendBuffer[6] = kI2CDisplayWriteAddress ^
1637 sendBuffer[0] ^ sendBuffer[1] ^
1638 sendBuffer[2] ^ sendBuffer[3] ^
1639 sendBuffer[4] ^ sendBuffer[5];
1640
1641 i2CRecord.csBusID = kVideoDefaultBus;
1642 i2CRecord.csSendAddress = kI2CDisplayWriteAddress;
1643 i2CRecord.csSendType = kVideoSimpleI2CType;
1644 i2CRecord.csSendBuffer = &sendBuffer;
1645 i2CRecord.csSendSize = 7;
1646 i2CRecord.csReplyType = kVideoNoTransactionType;
1647 i2CRecord.csReplyAddress = 0;
1648 i2CRecord.csReplyBuffer = 0;
1649 i2CRecord.csReplySize = 0;
1650
1651 if( supportedCommFlags & kVideoReplyMicroSecDelayMask) {
1652 // We know some displays are slow, this is an important call to get right
1653 i2CRecord.csCommFlags |= kVideoReplyMicroSecDelayMask;
1654 // 50 milliseconds should be enough time for the display to respond.
1655 i2CRecord.csMinReplyDelay = 50 * 1000;
1656 }
1657
1658 doControl( cscDoCommunication, &i2CRecord);
1659 }
1660 }
1661 IOReturn IONDRVFramebuffer::setAttributeForConnection( IOIndex connectIndex,
1662 IOSelect attribute, UInt32 info )
1663 {
1664 IOReturn err;
1665 VDSyncInfoRec theVDSyncInfoRec;
1666 VDPowerStateRec sleepInfo;
1667
1668 switch( attribute ) {
1669
1670 case kConnectionSyncEnable:
1671
1672 theVDSyncInfoRec.csMode = (unsigned char)(info>>8);
1673 theVDSyncInfoRec.csFlags = (unsigned char)(info & 0xFF);
1674 doControl( cscSetSync, &theVDSyncInfoRec);
1675
1676 sleepInfo.powerState = ((info>>8) & 0xff) ? kAVPowerSuspend : kAVPowerOn;
1677 sleepInfo.powerFlags = 0;
1678 sleepInfo.powerReserved1 = 0;
1679 sleepInfo.powerReserved2 = 0;
1680 doControl( cscSetPowerState, &sleepInfo);
1681
1682 displayI2CPower( ((info>>8) & 0xff) ? false : true );
1683
1684 err = kIOReturnSuccess;
1685 break;
1686
1687 default:
1688 err = super::setAttributeForConnection( connectIndex,
1689 attribute, info );
1690 break;
1691 }
1692 return( err );
1693 }
1694
1695
1696 IOReturn IONDRVFramebuffer::getAttributeForConnection( IOIndex connectIndex,
1697 IOSelect attribute, UInt32 * value )
1698 {
1699 IOReturn ret;
1700 VDSyncInfoRec theVDSyncInfoRec;
1701
1702 switch( attribute ) {
1703
1704 case kConnectionSyncFlags:
1705 // find out current state of sync lines
1706 theVDSyncInfoRec.csMode = 0x00;
1707 doStatus(cscGetSync,&theVDSyncInfoRec);
1708 * value = theVDSyncInfoRec.csMode;
1709 ret = kIOReturnSuccess;
1710 break;
1711 case kConnectionSyncEnable:
1712 // what are the sync-controlling capabilities of the ndrv?
1713 theVDSyncInfoRec.csMode = 0xFF;
1714 doStatus(cscGetSync,&theVDSyncInfoRec);
1715 * value = (UInt32)theVDSyncInfoRec.csMode;
1716 ret = kIOReturnSuccess;
1717 break;
1718 case kConnectionSupportsHLDDCSense:
1719 case kConnectionSupportsAppleSense:
1720 ret = kIOReturnSuccess;
1721 break;
1722 default:
1723 ret = super::getAttributeForConnection( connectIndex,
1724 attribute, value );
1725 break;
1726 }
1727
1728 return( ret );
1729 }
1730
1731 IOReturn IONDRVFramebuffer::getAppleSense( IOIndex connectIndex,
1732 UInt32 * senseType,
1733 UInt32 * primary,
1734 UInt32 * extended,
1735 UInt32 * displayType )
1736 {
1737 OSStatus err;
1738 VDMultiConnectInfoRec multiConnect;
1739 UInt32 sense, extSense;
1740
1741 if( connectIndex == 0 )
1742 err = doStatus( cscGetConnection, &multiConnect.csConnectInfo);
1743
1744 else {
1745 multiConnect.csDisplayCountOrNumber = connectIndex;
1746 err = doControl( cscSetMultiConnect, &multiConnect);
1747 }
1748 if( err)
1749 return( err);
1750
1751 if( multiConnect.csConnectInfo.csConnectFlags
1752 & ((1<<kReportsTagging) | (1<<kTaggingInfoNonStandard))
1753 != ((1<<kReportsTagging)) )
1754
1755 err = kIOReturnUnsupported;
1756
1757 else {
1758
1759 sense = multiConnect.csConnectInfo.csConnectTaggedType;
1760 extSense = multiConnect.csConnectInfo.csConnectTaggedData;
1761 // bug fixes for really old ATI driver
1762 if( sense == 0) {
1763 if( extSense == 6) {
1764 sense = kRSCSix;
1765 extSense = kESCSixStandard;
1766 }
1767 else
1768 if( extSense == 4) {
1769 sense = kRSCFour;
1770 extSense = kESCFourNTSC;
1771 }
1772 }
1773 if( primary)
1774 *primary = sense;
1775 if( extended)
1776 *extended = extSense;
1777 if( displayType)
1778 *displayType = multiConnect.csConnectInfo.csDisplayType;
1779 if( senseType)
1780 *senseType = 0;
1781 }
1782 return( err);
1783 }
1784
1785 IOReturn IONDRVFramebuffer::connectFlags( IOIndex /* connectIndex */,
1786 IODisplayModeID displayMode, IOOptionBits * flags )
1787 {
1788 VDTimingInfoRec timingInfo;
1789 OSStatus err;
1790
1791 timingInfo.csTimingMode = displayMode;
1792 // in case the driver doesn't do it:
1793 timingInfo.csTimingFormat = kDeclROMtables;
1794 err = doStatus( cscGetModeTiming, &timingInfo);
1795
1796 if( kDetailedTimingFormat == timingInfo.csTimingFormat)
1797 *flags = kDisplayModeValidFlag | kDisplayModeSafeFlag;
1798 else
1799 *flags = timingInfo.csTimingFlags;
1800
1801 return( err );
1802 }
1803
1804
1805 bool IONDRVFramebuffer::hasDDCConnect( IOIndex connectIndex )
1806 {
1807 OSStatus err;
1808 VDMultiConnectInfoRec multiConnect;
1809 enum { kNeedFlags = (1<<kReportsDDCConnection)
1810 | (1<<kHasDDCConnection) };
1811 if( connectIndex == 0 )
1812 err = doStatus( cscGetConnection, &multiConnect.csConnectInfo);
1813 else {
1814 multiConnect.csDisplayCountOrNumber = connectIndex;
1815 err = doControl( cscSetMultiConnect, &multiConnect);
1816 }
1817 if( err)
1818 return( err);
1819
1820 return( (multiConnect.csConnectInfo.csConnectFlags & kNeedFlags)
1821 == kNeedFlags );
1822 }
1823
1824 // I2C first year for Apple displays.
1825 // Apple monitors older than this (and Manta)
1826 // are never called with I2C commands
1827 enum {
1828 kFirstAppleI2CYear = 1999,
1829 kAppleVESAVendorID = 0x0610
1830 };
1831
1832 struct EDID {
1833 UInt8 header[8];
1834 UInt8 vendorProduct[4];
1835 UInt8 serialNumber[4];
1836 UInt8 weekOfManufacture;
1837 UInt8 yearOfManufacture;
1838 UInt8 version;
1839 UInt8 revision;
1840 UInt8 displayParams[5];
1841 UInt8 colorCharacteristics[10];
1842 UInt8 establishedTimings[3];
1843 UInt16 standardTimings[8];
1844 UInt8 descriptors[4][18];
1845 UInt8 extension;
1846 UInt8 checksum;
1847 };
1848
1849 static bool IsApplePowerBlock(UInt8 * theBlock)
1850 {
1851 return( theBlock &&
1852 0x00000000 == *(UInt32 *)&theBlock[0] &&
1853 0x00 == theBlock[4] &&
1854 0x06 == theBlock[5] &&
1855 0x10 == theBlock[6] );
1856 }
1857
1858 IOReturn IONDRVFramebuffer::getDDCBlock( IOIndex /* connectIndex */,
1859 UInt32 blockNumber,
1860 IOSelect blockType,
1861 IOOptionBits options,
1862 UInt8 * data, IOByteCount * length )
1863
1864 {
1865 OSStatus err = 0;
1866 VDDDCBlockRec ddcRec;
1867 ByteCount actualLength = *length;
1868
1869 ddcRec.ddcBlockNumber = blockNumber;
1870 ddcRec.ddcBlockType = blockType;
1871 ddcRec.ddcFlags = options;
1872
1873 err = doStatus( cscGetDDCBlock, &ddcRec);
1874
1875 if( err == noErr) {
1876
1877 if( actualLength < kDDCBlockSize)
1878 actualLength = actualLength;
1879 else
1880 actualLength = kDDCBlockSize;
1881 bcopy( ddcRec.ddcBlockData, data, actualLength);
1882 *length = actualLength;
1883
1884 if( (1 == blockNumber) && (kIODDCBlockTypeEDID == blockType)
1885 && (actualLength >= sizeof( EDID))) do {
1886
1887 EDID * edid;
1888 UInt32 vendor;
1889 UInt32 product;
1890
1891 edid = (EDID *) data;
1892 vendor = (edid->vendorProduct[0] << 8) | edid->vendorProduct[1];
1893 product = (edid->vendorProduct[3] << 8) | edid->vendorProduct[2];
1894 if( kAppleVESAVendorID == vendor) {
1895 if( (0x01F4 == product) || (0x9D02 == product))
1896 continue;
1897 if( edid->yearOfManufacture && ((edid->yearOfManufacture + 1990) < kFirstAppleI2CYear))
1898 continue;
1899 }
1900 shouldDoI2CPower = (IsApplePowerBlock( &edid->descriptors[1][0])
1901 || IsApplePowerBlock( &edid->descriptors[2][0])
1902 || IsApplePowerBlock( &edid->descriptors[3][0]));
1903
1904 } while( false );
1905 }
1906
1907 IOLog("%s: i2cPower %d\n", getName(), shouldDoI2CPower);
1908
1909 return( err);
1910 }
1911
1912 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1913 // initForPM
1914 //
1915 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1916
1917 void IONDRVFramebuffer::initForPM( void )
1918 {
1919 static const IOPMPowerState powerStates[ kIONDRVFramebufferPowerStateCount ] = {
1920 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1921 { 1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 }
1922 };
1923 // register ourselves with superclass policy-maker
1924 registerPowerDriver( this, (IOPMPowerState *) powerStates,
1925 kIONDRVFramebufferPowerStateCount );
1926 }
1927
1928
1929 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1930 // maxCapabilityForDomainState
1931 //
1932 // This simple device needs only power. If the power domain is supplying
1933 // power, the frame buffer can be on. If there is no power it can only be off.
1934 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1935
1936 unsigned long IONDRVFramebuffer::maxCapabilityForDomainState(
1937 IOPMPowerFlags domainState )
1938 {
1939 if( domainState & IOPMPowerOn)
1940 return( kIONDRVFramebufferPowerStateCount - 1);
1941 else
1942 return( 0);
1943 }
1944
1945 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1946 // initialPowerStateForDomainState
1947 //
1948 // The power domain may be changing state. If power is on in the new
1949 // state, that will not affect our state at all. If domain power is off,
1950 // we can attain only our lowest state, which is off.
1951 //
1952 // This implementation is incomplete. It only works in a system where
1953 // the frame buffer is never turned off. When we cross that bridge,
1954 // instead of returning 1, it should return 1 if the frame buffer
1955 // is on, or 0 if it is off.
1956 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1957
1958 unsigned long IONDRVFramebuffer::initialPowerStateForDomainState(
1959 IOPMPowerFlags domainState )
1960 {
1961 if( domainState & IOPMPowerOn)
1962 return( kIONDRVFramebufferPowerStateCount - 1);
1963 else
1964 return( 0);
1965 }
1966
1967
1968 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1969 // powerStateForDomainState
1970 //
1971 // The power domain may be changing state. If power is on in the new
1972 // state, that will not affect our state at all. If domain power is off,
1973 // we can attain only our lowest state, which is off.
1974 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1975
1976 unsigned long IONDRVFramebuffer::powerStateForDomainState(
1977 IOPMPowerFlags domainState )
1978 {
1979 if( domainState & IOPMPowerOn)
1980 return( pm_vars->myCurrentState);
1981 else
1982 return( 0);
1983 }
1984
1985
1986 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1987 // setPowerState
1988 //
1989 // Called by the superclass to turn the frame buffer on and off.
1990 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1991
1992 IOReturn IONDRVFramebuffer::setPowerState( unsigned long powerStateOrdinal,
1993 IOService * whichDevice )
1994 {
1995 static const unsigned long states[2][2] =
1996 { { kAVPowerOff, kAVPowerOn },
1997 { kHardwareSleep, kHardwareWake } };
1998
1999 VDPowerStateRec sleepInfo;
2000 IOReturn err;
2001 int deepSleep = 0;
2002 UInt32 newState;
2003 IOAGPDevice * agpDev;
2004
2005 if( powerStateOrdinal == powerState)
2006 return( IOPMAckImplied );
2007
2008 if( 0 == powerStateOrdinal)
2009 super::setPowerState( powerStateOrdinal, whichDevice );
2010
2011 sleepInfo.powerState = 0;
2012 sleepInfo.powerFlags = 0;
2013 sleepInfo.powerReserved1 = 0;
2014 sleepInfo.powerReserved2 = 0;
2015
2016 err = doStatus( cscGetPowerState, &sleepInfo);
2017 if( (kIOReturnSuccess == err)
2018 && (kPowerStateSleepCanPowerOffMask & sleepInfo.powerFlags))
2019 deepSleep = platformDeepSleep;
2020
2021 newState = states[deepSleep & 1][powerStateOrdinal & 1];
2022 sleepInfo.powerState = newState;
2023 sleepInfo.powerFlags = 0;
2024 sleepInfo.powerReserved1 = 0;
2025 sleepInfo.powerReserved2 = 0;
2026
2027 ignore_zero_fault( true );
2028 boolean_t ints = ml_set_interrupts_enabled( false );
2029
2030 err = doControl( cscSetPowerState, &sleepInfo);
2031
2032 ml_set_interrupts_enabled( ints );
2033 ignore_zero_fault( false );
2034
2035 if( powerStateOrdinal) {
2036 powerState = powerStateOrdinal;
2037 if( kAVPowerOn == newState) {
2038 VDPageInfo pageInfo;
2039 pageInfo.csData = 0;
2040 pageInfo.csPage = 0;
2041 doControl( cscGrayPage, &pageInfo);
2042 resetCursor();
2043 } else {
2044 IOSleep( 100 );
2045 setCursorImage( 0 );
2046 }
2047
2048 agpDev = OSDynamicCast(IOAGPDevice, nub);
2049 if( !agpDev)
2050 agpDev = OSDynamicCast( IOAGPDevice, nub->getParentEntry(gIODTPlane));
2051 if( agpDev)
2052 agpDev->resetAGP();
2053 }
2054 powerState = powerStateOrdinal;
2055
2056 if( powerStateOrdinal)
2057 super::setPowerState( powerStateOrdinal, whichDevice );
2058
2059 return( IOPMAckImplied );
2060 }
2061
2062 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2063
2064 // ATI patches.
2065 // Real problem : getStartupMode doesn't.
2066
2067 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2068
2069 #undef super
2070 #define super IONDRVFramebuffer
2071
2072 OSDefineMetaClassAndStructors(IOATINDRV, IONDRVFramebuffer)
2073 OSDefineMetaClassAndStructors(IOATI128NDRV, IOATINDRV)
2074
2075 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2076
2077 IOReturn IOATINDRV::getStartupDisplayMode(
2078 IODisplayModeID * displayMode, IOIndex * depth )
2079 {
2080 UInt16 * nvram;
2081 OSData * prop;
2082
2083 prop = OSDynamicCast( OSData, nub->getProperty("Sime"));
2084 if( prop) {
2085 nvram = (UInt16 *) prop->getBytesNoCopy();
2086 *displayMode = nvram[ 0 ]; // 1 is physDisplayMode
2087 *depth = nvram[ 2 ] - kDepthMode1;
2088 return( kIOReturnSuccess);
2089 } else
2090 return(super::getStartupDisplayMode( displayMode, depth));
2091 }
2092
2093 IODeviceMemory * IOATINDRV::findVRAM( void )
2094 {
2095 OSData * prop;
2096 IOByteCount * lengths;
2097 IOIndex count;
2098 IOPhysicalAddress vramBase;
2099 IOByteCount vramLength;
2100
2101 prop = OSDynamicCast( OSData, nub->getProperty("ATY,memsize"));
2102 if( !prop)
2103 return( super::findVRAM());
2104
2105 lengths = (IOByteCount *) prop->getBytesNoCopy();
2106 count = prop->getLength() / sizeof(IOByteCount);
2107
2108 prop = OSDynamicCast( OSData, nub->getProperty("ATY,Base"));
2109
2110 if( prop && (count > 1)) {
2111 vramBase = *((IOPhysicalAddress *)prop->getBytesNoCopy());
2112 vramLength = lengths[1];
2113 vramBase &= ~(vramLength - 1);
2114 } else {
2115 vramBase = physicalFramebuffer;
2116 vramLength = lengths[0];
2117 }
2118
2119 if( !vramLength)
2120 return( super::findVRAM());
2121
2122 vramLength = (vramLength + (vramBase & 0xffff)) & 0xffff0000;
2123 vramBase &= 0xffff0000;
2124
2125 return( makeSubRange( vramBase, vramLength ));
2126 }
2127
2128 static int g128ExtraCurs = 8;
2129 static int g128DeltaCurs = 0x25c0;
2130
2131 void IOATI128NDRV::flushCursor( void )
2132 {
2133 volatile UInt32 * fb;
2134 UInt32 x;
2135 int i;
2136
2137 fb = (volatile UInt32 *) frameBuffer;
2138 for( i = 0; i < g128ExtraCurs; i++) {
2139 x += *(fb++);
2140 fb += g128DeltaCurs;
2141 }
2142 }
2143
2144
2145
2146 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 0);
2147 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 1);
2148 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 2);
2149 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 3);
2150 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 4);
2151 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 5);
2152 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 6);
2153 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 7);
2154 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 8);
2155 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 9);
2156 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 10);
2157 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 11);
2158 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 12);
2159 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 13);
2160 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 14);
2161 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 15);
2162 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 16);
2163 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 17);
2164 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 18);
2165 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 19);
2166 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 20);
2167 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 21);
2168 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 22);
2169 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 23);
2170 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 24);
2171 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 25);
2172 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 26);
2173 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 27);
2174 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 28);
2175 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 29);
2176 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 30);
2177 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 31);