]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IOPMPagingPlexus.cpp
xnu-201.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPMPagingPlexus.cpp
diff --git a/iokit/Kernel/IOPMPagingPlexus.cpp b/iokit/Kernel/IOPMPagingPlexus.cpp
new file mode 100644 (file)
index 0000000..187e0a1
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ * 
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1998 Apple Computer, Inc.  All rights reserved. 
+ *
+ * HISTORY
+ * 9 May 01 suurballe.
+ */
+#include <IOKit/pwr_mgt/IOPMPagingPlexus.h>
+#include <IOKit/pwr_mgt/IOPM.h>
+#include <IOKit/pwr_mgt/RootDomain.h>
+#include <IOKit/pwr_mgt/IOPowerConnection.h>
+#include <IOKit/IOLib.h>
+
+extern char rootdevice[];
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#define super IOService
+OSDefineMetaClassAndStructors(IOPMPagingPlexus,IOService)
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+// stub driver has two power states, off and on
+
+enum { kIOPlexusPowerStateCount = 2 };
+
+static const IOPMPowerState powerStates[ kIOPlexusPowerStateCount ] = {
+    { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+    { 1, 0, IOPMPagingAvailable, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 }
+};
+
+//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+// initialize
+//
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+bool IOPMPagingPlexus::start ( IOService * provider )
+{
+    super::start(provider);
+
+    ourLock = IOLockAlloc();
+    systemBooting = true;
+
+    PMinit();                           // initialize superclass variables
+    
+    registerPowerDriver(this,(IOPMPowerState *)powerStates,kIOPlexusPowerStateCount);
+    
+    return true;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+// setAggressiveness
+//
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+IOReturn IOPMPagingPlexus::setAggressiveness ( unsigned long type, unsigned long )
+{
+    OSDictionary *     dict;
+    OSIterator *       iter;
+    OSObject *         next;
+    IOService *                candidate = 0;
+    IOService *                pagingProvider;
+
+    if( type != kPMMinutesToSleep)
+        return IOPMNoErr;
+    
+    IOLockLock(ourLock);
+    if ( systemBooting ) {
+        systemBooting = false;
+        IOLockUnlock(ourLock);
+        dict = IOBSDNameMatching(rootdevice);
+        if ( dict ) {
+            iter = getMatchingServices(dict);
+            if ( iter ) {
+                while ( (next = iter->getNextObject()) ) {
+                    if ( (candidate = OSDynamicCast(IOService,next)) ) {
+                        break;
+                    }
+                }
+                iter->release();
+            }
+        }
+        if ( candidate ) {
+            pagingProvider = findProvider(candidate);
+            if ( pagingProvider ) {
+                processSiblings(pagingProvider);
+                pagingProvider->addPowerChild(this);
+                getPMRootDomain()->removePowerChild(((IOPowerConnection *)getParentEntry(gIOPowerPlane)));
+                processChildren();
+            }
+        }
+    }
+    else {
+        IOLockUnlock(ourLock);
+    }
+    return IOPMNoErr;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+// findProvider
+//
+// Climb upward in the power tree from the node pointed to by the parameter.
+// Return a pointer to the first power-managed entity encountered.
+// This is the provider of paging services (the root device disk driver).
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+IOService * IOPMPagingPlexus::findProvider ( IOService * mediaObject )
+{
+    IORegistryEntry * node = mediaObject;
+    
+    if ( mediaObject == NULL ) {
+        return NULL;
+    }
+    
+    while ( node ) {
+        if ( node->inPlane(gIOPowerPlane) ) {
+            return (IOService *)node;
+        }
+        node = node->getParentEntry(gIOServicePlane);
+    }
+    return NULL;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+// processSiblings
+//
+// Climb upward in the power tree from the node pointed to by the parameter.
+// "Other" children of each ancestor (not the nodes in our upward path) are
+// made children of this plexus, so they get paging services from here.
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void IOPMPagingPlexus::processSiblings ( IOService * aNode )
+{
+    OSIterator *       parentIterator;
+    IORegistryEntry *  nextNub;
+    IORegistryEntry *  nextParent;
+    OSIterator *       siblingIterator;
+    IORegistryEntry *  nextSibling;
+
+    parentIterator = aNode->getParentIterator(gIOPowerPlane);          // iterate parents of this node
+
+    if ( parentIterator ) {
+        while ( true ) {
+            if ( ! (nextNub = (IORegistryEntry *)(parentIterator->getNextObject())) ) {
+                parentIterator->release();
+                break;
+            }
+            if ( OSDynamicCast(IOPowerConnection,nextNub) ) {
+                nextParent = nextNub->getParentEntry(gIOPowerPlane);
+                if ( nextParent == getPMRootDomain() ) {
+                    continue;                          // plexus already has root's children
+                }
+                if ( nextParent == this ) {
+                    parentIterator->release();
+                    removePowerChild((IOPowerConnection *)nextNub);
+                    break;
+                }
+                siblingIterator = nextParent->getChildIterator(gIOPowerPlane);
+                                                                                // iterate children of this parent
+                if ( siblingIterator ) {
+                    while ( (nextSibling = (IORegistryEntry *)(siblingIterator->getNextObject())) ) {
+                        if ( OSDynamicCast(IOPowerConnection,nextSibling) ) {
+                            nextSibling = nextSibling->getChildEntry(gIOPowerPlane);
+                            if ( nextSibling != aNode ) {                      // non-ancestor of driver gets
+                                addPowerChild((IOService *)nextSibling);       // plexus as parent
+                            }
+                        }
+                    }
+                    siblingIterator->release();
+                }
+                processSiblings((IOService *)nextParent);                      // do the same thing to this parent
+            }
+       }
+    }
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+// processChildren
+//
+// Now invent the need for paging services:  alter our children's arrays
+// to show that they need paging.
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void IOPMPagingPlexus::processChildren ( void )
+{
+    OSIterator *       childIterator;
+    IOPowerConnection *        nextChildNub;
+    IORegistryEntry *  nextChild;
+    IOService *                child;
+    unsigned int       i;
+    
+    childIterator = getChildIterator(gIOPowerPlane);
+
+    if ( childIterator ) {
+        while ( (nextChild = (IORegistryEntry *)(childIterator->getNextObject())) ) {
+            if ( (nextChildNub = OSDynamicCast(IOPowerConnection,nextChild)) ) {
+                child = (IOService *)nextChild->getChildEntry(gIOPowerPlane);
+                if ( child->pm_vars->theControllingDriver ) {
+                    for ( i = 1; i < child->pm_vars->theNumberOfPowerStates; i++ ) {
+                        child->pm_vars->thePowerStates[i].inputPowerRequirement |= IOPMPagingAvailable;
+                    }
+                }
+                if ( child->pm_vars->myCurrentState ) {
+                    nextChildNub->setDesiredDomainState(kIOPlexusPowerStateCount-1);
+                }
+            }
+        }
+        childIterator->release();
+    }
+}