/* * 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 #include #include #include #include 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(); } }