2 * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
29 #include <IOKit/pwr_mgt/IOPMPagingPlexus.h>
30 #include <IOKit/pwr_mgt/IOPM.h>
31 #include <IOKit/pwr_mgt/RootDomain.h>
32 #include <IOKit/pwr_mgt/IOPowerConnection.h>
33 #include <IOKit/IOLib.h>
35 extern char rootdevice
[];
37 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
39 #define super IOService
40 OSDefineMetaClassAndStructors(IOPMPagingPlexus
,IOService
)
43 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
45 // stub driver has two power states, off and on
47 enum { kIOPlexusPowerStateCount
= 2 };
49 static const IOPMPowerState powerStates
[ kIOPlexusPowerStateCount
] = {
50 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
51 { 1, 0, IOPMPagingAvailable
, IOPMPowerOn
, 0, 0, 0, 0, 0, 0, 0, 0 }
54 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
57 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
59 bool IOPMPagingPlexus::start ( IOService
* provider
)
61 super::start(provider
);
63 ourLock
= IOLockAlloc();
66 PMinit(); // initialize superclass variables
68 registerPowerDriver(this,(IOPMPowerState
*)powerStates
,kIOPlexusPowerStateCount
);
74 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
77 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
79 IOReturn
IOPMPagingPlexus::setAggressiveness ( unsigned long type
, unsigned long )
84 IOService
* candidate
= 0;
85 IOService
* pagingProvider
;
87 if( type
!= kPMMinutesToSleep
)
91 if ( systemBooting
) {
92 systemBooting
= false;
93 IOLockUnlock(ourLock
);
94 dict
= IOBSDNameMatching(rootdevice
);
96 iter
= getMatchingServices(dict
);
98 while ( (next
= iter
->getNextObject()) ) {
99 if ( (candidate
= OSDynamicCast(IOService
,next
)) ) {
107 pagingProvider
= findProvider(candidate
);
108 if ( pagingProvider
) {
109 processSiblings(pagingProvider
);
110 pagingProvider
->addPowerChild(this);
111 getPMRootDomain()->removePowerChild(((IOPowerConnection
*)getParentEntry(gIOPowerPlane
)));
117 IOLockUnlock(ourLock
);
123 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
126 // Climb upward in the power tree from the node pointed to by the parameter.
127 // Return a pointer to the first power-managed entity encountered.
128 // This is the provider of paging services (the root device disk driver).
129 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
131 IOService
* IOPMPagingPlexus::findProvider ( IOService
* mediaObject
)
133 IORegistryEntry
* node
= mediaObject
;
135 if ( mediaObject
== NULL
) {
140 if ( node
->inPlane(gIOPowerPlane
) ) {
141 return (IOService
*)node
;
143 node
= node
->getParentEntry(gIOServicePlane
);
148 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
151 // Climb upward in the power tree from the node pointed to by the parameter.
152 // "Other" children of each ancestor (not the nodes in our upward path) are
153 // made children of this plexus, so they get paging services from here.
154 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
156 void IOPMPagingPlexus::processSiblings ( IOService
* aNode
)
158 OSIterator
* parentIterator
;
159 IORegistryEntry
* nextNub
;
160 IORegistryEntry
* nextParent
;
161 OSIterator
* siblingIterator
;
162 IORegistryEntry
* nextSibling
;
164 parentIterator
= aNode
->getParentIterator(gIOPowerPlane
); // iterate parents of this node
166 if ( parentIterator
) {
168 if ( ! (nextNub
= (IORegistryEntry
*)(parentIterator
->getNextObject())) ) {
169 parentIterator
->release();
172 if ( OSDynamicCast(IOPowerConnection
,nextNub
) ) {
173 nextParent
= nextNub
->getParentEntry(gIOPowerPlane
);
174 if ( nextParent
== getPMRootDomain() ) {
175 continue; // plexus already has root's children
177 if ( nextParent
== this ) {
178 parentIterator
->release();
179 removePowerChild((IOPowerConnection
*)nextNub
);
182 siblingIterator
= nextParent
->getChildIterator(gIOPowerPlane
);
183 // iterate children of this parent
184 if ( siblingIterator
) {
185 while ( (nextSibling
= (IORegistryEntry
*)(siblingIterator
->getNextObject())) ) {
186 if ( OSDynamicCast(IOPowerConnection
,nextSibling
) ) {
187 nextSibling
= nextSibling
->getChildEntry(gIOPowerPlane
);
188 if ( nextSibling
!= aNode
) { // non-ancestor of driver gets
189 addPowerChild((IOService
*)nextSibling
); // plexus as parent
193 siblingIterator
->release();
195 processSiblings((IOService
*)nextParent
); // do the same thing to this parent
202 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
205 // Now invent the need for paging services: alter our children's arrays
206 // to show that they need paging.
207 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
209 void IOPMPagingPlexus::processChildren ( void )
211 OSIterator
* childIterator
;
212 IOPowerConnection
* nextChildNub
;
213 IORegistryEntry
* nextChild
;
217 childIterator
= getChildIterator(gIOPowerPlane
);
219 if ( childIterator
) {
220 while ( (nextChild
= (IORegistryEntry
*)(childIterator
->getNextObject())) ) {
221 if ( (nextChildNub
= OSDynamicCast(IOPowerConnection
,nextChild
)) ) {
222 child
= (IOService
*)nextChild
->getChildEntry(gIOPowerPlane
);
223 if ( child
->pm_vars
->theControllingDriver
) {
224 for ( i
= 1; i
< child
->pm_vars
->theNumberOfPowerStates
; i
++ ) {
225 child
->pm_vars
->thePowerStates
[i
].inputPowerRequirement
|= IOPMPagingAvailable
;
228 if ( child
->pm_vars
->myCurrentState
) {
229 nextChildNub
->setDesiredDomainState(kIOPlexusPowerStateCount
-1);
233 childIterator
->release();