IOPMPagingPlexus.cpp [plain text]
#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)
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 }
};
bool IOPMPagingPlexus::start ( IOService * provider )
{
super::start(provider);
ourLock = IOLockAlloc();
systemBooting = true;
PMinit();
registerPowerDriver(this,(IOPMPowerState *)powerStates,kIOPlexusPowerStateCount);
return true;
}
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;
}
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;
}
void IOPMPagingPlexus::processSiblings ( IOService * aNode )
{
OSIterator * parentIterator;
IORegistryEntry * nextNub;
IORegistryEntry * nextParent;
OSIterator * siblingIterator;
IORegistryEntry * nextSibling;
parentIterator = aNode->getParentIterator(gIOPowerPlane);
if ( parentIterator ) {
while ( true ) {
if ( ! (nextNub = (IORegistryEntry *)(parentIterator->getNextObject())) ) {
parentIterator->release();
break;
}
if ( OSDynamicCast(IOPowerConnection,nextNub) ) {
nextParent = nextNub->getParentEntry(gIOPowerPlane);
if ( nextParent == getPMRootDomain() ) {
continue; }
if ( nextParent == this ) {
parentIterator->release();
removePowerChild((IOPowerConnection *)nextNub);
break;
}
siblingIterator = nextParent->getChildIterator(gIOPowerPlane);
if ( siblingIterator ) {
while ( (nextSibling = (IORegistryEntry *)(siblingIterator->getNextObject())) ) {
if ( OSDynamicCast(IOPowerConnection,nextSibling) ) {
nextSibling = nextSibling->getChildEntry(gIOPowerPlane);
if ( nextSibling != aNode ) { addPowerChild((IOService *)nextSibling); }
}
}
siblingIterator->release();
}
processSiblings((IOService *)nextParent); }
}
}
}
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();
}
}