]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IONDRVSupport/IONDRVFramebuffer.cpp
2fe80f342cab9ddbb32ef400dd6b8acb15667fd3
[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 IOReturn IONDRVFramebuffer::setAttributeForConnection( IOIndex connectIndex,
1510 IOSelect attribute, UInt32 info )
1511 {
1512 IOReturn err;
1513 VDSyncInfoRec theVDSyncInfoRec;
1514 VDPowerStateRec sleepInfo;
1515
1516
1517 switch( attribute ) {
1518
1519 case kConnectionSyncEnable:
1520
1521 theVDSyncInfoRec.csMode = (unsigned char)(info>>8);
1522 theVDSyncInfoRec.csFlags = (unsigned char)(info & 0xFF);
1523 doControl( cscSetSync, &theVDSyncInfoRec);
1524
1525 sleepInfo.powerState = ((info>>8) & 0xff) ? kAVPowerSuspend : kAVPowerOn;
1526 sleepInfo.powerFlags = 0;
1527 sleepInfo.powerReserved1 = 0;
1528 sleepInfo.powerReserved2 = 0;
1529 doControl( cscSetPowerState, &sleepInfo);
1530
1531 err = kIOReturnSuccess;
1532 break;
1533
1534 default:
1535 err = super::setAttributeForConnection( connectIndex,
1536 attribute, info );
1537 break;
1538 }
1539 return( err );
1540 }
1541
1542
1543 IOReturn IONDRVFramebuffer::getAttributeForConnection( IOIndex connectIndex,
1544 IOSelect attribute, UInt32 * value )
1545 {
1546 IOReturn ret;
1547 VDSyncInfoRec theVDSyncInfoRec;
1548
1549 switch( attribute ) {
1550
1551 case kConnectionSyncFlags:
1552 // find out current state of sync lines
1553 theVDSyncInfoRec.csMode = 0x00;
1554 doStatus(cscGetSync,&theVDSyncInfoRec);
1555 * value = theVDSyncInfoRec.csMode;
1556 ret = kIOReturnSuccess;
1557 break;
1558 case kConnectionSyncEnable:
1559 // what are the sync-controlling capabilities of the ndrv?
1560 theVDSyncInfoRec.csMode = 0xFF;
1561 doStatus(cscGetSync,&theVDSyncInfoRec);
1562 * value = (UInt32)theVDSyncInfoRec.csMode;
1563 ret = kIOReturnSuccess;
1564 break;
1565 case kConnectionSupportsHLDDCSense:
1566 case kConnectionSupportsAppleSense:
1567 ret = kIOReturnSuccess;
1568 break;
1569 default:
1570 ret = super::getAttributeForConnection( connectIndex,
1571 attribute, value );
1572 break;
1573 }
1574
1575 return( ret );
1576 }
1577
1578 IOReturn IONDRVFramebuffer::getAppleSense( IOIndex connectIndex,
1579 UInt32 * senseType,
1580 UInt32 * primary,
1581 UInt32 * extended,
1582 UInt32 * displayType )
1583 {
1584 OSStatus err;
1585 VDMultiConnectInfoRec multiConnect;
1586 UInt32 sense, extSense;
1587
1588 if( connectIndex == 0 )
1589 err = doStatus( cscGetConnection, &multiConnect.csConnectInfo);
1590
1591 else {
1592 multiConnect.csDisplayCountOrNumber = connectIndex;
1593 err = doControl( cscSetMultiConnect, &multiConnect);
1594 }
1595 if( err)
1596 return( err);
1597
1598 if( multiConnect.csConnectInfo.csConnectFlags
1599 & ((1<<kReportsTagging) | (1<<kTaggingInfoNonStandard))
1600 != ((1<<kReportsTagging)) )
1601
1602 err = kIOReturnUnsupported;
1603
1604 else {
1605
1606 sense = multiConnect.csConnectInfo.csConnectTaggedType;
1607 extSense = multiConnect.csConnectInfo.csConnectTaggedData;
1608 // bug fixes for really old ATI driver
1609 if( sense == 0) {
1610 if( extSense == 6) {
1611 sense = kRSCSix;
1612 extSense = kESCSixStandard;
1613 }
1614 else
1615 if( extSense == 4) {
1616 sense = kRSCFour;
1617 extSense = kESCFourNTSC;
1618 }
1619 }
1620 if( primary)
1621 *primary = sense;
1622 if( extended)
1623 *extended = extSense;
1624 if( displayType)
1625 *displayType = multiConnect.csConnectInfo.csDisplayType;
1626 if( senseType)
1627 *senseType = 0;
1628 }
1629 return( err);
1630 }
1631
1632 IOReturn IONDRVFramebuffer::connectFlags( IOIndex /* connectIndex */,
1633 IODisplayModeID displayMode, IOOptionBits * flags )
1634 {
1635 VDTimingInfoRec timingInfo;
1636 OSStatus err;
1637
1638 timingInfo.csTimingMode = displayMode;
1639 // in case the driver doesn't do it:
1640 timingInfo.csTimingFormat = kDeclROMtables;
1641 err = doStatus( cscGetModeTiming, &timingInfo);
1642
1643 if( kDetailedTimingFormat == timingInfo.csTimingFormat)
1644 *flags = kDisplayModeValidFlag | kDisplayModeSafeFlag;
1645 else
1646 *flags = timingInfo.csTimingFlags;
1647
1648 return( err );
1649 }
1650
1651
1652 bool IONDRVFramebuffer::hasDDCConnect( IOIndex connectIndex )
1653 {
1654 OSStatus err;
1655 VDMultiConnectInfoRec multiConnect;
1656 enum { kNeedFlags = (1<<kReportsDDCConnection)
1657 | (1<<kHasDDCConnection) };
1658 if( connectIndex == 0 )
1659 err = doStatus( cscGetConnection, &multiConnect.csConnectInfo);
1660 else {
1661 multiConnect.csDisplayCountOrNumber = connectIndex;
1662 err = doControl( cscSetMultiConnect, &multiConnect);
1663 }
1664 if( err)
1665 return( err);
1666
1667 return( (multiConnect.csConnectInfo.csConnectFlags & kNeedFlags)
1668 == kNeedFlags );
1669 }
1670
1671 IOReturn IONDRVFramebuffer::getDDCBlock( IOIndex /* connectIndex */,
1672 UInt32 blockNumber,
1673 IOSelect blockType,
1674 IOOptionBits options,
1675 UInt8 * data, IOByteCount * length )
1676
1677 {
1678 OSStatus err = 0;
1679 VDDDCBlockRec ddcRec;
1680 ByteCount actualLength = *length;
1681
1682 ddcRec.ddcBlockNumber = blockNumber;
1683 ddcRec.ddcBlockType = blockType;
1684 ddcRec.ddcFlags = options;
1685
1686 err = doStatus( cscGetDDCBlock, &ddcRec);
1687
1688 if( err == noErr) {
1689
1690 if( actualLength < kDDCBlockSize)
1691 actualLength = actualLength;
1692 else
1693 actualLength = kDDCBlockSize;
1694 bcopy( ddcRec.ddcBlockData, data, actualLength);
1695 *length = actualLength;
1696 }
1697 return( err);
1698 }
1699
1700 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1701 // initForPM
1702 //
1703 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1704
1705 void IONDRVFramebuffer::initForPM( void )
1706 {
1707 static const IOPMPowerState powerStates[ kIONDRVFramebufferPowerStateCount ] = {
1708 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1709 { 1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 }
1710 };
1711 // register ourselves with superclass policy-maker
1712 registerPowerDriver( this, (IOPMPowerState *) powerStates,
1713 kIONDRVFramebufferPowerStateCount );
1714 }
1715
1716
1717 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1718 // maxCapabilityForDomainState
1719 //
1720 // This simple device needs only power. If the power domain is supplying
1721 // power, the frame buffer can be on. If there is no power it can only be off.
1722 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1723
1724 unsigned long IONDRVFramebuffer::maxCapabilityForDomainState(
1725 IOPMPowerFlags domainState )
1726 {
1727 if( domainState & IOPMPowerOn)
1728 return( kIONDRVFramebufferPowerStateCount - 1);
1729 else
1730 return( 0);
1731 }
1732
1733 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1734 // initialPowerStateForDomainState
1735 //
1736 // The power domain may be changing state. If power is on in the new
1737 // state, that will not affect our state at all. If domain power is off,
1738 // we can attain only our lowest state, which is off.
1739 //
1740 // This implementation is incomplete. It only works in a system where
1741 // the frame buffer is never turned off. When we cross that bridge,
1742 // instead of returning 1, it should return 1 if the frame buffer
1743 // is on, or 0 if it is off.
1744 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1745
1746 unsigned long IONDRVFramebuffer::initialPowerStateForDomainState(
1747 IOPMPowerFlags domainState )
1748 {
1749 if( domainState & IOPMPowerOn)
1750 return( kIONDRVFramebufferPowerStateCount - 1);
1751 else
1752 return( 0);
1753 }
1754
1755
1756 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1757 // powerStateForDomainState
1758 //
1759 // The power domain may be changing state. If power is on in the new
1760 // state, that will not affect our state at all. If domain power is off,
1761 // we can attain only our lowest state, which is off.
1762 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1763
1764 unsigned long IONDRVFramebuffer::powerStateForDomainState(
1765 IOPMPowerFlags domainState )
1766 {
1767 if( domainState & IOPMPowerOn)
1768 return( pm_vars->myCurrentState);
1769 else
1770 return( 0);
1771 }
1772
1773
1774 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1775 // setPowerState
1776 //
1777 // Called by the superclass to turn the frame buffer on and off.
1778 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1779
1780 IOReturn IONDRVFramebuffer::setPowerState( unsigned long powerStateOrdinal,
1781 IOService * whichDevice )
1782 {
1783 static const unsigned long states[2][2] =
1784 { { kAVPowerOff, kAVPowerOn },
1785 { kHardwareSleep, kHardwareWake } };
1786
1787 VDPowerStateRec sleepInfo;
1788 IOReturn err;
1789 int deepSleep = 0;
1790 UInt32 newState;
1791 IOAGPDevice * agpDev;
1792
1793 if( powerStateOrdinal == powerState)
1794 return( IOPMAckImplied );
1795
1796 if( 0 == powerStateOrdinal)
1797 super::setPowerState( powerStateOrdinal, whichDevice );
1798
1799 sleepInfo.powerState = 0;
1800 sleepInfo.powerFlags = 0;
1801 sleepInfo.powerReserved1 = 0;
1802 sleepInfo.powerReserved2 = 0;
1803
1804 err = doStatus( cscGetPowerState, &sleepInfo);
1805 if( (kIOReturnSuccess == err)
1806 && (kPowerStateSleepCanPowerOffMask & sleepInfo.powerFlags))
1807 deepSleep = platformDeepSleep;
1808
1809 newState = states[deepSleep & 1][powerStateOrdinal & 1];
1810 sleepInfo.powerState = newState;
1811 sleepInfo.powerFlags = 0;
1812 sleepInfo.powerReserved1 = 0;
1813 sleepInfo.powerReserved2 = 0;
1814
1815 ignore_zero_fault( true );
1816 boolean_t ints = ml_set_interrupts_enabled( false );
1817
1818 err = doControl( cscSetPowerState, &sleepInfo);
1819
1820 ml_set_interrupts_enabled( ints );
1821 ignore_zero_fault( false );
1822
1823 if( powerStateOrdinal) {
1824 powerState = powerStateOrdinal;
1825 if( kAVPowerOn == newState) {
1826 VDPageInfo pageInfo;
1827 pageInfo.csData = 0;
1828 pageInfo.csPage = 0;
1829 doControl( cscGrayPage, &pageInfo);
1830 resetCursor();
1831 } else {
1832 IOSleep( 100 );
1833 setCursorImage( 0 );
1834 }
1835
1836 agpDev = OSDynamicCast(IOAGPDevice, nub);
1837 if( !agpDev)
1838 agpDev = OSDynamicCast( IOAGPDevice, nub->getParentEntry(gIODTPlane));
1839 if( agpDev)
1840 agpDev->resetAGP();
1841 }
1842 powerState = powerStateOrdinal;
1843
1844 if( powerStateOrdinal)
1845 super::setPowerState( powerStateOrdinal, whichDevice );
1846
1847 return( IOPMAckImplied );
1848 }
1849
1850 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1851
1852 // ATI patches.
1853 // Real problem : getStartupMode doesn't.
1854
1855 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1856
1857 #undef super
1858 #define super IONDRVFramebuffer
1859
1860 OSDefineMetaClassAndStructors(IOATINDRV, IONDRVFramebuffer)
1861 OSDefineMetaClassAndStructors(IOATI128NDRV, IOATINDRV)
1862
1863 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1864
1865 IOReturn IOATINDRV::getStartupDisplayMode(
1866 IODisplayModeID * displayMode, IOIndex * depth )
1867 {
1868 UInt16 * nvram;
1869 OSData * prop;
1870
1871 prop = OSDynamicCast( OSData, nub->getProperty("Sime"));
1872 if( prop) {
1873 nvram = (UInt16 *) prop->getBytesNoCopy();
1874 *displayMode = nvram[ 0 ]; // 1 is physDisplayMode
1875 *depth = nvram[ 2 ] - kDepthMode1;
1876 return( kIOReturnSuccess);
1877 } else
1878 return(super::getStartupDisplayMode( displayMode, depth));
1879 }
1880
1881 IODeviceMemory * IOATINDRV::findVRAM( void )
1882 {
1883 OSData * prop;
1884 IOByteCount * lengths;
1885 IOIndex count;
1886 IOPhysicalAddress vramBase;
1887 IOByteCount vramLength;
1888
1889 prop = OSDynamicCast( OSData, nub->getProperty("ATY,memsize"));
1890 if( !prop)
1891 return( super::findVRAM());
1892
1893 lengths = (IOByteCount *) prop->getBytesNoCopy();
1894 count = prop->getLength() / sizeof(IOByteCount);
1895
1896 prop = OSDynamicCast( OSData, nub->getProperty("ATY,Base"));
1897
1898 if( prop && (count > 1)) {
1899 vramBase = *((IOPhysicalAddress *)prop->getBytesNoCopy());
1900 vramLength = lengths[1];
1901 vramBase &= ~(vramLength - 1);
1902 } else {
1903 vramBase = physicalFramebuffer;
1904 vramLength = lengths[0];
1905 }
1906
1907 if( !vramLength)
1908 return( super::findVRAM());
1909
1910 vramLength = (vramLength + (vramBase & 0xffff)) & 0xffff0000;
1911 vramBase &= 0xffff0000;
1912
1913 return( makeSubRange( vramBase, vramLength ));
1914 }
1915
1916 static int g128ExtraCurs = 8;
1917 static int g128DeltaCurs = 0x25c0;
1918
1919 void IOATI128NDRV::flushCursor( void )
1920 {
1921 volatile UInt32 * fb;
1922 UInt32 x;
1923 int i;
1924
1925 fb = (volatile UInt32 *) frameBuffer;
1926 for( i = 0; i < g128ExtraCurs; i++) {
1927 x += *(fb++);
1928 fb += g128DeltaCurs;
1929 }
1930 }
1931
1932
1933
1934 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 0);
1935 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 1);
1936 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 2);
1937 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 3);
1938 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 4);
1939 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 5);
1940 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 6);
1941 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 7);
1942 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 8);
1943 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 9);
1944 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 10);
1945 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 11);
1946 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 12);
1947 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 13);
1948 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 14);
1949 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 15);
1950 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 16);
1951 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 17);
1952 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 18);
1953 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 19);
1954 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 20);
1955 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 21);
1956 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 22);
1957 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 23);
1958 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 24);
1959 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 25);
1960 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 26);
1961 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 27);
1962 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 28);
1963 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 29);
1964 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 30);
1965 OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 31);