2 * Copyright (c) 1998-2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <IOKit/system.h>
31 #include <IOKit/IOService.h>
32 #include <libkern/c++/OSContainers.h>
33 #include <libkern/c++/OSUnserialize.h>
34 #include <IOKit/IOCatalogue.h>
35 #include <IOKit/IOCommand.h>
36 #include <IOKit/IODeviceMemory.h>
37 #include <IOKit/IOInterrupts.h>
38 #include <IOKit/IOInterruptController.h>
39 #include <IOKit/IOPlatformExpert.h>
40 #include <IOKit/IOMessage.h>
41 #include <IOKit/IOLib.h>
42 #include <IOKit/IOKitKeysPrivate.h>
43 #include <IOKit/IOBSD.h>
44 #include <IOKit/IOUserClient.h>
45 #include <IOKit/IOWorkLoop.h>
46 #include <mach/sync_policy.h>
47 #include <IOKit/assert.h>
48 #include <sys/errno.h>
53 #include "IOServicePrivate.h"
55 // take lockForArbitration before LOCKNOTIFY
57 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
59 #define super IORegistryEntry
61 OSDefineMetaClassAndStructors(IOService
, IORegistryEntry
)
63 OSDefineMetaClassAndStructors(_IOServiceNotifier
, IONotifier
)
65 OSDefineMetaClassAndStructors(_IOServiceInterestNotifier
, IONotifier
)
67 OSDefineMetaClassAndStructors(_IOConfigThread
, OSObject
)
69 OSDefineMetaClassAndStructors(_IOServiceJob
, OSObject
)
71 OSDefineMetaClassAndStructors(IOResources
, IOService
)
73 OSDefineMetaClassAndStructors(_IOOpenServiceIterator
, OSIterator
)
75 OSDefineMetaClassAndAbstractStructors(IONotifier
, OSObject
)
77 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
79 static IOPlatformExpert
* gIOPlatform
;
80 static class IOPMrootDomain
* gIOPMRootDomain
;
81 const IORegistryPlane
* gIOServicePlane
;
82 const IORegistryPlane
* gIOPowerPlane
;
83 const OSSymbol
* gIODeviceMemoryKey
;
84 const OSSymbol
* gIOInterruptControllersKey
;
85 const OSSymbol
* gIOInterruptSpecifiersKey
;
87 const OSSymbol
* gIOResourcesKey
;
88 const OSSymbol
* gIOResourceMatchKey
;
89 const OSSymbol
* gIOProviderClassKey
;
90 const OSSymbol
* gIONameMatchKey
;
91 const OSSymbol
* gIONameMatchedKey
;
92 const OSSymbol
* gIOPropertyMatchKey
;
93 const OSSymbol
* gIOLocationMatchKey
;
94 const OSSymbol
* gIOParentMatchKey
;
95 const OSSymbol
* gIOPathMatchKey
;
96 const OSSymbol
* gIOMatchCategoryKey
;
97 const OSSymbol
* gIODefaultMatchCategoryKey
;
98 const OSSymbol
* gIOMatchedServiceCountKey
;
100 const OSSymbol
* gIOUserClientClassKey
;
101 const OSSymbol
* gIOKitDebugKey
;
103 const OSSymbol
* gIOCommandPoolSizeKey
;
105 const OSSymbol
* gIOConsoleUsersKey
;
106 const OSSymbol
* gIOConsoleSessionUIDKey
;
107 const OSSymbol
* gIOConsoleUsersSeedKey
;
108 const OSSymbol
* gIOConsoleSessionOnConsoleKey
;
109 const OSSymbol
* gIOConsoleSessionSecureInputPIDKey
;
111 static int gIOResourceGenerationCount
;
113 const OSSymbol
* gIOServiceKey
;
114 const OSSymbol
* gIOPublishNotification
;
115 const OSSymbol
* gIOFirstPublishNotification
;
116 const OSSymbol
* gIOMatchedNotification
;
117 const OSSymbol
* gIOFirstMatchNotification
;
118 const OSSymbol
* gIOTerminatedNotification
;
120 const OSSymbol
* gIOGeneralInterest
;
121 const OSSymbol
* gIOBusyInterest
;
122 const OSSymbol
* gIOAppPowerStateInterest
;
123 const OSSymbol
* gIOPriorityPowerStateInterest
;
125 static OSDictionary
* gNotifications
;
126 static IORecursiveLock
* gNotificationLock
;
128 static IOService
* gIOResources
;
129 static IOService
* gIOServiceRoot
;
131 static OSOrderedSet
* gJobs
;
132 static semaphore_port_t gJobsSemaphore
;
133 static IOLock
* gJobsLock
;
134 static int gOutstandingJobs
;
135 static int gNumConfigThreads
;
136 static int gNumWaitingThreads
;
137 static IOLock
* gIOServiceBusyLock
;
139 static thread_t gIOTerminateThread
;
140 static UInt32 gIOTerminateWork
;
141 static OSArray
* gIOTerminatePhase2List
;
142 static OSArray
* gIOStopList
;
143 static OSArray
* gIOStopProviderList
;
144 static OSArray
* gIOFinalizeList
;
146 static SInt32 gIOConsoleUsersSeed
;
147 static OSData
* gIOConsoleUsersSeedValue
;
149 extern const OSSymbol
* gIODTPHandleKey
;
151 const OSSymbol
* gIOPlatformSleepActionKey
;
152 const OSSymbol
* gIOPlatformWakeActionKey
;
153 const OSSymbol
* gIOPlatformQuiesceActionKey
;
154 const OSSymbol
* gIOPlatformActiveActionKey
;
156 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
158 #define LOCKREADNOTIFY() \
159 IORecursiveLockLock( gNotificationLock )
160 #define LOCKWRITENOTIFY() \
161 IORecursiveLockLock( gNotificationLock )
162 #define LOCKWRITE2READNOTIFY()
163 #define UNLOCKNOTIFY() \
164 IORecursiveLockUnlock( gNotificationLock )
165 #define SLEEPNOTIFY(event) \
166 IORecursiveLockSleep( gNotificationLock, (void *)(event), THREAD_UNINT )
167 #define WAKEUPNOTIFY(event) \
168 IORecursiveLockWakeup( gNotificationLock, (void *)(event), /* wake one */ false )
170 #define randomDelay() \
171 int del = read_processor_clock(); \
172 del = (((int)IOThreadSelf()) ^ del ^ (del >> 10)) & 0x3ff; \
175 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
177 #define queue_element(entry, element, type, field) do { \
178 vm_address_t __ele = (vm_address_t) (entry); \
179 __ele -= -4 + ((size_t)(&((type) 4)->field)); \
180 (element) = (type) __ele; \
183 #define iterqueue(que, elt) \
184 for (queue_entry_t elt = queue_first(que); \
185 !queue_end(que, elt); \
186 elt = queue_next(elt))
188 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
190 struct ArbitrationLockQueueElement
{
199 static queue_head_t gArbitrationLockQueueActive
;
200 static queue_head_t gArbitrationLockQueueWaiting
;
201 static queue_head_t gArbitrationLockQueueFree
;
202 static IOLock
* gArbitrationLockQueueLock
;
204 bool IOService::isInactive( void ) const
205 { return( 0 != (kIOServiceInactiveState
& getState())); }
207 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
211 // Only used by the intel implementation of
212 // IOService::requireMaxBusStall(UInt32 __unused ns)
215 const IOService
*fService
;
219 static OSData
*sBusStall
= OSData::withCapacity(8 * sizeof(BusStallEntry
));
220 static IOLock
*sBusStallLock
= IOLockAlloc();
221 #endif /* __i386__ */
223 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
225 void IOService::initialize( void )
229 gIOServicePlane
= IORegistryEntry::makePlane( kIOServicePlane
);
230 gIOPowerPlane
= IORegistryEntry::makePlane( kIOPowerPlane
);
232 gIOProviderClassKey
= OSSymbol::withCStringNoCopy( kIOProviderClassKey
);
233 gIONameMatchKey
= OSSymbol::withCStringNoCopy( kIONameMatchKey
);
234 gIONameMatchedKey
= OSSymbol::withCStringNoCopy( kIONameMatchedKey
);
235 gIOPropertyMatchKey
= OSSymbol::withCStringNoCopy( kIOPropertyMatchKey
);
236 gIOPathMatchKey
= OSSymbol::withCStringNoCopy( kIOPathMatchKey
);
237 gIOLocationMatchKey
= OSSymbol::withCStringNoCopy( kIOLocationMatchKey
);
238 gIOParentMatchKey
= OSSymbol::withCStringNoCopy( kIOParentMatchKey
);
240 gIOMatchCategoryKey
= OSSymbol::withCStringNoCopy( kIOMatchCategoryKey
);
241 gIODefaultMatchCategoryKey
= OSSymbol::withCStringNoCopy(
242 kIODefaultMatchCategoryKey
);
243 gIOMatchedServiceCountKey
= OSSymbol::withCStringNoCopy(
244 kIOMatchedServiceCountKey
);
246 gIOUserClientClassKey
= OSSymbol::withCStringNoCopy( kIOUserClientClassKey
);
248 gIOResourcesKey
= OSSymbol::withCStringNoCopy( kIOResourcesClass
);
249 gIOResourceMatchKey
= OSSymbol::withCStringNoCopy( kIOResourceMatchKey
);
251 gIODeviceMemoryKey
= OSSymbol::withCStringNoCopy( "IODeviceMemory" );
252 gIOInterruptControllersKey
253 = OSSymbol::withCStringNoCopy("IOInterruptControllers");
254 gIOInterruptSpecifiersKey
255 = OSSymbol::withCStringNoCopy("IOInterruptSpecifiers");
257 gIOKitDebugKey
= OSSymbol::withCStringNoCopy( kIOKitDebugKey
);
259 gIOCommandPoolSizeKey
= OSSymbol::withCStringNoCopy( kIOCommandPoolSizeKey
);
261 gIOGeneralInterest
= OSSymbol::withCStringNoCopy( kIOGeneralInterest
);
262 gIOBusyInterest
= OSSymbol::withCStringNoCopy( kIOBusyInterest
);
263 gIOAppPowerStateInterest
= OSSymbol::withCStringNoCopy( kIOAppPowerStateInterest
);
264 gIOPriorityPowerStateInterest
= OSSymbol::withCStringNoCopy( kIOPriorityPowerStateInterest
);
266 gNotifications
= OSDictionary::withCapacity( 1 );
267 gIOPublishNotification
= OSSymbol::withCStringNoCopy(
268 kIOPublishNotification
);
269 gIOFirstPublishNotification
= OSSymbol::withCStringNoCopy(
270 kIOFirstPublishNotification
);
271 gIOMatchedNotification
= OSSymbol::withCStringNoCopy(
272 kIOMatchedNotification
);
273 gIOFirstMatchNotification
= OSSymbol::withCStringNoCopy(
274 kIOFirstMatchNotification
);
275 gIOTerminatedNotification
= OSSymbol::withCStringNoCopy(
276 kIOTerminatedNotification
);
277 gIOServiceKey
= OSSymbol::withCStringNoCopy( kIOServiceClass
);
279 gIOConsoleUsersKey
= OSSymbol::withCStringNoCopy( kIOConsoleUsersKey
);
280 gIOConsoleSessionUIDKey
= OSSymbol::withCStringNoCopy( kIOConsoleSessionUIDKey
);
281 gIOConsoleUsersSeedKey
= OSSymbol::withCStringNoCopy( kIOConsoleUsersSeedKey
);
282 gIOConsoleSessionOnConsoleKey
= OSSymbol::withCStringNoCopy( kIOConsoleSessionOnConsoleKey
);
283 gIOConsoleSessionSecureInputPIDKey
= OSSymbol::withCStringNoCopy( kIOConsoleSessionSecureInputPIDKey
);
284 gIOConsoleUsersSeedValue
= OSData::withBytesNoCopy(&gIOConsoleUsersSeed
, sizeof(gIOConsoleUsersSeed
));
286 gIOPlatformSleepActionKey
= OSSymbol::withCStringNoCopy(kIOPlatformSleepActionKey
);
287 gIOPlatformWakeActionKey
= OSSymbol::withCStringNoCopy(kIOPlatformWakeActionKey
);
288 gIOPlatformQuiesceActionKey
= OSSymbol::withCStringNoCopy(kIOPlatformQuiesceActionKey
);
289 gIOPlatformActiveActionKey
= OSSymbol::withCStringNoCopy(kIOPlatformActiveActionKey
);
291 gNotificationLock
= IORecursiveLockAlloc();
293 assert( gIOServicePlane
&& gIODeviceMemoryKey
294 && gIOInterruptControllersKey
&& gIOInterruptSpecifiersKey
295 && gIOResourcesKey
&& gNotifications
&& gNotificationLock
296 && gIOProviderClassKey
&& gIONameMatchKey
&& gIONameMatchedKey
297 && gIOMatchCategoryKey
&& gIODefaultMatchCategoryKey
298 && gIOPublishNotification
&& gIOMatchedNotification
299 && gIOTerminatedNotification
&& gIOServiceKey
300 && gIOConsoleUsersKey
&& gIOConsoleSessionUIDKey
301 && gIOConsoleSessionOnConsoleKey
&& gIOConsoleSessionSecureInputPIDKey
302 && gIOConsoleUsersSeedKey
&& gIOConsoleUsersSeedValue
);
304 gJobsLock
= IOLockAlloc();
305 gJobs
= OSOrderedSet::withCapacity( 10 );
307 gIOServiceBusyLock
= IOLockAlloc();
309 err
= semaphore_create(kernel_task
, &gJobsSemaphore
, SYNC_POLICY_FIFO
, 0);
311 assert( gIOServiceBusyLock
&& gJobs
&& gJobsLock
&& (err
== KERN_SUCCESS
) );
313 gIOResources
= IOResources::resources();
314 assert( gIOResources
);
316 gArbitrationLockQueueLock
= IOLockAlloc();
317 queue_init(&gArbitrationLockQueueActive
);
318 queue_init(&gArbitrationLockQueueWaiting
);
319 queue_init(&gArbitrationLockQueueFree
);
321 assert( gArbitrationLockQueueLock
);
323 gIOTerminatePhase2List
= OSArray::withCapacity( 2 );
324 gIOStopList
= OSArray::withCapacity( 16 );
325 gIOStopProviderList
= OSArray::withCapacity( 16 );
326 gIOFinalizeList
= OSArray::withCapacity( 16 );
327 assert( gIOTerminatePhase2List
&& gIOStopList
&& gIOStopProviderList
&& gIOFinalizeList
);
330 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
333 static UInt64
getDebugFlags( OSDictionary
* props
)
335 OSNumber
* debugProp
;
338 debugProp
= OSDynamicCast( OSNumber
,
339 props
->getObject( gIOKitDebugKey
));
341 debugFlags
= debugProp
->unsigned64BitValue();
343 debugFlags
= gIOKitDebug
;
345 return( debugFlags
);
349 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
351 // Probe a matched service and return an instance to be started.
352 // The default score is from the property table, & may be altered
353 // during probe to change the start order.
355 IOService
* IOService::probe( IOService
* provider
,
361 bool IOService::start( IOService
* provider
)
366 void IOService::stop( IOService
* provider
)
370 void IOService::free( void )
372 requireMaxBusStall(0);
373 if( getPropertyTable())
374 unregisterAllInterest();
380 * Attach in service plane
382 bool IOService::attach( IOService
* provider
)
388 if( gIOKitDebug
& kIOLogAttach
)
389 LOG( "%s::attach(%s)\n", getName(),
390 provider
->getName());
392 provider
->lockForArbitration();
393 if( provider
->__state
[0] & kIOServiceInactiveState
)
396 ok
= attachToParent( provider
, gIOServicePlane
);
397 provider
->unlockForArbitration();
400 gIOServiceRoot
= this;
401 ok
= attachToParent( getRegistryRoot(), gIOServicePlane
);
407 IOService
* IOService::getServiceRoot( void )
409 return( gIOServiceRoot
);
412 void IOService::detach( IOService
* provider
)
414 IOService
* newProvider
= 0;
418 if( gIOKitDebug
& kIOLogAttach
)
419 LOG("%s::detach(%s)\n", getName(), provider
->getName());
421 lockForArbitration();
423 adjParent
= ((busy
= (__state
[1] & kIOServiceBusyStateMask
))
424 && (provider
== getProvider()));
426 detachFromParent( provider
, gIOServicePlane
);
429 newProvider
= getProvider();
430 if( busy
&& (__state
[1] & kIOServiceTermPhase3State
) && (0 == newProvider
))
431 _adjustBusy( -busy
);
434 unlockForArbitration();
437 newProvider
->lockForArbitration();
438 newProvider
->_adjustBusy(1);
439 newProvider
->unlockForArbitration();
442 // check for last client detach from a terminated service
443 if( provider
->lockForArbitration( true )) {
445 provider
->_adjustBusy( -1 );
446 if( (provider
->__state
[1] & kIOServiceTermPhase3State
)
447 && (0 == provider
->getClient())) {
448 provider
->scheduleFinalize();
450 provider
->unlockForArbitration();
455 * Register instance - publish it for matching
458 void IOService::registerService( IOOptionBits options
)
464 enum { kMaxPathLen
= 256 };
465 enum { kMaxChars
= 63 };
467 IORegistryEntry
* parent
= this;
468 IORegistryEntry
* root
= getRegistryRoot();
469 while( parent
&& (parent
!= root
))
470 parent
= parent
->getParentEntry( gIOServicePlane
);
472 if( parent
!= root
) {
473 IOLog("%s: not registry member at registerService()\n", getName());
477 // Allow the Platform Expert to adjust this node.
478 if( gIOPlatform
&& (!gIOPlatform
->platformAdjustService(this)))
481 if( (this != gIOResources
)
482 && (kIOLogRegister
& gIOKitDebug
)) {
484 pathBuf
= (char *) IOMalloc( kMaxPathLen
);
486 IOLog( "Registering: " );
489 if( pathBuf
&& getPath( pathBuf
, &len
, gIOServicePlane
)) {
492 if( len
> kMaxChars
) {
496 if( (skip
= strchr( path
, '/')))
502 IOLog( "%s\n", path
);
505 IOFree( pathBuf
, kMaxPathLen
);
508 startMatching( options
);
511 void IOService::startMatching( IOOptionBits options
)
513 IOService
* provider
;
516 bool needWake
= false;
521 lockForArbitration();
523 sync
= (options
& kIOServiceSynchronous
)
524 || ((provider
= getProvider())
525 && (provider
->__state
[1] & kIOServiceSynchronousState
));
527 if ( options
& kIOServiceAsynchronous
)
530 needConfig
= (0 == (__state
[1] & (kIOServiceNeedConfigState
| kIOServiceConfigState
)))
531 && (0 == (__state
[0] & kIOServiceInactiveState
));
533 __state
[1] |= kIOServiceNeedConfigState
;
535 // __state[0] &= ~kIOServiceInactiveState;
537 // if( sync) LOG("OSKernelStackRemaining = %08x @ %s\n",
538 // OSKernelStackRemaining(), getName());
541 prevBusy
= _adjustBusy( 1 );
542 needWake
= (0 != (kIOServiceSyncPubState
& __state
[1]));
546 __state
[1] |= kIOServiceSynchronousState
;
548 __state
[1] &= ~kIOServiceSynchronousState
;
550 unlockForArbitration();
555 IOLockLock( gIOServiceBusyLock
);
556 thread_wakeup( (event_t
) this/*&__state[1]*/ );
557 IOLockUnlock( gIOServiceBusyLock
);
559 } else if( !sync
|| (kIOServiceAsynchronous
& options
)) {
561 ok
= (0 != _IOServiceJob::startJob( this, kMatchNubJob
, options
));
565 if( (__state
[1] & kIOServiceNeedConfigState
))
566 doServiceMatch( options
);
568 lockForArbitration();
569 IOLockLock( gIOServiceBusyLock
);
571 waitAgain
= (prevBusy
< (__state
[1] & kIOServiceBusyStateMask
));
573 __state
[1] |= kIOServiceSyncPubState
| kIOServiceBusyWaiterState
;
575 __state
[1] &= ~kIOServiceSyncPubState
;
577 unlockForArbitration();
580 assert_wait( (event_t
) this/*&__state[1]*/, THREAD_UNINT
);
582 IOLockUnlock( gIOServiceBusyLock
);
584 thread_block(THREAD_CONTINUE_NULL
);
586 } while( waitAgain
);
590 IOReturn
IOService::catalogNewDrivers( OSOrderedSet
* newTables
)
592 OSDictionary
* table
;
602 while( (table
= (OSDictionary
*) newTables
->getFirstObject())) {
605 set
= (OSSet
*) getExistingServices( table
,
606 kIOServiceRegisteredState
,
607 kIOServiceExistingSet
);
612 count
+= set
->getCount();
615 allSet
->merge((const OSSet
*) set
);
623 if( getDebugFlags( table
) & kIOLogMatch
)
624 LOG("Matching service count = %ld\n", count
);
626 newTables
->removeObject(table
);
630 while( (service
= (IOService
*) allSet
->getAnyObject())) {
631 service
->startMatching(kIOServiceAsynchronous
);
632 allSet
->removeObject(service
);
637 newTables
->release();
639 return( kIOReturnSuccess
);
642 _IOServiceJob
* _IOServiceJob::startJob( IOService
* nub
, int type
,
643 IOOptionBits options
)
647 job
= new _IOServiceJob
;
648 if( job
&& !job
->init()) {
656 job
->options
= options
;
657 nub
->retain(); // thread will release()
665 * Called on a registered service to see if it matches
669 bool IOService::matchPropertyTable( OSDictionary
* table
, SInt32
* score
)
671 return( matchPropertyTable(table
) );
674 bool IOService::matchPropertyTable( OSDictionary
* table
)
680 * Called on a matched service to allocate resources
681 * before first driver is attached.
684 IOReturn
IOService::getResources( void )
686 return( kIOReturnSuccess
);
690 * Client/provider accessors
693 IOService
* IOService::getProvider( void ) const
695 IOService
* self
= (IOService
*) this;
700 generation
= getGenerationCount();
701 if( __providerGeneration
== generation
)
704 parent
= (IOService
*) getParentEntry( gIOServicePlane
);
705 if( parent
== IORegistryEntry::getRegistryRoot())
706 /* root is not an IOService */
709 self
->__provider
= parent
;
710 // save the count before getParentEntry()
711 self
->__providerGeneration
= generation
;
716 IOWorkLoop
* IOService::getWorkLoop() const
718 IOService
*provider
= getProvider();
721 return provider
->getWorkLoop();
726 OSIterator
* IOService::getProviderIterator( void ) const
728 return( getParentIterator( gIOServicePlane
));
731 IOService
* IOService::getClient( void ) const
733 return( (IOService
*) getChildEntry( gIOServicePlane
));
736 OSIterator
* IOService::getClientIterator( void ) const
738 return( getChildIterator( gIOServicePlane
));
741 OSIterator
* _IOOpenServiceIterator::iterator( OSIterator
* _iter
,
742 const IOService
* client
,
743 const IOService
* provider
)
745 _IOOpenServiceIterator
* inst
;
750 inst
= new _IOOpenServiceIterator
;
752 if( inst
&& !inst
->init()) {
758 inst
->client
= client
;
759 inst
->provider
= provider
;
765 void _IOOpenServiceIterator::free()
769 last
->unlockForArbitration();
773 OSObject
* _IOOpenServiceIterator::getNextObject()
778 last
->unlockForArbitration();
780 while( (next
= (IOService
*) iter
->getNextObject())) {
782 next
->lockForArbitration();
783 if( (client
&& (next
->isOpen( client
)))
784 || (provider
&& (provider
->isOpen( next
))) )
786 next
->unlockForArbitration();
794 bool _IOOpenServiceIterator::isValid()
796 return( iter
->isValid() );
799 void _IOOpenServiceIterator::reset()
802 last
->unlockForArbitration();
808 OSIterator
* IOService::getOpenProviderIterator( void ) const
810 return( _IOOpenServiceIterator::iterator( getProviderIterator(), this, 0 ));
813 OSIterator
* IOService::getOpenClientIterator( void ) const
815 return( _IOOpenServiceIterator::iterator( getClientIterator(), 0, this ));
819 IOReturn
IOService::callPlatformFunction( const OSSymbol
* functionName
,
820 bool waitForFunction
,
821 void *param1
, void *param2
,
822 void *param3
, void *param4
)
824 IOReturn result
= kIOReturnUnsupported
;
825 IOService
*provider
= getProvider();
828 result
= provider
->callPlatformFunction(functionName
, waitForFunction
,
829 param1
, param2
, param3
, param4
);
835 IOReturn
IOService::callPlatformFunction( const char * functionName
,
836 bool waitForFunction
,
837 void *param1
, void *param2
,
838 void *param3
, void *param4
)
840 IOReturn result
= kIOReturnNoMemory
;
841 const OSSymbol
*functionSymbol
= OSSymbol::withCString(functionName
);
843 if (functionSymbol
!= 0) {
844 result
= callPlatformFunction(functionSymbol
, waitForFunction
,
845 param1
, param2
, param3
, param4
);
846 functionSymbol
->release();
854 * Accessors for global services
857 IOPlatformExpert
* IOService::getPlatform( void )
859 return( gIOPlatform
);
862 class IOPMrootDomain
* IOService::getPMRootDomain( void )
864 return( gIOPMRootDomain
);
867 IOService
* IOService::getResourceService( void )
869 return( gIOResources
);
872 void IOService::setPlatform( IOPlatformExpert
* platform
)
874 gIOPlatform
= platform
;
875 gIOResources
->attachToParent( gIOServiceRoot
, gIOServicePlane
);
878 void IOService::setPMRootDomain( class IOPMrootDomain
* rootDomain
)
880 gIOPMRootDomain
= rootDomain
;
881 publishResource("IOKit");
888 bool IOService::lockForArbitration( bool isSuccessRequired
)
892 ArbitrationLockQueueElement
* element
;
893 ArbitrationLockQueueElement
* active
;
894 ArbitrationLockQueueElement
* waiting
;
896 enum { kPutOnFreeQueue
, kPutOnActiveQueue
, kPutOnWaitingQueue
} action
;
898 // lock global access
899 IOTakeLock( gArbitrationLockQueueLock
);
901 // obtain an unused queue element
902 if( !queue_empty( &gArbitrationLockQueueFree
)) {
903 queue_remove_first( &gArbitrationLockQueueFree
,
905 ArbitrationLockQueueElement
*,
908 element
= IONew( ArbitrationLockQueueElement
, 1 );
912 // prepare the queue element
913 element
->thread
= IOThreadSelf();
914 element
->service
= this;
916 element
->required
= isSuccessRequired
;
917 element
->aborted
= false;
919 // determine whether this object is already locked (ie. on active queue)
921 queue_iterate( &gArbitrationLockQueueActive
,
923 ArbitrationLockQueueElement
*,
926 if( active
->service
== element
->service
) {
932 if( found
) { // this object is already locked
934 // determine whether it is the same or a different thread trying to lock
935 if( active
->thread
!= element
->thread
) { // it is a different thread
937 ArbitrationLockQueueElement
* victim
= 0;
939 // before placing this new thread on the waiting queue, we look for
940 // a deadlock cycle...
943 // determine whether the active thread holding the object we
944 // want is waiting for another object to be unlocked
946 queue_iterate( &gArbitrationLockQueueWaiting
,
948 ArbitrationLockQueueElement
*,
951 if( waiting
->thread
== active
->thread
) {
952 assert( false == waiting
->aborted
);
958 if( found
) { // yes, active thread waiting for another object
960 // this may be a candidate for rejection if the required
961 // flag is not set, should we detect a deadlock later on
962 if( false == waiting
->required
)
965 // find the thread that is holding this other object, that
966 // is blocking the active thread from proceeding (fun :-)
968 queue_iterate( &gArbitrationLockQueueActive
,
969 active
, // (reuse active queue element)
970 ArbitrationLockQueueElement
*,
973 if( active
->service
== waiting
->service
) {
979 // someone must be holding it or it wouldn't be waiting
982 if( active
->thread
== element
->thread
) {
984 // doh, it's waiting for the thread that originated
985 // this whole lock (ie. current thread) -> deadlock
986 if( false == element
->required
) { // willing to fail?
988 // the originating thread doesn't have the required
989 // flag, so it can fail
990 success
= false; // (fail originating lock request)
991 break; // (out of while)
993 } else { // originating thread is not willing to fail
995 // see if we came across a waiting thread that did
996 // not have the 'required' flag set: we'll fail it
999 // we do have a willing victim, fail it's lock
1000 victim
->aborted
= true;
1002 // take the victim off the waiting queue
1003 queue_remove( &gArbitrationLockQueueWaiting
,
1005 ArbitrationLockQueueElement
*,
1009 IOLockWakeup( gArbitrationLockQueueLock
,
1011 /* one thread */ true );
1013 // allow this thread to proceed (ie. wait)
1014 success
= true; // (put request on wait queue)
1015 break; // (out of while)
1018 // all the waiting threads we came across in
1019 // finding this loop had the 'required' flag
1020 // set, so we've got a deadlock we can't avoid
1021 panic("I/O Kit: Unrecoverable deadlock.");
1025 // repeat while loop, redefining active thread to be the
1026 // thread holding "this other object" (see above), and
1027 // looking for threads waiting on it; note the active
1028 // variable points to "this other object" already... so
1029 // there nothing to do in this else clause.
1031 } else { // no, active thread is not waiting for another object
1033 success
= true; // (put request on wait queue)
1034 break; // (out of while)
1038 if( success
) { // put the request on the waiting queue?
1039 kern_return_t wait_result
;
1041 // place this thread on the waiting queue and put it to sleep;
1042 // we place it at the tail of the queue...
1043 queue_enter( &gArbitrationLockQueueWaiting
,
1045 ArbitrationLockQueueElement
*,
1048 // declare that this thread will wait for a given event
1049 restart_sleep
: wait_result
= assert_wait( element
,
1050 element
->required
? THREAD_UNINT
1051 : THREAD_INTERRUPTIBLE
);
1053 // unlock global access
1054 IOUnlock( gArbitrationLockQueueLock
);
1056 // put thread to sleep, waiting for our event to fire...
1057 if (wait_result
== THREAD_WAITING
)
1058 wait_result
= thread_block(THREAD_CONTINUE_NULL
);
1061 // ...and we've been woken up; we might be in one of two states:
1062 // (a) we've been aborted and our queue element is not on
1063 // any of the three queues, but is floating around
1064 // (b) we're allowed to proceed with the lock and we have
1065 // already been moved from the waiting queue to the
1067 // ...plus a 3rd state, should the thread have been interrupted:
1068 // (c) we're still on the waiting queue
1070 // determine whether we were interrupted out of our sleep
1071 if( THREAD_INTERRUPTED
== wait_result
) {
1073 // re-lock global access
1074 IOTakeLock( gArbitrationLockQueueLock
);
1076 // determine whether we're still on the waiting queue
1078 queue_iterate( &gArbitrationLockQueueWaiting
,
1079 waiting
, // (reuse waiting queue element)
1080 ArbitrationLockQueueElement
*,
1083 if( waiting
== element
) {
1089 if( found
) { // yes, we're still on the waiting queue
1091 // determine whether we're willing to fail
1092 if( false == element
->required
) {
1094 // mark us as aborted
1095 element
->aborted
= true;
1097 // take us off the waiting queue
1098 queue_remove( &gArbitrationLockQueueWaiting
,
1100 ArbitrationLockQueueElement
*,
1102 } else { // we are not willing to fail
1104 // ignore interruption, go back to sleep
1109 // unlock global access
1110 IOUnlock( gArbitrationLockQueueLock
);
1112 // proceed as though this were a normal wake up
1113 wait_result
= THREAD_AWAKENED
;
1116 assert( THREAD_AWAKENED
== wait_result
);
1118 // determine whether we've been aborted while we were asleep
1119 if( element
->aborted
) {
1120 assert( false == element
->required
);
1122 // re-lock global access
1123 IOTakeLock( gArbitrationLockQueueLock
);
1125 action
= kPutOnFreeQueue
;
1127 } else { // we weren't aborted, so we must be ready to go :-)
1129 // we've already been moved from waiting to active queue
1133 } else { // the lock request is to be failed
1135 // return unused queue element to queue
1136 action
= kPutOnFreeQueue
;
1138 } else { // it is the same thread, recursive access is allowed
1140 // add one level of recursion
1143 // return unused queue element to queue
1144 action
= kPutOnFreeQueue
;
1147 } else { // this object is not already locked, so let this thread through
1148 action
= kPutOnActiveQueue
;
1152 // put the new element on a queue
1153 if( kPutOnActiveQueue
== action
) {
1154 queue_enter( &gArbitrationLockQueueActive
,
1156 ArbitrationLockQueueElement
*,
1158 } else if( kPutOnFreeQueue
== action
) {
1159 queue_enter( &gArbitrationLockQueueFree
,
1161 ArbitrationLockQueueElement
*,
1164 assert( 0 ); // kPutOnWaitingQueue never occurs, handled specially above
1167 // unlock global access
1168 IOUnlock( gArbitrationLockQueueLock
);
1173 void IOService::unlockForArbitration( void )
1176 ArbitrationLockQueueElement
* element
;
1178 // lock global access
1179 IOTakeLock( gArbitrationLockQueueLock
);
1181 // find the lock element for this object (ie. on active queue)
1183 queue_iterate( &gArbitrationLockQueueActive
,
1185 ArbitrationLockQueueElement
*,
1188 if( element
->service
== this ) {
1196 // determine whether the lock has been taken recursively
1197 if( element
->count
> 1 ) {
1198 // undo one level of recursion
1203 // remove it from the active queue
1204 queue_remove( &gArbitrationLockQueueActive
,
1206 ArbitrationLockQueueElement
*,
1209 // put it on the free queue
1210 queue_enter( &gArbitrationLockQueueFree
,
1212 ArbitrationLockQueueElement
*,
1215 // determine whether a thread is waiting for object (head to tail scan)
1217 queue_iterate( &gArbitrationLockQueueWaiting
,
1219 ArbitrationLockQueueElement
*,
1222 if( element
->service
== this ) {
1228 if ( found
) { // we found an interested thread on waiting queue
1230 // remove it from the waiting queue
1231 queue_remove( &gArbitrationLockQueueWaiting
,
1233 ArbitrationLockQueueElement
*,
1236 // put it on the active queue
1237 queue_enter( &gArbitrationLockQueueActive
,
1239 ArbitrationLockQueueElement
*,
1242 // wake the waiting thread
1243 IOLockWakeup( gArbitrationLockQueueLock
,
1245 /* one thread */ true );
1249 // unlock global access
1250 IOUnlock( gArbitrationLockQueueLock
);
1253 void IOService::applyToProviders( IOServiceApplierFunction applier
,
1256 applyToParents( (IORegistryEntryApplierFunction
) applier
,
1257 context
, gIOServicePlane
);
1260 void IOService::applyToClients( IOServiceApplierFunction applier
,
1263 applyToChildren( (IORegistryEntryApplierFunction
) applier
,
1264 context
, gIOServicePlane
);
1273 // send a message to a client or interested party of this service
1274 IOReturn
IOService::messageClient( UInt32 type
, OSObject
* client
,
1275 void * argument
, vm_size_t argSize
)
1278 IOService
* service
;
1279 _IOServiceInterestNotifier
* notify
;
1281 if( (service
= OSDynamicCast( IOService
, client
)))
1282 ret
= service
->message( type
, this, argument
);
1284 else if( (notify
= OSDynamicCast( _IOServiceInterestNotifier
, client
))) {
1286 _IOServiceNotifierInvocation invocation
;
1289 invocation
.thread
= current_thread();
1292 willNotify
= (0 != (kIOServiceNotifyEnable
& notify
->state
));
1295 queue_enter( ¬ify
->handlerInvocations
, &invocation
,
1296 _IOServiceNotifierInvocation
*, link
);
1302 ret
= (*notify
->handler
)( notify
->target
, notify
->ref
,
1303 type
, this, argument
, argSize
);
1306 queue_remove( ¬ify
->handlerInvocations
, &invocation
,
1307 _IOServiceNotifierInvocation
*, link
);
1308 if( kIOServiceNotifyWaiter
& notify
->state
) {
1309 notify
->state
&= ~kIOServiceNotifyWaiter
;
1310 WAKEUPNOTIFY( notify
);
1315 ret
= kIOReturnSuccess
;
1318 ret
= kIOReturnBadArgument
;
1324 applyToInterestNotifiers(const IORegistryEntry
*target
,
1325 const OSSymbol
* typeOfInterest
,
1326 OSObjectApplierFunction applier
,
1329 OSArray
* copyArray
= 0;
1333 IOCommand
*notifyList
=
1334 OSDynamicCast( IOCommand
, target
->getProperty( typeOfInterest
));
1337 copyArray
= OSArray::withCapacity(1);
1339 // iterate over queue, entry is set to each element in the list
1340 iterqueue(¬ifyList
->fCommandChain
, entry
) {
1341 _IOServiceInterestNotifier
* notify
;
1343 queue_element(entry
, notify
, _IOServiceInterestNotifier
*, chain
);
1344 copyArray
->setObject(notify
);
1353 for( index
= 0; (next
= copyArray
->getObject( index
)); index
++)
1354 (*applier
)(next
, context
);
1355 copyArray
->release();
1359 void IOService::applyToInterested( const OSSymbol
* typeOfInterest
,
1360 OSObjectApplierFunction applier
,
1363 if (gIOGeneralInterest
== typeOfInterest
)
1364 applyToClients( (IOServiceApplierFunction
) applier
, context
);
1365 applyToInterestNotifiers(this, typeOfInterest
, applier
, context
);
1368 struct MessageClientsContext
{
1369 IOService
* service
;
1376 static void messageClientsApplier( OSObject
* object
, void * ctx
)
1379 MessageClientsContext
* context
= (MessageClientsContext
*) ctx
;
1381 ret
= context
->service
->messageClient( context
->type
,
1382 object
, context
->argument
, context
->argSize
);
1383 if( kIOReturnSuccess
!= ret
)
1387 // send a message to all clients
1388 IOReturn
IOService::messageClients( UInt32 type
,
1389 void * argument
, vm_size_t argSize
)
1391 MessageClientsContext context
;
1393 context
.service
= this;
1394 context
.type
= type
;
1395 context
.argument
= argument
;
1396 context
.argSize
= argSize
;
1397 context
.ret
= kIOReturnSuccess
;
1399 applyToInterested( gIOGeneralInterest
,
1400 &messageClientsApplier
, &context
);
1402 return( context
.ret
);
1405 IOReturn
IOService::acknowledgeNotification( IONotificationRef notification
,
1406 IOOptionBits response
)
1408 return( kIOReturnUnsupported
);
1411 IONotifier
* IOService::registerInterest( const OSSymbol
* typeOfInterest
,
1412 IOServiceInterestHandler handler
, void * target
, void * ref
)
1414 _IOServiceInterestNotifier
* notify
= 0;
1416 if( (typeOfInterest
!= gIOGeneralInterest
)
1417 && (typeOfInterest
!= gIOBusyInterest
)
1418 && (typeOfInterest
!= gIOAppPowerStateInterest
)
1419 && (typeOfInterest
!= gIOPriorityPowerStateInterest
))
1422 lockForArbitration();
1423 if( 0 == (__state
[0] & kIOServiceInactiveState
)) {
1425 notify
= new _IOServiceInterestNotifier
;
1426 if( notify
&& !notify
->init()) {
1432 notify
->handler
= handler
;
1433 notify
->target
= target
;
1435 notify
->state
= kIOServiceNotifyEnable
;
1436 queue_init( ¬ify
->handlerInvocations
);
1442 // Get the head of the notifier linked list
1443 IOCommand
*notifyList
= (IOCommand
*) getProperty( typeOfInterest
);
1444 if (!notifyList
|| !OSDynamicCast(IOCommand
, notifyList
)) {
1445 notifyList
= OSTypeAlloc(IOCommand
);
1448 setProperty( typeOfInterest
, notifyList
);
1449 notifyList
->release();
1454 enqueue(¬ifyList
->fCommandChain
, ¬ify
->chain
);
1455 notify
->retain(); // ref'ed while in list
1461 unlockForArbitration();
1466 static void cleanInterestList( OSObject
* head
)
1468 IOCommand
*notifyHead
= OSDynamicCast(IOCommand
, head
);
1473 while ( queue_entry_t entry
= dequeue(¬ifyHead
->fCommandChain
) ) {
1474 queue_next(entry
) = queue_prev(entry
) = 0;
1476 _IOServiceInterestNotifier
* notify
;
1478 queue_element(entry
, notify
, _IOServiceInterestNotifier
*, chain
);
1484 void IOService::unregisterAllInterest( void )
1486 cleanInterestList( getProperty( gIOGeneralInterest
));
1487 cleanInterestList( getProperty( gIOBusyInterest
));
1488 cleanInterestList( getProperty( gIOAppPowerStateInterest
));
1489 cleanInterestList( getProperty( gIOPriorityPowerStateInterest
));
1493 * _IOServiceInterestNotifier
1496 // wait for all threads, other than the current one,
1497 // to exit the handler
1499 void _IOServiceInterestNotifier::wait()
1501 _IOServiceNotifierInvocation
* next
;
1506 queue_iterate( &handlerInvocations
, next
,
1507 _IOServiceNotifierInvocation
*, link
) {
1508 if( next
->thread
!= current_thread() ) {
1514 state
|= kIOServiceNotifyWaiter
;
1521 void _IOServiceInterestNotifier::free()
1523 assert( queue_empty( &handlerInvocations
));
1527 void _IOServiceInterestNotifier::remove()
1531 if( queue_next( &chain
)) {
1532 remqueue( 0, &chain
);
1533 queue_next( &chain
) = queue_prev( &chain
) = 0;
1537 state
&= ~kIOServiceNotifyEnable
;
1546 bool _IOServiceInterestNotifier::disable()
1552 ret
= (0 != (kIOServiceNotifyEnable
& state
));
1553 state
&= ~kIOServiceNotifyEnable
;
1562 void _IOServiceInterestNotifier::enable( bool was
)
1566 state
|= kIOServiceNotifyEnable
;
1568 state
&= ~kIOServiceNotifyEnable
;
1572 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1578 #define tailQ(o) setObject(o)
1579 #define headQ(o) setObject(0, o)
1580 #define TLOG(fmt, args...) { if(kIOLogYield & gIOKitDebug) IOLog(fmt, ## args); }
1582 inline void _workLoopAction( IOWorkLoop::Action action
,
1583 IOService
* service
,
1584 void * p0
= 0, void * p1
= 0,
1585 void * p2
= 0, void * p3
= 0 )
1589 if( (wl
= service
->getWorkLoop())) {
1591 wl
->runAction( action
, service
, p0
, p1
, p2
, p3
);
1594 (*action
)( service
, p0
, p1
, p2
, p3
);
1597 bool IOService::requestTerminate( IOService
* provider
, IOOptionBits options
)
1601 // if its our only provider
1602 ok
= isParent( provider
, gIOServicePlane
, true);
1606 provider
->terminateClient( this, options
| kIOServiceRecursing
);
1607 ok
= (0 != (__state
[1] & kIOServiceRecursing
));
1614 bool IOService::terminatePhase1( IOOptionBits options
)
1619 OSArray
* makeInactive
;
1622 bool startPhase2
= false;
1624 TLOG("%s::terminatePhase1(%08lx)\n", getName(), options
);
1627 if( options
& kIOServiceRecursing
) {
1628 __state
[1] |= kIOServiceRecursing
;
1633 makeInactive
= OSArray::withCapacity( 16 );
1642 didInactive
= victim
->lockForArbitration( true );
1644 didInactive
= (0 == (victim
->__state
[0] & kIOServiceInactiveState
));
1646 victim
->__state
[0] |= kIOServiceInactiveState
;
1647 victim
->__state
[0] &= ~(kIOServiceRegisteredState
| kIOServiceMatchedState
1648 | kIOServiceFirstPublishState
| kIOServiceFirstMatchState
);
1649 victim
->_adjustBusy( 1 );
1651 victim
->unlockForArbitration();
1654 startPhase2
= didInactive
;
1657 victim
->deliverNotification( gIOTerminatedNotification
, 0, 0xffffffff );
1658 IOUserClient::destroyUserReferences( victim
);
1660 iter
= victim
->getClientIterator();
1662 while( (client
= (IOService
*) iter
->getNextObject())) {
1663 TLOG("%s::requestTerminate(%s, %08lx)\n",
1664 client
->getName(), victim
->getName(), options
);
1665 ok
= client
->requestTerminate( victim
, options
);
1666 TLOG("%s::requestTerminate(%s, ok = %d)\n",
1667 client
->getName(), victim
->getName(), ok
);
1669 makeInactive
->setObject( client
);
1675 victim
= (IOService
*) makeInactive
->getObject(0);
1678 makeInactive
->removeObject(0);
1682 makeInactive
->release();
1685 scheduleTerminatePhase2( options
);
1690 void IOService::scheduleTerminatePhase2( IOOptionBits options
)
1692 AbsoluteTime deadline
;
1693 int waitResult
= THREAD_AWAKENED
;
1694 bool wait
, haveDeadline
= false;
1696 options
|= kIOServiceRequired
;
1700 IOLockLock( gJobsLock
);
1702 if( (options
& kIOServiceSynchronous
)
1703 && (current_thread() != gIOTerminateThread
)) {
1706 wait
= (gIOTerminateThread
!= 0);
1708 // wait to become the terminate thread
1709 IOLockSleep( gJobsLock
, &gIOTerminateThread
, THREAD_UNINT
);
1713 gIOTerminateThread
= current_thread();
1714 gIOTerminatePhase2List
->setObject( this );
1718 while( gIOTerminateWork
)
1719 terminateWorker( options
);
1720 wait
= (0 != (__state
[1] & kIOServiceBusyStateMask
));
1722 // wait for the victim to go non-busy
1723 if( !haveDeadline
) {
1724 clock_interval_to_deadline( 15, kSecondScale
, &deadline
);
1725 haveDeadline
= true;
1727 waitResult
= IOLockSleepDeadline( gJobsLock
, &gIOTerminateWork
,
1728 deadline
, THREAD_UNINT
);
1729 if( waitResult
== THREAD_TIMED_OUT
) {
1730 TLOG("%s::terminate(kIOServiceSynchronous) timeout", getName());
1733 } while(gIOTerminateWork
|| (wait
&& (waitResult
!= THREAD_TIMED_OUT
)));
1735 gIOTerminateThread
= 0;
1736 IOLockWakeup( gJobsLock
, (event_t
) &gIOTerminateThread
, /* one-thread */ false);
1739 // ! kIOServiceSynchronous
1741 gIOTerminatePhase2List
->setObject( this );
1742 if( 0 == gIOTerminateWork
++) {
1743 if( !gIOTerminateThread
)
1744 gIOTerminateThread
= IOCreateThread( &terminateThread
, (void *) options
);
1746 IOLockWakeup(gJobsLock
, (event_t
) &gIOTerminateWork
, /* one-thread */ false );
1750 IOLockUnlock( gJobsLock
);
1755 void IOService::terminateThread( void * arg
)
1757 IOLockLock( gJobsLock
);
1759 while (gIOTerminateWork
)
1760 terminateWorker( (IOOptionBits
) arg
);
1762 gIOTerminateThread
= 0;
1763 IOLockWakeup( gJobsLock
, (event_t
) &gIOTerminateThread
, /* one-thread */ false);
1765 IOLockUnlock( gJobsLock
);
1768 void IOService::scheduleStop( IOService
* provider
)
1770 TLOG("%s::scheduleStop(%s)\n", getName(), provider
->getName());
1772 IOLockLock( gJobsLock
);
1773 gIOStopList
->tailQ( this );
1774 gIOStopProviderList
->tailQ( provider
);
1776 if( 0 == gIOTerminateWork
++) {
1777 if( !gIOTerminateThread
)
1778 gIOTerminateThread
= IOCreateThread( &terminateThread
, (void *) 0 );
1780 IOLockWakeup(gJobsLock
, (event_t
) &gIOTerminateWork
, /* one-thread */ false );
1783 IOLockUnlock( gJobsLock
);
1786 void IOService::scheduleFinalize( void )
1788 TLOG("%s::scheduleFinalize\n", getName());
1790 IOLockLock( gJobsLock
);
1791 gIOFinalizeList
->tailQ( this );
1793 if( 0 == gIOTerminateWork
++) {
1794 if( !gIOTerminateThread
)
1795 gIOTerminateThread
= IOCreateThread( &terminateThread
, (void *) 0 );
1797 IOLockWakeup(gJobsLock
, (event_t
) &gIOTerminateWork
, /* one-thread */ false );
1800 IOLockUnlock( gJobsLock
);
1803 bool IOService::willTerminate( IOService
* provider
, IOOptionBits options
)
1808 bool IOService::didTerminate( IOService
* provider
, IOOptionBits options
, bool * defer
)
1810 if( false == *defer
) {
1812 if( lockForArbitration( true )) {
1813 if( false == provider
->handleIsOpen( this ))
1814 scheduleStop( provider
);
1817 message( kIOMessageServiceIsRequestingClose
, provider
, (void *) options
);
1818 if( false == provider
->handleIsOpen( this ))
1819 scheduleStop( provider
);
1822 unlockForArbitration();
1829 void IOService::actionWillTerminate( IOService
* victim
, IOOptionBits options
,
1830 OSArray
* doPhase2List
)
1836 iter
= victim
->getClientIterator();
1838 while( (client
= (IOService
*) iter
->getNextObject())) {
1839 TLOG("%s::willTerminate(%s, %08lx)\n",
1840 client
->getName(), victim
->getName(), options
);
1841 ok
= client
->willTerminate( victim
, options
);
1842 doPhase2List
->tailQ( client
);
1848 void IOService::actionDidTerminate( IOService
* victim
, IOOptionBits options
)
1854 victim
->messageClients( kIOMessageServiceIsTerminated
, (void *) options
);
1856 iter
= victim
->getClientIterator();
1858 while( (client
= (IOService
*) iter
->getNextObject())) {
1859 TLOG("%s::didTerminate(%s, %08lx)\n",
1860 client
->getName(), victim
->getName(), options
);
1861 client
->didTerminate( victim
, options
, &defer
);
1862 TLOG("%s::didTerminate(%s, defer %d)\n",
1863 client
->getName(), victim
->getName(), defer
);
1869 void IOService::actionFinalize( IOService
* victim
, IOOptionBits options
)
1871 TLOG("%s::finalize(%08lx)\n", victim
->getName(), options
);
1872 victim
->finalize( options
);
1875 void IOService::actionStop( IOService
* provider
, IOService
* client
)
1877 TLOG("%s::stop(%s)\n", client
->getName(), provider
->getName());
1878 client
->stop( provider
);
1879 if( provider
->isOpen( client
))
1880 provider
->close( client
);
1881 TLOG("%s::detach(%s)\n", client
->getName(), provider
->getName());
1882 client
->detach( provider
);
1885 void IOService::terminateWorker( IOOptionBits options
)
1887 OSArray
* doPhase2List
;
1888 OSArray
* didPhase2List
;
1893 IOService
* provider
;
1899 options
|= kIOServiceRequired
;
1901 doPhase2List
= OSArray::withCapacity( 16 );
1902 didPhase2List
= OSArray::withCapacity( 16 );
1903 freeList
= OSSet::withCapacity( 16 );
1904 if( (0 == doPhase2List
) || (0 == didPhase2List
) || (0 == freeList
))
1908 workDone
= gIOTerminateWork
;
1910 while( (victim
= (IOService
*) gIOTerminatePhase2List
->getObject(0) )) {
1913 gIOTerminatePhase2List
->removeObject(0);
1914 IOLockUnlock( gJobsLock
);
1918 doPhase2
= victim
->lockForArbitration( true );
1920 doPhase2
= (0 != (kIOServiceInactiveState
& victim
->__state
[0]));
1922 doPhase2
= (0 == (victim
->__state
[1] & kIOServiceTermPhase2State
))
1923 && (0 == (victim
->__state
[1] & kIOServiceConfigState
));
1925 victim
->__state
[1] |= kIOServiceTermPhase2State
;
1927 victim
->unlockForArbitration();
1930 if( 0 == victim
->getClient()) {
1931 // no clients - will go to finalize
1932 IOLockLock( gJobsLock
);
1933 gIOFinalizeList
->tailQ( victim
);
1934 IOLockUnlock( gJobsLock
);
1936 _workLoopAction( (IOWorkLoop::Action
) &actionWillTerminate
,
1937 victim
, (void *) options
, (void *) doPhase2List
);
1939 didPhase2List
->headQ( victim
);
1942 victim
= (IOService
*) doPhase2List
->getObject(0);
1945 doPhase2List
->removeObject(0);
1949 while( (victim
= (IOService
*) didPhase2List
->getObject(0)) ) {
1951 if( victim
->lockForArbitration( true )) {
1952 victim
->__state
[1] |= kIOServiceTermPhase3State
;
1953 victim
->unlockForArbitration();
1955 _workLoopAction( (IOWorkLoop::Action
) &actionDidTerminate
,
1956 victim
, (void *) options
);
1957 didPhase2List
->removeObject(0);
1959 IOLockLock( gJobsLock
);
1966 while( (victim
= (IOService
*) gIOFinalizeList
->getObject(0))) {
1968 IOLockUnlock( gJobsLock
);
1969 _workLoopAction( (IOWorkLoop::Action
) &actionFinalize
,
1970 victim
, (void *) options
);
1971 IOLockLock( gJobsLock
);
1973 freeList
->setObject( victim
);
1974 // safe if finalize list is append only
1975 gIOFinalizeList
->removeObject(0);
1979 (!doPhase3
) && (client
= (IOService
*) gIOStopList
->getObject(idx
)); ) {
1981 provider
= (IOService
*) gIOStopProviderList
->getObject(idx
);
1984 if( !provider
->isChild( client
, gIOServicePlane
)) {
1985 // may be multiply queued - nop it
1986 TLOG("%s::nop stop(%s)\n", client
->getName(), provider
->getName());
1988 // not ready for stop if it has clients, skip it
1989 if( (client
->__state
[1] & kIOServiceTermPhase3State
) && client
->getClient()) {
1990 TLOG("%s::defer stop(%s)\n", client
->getName(), provider
->getName());
1995 IOLockUnlock( gJobsLock
);
1996 _workLoopAction( (IOWorkLoop::Action
) &actionStop
,
1997 provider
, (void *) client
);
1998 IOLockLock( gJobsLock
);
1999 // check the finalize list now
2003 freeList
->setObject( client
);
2004 freeList
->setObject( provider
);
2006 // safe if stop list is append only
2007 gIOStopList
->removeObject( idx
);
2008 gIOStopProviderList
->removeObject( idx
);
2012 } while( doPhase3
);
2014 gIOTerminateWork
-= workDone
;
2015 moreToDo
= (gIOTerminateWork
!= 0);
2018 TLOG("iokit terminate done, %d stops remain\n", gIOStopList
->getCount());
2021 } while( moreToDo
);
2023 IOLockUnlock( gJobsLock
);
2025 freeList
->release();
2026 doPhase2List
->release();
2027 didPhase2List
->release();
2029 IOLockLock( gJobsLock
);
2032 bool IOService::finalize( IOOptionBits options
)
2035 IOService
* provider
;
2037 iter
= getProviderIterator();
2041 while( (provider
= (IOService
*) iter
->getNextObject())) {
2044 if( 0 == (__state
[1] & kIOServiceTermPhase3State
)) {
2045 /* we come down here on programmatic terminate */
2047 if( provider
->isOpen( this ))
2048 provider
->close( this );
2052 if( provider
->lockForArbitration( true )) {
2053 if( 0 == (provider
->__state
[1] & kIOServiceTermPhase3State
))
2054 scheduleStop( provider
);
2055 provider
->unlockForArbitration();
2072 void IOService::doServiceTerminate( IOOptionBits options
)
2076 // a method in case someone needs to override it
2077 bool IOService::terminateClient( IOService
* client
, IOOptionBits options
)
2081 if( client
->isParent( this, gIOServicePlane
, true))
2082 // we are the clients only provider
2083 ok
= client
->terminate( options
);
2090 bool IOService::terminate( IOOptionBits options
)
2092 options
|= kIOServiceTerminate
;
2094 return( terminatePhase1( options
));
2097 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2103 struct ServiceOpenMessageContext
2105 IOService
* service
;
2107 IOService
* excludeClient
;
2108 IOOptionBits options
;
2111 static void serviceOpenMessageApplier( OSObject
* object
, void * ctx
)
2113 ServiceOpenMessageContext
* context
= (ServiceOpenMessageContext
*) ctx
;
2115 if( object
!= context
->excludeClient
)
2116 context
->service
->messageClient( context
->type
, object
, (void *) context
->options
);
2119 bool IOService::open( IOService
* forClient
,
2120 IOOptionBits options
,
2124 ServiceOpenMessageContext context
;
2126 context
.service
= this;
2127 context
.type
= kIOMessageServiceIsAttemptingOpen
;
2128 context
.excludeClient
= forClient
;
2129 context
.options
= options
;
2131 applyToInterested( gIOGeneralInterest
,
2132 &serviceOpenMessageApplier
, &context
);
2134 if( false == lockForArbitration(false) )
2137 ok
= (0 == (__state
[0] & kIOServiceInactiveState
));
2139 ok
= handleOpen( forClient
, options
, arg
);
2141 unlockForArbitration();
2146 void IOService::close( IOService
* forClient
,
2147 IOOptionBits options
)
2152 lockForArbitration();
2154 wasClosed
= handleIsOpen( forClient
);
2156 handleClose( forClient
, options
);
2157 last
= (__state
[1] & kIOServiceTermPhase3State
);
2160 unlockForArbitration();
2163 forClient
->scheduleStop( this );
2165 else if( wasClosed
) {
2167 ServiceOpenMessageContext context
;
2169 context
.service
= this;
2170 context
.type
= kIOMessageServiceWasClosed
;
2171 context
.excludeClient
= forClient
;
2172 context
.options
= options
;
2174 applyToInterested( gIOGeneralInterest
,
2175 &serviceOpenMessageApplier
, &context
);
2179 bool IOService::isOpen( const IOService
* forClient
) const
2181 IOService
* self
= (IOService
*) this;
2184 self
->lockForArbitration();
2186 ok
= handleIsOpen( forClient
);
2188 self
->unlockForArbitration();
2193 bool IOService::handleOpen( IOService
* forClient
,
2194 IOOptionBits options
,
2199 ok
= (0 == __owner
);
2201 __owner
= forClient
;
2203 else if( options
& kIOServiceSeize
) {
2204 ok
= (kIOReturnSuccess
== messageClient( kIOMessageServiceIsRequestingClose
,
2205 __owner
, (void *) options
));
2206 if( ok
&& (0 == __owner
))
2207 __owner
= forClient
;
2214 void IOService::handleClose( IOService
* forClient
,
2215 IOOptionBits options
)
2217 if( __owner
== forClient
)
2221 bool IOService::handleIsOpen( const IOService
* forClient
) const
2224 return( __owner
== forClient
);
2226 return( __owner
!= forClient
);
2230 * Probing & starting
2232 static SInt32
IONotifyOrdering( const OSMetaClassBase
* inObj1
, const OSMetaClassBase
* inObj2
, void * ref
)
2234 const _IOServiceNotifier
* obj1
= (const _IOServiceNotifier
*) inObj1
;
2235 const _IOServiceNotifier
* obj2
= (const _IOServiceNotifier
*) inObj2
;
2243 val1
= obj1
->priority
;
2246 val2
= obj2
->priority
;
2248 return ( val1
- val2
);
2251 static SInt32
IOServiceObjectOrder( const OSObject
* entry
, void * ref
)
2253 OSDictionary
* dict
;
2254 IOService
* service
;
2255 _IOServiceNotifier
* notify
;
2256 OSSymbol
* key
= (OSSymbol
*) ref
;
2259 if( (notify
= OSDynamicCast( _IOServiceNotifier
, entry
)))
2260 return( notify
->priority
);
2262 else if( (service
= OSDynamicCast( IOService
, entry
)))
2263 offset
= OSDynamicCast(OSNumber
, service
->getProperty( key
));
2264 else if( (dict
= OSDynamicCast( OSDictionary
, entry
)))
2265 offset
= OSDynamicCast(OSNumber
, dict
->getObject( key
));
2272 return( (SInt32
) offset
->unsigned32BitValue());
2274 return( kIODefaultProbeScore
);
2277 SInt32
IOServiceOrdering( const OSMetaClassBase
* inObj1
, const OSMetaClassBase
* inObj2
, void * ref
)
2279 const OSObject
* obj1
= (const OSObject
*) inObj1
;
2280 const OSObject
* obj2
= (const OSObject
*) inObj2
;
2288 val1
= IOServiceObjectOrder( obj1
, ref
);
2291 val2
= IOServiceObjectOrder( obj2
, ref
);
2293 return ( val1
- val2
);
2296 IOService
* IOService::getClientWithCategory( const OSSymbol
* category
)
2298 IOService
* service
= 0;
2300 const OSSymbol
* nextCat
;
2302 iter
= getClientIterator();
2304 while( (service
= (IOService
*) iter
->getNextObject())) {
2305 if( kIOServiceInactiveState
& service
->__state
[0])
2307 nextCat
= (const OSSymbol
*) OSDynamicCast( OSSymbol
,
2308 service
->getProperty( gIOMatchCategoryKey
));
2309 if( category
== nextCat
)
2317 bool IOService::invokeNotifer( _IOServiceNotifier
* notify
)
2319 _IOServiceNotifierInvocation invocation
;
2323 invocation
.thread
= current_thread();
2326 willNotify
= (0 != (kIOServiceNotifyEnable
& notify
->state
));
2329 queue_enter( ¬ify
->handlerInvocations
, &invocation
,
2330 _IOServiceNotifierInvocation
*, link
);
2336 ret
= (*notify
->handler
)( notify
->target
, notify
->ref
, this );
2339 queue_remove( ¬ify
->handlerInvocations
, &invocation
,
2340 _IOServiceNotifierInvocation
*, link
);
2341 if( kIOServiceNotifyWaiter
& notify
->state
) {
2342 notify
->state
&= ~kIOServiceNotifyWaiter
;
2343 WAKEUPNOTIFY( notify
);
2352 * Alloc and probe matching classes,
2353 * called on the provider instance
2356 void IOService::probeCandidates( OSOrderedSet
* matches
)
2358 OSDictionary
* match
= 0;
2361 IOService
* newInst
;
2362 OSDictionary
* props
;
2365 OSOrderedSet
* familyMatches
= 0;
2366 OSOrderedSet
* startList
;
2367 OSDictionary
* startDict
= 0;
2368 const OSSymbol
* category
;
2370 _IOServiceNotifier
* notify
;
2371 OSObject
* nextMatch
= 0;
2373 bool needReloc
= false;
2374 #if CONFIG_MACF_KEXT
2375 OSBoolean
* isSandbox
= 0;
2376 bool useSandbox
= false;
2383 while( !needReloc
&& (nextMatch
= matches
->getFirstObject())) {
2385 nextMatch
->retain();
2386 matches
->removeObject(nextMatch
);
2388 if( (notify
= OSDynamicCast( _IOServiceNotifier
, nextMatch
))) {
2390 lockForArbitration();
2391 if( 0 == (__state
[0] & kIOServiceInactiveState
))
2392 invokeNotifer( notify
);
2393 unlockForArbitration();
2394 nextMatch
->release();
2398 } else if( !(match
= OSDynamicCast( OSDictionary
, nextMatch
))) {
2399 nextMatch
->release();
2406 debugFlags
= getDebugFlags( match
);
2410 category
= OSDynamicCast( OSSymbol
,
2411 match
->getObject( gIOMatchCategoryKey
));
2413 category
= gIODefaultMatchCategoryKey
;
2415 if( getClientWithCategory( category
)) {
2417 if( debugFlags
& kIOLogMatch
)
2418 LOG("%s: match category %s exists\n", getName(),
2419 category
->getCStringNoCopy());
2421 nextMatch
->release();
2426 // create a copy now in case its modified during matching
2427 props
= OSDictionary::withDictionary( match
, match
->getCount());
2430 props
->setCapacityIncrement(1);
2432 // check the nub matches
2433 if( false == passiveMatch( props
, true ))
2436 // Check to see if driver reloc has been loaded.
2437 needReloc
= (false == gIOCatalogue
->isModuleLoaded( match
));
2440 if( debugFlags
& kIOLogCatalogue
)
2441 LOG("%s: stalling for module\n", getName());
2443 // If reloc hasn't been loaded, exit;
2444 // reprobing will occur after reloc has been loaded.
2448 // reorder on family matchPropertyTable score.
2449 if( 0 == familyMatches
)
2450 familyMatches
= OSOrderedSet::withCapacity( 1,
2451 IOServiceOrdering
, (void *) gIOProbeScoreKey
);
2453 familyMatches
->setObject( props
);
2458 nextMatch
->release();
2467 if( familyMatches
) {
2470 && (props
= (OSDictionary
*) familyMatches
->getFirstObject())) {
2473 familyMatches
->removeObject( props
);
2478 debugFlags
= getDebugFlags( props
);
2481 symbol
= OSDynamicCast( OSSymbol
,
2482 props
->getObject( gIOClassKey
));
2486 //IOLog("%s alloc (symbol %p props %p)\n", symbol->getCStringNoCopy(), symbol, props);
2488 // alloc the driver instance
2489 inst
= (IOService
*) OSMetaClass::allocClassWithName( symbol
);
2492 IOLog("Couldn't alloc class \"%s\"\n",
2493 symbol
->getCStringNoCopy());
2497 // init driver instance
2498 if( !(inst
->init( props
))) {
2500 if( debugFlags
& kIOLogStart
)
2501 IOLog("%s::init fails\n", symbol
->getCStringNoCopy());
2505 if( __state
[1] & kIOServiceSynchronousState
)
2506 inst
->__state
[1] |= kIOServiceSynchronousState
;
2508 // give the driver the default match category if not specified
2509 category
= OSDynamicCast( OSSymbol
,
2510 props
->getObject( gIOMatchCategoryKey
));
2512 category
= gIODefaultMatchCategoryKey
;
2513 inst
->setProperty( gIOMatchCategoryKey
, (OSObject
*) category
);
2514 #if CONFIG_MACF_KEXT
2515 isSandbox
= OSDynamicCast(OSBoolean
,
2516 props
->getObject("IOKitForceMatch"));
2518 // attach driver instance
2519 if( !(inst
->attach( this )))
2522 // pass in score from property table
2523 score
= familyMatches
->orderObject( props
);
2525 // & probe the new driver instance
2527 if( debugFlags
& kIOLogProbe
)
2528 LOG("%s::probe(%s)\n",
2529 inst
->getMetaClass()->getClassName(), getName());
2532 newInst
= inst
->probe( this, &score
);
2533 inst
->detach( this );
2534 #if CONFIG_MACF_KEXT
2536 * If this is the Sandbox driver and it matched, this is a
2537 * disallowed device; toss any drivers that were already
2540 if (isSandbox
&& isSandbox
->isTrue() && newInst
!= 0) {
2541 if (startDict
!= 0) {
2542 startDict
->flushCollection();
2543 startDict
->release();
2551 if( debugFlags
& kIOLogProbe
)
2552 IOLog("%s::probe fails\n", symbol
->getCStringNoCopy());
2558 newPri
= OSNumber::withNumber( score
, 32 );
2560 newInst
->setProperty( gIOProbeScoreKey
, newPri
);
2564 // add to start list for the match category
2566 startDict
= OSDictionary::withCapacity( 1 );
2567 assert( startDict
);
2568 startList
= (OSOrderedSet
*)
2569 startDict
->getObject( category
);
2570 if( 0 == startList
) {
2571 startList
= OSOrderedSet::withCapacity( 1,
2572 IOServiceOrdering
, (void *) gIOProbeScoreKey
);
2573 if( startDict
&& startList
) {
2574 startDict
->setObject( category
, startList
);
2575 startList
->release();
2578 assert( startList
);
2580 startList
->setObject( newInst
);
2587 #if CONFIG_MACF_KEXT
2589 * If we're forcing the sandbox, drop out of the loop.
2591 if (isSandbox
&& isSandbox
->isTrue() && useSandbox
)
2595 familyMatches
->release();
2599 // start the best (until success) of each category
2601 iter
= OSCollectionIterator::withCollection( startDict
);
2603 while( (category
= (const OSSymbol
*) iter
->getNextObject())) {
2605 startList
= (OSOrderedSet
*) startDict
->getObject( category
);
2606 assert( startList
);
2611 while( true // (!started)
2612 && (inst
= (IOService
*)startList
->getFirstObject())) {
2615 startList
->removeObject(inst
);
2618 debugFlags
= getDebugFlags( inst
->getPropertyTable() );
2620 if( debugFlags
& kIOLogStart
) {
2622 LOG( "match category exists, skipping " );
2623 LOG( "%s::start(%s) <%d>\n", inst
->getName(),
2624 getName(), inst
->getRetainCount());
2627 if( false == started
)
2628 started
= startCandidate( inst
);
2630 if( (debugFlags
& kIOLogStart
) && (false == started
))
2631 LOG( "%s::start(%s) <%d> failed\n", inst
->getName(), getName(),
2632 inst
->getRetainCount());
2641 // adjust the busy count by -1 if matching is stalled for a module,
2642 // or +1 if a previously stalled matching is complete.
2643 lockForArbitration();
2646 adjBusy
= (__state
[1] & kIOServiceModuleStallState
) ? 0 : 1;
2648 __state
[1] |= kIOServiceModuleStallState
;
2650 } else if( __state
[1] & kIOServiceModuleStallState
) {
2651 __state
[1] &= ~kIOServiceModuleStallState
;
2655 _adjustBusy( adjBusy
);
2656 unlockForArbitration();
2659 startDict
->release();
2663 * Start a previously attached & probed instance,
2664 * called on exporting object instance
2667 bool IOService::startCandidate( IOService
* service
)
2671 ok
= service
->attach( this );
2675 if (this != gIOResources
)
2677 // stall for any nub resources
2679 // stall for any driver resources
2680 service
->checkResources();
2683 AbsoluteTime startTime
;
2684 AbsoluteTime endTime
;
2687 if (kIOLogStart
& gIOKitDebug
)
2688 clock_get_uptime(&startTime
);
2690 ok
= service
->start(this);
2692 if (kIOLogStart
& gIOKitDebug
)
2694 clock_get_uptime(&endTime
);
2696 if (CMP_ABSOLUTETIME(&endTime
, &startTime
) > 0)
2698 SUB_ABSOLUTETIME(&endTime
, &startTime
);
2699 absolutetime_to_nanoseconds(endTime
, &nano
);
2700 if (nano
> 500000000ULL)
2701 IOLog("%s::start took %ld ms\n", service
->getName(), (UInt32
)(nano
/ 1000000ULL));
2705 service
->detach( this );
2710 IOService
* IOService::resources( void )
2712 return( gIOResources
);
2715 void IOService::publishResource( const char * key
, OSObject
* value
)
2717 const OSSymbol
* sym
;
2719 if( (sym
= OSSymbol::withCString( key
))) {
2720 publishResource( sym
, value
);
2725 void IOService::publishResource( const OSSymbol
* key
, OSObject
* value
)
2728 value
= (OSObject
*) gIOServiceKey
;
2730 gIOResources
->setProperty( key
, value
);
2732 if( IORecursiveLockHaveLock( gNotificationLock
))
2735 gIOResourceGenerationCount
++;
2736 gIOResources
->registerService();
2739 bool IOService::addNeededResource( const char * key
)
2741 OSObject
* resourcesProp
;
2746 resourcesProp
= getProperty( gIOResourceMatchKey
);
2748 newKey
= OSString::withCString( key
);
2749 if( (0 == resourcesProp
) || (0 == newKey
))
2752 set
= OSDynamicCast( OSSet
, resourcesProp
);
2754 set
= OSSet::withCapacity( 1 );
2756 set
->setObject( resourcesProp
);
2761 set
->setObject( newKey
);
2763 ret
= setProperty( gIOResourceMatchKey
, set
);
2769 bool IOService::checkResource( OSObject
* matching
)
2772 OSDictionary
* table
;
2774 if( (str
= OSDynamicCast( OSString
, matching
))) {
2775 if( gIOResources
->getProperty( str
))
2780 table
= resourceMatching( str
);
2781 else if( (table
= OSDynamicCast( OSDictionary
, matching
)))
2784 IOLog("%s: Can't match using: %s\n", getName(),
2785 matching
->getMetaClass()->getClassName());
2786 /* false would stall forever */
2790 if( gIOKitDebug
& kIOLogConfig
)
2791 LOG("config(%x): stalling %s\n", (int) IOThreadSelf(), getName());
2793 waitForService( table
);
2795 if( gIOKitDebug
& kIOLogConfig
)
2796 LOG("config(%x): waking\n", (int) IOThreadSelf() );
2801 bool IOService::checkResources( void )
2803 OSObject
* resourcesProp
;
2808 resourcesProp
= getProperty( gIOResourceMatchKey
);
2809 if( 0 == resourcesProp
)
2812 if( (set
= OSDynamicCast( OSSet
, resourcesProp
))) {
2814 iter
= OSCollectionIterator::withCollection( set
);
2816 while( ok
&& (resourcesProp
= iter
->getNextObject()) )
2817 ok
= checkResource( resourcesProp
);
2822 ok
= checkResource( resourcesProp
);
2828 void _IOConfigThread::configThread( void )
2830 _IOConfigThread
* inst
;
2833 if( !(inst
= new _IOConfigThread
))
2837 if( !(IOCreateThread((IOThreadFunc
) &_IOConfigThread::main
, inst
)))
2850 void _IOConfigThread::free( void )
2855 void IOService::doServiceMatch( IOOptionBits options
)
2857 _IOServiceNotifier
* notify
;
2859 OSOrderedSet
* matches
;
2860 SInt32 catalogGeneration
;
2861 bool keepGuessing
= true;
2862 bool reRegistered
= true;
2864 // job->nub->deliverNotification( gIOPublishNotification,
2865 // kIOServiceRegisteredState, 0xffffffff );
2867 while( keepGuessing
) {
2869 matches
= gIOCatalogue
->findDrivers( this, &catalogGeneration
);
2870 // the matches list should always be created by findDrivers()
2873 lockForArbitration();
2874 if( 0 == (__state
[0] & kIOServiceFirstPublishState
))
2875 deliverNotification( gIOFirstPublishNotification
,
2876 kIOServiceFirstPublishState
, 0xffffffff );
2878 __state
[1] &= ~kIOServiceNeedConfigState
;
2879 __state
[1] |= kIOServiceConfigState
;
2880 __state
[0] |= kIOServiceRegisteredState
;
2882 if( reRegistered
&& (0 == (__state
[0] & kIOServiceInactiveState
))) {
2884 iter
= OSCollectionIterator::withCollection( (OSOrderedSet
*)
2885 gNotifications
->getObject( gIOPublishNotification
) );
2887 while((notify
= (_IOServiceNotifier
*)
2888 iter
->getNextObject())) {
2890 if( passiveMatch( notify
->matching
)
2891 && (kIOServiceNotifyEnable
& notify
->state
))
2892 matches
->setObject( notify
);
2899 unlockForArbitration();
2901 if( matches
->getCount() && (kIOReturnSuccess
== getResources()))
2902 probeCandidates( matches
);
2907 lockForArbitration();
2908 reRegistered
= (0 != (__state
[1] & kIOServiceNeedConfigState
));
2910 (reRegistered
|| (catalogGeneration
!=
2911 gIOCatalogue
->getGenerationCount()))
2912 && (0 == (__state
[0] & kIOServiceInactiveState
));
2915 unlockForArbitration();
2918 if( (0 == (__state
[0] & kIOServiceInactiveState
))
2919 && (0 == (__state
[1] & kIOServiceModuleStallState
)) ) {
2920 deliverNotification( gIOMatchedNotification
,
2921 kIOServiceMatchedState
, 0xffffffff );
2922 if( 0 == (__state
[0] & kIOServiceFirstMatchState
))
2923 deliverNotification( gIOFirstMatchNotification
,
2924 kIOServiceFirstMatchState
, 0xffffffff );
2927 __state
[1] &= ~kIOServiceConfigState
;
2928 if( __state
[0] & kIOServiceInactiveState
)
2929 scheduleTerminatePhase2();
2932 unlockForArbitration();
2935 UInt32
IOService::_adjustBusy( SInt32 delta
)
2940 bool wasQuiet
, nowQuiet
, needWake
;
2943 result
= __state
[1] & kIOServiceBusyStateMask
;
2947 next
->lockForArbitration();
2948 count
= next
->__state
[1] & kIOServiceBusyStateMask
;
2949 assert( count
< kIOServiceBusyMax
);
2950 wasQuiet
= (0 == count
);
2951 assert( (!wasQuiet
) || (delta
> 0));
2952 next
->__state
[1] += delta
;
2953 nowQuiet
= (0 == (next
->__state
[1] & kIOServiceBusyStateMask
));
2954 needWake
= (0 != (kIOServiceBusyWaiterState
& next
->__state
[1]));
2957 next
->__state
[1] &= ~kIOServiceBusyWaiterState
;
2958 IOLockLock( gIOServiceBusyLock
);
2959 thread_wakeup( (event_t
) next
);
2960 IOLockUnlock( gIOServiceBusyLock
);
2963 next
->unlockForArbitration();
2965 if( (wasQuiet
|| nowQuiet
) ) {
2966 MessageClientsContext context
;
2968 context
.service
= next
;
2969 context
.type
= kIOMessageServiceBusyStateChange
;
2970 context
.argument
= (void *) wasQuiet
; // busy now
2971 context
.argSize
= 0;
2973 applyToInterestNotifiers( next
, gIOBusyInterest
,
2974 &messageClientsApplier
, &context
);
2977 if( nowQuiet
&& (next
== gIOServiceRoot
))
2978 OSMetaClass::considerUnloads();
2982 delta
= nowQuiet
? -1 : +1;
2984 } while( (wasQuiet
|| nowQuiet
) && (next
= next
->getProvider()));
2989 void IOService::adjustBusy( SInt32 delta
)
2991 lockForArbitration();
2992 _adjustBusy( delta
);
2993 unlockForArbitration();
2996 UInt32
IOService::getBusyState( void )
2998 return( __state
[1] & kIOServiceBusyStateMask
);
3001 IOReturn
IOService::waitForState( UInt32 mask
, UInt32 value
,
3002 mach_timespec_t
* timeout
)
3005 int waitResult
= THREAD_AWAKENED
;
3006 bool computeDeadline
= true;
3007 AbsoluteTime abstime
;
3010 lockForArbitration();
3011 IOLockLock( gIOServiceBusyLock
);
3012 wait
= (value
!= (__state
[1] & mask
));
3014 __state
[1] |= kIOServiceBusyWaiterState
;
3015 unlockForArbitration();
3017 if( computeDeadline
) {
3018 AbsoluteTime nsinterval
;
3019 clock_interval_to_absolutetime_interval(
3020 timeout
->tv_sec
, kSecondScale
, &abstime
);
3021 clock_interval_to_absolutetime_interval(
3022 timeout
->tv_nsec
, kNanosecondScale
, &nsinterval
);
3023 ADD_ABSOLUTETIME( &abstime
, &nsinterval
);
3024 clock_absolutetime_interval_to_deadline(
3025 abstime
, &abstime
);
3026 computeDeadline
= false;
3029 assert_wait_deadline((event_t
)this, THREAD_UNINT
, __OSAbsoluteTime(abstime
));
3032 assert_wait((event_t
)this, THREAD_UNINT
);
3034 unlockForArbitration();
3035 IOLockUnlock( gIOServiceBusyLock
);
3037 waitResult
= thread_block(THREAD_CONTINUE_NULL
);
3039 } while( wait
&& (waitResult
!= THREAD_TIMED_OUT
));
3041 if( waitResult
== THREAD_TIMED_OUT
)
3042 return( kIOReturnTimeout
);
3044 return( kIOReturnSuccess
);
3047 IOReturn
IOService::waitQuiet( mach_timespec_t
* timeout
)
3049 return( waitForState( kIOServiceBusyStateMask
, 0, timeout
));
3052 bool IOService::serializeProperties( OSSerialize
* s
) const
3055 ((IOService
*)this)->setProperty( ((IOService
*)this)->__state
,
3056 sizeof( __state
), "__state");
3058 return( super::serializeProperties(s
) );
3062 void _IOConfigThread::main( _IOConfigThread
* self
)
3064 _IOServiceJob
* job
;
3068 thread_precedence_policy_data_t precedence
= { -1 };
3070 kr
= thread_policy_set(current_thread(),
3071 THREAD_PRECEDENCE_POLICY
,
3072 (thread_policy_t
) &precedence
,
3073 THREAD_PRECEDENCE_POLICY_COUNT
);
3074 if (KERN_SUCCESS
!= kr
)
3075 IOLog("thread_policy_set(%d)\n", kr
);
3081 semaphore_wait( gJobsSemaphore
);
3083 IOTakeLock( gJobsLock
);
3084 job
= (_IOServiceJob
*) gJobs
->getFirstObject();
3086 gJobs
->removeObject(job
);
3089 // gNumConfigThreads--; // we're out of service
3090 gNumWaitingThreads
--; // we're out of service
3092 IOUnlock( gJobsLock
);
3098 if( gIOKitDebug
& kIOLogConfig
)
3099 LOG("config(%x): starting on %s, %d\n",
3100 (int) IOThreadSelf(), job
->nub
->getName(), job
->type
);
3102 switch( job
->type
) {
3105 nub
->doServiceMatch( job
->options
);
3109 LOG("config(%x): strange type (%d)\n",
3110 (int) IOThreadSelf(), job
->type
);
3117 IOTakeLock( gJobsLock
);
3118 alive
= (gOutstandingJobs
> gNumWaitingThreads
);
3120 gNumWaitingThreads
++; // back in service
3121 // gNumConfigThreads++;
3123 if( 0 == --gNumConfigThreads
) {
3124 // IOLog("MATCH IDLE\n");
3125 IOLockWakeup( gJobsLock
, (event_t
) &gNumConfigThreads
, /* one-thread */ false );
3128 IOUnlock( gJobsLock
);
3133 if( gIOKitDebug
& kIOLogConfig
)
3134 LOG("config(%x): terminating\n", (int) IOThreadSelf() );
3139 IOReturn
IOService::waitMatchIdle( UInt32 msToWait
)
3142 int waitResult
= THREAD_AWAKENED
;
3143 bool computeDeadline
= true;
3144 AbsoluteTime abstime
;
3146 IOLockLock( gJobsLock
);
3148 wait
= (0 != gNumConfigThreads
);
3151 if( computeDeadline
) {
3152 clock_interval_to_absolutetime_interval(
3153 msToWait
, kMillisecondScale
, &abstime
);
3154 clock_absolutetime_interval_to_deadline(
3155 abstime
, &abstime
);
3156 computeDeadline
= false;
3158 waitResult
= IOLockSleepDeadline( gJobsLock
, &gNumConfigThreads
,
3159 abstime
, THREAD_UNINT
);
3161 waitResult
= IOLockSleep( gJobsLock
, &gNumConfigThreads
,
3165 } while( wait
&& (waitResult
!= THREAD_TIMED_OUT
));
3166 IOLockUnlock( gJobsLock
);
3168 if( waitResult
== THREAD_TIMED_OUT
)
3169 return( kIOReturnTimeout
);
3171 return( kIOReturnSuccess
);
3174 void _IOServiceJob::pingConfig( _IOServiceJob
* job
)
3181 IOTakeLock( gJobsLock
);
3184 gJobs
->setLastObject( job
);
3186 count
= gNumWaitingThreads
;
3187 // if( gNumConfigThreads) count++;// assume we're called from a config thread
3189 create
= ( (gOutstandingJobs
> count
)
3190 && (gNumConfigThreads
< kMaxConfigThreads
) );
3192 gNumConfigThreads
++;
3193 gNumWaitingThreads
++;
3196 IOUnlock( gJobsLock
);
3201 if( gIOKitDebug
& kIOLogConfig
)
3202 LOG("config(%d): creating\n", gNumConfigThreads
- 1);
3203 _IOConfigThread::configThread();
3206 semaphore_signal( gJobsSemaphore
);
3209 // internal - call with gNotificationLock
3210 OSObject
* IOService::getExistingServices( OSDictionary
* matching
,
3211 IOOptionBits inState
, IOOptionBits options
)
3213 OSObject
* current
= 0;
3215 IOService
* service
;
3222 && (obj
= matching
->getObject(gIOProviderClassKey
))
3224 && gIOResourcesKey
->isEqualTo(obj
)
3225 && (service
= gIOResources
))
3227 if( (inState
== (service
->__state
[0] & inState
))
3228 && (0 == (service
->__state
[0] & kIOServiceInactiveState
))
3229 && service
->passiveMatch( matching
))
3231 if( options
& kIONotifyOnce
)
3234 current
= OSSet::withObjects(
3235 (const OSObject
**) &service
, 1, 1 );
3240 iter
= IORegistryIterator::iterateOver( gIOServicePlane
,
3241 kIORegistryIterateRecursively
);
3245 while( (service
= (IOService
*) iter
->getNextObject())) {
3246 if( (inState
== (service
->__state
[0] & inState
))
3247 && (0 == (service
->__state
[0] & kIOServiceInactiveState
))
3248 && service
->passiveMatch( matching
)) {
3250 if( options
& kIONotifyOnce
) {
3255 ((OSSet
*)current
)->setObject( service
);
3257 current
= OSSet::withObjects(
3258 (const OSObject
**) &service
, 1, 1 );
3261 } while( !service
&& !iter
->isValid());
3266 if( current
&& (0 == (options
& (kIONotifyOnce
| kIOServiceExistingSet
)))) {
3267 iter
= OSCollectionIterator::withCollection( (OSSet
*)current
);
3276 OSIterator
* IOService::getMatchingServices( OSDictionary
* matching
)
3280 // is a lock even needed?
3283 iter
= (OSIterator
*) getExistingServices( matching
,
3284 kIOServiceMatchedState
);
3292 // internal - call with gNotificationLock
3293 IONotifier
* IOService::setNotification(
3294 const OSSymbol
* type
, OSDictionary
* matching
,
3295 IOServiceNotificationHandler handler
, void * target
, void * ref
,
3298 _IOServiceNotifier
* notify
= 0;
3304 notify
= new _IOServiceNotifier
;
3305 if( notify
&& !notify
->init()) {
3311 notify
->matching
= matching
;
3312 notify
->handler
= handler
;
3313 notify
->target
= target
;
3315 notify
->priority
= priority
;
3316 notify
->state
= kIOServiceNotifyEnable
;
3317 queue_init( ¬ify
->handlerInvocations
);
3321 if( 0 == (set
= (OSOrderedSet
*) gNotifications
->getObject( type
))) {
3322 set
= OSOrderedSet::withCapacity( 1,
3323 IONotifyOrdering
, 0 );
3325 gNotifications
->setObject( type
, set
);
3329 notify
->whence
= set
;
3331 set
->setObject( notify
);
3337 // internal - call with gNotificationLock
3338 IONotifier
* IOService::doInstallNotification(
3339 const OSSymbol
* type
, OSDictionary
* matching
,
3340 IOServiceNotificationHandler handler
,
3341 void * target
, void * ref
,
3342 SInt32 priority
, OSIterator
** existing
)
3345 IONotifier
* notify
;
3346 IOOptionBits inState
;
3351 if( type
== gIOPublishNotification
)
3352 inState
= kIOServiceRegisteredState
;
3354 else if( type
== gIOFirstPublishNotification
)
3355 inState
= kIOServiceFirstPublishState
;
3357 else if( (type
== gIOMatchedNotification
)
3358 || (type
== gIOFirstMatchNotification
))
3359 inState
= kIOServiceMatchedState
;
3360 else if( type
== gIOTerminatedNotification
)
3365 notify
= setNotification( type
, matching
, handler
, target
, ref
, priority
);
3368 // get the current set
3369 exist
= (OSIterator
*) getExistingServices( matching
, inState
);
3379 IONotifier
* IOService::installNotification(
3380 const OSSymbol
* type
, OSDictionary
* matching
,
3381 IOServiceNotificationHandler handler
,
3382 void * target
, void * ref
,
3383 SInt32 priority
, OSIterator
** existing
)
3385 IONotifier
* notify
;
3389 notify
= doInstallNotification( type
, matching
, handler
, target
, ref
,
3390 priority
, existing
);
3397 IONotifier
* IOService::addNotification(
3398 const OSSymbol
* type
, OSDictionary
* matching
,
3399 IOServiceNotificationHandler handler
,
3400 void * target
, void * ref
,
3403 OSIterator
* existing
= NULL
;
3404 _IOServiceNotifier
* notify
;
3407 notify
= (_IOServiceNotifier
*) installNotification( type
, matching
,
3408 handler
, target
, ref
, priority
, &existing
);
3410 // send notifications for existing set
3413 notify
->retain(); // in case handler remove()s
3414 while( (next
= (IOService
*) existing
->getNextObject())) {
3416 next
->lockForArbitration();
3417 if( 0 == (next
->__state
[0] & kIOServiceInactiveState
))
3418 next
->invokeNotifer( notify
);
3419 next
->unlockForArbitration();
3422 existing
->release();
3428 struct SyncNotifyVars
{
3429 semaphore_port_t waitHere
;
3433 bool IOService::syncNotificationHandler(
3434 void * /* target */, void * ref
,
3435 IOService
* newService
)
3438 // result may get written more than once before the
3439 // notification is removed!
3440 ((SyncNotifyVars
*) ref
)->result
= newService
;
3441 semaphore_signal( ((SyncNotifyVars
*) ref
)->waitHere
);
3446 IOService
* IOService::waitForService( OSDictionary
* matching
,
3447 mach_timespec_t
* timeout
)
3449 IONotifier
* notify
= 0;
3450 // priority doesn't help us much since we need a thread wakeup
3451 SInt32 priority
= 0;
3452 SyncNotifyVars state
;
3453 kern_return_t err
= kIOReturnBadArgument
;
3465 state
.result
= (IOService
*) getExistingServices( matching
,
3466 kIOServiceMatchedState
, kIONotifyOnce
);
3470 err
= semaphore_create( kernel_task
, &state
.waitHere
,
3471 SYNC_POLICY_FIFO
, 0 );
3472 if( KERN_SUCCESS
!= err
)
3475 notify
= IOService::setNotification( gIOMatchedNotification
, matching
,
3476 &IOService::syncNotificationHandler
, (void *) 0,
3477 (void *) &state
, priority
);
3485 err
= semaphore_timedwait( state
.waitHere
, *timeout
);
3487 err
= semaphore_wait( state
.waitHere
);
3491 notify
->remove(); // dequeues
3493 matching
->release();
3495 semaphore_destroy( kernel_task
, state
.waitHere
);
3497 return( state
.result
);
3500 void IOService::deliverNotification( const OSSymbol
* type
,
3501 IOOptionBits orNewState
, IOOptionBits andNewState
)
3503 _IOServiceNotifier
* notify
;
3505 OSArray
* willSend
= 0;
3507 lockForArbitration();
3509 if( (0 == (__state
[0] & kIOServiceInactiveState
))
3510 || (type
== gIOTerminatedNotification
)) {
3514 iter
= OSCollectionIterator::withCollection( (OSOrderedSet
*)
3515 gNotifications
->getObject( type
) );
3518 while( (notify
= (_IOServiceNotifier
*) iter
->getNextObject())) {
3520 if( passiveMatch( notify
->matching
)
3521 && (kIOServiceNotifyEnable
& notify
->state
)) {
3523 willSend
= OSArray::withCapacity(8);
3525 willSend
->setObject( notify
);
3531 __state
[0] = (__state
[0] | orNewState
) & andNewState
;
3537 for( unsigned int idx
= 0;
3538 (notify
= (_IOServiceNotifier
*) willSend
->getObject(idx
));
3540 invokeNotifer( notify
);
3542 willSend
->release();
3544 unlockForArbitration();
3547 IOOptionBits
IOService::getState( void ) const
3549 return( __state
[0] );
3553 * Helpers to make matching objects for simple cases
3556 OSDictionary
* IOService::serviceMatching( const OSString
* name
,
3557 OSDictionary
* table
)
3560 table
= OSDictionary::withCapacity( 2 );
3562 table
->setObject(gIOProviderClassKey
, (OSObject
*)name
);
3567 OSDictionary
* IOService::serviceMatching( const char * name
,
3568 OSDictionary
* table
)
3570 const OSString
* str
;
3572 str
= OSSymbol::withCString( name
);
3576 table
= serviceMatching( str
, table
);
3581 OSDictionary
* IOService::nameMatching( const OSString
* name
,
3582 OSDictionary
* table
)
3585 table
= OSDictionary::withCapacity( 2 );
3587 table
->setObject( gIONameMatchKey
, (OSObject
*)name
);
3592 OSDictionary
* IOService::nameMatching( const char * name
,
3593 OSDictionary
* table
)
3595 const OSString
* str
;
3597 str
= OSSymbol::withCString( name
);
3601 table
= nameMatching( str
, table
);
3606 OSDictionary
* IOService::resourceMatching( const OSString
* str
,
3607 OSDictionary
* table
)
3609 table
= serviceMatching( gIOResourcesKey
, table
);
3611 table
->setObject( gIOResourceMatchKey
, (OSObject
*) str
);
3616 OSDictionary
* IOService::resourceMatching( const char * name
,
3617 OSDictionary
* table
)
3619 const OSSymbol
* str
;
3621 str
= OSSymbol::withCString( name
);
3625 table
= resourceMatching( str
, table
);
3631 OSDictionary
* IOService::propertyMatching( const OSSymbol
* key
, const OSObject
* value
,
3632 OSDictionary
* table
)
3634 OSDictionary
* properties
;
3636 properties
= OSDictionary::withCapacity( 2 );
3639 properties
->setObject( key
, value
);
3642 table
= OSDictionary::withCapacity( 2 );
3644 table
->setObject( gIOPropertyMatchKey
, properties
);
3646 properties
->release();
3652 * _IOServiceNotifier
3655 // wait for all threads, other than the current one,
3656 // to exit the handler
3658 void _IOServiceNotifier::wait()
3660 _IOServiceNotifierInvocation
* next
;
3665 queue_iterate( &handlerInvocations
, next
,
3666 _IOServiceNotifierInvocation
*, link
) {
3667 if( next
->thread
!= current_thread() ) {
3673 state
|= kIOServiceNotifyWaiter
;
3680 void _IOServiceNotifier::free()
3682 assert( queue_empty( &handlerInvocations
));
3686 void _IOServiceNotifier::remove()
3691 whence
->removeObject( (OSObject
*) this );
3695 matching
->release();
3699 state
&= ~kIOServiceNotifyEnable
;
3708 bool _IOServiceNotifier::disable()
3714 ret
= (0 != (kIOServiceNotifyEnable
& state
));
3715 state
&= ~kIOServiceNotifyEnable
;
3724 void _IOServiceNotifier::enable( bool was
)
3728 state
|= kIOServiceNotifyEnable
;
3730 state
&= ~kIOServiceNotifyEnable
;
3738 IOService
* IOResources::resources( void )
3742 inst
= new IOResources
;
3743 if( inst
&& !inst
->init()) {
3751 IOWorkLoop
* IOResources::getWorkLoop() const
3753 // If we are the resource root then bringe over to the
3754 // platform to get its workloop
3755 if (this == (IOResources
*) gIOResources
)
3756 return getPlatform()->getWorkLoop();
3758 return IOService::getWorkLoop();
3761 bool IOResources::matchPropertyTable( OSDictionary
* table
)
3769 prop
= table
->getObject( gIOResourceMatchKey
);
3770 str
= OSDynamicCast( OSString
, prop
);
3772 ok
= (0 != getProperty( str
));
3774 else if( (set
= OSDynamicCast( OSSet
, prop
))) {
3776 iter
= OSCollectionIterator::withCollection( set
);
3778 while( ok
&& (str
= OSDynamicCast( OSString
, iter
->getNextObject()) ))
3779 ok
= (0 != getProperty( str
));
3788 IOReturn
IOResources::setProperties( OSObject
* properties
)
3791 const OSSymbol
* key
;
3792 OSDictionary
* dict
;
3793 OSCollectionIterator
* iter
;
3795 err
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
3796 if ( kIOReturnSuccess
!= err
)
3799 dict
= OSDynamicCast(OSDictionary
, properties
);
3801 return( kIOReturnBadArgument
);
3803 iter
= OSCollectionIterator::withCollection( dict
);
3805 return( kIOReturnBadArgument
);
3807 while( (key
= OSDynamicCast(OSSymbol
, iter
->getNextObject()))) {
3809 if (gIOConsoleUsersKey
== key
)
3811 IORegistryEntry::getRegistryRoot()->setProperty(key
, dict
->getObject(key
));
3812 OSIncrementAtomic( &gIOConsoleUsersSeed
);
3813 publishResource( gIOConsoleUsersSeedKey
, gIOConsoleUsersSeedValue
);
3817 publishResource( key
, dict
->getObject(key
) );
3822 return( kIOReturnSuccess
);
3826 * Helpers for matching dictionaries.
3827 * Keys existing in matching are checked in properties.
3828 * Keys may be a string or OSCollection of IOStrings
3831 bool IOService::compareProperty( OSDictionary
* matching
,
3837 value
= matching
->getObject( key
);
3839 ok
= value
->isEqualTo( getProperty( key
));
3847 bool IOService::compareProperty( OSDictionary
* matching
,
3848 const OSString
* key
)
3853 value
= matching
->getObject( key
);
3855 ok
= value
->isEqualTo( getProperty( key
));
3862 bool IOService::compareProperties( OSDictionary
* matching
,
3863 OSCollection
* keys
)
3865 OSCollectionIterator
* iter
;
3866 const OSString
* key
;
3869 if( !matching
|| !keys
)
3872 iter
= OSCollectionIterator::withCollection( keys
);
3875 while( ok
&& (key
= OSDynamicCast( OSString
, iter
->getNextObject())))
3876 ok
= compareProperty( matching
, key
);
3880 keys
->release(); // !! consume a ref !!
3885 /* Helper to add a location matching dict to the table */
3887 OSDictionary
* IOService::addLocation( OSDictionary
* table
)
3889 OSDictionary
* dict
;
3894 dict
= OSDictionary::withCapacity( 1 );
3896 table
->setObject( gIOLocationMatchKey
, dict
);
3904 * Go looking for a provider to match a location dict.
3907 IOService
* IOService::matchLocation( IOService
* /* client */ )
3911 parent
= getProvider();
3914 parent
= parent
->matchLocation( this );
3919 bool IOService::passiveMatch( OSDictionary
* table
, bool changesOK
)
3925 IORegistryEntry
* entry
;
3930 bool matchParent
= false;
3941 str
= OSDynamicCast( OSString
, table
->getObject( gIOProviderClassKey
));
3944 match
= (0 != where
->metaCast( str
));
3949 obj
= table
->getObject( gIONameMatchKey
);
3952 match
= where
->compareNames( obj
, changesOK
? &matched
: 0 );
3955 if( changesOK
&& matched
) {
3956 // leave a hint as to which name matched
3957 table
->setObject( gIONameMatchedKey
, matched
);
3962 str
= OSDynamicCast( OSString
, table
->getObject( gIOLocationMatchKey
));
3965 const OSSymbol
* sym
;
3969 sym
= where
->copyLocation();
3971 match
= sym
->isEqualTo( str
);
3978 obj
= table
->getObject( gIOPropertyMatchKey
);
3981 OSDictionary
* dict
;
3982 OSDictionary
* nextDict
;
3987 dict
= where
->dictionaryWithProperties();
3989 nextDict
= OSDynamicCast( OSDictionary
, obj
);
3993 iter
= OSCollectionIterator::withCollection(
3994 OSDynamicCast(OSCollection
, obj
));
3997 || (iter
&& (0 != (nextDict
= OSDynamicCast(OSDictionary
,
3998 iter
->getNextObject()))))) {
3999 match
= dict
->isEqualTo( nextDict
, nextDict
);
4012 str
= OSDynamicCast( OSString
, table
->getObject( gIOPathMatchKey
));
4015 entry
= IORegistryEntry::fromPath( str
->getCStringNoCopy() );
4016 match
= (where
== entry
);
4023 num
= OSDynamicCast( OSNumber
, table
->getObject( gIOMatchedServiceCountKey
));
4027 IOService
* service
= 0;
4028 UInt32 serviceCount
= 0;
4031 iter
= where
->getClientIterator();
4033 while( (service
= (IOService
*) iter
->getNextObject())) {
4034 if( kIOServiceInactiveState
& service
->__state
[0])
4036 if( 0 == service
->getProperty( gIOMatchCategoryKey
))
4042 match
= (serviceCount
== num
->unsigned32BitValue());
4047 if( done
== table
->getCount()) {
4048 // don't call family if we've done all the entries in the table
4049 matchParent
= false;
4053 // pass in score from property table
4054 score
= IOServiceObjectOrder( table
, (void *) gIOProbeScoreKey
);
4056 // do family specific matching
4057 match
= where
->matchPropertyTable( table
, &score
);
4061 if( kIOLogMatch
& getDebugFlags( table
))
4062 LOG("%s: family specific matching fails\n", where
->getName());
4069 newPri
= OSNumber::withNumber( score
, 32 );
4071 table
->setObject( gIOProbeScoreKey
, newPri
);
4076 if( !(match
= where
->compareProperty( table
, kIOBSDNameKey
)))
4078 if( !(match
= where
->compareProperty( table
, kIOBSDMajorKey
)))
4080 if( !(match
= where
->compareProperty( table
, kIOBSDMinorKey
)))
4082 if( !(match
= where
->compareProperty( table
, kIOBSDUnitKey
)))
4085 matchParent
= false;
4087 obj
= OSDynamicCast( OSDictionary
,
4088 table
->getObject( gIOParentMatchKey
));
4092 table
= (OSDictionary
*) obj
;
4096 table
= OSDynamicCast( OSDictionary
,
4097 table
->getObject( gIOLocationMatchKey
));
4100 where
= where
->getProvider();
4102 where
= where
->matchLocation( where
);
4105 } while( table
&& where
);
4107 } while( matchParent
&& (where
= where
->getProvider()) );
4109 if( kIOLogMatch
& gIOKitDebug
)
4111 LOG("match parent @ %s = %d\n",
4112 where
->getName(), match
);
4118 IOReturn
IOService::newUserClient( task_t owningTask
, void * securityID
,
4119 UInt32 type
, OSDictionary
* properties
,
4120 IOUserClient
** handler
)
4122 const OSSymbol
*userClientClass
= 0;
4123 IOUserClient
*client
;
4126 if (kIOReturnSuccess
== newUserClient( owningTask
, securityID
, type
, handler
))
4127 return kIOReturnSuccess
;
4129 // First try my own properties for a user client class name
4130 temp
= getProperty(gIOUserClientClassKey
);
4132 if (OSDynamicCast(OSSymbol
, temp
))
4133 userClientClass
= (const OSSymbol
*) temp
;
4134 else if (OSDynamicCast(OSString
, temp
)) {
4135 userClientClass
= OSSymbol::withString((OSString
*) temp
);
4136 if (userClientClass
)
4137 setProperty(kIOUserClientClassKey
,
4138 (OSObject
*) userClientClass
);
4142 // Didn't find one so lets just bomb out now without further ado.
4143 if (!userClientClass
)
4144 return kIOReturnUnsupported
;
4146 // This reference is consumed by the IOServiceOpen call
4147 temp
= OSMetaClass::allocClassWithName(userClientClass
);
4149 return kIOReturnNoMemory
;
4151 if (OSDynamicCast(IOUserClient
, temp
))
4152 client
= (IOUserClient
*) temp
;
4155 return kIOReturnUnsupported
;
4158 if ( !client
->initWithTask(owningTask
, securityID
, type
, properties
) ) {
4160 return kIOReturnBadArgument
;
4163 if ( !client
->attach(this) ) {
4165 return kIOReturnUnsupported
;
4168 if ( !client
->start(this) ) {
4169 client
->detach(this);
4171 return kIOReturnUnsupported
;
4175 return kIOReturnSuccess
;
4178 IOReturn
IOService::newUserClient( task_t owningTask
, void * securityID
,
4179 UInt32 type
, IOUserClient
** handler
)
4181 return( kIOReturnUnsupported
);
4184 IOReturn
IOService::requestProbe( IOOptionBits options
)
4186 return( kIOReturnUnsupported
);
4190 * Convert an IOReturn to text. Subclasses which add additional
4191 * IOReturn's should override this method and call
4192 * super::stringFromReturn if the desired value is not found.
4195 const char * IOService::stringFromReturn( IOReturn rtn
)
4197 static const IONamedValue IOReturn_values
[] = {
4198 {kIOReturnSuccess
, "success" },
4199 {kIOReturnError
, "general error" },
4200 {kIOReturnNoMemory
, "memory allocation error" },
4201 {kIOReturnNoResources
, "resource shortage" },
4202 {kIOReturnIPCError
, "Mach IPC failure" },
4203 {kIOReturnNoDevice
, "no such device" },
4204 {kIOReturnNotPrivileged
, "privilege violation" },
4205 {kIOReturnBadArgument
, "invalid argument" },
4206 {kIOReturnLockedRead
, "device is read locked" },
4207 {kIOReturnLockedWrite
, "device is write locked" },
4208 {kIOReturnExclusiveAccess
, "device is exclusive access" },
4209 {kIOReturnBadMessageID
, "bad IPC message ID" },
4210 {kIOReturnUnsupported
, "unsupported function" },
4211 {kIOReturnVMError
, "virtual memory error" },
4212 {kIOReturnInternalError
, "internal driver error" },
4213 {kIOReturnIOError
, "I/O error" },
4214 {kIOReturnCannotLock
, "cannot acquire lock" },
4215 {kIOReturnNotOpen
, "device is not open" },
4216 {kIOReturnNotReadable
, "device is not readable" },
4217 {kIOReturnNotWritable
, "device is not writeable" },
4218 {kIOReturnNotAligned
, "alignment error" },
4219 {kIOReturnBadMedia
, "media error" },
4220 {kIOReturnStillOpen
, "device is still open" },
4221 {kIOReturnRLDError
, "rld failure" },
4222 {kIOReturnDMAError
, "DMA failure" },
4223 {kIOReturnBusy
, "device is busy" },
4224 {kIOReturnTimeout
, "I/O timeout" },
4225 {kIOReturnOffline
, "device is offline" },
4226 {kIOReturnNotReady
, "device is not ready" },
4227 {kIOReturnNotAttached
, "device/channel is not attached" },
4228 {kIOReturnNoChannels
, "no DMA channels available" },
4229 {kIOReturnNoSpace
, "no space for data" },
4230 {kIOReturnPortExists
, "device port already exists" },
4231 {kIOReturnCannotWire
, "cannot wire physical memory" },
4232 {kIOReturnNoInterrupt
, "no interrupt attached" },
4233 {kIOReturnNoFrames
, "no DMA frames enqueued" },
4234 {kIOReturnMessageTooLarge
, "message is too large" },
4235 {kIOReturnNotPermitted
, "operation is not permitted" },
4236 {kIOReturnNoPower
, "device is without power" },
4237 {kIOReturnNoMedia
, "media is not present" },
4238 {kIOReturnUnformattedMedia
, "media is not formatted" },
4239 {kIOReturnUnsupportedMode
, "unsupported mode" },
4240 {kIOReturnUnderrun
, "data underrun" },
4241 {kIOReturnOverrun
, "data overrun" },
4242 {kIOReturnDeviceError
, "device error" },
4243 {kIOReturnNoCompletion
, "no completion routine" },
4244 {kIOReturnAborted
, "operation was aborted" },
4245 {kIOReturnNoBandwidth
, "bus bandwidth would be exceeded" },
4246 {kIOReturnNotResponding
, "device is not responding" },
4247 {kIOReturnInvalid
, "unanticipated driver error" },
4251 return IOFindNameForValue(rtn
, IOReturn_values
);
4255 * Convert an IOReturn to an errno.
4257 int IOService::errnoFromReturn( IOReturn rtn
)
4261 case kIOReturnSuccess
:
4263 case kIOReturnNoMemory
:
4265 case kIOReturnNoDevice
:
4267 case kIOReturnVMError
:
4269 case kIOReturnNotPermitted
:
4271 case kIOReturnNotPrivileged
:
4273 case kIOReturnIOError
:
4275 case kIOReturnNotWritable
:
4277 case kIOReturnBadArgument
:
4279 case kIOReturnUnsupported
:
4283 case kIOReturnNoPower
:
4285 case kIOReturnDeviceError
:
4287 case kIOReturnTimeout
:
4289 case kIOReturnMessageTooLarge
:
4291 case kIOReturnNoSpace
:
4293 case kIOReturnCannotLock
:
4297 case kIOReturnBadMessageID
:
4298 case kIOReturnNoCompletion
:
4299 case kIOReturnNotAligned
:
4301 case kIOReturnNotReady
:
4303 case kIOReturnRLDError
:
4305 case kIOReturnPortExists
:
4306 case kIOReturnStillOpen
:
4308 case kIOReturnExclusiveAccess
:
4309 case kIOReturnLockedRead
:
4310 case kIOReturnLockedWrite
:
4311 case kIOReturnNotAttached
:
4312 case kIOReturnNotOpen
:
4313 case kIOReturnNotReadable
:
4315 case kIOReturnCannotWire
:
4316 case kIOReturnNoResources
:
4318 case kIOReturnAborted
:
4319 case kIOReturnOffline
:
4320 case kIOReturnNotResponding
:
4322 case kIOReturnBadMedia
:
4323 case kIOReturnNoMedia
:
4324 case kIOReturnUnformattedMedia
:
4325 return(ENXIO
); // (media error)
4326 case kIOReturnDMAError
:
4327 case kIOReturnOverrun
:
4328 case kIOReturnUnderrun
:
4329 return(EIO
); // (transfer error)
4330 case kIOReturnNoBandwidth
:
4331 case kIOReturnNoChannels
:
4332 case kIOReturnNoFrames
:
4333 case kIOReturnNoInterrupt
:
4334 return(EIO
); // (hardware error)
4335 case kIOReturnError
:
4336 case kIOReturnInternalError
:
4337 case kIOReturnInvalid
:
4338 return(EIO
); // (generic error)
4339 case kIOReturnIPCError
:
4340 return(EIO
); // (ipc error)
4342 return(EIO
); // (all other errors)
4346 IOReturn
IOService::message( UInt32 type
, IOService
* provider
,
4350 * Generic entry point for calls from the provider. A return value of
4351 * kIOReturnSuccess indicates that the message was received, and where
4352 * applicable, that it was successful.
4355 return kIOReturnUnsupported
;
4362 IOItemCount
IOService::getDeviceMemoryCount( void )
4367 array
= OSDynamicCast( OSArray
, getProperty( gIODeviceMemoryKey
));
4369 count
= array
->getCount();
4376 IODeviceMemory
* IOService::getDeviceMemoryWithIndex( unsigned int index
)
4379 IODeviceMemory
* range
;
4381 array
= OSDynamicCast( OSArray
, getProperty( gIODeviceMemoryKey
));
4383 range
= (IODeviceMemory
*) array
->getObject( index
);
4390 IOMemoryMap
* IOService::mapDeviceMemoryWithIndex( unsigned int index
,
4391 IOOptionBits options
)
4393 IODeviceMemory
* range
;
4396 range
= getDeviceMemoryWithIndex( index
);
4398 map
= range
->map( options
);
4405 OSArray
* IOService::getDeviceMemory( void )
4407 return( OSDynamicCast( OSArray
, getProperty( gIODeviceMemoryKey
)));
4411 void IOService::setDeviceMemory( OSArray
* array
)
4413 setProperty( gIODeviceMemoryKey
, array
);
4417 * For machines where the transfers on an I/O bus can stall because
4418 * the CPU is in an idle mode, These APIs allow a driver to specify
4419 * the maximum bus stall that they can handle. 0 indicates no limit.
4422 setCPUSnoopDelay(UInt32 __unused ns
)
4425 ml_set_maxsnoop(ns
);
4426 #endif /* __i386__ */
4433 return ml_get_maxsnoop();
4436 #endif /* __i386__ */
4440 requireMaxBusStall(UInt32 __unused ns
)
4443 static const UInt kNoReplace
= -1U; // Must be an illegal index
4444 UInt replace
= kNoReplace
;
4446 IOLockLock(sBusStallLock
);
4448 UInt count
= sBusStall
->getLength() / sizeof(BusStallEntry
);
4449 BusStallEntry
*entries
= (BusStallEntry
*) sBusStall
->getBytesNoCopy();
4452 const BusStallEntry ne
= {this, ns
};
4454 // Set Maximum bus delay.
4455 for (UInt i
= 0; i
< count
; i
++) {
4456 const IOService
*thisService
= entries
[i
].fService
;
4457 if (this == thisService
)
4459 else if (!thisService
) {
4460 if (kNoReplace
== replace
)
4464 const UInt32 thisMax
= entries
[i
].fMaxDelay
;
4470 // Must be safe to call from locked context
4471 ml_set_maxbusdelay(ns
);
4473 if (kNoReplace
== replace
)
4474 sBusStall
->appendBytes(&ne
, sizeof(ne
));
4476 entries
[replace
] = ne
;
4479 ns
= -1U; // Set to max unsigned, i.e. no restriction
4481 for (UInt i
= 0; i
< count
; i
++) {
4482 // Clear a maximum bus delay.
4483 const IOService
*thisService
= entries
[i
].fService
;
4484 UInt32 thisMax
= entries
[i
].fMaxDelay
;
4485 if (this == thisService
)
4487 else if (thisService
&& thisMax
< ns
)
4491 // Check if entry found
4492 if (kNoReplace
!= replace
) {
4493 entries
[replace
].fService
= 0; // Null the entry
4494 ml_set_maxbusdelay(ns
);
4498 IOLockUnlock(sBusStallLock
);
4499 #endif /* __i386__ */
4506 IOReturn
IOService::resolveInterrupt(IOService
*nub
, int source
)
4508 IOInterruptController
*interruptController
;
4511 OSSymbol
*interruptControllerName
;
4513 IOInterruptSource
*interruptSources
;
4515 // Get the parents list from the nub.
4516 array
= OSDynamicCast(OSArray
, nub
->getProperty(gIOInterruptControllersKey
));
4517 if (array
== 0) return kIOReturnNoResources
;
4519 // Allocate space for the IOInterruptSources if needed... then return early.
4520 if (nub
->_interruptSources
== 0) {
4521 numSources
= array
->getCount();
4522 interruptSources
= (IOInterruptSource
*)IOMalloc(numSources
* sizeof(IOInterruptSource
));
4523 if (interruptSources
== 0) return kIOReturnNoMemory
;
4525 bzero(interruptSources
, numSources
* sizeof(IOInterruptSource
));
4527 nub
->_numInterruptSources
= numSources
;
4528 nub
->_interruptSources
= interruptSources
;
4529 return kIOReturnSuccess
;
4532 interruptControllerName
= OSDynamicCast(OSSymbol
,array
->getObject(source
));
4533 if (interruptControllerName
== 0) return kIOReturnNoResources
;
4535 interruptController
= getPlatform()->lookUpInterruptController(interruptControllerName
);
4536 if (interruptController
== 0) return kIOReturnNoResources
;
4538 // Get the interrupt numbers from the nub.
4539 array
= OSDynamicCast(OSArray
, nub
->getProperty(gIOInterruptSpecifiersKey
));
4540 if (array
== 0) return kIOReturnNoResources
;
4541 data
= OSDynamicCast(OSData
, array
->getObject(source
));
4542 if (data
== 0) return kIOReturnNoResources
;
4544 // Set the interruptController and interruptSource in the nub's table.
4545 interruptSources
= nub
->_interruptSources
;
4546 interruptSources
[source
].interruptController
= interruptController
;
4547 interruptSources
[source
].vectorData
= data
;
4549 return kIOReturnSuccess
;
4552 IOReturn
IOService::lookupInterrupt(int source
, bool resolve
, IOInterruptController
**interruptController
)
4556 /* Make sure the _interruptSources are set */
4557 if (_interruptSources
== 0) {
4558 ret
= resolveInterrupt(this, source
);
4559 if (ret
!= kIOReturnSuccess
) return ret
;
4562 /* Make sure the local source number is valid */
4563 if ((source
< 0) || (source
>= _numInterruptSources
))
4564 return kIOReturnNoInterrupt
;
4566 /* Look up the contoller for the local source */
4567 *interruptController
= _interruptSources
[source
].interruptController
;
4569 if (*interruptController
== NULL
) {
4570 if (!resolve
) return kIOReturnNoInterrupt
;
4572 /* Try to reslove the interrupt */
4573 ret
= resolveInterrupt(this, source
);
4574 if (ret
!= kIOReturnSuccess
) return ret
;
4576 *interruptController
= _interruptSources
[source
].interruptController
;
4579 return kIOReturnSuccess
;
4582 IOReturn
IOService::registerInterrupt(int source
, OSObject
*target
,
4583 IOInterruptAction handler
,
4586 IOInterruptController
*interruptController
;
4589 ret
= lookupInterrupt(source
, true, &interruptController
);
4590 if (ret
!= kIOReturnSuccess
) return ret
;
4592 /* Register the source */
4593 return interruptController
->registerInterrupt(this, source
, target
,
4594 (IOInterruptHandler
)handler
,
4598 IOReturn
IOService::unregisterInterrupt(int source
)
4600 IOInterruptController
*interruptController
;
4603 ret
= lookupInterrupt(source
, false, &interruptController
);
4604 if (ret
!= kIOReturnSuccess
) return ret
;
4606 /* Unregister the source */
4607 return interruptController
->unregisterInterrupt(this, source
);
4610 IOReturn
IOService::getInterruptType(int source
, int *interruptType
)
4612 IOInterruptController
*interruptController
;
4615 ret
= lookupInterrupt(source
, true, &interruptController
);
4616 if (ret
!= kIOReturnSuccess
) return ret
;
4618 /* Return the type */
4619 return interruptController
->getInterruptType(this, source
, interruptType
);
4622 IOReturn
IOService::enableInterrupt(int source
)
4624 IOInterruptController
*interruptController
;
4627 ret
= lookupInterrupt(source
, false, &interruptController
);
4628 if (ret
!= kIOReturnSuccess
) return ret
;
4630 /* Enable the source */
4631 return interruptController
->enableInterrupt(this, source
);
4634 IOReturn
IOService::disableInterrupt(int source
)
4636 IOInterruptController
*interruptController
;
4639 ret
= lookupInterrupt(source
, false, &interruptController
);
4640 if (ret
!= kIOReturnSuccess
) return ret
;
4642 /* Disable the source */
4643 return interruptController
->disableInterrupt(this, source
);
4646 IOReturn
IOService::causeInterrupt(int source
)
4648 IOInterruptController
*interruptController
;
4651 ret
= lookupInterrupt(source
, false, &interruptController
);
4652 if (ret
!= kIOReturnSuccess
) return ret
;
4654 /* Cause an interrupt for the source */
4655 return interruptController
->causeInterrupt(this, source
);
4658 OSMetaClassDefineReservedUsed(IOService
, 0);
4659 OSMetaClassDefineReservedUsed(IOService
, 1);
4660 OSMetaClassDefineReservedUsed(IOService
, 2);
4661 OSMetaClassDefineReservedUsed(IOService
, 3);
4662 OSMetaClassDefineReservedUsed(IOService
, 4);
4664 OSMetaClassDefineReservedUnused(IOService
, 5);
4665 OSMetaClassDefineReservedUnused(IOService
, 6);
4666 OSMetaClassDefineReservedUnused(IOService
, 7);
4667 OSMetaClassDefineReservedUnused(IOService
, 8);
4668 OSMetaClassDefineReservedUnused(IOService
, 9);
4669 OSMetaClassDefineReservedUnused(IOService
, 10);
4670 OSMetaClassDefineReservedUnused(IOService
, 11);
4671 OSMetaClassDefineReservedUnused(IOService
, 12);
4672 OSMetaClassDefineReservedUnused(IOService
, 13);
4673 OSMetaClassDefineReservedUnused(IOService
, 14);
4674 OSMetaClassDefineReservedUnused(IOService
, 15);
4675 OSMetaClassDefineReservedUnused(IOService
, 16);
4676 OSMetaClassDefineReservedUnused(IOService
, 17);
4677 OSMetaClassDefineReservedUnused(IOService
, 18);
4678 OSMetaClassDefineReservedUnused(IOService
, 19);
4679 OSMetaClassDefineReservedUnused(IOService
, 20);
4680 OSMetaClassDefineReservedUnused(IOService
, 21);
4681 OSMetaClassDefineReservedUnused(IOService
, 22);
4682 OSMetaClassDefineReservedUnused(IOService
, 23);
4683 OSMetaClassDefineReservedUnused(IOService
, 24);
4684 OSMetaClassDefineReservedUnused(IOService
, 25);
4685 OSMetaClassDefineReservedUnused(IOService
, 26);
4686 OSMetaClassDefineReservedUnused(IOService
, 27);
4687 OSMetaClassDefineReservedUnused(IOService
, 28);
4688 OSMetaClassDefineReservedUnused(IOService
, 29);
4689 OSMetaClassDefineReservedUnused(IOService
, 30);
4690 OSMetaClassDefineReservedUnused(IOService
, 31);
4691 OSMetaClassDefineReservedUnused(IOService
, 32);
4692 OSMetaClassDefineReservedUnused(IOService
, 33);
4693 OSMetaClassDefineReservedUnused(IOService
, 34);
4694 OSMetaClassDefineReservedUnused(IOService
, 35);
4695 OSMetaClassDefineReservedUnused(IOService
, 36);
4696 OSMetaClassDefineReservedUnused(IOService
, 37);
4697 OSMetaClassDefineReservedUnused(IOService
, 38);
4698 OSMetaClassDefineReservedUnused(IOService
, 39);
4699 OSMetaClassDefineReservedUnused(IOService
, 40);
4700 OSMetaClassDefineReservedUnused(IOService
, 41);
4701 OSMetaClassDefineReservedUnused(IOService
, 42);
4702 OSMetaClassDefineReservedUnused(IOService
, 43);
4703 OSMetaClassDefineReservedUnused(IOService
, 44);
4704 OSMetaClassDefineReservedUnused(IOService
, 45);
4705 OSMetaClassDefineReservedUnused(IOService
, 46);
4706 OSMetaClassDefineReservedUnused(IOService
, 47);
4709 OSMetaClassDefineReservedUnused(IOService
, 48);
4710 OSMetaClassDefineReservedUnused(IOService
, 49);
4711 OSMetaClassDefineReservedUnused(IOService
, 50);
4712 OSMetaClassDefineReservedUnused(IOService
, 51);
4713 OSMetaClassDefineReservedUnused(IOService
, 52);
4714 OSMetaClassDefineReservedUnused(IOService
, 53);
4715 OSMetaClassDefineReservedUnused(IOService
, 54);
4716 OSMetaClassDefineReservedUnused(IOService
, 55);
4717 OSMetaClassDefineReservedUnused(IOService
, 56);
4718 OSMetaClassDefineReservedUnused(IOService
, 57);
4719 OSMetaClassDefineReservedUnused(IOService
, 58);
4720 OSMetaClassDefineReservedUnused(IOService
, 59);
4721 OSMetaClassDefineReservedUnused(IOService
, 60);
4722 OSMetaClassDefineReservedUnused(IOService
, 61);
4723 OSMetaClassDefineReservedUnused(IOService
, 62);
4724 OSMetaClassDefineReservedUnused(IOService
, 63);