]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IOService.cpp
xnu-792.22.5.tar.gz
[apple/xnu.git] / iokit / Kernel / IOService.cpp
index 88f7def63e8c2160c694dbb30cf5d9c094698c79..b5991ba4e4dcde1777529279a6ad6634a215d69f 100644 (file)
@@ -1,14 +1,19 @@
 /*
  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ * 
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
  * 
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
@@ -18,7 +23,7 @@
  * Please see the License for the specific language governing rights and
  * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
  
 #include <IOKit/system.h>
@@ -100,6 +105,8 @@ const OSSymbol *            gIOCommandPoolSizeKey;
 const OSSymbol *               gIOConsoleUsersKey;
 const OSSymbol *               gIOConsoleSessionUIDKey;
 const OSSymbol *               gIOConsoleUsersSeedKey;
+const OSSymbol *        gIOConsoleSessionOnConsoleKey;
+const OSSymbol *        gIOConsoleSessionSecureInputPIDKey;
 
 static int                     gIOResourceGenerationCount;
 
@@ -192,6 +199,22 @@ bool IOService::isInactive( void ) const
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
+#if __i386__
+
+// Only used by the intel implementation of
+//     IOService::requireMaxBusStall(UInt32 __unused ns)
+struct BusStallEntry
+{
+    const IOService *fService;
+    UInt32 fMaxDelay;
+};
+
+static OSData *sBusStall     = OSData::withCapacity(8 * sizeof(BusStallEntry));
+static IOLock *sBusStallLock = IOLockAlloc();
+#endif /* __i386__ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
 void IOService::initialize( void )
 {
     kern_return_t      err;
@@ -249,6 +272,8 @@ void IOService::initialize( void )
     gIOConsoleUsersKey         = OSSymbol::withCStringNoCopy( kIOConsoleUsersKey);
     gIOConsoleSessionUIDKey    = OSSymbol::withCStringNoCopy( kIOConsoleSessionUIDKey);
     gIOConsoleUsersSeedKey     = OSSymbol::withCStringNoCopy( kIOConsoleUsersSeedKey);
+    gIOConsoleSessionOnConsoleKey = OSSymbol::withCStringNoCopy( kIOConsoleSessionOnConsoleKey);
+    gIOConsoleSessionSecureInputPIDKey = OSSymbol::withCStringNoCopy( kIOConsoleSessionSecureInputPIDKey);
     gIOConsoleUsersSeedValue   = OSData::withBytesNoCopy(&gIOConsoleUsersSeed, sizeof(gIOConsoleUsersSeed));
 
     gNotificationLock          = IORecursiveLockAlloc();
@@ -261,6 +286,7 @@ void IOService::initialize( void )
         && gIOPublishNotification && gIOMatchedNotification
         && gIOTerminatedNotification && gIOServiceKey
        && gIOConsoleUsersKey && gIOConsoleSessionUIDKey
+    && gIOConsoleSessionOnConsoleKey && gIOConsoleSessionSecureInputPIDKey
        && gIOConsoleUsersSeedKey && gIOConsoleUsersSeedValue);
 
     gJobsLock  = IOLockAlloc();
@@ -331,6 +357,7 @@ void IOService::stop( IOService * provider )
 
 void IOService::free( void )
 {
+    requireMaxBusStall(0);
     if( getPropertyTable())
         unregisterAllInterest();
     PMfree();
@@ -485,6 +512,8 @@ void IOService::startMatching( IOOptionBits options )
        || ((provider = getProvider())
                && (provider->__state[1] & kIOServiceSynchronousState));
 
+       if ( options & kIOServiceAsynchronous )
+               sync = false;
 
     needConfig =  (0 == (__state[1] & (kIOServiceNeedConfigState | kIOServiceConfigState)))
               && (0 == (__state[0] & kIOServiceInactiveState));
@@ -1279,18 +1308,18 @@ IOReturn IOService::messageClient( UInt32 type, OSObject * client,
     return( ret );
 }
 
-void IOService::applyToInterested( const OSSymbol * typeOfInterest,
-                                   OSObjectApplierFunction applier,
-                                   void * context )
+static void
+applyToInterestNotifiers(const IORegistryEntry *target,
+                        const OSSymbol * typeOfInterest,
+                        OSObjectApplierFunction applier,
+                        void * context )
 {
     OSArray *          copyArray = 0;
 
-    applyToClients( (IOServiceApplierFunction) applier, context );
-
     LOCKREADNOTIFY();
 
     IOCommand *notifyList =
-       OSDynamicCast( IOCommand, getProperty( typeOfInterest ));
+       OSDynamicCast( IOCommand, target->getProperty( typeOfInterest ));
 
     if( notifyList) {
         copyArray = OSArray::withCapacity(1);
@@ -1315,6 +1344,14 @@ void IOService::applyToInterested( const OSSymbol * typeOfInterest,
     }
 }
 
+void IOService::applyToInterested( const OSSymbol * typeOfInterest,
+                                   OSObjectApplierFunction applier,
+                                   void * context )
+{
+    applyToClients( (IOServiceApplierFunction) applier, context );
+    applyToInterestNotifiers(this, typeOfInterest, applier, context);
+}
+
 struct MessageClientsContext {
     IOService *        service;
     UInt32     type;
@@ -2882,21 +2919,15 @@ UInt32 IOService::_adjustBusy( SInt32 delta )
             next->unlockForArbitration();
 
         if( (wasQuiet || nowQuiet) ) {
-            OSArray *          array;
-            unsigned int       index;
-            OSObject *         interested;
-
-            array = OSDynamicCast( OSArray, next->getProperty( gIOBusyInterest ));
-            if( array) {
-                LOCKREADNOTIFY();
-                for( index = 0;
-                     (interested = array->getObject( index ));
-                     index++) {
-                    next->messageClient(kIOMessageServiceBusyStateChange,
-                                     interested, (void *) wasQuiet /* busy now */);
-                }
-                UNLOCKNOTIFY();
-            }
+           MessageClientsContext context;
+
+           context.service  = next;
+           context.type     = kIOMessageServiceBusyStateChange;
+           context.argument = (void *) wasQuiet;       // busy now
+           context.argSize  = 0;
+
+           applyToInterestNotifiers( next, gIOBusyInterest, 
+                                    &messageClientsApplier, &context );
 
             if( nowQuiet && (next == gIOServiceRoot))
                 OSMetaClass::considerUnloads();
@@ -4011,6 +4042,9 @@ IOReturn IOService::newUserClient( task_t owningTask, void * securityID,
     IOUserClient *client;
     OSObject *temp;
 
+    if (kIOReturnSuccess == newUserClient( owningTask, securityID, type, handler ))
+       return kIOReturnSuccess;
+
     // First try my own properties for a user client class name
     temp = getProperty(gIOUserClientClassKey);
     if (temp) {
@@ -4028,6 +4062,7 @@ IOReturn IOService::newUserClient( task_t owningTask, void * securityID,
     if (!userClientClass)
         return kIOReturnUnsupported;
 
+    // This reference is consumed by the IOServiceOpen call
     temp = OSMetaClass::allocClassWithName(userClientClass);
     if (!temp)
         return kIOReturnNoMemory;
@@ -4062,7 +4097,7 @@ IOReturn IOService::newUserClient( task_t owningTask, void * securityID,
 IOReturn IOService::newUserClient( task_t owningTask, void * securityID,
                                     UInt32 type, IOUserClient ** handler )
 {
-    return( newUserClient( owningTask, securityID, type, 0, handler ));
+    return( kIOReturnUnsupported );
 }
 
 IOReturn IOService::requestProbe( IOOptionBits options )
@@ -4297,6 +4332,92 @@ void IOService::setDeviceMemory( OSArray * array )
     setProperty( gIODeviceMemoryKey, array);
 }
 
+/*
+ * For machines where the transfers on an I/O bus can stall because
+ * the CPU is in an idle mode, These APIs allow a driver to specify
+ * the maximum bus stall that they can handle.  0 indicates no limit.
+ */
+void IOService::
+setCPUSnoopDelay(UInt32 __unused ns)
+{
+#if __i386__
+    ml_set_maxsnoop(ns); 
+#endif /* __i386__ */
+}
+
+UInt32 IOService::
+getCPUSnoopDelay()
+{
+#if __i386__
+    return ml_get_maxsnoop(); 
+#else
+    return 0;
+#endif /* __i386__ */
+}
+
+void IOService::
+requireMaxBusStall(UInt32 __unused ns)
+{
+#if __i386__
+    static const UInt kNoReplace = -1U;        // Must be an illegal index
+    UInt replace = kNoReplace;
+
+    IOLockLock(sBusStallLock);
+
+    UInt count = sBusStall->getLength() / sizeof(BusStallEntry);
+    BusStallEntry *entries = (BusStallEntry *) sBusStall->getBytesNoCopy();
+
+    if (ns) {
+       const BusStallEntry ne = {this, ns};
+
+       // Set Maximum bus delay.
+       for (UInt i = 0; i < count; i++) {
+           const IOService *thisService = entries[i].fService;
+           if (this == thisService)
+               replace = i;
+           else if (!thisService) {
+               if (kNoReplace == replace)
+                   replace = i;
+           }
+           else {
+               const UInt32 thisMax = entries[i].fMaxDelay;
+               if (thisMax < ns)
+                   ns = thisMax;
+           }
+       }
+
+       // Must be safe to call from locked context
+       ml_set_maxbusdelay(ns);
+
+       if (kNoReplace == replace)
+           sBusStall->appendBytes(&ne, sizeof(ne));
+       else
+           entries[replace] = ne;
+    }
+    else {
+       ns = -1U;       // Set to max unsigned, i.e. no restriction
+
+       for (UInt i = 0; i < count; i++) {
+           // Clear a maximum bus delay.
+           const IOService *thisService = entries[i].fService;
+           UInt32 thisMax = entries[i].fMaxDelay;
+           if (this == thisService)
+               replace = i;
+           else if (thisService && thisMax < ns)
+               ns = thisMax;
+       }
+
+       // Check if entry found
+       if (kNoReplace != replace) {
+           entries[replace].fService = 0;      // Null the entry
+           ml_set_maxbusdelay(ns);
+       }
+    }
+
+    IOLockUnlock(sBusStallLock);
+#endif /* __i386__ */
+}
+
 /*
  * Device interrupts
  */
@@ -4502,6 +4623,8 @@ OSMetaClassDefineReservedUnused(IOService, 44);
 OSMetaClassDefineReservedUnused(IOService, 45);
 OSMetaClassDefineReservedUnused(IOService, 46);
 OSMetaClassDefineReservedUnused(IOService, 47);
+
+#ifdef __ppc__
 OSMetaClassDefineReservedUnused(IOService, 48);
 OSMetaClassDefineReservedUnused(IOService, 49);
 OSMetaClassDefineReservedUnused(IOService, 50);
@@ -4518,3 +4641,4 @@ OSMetaClassDefineReservedUnused(IOService, 60);
 OSMetaClassDefineReservedUnused(IOService, 61);
 OSMetaClassDefineReservedUnused(IOService, 62);
 OSMetaClassDefineReservedUnused(IOService, 63);
+#endif