]> git.saurik.com Git - apple/xnu.git/blame - iokit/Families/IOGraphics/IOFramebufferUserClient.cpp
xnu-123.5.tar.gz
[apple/xnu.git] / iokit / Families / IOGraphics / IOFramebufferUserClient.cpp
CommitLineData
1c79356b
A
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 * 14 Aug 98 sdouglas created.
28 * 08 Dec 98 sdouglas cpp.
29 */
30
31#define IOFRAMEBUFFER_PRIVATE
32#include <IOKit/graphics/IOFramebufferShared.h>
33#include <IOKit/pwr_mgt/RootDomain.h>
34#include <IOKit/IOLib.h>
35#include <IOKit/IOMessage.h>
36#include <libkern/c++/OSContainers.h>
37#include <IOKit/IOBufferMemoryDescriptor.h>
38
39#include <IOKit/IOPlatformExpert.h>
40
41#include <IOKit/assert.h>
42
43#include "IOFramebufferUserClient.h"
44
45#include <IOKit/graphics/IOGraphicsEngine.h>
46
47
48/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
49
50#undef super
51#define super IOUserClient
52
53OSDefineMetaClassAndStructors(IOFramebufferUserClient, IOUserClient)
54
55/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
56
57static IOReturn myHandler(void *, void * , UInt32, IOService *, void *, unsigned int);
58static IOLock * gSleepFramebuffersLock;
59static OSOrderedSet * gSleepFramebuffers;
60static UInt32 gWakeCount;
61
62/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
63
64IOFramebufferUserClient * IOFramebufferUserClient::withTask( task_t owningTask )
65{
66 IOFramebufferUserClient * inst;
67
68 if( 0 == gSleepFramebuffersLock) {
69 gSleepFramebuffersLock = IOLockAlloc();
70 gSleepFramebuffers = OSOrderedSet::withCapacity(6);
71 assert( gSleepFramebuffersLock && gSleepFramebuffers );
72 }
73
74 inst = new IOFramebufferUserClient;
75
76 if( inst && !inst->init()) {
77 inst->release();
78 inst = 0;
79 }
80
81 return( inst );
82}
83
84bool IOFramebufferUserClient::start( IOService * _owner )
85{
86 static const IOExternalMethod methodTemplate[] = {
87/* 0 */ { NULL, NULL, kIOUCScalarIScalarO, 3, 0 },
88/* 1 */ { NULL, NULL, kIOUCScalarIStructO, 3, sizeof( IOPixelInformation) },
89/* 2 */ { NULL, NULL, kIOUCScalarIScalarO, 0, 2 },
90/* 3 */ { NULL, NULL, kIOUCScalarIScalarO, 2, 0 },
91/* 4 */ { NULL, NULL, kIOUCScalarIScalarO, 2, 0 },
92/* 5 */ { NULL, NULL, kIOUCScalarIStructO,
93 1, sizeof( IODisplayModeInformation) },
94/* 6 */ { NULL, NULL, kIOUCScalarIScalarO, 0, 1 },
95/* 7 */ { NULL, NULL, kIOUCStructIStructO, 0, 0xffffffff },
96/* 8 */ { NULL, NULL, kIOUCScalarIScalarO, 1, 1 },
97/* 9 */ { NULL, NULL, kIOUCStructIStructO, sizeof( Bounds), 0 },
98/* 10 */ { NULL, NULL, kIOUCScalarIScalarO, 3, 0 },
99/* 11 */ { NULL, NULL, kIOUCScalarIStructI, 3, 0xffffffff },
100/* 12 */ { NULL, NULL, kIOUCScalarIScalarO, 1, 0 },
101/* 13 */ { NULL, NULL, kIOUCScalarIScalarO, 2, 0 },
102/* 14 */ { NULL, NULL, kIOUCScalarIScalarO, 0, 0 },
103/* 15 */ { NULL, NULL, kIOUCScalarIStructI, 1, 0xffffffff },
104/* 16 */ { NULL, NULL, kIOUCScalarIStructI, 2, 0xffffffff },
105/* 17 */ { NULL, NULL, kIOUCStructIStructO, 0xffffffff, 0xffffffff },
106
107 };
108
109 if( !super::start( _owner ))
110 return( false);
111
112 owner = (IOFramebuffer *) _owner;
113
114 assert( sizeof( methodTemplate) == sizeof( externals));
115 bcopy( methodTemplate, externals, sizeof( externals ));
116
117 externals[0].object = owner;
118 externals[0].func = (IOMethod) &IOFramebuffer::createSharedCursor;
119
120 externals[1].object = owner;
121 externals[1].func = (IOMethod) &IOFramebuffer::getPixelInformation;
122
123 externals[2].object = owner;
124 externals[2].func = (IOMethod) &IOFramebuffer::getCurrentDisplayMode;
125
126 externals[3].object = owner;
127 externals[3].func = (IOMethod) &IOFramebuffer::setStartupDisplayMode;
128
129 externals[4].object = owner;
130 externals[4].func = (IOMethod) &IOFramebuffer::extSetDisplayMode;
131
132 externals[5].object = owner;
133 externals[5].func =
134 (IOMethod) &IOFramebuffer::extGetInformationForDisplayMode;
135
136 externals[6].object = owner;
137 externals[6].func = (IOMethod) &IOFramebuffer::extGetDisplayModeCount;
138
139 externals[7].object = owner;
140 externals[7].func = (IOMethod) &IOFramebuffer::extGetDisplayModes;
141
142 externals[8].object = owner;
143 externals[8].func = (IOMethod) &IOFramebuffer::extGetVRAMMapOffset;
144
145 externals[9].object = owner;
146 externals[9].func = (IOMethod) &IOFramebuffer::extSetBounds;
147
148 externals[10].object = owner;
149 externals[10].func = (IOMethod) &IOFramebuffer::extSetNewCursor;
150
151 externals[11].object = owner;
152 externals[11].func = (IOMethod) &IOFramebuffer::setGammaTable;
153
154 externals[12].object = owner;
155 externals[12].func = (IOMethod) &IOFramebuffer::extSetCursorVisible;
156
157 externals[13].object = owner;
158 externals[13].func = (IOMethod) &IOFramebuffer::extSetCursorPosition;
159
160 externals[14].object = this;
161 externals[14].func = (IOMethod) &IOFramebufferUserClient::acknowledgeNotification;
162
163 externals[15].object = owner;
164 externals[15].func = (IOMethod) &IOFramebuffer::extSetColorConvertTable;
165
166 externals[16].object = owner;
167 externals[16].func = (IOMethod) &IOFramebuffer::extSetCLUTWithEntries;
168
169 externals[17].object = owner;
170 externals[17].func = (IOMethod) &IOFramebuffer::extValidateDetailedTiming;
171
172
173 ackFrameBuffer = false;
174 ackRoot = false;
175
176 owner->serverConnect = this;
177
178 // register interest in sleep and wake
179 powerRootNotifier = registerSleepWakeInterest(myHandler, (void *) this);
180 // register interest in frame buffer
181 frameBufferNotifier = owner->registerInterest( gIOGeneralInterest, myHandler, this, 0 );
182 return( true );
183}
184
185
186IOReturn
187IOFramebufferUserClient::acknowledgeNotification( void )
188{
189 if( ackFrameBuffer ) {
190 ackFrameBuffer = false;
191 owner->allowPowerChange((unsigned long)PMrefcon);
192 }
193 if( ackRoot ) {
194 ackRoot = false;
195 owner->beginSystemSleep(PMrefcon);
196 }
197
198 return IOPMNoErr;
199}
200
201
202// We have registered for notification of power state changes in the framebuffer and the system in general.
203// We are notified here of such a change. "System" power changes refer to sleep/wake and power down/up.
204// "Device" changes refer to the framebuffer.
205
206static IOReturn
207myHandler(void * us, void *, UInt32 messageType, IOService *, void * params, unsigned int)
208{
209 kern_return_t r;
210 mach_msg_header_t *msgh;
211 IOFramebufferUserClient * self = (IOFramebufferUserClient *)us;
212
213 switch (messageType) {
214 case kIOMessageSystemWillSleep:
215 if ( !(self->WSKnowsWeAreOff) ) {
216 msgh = (mach_msg_header_t *)(self->notificationMsg);
217 if( msgh && (self->WSnotificationPort) ) {
218 msgh->msgh_id = 0;
219 self->WSKnowsWeAreOff = true;
220 self->ackRoot = true;
221 r = mach_msg_send_from_kernel( msgh, msgh->msgh_size);
222 if( KERN_SUCCESS == r) {
223 // WS will ack within ten seconds
224 ((sleepWakeNote *)params)->returnValue = 10000000;
225 self->PMrefcon = ((sleepWakeNote *)params)->powerRef;
226 IOLockLock( gSleepFramebuffersLock );
227 gSleepFramebuffers->setObject(self);
228 IOLockUnlock( gSleepFramebuffersLock );
229 return kIOReturnSuccess;
230 }
231 }
232 }
233 self->ackRoot = false;
234 ((sleepWakeNote *)params)->returnValue = 0;
235 return kIOReturnSuccess;
236
237 case kIOMessageDeviceWillPowerOff:
238 if ( !self->WSKnowsWeAreOff ) {
239 msgh = (mach_msg_header_t *)(self->notificationMsg);
240 if( msgh && (self->WSnotificationPort) ) {
241 msgh->msgh_id = 0;
242 self->WSKnowsWeAreOff = true;
243 self->ackFrameBuffer = true;
244 r = mach_msg_send_from_kernel( msgh, msgh->msgh_size);
245 if( KERN_SUCCESS == r) {
246 // WS will ack within ten seconds
247 ((sleepWakeNote *)params)->returnValue = 10000000;
248 self->PMrefcon = ((sleepWakeNote *)params)->powerRef;
249 IOLockLock( gSleepFramebuffersLock );
250 gSleepFramebuffers->setObject(self);
251 IOLockUnlock( gSleepFramebuffersLock );
252 return kIOReturnSuccess;
253 }
254 }
255 }
256 ((sleepWakeNote *)params)->returnValue = 0;
257 self->ackFrameBuffer = false;
258 return kIOReturnSuccess;
259
260 case kIOMessageDeviceHasPoweredOn:
261
262 IOLockLock( gSleepFramebuffersLock );
263 gWakeCount++;
264 if( gWakeCount == gSleepFramebuffers->getCount()) {
265 while( (self = (IOFramebufferUserClient *) gSleepFramebuffers->getFirstObject())) {
266 if ( self->WSKnowsWeAreOff ) {
267 msgh = (mach_msg_header_t *)(self->notificationMsg);
268 if( msgh && (self->WSnotificationPort)) {
269 msgh->msgh_id = 1;
270 self->WSKnowsWeAreOff = false;
271 r = mach_msg_send_from_kernel( msgh, msgh->msgh_size);
272 }
273 }
274 gSleepFramebuffers->removeObject( self );
275 }
276 gWakeCount = 0;
277 }
278 IOLockUnlock( gSleepFramebuffersLock );
279 return kIOReturnSuccess;
280 }
281 return kIOReturnUnsupported;
282}
283
284IOReturn IOFramebufferUserClient::registerNotificationPort(
285 mach_port_t port,
286 UInt32 type,
287 UInt32 refCon )
288{
289 static mach_msg_header_t init_msg = {
290 // mach_msg_bits_t msgh_bits;
291 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,0),
292 // mach_msg_size_t msgh_size;
293 sizeof (mach_msg_header_t),
294 // mach_port_t msgh_remote_port;
295 MACH_PORT_NULL,
296 // mach_port_t msgh_local_port;
297 MACH_PORT_NULL,
298 // mach_msg_size_t msgh_reserved;
299 0,
300 // mach_msg_id_t msgh_id;
301 0
302 };
303
304 if ( notificationMsg == NULL )
305 notificationMsg = IOMalloc( sizeof (mach_msg_header_t) );
306 // Initialize the power state change notification message.
307 *((mach_msg_header_t *)notificationMsg) = init_msg;
308
309 ((mach_msg_header_t *)notificationMsg)->msgh_remote_port = port;
310
311 WSnotificationPort = port;
312 WSKnowsWeAreOff = false;
313 return( kIOReturnSuccess);
314}
315
316IOReturn IOFramebufferUserClient::getNotificationSemaphore(
317 UInt32 interruptType, semaphore_t * semaphore )
318{
319 return( owner->getNotificationSemaphore(interruptType, semaphore) );
320}
321
322// The window server is going away.
323// We disallow power down to prevent idle sleep while the console is running.
324IOReturn IOFramebufferUserClient::clientClose( void )
325{
326 owner->close();
327 if( owner->isConsoleDevice())
328 getPlatform()->setConsoleInfo( 0, kPEAcquireScreen);
329
330 if( powerRootNotifier) {
331 powerRootNotifier->remove();
332 powerRootNotifier = 0;
333 }
334 if( frameBufferNotifier) {
335 frameBufferNotifier->remove();
336 frameBufferNotifier = 0;
337 }
338 if( notificationMsg) {
339 IOFree( notificationMsg, sizeof (mach_msg_header_t));
340 notificationMsg = 0;
341 }
342 owner->serverConnect = 0;
343 WSnotificationPort = NULL;
344 detach( owner);
345
346 return( kIOReturnSuccess);
347}
348
349IOService * IOFramebufferUserClient::getService( void )
350{
351 return( owner );
352}
353
354IOReturn IOFramebufferUserClient::clientMemoryForType( UInt32 type,
355 IOOptionBits * flags, IOMemoryDescriptor ** memory )
356{
357 IOMemoryDescriptor * mem;
358 IOReturn err;
359
360 switch( type) {
361
362 case kIOFBCursorMemory:
363 mem = owner->sharedCursor;
364 mem->retain();
365 break;
366
367 case kIOFBVRAMMemory:
368 mem = owner->getVRAMRange();
369 break;
370
371 default:
372 mem = (IOMemoryDescriptor *) owner->userAccessRanges->getObject( type );
373 mem->retain();
374 break;
375 }
376
377 *memory = mem;
378 if( mem)
379 err = kIOReturnSuccess;
380 else
381 err = kIOReturnBadArgument;
382
383 return( err );
384}
385
386IOExternalMethod * IOFramebufferUserClient::getExternalMethodForIndex( UInt32 index )
387{
388 if( index < (sizeof( externals) / sizeof( externals[0])))
389 return( externals + index);
390 else
391 return( NULL);
392}
393
394IOReturn IOFramebufferUserClient::setProperties( OSObject * properties )
395{
396 OSDictionary * dict;
397 OSArray * array;
398 IOReturn kr = kIOReturnUnsupported;
399
400 if( !(dict = OSDynamicCast( OSDictionary, properties)))
401 return( kIOReturnBadArgument);
402
403 if( (array = OSDynamicCast(OSArray,
404 dict->getObject( kIOFBDetailedTimingsKey))))
405 kr = owner->setDetailedTimings( array );
406 else
407 kr = kIOReturnBadArgument;
408
409 return( kr );
410}
411
412/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
413
414OSDefineMetaClassAndStructors(IOGraphicsEngineClient, IOUserClient)
415
416/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
417
418IOGraphicsEngineClient * IOGraphicsEngineClient::withTask( task_t owningTask )
419{
420 IOGraphicsEngineClient * inst;
421
422 inst = new IOGraphicsEngineClient;
423
424 if( inst && !inst->init()) {
425 inst->release();
426 inst = 0;
427 }
428 if( inst)
429 inst->owningTask = owningTask;
430
431 return( inst );
432}
433
434bool IOGraphicsEngineClient::start( IOService * _owner )
435{
436
437 static const IOExternalMethod methodTemplate[] = {
438/* 0 */ { NULL, NULL, kIOUCScalarIScalarO, 3, 1 },
439/* 1 */ { NULL, NULL, kIOUCScalarIScalarO, 2, 2 },
440/* 2 */ { NULL, NULL, kIOUCScalarIScalarO, 3, 2 },
441/* 3 */ { NULL, NULL, kIOUCScalarIScalarO, 1, 0 },
442 };
443
444 IOGraphicsEngineContext * mem;
445 IOByteCount size;
446
447 if( !super::start( _owner ))
448 return( false);
449
450 owner = (IOFramebuffer *) _owner;
451 agpDev = OSDynamicCast( IOAGPDevice, owner->getProvider());
452 descriptors = OSArray::withCapacity( 1 );
453
454 bcopy( methodTemplate, externals, sizeof( methodTemplate ));
455
456 externals[0].object = this;
457 externals[0].func = (IOMethod) &IOGraphicsEngineClient::addUserRange;
458 externals[1].object = this;
459 externals[1].func = (IOMethod) &IOGraphicsEngineClient::createAGPSpace;
460 externals[2].object = this;
461 externals[2].func = (IOMethod) &IOGraphicsEngineClient::commitAGPMemory;
462 externals[3].object = this;
463 externals[3].func = (IOMethod) &IOGraphicsEngineClient::releaseAGPMemory;
464
465 if( 0 == owner->engineContext) {
466
467 size = round_page( sizeof( IOGraphicsEngineContext));
468 owner->engineContext = IOBufferMemoryDescriptor::withCapacity(
469 size, kIODirectionNone, false );
470 if( !owner->engineContext)
471 return( kIOReturnNoMemory );
472 owner->engineContext->setLength( size );
473
474 mem = (IOGraphicsEngineContext *)
475 owner->engineContext->getBytesNoCopy();
476 memset((char *)mem, 0, size);
477 mem->version = kIOGraphicsEngineContextVersion;
478 mem->structSize = size;
479 }
480
481 return( true );
482}
483
484void IOGraphicsEngineClient::free()
485{
486 if( descriptors)
487 descriptors->free();
488
489 if( agpDev && haveAGP)
490 agpDev->destroyAGPSpace();
491
492 super::free();
493}
494
495IOReturn IOGraphicsEngineClient::clientClose( void )
496{
497 detach( owner );
498
499 return( kIOReturnSuccess);
500}
501
502IOService * IOGraphicsEngineClient::getService( void )
503{
504 return( owner );
505}
506
507IOReturn IOGraphicsEngineClient::clientMemoryForType( UInt32 type,
508 IOOptionBits * options, IOMemoryDescriptor ** memory )
509{
510 IOMemoryDescriptor * mem;
511
512 switch( type) {
513 case kIOGraphicsEngineContext:
514 mem = owner->engineContext;
515 break;
516 default:
517 mem = (IOMemoryDescriptor *) owner->engineAccessRanges->getObject( type );
518 break;
519 }
520
521 if( mem) {
522 mem->retain();
523 *memory = mem;
524 return( kIOReturnSuccess);
525 } else
526 return( kIOReturnBadArgument);
527}
528
529IOExternalMethod * IOGraphicsEngineClient::getExternalMethodForIndex( UInt32 index )
530{
531 if( index < (sizeof( externals) / sizeof( externals[0])))
532 return( externals + index);
533 else
534 return( NULL);
535}
536
537IOReturn IOGraphicsEngineClient::addUserRange( vm_address_t start,
538 vm_size_t length, UInt32 apertureIndex, IOPhysicalAddress * phys )
539{
540 IODeviceMemory * mem;
541 IOReturn err = kIOReturnSuccess;
542 OSArray * ranges;
543 int i;
544 IODeviceMemory * aperture
545 = owner->getProvider()->getDeviceMemoryWithIndex( apertureIndex );
546
547 if( 0 == aperture)
548 return( kIOReturnBadArgument );
549
550 ranges = owner->engineAccessRanges;
551 i = 0;
552 while( (mem = (IODeviceMemory *) ranges->getObject( i++ ))) {
553 if( (mem->getPhysicalAddress() ==
554 (start + aperture->getPhysicalAddress()))
555 && (length <= mem->getLength()) )
556 break;
557 }
558
559 if( 0 == mem) {
560 mem = IODeviceMemory::withSubRange(
561 aperture, start, length );
562 if( mem) {
563 owner->engineAccessRanges->setObject( mem );
564 err = kIOReturnSuccess;
565 } else
566 err = kIOReturnNoResources;
567 }
568
569 if( kIOReturnSuccess == err)
570 *phys = mem->getPhysicalAddress();
571
572 return( err );
573}
574
575IOReturn IOGraphicsEngineClient::createAGPSpace( IOOptionBits options,
576 IOPhysicalLength length,
577 IOPhysicalAddress * address,
578 IOPhysicalLength * lengthOut )
579{
580 IOReturn err;
581
582 if( !agpDev)
583 return( kIOReturnUnsupported );
584
585 *lengthOut = length;
586 err = agpDev->createAGPSpace( options, address, lengthOut );
587 haveAGP = (kIOReturnSuccess == err);
588
589 return( err );
590}
591
592/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
593
594class _IOGraphicsClientMemory : public OSObject {
595 OSDeclareDefaultStructors(_IOGraphicsClientMemory)
596public:
597 IOMemoryDescriptor * memory;
598 IOAGPDevice * agpDev;
599 IOByteCount agpOffset;
600
601 virtual bool init();
602 virtual void free();
603};
604
605OSDefineMetaClassAndStructors(_IOGraphicsClientMemory, OSObject)
606
607bool _IOGraphicsClientMemory::init()
608{
609 return( OSObject::init());
610}
611
612void _IOGraphicsClientMemory::free()
613{
614 if( memory) {
615 agpDev->getAGPRangeAllocator()->deallocate( agpOffset,
616 memory->getLength() );
617 memory->complete();
618 memory->release();
619 }
620
621 OSObject::free();
622}
623
624/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
625
626IOReturn IOGraphicsEngineClient::commitAGPMemory( vm_address_t start,
627 vm_size_t length, IOOptionBits options,
628 void ** ref, IOByteCount * offset )
629{
630 _IOGraphicsClientMemory * graphicsMem;
631 IORangeAllocator * rangeAllocator;
632 IOByteCount agpOffset;
633 IOReturn err = kIOReturnNoMemory;
634 bool ok;
635
636 if( !agpDev)
637 return( kIOReturnUnsupported );
638 if( (!start) || (!length))
639 return( kIOReturnBadArgument );
640 rangeAllocator = agpDev->getAGPRangeAllocator();
641 if( !rangeAllocator)
642 return( kIOReturnUnsupported );
643
644 do {
645 graphicsMem = new _IOGraphicsClientMemory;
646 if( (!graphicsMem) || (!graphicsMem->init()))
647 continue;
648
649 ok = rangeAllocator->allocate( length, (IORangeScalar *) &agpOffset );
650 if( !ok) {
651 err = kIOReturnNoSpace;
652 continue;
653 }
654
655 graphicsMem->agpDev = agpDev;
656 graphicsMem->agpOffset = agpOffset;
657
658 graphicsMem->memory = IOMemoryDescriptor::withAddress( start, length,
659 kIODirectionOut, owningTask );
660 if( !graphicsMem->memory)
661 continue;
662
663 err = graphicsMem->memory->prepare();
664 if( err != kIOReturnSuccess)
665 continue;
666
667 err = agpDev->commitAGPMemory( graphicsMem->memory, agpOffset );
668 if( err != kIOReturnSuccess)
669 continue;
670
671 *ref = (void *) descriptors->getCount();
672 *offset = agpOffset;
673 descriptors->setObject( graphicsMem );
674
675 } while( false );
676
677 if( graphicsMem)
678 graphicsMem->release();
679
680 if( (kIOReturnSuccess != err) && (!graphicsMem))
681 rangeAllocator->deallocate( agpOffset, length );
682
683 return( err );
684}
685
686IOReturn IOGraphicsEngineClient::releaseAGPMemory( void * ref )
687{
688 _IOGraphicsClientMemory * graphicsMem;
689 UInt32 index = (UInt32) ref;
690
691 if( 0 == (graphicsMem = (_IOGraphicsClientMemory *)
692 descriptors->getObject( index )))
693 return( kIOReturnBadArgument );
694
695 descriptors->removeObject( index );
696
697 return( kIOReturnSuccess );
698}
699
700/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
701
702OSDefineMetaClassAndStructors(IOFramebufferSharedUserClient, IOUserClient)
703
704/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
705
706IOFramebufferSharedUserClient * IOFramebufferSharedUserClient::withTask(
707 task_t owningTask )
708{
709 IOFramebufferSharedUserClient * inst;
710
711 inst = new IOFramebufferSharedUserClient;
712
713 if( inst && !inst->init()) {
714 inst->release();
715 inst = 0;
716 }
717
718 return( inst );
719}
720
721bool IOFramebufferSharedUserClient::start( IOService * _owner )
722{
723
724 static const IOExternalMethod methodTemplate[] = {
725 };
726
727 if( !super::start( _owner ))
728 return( false);
729
730 owner = (IOFramebuffer *) _owner;
731
732 bcopy( methodTemplate, externals, sizeof( methodTemplate ));
733
734 return( true );
735}
736
737void IOFramebufferSharedUserClient::free( void )
738{
739 retain(); retain();
740 owner->sharedConnect = 0;
741 detach( owner);
742 super::free();
743}
744
745void IOFramebufferSharedUserClient::release() const
746{
747 super::release(2);
748}
749
750IOReturn IOFramebufferSharedUserClient::clientClose( void )
751{
752 return( kIOReturnSuccess);
753}
754
755IOService * IOFramebufferSharedUserClient::getService( void )
756{
757 return( owner );
758}
759
760IOReturn IOFramebufferSharedUserClient::clientMemoryForType( UInt32 type,
761 IOOptionBits * options, IOMemoryDescriptor ** memory )
762{
763 IOMemoryDescriptor * mem = 0;
764 IOReturn err;
765
766 switch( type) {
767
768 case kIOFBCursorMemory:
769 mem = owner->sharedCursor;
770 mem->retain();
771 *options = kIOMapReadOnly;
772 break;
773
774 case kIOFBVRAMMemory:
775 mem = owner->getVRAMRange();
776 break;
777 }
778
779 *memory = mem;
780 if( mem)
781 err = kIOReturnSuccess;
782 else
783 err = kIOReturnBadArgument;
784
785 return( err );
786}
787
788IOReturn IOFramebufferSharedUserClient::getNotificationSemaphore(
789 UInt32 interruptType, semaphore_t * semaphore )
790{
791 return( owner->getNotificationSemaphore(interruptType, semaphore) );
792}
793
794IOExternalMethod * IOFramebufferSharedUserClient::getExternalMethodForIndex( UInt32 index )
795{
796 if( index < (sizeof( externals) / sizeof( externals[0])))
797 return( externals + index);
798 else
799 return( NULL);
800}
801