]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOPMPagingPlexus.cpp
xnu-517.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPMPagingPlexus.cpp
1 /*
2 * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
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
13 * file.
14 *
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.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
27 *
28 * HISTORY
29 * 9 May 01 suurballe.
30 */
31
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>
37
38 extern char rootdevice[];
39
40 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
41
42 #define super IOService
43 OSDefineMetaClassAndStructors(IOPMPagingPlexus,IOService)
44
45
46 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
47
48 // stub driver has two power states, off and on
49
50 enum { kIOPlexusPowerStateCount = 2 };
51
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 }
55 };
56
57 //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
58 // initialize
59 //
60 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
61
62 bool IOPMPagingPlexus::start ( IOService * provider )
63 {
64 super::start(provider);
65
66 ourLock = IOLockAlloc();
67 systemBooting = true;
68
69 PMinit(); // initialize superclass variables
70
71 registerPowerDriver(this,(IOPMPowerState *)powerStates,kIOPlexusPowerStateCount);
72
73 return true;
74 }
75
76
77 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
78 // setAggressiveness
79 //
80 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
81
82 IOReturn IOPMPagingPlexus::setAggressiveness ( unsigned long type, unsigned long )
83 {
84 OSDictionary * dict;
85 OSIterator * iter;
86 OSObject * next;
87 IOService * candidate = 0;
88 IOService * pagingProvider;
89
90 if( type != kPMMinutesToSleep)
91 return IOPMNoErr;
92
93 IOLockLock(ourLock);
94 if ( systemBooting ) {
95 systemBooting = false;
96 IOLockUnlock(ourLock);
97 dict = IOBSDNameMatching(rootdevice);
98 if ( dict ) {
99 iter = getMatchingServices(dict);
100 if ( iter ) {
101 while ( (next = iter->getNextObject()) ) {
102 if ( (candidate = OSDynamicCast(IOService,next)) ) {
103 break;
104 }
105 }
106 iter->release();
107 }
108 }
109 if ( candidate ) {
110 pagingProvider = findProvider(candidate);
111 if ( pagingProvider ) {
112 processSiblings(pagingProvider);
113 pagingProvider->addPowerChild(this);
114 getPMRootDomain()->removePowerChild(((IOPowerConnection *)getParentEntry(gIOPowerPlane)));
115 processChildren();
116 }
117 }
118 }
119 else {
120 IOLockUnlock(ourLock);
121 }
122 return IOPMNoErr;
123 }
124
125
126 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
127 // findProvider
128 //
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 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
133
134 IOService * IOPMPagingPlexus::findProvider ( IOService * mediaObject )
135 {
136 IORegistryEntry * node = mediaObject;
137
138 if ( mediaObject == NULL ) {
139 return NULL;
140 }
141
142 while ( node ) {
143 if ( node->inPlane(gIOPowerPlane) ) {
144 return (IOService *)node;
145 }
146 node = node->getParentEntry(gIOServicePlane);
147 }
148 return NULL;
149 }
150
151 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
152 // processSiblings
153 //
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 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
158
159 void IOPMPagingPlexus::processSiblings ( IOService * aNode )
160 {
161 OSIterator * parentIterator;
162 IORegistryEntry * nextNub;
163 IORegistryEntry * nextParent;
164 OSIterator * siblingIterator;
165 IORegistryEntry * nextSibling;
166
167 parentIterator = aNode->getParentIterator(gIOPowerPlane); // iterate parents of this node
168
169 if ( parentIterator ) {
170 while ( true ) {
171 if ( ! (nextNub = (IORegistryEntry *)(parentIterator->getNextObject())) ) {
172 parentIterator->release();
173 break;
174 }
175 if ( OSDynamicCast(IOPowerConnection,nextNub) ) {
176 nextParent = nextNub->getParentEntry(gIOPowerPlane);
177 if ( nextParent == getPMRootDomain() ) {
178 continue; // plexus already has root's children
179 }
180 if ( nextParent == this ) {
181 parentIterator->release();
182 removePowerChild((IOPowerConnection *)nextNub);
183 break;
184 }
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
193 }
194 }
195 }
196 siblingIterator->release();
197 }
198 processSiblings((IOService *)nextParent); // do the same thing to this parent
199 }
200 }
201 }
202 }
203
204
205 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
206 // processChildren
207 //
208 // Now invent the need for paging services: alter our children's arrays
209 // to show that they need paging.
210 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
211
212 void IOPMPagingPlexus::processChildren ( void )
213 {
214 OSIterator * childIterator;
215 IOPowerConnection * nextChildNub;
216 IORegistryEntry * nextChild;
217 IOService * child;
218 unsigned int i;
219
220 childIterator = getChildIterator(gIOPowerPlane);
221
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;
229 }
230 }
231 if ( child->pm_vars->myCurrentState ) {
232 nextChildNub->setDesiredDomainState(kIOPlexusPowerStateCount-1);
233 }
234 }
235 }
236 childIterator->release();
237 }
238 }