--- /dev/null
+/*
+ * 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();
+ }
+}