4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Copyright 2016 Joyent, Inc.
32 * Polled I/O safe ANSI terminal emulator module;
33 * Supporting TERM types 'sun' and 'sun-color, parsing
34 * ANSI x3.64 escape sequences, and the like. (See wscons(7d)
35 * for more information).
39 * The functions in this file *must* be able to function in
40 * standalone mode, ie. on a quiesced system. In that state,
41 * access is single threaded, only one CPU is running.
42 * System services are NOT available.
44 * The following restrictions pertain to every function
47 * - CANNOT use the DDI or LDI interfaces
48 * - CANNOT call system services
49 * - CANNOT use mutexes
50 * - CANNOT wait for interrupts
51 * - CANNOT allocate memory
53 * All non-static functions in this file which:
54 * - Operates on tems and tem_vt_state
55 * - Not only called from standalone mode, i.e. has
56 * a "calledfrom" argument
57 * should assert this at the beginning:
59 * ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
60 * called_from == CALLED_FROM_STANDALONE);
63 #include <sys/types.h>
64 #include <sys/ascii.h>
65 #include <sys/visual_io.h>
68 #include <sys/tem_impl.h>
69 #include <sys/ksynch.h>
70 #include <sys/sysmacros.h>
71 #include <sys/mutex.h>
73 #include <sys/t_lock.h>
75 tem_safe_callbacks_t tem_safe_text_callbacks
= {
76 &tem_safe_text_display
,
78 &tem_safe_text_cursor
,
82 tem_safe_callbacks_t tem_safe_pix_callbacks
= {
83 &tem_safe_pix_display
,
86 &tem_safe_pix_bit2pix
,
91 static void tem_safe_control(struct tem_vt_state
*, uchar_t
,
92 cred_t
*, enum called_from
);
93 static void tem_safe_setparam(struct tem_vt_state
*, int, int);
94 static void tem_safe_selgraph(struct tem_vt_state
*);
95 static void tem_safe_chkparam(struct tem_vt_state
*, uchar_t
,
96 cred_t
*, enum called_from
);
97 static void tem_safe_getparams(struct tem_vt_state
*, uchar_t
,
98 cred_t
*, enum called_from
);
99 static void tem_safe_outch(struct tem_vt_state
*, uchar_t
,
100 cred_t
*, enum called_from
);
101 static void tem_safe_parse(struct tem_vt_state
*, uchar_t
,
102 cred_t
*, enum called_from
);
104 static void tem_safe_new_line(struct tem_vt_state
*,
105 cred_t
*, enum called_from
);
106 static void tem_safe_cr(struct tem_vt_state
*);
107 static void tem_safe_lf(struct tem_vt_state
*,
108 cred_t
*, enum called_from
);
109 static void tem_safe_send_data(struct tem_vt_state
*, cred_t
*,
111 static void tem_safe_cls(struct tem_vt_state
*,
112 cred_t
*, enum called_from
);
113 static void tem_safe_tab(struct tem_vt_state
*,
114 cred_t
*, enum called_from
);
115 static void tem_safe_back_tab(struct tem_vt_state
*,
116 cred_t
*, enum called_from
);
117 static void tem_safe_clear_tabs(struct tem_vt_state
*, int);
118 static void tem_safe_set_tab(struct tem_vt_state
*);
119 static void tem_safe_mv_cursor(struct tem_vt_state
*, int, int,
120 cred_t
*, enum called_from
);
121 static void tem_safe_shift(struct tem_vt_state
*, int, int,
122 cred_t
*, enum called_from
);
123 static void tem_safe_scroll(struct tem_vt_state
*, int, int,
124 int, int, cred_t
*, enum called_from
);
125 static void tem_safe_clear_chars(struct tem_vt_state
*tem
,
126 int count
, screen_pos_t row
, screen_pos_t col
,
127 cred_t
*credp
, enum called_from called_from
);
128 static void tem_safe_copy_area(struct tem_vt_state
*tem
,
129 screen_pos_t s_col
, screen_pos_t s_row
,
130 screen_pos_t e_col
, screen_pos_t e_row
,
131 screen_pos_t t_col
, screen_pos_t t_row
,
132 cred_t
*credp
, enum called_from called_from
);
133 static void tem_safe_image_display(struct tem_vt_state
*, uchar_t
*,
134 int, int, screen_pos_t
, screen_pos_t
,
135 cred_t
*, enum called_from
);
136 static void tem_safe_bell(struct tem_vt_state
*tem
,
137 enum called_from called_from
);
138 static void tem_safe_pix_clear_prom_output(struct tem_vt_state
*tem
,
139 cred_t
*credp
, enum called_from called_from
);
141 static void tem_safe_virtual_cls(struct tem_vt_state
*, int, screen_pos_t
,
143 static void tem_safe_virtual_display(struct tem_vt_state
*,
144 unsigned char *, int, screen_pos_t
, screen_pos_t
,
145 text_color_t
, text_color_t
);
146 static void tem_safe_virtual_copy(struct tem_vt_state
*, screen_pos_t
,
147 screen_pos_t
, screen_pos_t
, screen_pos_t
,
148 screen_pos_t
, screen_pos_t
);
149 static void tem_safe_align_cursor(struct tem_vt_state
*tem
);
150 static void bit_to_pix4(struct tem_vt_state
*tem
, uchar_t c
,
151 text_color_t fg_color
, text_color_t bg_color
);
152 static void bit_to_pix8(struct tem_vt_state
*tem
, uchar_t c
,
153 text_color_t fg_color
, text_color_t bg_color
);
154 static void bit_to_pix24(struct tem_vt_state
*tem
, uchar_t c
,
155 text_color_t fg_color
, text_color_t bg_color
);
158 /* Bk Rd Gr Br Bl Mg Cy Wh */
159 static text_color_t dim_xlate
[] = { 1, 5, 3, 7, 2, 6, 4, 8 };
160 static text_color_t brt_xlate
[] = { 9, 13, 11, 15, 10, 14, 12, 0 };
164 text_cmap_t cmap4_to_24
= {
166 /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
167 Wh+ Bk Bl Gr Cy Rd Mg Br Wh Bk+ Bl+ Gr+ Cy+ Rd+ Mg+ Yw */
168 0xff,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x40,0x00,0x00,0x00,0xff,0xff,0xff,
169 0xff,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x40,0x00,0xff,0xff,0x00,0x00,0xff,
170 0xff,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x40,0xff,0x00,0xff,0x00,0xff,0x00
174 #define PIX4TO32(pix4) (uint32_t)( \
175 cmap4_to_24.red[pix4] << 16 | \
176 cmap4_to_24.green[pix4] << 8 | \
177 cmap4_to_24.blue[pix4])
179 #define INVERSE(ch) (ch ^ 0xff)
181 #define tem_safe_callback_display (*tems.ts_callbacks->tsc_display)
182 #define tem_safe_callback_copy (*tems.ts_callbacks->tsc_copy)
183 #define tem_safe_callback_cursor (*tems.ts_callbacks->tsc_cursor)
184 #define tem_safe_callback_cls (*tems.ts_callbacks->tsc_cls)
185 #define tem_safe_callback_bit2pix(tem, c, fg, bg) { \
186 ASSERT(tems.ts_callbacks->tsc_bit2pix != NULL); \
187 (void) (*tems.ts_callbacks->tsc_bit2pix)((tem), (c), (fg), (bg));\
191 tem_safe_check_first_time(
192 struct tem_vt_state
*tem
,
194 enum called_from called_from
)
196 static int first_time
= 1;
198 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
199 called_from
== CALLED_FROM_STANDALONE
);
202 * Realign the console cursor. We did this in tem_init().
203 * However, drivers in the console stream may emit additional
204 * messages before we are ready. This causes text overwrite
205 * on the screen. This is a workaround.
211 if (tems
.ts_display_mode
== VIS_TEXT
) {
212 tem_safe_text_cursor(tem
, VIS_GET_CURSOR
, credp
, called_from
);
213 tem_safe_align_cursor(tem
);
218 * This entry point handles output requests from restricted contexts like
219 * kmdb, where services like mutexes are not available. This function
220 * is entered when OBP or when a kernel debugger (such as kmdb)
221 * are generating console output. In those cases, power management
222 * concerns are handled by the abort sequence initiation (ie. when
223 * the user hits L1+A or the equivalent to enter OBP or the debugger.).
224 * It is also entered when the kernel is panicing.
227 tem_safe_polled_write(
228 tem_vt_state_t tem_arg
,
232 struct tem_vt_state
*tem
= (struct tem_vt_state
*)tem_arg
;
235 _NOTE(NO_COMPETING_THREADS_NOW
)
236 _NOTE(NO_COMPETING_THREADS_AS_SIDE_EFFECT
)
239 if (!tem
->tvs_initialized
) {
243 tem_safe_check_first_time(tem
, kcred
, CALLED_FROM_STANDALONE
);
244 tem_safe_terminal_emulate(tem
, buf
, len
, NULL
, CALLED_FROM_STANDALONE
);
247 /* Process partial UTF-8 sequence. */
249 tem_safe_input_partial(struct tem_vt_state
*tem
, cred_t
*credp
,
250 enum called_from called_from
)
255 if (tem
->tvs_utf8_left
== 0)
258 for (i
= 0; i
< sizeof (tem
->tvs_utf8_partial
); i
++) {
259 c
= (tem
->tvs_utf8_partial
>> (24 - (i
<< 3))) & 0xff;
261 tem_safe_parse(tem
, c
, credp
, called_from
);
264 tem
->tvs_utf8_left
= 0;
265 tem
->tvs_utf8_partial
= 0;
269 * Handle UTF-8 sequences.
272 tem_safe_input_byte(struct tem_vt_state
*tem
, uchar_t c
, cred_t
*credp
,
273 enum called_from called_from
)
276 * Check for UTF-8 code points. In case of error fall back to
277 * 8-bit code. As we only have 8859-1 fonts for console, this will set
278 * the limits on what chars we actually can display, therefore we
279 * have to return to this code once we have solved the font issue.
281 if ((c
& 0x80) == 0x00) {
282 /* One-byte sequence. */
283 tem_safe_input_partial(tem
, credp
, called_from
);
284 tem_safe_parse(tem
, c
, credp
, called_from
);
287 if ((c
& 0xe0) == 0xc0) {
288 /* Two-byte sequence. */
289 tem_safe_input_partial(tem
, credp
, called_from
);
290 tem
->tvs_utf8_left
= 1;
291 tem
->tvs_utf8_partial
= c
;
294 if ((c
& 0xf0) == 0xe0) {
295 /* Three-byte sequence. */
296 tem_safe_input_partial(tem
, credp
, called_from
);
297 tem
->tvs_utf8_left
= 2;
298 tem
->tvs_utf8_partial
= c
;
301 if ((c
& 0xf8) == 0xf0) {
302 /* Four-byte sequence. */
303 tem_safe_input_partial(tem
, credp
, called_from
);
304 tem
->tvs_utf8_left
= 3;
305 tem
->tvs_utf8_partial
= c
;
308 if ((c
& 0xc0) == 0x80) {
310 if (tem
->tvs_utf8_left
== 0) {
311 tem_safe_parse(tem
, c
, credp
, called_from
);
314 tem
->tvs_utf8_left
--;
315 tem
->tvs_utf8_partial
= (tem
->tvs_utf8_partial
<< 8) | c
;
316 if (tem
->tvs_utf8_left
== 0) {
321 * Transform the sequence of 2 to 4 bytes to
325 u
= tem
->tvs_utf8_partial
;
326 b
= (u
>> 24) & 0xff;
327 if (b
!= 0) { /* Four-byte sequence */
329 b
= (u
>> 16) & 0xff;
330 v
= (v
<< 6) | (b
& 0x3f);
332 v
= (v
<< 6) | (b
& 0x3f);
334 v
= (v
<< 6) | (b
& 0x3f);
335 } else if ((b
= (u
>> 16) & 0xff) != 0) {
336 v
= b
& 0x0f; /* Three-byte sequence */
338 v
= (v
<< 6) | (b
& 0x3f);
340 v
= (v
<< 6) | (b
& 0x3f);
341 } else if ((b
= (u
>> 8) & 0xff) != 0) {
342 v
= b
& 0x1f; /* Two-byte sequence */
344 v
= (v
<< 6) | (b
& 0x3f);
347 /* Use '?' as replacement if needed. */
350 tem_safe_parse(tem
, v
, credp
, called_from
);
351 tem
->tvs_utf8_partial
= 0;
355 /* Anything left is illegal in UTF-8 sequence. */
356 tem_safe_input_partial(tem
, credp
, called_from
);
357 tem_safe_parse(tem
, c
, credp
, called_from
);
361 * This is the main entry point into the terminal emulator.
363 * For each data message coming downstream, ANSI assumes that it is composed
364 * of ASCII characters, which are treated as a byte-stream input to the
365 * parsing state machine. All data is parsed immediately -- there is
369 tem_safe_terminal_emulate(
370 struct tem_vt_state
*tem
,
374 enum called_from called_from
)
377 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
378 called_from
== CALLED_FROM_STANDALONE
);
380 if (tem
->tvs_isactive
)
381 tem_safe_callback_cursor(tem
,
382 VIS_HIDE_CURSOR
, credp
, called_from
);
384 for (; len
> 0; len
--, buf
++)
385 tem_safe_input_byte(tem
, *buf
, credp
, called_from
);
388 * Send the data we just got to the framebuffer.
390 tem_safe_send_data(tem
, credp
, called_from
);
392 if (tem
->tvs_isactive
)
393 tem_safe_callback_cursor(tem
,
394 VIS_DISPLAY_CURSOR
, credp
, called_from
);
398 * Display an rectangular image on the frame buffer using the
399 * mechanism appropriate for the system state being called
400 * from quiesced or normal (ie. use polled I/O vs. layered ioctls)
403 tems_safe_display(struct vis_consdisplay
*pda
, cred_t
*credp
,
404 enum called_from called_from
)
406 if (called_from
== CALLED_FROM_STANDALONE
)
407 tems
.ts_fb_polledio
->display(tems
.ts_fb_polledio
->arg
, pda
);
409 tems_display_layered(pda
, credp
);
413 * Copy a rectangle from one location to another on the frame buffer
414 * using the mechanism appropriate for the system state being called
415 * from, quiesced or normal (ie. use polled I/O vs. layered ioctls)
418 tems_safe_copy(struct vis_conscopy
*pca
, cred_t
*credp
,
419 enum called_from called_from
)
421 if (called_from
== CALLED_FROM_STANDALONE
)
422 tems
.ts_fb_polledio
->copy(tems
.ts_fb_polledio
->arg
, pca
);
424 tems_copy_layered(pca
, credp
);
428 * Display or hide a rectangular block text cursor of a specificsize
429 * at a specific location on frame buffer* using the mechanism
430 * appropriate for the system state being called from, quisced or
431 * normal (ie. use polled I/O vs. layered ioctls).
434 tems_safe_cursor(struct vis_conscursor
*pca
, cred_t
*credp
,
435 enum called_from called_from
)
437 if (called_from
== CALLED_FROM_STANDALONE
)
438 tems
.ts_fb_polledio
->cursor(tems
.ts_fb_polledio
->arg
, pca
);
440 tems_cursor_layered(pca
, credp
);
444 * send the appropriate control message or set state based on the
445 * value of the control character ch
449 tem_safe_control(struct tem_vt_state
*tem
, uchar_t ch
, cred_t
*credp
,
450 enum called_from called_from
)
452 tem
->tvs_state
= A_STATE_START
;
455 tem_safe_bell(tem
, called_from
);
459 tem_safe_mv_cursor(tem
,
460 tem
->tvs_c_cursor
.row
,
461 tem
->tvs_c_cursor
.col
- 1,
466 tem_safe_tab(tem
, credp
, called_from
);
471 * tem_safe_send_data(tem, credp, called_from);
472 * tem_safe_new_line(tem, credp, called_from);
477 tem_safe_send_data(tem
, credp
, called_from
);
478 tem_safe_lf(tem
, credp
, called_from
);
482 tem_safe_send_data(tem
, credp
, called_from
);
483 tem_safe_cls(tem
, credp
, called_from
);
487 tem_safe_send_data(tem
, credp
, called_from
);
492 tem
->tvs_state
= A_STATE_ESC
;
498 tem
->tvs_curparam
= 0;
499 tem
->tvs_paramval
= 0;
500 tem
->tvs_gotparam
= B_FALSE
;
501 /* clear the parameters */
502 for (i
= 0; i
< TEM_MAXPARAMS
; i
++)
503 tem
->tvs_params
[i
] = -1;
504 tem
->tvs_state
= A_STATE_CSI
;
509 tem_safe_back_tab(tem
, credp
, called_from
);
519 * if parameters [0..count - 1] are not set, set them to the value
524 tem_safe_setparam(struct tem_vt_state
*tem
, int count
, int newparam
)
528 for (i
= 0; i
< count
; i
++) {
529 if (tem
->tvs_params
[i
] == -1)
530 tem
->tvs_params
[i
] = newparam
;
536 * select graphics mode based on the param vals stored in a_params
539 tem_safe_selgraph(struct tem_vt_state
*tem
)
545 tem
->tvs_state
= A_STATE_START
;
547 curparam
= tem
->tvs_curparam
;
549 param
= tem
->tvs_params
[count
];
554 /* reset to initial normal settings */
555 tem
->tvs_fg_color
= tems
.ts_init_color
.fg_color
;
556 tem
->tvs_bg_color
= tems
.ts_init_color
.bg_color
;
557 tem
->tvs_flags
= tems
.ts_init_color
.a_flags
;
560 case 1: /* Bold Intense */
561 tem
->tvs_flags
|= TEM_ATTR_BOLD
;
564 case 2: /* Faint Intense */
565 tem
->tvs_flags
&= ~TEM_ATTR_BOLD
;
569 tem
->tvs_flags
|= TEM_ATTR_BLINK
;
572 case 7: /* Reverse video */
573 if (tem
->tvs_flags
& TEM_ATTR_SCREEN_REVERSE
) {
574 tem
->tvs_flags
&= ~TEM_ATTR_REVERSE
;
576 tem
->tvs_flags
|= TEM_ATTR_REVERSE
;
580 case 30: /* black (grey) foreground */
581 case 31: /* red (light red) foreground */
582 case 32: /* green (light green) foreground */
583 case 33: /* brown (yellow) foreground */
584 case 34: /* blue (light blue) foreground */
585 case 35: /* magenta (light magenta) foreground */
586 case 36: /* cyan (light cyan) foreground */
587 case 37: /* white (bright white) foreground */
588 tem
->tvs_fg_color
= param
- 30;
589 tem
->tvs_flags
&= ~TEM_ATTR_BRIGHT_FG
;
594 * Reset the foreground colour and brightness.
596 tem
->tvs_fg_color
= tems
.ts_init_color
.fg_color
;
597 if (tems
.ts_init_color
.a_flags
& TEM_ATTR_BRIGHT_FG
)
598 tem
->tvs_flags
|= TEM_ATTR_BRIGHT_FG
;
600 tem
->tvs_flags
&= ~TEM_ATTR_BRIGHT_FG
;
603 case 40: /* black (grey) background */
604 case 41: /* red (light red) background */
605 case 42: /* green (light green) background */
606 case 43: /* brown (yellow) background */
607 case 44: /* blue (light blue) background */
608 case 45: /* magenta (light magenta) background */
609 case 46: /* cyan (light cyan) background */
610 case 47: /* white (bright white) background */
611 tem
->tvs_bg_color
= param
- 40;
612 tem
->tvs_flags
&= ~TEM_ATTR_BRIGHT_BG
;
617 * Reset the background colour and brightness.
619 tem
->tvs_bg_color
= tems
.ts_init_color
.bg_color
;
620 if (tems
.ts_init_color
.a_flags
& TEM_ATTR_BRIGHT_BG
)
621 tem
->tvs_flags
|= TEM_ATTR_BRIGHT_BG
;
623 tem
->tvs_flags
&= ~TEM_ATTR_BRIGHT_BG
;
626 case 90: /* black (grey) foreground */
627 case 91: /* red (light red) foreground */
628 case 92: /* green (light green) foreground */
629 case 93: /* brown (yellow) foreground */
630 case 94: /* blue (light blue) foreground */
631 case 95: /* magenta (light magenta) foreground */
632 case 96: /* cyan (light cyan) foreground */
633 case 97: /* white (bright white) foreground */
634 tem
->tvs_fg_color
= param
- 90;
635 tem
->tvs_flags
|= TEM_ATTR_BRIGHT_FG
;
638 case 100: /* black (grey) background */
639 case 101: /* red (light red) background */
640 case 102: /* green (light green) background */
641 case 103: /* brown (yellow) background */
642 case 104: /* blue (light blue) background */
643 case 105: /* magenta (light magenta) background */
644 case 106: /* cyan (light cyan) background */
645 case 107: /* white (bright white) background */
646 tem
->tvs_bg_color
= param
- 100;
647 tem
->tvs_flags
|= TEM_ATTR_BRIGHT_BG
;
656 } while (curparam
> 0);
660 * perform the appropriate action for the escape sequence
662 * General rule: This code does not validate the arguments passed.
663 * It assumes that the next lower level will do so.
666 tem_safe_chkparam(struct tem_vt_state
*tem
, uchar_t ch
, cred_t
*credp
,
667 enum called_from called_from
)
673 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
674 MUTEX_HELD(&tem
->tvs_lock
));
676 row
= tem
->tvs_c_cursor
.row
;
677 col
= tem
->tvs_c_cursor
.col
;
681 case 'm': /* select terminal graphics mode */
682 tem_safe_send_data(tem
, credp
, called_from
);
683 tem_safe_selgraph(tem
);
686 case '@': /* insert char */
687 tem_safe_setparam(tem
, 1, 1);
688 tem_safe_shift(tem
, tem
->tvs_params
[0], TEM_SHIFT_RIGHT
,
692 case 'A': /* cursor up */
693 tem_safe_setparam(tem
, 1, 1);
694 tem_safe_mv_cursor(tem
, row
- tem
->tvs_params
[0], col
,
698 case 'd': /* VPA - vertical position absolute */
699 tem_safe_setparam(tem
, 1, 1);
700 tem_safe_mv_cursor(tem
, tem
->tvs_params
[0] - 1, col
,
704 case 'e': /* VPR - vertical position relative */
705 case 'B': /* cursor down */
706 tem_safe_setparam(tem
, 1, 1);
707 tem_safe_mv_cursor(tem
, row
+ tem
->tvs_params
[0], col
,
711 case 'a': /* HPR - horizontal position relative */
712 case 'C': /* cursor right */
713 tem_safe_setparam(tem
, 1, 1);
714 tem_safe_mv_cursor(tem
, row
, col
+ tem
->tvs_params
[0],
718 case '`': /* HPA - horizontal position absolute */
719 tem_safe_setparam(tem
, 1, 1);
720 tem_safe_mv_cursor(tem
, row
, tem
->tvs_params
[0] - 1,
724 case 'D': /* cursor left */
725 tem_safe_setparam(tem
, 1, 1);
726 tem_safe_mv_cursor(tem
, row
, col
- tem
->tvs_params
[0],
730 case 'E': /* CNL cursor next line */
731 tem_safe_setparam(tem
, 1, 1);
732 tem_safe_mv_cursor(tem
, row
+ tem
->tvs_params
[0], 0,
736 case 'F': /* CPL cursor previous line */
737 tem_safe_setparam(tem
, 1, 1);
738 tem_safe_mv_cursor(tem
, row
- tem
->tvs_params
[0], 0,
742 case 'G': /* cursor horizontal position */
743 tem_safe_setparam(tem
, 1, 1);
744 tem_safe_mv_cursor(tem
, row
, tem
->tvs_params
[0] - 1,
748 case 'g': /* clear tabs */
749 tem_safe_setparam(tem
, 1, 0);
750 tem_safe_clear_tabs(tem
, tem
->tvs_params
[0]);
753 case 'f': /* HVP Horizontal and Vertical Position */
754 case 'H': /* CUP position cursor */
755 tem_safe_setparam(tem
, 2, 1);
756 tem_safe_mv_cursor(tem
,
757 tem
->tvs_params
[0] - 1,
758 tem
->tvs_params
[1] - 1,
762 case 'I': /* CHT - Cursor Horizontal Tab */
763 /* Not implemented */
766 case 'J': /* ED - Erase in Display */
767 tem_safe_send_data(tem
, credp
, called_from
);
768 tem_safe_setparam(tem
, 1, 0);
769 switch (tem
->tvs_params
[0]) {
771 /* erase cursor to end of screen */
772 /* FIRST erase cursor to end of line */
773 tem_safe_clear_chars(tem
,
774 tems
.ts_c_dimension
.width
-
775 tem
->tvs_c_cursor
.col
,
776 tem
->tvs_c_cursor
.row
,
777 tem
->tvs_c_cursor
.col
, credp
, called_from
);
779 /* THEN erase lines below the cursor */
780 for (row
= tem
->tvs_c_cursor
.row
+ 1;
781 row
< tems
.ts_c_dimension
.height
;
783 tem_safe_clear_chars(tem
,
784 tems
.ts_c_dimension
.width
,
785 row
, 0, credp
, called_from
);
790 /* erase beginning of screen to cursor */
791 /* FIRST erase lines above the cursor */
793 row
< tem
->tvs_c_cursor
.row
;
795 tem_safe_clear_chars(tem
,
796 tems
.ts_c_dimension
.width
,
797 row
, 0, credp
, called_from
);
799 /* THEN erase beginning of line to cursor */
800 tem_safe_clear_chars(tem
,
801 tem
->tvs_c_cursor
.col
+ 1,
802 tem
->tvs_c_cursor
.row
,
803 0, credp
, called_from
);
807 /* erase whole screen */
809 row
< tems
.ts_c_dimension
.height
;
811 tem_safe_clear_chars(tem
,
812 tems
.ts_c_dimension
.width
,
813 row
, 0, credp
, called_from
);
819 case 'K': /* EL - Erase in Line */
820 tem_safe_send_data(tem
, credp
, called_from
);
821 tem_safe_setparam(tem
, 1, 0);
822 switch (tem
->tvs_params
[0]) {
824 /* erase cursor to end of line */
825 tem_safe_clear_chars(tem
,
826 (tems
.ts_c_dimension
.width
-
827 tem
->tvs_c_cursor
.col
),
828 tem
->tvs_c_cursor
.row
,
829 tem
->tvs_c_cursor
.col
,
834 /* erase beginning of line to cursor */
835 tem_safe_clear_chars(tem
,
836 tem
->tvs_c_cursor
.col
+ 1,
837 tem
->tvs_c_cursor
.row
,
838 0, credp
, called_from
);
842 /* erase whole line */
843 tem_safe_clear_chars(tem
,
844 tems
.ts_c_dimension
.width
,
845 tem
->tvs_c_cursor
.row
,
846 0, credp
, called_from
);
851 case 'L': /* insert line */
852 tem_safe_send_data(tem
, credp
, called_from
);
853 tem_safe_setparam(tem
, 1, 1);
855 tem
->tvs_c_cursor
.row
,
856 tems
.ts_c_dimension
.height
- 1,
857 tem
->tvs_params
[0], TEM_SCROLL_DOWN
,
861 case 'M': /* delete line */
862 tem_safe_send_data(tem
, credp
, called_from
);
863 tem_safe_setparam(tem
, 1, 1);
865 tem
->tvs_c_cursor
.row
,
866 tems
.ts_c_dimension
.height
- 1,
867 tem
->tvs_params
[0], TEM_SCROLL_UP
,
871 case 'P': /* DCH - delete char */
872 tem_safe_setparam(tem
, 1, 1);
873 tem_safe_shift(tem
, tem
->tvs_params
[0], TEM_SHIFT_LEFT
,
877 case 'S': /* scroll up */
878 tem_safe_send_data(tem
, credp
, called_from
);
879 tem_safe_setparam(tem
, 1, 1);
880 tem_safe_scroll(tem
, 0,
881 tems
.ts_c_dimension
.height
- 1,
882 tem
->tvs_params
[0], TEM_SCROLL_UP
,
886 case 'T': /* scroll down */
887 tem_safe_send_data(tem
, credp
, called_from
);
888 tem_safe_setparam(tem
, 1, 1);
889 tem_safe_scroll(tem
, 0,
890 tems
.ts_c_dimension
.height
- 1,
891 tem
->tvs_params
[0], TEM_SCROLL_DOWN
,
895 case 'X': /* erase char */
896 tem_safe_setparam(tem
, 1, 1);
897 tem_safe_clear_chars(tem
,
899 tem
->tvs_c_cursor
.row
,
900 tem
->tvs_c_cursor
.col
,
904 case 'Z': /* cursor backward tabulation */
905 tem_safe_setparam(tem
, 1, 1);
908 * Rule exception - We do sanity checking here.
910 * Restrict the count to a sane value to keep from
911 * looping for a long time. There can't be more than one
912 * tab stop per column, so use that as a limit.
914 if (tem
->tvs_params
[0] > tems
.ts_c_dimension
.width
)
915 tem
->tvs_params
[0] = tems
.ts_c_dimension
.width
;
917 for (i
= 0; i
< tem
->tvs_params
[0]; i
++)
918 tem_safe_back_tab(tem
, credp
, called_from
);
921 tem
->tvs_state
= A_STATE_START
;
926 * Gather the parameters of an ANSI escape sequence
929 tem_safe_getparams(struct tem_vt_state
*tem
, uchar_t ch
,
930 cred_t
*credp
, enum called_from called_from
)
932 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
933 MUTEX_HELD(&tem
->tvs_lock
));
935 if (ch
>= '0' && ch
<= '9') {
936 tem
->tvs_paramval
= ((tem
->tvs_paramval
* 10) + (ch
- '0'));
937 tem
->tvs_gotparam
= B_TRUE
; /* Remember got parameter */
938 return; /* Return immediately */
939 } else if (tem
->tvs_state
== A_STATE_CSI_EQUAL
||
940 tem
->tvs_state
== A_STATE_CSI_QMARK
) {
941 tem
->tvs_state
= A_STATE_START
;
943 if (tem
->tvs_curparam
< TEM_MAXPARAMS
) {
944 if (tem
->tvs_gotparam
) {
945 /* get the parameter value */
946 tem
->tvs_params
[tem
->tvs_curparam
] =
953 /* Restart parameter search */
954 tem
->tvs_gotparam
= B_FALSE
;
955 tem
->tvs_paramval
= 0; /* No parame value yet */
957 /* Handle escape sequence */
958 tem_safe_chkparam(tem
, ch
, credp
, called_from
);
964 * Add character to internal buffer.
965 * When its full, send it to the next layer.
969 tem_safe_outch(struct tem_vt_state
*tem
, uchar_t ch
,
970 cred_t
*credp
, enum called_from called_from
)
973 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
974 called_from
== CALLED_FROM_STANDALONE
);
976 /* buffer up the character until later */
978 tem
->tvs_outbuf
[tem
->tvs_outindex
++] = ch
;
979 tem
->tvs_c_cursor
.col
++;
980 if (tem
->tvs_c_cursor
.col
>= tems
.ts_c_dimension
.width
) {
981 tem_safe_send_data(tem
, credp
, called_from
);
982 tem_safe_new_line(tem
, credp
, called_from
);
987 tem_safe_new_line(struct tem_vt_state
*tem
,
988 cred_t
*credp
, enum called_from called_from
)
991 tem_safe_lf(tem
, credp
, called_from
);
995 tem_safe_cr(struct tem_vt_state
*tem
)
997 tem
->tvs_c_cursor
.col
= 0;
998 tem_safe_align_cursor(tem
);
1002 tem_safe_lf(struct tem_vt_state
*tem
,
1003 cred_t
*credp
, enum called_from called_from
)
1007 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
1008 MUTEX_HELD(&tem
->tvs_lock
));
1011 * Sanity checking notes:
1012 * . a_nscroll was validated when it was set.
1013 * . Regardless of that, tem_safe_scroll and tem_safe_mv_cursor
1014 * will prevent anything bad from happening.
1016 row
= tem
->tvs_c_cursor
.row
+ 1;
1018 if (row
>= tems
.ts_c_dimension
.height
) {
1019 if (tem
->tvs_nscroll
!= 0) {
1020 tem_safe_scroll(tem
, 0,
1021 tems
.ts_c_dimension
.height
- 1,
1022 tem
->tvs_nscroll
, TEM_SCROLL_UP
,
1023 credp
, called_from
);
1024 row
= tems
.ts_c_dimension
.height
-
1026 } else { /* no scroll */
1028 * implement Esc[#r when # is zero. This means no
1029 * scroll but just return cursor to top of screen,
1030 * do not clear screen.
1036 tem_safe_mv_cursor(tem
, row
, tem
->tvs_c_cursor
.col
,
1037 credp
, called_from
);
1039 if (tem
->tvs_nscroll
== 0) {
1040 /* erase rest of cursor line */
1041 tem_safe_clear_chars(tem
,
1042 tems
.ts_c_dimension
.width
-
1043 tem
->tvs_c_cursor
.col
,
1044 tem
->tvs_c_cursor
.row
,
1045 tem
->tvs_c_cursor
.col
,
1046 credp
, called_from
);
1050 tem_safe_align_cursor(tem
);
1054 tem_safe_send_data(struct tem_vt_state
*tem
, cred_t
*credp
,
1055 enum called_from called_from
)
1057 text_color_t fg_color
;
1058 text_color_t bg_color
;
1060 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
1061 MUTEX_HELD(&tem
->tvs_lock
));
1063 if (tem
->tvs_outindex
== 0) {
1064 tem_safe_align_cursor(tem
);
1068 tem_safe_get_color(tem
, &fg_color
, &bg_color
, TEM_ATTR_REVERSE
);
1069 tem_safe_virtual_display(tem
,
1070 tem
->tvs_outbuf
, tem
->tvs_outindex
,
1071 tem
->tvs_s_cursor
.row
, tem
->tvs_s_cursor
.col
,
1072 fg_color
, bg_color
);
1074 if (tem
->tvs_isactive
) {
1076 * Call the primitive to render this data.
1078 tem_safe_callback_display(tem
,
1079 tem
->tvs_outbuf
, tem
->tvs_outindex
,
1080 tem
->tvs_s_cursor
.row
, tem
->tvs_s_cursor
.col
,
1082 credp
, called_from
);
1085 tem
->tvs_outindex
= 0;
1087 tem_safe_align_cursor(tem
);
1092 * We have just done something to the current output point. Reset the start
1093 * point for the buffered data in a_outbuf. There shouldn't be any data
1097 tem_safe_align_cursor(struct tem_vt_state
*tem
)
1099 tem
->tvs_s_cursor
.row
= tem
->tvs_c_cursor
.row
;
1100 tem
->tvs_s_cursor
.col
= tem
->tvs_c_cursor
.col
;
1104 * State machine parser based on the current state and character input
1105 * major terminations are to control character or normal character
1109 tem_safe_parse(struct tem_vt_state
*tem
, uchar_t ch
,
1110 cred_t
*credp
, enum called_from called_from
)
1114 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
1115 MUTEX_HELD(&tem
->tvs_lock
));
1117 if (tem
->tvs_state
== A_STATE_START
) { /* Normal state? */
1118 if (ch
== A_CSI
|| ch
== A_ESC
|| ch
< ' ') {
1120 tem_safe_control(tem
, ch
, credp
, called_from
);
1123 tem_safe_outch(tem
, ch
, credp
, called_from
);
1128 /* In <ESC> sequence */
1129 if (tem
->tvs_state
!= A_STATE_ESC
) { /* Need to get parameters? */
1130 if (tem
->tvs_state
!= A_STATE_CSI
) {
1131 tem_safe_getparams(tem
, ch
, credp
, called_from
);
1137 tem
->tvs_state
= A_STATE_CSI_QMARK
;
1140 tem
->tvs_state
= A_STATE_CSI_EQUAL
;
1144 * As defined below, this sequence
1145 * saves the cursor. However, Sun
1146 * defines ESC[s as reset. We resolved
1147 * the conflict by selecting reset as it
1148 * is exported in the termcap file for
1149 * sun-mon, while the "save cursor"
1150 * definition does not exist anywhere in
1152 * However, having no coherent
1153 * definition of reset, we have not
1159 * tem->tvs_r_cursor.row = tem->tvs_c_cursor.row;
1160 * tem->tvs_r_cursor.col = tem->tvs_c_cursor.col;
1161 * tem->tvs_state = A_STATE_START;
1164 tem
->tvs_state
= A_STATE_START
;
1167 tem_safe_mv_cursor(tem
, tem
->tvs_r_cursor
.row
,
1168 tem
->tvs_r_cursor
.col
, credp
, called_from
);
1169 tem
->tvs_state
= A_STATE_START
;
1171 case 'p': /* sunbow */
1172 tem_safe_send_data(tem
, credp
, called_from
);
1174 * Don't set anything if we are
1175 * already as we want to be.
1177 if (tem
->tvs_flags
& TEM_ATTR_SCREEN_REVERSE
) {
1178 tem
->tvs_flags
&= ~TEM_ATTR_SCREEN_REVERSE
;
1180 * If we have switched the characters to be the
1181 * inverse from the screen, then switch them as
1182 * well to keep them the inverse of the screen.
1184 if (tem
->tvs_flags
& TEM_ATTR_REVERSE
)
1185 tem
->tvs_flags
&= ~TEM_ATTR_REVERSE
;
1187 tem
->tvs_flags
|= TEM_ATTR_REVERSE
;
1189 tem_safe_cls(tem
, credp
, called_from
);
1190 tem
->tvs_state
= A_STATE_START
;
1192 case 'q': /* sunwob */
1193 tem_safe_send_data(tem
, credp
, called_from
);
1195 * Don't set anything if we are
1196 * already where as we want to be.
1198 if (!(tem
->tvs_flags
& TEM_ATTR_SCREEN_REVERSE
)) {
1199 tem
->tvs_flags
|= TEM_ATTR_SCREEN_REVERSE
;
1201 * If we have switched the characters to be the
1202 * inverse from the screen, then switch them as
1203 * well to keep them the inverse of the screen.
1205 if (!(tem
->tvs_flags
& TEM_ATTR_REVERSE
))
1206 tem
->tvs_flags
|= TEM_ATTR_REVERSE
;
1208 tem
->tvs_flags
&= ~TEM_ATTR_REVERSE
;
1211 tem_safe_cls(tem
, credp
, called_from
);
1212 tem
->tvs_state
= A_STATE_START
;
1214 case 'r': /* sunscrl */
1216 * Rule exception: check for validity here.
1218 tem
->tvs_nscroll
= tem
->tvs_paramval
;
1219 if (tem
->tvs_nscroll
> tems
.ts_c_dimension
.height
)
1220 tem
->tvs_nscroll
= tems
.ts_c_dimension
.height
;
1221 if (tem
->tvs_nscroll
< 0)
1222 tem
->tvs_nscroll
= 1;
1223 tem
->tvs_state
= A_STATE_START
;
1226 tem_safe_getparams(tem
, ch
, credp
, called_from
);
1231 /* Previous char was <ESC> */
1233 tem
->tvs_curparam
= 0;
1234 tem
->tvs_paramval
= 0;
1235 tem
->tvs_gotparam
= B_FALSE
;
1236 /* clear the parameters */
1237 for (i
= 0; i
< TEM_MAXPARAMS
; i
++)
1238 tem
->tvs_params
[i
] = -1;
1239 tem
->tvs_state
= A_STATE_CSI
;
1240 } else if (ch
== 'Q') { /* <ESC>Q ? */
1241 tem
->tvs_state
= A_STATE_START
;
1242 } else if (ch
== 'C') { /* <ESC>C ? */
1243 tem
->tvs_state
= A_STATE_START
;
1245 tem
->tvs_state
= A_STATE_START
;
1247 /* ESC c resets display */
1248 tem_safe_reset_display(tem
, credp
, called_from
,
1250 } else if (ch
== 'H') {
1251 /* ESC H sets a tab */
1252 tem_safe_set_tab(tem
);
1253 } else if (ch
== '7') {
1254 /* ESC 7 Save Cursor position */
1255 tem
->tvs_r_cursor
.row
= tem
->tvs_c_cursor
.row
;
1256 tem
->tvs_r_cursor
.col
= tem
->tvs_c_cursor
.col
;
1257 } else if (ch
== '8') {
1258 /* ESC 8 Restore Cursor position */
1259 tem_safe_mv_cursor(tem
, tem
->tvs_r_cursor
.row
,
1260 tem
->tvs_r_cursor
.col
, credp
, called_from
);
1261 /* check for control chars */
1262 } else if (ch
< ' ') {
1263 tem_safe_control(tem
, ch
, credp
, called_from
);
1265 tem_safe_outch(tem
, ch
, credp
, called_from
);
1272 tem_safe_bell(struct tem_vt_state
*tem
, enum called_from called_from
)
1274 if (called_from
== CALLED_FROM_STANDALONE
)
1275 (void) beep_polled(BEEP_CONSOLE
);
1277 (void) beep(BEEP_CONSOLE
);
1282 tem_safe_scroll(struct tem_vt_state
*tem
, int start
, int end
, int count
,
1283 int direction
, cred_t
*credp
, enum called_from called_from
)
1288 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1289 called_from
== CALLED_FROM_STANDALONE
);
1291 lines_affected
= end
- start
+ 1;
1292 if (count
> lines_affected
)
1293 count
= lines_affected
;
1297 switch (direction
) {
1299 if (count
< lines_affected
) {
1300 tem_safe_copy_area(tem
, 0, start
+ count
,
1301 tems
.ts_c_dimension
.width
- 1, end
,
1302 0, start
, credp
, called_from
);
1304 for (row
= (end
- count
) + 1; row
<= end
; row
++) {
1305 tem_safe_clear_chars(tem
, tems
.ts_c_dimension
.width
,
1306 row
, 0, credp
, called_from
);
1310 case TEM_SCROLL_DOWN
:
1311 if (count
< lines_affected
) {
1312 tem_safe_copy_area(tem
, 0, start
,
1313 tems
.ts_c_dimension
.width
- 1,
1314 end
- count
, 0, start
+ count
,
1315 credp
, called_from
);
1317 for (row
= start
; row
< start
+ count
; row
++) {
1318 tem_safe_clear_chars(tem
, tems
.ts_c_dimension
.width
,
1319 row
, 0, credp
, called_from
);
1326 tem_safe_copy_area(struct tem_vt_state
*tem
,
1327 screen_pos_t s_col
, screen_pos_t s_row
,
1328 screen_pos_t e_col
, screen_pos_t e_row
,
1329 screen_pos_t t_col
, screen_pos_t t_row
,
1330 cred_t
*credp
, enum called_from called_from
)
1335 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1336 called_from
== CALLED_FROM_STANDALONE
);
1338 if (s_col
< 0 || s_row
< 0 ||
1339 e_col
< 0 || e_row
< 0 ||
1340 t_col
< 0 || t_row
< 0 ||
1341 s_col
>= tems
.ts_c_dimension
.width
||
1342 e_col
>= tems
.ts_c_dimension
.width
||
1343 t_col
>= tems
.ts_c_dimension
.width
||
1344 s_row
>= tems
.ts_c_dimension
.height
||
1345 e_row
>= tems
.ts_c_dimension
.height
||
1346 t_row
>= tems
.ts_c_dimension
.height
)
1349 if (s_row
> e_row
|| s_col
> e_col
)
1352 rows
= e_row
- s_row
+ 1;
1353 cols
= e_col
- s_col
+ 1;
1354 if (t_row
+ rows
> tems
.ts_c_dimension
.height
||
1355 t_col
+ cols
> tems
.ts_c_dimension
.width
)
1358 tem_safe_virtual_copy(tem
,
1363 if (!tem
->tvs_isactive
)
1366 tem_safe_callback_copy(tem
, s_col
, s_row
,
1367 e_col
, e_row
, t_col
, t_row
, credp
, called_from
);
1371 tem_safe_clear_chars(struct tem_vt_state
*tem
, int count
, screen_pos_t row
,
1372 screen_pos_t col
, cred_t
*credp
, enum called_from called_from
)
1374 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1375 called_from
== CALLED_FROM_STANDALONE
);
1377 if (row
< 0 || row
>= tems
.ts_c_dimension
.height
||
1378 col
< 0 || col
>= tems
.ts_c_dimension
.width
||
1383 * Note that very large values of "count" could cause col+count
1384 * to overflow, so we check "count" independently.
1386 if (count
> tems
.ts_c_dimension
.width
||
1387 col
+ count
> tems
.ts_c_dimension
.width
)
1388 count
= tems
.ts_c_dimension
.width
- col
;
1390 tem_safe_virtual_cls(tem
, count
, row
, col
);
1392 if (!tem
->tvs_isactive
)
1395 tem_safe_callback_cls(tem
, count
, row
, col
, credp
, called_from
);
1400 tem_safe_text_display(struct tem_vt_state
*tem
, uchar_t
*string
,
1401 int count
, screen_pos_t row
, screen_pos_t col
,
1402 text_color_t fg_color
, text_color_t bg_color
,
1403 cred_t
*credp
, enum called_from called_from
)
1405 struct vis_consdisplay da
;
1407 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1408 called_from
== CALLED_FROM_STANDALONE
);
1411 da
.width
= (screen_size_t
)count
;
1415 da
.fg_color
= fg_color
;
1416 da
.bg_color
= bg_color
;
1418 tems_safe_display(&da
, credp
, called_from
);
1422 * This function is used to blit a rectangular color image,
1423 * unperturbed on the underlying framebuffer, to render
1424 * icons and pictures. The data is a pixel pattern that
1425 * fills a rectangle bounded to the width and height parameters.
1426 * The color pixel data must to be pre-adjusted by the caller
1427 * for the current video depth.
1429 * This function is unused now.
1433 tem_safe_image_display(struct tem_vt_state
*tem
, uchar_t
*image
,
1434 int height
, int width
, screen_pos_t row
, screen_pos_t col
,
1435 cred_t
*credp
, enum called_from called_from
)
1437 struct vis_consdisplay da
;
1439 mutex_enter(&tems
.ts_lock
);
1440 mutex_enter(&tem
->tvs_lock
);
1443 da
.width
= (screen_size_t
)width
;
1444 da
.height
= (screen_size_t
)height
;
1448 tems_safe_display(&da
, credp
, called_from
);
1450 mutex_exit(&tem
->tvs_lock
);
1451 mutex_exit(&tems
.ts_lock
);
1457 tem_safe_text_copy(struct tem_vt_state
*tem
,
1458 screen_pos_t s_col
, screen_pos_t s_row
,
1459 screen_pos_t e_col
, screen_pos_t e_row
,
1460 screen_pos_t t_col
, screen_pos_t t_row
,
1461 cred_t
*credp
, enum called_from called_from
)
1463 struct vis_conscopy da
;
1465 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1466 called_from
== CALLED_FROM_STANDALONE
);
1475 tems_safe_copy(&da
, credp
, called_from
);
1479 tem_safe_text_cls(struct tem_vt_state
*tem
,
1480 int count
, screen_pos_t row
, screen_pos_t col
, cred_t
*credp
,
1481 enum called_from called_from
)
1483 struct vis_consdisplay da
;
1485 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1486 called_from
== CALLED_FROM_STANDALONE
);
1488 da
.data
= tems
.ts_blank_line
;
1489 da
.width
= (screen_size_t
)count
;
1493 tem_safe_get_color(tem
, &da
.fg_color
, &da
.bg_color
,
1494 TEM_ATTR_SCREEN_REVERSE
);
1495 tems_safe_display(&da
, credp
, called_from
);
1499 tem_safe_pix_display(struct tem_vt_state
*tem
,
1500 uchar_t
*string
, int count
,
1501 screen_pos_t row
, screen_pos_t col
,
1502 text_color_t fg_color
, text_color_t bg_color
,
1503 cred_t
*credp
, enum called_from called_from
)
1505 struct vis_consdisplay da
;
1508 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1509 called_from
== CALLED_FROM_STANDALONE
);
1511 da
.data
= (uchar_t
*)tem
->tvs_pix_data
;
1512 da
.width
= tems
.ts_font
.width
;
1513 da
.height
= tems
.ts_font
.height
;
1514 da
.row
= (row
* da
.height
) + tems
.ts_p_offset
.y
;
1515 da
.col
= (col
* da
.width
) + tems
.ts_p_offset
.x
;
1517 for (i
= 0; i
< count
; i
++) {
1518 tem_safe_callback_bit2pix(tem
, string
[i
], fg_color
, bg_color
);
1519 tems_safe_display(&da
, credp
, called_from
);
1525 tem_safe_pix_copy(struct tem_vt_state
*tem
,
1526 screen_pos_t s_col
, screen_pos_t s_row
,
1527 screen_pos_t e_col
, screen_pos_t e_row
,
1528 screen_pos_t t_col
, screen_pos_t t_row
,
1530 enum called_from called_from
)
1532 struct vis_conscopy ma
;
1533 static boolean_t need_clear
= B_TRUE
;
1535 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1536 called_from
== CALLED_FROM_STANDALONE
);
1538 if (need_clear
&& tem
->tvs_first_line
> 0) {
1540 * Clear OBP output above our kernel console term
1541 * when our kernel console term begins to scroll up,
1542 * we hope it is user friendly.
1543 * (Also see comments on tem_safe_pix_clear_prom_output)
1545 * This is only one time call.
1547 tem_safe_pix_clear_prom_output(tem
, credp
, called_from
);
1549 need_clear
= B_FALSE
;
1551 ma
.s_row
= s_row
* tems
.ts_font
.height
+ tems
.ts_p_offset
.y
;
1552 ma
.e_row
= (e_row
+ 1) * tems
.ts_font
.height
+ tems
.ts_p_offset
.y
- 1;
1553 ma
.t_row
= t_row
* tems
.ts_font
.height
+ tems
.ts_p_offset
.y
;
1556 * Check if we're in process of clearing OBP's columns area,
1557 * which only happens when term scrolls up a whole line.
1559 if (tem
->tvs_first_line
> 0 && t_row
< s_row
&& t_col
== 0 &&
1560 e_col
== tems
.ts_c_dimension
.width
- 1) {
1562 * We need to clear OBP's columns area outside our kernel
1563 * console term. So that we set ma.e_col to entire row here.
1565 ma
.s_col
= s_col
* tems
.ts_font
.width
;
1566 ma
.e_col
= tems
.ts_p_dimension
.width
- 1;
1568 ma
.t_col
= t_col
* tems
.ts_font
.width
;
1570 ma
.s_col
= s_col
* tems
.ts_font
.width
+ tems
.ts_p_offset
.x
;
1571 ma
.e_col
= (e_col
+ 1) * tems
.ts_font
.width
+
1572 tems
.ts_p_offset
.x
- 1;
1573 ma
.t_col
= t_col
* tems
.ts_font
.width
+ tems
.ts_p_offset
.x
;
1576 tems_safe_copy(&ma
, credp
, called_from
);
1578 if (tem
->tvs_first_line
> 0 && t_row
< s_row
) {
1579 /* We have scrolled up (s_row - t_row) rows. */
1580 tem
->tvs_first_line
-= (s_row
- t_row
);
1581 if (tem
->tvs_first_line
<= 0) {
1582 /* All OBP rows have been cleared. */
1583 tem
->tvs_first_line
= 0;
1590 tem_safe_pix_bit2pix(struct tem_vt_state
*tem
, unsigned char c
,
1591 unsigned char fg
, unsigned char bg
)
1593 void (*fp
)(struct tem_vt_state
*, unsigned char,
1594 unsigned char, unsigned char);
1596 switch (tems
.ts_pdepth
) {
1613 * This function only clears count of columns in one row
1616 tem_safe_pix_cls(struct tem_vt_state
*tem
, int count
,
1617 screen_pos_t row
, screen_pos_t col
, cred_t
*credp
,
1618 enum called_from called_from
)
1620 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1621 called_from
== CALLED_FROM_STANDALONE
);
1623 tem_safe_pix_cls_range(tem
, row
, 1, tems
.ts_p_offset
.y
,
1624 col
, count
, tems
.ts_p_offset
.x
, B_FALSE
, credp
, called_from
);
1628 * This function clears OBP output above our kernel console term area
1629 * because OBP's term may have a bigger terminal window than that of
1630 * our kernel console term. So we need to clear OBP output garbage outside
1631 * of our kernel console term at a proper time, which is when the first
1632 * row output of our kernel console term scrolls at the first screen line.
1634 * _________________________________
1635 * | _____________________ | ---> OBP's bigger term window
1640 * |_|_|___________________|_______|
1641 * | | | ---> first line
1642 * | |___________________|---> our kernel console term window
1644 * |---> columns area to be cleared
1646 * This function only takes care of the output above our kernel console term,
1647 * and tem_prom_scroll_up takes care of columns area outside of our kernel
1651 tem_safe_pix_clear_prom_output(struct tem_vt_state
*tem
, cred_t
*credp
,
1652 enum called_from called_from
)
1654 int nrows
, ncols
, width
, height
;
1656 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1657 called_from
== CALLED_FROM_STANDALONE
);
1659 width
= tems
.ts_font
.width
;
1660 height
= tems
.ts_font
.height
;
1662 nrows
= (tems
.ts_p_offset
.y
+ (height
- 1))/ height
;
1663 ncols
= (tems
.ts_p_dimension
.width
+ (width
- 1))/ width
;
1665 tem_safe_pix_cls_range(tem
, 0, nrows
, 0, 0, ncols
, 0,
1666 B_FALSE
, credp
, called_from
);
1670 * clear the whole screen for pixel mode, just clear the
1674 tem_safe_pix_clear_entire_screen(struct tem_vt_state
*tem
, cred_t
*credp
,
1675 enum called_from called_from
)
1677 int nrows
, ncols
, width
, height
;
1679 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1680 called_from
== CALLED_FROM_STANDALONE
);
1682 width
= tems
.ts_font
.width
;
1683 height
= tems
.ts_font
.height
;
1685 nrows
= (tems
.ts_p_dimension
.height
+ (height
- 1))/ height
;
1686 ncols
= (tems
.ts_p_dimension
.width
+ (width
- 1))/ width
;
1688 tem_safe_pix_cls_range(tem
, 0, nrows
, 0, 0, ncols
, 0,
1689 B_FALSE
, credp
, called_from
);
1692 * Since the whole screen is cleared, we don't need
1693 * to clear OBP output later.
1695 if (tem
->tvs_first_line
> 0)
1696 tem
->tvs_first_line
= 0;
1700 * clear the whole screen, including the virtual screen buffer,
1701 * and reset the cursor to start point.
1704 tem_safe_cls(struct tem_vt_state
*tem
,
1705 cred_t
*credp
, enum called_from called_from
)
1709 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1710 called_from
== CALLED_FROM_STANDALONE
);
1712 if (tems
.ts_display_mode
== VIS_TEXT
) {
1713 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
1714 tem_safe_clear_chars(tem
, tems
.ts_c_dimension
.width
,
1715 row
, 0, credp
, called_from
);
1717 tem
->tvs_c_cursor
.row
= 0;
1718 tem
->tvs_c_cursor
.col
= 0;
1719 tem_safe_align_cursor(tem
);
1723 ASSERT(tems
.ts_display_mode
== VIS_PIXEL
);
1725 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
1726 tem_safe_virtual_cls(tem
, tems
.ts_c_dimension
.width
, row
, 0);
1728 tem
->tvs_c_cursor
.row
= 0;
1729 tem
->tvs_c_cursor
.col
= 0;
1730 tem_safe_align_cursor(tem
);
1732 if (!tem
->tvs_isactive
)
1735 tem_safe_pix_clear_entire_screen(tem
, credp
, called_from
);
1739 tem_safe_back_tab(struct tem_vt_state
*tem
,
1740 cred_t
*credp
, enum called_from called_from
)
1743 screen_pos_t tabstop
;
1745 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1746 called_from
== CALLED_FROM_STANDALONE
);
1750 for (i
= tem
->tvs_ntabs
- 1; i
>= 0; i
--) {
1751 if (tem
->tvs_tabs
[i
] < tem
->tvs_c_cursor
.col
) {
1752 tabstop
= tem
->tvs_tabs
[i
];
1757 tem_safe_mv_cursor(tem
, tem
->tvs_c_cursor
.row
,
1758 tabstop
, credp
, called_from
);
1762 tem_safe_tab(struct tem_vt_state
*tem
,
1763 cred_t
*credp
, enum called_from called_from
)
1766 screen_pos_t tabstop
;
1768 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1769 called_from
== CALLED_FROM_STANDALONE
);
1771 tabstop
= tems
.ts_c_dimension
.width
- 1;
1773 for (i
= 0; i
< tem
->tvs_ntabs
; i
++) {
1774 if (tem
->tvs_tabs
[i
] > tem
->tvs_c_cursor
.col
) {
1775 tabstop
= tem
->tvs_tabs
[i
];
1780 tem_safe_mv_cursor(tem
, tem
->tvs_c_cursor
.row
,
1781 tabstop
, credp
, called_from
);
1785 tem_safe_set_tab(struct tem_vt_state
*tem
)
1790 if (tem
->tvs_ntabs
== TEM_MAXTAB
)
1792 if (tem
->tvs_ntabs
== 0 ||
1793 tem
->tvs_tabs
[tem
->tvs_ntabs
] < tem
->tvs_c_cursor
.col
) {
1794 tem
->tvs_tabs
[tem
->tvs_ntabs
++] = tem
->tvs_c_cursor
.col
;
1797 for (i
= 0; i
< tem
->tvs_ntabs
; i
++) {
1798 if (tem
->tvs_tabs
[i
] == tem
->tvs_c_cursor
.col
)
1800 if (tem
->tvs_tabs
[i
] > tem
->tvs_c_cursor
.col
) {
1801 for (j
= tem
->tvs_ntabs
- 1; j
>= i
; j
--)
1802 tem
->tvs_tabs
[j
+ 1] = tem
->tvs_tabs
[j
];
1803 tem
->tvs_tabs
[i
] = tem
->tvs_c_cursor
.col
;
1811 tem_safe_clear_tabs(struct tem_vt_state
*tem
, int action
)
1817 case 3: /* clear all tabs */
1820 case 0: /* clr tab at cursor */
1822 for (i
= 0; i
< tem
->tvs_ntabs
; i
++) {
1823 if (tem
->tvs_tabs
[i
] == tem
->tvs_c_cursor
.col
) {
1825 for (j
= i
; j
< tem
->tvs_ntabs
; j
++)
1826 tem
->tvs_tabs
[j
] = tem
->tvs_tabs
[j
+ 1];
1835 tem_safe_mv_cursor(struct tem_vt_state
*tem
, int row
, int col
,
1836 cred_t
*credp
, enum called_from called_from
)
1838 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1839 called_from
== CALLED_FROM_STANDALONE
);
1842 * Sanity check and bounds enforcement. Out of bounds requests are
1843 * clipped to the screen boundaries. This seems to be what SPARC
1848 if (row
>= tems
.ts_c_dimension
.height
)
1849 row
= tems
.ts_c_dimension
.height
- 1;
1852 if (col
>= tems
.ts_c_dimension
.width
)
1853 col
= tems
.ts_c_dimension
.width
- 1;
1855 tem_safe_send_data(tem
, credp
, called_from
);
1856 tem
->tvs_c_cursor
.row
= (screen_pos_t
)row
;
1857 tem
->tvs_c_cursor
.col
= (screen_pos_t
)col
;
1858 tem_safe_align_cursor(tem
);
1863 tem_safe_reset_emulator(struct tem_vt_state
*tem
,
1864 cred_t
*credp
, enum called_from called_from
,
1865 boolean_t init_color
)
1869 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1870 called_from
== CALLED_FROM_STANDALONE
);
1872 tem
->tvs_c_cursor
.row
= 0;
1873 tem
->tvs_c_cursor
.col
= 0;
1874 tem
->tvs_r_cursor
.row
= 0;
1875 tem
->tvs_r_cursor
.col
= 0;
1876 tem
->tvs_s_cursor
.row
= 0;
1877 tem
->tvs_s_cursor
.col
= 0;
1878 tem
->tvs_outindex
= 0;
1879 tem
->tvs_state
= A_STATE_START
;
1880 tem
->tvs_gotparam
= B_FALSE
;
1881 tem
->tvs_curparam
= 0;
1882 tem
->tvs_paramval
= 0;
1883 tem
->tvs_nscroll
= 1;
1886 /* use initial settings */
1887 tem
->tvs_fg_color
= tems
.ts_init_color
.fg_color
;
1888 tem
->tvs_bg_color
= tems
.ts_init_color
.bg_color
;
1889 tem
->tvs_flags
= tems
.ts_init_color
.a_flags
;
1893 * set up the initial tab stops
1896 for (j
= 8; j
< tems
.ts_c_dimension
.width
; j
+= 8)
1897 tem
->tvs_tabs
[tem
->tvs_ntabs
++] = (screen_pos_t
)j
;
1899 for (j
= 0; j
< TEM_MAXPARAMS
; j
++)
1900 tem
->tvs_params
[j
] = 0;
1904 tem_safe_reset_display(struct tem_vt_state
*tem
,
1905 cred_t
*credp
, enum called_from called_from
,
1906 boolean_t clear_txt
, boolean_t init_color
)
1908 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1909 called_from
== CALLED_FROM_STANDALONE
);
1911 tem_safe_reset_emulator(tem
, credp
, called_from
, init_color
);
1914 if (tem
->tvs_isactive
)
1915 tem_safe_callback_cursor(tem
,
1916 VIS_HIDE_CURSOR
, credp
, called_from
);
1918 tem_safe_cls(tem
, credp
, called_from
);
1920 if (tem
->tvs_isactive
)
1921 tem_safe_callback_cursor(tem
,
1922 VIS_DISPLAY_CURSOR
, credp
, called_from
);
1928 struct tem_vt_state
*tem
,
1932 enum called_from called_from
)
1936 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1937 called_from
== CALLED_FROM_STANDALONE
);
1939 rest_of_line
= tems
.ts_c_dimension
.width
- tem
->tvs_c_cursor
.col
;
1940 if (count
> rest_of_line
)
1941 count
= rest_of_line
;
1946 switch (direction
) {
1947 case TEM_SHIFT_LEFT
:
1948 if (count
< rest_of_line
) {
1949 tem_safe_copy_area(tem
,
1950 tem
->tvs_c_cursor
.col
+ count
,
1951 tem
->tvs_c_cursor
.row
,
1952 tems
.ts_c_dimension
.width
- 1,
1953 tem
->tvs_c_cursor
.row
,
1954 tem
->tvs_c_cursor
.col
,
1955 tem
->tvs_c_cursor
.row
,
1956 credp
, called_from
);
1959 tem_safe_clear_chars(tem
, count
, tem
->tvs_c_cursor
.row
,
1960 (tems
.ts_c_dimension
.width
- count
), credp
,
1963 case TEM_SHIFT_RIGHT
:
1964 if (count
< rest_of_line
) {
1965 tem_safe_copy_area(tem
,
1966 tem
->tvs_c_cursor
.col
,
1967 tem
->tvs_c_cursor
.row
,
1968 tems
.ts_c_dimension
.width
- count
- 1,
1969 tem
->tvs_c_cursor
.row
,
1970 tem
->tvs_c_cursor
.col
+ count
,
1971 tem
->tvs_c_cursor
.row
,
1972 credp
, called_from
);
1975 tem_safe_clear_chars(tem
, count
, tem
->tvs_c_cursor
.row
,
1976 tem
->tvs_c_cursor
.col
, credp
, called_from
);
1982 tem_safe_text_cursor(struct tem_vt_state
*tem
, short action
,
1983 cred_t
*credp
, enum called_from called_from
)
1985 struct vis_conscursor ca
;
1987 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1988 called_from
== CALLED_FROM_STANDALONE
);
1990 ca
.row
= tem
->tvs_c_cursor
.row
;
1991 ca
.col
= tem
->tvs_c_cursor
.col
;
1994 tems_safe_cursor(&ca
, credp
, called_from
);
1996 if (action
== VIS_GET_CURSOR
) {
1997 tem
->tvs_c_cursor
.row
= ca
.row
;
1998 tem
->tvs_c_cursor
.col
= ca
.col
;
2003 tem_safe_pix_cursor(struct tem_vt_state
*tem
, short action
,
2004 cred_t
*credp
, enum called_from called_from
)
2006 struct vis_conscursor ca
;
2008 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
2009 called_from
== CALLED_FROM_STANDALONE
);
2011 ca
.row
= tem
->tvs_c_cursor
.row
* tems
.ts_font
.height
+
2013 ca
.col
= tem
->tvs_c_cursor
.col
* tems
.ts_font
.width
+
2015 ca
.width
= tems
.ts_font
.width
;
2016 ca
.height
= tems
.ts_font
.height
;
2017 if (tems
.ts_pdepth
== 8 || tems
.ts_pdepth
== 4) {
2018 if (tem
->tvs_flags
& TEM_ATTR_REVERSE
) {
2019 ca
.fg_color
.mono
= TEM_TEXT_WHITE
;
2020 ca
.bg_color
.mono
= TEM_TEXT_BLACK
;
2022 ca
.fg_color
.mono
= TEM_TEXT_BLACK
;
2023 ca
.bg_color
.mono
= TEM_TEXT_WHITE
;
2025 } else if (tems
.ts_pdepth
== 24 || tems
.ts_pdepth
== 32) {
2026 if (tem
->tvs_flags
& TEM_ATTR_REVERSE
) {
2027 ca
.fg_color
.twentyfour
[0] = TEM_TEXT_WHITE24_RED
;
2028 ca
.fg_color
.twentyfour
[1] = TEM_TEXT_WHITE24_GREEN
;
2029 ca
.fg_color
.twentyfour
[2] = TEM_TEXT_WHITE24_BLUE
;
2031 ca
.bg_color
.twentyfour
[0] = TEM_TEXT_BLACK24_RED
;
2032 ca
.bg_color
.twentyfour
[1] = TEM_TEXT_BLACK24_GREEN
;
2033 ca
.bg_color
.twentyfour
[2] = TEM_TEXT_BLACK24_BLUE
;
2035 ca
.fg_color
.twentyfour
[0] = TEM_TEXT_BLACK24_RED
;
2036 ca
.fg_color
.twentyfour
[1] = TEM_TEXT_BLACK24_GREEN
;
2037 ca
.fg_color
.twentyfour
[2] = TEM_TEXT_BLACK24_BLUE
;
2039 ca
.bg_color
.twentyfour
[0] = TEM_TEXT_WHITE24_RED
;
2040 ca
.bg_color
.twentyfour
[1] = TEM_TEXT_WHITE24_GREEN
;
2041 ca
.bg_color
.twentyfour
[2] = TEM_TEXT_WHITE24_BLUE
;
2047 tems_safe_cursor(&ca
, credp
, called_from
);
2051 bit_to_pix4(struct tem_vt_state
*tem
, uchar_t c
, text_color_t fg_color
,
2052 text_color_t bg_color
)
2054 uint8_t *dest
= (uint8_t *)tem
->tvs_pix_data
;
2055 font_bit_to_pix4(&tems
.ts_font
, dest
, c
, fg_color
, bg_color
);
2059 bit_to_pix8(struct tem_vt_state
*tem
, uchar_t c
, text_color_t fg_color
,
2060 text_color_t bg_color
)
2062 uint8_t *dest
= (uint8_t *)tem
->tvs_pix_data
;
2063 font_bit_to_pix8(&tems
.ts_font
, dest
, c
, fg_color
, bg_color
);
2067 bit_to_pix24(struct tem_vt_state
*tem
, uchar_t c
, text_color_t fg_color4
,
2068 text_color_t bg_color4
)
2070 uint32_t fg_color32
, bg_color32
, *dest
;
2072 ASSERT(fg_color4
< 16 && bg_color4
< 16);
2074 fg_color32
= PIX4TO32(fg_color4
);
2075 bg_color32
= PIX4TO32(bg_color4
);
2077 dest
= (uint32_t *)tem
->tvs_pix_data
;
2078 font_bit_to_pix24(&tems
.ts_font
, dest
, c
, fg_color32
, bg_color32
);
2082 ansi_bg_to_solaris(struct tem_vt_state
*tem
, int ansi
)
2084 if (tem
->tvs_flags
& TEM_ATTR_BRIGHT_BG
)
2085 return (brt_xlate
[ansi
]);
2087 return (dim_xlate
[ansi
]);
2091 ansi_fg_to_solaris(struct tem_vt_state
*tem
, int ansi
)
2093 if (tem
->tvs_flags
& TEM_ATTR_BRIGHT_FG
||
2094 tem
->tvs_flags
& TEM_ATTR_BOLD
) {
2095 return (brt_xlate
[ansi
]);
2097 return (dim_xlate
[ansi
]);
2102 * flag: TEM_ATTR_SCREEN_REVERSE or TEM_ATTR_REVERSE
2105 tem_safe_get_color(struct tem_vt_state
*tem
, text_color_t
*fg
,
2106 text_color_t
*bg
, uint8_t flag
)
2108 if (tem
->tvs_flags
& flag
) {
2109 *fg
= ansi_fg_to_solaris(tem
,
2111 *bg
= ansi_bg_to_solaris(tem
,
2114 *fg
= ansi_fg_to_solaris(tem
,
2116 *bg
= ansi_bg_to_solaris(tem
,
2122 * Clear a rectangle of screen for pixel mode.
2126 * nrows: the number of rows to clear
2127 * offset_y: the offset of height in pixels to begin clear
2129 * ncols: the number of cols to clear
2130 * offset_x: the offset of width in pixels to begin clear
2131 * scroll_up: whether this function is called during sroll up,
2132 * which is called only once.
2135 tem_safe_pix_cls_range(struct tem_vt_state
*tem
,
2136 screen_pos_t row
, int nrows
, int offset_y
,
2137 screen_pos_t col
, int ncols
, int offset_x
,
2138 boolean_t sroll_up
, cred_t
*credp
,
2139 enum called_from called_from
)
2141 struct vis_consdisplay da
;
2144 text_color_t fg_color
;
2145 text_color_t bg_color
;
2147 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
2148 called_from
== CALLED_FROM_STANDALONE
);
2151 row_add
= tems
.ts_c_dimension
.height
- 1;
2153 da
.width
= tems
.ts_font
.width
;
2154 da
.height
= tems
.ts_font
.height
;
2156 tem_safe_get_color(tem
, &fg_color
, &bg_color
, TEM_ATTR_SCREEN_REVERSE
);
2158 tem_safe_callback_bit2pix(tem
, ' ', fg_color
, bg_color
);
2159 da
.data
= (uchar_t
*)tem
->tvs_pix_data
;
2161 for (i
= 0; i
< nrows
; i
++, row
++) {
2162 da
.row
= (row
+ row_add
) * da
.height
+ offset_y
;
2163 da
.col
= col
* da
.width
+ offset_x
;
2164 for (j
= 0; j
< ncols
; j
++) {
2165 tems_safe_display(&da
, credp
, called_from
);
2172 * virtual screen operations
2175 tem_safe_virtual_display(struct tem_vt_state
*tem
, unsigned char *string
,
2176 int count
, screen_pos_t row
, screen_pos_t col
,
2177 text_color_t fg_color
, text_color_t bg_color
)
2180 unsigned char *addr
;
2181 text_color_t
*pfgcolor
;
2182 text_color_t
*pbgcolor
;
2184 if (row
< 0 || row
>= tems
.ts_c_dimension
.height
||
2185 col
< 0 || col
>= tems
.ts_c_dimension
.width
||
2186 col
+ count
> tems
.ts_c_dimension
.width
)
2189 width
= tems
.ts_c_dimension
.width
;
2190 addr
= tem
->tvs_screen_buf
+ (row
* width
+ col
);
2191 pfgcolor
= tem
->tvs_fg_buf
+ (row
* width
+ col
);
2192 pbgcolor
= tem
->tvs_bg_buf
+ (row
* width
+ col
);
2193 for (i
= 0; i
< count
; i
++) {
2194 *addr
++ = string
[i
];
2195 *pfgcolor
++ = fg_color
;
2196 *pbgcolor
++ = bg_color
;
2201 i_virtual_copy(unsigned char *base
,
2202 screen_pos_t s_col
, screen_pos_t s_row
,
2203 screen_pos_t e_col
, screen_pos_t e_row
,
2204 screen_pos_t t_col
, screen_pos_t t_row
)
2206 unsigned char *from
;
2209 screen_size_t chars_per_row
;
2210 unsigned char *to_row_start
;
2211 unsigned char *from_row_start
;
2212 screen_size_t rows_to_move
;
2213 int cols
= tems
.ts_c_dimension
.width
;
2215 chars_per_row
= e_col
- s_col
+ 1;
2216 rows_to_move
= e_row
- s_row
+ 1;
2218 to_row_start
= base
+ ((t_row
* cols
) + t_col
);
2219 from_row_start
= base
+ ((s_row
* cols
) + s_col
);
2221 if (to_row_start
< from_row_start
) {
2222 while (rows_to_move
-- > 0) {
2224 from
= from_row_start
;
2225 to_row_start
+= cols
;
2226 from_row_start
+= cols
;
2227 for (cnt
= chars_per_row
; cnt
-- > 0; )
2232 * Offset to the end of the region and copy backwards.
2234 cnt
= rows_to_move
* cols
+ chars_per_row
;
2235 to_row_start
+= cnt
;
2236 from_row_start
+= cnt
;
2238 while (rows_to_move
-- > 0) {
2239 to_row_start
-= cols
;
2240 from_row_start
-= cols
;
2242 from
= from_row_start
;
2243 for (cnt
= chars_per_row
; cnt
-- > 0; )
2250 tem_safe_virtual_copy(struct tem_vt_state
*tem
,
2251 screen_pos_t s_col
, screen_pos_t s_row
,
2252 screen_pos_t e_col
, screen_pos_t e_row
,
2253 screen_pos_t t_col
, screen_pos_t t_row
)
2255 screen_size_t chars_per_row
;
2256 screen_size_t rows_to_move
;
2257 int rows
= tems
.ts_c_dimension
.height
;
2258 int cols
= tems
.ts_c_dimension
.width
;
2260 if (s_col
< 0 || s_col
>= cols
||
2261 s_row
< 0 || s_row
>= rows
||
2262 e_col
< 0 || e_col
>= cols
||
2263 e_row
< 0 || e_row
>= rows
||
2264 t_col
< 0 || t_col
>= cols
||
2265 t_row
< 0 || t_row
>= rows
||
2270 chars_per_row
= e_col
- s_col
+ 1;
2271 rows_to_move
= e_row
- s_row
+ 1;
2273 /* More sanity checks. */
2274 if (t_row
+ rows_to_move
> rows
||
2275 t_col
+ chars_per_row
> cols
)
2278 i_virtual_copy(tem
->tvs_screen_buf
, s_col
, s_row
,
2279 e_col
, e_row
, t_col
, t_row
);
2281 /* text_color_t is the same size as char */
2282 i_virtual_copy((unsigned char *)tem
->tvs_fg_buf
,
2283 s_col
, s_row
, e_col
, e_row
, t_col
, t_row
);
2284 i_virtual_copy((unsigned char *)tem
->tvs_bg_buf
,
2285 s_col
, s_row
, e_col
, e_row
, t_col
, t_row
);
2290 tem_safe_virtual_cls(struct tem_vt_state
*tem
,
2291 int count
, screen_pos_t row
, screen_pos_t col
)
2293 text_color_t fg_color
;
2294 text_color_t bg_color
;
2296 tem_safe_get_color(tem
, &fg_color
, &bg_color
, TEM_ATTR_SCREEN_REVERSE
);
2297 tem_safe_virtual_display(tem
, tems
.ts_blank_line
, count
, row
, col
,
2298 fg_color
, bg_color
);
2302 * only blank screen, not clear our screen buffer
2305 tem_safe_blank_screen(struct tem_vt_state
*tem
, cred_t
*credp
,
2306 enum called_from called_from
)
2310 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
2311 called_from
== CALLED_FROM_STANDALONE
);
2313 if (tems
.ts_display_mode
== VIS_PIXEL
) {
2314 tem_safe_pix_clear_entire_screen(tem
, credp
, called_from
);
2318 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
2319 tem_safe_callback_cls(tem
,
2320 tems
.ts_c_dimension
.width
,
2321 row
, 0, credp
, called_from
);
2326 * unblank screen with associated tem from its screen buffer
2329 tem_safe_unblank_screen(struct tem_vt_state
*tem
, cred_t
*credp
,
2330 enum called_from called_from
)
2332 text_color_t fg_color
, fg_last
;
2333 text_color_t bg_color
, bg_last
;
2334 size_t tc_size
= sizeof (text_color_t
);
2335 int row
, col
, count
, col_start
;
2339 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
2340 called_from
== CALLED_FROM_STANDALONE
);
2342 if (tems
.ts_display_mode
== VIS_PIXEL
)
2343 tem_safe_pix_clear_entire_screen(tem
, credp
, called_from
);
2345 tem_safe_callback_cursor(tem
, VIS_HIDE_CURSOR
, credp
, called_from
);
2347 width
= tems
.ts_c_dimension
.width
;
2350 * Display data in tvs_screen_buf to the actual framebuffer in a
2352 * When dealing with one row, output data with the same foreground
2353 * and background color all together.
2355 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
2356 buf
= tem
->tvs_screen_buf
+ (row
* width
);
2357 count
= col_start
= 0;
2358 for (col
= 0; col
< width
; col
++) {
2360 tem
->tvs_fg_buf
[(row
* width
+ col
) * tc_size
];
2362 tem
->tvs_bg_buf
[(row
* width
+ col
) * tc_size
];
2368 if ((fg_color
!= fg_last
) || (bg_color
!= bg_last
)) {
2370 * Call the primitive to render this data.
2372 tem_safe_callback_display(tem
,
2373 buf
, count
, row
, col_start
,
2374 fg_last
, bg_last
, credp
, called_from
);
2385 if (col_start
== (width
- 1))
2389 * Call the primitive to render this data.
2391 tem_safe_callback_display(tem
,
2392 buf
, count
, row
, col_start
,
2393 fg_last
, bg_last
, credp
, called_from
);
2396 tem_safe_callback_cursor(tem
, VIS_DISPLAY_CURSOR
, credp
, called_from
);