]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOGraphics/IOFramebuffer.cpp
xnu-123.5.tar.gz
[apple/xnu.git] / iokit / Families / IOGraphics / IOFramebuffer.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) 1998 Apple Computer, Inc. All rights reserved.
24 *
25 * HISTORY
26 *
27 * 01 Sep 92 Portions from Joe Pasqua, Created.
28 */
29
30
31 #include <IOKit/IOLib.h>
32 #include <libkern/c++/OSContainers.h>
33
34 #include <IOKit/IOWorkLoop.h>
35 #include <IOKit/IOInterruptEventSource.h>
36 #include <IOKit/IOPlatformExpert.h>
37 #include <IOKit/IOBufferMemoryDescriptor.h>
38
39 #define IOFRAMEBUFFER_PRIVATE
40 #include <IOKit/graphics/IOFramebuffer.h>
41 #include <IOKit/graphics/IODisplay.h>
42
43 #include "IOFramebufferUserClient.h"
44 #include "IODisplayWrangler.h"
45 #include "IOFramebufferReallyPrivate.h"
46 #include <IOKit/pwr_mgt/RootDomain.h>
47
48 #include <string.h>
49 #include <IOKit/assert.h>
50 #include <sys/kdebug.h>
51
52 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
53
54 #undef super
55 #define super IOGraphicsDevice
56
57 OSDefineMetaClass( IOFramebuffer, IOGraphicsDevice )
58 OSDefineAbstractStructors( IOFramebuffer, IOGraphicsDevice )
59
60 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
61
62 #define GetShmem(instance) ((StdFBShmem_t *)(instance->priv))
63
64 #define CLEARSEMA(shmem) ev_unlock(&shmem->cursorSema)
65 #define SETSEMA(shmem) \
66 if (!ev_try_lock(&shmem->cursorSema)) return;
67 #define TOUCHBOUNDS(one, two) \
68 (((one.minx < two.maxx) && (two.minx < one.maxx)) && \
69 ((one.miny < two.maxy) && (two.miny < one.maxy)))
70
71 /*
72 * Cursor rendering
73 */
74
75 #include "IOCursorBlits.h"
76
77 inline void IOFramebuffer::StdFBDisplayCursor( IOFramebuffer * inst )
78 {
79 StdFBShmem_t *shmem;
80 Bounds saveRect;
81 volatile unsigned char *vramPtr; /* screen data pointer */
82 unsigned int cursStart;
83 unsigned int cursorWidth;
84 int width;
85 int height;
86
87 shmem = GetShmem(inst);
88 saveRect = shmem->cursorRect;
89 /* Clip saveRect vertical within screen bounds */
90 if (saveRect.miny < shmem->screenBounds.miny)
91 saveRect.miny = shmem->screenBounds.miny;
92 if (saveRect.maxy > shmem->screenBounds.maxy)
93 saveRect.maxy = shmem->screenBounds.maxy;
94 if (saveRect.minx < shmem->screenBounds.minx)
95 saveRect.minx = shmem->screenBounds.minx;
96 if (saveRect.maxx > shmem->screenBounds.maxx)
97 saveRect.maxx = shmem->screenBounds.maxx;
98 shmem->saveRect = saveRect; /* Remember save rect for RemoveCursor */
99
100 vramPtr = inst->frameBuffer +
101 (inst->rowBytes * (saveRect.miny - shmem->screenBounds.miny)) +
102 (inst->bytesPerPixel * (saveRect.minx - shmem->screenBounds.minx));
103
104 width = saveRect.maxx - saveRect.minx;
105 height = saveRect.maxy - saveRect.miny;
106 cursorWidth = shmem->cursorSize[shmem->frame].width;
107
108 cursStart = (saveRect.miny - shmem->cursorRect.miny) * cursorWidth +
109 (saveRect.minx - shmem->cursorRect.minx);
110
111 if( inst->cursorBlitProc)
112 inst->cursorBlitProc( inst,
113 (void *) shmem,
114 vramPtr,
115 cursStart,
116 inst->totalWidth - width, /* vramRow */
117 cursorWidth - width, /* cursRow */
118 width,
119 height);
120 }
121
122 // Description: RemoveCursor erases the cursor by replacing the background
123 // image that was saved by the previous call to DisplayCursor.
124 // If the frame buffer is cacheable, flush at the end of the
125 // drawing operation.
126
127 inline void IOFramebuffer::StdFBRemoveCursor( IOFramebuffer * inst )
128 {
129 StdFBShmem_t *shmem;
130 volatile unsigned char *vramPtr; /* screen data pointer */
131 unsigned int vramRow;
132 int width;
133 int height;
134
135 shmem = GetShmem(inst);
136
137 vramRow = inst->totalWidth; /* Scanline width in pixels */
138
139 vramPtr = inst->frameBuffer +
140 (inst->rowBytes * (shmem->saveRect.miny - shmem->screenBounds.miny))
141 + (inst->bytesPerPixel *
142 (shmem->saveRect.minx - shmem->screenBounds.minx));
143
144 width = shmem->saveRect.maxx - shmem->saveRect.minx;
145 height = shmem->saveRect.maxy - shmem->saveRect.miny;
146 vramRow -= width;
147
148 if( inst->cursorRemoveProc)
149 inst->cursorRemoveProc( inst, (void *)shmem,
150 vramPtr, vramRow, width, height);
151 }
152
153 inline void IOFramebuffer::RemoveCursor( IOFramebuffer * inst )
154 {
155 StdFBShmem_t * shmem = GetShmem(inst);
156
157 if( shmem->hardwareCursorActive ) {
158 Point * hs;
159
160 hs = &shmem->hotSpot[shmem->frame];
161 inst->setCursorState(
162 shmem->cursorLoc.x - hs->x - shmem->screenBounds.minx,
163 shmem->cursorLoc.y - hs->y - shmem->screenBounds.miny, false );
164 } else
165 StdFBRemoveCursor(inst);
166 }
167
168 inline void IOFramebuffer::DisplayCursor( IOFramebuffer * inst )
169 {
170 Point * hs;
171 StdFBShmem_t * shmem = GetShmem(inst);
172 SInt32 x, y;
173
174 hs = &shmem->hotSpot[shmem->frame];
175 x = shmem->cursorLoc.x - hs->x;
176 y = shmem->cursorLoc.y - hs->y;
177
178 if( shmem->hardwareCursorActive )
179 inst->setCursorState( x - shmem->screenBounds.minx,
180 y - shmem->screenBounds.miny, true );
181 else {
182 shmem->cursorRect.maxx = (shmem->cursorRect.minx = x)
183 + shmem->cursorSize[shmem->frame].width;
184 shmem->cursorRect.maxy = (shmem->cursorRect.miny = y)
185 + shmem->cursorSize[shmem->frame].height;
186 StdFBDisplayCursor(inst);
187 shmem->oldCursorRect = shmem->cursorRect;
188 }
189 }
190
191 inline void IOFramebuffer::SysHideCursor( IOFramebuffer * inst )
192 {
193 if (!GetShmem(inst)->cursorShow++)
194 RemoveCursor(inst);
195 }
196
197 inline void IOFramebuffer::SysShowCursor( IOFramebuffer * inst )
198 {
199 StdFBShmem_t *shmem;
200
201 shmem = GetShmem(inst);
202
203 if (shmem->cursorShow)
204 if (!--(shmem->cursorShow))
205 DisplayCursor(inst);
206 }
207
208 inline void IOFramebuffer::CheckShield( IOFramebuffer * inst )
209 {
210 Point * hs;
211 int intersect;
212 Bounds tempRect;
213 StdFBShmem_t * shmem = GetShmem(inst);
214
215 /* Calculate temp cursorRect */
216 hs = &shmem->hotSpot[shmem->frame];
217 tempRect.maxx = (tempRect.minx = (shmem->cursorLoc).x - hs->x)
218 + shmem->cursorSize[shmem->frame].width;
219 tempRect.maxy = (tempRect.miny = (shmem->cursorLoc).y - hs->y)
220 + shmem->cursorSize[shmem->frame].height;
221
222 intersect = TOUCHBOUNDS(tempRect, shmem->shieldRect);
223 if (intersect != shmem->shielded)
224 (shmem->shielded = intersect) ?
225 SysHideCursor(inst) : SysShowCursor(inst);
226 }
227
228 /**
229 ** external methods
230 **/
231
232 void IOFramebuffer::setupCursor( IOPixelInformation * info )
233 {
234 StdFBShmem_t * shmem = GetShmem(this);
235 volatile unsigned char * bits;
236 IOByteCount cursorImageBytes;
237
238 rowBytes = info->bytesPerRow;
239 totalWidth = (rowBytes * 8) / info->bitsPerPixel;
240 bytesPerPixel = info->bitsPerPixel / 8;
241 frameBuffer = (volatile unsigned char *) vramMap->getVirtualAddress();
242
243 if( shmem) {
244 if( (shmem->screenBounds.maxx == shmem->screenBounds.minx)
245 || (shmem->screenBounds.maxy == shmem->screenBounds.miny)) {
246 // a default if no one calls IOFBSetBounds()
247 shmem->screenBounds.minx = 0;
248 shmem->screenBounds.miny = 0;
249 shmem->screenBounds.maxx = info->activeWidth;
250 shmem->screenBounds.maxy = info->activeHeight;
251 }
252
253 cursorImageBytes = maxCursorSize.width * maxCursorSize.height
254 * bytesPerPixel;
255 bits = shmem->cursor;
256 for( int i = 0; i < kIOFBNumCursorFrames; i++ ) {
257 cursorImages[i] = bits;
258 bits += cursorImageBytes;
259 shmem->cursorSize[i] = maxCursorSize;
260 }
261 if( info->bitsPerPixel <= 8) {
262 for( int i = 0; i < kIOFBNumCursorFrames; i++ ) {
263 cursorMasks[i] = bits;
264 bits += cursorImageBytes;
265 }
266 }
267 cursorSave = bits;
268 }
269
270 switch( info->bitsPerPixel) {
271 case 8:
272 if( colorConvert.t._bm256To38SampleTable
273 && colorConvert.t._bm38To256SampleTable) {
274 cursorBlitProc = (CursorBlitProc) StdFBDisplayCursor8P;
275 cursorRemoveProc = (CursorRemoveProc) StdFBRemoveCursor8;
276 }
277 break;
278 case 16:
279 if( colorConvert.t._bm34To35SampleTable
280 && colorConvert.t._bm35To34SampleTable) {
281 cursorBlitProc = (CursorBlitProc) StdFBDisplayCursor555;
282 cursorRemoveProc = (CursorRemoveProc) StdFBRemoveCursor16;
283 }
284 break;
285 case 32:
286 if( colorConvert.t._bm256To38SampleTable
287 && colorConvert.t._bm38To256SampleTable) {
288 cursorBlitProc = (CursorBlitProc) StdFBDisplayCursor32Axxx;
289 cursorRemoveProc = (CursorRemoveProc) StdFBRemoveCursor32;
290 }
291 break;
292 default:
293 IOLog("%s: can't do cursor at depth %ld\n",
294 getName(), info->bitsPerPixel);
295 cursorBlitProc = (CursorBlitProc) NULL;
296 cursorRemoveProc = (CursorRemoveProc) NULL;
297 break;
298 }
299 }
300
301 void IOFramebuffer::stopCursor( void )
302 {
303 cursorBlitProc = (CursorBlitProc) NULL;
304 cursorRemoveProc = (CursorRemoveProc) NULL;
305 }
306
307 IOReturn IOFramebuffer::createSharedCursor(
308 int shmemVersion, int maxWidth, int maxHeight )
309 {
310 StdFBShmem_t * shmem;
311 IOByteCount size, maxImageSize;
312
313 kprintf("createSharedCursor vers = %d, %d x %d\n",
314 shmemVersion, maxWidth, maxHeight);
315
316 if( shmemVersion != kIOFBCurrentShmemVersion)
317 return( kIOReturnUnsupported);
318
319 shmemClientVersion = shmemVersion;
320 maxImageSize = (maxWidth * maxHeight * kIOFBMaxCursorDepth) / 8;
321
322 size = sizeof( StdFBShmem_t)
323 + ((kIOFBNumCursorFrames + 1) * maxImageSize);
324
325 if( !sharedCursor || (size != sharedCursor->getLength())) {
326 IOBufferMemoryDescriptor * newDesc;
327
328 priv = 0;
329 newDesc = IOBufferMemoryDescriptor::withOptions(
330 kIODirectionNone | kIOMemoryKernelUserShared, size );
331 if( !newDesc)
332 return( kIOReturnNoMemory );
333
334 if( sharedCursor)
335 sharedCursor->release();
336 sharedCursor = newDesc;
337 }
338 shmem = (StdFBShmem_t *) sharedCursor->getBytesNoCopy();
339 priv = shmem;
340
341 // Init shared memory area
342 bzero( shmem, size );
343 shmem->version = kIOFBCurrentShmemVersion;
344 shmem->structSize = size;
345 shmem->cursorShow = 1;
346 shmem->hardwareCursorCapable = haveHWCursor;
347
348 maxCursorSize.width = maxWidth;
349 maxCursorSize.height = maxHeight;
350
351 doSetup( false );
352
353 return( kIOReturnSuccess);
354 }
355
356 IOReturn IOFramebuffer::setBoundingRect( Bounds * bounds )
357 {
358 StdFBShmem_t *shmem;
359
360 shmem = GetShmem(this);
361 if( NULL == shmem)
362 return( kIOReturnUnsupported);
363
364 shmem->screenBounds = *bounds;
365
366 return( kIOReturnSuccess);
367 }
368
369 /**
370 ** IOUserClient methods
371 **/
372
373 IOReturn IOFramebuffer::newUserClient( task_t owningTask,
374 void * security_id,
375 UInt32 type,
376 IOUserClient ** handler )
377
378 {
379 #if 0
380 static UInt8 data[] = { 0x00, 0x03, 0x04, 0x07, 0x08, 0x0b, 0x0c, 0x0f,
381 0x10, 0x13, 0x14, 0x17, 0x18, 0x1b, 0x1c, 0x1f,
382
383 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03,
384 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07,
385 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b,
386 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f };
387 colorConvert.t._bm34To35SampleTable = data;
388 colorConvert.t._bm35To34SampleTable = data + 16;
389 #endif
390
391 IOReturn err = kIOReturnSuccess;
392 IOUserClient * newConnect = 0;
393 IOUserClient * theConnect = 0;
394
395 switch( type ) {
396
397 case kIOFBServerConnectType:
398 if( serverConnect)
399 err = kIOReturnExclusiveAccess;
400 else {
401
402 if( isConsoleDevice())
403 getPlatform()->setConsoleInfo( 0, kPEReleaseScreen);
404
405 err = IODisplayWrangler::clientStart( this );
406 if( kIOReturnSuccess == err)
407 newConnect = IOFramebufferUserClient::withTask(owningTask);
408 }
409 break;
410
411 case kIOFBSharedConnectType:
412 if( sharedConnect) {
413 theConnect = sharedConnect;
414 theConnect->retain();
415 } else if( serverConnect)
416 newConnect = IOFramebufferSharedUserClient::withTask(owningTask);
417 else
418 err = kIOReturnNotOpen;
419 break;
420
421 case kIOFBEngineControllerConnectType:
422 case kIOFBEngineConnectType:
423 newConnect = IOGraphicsEngineClient::withTask(owningTask);
424 break;
425
426 default:
427 err = kIOReturnBadArgument;
428 }
429
430 if( newConnect) {
431 if( (false == newConnect->attach( this ))
432 || (false == newConnect->start( this ))) {
433 newConnect->detach( this );
434 newConnect->release();
435 } else
436 theConnect = newConnect;
437 }
438
439 *handler = theConnect;
440 return( err );
441 }
442
443 IOReturn IOFramebuffer::extGetDisplayModeCount( IOItemCount * count )
444 {
445 *count = getDisplayModeCount();
446 return( kIOReturnSuccess);
447 }
448
449 IOReturn IOFramebuffer::extGetDisplayModes( IODisplayModeID * allModes, IOByteCount * size )
450 {
451 IOReturn err;
452 IOByteCount outSize;
453
454 outSize = getDisplayModeCount() * sizeof( IODisplayModeID);
455
456 if( *size < outSize)
457 return( kIOReturnBadArgument);
458
459 *size = outSize;
460 err = getDisplayModes( allModes );
461
462 return( err);
463 }
464
465 IOReturn IOFramebuffer::extGetVRAMMapOffset( IOPixelAperture /* aperture */,
466 IOByteCount * offset )
467 {
468 *offset = vramMapOffset;
469
470 return( kIOReturnSuccess );
471 }
472
473 IOReturn IOFramebuffer::extSetBounds( Bounds * bounds )
474 {
475 StdFBShmem_t *shmem;
476
477 shmem = GetShmem(this);
478 if( shmem)
479 shmem->screenBounds = *bounds;
480
481 return( kIOReturnSuccess );
482 }
483
484 IOReturn IOFramebuffer::extValidateDetailedTiming(
485 void * description, void * outDescription,
486 IOByteCount inSize, IOByteCount * outSize )
487 {
488 IOReturn err;
489
490 if( *outSize != inSize)
491 return( kIOReturnBadArgument );
492
493 err = validateDetailedTiming( description, inSize );
494
495 if( kIOReturnSuccess == err)
496 bcopy( description, outDescription, inSize );
497
498 return( err );
499 }
500
501
502 IOReturn IOFramebuffer::extSetColorConvertTable( UInt32 select,
503 UInt8 * data, IOByteCount length )
504 {
505 static const IOByteCount checkLength[] = {
506 16 * sizeof( UInt8),
507 32 * sizeof( UInt8),
508 256 * sizeof( UInt32),
509 5 * 256 * sizeof( UInt8) };
510
511 UInt8 * table;
512 IODisplayModeID mode;
513 IOIndex depth;
514 IOPixelInformation info;
515
516 if( select > 3)
517 return( kIOReturnBadArgument );
518
519 if( length != checkLength[select])
520 return( kIOReturnBadArgument );
521
522 table = colorConvert.tables[select];
523 if( 0 == table) {
524 table = (UInt8 *) IOMalloc( length );
525 colorConvert.tables[select] = table;
526 }
527 if( !table)
528 return( kIOReturnNoMemory );
529
530 bcopy( data, table, length );
531 if( select == 3)
532 white = data[data[255] + data[511] + data[767] + 1024];
533
534 if( (NULL == cursorBlitProc)
535 && colorConvert.tables[0] && colorConvert.tables[1]
536 && colorConvert.tables[2] && colorConvert.tables[3]
537 && vramMap
538 && (kIOReturnSuccess == getCurrentDisplayMode( &mode, &depth ))
539 && (kIOReturnSuccess == getPixelInformation( mode, depth, kIOFBSystemAperture, &info )))
540 setupCursor( &info );
541
542 return( kIOReturnSuccess );
543 }
544
545 IOReturn IOFramebuffer::extSetCLUTWithEntries( UInt32 index, IOOptionBits options,
546 IOColorEntry * colors, IOByteCount inputCount )
547 {
548 IOReturn kr;
549
550 kr = setCLUTWithEntries( colors, index,
551 inputCount / sizeof( IOColorEntry),
552 options );
553
554 return( kr );
555 }
556
557 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
558
559 //
560 // BEGIN: Implementation of the evScreen protocol
561 //
562
563 void IOFramebuffer::hideCursor( void )
564 {
565 StdFBShmem_t *shmem = GetShmem(this);
566
567 SETSEMA(shmem);
568 SysHideCursor(this);
569 CLEARSEMA(shmem);
570 }
571
572 #if 0
573 void IOFramebuffer::free()
574 {
575 if( vblSemaphore)
576 semaphore_destroy(kernel_task, vblSemaphore);
577 super::free();
578 }
579 #endif
580
581 void IOFramebuffer::deferredMoveCursor( IOFramebuffer * inst )
582 {
583 StdFBShmem_t * shmem = GetShmem(inst);
584 IOReturn err = kIOReturnSuccess;
585
586 if( shmem->hardwareCursorActive && (0 == shmem->frame) ) {
587
588 if (shmem->cursorObscured) {
589 shmem->cursorObscured = 0;
590 if (shmem->cursorShow)
591 --shmem->cursorShow;
592 }
593 if (!shmem->cursorShow) {
594 Point * hs;
595 hs = &shmem->hotSpot[shmem->frame];
596 err = inst->setCursorState(
597 shmem->cursorLoc.x - hs->x - shmem->screenBounds.minx,
598 shmem->cursorLoc.y - hs->y - shmem->screenBounds.miny, true );
599 }
600
601 } else {
602
603 if (!shmem->cursorShow++)
604 RemoveCursor(inst);
605 if (shmem->cursorObscured) {
606 shmem->cursorObscured = 0;
607 if (shmem->cursorShow)
608 --shmem->cursorShow;
609 }
610 if (shmem->shieldFlag) CheckShield(inst);
611 if (shmem->cursorShow)
612 if (!--shmem->cursorShow)
613 DisplayCursor(inst);
614
615 inst->flushCursor();
616 }
617 inst->needCursorService = (kIOReturnBusy == err);
618 }
619
620 void IOFramebuffer::moveCursor( Point * cursorLoc, int frame )
621 {
622 nextCursorLoc = *cursorLoc;
623 nextCursorFrame = frame;
624 needCursorService = true;
625
626 StdFBShmem_t *shmem = GetShmem(this);
627
628 SETSEMA(shmem);
629
630 if( !haveVBLService) {
631 shmem->cursorLoc = *cursorLoc;
632 shmem->frame = frame;
633 deferredMoveCursor( this );
634 }
635
636 CLEARSEMA(shmem);
637 }
638
639 void IOFramebuffer::handleVBL( IOFramebuffer * inst, void * ref )
640 {
641 StdFBShmem_t * shmem = GetShmem(inst);
642 AbsoluteTime now;
643
644 if( !shmem)
645 return;
646
647 clock_get_uptime( &now );
648 shmem->vblDelta = now;
649 SUB_ABSOLUTETIME( &shmem->vblDelta, &shmem->vblTime );
650 shmem->vblTime = now;
651
652 KERNEL_DEBUG(0xc000030 | DBG_FUNC_NONE,
653 shmem->vblDelta.hi, shmem->vblDelta.lo, 0, 0, 0);
654
655 if( inst->vblSemaphore)
656 semaphore_signal_all(inst->vblSemaphore);
657
658 SETSEMA(shmem);
659
660 if( inst->needCursorService) {
661 shmem->cursorLoc = inst->nextCursorLoc;
662 shmem->frame = inst->nextCursorFrame;
663 deferredMoveCursor( inst );
664 }
665
666 CLEARSEMA(shmem);
667 }
668
669 void IOFramebuffer::showCursor( Point * cursorLoc, int frame )
670 {
671 StdFBShmem_t *shmem;
672
673 shmem = GetShmem(this);
674 SETSEMA(shmem);
675 shmem->frame = frame;
676 shmem->hardwareCursorActive = hwCursorLoaded && (frame == 0);
677 shmem->cursorLoc = *cursorLoc;
678 if (shmem->shieldFlag) CheckShield(this);
679 SysShowCursor(this);
680 CLEARSEMA(shmem);
681 }
682
683 void IOFramebuffer::resetCursor( void )
684 {
685 StdFBShmem_t *shmem;
686
687 shmem = GetShmem(this);
688 hwCursorLoaded = false;
689 if( !shmem)
690 return;
691 hideCursor();
692 shmem->hardwareCursorActive = false;
693 showCursor( &shmem->cursorLoc, shmem->frame );
694 }
695
696 void IOFramebuffer::getVBLTime( AbsoluteTime * time, AbsoluteTime * delta )
697 {
698 StdFBShmem_t *shmem;
699
700 shmem = GetShmem(this);
701 if( shmem) {
702 *time = shmem->vblTime;
703 *delta = shmem->vblDelta;
704 } else
705 time->hi = time->lo = 0;
706 }
707
708 void IOFramebuffer::getBoundingRect( Bounds ** bounds )
709 {
710 StdFBShmem_t *shmem;
711
712 shmem = GetShmem(this);
713 if( NULL == shmem)
714 *bounds = NULL;
715 else
716 *bounds = &shmem->screenBounds;
717 }
718
719 //
720 // END: Implementation of the evScreen protocol
721 //
722
723 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
724
725 IOReturn IOFramebuffer::getNotificationSemaphore(
726 IOSelect interruptType, semaphore_t * semaphore )
727 {
728 kern_return_t kr;
729 semaphore_t sema;
730
731 if( interruptType != kIOFBVBLInterruptType)
732 return( kIOReturnUnsupported );
733
734 if( !haveVBLService)
735 return( kIOReturnNoResources );
736
737 if( MACH_PORT_NULL == vblSemaphore) {
738 kr = semaphore_create(kernel_task, &sema, SYNC_POLICY_FIFO, 0);
739 if( kr == KERN_SUCCESS)
740 vblSemaphore = sema;
741 } else
742 kr = KERN_SUCCESS;
743
744 if( kr == KERN_SUCCESS)
745 *semaphore = vblSemaphore;
746
747 return( kr );
748 }
749
750 IOReturn IOFramebuffer::extSetCursorVisible( bool visible )
751 {
752 IOReturn err;
753 Point * hs;
754 StdFBShmem_t * shmem = GetShmem(this);
755
756 if( shmem->hardwareCursorActive ) {
757 hs = &shmem->hotSpot[shmem->frame];
758 err = setCursorState(
759 shmem->cursorLoc.x - hs->x - shmem->screenBounds.minx,
760 shmem->cursorLoc.y - hs->y - shmem->screenBounds.miny,
761 visible );
762 } else
763 err = kIOReturnBadArgument;
764
765 return( err );
766 }
767
768 IOReturn IOFramebuffer::extSetCursorPosition( SInt32 x, SInt32 y )
769 {
770 return( kIOReturnUnsupported );
771 }
772
773 IOReturn IOFramebuffer::extSetNewCursor( void * cursor, IOIndex frame,
774 IOOptionBits options )
775 {
776 StdFBShmem_t * shmem = GetShmem(this);
777 IOReturn err;
778
779 if( cursor || options || frame)
780 err = kIOReturnBadArgument;
781 else {
782
783 if( (shmem->cursorSize[frame].width > maxCursorSize.width)
784 || (shmem->cursorSize[frame].height > maxCursorSize.height))
785 err = kIOReturnBadArgument;
786
787 else if( haveHWCursor)
788 err = setCursorImage( (void *) frame );
789 else
790 err = kIOReturnUnsupported;
791 }
792
793 hwCursorLoaded = (kIOReturnSuccess == err);
794 shmem->hardwareCursorActive = hwCursorLoaded && (shmem->frame == 0);
795
796 return( err );
797 }
798
799 bool IOFramebuffer::convertCursorImage( void * cursorImage,
800 IOHardwareCursorDescriptor * hwDesc,
801 IOHardwareCursorInfo * hwCursorInfo )
802 {
803 StdFBShmem_t * shmem = GetShmem(this);
804 UInt8 * dataOut = hwCursorInfo->hardwareCursorData;
805 IOColorEntry * clut = hwCursorInfo->colorMap;
806 UInt32 maxColors = hwDesc->numColors;
807 int frame = (int) cursorImage;
808
809 volatile unsigned short * cursPtr16;
810 volatile unsigned int * cursPtr32;
811 SInt32 x, y;
812 UInt32 index, numColors = 0;
813 UInt16 alpha, red, green, blue;
814 UInt16 s16;
815 UInt32 s32;
816 UInt8 data = 0;
817 UInt8 pixel = 0;
818 bool ok = true;
819
820 assert( frame < kIOFBNumCursorFrames );
821
822 if( bytesPerPixel == 4) {
823 cursPtr32 = (volatile unsigned int *) cursorImages[ frame ];
824 cursPtr16 = 0;
825 } else if( bytesPerPixel == 2) {
826 cursPtr32 = 0;
827 cursPtr16 = (volatile unsigned short *) cursorImages[ frame ];
828 } else
829 return( false );
830
831 x = shmem->cursorSize[frame].width;
832 y = shmem->cursorSize[frame].height;
833
834 if( (x > (SInt32) hwDesc->width) || (y > (SInt32) hwDesc->height))
835 return( false );
836 #if 0
837 hwCursorInfo->cursorWidth = x;
838 hwCursorInfo->cursorHeight = y;
839 while( (--y != -1) ) {
840 x = shmem->cursorSize[frame].width;
841 while( (--x != -1) ) {
842
843 if( cursPtr32) {
844 s32 = *(cursPtr32++);
845 alpha = (s32 >> 28) & 0xf;
846 if( alpha && (alpha != 0xf))
847 *(cursPtr32 - 1) = 0x00ffffff;
848
849 } else {
850 s16 = *(cursPtr16++);
851 alpha = s16 & 0x000F;
852 if( alpha && (alpha != 0xf))
853 *(cursPtr16 - 1) = 0xfff0;
854 }
855 }
856 }
857 #endif
858
859 hwCursorInfo->cursorWidth = x;
860 hwCursorInfo->cursorHeight = y;
861
862 while( ok && (--y != -1) ) {
863 x = shmem->cursorSize[frame].width;
864 while( ok && (--x != -1) ) {
865
866 if( cursPtr32) {
867 s32 = *(cursPtr32++);
868 alpha = (s32 >> 28) & 0xf;
869 red = (s32 >> 16) & 0xff;
870 red |= (red << 8);
871 green = (s32 >> 8) & 0xff;
872 green |= (green << 8);
873 blue = (s32) & 0xff;
874 blue |= (blue << 8);
875
876 } else {
877 #define RMASK16 0xF000
878 #define GMASK16 0x0F00
879 #define BMASK16 0x00F0
880 #define AMASK16 0x000F
881 s16 = *(cursPtr16++);
882 alpha = s16 & AMASK16;
883 red = s16 & RMASK16;
884 red |= (red >> 4) | (red >> 8) | (red >> 12);
885 green = s16 & GMASK16;
886 green |= (green << 4) | (green >> 4) | (green >> 8);
887 blue = s16 & BMASK16;
888 blue |= (blue << 8) | (blue << 4) | (blue >> 4);
889 }
890
891 if( alpha == 0 ) {
892
893 if( 0 == (red | green | blue)) {
894 /* Transparent black area. Leave dst as is. */
895 if( kTransparentEncodedPixel
896 & hwDesc->supportedSpecialEncodings)
897 pixel = hwDesc->specialEncodings[kTransparentEncoding];
898 else
899 ok = false;
900 } else if (0xffff == (red & green & blue)) {
901 /* Transparent white area. Invert dst. */
902 if( kInvertingEncodedPixel
903 & hwDesc->supportedSpecialEncodings)
904 pixel = hwDesc->specialEncodings[kInvertingEncoding];
905 else
906 ok = false;
907 } else
908 ok = false;
909
910 } else if( alpha == 0xf ) {
911
912 /* Opaque cursor pixel. Mark it. */
913 for( index = 0; index < numColors; index++ ) {
914 if( (red == clut[ index ].red)
915 && (green == clut[ index ].green)
916 && (blue == clut[ index ].blue) ) {
917
918 pixel = clut[ index ].index;
919 break;
920 }
921 }
922 if( index == numColors) {
923 ok = (numColors < maxColors);
924 if( ok) {
925 pixel = hwDesc->colorEncodings[ numColors++ ];
926 clut[ index ].red = red;
927 clut[ index ].green = green;
928 clut[ index ].blue = blue;
929 clut[ index ].index = pixel;
930 }
931 }
932
933 } else {
934 /* Alpha is not 0 or 1.0. Sover the cursor. */
935 ok = false;
936 break;
937 }
938
939 data <<= hwDesc->bitDepth;
940 data |= pixel;
941
942 if( 0 == (x & ((8 / hwDesc->bitDepth) - 1)))
943 *dataOut++ = data;
944 } /* x */
945 } /* y */
946
947 // if( !ok) kprintf("Couldnt do a hw curs\n");
948
949 return( ok );
950 }
951
952 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
953
954 void IOFramebuffer::initialize()
955 {
956 #if 0
957 static IOWorkLoop * gIOFramebufferWorkloop;
958 static IOLock * gIOFramebufferLock;
959
960 gIOFramebufferLock = IOLockAlloc();
961
962 gIOFramebufferWorkloop = IOWorkLoop::workLoop();
963
964 assert( gIOFramebufferLock && gIOFramebufferWorkloop );
965 #endif
966 }
967
968
969 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
970
971 #if 0
972 static bool serializeInfoCB( void * target, void * ref, OSSerialize * s )
973 {
974 return( ((IOFramebuffer *)target)->serializeInfo(s) );
975 }
976 #endif
977
978 static IOPMrootDomain * gIOPMRootDomain;
979
980 bool IOFramebuffer::start( IOService * provider )
981 {
982
983 if( ! super::start( provider))
984 return( false );
985
986 userAccessRanges = OSArray::withCapacity( 1 );
987 engineAccessRanges = OSArray::withCapacity( 1 );
988
989 #if 0
990 OSSerializer * infoSerializer = OSSerializer::forTarget( (void *) this, &serializeInfoCB );
991 if( !infoSerializer)
992 return( false );
993
994 setProperty( kIOFramebufferInfoKey, infoSerializer );
995 infoSerializer->release();
996
997
998 IOInterruptEventSource * eventSrc;
999
1000 eventSrc = IOInterruptEventSource::interruptEventSource(
1001 this, autopollArrived);
1002 if (!eventSrc ||
1003 kIOReturnSuccess != workLoop->addEventSource(eventSrc) ) {
1004 kprintf("Start is bailing\n");
1005 return false;
1006 }
1007 #endif
1008
1009 closed = true;
1010 registerService();
1011
1012 // initialize superclass power management variables
1013 PMinit();
1014 // attach into the power management hierarchy
1015 provider->joinPMtree(this);
1016 // clamp power on (the user client will change that when appropriate)
1017 // makeUsable();
1018
1019 if( !gIOPMRootDomain)
1020 gIOPMRootDomain = (IOPMrootDomain *)
1021 IORegistryEntry::fromPath("/IOPowerConnection/IOPMrootDomain", gIOPowerPlane);
1022 if( gIOPMRootDomain)
1023 gIOPMRootDomain->registerInterestedDriver(this);
1024
1025 return( true );
1026 }
1027
1028 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1029
1030 // Apple standard 8-bit CLUT
1031
1032 UInt8 appleClut8[ 256 * 3 ] = {
1033 // 00
1034 0xFF,0xFF,0xFF, 0xFF,0xFF,0xCC, 0xFF,0xFF,0x99, 0xFF,0xFF,0x66,
1035 0xFF,0xFF,0x33, 0xFF,0xFF,0x00, 0xFF,0xCC,0xFF, 0xFF,0xCC,0xCC,
1036 0xFF,0xCC,0x99, 0xFF,0xCC,0x66, 0xFF,0xCC,0x33, 0xFF,0xCC,0x00,
1037 0xFF,0x99,0xFF, 0xFF,0x99,0xCC, 0xFF,0x99,0x99, 0xFF,0x99,0x66,
1038 // 10
1039 0xFF,0x99,0x33, 0xFF,0x99,0x00, 0xFF,0x66,0xFF, 0xFF,0x66,0xCC,
1040 0xFF,0x66,0x99, 0xFF,0x66,0x66, 0xFF,0x66,0x33, 0xFF,0x66,0x00,
1041 0xFF,0x33,0xFF, 0xFF,0x33,0xCC, 0xFF,0x33,0x99, 0xFF,0x33,0x66,
1042 0xFF,0x33,0x33, 0xFF,0x33,0x00, 0xFF,0x00,0xFF, 0xFF,0x00,0xCC,
1043 // 20
1044 0xFF,0x00,0x99, 0xFF,0x00,0x66, 0xFF,0x00,0x33, 0xFF,0x00,0x00,
1045 0xCC,0xFF,0xFF, 0xCC,0xFF,0xCC, 0xCC,0xFF,0x99, 0xCC,0xFF,0x66,
1046 0xCC,0xFF,0x33, 0xCC,0xFF,0x00, 0xCC,0xCC,0xFF, 0xCC,0xCC,0xCC,
1047 0xCC,0xCC,0x99, 0xCC,0xCC,0x66, 0xCC,0xCC,0x33, 0xCC,0xCC,0x00,
1048 // 30
1049 0xCC,0x99,0xFF, 0xCC,0x99,0xCC, 0xCC,0x99,0x99, 0xCC,0x99,0x66,
1050 0xCC,0x99,0x33, 0xCC,0x99,0x00, 0xCC,0x66,0xFF, 0xCC,0x66,0xCC,
1051 0xCC,0x66,0x99, 0xCC,0x66,0x66, 0xCC,0x66,0x33, 0xCC,0x66,0x00,
1052 0xCC,0x33,0xFF, 0xCC,0x33,0xCC, 0xCC,0x33,0x99, 0xCC,0x33,0x66,
1053 // 40
1054 0xCC,0x33,0x33, 0xCC,0x33,0x00, 0xCC,0x00,0xFF, 0xCC,0x00,0xCC,
1055 0xCC,0x00,0x99, 0xCC,0x00,0x66, 0xCC,0x00,0x33, 0xCC,0x00,0x00,
1056 0x99,0xFF,0xFF, 0x99,0xFF,0xCC, 0x99,0xFF,0x99, 0x99,0xFF,0x66,
1057 0x99,0xFF,0x33, 0x99,0xFF,0x00, 0x99,0xCC,0xFF, 0x99,0xCC,0xCC,
1058 // 50
1059 0x99,0xCC,0x99, 0x99,0xCC,0x66, 0x99,0xCC,0x33, 0x99,0xCC,0x00,
1060 0x99,0x99,0xFF, 0x99,0x99,0xCC, 0x99,0x99,0x99, 0x99,0x99,0x66,
1061 0x99,0x99,0x33, 0x99,0x99,0x00, 0x99,0x66,0xFF, 0x99,0x66,0xCC,
1062 0x99,0x66,0x99, 0x99,0x66,0x66, 0x99,0x66,0x33, 0x99,0x66,0x00,
1063 // 60
1064 0x99,0x33,0xFF, 0x99,0x33,0xCC, 0x99,0x33,0x99, 0x99,0x33,0x66,
1065 0x99,0x33,0x33, 0x99,0x33,0x00, 0x99,0x00,0xFF, 0x99,0x00,0xCC,
1066 0x99,0x00,0x99, 0x99,0x00,0x66, 0x99,0x00,0x33, 0x99,0x00,0x00,
1067 0x66,0xFF,0xFF, 0x66,0xFF,0xCC, 0x66,0xFF,0x99, 0x66,0xFF,0x66,
1068 // 70
1069 0x66,0xFF,0x33, 0x66,0xFF,0x00, 0x66,0xCC,0xFF, 0x66,0xCC,0xCC,
1070 0x66,0xCC,0x99, 0x66,0xCC,0x66, 0x66,0xCC,0x33, 0x66,0xCC,0x00,
1071 0x66,0x99,0xFF, 0x66,0x99,0xCC, 0x66,0x99,0x99, 0x66,0x99,0x66,
1072 0x66,0x99,0x33, 0x66,0x99,0x00, 0x66,0x66,0xFF, 0x66,0x66,0xCC,
1073 // 80
1074 0x66,0x66,0x99, 0x66,0x66,0x66, 0x66,0x66,0x33, 0x66,0x66,0x00,
1075 0x66,0x33,0xFF, 0x66,0x33,0xCC, 0x66,0x33,0x99, 0x66,0x33,0x66,
1076 0x66,0x33,0x33, 0x66,0x33,0x00, 0x66,0x00,0xFF, 0x66,0x00,0xCC,
1077 0x66,0x00,0x99, 0x66,0x00,0x66, 0x66,0x00,0x33, 0x66,0x00,0x00,
1078 // 90
1079 0x33,0xFF,0xFF, 0x33,0xFF,0xCC, 0x33,0xFF,0x99, 0x33,0xFF,0x66,
1080 0x33,0xFF,0x33, 0x33,0xFF,0x00, 0x33,0xCC,0xFF, 0x33,0xCC,0xCC,
1081 0x33,0xCC,0x99, 0x33,0xCC,0x66, 0x33,0xCC,0x33, 0x33,0xCC,0x00,
1082 0x33,0x99,0xFF, 0x33,0x99,0xCC, 0x33,0x99,0x99, 0x33,0x99,0x66,
1083 // a0
1084 0x33,0x99,0x33, 0x33,0x99,0x00, 0x33,0x66,0xFF, 0x33,0x66,0xCC,
1085 0x33,0x66,0x99, 0x33,0x66,0x66, 0x33,0x66,0x33, 0x33,0x66,0x00,
1086 0x33,0x33,0xFF, 0x33,0x33,0xCC, 0x33,0x33,0x99, 0x33,0x33,0x66,
1087 0x33,0x33,0x33, 0x33,0x33,0x00, 0x33,0x00,0xFF, 0x33,0x00,0xCC,
1088 // b0
1089 0x33,0x00,0x99, 0x33,0x00,0x66, 0x33,0x00,0x33, 0x33,0x00,0x00,
1090 0x00,0xFF,0xFF, 0x00,0xFF,0xCC, 0x00,0xFF,0x99, 0x00,0xFF,0x66,
1091 0x00,0xFF,0x33, 0x00,0xFF,0x00, 0x00,0xCC,0xFF, 0x00,0xCC,0xCC,
1092 0x00,0xCC,0x99, 0x00,0xCC,0x66, 0x00,0xCC,0x33, 0x00,0xCC,0x00,
1093 // c0
1094 0x00,0x99,0xFF, 0x00,0x99,0xCC, 0x00,0x99,0x99, 0x00,0x99,0x66,
1095 0x00,0x99,0x33, 0x00,0x99,0x00, 0x00,0x66,0xFF, 0x00,0x66,0xCC,
1096 0x00,0x66,0x99, 0x00,0x66,0x66, 0x00,0x66,0x33, 0x00,0x66,0x00,
1097 0x00,0x33,0xFF, 0x00,0x33,0xCC, 0x00,0x33,0x99, 0x00,0x33,0x66,
1098 // d0
1099 0x00,0x33,0x33, 0x00,0x33,0x00, 0x00,0x00,0xFF, 0x00,0x00,0xCC,
1100 0x00,0x00,0x99, 0x00,0x00,0x66, 0x00,0x00,0x33, 0xEE,0x00,0x00,
1101 0xDD,0x00,0x00, 0xBB,0x00,0x00, 0xAA,0x00,0x00, 0x88,0x00,0x00,
1102 0x77,0x00,0x00, 0x55,0x00,0x00, 0x44,0x00,0x00, 0x22,0x00,0x00,
1103 // e0
1104 0x11,0x00,0x00, 0x00,0xEE,0x00, 0x00,0xDD,0x00, 0x00,0xBB,0x00,
1105 0x00,0xAA,0x00, 0x00,0x88,0x00, 0x00,0x77,0x00, 0x00,0x55,0x00,
1106 0x00,0x44,0x00, 0x00,0x22,0x00, 0x00,0x11,0x00, 0x00,0x00,0xEE,
1107 0x00,0x00,0xDD, 0x00,0x00,0xBB, 0x00,0x00,0xAA, 0x00,0x00,0x88,
1108 // f0
1109 0x00,0x00,0x77, 0x00,0x00,0x55, 0x00,0x00,0x44, 0x00,0x00,0x22,
1110 0x00,0x00,0x11, 0xEE,0xEE,0xEE, 0xDD,0xDD,0xDD, 0xBB,0xBB,0xBB,
1111 0xAA,0xAA,0xAA, 0x88,0x88,0x88, 0x77,0x77,0x77, 0x55,0x55,0x55,
1112 0x44,0x44,0x44, 0x22,0x22,0x22, 0x11,0x11,0x11, 0x00,0x00,0x00
1113 };
1114
1115
1116 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1117
1118 #ifdef __ppc__
1119 extern
1120 #endif
1121 int killprint;
1122 extern "C" { int kmputc( int c ); }
1123
1124 IOReturn IOFramebuffer::setPowerState( unsigned long powerStateOrdinal,
1125 IOService * whichDevice )
1126 {
1127 if( 0 == powerStateOrdinal ) {
1128 if( isConsoleDevice())
1129 killprint = 1;
1130 deliverFramebufferNotification( kIOFBNotifyWillSleep );
1131
1132 } else {
1133
1134 if( isConsoleDevice()) {
1135 killprint = 0;
1136 kmputc( 033 );
1137 kmputc( 'c' );
1138 }
1139 deliverFramebufferNotification( kIOFBNotifyDidWake );
1140 }
1141
1142 return( IOPMAckImplied);
1143 }
1144
1145 IOReturn IOFramebuffer::beginSystemSleep( void * ackRef )
1146 {
1147 pmRef = ackRef;
1148 powerOverrideOnPriv();
1149 changePowerStateToPriv(0);
1150
1151 return( kIOReturnSuccess );
1152 }
1153
1154 IOReturn IOFramebuffer::powerStateWillChangeTo( IOPMPowerFlags flags,
1155 unsigned long, IOService * whatDevice )
1156 {
1157 if( (whatDevice == gIOPMRootDomain) && (IOPMPowerOn & flags))
1158 // end system sleep
1159 powerOverrideOffPriv();
1160
1161 return( IOPMAckImplied );
1162 }
1163
1164 IOReturn IOFramebuffer::powerStateDidChangeTo( IOPMPowerFlags flags,
1165 unsigned long, IOService* whatDevice )
1166 {
1167 if( (whatDevice == this) && pmRef && (0 == (IOPMDeviceUsable & flags))) {
1168 // root can proceed
1169 acknowledgeSleepWakeNotification(pmRef);
1170 pmRef = 0;
1171 }
1172
1173 return( IOPMAckImplied );
1174 }
1175
1176 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1177
1178 IODeviceMemory * IOFramebuffer::getVRAMRange( void )
1179 {
1180 return( getApertureRange( kIOFBSystemAperture ));
1181 }
1182
1183 void IOFramebuffer::close( void ) // called by the user client when
1184 { // the window server exits
1185
1186 }
1187
1188
1189
1190 IOReturn IOFramebuffer::open( void )
1191 {
1192 IOReturn err = kIOReturnSuccess;
1193 UInt32 value;
1194
1195 do {
1196 if( opened)
1197 continue;
1198
1199 // tell the console if it's on this display, it's going away
1200 if( isConsoleDevice())
1201 getPlatform()->setConsoleInfo( 0, kPEDisableScreen);
1202
1203 deliverFramebufferNotification( kIOFBNotifyDisplayModeWillChange );
1204
1205 err = enableController();
1206 if( kIOReturnSuccess != err) {
1207 deliverFramebufferNotification( kIOFBNotifyDisplayModeDidChange );
1208 continue;
1209 }
1210 err = registerForInterruptType( kIOFBVBLInterruptType,
1211 (IOFBInterruptProc) &handleVBL,
1212 this, priv, &vblInterrupt );
1213 haveVBLService = (err == kIOReturnSuccess );
1214
1215 err = getAttribute( kIOHardwareCursorAttribute, &value );
1216 haveHWCursor = ((err == kIOReturnSuccess) && value);
1217
1218 err = kIOReturnSuccess;
1219 opened = true;
1220
1221 } while( false );
1222
1223 return( err );
1224 }
1225
1226 IOReturn IOFramebuffer::setUserRanges( void )
1227 {
1228 #if 1 /* print ranges */
1229
1230 UInt32 i, numRanges;
1231 IODeviceMemory * mem;
1232
1233 numRanges = userAccessRanges->getCount();
1234 IOLog("%s: user ranges num:%ld", getName(), numRanges);
1235 for( i = 0; i < numRanges; i++) {
1236 mem = (IODeviceMemory *) userAccessRanges->getObject( i );
1237 if( 0 == mem)
1238 continue;
1239 IOLog(" start:%lx size:%lx",
1240 mem->getPhysicalAddress(), mem->getLength() );
1241 }
1242 IOLog("\n");
1243
1244 #endif
1245 return( kIOReturnSuccess);
1246 }
1247
1248 IOReturn IOFramebuffer::setupForCurrentConfig( void )
1249 {
1250 return( doSetup( true ));
1251 }
1252
1253 IOReturn IOFramebuffer::doSetup( bool full )
1254 {
1255 IOReturn err;
1256 IODisplayModeID mode;
1257 IOIndex depth;
1258 IOPixelInformation info;
1259 IODisplayModeInformation dmInfo;
1260 IODeviceMemory * mem;
1261 IODeviceMemory * fbRange;
1262 IOPhysicalAddress base;
1263 PE_Video newConsole;
1264
1265 err = getCurrentDisplayMode( &mode, &depth );
1266 if( err)
1267 IOLog("%s: getCurrentDisplayMode %d\n", getName(), err);
1268
1269 err = getPixelInformation( mode, depth, kIOFBSystemAperture, &info );
1270 if( err)
1271 IOLog("%s: getPixelInformation %d\n", getName(), err);
1272
1273 if( full && (clutValid == false) && (info.pixelType == kIOCLUTPixels)) {
1274
1275 IOColorEntry * tempTable;
1276 int i;
1277
1278 tempTable = (IOColorEntry *) IOMalloc( 256 * sizeof( *tempTable));
1279 if( tempTable) {
1280
1281 for( i = 0; i < 256; i++) {
1282 if( currentMono) {
1283 UInt32 lum;
1284
1285 lum = 0x0101 * i;
1286 tempTable[ i ].red = lum;
1287 tempTable[ i ].green = lum;
1288 tempTable[ i ].blue = lum;
1289 } else {
1290 tempTable[ i ].red = (appleClut8[ i * 3 + 0 ] << 8)
1291 | appleClut8[ i * 3 + 0 ];
1292 tempTable[ i ].green = (appleClut8[ i * 3 + 1 ] << 8)
1293 | appleClut8[ i * 3 + 1 ];
1294 tempTable[ i ].blue = (appleClut8[ i * 3 + 2 ] << 8)
1295 | appleClut8[ i * 3 + 2 ];
1296 }
1297 }
1298 setCLUTWithEntries( tempTable, 0, 256, 1 * kSetCLUTImmediately );
1299 IOFree( tempTable, 256 * sizeof( *tempTable));
1300 }
1301 clutValid = true;
1302 }
1303
1304 fbRange = getApertureRange( kIOFBSystemAperture );
1305
1306 if( full && fbRange) {
1307
1308 userAccessRanges->removeObject( kIOFBSystemAperture );
1309 userAccessRanges->setObject( kIOFBSystemAperture, fbRange );
1310 err = setUserRanges();
1311
1312 base = fbRange->getPhysicalAddress();
1313 if( (mem = getVRAMRange())) {
1314 vramMapOffset = base - mem->getPhysicalAddress();
1315 mem->release();
1316 }
1317
1318 if( vramMap)
1319 vramMap->release();
1320 vramMap = fbRange->map();
1321 assert( vramMap );
1322 if( vramMap)
1323 base = vramMap->getVirtualAddress();
1324
1325 // console now available
1326 if( info.activeWidth >= 128) {
1327 newConsole.v_baseAddr = base;
1328 newConsole.v_rowBytes = info.bytesPerRow;
1329 newConsole.v_width = info.activeWidth;
1330 newConsole.v_height = info.activeHeight;
1331 newConsole.v_depth = info.bitsPerPixel;
1332 // strcpy( consoleInfo->v_pixelFormat, "PPPPPPPP");
1333 getPlatform()->setConsoleInfo( &newConsole, kPEEnableScreen );
1334 }
1335
1336 deliverFramebufferNotification( kIOFBNotifyDisplayModeDidChange, 0 );
1337
1338 (void) getInformationForDisplayMode( mode, &dmInfo );
1339 IOLog( "%s: using (%ldx%ld@%ldHz,%ld bpp)\n", getName(),
1340 info.activeWidth, info.activeHeight,
1341 (dmInfo.refreshRate + 0x8000) >> 16, info.bitsPerPixel );
1342 }
1343
1344 if( fbRange)
1345 fbRange->release();
1346 if( vramMap)
1347 setupCursor( &info );
1348
1349 return( kIOReturnSuccess );
1350 }
1351
1352 IOReturn IOFramebuffer::extSetDisplayMode( IODisplayModeID displayMode,
1353 IOIndex depth )
1354 {
1355 IOReturn err;
1356
1357 stopCursor();
1358
1359 if( isConsoleDevice())
1360 getPlatform()->setConsoleInfo( 0, kPEDisableScreen);
1361
1362 deliverFramebufferNotification( kIOFBNotifyDisplayModeWillChange );
1363
1364 err = setDisplayMode( displayMode, depth );
1365
1366 clutValid = false;
1367
1368 setupForCurrentConfig();
1369
1370 return( err );
1371 }
1372
1373 IOReturn IOFramebuffer::extGetInformationForDisplayMode(
1374 IODisplayModeID mode, IODisplayModeInformation * info )
1375 {
1376 UInt32 flags = 0;
1377 IOReturn err;
1378 IOTimingInformation timingInfo;
1379
1380 err = getInformationForDisplayMode( mode, info );
1381 if( kIOReturnSuccess == err) {
1382 err = IODisplayWrangler::getFlagsForDisplayMode( this, mode, &flags);
1383 if( kIOReturnSuccess == err) {
1384 info->flags &= ~kDisplayModeSafetyFlags;
1385 info->flags |= flags;
1386 }
1387 if( kIOReturnSuccess == getTimingInfoForDisplayMode( mode, &timingInfo ))
1388 info->reserved[0] = timingInfo.appleTimingID;
1389
1390 }
1391
1392 return( err );
1393 }
1394
1395 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1396
1397 bool IOFramebuffer::setNumber( OSDictionary * dict, const char * key,
1398 UInt32 value )
1399 {
1400 OSNumber * num;
1401 bool ok;
1402
1403 num = OSNumber::withNumber( value, 32 );
1404 if( !num)
1405 return( false );
1406
1407 ok = dict->setObject( key, num );
1408 num->release();
1409
1410 return( ok );
1411 }
1412
1413 bool IOFramebuffer::serializeInfo( OSSerialize * s )
1414 {
1415 IOReturn err;
1416 IODisplayModeInformation info;
1417 IOPixelInformation pixelInfo;
1418 IODisplayModeID * modeIDs;
1419 IOItemCount modeCount, modeNum, aperture;
1420 IOIndex depthNum;
1421 OSDictionary * infoDict;
1422 OSDictionary * modeDict;
1423 OSDictionary * pixelDict;
1424 char keyBuf[12];
1425 bool ok = true;
1426
1427 modeCount = getDisplayModeCount();
1428 modeIDs = IONew( IODisplayModeID, modeCount );
1429 if( !modeIDs)
1430 return( false );
1431
1432 err = getDisplayModes( modeIDs );
1433 if( err)
1434 return( false );
1435
1436 infoDict = OSDictionary::withCapacity( 10 );
1437 if( !infoDict)
1438 return( false );
1439
1440 for( modeNum = 0; modeNum < modeCount; modeNum++ ) {
1441
1442 err = getInformationForDisplayMode( modeIDs[ modeNum ], &info );
1443 if( err)
1444 continue;
1445
1446 modeDict = OSDictionary::withCapacity( 10 );
1447 if( !modeDict)
1448 break;
1449
1450 ok = setNumber( modeDict, kIOFBWidthKey,
1451 info.nominalWidth )
1452 && setNumber( modeDict, kIOFBHeightKey,
1453 info.nominalHeight )
1454 && setNumber( modeDict, kIOFBRefreshRateKey,
1455 info.refreshRate )
1456 && setNumber( modeDict, kIOFBFlagsKey,
1457 info.flags );
1458 if( !ok)
1459 break;
1460
1461 for( depthNum = 0; depthNum < info.maxDepthIndex; depthNum++ ) {
1462
1463 for( aperture = 0; ; aperture++ ) {
1464
1465 err = getPixelInformation( modeIDs[ modeNum ], depthNum,
1466 aperture, &pixelInfo );
1467 if( err)
1468 break;
1469
1470 pixelDict = OSDictionary::withCapacity( 10 );
1471 if( !pixelDict)
1472 continue;
1473
1474 ok = setNumber( pixelDict, kIOFBBytesPerRowKey,
1475 pixelInfo.bytesPerRow )
1476 && setNumber( pixelDict, kIOFBBytesPerPlaneKey,
1477 pixelInfo.bytesPerPlane )
1478 && setNumber( pixelDict, kIOFBBitsPerPixelKey,
1479 pixelInfo.bitsPerPixel )
1480 && setNumber( pixelDict, kIOFBComponentCountKey,
1481 pixelInfo.componentCount )
1482 && setNumber( pixelDict, kIOFBBitsPerComponentKey,
1483 pixelInfo.bitsPerComponent )
1484 && setNumber( pixelDict, kIOFBFlagsKey,
1485 pixelInfo.flags )
1486 && setNumber( pixelDict, kIOFBWidthKey,
1487 pixelInfo.activeWidth )
1488 && setNumber( pixelDict, kIOFBHeightKey,
1489 pixelInfo.activeHeight );
1490 if( !ok)
1491 break;
1492
1493 sprintf( keyBuf, "%lx", depthNum + (aperture << 16) );
1494 modeDict->setObject( keyBuf, pixelDict );
1495 pixelDict->release();
1496 }
1497 }
1498
1499 sprintf( keyBuf, "%lx", modeIDs[ modeNum ] );
1500 infoDict->setObject( keyBuf, modeDict );
1501 modeDict->release();
1502 }
1503
1504 IODelete( modeIDs, IODisplayModeID, modeCount );
1505
1506 ok &= infoDict->serialize( s );
1507 infoDict->release();
1508
1509 return( ok );
1510 }
1511
1512 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1513
1514 OSDefineMetaClassAndStructors(_IOFramebufferNotifier, IONotifier)
1515 #define LOCKNOTIFY()
1516 #define UNLOCKNOTIFY()
1517
1518 void _IOFramebufferNotifier::remove()
1519 {
1520 LOCKNOTIFY();
1521
1522 if( whence) {
1523 whence->removeObject( (OSObject *) this );
1524 whence = 0;
1525 }
1526
1527 fEnable = false;
1528
1529 UNLOCKNOTIFY();
1530
1531 release();
1532 }
1533
1534 bool _IOFramebufferNotifier::disable()
1535 {
1536 bool ret;
1537
1538 LOCKNOTIFY();
1539 ret = fEnable;
1540 fEnable = false;
1541 UNLOCKNOTIFY();
1542
1543 return( ret );
1544 }
1545
1546 void _IOFramebufferNotifier::enable( bool was )
1547 {
1548 LOCKNOTIFY();
1549 fEnable = was;
1550 UNLOCKNOTIFY();
1551 }
1552
1553 IONotifier * IOFramebuffer::addFramebufferNotification(
1554 IOFramebufferNotificationHandler handler,
1555 OSObject * self, void * ref)
1556 {
1557 _IOFramebufferNotifier * notify = 0;
1558
1559 notify = new _IOFramebufferNotifier;
1560 if( notify && !notify->init()) {
1561 notify->release();
1562 notify = 0;
1563 }
1564
1565 if( notify) {
1566 notify->handler = handler;
1567 notify->self = self;
1568 notify->ref = ref;
1569 notify->fEnable = true;
1570
1571 if( 0 == fbNotifications)
1572 fbNotifications = OSSet::withCapacity(1);
1573
1574 notify->whence = fbNotifications;
1575 if( fbNotifications)
1576 fbNotifications->setObject( notify );
1577 }
1578
1579 return( notify );
1580 }
1581
1582 IOReturn IOFramebuffer::deliverFramebufferNotification(
1583 IOIndex event, void * info = 0 )
1584 {
1585 OSIterator * iter;
1586 _IOFramebufferNotifier * notify;
1587 IOReturn ret = kIOReturnSuccess;
1588 IOReturn r;
1589
1590 LOCKNOTIFY();
1591
1592 iter = OSCollectionIterator::withCollection( fbNotifications );
1593
1594 if( iter) {
1595 while( (notify = (_IOFramebufferNotifier *) iter->getNextObject())) {
1596
1597 if( notify->fEnable) {
1598 r = (*notify->handler)( notify->self, notify->ref, this,
1599 event, info );
1600 if( kIOReturnSuccess != ret)
1601 ret = r;
1602 }
1603 }
1604 iter->release();
1605 }
1606
1607 UNLOCKNOTIFY();
1608
1609 return( ret );
1610 }
1611
1612 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1613
1614 // Some stubs
1615
1616 IOReturn IOFramebuffer::enableController ( void )
1617 {
1618 return( kIOReturnSuccess );
1619 }
1620
1621 bool IOFramebuffer::isConsoleDevice( void )
1622 {
1623 return( false );
1624 }
1625
1626 // Set display mode and depth
1627 IOReturn IOFramebuffer::setDisplayMode( IODisplayModeID /* displayMode */,
1628 IOIndex /* depth */ )
1629 {
1630 return( kIOReturnUnsupported);
1631 }
1632
1633 // For pages
1634 IOReturn IOFramebuffer::setApertureEnable(
1635 IOPixelAperture /* aperture */, IOOptionBits /* enable */ )
1636 {
1637 return( kIOReturnUnsupported);
1638 }
1639
1640 // Display mode and depth for startup
1641 IOReturn IOFramebuffer::setStartupDisplayMode(
1642 IODisplayModeID /* displayMode */, IOIndex /* depth */ )
1643 {
1644 return( kIOReturnUnsupported);
1645 }
1646
1647 IOReturn IOFramebuffer::getStartupDisplayMode(
1648 IODisplayModeID * /* displayMode */, IOIndex * /* depth */ )
1649 {
1650 return( kIOReturnUnsupported);
1651 }
1652
1653 //// CLUTs
1654
1655 IOReturn IOFramebuffer::setCLUTWithEntries(
1656 IOColorEntry * /* colors */, UInt32 /* index */,
1657 UInt32 /* numEntries */, IOOptionBits /* options */ )
1658 {
1659 return( kIOReturnUnsupported);
1660 }
1661
1662 //// Gamma
1663
1664 IOReturn IOFramebuffer::setGammaTable( UInt32 /* channelCount */,
1665 UInt32 /* dataCount */, UInt32 /* dataWidth */, void * /* data */ )
1666 {
1667 return( kIOReturnUnsupported);
1668 }
1669
1670 //// Controller attributes
1671
1672 IOReturn IOFramebuffer::setAttribute( IOSelect /* attribute */, UInt32 /* value */ )
1673 {
1674 return( kIOReturnUnsupported);
1675 }
1676
1677 IOReturn IOFramebuffer::getAttribute( IOSelect /* attribute */,
1678 UInt32 * /* value */ )
1679 {
1680 return( kIOReturnUnsupported);
1681 }
1682
1683 //// Display mode timing information
1684
1685 IOReturn IOFramebuffer::getTimingInfoForDisplayMode(
1686 IODisplayModeID /* displayMode */,
1687 IOTimingInformation * /* info */ )
1688 {
1689 return( kIOReturnUnsupported);
1690 }
1691
1692 IOReturn IOFramebuffer::validateDetailedTiming(
1693 void * description, IOByteCount descripSize )
1694 {
1695 return( kIOReturnUnsupported);
1696 }
1697
1698 IOReturn IOFramebuffer::setDetailedTimings( OSArray * array )
1699 {
1700 return( kIOReturnUnsupported);
1701 }
1702
1703 //// Connections
1704
1705 IOItemCount IOFramebuffer::getConnectionCount( void )
1706 {
1707 return( 1);
1708 }
1709
1710 IOReturn IOFramebuffer::setAttributeForConnection( IOIndex /* connectIndex */,
1711 IOSelect /* attribute */, UInt32 /* value */ )
1712 {
1713 return( kIOReturnUnsupported);
1714 }
1715
1716 IOReturn IOFramebuffer::getAttributeForConnection( IOIndex /* connectIndex */,
1717 IOSelect /* attribute */, UInt32 * /* value */ )
1718 {
1719 return( kIOReturnUnsupported);
1720 }
1721
1722 //// HW Cursors
1723
1724 IOReturn IOFramebuffer::setCursorImage( void * cursorImage )
1725 {
1726 return( kIOReturnUnsupported);
1727 }
1728
1729 IOReturn IOFramebuffer::setCursorState( SInt32 x, SInt32 y, bool visible )
1730 {
1731 return( kIOReturnUnsupported);
1732 }
1733
1734 void IOFramebuffer::flushCursor( void )
1735 {
1736 }
1737
1738 //// Interrupts
1739
1740 IOReturn IOFramebuffer::registerForInterruptType( IOSelect interruptType,
1741 IOFBInterruptProc proc, OSObject * target, void * ref,
1742 void ** interruptRef )
1743 {
1744 return( kIOReturnUnsupported);
1745 }
1746
1747 IOReturn IOFramebuffer::unregisterInterrupt( void * interruptRef )
1748 {
1749 return( kIOReturnUnsupported);
1750 }
1751
1752 IOReturn IOFramebuffer::setInterruptState( void * interruptRef, UInt32 state )
1753 {
1754 return( kIOReturnUnsupported);
1755 }
1756
1757 // Apple sensing
1758
1759 IOReturn IOFramebuffer::getAppleSense(
1760 IOIndex /* connectIndex */,
1761 UInt32 * /* senseType */,
1762 UInt32 * /* primary */,
1763 UInt32 * /* extended */,
1764 UInt32 * /* displayType */ )
1765 {
1766 return( kIOReturnUnsupported);
1767 }
1768
1769 IOReturn IOFramebuffer::connectFlags( IOIndex /* connectIndex */,
1770 IODisplayModeID /* displayMode */, IOOptionBits * /* flags */ )
1771 {
1772 return( kIOReturnUnsupported);
1773 }
1774
1775 //// IOLowLevelDDCSense
1776
1777 void IOFramebuffer::setDDCClock( IOIndex /* connectIndex */, UInt32 /* value */ )
1778 {
1779 }
1780
1781 void IOFramebuffer::setDDCData( IOIndex /* connectIndex */, UInt32 /* value */ )
1782 {
1783 }
1784
1785 bool IOFramebuffer::readDDCClock( IOIndex /* connectIndex */ )
1786 {
1787 return( false);
1788 }
1789
1790 bool IOFramebuffer::readDDCData( IOIndex /* connectIndex */ )
1791 {
1792 return( false);
1793 }
1794
1795 IOReturn IOFramebuffer::enableDDCRaster( bool /* enable */ )
1796 {
1797 return( kIOReturnUnsupported);
1798 }
1799
1800
1801 //// IOHighLevelDDCSense
1802
1803 bool IOFramebuffer::hasDDCConnect( IOIndex /* connectIndex */ )
1804 {
1805 return( kIOReturnUnsupported);
1806 }
1807
1808 IOReturn IOFramebuffer::getDDCBlock( IOIndex /* connectIndex */, UInt32 /* blockNumber */,
1809 IOSelect /* blockType */, IOOptionBits /* options */,
1810 UInt8 * /* data */, IOByteCount * /* length */ )
1811 {
1812 return( kIOReturnUnsupported);
1813 }
1814
1815 OSMetaClassDefineReservedUnused(IOFramebuffer, 0);
1816 OSMetaClassDefineReservedUnused(IOFramebuffer, 1);
1817 OSMetaClassDefineReservedUnused(IOFramebuffer, 2);
1818 OSMetaClassDefineReservedUnused(IOFramebuffer, 3);
1819 OSMetaClassDefineReservedUnused(IOFramebuffer, 4);
1820 OSMetaClassDefineReservedUnused(IOFramebuffer, 5);
1821 OSMetaClassDefineReservedUnused(IOFramebuffer, 6);
1822 OSMetaClassDefineReservedUnused(IOFramebuffer, 7);
1823 OSMetaClassDefineReservedUnused(IOFramebuffer, 8);
1824 OSMetaClassDefineReservedUnused(IOFramebuffer, 9);
1825 OSMetaClassDefineReservedUnused(IOFramebuffer, 10);
1826 OSMetaClassDefineReservedUnused(IOFramebuffer, 11);
1827 OSMetaClassDefineReservedUnused(IOFramebuffer, 12);
1828 OSMetaClassDefineReservedUnused(IOFramebuffer, 13);
1829 OSMetaClassDefineReservedUnused(IOFramebuffer, 14);
1830 OSMetaClassDefineReservedUnused(IOFramebuffer, 15);
1831 OSMetaClassDefineReservedUnused(IOFramebuffer, 16);
1832 OSMetaClassDefineReservedUnused(IOFramebuffer, 17);
1833 OSMetaClassDefineReservedUnused(IOFramebuffer, 18);
1834 OSMetaClassDefineReservedUnused(IOFramebuffer, 19);
1835 OSMetaClassDefineReservedUnused(IOFramebuffer, 20);
1836 OSMetaClassDefineReservedUnused(IOFramebuffer, 21);
1837 OSMetaClassDefineReservedUnused(IOFramebuffer, 22);
1838 OSMetaClassDefineReservedUnused(IOFramebuffer, 23);
1839 OSMetaClassDefineReservedUnused(IOFramebuffer, 24);
1840 OSMetaClassDefineReservedUnused(IOFramebuffer, 25);
1841 OSMetaClassDefineReservedUnused(IOFramebuffer, 26);
1842 OSMetaClassDefineReservedUnused(IOFramebuffer, 27);
1843 OSMetaClassDefineReservedUnused(IOFramebuffer, 28);
1844 OSMetaClassDefineReservedUnused(IOFramebuffer, 29);
1845 OSMetaClassDefineReservedUnused(IOFramebuffer, 30);
1846 OSMetaClassDefineReservedUnused(IOFramebuffer, 31);
1847