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 * Polled I/O safe ANSI terminal emulator module;
29 * Supporting TERM types 'sun' and 'sun-color, parsing
30 * ANSI x3.64 escape sequences, and the like. (See wscons(7d)
31 * for more information).
35 * The functions in this file *must* be able to function in
36 * standalone mode, ie. on a quiesced system. In that state,
37 * access is single threaded, only one CPU is running.
38 * System services are NOT available.
40 * The following restrictions pertain to every function
43 * - CANNOT use the DDI or LDI interfaces
44 * - CANNOT call system services
45 * - CANNOT use mutexes
46 * - CANNOT wait for interrupts
47 * - CANNOT allocate memory
49 * All non-static functions in this file which:
50 * - Operates on tems and tem_vt_state
51 * - Not only called from standalone mode, i.e. has
52 * a "calledfrom" argument
53 * should assert this at the beginning:
55 * ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) ||
56 * called_from == CALLED_FROM_STANDALONE);
59 #include <sys/types.h>
60 #include <sys/ascii.h>
61 #include <sys/visual_io.h>
64 #include <sys/tem_impl.h>
65 #include <sys/ksynch.h>
66 #include <sys/sysmacros.h>
67 #include <sys/mutex.h>
69 #include <sys/t_lock.h>
71 tem_safe_callbacks_t tem_safe_text_callbacks
= {
72 &tem_safe_text_display
,
74 &tem_safe_text_cursor
,
78 tem_safe_callbacks_t tem_safe_pix_callbacks
= {
79 &tem_safe_pix_display
,
82 &tem_safe_pix_bit2pix
,
87 static void tem_safe_control(struct tem_vt_state
*, uchar_t
,
88 cred_t
*, enum called_from
);
89 static void tem_safe_setparam(struct tem_vt_state
*, int, int);
90 static void tem_safe_selgraph(struct tem_vt_state
*);
91 static void tem_safe_chkparam(struct tem_vt_state
*, uchar_t
,
92 cred_t
*, enum called_from
);
93 static void tem_safe_getparams(struct tem_vt_state
*, uchar_t
,
94 cred_t
*, enum called_from
);
95 static void tem_safe_outch(struct tem_vt_state
*, uchar_t
,
96 cred_t
*, enum called_from
);
97 static void tem_safe_parse(struct tem_vt_state
*, uchar_t
,
98 cred_t
*, enum called_from
);
100 static void tem_safe_new_line(struct tem_vt_state
*,
101 cred_t
*, enum called_from
);
102 static void tem_safe_cr(struct tem_vt_state
*);
103 static void tem_safe_lf(struct tem_vt_state
*,
104 cred_t
*, enum called_from
);
105 static void tem_safe_send_data(struct tem_vt_state
*, cred_t
*,
107 static void tem_safe_cls(struct tem_vt_state
*,
108 cred_t
*, enum called_from
);
109 static void tem_safe_tab(struct tem_vt_state
*,
110 cred_t
*, enum called_from
);
111 static void tem_safe_back_tab(struct tem_vt_state
*,
112 cred_t
*, enum called_from
);
113 static void tem_safe_clear_tabs(struct tem_vt_state
*, int);
114 static void tem_safe_set_tab(struct tem_vt_state
*);
115 static void tem_safe_mv_cursor(struct tem_vt_state
*, int, int,
116 cred_t
*, enum called_from
);
117 static void tem_safe_shift(struct tem_vt_state
*, int, int,
118 cred_t
*, enum called_from
);
119 static void tem_safe_scroll(struct tem_vt_state
*, int, int,
120 int, int, cred_t
*, enum called_from
);
121 static void tem_safe_clear_chars(struct tem_vt_state
*tem
,
122 int count
, screen_pos_t row
, screen_pos_t col
,
123 cred_t
*credp
, enum called_from called_from
);
124 static void tem_safe_copy_area(struct tem_vt_state
*tem
,
125 screen_pos_t s_col
, screen_pos_t s_row
,
126 screen_pos_t e_col
, screen_pos_t e_row
,
127 screen_pos_t t_col
, screen_pos_t t_row
,
128 cred_t
*credp
, enum called_from called_from
);
129 static void tem_safe_image_display(struct tem_vt_state
*, uchar_t
*,
130 int, int, screen_pos_t
, screen_pos_t
,
131 cred_t
*, enum called_from
);
132 static void tem_safe_bell(struct tem_vt_state
*tem
,
133 enum called_from called_from
);
134 static void tem_safe_pix_clear_prom_output(struct tem_vt_state
*tem
,
135 cred_t
*credp
, enum called_from called_from
);
137 static void tem_safe_virtual_cls(struct tem_vt_state
*, int, screen_pos_t
,
139 static void tem_safe_virtual_display(struct tem_vt_state
*,
140 unsigned char *, int, screen_pos_t
, screen_pos_t
,
141 text_color_t
, text_color_t
);
142 static void tem_safe_virtual_copy(struct tem_vt_state
*, screen_pos_t
,
143 screen_pos_t
, screen_pos_t
, screen_pos_t
,
144 screen_pos_t
, screen_pos_t
);
145 static void tem_safe_align_cursor(struct tem_vt_state
*tem
);
146 static void bit_to_pix4(struct tem_vt_state
*tem
, uchar_t c
,
147 text_color_t fg_color
, text_color_t bg_color
);
148 static void bit_to_pix8(struct tem_vt_state
*tem
, uchar_t c
,
149 text_color_t fg_color
, text_color_t bg_color
);
150 static void bit_to_pix24(struct tem_vt_state
*tem
, uchar_t c
,
151 text_color_t fg_color
, text_color_t bg_color
);
154 /* Bk Rd Gr Br Bl Mg Cy Wh */
155 static text_color_t fg_dim_xlate
[] = { 1, 5, 3, 7, 2, 6, 4, 8 };
156 static text_color_t fg_brt_xlate
[] = { 9, 13, 11, 15, 10, 14, 12, 0 };
157 static text_color_t bg_xlate
[] = { 1, 5, 3, 7, 2, 6, 4, 0 };
161 text_cmap_t cmap4_to_24
= {
163 /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
164 Wh+ Bk Bl Gr Cy Rd Mg Br Wh Bk+ Bl+ Gr+ Cy+ Rd+ Mg+ Yw */
165 0xff,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x40,0x00,0x00,0x00,0xff,0xff,0xff,
166 0xff,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x40,0x00,0xff,0xff,0x00,0x00,0xff,
167 0xff,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x40,0xff,0x00,0xff,0x00,0xff,0x00
171 #define PIX4TO32(pix4) (pixel32_t)( \
172 cmap4_to_24.red[pix4] << 16 | \
173 cmap4_to_24.green[pix4] << 8 | \
174 cmap4_to_24.blue[pix4])
177 * Fonts are statically linked with this module. At some point an
178 * RFE might be desireable to allow dynamic font loading. The
179 * original intention to facilitate dynamic fonts can be seen
180 * by examining the data structures and set_font(). As much of
181 * the original code is retained but modified to be suited to
182 * traversing a list of static fonts.
184 extern struct fontlist fonts
[];
186 #define DEFAULT_FONT_DATA font_data_12x22
188 extern bitmap_data_t font_data_12x22
;
189 extern bitmap_data_t font_data_7x14
;
190 extern bitmap_data_t font_data_6x10
;
192 * Must be sorted by font size in descending order
194 struct fontlist fonts
[] = {
195 { &font_data_12x22
, NULL
},
196 { &font_data_7x14
, NULL
},
197 { &font_data_6x10
, NULL
},
201 #define INVERSE(ch) (ch ^ 0xff)
203 #define tem_safe_callback_display (*tems.ts_callbacks->tsc_display)
204 #define tem_safe_callback_copy (*tems.ts_callbacks->tsc_copy)
205 #define tem_safe_callback_cursor (*tems.ts_callbacks->tsc_cursor)
206 #define tem_safe_callback_cls (*tems.ts_callbacks->tsc_cls)
207 #define tem_safe_callback_bit2pix(tem, c, fg, bg) { \
208 ASSERT(tems.ts_callbacks->tsc_bit2pix != NULL); \
209 (void) (*tems.ts_callbacks->tsc_bit2pix)((tem), (c), (fg), (bg));\
213 tem_safe_check_first_time(
214 struct tem_vt_state
*tem
,
216 enum called_from called_from
)
218 static int first_time
= 1;
220 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
221 called_from
== CALLED_FROM_STANDALONE
);
224 * Realign the console cursor. We did this in tem_init().
225 * However, drivers in the console stream may emit additional
226 * messages before we are ready. This causes text overwrite
227 * on the screen. This is a workaround.
233 if (tems
.ts_display_mode
== VIS_TEXT
) {
234 tem_safe_text_cursor(tem
, VIS_GET_CURSOR
, credp
, called_from
);
235 tem_safe_align_cursor(tem
);
240 * This entry point handles output requests from restricted contexts like
241 * kmdb, where services like mutexes are not available. This function
242 * is entered when OBP or when a kernel debugger (such as kmdb)
243 * are generating console output. In those cases, power management
244 * concerns are handled by the abort sequence initiation (ie. when
245 * the user hits L1+A or the equivalent to enter OBP or the debugger.).
246 * It is also entered when the kernel is panicing.
249 tem_safe_polled_write(
250 tem_vt_state_t tem_arg
,
254 struct tem_vt_state
*tem
= (struct tem_vt_state
*)tem_arg
;
257 _NOTE(NO_COMPETING_THREADS_NOW
)
258 _NOTE(NO_COMPETING_THREADS_AS_SIDE_EFFECT
)
261 if (!tem
->tvs_initialized
) {
265 tem_safe_check_first_time(tem
, kcred
, CALLED_FROM_STANDALONE
);
266 tem_safe_terminal_emulate(tem
, buf
, len
, NULL
, CALLED_FROM_STANDALONE
);
271 * This is the main entry point into the terminal emulator.
273 * For each data message coming downstream, ANSI assumes that it is composed
274 * of ASCII characters, which are treated as a byte-stream input to the
275 * parsing state machine. All data is parsed immediately -- there is
279 tem_safe_terminal_emulate(
280 struct tem_vt_state
*tem
,
284 enum called_from called_from
)
287 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
288 called_from
== CALLED_FROM_STANDALONE
);
290 if (tem
->tvs_isactive
)
291 tem_safe_callback_cursor(tem
,
292 VIS_HIDE_CURSOR
, credp
, called_from
);
294 for (; len
> 0; len
--, buf
++)
295 tem_safe_parse(tem
, *buf
, credp
, called_from
);
298 * Send the data we just got to the framebuffer.
300 tem_safe_send_data(tem
, credp
, called_from
);
302 if (tem
->tvs_isactive
)
303 tem_safe_callback_cursor(tem
,
304 VIS_DISPLAY_CURSOR
, credp
, called_from
);
308 * Display an rectangular image on the frame buffer using the
309 * mechanism appropriate for the system state being called
310 * from quiesced or normal (ie. use polled I/O vs. layered ioctls)
314 struct vis_consdisplay
*pda
,
316 enum called_from called_from
)
318 if (called_from
== CALLED_FROM_STANDALONE
)
319 tems
.ts_fb_polledio
->display(tems
.ts_fb_polledio
->arg
, pda
);
321 tems_display_layered(pda
, credp
);
325 * Copy a rectangle from one location to another on the frame buffer
326 * using the mechanism appropriate for the system state being called
327 * from, quiesced or normal (ie. use polled I/O vs. layered ioctls)
331 struct vis_conscopy
*pca
,
333 enum called_from called_from
)
335 if (called_from
== CALLED_FROM_STANDALONE
)
336 tems
.ts_fb_polledio
->copy(tems
.ts_fb_polledio
->arg
, pca
);
338 tems_copy_layered(pca
, credp
);
342 * Display or hide a rectangular block text cursor of a specificsize
343 * at a specific location on frame buffer* using the mechanism
344 * appropriate for the system state being called from, quisced or
345 * normal (ie. use polled I/O vs. layered ioctls).
349 struct vis_conscursor
*pca
,
351 enum called_from called_from
)
353 if (called_from
== CALLED_FROM_STANDALONE
)
354 tems
.ts_fb_polledio
->cursor(tems
.ts_fb_polledio
->arg
, pca
);
356 tems_cursor_layered(pca
, credp
);
360 * send the appropriate control message or set state based on the
361 * value of the control character ch
366 struct tem_vt_state
*tem
,
369 enum called_from called_from
)
371 tem
->tvs_state
= A_STATE_START
;
374 tem_safe_bell(tem
, called_from
);
378 tem_safe_mv_cursor(tem
,
379 tem
->tvs_c_cursor
.row
,
380 tem
->tvs_c_cursor
.col
- 1,
385 tem_safe_tab(tem
, credp
, called_from
);
390 * tem_safe_send_data(tem, credp, called_from);
391 * tem_safe_new_line(tem, credp, called_from);
396 tem_safe_send_data(tem
, credp
, called_from
);
397 tem_safe_lf(tem
, credp
, called_from
);
401 tem_safe_send_data(tem
, credp
, called_from
);
402 tem_safe_cls(tem
, credp
, called_from
);
406 tem_safe_send_data(tem
, credp
, called_from
);
411 tem
->tvs_state
= A_STATE_ESC
;
417 tem
->tvs_curparam
= 0;
418 tem
->tvs_paramval
= 0;
419 tem
->tvs_gotparam
= B_FALSE
;
420 /* clear the parameters */
421 for (i
= 0; i
< TEM_MAXPARAMS
; i
++)
422 tem
->tvs_params
[i
] = -1;
423 tem
->tvs_state
= A_STATE_CSI
;
428 tem_safe_back_tab(tem
, credp
, called_from
);
438 * if parameters [0..count - 1] are not set, set them to the value
443 tem_safe_setparam(struct tem_vt_state
*tem
, int count
, int newparam
)
447 for (i
= 0; i
< count
; i
++) {
448 if (tem
->tvs_params
[i
] == -1)
449 tem
->tvs_params
[i
] = newparam
;
455 * select graphics mode based on the param vals stored in a_params
458 tem_safe_selgraph(struct tem_vt_state
*tem
)
464 tem
->tvs_state
= A_STATE_START
;
466 curparam
= tem
->tvs_curparam
;
468 param
= tem
->tvs_params
[count
];
473 /* reset to initial normal settings */
474 tem
->tvs_fg_color
= tems
.ts_init_color
.fg_color
;
475 tem
->tvs_bg_color
= tems
.ts_init_color
.bg_color
;
476 tem
->tvs_flags
= tems
.ts_init_color
.a_flags
;
479 case 1: /* Bold Intense */
480 tem
->tvs_flags
|= TEM_ATTR_BOLD
;
483 case 2: /* Faint Intense */
484 tem
->tvs_flags
&= ~TEM_ATTR_BOLD
;
488 tem
->tvs_flags
|= TEM_ATTR_BLINK
;
491 case 7: /* Reverse video */
492 if (tem
->tvs_flags
& TEM_ATTR_SCREEN_REVERSE
) {
493 tem
->tvs_flags
&= ~TEM_ATTR_REVERSE
;
495 tem
->tvs_flags
|= TEM_ATTR_REVERSE
;
499 case 30: /* black (grey) foreground */
500 case 31: /* red (light red) foreground */
501 case 32: /* green (light green) foreground */
502 case 33: /* brown (yellow) foreground */
503 case 34: /* blue (light blue) foreground */
504 case 35: /* magenta (light magenta) foreground */
505 case 36: /* cyan (light cyan) foreground */
506 case 37: /* white (bright white) foreground */
507 tem
->tvs_fg_color
= param
- 30;
510 case 40: /* black (grey) background */
511 case 41: /* red (light red) background */
512 case 42: /* green (light green) background */
513 case 43: /* brown (yellow) background */
514 case 44: /* blue (light blue) background */
515 case 45: /* magenta (light magenta) background */
516 case 46: /* cyan (light cyan) background */
517 case 47: /* white (bright white) background */
518 tem
->tvs_bg_color
= param
- 40;
527 } while (curparam
> 0);
531 * perform the appropriate action for the escape sequence
533 * General rule: This code does not validate the arguments passed.
534 * It assumes that the next lower level will do so.
538 struct tem_vt_state
*tem
,
541 enum called_from called_from
)
547 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
548 MUTEX_HELD(&tem
->tvs_lock
));
550 row
= tem
->tvs_c_cursor
.row
;
551 col
= tem
->tvs_c_cursor
.col
;
555 case 'm': /* select terminal graphics mode */
556 tem_safe_send_data(tem
, credp
, called_from
);
557 tem_safe_selgraph(tem
);
560 case '@': /* insert char */
561 tem_safe_setparam(tem
, 1, 1);
562 tem_safe_shift(tem
, tem
->tvs_params
[0], TEM_SHIFT_RIGHT
,
566 case 'A': /* cursor up */
567 tem_safe_setparam(tem
, 1, 1);
568 tem_safe_mv_cursor(tem
, row
- tem
->tvs_params
[0], col
,
572 case 'd': /* VPA - vertical position absolute */
573 tem_safe_setparam(tem
, 1, 1);
574 tem_safe_mv_cursor(tem
, tem
->tvs_params
[0] - 1, col
,
578 case 'e': /* VPR - vertical position relative */
579 case 'B': /* cursor down */
580 tem_safe_setparam(tem
, 1, 1);
581 tem_safe_mv_cursor(tem
, row
+ tem
->tvs_params
[0], col
,
585 case 'a': /* HPR - horizontal position relative */
586 case 'C': /* cursor right */
587 tem_safe_setparam(tem
, 1, 1);
588 tem_safe_mv_cursor(tem
, row
, col
+ tem
->tvs_params
[0],
592 case '`': /* HPA - horizontal position absolute */
593 tem_safe_setparam(tem
, 1, 1);
594 tem_safe_mv_cursor(tem
, row
, tem
->tvs_params
[0] - 1,
598 case 'D': /* cursor left */
599 tem_safe_setparam(tem
, 1, 1);
600 tem_safe_mv_cursor(tem
, row
, col
- tem
->tvs_params
[0],
604 case 'E': /* CNL cursor next line */
605 tem_safe_setparam(tem
, 1, 1);
606 tem_safe_mv_cursor(tem
, row
+ tem
->tvs_params
[0], 0,
610 case 'F': /* CPL cursor previous line */
611 tem_safe_setparam(tem
, 1, 1);
612 tem_safe_mv_cursor(tem
, row
- tem
->tvs_params
[0], 0,
616 case 'G': /* cursor horizontal position */
617 tem_safe_setparam(tem
, 1, 1);
618 tem_safe_mv_cursor(tem
, row
, tem
->tvs_params
[0] - 1,
622 case 'g': /* clear tabs */
623 tem_safe_setparam(tem
, 1, 0);
624 tem_safe_clear_tabs(tem
, tem
->tvs_params
[0]);
627 case 'f': /* HVP Horizontal and Vertical Position */
628 case 'H': /* CUP position cursor */
629 tem_safe_setparam(tem
, 2, 1);
630 tem_safe_mv_cursor(tem
,
631 tem
->tvs_params
[0] - 1,
632 tem
->tvs_params
[1] - 1,
636 case 'I': /* CHT - Cursor Horizontal Tab */
637 /* Not implemented */
640 case 'J': /* ED - Erase in Display */
641 tem_safe_send_data(tem
, credp
, called_from
);
642 tem_safe_setparam(tem
, 1, 0);
643 switch (tem
->tvs_params
[0]) {
645 /* erase cursor to end of screen */
646 /* FIRST erase cursor to end of line */
647 tem_safe_clear_chars(tem
,
648 tems
.ts_c_dimension
.width
-
649 tem
->tvs_c_cursor
.col
,
650 tem
->tvs_c_cursor
.row
,
651 tem
->tvs_c_cursor
.col
, credp
, called_from
);
653 /* THEN erase lines below the cursor */
654 for (row
= tem
->tvs_c_cursor
.row
+ 1;
655 row
< tems
.ts_c_dimension
.height
;
657 tem_safe_clear_chars(tem
,
658 tems
.ts_c_dimension
.width
,
659 row
, 0, credp
, called_from
);
664 /* erase beginning of screen to cursor */
665 /* FIRST erase lines above the cursor */
667 row
< tem
->tvs_c_cursor
.row
;
669 tem_safe_clear_chars(tem
,
670 tems
.ts_c_dimension
.width
,
671 row
, 0, credp
, called_from
);
673 /* THEN erase beginning of line to cursor */
674 tem_safe_clear_chars(tem
,
675 tem
->tvs_c_cursor
.col
+ 1,
676 tem
->tvs_c_cursor
.row
,
677 0, credp
, called_from
);
681 /* erase whole screen */
683 row
< tems
.ts_c_dimension
.height
;
685 tem_safe_clear_chars(tem
,
686 tems
.ts_c_dimension
.width
,
687 row
, 0, credp
, called_from
);
693 case 'K': /* EL - Erase in Line */
694 tem_safe_send_data(tem
, credp
, called_from
);
695 tem_safe_setparam(tem
, 1, 0);
696 switch (tem
->tvs_params
[0]) {
698 /* erase cursor to end of line */
699 tem_safe_clear_chars(tem
,
700 (tems
.ts_c_dimension
.width
-
701 tem
->tvs_c_cursor
.col
),
702 tem
->tvs_c_cursor
.row
,
703 tem
->tvs_c_cursor
.col
,
708 /* erase beginning of line to cursor */
709 tem_safe_clear_chars(tem
,
710 tem
->tvs_c_cursor
.col
+ 1,
711 tem
->tvs_c_cursor
.row
,
712 0, credp
, called_from
);
716 /* erase whole line */
717 tem_safe_clear_chars(tem
,
718 tems
.ts_c_dimension
.width
,
719 tem
->tvs_c_cursor
.row
,
720 0, credp
, called_from
);
725 case 'L': /* insert line */
726 tem_safe_send_data(tem
, credp
, called_from
);
727 tem_safe_setparam(tem
, 1, 1);
729 tem
->tvs_c_cursor
.row
,
730 tems
.ts_c_dimension
.height
- 1,
731 tem
->tvs_params
[0], TEM_SCROLL_DOWN
,
735 case 'M': /* delete line */
736 tem_safe_send_data(tem
, credp
, called_from
);
737 tem_safe_setparam(tem
, 1, 1);
739 tem
->tvs_c_cursor
.row
,
740 tems
.ts_c_dimension
.height
- 1,
741 tem
->tvs_params
[0], TEM_SCROLL_UP
,
745 case 'P': /* DCH - delete char */
746 tem_safe_setparam(tem
, 1, 1);
747 tem_safe_shift(tem
, tem
->tvs_params
[0], TEM_SHIFT_LEFT
,
751 case 'S': /* scroll up */
752 tem_safe_send_data(tem
, credp
, called_from
);
753 tem_safe_setparam(tem
, 1, 1);
754 tem_safe_scroll(tem
, 0,
755 tems
.ts_c_dimension
.height
- 1,
756 tem
->tvs_params
[0], TEM_SCROLL_UP
,
760 case 'T': /* scroll down */
761 tem_safe_send_data(tem
, credp
, called_from
);
762 tem_safe_setparam(tem
, 1, 1);
763 tem_safe_scroll(tem
, 0,
764 tems
.ts_c_dimension
.height
- 1,
765 tem
->tvs_params
[0], TEM_SCROLL_DOWN
,
769 case 'X': /* erase char */
770 tem_safe_setparam(tem
, 1, 1);
771 tem_safe_clear_chars(tem
,
773 tem
->tvs_c_cursor
.row
,
774 tem
->tvs_c_cursor
.col
,
778 case 'Z': /* cursor backward tabulation */
779 tem_safe_setparam(tem
, 1, 1);
782 * Rule exception - We do sanity checking here.
784 * Restrict the count to a sane value to keep from
785 * looping for a long time. There can't be more than one
786 * tab stop per column, so use that as a limit.
788 if (tem
->tvs_params
[0] > tems
.ts_c_dimension
.width
)
789 tem
->tvs_params
[0] = tems
.ts_c_dimension
.width
;
791 for (i
= 0; i
< tem
->tvs_params
[0]; i
++)
792 tem_safe_back_tab(tem
, credp
, called_from
);
795 tem
->tvs_state
= A_STATE_START
;
800 * Gather the parameters of an ANSI escape sequence
803 tem_safe_getparams(struct tem_vt_state
*tem
, uchar_t ch
,
804 cred_t
*credp
, enum called_from called_from
)
806 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
807 MUTEX_HELD(&tem
->tvs_lock
));
809 if (ch
>= '0' && ch
<= '9') {
810 tem
->tvs_paramval
= ((tem
->tvs_paramval
* 10) + (ch
- '0'));
811 tem
->tvs_gotparam
= B_TRUE
; /* Remember got parameter */
812 return; /* Return immediately */
813 } else if (tem
->tvs_state
== A_STATE_CSI_EQUAL
||
814 tem
->tvs_state
== A_STATE_CSI_QMARK
) {
815 tem
->tvs_state
= A_STATE_START
;
817 if (tem
->tvs_curparam
< TEM_MAXPARAMS
) {
818 if (tem
->tvs_gotparam
) {
819 /* get the parameter value */
820 tem
->tvs_params
[tem
->tvs_curparam
] =
827 /* Restart parameter search */
828 tem
->tvs_gotparam
= B_FALSE
;
829 tem
->tvs_paramval
= 0; /* No parame value yet */
831 /* Handle escape sequence */
832 tem_safe_chkparam(tem
, ch
, credp
, called_from
);
838 * Add character to internal buffer.
839 * When its full, send it to the next layer.
843 tem_safe_outch(struct tem_vt_state
*tem
, uchar_t ch
,
844 cred_t
*credp
, enum called_from called_from
)
847 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
848 called_from
== CALLED_FROM_STANDALONE
);
850 /* buffer up the character until later */
852 tem
->tvs_outbuf
[tem
->tvs_outindex
++] = ch
;
853 tem
->tvs_c_cursor
.col
++;
854 if (tem
->tvs_c_cursor
.col
>= tems
.ts_c_dimension
.width
) {
855 tem_safe_send_data(tem
, credp
, called_from
);
856 tem_safe_new_line(tem
, credp
, called_from
);
861 tem_safe_new_line(struct tem_vt_state
*tem
,
862 cred_t
*credp
, enum called_from called_from
)
865 tem_safe_lf(tem
, credp
, called_from
);
869 tem_safe_cr(struct tem_vt_state
*tem
)
871 tem
->tvs_c_cursor
.col
= 0;
872 tem_safe_align_cursor(tem
);
876 tem_safe_lf(struct tem_vt_state
*tem
,
877 cred_t
*credp
, enum called_from called_from
)
881 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
882 MUTEX_HELD(&tem
->tvs_lock
));
885 * Sanity checking notes:
886 * . a_nscroll was validated when it was set.
887 * . Regardless of that, tem_safe_scroll and tem_safe_mv_cursor
888 * will prevent anything bad from happening.
890 row
= tem
->tvs_c_cursor
.row
+ 1;
892 if (row
>= tems
.ts_c_dimension
.height
) {
893 if (tem
->tvs_nscroll
!= 0) {
894 tem_safe_scroll(tem
, 0,
895 tems
.ts_c_dimension
.height
- 1,
896 tem
->tvs_nscroll
, TEM_SCROLL_UP
,
898 row
= tems
.ts_c_dimension
.height
-
900 } else { /* no scroll */
902 * implement Esc[#r when # is zero. This means no
903 * scroll but just return cursor to top of screen,
904 * do not clear screen.
910 tem_safe_mv_cursor(tem
, row
, tem
->tvs_c_cursor
.col
,
913 if (tem
->tvs_nscroll
== 0) {
914 /* erase rest of cursor line */
915 tem_safe_clear_chars(tem
,
916 tems
.ts_c_dimension
.width
-
917 tem
->tvs_c_cursor
.col
,
918 tem
->tvs_c_cursor
.row
,
919 tem
->tvs_c_cursor
.col
,
924 tem_safe_align_cursor(tem
);
928 tem_safe_send_data(struct tem_vt_state
*tem
, cred_t
*credp
,
929 enum called_from called_from
)
931 text_color_t fg_color
;
932 text_color_t bg_color
;
934 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
935 MUTEX_HELD(&tem
->tvs_lock
));
937 if (tem
->tvs_outindex
== 0) {
938 tem_safe_align_cursor(tem
);
942 tem_safe_get_color(tem
, &fg_color
, &bg_color
, TEM_ATTR_REVERSE
);
943 tem_safe_virtual_display(tem
,
944 tem
->tvs_outbuf
, tem
->tvs_outindex
,
945 tem
->tvs_s_cursor
.row
, tem
->tvs_s_cursor
.col
,
948 if (tem
->tvs_isactive
) {
950 * Call the primitive to render this data.
952 tem_safe_callback_display(tem
,
953 tem
->tvs_outbuf
, tem
->tvs_outindex
,
954 tem
->tvs_s_cursor
.row
, tem
->tvs_s_cursor
.col
,
959 tem
->tvs_outindex
= 0;
961 tem_safe_align_cursor(tem
);
966 * We have just done something to the current output point. Reset the start
967 * point for the buffered data in a_outbuf. There shouldn't be any data
971 tem_safe_align_cursor(struct tem_vt_state
*tem
)
973 tem
->tvs_s_cursor
.row
= tem
->tvs_c_cursor
.row
;
974 tem
->tvs_s_cursor
.col
= tem
->tvs_c_cursor
.col
;
978 * State machine parser based on the current state and character input
979 * major terminations are to control character or normal character
983 tem_safe_parse(struct tem_vt_state
*tem
, uchar_t ch
,
984 cred_t
*credp
, enum called_from called_from
)
988 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
989 MUTEX_HELD(&tem
->tvs_lock
));
991 if (tem
->tvs_state
== A_STATE_START
) { /* Normal state? */
992 if (ch
== A_CSI
|| ch
== A_ESC
|| ch
< ' ') {
994 tem_safe_control(tem
, ch
, credp
, called_from
);
997 tem_safe_outch(tem
, ch
, credp
, called_from
);
1002 /* In <ESC> sequence */
1003 if (tem
->tvs_state
!= A_STATE_ESC
) { /* Need to get parameters? */
1004 if (tem
->tvs_state
!= A_STATE_CSI
) {
1005 tem_safe_getparams(tem
, ch
, credp
, called_from
);
1011 tem
->tvs_state
= A_STATE_CSI_QMARK
;
1014 tem
->tvs_state
= A_STATE_CSI_EQUAL
;
1018 * As defined below, this sequence
1019 * saves the cursor. However, Sun
1020 * defines ESC[s as reset. We resolved
1021 * the conflict by selecting reset as it
1022 * is exported in the termcap file for
1023 * sun-mon, while the "save cursor"
1024 * definition does not exist anywhere in
1026 * However, having no coherent
1027 * definition of reset, we have not
1033 * tem->tvs_r_cursor.row = tem->tvs_c_cursor.row;
1034 * tem->tvs_r_cursor.col = tem->tvs_c_cursor.col;
1035 * tem->tvs_state = A_STATE_START;
1038 tem
->tvs_state
= A_STATE_START
;
1041 tem_safe_mv_cursor(tem
, tem
->tvs_r_cursor
.row
,
1042 tem
->tvs_r_cursor
.col
, credp
, called_from
);
1043 tem
->tvs_state
= A_STATE_START
;
1045 case 'p': /* sunbow */
1046 tem_safe_send_data(tem
, credp
, called_from
);
1048 * Don't set anything if we are
1049 * already as we want to be.
1051 if (tem
->tvs_flags
& TEM_ATTR_SCREEN_REVERSE
) {
1052 tem
->tvs_flags
&= ~TEM_ATTR_SCREEN_REVERSE
;
1054 * If we have switched the characters to be the
1055 * inverse from the screen, then switch them as
1056 * well to keep them the inverse of the screen.
1058 if (tem
->tvs_flags
& TEM_ATTR_REVERSE
)
1059 tem
->tvs_flags
&= ~TEM_ATTR_REVERSE
;
1061 tem
->tvs_flags
|= TEM_ATTR_REVERSE
;
1063 tem_safe_cls(tem
, credp
, called_from
);
1064 tem
->tvs_state
= A_STATE_START
;
1066 case 'q': /* sunwob */
1067 tem_safe_send_data(tem
, credp
, called_from
);
1069 * Don't set anything if we are
1070 * already where as we want to be.
1072 if (!(tem
->tvs_flags
& TEM_ATTR_SCREEN_REVERSE
)) {
1073 tem
->tvs_flags
|= TEM_ATTR_SCREEN_REVERSE
;
1075 * If we have switched the characters to be the
1076 * inverse from the screen, then switch them as
1077 * well to keep them the inverse of the screen.
1079 if (!(tem
->tvs_flags
& TEM_ATTR_REVERSE
))
1080 tem
->tvs_flags
|= TEM_ATTR_REVERSE
;
1082 tem
->tvs_flags
&= ~TEM_ATTR_REVERSE
;
1085 tem_safe_cls(tem
, credp
, called_from
);
1086 tem
->tvs_state
= A_STATE_START
;
1088 case 'r': /* sunscrl */
1090 * Rule exception: check for validity here.
1092 tem
->tvs_nscroll
= tem
->tvs_paramval
;
1093 if (tem
->tvs_nscroll
> tems
.ts_c_dimension
.height
)
1094 tem
->tvs_nscroll
= tems
.ts_c_dimension
.height
;
1095 if (tem
->tvs_nscroll
< 0)
1096 tem
->tvs_nscroll
= 1;
1097 tem
->tvs_state
= A_STATE_START
;
1100 tem_safe_getparams(tem
, ch
, credp
, called_from
);
1105 /* Previous char was <ESC> */
1107 tem
->tvs_curparam
= 0;
1108 tem
->tvs_paramval
= 0;
1109 tem
->tvs_gotparam
= B_FALSE
;
1110 /* clear the parameters */
1111 for (i
= 0; i
< TEM_MAXPARAMS
; i
++)
1112 tem
->tvs_params
[i
] = -1;
1113 tem
->tvs_state
= A_STATE_CSI
;
1114 } else if (ch
== 'Q') { /* <ESC>Q ? */
1115 tem
->tvs_state
= A_STATE_START
;
1116 } else if (ch
== 'C') { /* <ESC>C ? */
1117 tem
->tvs_state
= A_STATE_START
;
1119 tem
->tvs_state
= A_STATE_START
;
1121 /* ESC c resets display */
1122 tem_safe_reset_display(tem
, credp
, called_from
,
1124 } else if (ch
== 'H') {
1125 /* ESC H sets a tab */
1126 tem_safe_set_tab(tem
);
1127 } else if (ch
== '7') {
1128 /* ESC 7 Save Cursor position */
1129 tem
->tvs_r_cursor
.row
= tem
->tvs_c_cursor
.row
;
1130 tem
->tvs_r_cursor
.col
= tem
->tvs_c_cursor
.col
;
1131 } else if (ch
== '8') {
1132 /* ESC 8 Restore Cursor position */
1133 tem_safe_mv_cursor(tem
, tem
->tvs_r_cursor
.row
,
1134 tem
->tvs_r_cursor
.col
, credp
, called_from
);
1135 /* check for control chars */
1136 } else if (ch
< ' ') {
1137 tem_safe_control(tem
, ch
, credp
, called_from
);
1139 tem_safe_outch(tem
, ch
, credp
, called_from
);
1146 tem_safe_bell(struct tem_vt_state
*tem
, enum called_from called_from
)
1148 if (called_from
== CALLED_FROM_STANDALONE
)
1149 (void) beep_polled(BEEP_CONSOLE
);
1151 (void) beep(BEEP_CONSOLE
);
1156 tem_safe_scroll(struct tem_vt_state
*tem
, int start
, int end
, int count
,
1158 cred_t
*credp
, enum called_from called_from
)
1163 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1164 called_from
== CALLED_FROM_STANDALONE
);
1166 lines_affected
= end
- start
+ 1;
1167 if (count
> lines_affected
)
1168 count
= lines_affected
;
1172 switch (direction
) {
1174 if (count
< lines_affected
) {
1175 tem_safe_copy_area(tem
, 0, start
+ count
,
1176 tems
.ts_c_dimension
.width
- 1, end
,
1177 0, start
, credp
, called_from
);
1179 for (row
= (end
- count
) + 1; row
<= end
; row
++) {
1180 tem_safe_clear_chars(tem
, tems
.ts_c_dimension
.width
,
1181 row
, 0, credp
, called_from
);
1185 case TEM_SCROLL_DOWN
:
1186 if (count
< lines_affected
) {
1187 tem_safe_copy_area(tem
, 0, start
,
1188 tems
.ts_c_dimension
.width
- 1,
1189 end
- count
, 0, start
+ count
,
1190 credp
, called_from
);
1192 for (row
= start
; row
< start
+ count
; row
++) {
1193 tem_safe_clear_chars(tem
, tems
.ts_c_dimension
.width
,
1194 row
, 0, credp
, called_from
);
1201 tem_safe_copy_area(struct tem_vt_state
*tem
,
1202 screen_pos_t s_col
, screen_pos_t s_row
,
1203 screen_pos_t e_col
, screen_pos_t e_row
,
1204 screen_pos_t t_col
, screen_pos_t t_row
,
1205 cred_t
*credp
, enum called_from called_from
)
1210 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1211 called_from
== CALLED_FROM_STANDALONE
);
1213 if (s_col
< 0 || s_row
< 0 ||
1214 e_col
< 0 || e_row
< 0 ||
1215 t_col
< 0 || t_row
< 0 ||
1216 s_col
>= tems
.ts_c_dimension
.width
||
1217 e_col
>= tems
.ts_c_dimension
.width
||
1218 t_col
>= tems
.ts_c_dimension
.width
||
1219 s_row
>= tems
.ts_c_dimension
.height
||
1220 e_row
>= tems
.ts_c_dimension
.height
||
1221 t_row
>= tems
.ts_c_dimension
.height
)
1224 if (s_row
> e_row
|| s_col
> e_col
)
1227 rows
= e_row
- s_row
+ 1;
1228 cols
= e_col
- s_col
+ 1;
1229 if (t_row
+ rows
> tems
.ts_c_dimension
.height
||
1230 t_col
+ cols
> tems
.ts_c_dimension
.width
)
1233 tem_safe_virtual_copy(tem
,
1238 if (!tem
->tvs_isactive
)
1241 tem_safe_callback_copy(tem
, s_col
, s_row
,
1242 e_col
, e_row
, t_col
, t_row
, credp
, called_from
);
1246 tem_safe_clear_chars(struct tem_vt_state
*tem
, int count
, screen_pos_t row
,
1247 screen_pos_t col
, cred_t
*credp
, enum called_from called_from
)
1249 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1250 called_from
== CALLED_FROM_STANDALONE
);
1252 if (row
< 0 || row
>= tems
.ts_c_dimension
.height
||
1253 col
< 0 || col
>= tems
.ts_c_dimension
.width
||
1258 * Note that very large values of "count" could cause col+count
1259 * to overflow, so we check "count" independently.
1261 if (count
> tems
.ts_c_dimension
.width
||
1262 col
+ count
> tems
.ts_c_dimension
.width
)
1263 count
= tems
.ts_c_dimension
.width
- col
;
1265 tem_safe_virtual_cls(tem
, count
, row
, col
);
1267 if (!tem
->tvs_isactive
)
1270 tem_safe_callback_cls(tem
, count
, row
, col
, credp
, called_from
);
1275 tem_safe_text_display(struct tem_vt_state
*tem
, uchar_t
*string
,
1276 int count
, screen_pos_t row
, screen_pos_t col
,
1277 text_color_t fg_color
, text_color_t bg_color
,
1278 cred_t
*credp
, enum called_from called_from
)
1280 struct vis_consdisplay da
;
1282 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1283 called_from
== CALLED_FROM_STANDALONE
);
1286 da
.width
= (screen_size_t
)count
;
1290 da
.fg_color
= fg_color
;
1291 da
.bg_color
= bg_color
;
1293 tems_safe_display(&da
, credp
, called_from
);
1297 * This function is used to blit a rectangular color image,
1298 * unperturbed on the underlying framebuffer, to render
1299 * icons and pictures. The data is a pixel pattern that
1300 * fills a rectangle bounded to the width and height parameters.
1301 * The color pixel data must to be pre-adjusted by the caller
1302 * for the current video depth.
1304 * This function is unused now.
1308 tem_safe_image_display(struct tem_vt_state
*tem
, uchar_t
*image
,
1309 int height
, int width
, screen_pos_t row
, screen_pos_t col
,
1310 cred_t
*credp
, enum called_from called_from
)
1312 struct vis_consdisplay da
;
1314 mutex_enter(&tems
.ts_lock
);
1315 mutex_enter(&tem
->tvs_lock
);
1318 da
.width
= (screen_size_t
)width
;
1319 da
.height
= (screen_size_t
)height
;
1323 tems_safe_display(&da
, credp
, called_from
);
1325 mutex_exit(&tem
->tvs_lock
);
1326 mutex_exit(&tems
.ts_lock
);
1332 tem_safe_text_copy(struct tem_vt_state
*tem
,
1333 screen_pos_t s_col
, screen_pos_t s_row
,
1334 screen_pos_t e_col
, screen_pos_t e_row
,
1335 screen_pos_t t_col
, screen_pos_t t_row
,
1336 cred_t
*credp
, enum called_from called_from
)
1338 struct vis_conscopy da
;
1340 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1341 called_from
== CALLED_FROM_STANDALONE
);
1350 tems_safe_copy(&da
, credp
, called_from
);
1354 tem_safe_text_cls(struct tem_vt_state
*tem
,
1355 int count
, screen_pos_t row
, screen_pos_t col
, cred_t
*credp
,
1356 enum called_from called_from
)
1358 struct vis_consdisplay da
;
1360 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1361 called_from
== CALLED_FROM_STANDALONE
);
1363 da
.data
= tems
.ts_blank_line
;
1364 da
.width
= (screen_size_t
)count
;
1368 tem_safe_get_color(tem
, &da
.fg_color
, &da
.bg_color
,
1369 TEM_ATTR_SCREEN_REVERSE
);
1370 tems_safe_display(&da
, credp
, called_from
);
1376 tem_safe_pix_display(struct tem_vt_state
*tem
,
1377 uchar_t
*string
, int count
,
1378 screen_pos_t row
, screen_pos_t col
,
1379 text_color_t fg_color
, text_color_t bg_color
,
1380 cred_t
*credp
, enum called_from called_from
)
1382 struct vis_consdisplay da
;
1385 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1386 called_from
== CALLED_FROM_STANDALONE
);
1388 da
.data
= (uchar_t
*)tem
->tvs_pix_data
;
1389 da
.width
= tems
.ts_font
.width
;
1390 da
.height
= tems
.ts_font
.height
;
1391 da
.row
= (row
* da
.height
) + tems
.ts_p_offset
.y
;
1392 da
.col
= (col
* da
.width
) + tems
.ts_p_offset
.x
;
1394 for (i
= 0; i
< count
; i
++) {
1395 tem_safe_callback_bit2pix(tem
, string
[i
], fg_color
, bg_color
);
1396 tems_safe_display(&da
, credp
, called_from
);
1402 tem_safe_pix_copy(struct tem_vt_state
*tem
,
1403 screen_pos_t s_col
, screen_pos_t s_row
,
1404 screen_pos_t e_col
, screen_pos_t e_row
,
1405 screen_pos_t t_col
, screen_pos_t t_row
,
1407 enum called_from called_from
)
1409 struct vis_conscopy ma
;
1410 static boolean_t need_clear
= B_TRUE
;
1412 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1413 called_from
== CALLED_FROM_STANDALONE
);
1415 if (need_clear
&& tem
->tvs_first_line
> 0) {
1417 * Clear OBP output above our kernel console term
1418 * when our kernel console term begins to scroll up,
1419 * we hope it is user friendly.
1420 * (Also see comments on tem_safe_pix_clear_prom_output)
1422 * This is only one time call.
1424 tem_safe_pix_clear_prom_output(tem
, credp
, called_from
);
1426 need_clear
= B_FALSE
;
1428 ma
.s_row
= s_row
* tems
.ts_font
.height
+ tems
.ts_p_offset
.y
;
1429 ma
.e_row
= (e_row
+ 1) * tems
.ts_font
.height
+ tems
.ts_p_offset
.y
- 1;
1430 ma
.t_row
= t_row
* tems
.ts_font
.height
+ tems
.ts_p_offset
.y
;
1433 * Check if we're in process of clearing OBP's columns area,
1434 * which only happens when term scrolls up a whole line.
1436 if (tem
->tvs_first_line
> 0 && t_row
< s_row
&& t_col
== 0 &&
1437 e_col
== tems
.ts_c_dimension
.width
- 1) {
1439 * We need to clear OBP's columns area outside our kernel
1440 * console term. So that we set ma.e_col to entire row here.
1442 ma
.s_col
= s_col
* tems
.ts_font
.width
;
1443 ma
.e_col
= tems
.ts_p_dimension
.width
- 1;
1445 ma
.t_col
= t_col
* tems
.ts_font
.width
;
1447 ma
.s_col
= s_col
* tems
.ts_font
.width
+ tems
.ts_p_offset
.x
;
1448 ma
.e_col
= (e_col
+ 1) * tems
.ts_font
.width
+
1449 tems
.ts_p_offset
.x
- 1;
1450 ma
.t_col
= t_col
* tems
.ts_font
.width
+ tems
.ts_p_offset
.x
;
1453 tems_safe_copy(&ma
, credp
, called_from
);
1455 if (tem
->tvs_first_line
> 0 && t_row
< s_row
) {
1456 /* We have scrolled up (s_row - t_row) rows. */
1457 tem
->tvs_first_line
-= (s_row
- t_row
);
1458 if (tem
->tvs_first_line
<= 0) {
1459 /* All OBP rows have been cleared. */
1460 tem
->tvs_first_line
= 0;
1467 tem_safe_pix_bit2pix(struct tem_vt_state
*tem
, unsigned char c
,
1468 unsigned char fg
, unsigned char bg
)
1470 void (*fp
)(struct tem_vt_state
*, unsigned char,
1471 unsigned char, unsigned char);
1473 switch (tems
.ts_pdepth
) {
1490 * This function only clears count of columns in one row
1493 tem_safe_pix_cls(struct tem_vt_state
*tem
, int count
,
1494 screen_pos_t row
, screen_pos_t col
, cred_t
*credp
,
1495 enum called_from called_from
)
1497 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1498 called_from
== CALLED_FROM_STANDALONE
);
1500 tem_safe_pix_cls_range(tem
, row
, 1, tems
.ts_p_offset
.y
,
1501 col
, count
, tems
.ts_p_offset
.x
, B_FALSE
, credp
, called_from
);
1505 * This function clears OBP output above our kernel console term area
1506 * because OBP's term may have a bigger terminal window than that of
1507 * our kernel console term. So we need to clear OBP output garbage outside
1508 * of our kernel console term at a proper time, which is when the first
1509 * row output of our kernel console term scrolls at the first screen line.
1511 * _________________________________
1512 * | _____________________ | ---> OBP's bigger term window
1517 * |_|_|___________________|_______|
1518 * | | | ---> first line
1519 * | |___________________|---> our kernel console term window
1521 * |---> columns area to be cleared
1523 * This function only takes care of the output above our kernel console term,
1524 * and tem_prom_scroll_up takes care of columns area outside of our kernel
1528 tem_safe_pix_clear_prom_output(struct tem_vt_state
*tem
, cred_t
*credp
,
1529 enum called_from called_from
)
1531 int nrows
, ncols
, width
, height
;
1533 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1534 called_from
== CALLED_FROM_STANDALONE
);
1536 width
= tems
.ts_font
.width
;
1537 height
= tems
.ts_font
.height
;
1539 nrows
= (tems
.ts_p_offset
.y
+ (height
- 1))/ height
;
1540 ncols
= (tems
.ts_p_dimension
.width
+ (width
- 1))/ width
;
1542 tem_safe_pix_cls_range(tem
, 0, nrows
, 0, 0, ncols
, 0,
1543 B_FALSE
, credp
, called_from
);
1547 * clear the whole screen for pixel mode, just clear the
1551 tem_safe_pix_clear_entire_screen(struct tem_vt_state
*tem
, cred_t
*credp
,
1552 enum called_from called_from
)
1554 int nrows
, ncols
, width
, height
;
1556 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1557 called_from
== CALLED_FROM_STANDALONE
);
1559 width
= tems
.ts_font
.width
;
1560 height
= tems
.ts_font
.height
;
1562 nrows
= (tems
.ts_p_dimension
.height
+ (height
- 1))/ height
;
1563 ncols
= (tems
.ts_p_dimension
.width
+ (width
- 1))/ width
;
1565 tem_safe_pix_cls_range(tem
, 0, nrows
, 0, 0, ncols
, 0,
1566 B_FALSE
, credp
, called_from
);
1569 * Since the whole screen is cleared, we don't need
1570 * to clear OBP output later.
1572 if (tem
->tvs_first_line
> 0)
1573 tem
->tvs_first_line
= 0;
1577 * clear the whole screen, including the virtual screen buffer,
1578 * and reset the cursor to start point.
1581 tem_safe_cls(struct tem_vt_state
*tem
,
1582 cred_t
*credp
, enum called_from called_from
)
1586 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1587 called_from
== CALLED_FROM_STANDALONE
);
1589 if (tems
.ts_display_mode
== VIS_TEXT
) {
1590 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
1591 tem_safe_clear_chars(tem
, tems
.ts_c_dimension
.width
,
1592 row
, 0, credp
, called_from
);
1594 tem
->tvs_c_cursor
.row
= 0;
1595 tem
->tvs_c_cursor
.col
= 0;
1596 tem_safe_align_cursor(tem
);
1600 ASSERT(tems
.ts_display_mode
== VIS_PIXEL
);
1602 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
1603 tem_safe_virtual_cls(tem
, tems
.ts_c_dimension
.width
, row
, 0);
1605 tem
->tvs_c_cursor
.row
= 0;
1606 tem
->tvs_c_cursor
.col
= 0;
1607 tem_safe_align_cursor(tem
);
1609 if (!tem
->tvs_isactive
)
1612 tem_safe_pix_clear_entire_screen(tem
, credp
, called_from
);
1616 tem_safe_back_tab(struct tem_vt_state
*tem
,
1617 cred_t
*credp
, enum called_from called_from
)
1620 screen_pos_t tabstop
;
1622 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1623 called_from
== CALLED_FROM_STANDALONE
);
1627 for (i
= tem
->tvs_ntabs
- 1; i
>= 0; i
--) {
1628 if (tem
->tvs_tabs
[i
] < tem
->tvs_c_cursor
.col
) {
1629 tabstop
= tem
->tvs_tabs
[i
];
1634 tem_safe_mv_cursor(tem
, tem
->tvs_c_cursor
.row
,
1635 tabstop
, credp
, called_from
);
1639 tem_safe_tab(struct tem_vt_state
*tem
,
1640 cred_t
*credp
, enum called_from called_from
)
1643 screen_pos_t tabstop
;
1645 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1646 called_from
== CALLED_FROM_STANDALONE
);
1648 tabstop
= tems
.ts_c_dimension
.width
- 1;
1650 for (i
= 0; i
< tem
->tvs_ntabs
; i
++) {
1651 if (tem
->tvs_tabs
[i
] > tem
->tvs_c_cursor
.col
) {
1652 tabstop
= tem
->tvs_tabs
[i
];
1657 tem_safe_mv_cursor(tem
, tem
->tvs_c_cursor
.row
,
1658 tabstop
, credp
, called_from
);
1662 tem_safe_set_tab(struct tem_vt_state
*tem
)
1667 if (tem
->tvs_ntabs
== TEM_MAXTAB
)
1669 if (tem
->tvs_ntabs
== 0 ||
1670 tem
->tvs_tabs
[tem
->tvs_ntabs
] < tem
->tvs_c_cursor
.col
) {
1671 tem
->tvs_tabs
[tem
->tvs_ntabs
++] = tem
->tvs_c_cursor
.col
;
1674 for (i
= 0; i
< tem
->tvs_ntabs
; i
++) {
1675 if (tem
->tvs_tabs
[i
] == tem
->tvs_c_cursor
.col
)
1677 if (tem
->tvs_tabs
[i
] > tem
->tvs_c_cursor
.col
) {
1678 for (j
= tem
->tvs_ntabs
- 1; j
>= i
; j
--)
1679 tem
->tvs_tabs
[j
+ 1] = tem
->tvs_tabs
[j
];
1680 tem
->tvs_tabs
[i
] = tem
->tvs_c_cursor
.col
;
1688 tem_safe_clear_tabs(struct tem_vt_state
*tem
, int action
)
1694 case 3: /* clear all tabs */
1697 case 0: /* clr tab at cursor */
1699 for (i
= 0; i
< tem
->tvs_ntabs
; i
++) {
1700 if (tem
->tvs_tabs
[i
] == tem
->tvs_c_cursor
.col
) {
1702 for (j
= i
; j
< tem
->tvs_ntabs
; j
++)
1703 tem
->tvs_tabs
[j
] = tem
->tvs_tabs
[j
+ 1];
1712 tem_safe_mv_cursor(struct tem_vt_state
*tem
, int row
, int col
,
1713 cred_t
*credp
, enum called_from called_from
)
1715 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1716 called_from
== CALLED_FROM_STANDALONE
);
1719 * Sanity check and bounds enforcement. Out of bounds requests are
1720 * clipped to the screen boundaries. This seems to be what SPARC
1725 if (row
>= tems
.ts_c_dimension
.height
)
1726 row
= tems
.ts_c_dimension
.height
- 1;
1729 if (col
>= tems
.ts_c_dimension
.width
)
1730 col
= tems
.ts_c_dimension
.width
- 1;
1732 tem_safe_send_data(tem
, credp
, called_from
);
1733 tem
->tvs_c_cursor
.row
= (screen_pos_t
)row
;
1734 tem
->tvs_c_cursor
.col
= (screen_pos_t
)col
;
1735 tem_safe_align_cursor(tem
);
1740 tem_safe_reset_emulator(struct tem_vt_state
*tem
,
1741 cred_t
*credp
, enum called_from called_from
,
1742 boolean_t init_color
)
1746 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1747 called_from
== CALLED_FROM_STANDALONE
);
1749 tem
->tvs_c_cursor
.row
= 0;
1750 tem
->tvs_c_cursor
.col
= 0;
1751 tem
->tvs_r_cursor
.row
= 0;
1752 tem
->tvs_r_cursor
.col
= 0;
1753 tem
->tvs_s_cursor
.row
= 0;
1754 tem
->tvs_s_cursor
.col
= 0;
1755 tem
->tvs_outindex
= 0;
1756 tem
->tvs_state
= A_STATE_START
;
1757 tem
->tvs_gotparam
= B_FALSE
;
1758 tem
->tvs_curparam
= 0;
1759 tem
->tvs_paramval
= 0;
1760 tem
->tvs_nscroll
= 1;
1763 /* use initial settings */
1764 tem
->tvs_fg_color
= tems
.ts_init_color
.fg_color
;
1765 tem
->tvs_bg_color
= tems
.ts_init_color
.bg_color
;
1766 tem
->tvs_flags
= tems
.ts_init_color
.a_flags
;
1770 * set up the initial tab stops
1773 for (j
= 8; j
< tems
.ts_c_dimension
.width
; j
+= 8)
1774 tem
->tvs_tabs
[tem
->tvs_ntabs
++] = (screen_pos_t
)j
;
1776 for (j
= 0; j
< TEM_MAXPARAMS
; j
++)
1777 tem
->tvs_params
[j
] = 0;
1781 tem_safe_reset_display(struct tem_vt_state
*tem
,
1782 cred_t
*credp
, enum called_from called_from
,
1783 boolean_t clear_txt
, boolean_t init_color
)
1785 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1786 called_from
== CALLED_FROM_STANDALONE
);
1788 tem_safe_reset_emulator(tem
, credp
, called_from
, init_color
);
1791 if (tem
->tvs_isactive
)
1792 tem_safe_callback_cursor(tem
,
1793 VIS_HIDE_CURSOR
, credp
, called_from
);
1795 tem_safe_cls(tem
, credp
, called_from
);
1797 if (tem
->tvs_isactive
)
1798 tem_safe_callback_cursor(tem
,
1799 VIS_DISPLAY_CURSOR
, credp
, called_from
);
1805 struct tem_vt_state
*tem
,
1809 enum called_from called_from
)
1813 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1814 called_from
== CALLED_FROM_STANDALONE
);
1816 rest_of_line
= tems
.ts_c_dimension
.width
- tem
->tvs_c_cursor
.col
;
1817 if (count
> rest_of_line
)
1818 count
= rest_of_line
;
1823 switch (direction
) {
1824 case TEM_SHIFT_LEFT
:
1825 if (count
< rest_of_line
) {
1826 tem_safe_copy_area(tem
,
1827 tem
->tvs_c_cursor
.col
+ count
,
1828 tem
->tvs_c_cursor
.row
,
1829 tems
.ts_c_dimension
.width
- 1,
1830 tem
->tvs_c_cursor
.row
,
1831 tem
->tvs_c_cursor
.col
,
1832 tem
->tvs_c_cursor
.row
,
1833 credp
, called_from
);
1836 tem_safe_clear_chars(tem
, count
, tem
->tvs_c_cursor
.row
,
1837 (tems
.ts_c_dimension
.width
- count
), credp
,
1840 case TEM_SHIFT_RIGHT
:
1841 if (count
< rest_of_line
) {
1842 tem_safe_copy_area(tem
,
1843 tem
->tvs_c_cursor
.col
,
1844 tem
->tvs_c_cursor
.row
,
1845 tems
.ts_c_dimension
.width
- count
- 1,
1846 tem
->tvs_c_cursor
.row
,
1847 tem
->tvs_c_cursor
.col
+ count
,
1848 tem
->tvs_c_cursor
.row
,
1849 credp
, called_from
);
1852 tem_safe_clear_chars(tem
, count
, tem
->tvs_c_cursor
.row
,
1853 tem
->tvs_c_cursor
.col
, credp
, called_from
);
1859 tem_safe_text_cursor(struct tem_vt_state
*tem
, short action
,
1860 cred_t
*credp
, enum called_from called_from
)
1862 struct vis_conscursor ca
;
1864 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1865 called_from
== CALLED_FROM_STANDALONE
);
1867 ca
.row
= tem
->tvs_c_cursor
.row
;
1868 ca
.col
= tem
->tvs_c_cursor
.col
;
1871 tems_safe_cursor(&ca
, credp
, called_from
);
1873 if (action
== VIS_GET_CURSOR
) {
1874 tem
->tvs_c_cursor
.row
= ca
.row
;
1875 tem
->tvs_c_cursor
.col
= ca
.col
;
1880 tem_safe_pix_cursor(struct tem_vt_state
*tem
, short action
,
1881 cred_t
*credp
, enum called_from called_from
)
1883 struct vis_conscursor ca
;
1885 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1886 called_from
== CALLED_FROM_STANDALONE
);
1888 ca
.row
= tem
->tvs_c_cursor
.row
* tems
.ts_font
.height
+
1890 ca
.col
= tem
->tvs_c_cursor
.col
* tems
.ts_font
.width
+
1892 ca
.width
= tems
.ts_font
.width
;
1893 ca
.height
= tems
.ts_font
.height
;
1894 if (tems
.ts_pdepth
== 8 || tems
.ts_pdepth
== 4) {
1895 if (tem
->tvs_flags
& TEM_ATTR_REVERSE
) {
1896 ca
.fg_color
.mono
= TEM_TEXT_WHITE
;
1897 ca
.bg_color
.mono
= TEM_TEXT_BLACK
;
1899 ca
.fg_color
.mono
= TEM_TEXT_BLACK
;
1900 ca
.bg_color
.mono
= TEM_TEXT_WHITE
;
1902 } else if (tems
.ts_pdepth
== 24 || tems
.ts_pdepth
== 32) {
1903 if (tem
->tvs_flags
& TEM_ATTR_REVERSE
) {
1904 ca
.fg_color
.twentyfour
[0] = TEM_TEXT_WHITE24_RED
;
1905 ca
.fg_color
.twentyfour
[1] = TEM_TEXT_WHITE24_GREEN
;
1906 ca
.fg_color
.twentyfour
[2] = TEM_TEXT_WHITE24_BLUE
;
1908 ca
.bg_color
.twentyfour
[0] = TEM_TEXT_BLACK24_RED
;
1909 ca
.bg_color
.twentyfour
[1] = TEM_TEXT_BLACK24_GREEN
;
1910 ca
.bg_color
.twentyfour
[2] = TEM_TEXT_BLACK24_BLUE
;
1912 ca
.fg_color
.twentyfour
[0] = TEM_TEXT_BLACK24_RED
;
1913 ca
.fg_color
.twentyfour
[1] = TEM_TEXT_BLACK24_GREEN
;
1914 ca
.fg_color
.twentyfour
[2] = TEM_TEXT_BLACK24_BLUE
;
1916 ca
.bg_color
.twentyfour
[0] = TEM_TEXT_WHITE24_RED
;
1917 ca
.bg_color
.twentyfour
[1] = TEM_TEXT_WHITE24_GREEN
;
1918 ca
.bg_color
.twentyfour
[2] = TEM_TEXT_WHITE24_BLUE
;
1924 tems_safe_cursor(&ca
, credp
, called_from
);
1927 #define BORDER_PIXELS 10
1929 set_font(struct font
*f
, short *rows
, short *cols
, short height
, short width
)
1931 bitmap_data_t
*font_selected
= NULL
;
1932 struct fontlist
*fl
;
1935 * Find best font for these dimensions, or use default
1937 * A 1 pixel border is the absolute minimum we could have
1938 * as a border around the text window (BORDER_PIXELS = 2),
1939 * however a slightly larger border not only looks better
1940 * but for the fonts currently statically built into the
1941 * emulator causes much better font selection for the
1942 * normal range of screen resolutions.
1944 for (fl
= fonts
; fl
->data
; fl
++) {
1945 if ((((*rows
* fl
->data
->height
) + BORDER_PIXELS
) <= height
) &&
1946 (((*cols
* fl
->data
->width
) + BORDER_PIXELS
) <= width
)) {
1947 font_selected
= fl
->data
;
1952 * The minus 2 is to make sure we have at least a 1 pixel
1953 * boarder around the entire screen.
1955 if (font_selected
== NULL
) {
1956 if (((*rows
* DEFAULT_FONT_DATA
.height
) > height
) ||
1957 ((*cols
* DEFAULT_FONT_DATA
.width
) > width
)) {
1958 *rows
= (height
- 2) / DEFAULT_FONT_DATA
.height
;
1959 *cols
= (width
- 2) / DEFAULT_FONT_DATA
.width
;
1961 font_selected
= &DEFAULT_FONT_DATA
;
1964 f
->width
= font_selected
->width
;
1965 f
->height
= font_selected
->height
;
1966 bcopy((caddr_t
)font_selected
->encoding
, (caddr_t
)f
->char_ptr
,
1967 sizeof (f
->char_ptr
));
1968 f
->image_data
= font_selected
->image
;
1973 * bit_to_pix4 is for 4-bit frame buffers. It will write one output byte
1974 * for each 2 bits of input bitmap. It inverts the input bits before
1975 * doing the output translation, for reverse video.
1977 * Assuming foreground is 0001 and background is 0000...
1978 * An input data byte of 0x53 will output the bit pattern
1979 * 00000001 00000001 00000000 00010001.
1984 struct tem_vt_state
*tem
,
1986 text_color_t fg_color
,
1987 text_color_t bg_color
)
1998 dest
= (uint8_t *)tem
->tvs_pix_data
;
2000 cp
= tems
.ts_font
.char_ptr
[c
];
2001 bytes_wide
= (tems
.ts_font
.width
+ 7) / 8;
2003 for (row
= 0; row
< tems
.ts_font
.height
; row
++) {
2004 for (byte
= 0; byte
< bytes_wide
; byte
++) {
2006 for (i
= 0; i
< 4; i
++) {
2007 nibblett
= (data
>> ((3-i
) * 2)) & 0x3;
2010 *dest
++ = bg_color
<< 4 | bg_color
;
2013 *dest
++ = bg_color
<< 4 | fg_color
;
2016 *dest
++ = fg_color
<< 4 | bg_color
;
2019 *dest
++ = fg_color
<< 4 | fg_color
;
2028 * bit_to_pix8 is for 8-bit frame buffers. It will write one output byte
2029 * for each bit of input bitmap. It inverts the input bits before
2030 * doing the output translation, for reverse video.
2032 * Assuming foreground is 00000001 and background is 00000000...
2033 * An input data byte of 0x53 will output the bit pattern
2034 * 0000000 000000001 00000000 00000001 00000000 00000000 00000001 00000001.
2039 struct tem_vt_state
*tem
,
2041 text_color_t fg_color
,
2042 text_color_t bg_color
)
2051 int bitsleft
, nbits
;
2054 dest
= (uint8_t *)tem
->tvs_pix_data
;
2056 cp
= tems
.ts_font
.char_ptr
[c
];
2057 bytes_wide
= (tems
.ts_font
.width
+ 7) / 8;
2059 for (row
= 0; row
< tems
.ts_font
.height
; row
++) {
2060 bitsleft
= tems
.ts_font
.width
;
2061 for (byte
= 0; byte
< bytes_wide
; byte
++) {
2064 nbits
= MIN(8, bitsleft
);
2066 for (i
= 0; i
< nbits
; i
++) {
2067 *dest
++ = (data
& mask
? fg_color
: bg_color
);
2075 * bit_to_pix24 is for 24-bit frame buffers. It will write four output bytes
2076 * for each bit of input bitmap. It inverts the input bits before
2077 * doing the output translation, for reverse video. Note that each
2078 * 24-bit RGB value is finally stored in a 32-bit unsigned int, with the
2079 * high-order byte set to zero.
2081 * Assuming foreground is 00000000 11111111 11111111 11111111
2082 * and background is 00000000 00000000 00000000 00000000
2083 * An input data byte of 0x53 will output the bit pattern
2085 * 00000000 00000000 00000000 00000000
2086 * 00000000 11111111 11111111 11111111
2087 * 00000000 00000000 00000000 00000000
2088 * 00000000 11111111 11111111 11111111
2089 * 00000000 00000000 00000000 00000000
2090 * 00000000 00000000 00000000 00000000
2091 * 00000000 11111111 11111111 11111111
2092 * 00000000 11111111 11111111 11111111
2095 typedef uint32_t pixel32_t
;
2099 struct tem_vt_state
*tem
,
2101 text_color_t fg_color4
,
2102 text_color_t bg_color4
)
2110 int bitsleft
, nbits
;
2112 pixel32_t fg_color32
, bg_color32
, *destp
;
2114 ASSERT(fg_color4
< 16 && bg_color4
< 16);
2116 fg_color32
= PIX4TO32(fg_color4
);
2117 bg_color32
= PIX4TO32(bg_color4
);
2119 destp
= (pixel32_t
*)tem
->tvs_pix_data
;
2120 cp
= tems
.ts_font
.char_ptr
[c
];
2121 bytes_wide
= (tems
.ts_font
.width
+ 7) / 8;
2123 for (row
= 0; row
< tems
.ts_font
.height
; row
++) {
2124 bitsleft
= tems
.ts_font
.width
;
2125 for (byte
= 0; byte
< bytes_wide
; byte
++) {
2127 nbits
= MIN(8, bitsleft
);
2129 for (i
= 0; i
< nbits
; i
++) {
2130 *destp
++ = ((data
<< i
) & 0x80 ?
2131 fg_color32
: bg_color32
);
2139 ansi_bg_to_solaris(struct tem_vt_state
*tem
, int ansi
)
2141 return (bg_xlate
[ansi
]);
2145 ansi_fg_to_solaris(struct tem_vt_state
*tem
, int ansi
)
2147 if (tem
->tvs_flags
& TEM_ATTR_BOLD
)
2148 return (fg_brt_xlate
[ansi
]);
2150 return (fg_dim_xlate
[ansi
]);
2154 * flag: TEM_ATTR_SCREEN_REVERSE or TEM_ATTR_REVERSE
2157 tem_safe_get_color(struct tem_vt_state
*tem
, text_color_t
*fg
,
2158 text_color_t
*bg
, uint8_t flag
)
2160 if (tem
->tvs_flags
& flag
) {
2161 *fg
= ansi_fg_to_solaris(tem
,
2163 *bg
= ansi_bg_to_solaris(tem
,
2166 *fg
= ansi_fg_to_solaris(tem
,
2168 *bg
= ansi_bg_to_solaris(tem
,
2174 * Clear a rectangle of screen for pixel mode.
2178 * nrows: the number of rows to clear
2179 * offset_y: the offset of height in pixels to begin clear
2181 * ncols: the number of cols to clear
2182 * offset_x: the offset of width in pixels to begin clear
2183 * scroll_up: whether this function is called during sroll up,
2184 * which is called only once.
2187 tem_safe_pix_cls_range(struct tem_vt_state
*tem
,
2188 screen_pos_t row
, int nrows
, int offset_y
,
2189 screen_pos_t col
, int ncols
, int offset_x
,
2190 boolean_t sroll_up
, cred_t
*credp
,
2191 enum called_from called_from
)
2193 struct vis_consdisplay da
;
2196 text_color_t fg_color
;
2197 text_color_t bg_color
;
2199 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
2200 called_from
== CALLED_FROM_STANDALONE
);
2203 row_add
= tems
.ts_c_dimension
.height
- 1;
2205 da
.width
= tems
.ts_font
.width
;
2206 da
.height
= tems
.ts_font
.height
;
2208 tem_safe_get_color(tem
, &fg_color
, &bg_color
, TEM_ATTR_SCREEN_REVERSE
);
2210 tem_safe_callback_bit2pix(tem
, ' ', fg_color
, bg_color
);
2211 da
.data
= (uchar_t
*)tem
->tvs_pix_data
;
2213 for (i
= 0; i
< nrows
; i
++, row
++) {
2214 da
.row
= (row
+ row_add
) * da
.height
+ offset_y
;
2215 da
.col
= col
* da
.width
+ offset_x
;
2216 for (j
= 0; j
< ncols
; j
++) {
2217 tems_safe_display(&da
, credp
, called_from
);
2224 * virtual screen operations
2227 tem_safe_virtual_display(struct tem_vt_state
*tem
, unsigned char *string
,
2228 int count
, screen_pos_t row
, screen_pos_t col
,
2229 text_color_t fg_color
, text_color_t bg_color
)
2232 unsigned char *addr
;
2233 text_color_t
*pfgcolor
;
2234 text_color_t
*pbgcolor
;
2236 if (row
< 0 || row
>= tems
.ts_c_dimension
.height
||
2237 col
< 0 || col
>= tems
.ts_c_dimension
.width
||
2238 col
+ count
> tems
.ts_c_dimension
.width
)
2241 width
= tems
.ts_c_dimension
.width
;
2242 addr
= tem
->tvs_screen_buf
+ (row
* width
+ col
);
2243 pfgcolor
= tem
->tvs_fg_buf
+ (row
* width
+ col
);
2244 pbgcolor
= tem
->tvs_bg_buf
+ (row
* width
+ col
);
2245 for (i
= 0; i
< count
; i
++) {
2246 *addr
++ = string
[i
];
2247 *pfgcolor
++ = fg_color
;
2248 *pbgcolor
++ = bg_color
;
2253 i_virtual_copy(unsigned char *base
,
2254 screen_pos_t s_col
, screen_pos_t s_row
,
2255 screen_pos_t e_col
, screen_pos_t e_row
,
2256 screen_pos_t t_col
, screen_pos_t t_row
)
2258 unsigned char *from
;
2261 screen_size_t chars_per_row
;
2262 unsigned char *to_row_start
;
2263 unsigned char *from_row_start
;
2264 screen_size_t rows_to_move
;
2265 int cols
= tems
.ts_c_dimension
.width
;
2267 chars_per_row
= e_col
- s_col
+ 1;
2268 rows_to_move
= e_row
- s_row
+ 1;
2270 to_row_start
= base
+ ((t_row
* cols
) + t_col
);
2271 from_row_start
= base
+ ((s_row
* cols
) + s_col
);
2273 if (to_row_start
< from_row_start
) {
2274 while (rows_to_move
-- > 0) {
2276 from
= from_row_start
;
2277 to_row_start
+= cols
;
2278 from_row_start
+= cols
;
2279 for (cnt
= chars_per_row
; cnt
-- > 0; )
2284 * Offset to the end of the region and copy backwards.
2286 cnt
= rows_to_move
* cols
+ chars_per_row
;
2287 to_row_start
+= cnt
;
2288 from_row_start
+= cnt
;
2290 while (rows_to_move
-- > 0) {
2291 to_row_start
-= cols
;
2292 from_row_start
-= cols
;
2294 from
= from_row_start
;
2295 for (cnt
= chars_per_row
; cnt
-- > 0; )
2302 tem_safe_virtual_copy(struct tem_vt_state
*tem
,
2303 screen_pos_t s_col
, screen_pos_t s_row
,
2304 screen_pos_t e_col
, screen_pos_t e_row
,
2305 screen_pos_t t_col
, screen_pos_t t_row
)
2307 screen_size_t chars_per_row
;
2308 screen_size_t rows_to_move
;
2309 int rows
= tems
.ts_c_dimension
.height
;
2310 int cols
= tems
.ts_c_dimension
.width
;
2312 if (s_col
< 0 || s_col
>= cols
||
2313 s_row
< 0 || s_row
>= rows
||
2314 e_col
< 0 || e_col
>= cols
||
2315 e_row
< 0 || e_row
>= rows
||
2316 t_col
< 0 || t_col
>= cols
||
2317 t_row
< 0 || t_row
>= rows
||
2322 chars_per_row
= e_col
- s_col
+ 1;
2323 rows_to_move
= e_row
- s_row
+ 1;
2325 /* More sanity checks. */
2326 if (t_row
+ rows_to_move
> rows
||
2327 t_col
+ chars_per_row
> cols
)
2330 i_virtual_copy(tem
->tvs_screen_buf
, s_col
, s_row
,
2331 e_col
, e_row
, t_col
, t_row
);
2333 /* text_color_t is the same size as char */
2334 i_virtual_copy((unsigned char *)tem
->tvs_fg_buf
,
2335 s_col
, s_row
, e_col
, e_row
, t_col
, t_row
);
2336 i_virtual_copy((unsigned char *)tem
->tvs_bg_buf
,
2337 s_col
, s_row
, e_col
, e_row
, t_col
, t_row
);
2342 tem_safe_virtual_cls(struct tem_vt_state
*tem
,
2343 int count
, screen_pos_t row
, screen_pos_t col
)
2345 text_color_t fg_color
;
2346 text_color_t bg_color
;
2348 tem_safe_get_color(tem
, &fg_color
, &bg_color
, TEM_ATTR_SCREEN_REVERSE
);
2349 tem_safe_virtual_display(tem
, tems
.ts_blank_line
, count
, row
, col
,
2350 fg_color
, bg_color
);
2354 * only blank screen, not clear our screen buffer
2357 tem_safe_blank_screen(struct tem_vt_state
*tem
, cred_t
*credp
,
2358 enum called_from called_from
)
2362 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
2363 called_from
== CALLED_FROM_STANDALONE
);
2365 if (tems
.ts_display_mode
== VIS_PIXEL
) {
2366 tem_safe_pix_clear_entire_screen(tem
, credp
, called_from
);
2370 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
2371 tem_safe_callback_cls(tem
,
2372 tems
.ts_c_dimension
.width
,
2373 row
, 0, credp
, called_from
);
2378 * unblank screen with associated tem from its screen buffer
2381 tem_safe_unblank_screen(struct tem_vt_state
*tem
, cred_t
*credp
,
2382 enum called_from called_from
)
2384 text_color_t fg_color
, fg_last
;
2385 text_color_t bg_color
, bg_last
;
2386 size_t tc_size
= sizeof (text_color_t
);
2387 int row
, col
, count
, col_start
;
2391 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
2392 called_from
== CALLED_FROM_STANDALONE
);
2394 if (tems
.ts_display_mode
== VIS_PIXEL
)
2395 tem_safe_pix_clear_entire_screen(tem
, credp
, called_from
);
2397 tem_safe_callback_cursor(tem
, VIS_HIDE_CURSOR
, credp
, called_from
);
2399 width
= tems
.ts_c_dimension
.width
;
2402 * Display data in tvs_screen_buf to the actual framebuffer in a
2404 * When dealing with one row, output data with the same foreground
2405 * and background color all together.
2407 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
2408 buf
= tem
->tvs_screen_buf
+ (row
* width
);
2409 count
= col_start
= 0;
2410 for (col
= 0; col
< width
; col
++) {
2412 tem
->tvs_fg_buf
[(row
* width
+ col
) * tc_size
];
2414 tem
->tvs_bg_buf
[(row
* width
+ col
) * tc_size
];
2420 if ((fg_color
!= fg_last
) || (bg_color
!= bg_last
)) {
2422 * Call the primitive to render this data.
2424 tem_safe_callback_display(tem
,
2425 buf
, count
, row
, col_start
,
2426 fg_last
, bg_last
, credp
, called_from
);
2437 if (col_start
== (width
- 1))
2441 * Call the primitive to render this data.
2443 tem_safe_callback_display(tem
,
2444 buf
, count
, row
, col_start
,
2445 fg_last
, bg_last
, credp
, called_from
);
2448 tem_safe_callback_cursor(tem
, VIS_DISPLAY_CURSOR
, credp
, called_from
);