]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOPMPagingPlexus.cpp
xnu-517.3.15.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPMPagingPlexus.cpp
CommitLineData
0b4e3aa0
A
1/*
2 * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
0b4e3aa0 7 *
43866e37
A
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
0b4e3aa0
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
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.
0b4e3aa0
A
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
38extern char rootdevice[];
39
40/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
41
42#define super IOService
43OSDefineMetaClassAndStructors(IOPMPagingPlexus,IOService)
44
45
46/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
47
48// stub driver has two power states, off and on
49
50enum { kIOPlexusPowerStateCount = 2 };
51
52static 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
62bool 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
82IOReturn 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
134IOService * 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
159void 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
212void 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}