xref: /illumos-gate/usr/src/uts/common/io/tem.c (revision d863b4c1)
1fea9cb91Slq /*
2fea9cb91Slq  * CDDL HEADER START
3fea9cb91Slq  *
4fea9cb91Slq  * The contents of this file are subject to the terms of the
5fea9cb91Slq  * Common Development and Distribution License (the "License").
6fea9cb91Slq  * You may not use this file except in compliance with the License.
7fea9cb91Slq  *
8fea9cb91Slq  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fea9cb91Slq  * or http://www.opensolaris.org/os/licensing.
10fea9cb91Slq  * See the License for the specific language governing permissions
11fea9cb91Slq  * and limitations under the License.
12fea9cb91Slq  *
13fea9cb91Slq  * When distributing Covered Code, include this CDDL HEADER in each
14fea9cb91Slq  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fea9cb91Slq  * If applicable, add the following below this CDDL HEADER, with the
16fea9cb91Slq  * fields enclosed by brackets "[]" replaced with your own identifying
17fea9cb91Slq  * information: Portions Copyright [yyyy] [name of copyright owner]
18fea9cb91Slq  *
19fea9cb91Slq  * CDDL HEADER END
20fea9cb91Slq  */
21fea9cb91Slq 
22fea9cb91Slq /*
23b52fe415Slipeng sang - Sun Microsystems - Beijing China  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24fea9cb91Slq  * Use is subject to license terms.
25fea9cb91Slq  */
26fea9cb91Slq 
27fea9cb91Slq /*
28fea9cb91Slq  * ANSI terminal emulator module; parse ANSI X3.64 escape sequences and
29fea9cb91Slq  * the like.
30aecfc01dSrui zang - Sun Microsystems - Beijing China  *
31aecfc01dSrui zang - Sun Microsystems - Beijing China  * How Virtual Terminal Emulator Works:
32aecfc01dSrui zang - Sun Microsystems - Beijing China  *
33aecfc01dSrui zang - Sun Microsystems - Beijing China  * Every virtual terminal is associated with a tem_vt_state structure
34aecfc01dSrui zang - Sun Microsystems - Beijing China  * and maintains a virtual screen buffer in tvs_screen_buf, which contains
35aecfc01dSrui zang - Sun Microsystems - Beijing China  * all the characters which should be shown on the physical screen when
36aecfc01dSrui zang - Sun Microsystems - Beijing China  * the terminal is activated.  There are also two other buffers, tvs_fg_buf
37aecfc01dSrui zang - Sun Microsystems - Beijing China  * and tvs_bg_buf, which track the foreground and background colors of the
38aecfc01dSrui zang - Sun Microsystems - Beijing China  * on screen characters
39aecfc01dSrui zang - Sun Microsystems - Beijing China  *
40aecfc01dSrui zang - Sun Microsystems - Beijing China  * Data written to a virtual terminal is composed of characters which
41aecfc01dSrui zang - Sun Microsystems - Beijing China  * should be displayed on the screen when this virtual terminal is
42aecfc01dSrui zang - Sun Microsystems - Beijing China  * activated, fg/bg colors of these characters, and other control
43aecfc01dSrui zang - Sun Microsystems - Beijing China  * information (escape sequence, etc).
44aecfc01dSrui zang - Sun Microsystems - Beijing China  *
45aecfc01dSrui zang - Sun Microsystems - Beijing China  * When data is passed to a virtual terminal it first is parsed for
46aecfc01dSrui zang - Sun Microsystems - Beijing China  * control information by tem_safe_parse().  Subsequently the character
47aecfc01dSrui zang - Sun Microsystems - Beijing China  * and color data are written to tvs_screen_buf, tvs_fg_buf, and
48aecfc01dSrui zang - Sun Microsystems - Beijing China  * tvs_bg_buf.  They are saved in these buffers in order to refresh
49aecfc01dSrui zang - Sun Microsystems - Beijing China  * the screen when this terminal is activated.  If the terminal is
50aecfc01dSrui zang - Sun Microsystems - Beijing China  * currently active, the data (characters and colors) are also written
51aecfc01dSrui zang - Sun Microsystems - Beijing China  * to the physical screen by invoking a callback function,
52aecfc01dSrui zang - Sun Microsystems - Beijing China  * tem_safe_text_callbacks() or tem_safe_pix_callbacks().
53aecfc01dSrui zang - Sun Microsystems - Beijing China  *
54aecfc01dSrui zang - Sun Microsystems - Beijing China  * When rendering data to the framebuffer, if the framebuffer is in
55aecfc01dSrui zang - Sun Microsystems - Beijing China  * VIS_PIXEL mode, the character data will first be converted to pixel
56aecfc01dSrui zang - Sun Microsystems - Beijing China  * data using tem_safe_pix_bit2pix(), and then the pixels get displayed
57aecfc01dSrui zang - Sun Microsystems - Beijing China  * on the physical screen.  We only store the character and color data in
58aecfc01dSrui zang - Sun Microsystems - Beijing China  * tem_vt_state since the bit2pix conversion only happens when actually
59aecfc01dSrui zang - Sun Microsystems - Beijing China  * rendering to the physical framebuffer.
60fea9cb91Slq  */
61fea9cb91Slq 
62aecfc01dSrui zang - Sun Microsystems - Beijing China 
63fea9cb91Slq #include <sys/types.h>
64fea9cb91Slq #include <sys/file.h>
65fea9cb91Slq #include <sys/conf.h>
66fea9cb91Slq #include <sys/errno.h>
67fea9cb91Slq #include <sys/open.h>
68fea9cb91Slq #include <sys/cred.h>
69fea9cb91Slq #include <sys/kmem.h>
70fea9cb91Slq #include <sys/ascii.h>
71fea9cb91Slq #include <sys/consdev.h>
72fea9cb91Slq #include <sys/font.h>
73fea9cb91Slq #include <sys/fbio.h>
74fea9cb91Slq #include <sys/conf.h>
75fea9cb91Slq #include <sys/modctl.h>
76fea9cb91Slq #include <sys/strsubr.h>
77fea9cb91Slq #include <sys/stat.h>
78fea9cb91Slq #include <sys/visual_io.h>
79fea9cb91Slq #include <sys/mutex.h>
80fea9cb91Slq #include <sys/param.h>
81fea9cb91Slq #include <sys/debug.h>
82fea9cb91Slq #include <sys/cmn_err.h>
83fea9cb91Slq #include <sys/console.h>
84fea9cb91Slq #include <sys/ddi.h>
85fea9cb91Slq #include <sys/sunddi.h>
86fea9cb91Slq #include <sys/sunldi.h>
87fea9cb91Slq #include <sys/tem_impl.h>
88fea9cb91Slq #ifdef _HAVE_TEM_FIRMWARE
89fea9cb91Slq #include <sys/promif.h>
90fea9cb91Slq #endif /* _HAVE_TEM_FIRMWARE */
91b52fe415Slipeng sang - Sun Microsystems - Beijing China #include <sys/consplat.h>
92aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/kd.h>
93aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/sysmacros.h>
94aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/note.h>
95aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/t_lock.h>
96aecfc01dSrui zang - Sun Microsystems - Beijing China 
97aecfc01dSrui zang - Sun Microsystems - Beijing China /* Terminal emulator internal helper functions */
98aecfc01dSrui zang - Sun Microsystems - Beijing China static void	tems_setup_terminal(struct vis_devinit *, size_t, size_t);
99aecfc01dSrui zang - Sun Microsystems - Beijing China static void	tems_modechange_callback(struct vis_modechg_arg *,
100aecfc01dSrui zang - Sun Microsystems - Beijing China 		struct vis_devinit *);
101fea9cb91Slq 
102aecfc01dSrui zang - Sun Microsystems - Beijing China static void	tems_reset_colormap(cred_t *, enum called_from);
103aecfc01dSrui zang - Sun Microsystems - Beijing China 
104aecfc01dSrui zang - Sun Microsystems - Beijing China static void	tem_free_buf(struct tem_vt_state *);
105aecfc01dSrui zang - Sun Microsystems - Beijing China static void	tem_internal_init(struct tem_vt_state *, cred_t *, boolean_t,
106aecfc01dSrui zang - Sun Microsystems - Beijing China 		    boolean_t);
107aecfc01dSrui zang - Sun Microsystems - Beijing China static void	tems_get_initial_color(tem_color_t *pcolor);
108fea9cb91Slq 
109fea9cb91Slq /*
110fea9cb91Slq  * Globals
111fea9cb91Slq  */
112aecfc01dSrui zang - Sun Microsystems - Beijing China static ldi_ident_t	term_li = NULL;
113aecfc01dSrui zang - Sun Microsystems - Beijing China tem_state_t	tems;	/* common term info */
114aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(MUTEX_PROTECTS_DATA(tems.ts_lock, tems))
115fea9cb91Slq 
116fea9cb91Slq extern struct mod_ops mod_miscops;
117fea9cb91Slq 
118fea9cb91Slq static struct modlmisc	modlmisc = {
119fea9cb91Slq 	&mod_miscops,	/* modops */
120fea9cb91Slq 	"ANSI Terminal Emulator", /* name */
121fea9cb91Slq };
122fea9cb91Slq 
123fea9cb91Slq static struct modlinkage modlinkage = {
124cbc8e155SToomas Soome 	MODREV_1, { (void *)&modlmisc, NULL }
125fea9cb91Slq };
126fea9cb91Slq 
127fea9cb91Slq int
_init(void)128fea9cb91Slq _init(void)
129fea9cb91Slq {
130fea9cb91Slq 	int ret;
131fea9cb91Slq 	ret = mod_install(&modlinkage);
132fea9cb91Slq 	if (ret != 0)
133fea9cb91Slq 		return (ret);
134fea9cb91Slq 	ret = ldi_ident_from_mod(&modlinkage, &term_li);
135fea9cb91Slq 	if (ret != 0) {
136fea9cb91Slq 		(void) mod_remove(&modlinkage);
137fea9cb91Slq 		return (ret);
138fea9cb91Slq 	}
139aecfc01dSrui zang - Sun Microsystems - Beijing China 
140aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_init(&tems.ts_lock, (char *)NULL, MUTEX_DRIVER, NULL);
141aecfc01dSrui zang - Sun Microsystems - Beijing China 	list_create(&tems.ts_list, sizeof (struct tem_vt_state),
142aecfc01dSrui zang - Sun Microsystems - Beijing China 	    offsetof(struct tem_vt_state, tvs_list_node));
143aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_active = NULL;
144aecfc01dSrui zang - Sun Microsystems - Beijing China 
145fea9cb91Slq 	return (0);
146fea9cb91Slq }
147fea9cb91Slq 
148fea9cb91Slq int
_fini()149fea9cb91Slq _fini()
150fea9cb91Slq {
151fea9cb91Slq 	int ret;
152fea9cb91Slq 
153fea9cb91Slq 	ret = mod_remove(&modlinkage);
154fea9cb91Slq 	if (ret == 0) {
155fea9cb91Slq 		ldi_ident_release(term_li);
156fea9cb91Slq 		term_li = NULL;
157fea9cb91Slq 	}
158fea9cb91Slq 	return (ret);
159fea9cb91Slq }
160fea9cb91Slq 
161fea9cb91Slq int
_info(struct modinfo * modinfop)162fea9cb91Slq _info(struct modinfo *modinfop)
163fea9cb91Slq {
164fea9cb91Slq 	return (mod_info(&modlinkage, modinfop));
165fea9cb91Slq }
166fea9cb91Slq 
167aecfc01dSrui zang - Sun Microsystems - Beijing China static void
tem_add(struct tem_vt_state * tem)168aecfc01dSrui zang - Sun Microsystems - Beijing China tem_add(struct tem_vt_state *tem)
169fea9cb91Slq {
170aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock));
171fea9cb91Slq 
172aecfc01dSrui zang - Sun Microsystems - Beijing China 	list_insert_head(&tems.ts_list, tem);
173aecfc01dSrui zang - Sun Microsystems - Beijing China }
174fea9cb91Slq 
175aecfc01dSrui zang - Sun Microsystems - Beijing China static void
tem_rm(struct tem_vt_state * tem)176aecfc01dSrui zang - Sun Microsystems - Beijing China tem_rm(struct tem_vt_state *tem)
177aecfc01dSrui zang - Sun Microsystems - Beijing China {
178aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock));
179fea9cb91Slq 
180aecfc01dSrui zang - Sun Microsystems - Beijing China 	list_remove(&tems.ts_list, tem);
181aecfc01dSrui zang - Sun Microsystems - Beijing China }
182fea9cb91Slq 
183aecfc01dSrui zang - Sun Microsystems - Beijing China /*
184aecfc01dSrui zang - Sun Microsystems - Beijing China  * This is the main entry point to the module.  It handles output requests
185aecfc01dSrui zang - Sun Microsystems - Beijing China  * during normal system operation, when (e.g.) mutexes are available.
186aecfc01dSrui zang - Sun Microsystems - Beijing China  */
187aecfc01dSrui zang - Sun Microsystems - Beijing China void
tem_write(tem_vt_state_t tem_arg,uchar_t * buf,ssize_t len,cred_t * credp)188aecfc01dSrui zang - Sun Microsystems - Beijing China tem_write(tem_vt_state_t tem_arg, uchar_t *buf, ssize_t len, cred_t *credp)
189aecfc01dSrui zang - Sun Microsystems - Beijing China {
190aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
191fea9cb91Slq 
192aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
193aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tem->tvs_lock);
194fea9cb91Slq 
195aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (!tem->tvs_initialized) {
196aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tem->tvs_lock);
197aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
198aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
199aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
200fea9cb91Slq 
201aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_safe_check_first_time(tem, credp, CALLED_FROM_NORMAL);
202aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_safe_terminal_emulate(tem, buf, len, credp, CALLED_FROM_NORMAL);
203aecfc01dSrui zang - Sun Microsystems - Beijing China 
204aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tem->tvs_lock);
205aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
206fea9cb91Slq }
207fea9cb91Slq 
208aecfc01dSrui 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)209aecfc01dSrui zang - Sun Microsystems - Beijing China tem_internal_init(struct tem_vt_state *ptem, cred_t *credp,
210aecfc01dSrui zang - Sun Microsystems - Beijing China     boolean_t init_color, boolean_t clear_screen)
211fea9cb91Slq {
212cbc8e155SToomas Soome 	unsigned i, j, width, height;
213cbc8e155SToomas Soome 	text_attr_t attr;
214aecfc01dSrui zang - Sun Microsystems - Beijing China 	text_color_t fg;
215aecfc01dSrui zang - Sun Microsystems - Beijing China 	text_color_t bg;
216aecfc01dSrui zang - Sun Microsystems - Beijing China 
217aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&ptem->tvs_lock));
218aecfc01dSrui zang - Sun Microsystems - Beijing China 
219aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tems.ts_display_mode == VIS_PIXEL) {
220aecfc01dSrui zang - Sun Microsystems - Beijing China 		ptem->tvs_pix_data_size = tems.ts_pix_data_size;
221aecfc01dSrui zang - Sun Microsystems - Beijing China 		ptem->tvs_pix_data =
222aecfc01dSrui zang - Sun Microsystems - Beijing China 		    kmem_alloc(ptem->tvs_pix_data_size, KM_SLEEP);
223aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
224fea9cb91Slq 
225*d863b4c1SToomas Soome 	ptem->tvs_stateflags = TVS_AUTOWRAP;
226*d863b4c1SToomas Soome 
2270e3b7565SToomas Soome 	ptem->tvs_outbuf_size = tems.ts_c_dimension.width *
2280e3b7565SToomas Soome 	    sizeof (*ptem->tvs_outbuf);
2290e3b7565SToomas Soome 	ptem->tvs_outbuf = kmem_alloc(ptem->tvs_outbuf_size, KM_SLEEP);
230fea9cb91Slq 
231aecfc01dSrui zang - Sun Microsystems - Beijing China 	width = tems.ts_c_dimension.width;
232aecfc01dSrui zang - Sun Microsystems - Beijing China 	height = tems.ts_c_dimension.height;
233cbc8e155SToomas Soome 	ptem->tvs_screen_history_size = height;
234cbc8e155SToomas Soome 
235cbc8e155SToomas Soome 	ptem->tvs_screen_buf_size = width * ptem->tvs_screen_history_size *
2360e3b7565SToomas Soome 	    sizeof (*ptem->tvs_screen_buf);
2370e3b7565SToomas Soome 	ptem->tvs_screen_buf = kmem_alloc(ptem->tvs_screen_buf_size, KM_SLEEP);
238cbc8e155SToomas Soome 	ptem->tvs_screen_rows = kmem_alloc(ptem->tvs_screen_history_size *
239cbc8e155SToomas Soome 	    sizeof (term_char_t *), KM_SLEEP);
240aecfc01dSrui zang - Sun Microsystems - Beijing China 
241835b861bSToomas Soome 	ptem->tvs_maxtab = width / 8;
242835b861bSToomas Soome 	ptem->tvs_tabs = kmem_alloc(ptem->tvs_maxtab * sizeof (*ptem->tvs_tabs),
243835b861bSToomas Soome 	    KM_SLEEP);
244835b861bSToomas Soome 
245aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_safe_reset_display(ptem, credp, CALLED_FROM_NORMAL,
246aecfc01dSrui zang - Sun Microsystems - Beijing China 	    clear_screen, init_color);
247aecfc01dSrui zang - Sun Microsystems - Beijing China 
248ac9b7c93SToomas Soome 	ptem->tvs_utf8_left = 0;
249ac9b7c93SToomas Soome 	ptem->tvs_utf8_partial = 0;
250ac9b7c93SToomas Soome 
251cbc8e155SToomas Soome 	/* Get default attributes and fill up the screen buffer. */
252cbc8e155SToomas Soome 	tem_safe_get_attr(ptem, &fg, &bg, &attr, TEM_ATTR_SCREEN_REVERSE);
253cbc8e155SToomas Soome 	for (i = 0; i < ptem->tvs_screen_history_size; i++) {
254cbc8e155SToomas Soome 		ptem->tvs_screen_rows[i] = &ptem->tvs_screen_buf[i * width];
255cbc8e155SToomas Soome 
256aecfc01dSrui zang - Sun Microsystems - Beijing China 		for (j = 0; j < width; j++) {
257cbc8e155SToomas Soome 			ptem->tvs_screen_rows[i][j].tc_fg_color = fg;
258cbc8e155SToomas Soome 			ptem->tvs_screen_rows[i][j].tc_bg_color = bg;
259cbc8e155SToomas Soome 			ptem->tvs_screen_rows[i][j].tc_char =
260cbc8e155SToomas Soome 			    TEM_ATTR(attr) | ' ';
261aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
262cbc8e155SToomas Soome 	}
263aecfc01dSrui zang - Sun Microsystems - Beijing China 
264cbc8e155SToomas Soome 	ptem->tvs_initialized = B_TRUE;
265fea9cb91Slq }
266fea9cb91Slq 
267cbc8e155SToomas Soome boolean_t
tem_initialized(tem_vt_state_t tem_arg)268aecfc01dSrui zang - Sun Microsystems - Beijing China tem_initialized(tem_vt_state_t tem_arg)
269fea9cb91Slq {
270aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *ptem = (struct tem_vt_state *)tem_arg;
271cbc8e155SToomas Soome 	boolean_t ret;
272aecfc01dSrui zang - Sun Microsystems - Beijing China 
273aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&ptem->tvs_lock);
274aecfc01dSrui zang - Sun Microsystems - Beijing China 	ret = ptem->tvs_initialized;
275aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&ptem->tvs_lock);
276fea9cb91Slq 
277aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (ret);
278fea9cb91Slq }
279fea9cb91Slq 
280aecfc01dSrui zang - Sun Microsystems - Beijing China tem_vt_state_t
tem_init(cred_t * credp,queue_t * rq)2815c22bad5SToomas Soome tem_init(cred_t *credp, queue_t *rq)
282fea9cb91Slq {
283aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *ptem;
284aecfc01dSrui zang - Sun Microsystems - Beijing China 
285aecfc01dSrui zang - Sun Microsystems - Beijing China 	ptem = kmem_zalloc(sizeof (struct tem_vt_state), KM_SLEEP);
286aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_init(&ptem->tvs_lock, (char *)NULL, MUTEX_DRIVER, NULL);
287aecfc01dSrui zang - Sun Microsystems - Beijing China 
288aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
289aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&ptem->tvs_lock);
290aecfc01dSrui zang - Sun Microsystems - Beijing China 
291aecfc01dSrui zang - Sun Microsystems - Beijing China 	ptem->tvs_isactive = B_FALSE;
292aecfc01dSrui zang - Sun Microsystems - Beijing China 	ptem->tvs_fbmode = KD_TEXT;
2935c22bad5SToomas Soome 	ptem->tvs_queue = rq;
294aecfc01dSrui zang - Sun Microsystems - Beijing China 
295aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
296aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * A tem is regarded as initialized only after tem_internal_init(),
297aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * will be set at the end of tem_internal_init().
298aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
299cbc8e155SToomas Soome 	ptem->tvs_initialized = B_FALSE;
300aecfc01dSrui zang - Sun Microsystems - Beijing China 
301fea9cb91Slq 
302aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (!tems.ts_initialized) {
303aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
304aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * Only happens during early console configuration.
305aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
306aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_add(ptem);
307aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&ptem->tvs_lock);
308aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
309aecfc01dSrui zang - Sun Microsystems - Beijing China 		return ((tem_vt_state_t)ptem);
310aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
311fea9cb91Slq 
312aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_internal_init(ptem, credp, B_TRUE, B_FALSE);
313aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_add(ptem);
314aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&ptem->tvs_lock);
315aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
316aecfc01dSrui zang - Sun Microsystems - Beijing China 
317aecfc01dSrui zang - Sun Microsystems - Beijing China 	return ((tem_vt_state_t)ptem);
318fea9cb91Slq }
319fea9cb91Slq 
320fea9cb91Slq /*
321aecfc01dSrui zang - Sun Microsystems - Beijing China  * re-init the tem after video mode has changed and tems_info has
322aecfc01dSrui zang - Sun Microsystems - Beijing China  * been re-inited. The lock is already held.
323fea9cb91Slq  */
324aecfc01dSrui zang - Sun Microsystems - Beijing China static void
tem_reinit(struct tem_vt_state * tem,boolean_t reset_display)325aecfc01dSrui zang - Sun Microsystems - Beijing China tem_reinit(struct tem_vt_state *tem, boolean_t reset_display)
326aecfc01dSrui zang - Sun Microsystems - Beijing China {
327aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock));
328aecfc01dSrui zang - Sun Microsystems - Beijing China 
329aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_free_buf(tem); /* only free virtual buffers */
330aecfc01dSrui zang - Sun Microsystems - Beijing China 
331aecfc01dSrui zang - Sun Microsystems - Beijing China 	/* reserve color */
332aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_internal_init(tem, kcred, B_FALSE, reset_display);
333aecfc01dSrui zang - Sun Microsystems - Beijing China }
334aecfc01dSrui zang - Sun Microsystems - Beijing China 
335aecfc01dSrui zang - Sun Microsystems - Beijing China static void
tem_free_buf(struct tem_vt_state * tem)336aecfc01dSrui zang - Sun Microsystems - Beijing China tem_free_buf(struct tem_vt_state *tem)
337aecfc01dSrui zang - Sun Microsystems - Beijing China {
338aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(tem != NULL && MUTEX_HELD(&tem->tvs_lock));
339aecfc01dSrui zang - Sun Microsystems - Beijing China 
340aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tem->tvs_outbuf != NULL)
341aecfc01dSrui zang - Sun Microsystems - Beijing China 		kmem_free(tem->tvs_outbuf, tem->tvs_outbuf_size);
342aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tem->tvs_pix_data != NULL)
343aecfc01dSrui zang - Sun Microsystems - Beijing China 		kmem_free(tem->tvs_pix_data, tem->tvs_pix_data_size);
344aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tem->tvs_screen_buf != NULL)
345aecfc01dSrui zang - Sun Microsystems - Beijing China 		kmem_free(tem->tvs_screen_buf, tem->tvs_screen_buf_size);
346cbc8e155SToomas Soome 	if (tem->tvs_screen_rows != NULL) {
347cbc8e155SToomas Soome 		kmem_free(tem->tvs_screen_rows, tem->tvs_screen_history_size *
348cbc8e155SToomas Soome 		    sizeof (term_char_t *));
349cbc8e155SToomas Soome 	}
350835b861bSToomas Soome 	if (tem->tvs_tabs != NULL) {
351835b861bSToomas Soome 		kmem_free(tem->tvs_tabs, tem->tvs_maxtab *
352835b861bSToomas Soome 		    sizeof (*tem->tvs_tabs));
353835b861bSToomas Soome 	}
354aecfc01dSrui zang - Sun Microsystems - Beijing China }
355aecfc01dSrui zang - Sun Microsystems - Beijing China 
356fea9cb91Slq void
tem_destroy(tem_vt_state_t tem_arg,cred_t * credp)357aecfc01dSrui zang - Sun Microsystems - Beijing China tem_destroy(tem_vt_state_t tem_arg, cred_t *credp)
358fea9cb91Slq {
359aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
360fea9cb91Slq 
361aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
362aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tem->tvs_lock);
363fea9cb91Slq 
364aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tem->tvs_isactive && tem->tvs_fbmode == KD_TEXT)
365aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_safe_blank_screen(tem, credp, CALLED_FROM_NORMAL);
366fea9cb91Slq 
367aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_free_buf(tem);
368aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_rm(tem);
369aecfc01dSrui zang - Sun Microsystems - Beijing China 
370aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tems.ts_active == tem)
371aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_active = NULL;
372aecfc01dSrui zang - Sun Microsystems - Beijing China 
373aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tem->tvs_lock);
374aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
375aecfc01dSrui zang - Sun Microsystems - Beijing China 
376aecfc01dSrui zang - Sun Microsystems - Beijing China 	kmem_free(tem, sizeof (struct tem_vt_state));
377aecfc01dSrui zang - Sun Microsystems - Beijing China }
378aecfc01dSrui zang - Sun Microsystems - Beijing China 
379aecfc01dSrui zang - Sun Microsystems - Beijing China static int
tems_failed(cred_t * credp,boolean_t finish_ioctl)380aecfc01dSrui zang - Sun Microsystems - Beijing China tems_failed(cred_t *credp, boolean_t finish_ioctl)
381aecfc01dSrui zang - Sun Microsystems - Beijing China {
382aecfc01dSrui zang - Sun Microsystems - Beijing China 	int	lyr_rval;
383aecfc01dSrui zang - Sun Microsystems - Beijing China 
384aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(MUTEX_HELD(&tems.ts_lock));
385aecfc01dSrui zang - Sun Microsystems - Beijing China 
386aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (finish_ioctl)
387aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) ldi_ioctl(tems.ts_hdl, VIS_DEVFINI, 0,
3884291d474SToomas Soome 		    FWRITE | FKIOCTL, credp, &lyr_rval);
389aecfc01dSrui zang - Sun Microsystems - Beijing China 
3906efbc8a9SToomas Soome 	(void) ldi_close(tems.ts_hdl, 0, credp);
391aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_hdl = NULL;
392aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (ENXIO);
393fea9cb91Slq }
394fea9cb91Slq 
395aecfc01dSrui zang - Sun Microsystems - Beijing China /*
396aecfc01dSrui zang - Sun Microsystems - Beijing China  * only called once during boot
397aecfc01dSrui zang - Sun Microsystems - Beijing China  */
398fea9cb91Slq int
tem_info_init(char * pathname,cred_t * credp)399aecfc01dSrui zang - Sun Microsystems - Beijing China tem_info_init(char *pathname, cred_t *credp)
400fea9cb91Slq {
401aecfc01dSrui zang - Sun Microsystems - Beijing China 	int			lyr_rval, ret;
402aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct vis_devinit	temargs;
403aecfc01dSrui zang - Sun Microsystems - Beijing China 	char			*pathbuf;
404fea9cb91Slq 	size_t height = 0;
405fea9cb91Slq 	size_t width = 0;
406aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *p;
407fea9cb91Slq 
408aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
409fea9cb91Slq 
410aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tems.ts_initialized) {
411aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
412aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (0);
413aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
414fea9cb91Slq 
415fea9cb91Slq 	/*
416fea9cb91Slq 	 * Open the layered device using the devfs physical device name
417fea9cb91Slq 	 * after adding the /devices prefix.
418fea9cb91Slq 	 */
419fea9cb91Slq 	pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
420fea9cb91Slq 	(void) strcpy(pathbuf, "/devices");
421fea9cb91Slq 	if (i_ddi_prompath_to_devfspath(pathname,
422fea9cb91Slq 	    pathbuf + strlen("/devices")) != DDI_SUCCESS) {
423aecfc01dSrui zang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "terminal-emulator:  path conversion error");
424fea9cb91Slq 		kmem_free(pathbuf, MAXPATHLEN);
425aecfc01dSrui zang - Sun Microsystems - Beijing China 
426aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
427fea9cb91Slq 		return (ENXIO);
428fea9cb91Slq 	}
429aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (ldi_open_by_name(pathbuf, FWRITE, credp,
430aecfc01dSrui zang - Sun Microsystems - Beijing China 	    &tems.ts_hdl, term_li) != 0) {
431aecfc01dSrui zang - Sun Microsystems - Beijing China 		cmn_err(CE_WARN, "terminal-emulator:  device path open error");
432fea9cb91Slq 		kmem_free(pathbuf, MAXPATHLEN);
433aecfc01dSrui zang - Sun Microsystems - Beijing China 
434aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
435fea9cb91Slq 		return (ENXIO);
436fea9cb91Slq 	}
437fea9cb91Slq 	kmem_free(pathbuf, MAXPATHLEN);
438fea9cb91Slq 
439aecfc01dSrui zang - Sun Microsystems - Beijing China 	temargs.modechg_cb  = (vis_modechg_cb_t)tems_modechange_callback;
440aecfc01dSrui zang - Sun Microsystems - Beijing China 	temargs.modechg_arg = NULL;
441fea9cb91Slq 
442fea9cb91Slq 	/*
443fea9cb91Slq 	 * Initialize the console and get the device parameters
444fea9cb91Slq 	 */
445aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (ldi_ioctl(tems.ts_hdl, VIS_DEVINIT,
446aecfc01dSrui zang - Sun Microsystems - Beijing China 	    (intptr_t)&temargs, FWRITE|FKIOCTL, credp, &lyr_rval) != 0) {
447fea9cb91Slq 		cmn_err(CE_WARN, "terminal emulator: Compatible fb not found");
448aecfc01dSrui zang - Sun Microsystems - Beijing China 		ret = tems_failed(credp, B_FALSE);
449aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
450aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (ret);
451fea9cb91Slq 	}
452fea9cb91Slq 
453fea9cb91Slq 	/* Make sure the fb driver and terminal emulator versions match */
454aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (temargs.version != VIS_CONS_REV) {
455fea9cb91Slq 		cmn_err(CE_WARN,
456fea9cb91Slq 		    "terminal emulator: VIS_CONS_REV %d (see sys/visual_io.h) "
457aecfc01dSrui zang - Sun Microsystems - Beijing China 		    "of console fb driver not supported", temargs.version);
458aecfc01dSrui zang - Sun Microsystems - Beijing China 		ret = tems_failed(credp, B_TRUE);
459aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
460aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (ret);
461fea9cb91Slq 	}
462fea9cb91Slq 
463aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((tems.ts_fb_polledio = temargs.polledio) == NULL) {
464fea9cb91Slq 		cmn_err(CE_WARN, "terminal emulator: fb doesn't support polled "
465fea9cb91Slq 		    "I/O");
466aecfc01dSrui zang - Sun Microsystems - Beijing China 		ret = tems_failed(credp, B_TRUE);
467aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
468aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (ret);
469fea9cb91Slq 	}
470fea9cb91Slq 
471fea9cb91Slq 	/* other sanity checks */
472aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (!((temargs.depth == 4) || (temargs.depth == 8) ||
4735a801801SToomas Soome 	    (temargs.depth == 15) || (temargs.depth == 16) ||
474aecfc01dSrui zang - Sun Microsystems - Beijing China 	    (temargs.depth == 24) || (temargs.depth == 32))) {
475fea9cb91Slq 		cmn_err(CE_WARN, "terminal emulator: unsupported depth");
476aecfc01dSrui zang - Sun Microsystems - Beijing China 		ret = tems_failed(credp, B_TRUE);
477aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
478aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (ret);
479fea9cb91Slq 	}
480fea9cb91Slq 
481aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((temargs.mode != VIS_TEXT) && (temargs.mode != VIS_PIXEL)) {
482fea9cb91Slq 		cmn_err(CE_WARN, "terminal emulator: unsupported mode");
483aecfc01dSrui zang - Sun Microsystems - Beijing China 		ret = tems_failed(credp, B_TRUE);
484aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
485aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (ret);
486fea9cb91Slq 	}
487fea9cb91Slq 
488aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((temargs.mode == VIS_PIXEL) && plat_stdout_is_framebuffer())
489fea9cb91Slq 		plat_tem_get_prom_size(&height, &width);
490fea9cb91Slq 
491fea9cb91Slq 	/*
492aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * Initialize the common terminal emulator info
493fea9cb91Slq 	 */
494aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems_setup_terminal(&temargs, height, width);
495fea9cb91Slq 
496aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems_reset_colormap(credp, CALLED_FROM_NORMAL);
497aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems_get_initial_color(&tems.ts_init_color);
498c9503a49Slq 
499aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_initialized = 1; /* initialization flag */
500fea9cb91Slq 
501aecfc01dSrui zang - Sun Microsystems - Beijing China 	for (p = list_head(&tems.ts_list); p != NULL;
502aecfc01dSrui zang - Sun Microsystems - Beijing China 	    p = list_next(&tems.ts_list, p)) {
503aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_enter(&p->tvs_lock);
504aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_internal_init(p, credp, B_TRUE, B_FALSE);
5054291d474SToomas Soome 		tem_align(p, credp, CALLED_FROM_NORMAL);
506aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&p->tvs_lock);
507fea9cb91Slq 	}
508fea9cb91Slq 
509aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
510fea9cb91Slq 	return (0);
511fea9cb91Slq }
512fea9cb91Slq 
513aecfc01dSrui zang - Sun Microsystems - Beijing China #define	TEMS_DEPTH_DIFF		0x01
514aecfc01dSrui zang - Sun Microsystems - Beijing China #define	TEMS_DIMENSION_DIFF	0x02
515c9503a49Slq 
516aecfc01dSrui zang - Sun Microsystems - Beijing China static uchar_t
tems_check_videomode(struct vis_devinit * tp)517aecfc01dSrui zang - Sun Microsystems - Beijing China tems_check_videomode(struct vis_devinit *tp)
518aecfc01dSrui zang - Sun Microsystems - Beijing China {
519aecfc01dSrui zang - Sun Microsystems - Beijing China 	uchar_t result = 0;
520fea9cb91Slq 
521aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tems.ts_pdepth != tp->depth)
522aecfc01dSrui zang - Sun Microsystems - Beijing China 		result |= TEMS_DEPTH_DIFF;
523fea9cb91Slq 
524aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tp->mode == VIS_TEXT) {
525aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (tems.ts_c_dimension.width != tp->width ||
526aecfc01dSrui zang - Sun Microsystems - Beijing China 		    tems.ts_c_dimension.height != tp->height)
527aecfc01dSrui zang - Sun Microsystems - Beijing China 			result |= TEMS_DIMENSION_DIFF;
528aecfc01dSrui zang - Sun Microsystems - Beijing China 	} else {
529aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (tems.ts_p_dimension.width != tp->width ||
530aecfc01dSrui zang - Sun Microsystems - Beijing China 		    tems.ts_p_dimension.height != tp->height)
531aecfc01dSrui zang - Sun Microsystems - Beijing China 			result |= TEMS_DIMENSION_DIFF;
532aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
533fea9cb91Slq 
534aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (result);
535fea9cb91Slq }
536fea9cb91Slq 
537aecfc01dSrui zang - Sun Microsystems - Beijing China static void
tems_setup_font(screen_size_t height,screen_size_t width)538e0721d5aSToomas Soome tems_setup_font(screen_size_t height, screen_size_t width)
539fea9cb91Slq {
540cbc8e155SToomas Soome 	bitmap_data_t *font_data;
541fea9cb91Slq 	int i;
542e0721d5aSToomas Soome 
543e0721d5aSToomas Soome 	/*
544e0721d5aSToomas Soome 	 * set_font() will select an appropriate sized font for
545e0721d5aSToomas Soome 	 * the number of rows and columns selected. If we don't
546e0721d5aSToomas Soome 	 * have a font that will fit, then it will use the
547e0721d5aSToomas Soome 	 * default builtin font and adjust the rows and columns
548e0721d5aSToomas Soome 	 * to fit on the screen.
549e0721d5aSToomas Soome 	 */
550e0721d5aSToomas Soome 	font_data = set_font(&tems.ts_c_dimension.height,
551e0721d5aSToomas Soome 	    &tems.ts_c_dimension.width, height, width);
552e0721d5aSToomas Soome 
553e0721d5aSToomas Soome 	/*
554e0721d5aSToomas Soome 	 * To use loaded font, we assign the loaded font data to tems.ts_font.
555e0721d5aSToomas Soome 	 * In case of next load, the previously loaded data is freed
556e0721d5aSToomas Soome 	 * when loading the new font.
557e0721d5aSToomas Soome 	 */
558e0721d5aSToomas Soome 	for (i = 0; i < VFNT_MAPS; i++) {
559e0721d5aSToomas Soome 		tems.ts_font.vf_map[i] =
560e0721d5aSToomas Soome 		    font_data->font->vf_map[i];
561e0721d5aSToomas Soome 		tems.ts_font.vf_map_count[i] =
562e0721d5aSToomas Soome 		    font_data->font->vf_map_count[i];
563e0721d5aSToomas Soome 	}
564e0721d5aSToomas Soome 
565e0721d5aSToomas Soome 	tems.ts_font.vf_bytes = font_data->font->vf_bytes;
566e0721d5aSToomas Soome 	tems.ts_font.vf_width = font_data->font->vf_width;
567e0721d5aSToomas Soome 	tems.ts_font.vf_height = font_data->font->vf_height;
568e0721d5aSToomas Soome }
569e0721d5aSToomas Soome 
570e0721d5aSToomas Soome static void
tems_setup_terminal(struct vis_devinit * tp,size_t height,size_t width)571e0721d5aSToomas Soome tems_setup_terminal(struct vis_devinit *tp, size_t height, size_t width)
572e0721d5aSToomas Soome {
5730e3b7565SToomas Soome 	int old_blank_buf_size = tems.ts_c_dimension.width *
5740e3b7565SToomas Soome 	    sizeof (*tems.ts_blank_line);
575fea9cb91Slq 
576aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(MUTEX_HELD(&tems.ts_lock));
577fea9cb91Slq 
578aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_pdepth = tp->depth;
579aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_linebytes = tp->linebytes;
580aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_display_mode = tp->mode;
5815a801801SToomas Soome 	tems.ts_color_map = tp->color_map;
582fea9cb91Slq 
583aecfc01dSrui zang - Sun Microsystems - Beijing China 	switch (tp->mode) {
584fea9cb91Slq 	case VIS_TEXT:
585aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_p_dimension.width = 0;
586aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_p_dimension.height = 0;
587aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_c_dimension.width = tp->width;
588aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_c_dimension.height = tp->height;
589aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_callbacks = &tem_safe_text_callbacks;
590fea9cb91Slq 
591e0721d5aSToomas Soome 		tems_setup_font(16 * tp->height + BORDER_PIXELS,
592e0721d5aSToomas Soome 		    8 * tp->width + BORDER_PIXELS);
593e0721d5aSToomas Soome 
594fea9cb91Slq 		break;
595fea9cb91Slq 
596aecfc01dSrui zang - Sun Microsystems - Beijing China 	case VIS_PIXEL:
597fea9cb91Slq 		/*
598fea9cb91Slq 		 * First check to see if the user has specified a screen size.
599fea9cb91Slq 		 * If so, use those values.  Else use 34x80 as the default.
600fea9cb91Slq 		 */
601fea9cb91Slq 		if (width == 0) {
602fea9cb91Slq 			width = TEM_DEFAULT_COLS;
603fea9cb91Slq 			height = TEM_DEFAULT_ROWS;
604fea9cb91Slq 		}
605aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_c_dimension.height = (screen_size_t)height;
606aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_c_dimension.width = (screen_size_t)width;
607aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_p_dimension.height = tp->height;
608aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_p_dimension.width = tp->width;
609aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_callbacks = &tem_safe_pix_callbacks;
610fea9cb91Slq 
611e0721d5aSToomas Soome 		tems_setup_font(tp->height, tp->width);
612cbc8e155SToomas Soome 
613aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_p_offset.y = (tems.ts_p_dimension.height -
614cbc8e155SToomas Soome 		    (tems.ts_c_dimension.height * tems.ts_font.vf_height)) / 2;
615aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_p_offset.x = (tems.ts_p_dimension.width -
616cbc8e155SToomas Soome 		    (tems.ts_c_dimension.width * tems.ts_font.vf_width)) / 2;
617fea9cb91Slq 
618aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_pix_data_size =
619cbc8e155SToomas Soome 		    tems.ts_font.vf_width * tems.ts_font.vf_height;
620aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_pix_data_size *= 4;
621aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_pdepth = tp->depth;
622fea9cb91Slq 
623fea9cb91Slq 		break;
624aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
625aecfc01dSrui zang - Sun Microsystems - Beijing China 
626aecfc01dSrui zang - Sun Microsystems - Beijing China 	/* Now virtual cls also uses the blank_line buffer */
627aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tems.ts_blank_line)
628aecfc01dSrui zang - Sun Microsystems - Beijing China 		kmem_free(tems.ts_blank_line, old_blank_buf_size);
629fea9cb91Slq 
630cbc8e155SToomas Soome 	tems.ts_blank_line = kmem_alloc(tems.ts_c_dimension.width *
631cbc8e155SToomas Soome 	    sizeof (*tems.ts_blank_line), KM_SLEEP);
632aecfc01dSrui zang - Sun Microsystems - Beijing China }
633aecfc01dSrui zang - Sun Microsystems - Beijing China 
634aecfc01dSrui zang - Sun Microsystems - Beijing China /*
635aecfc01dSrui zang - Sun Microsystems - Beijing China  * This is a callback function that we register with the frame
636aecfc01dSrui zang - Sun Microsystems - Beijing China  * buffer driver layered underneath.  It gets invoked from
637aecfc01dSrui zang - Sun Microsystems - Beijing China  * the underlying frame buffer driver to reconfigure the terminal
638aecfc01dSrui zang - Sun Microsystems - Beijing China  * emulator to a new screen size and depth in conjunction with
639aecfc01dSrui zang - Sun Microsystems - Beijing China  * framebuffer videomode changes.
640aecfc01dSrui zang - Sun Microsystems - Beijing China  * Here we keep the foreground/background color and attributes,
641aecfc01dSrui zang - Sun Microsystems - Beijing China  * which may be different with the initial settings, so that
642aecfc01dSrui zang - Sun Microsystems - Beijing China  * the color won't change while the framebuffer videomode changes.
643aecfc01dSrui zang - Sun Microsystems - Beijing China  * And we also reset the kernel terminal emulator and clear the
644aecfc01dSrui zang - Sun Microsystems - Beijing China  * whole screen.
645aecfc01dSrui zang - Sun Microsystems - Beijing China  */
646aecfc01dSrui zang - Sun Microsystems - Beijing China /* ARGSUSED */
647aecfc01dSrui zang - Sun Microsystems - Beijing China void
tems_modechange_callback(struct vis_modechg_arg * arg,struct vis_devinit * devinit)648aecfc01dSrui zang - Sun Microsystems - Beijing China tems_modechange_callback(struct vis_modechg_arg *arg,
649aecfc01dSrui zang - Sun Microsystems - Beijing China     struct vis_devinit *devinit)
650aecfc01dSrui zang - Sun Microsystems - Beijing China {
651aecfc01dSrui zang - Sun Microsystems - Beijing China 	uchar_t diff;
652aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *p;
653aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_modechg_cb_t cb;
654aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_modechg_cb_arg_t cb_arg;
655aecfc01dSrui zang - Sun Microsystems - Beijing China 
656aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(!(list_is_empty(&tems.ts_list)));
657aecfc01dSrui zang - Sun Microsystems - Beijing China 
658aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
659aecfc01dSrui zang - Sun Microsystems - Beijing China 
660aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
661aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * currently only for pixel mode
662aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
663aecfc01dSrui zang - Sun Microsystems - Beijing China 	diff = tems_check_videomode(devinit);
664aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (diff == 0) {
665aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
666aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
667aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
668aecfc01dSrui zang - Sun Microsystems - Beijing China 
669aecfc01dSrui zang - Sun Microsystems - Beijing China 	diff = diff & TEMS_DIMENSION_DIFF;
670aecfc01dSrui zang - Sun Microsystems - Beijing China 
671aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (diff == 0) {
672fea9cb91Slq 		/*
673aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * Only need to reinit the active tem.
674fea9cb91Slq 		 */
675aecfc01dSrui zang - Sun Microsystems - Beijing China 		struct tem_vt_state *active = tems.ts_active;
676aecfc01dSrui zang - Sun Microsystems - Beijing China 		tems.ts_pdepth = devinit->depth;
677aecfc01dSrui zang - Sun Microsystems - Beijing China 
678aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_enter(&active->tvs_lock);
679aecfc01dSrui zang - Sun Microsystems - Beijing China 		ASSERT(active->tvs_isactive);
680aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_reinit(active, B_TRUE);
681aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&active->tvs_lock);
682aecfc01dSrui zang - Sun Microsystems - Beijing China 
683aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
684aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
685fea9cb91Slq 	}
686fea9cb91Slq 
687aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems_setup_terminal(devinit, tems.ts_c_dimension.height,
688aecfc01dSrui zang - Sun Microsystems - Beijing China 	    tems.ts_c_dimension.width);
689fea9cb91Slq 
690aecfc01dSrui zang - Sun Microsystems - Beijing China 	for (p = list_head(&tems.ts_list); p != NULL;
691aecfc01dSrui zang - Sun Microsystems - Beijing China 	    p = list_next(&tems.ts_list, p)) {
692aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_enter(&p->tvs_lock);
693aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_reinit(p, p->tvs_isactive);
694aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&p->tvs_lock);
695aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
696fea9cb91Slq 
697fea9cb91Slq 
698aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tems.ts_modechg_cb == NULL) {
699aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
700aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
701aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
702aecfc01dSrui zang - Sun Microsystems - Beijing China 
703aecfc01dSrui zang - Sun Microsystems - Beijing China 	cb = tems.ts_modechg_cb;
704aecfc01dSrui zang - Sun Microsystems - Beijing China 	cb_arg = tems.ts_modechg_arg;
705aecfc01dSrui zang - Sun Microsystems - Beijing China 
706aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
707aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * Release the lock while doing callback.
708aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
709aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
710aecfc01dSrui zang - Sun Microsystems - Beijing China 	cb(cb_arg);
711fea9cb91Slq }
712fea9cb91Slq 
7135a801801SToomas Soome /*
7145a801801SToomas Soome  * This function is used to clear entire screen via the underlying framebuffer
7155a801801SToomas Soome  * driver.
7165a801801SToomas Soome  */
7175a801801SToomas Soome int
tems_cls_layered(struct vis_consclear * pda,cred_t * credp)7185a801801SToomas Soome tems_cls_layered(struct vis_consclear *pda,
7195a801801SToomas Soome     cred_t *credp)
7205a801801SToomas Soome {
7215a801801SToomas Soome 	int rval;
7225a801801SToomas Soome 
7235a801801SToomas Soome 	(void) ldi_ioctl(tems.ts_hdl, VIS_CONSCLEAR,
7245a801801SToomas Soome 	    (intptr_t)pda, FKIOCTL, credp, &rval);
7255a801801SToomas Soome 	return (rval);
7265a801801SToomas Soome }
7275a801801SToomas Soome 
728fea9cb91Slq /*
729fea9cb91Slq  * This function is used to display a rectangular blit of data
730fea9cb91Slq  * of a given size and location via the underlying framebuffer driver.
731fea9cb91Slq  * The blit can be as small as a pixel or as large as the screen.
732fea9cb91Slq  */
733fea9cb91Slq void
tems_display_layered(struct vis_consdisplay * pda,cred_t * credp)7345a801801SToomas Soome tems_display_layered(struct vis_consdisplay *pda,
7355a801801SToomas Soome     cred_t *credp)
736fea9cb91Slq {
737fea9cb91Slq 	int rval;
738fea9cb91Slq 
739aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) ldi_ioctl(tems.ts_hdl, VIS_CONSDISPLAY,
740fea9cb91Slq 	    (intptr_t)pda, FKIOCTL, credp, &rval);
741fea9cb91Slq }
742fea9cb91Slq 
743fea9cb91Slq /*
744fea9cb91Slq  * This function is used to invoke a block copy operation in the
745fea9cb91Slq  * underlying framebuffer driver.  Rectangle copies are how scrolling
746fea9cb91Slq  * is implemented, as well as horizontal text shifting escape seqs.
747fea9cb91Slq  * such as from vi when deleting characters and words.
748fea9cb91Slq  */
749fea9cb91Slq void
tems_copy_layered(struct vis_conscopy * pma,cred_t * credp)7505a801801SToomas Soome tems_copy_layered(struct vis_conscopy *pma,
7515a801801SToomas Soome     cred_t *credp)
752fea9cb91Slq {
753fea9cb91Slq 	int rval;
754fea9cb91Slq 
755aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) ldi_ioctl(tems.ts_hdl, VIS_CONSCOPY,
756fea9cb91Slq 	    (intptr_t)pma, FKIOCTL, credp, &rval);
757fea9cb91Slq }
758fea9cb91Slq 
759fea9cb91Slq /*
760fea9cb91Slq  * This function is used to show or hide a rectangluar monochrom
761fea9cb91Slq  * pixel inverting, text block cursor via the underlying framebuffer.
762fea9cb91Slq  */
763fea9cb91Slq void
tems_cursor_layered(struct vis_conscursor * pca,cred_t * credp)7645a801801SToomas Soome tems_cursor_layered(struct vis_conscursor *pca,
7655a801801SToomas Soome     cred_t *credp)
766fea9cb91Slq {
767fea9cb91Slq 	int rval;
768fea9cb91Slq 
769aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) ldi_ioctl(tems.ts_hdl, VIS_CONSCURSOR,
770fea9cb91Slq 	    (intptr_t)pca, FKIOCTL, credp, &rval);
771fea9cb91Slq }
772fea9cb91Slq 
773aecfc01dSrui zang - Sun Microsystems - Beijing China static void
tem_kdsetmode(int mode,cred_t * credp)774aecfc01dSrui zang - Sun Microsystems - Beijing China tem_kdsetmode(int mode, cred_t *credp)
775aecfc01dSrui zang - Sun Microsystems - Beijing China {
776aecfc01dSrui zang - Sun Microsystems - Beijing China 	int rval;
777aecfc01dSrui zang - Sun Microsystems - Beijing China 
778aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) ldi_ioctl(tems.ts_hdl, KDSETMODE,
779aecfc01dSrui zang - Sun Microsystems - Beijing China 	    (intptr_t)mode, FKIOCTL, credp, &rval);
780aecfc01dSrui zang - Sun Microsystems - Beijing China 
781aecfc01dSrui zang - Sun Microsystems - Beijing China }
782aecfc01dSrui zang - Sun Microsystems - Beijing China 
783aecfc01dSrui zang - Sun Microsystems - Beijing China static void
tems_reset_colormap(cred_t * credp,enum called_from called_from)784aecfc01dSrui zang - Sun Microsystems - Beijing China tems_reset_colormap(cred_t *credp, enum called_from called_from)
785fea9cb91Slq {
786fea9cb91Slq 	struct vis_cmap cm;
787fea9cb91Slq 	int rval;
788fea9cb91Slq 
789fea9cb91Slq 	if (called_from == CALLED_FROM_STANDALONE)
790fea9cb91Slq 		return;
791fea9cb91Slq 
792aecfc01dSrui zang - Sun Microsystems - Beijing China 	switch (tems.ts_pdepth) {
793fea9cb91Slq 	case 8:
794fea9cb91Slq 		cm.index = 0;
795fea9cb91Slq 		cm.count = 16;
796cbc8e155SToomas Soome 		cm.red   = (uint8_t *)cmap4_to_24.red;
797cbc8e155SToomas Soome 		cm.blue  = (uint8_t *)cmap4_to_24.blue;
798cbc8e155SToomas Soome 		cm.green = (uint8_t *)cmap4_to_24.green;
799aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) ldi_ioctl(tems.ts_hdl, VIS_PUTCMAP, (intptr_t)&cm,
800fea9cb91Slq 		    FKIOCTL, credp, &rval);
801fea9cb91Slq 		break;
802fea9cb91Slq 	}
803fea9cb91Slq }
804fea9cb91Slq 
805fea9cb91Slq void
tem_get_size(ushort_t * r,ushort_t * c,ushort_t * x,ushort_t * y)806b6bd4f48SToomas Soome tem_get_size(ushort_t *r, ushort_t *c, ushort_t *x, ushort_t *y)
807fea9cb91Slq {
808aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
809aecfc01dSrui zang - Sun Microsystems - Beijing China 	*r = (ushort_t)tems.ts_c_dimension.height;
810aecfc01dSrui zang - Sun Microsystems - Beijing China 	*c = (ushort_t)tems.ts_c_dimension.width;
811aecfc01dSrui zang - Sun Microsystems - Beijing China 	*x = (ushort_t)tems.ts_p_dimension.width;
812aecfc01dSrui zang - Sun Microsystems - Beijing China 	*y = (ushort_t)tems.ts_p_dimension.height;
813aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
814fea9cb91Slq }
815fea9cb91Slq 
816fea9cb91Slq void
tem_register_modechg_cb(tem_modechg_cb_t func,tem_modechg_cb_arg_t arg)817b6bd4f48SToomas Soome tem_register_modechg_cb(tem_modechg_cb_t func, tem_modechg_cb_arg_t arg)
818fea9cb91Slq {
819aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
820aecfc01dSrui zang - Sun Microsystems - Beijing China 
821aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_modechg_cb = func;
822aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_modechg_arg = arg;
823aecfc01dSrui zang - Sun Microsystems - Beijing China 
824aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
825fea9cb91Slq }
826fea9cb91Slq 
827fea9cb91Slq /*
828fea9cb91Slq  * This function is to scroll up the OBP output, which has
829fea9cb91Slq  * different screen height and width with our kernel console.
830fea9cb91Slq  */
831fea9cb91Slq static void
tem_prom_scroll_up(struct tem_vt_state * tem,int nrows,cred_t * credp,enum called_from called_from)832aecfc01dSrui zang - Sun Microsystems - Beijing China tem_prom_scroll_up(struct tem_vt_state *tem, int nrows, cred_t *credp,
833aecfc01dSrui zang - Sun Microsystems - Beijing China     enum called_from called_from)
834fea9cb91Slq {
835fea9cb91Slq 	struct vis_conscopy	ma;
836fea9cb91Slq 	int	ncols, width;
837fea9cb91Slq 
838fea9cb91Slq 	/* copy */
839cbc8e155SToomas Soome 	ma.s_row = nrows * tems.ts_font.vf_height;
840aecfc01dSrui zang - Sun Microsystems - Beijing China 	ma.e_row = tems.ts_p_dimension.height - 1;
841fea9cb91Slq 	ma.t_row = 0;
842fea9cb91Slq 
843fea9cb91Slq 	ma.s_col = 0;
844aecfc01dSrui zang - Sun Microsystems - Beijing China 	ma.e_col = tems.ts_p_dimension.width - 1;
845fea9cb91Slq 	ma.t_col = 0;
846fea9cb91Slq 
847aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems_safe_copy(&ma, credp, called_from);
848fea9cb91Slq 
849fea9cb91Slq 	/* clear */
850cbc8e155SToomas Soome 	width = tems.ts_font.vf_width;
851aecfc01dSrui zang - Sun Microsystems - Beijing China 	ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
852fea9cb91Slq 
853aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_safe_pix_cls_range(tem, 0, nrows, tems.ts_p_offset.y,
854aecfc01dSrui zang - Sun Microsystems - Beijing China 	    0, ncols, 0, B_TRUE, credp, called_from);
855fea9cb91Slq }
856fea9cb91Slq 
857fea9cb91Slq #define	PROM_DEFAULT_FONT_HEIGHT	22
858aecfc01dSrui zang - Sun Microsystems - Beijing China #define	PROM_DEFAULT_WINDOW_TOP		0x8a
859fea9cb91Slq 
860fea9cb91Slq /*
861fea9cb91Slq  * This function is to compute the starting row of the console, according to
862fea9cb91Slq  * PROM cursor's position. Here we have to take different fonts into account.
863fea9cb91Slq  */
864fea9cb91Slq static int
tem_adjust_row(struct tem_vt_state * tem,int prom_row,cred_t * credp,enum called_from called_from)865aecfc01dSrui zang - Sun Microsystems - Beijing China tem_adjust_row(struct tem_vt_state *tem, int prom_row, cred_t *credp,
866aecfc01dSrui zang - Sun Microsystems - Beijing China     enum called_from called_from)
867fea9cb91Slq {
868fea9cb91Slq 	int	tem_row;
869fea9cb91Slq 	int	tem_y;
870fea9cb91Slq 	int	prom_charheight = 0;
871fea9cb91Slq 	int	prom_window_top = 0;
872fea9cb91Slq 	int	scroll_up_lines;
873fea9cb91Slq 
8744291d474SToomas Soome 	if (tems.ts_display_mode == VIS_TEXT)
8754291d474SToomas Soome 		return (prom_row);
8764291d474SToomas Soome 
877fea9cb91Slq 	plat_tem_get_prom_font_size(&prom_charheight, &prom_window_top);
878fea9cb91Slq 	if (prom_charheight == 0)
879fea9cb91Slq 		prom_charheight = PROM_DEFAULT_FONT_HEIGHT;
880fea9cb91Slq 	if (prom_window_top == 0)
881fea9cb91Slq 		prom_window_top = PROM_DEFAULT_WINDOW_TOP;
882fea9cb91Slq 
883fea9cb91Slq 	tem_y = (prom_row + 1) * prom_charheight + prom_window_top -
884aecfc01dSrui zang - Sun Microsystems - Beijing China 	    tems.ts_p_offset.y;
885cbc8e155SToomas Soome 	tem_row = (tem_y + tems.ts_font.vf_height - 1) /
886cbc8e155SToomas Soome 	    tems.ts_font.vf_height - 1;
887fea9cb91Slq 
888fea9cb91Slq 	if (tem_row < 0) {
889fea9cb91Slq 		tem_row = 0;
890aecfc01dSrui zang - Sun Microsystems - Beijing China 	} else if (tem_row >= (tems.ts_c_dimension.height - 1)) {
891fea9cb91Slq 		/*
892fea9cb91Slq 		 * Scroll up the prom outputs if the PROM cursor's position is
893fea9cb91Slq 		 * below our tem's lower boundary.
894fea9cb91Slq 		 */
895fea9cb91Slq 		scroll_up_lines = tem_row -
896aecfc01dSrui zang - Sun Microsystems - Beijing China 		    (tems.ts_c_dimension.height - 1);
897aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_prom_scroll_up(tem, scroll_up_lines, credp, called_from);
898aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_row = tems.ts_c_dimension.height - 1;
899fea9cb91Slq 	}
900fea9cb91Slq 
901fea9cb91Slq 	return (tem_row);
902fea9cb91Slq }
903c9503a49Slq 
904aecfc01dSrui zang - Sun Microsystems - Beijing China void
tem_align(struct tem_vt_state * tem,cred_t * credp,enum called_from called_from)9054291d474SToomas Soome tem_align(struct tem_vt_state *tem, cred_t *credp,
906aecfc01dSrui zang - Sun Microsystems - Beijing China     enum called_from called_from)
907aecfc01dSrui zang - Sun Microsystems - Beijing China {
908aecfc01dSrui zang - Sun Microsystems - Beijing China 	uint32_t row = 0;
909aecfc01dSrui zang - Sun Microsystems - Beijing China 	uint32_t col = 0;
910aecfc01dSrui zang - Sun Microsystems - Beijing China 
9114291d474SToomas Soome 	plat_tem_hide_prom_cursor();
912aecfc01dSrui zang - Sun Microsystems - Beijing China 
9134291d474SToomas Soome 	/*
9144291d474SToomas Soome 	 * We are getting the current cursor position in pixel
9154291d474SToomas Soome 	 * mode so that we don't over-write the console output
9164291d474SToomas Soome 	 * during boot.
9174291d474SToomas Soome 	 */
9184291d474SToomas Soome 	plat_tem_get_prom_pos(&row, &col);
919aecfc01dSrui zang - Sun Microsystems - Beijing China 
9204291d474SToomas Soome 	/*
9214291d474SToomas Soome 	 * Adjust the row if necessary when the font of our
9224291d474SToomas Soome 	 * kernel console tem is different with that of prom
9234291d474SToomas Soome 	 * tem.
9244291d474SToomas Soome 	 */
9254291d474SToomas Soome 	row = tem_adjust_row(tem, row, credp, called_from);
926aecfc01dSrui zang - Sun Microsystems - Beijing China 
9274291d474SToomas Soome 	/* first line of our kernel console output */
9284291d474SToomas Soome 	tem->tvs_first_line = row + 1;
929aecfc01dSrui zang - Sun Microsystems - Beijing China 
9304291d474SToomas Soome 	/* re-set and align cursor position */
9314291d474SToomas Soome 	tem->tvs_s_cursor.row = tem->tvs_c_cursor.row =
9324291d474SToomas Soome 	    (screen_pos_t)row;
9334291d474SToomas Soome 	tem->tvs_s_cursor.col = tem->tvs_c_cursor.col = 0;
9342e5d9c98SToomas Soome 
9354291d474SToomas Soome 	/*
9364291d474SToomas Soome 	 * When tem is starting up, part of the screen is filled
9374291d474SToomas Soome 	 * with information from boot loader and early boot.
9384291d474SToomas Soome 	 * For tem, the screen content above current cursor
9394291d474SToomas Soome 	 * should be treated as image.
9404291d474SToomas Soome 	 */
9414291d474SToomas Soome 	for (; row > 0; row--) {
9424291d474SToomas Soome 		for (col = 0; col < tems.ts_c_dimension.width; col++) {
9434291d474SToomas Soome 			tem->tvs_screen_rows[row][col].tc_char =
9444291d474SToomas Soome 			    TEM_ATTR(TEM_ATTR_IMAGE);
9452e5d9c98SToomas Soome 		}
946aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
947aecfc01dSrui zang - Sun Microsystems - Beijing China }
948aecfc01dSrui zang - Sun Microsystems - Beijing China 
949c9503a49Slq static void
tems_get_inverses(boolean_t * p_inverse,boolean_t * p_inverse_screen)950aecfc01dSrui zang - Sun Microsystems - Beijing China tems_get_inverses(boolean_t *p_inverse, boolean_t *p_inverse_screen)
951c9503a49Slq {
952c9503a49Slq 	int i_inverse = 0;
953c9503a49Slq 	int i_inverse_screen = 0;
954c9503a49Slq 
955c9503a49Slq 	plat_tem_get_inverses(&i_inverse, &i_inverse_screen);
956c9503a49Slq 
957c9503a49Slq 	*p_inverse = (i_inverse == 0) ? B_FALSE : B_TRUE;
958c9503a49Slq 	*p_inverse_screen = (i_inverse_screen == 0) ? B_FALSE : B_TRUE;
959c9503a49Slq }
960c9503a49Slq 
961c9503a49Slq /*
962c9503a49Slq  * Get the foreground/background color and attributes from the initial
963c9503a49Slq  * PROM, so that our kernel console can keep the same visual behaviour.
964c9503a49Slq  */
965c9503a49Slq static void
tems_get_initial_color(tem_color_t * pcolor)966aecfc01dSrui zang - Sun Microsystems - Beijing China tems_get_initial_color(tem_color_t *pcolor)
967c9503a49Slq {
968c9503a49Slq 	boolean_t inverse, inverse_screen;
969c9503a49Slq 	unsigned short  flags = 0;
970fa9eb222SToomas Soome 	uint8_t fg, bg;
971c9503a49Slq 
972fa9eb222SToomas Soome 	fg = DEFAULT_ANSI_FOREGROUND;
973fa9eb222SToomas Soome 	bg = DEFAULT_ANSI_BACKGROUND;
9744dfe872dSToomas Soome #ifndef _HAVE_TEM_FIRMWARE
9754dfe872dSToomas Soome 	/*
9764dfe872dSToomas Soome 	 * _HAVE_TEM_FIRMWARE is defined on SPARC, at this time, the
9774dfe872dSToomas Soome 	 * plat_tem_get_colors() is implemented only on x86.
9784dfe872dSToomas Soome 	 */
979fa9eb222SToomas Soome 
980fa9eb222SToomas Soome 	plat_tem_get_colors(&fg, &bg);
9814dfe872dSToomas Soome #endif
982fa9eb222SToomas Soome 	pcolor->fg_color.n = fg;
983fa9eb222SToomas Soome 	pcolor->bg_color.n = bg;
984c9503a49Slq 
9854dfe872dSToomas Soome 	tems_get_inverses(&inverse, &inverse_screen);
9864dfe872dSToomas Soome 	if (inverse)
9874dfe872dSToomas Soome 		flags |= TEM_ATTR_REVERSE;
9884dfe872dSToomas Soome 	if (inverse_screen)
9894dfe872dSToomas Soome 		flags |= TEM_ATTR_SCREEN_REVERSE;
9904dfe872dSToomas Soome 
991e0721d5aSToomas Soome #ifdef _HAVE_TEM_FIRMWARE
9924dfe872dSToomas Soome 	if (flags != 0) {
9934dfe872dSToomas Soome 		/*
9944dfe872dSToomas Soome 		 * If either reverse flag is set, the screen is in
9954dfe872dSToomas Soome 		 * white-on-black mode.  We set the bold flag to
9964dfe872dSToomas Soome 		 * improve readability.
9974dfe872dSToomas Soome 		 */
9984dfe872dSToomas Soome 		flags |= TEM_ATTR_BOLD;
9994dfe872dSToomas Soome 	} else {
10004dfe872dSToomas Soome 		/*
10014dfe872dSToomas Soome 		 * Otherwise, the screen is in black-on-white mode.
10024dfe872dSToomas Soome 		 * The SPARC PROM console, which starts in this mode,
10034dfe872dSToomas Soome 		 * uses the bright white background colour so we
10044dfe872dSToomas Soome 		 * match it here.
10054dfe872dSToomas Soome 		 */
10066a8b10feSToomas Soome 		if (pcolor->bg_color.n == ANSI_COLOR_WHITE)
10074dfe872dSToomas Soome 			flags |= TEM_ATTR_BRIGHT_BG;
1008c9503a49Slq 	}
1009e0721d5aSToomas Soome #else
1010e0721d5aSToomas Soome 	if (flags != 0) {
1011fa9eb222SToomas Soome 		if (pcolor->fg_color.n == ANSI_COLOR_WHITE)
1012e0721d5aSToomas Soome 			flags |= TEM_ATTR_BRIGHT_BG;
1013e0721d5aSToomas Soome 
1014fa9eb222SToomas Soome 		if (pcolor->fg_color.n == ANSI_COLOR_BLACK)
1015e0721d5aSToomas Soome 			flags &= ~TEM_ATTR_BRIGHT_BG;
1016e0721d5aSToomas Soome 	} else {
1017e0721d5aSToomas Soome 		/*
1018e0721d5aSToomas Soome 		 * In case of black on white we want bright white for BG.
1019e0721d5aSToomas Soome 		 */
1020fa9eb222SToomas Soome 		if (pcolor->bg_color.n == ANSI_COLOR_WHITE)
1021e0721d5aSToomas Soome 			flags |= TEM_ATTR_BRIGHT_BG;
1022e0721d5aSToomas Soome 	}
1023e0721d5aSToomas Soome #endif
1024c9503a49Slq 
1025aecfc01dSrui zang - Sun Microsystems - Beijing China 	pcolor->a_flags = flags;
1026aecfc01dSrui zang - Sun Microsystems - Beijing China }
1027aecfc01dSrui zang - Sun Microsystems - Beijing China 
1028aecfc01dSrui zang - Sun Microsystems - Beijing China uchar_t
tem_get_fbmode(tem_vt_state_t tem_arg)1029aecfc01dSrui zang - Sun Microsystems - Beijing China tem_get_fbmode(tem_vt_state_t tem_arg)
1030aecfc01dSrui zang - Sun Microsystems - Beijing China {
1031aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
1032aecfc01dSrui zang - Sun Microsystems - Beijing China 
1033aecfc01dSrui zang - Sun Microsystems - Beijing China 	uchar_t fbmode;
1034aecfc01dSrui zang - Sun Microsystems - Beijing China 
1035aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tem->tvs_lock);
1036aecfc01dSrui zang - Sun Microsystems - Beijing China 	fbmode = tem->tvs_fbmode;
1037aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tem->tvs_lock);
1038aecfc01dSrui zang - Sun Microsystems - Beijing China 
1039aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (fbmode);
1040aecfc01dSrui zang - Sun Microsystems - Beijing China }
1041aecfc01dSrui zang - Sun Microsystems - Beijing China 
1042aecfc01dSrui zang - Sun Microsystems - Beijing China void
tem_set_fbmode(tem_vt_state_t tem_arg,uchar_t fbmode,cred_t * credp)1043aecfc01dSrui zang - Sun Microsystems - Beijing China tem_set_fbmode(tem_vt_state_t tem_arg, uchar_t fbmode, cred_t *credp)
1044aecfc01dSrui zang - Sun Microsystems - Beijing China {
1045aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
1046aecfc01dSrui zang - Sun Microsystems - Beijing China 
1047aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
1048aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tem->tvs_lock);
1049aecfc01dSrui zang - Sun Microsystems - Beijing China 
1050aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (fbmode == tem->tvs_fbmode) {
1051aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tem->tvs_lock);
1052aecfc01dSrui zang - Sun Microsystems - Beijing China 		mutex_exit(&tems.ts_lock);
1053aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
1054aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1055aecfc01dSrui zang - Sun Microsystems - Beijing China 
1056aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem->tvs_fbmode = fbmode;
1057aecfc01dSrui zang - Sun Microsystems - Beijing China 
1058aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tem->tvs_isactive) {
1059aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_kdsetmode(tem->tvs_fbmode, credp);
1060aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (fbmode == KD_TEXT)
1061aecfc01dSrui zang - Sun Microsystems - Beijing China 			tem_safe_unblank_screen(tem, credp, CALLED_FROM_NORMAL);
1062aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1063aecfc01dSrui zang - Sun Microsystems - Beijing China 
1064aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tem->tvs_lock);
1065aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
1066aecfc01dSrui zang - Sun Microsystems - Beijing China }
1067aecfc01dSrui zang - Sun Microsystems - Beijing China 
1068aecfc01dSrui zang - Sun Microsystems - Beijing China void
tem_activate(tem_vt_state_t tem_arg,boolean_t unblank,cred_t * credp)1069aecfc01dSrui zang - Sun Microsystems - Beijing China tem_activate(tem_vt_state_t tem_arg, boolean_t unblank, cred_t *credp)
1070aecfc01dSrui zang - Sun Microsystems - Beijing China {
1071aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
1072aecfc01dSrui zang - Sun Microsystems - Beijing China 
1073aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
1074aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_active = tem;
1075aecfc01dSrui zang - Sun Microsystems - Beijing China 
1076aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tem->tvs_lock);
1077aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem->tvs_isactive = B_TRUE;
1078aecfc01dSrui zang - Sun Microsystems - Beijing China 
1079aecfc01dSrui zang - Sun Microsystems - Beijing China 	tem_kdsetmode(tem->tvs_fbmode, credp);
1080aecfc01dSrui zang - Sun Microsystems - Beijing China 
1081aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (unblank)
1082aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_safe_unblank_screen(tem, credp, CALLED_FROM_NORMAL);
1083aecfc01dSrui zang - Sun Microsystems - Beijing China 
1084aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tem->tvs_lock);
1085aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
1086aecfc01dSrui zang - Sun Microsystems - Beijing China }
1087aecfc01dSrui zang - Sun Microsystems - Beijing China 
1088aecfc01dSrui zang - Sun Microsystems - Beijing China void
tem_switch(tem_vt_state_t tem_arg1,tem_vt_state_t tem_arg2,cred_t * credp)1089aecfc01dSrui zang - Sun Microsystems - Beijing China tem_switch(tem_vt_state_t tem_arg1, tem_vt_state_t tem_arg2, cred_t *credp)
1090aecfc01dSrui zang - Sun Microsystems - Beijing China {
1091aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *cur = (struct tem_vt_state *)tem_arg1;
1092aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct tem_vt_state *tobe = (struct tem_vt_state *)tem_arg2;
1093aecfc01dSrui zang - Sun Microsystems - Beijing China 
1094aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tems.ts_lock);
1095aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&tobe->tvs_lock);
1096aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&cur->tvs_lock);
1097aecfc01dSrui zang - Sun Microsystems - Beijing China 
1098aecfc01dSrui zang - Sun Microsystems - Beijing China 	tems.ts_active = tobe;
1099aecfc01dSrui zang - Sun Microsystems - Beijing China 	cur->tvs_isactive = B_FALSE;
1100aecfc01dSrui zang - Sun Microsystems - Beijing China 	tobe->tvs_isactive = B_TRUE;
1101aecfc01dSrui zang - Sun Microsystems - Beijing China 
1102aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&cur->tvs_lock);
1103aecfc01dSrui zang - Sun Microsystems - Beijing China 
1104aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (cur->tvs_fbmode != tobe->tvs_fbmode)
1105aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_kdsetmode(tobe->tvs_fbmode, credp);
1106aecfc01dSrui zang - Sun Microsystems - Beijing China 
1107aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (tobe->tvs_fbmode == KD_TEXT)
1108aecfc01dSrui zang - Sun Microsystems - Beijing China 		tem_safe_unblank_screen(tobe, credp, CALLED_FROM_NORMAL);
1109aecfc01dSrui zang - Sun Microsystems - Beijing China 
1110aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tobe->tvs_lock);
1111aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&tems.ts_lock);
1112c9503a49Slq }
1113