|
|
1.1 root 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/ndrvsupport/IONDRVFramebuffer.h>
39: #include <IOKit/assert.h>
40:
41: #include <libkern/c++/OSContainers.h>
42:
43: #include "IONDRV.h"
44:
45: #include <string.h>
46:
47: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
48:
49: class IOATINDRV : public IONDRVFramebuffer
50: {
51: OSDeclareDefaultStructors(IOATINDRV)
52:
53: public:
54: virtual IOReturn getStartupDisplayMode( IODisplayModeID * displayMode,
55: IOIndex * depth );
56: virtual IODeviceMemory * findVRAM( void );
57:
58: };
59:
60: class IOATI128NDRV : public IOATINDRV
61: {
62: OSDeclareDefaultStructors(IOATI128NDRV)
63:
64: public:
65: virtual void flushCursor( void );
66: };
67:
68: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
69:
70: struct _VSLService {
71: class IONDRVFramebuffer * framebuffer;
72: IOSelect type;
73: IOFBInterruptProc handler;
74: OSObject * target;
75: void * ref;
76: _VSLService * next;
77: };
78:
79: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
80:
81: // frame buffer has two power states, off and on
82: #define number_of_power_states 2
83:
84: static IOPMPowerState ourPowerStates[number_of_power_states] = {
85: {1,0,0,0,0,0,0,0,0,0,0,0},
86: {1,IOPMDeviceUsable,IOPMPowerOn,IOPMPowerOn,0,0,0,0,0,0,0,0}
87: };
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( IONDRV::fromRegistryEntry( provider )) {
112:
113: // temporary for in-kernel acceleration
114: name = provider->getName();
115: if( 0 == strncmp("ATY,Rage128", name, strlen("ATY,Rage128")))
116: newInst = new IOATI128NDRV;
117: else if( 0 == strncmp("ATY,", name, strlen("ATY,")))
118: newInst = new IOATINDRV;
119:
120: if( newInst) {
121: if( ! newInst->init( inst->getPropertyTable())) {
122: newInst->release();
123: newInst = 0;
124: }
125: inst = newInst;
126: }
127: } else
128: inst = 0;
129:
130: return( inst );
131: }
132:
133: bool IONDRVFramebuffer::start( IOService * provider )
134: {
135: bool ok = false;
136: IOService * parent;
137:
138: do {
139: nub = provider;
140: ndrv = IONDRV::fromRegistryEntry( provider );
141: if( 0 == ndrv)
142: continue;
143:
144: setName( ndrv->driverName());
145: startAt8 = 3;
146: consoleDevice = (0 != provider->getProperty("AAPL,boot-display"));
147:
148: if( 0 == nub->getDeviceMemoryCount()) {
149: parent = OSDynamicCast( IOService, nub->getParentEntry(gIODTPlane));
150: if( parent) {
151: parent->getResources();
152: OSArray * array = parent->getDeviceMemory();
153: array->retain();
154: nub->setDeviceMemory( array);
155: array->release();
156: }
157: }
158:
159: if( false == super::start( nub ))
160: continue;
161:
162: ok = true; // Success
163:
164: } while( false);
165:
166: return( ok);
167: }
168:
169: bool IONDRVFramebuffer::isConsoleDevice( void )
170: {
171: return( consoleDevice );
172: }
173:
174: // osfmk/ppc/mappings.h
175: extern "C" { extern void ignore_zero_fault(boolean_t); }
176:
177: IOReturn IONDRVFramebuffer::enableController( void )
178: {
179: IOReturn err;
180: const char * logname;
181:
182: logname = getProvider()->getName();
183:
184: if( 0 == strcmp( "control", logname))
185: waitForService( resourceMatching( "IOiic0" ));
186:
187: err = IONDRVLibrariesInitialize( getProvider() );
188:
189: if( kIOReturnSuccess == err) do {
190:
191: ignore_zero_fault( true );
192: err = checkDriver();
193: ignore_zero_fault( false );
194:
195: if( err) {
196: IOLog("%s: Not usable\n", logname );
197: if( err == -999)
198: IOLog("%s: driver incompatible.\n", logname );
199: continue;
200: }
201: getCurrentConfiguration();
202: vramMemory = findVRAM();
203:
204: } while( false);
205:
206: // initialize power management of the device
207: initForPM();
208:
209: return( err);
210: }
211:
212: IODeviceMemory * IONDRVFramebuffer::getVRAMRange( void )
213: {
214: if( vramMemory)
215: vramMemory->retain();
216:
217: return( vramMemory );
218: }
219:
220: void IONDRVFramebuffer::free( void )
221: {
222: super::free();
223: }
224:
225: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
226:
227: IOReturn IONDRVFramebuffer::registerForInterruptType( IOSelect interruptType,
228: IOFBInterruptProc proc, OSObject * target, void * ref,
229: void ** interruptRef )
230:
231: {
232: _VSLService * service;
233: IOReturn err;
234:
235: if( (interruptType == kIOFBVBLInterruptType)
236: && (getProvider()->getProperty("Ignore VBL")))
237: return( kIOReturnUnsupported );
238:
239: for( service = vslServices;
240: service && (service->type != interruptType);
241: service = service->next ) {}
242:
243: if( service) {
244:
245: if( service->handler)
246: err = kIOReturnBusy;
247:
248: else {
249: service->target = target;
250: service->ref = ref;
251: service->handler = proc;
252: *interruptRef = service;
253: err = kIOReturnSuccess;
254: }
255:
256: } else
257: err = kIOReturnNoResources;
258:
259: return( err );
260: }
261:
262: IOReturn IONDRVFramebuffer::unregisterInterrupt( void * interruptRef )
263: {
264: _VSLService * service = (_VSLService *) interruptRef;
265:
266: service->handler = 0;
267:
268: return( kIOReturnSuccess );
269: }
270:
271: IOReturn IONDRVFramebuffer::setInterruptState( void * interruptRef,
272: UInt32 state )
273: {
274: return( kIOReturnUnsupported );
275: }
276:
277: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
278:
279: //// VSL calls
280:
281: OSStatus IONDRVFramebuffer::VSLNewInterruptService(
282: void * entryID,
283: IOSelect serviceType,
284: _VSLService ** vslService )
285: {
286: IORegistryEntry * regEntry;
287: IONDRVFramebuffer * fb;
288: _VSLService * service;
289: IOReturn err = kIOReturnSuccess;
290:
291: REG_ENTRY_TO_OBJ( (const RegEntryID *) entryID, regEntry)
292:
293: fb = OSDynamicCast( IONDRVFramebuffer,
294: regEntry->getChildEntry( gIOServicePlane ));
295: assert( fb );
296:
297: if( fb) {
298: service = IONew( _VSLService, 1 );
299:
300: if( service) {
301: service->framebuffer = fb;
302: service->type = serviceType;
303: service->handler = 0;
304: service->next = fb->vslServices;
305: fb->vslServices = service;
306:
307: *vslService = service;
308:
309: } else
310: err = kIOReturnNoMemory;
311:
312: } else
313: err = kIOReturnBadArgument;
314:
315: return( err );
316: }
317:
318: OSStatus IONDRVFramebuffer::VSLDisposeInterruptService(_VSLService * vslService)
319: {
320: IONDRVFramebuffer * fb;
321: _VSLService * next;
322: _VSLService * prev;
323:
324: if( vslService) {
325:
326: fb = vslService->framebuffer;
327:
328: prev = fb->vslServices;
329: if( prev == vslService)
330: fb->vslServices = vslService->next;
331: else {
332: while( ((next = prev->next) != vslService) && next)
333: prev = next;
334: if( next)
335: prev->next = vslService->next;
336: }
337:
338: IODelete( vslService, _VSLService, 1 );
339: }
340:
341: return( kIOReturnSuccess );
342: }
343:
344: OSStatus IONDRVFramebuffer::VSLDoInterruptService( _VSLService * vslService )
345: {
346: IOFBInterruptProc proc;
347:
348: if( vslService) {
349: if( (proc = vslService->handler))
350: (*proc) (vslService->target, vslService->ref);
351: }
352:
353: return( kIOReturnSuccess );
354: }
355:
356: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
357:
358: struct _VSLCursorRef {
359: IOFramebuffer * framebuffer;
360: void * cursorImage;
361: };
362:
363: Boolean IONDRVFramebuffer::VSLPrepareCursorForHardwareCursor(
364: void * cursorRef,
365: IOHardwareCursorDescriptor * hwDesc,
366: IOHardwareCursorInfo * hwCursorInfo )
367: {
368: _VSLCursorRef * cursor = (_VSLCursorRef *) cursorRef;
369: bool ok;
370:
371: if( hwCursorInfo->colorMap)
372: hwCursorInfo->colorMap += 1;
373: ok = cursor->framebuffer->convertCursorImage(
374: cursor->cursorImage, hwDesc, hwCursorInfo );
375: if( hwCursorInfo->colorMap)
376: hwCursorInfo->colorMap -= 1;
377:
378: return( ok );
379: }
380:
381: IOReturn IONDRVFramebuffer::setCursorImage( void * cursorImage )
382: {
383: _VSLCursorRef cursorRef;
384: VDSetHardwareCursorRec setCursor;
385: IOReturn err;
386:
387: cursorRef.framebuffer = this;
388: cursorRef.cursorImage = cursorImage;
389:
390: setCursor.csCursorRef = (void *) &cursorRef;
391: setCursor.csReserved1 = 0;
392: setCursor.csReserved2 = 0;
393:
394: err = doControl( cscSetHardwareCursor, &setCursor );
395:
396: return( err );
397: }
398:
399: IOReturn IONDRVFramebuffer::setCursorState( SInt32 x, SInt32 y, bool visible )
400: {
401: VDDrawHardwareCursorRec drawCursor;
402: IOReturn err;
403:
404: if( 0 == OSIncrementAtomic( &ndrvEnter))
405: {
406:
407: drawCursor.csCursorX = x;
408: drawCursor.csCursorY = y;
409: drawCursor.csCursorVisible = visible;
410: drawCursor.csReserved1 = 0;
411: drawCursor.csReserved2 = 0;
412:
413: err = doControl( cscDrawHardwareCursor, &drawCursor );
414:
415: } else
416: err = kIOReturnBusy;
417:
418: OSDecrementAtomic( &ndrvEnter );
419:
420: return( err );
421: }
422:
423: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
424:
425: //============
426: //= Internal =
427: //============
428:
429: IOReturn IONDRVFramebuffer::doControl( UInt32 code, void * params )
430: {
431: IOReturn err;
432: CntrlParam pb;
433:
434: if( ndrvState == 0)
435: return( kIOReturnNotOpen);
436:
437: pb.qLink = 0;
438: pb.csCode = code;
439: pb.csParams = params;
440:
441: OSIncrementAtomic( &ndrvEnter );
442: err = ndrv->doDriverIO( /*ID*/ (UInt32) &pb, &pb,
443: kControlCommand, kImmediateIOCommandKind );
444: OSDecrementAtomic( &ndrvEnter );
445:
446: return( err);
447: }
448:
449: IOReturn IONDRVFramebuffer::doStatus( UInt32 code, void * params )
450: {
451: IOReturn err;
452: CntrlParam pb;
453:
454: if( ndrvState == 0)
455: return( kIOReturnNotOpen);
456:
457: pb.qLink = 0;
458: pb.csCode = code;
459: pb.csParams = params;
460:
461: OSIncrementAtomic( &ndrvEnter );
462: err = ndrv->doDriverIO( /*ID*/ (UInt32) &pb, &pb,
463: kStatusCommand, kImmediateIOCommandKind );
464: OSDecrementAtomic( &ndrvEnter );
465:
466: return( err);
467: }
468:
469:
470: IOReturn IONDRVFramebuffer::checkDriver( void )
471: {
472: OSStatus err = noErr;
473: struct DriverInitInfo initInfo;
474: CntrlParam pb;
475: VDClutBehavior clutSetting;
476: VDGammaRecord gammaRec;
477: VDSwitchInfoRec switchInfo;
478: IOTimingInformation info;
479: VDPageInfo pageInfo;
480:
481: if( ndrvState == 0) {
482: do {
483: initInfo.refNum = 0xffcd; // ...sure.
484: MAKE_REG_ENTRY(initInfo.deviceEntry, nub )
485:
486: err = ndrv->doDriverIO( 0, &initInfo,
487: kInitializeCommand, kImmediateIOCommandKind );
488: if( err) continue;
489:
490: err = ndrv->doDriverIO( 0, &pb,
491: kOpenCommand, kImmediateIOCommandKind );
492:
493: } while( false);
494:
495: if( err)
496: return( err);
497:
498: // allow calls to ndrv
499: ndrvState = 1;
500:
501: if( (noErr == doStatus( cscGetCurMode, &switchInfo ))
502: && (noErr == getTimingInfoForDisplayMode( switchInfo.csData, &info))
503: && (timingApple_0x0_0hz_Offline == info.appleTimingID)) {
504:
505: IOLog("%s: display offline\n", getName());
506: err = kIOReturnOffline;
507: return( err);
508: } else
509: ndrvState = 2;
510:
511: // duplicate QD InitGDevice
512: pageInfo.csMode = switchInfo.csMode;
513: pageInfo.csData = 0;
514: pageInfo.csPage = 0;
515: doControl( cscGrayPage, &pageInfo);
516:
517: clutSetting = kSetClutAtSetEntries;
518: lastClutSetting = clutSetting;
519: doControl( cscSetClutBehavior, &clutSetting);
520:
521: #if 1
522: // bogus for ROM control
523: do {
524:
525: VDGetGammaListRec scan;
526: VDRetrieveGammaRec get;
527: GammaTbl * table;
528: char name[ 64 ];
529:
530: scan.csPreviousGammaTableID = kGammaTableIDFindFirst;
531: scan.csGammaTableName = name;
532: err = doStatus( cscGetGammaInfoList, &scan);
533: if( err || (scan.csGammaTableID == kGammaTableIDNoMoreTables))
534: continue;
535:
536: table = (GammaTbl *)IOMalloc( scan.csGammaTableSize);
537: if( 0 == table)
538: continue;
539: get.csGammaTableID = scan.csGammaTableID;
540: get.csGammaTablePtr = table;
541:
542: err = doStatus( cscRetrieveGammaTable, &get );
543: if( noErr == err) {
544: kprintf("Setting gamma %s\n", scan.csGammaTableName);
545: gammaRec.csGTable = (Ptr) table;
546: doControl( cscSetGamma, &gammaRec );
547: }
548:
549: IOFree( table, scan.csGammaTableSize);
550:
551: } while( false);
552: #endif
553: }
554: return( noErr);
555: }
556:
557:
558: UInt32 IONDRVFramebuffer::iterateAllModes( IODisplayModeID * displayModeIDs )
559: {
560: VDResolutionInfoRec info;
561: UInt32 num = 0;
562:
563: info.csPreviousDisplayModeID = kDisplayModeIDFindFirstResolution;
564:
565: while(
566: (noErr == doStatus( cscGetNextResolution, &info))
567: && ((SInt32) info.csDisplayModeID > 0) ) {
568:
569: if( displayModeIDs)
570: displayModeIDs[ num ] = info.csDisplayModeID;
571:
572: info.csPreviousDisplayModeID = info.csDisplayModeID;
573: num++;
574: }
575: return( num);
576: }
577:
578:
579: IOReturn IONDRVFramebuffer::getResInfoForMode( IODisplayModeID modeID,
580: VDResolutionInfoRec ** theInfo )
581: {
582: // unfortunately, there is no "kDisplayModeIDFindSpecific"
583:
584: if( (SInt32) modeID <= 0)
585: return( kIOReturnUnsupportedMode);
586:
587: *theInfo = &cachedVDResolution;
588:
589: if( cachedVDResolution.csDisplayModeID == (UInt32) modeID)
590: return( noErr);
591:
592: // try the next after cached mode
593: cachedVDResolution.csPreviousDisplayModeID = cachedVDResolution.csDisplayModeID;
594:
595: if( (noErr == doStatus( cscGetNextResolution, &cachedVDResolution))
596: && (cachedVDResolution.csDisplayModeID == (UInt32) modeID) )
597: return( noErr);
598:
599: // full blown iterate
600: cachedVDResolution.csPreviousDisplayModeID = kDisplayModeIDFindFirstResolution;
601:
602: while(
603: (noErr == doStatus( cscGetNextResolution, &cachedVDResolution))
604: && (cachedVDResolution.csDisplayModeID != (UInt32) modeID)
605: && ((SInt32) cachedVDResolution.csDisplayModeID > 0)) {
606:
607: cachedVDResolution.csPreviousDisplayModeID = cachedVDResolution.csDisplayModeID;
608: }
609:
610: if( cachedVDResolution.csDisplayModeID == (UInt32) modeID)
611: return( noErr);
612:
613: cachedVDResolution.csDisplayModeID = 0xffffffff;
614: return( kIOReturnUnsupportedMode);
615: }
616:
617: void IONDRVFramebuffer::getCurrentConfiguration( void )
618: {
619: IOReturn err;
620: VDSwitchInfoRec switchInfo;
621: VDGrayRecord grayRec;
622:
623: grayRec.csMode = 0; // turn off luminance map
624: err = doControl( cscSetGray, &grayRec );
625: // driver refused => mono display
626: grayMode = ((noErr == err) && (0 != grayRec.csMode));
627:
628: err = doStatus( cscGetCurMode, &switchInfo );
629: if( err == noErr) {
630: currentDisplayMode = switchInfo.csData;
631: currentDepth = switchInfo.csMode - kDepthMode1;
632: currentPage = switchInfo.csPage;
633: if( 0 == (physicalFramebuffer = pmap_extract( kernel_pmap,
634: ((vm_address_t) switchInfo.csBaseAddr) )))
635: physicalFramebuffer = (UInt32) switchInfo.csBaseAddr;
636: } else
637: IOLog("%s: cscGetCurMode failed\n", nub->getName());
638: }
639:
640: IODeviceMemory * IONDRVFramebuffer::makeSubRange(
641: IOPhysicalAddress start,
642: IOPhysicalLength length )
643: {
644: IODeviceMemory * mem = 0;
645: UInt32 numMaps, i;
646: IOService * device;
647:
648: device = nub;
649: numMaps = device->getDeviceMemoryCount();
650:
651: for( i = 0; (!mem) && (i < numMaps); i++) {
652: mem = device->getDeviceMemoryWithIndex(i);
653: if( !mem)
654: continue;
655: mem = IODeviceMemory::withSubRange( mem,
656: start - mem->getPhysicalAddress(), length );
657: }
658: if( !mem)
659: mem = IODeviceMemory::withRange( start, length );
660:
661: return( mem );
662: }
663:
664: IODeviceMemory * IONDRVFramebuffer::getApertureRange( IOPixelAperture aper )
665: {
666: IOReturn err;
667: IOPixelInformation info;
668: IOByteCount bytes;
669:
670: err = getPixelInformation( currentDisplayMode, currentDepth, aper,
671: &info );
672: if( err)
673: return( 0 );
674:
675: bytes = (info.bytesPerRow * info.activeHeight) + 128;
676:
677: return( makeSubRange( physicalFramebuffer, bytes ));
678: }
679:
680: IODeviceMemory * IONDRVFramebuffer::findVRAM( void )
681: {
682: VDVideoParametersInfoRec pixelParams;
683: VPBlock pixelInfo;
684: VDResolutionInfoRec vdRes;
685: UInt32 size;
686: IOPhysicalAddress vramBase;
687: IOByteCount vramLength;
688: IOReturn err;
689:
690: vramLength = 0;
691: vdRes.csPreviousDisplayModeID = kDisplayModeIDFindFirstResolution;
692: while(
693: (noErr == doStatus( cscGetNextResolution, &vdRes))
694: && ((SInt32) vdRes.csDisplayModeID > 0) )
695: {
696: pixelParams.csDisplayModeID = vdRes.csDisplayModeID;
697: pixelParams.csDepthMode = vdRes.csMaxDepthMode;
698: pixelParams.csVPBlockPtr = &pixelInfo;
699: err = doStatus( cscGetVideoParameters, &pixelParams);
700: if( err)
701: continue;
702:
703: // Control hangs its framebuffer off the end of the aperture to support
704: // 832 x 624 @ 32bpp. The commented out version will correctly calculate
705: // the vram length, but DPS needs the full extent to be mapped, so we'll
706: // end up mapping an extra page that will address vram through the
707: // little endian aperture. No other drivers like this known.
708: #if 1
709: size = 0x40 + pixelInfo.vpBounds.bottom *
710: (pixelInfo.vpRowBytes & 0x7fff);
711: #else
712: size = ( (pixelInfo.vpBounds.right * pixelInfo.vpPixelSize) / 8) // last line
713: + (pixelInfo.vpBounds.bottom - 1) *
714: (pixelInfo.vpRowBytes & 0x7fff);
715: #endif
716: if( size > vramLength)
717: vramLength = size;
718:
719: vdRes.csPreviousDisplayModeID = vdRes.csDisplayModeID;
720: }
721:
722: vramBase = physicalFramebuffer;
723: vramLength = (vramLength + (vramBase & 0xffff) + 0xffff) & 0xffff0000;
724: vramBase &= 0xffff0000;
725:
726: return( makeSubRange( vramBase, vramLength ));
727: }
728:
729: //============
730: //= External =
731: //============
732:
733: const char * IONDRVFramebuffer::getPixelFormats( void )
734: {
735: static const char * ndrvPixelFormats =
736: IO1BitIndexedPixels "\0"
737: IO2BitIndexedPixels "\0"
738: IO4BitIndexedPixels "\0"
739: IO8BitIndexedPixels "\0"
740: IO16BitDirectPixels "\0"
741: IO32BitDirectPixels "\0"
742: "\0";
743:
744: return( ndrvPixelFormats);
745: }
746:
747: IOItemCount IONDRVFramebuffer::getDisplayModeCount( void )
748: {
749: return( iterateAllModes( 0 ));
750: }
751:
752: IOReturn IONDRVFramebuffer::getDisplayModes( IODisplayModeID * allDisplayModes )
753: {
754: iterateAllModes( allDisplayModes );
755: return( kIOReturnSuccess );
756: }
757:
758: IOReturn IONDRVFramebuffer::getInformationForDisplayMode(
759: IODisplayModeID displayMode, IODisplayModeInformation * info )
760: {
761: IOReturn err;
762: VDResolutionInfoRec * resInfo;
763:
764: bzero( info, sizeof( *info));
765: do {
766: err = getResInfoForMode( displayMode, &resInfo );
767: if( err)
768: continue;
769: info->maxDepthIndex = resInfo->csMaxDepthMode - kDepthMode1;
770: info->nominalWidth = resInfo->csHorizontalPixels;
771: info->nominalHeight = resInfo->csVerticalLines;
772: info->refreshRate = resInfo->csRefreshRate;
773: return( noErr);
774: } while( false);
775:
776: return( kIOReturnUnsupportedMode);
777: }
778:
779:
780: UInt64 IONDRVFramebuffer::getPixelFormatsForDisplayMode(
781: IODisplayModeID /* displayMode */, IOIndex depthIndex )
782: {
783: return( 1 << (depthIndex + startAt8));
784: }
785:
786: IOReturn IONDRVFramebuffer::getPixelInformation(
787: IODisplayModeID displayMode, IOIndex depth,
788: IOPixelAperture aperture, IOPixelInformation * info )
789: {
790: SInt32 err;
791: VDVideoParametersInfoRec pixelParams;
792: VPBlock pixelInfo;
793: const char * formats;
794: UInt32 mask;
795: int index;
796:
797: bzero( info, sizeof( *info));
798:
799: if( aperture)
800: return( kIOReturnUnsupportedMode);
801:
802: do {
803: pixelParams.csDisplayModeID = displayMode;
804: pixelParams.csDepthMode = depth + kDepthMode1;
805: pixelParams.csVPBlockPtr = &pixelInfo;
806: err = doStatus( cscGetVideoParameters, &pixelParams );
807: if( err)
808: continue;
809:
810: //info->flags = kFramebufferSupportsCopybackCache;
811:
812: info->activeWidth = pixelInfo.vpBounds.right;
813: info->activeHeight = pixelInfo.vpBounds.bottom;
814: info->bytesPerRow = pixelInfo.vpRowBytes & 0x7fff;
815: info->bytesPerPlane = pixelInfo.vpPlaneBytes;
816: info->bitsPerPixel = pixelInfo.vpPixelSize;
817:
818: formats = getPixelFormats();
819: mask = getPixelFormatsForDisplayMode( displayMode, depth );
820:
821: for( index = 0; index < 32; index++) {
822: if( (mask & (1 << index)) && ((aperture--) == 0)) {
823: strcpy( info->pixelFormat, formats);
824: break;
825: }
826: formats += strlen( formats) + 1;
827: }
828:
829: if( 0 == strcmp("PPPPPPPP", info->pixelFormat)) {
830: info->pixelType = kIOCLUTPixels;
831: info->componentMasks[0] = 0xff;
832: info->bitsPerPixel = 8;
833: info->componentCount = 1;
834: info->bitsPerComponent = 8;
835:
836: } else if( 0 == strcmp("-RRRRRGGGGGBBBBB", info->pixelFormat)) {
837: info->pixelType = kIORGBDirectPixels;
838: info->componentMasks[0] = 0x7c00;
839: info->componentMasks[1] = 0x03e0;
840: info->componentMasks[2] = 0x001f;
841: info->bitsPerPixel = 16;
842: info->componentCount = 3;
843: info->bitsPerComponent = 5;
844:
845: } else if( 0 == strcmp("--------RRRRRRRRGGGGGGGGBBBBBBBB",
846: info->pixelFormat)) {
847: info->pixelType = kIORGBDirectPixels;
848: info->componentMasks[0] = 0x00ff0000;
849: info->componentMasks[1] = 0x0000ff00;
850: info->componentMasks[2] = 0x000000ff;
851: info->bitsPerPixel = 32;
852: info->componentCount = 3;
853: info->bitsPerComponent = 8;
854: }
855:
856: } while( false);
857:
858: return( err);
859: }
860:
861: IOReturn IONDRVFramebuffer::getTimingInfoForDisplayMode(
862: IODisplayModeID displayMode, IOTimingInformation * info )
863: {
864: VDTimingInfoRec timingInfo;
865: OSStatus err;
866:
867: timingInfo.csTimingMode = displayMode;
868: // in case the driver doesn't do it:
869: timingInfo.csTimingFormat = kDeclROMtables;
870: err = doStatus( cscGetModeTiming, &timingInfo);
871: if( err == noErr) {
872: if( timingInfo.csTimingFormat == kDeclROMtables)
873: info->appleTimingID = timingInfo.csTimingData;
874: else
875: info->appleTimingID = timingInvalid;
876:
877: return( kIOReturnSuccess);
878: }
879:
880: return( kIOReturnUnsupportedMode);
881: }
882:
883: IOReturn IONDRVFramebuffer::getCurrentDisplayMode(
884: IODisplayModeID * displayMode, IOIndex * depth )
885: {
886: if( displayMode)
887: *displayMode = currentDisplayMode;
888: if( depth)
889: *depth = currentDepth;
890:
891: return( kIOReturnSuccess);
892: }
893:
894: IOReturn IONDRVFramebuffer::setDisplayMode( IODisplayModeID displayMode, IOIndex depth )
895: {
896: SInt32 err;
897: VDSwitchInfoRec switchInfo;
898: VDPageInfo pageInfo;
899:
900: switchInfo.csData = displayMode;
901: switchInfo.csMode = depth + kDepthMode1;
902: switchInfo.csPage = 0;
903: err = doControl( cscSwitchMode, &switchInfo);
904: if(err)
905: IOLog("%s: cscSwitchMode:%d\n", nub->getName(), (int)err);
906:
907: // duplicate QD InitGDevice
908: pageInfo.csMode = switchInfo.csMode;
909: pageInfo.csData = 0;
910: pageInfo.csPage = 0;
911: doControl( cscSetMode, &pageInfo);
912: doControl( cscGrayPage, &pageInfo);
913:
914: getCurrentConfiguration();
915:
916: return( err);
917: }
918:
919: IOReturn IONDRVFramebuffer::setStartupDisplayMode(
920: IODisplayModeID displayMode, IOIndex depth )
921: {
922: SInt32 err;
923: VDSwitchInfoRec switchInfo;
924:
925: switchInfo.csData = displayMode;
926: switchInfo.csMode = depth + kDepthMode1;
927: err = doControl( cscSavePreferredConfiguration, &switchInfo);
928: return( err);
929: }
930:
931: IOReturn IONDRVFramebuffer::getStartupDisplayMode(
932: IODisplayModeID * displayMode, IOIndex * depth )
933: {
934: SInt32 err;
935: VDSwitchInfoRec switchInfo;
936:
937: err = doStatus( cscGetPreferredConfiguration, &switchInfo);
938: if( err == noErr) {
939: *displayMode = switchInfo.csData;
940: *depth = switchInfo.csMode - kDepthMode1;
941: }
942: return( err);
943: }
944:
945: IOReturn IONDRVFramebuffer::setApertureEnable( IOPixelAperture /* aperture */,
946: IOOptionBits /* enable */ )
947: {
948: return( kIOReturnSuccess);
949: }
950:
951: IOReturn IONDRVFramebuffer::setCLUTWithEntries(
952: IOColorEntry * colors, UInt32 index, UInt32 numEntries,
953: IOOptionBits options )
954: {
955: IOReturn err;
956: UInt32 code;
957: VDSetEntryRecord setEntryRec;
958: VDClutBehavior clutSetting;
959: VDGrayRecord grayRec;
960:
961: if( options & kSetCLUTWithLuminance)
962: grayRec.csMode = 1; // turn on luminance map
963: else
964: grayRec.csMode = 0; // turn off luminance map
965:
966: if( grayRec.csMode != lastGrayMode) {
967: doControl( cscSetGray, &grayRec);
968: lastGrayMode = grayRec.csMode;
969: }
970:
971: if( options & kSetCLUTImmediately)
972: clutSetting = kSetClutAtSetEntries;
973: else
974: clutSetting = kSetClutAtVBL;
975:
976: if( clutSetting != lastClutSetting) {
977: doControl( cscSetClutBehavior, &clutSetting);
978: lastClutSetting = clutSetting;
979: }
980:
981: if( options & kSetCLUTByValue)
982: setEntryRec.csStart = -1;
983: else
984: setEntryRec.csStart = index;
985:
986: setEntryRec.csTable = (ColorSpec *) colors;
987: setEntryRec.csCount = numEntries - 1;
988: if( directMode)
989: code = cscDirectSetEntries;
990: else
991: code = cscSetEntries;
992: err = doControl( code, &setEntryRec);
993:
994: return( err);
995: }
996:
997: IOReturn IONDRVFramebuffer::setGammaTable( UInt32 channelCount, UInt32 dataCount,
998: UInt32 dataWidth, void * data )
999: {
1000: IOReturn err;
1001: VDGammaRecord gammaRec;
1002: struct GammaTbl {
1003: short gVersion; /*gamma version number*/
1004: short gType; /*gamma data type*/
1005: short gFormulaSize; /*Formula data size*/
1006: short gChanCnt; /*number of channels of data*/
1007: short gDataCnt; /*number of values/channel*/
1008: short gDataWidth; /*bits/corrected value */
1009: /* (data packed to next larger byte size)*/
1010: UInt8 gFormulaData[0]; /*data for formulas followed by gamma values*/
1011: };
1012: GammaTbl * table = NULL;
1013: IOByteCount dataLen = 0;
1014:
1015: if( data) {
1016: dataLen = (dataWidth + 7) / 8;
1017: dataLen *= dataCount * channelCount;
1018: table = (GammaTbl *) IOMalloc( dataLen + sizeof( struct GammaTbl));
1019: if( NULL == table)
1020: return( kIOReturnNoMemory);
1021:
1022: table->gVersion = 0;
1023: table->gType = 0;
1024: table->gFormulaSize = 0;
1025: table->gChanCnt = channelCount;
1026: table-> gDataCnt = dataCount;
1027: table->gDataWidth = dataWidth;
1028: bcopy( data, table->gFormulaData, dataLen);
1029: }
1030:
1031: gammaRec.csGTable = (Ptr) table;
1032: err = doControl( cscSetGamma, &gammaRec);
1033: if( table)
1034: IOFree( table, dataLen + sizeof( struct GammaTbl));
1035:
1036: return( err);
1037: }
1038:
1039: IOReturn IONDRVFramebuffer::getAttribute( IOSelect attribute, UInt32 * value )
1040: {
1041: IOReturn err = kIOReturnSuccess;
1042: VDSupportsHardwareCursorRec hwCrsrSupport;
1043:
1044: switch( attribute ) {
1045:
1046: case kIOHardwareCursorAttribute:
1047:
1048: *value = ((kIOReturnSuccess ==
1049: doStatus( cscSupportsHardwareCursor, &hwCrsrSupport))
1050: && (hwCrsrSupport.csSupportsHardwareCursor));
1051: break;
1052:
1053: default:
1054: err = super::getAttribute( attribute, value );
1055: }
1056:
1057: return( err );
1058: }
1059:
1060: UInt32 IONDRVFramebuffer::getConnectionCount( void )
1061: {
1062: VDMultiConnectInfoRec theRecord;
1063:
1064: if( doStatus(cscGetMultiConnect,&theRecord) == 0 ) {
1065: return theRecord.csDisplayCountOrNumber;
1066: }
1067: return 1;
1068: }
1069:
1070: IOReturn IONDRVFramebuffer::setAttributeForConnection( IOIndex connectIndex,
1071: IOSelect attribute, UInt32 info )
1072: {
1073: IOReturn ret;
1074: VDSyncInfoRec theVDSyncInfoRec;
1075:
1076: switch( attribute ) {
1077:
1078: case kConnectionSyncEnable:
1079: theVDSyncInfoRec.csMode = (unsigned char)(info>>8);
1080: theVDSyncInfoRec.csFlags = (unsigned char)(info & 0xFF);
1081: doControl(cscSetSync,&theVDSyncInfoRec);
1082: ret = kIOReturnSuccess;
1083: break;
1084: default:
1085: ret = super::setAttributeForConnection( connectIndex,
1086: attribute, info );
1087: break;
1088: }
1089: return( ret );
1090: }
1091:
1092:
1093: IOReturn IONDRVFramebuffer::getAttributeForConnection( IOIndex connectIndex,
1094: IOSelect attribute, UInt32 * value )
1095: {
1096: IOReturn ret;
1097: VDSyncInfoRec theVDSyncInfoRec;
1098:
1099: switch( attribute ) {
1100:
1101: case kConnectionSyncFlags:
1102: // find out current state of sync lines
1103: theVDSyncInfoRec.csMode = 0x00;
1104: doStatus(cscGetSync,&theVDSyncInfoRec);
1105: * value = theVDSyncInfoRec.csMode;
1106: ret = kIOReturnSuccess;
1107: break;
1108: case kConnectionSyncEnable:
1109: // what are the sync-controlling capabilities of the ndrv?
1110: theVDSyncInfoRec.csMode = 0xFF;
1111: doStatus(cscGetSync,&theVDSyncInfoRec);
1112: * value = (UInt32)theVDSyncInfoRec.csMode;
1113: ret = kIOReturnSuccess;
1114: break;
1115: case kConnectionSupportsHLDDCSense:
1116: case kConnectionSupportsAppleSense:
1117: ret = kIOReturnSuccess;
1118: break;
1119: default:
1120: ret = super::getAttributeForConnection( connectIndex,
1121: attribute, value );
1122: break;
1123: }
1124:
1125: return( ret );
1126: }
1127:
1128: IOReturn IONDRVFramebuffer::getAppleSense( IOIndex connectIndex,
1129: UInt32 * senseType,
1130: UInt32 * primary,
1131: UInt32 * extended,
1132: UInt32 * displayType )
1133: {
1134: OSStatus err;
1135: VDMultiConnectInfoRec multiConnect;
1136: UInt32 sense, extSense;
1137:
1138: if( connectIndex == 0 )
1139: err = doStatus( cscGetConnection, &multiConnect.csConnectInfo);
1140:
1141: else {
1142: multiConnect.csDisplayCountOrNumber = connectIndex;
1143: err = doControl( cscSetMultiConnect, &multiConnect);
1144: }
1145: if( err)
1146: return( err);
1147:
1148: if( multiConnect.csConnectInfo.csConnectFlags
1149: & ((1<<kReportsTagging) | (1<<kTaggingInfoNonStandard))
1150: != ((1<<kReportsTagging)) )
1151:
1152: err = kIOReturnUnsupported;
1153:
1154: else {
1155:
1156: sense = multiConnect.csConnectInfo.csConnectTaggedType;
1157: extSense = multiConnect.csConnectInfo.csConnectTaggedData;
1158: // bug fixes for really old ATI driver
1159: if( sense == 0) {
1160: if( extSense == 6) {
1161: sense = kRSCSix;
1162: extSense = kESCSixStandard;
1163: }
1164: else
1165: if( extSense == 4) {
1166: sense = kRSCFour;
1167: extSense = kESCFourNTSC;
1168: }
1169: }
1170: if( primary)
1171: *primary = sense;
1172: if( extended)
1173: *extended = extSense;
1174: if( displayType)
1175: *displayType = multiConnect.csConnectInfo.csDisplayType;
1176: if( senseType)
1177: *senseType = 0;
1178: }
1179: return( err);
1180: }
1181:
1182: IOReturn IONDRVFramebuffer::connectFlags( IOIndex /* connectIndex */,
1183: IODisplayModeID displayMode, IOOptionBits * flags )
1184: {
1185: VDTimingInfoRec timingInfo;
1186: OSStatus err;
1187:
1188: timingInfo.csTimingMode = displayMode;
1189: // in case the driver doesn't do it:
1190: timingInfo.csTimingFormat = kDeclROMtables;
1191: err = doStatus( cscGetModeTiming, &timingInfo);
1192: *flags = timingInfo.csTimingFlags;
1193: return( err );
1194: }
1195:
1196:
1197: bool IONDRVFramebuffer::hasDDCConnect( IOIndex connectIndex )
1198: {
1199: OSStatus err;
1200: VDMultiConnectInfoRec multiConnect;
1201: enum { kNeedFlags = (1<<kReportsDDCConnection)
1202: | (1<<kHasDDCConnection) };
1203: if( connectIndex == 0 )
1204: err = doStatus( cscGetConnection, &multiConnect.csConnectInfo);
1205: else {
1206: multiConnect.csDisplayCountOrNumber = connectIndex;
1207: err = doControl( cscSetMultiConnect, &multiConnect);
1208: }
1209: if( err)
1210: return( err);
1211:
1212: return( (multiConnect.csConnectInfo.csConnectFlags & kNeedFlags)
1213: == kNeedFlags );
1214: }
1215:
1216: IOReturn IONDRVFramebuffer::getDDCBlock( IOIndex /* connectIndex */,
1217: UInt32 blockNumber,
1218: IOSelect blockType,
1219: IOOptionBits options,
1220: UInt8 * data, IOByteCount * length )
1221:
1222: {
1223: OSStatus err = 0;
1224: VDDDCBlockRec ddcRec;
1225: ByteCount actualLength = *length;
1226:
1227: ddcRec.ddcBlockNumber = blockNumber;
1228: ddcRec.ddcBlockType = blockType;
1229: ddcRec.ddcFlags = options;
1230:
1231: err = doStatus( cscGetDDCBlock, &ddcRec);
1232:
1233: if( err == noErr) {
1234:
1235: if( actualLength < kDDCBlockSize)
1236: actualLength = actualLength;
1237: else
1238: actualLength = kDDCBlockSize;
1239: bcopy( ddcRec.ddcBlockData, data, actualLength);
1240: *length = actualLength;
1241: }
1242: return( err);
1243: }
1244:
1245: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1246: // initForPM
1247: //
1248: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1249: void IONDRVFramebuffer::initForPM ( void )
1250: {
1251: // register ourselves with superclass policy-maker
1252: registerControllingDriver(this,ourPowerStates,number_of_power_states);
1253: }
1254:
1255:
1256: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1257: // maxCapabilityForDomainState
1258: //
1259: // This simple device needs only power. If the power domain is supplying
1260: // power, the frame buffer can be on. If there is no power it can only be off.
1261: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1262:
1263: unsigned long IONDRVFramebuffer::maxCapabilityForDomainState(
1264: IOPMPowerFlags domainState )
1265: {
1266: if( domainState & IOPMPowerOn )
1267: return number_of_power_states-1;
1268: else
1269: return 0;
1270: }
1271:
1272:
1273: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1274: // initialPowerStateForDomainState
1275: //
1276: // The power domain may be changing state. If power is on in the new
1277: // state, that will not affect our state at all. If domain power is off,
1278: // we can attain only our lowest state, which is off.
1279: //
1280: // This implementation is incomplete. It only works in a system where
1281: // the frame buffer is never turned off. When we cross that bridge,
1282: // instead of returning 1, it should return 1 if the frame buffer
1283: // is on, or 0 if it is off.
1284: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1285: unsigned long IONDRVFramebuffer::initialPowerStateForDomainState(
1286: IOPMPowerFlags domainState )
1287: {
1288: if( domainState & IOPMPowerOn )
1289: return number_of_power_states-1;
1290: else
1291: return 0;
1292: }
1293:
1294:
1295: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1296: // powerStateForDomainState
1297: //
1298: // The power domain may be changing state. If power is on in the new
1299: // state, that will not affect our state at all. If domain power is off,
1300: // we can attain only our lowest state, which is off.
1301: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1302: unsigned long IONDRVFramebuffer::powerStateForDomainState(
1303: IOPMPowerFlags domainState )
1304: {
1305: if( domainState & IOPMPowerOn )
1306: return pm_vars->myCurrentState;
1307: else
1308: return 0;
1309: }
1310:
1311:
1312: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1313: // setPowerState
1314: //
1315: // Called by the superclass to turn the frame buffer on and off.
1316: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1317: IOReturn IONDRVFramebuffer::setPowerState( unsigned long powerStateOrdinal,
1318: IOService* whatDevice )
1319: {
1320: if ( powerStateOrdinal == 0 ) {
1321: kprintf("frame buffer would be powered off here\n");
1322: }
1323: if ( powerStateOrdinal == 1 ) {
1324: kprintf("frame buffer would be powered on here\n");
1325: }
1326: return IOPMAckImplied;
1327: }
1328:
1329: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1330:
1331: // ATI patches.
1332: // Real problem : getStartupMode doesn't.
1333:
1334: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1335:
1336: #undef super
1337: #define super IONDRVFramebuffer
1338:
1339: OSDefineMetaClassAndStructors(IOATINDRV, IONDRVFramebuffer)
1340: OSDefineMetaClassAndStructors(IOATI128NDRV, IOATINDRV)
1341:
1342: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1343:
1344: IOReturn IOATINDRV::getStartupDisplayMode(
1345: IODisplayModeID * displayMode, IOIndex * depth )
1346: {
1347: UInt16 * nvram;
1348: OSData * prop;
1349:
1350: prop = OSDynamicCast( OSData, nub->getProperty("Sime"));
1351: if( prop) {
1352: nvram = (UInt16 *) prop->getBytesNoCopy();
1353: *displayMode = nvram[ 0 ]; // 1 is physDisplayMode
1354: *depth = nvram[ 2 ] - kDepthMode1;
1355: return( kIOReturnSuccess);
1356: } else
1357: return(super::getStartupDisplayMode( displayMode, depth));
1358: }
1359:
1360: IODeviceMemory * IOATINDRV::findVRAM( void )
1361: {
1362: OSData * prop;
1363: IOPhysicalAddress vramBase;
1364: IOByteCount vramLength;
1365:
1366: prop = OSDynamicCast( OSData, nub->getProperty("APPL,VRAMSize"));
1367: if( !prop)
1368: prop = OSDynamicCast( OSData, nub->getProperty("ATY,memsize"));
1369: if( !prop)
1370: return( super::findVRAM());
1371:
1372: vramBase = physicalFramebuffer;
1373: vramLength = *((IOByteCount *)prop->getBytesNoCopy());
1374: if( !vramLength)
1375: return( super::findVRAM());
1376: vramLength = (vramLength + (vramBase & 0xffff)) & 0xffff0000;
1377: vramBase &= 0xffff0000;
1378:
1379: return( makeSubRange( vramBase, vramLength ));
1380: }
1381:
1382: static int g128ExtraCurs = 8;
1383: static int g128DeltaCurs = 0x25c0;
1384:
1385: void IOATI128NDRV::flushCursor( void )
1386: {
1387: volatile UInt32 * fb;
1388: UInt32 x;
1389: int i;
1390:
1391: fb = (volatile UInt32 *) frameBuffer;
1392: for( i = 0; i < g128ExtraCurs; i++) {
1393: x += *(fb++);
1394: fb += g128DeltaCurs;
1395: }
1396: }
1397:
1398:
1399:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.