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