xnu-1504.7.4.tar.gz
[apple/xnu.git] / iokit / Kernel / IOService.cpp
1 /*
2 * Copyright (c) 1998-2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <IOKit/system.h>
30
31 #include <IOKit/IOService.h>
32 #include <libkern/OSDebug.h>
33 #include <libkern/c++/OSContainers.h>
34 #include <libkern/c++/OSKext.h>
35 #include <libkern/c++/OSUnserialize.h>
36 #include <IOKit/IOCatalogue.h>
37 #include <IOKit/IOCommand.h>
38 #include <IOKit/IODeviceMemory.h>
39 #include <IOKit/IOInterrupts.h>
40 #include <IOKit/IOInterruptController.h>
41 #include <IOKit/IOPlatformExpert.h>
42 #include <IOKit/IOMessage.h>
43 #include <IOKit/IOLib.h>
44 #include <IOKit/IOKitKeysPrivate.h>
45 #include <IOKit/IOBSD.h>
46 #include <IOKit/IOUserClient.h>
47 #include <IOKit/IOWorkLoop.h>
48 #include <IOKit/IOTimeStamp.h>
49 #include <mach/sync_policy.h>
50 #include <IOKit/assert.h>
51 #include <sys/errno.h>
52
53 #define LOG kprintf
54 //#define LOG IOLog
55
56 #include "IOServicePrivate.h"
57
58 // take lockForArbitration before LOCKNOTIFY
59
60 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
61
62 #define super IORegistryEntry
63
64 OSDefineMetaClassAndStructors(IOService, IORegistryEntry)
65
66 OSDefineMetaClassAndStructors(_IOServiceNotifier, IONotifier)
67
68 OSDefineMetaClassAndStructors(_IOServiceInterestNotifier, IONotifier)
69
70 OSDefineMetaClassAndStructors(_IOConfigThread, OSObject)
71
72 OSDefineMetaClassAndStructors(_IOServiceJob, OSObject)
73
74 OSDefineMetaClassAndStructors(IOResources, IOService)
75
76 OSDefineMetaClassAndStructors(_IOOpenServiceIterator, OSIterator)
77
78 OSDefineMetaClassAndAbstractStructors(IONotifier, OSObject)
79
80 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
81
82 static IOPlatformExpert * gIOPlatform;
83 static class IOPMrootDomain * gIOPMRootDomain;
84 const IORegistryPlane * gIOServicePlane;
85 const IORegistryPlane * gIOPowerPlane;
86 const OSSymbol * gIODeviceMemoryKey;
87 const OSSymbol * gIOInterruptControllersKey;
88 const OSSymbol * gIOInterruptSpecifiersKey;
89
90 const OSSymbol * gIOResourcesKey;
91 const OSSymbol * gIOResourceMatchKey;
92 const OSSymbol * gIOProviderClassKey;
93 const OSSymbol * gIONameMatchKey;
94 const OSSymbol * gIONameMatchedKey;
95 const OSSymbol * gIOPropertyMatchKey;
96 const OSSymbol * gIOLocationMatchKey;
97 const OSSymbol * gIOParentMatchKey;
98 const OSSymbol * gIOPathMatchKey;
99 const OSSymbol * gIOMatchCategoryKey;
100 const OSSymbol * gIODefaultMatchCategoryKey;
101 const OSSymbol * gIOMatchedServiceCountKey;
102
103 const OSSymbol * gIOMapperIDKey;
104 const OSSymbol * gIOUserClientClassKey;
105 const OSSymbol * gIOKitDebugKey;
106
107 const OSSymbol * gIOCommandPoolSizeKey;
108
109 const OSSymbol * gIOConsoleUsersKey;
110 const OSSymbol * gIOConsoleSessionUIDKey;
111 const OSSymbol * gIOConsoleUsersSeedKey;
112 const OSSymbol * gIOConsoleSessionOnConsoleKey;
113 const OSSymbol * gIOConsoleSessionSecureInputPIDKey;
114
115 static int gIOResourceGenerationCount;
116
117 const OSSymbol * gIOServiceKey;
118 const OSSymbol * gIOPublishNotification;
119 const OSSymbol * gIOFirstPublishNotification;
120 const OSSymbol * gIOMatchedNotification;
121 const OSSymbol * gIOFirstMatchNotification;
122 const OSSymbol * gIOTerminatedNotification;
123
124 const OSSymbol * gIOGeneralInterest;
125 const OSSymbol * gIOBusyInterest;
126 const OSSymbol * gIOAppPowerStateInterest;
127 const OSSymbol * gIOPriorityPowerStateInterest;
128
129 static OSDictionary * gNotifications;
130 static IORecursiveLock * gNotificationLock;
131
132 static IOService * gIOResources;
133 static IOService * gIOServiceRoot;
134
135 static OSOrderedSet * gJobs;
136 static semaphore_port_t gJobsSemaphore;
137 static IOLock * gJobsLock;
138 static int gOutstandingJobs;
139 static int gNumConfigThreads;
140 static int gNumWaitingThreads;
141 static IOLock * gIOServiceBusyLock;
142
143 static thread_t gIOTerminateThread;
144 static UInt32 gIOTerminateWork;
145 static OSArray * gIOTerminatePhase2List;
146 static OSArray * gIOStopList;
147 static OSArray * gIOStopProviderList;
148 static OSArray * gIOFinalizeList;
149
150 static SInt32 gIOConsoleUsersSeed;
151 static OSData * gIOConsoleUsersSeedValue;
152
153 extern const OSSymbol * gIODTPHandleKey;
154
155 const OSSymbol * gIOPlatformSleepActionKey;
156 const OSSymbol * gIOPlatformWakeActionKey;
157 const OSSymbol * gIOPlatformQuiesceActionKey;
158 const OSSymbol * gIOPlatformActiveActionKey;
159
160 const OSSymbol * gIOPlatformFunctionHandlerSet;
161
162 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
163
164 #define LOCKREADNOTIFY() \
165 IORecursiveLockLock( gNotificationLock )
166 #define LOCKWRITENOTIFY() \
167 IORecursiveLockLock( gNotificationLock )
168 #define LOCKWRITE2READNOTIFY()
169 #define UNLOCKNOTIFY() \
170 IORecursiveLockUnlock( gNotificationLock )
171 #define SLEEPNOTIFY(event) \
172 IORecursiveLockSleep( gNotificationLock, (void *)(event), THREAD_UNINT )
173 #define SLEEPNOTIFYTO(event, deadline) \
174 IORecursiveLockSleepDeadline( gNotificationLock, (void *)(event), deadline, THREAD_UNINT )
175 #define WAKEUPNOTIFY(event) \
176 IORecursiveLockWakeup( gNotificationLock, (void *)(event), /* wake one */ false )
177
178 #define randomDelay() \
179 int del = read_processor_clock(); \
180 del = (((int)IOThreadSelf()) ^ del ^ (del >> 10)) & 0x3ff; \
181 IOSleep( del );
182
183 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
184
185 #define queue_element(entry, element, type, field) do { \
186 vm_address_t __ele = (vm_address_t) (entry); \
187 __ele -= -4 + ((size_t)(&((type) 4)->field)); \
188 (element) = (type) __ele; \
189 } while(0)
190
191 #define iterqueue(que, elt) \
192 for (queue_entry_t elt = queue_first(que); \
193 !queue_end(que, elt); \
194 elt = queue_next(elt))
195
196 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
197
198 struct ArbitrationLockQueueElement {
199 queue_chain_t link;
200 IOThread thread;
201 IOService * service;
202 unsigned count;
203 bool required;
204 bool aborted;
205 };
206
207 static queue_head_t gArbitrationLockQueueActive;
208 static queue_head_t gArbitrationLockQueueWaiting;
209 static queue_head_t gArbitrationLockQueueFree;
210 static IOLock * gArbitrationLockQueueLock;
211
212 bool IOService::isInactive( void ) const
213 { return( 0 != (kIOServiceInactiveState & getState())); }
214
215
216 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
217
218 #define IOServiceTrace(csc, a, b, c, d) { \
219 if(kIOTraceIOService & gIOKitDebug) { \
220 KERNEL_DEBUG_CONSTANT(IODBG_IOSERVICE(csc), a, b, c, d, 0); \
221 } \
222 }
223
224 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
225
226 #if defined(__i386__) || defined(__x86_64__)
227
228 // Only used by the intel implementation of
229 // IOService::requireMaxBusStall(UInt32 ns)
230 // IOService::requireMaxInterruptDelay(uint32_t ns)
231 struct CpuDelayEntry
232 {
233 IOService * fService;
234 UInt32 fMaxDelay;
235 UInt32 fDelayType;
236 };
237
238 enum {
239 kCpuDelayBusStall, kCpuDelayInterrupt,
240 kCpuNumDelayTypes
241 };
242
243 static OSData *sCpuDelayData = OSData::withCapacity(8 * sizeof(CpuDelayEntry));
244 static IORecursiveLock *sCpuDelayLock = IORecursiveLockAlloc();
245 static OSArray *sCpuLatencyHandlers[kCpuNumDelayTypes];
246 const OSSymbol *sCPULatencyFunctionName[kCpuNumDelayTypes];
247
248 static void
249 requireMaxCpuDelay(IOService * service, UInt32 ns, UInt32 delayType);
250 static IOReturn
251 setLatencyHandler(UInt32 delayType, IOService * target, bool enable);
252
253 #endif /* defined(__i386__) || defined(__x86_64__) */
254
255 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
256
257 void IOService::initialize( void )
258 {
259 kern_return_t err;
260
261 gIOServicePlane = IORegistryEntry::makePlane( kIOServicePlane );
262 gIOPowerPlane = IORegistryEntry::makePlane( kIOPowerPlane );
263
264 gIOProviderClassKey = OSSymbol::withCStringNoCopy( kIOProviderClassKey );
265 gIONameMatchKey = OSSymbol::withCStringNoCopy( kIONameMatchKey );
266 gIONameMatchedKey = OSSymbol::withCStringNoCopy( kIONameMatchedKey );
267 gIOPropertyMatchKey = OSSymbol::withCStringNoCopy( kIOPropertyMatchKey );
268 gIOPathMatchKey = OSSymbol::withCStringNoCopy( kIOPathMatchKey );
269 gIOLocationMatchKey = OSSymbol::withCStringNoCopy( kIOLocationMatchKey );
270 gIOParentMatchKey = OSSymbol::withCStringNoCopy( kIOParentMatchKey );
271
272 gIOMatchCategoryKey = OSSymbol::withCStringNoCopy( kIOMatchCategoryKey );
273 gIODefaultMatchCategoryKey = OSSymbol::withCStringNoCopy(
274 kIODefaultMatchCategoryKey );
275 gIOMatchedServiceCountKey = OSSymbol::withCStringNoCopy(
276 kIOMatchedServiceCountKey );
277
278 gIOUserClientClassKey = OSSymbol::withCStringNoCopy( kIOUserClientClassKey );
279
280 gIOResourcesKey = OSSymbol::withCStringNoCopy( kIOResourcesClass );
281 gIOResourceMatchKey = OSSymbol::withCStringNoCopy( kIOResourceMatchKey );
282
283 gIODeviceMemoryKey = OSSymbol::withCStringNoCopy( "IODeviceMemory" );
284 gIOInterruptControllersKey
285 = OSSymbol::withCStringNoCopy("IOInterruptControllers");
286 gIOInterruptSpecifiersKey
287 = OSSymbol::withCStringNoCopy("IOInterruptSpecifiers");
288
289 gIOMapperIDKey = OSSymbol::withCStringNoCopy(kIOMapperIDKey);
290
291 gIOKitDebugKey = OSSymbol::withCStringNoCopy( kIOKitDebugKey );
292
293 gIOCommandPoolSizeKey = OSSymbol::withCStringNoCopy( kIOCommandPoolSizeKey );
294
295 gIOGeneralInterest = OSSymbol::withCStringNoCopy( kIOGeneralInterest );
296 gIOBusyInterest = OSSymbol::withCStringNoCopy( kIOBusyInterest );
297 gIOAppPowerStateInterest = OSSymbol::withCStringNoCopy( kIOAppPowerStateInterest );
298 gIOPriorityPowerStateInterest = OSSymbol::withCStringNoCopy( kIOPriorityPowerStateInterest );
299
300 gNotifications = OSDictionary::withCapacity( 1 );
301 gIOPublishNotification = OSSymbol::withCStringNoCopy(
302 kIOPublishNotification );
303 gIOFirstPublishNotification = OSSymbol::withCStringNoCopy(
304 kIOFirstPublishNotification );
305 gIOMatchedNotification = OSSymbol::withCStringNoCopy(
306 kIOMatchedNotification );
307 gIOFirstMatchNotification = OSSymbol::withCStringNoCopy(
308 kIOFirstMatchNotification );
309 gIOTerminatedNotification = OSSymbol::withCStringNoCopy(
310 kIOTerminatedNotification );
311 gIOServiceKey = OSSymbol::withCStringNoCopy( kIOServiceClass);
312
313 gIOConsoleUsersKey = OSSymbol::withCStringNoCopy( kIOConsoleUsersKey);
314 gIOConsoleSessionUIDKey = OSSymbol::withCStringNoCopy( kIOConsoleSessionUIDKey);
315 gIOConsoleUsersSeedKey = OSSymbol::withCStringNoCopy( kIOConsoleUsersSeedKey);
316 gIOConsoleSessionOnConsoleKey = OSSymbol::withCStringNoCopy( kIOConsoleSessionOnConsoleKey);
317 gIOConsoleSessionSecureInputPIDKey = OSSymbol::withCStringNoCopy( kIOConsoleSessionSecureInputPIDKey);
318 gIOConsoleUsersSeedValue = OSData::withBytesNoCopy(&gIOConsoleUsersSeed, sizeof(gIOConsoleUsersSeed));
319
320 gIOPlatformSleepActionKey = OSSymbol::withCStringNoCopy(kIOPlatformSleepActionKey);
321 gIOPlatformWakeActionKey = OSSymbol::withCStringNoCopy(kIOPlatformWakeActionKey);
322 gIOPlatformQuiesceActionKey = OSSymbol::withCStringNoCopy(kIOPlatformQuiesceActionKey);
323 gIOPlatformActiveActionKey = OSSymbol::withCStringNoCopy(kIOPlatformActiveActionKey);
324
325 gIOPlatformFunctionHandlerSet = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerSet);
326 #if defined(__i386__) || defined(__x86_64__)
327 sCPULatencyFunctionName[kCpuDelayBusStall] = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerMaxBusDelay);
328 sCPULatencyFunctionName[kCpuDelayInterrupt] = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerMaxInterruptDelay);
329 #endif
330 gNotificationLock = IORecursiveLockAlloc();
331
332 assert( gIOServicePlane && gIODeviceMemoryKey
333 && gIOInterruptControllersKey && gIOInterruptSpecifiersKey
334 && gIOResourcesKey && gNotifications && gNotificationLock
335 && gIOProviderClassKey && gIONameMatchKey && gIONameMatchedKey
336 && gIOMatchCategoryKey && gIODefaultMatchCategoryKey
337 && gIOPublishNotification && gIOMatchedNotification
338 && gIOTerminatedNotification && gIOServiceKey
339 && gIOConsoleUsersKey && gIOConsoleSessionUIDKey
340 && gIOConsoleSessionOnConsoleKey && gIOConsoleSessionSecureInputPIDKey
341 && gIOConsoleUsersSeedKey && gIOConsoleUsersSeedValue);
342
343 gJobsLock = IOLockAlloc();
344 gJobs = OSOrderedSet::withCapacity( 10 );
345
346 gIOServiceBusyLock = IOLockAlloc();
347
348 err = semaphore_create(kernel_task, &gJobsSemaphore, SYNC_POLICY_FIFO, 0);
349
350 assert( gIOServiceBusyLock && gJobs && gJobsLock && (err == KERN_SUCCESS) );
351
352 gIOResources = IOResources::resources();
353 assert( gIOResources );
354
355 gArbitrationLockQueueLock = IOLockAlloc();
356 queue_init(&gArbitrationLockQueueActive);
357 queue_init(&gArbitrationLockQueueWaiting);
358 queue_init(&gArbitrationLockQueueFree);
359
360 assert( gArbitrationLockQueueLock );
361
362 gIOTerminatePhase2List = OSArray::withCapacity( 2 );
363 gIOStopList = OSArray::withCapacity( 16 );
364 gIOStopProviderList = OSArray::withCapacity( 16 );
365 gIOFinalizeList = OSArray::withCapacity( 16 );
366 assert( gIOTerminatePhase2List && gIOStopList && gIOStopProviderList && gIOFinalizeList );
367 }
368
369 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
370
371 #if IOMATCHDEBUG
372 static UInt64 getDebugFlags( OSDictionary * props )
373 {
374 OSNumber * debugProp;
375 UInt64 debugFlags;
376
377 debugProp = OSDynamicCast( OSNumber,
378 props->getObject( gIOKitDebugKey ));
379 if( debugProp)
380 debugFlags = debugProp->unsigned64BitValue();
381 else
382 debugFlags = gIOKitDebug;
383
384 return( debugFlags );
385 }
386 #endif
387
388 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
389
390 // Probe a matched service and return an instance to be started.
391 // The default score is from the property table, & may be altered
392 // during probe to change the start order.
393
394 IOService * IOService::probe( IOService * provider,
395 SInt32 * score )
396 {
397 return( this );
398 }
399
400 bool IOService::start( IOService * provider )
401 {
402 return( true );
403 }
404
405 void IOService::stop( IOService * provider )
406 {
407 }
408
409 void IOService::free( void )
410 {
411 requireMaxBusStall(0);
412 requireMaxInterruptDelay(0);
413 if( getPropertyTable())
414 unregisterAllInterest();
415 PMfree();
416 super::free();
417 }
418
419 /*
420 * Attach in service plane
421 */
422 bool IOService::attach( IOService * provider )
423 {
424 bool ok;
425
426 if( provider) {
427
428 if( gIOKitDebug & kIOLogAttach)
429 LOG( "%s::attach(%s)\n", getName(),
430 provider->getName());
431
432 provider->lockForArbitration();
433 if( provider->__state[0] & kIOServiceInactiveState)
434 ok = false;
435 else
436 ok = attachToParent( provider, gIOServicePlane);
437 provider->unlockForArbitration();
438
439 } else {
440 gIOServiceRoot = this;
441 ok = attachToParent( getRegistryRoot(), gIOServicePlane);
442 }
443
444 return( ok );
445 }
446
447 IOService * IOService::getServiceRoot( void )
448 {
449 return( gIOServiceRoot );
450 }
451
452 void IOService::detach( IOService * provider )
453 {
454 IOService * newProvider = 0;
455 SInt32 busy;
456 bool adjParent;
457
458 if( gIOKitDebug & kIOLogAttach)
459 LOG("%s::detach(%s)\n", getName(), provider->getName());
460
461 lockForArbitration();
462
463 adjParent = ((busy = (__state[1] & kIOServiceBusyStateMask))
464 && (provider == getProvider()));
465
466 detachFromParent( provider, gIOServicePlane );
467
468 if( busy) {
469 newProvider = getProvider();
470 if( busy && (__state[1] & kIOServiceTermPhase3State) && (0 == newProvider))
471 _adjustBusy( -busy );
472 }
473
474 unlockForArbitration();
475
476 if( newProvider) {
477 newProvider->lockForArbitration();
478 newProvider->_adjustBusy(1);
479 newProvider->unlockForArbitration();
480 }
481
482 // check for last client detach from a terminated service
483 if( provider->lockForArbitration( true )) {
484 if( adjParent)
485 provider->_adjustBusy( -1 );
486 if( (provider->__state[1] & kIOServiceTermPhase3State)
487 && (0 == provider->getClient())) {
488 provider->scheduleFinalize();
489 }
490 provider->unlockForArbitration();
491 }
492 }
493
494 /*
495 * Register instance - publish it for matching
496 */
497
498 void IOService::registerService( IOOptionBits options )
499 {
500 char * pathBuf;
501 const char * path;
502 char * skip;
503 int len;
504 enum { kMaxPathLen = 256 };
505 enum { kMaxChars = 63 };
506
507 IORegistryEntry * parent = this;
508 IORegistryEntry * root = getRegistryRoot();
509 while( parent && (parent != root))
510 parent = parent->getParentEntry( gIOServicePlane);
511
512 if( parent != root) {
513 IOLog("%s: not registry member at registerService()\n", getName());
514 return;
515 }
516
517 // Allow the Platform Expert to adjust this node.
518 if( gIOPlatform && (!gIOPlatform->platformAdjustService(this)))
519 return;
520
521 if( (this != gIOResources)
522 && (kIOLogRegister & gIOKitDebug)) {
523
524 pathBuf = (char *) IOMalloc( kMaxPathLen );
525
526 IOLog( "Registering: " );
527
528 len = kMaxPathLen;
529 if( pathBuf && getPath( pathBuf, &len, gIOServicePlane)) {
530
531 path = pathBuf;
532 if( len > kMaxChars) {
533 IOLog("..");
534 len -= kMaxChars;
535 path += len;
536 if( (skip = strchr( path, '/')))
537 path = skip;
538 }
539 } else
540 path = getName();
541
542 IOLog( "%s\n", path );
543
544 if( pathBuf)
545 IOFree( pathBuf, kMaxPathLen );
546 }
547
548 startMatching( options );
549 }
550
551 void IOService::startMatching( IOOptionBits options )
552 {
553 IOService * provider;
554 UInt32 prevBusy = 0;
555 bool needConfig;
556 bool needWake = false;
557 bool ok;
558 bool sync;
559 bool waitAgain;
560
561 lockForArbitration();
562
563 sync = (options & kIOServiceSynchronous)
564 || ((provider = getProvider())
565 && (provider->__state[1] & kIOServiceSynchronousState));
566
567 if ( options & kIOServiceAsynchronous )
568 sync = false;
569
570 needConfig = (0 == (__state[1] & (kIOServiceNeedConfigState | kIOServiceConfigState)))
571 && (0 == (__state[0] & kIOServiceInactiveState));
572
573 __state[1] |= kIOServiceNeedConfigState;
574
575 // __state[0] &= ~kIOServiceInactiveState;
576
577 // if( sync) LOG("OSKernelStackRemaining = %08x @ %s\n",
578 // OSKernelStackRemaining(), getName());
579
580 if( needConfig) {
581 prevBusy = _adjustBusy( 1 );
582 needWake = (0 != (kIOServiceSyncPubState & __state[1]));
583 }
584
585 if( sync)
586 __state[1] |= kIOServiceSynchronousState;
587 else
588 __state[1] &= ~kIOServiceSynchronousState;
589
590 unlockForArbitration();
591
592 if( needConfig) {
593
594 if( needWake) {
595 IOLockLock( gIOServiceBusyLock );
596 thread_wakeup( (event_t) this/*&__state[1]*/ );
597 IOLockUnlock( gIOServiceBusyLock );
598
599 } else if( !sync || (kIOServiceAsynchronous & options)) {
600
601 ok = (0 != _IOServiceJob::startJob( this, kMatchNubJob, options ));
602
603 } else do {
604
605 if( (__state[1] & kIOServiceNeedConfigState))
606 doServiceMatch( options );
607
608 lockForArbitration();
609 IOLockLock( gIOServiceBusyLock );
610
611 waitAgain = (prevBusy < (__state[1] & kIOServiceBusyStateMask));
612 if( waitAgain)
613 __state[1] |= kIOServiceSyncPubState | kIOServiceBusyWaiterState;
614 else
615 __state[1] &= ~kIOServiceSyncPubState;
616
617 unlockForArbitration();
618
619 if( waitAgain)
620 assert_wait( (event_t) this/*&__state[1]*/, THREAD_UNINT);
621
622 IOLockUnlock( gIOServiceBusyLock );
623 if( waitAgain)
624 thread_block(THREAD_CONTINUE_NULL);
625
626 } while( waitAgain );
627 }
628 }
629
630 IOReturn IOService::catalogNewDrivers( OSOrderedSet * newTables )
631 {
632 OSDictionary * table;
633 OSSet * set;
634 OSSet * allSet = 0;
635 IOService * service;
636 #if IOMATCHDEBUG
637 SInt32 count = 0;
638 #endif
639
640 newTables->retain();
641
642 while( (table = (OSDictionary *) newTables->getFirstObject())) {
643
644 LOCKWRITENOTIFY();
645 set = (OSSet *) copyExistingServices( table,
646 kIOServiceRegisteredState,
647 kIOServiceExistingSet);
648 UNLOCKNOTIFY();
649 if( set) {
650
651 #if IOMATCHDEBUG
652 count += set->getCount();
653 #endif
654 if (allSet) {
655 allSet->merge((const OSSet *) set);
656 set->release();
657 }
658 else
659 allSet = set;
660 }
661
662 #if IOMATCHDEBUG
663 if( getDebugFlags( table ) & kIOLogMatch)
664 LOG("Matching service count = %ld\n", (long)count);
665 #endif
666 newTables->removeObject(table);
667 }
668
669 if (allSet) {
670 while( (service = (IOService *) allSet->getAnyObject())) {
671 service->startMatching(kIOServiceAsynchronous);
672 allSet->removeObject(service);
673 }
674 allSet->release();
675 }
676
677 newTables->release();
678
679 return( kIOReturnSuccess );
680 }
681
682 _IOServiceJob * _IOServiceJob::startJob( IOService * nub, int type,
683 IOOptionBits options )
684 {
685 _IOServiceJob * job;
686
687 job = new _IOServiceJob;
688 if( job && !job->init()) {
689 job->release();
690 job = 0;
691 }
692
693 if( job) {
694 job->type = type;
695 job->nub = nub;
696 job->options = options;
697 nub->retain(); // thread will release()
698 pingConfig( job );
699 }
700
701 return( job );
702 }
703
704 /*
705 * Called on a registered service to see if it matches
706 * a property table.
707 */
708
709 bool IOService::matchPropertyTable( OSDictionary * table, SInt32 * score )
710 {
711 return( matchPropertyTable(table) );
712 }
713
714 bool IOService::matchPropertyTable( OSDictionary * table )
715 {
716 return( true );
717 }
718
719 /*
720 * Called on a matched service to allocate resources
721 * before first driver is attached.
722 */
723
724 IOReturn IOService::getResources( void )
725 {
726 return( kIOReturnSuccess);
727 }
728
729 /*
730 * Client/provider accessors
731 */
732
733 IOService * IOService::getProvider( void ) const
734 {
735 IOService * self = (IOService *) this;
736 IOService * parent;
737 SInt32 generation;
738
739 parent = __provider;
740 generation = getGenerationCount();
741 if( __providerGeneration == generation)
742 return( parent );
743
744 parent = (IOService *) getParentEntry( gIOServicePlane);
745 if( parent == IORegistryEntry::getRegistryRoot())
746 /* root is not an IOService */
747 parent = 0;
748
749 self->__provider = parent;
750 // save the count before getParentEntry()
751 self->__providerGeneration = generation;
752
753 return( parent );
754 }
755
756 IOWorkLoop * IOService::getWorkLoop() const
757 {
758 IOService *provider = getProvider();
759
760 if (provider)
761 return provider->getWorkLoop();
762 else
763 return 0;
764 }
765
766 OSIterator * IOService::getProviderIterator( void ) const
767 {
768 return( getParentIterator( gIOServicePlane));
769 }
770
771 IOService * IOService::getClient( void ) const
772 {
773 return( (IOService *) getChildEntry( gIOServicePlane));
774 }
775
776 OSIterator * IOService::getClientIterator( void ) const
777 {
778 return( getChildIterator( gIOServicePlane));
779 }
780
781 OSIterator * _IOOpenServiceIterator::iterator( OSIterator * _iter,
782 const IOService * client,
783 const IOService * provider )
784 {
785 _IOOpenServiceIterator * inst;
786
787 if( !_iter)
788 return( 0 );
789
790 inst = new _IOOpenServiceIterator;
791
792 if( inst && !inst->init()) {
793 inst->release();
794 inst = 0;
795 }
796 if( inst) {
797 inst->iter = _iter;
798 inst->client = client;
799 inst->provider = provider;
800 }
801
802 return( inst );
803 }
804
805 void _IOOpenServiceIterator::free()
806 {
807 iter->release();
808 if( last)
809 last->unlockForArbitration();
810 OSIterator::free();
811 }
812
813 OSObject * _IOOpenServiceIterator::getNextObject()
814 {
815 IOService * next;
816
817 if( last)
818 last->unlockForArbitration();
819
820 while( (next = (IOService *) iter->getNextObject())) {
821
822 next->lockForArbitration();
823 if( (client && (next->isOpen( client )))
824 || (provider && (provider->isOpen( next ))) )
825 break;
826 next->unlockForArbitration();
827 }
828
829 last = next;
830
831 return( next );
832 }
833
834 bool _IOOpenServiceIterator::isValid()
835 {
836 return( iter->isValid() );
837 }
838
839 void _IOOpenServiceIterator::reset()
840 {
841 if( last) {
842 last->unlockForArbitration();
843 last = 0;
844 }
845 iter->reset();
846 }
847
848 OSIterator * IOService::getOpenProviderIterator( void ) const
849 {
850 return( _IOOpenServiceIterator::iterator( getProviderIterator(), this, 0 ));
851 }
852
853 OSIterator * IOService::getOpenClientIterator( void ) const
854 {
855 return( _IOOpenServiceIterator::iterator( getClientIterator(), 0, this ));
856 }
857
858
859 IOReturn IOService::callPlatformFunction( const OSSymbol * functionName,
860 bool waitForFunction,
861 void *param1, void *param2,
862 void *param3, void *param4 )
863 {
864 IOReturn result = kIOReturnUnsupported;
865 IOService *provider;
866
867 if (gIOPlatformFunctionHandlerSet == functionName)
868 {
869 #if defined(__i386__) || defined(__x86_64__)
870 const OSSymbol * functionHandlerName = (const OSSymbol *) param1;
871 IOService * target = (IOService *) param2;
872 bool enable = (param3 != 0);
873
874 if (sCPULatencyFunctionName[kCpuDelayBusStall] == functionHandlerName)
875 result = setLatencyHandler(kCpuDelayBusStall, target, enable);
876 else if (sCPULatencyFunctionName[kCpuDelayInterrupt] == param1)
877 result = setLatencyHandler(kCpuDelayInterrupt, target, enable);
878 #endif /* defined(__i386__) || defined(__x86_64__) */
879 }
880
881 if ((kIOReturnUnsupported == result) && (provider = getProvider())) {
882 result = provider->callPlatformFunction(functionName, waitForFunction,
883 param1, param2, param3, param4);
884 }
885
886 return result;
887 }
888
889 IOReturn IOService::callPlatformFunction( const char * functionName,
890 bool waitForFunction,
891 void *param1, void *param2,
892 void *param3, void *param4 )
893 {
894 IOReturn result = kIOReturnNoMemory;
895 const OSSymbol *functionSymbol = OSSymbol::withCString(functionName);
896
897 if (functionSymbol != 0) {
898 result = callPlatformFunction(functionSymbol, waitForFunction,
899 param1, param2, param3, param4);
900 functionSymbol->release();
901 }
902
903 return result;
904 }
905
906
907 /*
908 * Accessors for global services
909 */
910
911 IOPlatformExpert * IOService::getPlatform( void )
912 {
913 return( gIOPlatform);
914 }
915
916 class IOPMrootDomain * IOService::getPMRootDomain( void )
917 {
918 return( gIOPMRootDomain);
919 }
920
921 IOService * IOService::getResourceService( void )
922 {
923 return( gIOResources );
924 }
925
926 void IOService::setPlatform( IOPlatformExpert * platform)
927 {
928 gIOPlatform = platform;
929 gIOResources->attachToParent( gIOServiceRoot, gIOServicePlane );
930 }
931
932 void IOService::setPMRootDomain( class IOPMrootDomain * rootDomain)
933 {
934 gIOPMRootDomain = rootDomain;
935 publishResource("IOKit");
936 }
937
938 /*
939 * Stacking change
940 */
941
942 bool IOService::lockForArbitration( bool isSuccessRequired )
943 {
944 bool found;
945 bool success;
946 ArbitrationLockQueueElement * element;
947 ArbitrationLockQueueElement * active;
948 ArbitrationLockQueueElement * waiting;
949
950 enum { kPutOnFreeQueue, kPutOnActiveQueue, kPutOnWaitingQueue } action;
951
952 // lock global access
953 IOTakeLock( gArbitrationLockQueueLock );
954
955 // obtain an unused queue element
956 if( !queue_empty( &gArbitrationLockQueueFree )) {
957 queue_remove_first( &gArbitrationLockQueueFree,
958 element,
959 ArbitrationLockQueueElement *,
960 link );
961 } else {
962 element = IONew( ArbitrationLockQueueElement, 1 );
963 assert( element );
964 }
965
966 // prepare the queue element
967 element->thread = IOThreadSelf();
968 element->service = this;
969 element->count = 1;
970 element->required = isSuccessRequired;
971 element->aborted = false;
972
973 // determine whether this object is already locked (ie. on active queue)
974 found = false;
975 queue_iterate( &gArbitrationLockQueueActive,
976 active,
977 ArbitrationLockQueueElement *,
978 link )
979 {
980 if( active->service == element->service ) {
981 found = true;
982 break;
983 }
984 }
985
986 if( found ) { // this object is already locked
987
988 // determine whether it is the same or a different thread trying to lock
989 if( active->thread != element->thread ) { // it is a different thread
990
991 ArbitrationLockQueueElement * victim = 0;
992
993 // before placing this new thread on the waiting queue, we look for
994 // a deadlock cycle...
995
996 while( 1 ) {
997 // determine whether the active thread holding the object we
998 // want is waiting for another object to be unlocked
999 found = false;
1000 queue_iterate( &gArbitrationLockQueueWaiting,
1001 waiting,
1002 ArbitrationLockQueueElement *,
1003 link )
1004 {
1005 if( waiting->thread == active->thread ) {
1006 assert( false == waiting->aborted );
1007 found = true;
1008 break;
1009 }
1010 }
1011
1012 if( found ) { // yes, active thread waiting for another object
1013
1014 // this may be a candidate for rejection if the required
1015 // flag is not set, should we detect a deadlock later on
1016 if( false == waiting->required )
1017 victim = waiting;
1018
1019 // find the thread that is holding this other object, that
1020 // is blocking the active thread from proceeding (fun :-)
1021 found = false;
1022 queue_iterate( &gArbitrationLockQueueActive,
1023 active, // (reuse active queue element)
1024 ArbitrationLockQueueElement *,
1025 link )
1026 {
1027 if( active->service == waiting->service ) {
1028 found = true;
1029 break;
1030 }
1031 }
1032
1033 // someone must be holding it or it wouldn't be waiting
1034 assert( found );
1035
1036 if( active->thread == element->thread ) {
1037
1038 // doh, it's waiting for the thread that originated
1039 // this whole lock (ie. current thread) -> deadlock
1040 if( false == element->required ) { // willing to fail?
1041
1042 // the originating thread doesn't have the required
1043 // flag, so it can fail
1044 success = false; // (fail originating lock request)
1045 break; // (out of while)
1046
1047 } else { // originating thread is not willing to fail
1048
1049 // see if we came across a waiting thread that did
1050 // not have the 'required' flag set: we'll fail it
1051 if( victim ) {
1052
1053 // we do have a willing victim, fail it's lock
1054 victim->aborted = true;
1055
1056 // take the victim off the waiting queue
1057 queue_remove( &gArbitrationLockQueueWaiting,
1058 victim,
1059 ArbitrationLockQueueElement *,
1060 link );
1061
1062 // wake the victim
1063 IOLockWakeup( gArbitrationLockQueueLock,
1064 victim,
1065 /* one thread */ true );
1066
1067 // allow this thread to proceed (ie. wait)
1068 success = true; // (put request on wait queue)
1069 break; // (out of while)
1070 } else {
1071
1072 // all the waiting threads we came across in
1073 // finding this loop had the 'required' flag
1074 // set, so we've got a deadlock we can't avoid
1075 panic("I/O Kit: Unrecoverable deadlock.");
1076 }
1077 }
1078 } else {
1079 // repeat while loop, redefining active thread to be the
1080 // thread holding "this other object" (see above), and
1081 // looking for threads waiting on it; note the active
1082 // variable points to "this other object" already... so
1083 // there nothing to do in this else clause.
1084 }
1085 } else { // no, active thread is not waiting for another object
1086
1087 success = true; // (put request on wait queue)
1088 break; // (out of while)
1089 }
1090 } // while forever
1091
1092 if( success ) { // put the request on the waiting queue?
1093 kern_return_t wait_result;
1094
1095 // place this thread on the waiting queue and put it to sleep;
1096 // we place it at the tail of the queue...
1097 queue_enter( &gArbitrationLockQueueWaiting,
1098 element,
1099 ArbitrationLockQueueElement *,
1100 link );
1101
1102 // declare that this thread will wait for a given event
1103 restart_sleep: wait_result = assert_wait( element,
1104 element->required ? THREAD_UNINT
1105 : THREAD_INTERRUPTIBLE );
1106
1107 // unlock global access
1108 IOUnlock( gArbitrationLockQueueLock );
1109
1110 // put thread to sleep, waiting for our event to fire...
1111 if (wait_result == THREAD_WAITING)
1112 wait_result = thread_block(THREAD_CONTINUE_NULL);
1113
1114
1115 // ...and we've been woken up; we might be in one of two states:
1116 // (a) we've been aborted and our queue element is not on
1117 // any of the three queues, but is floating around
1118 // (b) we're allowed to proceed with the lock and we have
1119 // already been moved from the waiting queue to the
1120 // active queue.
1121 // ...plus a 3rd state, should the thread have been interrupted:
1122 // (c) we're still on the waiting queue
1123
1124 // determine whether we were interrupted out of our sleep
1125 if( THREAD_INTERRUPTED == wait_result ) {
1126
1127 // re-lock global access
1128 IOTakeLock( gArbitrationLockQueueLock );
1129
1130 // determine whether we're still on the waiting queue
1131 found = false;
1132 queue_iterate( &gArbitrationLockQueueWaiting,
1133 waiting, // (reuse waiting queue element)
1134 ArbitrationLockQueueElement *,
1135 link )
1136 {
1137 if( waiting == element ) {
1138 found = true;
1139 break;
1140 }
1141 }
1142
1143 if( found ) { // yes, we're still on the waiting queue
1144
1145 // determine whether we're willing to fail
1146 if( false == element->required ) {
1147
1148 // mark us as aborted
1149 element->aborted = true;
1150
1151 // take us off the waiting queue
1152 queue_remove( &gArbitrationLockQueueWaiting,
1153 element,
1154 ArbitrationLockQueueElement *,
1155 link );
1156 } else { // we are not willing to fail
1157
1158 // ignore interruption, go back to sleep
1159 goto restart_sleep;
1160 }
1161 }
1162
1163 // unlock global access
1164 IOUnlock( gArbitrationLockQueueLock );
1165
1166 // proceed as though this were a normal wake up
1167 wait_result = THREAD_AWAKENED;
1168 }
1169
1170 assert( THREAD_AWAKENED == wait_result );
1171
1172 // determine whether we've been aborted while we were asleep
1173 if( element->aborted ) {
1174 assert( false == element->required );
1175
1176 // re-lock global access
1177 IOTakeLock( gArbitrationLockQueueLock );
1178
1179 action = kPutOnFreeQueue;
1180 success = false;
1181 } else { // we weren't aborted, so we must be ready to go :-)
1182
1183 // we've already been moved from waiting to active queue
1184 return true;
1185 }
1186
1187 } else { // the lock request is to be failed
1188
1189 // return unused queue element to queue
1190 action = kPutOnFreeQueue;
1191 }
1192 } else { // it is the same thread, recursive access is allowed
1193
1194 // add one level of recursion
1195 active->count++;
1196
1197 // return unused queue element to queue
1198 action = kPutOnFreeQueue;
1199 success = true;
1200 }
1201 } else { // this object is not already locked, so let this thread through
1202 action = kPutOnActiveQueue;
1203 success = true;
1204 }
1205
1206 // put the new element on a queue
1207 if( kPutOnActiveQueue == action ) {
1208 queue_enter( &gArbitrationLockQueueActive,
1209 element,
1210 ArbitrationLockQueueElement *,
1211 link );
1212 } else if( kPutOnFreeQueue == action ) {
1213 queue_enter( &gArbitrationLockQueueFree,
1214 element,
1215 ArbitrationLockQueueElement *,
1216 link );
1217 } else {
1218 assert( 0 ); // kPutOnWaitingQueue never occurs, handled specially above
1219 }
1220
1221 // unlock global access
1222 IOUnlock( gArbitrationLockQueueLock );
1223
1224 return( success );
1225 }
1226
1227 void IOService::unlockForArbitration( void )
1228 {
1229 bool found;
1230 ArbitrationLockQueueElement * element;
1231
1232 // lock global access
1233 IOTakeLock( gArbitrationLockQueueLock );
1234
1235 // find the lock element for this object (ie. on active queue)
1236 found = false;
1237 queue_iterate( &gArbitrationLockQueueActive,
1238 element,
1239 ArbitrationLockQueueElement *,
1240 link )
1241 {
1242 if( element->service == this ) {
1243 found = true;
1244 break;
1245 }
1246 }
1247
1248 assert( found );
1249
1250 // determine whether the lock has been taken recursively
1251 if( element->count > 1 ) {
1252 // undo one level of recursion
1253 element->count--;
1254
1255 } else {
1256
1257 // remove it from the active queue
1258 queue_remove( &gArbitrationLockQueueActive,
1259 element,
1260 ArbitrationLockQueueElement *,
1261 link );
1262
1263 // put it on the free queue
1264 queue_enter( &gArbitrationLockQueueFree,
1265 element,
1266 ArbitrationLockQueueElement *,
1267 link );
1268
1269 // determine whether a thread is waiting for object (head to tail scan)
1270 found = false;
1271 queue_iterate( &gArbitrationLockQueueWaiting,
1272 element,
1273 ArbitrationLockQueueElement *,
1274 link )
1275 {
1276 if( element->service == this ) {
1277 found = true;
1278 break;
1279 }
1280 }
1281
1282 if ( found ) { // we found an interested thread on waiting queue
1283
1284 // remove it from the waiting queue
1285 queue_remove( &gArbitrationLockQueueWaiting,
1286 element,
1287 ArbitrationLockQueueElement *,
1288 link );
1289
1290 // put it on the active queue
1291 queue_enter( &gArbitrationLockQueueActive,
1292 element,
1293 ArbitrationLockQueueElement *,
1294 link );
1295
1296 // wake the waiting thread
1297 IOLockWakeup( gArbitrationLockQueueLock,
1298 element,
1299 /* one thread */ true );
1300 }
1301 }
1302
1303 // unlock global access
1304 IOUnlock( gArbitrationLockQueueLock );
1305 }
1306
1307 void IOService::applyToProviders( IOServiceApplierFunction applier,
1308 void * context )
1309 {
1310 applyToParents( (IORegistryEntryApplierFunction) applier,
1311 context, gIOServicePlane );
1312 }
1313
1314 void IOService::applyToClients( IOServiceApplierFunction applier,
1315 void * context )
1316 {
1317 applyToChildren( (IORegistryEntryApplierFunction) applier,
1318 context, gIOServicePlane );
1319 }
1320
1321
1322 /*
1323 * Client messages
1324 */
1325
1326
1327 // send a message to a client or interested party of this service
1328 IOReturn IOService::messageClient( UInt32 type, OSObject * client,
1329 void * argument, vm_size_t argSize )
1330 {
1331 IOReturn ret;
1332 IOService * service;
1333 _IOServiceInterestNotifier * notify;
1334
1335 if( (service = OSDynamicCast( IOService, client)))
1336 ret = service->message( type, this, argument );
1337
1338 else if( (notify = OSDynamicCast( _IOServiceInterestNotifier, client))) {
1339
1340 _IOServiceNotifierInvocation invocation;
1341 bool willNotify;
1342
1343 invocation.thread = current_thread();
1344
1345 LOCKWRITENOTIFY();
1346 willNotify = (0 != (kIOServiceNotifyEnable & notify->state));
1347
1348 if( willNotify) {
1349 queue_enter( &notify->handlerInvocations, &invocation,
1350 _IOServiceNotifierInvocation *, link );
1351 }
1352 UNLOCKNOTIFY();
1353
1354 if( willNotify) {
1355
1356 ret = (*notify->handler)( notify->target, notify->ref,
1357 type, this, argument, argSize );
1358
1359 LOCKWRITENOTIFY();
1360 queue_remove( &notify->handlerInvocations, &invocation,
1361 _IOServiceNotifierInvocation *, link );
1362 if( kIOServiceNotifyWaiter & notify->state) {
1363 notify->state &= ~kIOServiceNotifyWaiter;
1364 WAKEUPNOTIFY( notify );
1365 }
1366 UNLOCKNOTIFY();
1367
1368 } else
1369 ret = kIOReturnSuccess;
1370
1371 } else
1372 ret = kIOReturnBadArgument;
1373
1374 return( ret );
1375 }
1376
1377 static void
1378 applyToInterestNotifiers(const IORegistryEntry *target,
1379 const OSSymbol * typeOfInterest,
1380 OSObjectApplierFunction applier,
1381 void * context )
1382 {
1383 OSArray * copyArray = 0;
1384
1385 LOCKREADNOTIFY();
1386
1387 IOCommand *notifyList =
1388 OSDynamicCast( IOCommand, target->getProperty( typeOfInterest ));
1389
1390 if( notifyList) {
1391 copyArray = OSArray::withCapacity(1);
1392
1393 // iterate over queue, entry is set to each element in the list
1394 iterqueue(&notifyList->fCommandChain, entry) {
1395 _IOServiceInterestNotifier * notify;
1396
1397 queue_element(entry, notify, _IOServiceInterestNotifier *, chain);
1398 copyArray->setObject(notify);
1399 }
1400 }
1401 UNLOCKNOTIFY();
1402
1403 if( copyArray) {
1404 unsigned int index;
1405 OSObject * next;
1406
1407 for( index = 0; (next = copyArray->getObject( index )); index++)
1408 (*applier)(next, context);
1409 copyArray->release();
1410 }
1411 }
1412
1413 void IOService::applyToInterested( const OSSymbol * typeOfInterest,
1414 OSObjectApplierFunction applier,
1415 void * context )
1416 {
1417 if (gIOGeneralInterest == typeOfInterest)
1418 applyToClients( (IOServiceApplierFunction) applier, context );
1419 applyToInterestNotifiers(this, typeOfInterest, applier, context);
1420 }
1421
1422 struct MessageClientsContext {
1423 IOService * service;
1424 UInt32 type;
1425 void * argument;
1426 vm_size_t argSize;
1427 IOReturn ret;
1428 };
1429
1430 static void messageClientsApplier( OSObject * object, void * ctx )
1431 {
1432 IOReturn ret;
1433 MessageClientsContext * context = (MessageClientsContext *) ctx;
1434
1435 ret = context->service->messageClient( context->type,
1436 object, context->argument, context->argSize );
1437 if( kIOReturnSuccess != ret)
1438 context->ret = ret;
1439 }
1440
1441 // send a message to all clients
1442 IOReturn IOService::messageClients( UInt32 type,
1443 void * argument, vm_size_t argSize )
1444 {
1445 MessageClientsContext context;
1446
1447 context.service = this;
1448 context.type = type;
1449 context.argument = argument;
1450 context.argSize = argSize;
1451 context.ret = kIOReturnSuccess;
1452
1453 applyToInterested( gIOGeneralInterest,
1454 &messageClientsApplier, &context );
1455
1456 return( context.ret );
1457 }
1458
1459 IOReturn IOService::acknowledgeNotification( IONotificationRef notification,
1460 IOOptionBits response )
1461 {
1462 return( kIOReturnUnsupported );
1463 }
1464
1465 IONotifier * IOService::registerInterest( const OSSymbol * typeOfInterest,
1466 IOServiceInterestHandler handler, void * target, void * ref )
1467 {
1468 _IOServiceInterestNotifier * notify = 0;
1469
1470 if( (typeOfInterest != gIOGeneralInterest)
1471 && (typeOfInterest != gIOBusyInterest)
1472 && (typeOfInterest != gIOAppPowerStateInterest)
1473 && (typeOfInterest != gIOPriorityPowerStateInterest))
1474 return( 0 );
1475
1476 lockForArbitration();
1477 if( 0 == (__state[0] & kIOServiceInactiveState)) {
1478
1479 notify = new _IOServiceInterestNotifier;
1480 if( notify && !notify->init()) {
1481 notify->release();
1482 notify = 0;
1483 }
1484
1485 if( notify) {
1486 notify->handler = handler;
1487 notify->target = target;
1488 notify->ref = ref;
1489 notify->state = kIOServiceNotifyEnable;
1490 queue_init( &notify->handlerInvocations );
1491
1492 ////// queue
1493
1494 LOCKWRITENOTIFY();
1495
1496 // Get the head of the notifier linked list
1497 IOCommand *notifyList = (IOCommand *) getProperty( typeOfInterest );
1498 if (!notifyList || !OSDynamicCast(IOCommand, notifyList)) {
1499 notifyList = OSTypeAlloc(IOCommand);
1500 if (notifyList) {
1501 notifyList->init();
1502 setProperty( typeOfInterest, notifyList);
1503 notifyList->release();
1504 }
1505 }
1506
1507 if (notifyList) {
1508 enqueue(&notifyList->fCommandChain, &notify->chain);
1509 notify->retain(); // ref'ed while in list
1510 }
1511
1512 UNLOCKNOTIFY();
1513 }
1514 }
1515 unlockForArbitration();
1516
1517 return( notify );
1518 }
1519
1520 static void cleanInterestList( OSObject * head )
1521 {
1522 IOCommand *notifyHead = OSDynamicCast(IOCommand, head);
1523 if (!notifyHead)
1524 return;
1525
1526 LOCKWRITENOTIFY();
1527 while ( queue_entry_t entry = dequeue(&notifyHead->fCommandChain) ) {
1528 queue_next(entry) = queue_prev(entry) = 0;
1529
1530 _IOServiceInterestNotifier * notify;
1531
1532 queue_element(entry, notify, _IOServiceInterestNotifier *, chain);
1533 notify->release();
1534 }
1535 UNLOCKNOTIFY();
1536 }
1537
1538 void IOService::unregisterAllInterest( void )
1539 {
1540 cleanInterestList( getProperty( gIOGeneralInterest ));
1541 cleanInterestList( getProperty( gIOBusyInterest ));
1542 cleanInterestList( getProperty( gIOAppPowerStateInterest ));
1543 cleanInterestList( getProperty( gIOPriorityPowerStateInterest ));
1544 }
1545
1546 /*
1547 * _IOServiceInterestNotifier
1548 */
1549
1550 // wait for all threads, other than the current one,
1551 // to exit the handler
1552
1553 void _IOServiceInterestNotifier::wait()
1554 {
1555 _IOServiceNotifierInvocation * next;
1556 bool doWait;
1557
1558 do {
1559 doWait = false;
1560 queue_iterate( &handlerInvocations, next,
1561 _IOServiceNotifierInvocation *, link) {
1562 if( next->thread != current_thread() ) {
1563 doWait = true;
1564 break;
1565 }
1566 }
1567 if( doWait) {
1568 state |= kIOServiceNotifyWaiter;
1569 SLEEPNOTIFY(this);
1570 }
1571
1572 } while( doWait );
1573 }
1574
1575 void _IOServiceInterestNotifier::free()
1576 {
1577 assert( queue_empty( &handlerInvocations ));
1578 OSObject::free();
1579 }
1580
1581 void _IOServiceInterestNotifier::remove()
1582 {
1583 LOCKWRITENOTIFY();
1584
1585 if( queue_next( &chain )) {
1586 remqueue( 0, &chain);
1587 queue_next( &chain) = queue_prev( &chain) = 0;
1588 release();
1589 }
1590
1591 state &= ~kIOServiceNotifyEnable;
1592
1593 wait();
1594
1595 UNLOCKNOTIFY();
1596
1597 release();
1598 }
1599
1600 bool _IOServiceInterestNotifier::disable()
1601 {
1602 bool ret;
1603
1604 LOCKWRITENOTIFY();
1605
1606 ret = (0 != (kIOServiceNotifyEnable & state));
1607 state &= ~kIOServiceNotifyEnable;
1608 if( ret)
1609 wait();
1610
1611 UNLOCKNOTIFY();
1612
1613 return( ret );
1614 }
1615
1616 void _IOServiceInterestNotifier::enable( bool was )
1617 {
1618 LOCKWRITENOTIFY();
1619 if( was)
1620 state |= kIOServiceNotifyEnable;
1621 else
1622 state &= ~kIOServiceNotifyEnable;
1623 UNLOCKNOTIFY();
1624 }
1625
1626 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1627
1628 /*
1629 * Termination
1630 */
1631
1632 #define tailQ(o) setObject(o)
1633 #define headQ(o) setObject(0, o)
1634 #define TLOG(fmt, args...) { if(kIOLogYield & gIOKitDebug) IOLog(fmt, ## args); }
1635
1636 static void _workLoopAction( IOWorkLoop::Action action,
1637 IOService * service,
1638 void * p0 = 0, void * p1 = 0,
1639 void * p2 = 0, void * p3 = 0 )
1640 {
1641 IOWorkLoop * wl;
1642
1643 if( (wl = service->getWorkLoop())) {
1644 wl->retain();
1645 wl->runAction( action, service, p0, p1, p2, p3 );
1646 wl->release();
1647 } else
1648 (*action)( service, p0, p1, p2, p3 );
1649 }
1650
1651 bool IOService::requestTerminate( IOService * provider, IOOptionBits options )
1652 {
1653 bool ok;
1654
1655 // if its our only provider
1656 ok = isParent( provider, gIOServicePlane, true);
1657
1658 // -- compat
1659 if( ok) {
1660 provider->terminateClient( this, options | kIOServiceRecursing );
1661 ok = (0 != (__state[1] & kIOServiceRecursing));
1662 }
1663 // --
1664
1665 return( ok );
1666 }
1667
1668 bool IOService::terminatePhase1( IOOptionBits options )
1669 {
1670 IOService * victim;
1671 IOService * client;
1672 OSIterator * iter;
1673 OSArray * makeInactive;
1674 bool ok;
1675 bool didInactive;
1676 bool startPhase2 = false;
1677
1678 TLOG("%s::terminatePhase1(%08llx)\n", getName(), (long long)options);
1679
1680 uint64_t regID = getRegistryEntryID();
1681 IOServiceTrace(
1682 IOSERVICE_TERMINATE_PHASE1,
1683 (uintptr_t) regID,
1684 (uintptr_t) (regID >> 32),
1685 (uintptr_t) this,
1686 (uintptr_t) options);
1687
1688 // -- compat
1689 if( options & kIOServiceRecursing) {
1690 __state[1] |= kIOServiceRecursing;
1691 return( true );
1692 }
1693 // --
1694
1695 makeInactive = OSArray::withCapacity( 16 );
1696 if( !makeInactive)
1697 return( false );
1698
1699 victim = this;
1700 victim->retain();
1701
1702 while( victim ) {
1703
1704 didInactive = victim->lockForArbitration( true );
1705 if( didInactive) {
1706 didInactive = (0 == (victim->__state[0] & kIOServiceInactiveState));
1707 if( didInactive) {
1708 victim->__state[0] |= kIOServiceInactiveState;
1709 victim->__state[0] &= ~(kIOServiceRegisteredState | kIOServiceMatchedState
1710 | kIOServiceFirstPublishState | kIOServiceFirstMatchState);
1711 victim->_adjustBusy( 1 );
1712 }
1713 victim->unlockForArbitration();
1714 }
1715 if( victim == this)
1716 startPhase2 = didInactive;
1717 if( didInactive) {
1718
1719 victim->deliverNotification( gIOTerminatedNotification, 0, 0xffffffff );
1720 IOUserClient::destroyUserReferences( victim );
1721
1722 iter = victim->getClientIterator();
1723 if( iter) {
1724 while( (client = (IOService *) iter->getNextObject())) {
1725 TLOG("%s::requestTerminate(%s, %08llx)\n",
1726 client->getName(), victim->getName(), (long long)options);
1727 ok = client->requestTerminate( victim, options );
1728 TLOG("%s::requestTerminate(%s, ok = %d)\n",
1729 client->getName(), victim->getName(), ok);
1730
1731 uint64_t regID1 = client->getRegistryEntryID();
1732 uint64_t regID2 = victim->getRegistryEntryID();
1733 IOServiceTrace(
1734 (ok ? IOSERVICE_TERMINATE_REQUEST_OK
1735 : IOSERVICE_TERMINATE_REQUEST_FAIL),
1736 (uintptr_t) regID1,
1737 (uintptr_t) (regID1 >> 32),
1738 (uintptr_t) regID2,
1739 (uintptr_t) (regID2 >> 32));
1740
1741 if( ok)
1742 makeInactive->setObject( client );
1743 }
1744 iter->release();
1745 }
1746 }
1747 victim->release();
1748 victim = (IOService *) makeInactive->getObject(0);
1749 if( victim) {
1750 victim->retain();
1751 makeInactive->removeObject(0);
1752 }
1753 }
1754
1755 makeInactive->release();
1756
1757 if( startPhase2)
1758 scheduleTerminatePhase2( options );
1759
1760 return( true );
1761 }
1762
1763 void IOService::scheduleTerminatePhase2( IOOptionBits options )
1764 {
1765 AbsoluteTime deadline;
1766 int waitResult = THREAD_AWAKENED;
1767 bool wait, haveDeadline = false;
1768
1769 options |= kIOServiceRequired;
1770
1771 retain();
1772
1773 IOLockLock( gJobsLock );
1774
1775 if( (options & kIOServiceSynchronous)
1776 && (current_thread() != gIOTerminateThread)) {
1777
1778 do {
1779 wait = (gIOTerminateThread != 0);
1780 if( wait) {
1781 // wait to become the terminate thread
1782 IOLockSleep( gJobsLock, &gIOTerminateThread, THREAD_UNINT);
1783 }
1784 } while( wait );
1785
1786 gIOTerminateThread = current_thread();
1787 gIOTerminatePhase2List->setObject( this );
1788 gIOTerminateWork++;
1789
1790 do {
1791 while( gIOTerminateWork )
1792 terminateWorker( options );
1793 wait = (0 != (__state[1] & kIOServiceBusyStateMask));
1794 if( wait) {
1795 // wait for the victim to go non-busy
1796 if( !haveDeadline) {
1797 clock_interval_to_deadline( 15, kSecondScale, &deadline );
1798 haveDeadline = true;
1799 }
1800 waitResult = IOLockSleepDeadline( gJobsLock, &gIOTerminateWork,
1801 deadline, THREAD_UNINT );
1802 if( waitResult == THREAD_TIMED_OUT) {
1803 IOLog("%s::terminate(kIOServiceSynchronous) timeout\n", getName());
1804 }
1805 }
1806 } while(gIOTerminateWork || (wait && (waitResult != THREAD_TIMED_OUT)));
1807
1808 gIOTerminateThread = 0;
1809 IOLockWakeup( gJobsLock, (event_t) &gIOTerminateThread, /* one-thread */ false);
1810
1811 } else {
1812 // ! kIOServiceSynchronous
1813
1814 gIOTerminatePhase2List->setObject( this );
1815 if( 0 == gIOTerminateWork++) {
1816 if( !gIOTerminateThread)
1817 kernel_thread_start(&terminateThread, (void *) options, &gIOTerminateThread);
1818 else
1819 IOLockWakeup(gJobsLock, (event_t) &gIOTerminateWork, /* one-thread */ false );
1820 }
1821 }
1822
1823 IOLockUnlock( gJobsLock );
1824
1825 release();
1826 }
1827
1828 void IOService::terminateThread( void * arg, wait_result_t waitResult )
1829 {
1830 IOLockLock( gJobsLock );
1831
1832 while (gIOTerminateWork)
1833 terminateWorker( (uintptr_t) arg );
1834
1835 thread_deallocate(gIOTerminateThread);
1836 gIOTerminateThread = 0;
1837 IOLockWakeup( gJobsLock, (event_t) &gIOTerminateThread, /* one-thread */ false);
1838
1839 IOLockUnlock( gJobsLock );
1840 }
1841
1842 void IOService::scheduleStop( IOService * provider )
1843 {
1844 TLOG("%s::scheduleStop(%s)\n", getName(), provider->getName());
1845
1846 uint64_t regID1 = getRegistryEntryID();
1847 uint64_t regID2 = provider->getRegistryEntryID();
1848 IOServiceTrace(
1849 IOSERVICE_TERMINATE_SCHEDULE_STOP,
1850 (uintptr_t) regID1,
1851 (uintptr_t) (regID1 >> 32),
1852 (uintptr_t) regID2,
1853 (uintptr_t) (regID2 >> 32));
1854
1855 IOLockLock( gJobsLock );
1856 gIOStopList->tailQ( this );
1857 gIOStopProviderList->tailQ( provider );
1858
1859 if( 0 == gIOTerminateWork++) {
1860 if( !gIOTerminateThread)
1861 kernel_thread_start(&terminateThread, (void *) 0, &gIOTerminateThread);
1862 else
1863 IOLockWakeup(gJobsLock, (event_t) &gIOTerminateWork, /* one-thread */ false );
1864 }
1865
1866 IOLockUnlock( gJobsLock );
1867 }
1868
1869 void IOService::scheduleFinalize( void )
1870 {
1871 TLOG("%s::scheduleFinalize\n", getName());
1872
1873 uint64_t regID1 = getRegistryEntryID();
1874 IOServiceTrace(
1875 IOSERVICE_TERMINATE_SCHEDULE_FINALIZE,
1876 (uintptr_t) regID1,
1877 (uintptr_t) (regID1 >> 32),
1878 0, 0);
1879
1880 IOLockLock( gJobsLock );
1881 gIOFinalizeList->tailQ( this );
1882
1883 if( 0 == gIOTerminateWork++) {
1884 if( !gIOTerminateThread)
1885 kernel_thread_start(&terminateThread, (void *) 0, &gIOTerminateThread);
1886 else
1887 IOLockWakeup(gJobsLock, (event_t) &gIOTerminateWork, /* one-thread */ false );
1888 }
1889
1890 IOLockUnlock( gJobsLock );
1891 }
1892
1893 bool IOService::willTerminate( IOService * provider, IOOptionBits options )
1894 {
1895 return( true );
1896 }
1897
1898 bool IOService::didTerminate( IOService * provider, IOOptionBits options, bool * defer )
1899 {
1900 if( false == *defer) {
1901
1902 if( lockForArbitration( true )) {
1903 if( false == provider->handleIsOpen( this ))
1904 scheduleStop( provider );
1905 // -- compat
1906 else {
1907 message( kIOMessageServiceIsRequestingClose, provider, (void *) options );
1908 if( false == provider->handleIsOpen( this ))
1909 scheduleStop( provider );
1910 }
1911 // --
1912 unlockForArbitration();
1913 }
1914 }
1915
1916 return( true );
1917 }
1918
1919 void IOService::actionWillTerminate( IOService * victim, IOOptionBits options,
1920 OSArray * doPhase2List )
1921 {
1922 OSIterator * iter;
1923 IOService * client;
1924 bool ok;
1925
1926 iter = victim->getClientIterator();
1927 if( iter) {
1928 while( (client = (IOService *) iter->getNextObject())) {
1929 TLOG("%s::willTerminate(%s, %08llx)\n",
1930 client->getName(), victim->getName(), (long long)options);
1931
1932 uint64_t regID1 = client->getRegistryEntryID();
1933 uint64_t regID2 = victim->getRegistryEntryID();
1934 IOServiceTrace(
1935 IOSERVICE_TERMINATE_WILL,
1936 (uintptr_t) regID1,
1937 (uintptr_t) (regID1 >> 32),
1938 (uintptr_t) regID2,
1939 (uintptr_t) (regID2 >> 32));
1940
1941 ok = client->willTerminate( victim, options );
1942 doPhase2List->tailQ( client );
1943 }
1944 iter->release();
1945 }
1946 }
1947
1948 void IOService::actionDidTerminate( IOService * victim, IOOptionBits options )
1949 {
1950 OSIterator * iter;
1951 IOService * client;
1952 bool defer = false;
1953
1954 victim->messageClients( kIOMessageServiceIsTerminated, (void *) options );
1955
1956 iter = victim->getClientIterator();
1957 if( iter) {
1958 while( (client = (IOService *) iter->getNextObject())) {
1959 TLOG("%s::didTerminate(%s, %08llx)\n",
1960 client->getName(), victim->getName(), (long long)options);
1961 client->didTerminate( victim, options, &defer );
1962
1963 uint64_t regID1 = client->getRegistryEntryID();
1964 uint64_t regID2 = victim->getRegistryEntryID();
1965 IOServiceTrace(
1966 (defer ? IOSERVICE_TERMINATE_DID_DEFER
1967 : IOSERVICE_TERMINATE_DID),
1968 (uintptr_t) regID1,
1969 (uintptr_t) (regID1 >> 32),
1970 (uintptr_t) regID2,
1971 (uintptr_t) (regID2 >> 32));
1972
1973 TLOG("%s::didTerminate(%s, defer %d)\n",
1974 client->getName(), victim->getName(), defer);
1975 }
1976 iter->release();
1977 }
1978 }
1979
1980 void IOService::actionFinalize( IOService * victim, IOOptionBits options )
1981 {
1982 TLOG("%s::finalize(%08llx)\n", victim->getName(), (long long)options);
1983
1984 uint64_t regID1 = victim->getRegistryEntryID();
1985 IOServiceTrace(
1986 IOSERVICE_TERMINATE_FINALIZE,
1987 (uintptr_t) regID1,
1988 (uintptr_t) (regID1 >> 32),
1989 0, 0);
1990
1991 victim->finalize( options );
1992 }
1993
1994 void IOService::actionStop( IOService * provider, IOService * client )
1995 {
1996 TLOG("%s::stop(%s)\n", client->getName(), provider->getName());
1997
1998 uint64_t regID1 = provider->getRegistryEntryID();
1999 uint64_t regID2 = client->getRegistryEntryID();
2000 IOServiceTrace(
2001 IOSERVICE_TERMINATE_STOP,
2002 (uintptr_t) regID1,
2003 (uintptr_t) (regID1 >> 32),
2004 (uintptr_t) regID2,
2005 (uintptr_t) (regID2 >> 32));
2006
2007 client->stop( provider );
2008 if( provider->isOpen( client ))
2009 provider->close( client );
2010 TLOG("%s::detach(%s)\n", client->getName(), provider->getName());
2011 client->detach( provider );
2012 }
2013
2014 void IOService::terminateWorker( IOOptionBits options )
2015 {
2016 OSArray * doPhase2List;
2017 OSArray * didPhase2List;
2018 OSSet * freeList;
2019 UInt32 workDone;
2020 IOService * victim;
2021 IOService * client;
2022 IOService * provider;
2023 unsigned int idx;
2024 bool moreToDo;
2025 bool doPhase2;
2026 bool doPhase3;
2027
2028 options |= kIOServiceRequired;
2029
2030 doPhase2List = OSArray::withCapacity( 16 );
2031 didPhase2List = OSArray::withCapacity( 16 );
2032 freeList = OSSet::withCapacity( 16 );
2033 if( (0 == doPhase2List) || (0 == didPhase2List) || (0 == freeList))
2034 return;
2035
2036 do {
2037 workDone = gIOTerminateWork;
2038
2039 while( (victim = (IOService *) gIOTerminatePhase2List->getObject(0) )) {
2040
2041 victim->retain();
2042 gIOTerminatePhase2List->removeObject(0);
2043 IOLockUnlock( gJobsLock );
2044
2045 while( victim ) {
2046
2047 doPhase2 = victim->lockForArbitration( true );
2048 if( doPhase2) {
2049 doPhase2 = (0 != (kIOServiceInactiveState & victim->__state[0]));
2050 if( doPhase2) {
2051 doPhase2 = (0 == (victim->__state[1] & kIOServiceTermPhase2State))
2052 && (0 == (victim->__state[1] & kIOServiceConfigState));
2053 if( doPhase2)
2054 victim->__state[1] |= kIOServiceTermPhase2State;
2055 }
2056 victim->unlockForArbitration();
2057 }
2058 if( doPhase2) {
2059 if( 0 == victim->getClient()) {
2060 // no clients - will go to finalize
2061 IOLockLock( gJobsLock );
2062 gIOFinalizeList->tailQ( victim );
2063 IOLockUnlock( gJobsLock );
2064 } else {
2065 _workLoopAction( (IOWorkLoop::Action) &actionWillTerminate,
2066 victim, (void *) options, (void *) doPhase2List );
2067 }
2068 didPhase2List->headQ( victim );
2069 }
2070 victim->release();
2071 victim = (IOService *) doPhase2List->getObject(0);
2072 if( victim) {
2073 victim->retain();
2074 doPhase2List->removeObject(0);
2075 }
2076 }
2077
2078 while( (victim = (IOService *) didPhase2List->getObject(0)) ) {
2079
2080 if( victim->lockForArbitration( true )) {
2081 victim->__state[1] |= kIOServiceTermPhase3State;
2082 victim->unlockForArbitration();
2083 }
2084 _workLoopAction( (IOWorkLoop::Action) &actionDidTerminate,
2085 victim, (void *) options );
2086 didPhase2List->removeObject(0);
2087 }
2088 IOLockLock( gJobsLock );
2089 }
2090
2091 // phase 3
2092 do {
2093 doPhase3 = false;
2094 // finalize leaves
2095 while( (victim = (IOService *) gIOFinalizeList->getObject(0))) {
2096
2097 IOLockUnlock( gJobsLock );
2098 _workLoopAction( (IOWorkLoop::Action) &actionFinalize,
2099 victim, (void *) options );
2100 IOLockLock( gJobsLock );
2101 // hold off free
2102 freeList->setObject( victim );
2103 // safe if finalize list is append only
2104 gIOFinalizeList->removeObject(0);
2105 }
2106
2107 for( idx = 0;
2108 (!doPhase3) && (client = (IOService *) gIOStopList->getObject(idx)); ) {
2109
2110 provider = (IOService *) gIOStopProviderList->getObject(idx);
2111 assert( provider );
2112
2113 if( !provider->isChild( client, gIOServicePlane )) {
2114 // may be multiply queued - nop it
2115 TLOG("%s::nop stop(%s)\n", client->getName(), provider->getName());
2116
2117 uint64_t regID1 = provider->getRegistryEntryID();
2118 uint64_t regID2 = client->getRegistryEntryID();
2119 IOServiceTrace(
2120 IOSERVICE_TERMINATE_STOP_NOP,
2121 (uintptr_t) regID1,
2122 (uintptr_t) (regID1 >> 32),
2123 (uintptr_t) regID2,
2124 (uintptr_t) (regID2 >> 32));
2125
2126 } else {
2127 // not ready for stop if it has clients, skip it
2128 if( (client->__state[1] & kIOServiceTermPhase3State) && client->getClient()) {
2129 TLOG("%s::defer stop(%s)\n", client->getName(), provider->getName());
2130
2131 uint64_t regID1 = provider->getRegistryEntryID();
2132 uint64_t regID2 = client->getRegistryEntryID();
2133 IOServiceTrace(
2134 IOSERVICE_TERMINATE_STOP_DEFER,
2135 (uintptr_t) regID1,
2136 (uintptr_t) (regID1 >> 32),
2137 (uintptr_t) regID2,
2138 (uintptr_t) (regID2 >> 32));
2139
2140 idx++;
2141 continue;
2142 }
2143
2144 IOLockUnlock( gJobsLock );
2145 _workLoopAction( (IOWorkLoop::Action) &actionStop,
2146 provider, (void *) client );
2147 IOLockLock( gJobsLock );
2148 // check the finalize list now
2149 doPhase3 = true;
2150 }
2151 // hold off free
2152 freeList->setObject( client );
2153 freeList->setObject( provider );
2154
2155 // safe if stop list is append only
2156 gIOStopList->removeObject( idx );
2157 gIOStopProviderList->removeObject( idx );
2158 idx = 0;
2159 }
2160
2161 } while( doPhase3 );
2162
2163 gIOTerminateWork -= workDone;
2164 moreToDo = (gIOTerminateWork != 0);
2165
2166 if( !moreToDo) {
2167 TLOG("iokit terminate done, %d stops remain\n", gIOStopList->getCount());
2168 IOServiceTrace(
2169 IOSERVICE_TERMINATE_DONE,
2170 (uintptr_t) gIOStopList->getCount(), 0, 0, 0);
2171 }
2172
2173 } while( moreToDo );
2174
2175 IOLockUnlock( gJobsLock );
2176
2177 freeList->release();
2178 doPhase2List->release();
2179 didPhase2List->release();
2180
2181 IOLockLock( gJobsLock );
2182 }
2183
2184 bool IOService::finalize( IOOptionBits options )
2185 {
2186 OSIterator * iter;
2187 IOService * provider;
2188
2189 iter = getProviderIterator();
2190 assert( iter );
2191
2192 if( iter) {
2193 while( (provider = (IOService *) iter->getNextObject())) {
2194
2195 // -- compat
2196 if( 0 == (__state[1] & kIOServiceTermPhase3State)) {
2197 /* we come down here on programmatic terminate */
2198 stop( provider );
2199 if( provider->isOpen( this ))
2200 provider->close( this );
2201 detach( provider );
2202 } else {
2203 //--
2204 if( provider->lockForArbitration( true )) {
2205 if( 0 == (provider->__state[1] & kIOServiceTermPhase3State))
2206 scheduleStop( provider );
2207 provider->unlockForArbitration();
2208 }
2209 }
2210 }
2211 iter->release();
2212 }
2213
2214 return( true );
2215 }
2216
2217 #undef tailQ
2218 #undef headQ
2219
2220 /*
2221 * Terminate
2222 */
2223
2224 void IOService::doServiceTerminate( IOOptionBits options )
2225 {
2226 }
2227
2228 // a method in case someone needs to override it
2229 bool IOService::terminateClient( IOService * client, IOOptionBits options )
2230 {
2231 bool ok;
2232
2233 if( client->isParent( this, gIOServicePlane, true))
2234 // we are the clients only provider
2235 ok = client->terminate( options );
2236 else
2237 ok = true;
2238
2239 return( ok );
2240 }
2241
2242 bool IOService::terminate( IOOptionBits options )
2243 {
2244 options |= kIOServiceTerminate;
2245
2246 return( terminatePhase1( options ));
2247 }
2248
2249 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2250
2251 /*
2252 * Open & close
2253 */
2254
2255 struct ServiceOpenMessageContext
2256 {
2257 IOService * service;
2258 UInt32 type;
2259 IOService * excludeClient;
2260 IOOptionBits options;
2261 };
2262
2263 static void serviceOpenMessageApplier( OSObject * object, void * ctx )
2264 {
2265 ServiceOpenMessageContext * context = (ServiceOpenMessageContext *) ctx;
2266
2267 if( object != context->excludeClient)
2268 context->service->messageClient( context->type, object, (void *) context->options );
2269 }
2270
2271 bool IOService::open( IOService * forClient,
2272 IOOptionBits options,
2273 void * arg )
2274 {
2275 bool ok;
2276 ServiceOpenMessageContext context;
2277
2278 context.service = this;
2279 context.type = kIOMessageServiceIsAttemptingOpen;
2280 context.excludeClient = forClient;
2281 context.options = options;
2282
2283 applyToInterested( gIOGeneralInterest,
2284 &serviceOpenMessageApplier, &context );
2285
2286 if( false == lockForArbitration(false) )
2287 return false;
2288
2289 ok = (0 == (__state[0] & kIOServiceInactiveState));
2290 if( ok)
2291 ok = handleOpen( forClient, options, arg );
2292
2293 unlockForArbitration();
2294
2295 return( ok );
2296 }
2297
2298 void IOService::close( IOService * forClient,
2299 IOOptionBits options )
2300 {
2301 bool wasClosed;
2302 bool last = false;
2303
2304 lockForArbitration();
2305
2306 wasClosed = handleIsOpen( forClient );
2307 if( wasClosed) {
2308 handleClose( forClient, options );
2309 last = (__state[1] & kIOServiceTermPhase3State);
2310 }
2311
2312 unlockForArbitration();
2313
2314 if( last)
2315 forClient->scheduleStop( this );
2316
2317 else if( wasClosed) {
2318
2319 ServiceOpenMessageContext context;
2320
2321 context.service = this;
2322 context.type = kIOMessageServiceWasClosed;
2323 context.excludeClient = forClient;
2324 context.options = options;
2325
2326 applyToInterested( gIOGeneralInterest,
2327 &serviceOpenMessageApplier, &context );
2328 }
2329 }
2330
2331 bool IOService::isOpen( const IOService * forClient ) const
2332 {
2333 IOService * self = (IOService *) this;
2334 bool ok;
2335
2336 self->lockForArbitration();
2337
2338 ok = handleIsOpen( forClient );
2339
2340 self->unlockForArbitration();
2341
2342 return( ok );
2343 }
2344
2345 bool IOService::handleOpen( IOService * forClient,
2346 IOOptionBits options,
2347 void * arg )
2348 {
2349 bool ok;
2350
2351 ok = (0 == __owner);
2352 if( ok )
2353 __owner = forClient;
2354
2355 else if( options & kIOServiceSeize ) {
2356 ok = (kIOReturnSuccess == messageClient( kIOMessageServiceIsRequestingClose,
2357 __owner, (void *) options ));
2358 if( ok && (0 == __owner ))
2359 __owner = forClient;
2360 else
2361 ok = false;
2362 }
2363 return( ok );
2364 }
2365
2366 void IOService::handleClose( IOService * forClient,
2367 IOOptionBits options )
2368 {
2369 if( __owner == forClient)
2370 __owner = 0;
2371 }
2372
2373 bool IOService::handleIsOpen( const IOService * forClient ) const
2374 {
2375 if( forClient)
2376 return( __owner == forClient );
2377 else
2378 return( __owner != forClient );
2379 }
2380
2381 /*
2382 * Probing & starting
2383 */
2384 static SInt32 IONotifyOrdering( const OSMetaClassBase * inObj1, const OSMetaClassBase * inObj2, void * ref )
2385 {
2386 const _IOServiceNotifier * obj1 = (const _IOServiceNotifier *) inObj1;
2387 const _IOServiceNotifier * obj2 = (const _IOServiceNotifier *) inObj2;
2388 SInt32 val1;
2389 SInt32 val2;
2390
2391 val1 = 0;
2392 val2 = 0;
2393
2394 if ( obj1 )
2395 val1 = obj1->priority;
2396
2397 if ( obj2 )
2398 val2 = obj2->priority;
2399
2400 return ( val1 - val2 );
2401 }
2402
2403 static SInt32 IOServiceObjectOrder( const OSObject * entry, void * ref)
2404 {
2405 OSDictionary * dict;
2406 IOService * service;
2407 _IOServiceNotifier * notify;
2408 OSSymbol * key = (OSSymbol *) ref;
2409 OSNumber * offset;
2410
2411 if( (notify = OSDynamicCast( _IOServiceNotifier, entry)))
2412 return( notify->priority );
2413
2414 else if( (service = OSDynamicCast( IOService, entry)))
2415 offset = OSDynamicCast(OSNumber, service->getProperty( key ));
2416 else if( (dict = OSDynamicCast( OSDictionary, entry)))
2417 offset = OSDynamicCast(OSNumber, dict->getObject( key ));
2418 else {
2419 assert( false );
2420 offset = 0;
2421 }
2422
2423 if( offset)
2424 return( (SInt32) offset->unsigned32BitValue());
2425 else
2426 return( kIODefaultProbeScore );
2427 }
2428
2429 SInt32 IOServiceOrdering( const OSMetaClassBase * inObj1, const OSMetaClassBase * inObj2, void * ref )
2430 {
2431 const OSObject * obj1 = (const OSObject *) inObj1;
2432 const OSObject * obj2 = (const OSObject *) inObj2;
2433 SInt32 val1;
2434 SInt32 val2;
2435
2436 val1 = 0;
2437 val2 = 0;
2438
2439 if ( obj1 )
2440 val1 = IOServiceObjectOrder( obj1, ref );
2441
2442 if ( obj2 )
2443 val2 = IOServiceObjectOrder( obj2, ref );
2444
2445 return ( val1 - val2 );
2446 }
2447
2448 IOService * IOService::copyClientWithCategory( const OSSymbol * category )
2449 {
2450 IOService * service = 0;
2451 OSIterator * iter;
2452 const OSSymbol * nextCat;
2453
2454 iter = getClientIterator();
2455 if( iter) {
2456 while( (service = (IOService *) iter->getNextObject())) {
2457 if( kIOServiceInactiveState & service->__state[0])
2458 continue;
2459 nextCat = (const OSSymbol *) OSDynamicCast( OSSymbol,
2460 service->getProperty( gIOMatchCategoryKey ));
2461 if( category == nextCat)
2462 {
2463 service->retain();
2464 break;
2465 }
2466 }
2467 iter->release();
2468 }
2469 return( service );
2470 }
2471
2472 IOService * IOService::getClientWithCategory( const OSSymbol * category )
2473 {
2474 IOService *
2475 service = copyClientWithCategory(category);
2476 if (service)
2477 service->release();
2478 return (service);
2479 }
2480
2481 bool IOService::invokeNotifer( _IOServiceNotifier * notify )
2482 {
2483 _IOServiceNotifierInvocation invocation;
2484 bool willNotify;
2485 bool ret = true;
2486
2487 invocation.thread = current_thread();
2488
2489 LOCKWRITENOTIFY();
2490 willNotify = (0 != (kIOServiceNotifyEnable & notify->state));
2491
2492 if( willNotify) {
2493 queue_enter( &notify->handlerInvocations, &invocation,
2494 _IOServiceNotifierInvocation *, link );
2495 }
2496 UNLOCKNOTIFY();
2497
2498 if( willNotify) {
2499
2500 ret = (*notify->handler)(notify->target, notify->ref, this, notify);
2501
2502 LOCKWRITENOTIFY();
2503 queue_remove( &notify->handlerInvocations, &invocation,
2504 _IOServiceNotifierInvocation *, link );
2505 if( kIOServiceNotifyWaiter & notify->state) {
2506 notify->state &= ~kIOServiceNotifyWaiter;
2507 WAKEUPNOTIFY( notify );
2508 }
2509 UNLOCKNOTIFY();
2510 }
2511
2512 return( ret );
2513 }
2514
2515 /*
2516 * Alloc and probe matching classes,
2517 * called on the provider instance
2518 */
2519
2520 void IOService::probeCandidates( OSOrderedSet * matches )
2521 {
2522 OSDictionary * match = 0;
2523 OSSymbol * symbol;
2524 IOService * inst;
2525 IOService * newInst;
2526 OSDictionary * props;
2527 SInt32 score;
2528 OSNumber * newPri;
2529 OSOrderedSet * familyMatches = 0;
2530 OSOrderedSet * startList;
2531 OSDictionary * startDict = 0;
2532 const OSSymbol * category;
2533 OSIterator * iter;
2534 _IOServiceNotifier * notify;
2535 OSObject * nextMatch = 0;
2536 bool started;
2537 bool needReloc = false;
2538 #if CONFIG_MACF_KEXT
2539 OSBoolean * isSandbox = 0;
2540 bool useSandbox = false;
2541 #endif
2542 #if IOMATCHDEBUG
2543 SInt64 debugFlags;
2544 #endif
2545 IOService * client = NULL;
2546
2547
2548 assert( matches );
2549 while( !needReloc && (nextMatch = matches->getFirstObject())) {
2550
2551 nextMatch->retain();
2552 matches->removeObject(nextMatch);
2553
2554 if( (notify = OSDynamicCast( _IOServiceNotifier, nextMatch ))) {
2555
2556 lockForArbitration();
2557 if( 0 == (__state[0] & kIOServiceInactiveState))
2558 invokeNotifer( notify );
2559 unlockForArbitration();
2560 nextMatch->release();
2561 nextMatch = 0;
2562 continue;
2563
2564 } else if( !(match = OSDynamicCast( OSDictionary, nextMatch ))) {
2565 nextMatch->release();
2566 nextMatch = 0;
2567 continue;
2568 }
2569
2570 props = 0;
2571 #if IOMATCHDEBUG
2572 debugFlags = getDebugFlags( match );
2573 #endif
2574
2575 do {
2576 category = OSDynamicCast( OSSymbol,
2577 match->getObject( gIOMatchCategoryKey ));
2578 if( 0 == category)
2579 category = gIODefaultMatchCategoryKey;
2580
2581 if( (client = copyClientWithCategory(category)) ) {
2582 #if IOMATCHDEBUG
2583 if( debugFlags & kIOLogMatch)
2584 LOG("%s: match category %s exists\n", getName(),
2585 category->getCStringNoCopy());
2586 #endif
2587 nextMatch->release();
2588 nextMatch = 0;
2589
2590 client->release();
2591 client = NULL;
2592
2593 continue;
2594 }
2595
2596 // create a copy now in case its modified during matching
2597 props = OSDictionary::withDictionary( match, match->getCount());
2598 if( 0 == props)
2599 continue;
2600 props->setCapacityIncrement(1);
2601
2602 // check the nub matches
2603 if( false == passiveMatch( props, true ))
2604 continue;
2605
2606 // Check to see if driver reloc has been loaded.
2607 needReloc = (false == gIOCatalogue->isModuleLoaded( match ));
2608 if( needReloc) {
2609 #if IOMATCHDEBUG
2610 if( debugFlags & kIOLogCatalogue)
2611 LOG("%s: stalling for module\n", getName());
2612 #endif
2613 // If reloc hasn't been loaded, exit;
2614 // reprobing will occur after reloc has been loaded.
2615 continue;
2616 }
2617
2618 // reorder on family matchPropertyTable score.
2619 if( 0 == familyMatches)
2620 familyMatches = OSOrderedSet::withCapacity( 1,
2621 IOServiceOrdering, (void *) gIOProbeScoreKey );
2622 if( familyMatches)
2623 familyMatches->setObject( props );
2624
2625 } while( false );
2626
2627 if (nextMatch) {
2628 nextMatch->release();
2629 nextMatch = 0;
2630 }
2631 if( props)
2632 props->release();
2633 }
2634 matches->release();
2635 matches = 0;
2636
2637 if( familyMatches) {
2638
2639 while( !needReloc
2640 && (props = (OSDictionary *) familyMatches->getFirstObject())) {
2641
2642 props->retain();
2643 familyMatches->removeObject( props );
2644
2645 inst = 0;
2646 newInst = 0;
2647 #if IOMATCHDEBUG
2648 debugFlags = getDebugFlags( props );
2649 #endif
2650 do {
2651 symbol = OSDynamicCast( OSSymbol,
2652 props->getObject( gIOClassKey));
2653 if( !symbol)
2654 continue;
2655
2656 //IOLog("%s alloc (symbol %p props %p)\n", symbol->getCStringNoCopy(), symbol, props);
2657
2658 // alloc the driver instance
2659 inst = (IOService *) OSMetaClass::allocClassWithName( symbol);
2660
2661 if( !inst) {
2662 IOLog("Couldn't alloc class \"%s\"\n",
2663 symbol->getCStringNoCopy());
2664 continue;
2665 }
2666
2667 // init driver instance
2668 if( !(inst->init( props ))) {
2669 #if IOMATCHDEBUG
2670 if( debugFlags & kIOLogStart)
2671 IOLog("%s::init fails\n", symbol->getCStringNoCopy());
2672 #endif
2673 continue;
2674 }
2675 if( __state[1] & kIOServiceSynchronousState)
2676 inst->__state[1] |= kIOServiceSynchronousState;
2677
2678 // give the driver the default match category if not specified
2679 category = OSDynamicCast( OSSymbol,
2680 props->getObject( gIOMatchCategoryKey ));
2681 if( 0 == category)
2682 category = gIODefaultMatchCategoryKey;
2683 inst->setProperty( gIOMatchCategoryKey, (OSObject *) category );
2684 #if CONFIG_MACF_KEXT
2685 isSandbox = OSDynamicCast(OSBoolean,
2686 props->getObject("IOKitForceMatch"));
2687 #endif
2688 // attach driver instance
2689 if( !(inst->attach( this )))
2690 continue;
2691
2692 // pass in score from property table
2693 score = familyMatches->orderObject( props );
2694
2695 // & probe the new driver instance
2696 #if IOMATCHDEBUG
2697 if( debugFlags & kIOLogProbe)
2698 LOG("%s::probe(%s)\n",
2699 inst->getMetaClass()->getClassName(), getName());
2700 #endif
2701
2702 newInst = inst->probe( this, &score );
2703 inst->detach( this );
2704 #if CONFIG_MACF_KEXT
2705 /*
2706 * If this is the Sandbox driver and it matched, this is a
2707 * disallowed device; toss any drivers that were already
2708 * matched.
2709 */
2710 if (isSandbox && isSandbox->isTrue() && newInst != 0) {
2711 if (startDict != 0) {
2712 startDict->flushCollection();
2713 startDict->release();
2714 startDict = 0;
2715 }
2716 useSandbox = true;
2717 }
2718 #endif
2719 if( 0 == newInst) {
2720 #if IOMATCHDEBUG
2721 if( debugFlags & kIOLogProbe)
2722 IOLog("%s::probe fails\n", symbol->getCStringNoCopy());
2723 #endif
2724 continue;
2725 }
2726
2727 // save the score
2728 newPri = OSNumber::withNumber( score, 32 );
2729 if( newPri) {
2730 newInst->setProperty( gIOProbeScoreKey, newPri );
2731 newPri->release();
2732 }
2733
2734 // add to start list for the match category
2735 if( 0 == startDict)
2736 startDict = OSDictionary::withCapacity( 1 );
2737 assert( startDict );
2738 startList = (OSOrderedSet *)
2739 startDict->getObject( category );
2740 if( 0 == startList) {
2741 startList = OSOrderedSet::withCapacity( 1,
2742 IOServiceOrdering, (void *) gIOProbeScoreKey );
2743 if( startDict && startList) {
2744 startDict->setObject( category, startList );
2745 startList->release();
2746 }
2747 }
2748 assert( startList );
2749 if( startList)
2750 startList->setObject( newInst );
2751
2752 } while( false );
2753
2754 props->release();
2755 if( inst)
2756 inst->release();
2757 #if CONFIG_MACF_KEXT
2758 /*
2759 * If we're forcing the sandbox, drop out of the loop.
2760 */
2761 if (isSandbox && isSandbox->isTrue() && useSandbox)
2762 break;
2763 #endif
2764 }
2765 familyMatches->release();
2766 familyMatches = 0;
2767 }
2768
2769 // start the best (until success) of each category
2770
2771 iter = OSCollectionIterator::withCollection( startDict );
2772 if( iter) {
2773 while( (category = (const OSSymbol *) iter->getNextObject())) {
2774
2775 startList = (OSOrderedSet *) startDict->getObject( category );
2776 assert( startList );
2777 if( !startList)
2778 continue;
2779
2780 started = false;
2781 while( true // (!started)
2782 && (inst = (IOService *)startList->getFirstObject())) {
2783
2784 inst->retain();
2785 startList->removeObject(inst);
2786
2787 #if IOMATCHDEBUG
2788 debugFlags = getDebugFlags( inst->getPropertyTable() );
2789
2790 if( debugFlags & kIOLogStart) {
2791 if( started)
2792 LOG( "match category exists, skipping " );
2793 LOG( "%s::start(%s) <%d>\n", inst->getName(),
2794 getName(), inst->getRetainCount());
2795 }
2796 #endif
2797 if( false == started)
2798 started = startCandidate( inst );
2799 #if IOMATCHDEBUG
2800 if( (debugFlags & kIOLogStart) && (false == started))
2801 LOG( "%s::start(%s) <%d> failed\n", inst->getName(), getName(),
2802 inst->getRetainCount());
2803 #endif
2804 inst->release();
2805 }
2806 }
2807 iter->release();
2808 }
2809
2810
2811 // adjust the busy count by +1 if matching is stalled for a module,
2812 // or -1 if a previously stalled matching is complete.
2813 lockForArbitration();
2814 SInt32 adjBusy = 0;
2815 uint64_t regID = getRegistryEntryID();
2816
2817 if( needReloc) {
2818 adjBusy = (__state[1] & kIOServiceModuleStallState) ? 0 : 1;
2819 if( adjBusy) {
2820
2821 IOServiceTrace(
2822 IOSERVICE_MODULESTALL,
2823 (uintptr_t) regID,
2824 (uintptr_t) (regID >> 32),
2825 (uintptr_t) this,
2826 0);
2827
2828 __state[1] |= kIOServiceModuleStallState;
2829 }
2830
2831 } else if( __state[1] & kIOServiceModuleStallState) {
2832
2833 IOServiceTrace(
2834 IOSERVICE_MODULEUNSTALL,
2835 (uintptr_t) regID,
2836 (uintptr_t) (regID >> 32),
2837 (uintptr_t) this,
2838 0);
2839
2840 __state[1] &= ~kIOServiceModuleStallState;
2841 adjBusy = -1;
2842 }
2843 if( adjBusy)
2844 _adjustBusy( adjBusy );
2845 unlockForArbitration();
2846
2847 if( startDict)
2848 startDict->release();
2849 }
2850
2851 /*
2852 * Start a previously attached & probed instance,
2853 * called on exporting object instance
2854 */
2855
2856 bool IOService::startCandidate( IOService * service )
2857 {
2858 bool ok;
2859
2860 ok = service->attach( this );
2861
2862 if( ok)
2863 {
2864 if (this != gIOResources)
2865 {
2866 // stall for any nub resources
2867 checkResources();
2868 // stall for any driver resources
2869 service->checkResources();
2870 }
2871
2872 AbsoluteTime startTime;
2873 AbsoluteTime endTime;
2874 UInt64 nano;
2875
2876 if (kIOLogStart & gIOKitDebug)
2877 clock_get_uptime(&startTime);
2878
2879 ok = service->start(this);
2880
2881 if (kIOLogStart & gIOKitDebug)
2882 {
2883 clock_get_uptime(&endTime);
2884
2885 if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0)
2886 {
2887 SUB_ABSOLUTETIME(&endTime, &startTime);
2888 absolutetime_to_nanoseconds(endTime, &nano);
2889 if (nano > 500000000ULL)
2890 IOLog("%s::start took %ld ms\n", service->getName(), (long)(UInt32)(nano / 1000000ULL));
2891 }
2892 }
2893 if( !ok)
2894 service->detach( this );
2895 }
2896 return( ok );
2897 }
2898
2899 void IOService::publishResource( const char * key, OSObject * value )
2900 {
2901 const OSSymbol * sym;
2902
2903 if( (sym = OSSymbol::withCString( key))) {
2904 publishResource( sym, value);
2905 sym->release();
2906 }
2907 }
2908
2909 void IOService::publishResource( const OSSymbol * key, OSObject * value )
2910 {
2911 if( 0 == value)
2912 value = (OSObject *) gIOServiceKey;
2913
2914 gIOResources->setProperty( key, value);
2915
2916 if( IORecursiveLockHaveLock( gNotificationLock))
2917 return;
2918
2919 gIOResourceGenerationCount++;
2920 gIOResources->registerService();
2921 }
2922
2923 bool IOService::addNeededResource( const char * key )
2924 {
2925 OSObject * resourcesProp;
2926 OSSet * set;
2927 OSString * newKey;
2928 bool ret;
2929
2930 resourcesProp = getProperty( gIOResourceMatchKey );
2931
2932 newKey = OSString::withCString( key );
2933 if( (0 == resourcesProp) || (0 == newKey))
2934 return( false);
2935
2936 set = OSDynamicCast( OSSet, resourcesProp );
2937 if( !set) {
2938 set = OSSet::withCapacity( 1 );
2939 if( set)
2940 set->setObject( resourcesProp );
2941 }
2942 else
2943 set->retain();
2944
2945 set->setObject( newKey );
2946 newKey->release();
2947 ret = setProperty( gIOResourceMatchKey, set );
2948 set->release();
2949
2950 return( ret );
2951 }
2952
2953 bool IOService::checkResource( OSObject * matching )
2954 {
2955 OSString * str;
2956 OSDictionary * table;
2957
2958 if( (str = OSDynamicCast( OSString, matching ))) {
2959 if( gIOResources->getProperty( str ))
2960 return( true );
2961 }
2962
2963 if( str)
2964 table = resourceMatching( str );
2965 else if( (table = OSDynamicCast( OSDictionary, matching )))
2966 table->retain();
2967 else {
2968 IOLog("%s: Can't match using: %s\n", getName(),
2969 matching->getMetaClass()->getClassName());
2970 /* false would stall forever */
2971 return( true );
2972 }
2973
2974 if( gIOKitDebug & kIOLogConfig)
2975 LOG("config(%p): stalling %s\n", IOThreadSelf(), getName());
2976
2977 waitForService( table );
2978
2979 if( gIOKitDebug & kIOLogConfig)
2980 LOG("config(%p): waking\n", IOThreadSelf() );
2981
2982 return( true );
2983 }
2984
2985 bool IOService::checkResources( void )
2986 {
2987 OSObject * resourcesProp;
2988 OSSet * set;
2989 OSIterator * iter;
2990 bool ok;
2991
2992 resourcesProp = getProperty( gIOResourceMatchKey );
2993 if( 0 == resourcesProp)
2994 return( true );
2995
2996 if( (set = OSDynamicCast( OSSet, resourcesProp ))) {
2997
2998 iter = OSCollectionIterator::withCollection( set );
2999 ok = (0 != iter);
3000 while( ok && (resourcesProp = iter->getNextObject()) )
3001 ok = checkResource( resourcesProp );
3002 if( iter)
3003 iter->release();
3004
3005 } else
3006 ok = checkResource( resourcesProp );
3007
3008 return( ok );
3009 }
3010
3011
3012 void _IOConfigThread::configThread( void )
3013 {
3014 _IOConfigThread * inst;
3015
3016 do {
3017 if( !(inst = new _IOConfigThread))
3018 continue;
3019 if( !inst->init())
3020 continue;
3021 thread_t unused;
3022 if (KERN_SUCCESS != kernel_thread_start(&_IOConfigThread::main, inst, &unused))
3023 continue;
3024
3025 return;
3026
3027 } while( false);
3028
3029 if( inst)
3030 inst->release();
3031
3032 return;
3033 }
3034
3035 void _IOConfigThread::free( void )
3036 {
3037 thread_deallocate(current_thread());
3038 OSObject::free();
3039 }
3040
3041 void IOService::doServiceMatch( IOOptionBits options )
3042 {
3043 _IOServiceNotifier * notify;
3044 OSIterator * iter;
3045 OSOrderedSet * matches;
3046 SInt32 catalogGeneration;
3047 bool keepGuessing = true;
3048 bool reRegistered = true;
3049
3050 // job->nub->deliverNotification( gIOPublishNotification,
3051 // kIOServiceRegisteredState, 0xffffffff );
3052
3053 while( keepGuessing ) {
3054
3055 matches = gIOCatalogue->findDrivers( this, &catalogGeneration );
3056 // the matches list should always be created by findDrivers()
3057 if( matches) {
3058
3059 lockForArbitration();
3060 if( 0 == (__state[0] & kIOServiceFirstPublishState))
3061 deliverNotification( gIOFirstPublishNotification,
3062 kIOServiceFirstPublishState, 0xffffffff );
3063 LOCKREADNOTIFY();
3064 __state[1] &= ~kIOServiceNeedConfigState;
3065 __state[1] |= kIOServiceConfigState;
3066 __state[0] |= kIOServiceRegisteredState;
3067
3068 if( reRegistered && (0 == (__state[0] & kIOServiceInactiveState))) {
3069
3070 iter = OSCollectionIterator::withCollection( (OSOrderedSet *)
3071 gNotifications->getObject( gIOPublishNotification ) );
3072 if( iter) {
3073 while((notify = (_IOServiceNotifier *)
3074 iter->getNextObject())) {
3075
3076 if( passiveMatch( notify->matching )
3077 && (kIOServiceNotifyEnable & notify->state))
3078 matches->setObject( notify );
3079 }
3080 iter->release();
3081 }
3082 }
3083
3084 UNLOCKNOTIFY();
3085 unlockForArbitration();
3086
3087 if( matches->getCount() && (kIOReturnSuccess == getResources()))
3088 probeCandidates( matches );
3089 else
3090 matches->release();
3091 }
3092
3093 lockForArbitration();
3094 reRegistered = (0 != (__state[1] & kIOServiceNeedConfigState));
3095 keepGuessing =
3096 (reRegistered || (catalogGeneration !=
3097 gIOCatalogue->getGenerationCount()))
3098 && (0 == (__state[0] & kIOServiceInactiveState));
3099
3100 if( keepGuessing)
3101 unlockForArbitration();
3102 }
3103
3104 if( (0 == (__state[0] & kIOServiceInactiveState))
3105 && (0 == (__state[1] & kIOServiceModuleStallState)) ) {
3106 deliverNotification( gIOMatchedNotification,
3107 kIOServiceMatchedState, 0xffffffff );
3108 if( 0 == (__state[0] & kIOServiceFirstMatchState))
3109 deliverNotification( gIOFirstMatchNotification,
3110 kIOServiceFirstMatchState, 0xffffffff );
3111 }
3112
3113 __state[1] &= ~kIOServiceConfigState;
3114 if( __state[0] & kIOServiceInactiveState)
3115 scheduleTerminatePhase2();
3116
3117 _adjustBusy( -1 );
3118 unlockForArbitration();
3119 }
3120
3121 UInt32 IOService::_adjustBusy( SInt32 delta )
3122 {
3123 IOService * next;
3124 UInt32 count;
3125 UInt32 result;
3126 bool wasQuiet, nowQuiet, needWake;
3127
3128 next = this;
3129 result = __state[1] & kIOServiceBusyStateMask;
3130
3131 if( delta) do {
3132 if( next != this)
3133 next->lockForArbitration();
3134 count = next->__state[1] & kIOServiceBusyStateMask;
3135 wasQuiet = (0 == count);
3136 if (((delta < 0) && wasQuiet) || ((delta > 0) && (kIOServiceBusyMax == count)))
3137 OSReportWithBacktrace("%s: bad busy count (%d,%d)\n", next->getName(), count, delta);
3138 else
3139 count += delta;
3140 next->__state[1] = (next->__state[1] & ~kIOServiceBusyStateMask) | count;
3141 nowQuiet = (0 == count);
3142 needWake = (0 != (kIOServiceBusyWaiterState & next->__state[1]));
3143
3144 if( needWake) {
3145 next->__state[1] &= ~kIOServiceBusyWaiterState;
3146 IOLockLock( gIOServiceBusyLock );
3147 thread_wakeup( (event_t) next);
3148 IOLockUnlock( gIOServiceBusyLock );
3149 }
3150 if( next != this)
3151 next->unlockForArbitration();
3152
3153 if( (wasQuiet || nowQuiet) ) {
3154 uint64_t regID = next->getRegistryEntryID();
3155
3156 IOServiceTrace(
3157 ((wasQuiet/*nowBusy*/) ? IOSERVICE_BUSY : IOSERVICE_NONBUSY),
3158 (uintptr_t) regID,
3159 (uintptr_t) (regID >> 32),
3160 (uintptr_t) next,
3161 0);
3162
3163 if (wasQuiet)
3164 {
3165 next->__timeBusy = mach_absolute_time();
3166 }
3167 else
3168 {
3169 next->__accumBusy += mach_absolute_time() - next->__timeBusy;
3170 next->__timeBusy = 0;
3171 }
3172
3173 MessageClientsContext context;
3174
3175 context.service = next;
3176 context.type = kIOMessageServiceBusyStateChange;
3177 context.argument = (void *) wasQuiet; /*nowBusy*/
3178 context.argSize = 0;
3179
3180 applyToInterestNotifiers( next, gIOBusyInterest,
3181 &messageClientsApplier, &context );
3182
3183 #if !NO_KEXTD
3184 if( nowQuiet && (next == gIOServiceRoot))
3185 OSKext::considerUnloads();
3186 #endif
3187 }
3188
3189 delta = nowQuiet ? -1 : +1;
3190
3191 } while( (wasQuiet || nowQuiet) && (next = next->getProvider()));
3192
3193 return( result );
3194 }
3195
3196 void IOService::adjustBusy( SInt32 delta )
3197 {
3198 lockForArbitration();
3199 _adjustBusy( delta );
3200 unlockForArbitration();
3201 }
3202
3203 uint64_t IOService::getAccumulatedBusyTime( void )
3204 {
3205 uint64_t accumBusy = __accumBusy;
3206 uint64_t timeBusy = __timeBusy;
3207 uint64_t nano;
3208
3209 do
3210 {
3211 accumBusy = __accumBusy;
3212 timeBusy = __timeBusy;
3213 if (timeBusy)
3214 accumBusy += mach_absolute_time() - timeBusy;
3215 }
3216 while (timeBusy != __timeBusy);
3217
3218 absolutetime_to_nanoseconds(*(AbsoluteTime *)&accumBusy, &nano);
3219
3220 return (nano);
3221 }
3222
3223 UInt32 IOService::getBusyState( void )
3224 {
3225 return( __state[1] & kIOServiceBusyStateMask );
3226 }
3227
3228 IOReturn IOService::waitForState( UInt32 mask, UInt32 value,
3229 mach_timespec_t * timeout )
3230 {
3231 panic("waitForState");
3232 return (kIOReturnUnsupported);
3233 }
3234
3235 IOReturn IOService::waitForState( UInt32 mask, UInt32 value,
3236 uint64_t timeout )
3237 {
3238 bool wait;
3239 int waitResult = THREAD_AWAKENED;
3240 bool computeDeadline = true;
3241 AbsoluteTime abstime;
3242
3243 do {
3244 lockForArbitration();
3245 IOLockLock( gIOServiceBusyLock );
3246 wait = (value != (__state[1] & mask));
3247 if( wait) {
3248 __state[1] |= kIOServiceBusyWaiterState;
3249 unlockForArbitration();
3250 if( timeout != UINT64_MAX ) {
3251 if( computeDeadline ) {
3252 AbsoluteTime nsinterval;
3253 nanoseconds_to_absolutetime(timeout, &nsinterval );
3254 clock_absolutetime_interval_to_deadline(nsinterval, &abstime);
3255 computeDeadline = false;
3256 }
3257 assert_wait_deadline((event_t)this, THREAD_UNINT, __OSAbsoluteTime(abstime));
3258 }
3259 else
3260 assert_wait((event_t)this, THREAD_UNINT );
3261 } else
3262 unlockForArbitration();
3263 IOLockUnlock( gIOServiceBusyLock );
3264 if( wait)
3265 waitResult = thread_block(THREAD_CONTINUE_NULL);
3266
3267 } while( wait && (waitResult != THREAD_TIMED_OUT));
3268
3269 if( waitResult == THREAD_TIMED_OUT)
3270 return( kIOReturnTimeout );
3271 else
3272 return( kIOReturnSuccess );
3273 }
3274
3275 IOReturn IOService::waitQuiet( uint64_t timeout )
3276 {
3277 return( waitForState( kIOServiceBusyStateMask, 0, timeout ));
3278 }
3279
3280 IOReturn IOService::waitQuiet( mach_timespec_t * timeout )
3281 {
3282 uint64_t timeoutNS;
3283
3284 if (timeout)
3285 {
3286 timeoutNS = timeout->tv_sec;
3287 timeoutNS *= kSecondScale;
3288 timeoutNS += timeout->tv_nsec;
3289 }
3290 else
3291 timeoutNS = UINT64_MAX;
3292
3293 return( waitForState( kIOServiceBusyStateMask, 0, timeoutNS ));
3294 }
3295
3296 bool IOService::serializeProperties( OSSerialize * s ) const
3297 {
3298 #if 0
3299 ((IOService *)this)->setProperty( ((IOService *)this)->__state,
3300 sizeof( __state), "__state");
3301 #endif
3302 return( super::serializeProperties(s) );
3303 }
3304
3305
3306 void _IOConfigThread::main(void * arg, wait_result_t result)
3307 {
3308 _IOConfigThread * self = (_IOConfigThread *) arg;
3309 _IOServiceJob * job;
3310 IOService * nub;
3311 bool alive = true;
3312 kern_return_t kr;
3313 thread_precedence_policy_data_t precedence = { -1 };
3314
3315 kr = thread_policy_set(current_thread(),
3316 THREAD_PRECEDENCE_POLICY,
3317 (thread_policy_t) &precedence,
3318 THREAD_PRECEDENCE_POLICY_COUNT);
3319 if (KERN_SUCCESS != kr)
3320 IOLog("thread_policy_set(%d)\n", kr);
3321
3322 do {
3323
3324 // randomDelay();
3325
3326 semaphore_wait( gJobsSemaphore );
3327
3328 IOTakeLock( gJobsLock );
3329 job = (_IOServiceJob *) gJobs->getFirstObject();
3330 job->retain();
3331 gJobs->removeObject(job);
3332 if( job) {
3333 gOutstandingJobs--;
3334 // gNumConfigThreads--; // we're out of service
3335 gNumWaitingThreads--; // we're out of service
3336 }
3337 IOUnlock( gJobsLock );
3338
3339 if( job) {
3340
3341 nub = job->nub;
3342
3343 if( gIOKitDebug & kIOLogConfig)
3344 LOG("config(%p): starting on %s, %d\n",
3345 IOThreadSelf(), job->nub->getName(), job->type);
3346
3347 switch( job->type) {
3348
3349 case kMatchNubJob:
3350 nub->doServiceMatch( job->options );
3351 break;
3352
3353 default:
3354 LOG("config(%p): strange type (%d)\n",
3355 IOThreadSelf(), job->type );
3356 break;
3357 }
3358
3359 nub->release();
3360 job->release();
3361
3362 IOTakeLock( gJobsLock );
3363 alive = (gOutstandingJobs > gNumWaitingThreads);
3364 if( alive)
3365 gNumWaitingThreads++; // back in service
3366 // gNumConfigThreads++;
3367 else {
3368 if( 0 == --gNumConfigThreads) {
3369 // IOLog("MATCH IDLE\n");
3370 IOLockWakeup( gJobsLock, (event_t) &gNumConfigThreads, /* one-thread */ false );
3371 }
3372 }
3373 IOUnlock( gJobsLock );
3374 }
3375
3376 } while( alive );
3377
3378 if( gIOKitDebug & kIOLogConfig)
3379 LOG("config(%p): terminating\n", IOThreadSelf() );
3380
3381 self->release();
3382 }
3383
3384 IOReturn IOService::waitMatchIdle( UInt32 msToWait )
3385 {
3386 bool wait;
3387 int waitResult = THREAD_AWAKENED;
3388 bool computeDeadline = true;
3389 AbsoluteTime abstime;
3390
3391 IOLockLock( gJobsLock );
3392 do {
3393 wait = (0 != gNumConfigThreads);
3394 if( wait) {
3395 if( msToWait) {
3396 if( computeDeadline ) {
3397 clock_interval_to_absolutetime_interval(
3398 msToWait, kMillisecondScale, &abstime );
3399 clock_absolutetime_interval_to_deadline(
3400 abstime, &abstime );
3401 computeDeadline = false;
3402 }
3403 waitResult = IOLockSleepDeadline( gJobsLock, &gNumConfigThreads,
3404 abstime, THREAD_UNINT );
3405 } else {
3406 waitResult = IOLockSleep( gJobsLock, &gNumConfigThreads,
3407 THREAD_UNINT );
3408 }
3409 }
3410 } while( wait && (waitResult != THREAD_TIMED_OUT));
3411 IOLockUnlock( gJobsLock );
3412
3413 if( waitResult == THREAD_TIMED_OUT)
3414 return( kIOReturnTimeout );
3415 else
3416 return( kIOReturnSuccess );
3417 }
3418
3419 void _IOServiceJob::pingConfig( _IOServiceJob * job )
3420 {
3421 int count;
3422 bool create;
3423
3424 assert( job );
3425
3426 IOTakeLock( gJobsLock );
3427
3428 gOutstandingJobs++;
3429 gJobs->setLastObject( job );
3430
3431 count = gNumWaitingThreads;
3432 // if( gNumConfigThreads) count++;// assume we're called from a config thread
3433
3434 create = ( (gOutstandingJobs > count)
3435 && (gNumConfigThreads < kMaxConfigThreads) );
3436 if( create) {
3437 gNumConfigThreads++;
3438 gNumWaitingThreads++;
3439 }
3440
3441 IOUnlock( gJobsLock );
3442
3443 job->release();
3444
3445 if( create) {
3446 if( gIOKitDebug & kIOLogConfig)
3447 LOG("config(%d): creating\n", gNumConfigThreads - 1);
3448 _IOConfigThread::configThread();
3449 }
3450
3451 semaphore_signal( gJobsSemaphore );
3452 }
3453
3454 // internal - call with gNotificationLock
3455 OSObject * IOService::copyExistingServices( OSDictionary * matching,
3456 IOOptionBits inState, IOOptionBits options )
3457 {
3458 OSObject * current = 0;
3459 OSIterator * iter;
3460 IOService * service;
3461 OSObject * obj;
3462
3463 if( !matching)
3464 return( 0 );
3465
3466 if(true
3467 && (obj = matching->getObject(gIOProviderClassKey))
3468 && gIOResourcesKey
3469 && gIOResourcesKey->isEqualTo(obj)
3470 && (service = gIOResources))
3471 {
3472 if( (inState == (service->__state[0] & inState))
3473 && (0 == (service->__state[0] & kIOServiceInactiveState))
3474 && service->passiveMatch( matching ))
3475 {
3476 if( options & kIONotifyOnce)
3477 {
3478 service->retain();
3479 current = service;
3480 }
3481 else
3482 current = OSSet::withObjects(
3483 (const OSObject **) &service, 1, 1 );
3484 }
3485 }
3486 else
3487 {
3488 iter = IORegistryIterator::iterateOver( gIOServicePlane,
3489 kIORegistryIterateRecursively );
3490 if( iter) {
3491 do {
3492 iter->reset();
3493 while( (service = (IOService *) iter->getNextObject())) {
3494 if( (inState == (service->__state[0] & inState))
3495 && (0 == (service->__state[0] & kIOServiceInactiveState))
3496 && service->passiveMatch( matching )) {
3497
3498 if( options & kIONotifyOnce) {
3499 service->retain();
3500 current = service;
3501 break;
3502 }
3503 if( current)
3504 ((OSSet *)current)->setObject( service );
3505 else
3506 current = OSSet::withObjects(
3507 (const OSObject **) &service, 1, 1 );
3508 }
3509 }
3510 } while( !service && !iter->isValid());
3511 iter->release();
3512 }
3513 }
3514
3515 if( current && (0 == (options & (kIONotifyOnce | kIOServiceExistingSet)))) {
3516 iter = OSCollectionIterator::withCollection( (OSSet *)current );
3517 current->release();
3518 current = iter;
3519 }
3520
3521 return( current );
3522 }
3523
3524 // public version
3525 OSIterator * IOService::getMatchingServices( OSDictionary * matching )
3526 {
3527 OSIterator * iter;
3528
3529 // is a lock even needed?
3530 LOCKWRITENOTIFY();
3531
3532 iter = (OSIterator *) copyExistingServices( matching,
3533 kIOServiceMatchedState );
3534
3535 UNLOCKNOTIFY();
3536
3537 return( iter );
3538 }
3539
3540 struct _IOServiceMatchingNotificationHandlerRef
3541 {
3542 IOServiceNotificationHandler handler;
3543 void * ref;
3544 };
3545
3546 static bool _IOServiceMatchingNotificationHandler( void * target, void * refCon,
3547 IOService * newService,
3548 IONotifier * notifier )
3549 {
3550 return ((*((_IOServiceNotifier *) notifier)->compatHandler)(target, refCon, newService));
3551 }
3552
3553 // internal - call with gNotificationLock
3554 IONotifier * IOService::setNotification(
3555 const OSSymbol * type, OSDictionary * matching,
3556 IOServiceMatchingNotificationHandler handler, void * target, void * ref,
3557 SInt32 priority )
3558 {
3559 _IOServiceNotifier * notify = 0;
3560 OSOrderedSet * set;
3561
3562 if( !matching)
3563 return( 0 );
3564
3565 notify = new _IOServiceNotifier;
3566 if( notify && !notify->init()) {
3567 notify->release();
3568 notify = 0;
3569 }
3570
3571 if( notify) {
3572 notify->handler = handler;
3573 notify->target = target;
3574 notify->matching = matching;
3575 matching->retain();
3576 if (handler == &_IOServiceMatchingNotificationHandler)
3577 {
3578 notify->compatHandler = ((_IOServiceMatchingNotificationHandlerRef *)ref)->handler;
3579 notify->ref = ((_IOServiceMatchingNotificationHandlerRef *)ref)->ref;
3580 }
3581 else
3582 notify->ref = ref;
3583 notify->priority = priority;
3584 notify->state = kIOServiceNotifyEnable;
3585 queue_init( &notify->handlerInvocations );
3586
3587 ////// queue
3588
3589 if( 0 == (set = (OSOrderedSet *) gNotifications->getObject( type ))) {
3590 set = OSOrderedSet::withCapacity( 1,
3591 IONotifyOrdering, 0 );
3592 if( set) {
3593 gNotifications->setObject( type, set );
3594 set->release();
3595 }
3596 }
3597 notify->whence = set;
3598 if( set)
3599 set->setObject( notify );
3600 }
3601
3602 return( notify );
3603 }
3604
3605 // internal - call with gNotificationLock
3606 IONotifier * IOService::doInstallNotification(
3607 const OSSymbol * type, OSDictionary * matching,
3608 IOServiceMatchingNotificationHandler handler,
3609 void * target, void * ref,
3610 SInt32 priority, OSIterator ** existing )
3611 {
3612 OSIterator * exist;
3613 IONotifier * notify;
3614 IOOptionBits inState;
3615
3616 if( !matching)
3617 return( 0 );
3618
3619 if( type == gIOPublishNotification)
3620 inState = kIOServiceRegisteredState;
3621
3622 else if( type == gIOFirstPublishNotification)
3623 inState = kIOServiceFirstPublishState;
3624
3625 else if( (type == gIOMatchedNotification)
3626 || (type == gIOFirstMatchNotification))
3627 inState = kIOServiceMatchedState;
3628 else if( type == gIOTerminatedNotification)
3629 inState = 0;
3630 else
3631 return( 0 );
3632
3633 notify = setNotification( type, matching, handler, target, ref, priority );
3634
3635 if( inState)
3636 // get the current set
3637 exist = (OSIterator *) copyExistingServices( matching, inState );
3638 else
3639 exist = 0;
3640
3641 *existing = exist;
3642
3643 return( notify );
3644 }
3645
3646 #if !defined(__LP64__)
3647 IONotifier * IOService::installNotification(const OSSymbol * type, OSDictionary * matching,
3648 IOServiceNotificationHandler handler,
3649 void * target, void * refCon,
3650 SInt32 priority, OSIterator ** existing )
3651 {
3652 IONotifier * result;
3653 _IOServiceMatchingNotificationHandlerRef ref;
3654 ref.handler = handler;
3655 ref.ref = refCon;
3656
3657 result = (_IOServiceNotifier *) installNotification( type, matching,
3658 &_IOServiceMatchingNotificationHandler,
3659 target, &ref, priority, existing );
3660 if (result)
3661 matching->release();
3662
3663 return (result);
3664 }
3665 #endif /* !defined(__LP64__) */
3666
3667
3668 IONotifier * IOService::installNotification(
3669 const OSSymbol * type, OSDictionary * matching,
3670 IOServiceMatchingNotificationHandler handler,
3671 void * target, void * ref,
3672 SInt32 priority, OSIterator ** existing )
3673 {
3674 IONotifier * notify;
3675
3676 LOCKWRITENOTIFY();
3677
3678 notify = doInstallNotification( type, matching, handler, target, ref,
3679 priority, existing );
3680
3681 UNLOCKNOTIFY();
3682
3683 return( notify );
3684 }
3685
3686 IONotifier * IOService::addNotification(
3687 const OSSymbol * type, OSDictionary * matching,
3688 IOServiceNotificationHandler handler,
3689 void * target, void * refCon,
3690 SInt32 priority )
3691 {
3692 IONotifier * result;
3693 _IOServiceMatchingNotificationHandlerRef ref;
3694
3695 ref.handler = handler;
3696 ref.ref = refCon;
3697
3698 result = addMatchingNotification(type, matching, &_IOServiceMatchingNotificationHandler,
3699 target, &ref, priority);
3700
3701 if (result)
3702 matching->release();
3703
3704 return (result);
3705 }
3706
3707 IONotifier * IOService::addMatchingNotification(
3708 const OSSymbol * type, OSDictionary * matching,
3709 IOServiceMatchingNotificationHandler handler,
3710 void * target, void * ref,
3711 SInt32 priority )
3712 {
3713 OSIterator * existing = NULL;
3714 _IOServiceNotifier * notify;
3715 IOService * next;
3716
3717 notify = (_IOServiceNotifier *) installNotification( type, matching,
3718 handler, target, ref, priority, &existing );
3719
3720 // send notifications for existing set
3721 if( existing) {
3722
3723 notify->retain(); // in case handler remove()s
3724 while( (next = (IOService *) existing->getNextObject())) {
3725
3726 next->lockForArbitration();
3727 if( 0 == (next->__state[0] & kIOServiceInactiveState))
3728 next->invokeNotifer( notify );
3729 next->unlockForArbitration();
3730 }
3731 notify->release();
3732 existing->release();
3733 }
3734
3735 return( notify );
3736 }
3737
3738 bool IOService::syncNotificationHandler(
3739 void * /* target */, void * ref,
3740 IOService * newService,
3741 IONotifier * notifier )
3742 {
3743
3744 LOCKWRITENOTIFY();
3745 if (!*((IOService **) ref))
3746 {
3747 newService->retain();
3748 (*(IOService **) ref) = newService;
3749 WAKEUPNOTIFY(ref);
3750 }
3751 UNLOCKNOTIFY();
3752
3753 return( false );
3754 }
3755
3756 IOService * IOService::waitForMatchingService( OSDictionary * matching,
3757 uint64_t timeout)
3758 {
3759 IONotifier * notify = 0;
3760 // priority doesn't help us much since we need a thread wakeup
3761 SInt32 priority = 0;
3762 IOService * result;
3763
3764 if (!matching)
3765 return( 0 );
3766
3767 result = NULL;
3768
3769 LOCKWRITENOTIFY();
3770 do
3771 {
3772 result = (IOService *) copyExistingServices( matching,
3773 kIOServiceMatchedState, kIONotifyOnce );
3774 if (result)
3775 break;
3776 notify = IOService::setNotification( gIOMatchedNotification, matching,
3777 &IOService::syncNotificationHandler, (void *) 0,
3778 &result, priority );
3779 if (!notify)
3780 break;
3781 if (UINT64_MAX != timeout)
3782 {
3783 AbsoluteTime deadline;
3784 nanoseconds_to_absolutetime(timeout, &deadline);
3785 clock_absolutetime_interval_to_deadline(deadline, &deadline);
3786 SLEEPNOTIFYTO(&result, deadline);
3787 }
3788 else
3789 {
3790 SLEEPNOTIFY(&result);
3791 }
3792 }
3793 while( false );
3794
3795 UNLOCKNOTIFY();
3796
3797 if (notify)
3798 notify->remove(); // dequeues
3799
3800 return( result );
3801 }
3802
3803 IOService * IOService::waitForService( OSDictionary * matching,
3804 mach_timespec_t * timeout )
3805 {
3806 IOService * result;
3807 uint64_t timeoutNS;
3808
3809 if (timeout)
3810 {
3811 timeoutNS = timeout->tv_sec;
3812 timeoutNS *= kSecondScale;
3813 timeoutNS += timeout->tv_nsec;
3814 }
3815 else
3816 timeoutNS = UINT64_MAX;
3817
3818 result = waitForMatchingService(matching, timeoutNS);
3819
3820 matching->release();
3821 if (result)
3822 result->release();
3823
3824 return (result);
3825 }
3826
3827 void IOService::deliverNotification( const OSSymbol * type,
3828 IOOptionBits orNewState, IOOptionBits andNewState )
3829 {
3830 _IOServiceNotifier * notify;
3831 OSIterator * iter;
3832 OSArray * willSend = 0;
3833
3834 lockForArbitration();
3835
3836 if( (0 == (__state[0] & kIOServiceInactiveState))
3837 || (type == gIOTerminatedNotification)) {
3838
3839 LOCKREADNOTIFY();
3840
3841 iter = OSCollectionIterator::withCollection( (OSOrderedSet *)
3842 gNotifications->getObject( type ) );
3843
3844 if( iter) {
3845 while( (notify = (_IOServiceNotifier *) iter->getNextObject())) {
3846
3847 if( passiveMatch( notify->matching)
3848 && (kIOServiceNotifyEnable & notify->state)) {
3849 if( 0 == willSend)
3850 willSend = OSArray::withCapacity(8);
3851 if( willSend)
3852 willSend->setObject( notify );
3853 }
3854 }
3855 iter->release();
3856 }
3857
3858 __state[0] = (__state[0] | orNewState) & andNewState;
3859
3860 UNLOCKNOTIFY();
3861 }
3862
3863 if( willSend) {
3864 for( unsigned int idx = 0;
3865 (notify = (_IOServiceNotifier *) willSend->getObject(idx));
3866 idx++) {
3867 invokeNotifer( notify );
3868 }
3869 willSend->release();
3870 }
3871 unlockForArbitration();
3872 }
3873
3874 IOOptionBits IOService::getState( void ) const
3875 {
3876 return( __state[0] );
3877 }
3878
3879 /*
3880 * Helpers to make matching objects for simple cases
3881 */
3882
3883 OSDictionary * IOService::serviceMatching( const OSString * name,
3884 OSDictionary * table )
3885 {
3886 if( !table)
3887 table = OSDictionary::withCapacity( 2 );
3888 if( table)
3889 table->setObject(gIOProviderClassKey, (OSObject *)name );
3890
3891 return( table );
3892 }
3893
3894 OSDictionary * IOService::serviceMatching( const char * name,
3895 OSDictionary * table )
3896 {
3897 const OSString * str;
3898
3899 str = OSSymbol::withCString( name );
3900 if( !str)
3901 return( 0 );
3902
3903 table = serviceMatching( str, table );
3904 str->release();
3905 return( table );
3906 }
3907
3908 OSDictionary * IOService::nameMatching( const OSString * name,
3909 OSDictionary * table )
3910 {
3911 if( !table)
3912 table = OSDictionary::withCapacity( 2 );
3913 if( table)
3914 table->setObject( gIONameMatchKey, (OSObject *)name );
3915
3916 return( table );
3917 }
3918
3919 OSDictionary * IOService::nameMatching( const char * name,
3920 OSDictionary * table )
3921 {
3922 const OSString * str;
3923
3924 str = OSSymbol::withCString( name );
3925 if( !str)
3926 return( 0 );
3927
3928 table = nameMatching( str, table );
3929 str->release();
3930 return( table );
3931 }
3932
3933 OSDictionary * IOService::resourceMatching( const OSString * str,
3934 OSDictionary * table )
3935 {
3936 table = serviceMatching( gIOResourcesKey, table );
3937 if( table)
3938 table->setObject( gIOResourceMatchKey, (OSObject *) str );
3939
3940 return( table );
3941 }
3942
3943 OSDictionary * IOService::resourceMatching( const char * name,
3944 OSDictionary * table )
3945 {
3946 const OSSymbol * str;
3947
3948 str = OSSymbol::withCString( name );
3949 if( !str)
3950 return( 0 );
3951
3952 table = resourceMatching( str, table );
3953 str->release();
3954
3955 return( table );
3956 }
3957
3958 OSDictionary * IOService::propertyMatching( const OSSymbol * key, const OSObject * value,
3959 OSDictionary * table )
3960 {
3961 OSDictionary * properties;
3962
3963 properties = OSDictionary::withCapacity( 2 );
3964 if( !properties)
3965 return( 0 );
3966 properties->setObject( key, value );
3967
3968 if( !table)
3969 table = OSDictionary::withCapacity( 2 );
3970 if( table)
3971 table->setObject( gIOPropertyMatchKey, properties );
3972
3973 properties->release();
3974
3975 return( table );
3976 }
3977
3978 OSDictionary * IOService::registryEntryIDMatching( uint64_t entryID,
3979 OSDictionary * table )
3980 {
3981 OSNumber * num;
3982
3983 num = OSNumber::withNumber( entryID, 64 );
3984 if( !num)
3985 return( 0 );
3986
3987 if( !table)
3988 table = OSDictionary::withCapacity( 2 );
3989 if( table)
3990 table->setObject( gIORegistryEntryIDKey, num );
3991
3992 if (num)
3993 num->release();
3994
3995 return( table );
3996 }
3997
3998
3999 /*
4000 * _IOServiceNotifier
4001 */
4002
4003 // wait for all threads, other than the current one,
4004 // to exit the handler
4005
4006 void _IOServiceNotifier::wait()
4007 {
4008 _IOServiceNotifierInvocation * next;
4009 bool doWait;
4010
4011 do {
4012 doWait = false;
4013 queue_iterate( &handlerInvocations, next,
4014 _IOServiceNotifierInvocation *, link) {
4015 if( next->thread != current_thread() ) {
4016 doWait = true;
4017 break;
4018 }
4019 }
4020 if( doWait) {
4021 state |= kIOServiceNotifyWaiter;
4022 SLEEPNOTIFY(this);
4023 }
4024
4025 } while( doWait );
4026 }
4027
4028 void _IOServiceNotifier::free()
4029 {
4030 assert( queue_empty( &handlerInvocations ));
4031 OSObject::free();
4032 }
4033
4034 void _IOServiceNotifier::remove()
4035 {
4036 LOCKWRITENOTIFY();
4037
4038 if( whence) {
4039 whence->removeObject( (OSObject *) this );
4040 whence = 0;
4041 }
4042 if( matching) {
4043 matching->release();
4044 matching = 0;
4045 }
4046
4047 state &= ~kIOServiceNotifyEnable;
4048
4049 wait();
4050
4051 UNLOCKNOTIFY();
4052
4053 release();
4054 }
4055
4056 bool _IOServiceNotifier::disable()
4057 {
4058 bool ret;
4059
4060 LOCKWRITENOTIFY();
4061
4062 ret = (0 != (kIOServiceNotifyEnable & state));
4063 state &= ~kIOServiceNotifyEnable;
4064 if( ret)
4065 wait();
4066
4067 UNLOCKNOTIFY();
4068
4069 return( ret );
4070 }
4071
4072 void _IOServiceNotifier::enable( bool was )
4073 {
4074 LOCKWRITENOTIFY();
4075 if( was)
4076 state |= kIOServiceNotifyEnable;
4077 else
4078 state &= ~kIOServiceNotifyEnable;
4079 UNLOCKNOTIFY();
4080 }
4081
4082 /*
4083 * IOResources
4084 */
4085
4086 IOService * IOResources::resources( void )
4087 {
4088 IOResources * inst;
4089
4090 inst = new IOResources;
4091 if( inst && !inst->init()) {
4092 inst->release();
4093 inst = 0;
4094 }
4095
4096 return( inst );
4097 }
4098
4099 IOWorkLoop * IOResources::getWorkLoop() const
4100 {
4101 // If we are the resource root
4102 // then use the platform's workloop
4103 if (this == (IOResources *) gIOResources)
4104 return getPlatform()->getWorkLoop();
4105 else
4106 return IOService::getWorkLoop();
4107 }
4108
4109 bool IOResources::matchPropertyTable( OSDictionary * table )
4110 {
4111 OSObject * prop;
4112 OSString * str;
4113 OSSet * set;
4114 OSIterator * iter;
4115 bool ok = false;
4116
4117 prop = table->getObject( gIOResourceMatchKey );
4118 str = OSDynamicCast( OSString, prop );
4119 if( str)
4120 ok = (0 != getProperty( str ));
4121
4122 else if( (set = OSDynamicCast( OSSet, prop))) {
4123
4124 iter = OSCollectionIterator::withCollection( set );
4125 ok = (iter != 0);
4126 while( ok && (str = OSDynamicCast( OSString, iter->getNextObject()) ))
4127 ok = (0 != getProperty( str ));
4128
4129 if( iter)
4130 iter->release();
4131 }
4132
4133 return( ok );
4134 }
4135
4136 IOReturn IOResources::setProperties( OSObject * properties )
4137 {
4138 IOReturn err;
4139 const OSSymbol * key;
4140 OSDictionary * dict;
4141 OSCollectionIterator * iter;
4142
4143 err = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
4144 if ( kIOReturnSuccess != err)
4145 return( err );
4146
4147 dict = OSDynamicCast(OSDictionary, properties);
4148 if( 0 == dict)
4149 return( kIOReturnBadArgument);
4150
4151 iter = OSCollectionIterator::withCollection( dict);
4152 if( 0 == iter)
4153 return( kIOReturnBadArgument);
4154
4155 while( (key = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
4156
4157 if (gIOConsoleUsersKey == key)
4158 {
4159 IORegistryEntry::getRegistryRoot()->setProperty(key, dict->getObject(key));
4160 OSIncrementAtomic( &gIOConsoleUsersSeed );
4161 publishResource( gIOConsoleUsersSeedKey, gIOConsoleUsersSeedValue );
4162 continue;
4163 }
4164
4165 publishResource( key, dict->getObject(key) );
4166 }
4167
4168 iter->release();
4169
4170 return( kIOReturnSuccess );
4171 }
4172
4173 /*
4174 * Helpers for matching dictionaries.
4175 * Keys existing in matching are checked in properties.
4176 * Keys may be a string or OSCollection of IOStrings
4177 */
4178
4179 bool IOService::compareProperty( OSDictionary * matching,
4180 const char * key )
4181 {
4182 OSObject * value;
4183 bool ok;
4184
4185 value = matching->getObject( key );
4186 if( value)
4187 ok = value->isEqualTo( getProperty( key ));
4188 else
4189 ok = true;
4190
4191 return( ok );
4192 }
4193
4194
4195 bool IOService::compareProperty( OSDictionary * matching,
4196 const OSString * key )
4197 {
4198 OSObject * value;
4199 bool ok;
4200
4201 value = matching->getObject( key );
4202 if( value)
4203 ok = value->isEqualTo( getProperty( key ));
4204 else
4205 ok = true;
4206
4207 return( ok );
4208 }
4209
4210 bool IOService::compareProperties( OSDictionary * matching,
4211 OSCollection * keys )
4212 {
4213 OSCollectionIterator * iter;
4214 const OSString * key;
4215 bool ok = true;
4216
4217 if( !matching || !keys)
4218 return( false );
4219
4220 iter = OSCollectionIterator::withCollection( keys );
4221
4222 if( iter) {
4223 while( ok && (key = OSDynamicCast( OSString, iter->getNextObject())))
4224 ok = compareProperty( matching, key );
4225
4226 iter->release();
4227 }
4228 keys->release(); // !! consume a ref !!
4229
4230 return( ok );
4231 }
4232
4233 /* Helper to add a location matching dict to the table */
4234
4235 OSDictionary * IOService::addLocation( OSDictionary * table )
4236 {
4237 OSDictionary * dict;
4238
4239 if( !table)
4240 return( 0 );
4241
4242 dict = OSDictionary::withCapacity( 1 );
4243 if( dict) {
4244 table->setObject( gIOLocationMatchKey, dict );
4245 dict->release();
4246 }
4247
4248 return( dict );
4249 }
4250
4251 /*
4252 * Go looking for a provider to match a location dict.
4253 */
4254
4255 IOService * IOService::matchLocation( IOService * /* client */ )
4256 {
4257 IOService * parent;
4258
4259 parent = getProvider();
4260
4261 if( parent)
4262 parent = parent->matchLocation( this );
4263
4264 return( parent );
4265 }
4266
4267 bool IOService::passiveMatch( OSDictionary * table, bool changesOK )
4268 {
4269 IOService * where;
4270 OSString * matched;
4271 OSObject * obj;
4272 OSString * str;
4273 IORegistryEntry * entry;
4274 OSNumber * num;
4275 SInt32 score;
4276 OSNumber * newPri;
4277 bool match = true;
4278 bool matchParent = false;
4279 UInt32 done;
4280
4281 assert( table );
4282
4283 where = this;
4284
4285 do {
4286 do {
4287 done = 0;
4288
4289 str = OSDynamicCast( OSString, table->getObject( gIOProviderClassKey));
4290 if( str) {
4291 done++;
4292 match = (0 != where->metaCast( str ));
4293 if( !match)
4294 break;
4295 }
4296
4297 obj = table->getObject( gIONameMatchKey );
4298 if( obj) {
4299 done++;
4300 match = where->compareNames( obj, changesOK ? &matched : 0 );
4301 if( !match)
4302 break;
4303 if( changesOK && matched) {
4304 // leave a hint as to which name matched
4305 table->setObject( gIONameMatchedKey, matched );
4306 matched->release();
4307 }
4308 }
4309
4310 str = OSDynamicCast( OSString, table->getObject( gIOLocationMatchKey ));
4311 if( str) {
4312
4313 const OSSymbol * sym;
4314
4315 done++;
4316 match = false;
4317 sym = where->copyLocation();
4318 if( sym) {
4319 match = sym->isEqualTo( str );
4320 sym->release();
4321 }
4322 if( !match)
4323 break;
4324 }
4325
4326 obj = table->getObject( gIOPropertyMatchKey );
4327 if( obj) {
4328
4329 OSDictionary * dict;
4330 OSDictionary * nextDict;
4331 OSIterator * iter;
4332
4333 done++;
4334 match = false;
4335 dict = where->dictionaryWithProperties();
4336 if( dict) {
4337 nextDict = OSDynamicCast( OSDictionary, obj);
4338 if( nextDict)
4339 iter = 0;
4340 else
4341 iter = OSCollectionIterator::withCollection(
4342 OSDynamicCast(OSCollection, obj));
4343
4344 while( nextDict
4345 || (iter && (0 != (nextDict = OSDynamicCast(OSDictionary,
4346 iter->getNextObject()))))) {
4347 match = dict->isEqualTo( nextDict, nextDict);
4348 if( match)
4349 break;
4350 nextDict = 0;
4351 }
4352 dict->release();
4353 if( iter)
4354 iter->release();
4355 }
4356 if( !match)
4357 break;
4358 }
4359
4360 str = OSDynamicCast( OSString, table->getObject( gIOPathMatchKey ));
4361 if( str) {
4362 done++;
4363 entry = IORegistryEntry::fromPath( str->getCStringNoCopy() );
4364 match = (where == entry);
4365 if( entry)
4366 entry->release();
4367 if( !match)
4368 break;
4369 }
4370
4371 num = OSDynamicCast( OSNumber, table->getObject( gIORegistryEntryIDKey ));
4372 if( num) {
4373 done++;
4374 match = (getRegistryEntryID() == num->unsigned64BitValue());
4375 }
4376
4377 num = OSDynamicCast( OSNumber, table->getObject( gIOMatchedServiceCountKey ));
4378 if( num) {
4379
4380 OSIterator * iter;
4381 IOService * service = 0;
4382 UInt32 serviceCount = 0;
4383
4384 done++;
4385 iter = where->getClientIterator();
4386 if( iter) {
4387 while( (service = (IOService *) iter->getNextObject())) {
4388 if( kIOServiceInactiveState & service->__state[0])
4389 continue;
4390 if( 0 == service->getProperty( gIOMatchCategoryKey ))
4391 continue;
4392 ++serviceCount;
4393 }
4394 iter->release();
4395 }
4396 match = (serviceCount == num->unsigned32BitValue());
4397 if( !match)
4398 break;
4399 }
4400
4401 if( done == table->getCount()) {
4402 // don't call family if we've done all the entries in the table
4403 matchParent = false;
4404 break;
4405 }
4406
4407 // pass in score from property table
4408 score = IOServiceObjectOrder( table, (void *) gIOProbeScoreKey);
4409
4410 // do family specific matching
4411 match = where->matchPropertyTable( table, &score );
4412
4413 if( !match) {
4414 #if IOMATCHDEBUG
4415 if( kIOLogMatch & getDebugFlags( table ))
4416 LOG("%s: family specific matching fails\n", where->getName());
4417 #endif
4418 break;
4419 }
4420
4421 if( changesOK) {
4422 // save the score
4423 newPri = OSNumber::withNumber( score, 32 );
4424 if( newPri) {
4425 table->setObject( gIOProbeScoreKey, newPri );
4426 newPri->release();
4427 }
4428 }
4429
4430 if( !(match = where->compareProperty( table, kIOBSDNameKey )))
4431 break;
4432 if( !(match = where->compareProperty( table, kIOBSDMajorKey )))
4433 break;
4434 if( !(match = where->compareProperty( table, kIOBSDMinorKey )))
4435 break;
4436 if( !(match = where->compareProperty( table, kIOBSDUnitKey )))
4437 break;
4438
4439 matchParent = false;
4440
4441 obj = OSDynamicCast( OSDictionary,
4442 table->getObject( gIOParentMatchKey ));
4443 if( obj) {
4444 match = false;
4445 matchParent = true;
4446 table = (OSDictionary *) obj;
4447 break;
4448 }
4449
4450 table = OSDynamicCast( OSDictionary,
4451 table->getObject( gIOLocationMatchKey ));
4452 if( table) {
4453 match = false;
4454 where = where->getProvider();
4455 if( where)
4456 where = where->matchLocation( where );
4457 }
4458
4459 } while( table && where );
4460
4461 } while( matchParent && (where = where->getProvider()) );
4462
4463 if( kIOLogMatch & gIOKitDebug)
4464 if( where != this)
4465 LOG("match parent @ %s = %d\n",
4466 where->getName(), match );
4467
4468 return( match );
4469 }
4470
4471
4472 IOReturn IOService::newUserClient( task_t owningTask, void * securityID,
4473 UInt32 type, OSDictionary * properties,
4474 IOUserClient ** handler )
4475 {
4476 const OSSymbol *userClientClass = 0;
4477 IOUserClient *client;
4478 OSObject *temp;
4479
4480 if (kIOReturnSuccess == newUserClient( owningTask, securityID, type, handler ))
4481 return kIOReturnSuccess;
4482
4483 // First try my own properties for a user client class name
4484 temp = getProperty(gIOUserClientClassKey);
4485 if (temp) {
4486 if (OSDynamicCast(OSSymbol, temp))
4487 userClientClass = (const OSSymbol *) temp;
4488 else if (OSDynamicCast(OSString, temp)) {
4489 userClientClass = OSSymbol::withString((OSString *) temp);
4490 if (userClientClass)
4491 setProperty(kIOUserClientClassKey,
4492 (OSObject *) userClientClass);
4493 }
4494 }
4495
4496 // Didn't find one so lets just bomb out now without further ado.
4497 if (!userClientClass)
4498 return kIOReturnUnsupported;
4499
4500 // This reference is consumed by the IOServiceOpen call
4501 temp = OSMetaClass::allocClassWithName(userClientClass);
4502 if (!temp)
4503 return kIOReturnNoMemory;
4504
4505 if (OSDynamicCast(IOUserClient, temp))
4506 client = (IOUserClient *) temp;
4507 else {
4508 temp->release();
4509 return kIOReturnUnsupported;
4510 }
4511
4512 if ( !client->initWithTask(owningTask, securityID, type, properties) ) {
4513 client->release();
4514 return kIOReturnBadArgument;
4515 }
4516
4517 if ( !client->attach(this) ) {
4518 client->release();
4519 return kIOReturnUnsupported;
4520 }
4521
4522 if ( !client->start(this) ) {
4523 client->detach(this);
4524 client->release();
4525 return kIOReturnUnsupported;
4526 }
4527
4528 *handler = client;
4529 return kIOReturnSuccess;
4530 }
4531
4532 IOReturn IOService::newUserClient( task_t owningTask, void * securityID,
4533 UInt32 type, IOUserClient ** handler )
4534 {
4535 return( kIOReturnUnsupported );
4536 }
4537
4538 IOReturn IOService::requestProbe( IOOptionBits options )
4539 {
4540 return( kIOReturnUnsupported);
4541 }
4542
4543 /*
4544 * Convert an IOReturn to text. Subclasses which add additional
4545 * IOReturn's should override this method and call
4546 * super::stringFromReturn if the desired value is not found.
4547 */
4548
4549 const char * IOService::stringFromReturn( IOReturn rtn )
4550 {
4551 static const IONamedValue IOReturn_values[] = {
4552 {kIOReturnSuccess, "success" },
4553 {kIOReturnError, "general error" },
4554 {kIOReturnNoMemory, "memory allocation error" },
4555 {kIOReturnNoResources, "resource shortage" },
4556 {kIOReturnIPCError, "Mach IPC failure" },
4557 {kIOReturnNoDevice, "no such device" },
4558 {kIOReturnNotPrivileged, "privilege violation" },
4559 {kIOReturnBadArgument, "invalid argument" },
4560 {kIOReturnLockedRead, "device is read locked" },
4561 {kIOReturnLockedWrite, "device is write locked" },
4562 {kIOReturnExclusiveAccess, "device is exclusive access" },
4563 {kIOReturnBadMessageID, "bad IPC message ID" },
4564 {kIOReturnUnsupported, "unsupported function" },
4565 {kIOReturnVMError, "virtual memory error" },
4566 {kIOReturnInternalError, "internal driver error" },
4567 {kIOReturnIOError, "I/O error" },
4568 {kIOReturnCannotLock, "cannot acquire lock" },
4569 {kIOReturnNotOpen, "device is not open" },
4570 {kIOReturnNotReadable, "device is not readable" },
4571 {kIOReturnNotWritable, "device is not writeable" },
4572 {kIOReturnNotAligned, "alignment error" },
4573 {kIOReturnBadMedia, "media error" },
4574 {kIOReturnStillOpen, "device is still open" },
4575 {kIOReturnRLDError, "rld failure" },
4576 {kIOReturnDMAError, "DMA failure" },
4577 {kIOReturnBusy, "device is busy" },
4578 {kIOReturnTimeout, "I/O timeout" },
4579 {kIOReturnOffline, "device is offline" },
4580 {kIOReturnNotReady, "device is not ready" },
4581 {kIOReturnNotAttached, "device/channel is not attached" },
4582 {kIOReturnNoChannels, "no DMA channels available" },
4583 {kIOReturnNoSpace, "no space for data" },
4584 {kIOReturnPortExists, "device port already exists" },
4585 {kIOReturnCannotWire, "cannot wire physical memory" },
4586 {kIOReturnNoInterrupt, "no interrupt attached" },
4587 {kIOReturnNoFrames, "no DMA frames enqueued" },
4588 {kIOReturnMessageTooLarge, "message is too large" },
4589 {kIOReturnNotPermitted, "operation is not permitted" },
4590 {kIOReturnNoPower, "device is without power" },
4591 {kIOReturnNoMedia, "media is not present" },
4592 {kIOReturnUnformattedMedia, "media is not formatted" },
4593 {kIOReturnUnsupportedMode, "unsupported mode" },
4594 {kIOReturnUnderrun, "data underrun" },
4595 {kIOReturnOverrun, "data overrun" },
4596 {kIOReturnDeviceError, "device error" },
4597 {kIOReturnNoCompletion, "no completion routine" },
4598 {kIOReturnAborted, "operation was aborted" },
4599 {kIOReturnNoBandwidth, "bus bandwidth would be exceeded" },
4600 {kIOReturnNotResponding, "device is not responding" },
4601 {kIOReturnInvalid, "unanticipated driver error" },
4602 {0, NULL }
4603 };
4604
4605 return IOFindNameForValue(rtn, IOReturn_values);
4606 }
4607
4608 /*
4609 * Convert an IOReturn to an errno.
4610 */
4611 int IOService::errnoFromReturn( IOReturn rtn )
4612 {
4613 switch(rtn) {
4614 // (obvious match)
4615 case kIOReturnSuccess:
4616 return(0);
4617 case kIOReturnNoMemory:
4618 return(ENOMEM);
4619 case kIOReturnNoDevice:
4620 return(ENXIO);
4621 case kIOReturnVMError:
4622 return(EFAULT);
4623 case kIOReturnNotPermitted:
4624 return(EPERM);
4625 case kIOReturnNotPrivileged:
4626 return(EACCES);
4627 case kIOReturnIOError:
4628 return(EIO);
4629 case kIOReturnNotWritable:
4630 return(EROFS);
4631 case kIOReturnBadArgument:
4632 return(EINVAL);
4633 case kIOReturnUnsupported:
4634 return(ENOTSUP);
4635 case kIOReturnBusy:
4636 return(EBUSY);
4637 case kIOReturnNoPower:
4638 return(EPWROFF);
4639 case kIOReturnDeviceError:
4640 return(EDEVERR);
4641 case kIOReturnTimeout:
4642 return(ETIMEDOUT);
4643 case kIOReturnMessageTooLarge:
4644 return(EMSGSIZE);
4645 case kIOReturnNoSpace:
4646 return(ENOSPC);
4647 case kIOReturnCannotLock:
4648 return(ENOLCK);
4649
4650 // (best match)
4651 case kIOReturnBadMessageID:
4652 case kIOReturnNoCompletion:
4653 case kIOReturnNotAligned:
4654 return(EINVAL);
4655 case kIOReturnNotReady:
4656 return(EBUSY);
4657 case kIOReturnRLDError:
4658 return(EBADMACHO);
4659 case kIOReturnPortExists:
4660 case kIOReturnStillOpen:
4661 return(EEXIST);
4662 case kIOReturnExclusiveAccess:
4663 case kIOReturnLockedRead:
4664 case kIOReturnLockedWrite:
4665 case kIOReturnNotOpen:
4666 case kIOReturnNotReadable:
4667 return(EACCES);
4668 case kIOReturnCannotWire:
4669 case kIOReturnNoResources:
4670 return(ENOMEM);
4671 case kIOReturnAborted:
4672 case kIOReturnOffline:
4673 case kIOReturnNotResponding:
4674 return(EBUSY);
4675 case kIOReturnBadMedia:
4676 case kIOReturnNoMedia:
4677 case kIOReturnNotAttached:
4678 case kIOReturnUnformattedMedia:
4679 return(ENXIO); // (media error)
4680 case kIOReturnDMAError:
4681 case kIOReturnOverrun:
4682 case kIOReturnUnderrun:
4683 return(EIO); // (transfer error)
4684 case kIOReturnNoBandwidth:
4685 case kIOReturnNoChannels:
4686 case kIOReturnNoFrames:
4687 case kIOReturnNoInterrupt:
4688 return(EIO); // (hardware error)
4689 case kIOReturnError:
4690 case kIOReturnInternalError:
4691 case kIOReturnInvalid:
4692 return(EIO); // (generic error)
4693 case kIOReturnIPCError:
4694 return(EIO); // (ipc error)
4695 default:
4696 return(EIO); // (all other errors)
4697 }
4698 }
4699
4700 IOReturn IOService::message( UInt32 type, IOService * provider,
4701 void * argument )
4702 {
4703 /*
4704 * Generic entry point for calls from the provider. A return value of
4705 * kIOReturnSuccess indicates that the message was received, and where
4706 * applicable, that it was successful.
4707 */
4708
4709 return kIOReturnUnsupported;
4710 }
4711
4712 /*
4713 * Device memory
4714 */
4715
4716 IOItemCount IOService::getDeviceMemoryCount( void )
4717 {
4718 OSArray * array;
4719 IOItemCount count;
4720
4721 array = OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
4722 if( array)
4723 count = array->getCount();
4724 else
4725 count = 0;
4726
4727 return( count);
4728 }
4729
4730 IODeviceMemory * IOService::getDeviceMemoryWithIndex( unsigned int index )
4731 {
4732 OSArray * array;
4733 IODeviceMemory * range;
4734
4735 array = OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
4736 if( array)
4737 range = (IODeviceMemory *) array->getObject( index );
4738 else
4739 range = 0;
4740
4741 return( range);
4742 }
4743
4744 IOMemoryMap * IOService::mapDeviceMemoryWithIndex( unsigned int index,
4745 IOOptionBits options )
4746 {
4747 IODeviceMemory * range;
4748 IOMemoryMap * map;
4749
4750 range = getDeviceMemoryWithIndex( index );
4751 if( range)
4752 map = range->map( options );
4753 else
4754 map = 0;
4755
4756 return( map );
4757 }
4758
4759 OSArray * IOService::getDeviceMemory( void )
4760 {
4761 return( OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey)));
4762 }
4763
4764
4765 void IOService::setDeviceMemory( OSArray * array )
4766 {
4767 setProperty( gIODeviceMemoryKey, array);
4768 }
4769
4770 /*
4771 * For machines where the transfers on an I/O bus can stall because
4772 * the CPU is in an idle mode, These APIs allow a driver to specify
4773 * the maximum bus stall that they can handle. 0 indicates no limit.
4774 */
4775 void IOService::
4776 setCPUSnoopDelay(UInt32 __unused ns)
4777 {
4778 #if defined(__i386__) || defined(__x86_64__)
4779 ml_set_maxsnoop(ns);
4780 #endif /* defined(__i386__) || defined(__x86_64__) */
4781 }
4782
4783 UInt32 IOService::
4784 getCPUSnoopDelay()
4785 {
4786 #if defined(__i386__) || defined(__x86_64__)
4787 return ml_get_maxsnoop();
4788 #else
4789 return 0;
4790 #endif /* defined(__i386__) || defined(__x86_64__) */
4791 }
4792
4793 #if defined(__i386__) || defined(__x86_64__)
4794 static void
4795 requireMaxCpuDelay(IOService * service, UInt32 ns, UInt32 delayType)
4796 {
4797 static const UInt kNoReplace = -1U; // Must be an illegal index
4798 UInt replace = kNoReplace;
4799 bool setCpuDelay = false;
4800
4801 IORecursiveLockLock(sCpuDelayLock);
4802
4803 UInt count = sCpuDelayData->getLength() / sizeof(CpuDelayEntry);
4804 CpuDelayEntry *entries = (CpuDelayEntry *) sCpuDelayData->getBytesNoCopy();
4805 IOService * holder = NULL;
4806
4807 if (ns) {
4808 const CpuDelayEntry ne = {service, ns, delayType};
4809 holder = service;
4810 // Set maximum delay.
4811 for (UInt i = 0; i < count; i++) {
4812 IOService *thisService = entries[i].fService;
4813 bool sameType = (delayType == entries[i].fDelayType);
4814 if ((service == thisService) && sameType)
4815 replace = i;
4816 else if (!thisService) {
4817 if (kNoReplace == replace)
4818 replace = i;
4819 }
4820 else if (sameType) {
4821 const UInt32 thisMax = entries[i].fMaxDelay;
4822 if (thisMax < ns)
4823 {
4824 ns = thisMax;
4825 holder = thisService;
4826 }
4827 }
4828 }
4829
4830 setCpuDelay = true;
4831 if (kNoReplace == replace)
4832 sCpuDelayData->appendBytes(&ne, sizeof(ne));
4833 else
4834 entries[replace] = ne;
4835 }
4836 else {
4837 ns = -1U; // Set to max unsigned, i.e. no restriction
4838
4839 for (UInt i = 0; i < count; i++) {
4840 // Clear a maximum delay.
4841 IOService *thisService = entries[i].fService;
4842 if (thisService && (delayType == entries[i].fDelayType)) {
4843 UInt32 thisMax = entries[i].fMaxDelay;
4844 if (service == thisService)
4845 replace = i;
4846 else if (thisMax < ns) {
4847 ns = thisMax;
4848 holder = thisService;
4849 }
4850 }
4851 }
4852
4853 // Check if entry found
4854 if (kNoReplace != replace) {
4855 entries[replace].fService = 0; // Null the entry
4856 setCpuDelay = true;
4857 }
4858 }
4859
4860 if (setCpuDelay)
4861 {
4862 // Must be safe to call from locked context
4863 if (delayType == kCpuDelayBusStall)
4864 {
4865 ml_set_maxbusdelay(ns);
4866 }
4867 else if (delayType == kCpuDelayInterrupt)
4868 {
4869 ml_set_maxintdelay(ns);
4870 }
4871
4872 OSArray * handlers = sCpuLatencyHandlers[delayType];
4873 IOService * target;
4874 if (handlers) for (unsigned int idx = 0;
4875 (target = (IOService *) handlers->getObject(idx));
4876 idx++)
4877 {
4878 target->callPlatformFunction(sCPULatencyFunctionName[delayType], false,
4879 (void *) (uintptr_t) ns, holder,
4880 NULL, NULL);
4881 }
4882 }
4883
4884 IORecursiveLockUnlock(sCpuDelayLock);
4885 }
4886
4887 static IOReturn
4888 setLatencyHandler(UInt32 delayType, IOService * target, bool enable)
4889 {
4890 IOReturn result = kIOReturnNotFound;
4891 OSArray * array;
4892 unsigned int idx;
4893
4894 IORecursiveLockLock(sCpuDelayLock);
4895
4896 do
4897 {
4898 if (enable && !sCpuLatencyHandlers[delayType])
4899 sCpuLatencyHandlers[delayType] = OSArray::withCapacity(4);
4900 array = sCpuLatencyHandlers[delayType];
4901 if (!array)
4902 break;
4903 idx = array->getNextIndexOfObject(target, 0);
4904 if (!enable)
4905 {
4906 if (-1U != idx)
4907 {
4908 array->removeObject(idx);
4909 result = kIOReturnSuccess;
4910 }
4911 }
4912 else
4913 {
4914 if (-1U != idx) {
4915 result = kIOReturnExclusiveAccess;
4916 break;
4917 }
4918 array->setObject(target);
4919
4920 UInt count = sCpuDelayData->getLength() / sizeof(CpuDelayEntry);
4921 CpuDelayEntry *entries = (CpuDelayEntry *) sCpuDelayData->getBytesNoCopy();
4922 UInt32 ns = -1U; // Set to max unsigned, i.e. no restriction
4923 IOService * holder = NULL;
4924
4925 for (UInt i = 0; i < count; i++) {
4926 if (entries[i].fService
4927 && (delayType == entries[i].fDelayType)
4928 && (entries[i].fMaxDelay < ns)) {
4929 ns = entries[i].fMaxDelay;
4930 holder = entries[i].fService;
4931 }
4932 }
4933 target->callPlatformFunction(sCPULatencyFunctionName[delayType], false,
4934 (void *) (uintptr_t) ns, holder,
4935 NULL, NULL);
4936 result = kIOReturnSuccess;
4937 }
4938 }
4939 while (false);
4940
4941 IORecursiveLockUnlock(sCpuDelayLock);
4942
4943 return (result);
4944 }
4945
4946 #endif /* defined(__i386__) || defined(__x86_64__) */
4947
4948 void IOService::
4949 requireMaxBusStall(UInt32 __unused ns)
4950 {
4951 #if defined(__i386__) || defined(__x86_64__)
4952 requireMaxCpuDelay(this, ns, kCpuDelayBusStall);
4953 #endif
4954 }
4955
4956 void IOService::
4957 requireMaxInterruptDelay(uint32_t __unused ns)
4958 {
4959 #if defined(__i386__) || defined(__x86_64__)
4960 requireMaxCpuDelay(this, ns, kCpuDelayInterrupt);
4961 #endif
4962 }
4963
4964 /*
4965 * Device interrupts
4966 */
4967
4968 IOReturn IOService::resolveInterrupt(IOService *nub, int source)
4969 {
4970 IOInterruptController *interruptController;
4971 OSArray *array;
4972 OSData *data;
4973 OSSymbol *interruptControllerName;
4974 long numSources;
4975 IOInterruptSource *interruptSources;
4976
4977 // Get the parents list from the nub.
4978 array = OSDynamicCast(OSArray, nub->getProperty(gIOInterruptControllersKey));
4979 if (array == 0) return kIOReturnNoResources;
4980
4981 // Allocate space for the IOInterruptSources if needed... then return early.
4982 if (nub->_interruptSources == 0) {
4983 numSources = array->getCount();
4984 interruptSources = (IOInterruptSource *)IOMalloc(numSources * sizeof(IOInterruptSource));
4985 if (interruptSources == 0) return kIOReturnNoMemory;
4986
4987 bzero(interruptSources, numSources * sizeof(IOInterruptSource));
4988
4989 nub->_numInterruptSources = numSources;
4990 nub->_interruptSources = interruptSources;
4991 return kIOReturnSuccess;
4992 }
4993
4994 interruptControllerName = OSDynamicCast(OSSymbol,array->getObject(source));
4995 if (interruptControllerName == 0) return kIOReturnNoResources;
4996
4997 interruptController = getPlatform()->lookUpInterruptController(interruptControllerName);
4998 if (interruptController == 0) return kIOReturnNoResources;
4999
5000 // Get the interrupt numbers from the nub.
5001 array = OSDynamicCast(OSArray, nub->getProperty(gIOInterruptSpecifiersKey));
5002 if (array == 0) return kIOReturnNoResources;
5003 data = OSDynamicCast(OSData, array->getObject(source));
5004 if (data == 0) return kIOReturnNoResources;
5005
5006 // Set the interruptController and interruptSource in the nub's table.
5007 interruptSources = nub->_interruptSources;
5008 interruptSources[source].interruptController = interruptController;
5009 interruptSources[source].vectorData = data;
5010
5011 return kIOReturnSuccess;
5012 }
5013
5014 IOReturn IOService::lookupInterrupt(int source, bool resolve, IOInterruptController **interruptController)
5015 {
5016 IOReturn ret;
5017
5018 /* Make sure the _interruptSources are set */
5019 if (_interruptSources == 0) {
5020 ret = resolveInterrupt(this, source);
5021 if (ret != kIOReturnSuccess) return ret;
5022 }
5023
5024 /* Make sure the local source number is valid */
5025 if ((source < 0) || (source >= _numInterruptSources))
5026 return kIOReturnNoInterrupt;
5027
5028 /* Look up the contoller for the local source */
5029 *interruptController = _interruptSources[source].interruptController;
5030
5031 if (*interruptController == NULL) {
5032 if (!resolve) return kIOReturnNoInterrupt;
5033
5034 /* Try to reslove the interrupt */
5035 ret = resolveInterrupt(this, source);
5036 if (ret != kIOReturnSuccess) return ret;
5037
5038 *interruptController = _interruptSources[source].interruptController;
5039 }
5040
5041 return kIOReturnSuccess;
5042 }
5043
5044 IOReturn IOService::registerInterrupt(int source, OSObject *target,
5045 IOInterruptAction handler,
5046 void *refCon)
5047 {
5048 IOInterruptController *interruptController;
5049 IOReturn ret;
5050
5051 ret = lookupInterrupt(source, true, &interruptController);
5052 if (ret != kIOReturnSuccess) return ret;
5053
5054 /* Register the source */
5055 return interruptController->registerInterrupt(this, source, target,
5056 (IOInterruptHandler)handler,
5057 refCon);
5058 }
5059
5060 IOReturn IOService::unregisterInterrupt(int source)
5061 {
5062 IOInterruptController *interruptController;
5063 IOReturn ret;
5064
5065 ret = lookupInterrupt(source, false, &interruptController);
5066 if (ret != kIOReturnSuccess) return ret;
5067
5068 /* Unregister the source */
5069 return interruptController->unregisterInterrupt(this, source);
5070 }
5071
5072 IOReturn IOService::getInterruptType(int source, int *interruptType)
5073 {
5074 IOInterruptController *interruptController;
5075 IOReturn ret;
5076
5077 ret = lookupInterrupt(source, true, &interruptController);
5078 if (ret != kIOReturnSuccess) return ret;
5079
5080 /* Return the type */
5081 return interruptController->getInterruptType(this, source, interruptType);
5082 }
5083
5084 IOReturn IOService::enableInterrupt(int source)
5085 {
5086 IOInterruptController *interruptController;
5087 IOReturn ret;
5088
5089 ret = lookupInterrupt(source, false, &interruptController);
5090 if (ret != kIOReturnSuccess) return ret;
5091
5092 /* Enable the source */
5093 return interruptController->enableInterrupt(this, source);
5094 }
5095
5096 IOReturn IOService::disableInterrupt(int source)
5097 {
5098 IOInterruptController *interruptController;
5099 IOReturn ret;
5100
5101 ret = lookupInterrupt(source, false, &interruptController);
5102 if (ret != kIOReturnSuccess) return ret;
5103
5104 /* Disable the source */
5105 return interruptController->disableInterrupt(this, source);
5106 }
5107
5108 IOReturn IOService::causeInterrupt(int source)
5109 {
5110 IOInterruptController *interruptController;
5111 IOReturn ret;
5112
5113 ret = lookupInterrupt(source, false, &interruptController);
5114 if (ret != kIOReturnSuccess) return ret;
5115
5116 /* Cause an interrupt for the source */
5117 return interruptController->causeInterrupt(this, source);
5118 }
5119
5120 #if __LP64__
5121 OSMetaClassDefineReservedUnused(IOService, 0);
5122 OSMetaClassDefineReservedUnused(IOService, 1);
5123 OSMetaClassDefineReservedUnused(IOService, 2);
5124 OSMetaClassDefineReservedUnused(IOService, 3);
5125 OSMetaClassDefineReservedUnused(IOService, 4);
5126 OSMetaClassDefineReservedUnused(IOService, 5);
5127 #else
5128 OSMetaClassDefineReservedUsed(IOService, 0);
5129 OSMetaClassDefineReservedUsed(IOService, 1);
5130 OSMetaClassDefineReservedUsed(IOService, 2);
5131 OSMetaClassDefineReservedUsed(IOService, 3);
5132 OSMetaClassDefineReservedUsed(IOService, 4);
5133 OSMetaClassDefineReservedUsed(IOService, 5);
5134 #endif
5135 OSMetaClassDefineReservedUnused(IOService, 6);
5136 OSMetaClassDefineReservedUnused(IOService, 7);
5137 OSMetaClassDefineReservedUnused(IOService, 8);
5138 OSMetaClassDefineReservedUnused(IOService, 9);
5139 OSMetaClassDefineReservedUnused(IOService, 10);
5140 OSMetaClassDefineReservedUnused(IOService, 11);
5141 OSMetaClassDefineReservedUnused(IOService, 12);
5142 OSMetaClassDefineReservedUnused(IOService, 13);
5143 OSMetaClassDefineReservedUnused(IOService, 14);
5144 OSMetaClassDefineReservedUnused(IOService, 15);
5145 OSMetaClassDefineReservedUnused(IOService, 16);
5146 OSMetaClassDefineReservedUnused(IOService, 17);
5147 OSMetaClassDefineReservedUnused(IOService, 18);
5148 OSMetaClassDefineReservedUnused(IOService, 19);
5149 OSMetaClassDefineReservedUnused(IOService, 20);
5150 OSMetaClassDefineReservedUnused(IOService, 21);
5151 OSMetaClassDefineReservedUnused(IOService, 22);
5152 OSMetaClassDefineReservedUnused(IOService, 23);
5153 OSMetaClassDefineReservedUnused(IOService, 24);
5154 OSMetaClassDefineReservedUnused(IOService, 25);
5155 OSMetaClassDefineReservedUnused(IOService, 26);
5156 OSMetaClassDefineReservedUnused(IOService, 27);
5157 OSMetaClassDefineReservedUnused(IOService, 28);
5158 OSMetaClassDefineReservedUnused(IOService, 29);
5159 OSMetaClassDefineReservedUnused(IOService, 30);
5160 OSMetaClassDefineReservedUnused(IOService, 31);
5161 OSMetaClassDefineReservedUnused(IOService, 32);
5162 OSMetaClassDefineReservedUnused(IOService, 33);
5163 OSMetaClassDefineReservedUnused(IOService, 34);
5164 OSMetaClassDefineReservedUnused(IOService, 35);
5165 OSMetaClassDefineReservedUnused(IOService, 36);
5166 OSMetaClassDefineReservedUnused(IOService, 37);
5167 OSMetaClassDefineReservedUnused(IOService, 38);
5168 OSMetaClassDefineReservedUnused(IOService, 39);
5169 OSMetaClassDefineReservedUnused(IOService, 40);
5170 OSMetaClassDefineReservedUnused(IOService, 41);
5171 OSMetaClassDefineReservedUnused(IOService, 42);
5172 OSMetaClassDefineReservedUnused(IOService, 43);
5173 OSMetaClassDefineReservedUnused(IOService, 44);
5174 OSMetaClassDefineReservedUnused(IOService, 45);
5175 OSMetaClassDefineReservedUnused(IOService, 46);
5176 OSMetaClassDefineReservedUnused(IOService, 47);
5177
5178 #ifdef __ppc__
5179 OSMetaClassDefineReservedUnused(IOService, 48);
5180 OSMetaClassDefineReservedUnused(IOService, 49);
5181 OSMetaClassDefineReservedUnused(IOService, 50);
5182 OSMetaClassDefineReservedUnused(IOService, 51);
5183 OSMetaClassDefineReservedUnused(IOService, 52);
5184 OSMetaClassDefineReservedUnused(IOService, 53);
5185 OSMetaClassDefineReservedUnused(IOService, 54);
5186 OSMetaClassDefineReservedUnused(IOService, 55);
5187 OSMetaClassDefineReservedUnused(IOService, 56);
5188 OSMetaClassDefineReservedUnused(IOService, 57);
5189 OSMetaClassDefineReservedUnused(IOService, 58);
5190 OSMetaClassDefineReservedUnused(IOService, 59);
5191 OSMetaClassDefineReservedUnused(IOService, 60);
5192 OSMetaClassDefineReservedUnused(IOService, 61);
5193 OSMetaClassDefineReservedUnused(IOService, 62);
5194 OSMetaClassDefineReservedUnused(IOService, 63);
5195 #endif