]>
Commit | Line | Data |
---|---|---|
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 | ||
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 |