2 * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
32 #include <IOKit/pwr_mgt/IOPMPagingPlexus.h>
33 #include <IOKit/pwr_mgt/IOPM.h>
34 #include <IOKit/pwr_mgt/RootDomain.h>
35 #include <IOKit/pwr_mgt/IOPowerConnection.h>
36 #include <IOKit/IOLib.h>
38 extern char rootdevice
[];
40 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
42 #define super IOService
43 OSDefineMetaClassAndStructors(IOPMPagingPlexus
,IOService
)
46 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
48 // stub driver has two power states, off and on
50 enum { kIOPlexusPowerStateCount
= 2 };
52 static const IOPMPowerState powerStates
[ kIOPlexusPowerStateCount
] = {
53 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
54 { 1, 0, IOPMPagingAvailable
, IOPMPowerOn
, 0, 0, 0, 0, 0, 0, 0, 0 }
57 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
60 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
62 bool IOPMPagingPlexus::start ( IOService
* provider
)
64 super::start(provider
);
66 ourLock
= IOLockAlloc();
69 PMinit(); // initialize superclass variables
71 registerPowerDriver(this,(IOPMPowerState
*)powerStates
,kIOPlexusPowerStateCount
);
77 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
80 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
82 IOReturn
IOPMPagingPlexus::setAggressiveness ( unsigned long type
, unsigned long )
87 IOService
* candidate
= 0;
88 IOService
* pagingProvider
;
90 if( type
!= kPMMinutesToSleep
)
94 if ( systemBooting
) {
95 systemBooting
= false;
96 IOLockUnlock(ourLock
);
97 dict
= IOBSDNameMatching(rootdevice
);
99 iter
= getMatchingServices(dict
);
101 while ( (next
= iter
->getNextObject()) ) {
102 if ( (candidate
= OSDynamicCast(IOService
,next
)) ) {
110 pagingProvider
= findProvider(candidate
);
111 if ( pagingProvider
) {
112 processSiblings(pagingProvider
);
113 pagingProvider
->addPowerChild(this);
114 getPMRootDomain()->removePowerChild(((IOPowerConnection
*)getParentEntry(gIOPowerPlane
)));
120 IOLockUnlock(ourLock
);
126 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
129 // Climb upward in the power tree from the node pointed to by the parameter.
130 // Return a pointer to the first power-managed entity encountered.
131 // This is the provider of paging services (the root device disk driver).
132 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
134 IOService
* IOPMPagingPlexus::findProvider ( IOService
* mediaObject
)
136 IORegistryEntry
* node
= mediaObject
;
138 if ( mediaObject
== NULL
) {
143 if ( node
->inPlane(gIOPowerPlane
) ) {
144 return (IOService
*)node
;
146 node
= node
->getParentEntry(gIOServicePlane
);
151 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
154 // Climb upward in the power tree from the node pointed to by the parameter.
155 // "Other" children of each ancestor (not the nodes in our upward path) are
156 // made children of this plexus, so they get paging services from here.
157 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
159 void IOPMPagingPlexus::processSiblings ( IOService
* aNode
)
161 OSIterator
* parentIterator
;
162 IORegistryEntry
* nextNub
;
163 IORegistryEntry
* nextParent
;
164 OSIterator
* siblingIterator
;
165 IORegistryEntry
* nextSibling
;
167 parentIterator
= aNode
->getParentIterator(gIOPowerPlane
); // iterate parents of this node
169 if ( parentIterator
) {
171 if ( ! (nextNub
= (IORegistryEntry
*)(parentIterator
->getNextObject())) ) {
172 parentIterator
->release();
175 if ( OSDynamicCast(IOPowerConnection
,nextNub
) ) {
176 nextParent
= nextNub
->getParentEntry(gIOPowerPlane
);
177 if ( nextParent
== getPMRootDomain() ) {
178 continue; // plexus already has root's children
180 if ( nextParent
== this ) {
181 parentIterator
->release();
182 removePowerChild((IOPowerConnection
*)nextNub
);
185 siblingIterator
= nextParent
->getChildIterator(gIOPowerPlane
);
186 // iterate children of this parent
187 if ( siblingIterator
) {
188 while ( (nextSibling
= (IORegistryEntry
*)(siblingIterator
->getNextObject())) ) {
189 if ( OSDynamicCast(IOPowerConnection
,nextSibling
) ) {
190 nextSibling
= nextSibling
->getChildEntry(gIOPowerPlane
);
191 if ( nextSibling
!= aNode
) { // non-ancestor of driver gets
192 addPowerChild((IOService
*)nextSibling
); // plexus as parent
196 siblingIterator
->release();
198 processSiblings((IOService
*)nextParent
); // do the same thing to this parent
205 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
208 // Now invent the need for paging services: alter our children's arrays
209 // to show that they need paging.
210 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
212 void IOPMPagingPlexus::processChildren ( void )
214 OSIterator
* childIterator
;
215 IOPowerConnection
* nextChildNub
;
216 IORegistryEntry
* nextChild
;
220 childIterator
= getChildIterator(gIOPowerPlane
);
222 if ( childIterator
) {
223 while ( (nextChild
= (IORegistryEntry
*)(childIterator
->getNextObject())) ) {
224 if ( (nextChildNub
= OSDynamicCast(IOPowerConnection
,nextChild
)) ) {
225 child
= (IOService
*)nextChild
->getChildEntry(gIOPowerPlane
);
226 if ( child
->pm_vars
->theControllingDriver
) {
227 for ( i
= 1; i
< child
->pm_vars
->theNumberOfPowerStates
; i
++ ) {
228 child
->pm_vars
->thePowerStates
[i
].inputPowerRequirement
|= IOPMPagingAvailable
;
231 if ( child
->pm_vars
->myCurrentState
) {
232 nextChildNub
->setDesiredDomainState(kIOPlexusPowerStateCount
-1);
236 childIterator
->release();