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