]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOGraphics/IOFramebufferUserClient.cpp
3667cce8c8daa33e310599615e94a1796a728526
[apple/xnu.git] / iokit / Families / IOGraphics / IOFramebufferUserClient.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 * 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
53 OSDefineMetaClassAndStructors(IOFramebufferUserClient, IOUserClient)
54
55 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
56
57 static IOReturn myHandler(void *, void * , UInt32, IOService *, void *, unsigned int);
58 static IOLock * gSleepFramebuffersLock;
59 static OSOrderedSet * gSleepFramebuffers;
60 static UInt32 gWakeCount;
61
62 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
63
64 IOFramebufferUserClient * 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
84 bool 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
186 IOReturn
187 IOFramebufferUserClient::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
206 static IOReturn
207 myHandler(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
284 IOReturn 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
316 IOReturn 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.
324 IOReturn 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
349 IOService * IOFramebufferUserClient::getService( void )
350 {
351 return( owner );
352 }
353
354 IOReturn 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
386 IOExternalMethod * IOFramebufferUserClient::getExternalMethodForIndex( UInt32 index )
387 {
388 if( index < (sizeof( externals) / sizeof( externals[0])))
389 return( externals + index);
390 else
391 return( NULL);
392 }
393
394 IOReturn 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
414 OSDefineMetaClassAndStructors(IOGraphicsEngineClient, IOUserClient)
415
416 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
417
418 IOGraphicsEngineClient * 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
434 bool 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
484 void IOGraphicsEngineClient::free()
485 {
486 if( descriptors)
487 descriptors->free();
488
489 if( agpDev && haveAGP)
490 agpDev->destroyAGPSpace();
491
492 super::free();
493 }
494
495 IOReturn IOGraphicsEngineClient::clientClose( void )
496 {
497 detach( owner );
498
499 return( kIOReturnSuccess);
500 }
501
502 IOService * IOGraphicsEngineClient::getService( void )
503 {
504 return( owner );
505 }
506
507 IOReturn 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
529 IOExternalMethod * IOGraphicsEngineClient::getExternalMethodForIndex( UInt32 index )
530 {
531 if( index < (sizeof( externals) / sizeof( externals[0])))
532 return( externals + index);
533 else
534 return( NULL);
535 }
536
537 IOReturn 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
575 IOReturn 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
594 class _IOGraphicsClientMemory : public OSObject {
595 OSDeclareDefaultStructors(_IOGraphicsClientMemory)
596 public:
597 IOMemoryDescriptor * memory;
598 IOAGPDevice * agpDev;
599 IOByteCount agpOffset;
600
601 virtual bool init();
602 virtual void free();
603 };
604
605 OSDefineMetaClassAndStructors(_IOGraphicsClientMemory, OSObject)
606
607 bool _IOGraphicsClientMemory::init()
608 {
609 return( OSObject::init());
610 }
611
612 void _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
626 IOReturn 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
686 IOReturn 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
702 OSDefineMetaClassAndStructors(IOFramebufferSharedUserClient, IOUserClient)
703
704 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
705
706 IOFramebufferSharedUserClient * 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
721 bool 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
737 void IOFramebufferSharedUserClient::free( void )
738 {
739 retain(); retain();
740 owner->sharedConnect = 0;
741 detach( owner);
742 super::free();
743 }
744
745 void IOFramebufferSharedUserClient::release() const
746 {
747 super::release(2);
748 }
749
750 IOReturn IOFramebufferSharedUserClient::clientClose( void )
751 {
752 return( kIOReturnSuccess);
753 }
754
755 IOService * IOFramebufferSharedUserClient::getService( void )
756 {
757 return( owner );
758 }
759
760 IOReturn 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
788 IOReturn IOFramebufferSharedUserClient::getNotificationSemaphore(
789 UInt32 interruptType, semaphore_t * semaphore )
790 {
791 return( owner->getNotificationSemaphore(interruptType, semaphore) );
792 }
793
794 IOExternalMethod * IOFramebufferSharedUserClient::getExternalMethodForIndex( UInt32 index )
795 {
796 if( index < (sizeof( externals) / sizeof( externals[0])))
797 return( externals + index);
798 else
799 return( NULL);
800 }
801