xref: /titanic_50/usr/src/uts/common/io/tem.c (revision aecfc01d1bad84e66649703f7fc2926ef70b34ba)
1fea9cb91Slq150181 /*
2fea9cb91Slq150181  * CDDL HEADER START
3fea9cb91Slq150181  *
4fea9cb91Slq150181  * The contents of this file are subject to the terms of the
5fea9cb91Slq150181  * Common Development and Distribution License (the "License").
6fea9cb91Slq150181  * You may not use this file except in compliance with the License.
7fea9cb91Slq150181  *
8fea9cb91Slq150181  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fea9cb91Slq150181  * or http://www.opensolaris.org/os/licensing.
10fea9cb91Slq150181  * See the License for the specific language governing permissions
11fea9cb91Slq150181  * and limitations under the License.
12fea9cb91Slq150181  *
13fea9cb91Slq150181  * When distributing Covered Code, include this CDDL HEADER in each
14fea9cb91Slq150181  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fea9cb91Slq150181  * If applicable, add the following below this CDDL HEADER, with the
16fea9cb91Slq150181  * fields enclosed by brackets "[]" replaced with your own identifying
17fea9cb91Slq150181  * information: Portions Copyright [yyyy] [name of copyright owner]
18fea9cb91Slq150181  *
19fea9cb91Slq150181  * CDDL HEADER END
20fea9cb91Slq150181  */
21fea9cb91Slq150181 
22fea9cb91Slq150181 /*
23b52fe415Slipeng sang - Sun Microsystems - Beijing China  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24fea9cb91Slq150181  * Use is subject to license terms.
25fea9cb91Slq150181  */
26fea9cb91Slq150181 
27fea9cb91Slq150181 /*
28fea9cb91Slq150181  * ANSI terminal emulator module; parse ANSI X3.64 escape sequences and
29fea9cb91Slq150181  * the like.
30*aecfc01dSrui zang - Sun Microsystems - Beijing China  *
31*aecfc01dSrui zang - Sun Microsystems - Beijing China  * How Virtual Terminal Emulator Works:
32*aecfc01dSrui zang - Sun Microsystems - Beijing China  *
33*aecfc01dSrui zang - Sun Microsystems - Beijing China  * Every virtual terminal is associated with a tem_vt_state structure
34*aecfc01dSrui zang - Sun Microsystems - Beijing China  * and maintains a virtual screen buffer in tvs_screen_buf, which contains
35*aecfc01dSrui zang - Sun Microsystems - Beijing China  * all the characters which should be shown on the physical screen when
36*aecfc01dSrui zang - Sun Microsystems - Beijing China  * the terminal is activated.  There are also two other buffers, tvs_fg_buf
37*aecfc01dSrui zang - Sun Microsystems - Beijing China  * and tvs_bg_buf, which track the foreground and background colors of the
38*aecfc01dSrui zang - Sun Microsystems - Beijing China  * on screen characters
39*aecfc01dSrui zang - Sun Microsystems - Beijing China  *
40*aecfc01dSrui zang - Sun Microsystems - Beijing China  * Data written to a virtual terminal is composed of characters which
41*aecfc01dSrui zang - Sun Microsystems - Beijing China  * should be displayed on the screen when this virtual terminal is
42*aecfc01dSrui zang - Sun Microsystems - Beijing China  * activated, fg/bg colors of these characters, and other control
43*aecfc01dSrui zang - Sun Microsystems - Beijing China  * information (escape sequence, etc).
44*aecfc01dSrui zang - Sun Microsystems - Beijing China  *
45*aecfc01dSrui zang - Sun Microsystems - Beijing China  * When data is passed to a virtual terminal it first is parsed for
46*aecfc01dSrui zang - Sun Microsystems - Beijing China  * control information by tem_safe_parse().  Subsequently the character
47*aecfc01dSrui zang - Sun Microsystems - Beijing China  * and color data are written to tvs_screen_buf, tvs_fg_buf, and
48*aecfc01dSrui zang - Sun Microsystems - Beijing China  * tvs_bg_buf.  They are saved in these buffers in order to refresh
49*aecfc01dSrui zang - Sun Microsystems - Beijing China  * the screen when this terminal is activated.  If the terminal is
50*aecfc01dSrui zang - Sun Microsystems - Beijing China  * currently active, the data (characters and colors) are also written
51*aecfc01dSrui zang - Sun Microsystems - Beijing China  * to the physical screen by invoking a callback function,
52*aecfc01dSrui zang - Sun Microsystems - Beijing China  * tem_safe_text_callbacks() or tem_safe_pix_callbacks().
53*aecfc01dSrui zang - Sun Microsystems - Beijing China  *
54*aecfc01dSrui zang - Sun Microsystems - Beijing China  * When rendering data to the framebuffer, if the framebuffer is in
55*aecfc01dSrui zang - Sun Microsystems - Beijing China  * VIS_PIXEL mode, the character data will first be converted to pixel
56*aecfc01dSrui zang - Sun Microsystems - Beijing China  * data using tem_safe_pix_bit2pix(), and then the pixels get displayed
57*aecfc01dSrui zang - Sun Microsystems - Beijing China  * on the physical screen.  We only store the character and color data in
58*aecfc01dSrui zang - Sun Microsystems - Beijing China  * tem_vt_state since the bit2pix conversion only happens when actually
59*aecfc01dSrui zang - Sun Microsystems - Beijing China  * rendering to the physical framebuffer.
60fea9cb91Slq150181  */
61fea9cb91Slq150181 
62*aecfc01dSrui zang - Sun Microsystems - Beijing China 
63fea9cb91Slq150181 #include <sys/types.h>
64fea9cb91Slq150181 #include <sys/file.h>
65fea9cb91Slq150181 #include <sys/conf.h>
66fea9cb91Slq150181 #include <sys/errno.h>
67fea9cb91Slq150181 #include <sys/open.h>
68fea9cb91Slq150181 #include <sys/cred.h>
69fea9cb91Slq150181 #include <sys/kmem.h>
70fea9cb91Slq150181 #include <sys/ascii.h>
71fea9cb91Slq150181 #include <sys/consdev.h>
72fea9cb91Slq150181 #include <sys/font.h>
73fea9cb91Slq150181 #include <sys/fbio.h>
74fea9cb91Slq150181 #include <sys/conf.h>
75fea9cb91Slq150181 #include <sys/modctl.h>
76fea9cb91Slq150181 #include <sys/strsubr.h>
77fea9cb91Slq150181 #include <sys/stat.h>
78fea9cb91Slq150181 #include <sys/visual_io.h>
79fea9cb91Slq150181 #include <sys/mutex.h>
80fea9cb91Slq150181 #include <sys/param.h>
81fea9cb91Slq150181 #include <sys/debug.h>
82fea9cb91Slq150181 #include <sys/cmn_err.h>
83fea9cb91Slq150181 #include <sys/console.h>
84fea9cb91Slq150181 #include <sys/ddi.h>
85fea9cb91Slq150181 #include <sys/sunddi.h>
86fea9cb91Slq150181 #include <sys/sunldi.h>
87fea9cb91Slq150181 #include <sys/tem_impl.h>
88fea9cb91Slq150181 #ifdef _HAVE_TEM_FIRMWARE
89fea9cb91Slq150181 #include <sys/promif.h>
90fea9cb91Slq150181 #endif /* _HAVE_TEM_FIRMWARE */
91b52fe415Slipeng sang - Sun Microsystems - Beijing China #include <sys/consplat.h>
92*aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/kd.h>
93*aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/sysmacros.h>
94*aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/note.h>
95*aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/t_lock.h>
96fea9cb91Slq150181 
97*aecfc01dSrui zang - Sun Microsystems - Beijing China /* Terminal emulator internal helper functions */
98*aecfc01dSrui zang - Sun Microsystems - Beijing China static void	tems_setup_terminal(struct vis_devinit *, size_t, size_t);
99*aecfc01dSrui zang - Sun Microsystems - Beijing China static void	tems_modechange_callback(struct vis_modechg_arg *,
100*aecfc01dSrui zang - Sun Microsystems - Beijing China 		struct vis_devinit *);
101*aecfc01dSrui zang - Sun Microsystems - Beijing China 
102*aecfc01dSrui zang - Sun Microsystems - Beijing China static void	tems_reset_colormap(cred_t *, enum called_from);
103*aecfc01dSrui zang - Sun Microsystems - Beijing China 
104*aecfc01dSrui zang - Sun Microsystems - Beijing China static void	tem_free_buf(struct tem_vt_state *);
105*aecfc01dSrui zang - Sun Microsystems - Beijing China static void	tem_internal_init(struct tem_vt_state *, cred_t *, boolean_t,
106*aecfc01dSrui zang - Sun Microsystems - Beijing China 		    boolean_t);
107*aecfc01dSrui zang - Sun Microsystems - Beijing China static void	tems_get_initial_color(tem_color_t *pcolor);
108fea9cb91Slq150181 
109fea9cb91Slq150181 /*
110fea9cb91Slq150181  * Globals
111fea9cb91Slq150181  */
112*aecfc01dSrui zang - Sun Microsystems - Beijing China static ldi_ident_t	term_li = NULL;
113*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_state_t	tems;	/* common term info */
114*aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(MUTEX_PROTECTS_DATA(tems.ts_lock, tems))
115fea9cb91Slq150181 
116fea9cb91Slq150181 extern struct mod_ops mod_miscops;
117fea9cb91Slq150181 
118fea9cb91Slq150181 static struct modlmisc	modlmisc = {
119fea9cb91Slq150181 	&mod_miscops,	/* modops */
120fea9cb91Slq150181 	"ANSI Terminal Emulator", /* name */
121fea9cb91Slq150181 };
122fea9cb91Slq150181 
123fea9cb91Slq150181 static struct modlinkage modlinkage = {
124fea9cb91Slq150181 	MODREV_1, (void *)&modlmisc, NULL
125fea9cb91Slq150181 };
126fea9cb91Slq150181 
127fea9cb91Slq150181 int
_init(void)128fea9cb91Slq150181 _init(void)
129fea9cb91Slq150181 {
130fea9cb91Slq150181 	int ret;
131fea9cb91Slq150181 	ret = mod_install(&modlinkage);
132fea9cb91Slq150181 	if (ret != 0)
133fea9cb91Slq150181 		return (ret);
134fea9cb91Slq150181 	ret = ldi_ident_from_mod(&modlinkage, &term_li);
135fea9cb91Slq150181 	if (ret != 0) {
136fea9cb91Slq150181 		(void) mod_remove(&modlinkage);
137fea9cb91Slq150181 		return (ret);
138fea9cb91Slq150181 	}
139*aecfc01dSrui zang - Sun Microsystems - Beijing China 
140*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_init(&tems.ts_lock, (char *)NULL, MUTEX_DRIVER, NULL);
141*aecfc01dSrui zang - Sun Microsystems - Beijing China 	list_create(&tems.ts_list, sizeof (struct tem_vt_state),
142*aecfc01dSrui zang - Sun Microsystems - Beijing China 	    offsetof(struct tem_vt_state, tvs_list_node));
143*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_active = NULL;
144*aecfc01dSrui zang - Sun Microsystems - Beijing China 
145fea9cb91Slq150181 	return (0);
146fea9cb91Slq150181 }
147fea9cb91Slq150181 
148fea9cb91Slq150181 int
_fini()149fea9cb91Slq150181 _fini()
150fea9cb91Slq150181 {
151fea9cb91Slq150181 	int ret;
152fea9cb91Slq150181 
153fea9cb91Slq150181 	ret = mod_remove(&modlinkage);
154fea9cb91Slq150181 	if (ret == 0) {
155fea9cb91Slq150181 		ldi_ident_release(term_li);
156fea9cb91Slq150181 		term_li = NULL;
157fea9cb91Slq150181 	}
158fea9cb91Slq150181 	return (ret);
159fea9cb91Slq150181 }
160fea9cb91Slq150181 
161fea9cb91Slq150181 int
_info(struct modinfo * modinfop)162fea9cb91Slq150181 _info(struct modinfo *modinfop)
163fea9cb91Slq150181 {
164fea9cb91Slq150181 	return (mod_info(&modlinkage, modinfop));
165fea9cb91Slq150181 }
166fea9cb91Slq150181 
167*aecfc01dSrui zang - Sun Microsystems - Beijing China static void
tem_add(struct tem_vt_state * tem)168*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_add(struct tem_vt_state *tem)
169fea9cb91Slq150181 {
170*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock));
171fea9cb91Slq150181 
172*aecfc01dSrui zang - Sun Microsystems - Beijing China 	list_insert_head(&tems.ts_list, tem);
173fea9cb91Slq150181 }
174fea9cb91Slq150181 
175fea9cb91Slq150181 static void
tem_rm(struct tem_vt_state * tem)176*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_rm(struct tem_vt_state *tem)
177fea9cb91Slq150181 {
178*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock));
179fea9cb91Slq150181 
180*aecfc01dSrui zang - Sun Microsystems - Beijing China 	list_remove(&tems.ts_list, tem);
181fea9cb91Slq150181 }
182fea9cb91Slq150181 
183fea9cb91Slq150181 /*
184fea9cb91Slq150181  * This is the main entry point to the module.  It handles output requests
185fea9cb91Slq150181  * during normal system operation, when (e.g.) mutexes are available.
186fea9cb91Slq150181  */
187fea9cb91Slq150181 void
tem_write(tem_vt_state_t tem_arg,uchar_t * buf,ssize_t len,cred_t * credp)188*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_write(tem_vt_state_t tem_arg, uchar_t *buf, ssize_t len, cred_t *credp)
189fea9cb91Slq150181 {
190*aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
191fea9cb91Slq150181 
192*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
193*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tem->tvs_lock);
194fea9cb91Slq150181 
195*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (!tem->tvs_initialized) {
196*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tem->tvs_lock);
197*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
198*aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
199*aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
200fea9cb91Slq150181 
201*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_safe_check_first_time(tem, credp, CALLED_FROM_NORMAL);
202*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_safe_terminal_emulate(tem, buf, len, credp, CALLED_FROM_NORMAL);
203*aecfc01dSrui zang - Sun Microsystems - Beijing China 
204*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tem->tvs_lock);
205*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
206*aecfc01dSrui zang - Sun Microsystems - Beijing China }
207*aecfc01dSrui zang - Sun Microsystems - Beijing China 
208*aecfc01dSrui zang - Sun Microsystems - Beijing China static void
tem_internal_init(struct tem_vt_state * ptem,cred_t * credp,boolean_t init_color,boolean_t clear_screen)209*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_internal_init(struct tem_vt_state *ptem, cred_t *credp,
210*aecfc01dSrui zang - Sun Microsystems - Beijing China     boolean_t init_color, boolean_t clear_screen)
211*aecfc01dSrui zang - Sun Microsystems - Beijing China {
212*aecfc01dSrui zang - Sun Microsystems - Beijing China 	int i, j;
213*aecfc01dSrui zang - Sun Microsystems - Beijing China 	int width, height;
214*aecfc01dSrui zang - Sun Microsystems - Beijing China 	int total;
215*aecfc01dSrui zang - Sun Microsystems - Beijing China 	text_color_t fg;
216*aecfc01dSrui zang - Sun Microsystems - Beijing China 	text_color_t bg;
217*aecfc01dSrui zang - Sun Microsystems - Beijing China 	size_t	tc_size = sizeof (text_color_t);
218*aecfc01dSrui zang - Sun Microsystems - Beijing China 
219*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&ptem->tvs_lock));
220*aecfc01dSrui zang - Sun Microsystems - Beijing China 
221*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tems.ts_display_mode == VIS_PIXEL) {
222*aecfc01dSrui zang - Sun Microsystems - Beijing China 		ptem->tvs_pix_data_size = tems.ts_pix_data_size;
223*aecfc01dSrui zang - Sun Microsystems - Beijing China 		ptem->tvs_pix_data =
224*aecfc01dSrui zang - Sun Microsystems - Beijing China 		    kmem_alloc(ptem->tvs_pix_data_size, KM_SLEEP);
225*aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
226*aecfc01dSrui zang - Sun Microsystems - Beijing China 
227*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ptem->tvs_outbuf_size = tems.ts_c_dimension.width;
228*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ptem->tvs_outbuf =
229*aecfc01dSrui zang - Sun Microsystems - Beijing China 	    (unsigned char *)kmem_alloc(ptem->tvs_outbuf_size, KM_SLEEP);
230*aecfc01dSrui zang - Sun Microsystems - Beijing China 
231*aecfc01dSrui zang - Sun Microsystems - Beijing China 	width = tems.ts_c_dimension.width;
232*aecfc01dSrui zang - Sun Microsystems - Beijing China 	height = tems.ts_c_dimension.height;
233*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ptem->tvs_screen_buf_size = width * height;
234*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ptem->tvs_screen_buf =
235*aecfc01dSrui zang - Sun Microsystems - Beijing China 	    (unsigned char *)kmem_alloc(width * height, KM_SLEEP);
236*aecfc01dSrui zang - Sun Microsystems - Beijing China 
237*aecfc01dSrui zang - Sun Microsystems - Beijing China 	total = width * height * tc_size;
238*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ptem->tvs_fg_buf = (text_color_t *)kmem_alloc(total, KM_SLEEP);
239*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ptem->tvs_bg_buf = (text_color_t *)kmem_alloc(total, KM_SLEEP);
240*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ptem->tvs_color_buf_size = total;
241*aecfc01dSrui zang - Sun Microsystems - Beijing China 
242*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_safe_reset_display(ptem, credp, CALLED_FROM_NORMAL,
243*aecfc01dSrui zang - Sun Microsystems - Beijing China 	    clear_screen, init_color);
244*aecfc01dSrui zang - Sun Microsystems - Beijing China 
245*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_safe_get_color(ptem, &fg, &bg, TEM_ATTR_SCREEN_REVERSE);
246*aecfc01dSrui zang - Sun Microsystems - Beijing China 	for (i = 0; i < height; i++)
247*aecfc01dSrui zang - Sun Microsystems - Beijing China 		for (j = 0; j < width; j++) {
248*aecfc01dSrui zang - Sun Microsystems - Beijing China 			ptem->tvs_screen_buf[i * width + j] = ' ';
249*aecfc01dSrui zang - Sun Microsystems - Beijing China 			ptem->tvs_fg_buf[(i * width +j) * tc_size] = fg;
250*aecfc01dSrui zang - Sun Microsystems - Beijing China 			ptem->tvs_bg_buf[(i * width +j) * tc_size] = bg;
251*aecfc01dSrui zang - Sun Microsystems - Beijing China 
252*aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
253*aecfc01dSrui zang - Sun Microsystems - Beijing China 
254*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ptem->tvs_initialized  = 1;
255fea9cb91Slq150181 }
256fea9cb91Slq150181 
257fea9cb91Slq150181 int
tem_initialized(tem_vt_state_t tem_arg)258*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_initialized(tem_vt_state_t tem_arg)
259fea9cb91Slq150181 {
260*aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *ptem = (struct tem_vt_state *)tem_arg;
261*aecfc01dSrui zang - Sun Microsystems - Beijing China 	int ret;
262*aecfc01dSrui zang - Sun Microsystems - Beijing China 
263*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&ptem->tvs_lock);
264*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ret = ptem->tvs_initialized;
265*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&ptem->tvs_lock);
266*aecfc01dSrui zang - Sun Microsystems - Beijing China 
267*aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (ret);
268*aecfc01dSrui zang - Sun Microsystems - Beijing China }
269*aecfc01dSrui zang - Sun Microsystems - Beijing China 
270*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_vt_state_t
tem_init(cred_t * credp)271*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_init(cred_t *credp)
272*aecfc01dSrui zang - Sun Microsystems - Beijing China {
273*aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *ptem;
274*aecfc01dSrui zang - Sun Microsystems - Beijing China 
275*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ptem = kmem_zalloc(sizeof (struct tem_vt_state), KM_SLEEP);
276*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_init(&ptem->tvs_lock, (char *)NULL, MUTEX_DRIVER, NULL);
277*aecfc01dSrui zang - Sun Microsystems - Beijing China 
278*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
279*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&ptem->tvs_lock);
280*aecfc01dSrui zang - Sun Microsystems - Beijing China 
281*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ptem->tvs_isactive = B_FALSE;
282*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ptem->tvs_fbmode = KD_TEXT;
283*aecfc01dSrui zang - Sun Microsystems - Beijing China 
284*aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
285*aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * A tem is regarded as initialized only after tem_internal_init(),
286*aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * will be set at the end of tem_internal_init().
287*aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
288*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ptem->tvs_initialized = 0;
289*aecfc01dSrui zang - Sun Microsystems - Beijing China 
290*aecfc01dSrui zang - Sun Microsystems - Beijing China 
291*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (!tems.ts_initialized) {
292*aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
293*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * Only happens during early console configuration.
294*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
295*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_add(ptem);
296*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&ptem->tvs_lock);
297*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
298*aecfc01dSrui zang - Sun Microsystems - Beijing China 		return ((tem_vt_state_t)ptem);
299*aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
300*aecfc01dSrui zang - Sun Microsystems - Beijing China 
301*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_internal_init(ptem, credp, B_TRUE, B_FALSE);
302*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_add(ptem);
303*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&ptem->tvs_lock);
304*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
305*aecfc01dSrui zang - Sun Microsystems - Beijing China 
306*aecfc01dSrui zang - Sun Microsystems - Beijing China 	return ((tem_vt_state_t)ptem);
307*aecfc01dSrui zang - Sun Microsystems - Beijing China }
308*aecfc01dSrui zang - Sun Microsystems - Beijing China 
309*aecfc01dSrui zang - Sun Microsystems - Beijing China /*
310*aecfc01dSrui zang - Sun Microsystems - Beijing China  * re-init the tem after video mode has changed and tems_info has
311*aecfc01dSrui zang - Sun Microsystems - Beijing China  * been re-inited. The lock is already held.
312*aecfc01dSrui zang - Sun Microsystems - Beijing China  */
313*aecfc01dSrui zang - Sun Microsystems - Beijing China static void
tem_reinit(struct tem_vt_state * tem,boolean_t reset_display)314*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_reinit(struct tem_vt_state *tem, boolean_t reset_display)
315*aecfc01dSrui zang - Sun Microsystems - Beijing China {
316*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock));
317*aecfc01dSrui zang - Sun Microsystems - Beijing China 
318*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_free_buf(tem); /* only free virtual buffers */
319*aecfc01dSrui zang - Sun Microsystems - Beijing China 
320*aecfc01dSrui zang - Sun Microsystems - Beijing China 	/* reserve color */
321*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_internal_init(tem, kcred, B_FALSE, reset_display);
322*aecfc01dSrui zang - Sun Microsystems - Beijing China }
323*aecfc01dSrui zang - Sun Microsystems - Beijing China 
324*aecfc01dSrui zang - Sun Microsystems - Beijing China static void
tem_free_buf(struct tem_vt_state * tem)325*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_free_buf(struct tem_vt_state *tem)
326*aecfc01dSrui zang - Sun Microsystems - Beijing China {
327*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(tem != NULL && MUTEX_HELD(&tem->tvs_lock));
328*aecfc01dSrui zang - Sun Microsystems - Beijing China 
329*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tem->tvs_outbuf != NULL)
330*aecfc01dSrui zang - Sun Microsystems - Beijing China 		kmem_free(tem->tvs_outbuf, tem->tvs_outbuf_size);
331*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tem->tvs_pix_data != NULL)
332*aecfc01dSrui zang - Sun Microsystems - Beijing China 		kmem_free(tem->tvs_pix_data, tem->tvs_pix_data_size);
333*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tem->tvs_screen_buf != NULL)
334*aecfc01dSrui zang - Sun Microsystems - Beijing China 		kmem_free(tem->tvs_screen_buf, tem->tvs_screen_buf_size);
335*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tem->tvs_fg_buf != NULL)
336*aecfc01dSrui zang - Sun Microsystems - Beijing China 		kmem_free(tem->tvs_fg_buf, tem->tvs_color_buf_size);
337*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tem->tvs_bg_buf != NULL)
338*aecfc01dSrui zang - Sun Microsystems - Beijing China 		kmem_free(tem->tvs_bg_buf, tem->tvs_color_buf_size);
339*aecfc01dSrui zang - Sun Microsystems - Beijing China }
340*aecfc01dSrui zang - Sun Microsystems - Beijing China 
341*aecfc01dSrui zang - Sun Microsystems - Beijing China void
tem_destroy(tem_vt_state_t tem_arg,cred_t * credp)342*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_destroy(tem_vt_state_t tem_arg, cred_t *credp)
343*aecfc01dSrui zang - Sun Microsystems - Beijing China {
344*aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
345*aecfc01dSrui zang - Sun Microsystems - Beijing China 
346*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
347*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tem->tvs_lock);
348*aecfc01dSrui zang - Sun Microsystems - Beijing China 
349*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tem->tvs_isactive && tem->tvs_fbmode == KD_TEXT)
350*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_safe_blank_screen(tem, credp, CALLED_FROM_NORMAL);
351*aecfc01dSrui zang - Sun Microsystems - Beijing China 
352*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_free_buf(tem);
353*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_rm(tem);
354*aecfc01dSrui zang - Sun Microsystems - Beijing China 
355*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tems.ts_active == tem)
356*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_active = NULL;
357*aecfc01dSrui zang - Sun Microsystems - Beijing China 
358*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tem->tvs_lock);
359*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
360*aecfc01dSrui zang - Sun Microsystems - Beijing China 
361*aecfc01dSrui zang - Sun Microsystems - Beijing China 	kmem_free(tem, sizeof (struct tem_vt_state));
362*aecfc01dSrui zang - Sun Microsystems - Beijing China }
363*aecfc01dSrui zang - Sun Microsystems - Beijing China 
364*aecfc01dSrui zang - Sun Microsystems - Beijing China static int
tems_failed(cred_t * credp,boolean_t finish_ioctl)365*aecfc01dSrui zang - Sun Microsystems - Beijing China tems_failed(cred_t *credp, boolean_t finish_ioctl)
366*aecfc01dSrui zang - Sun Microsystems - Beijing China {
367fea9cb91Slq150181 	int	lyr_rval;
368fea9cb91Slq150181 
369*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(MUTEX_HELD(&tems.ts_lock));
370fea9cb91Slq150181 
371*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (finish_ioctl)
372*aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) ldi_ioctl(tems.ts_hdl, VIS_DEVFINI, 0,
373*aecfc01dSrui zang - Sun Microsystems - Beijing China 		    FWRITE|FKIOCTL, credp, &lyr_rval);
374fea9cb91Slq150181 
375*aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) ldi_close(tems.ts_hdl, NULL, credp);
376*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_hdl = NULL;
377*aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (ENXIO);
378*aecfc01dSrui zang - Sun Microsystems - Beijing China }
379*aecfc01dSrui zang - Sun Microsystems - Beijing China 
380*aecfc01dSrui zang - Sun Microsystems - Beijing China /*
381*aecfc01dSrui zang - Sun Microsystems - Beijing China  * only called once during boot
382*aecfc01dSrui zang - Sun Microsystems - Beijing China  */
383*aecfc01dSrui zang - Sun Microsystems - Beijing China int
tem_info_init(char * pathname,cred_t * credp)384*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_info_init(char *pathname, cred_t *credp)
385*aecfc01dSrui zang - Sun Microsystems - Beijing China {
386*aecfc01dSrui zang - Sun Microsystems - Beijing China 	int			lyr_rval, ret;
387*aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct vis_devinit	temargs;
388*aecfc01dSrui zang - Sun Microsystems - Beijing China 	char			*pathbuf;
389*aecfc01dSrui zang - Sun Microsystems - Beijing China 	size_t height = 0;
390*aecfc01dSrui zang - Sun Microsystems - Beijing China 	size_t width = 0;
391*aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *p;
392*aecfc01dSrui zang - Sun Microsystems - Beijing China 
393*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
394*aecfc01dSrui zang - Sun Microsystems - Beijing China 
395*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tems.ts_initialized) {
396*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
397*aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (0);
398*aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
399fea9cb91Slq150181 
400fea9cb91Slq150181 	/*
401fea9cb91Slq150181 	 * Open the layered device using the devfs physical device name
402fea9cb91Slq150181 	 * after adding the /devices prefix.
403fea9cb91Slq150181 	 */
404fea9cb91Slq150181 	pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
405fea9cb91Slq150181 	(void) strcpy(pathbuf, "/devices");
406fea9cb91Slq150181 	if (i_ddi_prompath_to_devfspath(pathname,
407fea9cb91Slq150181 	    pathbuf + strlen("/devices")) != DDI_SUCCESS) {
408*aecfc01dSrui zang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "terminal-emulator:  path conversion error");
409fea9cb91Slq150181 		kmem_free(pathbuf, MAXPATHLEN);
410*aecfc01dSrui zang - Sun Microsystems - Beijing China 
411*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
412fea9cb91Slq150181 		return (ENXIO);
413fea9cb91Slq150181 	}
414*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (ldi_open_by_name(pathbuf, FWRITE, credp,
415*aecfc01dSrui zang - Sun Microsystems - Beijing China 	    &tems.ts_hdl, term_li) != 0) {
416*aecfc01dSrui zang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "terminal-emulator:  device path open error");
417fea9cb91Slq150181 		kmem_free(pathbuf, MAXPATHLEN);
418*aecfc01dSrui zang - Sun Microsystems - Beijing China 
419*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
420fea9cb91Slq150181 		return (ENXIO);
421fea9cb91Slq150181 	}
422fea9cb91Slq150181 	kmem_free(pathbuf, MAXPATHLEN);
423fea9cb91Slq150181 
424*aecfc01dSrui zang - Sun Microsystems - Beijing China 	temargs.modechg_cb  = (vis_modechg_cb_t)tems_modechange_callback;
425*aecfc01dSrui zang - Sun Microsystems - Beijing China 	temargs.modechg_arg = NULL;
426fea9cb91Slq150181 
427fea9cb91Slq150181 	/*
428fea9cb91Slq150181 	 * Initialize the console and get the device parameters
429fea9cb91Slq150181 	 */
430*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (ldi_ioctl(tems.ts_hdl, VIS_DEVINIT,
431*aecfc01dSrui zang - Sun Microsystems - Beijing China 	    (intptr_t)&temargs, FWRITE|FKIOCTL, credp, &lyr_rval) != 0) {
432fea9cb91Slq150181 		cmn_err(CE_WARN, "terminal emulator: Compatible fb not found");
433*aecfc01dSrui zang - Sun Microsystems - Beijing China 		ret = tems_failed(credp, B_FALSE);
434*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
435*aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (ret);
436fea9cb91Slq150181 	}
437fea9cb91Slq150181 
438fea9cb91Slq150181 	/* Make sure the fb driver and terminal emulator versions match */
439*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (temargs.version != VIS_CONS_REV) {
440fea9cb91Slq150181 		cmn_err(CE_WARN,
441fea9cb91Slq150181 		    "terminal emulator: VIS_CONS_REV %d (see sys/visual_io.h) "
442*aecfc01dSrui zang - Sun Microsystems - Beijing China 		    "of console fb driver not supported", temargs.version);
443*aecfc01dSrui zang - Sun Microsystems - Beijing China 		ret = tems_failed(credp, B_TRUE);
444*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
445*aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (ret);
446fea9cb91Slq150181 	}
447fea9cb91Slq150181 
448*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((tems.ts_fb_polledio = temargs.polledio) == NULL) {
449fea9cb91Slq150181 		cmn_err(CE_WARN, "terminal emulator: fb doesn't support polled "
450fea9cb91Slq150181 		    "I/O");
451*aecfc01dSrui zang - Sun Microsystems - Beijing China 		ret = tems_failed(credp, B_TRUE);
452*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
453*aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (ret);
454fea9cb91Slq150181 	}
455fea9cb91Slq150181 
456fea9cb91Slq150181 	/* other sanity checks */
457*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (!((temargs.depth == 4) || (temargs.depth == 8) ||
458*aecfc01dSrui zang - Sun Microsystems - Beijing China 	    (temargs.depth == 24) || (temargs.depth == 32))) {
459fea9cb91Slq150181 		cmn_err(CE_WARN, "terminal emulator: unsupported depth");
460*aecfc01dSrui zang - Sun Microsystems - Beijing China 		ret = tems_failed(credp, B_TRUE);
461*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
462*aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (ret);
463fea9cb91Slq150181 	}
464fea9cb91Slq150181 
465*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((temargs.mode != VIS_TEXT) && (temargs.mode != VIS_PIXEL)) {
466fea9cb91Slq150181 		cmn_err(CE_WARN, "terminal emulator: unsupported mode");
467*aecfc01dSrui zang - Sun Microsystems - Beijing China 		ret = tems_failed(credp, B_TRUE);
468*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
469*aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (ret);
470fea9cb91Slq150181 	}
471fea9cb91Slq150181 
472*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((temargs.mode == VIS_PIXEL) && plat_stdout_is_framebuffer())
473fea9cb91Slq150181 		plat_tem_get_prom_size(&height, &width);
474*aecfc01dSrui zang - Sun Microsystems - Beijing China 
475*aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
476*aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * Initialize the common terminal emulator info
477*aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
478*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems_setup_terminal(&temargs, height, width);
479*aecfc01dSrui zang - Sun Microsystems - Beijing China 
480*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems_reset_colormap(credp, CALLED_FROM_NORMAL);
481*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems_get_initial_color(&tems.ts_init_color);
482*aecfc01dSrui zang - Sun Microsystems - Beijing China 
483*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_initialized = 1; /* initialization flag */
484*aecfc01dSrui zang - Sun Microsystems - Beijing China 
485*aecfc01dSrui zang - Sun Microsystems - Beijing China 	for (p = list_head(&tems.ts_list); p != NULL;
486*aecfc01dSrui zang - Sun Microsystems - Beijing China 	    p = list_next(&tems.ts_list, p)) {
487*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_enter(&p->tvs_lock);
488*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_internal_init(p, credp, B_TRUE, B_FALSE);
489*aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (temargs.mode == VIS_PIXEL)
490*aecfc01dSrui zang - Sun Microsystems - Beijing China 			tem_pix_align(p, credp, CALLED_FROM_NORMAL);
491*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&p->tvs_lock);
492fea9cb91Slq150181 	}
493fea9cb91Slq150181 
494*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
495fea9cb91Slq150181 	return (0);
496fea9cb91Slq150181 }
497fea9cb91Slq150181 
498*aecfc01dSrui zang - Sun Microsystems - Beijing China #define	TEMS_DEPTH_DIFF		0x01
499*aecfc01dSrui zang - Sun Microsystems - Beijing China #define	TEMS_DIMENSION_DIFF	0x02
500*aecfc01dSrui zang - Sun Microsystems - Beijing China 
501*aecfc01dSrui zang - Sun Microsystems - Beijing China static uchar_t
tems_check_videomode(struct vis_devinit * tp)502*aecfc01dSrui zang - Sun Microsystems - Beijing China tems_check_videomode(struct vis_devinit *tp)
503*aecfc01dSrui zang - Sun Microsystems - Beijing China {
504*aecfc01dSrui zang - Sun Microsystems - Beijing China 	uchar_t result = 0;
505*aecfc01dSrui zang - Sun Microsystems - Beijing China 
506*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tems.ts_pdepth != tp->depth)
507*aecfc01dSrui zang - Sun Microsystems - Beijing China 		result |= TEMS_DEPTH_DIFF;
508*aecfc01dSrui zang - Sun Microsystems - Beijing China 
509*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tp->mode == VIS_TEXT) {
510*aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (tems.ts_c_dimension.width != tp->width ||
511*aecfc01dSrui zang - Sun Microsystems - Beijing China 		    tems.ts_c_dimension.height != tp->height)
512*aecfc01dSrui zang - Sun Microsystems - Beijing China 			result |= TEMS_DIMENSION_DIFF;
513*aecfc01dSrui zang - Sun Microsystems - Beijing China 	} else {
514*aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (tems.ts_p_dimension.width != tp->width ||
515*aecfc01dSrui zang - Sun Microsystems - Beijing China 		    tems.ts_p_dimension.height != tp->height)
516*aecfc01dSrui zang - Sun Microsystems - Beijing China 			result |= TEMS_DIMENSION_DIFF;
517*aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
518*aecfc01dSrui zang - Sun Microsystems - Beijing China 
519*aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (result);
520*aecfc01dSrui zang - Sun Microsystems - Beijing China }
521*aecfc01dSrui zang - Sun Microsystems - Beijing China 
522*aecfc01dSrui zang - Sun Microsystems - Beijing China static void
tems_setup_terminal(struct vis_devinit * tp,size_t height,size_t width)523*aecfc01dSrui zang - Sun Microsystems - Beijing China tems_setup_terminal(struct vis_devinit *tp, size_t height, size_t width)
524*aecfc01dSrui zang - Sun Microsystems - Beijing China {
525*aecfc01dSrui zang - Sun Microsystems - Beijing China 	int i;
526*aecfc01dSrui zang - Sun Microsystems - Beijing China 	int old_blank_buf_size = tems.ts_c_dimension.width;
527*aecfc01dSrui zang - Sun Microsystems - Beijing China 
528*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(MUTEX_HELD(&tems.ts_lock));
529*aecfc01dSrui zang - Sun Microsystems - Beijing China 
530*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_pdepth = tp->depth;
531*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_linebytes = tp->linebytes;
532*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_display_mode = tp->mode;
533*aecfc01dSrui zang - Sun Microsystems - Beijing China 
534*aecfc01dSrui zang - Sun Microsystems - Beijing China 	switch (tp->mode) {
535*aecfc01dSrui zang - Sun Microsystems - Beijing China 	case VIS_TEXT:
536*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_p_dimension.width = 0;
537*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_p_dimension.height = 0;
538*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_c_dimension.width = tp->width;
539*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_c_dimension.height = tp->height;
540*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_callbacks = &tem_safe_text_callbacks;
541*aecfc01dSrui zang - Sun Microsystems - Beijing China 
542*aecfc01dSrui zang - Sun Microsystems - Beijing China 		break;
543*aecfc01dSrui zang - Sun Microsystems - Beijing China 
544*aecfc01dSrui zang - Sun Microsystems - Beijing China 	case VIS_PIXEL:
545*aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
546*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * First check to see if the user has specified a screen size.
547*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * If so, use those values.  Else use 34x80 as the default.
548*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
549*aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (width == 0) {
550*aecfc01dSrui zang - Sun Microsystems - Beijing China 			width = TEM_DEFAULT_COLS;
551*aecfc01dSrui zang - Sun Microsystems - Beijing China 			height = TEM_DEFAULT_ROWS;
552*aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
553*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_c_dimension.height = (screen_size_t)height;
554*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_c_dimension.width = (screen_size_t)width;
555*aecfc01dSrui zang - Sun Microsystems - Beijing China 
556*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_p_dimension.height = tp->height;
557*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_p_dimension.width = tp->width;
558*aecfc01dSrui zang - Sun Microsystems - Beijing China 
559*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_callbacks = &tem_safe_pix_callbacks;
560*aecfc01dSrui zang - Sun Microsystems - Beijing China 
561*aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
562*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * set_font() will select a appropriate sized font for
563*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * the number of rows and columns selected.  If we don't
564*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * have a font that will fit, then it will use the
565*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * default builtin font and adjust the rows and columns
566*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * to fit on the screen.
567*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
568*aecfc01dSrui zang - Sun Microsystems - Beijing China 		set_font(&tems.ts_font,
569*aecfc01dSrui zang - Sun Microsystems - Beijing China 		    &tems.ts_c_dimension.height,
570*aecfc01dSrui zang - Sun Microsystems - Beijing China 		    &tems.ts_c_dimension.width,
571*aecfc01dSrui zang - Sun Microsystems - Beijing China 		    tems.ts_p_dimension.height,
572*aecfc01dSrui zang - Sun Microsystems - Beijing China 		    tems.ts_p_dimension.width);
573*aecfc01dSrui zang - Sun Microsystems - Beijing China 
574*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_p_offset.y = (tems.ts_p_dimension.height -
575*aecfc01dSrui zang - Sun Microsystems - Beijing China 		    (tems.ts_c_dimension.height * tems.ts_font.height)) / 2;
576*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_p_offset.x = (tems.ts_p_dimension.width -
577*aecfc01dSrui zang - Sun Microsystems - Beijing China 		    (tems.ts_c_dimension.width * tems.ts_font.width)) / 2;
578*aecfc01dSrui zang - Sun Microsystems - Beijing China 
579*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_pix_data_size =
580*aecfc01dSrui zang - Sun Microsystems - Beijing China 		    tems.ts_font.width * tems.ts_font.height;
581*aecfc01dSrui zang - Sun Microsystems - Beijing China 
582*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_pix_data_size *= 4;
583*aecfc01dSrui zang - Sun Microsystems - Beijing China 
584*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_pdepth = tp->depth;
585*aecfc01dSrui zang - Sun Microsystems - Beijing China 
586*aecfc01dSrui zang - Sun Microsystems - Beijing China 		break;
587*aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
588*aecfc01dSrui zang - Sun Microsystems - Beijing China 
589*aecfc01dSrui zang - Sun Microsystems - Beijing China 	/* Now virtual cls also uses the blank_line buffer */
590*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tems.ts_blank_line)
591*aecfc01dSrui zang - Sun Microsystems - Beijing China 		kmem_free(tems.ts_blank_line, old_blank_buf_size);
592*aecfc01dSrui zang - Sun Microsystems - Beijing China 
593*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_blank_line = (unsigned char *)
594*aecfc01dSrui zang - Sun Microsystems - Beijing China 	    kmem_alloc(tems.ts_c_dimension.width, KM_SLEEP);
595*aecfc01dSrui zang - Sun Microsystems - Beijing China 	for (i = 0; i < tems.ts_c_dimension.width; i++)
596*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_blank_line[i] = ' ';
597*aecfc01dSrui zang - Sun Microsystems - Beijing China }
598*aecfc01dSrui zang - Sun Microsystems - Beijing China 
599fea9cb91Slq150181 /*
600fea9cb91Slq150181  * This is a callback function that we register with the frame
601fea9cb91Slq150181  * buffer driver layered underneath.  It gets invoked from
602fea9cb91Slq150181  * the underlying frame buffer driver to reconfigure the terminal
603fea9cb91Slq150181  * emulator to a new screen size and depth in conjunction with
604fea9cb91Slq150181  * framebuffer videomode changes.
605c9503a49Slq150181  * Here we keep the foreground/background color and attributes,
606c9503a49Slq150181  * which may be different with the initial settings, so that
607c9503a49Slq150181  * the color won't change while the framebuffer videomode changes.
608c9503a49Slq150181  * And we also reset the kernel terminal emulator and clear the
609c9503a49Slq150181  * whole screen.
610fea9cb91Slq150181  */
611*aecfc01dSrui zang - Sun Microsystems - Beijing China /* ARGSUSED */
612fea9cb91Slq150181 void
tems_modechange_callback(struct vis_modechg_arg * arg,struct vis_devinit * devinit)613*aecfc01dSrui zang - Sun Microsystems - Beijing China tems_modechange_callback(struct vis_modechg_arg *arg,
614*aecfc01dSrui zang - Sun Microsystems - Beijing China     struct vis_devinit *devinit)
615fea9cb91Slq150181 {
616*aecfc01dSrui zang - Sun Microsystems - Beijing China 	uchar_t diff;
617*aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *p;
618*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_modechg_cb_t cb;
619*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_modechg_cb_arg_t cb_arg;
620c9503a49Slq150181 
621*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(!(list_is_empty(&tems.ts_list)));
622fea9cb91Slq150181 
623*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
624fea9cb91Slq150181 
625fea9cb91Slq150181 	/*
626*aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * currently only for pixel mode
627fea9cb91Slq150181 	 */
628*aecfc01dSrui zang - Sun Microsystems - Beijing China 	diff = tems_check_videomode(devinit);
629*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (diff == 0) {
630*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
631*aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
632fea9cb91Slq150181 	}
633fea9cb91Slq150181 
634*aecfc01dSrui zang - Sun Microsystems - Beijing China 	diff = diff & TEMS_DIMENSION_DIFF;
635fea9cb91Slq150181 
636*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (diff == 0) {
637fea9cb91Slq150181 		/*
638*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * Only need to reinit the active tem.
639fea9cb91Slq150181 		 */
640*aecfc01dSrui zang - Sun Microsystems - Beijing China 		struct tem_vt_state *active = tems.ts_active;
641*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_pdepth = devinit->depth;
642*aecfc01dSrui zang - Sun Microsystems - Beijing China 
643*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_enter(&active->tvs_lock);
644*aecfc01dSrui zang - Sun Microsystems - Beijing China 		ASSERT(active->tvs_isactive);
645*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_reinit(active, B_TRUE);
646*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&active->tvs_lock);
647*aecfc01dSrui zang - Sun Microsystems - Beijing China 
648*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
649*aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
650fea9cb91Slq150181 	}
651fea9cb91Slq150181 
652*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems_setup_terminal(devinit, tems.ts_c_dimension.height,
653*aecfc01dSrui zang - Sun Microsystems - Beijing China 	    tems.ts_c_dimension.width);
654*aecfc01dSrui zang - Sun Microsystems - Beijing China 
655*aecfc01dSrui zang - Sun Microsystems - Beijing China 	for (p = list_head(&tems.ts_list); p != NULL;
656*aecfc01dSrui zang - Sun Microsystems - Beijing China 	    p = list_next(&tems.ts_list, p)) {
657*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_enter(&p->tvs_lock);
658*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_reinit(p, p->tvs_isactive);
659*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&p->tvs_lock);
660*aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
661*aecfc01dSrui zang - Sun Microsystems - Beijing China 
662*aecfc01dSrui zang - Sun Microsystems - Beijing China 
663*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tems.ts_modechg_cb == NULL) {
664*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
665*aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
666*aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
667*aecfc01dSrui zang - Sun Microsystems - Beijing China 
668*aecfc01dSrui zang - Sun Microsystems - Beijing China 	cb = tems.ts_modechg_cb;
669*aecfc01dSrui zang - Sun Microsystems - Beijing China 	cb_arg = tems.ts_modechg_arg;
670fea9cb91Slq150181 
671fea9cb91Slq150181 	/*
672*aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * Release the lock while doing callback.
673fea9cb91Slq150181 	 */
674*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
675*aecfc01dSrui zang - Sun Microsystems - Beijing China 	cb(cb_arg);
676fea9cb91Slq150181 }
677fea9cb91Slq150181 
678fea9cb91Slq150181 /*
679fea9cb91Slq150181  * This function is used to display a rectangular blit of data
680fea9cb91Slq150181  * of a given size and location via the underlying framebuffer driver.
681fea9cb91Slq150181  * The blit can be as small as a pixel or as large as the screen.
682fea9cb91Slq150181  */
683fea9cb91Slq150181 void
tems_display_layered(struct vis_consdisplay * pda,cred_t * credp)684*aecfc01dSrui zang - Sun Microsystems - Beijing China tems_display_layered(
685fea9cb91Slq150181 	struct vis_consdisplay *pda,
686fea9cb91Slq150181 	cred_t *credp)
687fea9cb91Slq150181 {
688fea9cb91Slq150181 	int rval;
689fea9cb91Slq150181 
690*aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) ldi_ioctl(tems.ts_hdl, VIS_CONSDISPLAY,
691fea9cb91Slq150181 	    (intptr_t)pda, FKIOCTL, credp, &rval);
692fea9cb91Slq150181 }
693fea9cb91Slq150181 
694fea9cb91Slq150181 /*
695fea9cb91Slq150181  * This function is used to invoke a block copy operation in the
696fea9cb91Slq150181  * underlying framebuffer driver.  Rectangle copies are how scrolling
697fea9cb91Slq150181  * is implemented, as well as horizontal text shifting escape seqs.
698fea9cb91Slq150181  * such as from vi when deleting characters and words.
699fea9cb91Slq150181  */
700fea9cb91Slq150181 void
tems_copy_layered(struct vis_conscopy * pma,cred_t * credp)701*aecfc01dSrui zang - Sun Microsystems - Beijing China tems_copy_layered(
702fea9cb91Slq150181 	struct vis_conscopy *pma,
703fea9cb91Slq150181 	cred_t *credp)
704fea9cb91Slq150181 {
705fea9cb91Slq150181 	int rval;
706fea9cb91Slq150181 
707*aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) ldi_ioctl(tems.ts_hdl, VIS_CONSCOPY,
708fea9cb91Slq150181 	    (intptr_t)pma, FKIOCTL, credp, &rval);
709fea9cb91Slq150181 }
710fea9cb91Slq150181 
711fea9cb91Slq150181 /*
712fea9cb91Slq150181  * This function is used to show or hide a rectangluar monochrom
713fea9cb91Slq150181  * pixel inverting, text block cursor via the underlying framebuffer.
714fea9cb91Slq150181  */
715fea9cb91Slq150181 void
tems_cursor_layered(struct vis_conscursor * pca,cred_t * credp)716*aecfc01dSrui zang - Sun Microsystems - Beijing China tems_cursor_layered(
717fea9cb91Slq150181 	struct vis_conscursor *pca,
718fea9cb91Slq150181 	cred_t *credp)
719fea9cb91Slq150181 {
720fea9cb91Slq150181 	int rval;
721fea9cb91Slq150181 
722*aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) ldi_ioctl(tems.ts_hdl, VIS_CONSCURSOR,
723fea9cb91Slq150181 	    (intptr_t)pca, FKIOCTL, credp, &rval);
724fea9cb91Slq150181 }
725fea9cb91Slq150181 
726*aecfc01dSrui zang - Sun Microsystems - Beijing China static void
tem_kdsetmode(int mode,cred_t * credp)727*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_kdsetmode(int mode, cred_t *credp)
728*aecfc01dSrui zang - Sun Microsystems - Beijing China {
729*aecfc01dSrui zang - Sun Microsystems - Beijing China 	int rval;
730*aecfc01dSrui zang - Sun Microsystems - Beijing China 
731*aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) ldi_ioctl(tems.ts_hdl, KDSETMODE,
732*aecfc01dSrui zang - Sun Microsystems - Beijing China 	    (intptr_t)mode, FKIOCTL, credp, &rval);
733*aecfc01dSrui zang - Sun Microsystems - Beijing China 
734*aecfc01dSrui zang - Sun Microsystems - Beijing China }
735*aecfc01dSrui zang - Sun Microsystems - Beijing China 
736*aecfc01dSrui zang - Sun Microsystems - Beijing China static void
tems_reset_colormap(cred_t * credp,enum called_from called_from)737*aecfc01dSrui zang - Sun Microsystems - Beijing China tems_reset_colormap(cred_t *credp, enum called_from called_from)
738fea9cb91Slq150181 {
739fea9cb91Slq150181 	struct vis_cmap cm;
740fea9cb91Slq150181 	int rval;
741fea9cb91Slq150181 
742fea9cb91Slq150181 	if (called_from == CALLED_FROM_STANDALONE)
743fea9cb91Slq150181 		return;
744fea9cb91Slq150181 
745*aecfc01dSrui zang - Sun Microsystems - Beijing China 	switch (tems.ts_pdepth) {
746fea9cb91Slq150181 	case 8:
747fea9cb91Slq150181 		cm.index = 0;
748fea9cb91Slq150181 		cm.count = 16;
749fea9cb91Slq150181 		cm.red   = cmap4_to_24.red;   /* 8-bits (1/3 of TrueColor 24) */
750fea9cb91Slq150181 		cm.blue  = cmap4_to_24.blue;  /* 8-bits (1/3 of TrueColor 24) */
751fea9cb91Slq150181 		cm.green = cmap4_to_24.green; /* 8-bits (1/3 of TrueColor 24) */
752*aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) ldi_ioctl(tems.ts_hdl, VIS_PUTCMAP, (intptr_t)&cm,
753fea9cb91Slq150181 		    FKIOCTL, credp, &rval);
754fea9cb91Slq150181 		break;
755fea9cb91Slq150181 	}
756fea9cb91Slq150181 }
757fea9cb91Slq150181 
758fea9cb91Slq150181 void
tem_get_size(ushort_t * r,ushort_t * c,ushort_t * x,ushort_t * y)759*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_get_size(ushort_t *r, ushort_t *c,
760fea9cb91Slq150181 	ushort_t *x, ushort_t *y)
761fea9cb91Slq150181 {
762*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
763*aecfc01dSrui zang - Sun Microsystems - Beijing China 	*r = (ushort_t)tems.ts_c_dimension.height;
764*aecfc01dSrui zang - Sun Microsystems - Beijing China 	*c = (ushort_t)tems.ts_c_dimension.width;
765*aecfc01dSrui zang - Sun Microsystems - Beijing China 	*x = (ushort_t)tems.ts_p_dimension.width;
766*aecfc01dSrui zang - Sun Microsystems - Beijing China 	*y = (ushort_t)tems.ts_p_dimension.height;
767*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
768fea9cb91Slq150181 }
769fea9cb91Slq150181 
770fea9cb91Slq150181 void
tem_register_modechg_cb(tem_modechg_cb_t func,tem_modechg_cb_arg_t arg)771*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_register_modechg_cb(tem_modechg_cb_t func,
772fea9cb91Slq150181 	tem_modechg_cb_arg_t arg)
773fea9cb91Slq150181 {
774*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
775*aecfc01dSrui zang - Sun Microsystems - Beijing China 
776*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_modechg_cb = func;
777*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_modechg_arg = arg;
778*aecfc01dSrui zang - Sun Microsystems - Beijing China 
779*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
780fea9cb91Slq150181 }
781fea9cb91Slq150181 
782fea9cb91Slq150181 /*
783fea9cb91Slq150181  * This function is to scroll up the OBP output, which has
784fea9cb91Slq150181  * different screen height and width with our kernel console.
785fea9cb91Slq150181  */
786fea9cb91Slq150181 static void
tem_prom_scroll_up(struct tem_vt_state * tem,int nrows,cred_t * credp,enum called_from called_from)787*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_prom_scroll_up(struct tem_vt_state *tem, int nrows, cred_t *credp,
788*aecfc01dSrui zang - Sun Microsystems - Beijing China     enum called_from called_from)
789fea9cb91Slq150181 {
790fea9cb91Slq150181 	struct vis_conscopy	ma;
791fea9cb91Slq150181 	int	ncols, width;
792fea9cb91Slq150181 
793fea9cb91Slq150181 	/* copy */
794*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ma.s_row = nrows * tems.ts_font.height;
795*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ma.e_row = tems.ts_p_dimension.height - 1;
796fea9cb91Slq150181 	ma.t_row = 0;
797fea9cb91Slq150181 
798fea9cb91Slq150181 	ma.s_col = 0;
799*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ma.e_col = tems.ts_p_dimension.width - 1;
800fea9cb91Slq150181 	ma.t_col = 0;
801fea9cb91Slq150181 
802*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems_safe_copy(&ma, credp, called_from);
803fea9cb91Slq150181 
804fea9cb91Slq150181 	/* clear */
805*aecfc01dSrui zang - Sun Microsystems - Beijing China 	width = tems.ts_font.width;
806*aecfc01dSrui zang - Sun Microsystems - Beijing China 	ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
807fea9cb91Slq150181 
808*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_safe_pix_cls_range(tem, 0, nrows, tems.ts_p_offset.y,
809*aecfc01dSrui zang - Sun Microsystems - Beijing China 	    0, ncols, 0, B_TRUE, credp, called_from);
810fea9cb91Slq150181 }
811fea9cb91Slq150181 
812fea9cb91Slq150181 #define	PROM_DEFAULT_FONT_HEIGHT	22
813fea9cb91Slq150181 #define	PROM_DEFAULT_WINDOW_TOP		0x8a
814fea9cb91Slq150181 
815fea9cb91Slq150181 /*
816fea9cb91Slq150181  * This function is to compute the starting row of the console, according to
817fea9cb91Slq150181  * PROM cursor's position. Here we have to take different fonts into account.
818fea9cb91Slq150181  */
819fea9cb91Slq150181 static int
tem_adjust_row(struct tem_vt_state * tem,int prom_row,cred_t * credp,enum called_from called_from)820*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_adjust_row(struct tem_vt_state *tem, int prom_row, cred_t *credp,
821*aecfc01dSrui zang - Sun Microsystems - Beijing China     enum called_from called_from)
822fea9cb91Slq150181 {
823fea9cb91Slq150181 	int	tem_row;
824fea9cb91Slq150181 	int	tem_y;
825fea9cb91Slq150181 	int	prom_charheight = 0;
826fea9cb91Slq150181 	int	prom_window_top = 0;
827fea9cb91Slq150181 	int	scroll_up_lines;
828fea9cb91Slq150181 
829fea9cb91Slq150181 	plat_tem_get_prom_font_size(&prom_charheight, &prom_window_top);
830fea9cb91Slq150181 	if (prom_charheight == 0)
831fea9cb91Slq150181 		prom_charheight = PROM_DEFAULT_FONT_HEIGHT;
832fea9cb91Slq150181 	if (prom_window_top == 0)
833fea9cb91Slq150181 		prom_window_top = PROM_DEFAULT_WINDOW_TOP;
834fea9cb91Slq150181 
835fea9cb91Slq150181 	tem_y = (prom_row + 1) * prom_charheight + prom_window_top -
836*aecfc01dSrui zang - Sun Microsystems - Beijing China 	    tems.ts_p_offset.y;
837*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_row = (tem_y + tems.ts_font.height - 1) /
838*aecfc01dSrui zang - Sun Microsystems - Beijing China 	    tems.ts_font.height - 1;
839fea9cb91Slq150181 
840fea9cb91Slq150181 	if (tem_row < 0) {
841fea9cb91Slq150181 		tem_row = 0;
842*aecfc01dSrui zang - Sun Microsystems - Beijing China 	} else if (tem_row >= (tems.ts_c_dimension.height - 1)) {
843fea9cb91Slq150181 		/*
844fea9cb91Slq150181 		 * Scroll up the prom outputs if the PROM cursor's position is
845fea9cb91Slq150181 		 * below our tem's lower boundary.
846fea9cb91Slq150181 		 */
847fea9cb91Slq150181 		scroll_up_lines = tem_row -
848*aecfc01dSrui zang - Sun Microsystems - Beijing China 		    (tems.ts_c_dimension.height - 1);
849*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_prom_scroll_up(tem, scroll_up_lines, credp, called_from);
850*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_row = tems.ts_c_dimension.height - 1;
851fea9cb91Slq150181 	}
852fea9cb91Slq150181 
853fea9cb91Slq150181 	return (tem_row);
854fea9cb91Slq150181 }
855c9503a49Slq150181 
856*aecfc01dSrui zang - Sun Microsystems - Beijing China void
tem_pix_align(struct tem_vt_state * tem,cred_t * credp,enum called_from called_from)857*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_pix_align(struct tem_vt_state *tem, cred_t *credp,
858*aecfc01dSrui zang - Sun Microsystems - Beijing China     enum called_from called_from)
859*aecfc01dSrui zang - Sun Microsystems - Beijing China {
860*aecfc01dSrui zang - Sun Microsystems - Beijing China 	uint32_t row = 0;
861*aecfc01dSrui zang - Sun Microsystems - Beijing China 	uint32_t col = 0;
862*aecfc01dSrui zang - Sun Microsystems - Beijing China 
863*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (plat_stdout_is_framebuffer()) {
864*aecfc01dSrui zang - Sun Microsystems - Beijing China 		plat_tem_hide_prom_cursor();
865*aecfc01dSrui zang - Sun Microsystems - Beijing China 
866*aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
867*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * We are getting the current cursor position in pixel
868*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * mode so that we don't over-write the console output
869*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * during boot.
870*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
871*aecfc01dSrui zang - Sun Microsystems - Beijing China 		plat_tem_get_prom_pos(&row, &col);
872*aecfc01dSrui zang - Sun Microsystems - Beijing China 
873*aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
874*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * Adjust the row if necessary when the font of our
875*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * kernel console tem is different with that of prom
876*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * tem.
877*aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
878*aecfc01dSrui zang - Sun Microsystems - Beijing China 		row = tem_adjust_row(tem, row, credp, called_from);
879*aecfc01dSrui zang - Sun Microsystems - Beijing China 
880*aecfc01dSrui zang - Sun Microsystems - Beijing China 		/* first line of our kernel console output */
881*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem->tvs_first_line = row + 1;
882*aecfc01dSrui zang - Sun Microsystems - Beijing China 
883*aecfc01dSrui zang - Sun Microsystems - Beijing China 		/* re-set and align cusror position */
884*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem->tvs_s_cursor.row = tem->tvs_c_cursor.row =
885*aecfc01dSrui zang - Sun Microsystems - Beijing China 		    (screen_pos_t)row;
886*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem->tvs_s_cursor.col = tem->tvs_c_cursor.col = 0;
887*aecfc01dSrui zang - Sun Microsystems - Beijing China 	} else {
888*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_safe_reset_display(tem, credp, called_from, B_TRUE, B_TRUE);
889*aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
890*aecfc01dSrui zang - Sun Microsystems - Beijing China }
891*aecfc01dSrui zang - Sun Microsystems - Beijing China 
892c9503a49Slq150181 static void
tems_get_inverses(boolean_t * p_inverse,boolean_t * p_inverse_screen)893*aecfc01dSrui zang - Sun Microsystems - Beijing China tems_get_inverses(boolean_t *p_inverse, boolean_t *p_inverse_screen)
894c9503a49Slq150181 {
895c9503a49Slq150181 	int i_inverse = 0;
896c9503a49Slq150181 	int i_inverse_screen = 0;
897c9503a49Slq150181 
898c9503a49Slq150181 	plat_tem_get_inverses(&i_inverse, &i_inverse_screen);
899c9503a49Slq150181 
900c9503a49Slq150181 	*p_inverse = (i_inverse == 0) ? B_FALSE : B_TRUE;
901c9503a49Slq150181 	*p_inverse_screen = (i_inverse_screen == 0) ? B_FALSE : B_TRUE;
902c9503a49Slq150181 }
903c9503a49Slq150181 
904c9503a49Slq150181 /*
905c9503a49Slq150181  * Get the foreground/background color and attributes from the initial
906c9503a49Slq150181  * PROM, so that our kernel console can keep the same visual behaviour.
907c9503a49Slq150181  */
908c9503a49Slq150181 static void
tems_get_initial_color(tem_color_t * pcolor)909*aecfc01dSrui zang - Sun Microsystems - Beijing China tems_get_initial_color(tem_color_t *pcolor)
910c9503a49Slq150181 {
911c9503a49Slq150181 	boolean_t inverse, inverse_screen;
912c9503a49Slq150181 	unsigned short  flags = 0;
913c9503a49Slq150181 
914*aecfc01dSrui zang - Sun Microsystems - Beijing China 	pcolor->fg_color = DEFAULT_ANSI_FOREGROUND;
915*aecfc01dSrui zang - Sun Microsystems - Beijing China 	pcolor->bg_color = DEFAULT_ANSI_BACKGROUND;
916c9503a49Slq150181 
917c9503a49Slq150181 	if (plat_stdout_is_framebuffer()) {
918*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems_get_inverses(&inverse, &inverse_screen);
919c9503a49Slq150181 		if (inverse)
920c9503a49Slq150181 			flags |= TEM_ATTR_REVERSE;
921c9503a49Slq150181 		if (inverse_screen)
922c9503a49Slq150181 			flags |= TEM_ATTR_SCREEN_REVERSE;
923c9503a49Slq150181 		if (flags != 0)
924c9503a49Slq150181 			flags |= TEM_ATTR_BOLD;
925c9503a49Slq150181 	}
926c9503a49Slq150181 
927*aecfc01dSrui zang - Sun Microsystems - Beijing China 	pcolor->a_flags = flags;
928*aecfc01dSrui zang - Sun Microsystems - Beijing China }
929*aecfc01dSrui zang - Sun Microsystems - Beijing China 
930*aecfc01dSrui zang - Sun Microsystems - Beijing China uchar_t
tem_get_fbmode(tem_vt_state_t tem_arg)931*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_get_fbmode(tem_vt_state_t tem_arg)
932*aecfc01dSrui zang - Sun Microsystems - Beijing China {
933*aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
934*aecfc01dSrui zang - Sun Microsystems - Beijing China 
935*aecfc01dSrui zang - Sun Microsystems - Beijing China 	uchar_t fbmode;
936*aecfc01dSrui zang - Sun Microsystems - Beijing China 
937*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tem->tvs_lock);
938*aecfc01dSrui zang - Sun Microsystems - Beijing China 	fbmode = tem->tvs_fbmode;
939*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tem->tvs_lock);
940*aecfc01dSrui zang - Sun Microsystems - Beijing China 
941*aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (fbmode);
942*aecfc01dSrui zang - Sun Microsystems - Beijing China }
943*aecfc01dSrui zang - Sun Microsystems - Beijing China 
944*aecfc01dSrui zang - Sun Microsystems - Beijing China void
tem_set_fbmode(tem_vt_state_t tem_arg,uchar_t fbmode,cred_t * credp)945*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_set_fbmode(tem_vt_state_t tem_arg, uchar_t fbmode, cred_t *credp)
946*aecfc01dSrui zang - Sun Microsystems - Beijing China {
947*aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
948*aecfc01dSrui zang - Sun Microsystems - Beijing China 
949*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
950*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tem->tvs_lock);
951*aecfc01dSrui zang - Sun Microsystems - Beijing China 
952*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (fbmode == tem->tvs_fbmode) {
953*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tem->tvs_lock);
954*aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
955*aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
956*aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
957*aecfc01dSrui zang - Sun Microsystems - Beijing China 
958*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem->tvs_fbmode = fbmode;
959*aecfc01dSrui zang - Sun Microsystems - Beijing China 
960*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tem->tvs_isactive) {
961*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_kdsetmode(tem->tvs_fbmode, credp);
962*aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (fbmode == KD_TEXT)
963*aecfc01dSrui zang - Sun Microsystems - Beijing China 			tem_safe_unblank_screen(tem, credp, CALLED_FROM_NORMAL);
964*aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
965*aecfc01dSrui zang - Sun Microsystems - Beijing China 
966*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tem->tvs_lock);
967*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
968*aecfc01dSrui zang - Sun Microsystems - Beijing China }
969*aecfc01dSrui zang - Sun Microsystems - Beijing China 
970*aecfc01dSrui zang - Sun Microsystems - Beijing China void
tem_activate(tem_vt_state_t tem_arg,boolean_t unblank,cred_t * credp)971*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_activate(tem_vt_state_t tem_arg, boolean_t unblank, cred_t *credp)
972*aecfc01dSrui zang - Sun Microsystems - Beijing China {
973*aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
974*aecfc01dSrui zang - Sun Microsystems - Beijing China 
975*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
976*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_active = tem;
977*aecfc01dSrui zang - Sun Microsystems - Beijing China 
978*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tem->tvs_lock);
979*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem->tvs_isactive = B_TRUE;
980*aecfc01dSrui zang - Sun Microsystems - Beijing China 
981*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_kdsetmode(tem->tvs_fbmode, credp);
982*aecfc01dSrui zang - Sun Microsystems - Beijing China 
983*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (unblank)
984*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_safe_unblank_screen(tem, credp, CALLED_FROM_NORMAL);
985*aecfc01dSrui zang - Sun Microsystems - Beijing China 
986*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tem->tvs_lock);
987*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
988*aecfc01dSrui zang - Sun Microsystems - Beijing China }
989*aecfc01dSrui zang - Sun Microsystems - Beijing China 
990*aecfc01dSrui zang - Sun Microsystems - Beijing China void
tem_switch(tem_vt_state_t tem_arg1,tem_vt_state_t tem_arg2,cred_t * credp)991*aecfc01dSrui zang - Sun Microsystems - Beijing China tem_switch(tem_vt_state_t tem_arg1, tem_vt_state_t tem_arg2, cred_t *credp)
992*aecfc01dSrui zang - Sun Microsystems - Beijing China {
993*aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *cur = (struct tem_vt_state *)tem_arg1;
994*aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *tobe = (struct tem_vt_state *)tem_arg2;
995*aecfc01dSrui zang - Sun Microsystems - Beijing China 
996*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
997*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tobe->tvs_lock);
998*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&cur->tvs_lock);
999*aecfc01dSrui zang - Sun Microsystems - Beijing China 
1000*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_active = tobe;
1001*aecfc01dSrui zang - Sun Microsystems - Beijing China 	cur->tvs_isactive = B_FALSE;
1002*aecfc01dSrui zang - Sun Microsystems - Beijing China 	tobe->tvs_isactive = B_TRUE;
1003*aecfc01dSrui zang - Sun Microsystems - Beijing China 
1004*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&cur->tvs_lock);
1005*aecfc01dSrui zang - Sun Microsystems - Beijing China 
1006*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (cur->tvs_fbmode != tobe->tvs_fbmode)
1007*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_kdsetmode(tobe->tvs_fbmode, credp);
1008*aecfc01dSrui zang - Sun Microsystems - Beijing China 
1009*aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tobe->tvs_fbmode == KD_TEXT)
1010*aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_safe_unblank_screen(tobe, credp, CALLED_FROM_NORMAL);
1011*aecfc01dSrui zang - Sun Microsystems - Beijing China 
1012*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tobe->tvs_lock);
1013*aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
1014c9503a49Slq150181 }
1015