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