xref: /onnv-gate/usr/src/psm/promif/ieee1275/common/prom_env.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/promif.h>
30*0Sstevel@tonic-gate #include <sys/promimpl.h>
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate /*
33*0Sstevel@tonic-gate  * The functions in this file are used to control the pre- and post-processing
34*0Sstevel@tonic-gate  * functions that bracket calls to the OBP CIF handler.  One set, promif_preprom
35*0Sstevel@tonic-gate  * and promif_postprom, are provided for general kernel use.  The other set,
36*0Sstevel@tonic-gate  * promif_preout and promif_postout, are used by the power management subsystem
37*0Sstevel@tonic-gate  * to ensure that the framebuffer is active when PROM functions that interact
38*0Sstevel@tonic-gate  * with the console are invoked.
39*0Sstevel@tonic-gate  *
40*0Sstevel@tonic-gate  * In some cases, the operation of these functions must be suppressed.  As such,
41*0Sstevel@tonic-gate  * this file provides the ability to suspend and resume use of both sets
42*0Sstevel@tonic-gate  * simultaneously.  Complicating matters is the fact that both current uses of
43*0Sstevel@tonic-gate  * the pre- and post-processor suspension and resume facilities, kmdb and CPR
44*0Sstevel@tonic-gate  * may be used simultaneously.  We therefore support normal operation and two
45*0Sstevel@tonic-gate  * levels of suspension.  The pre- and post-processing functions are only
46*0Sstevel@tonic-gate  * called during normal operation.  With each suspension request, this
47*0Sstevel@tonic-gate  * subsystem enters the first suspension level, or passes to the second
48*0Sstevel@tonic-gate  * suspension level, as appropriate.  Resume calls decrement the suspension
49*0Sstevel@tonic-gate  * level.  Only two nested suspensions are supported.
50*0Sstevel@tonic-gate  *
51*0Sstevel@tonic-gate  * As indicated above, the two current users are CPR and kmdb.  CPR must prevent
52*0Sstevel@tonic-gate  * kernel accesses outside of the nucleus page during the late stages of system
53*0Sstevel@tonic-gate  * suspension and during the early stages of system resumption.  As such, the
54*0Sstevel@tonic-gate  * PM-related processing must not occur during these times.
55*0Sstevel@tonic-gate  *
56*0Sstevel@tonic-gate  * The platform-specific portions of kmdb live in the platmods, and thus execute
57*0Sstevel@tonic-gate  * in the linker environment of the platmods.  That is, any promif calls they
58*0Sstevel@tonic-gate  * may make are executed by the kernel copies of those functions, rather than
59*0Sstevel@tonic-gate  * the versions included with kmdb.  The only difference between the two copies
60*0Sstevel@tonic-gate  * being the nonuse of the pre- and post-processing functions in the kmdb
61*0Sstevel@tonic-gate  * versions, we must ensure that these functions are not used when the kmdb
62*0Sstevel@tonic-gate  * platmod code executes.  Accordingly, kmdb disables the pre- and post-
63*0Sstevel@tonic-gate  * processing functions via the KDI prior to passing control to the platmod
64*0Sstevel@tonic-gate  * debugger code.
65*0Sstevel@tonic-gate  */
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate static int promif_suspendlevel;
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate static promif_preprom_f *promif_preprom_fn;
70*0Sstevel@tonic-gate static promif_postprom_f *promif_postprom_fn;
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate void
73*0Sstevel@tonic-gate prom_set_preprom(promif_preprom_f *new)
74*0Sstevel@tonic-gate {
75*0Sstevel@tonic-gate 	promif_preprom_fn = new;
76*0Sstevel@tonic-gate }
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate void
79*0Sstevel@tonic-gate prom_set_postprom(promif_postprom_f *new)
80*0Sstevel@tonic-gate {
81*0Sstevel@tonic-gate 	promif_postprom_fn = new;
82*0Sstevel@tonic-gate }
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate void
85*0Sstevel@tonic-gate promif_preprom(void)
86*0Sstevel@tonic-gate {
87*0Sstevel@tonic-gate 	if (promif_suspendlevel == 0 && promif_preprom_fn != NULL)
88*0Sstevel@tonic-gate 		promif_preprom_fn();
89*0Sstevel@tonic-gate }
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate void
92*0Sstevel@tonic-gate promif_postprom(void)
93*0Sstevel@tonic-gate {
94*0Sstevel@tonic-gate 	if (promif_suspendlevel == 0 && promif_postprom_fn != NULL)
95*0Sstevel@tonic-gate 		promif_postprom_fn();
96*0Sstevel@tonic-gate }
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate /*
99*0Sstevel@tonic-gate  * The reader will note that the layout and calling conventions of the
100*0Sstevel@tonic-gate  * prom_preout and prom_postout functions differ from the prom_preprom and
101*0Sstevel@tonic-gate  * prom_postprom functions, above.  At the time the preout and postout
102*0Sstevel@tonic-gate  * functions are initialized, kernel startup is well underway.  There exists
103*0Sstevel@tonic-gate  * a race condition whereby a PROM call may begin before preout has been
104*0Sstevel@tonic-gate  * initialized, and may end after postout has been initialized.  In such
105*0Sstevel@tonic-gate  * cases, there will be a call to postout without a corresponding preout
106*0Sstevel@tonic-gate  * call.  The preprom and postprom calls above are initialized early enough
107*0Sstevel@tonic-gate  * that this race condition does not occur.
108*0Sstevel@tonic-gate  *
109*0Sstevel@tonic-gate  * To avoid the race condition, the preout/postout functions are designed
110*0Sstevel@tonic-gate  * such that the initialization is atomic.  Further, the preout call returns
111*0Sstevel@tonic-gate  * a data structure that includes a pointer to the postout function that
112*0Sstevel@tonic-gate  * corresponds to the invoked preout function.  This ensures that the preout
113*0Sstevel@tonic-gate  * and postout functions will only be used as a matched set.
114*0Sstevel@tonic-gate  */
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate static void
117*0Sstevel@tonic-gate null_outfunc(void)
118*0Sstevel@tonic-gate {
119*0Sstevel@tonic-gate }
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate static promif_owrap_t nullwrapper =
122*0Sstevel@tonic-gate {
123*0Sstevel@tonic-gate 	null_outfunc,
124*0Sstevel@tonic-gate 	null_outfunc
125*0Sstevel@tonic-gate };
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate static promif_owrap_t *wrapper = &nullwrapper;
128*0Sstevel@tonic-gate static promif_owrap_t pmwrapper;
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate promif_owrap_t
131*0Sstevel@tonic-gate *promif_preout(void)
132*0Sstevel@tonic-gate {
133*0Sstevel@tonic-gate 	promif_owrap_t *ow;
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate 	if (promif_suspendlevel > 0)
136*0Sstevel@tonic-gate 		return (&nullwrapper);
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate 	ow = wrapper;
139*0Sstevel@tonic-gate 	if (ow->preout != NULL)
140*0Sstevel@tonic-gate 		(ow->preout)();
141*0Sstevel@tonic-gate 	return (ow);
142*0Sstevel@tonic-gate }
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate void
145*0Sstevel@tonic-gate promif_postout(promif_owrap_t *ow)
146*0Sstevel@tonic-gate {
147*0Sstevel@tonic-gate 	if (ow->postout != NULL)
148*0Sstevel@tonic-gate 		(ow->postout)();
149*0Sstevel@tonic-gate }
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate void
152*0Sstevel@tonic-gate prom_set_outfuncs(void (*pref)(void), void (*postf)(void))
153*0Sstevel@tonic-gate {
154*0Sstevel@tonic-gate 	pmwrapper.preout = pref;
155*0Sstevel@tonic-gate 	pmwrapper.postout = postf;
156*0Sstevel@tonic-gate 	wrapper = &pmwrapper;
157*0Sstevel@tonic-gate }
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate void
160*0Sstevel@tonic-gate prom_suspend_prepost(void)
161*0Sstevel@tonic-gate {
162*0Sstevel@tonic-gate 	ASSERT(promif_suspendlevel < 2);
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate 	promif_suspendlevel++;
165*0Sstevel@tonic-gate }
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate void
168*0Sstevel@tonic-gate prom_resume_prepost(void)
169*0Sstevel@tonic-gate {
170*0Sstevel@tonic-gate 	ASSERT(promif_suspendlevel >= 0);
171*0Sstevel@tonic-gate 
172*0Sstevel@tonic-gate 	promif_suspendlevel--;
173*0Sstevel@tonic-gate }
174