1 |
27 |
unneback |
<!-- Copyright (C) 2001 Red Hat, Inc. -->
|
2 |
|
|
<!-- This material may be distributed only subject to the terms -->
|
3 |
|
|
<!-- and conditions set forth in the Open Publication License, v1.0 -->
|
4 |
|
|
<!-- or later (the latest version is presently available at -->
|
5 |
|
|
<!-- http://www.opencontent.org/openpub/). -->
|
6 |
|
|
<!-- Distribution of substantively modified versions of this -->
|
7 |
|
|
<!-- document is prohibited without the explicit permission of the -->
|
8 |
|
|
<!-- copyright holder. -->
|
9 |
|
|
<!-- Distribution of the work or derivative of the work in any -->
|
10 |
|
|
<!-- standard (paper) book form is prohibited unless prior -->
|
11 |
|
|
<!-- permission is obtained from the copyright holder. -->
|
12 |
|
|
<HTML
|
13 |
|
|
><HEAD
|
14 |
|
|
><TITLE
|
15 |
|
|
>Implementing a Power Controller</TITLE
|
16 |
|
|
><meta name="MSSmartTagsPreventParsing" content="TRUE">
|
17 |
|
|
<META
|
18 |
|
|
NAME="GENERATOR"
|
19 |
|
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.64
|
20 |
|
|
"><LINK
|
21 |
|
|
REL="HOME"
|
22 |
|
|
TITLE="eCos Power Management Support"
|
23 |
|
|
HREF="services-power.html"><LINK
|
24 |
|
|
REL="PREVIOUS"
|
25 |
|
|
TITLE="Attached and Detached Controllers"
|
26 |
|
|
HREF="power-attached.html"></HEAD
|
27 |
|
|
><BODY
|
28 |
|
|
CLASS="REFENTRY"
|
29 |
|
|
BGCOLOR="#FFFFFF"
|
30 |
|
|
TEXT="#000000"
|
31 |
|
|
LINK="#0000FF"
|
32 |
|
|
VLINK="#840084"
|
33 |
|
|
ALINK="#0000FF"
|
34 |
|
|
><DIV
|
35 |
|
|
CLASS="NAVHEADER"
|
36 |
|
|
><TABLE
|
37 |
|
|
WIDTH="100%"
|
38 |
|
|
BORDER="0"
|
39 |
|
|
CELLPADDING="0"
|
40 |
|
|
CELLSPACING="0"
|
41 |
|
|
><TR
|
42 |
|
|
><TH
|
43 |
|
|
COLSPAN="3"
|
44 |
|
|
ALIGN="center"
|
45 |
|
|
>eCos Power Management Support</TH
|
46 |
|
|
></TR
|
47 |
|
|
><TR
|
48 |
|
|
><TD
|
49 |
|
|
WIDTH="10%"
|
50 |
|
|
ALIGN="left"
|
51 |
|
|
VALIGN="bottom"
|
52 |
|
|
><A
|
53 |
|
|
HREF="power-attached.html"
|
54 |
|
|
>Prev</A
|
55 |
|
|
></TD
|
56 |
|
|
><TD
|
57 |
|
|
WIDTH="80%"
|
58 |
|
|
ALIGN="center"
|
59 |
|
|
VALIGN="bottom"
|
60 |
|
|
></TD
|
61 |
|
|
><TD
|
62 |
|
|
WIDTH="10%"
|
63 |
|
|
ALIGN="right"
|
64 |
|
|
VALIGN="bottom"
|
65 |
|
|
> </TD
|
66 |
|
|
></TR
|
67 |
|
|
></TABLE
|
68 |
|
|
><HR
|
69 |
|
|
ALIGN="LEFT"
|
70 |
|
|
WIDTH="100%"></DIV
|
71 |
|
|
><H1
|
72 |
|
|
><A
|
73 |
|
|
NAME="POWER-CONTROLLER"
|
74 |
|
|
>Implementing a Power Controller</A
|
75 |
|
|
></H1
|
76 |
|
|
><DIV
|
77 |
|
|
CLASS="REFNAMEDIV"
|
78 |
|
|
><A
|
79 |
|
|
NAME="AEN355"
|
80 |
|
|
></A
|
81 |
|
|
><H2
|
82 |
|
|
>Name</H2
|
83 |
|
|
>Implementing a Power Controller -- adding power management support to device drivers and
|
84 |
|
|
other packages</DIV
|
85 |
|
|
><DIV
|
86 |
|
|
CLASS="REFSECT1"
|
87 |
|
|
><A
|
88 |
|
|
NAME="AEN358"
|
89 |
|
|
></A
|
90 |
|
|
><H2
|
91 |
|
|
>Implementing a Power Controller</H2
|
92 |
|
|
><P
|
93 |
|
|
>A system will have some number of power controllers. Usually there
|
94 |
|
|
will be one power controller for the cpu,
|
95 |
|
|
<TT
|
96 |
|
|
CLASS="VARNAME"
|
97 |
|
|
>power_controller_cpu</TT
|
98 |
|
|
>, typically provided by one of
|
99 |
|
|
the HAL packages and responsible for managing the processor itself and
|
100 |
|
|
associated critical components such as memory. Some or all of the
|
101 |
|
|
device drivers will provide power controllers, allowing the power
|
102 |
|
|
consumption of the associated devices to be controlled. There may be
|
103 |
|
|
some arbitrary number of other controllers present in the system. The
|
104 |
|
|
power management package does not impose any restrictions on the
|
105 |
|
|
number or nature of the power controllers in the system, other than
|
106 |
|
|
insisting that at most one <TT
|
107 |
|
|
CLASS="VARNAME"
|
108 |
|
|
>power_controller_cpu</TT
|
109 |
|
|
> be
|
110 |
|
|
provided.</P
|
111 |
|
|
><P
|
112 |
|
|
>Each power controller involves a single data structure of type
|
113 |
|
|
<SPAN
|
114 |
|
|
CLASS="STRUCTNAME"
|
115 |
|
|
>PowerController</SPAN
|
116 |
|
|
>, defined in the header file
|
117 |
|
|
<TT
|
118 |
|
|
CLASS="FILENAME"
|
119 |
|
|
>cyg/power/power.h</TT
|
120 |
|
|
>. These data
|
121 |
|
|
structures should all be placed in the table
|
122 |
|
|
<TT
|
123 |
|
|
CLASS="LITERAL"
|
124 |
|
|
>__POWER__</TT
|
125 |
|
|
>, so that the power management package and
|
126 |
|
|
other code can easily locate all the controllers in the system. This
|
127 |
|
|
table is constructed at link-time, avoiding code-size or run-time
|
128 |
|
|
overheads. To facilitate this the package provides two macros which
|
129 |
|
|
should be used to define a power controller,
|
130 |
|
|
<TT
|
131 |
|
|
CLASS="LITERAL"
|
132 |
|
|
>POWER_CONTROLLER()</TT
|
133 |
|
|
> and
|
134 |
|
|
<TT
|
135 |
|
|
CLASS="LITERAL"
|
136 |
|
|
>POWER_CONTROLLER_CPU()</TT
|
137 |
|
|
>.</P
|
138 |
|
|
><P
|
139 |
|
|
>The macro <TT
|
140 |
|
|
CLASS="LITERAL"
|
141 |
|
|
>POWER_CONTROLLER</TT
|
142 |
|
|
> takes four arguments:</P
|
143 |
|
|
><P
|
144 |
|
|
></P
|
145 |
|
|
><OL
|
146 |
|
|
TYPE="1"
|
147 |
|
|
><LI
|
148 |
|
|
><P
|
149 |
|
|
>A variable name. This can be used to access the power controller
|
150 |
|
|
directly, as well as via the table.</P
|
151 |
|
|
></LI
|
152 |
|
|
><LI
|
153 |
|
|
><P
|
154 |
|
|
>A priority. The table of power controllers is sorted, such that power
|
155 |
|
|
controllers with a numerically lower priority come earlier in the
|
156 |
|
|
table. The special controller <TT
|
157 |
|
|
CLASS="VARNAME"
|
158 |
|
|
>power_controller_cpu</TT
|
159 |
|
|
>
|
160 |
|
|
always comes at the end of the table. When moving from a high-power
|
161 |
|
|
mode to a lower-powered mode, the power management package iterates
|
162 |
|
|
through the table from front to back. When moving to a higher-powered
|
163 |
|
|
mode the reverse direction is used. The intention is that the power
|
164 |
|
|
controller for a software-only package such as a TCP/IP stack should
|
165 |
|
|
appear near the start of the table, whereas the controllers for the
|
166 |
|
|
ethernet and similar devices would be near the end of the table. Hence
|
167 |
|
|
when the policy module initiates a mode change to a lower-powered mode
|
168 |
|
|
the TCP/IP stack gets a chance to cancel this mode change, before the
|
169 |
|
|
devices it depends on are powered down. Similarly when moving to a
|
170 |
|
|
higher-powered mode the devices will be re-activated before any
|
171 |
|
|
software that depends on those devices.</P
|
172 |
|
|
><P
|
173 |
|
|
>The header file <TT
|
174 |
|
|
CLASS="FILENAME"
|
175 |
|
|
>cyg/power/power.h</TT
|
176 |
|
|
> defines three
|
177 |
|
|
priorities <TT
|
178 |
|
|
CLASS="LITERAL"
|
179 |
|
|
>PowerPri_Early</TT
|
180 |
|
|
>,
|
181 |
|
|
<TT
|
182 |
|
|
CLASS="LITERAL"
|
183 |
|
|
>PowerPri_Typical</TT
|
184 |
|
|
> and
|
185 |
|
|
<TT
|
186 |
|
|
CLASS="LITERAL"
|
187 |
|
|
>PowerPri_Late</TT
|
188 |
|
|
>. For most controllers one of these
|
189 |
|
|
priorities, possibly with a small number added or subtracted, will
|
190 |
|
|
give sufficient control. If an application developer is uncertain
|
191 |
|
|
about the relative priorities of the various controllers, a simple
|
192 |
|
|
<A
|
193 |
|
|
HREF="power-info.html#POWER-INFO-IDS"
|
194 |
|
|
>test program</A
|
195 |
|
|
> that iterates over
|
196 |
|
|
the table will quickly eliminate any confusion.</P
|
197 |
|
|
></LI
|
198 |
|
|
><LI
|
199 |
|
|
><P
|
200 |
|
|
>A constant string identifier. If the system has been configured
|
201 |
|
|
without support for such identifiers
|
202 |
|
|
(<TT
|
203 |
|
|
CLASS="VARNAME"
|
204 |
|
|
>CYGIMP_POWER_PROVIDE_STRINGS</TT
|
205 |
|
|
>) then this identifer
|
206 |
|
|
will be discarded at compile-time. Otherwise it will be made available
|
207 |
|
|
to higher-level code using the function
|
208 |
|
|
<TT
|
209 |
|
|
CLASS="FUNCTION"
|
210 |
|
|
>power_get_controller_id</TT
|
211 |
|
|
>. </P
|
212 |
|
|
></LI
|
213 |
|
|
><LI
|
214 |
|
|
><P
|
215 |
|
|
>A function pointer. This will be invoked to perform actual mode
|
216 |
|
|
changes, as described below.</P
|
217 |
|
|
></LI
|
218 |
|
|
></OL
|
219 |
|
|
><P
|
220 |
|
|
>A typical example of the use of the
|
221 |
|
|
<TT
|
222 |
|
|
CLASS="LITERAL"
|
223 |
|
|
>POWER_CONTROLLER</TT
|
224 |
|
|
> macro would be as follows:</P
|
225 |
|
|
><TABLE
|
226 |
|
|
BORDER="0"
|
227 |
|
|
BGCOLOR="#E0E0E0"
|
228 |
|
|
WIDTH="100%"
|
229 |
|
|
><TR
|
230 |
|
|
><TD
|
231 |
|
|
><PRE
|
232 |
|
|
CLASS="PROGRAMLISTING"
|
233 |
|
|
>#include <pkgconf/system.h>
|
234 |
|
|
|
235 |
|
|
#ifdef CYGPKG_POWER
|
236 |
|
|
# include <cyg/power/power.h>
|
237 |
|
|
|
238 |
|
|
static void
|
239 |
|
|
xyzzy_device_power_mode_change(
|
240 |
|
|
PowerController* controller,
|
241 |
|
|
PowerMode desired_mode,
|
242 |
|
|
PowerModeChange change)
|
243 |
|
|
{
|
244 |
|
|
// Do the work
|
245 |
|
|
}
|
246 |
|
|
|
247 |
|
|
static POWER_CONTROLLER(xyzzy_power_controller, \
|
248 |
|
|
PowerPri_Late, \
|
249 |
|
|
"xyzzy device", \
|
250 |
|
|
&xyzzy_device_power_mode_change);
|
251 |
|
|
#endif</PRE
|
252 |
|
|
></TD
|
253 |
|
|
></TR
|
254 |
|
|
></TABLE
|
255 |
|
|
><P
|
256 |
|
|
>This creates a variable <TT
|
257 |
|
|
CLASS="VARNAME"
|
258 |
|
|
>xyzzy_power_controller</TT
|
259 |
|
|
>,
|
260 |
|
|
which is a power controller data structure that will end up near the
|
261 |
|
|
end of the table of power controllers. Higher-level code can
|
262 |
|
|
iterate through this table and report the string <TT
|
263 |
|
|
CLASS="LITERAL"
|
264 |
|
|
>"xyzzy
|
265 |
|
|
device"</TT
|
266 |
|
|
> to the user. Whenever there is a mode change
|
267 |
|
|
operation that affects this controller, the function
|
268 |
|
|
<TT
|
269 |
|
|
CLASS="FUNCTION"
|
270 |
|
|
>xyzzy_device_power_mode_change</TT
|
271 |
|
|
> will be invoked.
|
272 |
|
|
The variable is declared static so this controller cannot be
|
273 |
|
|
manipulated by name in any other code. Alternatively, if the variable
|
274 |
|
|
had not been declared static other code could manipulate this
|
275 |
|
|
controller by name as well as through the table, especially if the
|
276 |
|
|
package for the xyzzy device driver explicitly declared this
|
277 |
|
|
variable in an exported header file. Obviously exporting the variable
|
278 |
|
|
involves a slight risk of a name clash at link time.</P
|
279 |
|
|
><P
|
280 |
|
|
>The above code explicitly checks for the presence of the power
|
281 |
|
|
management package before including that package's header file or
|
282 |
|
|
providing any related functionality. Since power management
|
283 |
|
|
functionality is optional, such checks are recommended.</P
|
284 |
|
|
><P
|
285 |
|
|
>The macro <TT
|
286 |
|
|
CLASS="LITERAL"
|
287 |
|
|
>POWER_CONTROLLER_CPU</TT
|
288 |
|
|
> only takes two
|
289 |
|
|
arguments, a string identifier and a mode change function pointer.
|
290 |
|
|
This macro always instantiates a variable
|
291 |
|
|
<TT
|
292 |
|
|
CLASS="VARNAME"
|
293 |
|
|
>power_controller_cpu</TT
|
294 |
|
|
> so there is no need to provide
|
295 |
|
|
a variable name. The resulting power controller structure always
|
296 |
|
|
appears at the end of the table, so there is no need to specify a
|
297 |
|
|
priority. Typical usage of the <TT
|
298 |
|
|
CLASS="LITERAL"
|
299 |
|
|
>POWER_CONTROLLER_CPU</TT
|
300 |
|
|
>
|
301 |
|
|
macro would be:</P
|
302 |
|
|
><TABLE
|
303 |
|
|
BORDER="0"
|
304 |
|
|
BGCOLOR="#E0E0E0"
|
305 |
|
|
WIDTH="100%"
|
306 |
|
|
><TR
|
307 |
|
|
><TD
|
308 |
|
|
><PRE
|
309 |
|
|
CLASS="PROGRAMLISTING"
|
310 |
|
|
>static void
|
311 |
|
|
wumpus_processor_power_mode_change(
|
312 |
|
|
PowerController* controller,
|
313 |
|
|
PowerMode desired_mode,
|
314 |
|
|
PowerModeChange change)
|
315 |
|
|
{
|
316 |
|
|
// Do the work
|
317 |
|
|
}
|
318 |
|
|
|
319 |
|
|
POWER_CONTROLLER_CPU("wumpus processor", \
|
320 |
|
|
&wumpus_processor_power_mode_change);</PRE
|
321 |
|
|
></TD
|
322 |
|
|
></TR
|
323 |
|
|
></TABLE
|
324 |
|
|
><P
|
325 |
|
|
>This defines a power controller structure
|
326 |
|
|
<TT
|
327 |
|
|
CLASS="VARNAME"
|
328 |
|
|
>power_controller_cpu</TT
|
329 |
|
|
>. It should not be declared
|
330 |
|
|
static since higher-level code may well want to manipulate the cpu's
|
331 |
|
|
power mode directly, and the variable is declared by the power
|
332 |
|
|
management package's header file.</P
|
333 |
|
|
><P
|
334 |
|
|
>Some care has to be taken to ensure that the power controllers
|
335 |
|
|
actually end up in the final executable. If a power controller
|
336 |
|
|
variable ends up in an ordinary library and is never referenced
|
337 |
|
|
directly then typically the linker will believe that the variable is
|
338 |
|
|
not needed and it will not end up in the executable. For eCos packages
|
339 |
|
|
this can be achieved in the CDL, by specifying that the containing
|
340 |
|
|
source file should end up in <TT
|
341 |
|
|
CLASS="FILENAME"
|
342 |
|
|
>libextras.a</TT
|
343 |
|
|
> rather
|
344 |
|
|
than the default <TT
|
345 |
|
|
CLASS="FILENAME"
|
346 |
|
|
>libtarget.a</TT
|
347 |
|
|
>:</P
|
348 |
|
|
><TABLE
|
349 |
|
|
BORDER="0"
|
350 |
|
|
BGCOLOR="#E0E0E0"
|
351 |
|
|
WIDTH="100%"
|
352 |
|
|
><TR
|
353 |
|
|
><TD
|
354 |
|
|
><PRE
|
355 |
|
|
CLASS="PROGRAMLISTING"
|
356 |
|
|
>cdl_package CYGPKG_HAL_WUMPUS_ARCH {
|
357 |
|
|
…
|
358 |
|
|
compile -library=libextras.a data.c
|
359 |
|
|
}</PRE
|
360 |
|
|
></TD
|
361 |
|
|
></TR
|
362 |
|
|
></TABLE
|
363 |
|
|
><P
|
364 |
|
|
>If the file <TT
|
365 |
|
|
CLASS="FILENAME"
|
366 |
|
|
>data.c</TT
|
367 |
|
|
> instantiates a power
|
368 |
|
|
controller this is now guaranteed to end up in the final executable,
|
369 |
|
|
as intended. Typically HAL and device driver packages will already
|
370 |
|
|
have some data that must not be eliminated by the linker, so they will
|
371 |
|
|
already contain a file that gets built into
|
372 |
|
|
<TT
|
373 |
|
|
CLASS="FILENAME"
|
374 |
|
|
>libextras.a</TT
|
375 |
|
|
>. For power controllers defined inside
|
376 |
|
|
application code it is important that the power controllers end up in
|
377 |
|
|
<TT
|
378 |
|
|
CLASS="FILENAME"
|
379 |
|
|
>.o</TT
|
380 |
|
|
> object files rather than in
|
381 |
|
|
<TT
|
382 |
|
|
CLASS="FILENAME"
|
383 |
|
|
>.a</TT
|
384 |
|
|
> library archive files.</P
|
385 |
|
|
><P
|
386 |
|
|
>All the real work of a power controller is done by the mode change
|
387 |
|
|
function. If the power management package has been configured to use a
|
388 |
|
|
separate thread then this mode change function will be invoked by that
|
389 |
|
|
thread (except for the special case of <A
|
390 |
|
|
HREF="power-change.html#POWER-CHANGE-CONTROLLER-NOW"
|
391 |
|
|
><TT
|
392 |
|
|
CLASS="FUNCTION"
|
393 |
|
|
>power_set_controller_mode_now</TT
|
394 |
|
|
></A
|
395 |
|
|
>).
|
396 |
|
|
If no separate thread is used then the mode change function will be
|
397 |
|
|
invoked directly by <TT
|
398 |
|
|
CLASS="FUNCTION"
|
399 |
|
|
>power_set_mode</TT
|
400 |
|
|
> or
|
401 |
|
|
<TT
|
402 |
|
|
CLASS="FUNCTION"
|
403 |
|
|
>power_set_controller_mode</TT
|
404 |
|
|
>.</P
|
405 |
|
|
><P
|
406 |
|
|
>The mode change function will be invoked with three arguments. The
|
407 |
|
|
first argument identifies the power controller. Usually this argument
|
408 |
|
|
is not actually required since a given mode change function will only
|
409 |
|
|
ever be invoked for a single power controller. For example,
|
410 |
|
|
<TT
|
411 |
|
|
CLASS="FUNCTION"
|
412 |
|
|
>xyzzy_device_power_mode_change</TT
|
413 |
|
|
> will only ever be
|
414 |
|
|
used in conjunction with <TT
|
415 |
|
|
CLASS="VARNAME"
|
416 |
|
|
>xyzzy_power_controller</TT
|
417 |
|
|
>.
|
418 |
|
|
However there may be some packages which contain multiple controllers,
|
419 |
|
|
all of which can share a single mode change function, and in that case
|
420 |
|
|
it is essential to identify the specific controller. The second
|
421 |
|
|
argument specifies the mode the controller should switch to, if
|
422 |
|
|
possible: it will be one of <TT
|
423 |
|
|
CLASS="LITERAL"
|
424 |
|
|
>PowerMode_Active</TT
|
425 |
|
|
>,
|
426 |
|
|
<TT
|
427 |
|
|
CLASS="LITERAL"
|
428 |
|
|
>PowerMode_Idle</TT
|
429 |
|
|
>, <TT
|
430 |
|
|
CLASS="LITERAL"
|
431 |
|
|
>PowerMode_Sleep</TT
|
432 |
|
|
>
|
433 |
|
|
or <TT
|
434 |
|
|
CLASS="LITERAL"
|
435 |
|
|
>PowerMode_Off</TT
|
436 |
|
|
>. The final argument will be one of
|
437 |
|
|
<TT
|
438 |
|
|
CLASS="LITERAL"
|
439 |
|
|
>PowerModeChange_Controller</TT
|
440 |
|
|
>,
|
441 |
|
|
PowerModeChange_ControllerNow, or
|
442 |
|
|
<TT
|
443 |
|
|
CLASS="LITERAL"
|
444 |
|
|
>PowerModeChange_Global</TT
|
445 |
|
|
>, and identifies the call
|
446 |
|
|
that caused this invocation. For example, if the mode change function
|
447 |
|
|
was invoked because of a call to <TT
|
448 |
|
|
CLASS="FUNCTION"
|
449 |
|
|
>power_set_mode</TT
|
450 |
|
|
>
|
451 |
|
|
then this argument will be <TT
|
452 |
|
|
CLASS="LITERAL"
|
453 |
|
|
>PowerModeChange_Global</TT
|
454 |
|
|
>.
|
455 |
|
|
It is up to each controller to decide how to interpret this final
|
456 |
|
|
argument. A typical controller might reject a global request to switch
|
457 |
|
|
to <SPAN
|
458 |
|
|
CLASS="TYPE"
|
459 |
|
|
>off</SPAN
|
460 |
|
|
> mode if the associated device is still busy, but
|
461 |
|
|
if the request was aimed specifically at this controller then it could
|
462 |
|
|
instead abort any current I/O operations and switch off the device.</P
|
463 |
|
|
><P
|
464 |
|
|
>The <SPAN
|
465 |
|
|
CLASS="STRUCTNAME"
|
466 |
|
|
>PowerController</SPAN
|
467 |
|
|
> data structure contains
|
468 |
|
|
one field, <TT
|
469 |
|
|
CLASS="STRUCTFIELD"
|
470 |
|
|
><I
|
471 |
|
|
>mode</I
|
472 |
|
|
></TT
|
473 |
|
|
>, that needs to be updated
|
474 |
|
|
by the power mode change function. At all times it should indicate the
|
475 |
|
|
current mode for this controller. When a mode change is requested the
|
476 |
|
|
desired mode is passed as the second argument. The exact operation of
|
477 |
|
|
the power mode change function depends very much on what is being
|
478 |
|
|
controlled and the current circumstances, but some guidelines are
|
479 |
|
|
possible:</P
|
480 |
|
|
><P
|
481 |
|
|
></P
|
482 |
|
|
><OL
|
483 |
|
|
TYPE="1"
|
484 |
|
|
><LI
|
485 |
|
|
><P
|
486 |
|
|
>If the request can be satisfied without obvious detriment, do so and
|
487 |
|
|
update the <TT
|
488 |
|
|
CLASS="STRUCTFIELD"
|
489 |
|
|
><I
|
490 |
|
|
>mode</I
|
491 |
|
|
></TT
|
492 |
|
|
> field. Reducing the power
|
493 |
|
|
consumption of a device that is not currently being used is generally
|
494 |
|
|
harmless.</P
|
495 |
|
|
></LI
|
496 |
|
|
><LI
|
497 |
|
|
><P
|
498 |
|
|
>If a request is a no-op, for example if the system is switching
|
499 |
|
|
from <SPAN
|
500 |
|
|
CLASS="TYPE"
|
501 |
|
|
>idle</SPAN
|
502 |
|
|
> to <SPAN
|
503 |
|
|
CLASS="TYPE"
|
504 |
|
|
>sleep</SPAN
|
505 |
|
|
> mode and the controller
|
506 |
|
|
does not distinguish between these modes, simply act as if the request
|
507 |
|
|
was satisfied.</P
|
508 |
|
|
></LI
|
509 |
|
|
><LI
|
510 |
|
|
><P
|
511 |
|
|
>If a request is felt to be unsafe, for example shutting down a
|
512 |
|
|
device that is still in use, then the controller may decide
|
513 |
|
|
to reject this request. This is especially true if the request was a
|
514 |
|
|
global mode change as opposed to one intended specifically for this
|
515 |
|
|
controller: in the latter case the policy module should be given due
|
516 |
|
|
deference. There are a number of ways in which a request can be
|
517 |
|
|
rejected:</P
|
518 |
|
|
><P
|
519 |
|
|
></P
|
520 |
|
|
><OL
|
521 |
|
|
TYPE="a"
|
522 |
|
|
><LI
|
523 |
|
|
><P
|
524 |
|
|
>If the request cannot be satisfied immediately but may be feasible in
|
525 |
|
|
a short while, leave the <TT
|
526 |
|
|
CLASS="STRUCTFIELD"
|
527 |
|
|
><I
|
528 |
|
|
>mode</I
|
529 |
|
|
></TT
|
530 |
|
|
> field
|
531 |
|
|
unchanged. Higher-level code in the policy module can interpret this
|
532 |
|
|
as a hint to retry the operation a little bit later. This approach is
|
533 |
|
|
also useful if the mode change can be started but will take some time
|
534 |
|
|
to complete, for example shutting down a socket connection, and
|
535 |
|
|
additional processing will be needed later on.</P
|
536 |
|
|
></LI
|
537 |
|
|
><LI
|
538 |
|
|
><P
|
539 |
|
|
>If the request is felt to be inappropriate, for example switching off
|
540 |
|
|
a device that is still in use, the mode change function can
|
541 |
|
|
call <TT
|
542 |
|
|
CLASS="FUNCTION"
|
543 |
|
|
>power_set_controller_mode</TT
|
544 |
|
|
> to reset the
|
545 |
|
|
desired mode for this controller back to the current mode.
|
546 |
|
|
Higher-level code can then interpret this as a hint that there is more
|
547 |
|
|
activity in the system than had been apparent.</P
|
548 |
|
|
></LI
|
549 |
|
|
><LI
|
550 |
|
|
><P
|
551 |
|
|
>For a global mode change, if the new mode is felt to be inappropriate
|
552 |
|
|
then the power controller can call <TT
|
553 |
|
|
CLASS="FUNCTION"
|
554 |
|
|
>power_set_mode</TT
|
555 |
|
|
>
|
556 |
|
|
to indicate this. An example of this would be the policy module
|
557 |
|
|
deciding to switch off the whole unit while there is still I/O
|
558 |
|
|
activity.</P
|
559 |
|
|
></LI
|
560 |
|
|
></OL
|
561 |
|
|
></LI
|
562 |
|
|
></OL
|
563 |
|
|
><P
|
564 |
|
|
>Mode change functions should not directly manipulate any other fields
|
565 |
|
|
in the <SPAN
|
566 |
|
|
CLASS="STRUCTNAME"
|
567 |
|
|
>PowerController</SPAN
|
568 |
|
|
> data structure. If it
|
569 |
|
|
is necessary to keep track of additional data then static variables
|
570 |
|
|
can be used.</P
|
571 |
|
|
><P
|
572 |
|
|
>It should be noted that the above are only guidelines. Their
|
573 |
|
|
application in any given situation may be unclear. In addition the
|
574 |
|
|
detailed requirements of specific systems will vary, so even if the
|
575 |
|
|
power controller for a given device driver follows the above
|
576 |
|
|
guidelines exactly it may turn out that slightly different behaviour
|
577 |
|
|
would be more appropriate for the actual system that is being
|
578 |
|
|
developed. Fortunately the open source nature of
|
579 |
|
|
<SPAN
|
580 |
|
|
CLASS="PRODUCTNAME"
|
581 |
|
|
>eCos</SPAN
|
582 |
|
|
> allows system developers to fine-tune
|
583 |
|
|
power controllers to meet their exact requirements.</P
|
584 |
|
|
></DIV
|
585 |
|
|
><DIV
|
586 |
|
|
CLASS="NAVFOOTER"
|
587 |
|
|
><HR
|
588 |
|
|
ALIGN="LEFT"
|
589 |
|
|
WIDTH="100%"><TABLE
|
590 |
|
|
WIDTH="100%"
|
591 |
|
|
BORDER="0"
|
592 |
|
|
CELLPADDING="0"
|
593 |
|
|
CELLSPACING="0"
|
594 |
|
|
><TR
|
595 |
|
|
><TD
|
596 |
|
|
WIDTH="33%"
|
597 |
|
|
ALIGN="left"
|
598 |
|
|
VALIGN="top"
|
599 |
|
|
><A
|
600 |
|
|
HREF="power-attached.html"
|
601 |
|
|
>Prev</A
|
602 |
|
|
></TD
|
603 |
|
|
><TD
|
604 |
|
|
WIDTH="34%"
|
605 |
|
|
ALIGN="center"
|
606 |
|
|
VALIGN="top"
|
607 |
|
|
><A
|
608 |
|
|
HREF="services-power.html"
|
609 |
|
|
>Home</A
|
610 |
|
|
></TD
|
611 |
|
|
><TD
|
612 |
|
|
WIDTH="33%"
|
613 |
|
|
ALIGN="right"
|
614 |
|
|
VALIGN="top"
|
615 |
|
|
> </TD
|
616 |
|
|
></TR
|
617 |
|
|
><TR
|
618 |
|
|
><TD
|
619 |
|
|
WIDTH="33%"
|
620 |
|
|
ALIGN="left"
|
621 |
|
|
VALIGN="top"
|
622 |
|
|
>Attached and Detached Controllers</TD
|
623 |
|
|
><TD
|
624 |
|
|
WIDTH="34%"
|
625 |
|
|
ALIGN="center"
|
626 |
|
|
VALIGN="top"
|
627 |
|
|
> </TD
|
628 |
|
|
><TD
|
629 |
|
|
WIDTH="33%"
|
630 |
|
|
ALIGN="right"
|
631 |
|
|
VALIGN="top"
|
632 |
|
|
> </TD
|
633 |
|
|
></TR
|
634 |
|
|
></TABLE
|
635 |
|
|
></DIV
|
636 |
|
|
></BODY
|
637 |
|
|
></HTML
|
638 |
|
|
>
|