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) (pixel32_t)( \
175 cmap4_to_24.red[pix4] << 16 | \
176 cmap4_to_24.green[pix4] << 8 | \
177 cmap4_to_24.blue[pix4])
180 * Fonts are statically linked with this module. At some point an
181 * RFE might be desireable to allow dynamic font loading. The
182 * original intention to facilitate dynamic fonts can be seen
183 * by examining the data structures and set_font(). As much of
184 * the original code is retained but modified to be suited to
185 * traversing a list of static fonts.
187 extern struct fontlist fonts
[];
189 #define DEFAULT_FONT_DATA font_data_12x22
191 extern bitmap_data_t font_data_12x22
;
192 extern bitmap_data_t font_data_7x14
;
193 extern bitmap_data_t font_data_6x10
;
195 * Must be sorted by font size in descending order
197 struct fontlist fonts
[] = {
198 { &font_data_12x22
, NULL
},
199 { &font_data_7x14
, NULL
},
200 { &font_data_6x10
, NULL
},
204 #define INVERSE(ch) (ch ^ 0xff)
206 #define tem_safe_callback_display (*tems.ts_callbacks->tsc_display)
207 #define tem_safe_callback_copy (*tems.ts_callbacks->tsc_copy)
208 #define tem_safe_callback_cursor (*tems.ts_callbacks->tsc_cursor)
209 #define tem_safe_callback_cls (*tems.ts_callbacks->tsc_cls)
210 #define tem_safe_callback_bit2pix(tem, c, fg, bg) { \
211 ASSERT(tems.ts_callbacks->tsc_bit2pix != NULL); \
212 (void) (*tems.ts_callbacks->tsc_bit2pix)((tem), (c), (fg), (bg));\
216 tem_safe_check_first_time(
217 struct tem_vt_state
*tem
,
219 enum called_from called_from
)
221 static int first_time
= 1;
223 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
224 called_from
== CALLED_FROM_STANDALONE
);
227 * Realign the console cursor. We did this in tem_init().
228 * However, drivers in the console stream may emit additional
229 * messages before we are ready. This causes text overwrite
230 * on the screen. This is a workaround.
236 if (tems
.ts_display_mode
== VIS_TEXT
) {
237 tem_safe_text_cursor(tem
, VIS_GET_CURSOR
, credp
, called_from
);
238 tem_safe_align_cursor(tem
);
243 * This entry point handles output requests from restricted contexts like
244 * kmdb, where services like mutexes are not available. This function
245 * is entered when OBP or when a kernel debugger (such as kmdb)
246 * are generating console output. In those cases, power management
247 * concerns are handled by the abort sequence initiation (ie. when
248 * the user hits L1+A or the equivalent to enter OBP or the debugger.).
249 * It is also entered when the kernel is panicing.
252 tem_safe_polled_write(
253 tem_vt_state_t tem_arg
,
257 struct tem_vt_state
*tem
= (struct tem_vt_state
*)tem_arg
;
260 _NOTE(NO_COMPETING_THREADS_NOW
)
261 _NOTE(NO_COMPETING_THREADS_AS_SIDE_EFFECT
)
264 if (!tem
->tvs_initialized
) {
268 tem_safe_check_first_time(tem
, kcred
, CALLED_FROM_STANDALONE
);
269 tem_safe_terminal_emulate(tem
, buf
, len
, NULL
, CALLED_FROM_STANDALONE
);
274 * This is the main entry point into the terminal emulator.
276 * For each data message coming downstream, ANSI assumes that it is composed
277 * of ASCII characters, which are treated as a byte-stream input to the
278 * parsing state machine. All data is parsed immediately -- there is
282 tem_safe_terminal_emulate(
283 struct tem_vt_state
*tem
,
287 enum called_from called_from
)
290 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
291 called_from
== CALLED_FROM_STANDALONE
);
293 if (tem
->tvs_isactive
)
294 tem_safe_callback_cursor(tem
,
295 VIS_HIDE_CURSOR
, credp
, called_from
);
297 for (; len
> 0; len
--, buf
++)
298 tem_safe_parse(tem
, *buf
, credp
, called_from
);
301 * Send the data we just got to the framebuffer.
303 tem_safe_send_data(tem
, credp
, called_from
);
305 if (tem
->tvs_isactive
)
306 tem_safe_callback_cursor(tem
,
307 VIS_DISPLAY_CURSOR
, credp
, called_from
);
311 * Display an rectangular image on the frame buffer using the
312 * mechanism appropriate for the system state being called
313 * from quiesced or normal (ie. use polled I/O vs. layered ioctls)
317 struct vis_consdisplay
*pda
,
319 enum called_from called_from
)
321 if (called_from
== CALLED_FROM_STANDALONE
)
322 tems
.ts_fb_polledio
->display(tems
.ts_fb_polledio
->arg
, pda
);
324 tems_display_layered(pda
, credp
);
328 * Copy a rectangle from one location to another on the frame buffer
329 * using the mechanism appropriate for the system state being called
330 * from, quiesced or normal (ie. use polled I/O vs. layered ioctls)
334 struct vis_conscopy
*pca
,
336 enum called_from called_from
)
338 if (called_from
== CALLED_FROM_STANDALONE
)
339 tems
.ts_fb_polledio
->copy(tems
.ts_fb_polledio
->arg
, pca
);
341 tems_copy_layered(pca
, credp
);
345 * Display or hide a rectangular block text cursor of a specificsize
346 * at a specific location on frame buffer* using the mechanism
347 * appropriate for the system state being called from, quisced or
348 * normal (ie. use polled I/O vs. layered ioctls).
352 struct vis_conscursor
*pca
,
354 enum called_from called_from
)
356 if (called_from
== CALLED_FROM_STANDALONE
)
357 tems
.ts_fb_polledio
->cursor(tems
.ts_fb_polledio
->arg
, pca
);
359 tems_cursor_layered(pca
, credp
);
363 * send the appropriate control message or set state based on the
364 * value of the control character ch
369 struct tem_vt_state
*tem
,
372 enum called_from called_from
)
374 tem
->tvs_state
= A_STATE_START
;
377 tem_safe_bell(tem
, called_from
);
381 tem_safe_mv_cursor(tem
,
382 tem
->tvs_c_cursor
.row
,
383 tem
->tvs_c_cursor
.col
- 1,
388 tem_safe_tab(tem
, credp
, called_from
);
393 * tem_safe_send_data(tem, credp, called_from);
394 * tem_safe_new_line(tem, credp, called_from);
399 tem_safe_send_data(tem
, credp
, called_from
);
400 tem_safe_lf(tem
, credp
, called_from
);
404 tem_safe_send_data(tem
, credp
, called_from
);
405 tem_safe_cls(tem
, credp
, called_from
);
409 tem_safe_send_data(tem
, credp
, called_from
);
414 tem
->tvs_state
= A_STATE_ESC
;
420 tem
->tvs_curparam
= 0;
421 tem
->tvs_paramval
= 0;
422 tem
->tvs_gotparam
= B_FALSE
;
423 /* clear the parameters */
424 for (i
= 0; i
< TEM_MAXPARAMS
; i
++)
425 tem
->tvs_params
[i
] = -1;
426 tem
->tvs_state
= A_STATE_CSI
;
431 tem_safe_back_tab(tem
, credp
, called_from
);
441 * if parameters [0..count - 1] are not set, set them to the value
446 tem_safe_setparam(struct tem_vt_state
*tem
, int count
, int newparam
)
450 for (i
= 0; i
< count
; i
++) {
451 if (tem
->tvs_params
[i
] == -1)
452 tem
->tvs_params
[i
] = newparam
;
458 * select graphics mode based on the param vals stored in a_params
461 tem_safe_selgraph(struct tem_vt_state
*tem
)
467 tem
->tvs_state
= A_STATE_START
;
469 curparam
= tem
->tvs_curparam
;
471 param
= tem
->tvs_params
[count
];
476 /* reset to initial normal settings */
477 tem
->tvs_fg_color
= tems
.ts_init_color
.fg_color
;
478 tem
->tvs_bg_color
= tems
.ts_init_color
.bg_color
;
479 tem
->tvs_flags
= tems
.ts_init_color
.a_flags
;
482 case 1: /* Bold Intense */
483 tem
->tvs_flags
|= TEM_ATTR_BOLD
;
486 case 2: /* Faint Intense */
487 tem
->tvs_flags
&= ~TEM_ATTR_BOLD
;
491 tem
->tvs_flags
|= TEM_ATTR_BLINK
;
494 case 7: /* Reverse video */
495 if (tem
->tvs_flags
& TEM_ATTR_SCREEN_REVERSE
) {
496 tem
->tvs_flags
&= ~TEM_ATTR_REVERSE
;
498 tem
->tvs_flags
|= TEM_ATTR_REVERSE
;
502 case 30: /* black (grey) foreground */
503 case 31: /* red (light red) foreground */
504 case 32: /* green (light green) foreground */
505 case 33: /* brown (yellow) foreground */
506 case 34: /* blue (light blue) foreground */
507 case 35: /* magenta (light magenta) foreground */
508 case 36: /* cyan (light cyan) foreground */
509 case 37: /* white (bright white) foreground */
510 tem
->tvs_fg_color
= param
- 30;
511 tem
->tvs_flags
&= ~TEM_ATTR_BRIGHT_FG
;
516 * Reset the foreground colour and brightness.
518 tem
->tvs_fg_color
= tems
.ts_init_color
.fg_color
;
519 if (tems
.ts_init_color
.a_flags
& TEM_ATTR_BRIGHT_FG
)
520 tem
->tvs_flags
|= TEM_ATTR_BRIGHT_FG
;
522 tem
->tvs_flags
&= ~TEM_ATTR_BRIGHT_FG
;
525 case 40: /* black (grey) background */
526 case 41: /* red (light red) background */
527 case 42: /* green (light green) background */
528 case 43: /* brown (yellow) background */
529 case 44: /* blue (light blue) background */
530 case 45: /* magenta (light magenta) background */
531 case 46: /* cyan (light cyan) background */
532 case 47: /* white (bright white) background */
533 tem
->tvs_bg_color
= param
- 40;
534 tem
->tvs_flags
&= ~TEM_ATTR_BRIGHT_BG
;
539 * Reset the background colour and brightness.
541 tem
->tvs_bg_color
= tems
.ts_init_color
.bg_color
;
542 if (tems
.ts_init_color
.a_flags
& TEM_ATTR_BRIGHT_BG
)
543 tem
->tvs_flags
|= TEM_ATTR_BRIGHT_BG
;
545 tem
->tvs_flags
&= ~TEM_ATTR_BRIGHT_BG
;
548 case 90: /* black (grey) foreground */
549 case 91: /* red (light red) foreground */
550 case 92: /* green (light green) foreground */
551 case 93: /* brown (yellow) foreground */
552 case 94: /* blue (light blue) foreground */
553 case 95: /* magenta (light magenta) foreground */
554 case 96: /* cyan (light cyan) foreground */
555 case 97: /* white (bright white) foreground */
556 tem
->tvs_fg_color
= param
- 90;
557 tem
->tvs_flags
|= TEM_ATTR_BRIGHT_FG
;
560 case 100: /* black (grey) background */
561 case 101: /* red (light red) background */
562 case 102: /* green (light green) background */
563 case 103: /* brown (yellow) background */
564 case 104: /* blue (light blue) background */
565 case 105: /* magenta (light magenta) background */
566 case 106: /* cyan (light cyan) background */
567 case 107: /* white (bright white) background */
568 tem
->tvs_bg_color
= param
- 100;
569 tem
->tvs_flags
|= TEM_ATTR_BRIGHT_BG
;
578 } while (curparam
> 0);
582 * perform the appropriate action for the escape sequence
584 * General rule: This code does not validate the arguments passed.
585 * It assumes that the next lower level will do so.
589 struct tem_vt_state
*tem
,
592 enum called_from called_from
)
598 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
599 MUTEX_HELD(&tem
->tvs_lock
));
601 row
= tem
->tvs_c_cursor
.row
;
602 col
= tem
->tvs_c_cursor
.col
;
606 case 'm': /* select terminal graphics mode */
607 tem_safe_send_data(tem
, credp
, called_from
);
608 tem_safe_selgraph(tem
);
611 case '@': /* insert char */
612 tem_safe_setparam(tem
, 1, 1);
613 tem_safe_shift(tem
, tem
->tvs_params
[0], TEM_SHIFT_RIGHT
,
617 case 'A': /* cursor up */
618 tem_safe_setparam(tem
, 1, 1);
619 tem_safe_mv_cursor(tem
, row
- tem
->tvs_params
[0], col
,
623 case 'd': /* VPA - vertical position absolute */
624 tem_safe_setparam(tem
, 1, 1);
625 tem_safe_mv_cursor(tem
, tem
->tvs_params
[0] - 1, col
,
629 case 'e': /* VPR - vertical position relative */
630 case 'B': /* cursor down */
631 tem_safe_setparam(tem
, 1, 1);
632 tem_safe_mv_cursor(tem
, row
+ tem
->tvs_params
[0], col
,
636 case 'a': /* HPR - horizontal position relative */
637 case 'C': /* cursor right */
638 tem_safe_setparam(tem
, 1, 1);
639 tem_safe_mv_cursor(tem
, row
, col
+ tem
->tvs_params
[0],
643 case '`': /* HPA - horizontal position absolute */
644 tem_safe_setparam(tem
, 1, 1);
645 tem_safe_mv_cursor(tem
, row
, tem
->tvs_params
[0] - 1,
649 case 'D': /* cursor left */
650 tem_safe_setparam(tem
, 1, 1);
651 tem_safe_mv_cursor(tem
, row
, col
- tem
->tvs_params
[0],
655 case 'E': /* CNL cursor next line */
656 tem_safe_setparam(tem
, 1, 1);
657 tem_safe_mv_cursor(tem
, row
+ tem
->tvs_params
[0], 0,
661 case 'F': /* CPL cursor previous line */
662 tem_safe_setparam(tem
, 1, 1);
663 tem_safe_mv_cursor(tem
, row
- tem
->tvs_params
[0], 0,
667 case 'G': /* cursor horizontal position */
668 tem_safe_setparam(tem
, 1, 1);
669 tem_safe_mv_cursor(tem
, row
, tem
->tvs_params
[0] - 1,
673 case 'g': /* clear tabs */
674 tem_safe_setparam(tem
, 1, 0);
675 tem_safe_clear_tabs(tem
, tem
->tvs_params
[0]);
678 case 'f': /* HVP Horizontal and Vertical Position */
679 case 'H': /* CUP position cursor */
680 tem_safe_setparam(tem
, 2, 1);
681 tem_safe_mv_cursor(tem
,
682 tem
->tvs_params
[0] - 1,
683 tem
->tvs_params
[1] - 1,
687 case 'I': /* CHT - Cursor Horizontal Tab */
688 /* Not implemented */
691 case 'J': /* ED - Erase in Display */
692 tem_safe_send_data(tem
, credp
, called_from
);
693 tem_safe_setparam(tem
, 1, 0);
694 switch (tem
->tvs_params
[0]) {
696 /* erase cursor to end of screen */
697 /* FIRST erase cursor to end of line */
698 tem_safe_clear_chars(tem
,
699 tems
.ts_c_dimension
.width
-
700 tem
->tvs_c_cursor
.col
,
701 tem
->tvs_c_cursor
.row
,
702 tem
->tvs_c_cursor
.col
, credp
, called_from
);
704 /* THEN erase lines below the cursor */
705 for (row
= tem
->tvs_c_cursor
.row
+ 1;
706 row
< tems
.ts_c_dimension
.height
;
708 tem_safe_clear_chars(tem
,
709 tems
.ts_c_dimension
.width
,
710 row
, 0, credp
, called_from
);
715 /* erase beginning of screen to cursor */
716 /* FIRST erase lines above the cursor */
718 row
< tem
->tvs_c_cursor
.row
;
720 tem_safe_clear_chars(tem
,
721 tems
.ts_c_dimension
.width
,
722 row
, 0, credp
, called_from
);
724 /* THEN erase beginning of line to cursor */
725 tem_safe_clear_chars(tem
,
726 tem
->tvs_c_cursor
.col
+ 1,
727 tem
->tvs_c_cursor
.row
,
728 0, credp
, called_from
);
732 /* erase whole screen */
734 row
< tems
.ts_c_dimension
.height
;
736 tem_safe_clear_chars(tem
,
737 tems
.ts_c_dimension
.width
,
738 row
, 0, credp
, called_from
);
744 case 'K': /* EL - Erase in Line */
745 tem_safe_send_data(tem
, credp
, called_from
);
746 tem_safe_setparam(tem
, 1, 0);
747 switch (tem
->tvs_params
[0]) {
749 /* erase cursor to end of line */
750 tem_safe_clear_chars(tem
,
751 (tems
.ts_c_dimension
.width
-
752 tem
->tvs_c_cursor
.col
),
753 tem
->tvs_c_cursor
.row
,
754 tem
->tvs_c_cursor
.col
,
759 /* erase beginning of line to cursor */
760 tem_safe_clear_chars(tem
,
761 tem
->tvs_c_cursor
.col
+ 1,
762 tem
->tvs_c_cursor
.row
,
763 0, credp
, called_from
);
767 /* erase whole line */
768 tem_safe_clear_chars(tem
,
769 tems
.ts_c_dimension
.width
,
770 tem
->tvs_c_cursor
.row
,
771 0, credp
, called_from
);
776 case 'L': /* insert line */
777 tem_safe_send_data(tem
, credp
, called_from
);
778 tem_safe_setparam(tem
, 1, 1);
780 tem
->tvs_c_cursor
.row
,
781 tems
.ts_c_dimension
.height
- 1,
782 tem
->tvs_params
[0], TEM_SCROLL_DOWN
,
786 case 'M': /* delete line */
787 tem_safe_send_data(tem
, credp
, called_from
);
788 tem_safe_setparam(tem
, 1, 1);
790 tem
->tvs_c_cursor
.row
,
791 tems
.ts_c_dimension
.height
- 1,
792 tem
->tvs_params
[0], TEM_SCROLL_UP
,
796 case 'P': /* DCH - delete char */
797 tem_safe_setparam(tem
, 1, 1);
798 tem_safe_shift(tem
, tem
->tvs_params
[0], TEM_SHIFT_LEFT
,
802 case 'S': /* scroll up */
803 tem_safe_send_data(tem
, credp
, called_from
);
804 tem_safe_setparam(tem
, 1, 1);
805 tem_safe_scroll(tem
, 0,
806 tems
.ts_c_dimension
.height
- 1,
807 tem
->tvs_params
[0], TEM_SCROLL_UP
,
811 case 'T': /* scroll down */
812 tem_safe_send_data(tem
, credp
, called_from
);
813 tem_safe_setparam(tem
, 1, 1);
814 tem_safe_scroll(tem
, 0,
815 tems
.ts_c_dimension
.height
- 1,
816 tem
->tvs_params
[0], TEM_SCROLL_DOWN
,
820 case 'X': /* erase char */
821 tem_safe_setparam(tem
, 1, 1);
822 tem_safe_clear_chars(tem
,
824 tem
->tvs_c_cursor
.row
,
825 tem
->tvs_c_cursor
.col
,
829 case 'Z': /* cursor backward tabulation */
830 tem_safe_setparam(tem
, 1, 1);
833 * Rule exception - We do sanity checking here.
835 * Restrict the count to a sane value to keep from
836 * looping for a long time. There can't be more than one
837 * tab stop per column, so use that as a limit.
839 if (tem
->tvs_params
[0] > tems
.ts_c_dimension
.width
)
840 tem
->tvs_params
[0] = tems
.ts_c_dimension
.width
;
842 for (i
= 0; i
< tem
->tvs_params
[0]; i
++)
843 tem_safe_back_tab(tem
, credp
, called_from
);
846 tem
->tvs_state
= A_STATE_START
;
851 * Gather the parameters of an ANSI escape sequence
854 tem_safe_getparams(struct tem_vt_state
*tem
, uchar_t ch
,
855 cred_t
*credp
, enum called_from called_from
)
857 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
858 MUTEX_HELD(&tem
->tvs_lock
));
860 if (ch
>= '0' && ch
<= '9') {
861 tem
->tvs_paramval
= ((tem
->tvs_paramval
* 10) + (ch
- '0'));
862 tem
->tvs_gotparam
= B_TRUE
; /* Remember got parameter */
863 return; /* Return immediately */
864 } else if (tem
->tvs_state
== A_STATE_CSI_EQUAL
||
865 tem
->tvs_state
== A_STATE_CSI_QMARK
) {
866 tem
->tvs_state
= A_STATE_START
;
868 if (tem
->tvs_curparam
< TEM_MAXPARAMS
) {
869 if (tem
->tvs_gotparam
) {
870 /* get the parameter value */
871 tem
->tvs_params
[tem
->tvs_curparam
] =
878 /* Restart parameter search */
879 tem
->tvs_gotparam
= B_FALSE
;
880 tem
->tvs_paramval
= 0; /* No parame value yet */
882 /* Handle escape sequence */
883 tem_safe_chkparam(tem
, ch
, credp
, called_from
);
889 * Add character to internal buffer.
890 * When its full, send it to the next layer.
894 tem_safe_outch(struct tem_vt_state
*tem
, uchar_t ch
,
895 cred_t
*credp
, enum called_from called_from
)
898 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
899 called_from
== CALLED_FROM_STANDALONE
);
901 /* buffer up the character until later */
903 tem
->tvs_outbuf
[tem
->tvs_outindex
++] = ch
;
904 tem
->tvs_c_cursor
.col
++;
905 if (tem
->tvs_c_cursor
.col
>= tems
.ts_c_dimension
.width
) {
906 tem_safe_send_data(tem
, credp
, called_from
);
907 tem_safe_new_line(tem
, credp
, called_from
);
912 tem_safe_new_line(struct tem_vt_state
*tem
,
913 cred_t
*credp
, enum called_from called_from
)
916 tem_safe_lf(tem
, credp
, called_from
);
920 tem_safe_cr(struct tem_vt_state
*tem
)
922 tem
->tvs_c_cursor
.col
= 0;
923 tem_safe_align_cursor(tem
);
927 tem_safe_lf(struct tem_vt_state
*tem
,
928 cred_t
*credp
, enum called_from called_from
)
932 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
933 MUTEX_HELD(&tem
->tvs_lock
));
936 * Sanity checking notes:
937 * . a_nscroll was validated when it was set.
938 * . Regardless of that, tem_safe_scroll and tem_safe_mv_cursor
939 * will prevent anything bad from happening.
941 row
= tem
->tvs_c_cursor
.row
+ 1;
943 if (row
>= tems
.ts_c_dimension
.height
) {
944 if (tem
->tvs_nscroll
!= 0) {
945 tem_safe_scroll(tem
, 0,
946 tems
.ts_c_dimension
.height
- 1,
947 tem
->tvs_nscroll
, TEM_SCROLL_UP
,
949 row
= tems
.ts_c_dimension
.height
-
951 } else { /* no scroll */
953 * implement Esc[#r when # is zero. This means no
954 * scroll but just return cursor to top of screen,
955 * do not clear screen.
961 tem_safe_mv_cursor(tem
, row
, tem
->tvs_c_cursor
.col
,
964 if (tem
->tvs_nscroll
== 0) {
965 /* erase rest of cursor line */
966 tem_safe_clear_chars(tem
,
967 tems
.ts_c_dimension
.width
-
968 tem
->tvs_c_cursor
.col
,
969 tem
->tvs_c_cursor
.row
,
970 tem
->tvs_c_cursor
.col
,
975 tem_safe_align_cursor(tem
);
979 tem_safe_send_data(struct tem_vt_state
*tem
, cred_t
*credp
,
980 enum called_from called_from
)
982 text_color_t fg_color
;
983 text_color_t bg_color
;
985 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
986 MUTEX_HELD(&tem
->tvs_lock
));
988 if (tem
->tvs_outindex
== 0) {
989 tem_safe_align_cursor(tem
);
993 tem_safe_get_color(tem
, &fg_color
, &bg_color
, TEM_ATTR_REVERSE
);
994 tem_safe_virtual_display(tem
,
995 tem
->tvs_outbuf
, tem
->tvs_outindex
,
996 tem
->tvs_s_cursor
.row
, tem
->tvs_s_cursor
.col
,
999 if (tem
->tvs_isactive
) {
1001 * Call the primitive to render this data.
1003 tem_safe_callback_display(tem
,
1004 tem
->tvs_outbuf
, tem
->tvs_outindex
,
1005 tem
->tvs_s_cursor
.row
, tem
->tvs_s_cursor
.col
,
1007 credp
, called_from
);
1010 tem
->tvs_outindex
= 0;
1012 tem_safe_align_cursor(tem
);
1017 * We have just done something to the current output point. Reset the start
1018 * point for the buffered data in a_outbuf. There shouldn't be any data
1022 tem_safe_align_cursor(struct tem_vt_state
*tem
)
1024 tem
->tvs_s_cursor
.row
= tem
->tvs_c_cursor
.row
;
1025 tem
->tvs_s_cursor
.col
= tem
->tvs_c_cursor
.col
;
1029 * State machine parser based on the current state and character input
1030 * major terminations are to control character or normal character
1034 tem_safe_parse(struct tem_vt_state
*tem
, uchar_t ch
,
1035 cred_t
*credp
, enum called_from called_from
)
1039 ASSERT((called_from
== CALLED_FROM_STANDALONE
) ||
1040 MUTEX_HELD(&tem
->tvs_lock
));
1042 if (tem
->tvs_state
== A_STATE_START
) { /* Normal state? */
1043 if (ch
== A_CSI
|| ch
== A_ESC
|| ch
< ' ') {
1045 tem_safe_control(tem
, ch
, credp
, called_from
);
1048 tem_safe_outch(tem
, ch
, credp
, called_from
);
1053 /* In <ESC> sequence */
1054 if (tem
->tvs_state
!= A_STATE_ESC
) { /* Need to get parameters? */
1055 if (tem
->tvs_state
!= A_STATE_CSI
) {
1056 tem_safe_getparams(tem
, ch
, credp
, called_from
);
1062 tem
->tvs_state
= A_STATE_CSI_QMARK
;
1065 tem
->tvs_state
= A_STATE_CSI_EQUAL
;
1069 * As defined below, this sequence
1070 * saves the cursor. However, Sun
1071 * defines ESC[s as reset. We resolved
1072 * the conflict by selecting reset as it
1073 * is exported in the termcap file for
1074 * sun-mon, while the "save cursor"
1075 * definition does not exist anywhere in
1077 * However, having no coherent
1078 * definition of reset, we have not
1084 * tem->tvs_r_cursor.row = tem->tvs_c_cursor.row;
1085 * tem->tvs_r_cursor.col = tem->tvs_c_cursor.col;
1086 * tem->tvs_state = A_STATE_START;
1089 tem
->tvs_state
= A_STATE_START
;
1092 tem_safe_mv_cursor(tem
, tem
->tvs_r_cursor
.row
,
1093 tem
->tvs_r_cursor
.col
, credp
, called_from
);
1094 tem
->tvs_state
= A_STATE_START
;
1096 case 'p': /* sunbow */
1097 tem_safe_send_data(tem
, credp
, called_from
);
1099 * Don't set anything if we are
1100 * already as we want to be.
1102 if (tem
->tvs_flags
& TEM_ATTR_SCREEN_REVERSE
) {
1103 tem
->tvs_flags
&= ~TEM_ATTR_SCREEN_REVERSE
;
1105 * If we have switched the characters to be the
1106 * inverse from the screen, then switch them as
1107 * well to keep them the inverse of the screen.
1109 if (tem
->tvs_flags
& TEM_ATTR_REVERSE
)
1110 tem
->tvs_flags
&= ~TEM_ATTR_REVERSE
;
1112 tem
->tvs_flags
|= TEM_ATTR_REVERSE
;
1114 tem_safe_cls(tem
, credp
, called_from
);
1115 tem
->tvs_state
= A_STATE_START
;
1117 case 'q': /* sunwob */
1118 tem_safe_send_data(tem
, credp
, called_from
);
1120 * Don't set anything if we are
1121 * already where as we want to be.
1123 if (!(tem
->tvs_flags
& TEM_ATTR_SCREEN_REVERSE
)) {
1124 tem
->tvs_flags
|= TEM_ATTR_SCREEN_REVERSE
;
1126 * If we have switched the characters to be the
1127 * inverse from the screen, then switch them as
1128 * well to keep them the inverse of the screen.
1130 if (!(tem
->tvs_flags
& TEM_ATTR_REVERSE
))
1131 tem
->tvs_flags
|= TEM_ATTR_REVERSE
;
1133 tem
->tvs_flags
&= ~TEM_ATTR_REVERSE
;
1136 tem_safe_cls(tem
, credp
, called_from
);
1137 tem
->tvs_state
= A_STATE_START
;
1139 case 'r': /* sunscrl */
1141 * Rule exception: check for validity here.
1143 tem
->tvs_nscroll
= tem
->tvs_paramval
;
1144 if (tem
->tvs_nscroll
> tems
.ts_c_dimension
.height
)
1145 tem
->tvs_nscroll
= tems
.ts_c_dimension
.height
;
1146 if (tem
->tvs_nscroll
< 0)
1147 tem
->tvs_nscroll
= 1;
1148 tem
->tvs_state
= A_STATE_START
;
1151 tem_safe_getparams(tem
, ch
, credp
, called_from
);
1156 /* Previous char was <ESC> */
1158 tem
->tvs_curparam
= 0;
1159 tem
->tvs_paramval
= 0;
1160 tem
->tvs_gotparam
= B_FALSE
;
1161 /* clear the parameters */
1162 for (i
= 0; i
< TEM_MAXPARAMS
; i
++)
1163 tem
->tvs_params
[i
] = -1;
1164 tem
->tvs_state
= A_STATE_CSI
;
1165 } else if (ch
== 'Q') { /* <ESC>Q ? */
1166 tem
->tvs_state
= A_STATE_START
;
1167 } else if (ch
== 'C') { /* <ESC>C ? */
1168 tem
->tvs_state
= A_STATE_START
;
1170 tem
->tvs_state
= A_STATE_START
;
1172 /* ESC c resets display */
1173 tem_safe_reset_display(tem
, credp
, called_from
,
1175 } else if (ch
== 'H') {
1176 /* ESC H sets a tab */
1177 tem_safe_set_tab(tem
);
1178 } else if (ch
== '7') {
1179 /* ESC 7 Save Cursor position */
1180 tem
->tvs_r_cursor
.row
= tem
->tvs_c_cursor
.row
;
1181 tem
->tvs_r_cursor
.col
= tem
->tvs_c_cursor
.col
;
1182 } else if (ch
== '8') {
1183 /* ESC 8 Restore Cursor position */
1184 tem_safe_mv_cursor(tem
, tem
->tvs_r_cursor
.row
,
1185 tem
->tvs_r_cursor
.col
, credp
, called_from
);
1186 /* check for control chars */
1187 } else if (ch
< ' ') {
1188 tem_safe_control(tem
, ch
, credp
, called_from
);
1190 tem_safe_outch(tem
, ch
, credp
, called_from
);
1197 tem_safe_bell(struct tem_vt_state
*tem
, enum called_from called_from
)
1199 if (called_from
== CALLED_FROM_STANDALONE
)
1200 (void) beep_polled(BEEP_CONSOLE
);
1202 (void) beep(BEEP_CONSOLE
);
1207 tem_safe_scroll(struct tem_vt_state
*tem
, int start
, int end
, int count
,
1208 int direction
, cred_t
*credp
, enum called_from called_from
)
1213 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1214 called_from
== CALLED_FROM_STANDALONE
);
1216 lines_affected
= end
- start
+ 1;
1217 if (count
> lines_affected
)
1218 count
= lines_affected
;
1222 switch (direction
) {
1224 if (count
< lines_affected
) {
1225 tem_safe_copy_area(tem
, 0, start
+ count
,
1226 tems
.ts_c_dimension
.width
- 1, end
,
1227 0, start
, credp
, called_from
);
1229 for (row
= (end
- count
) + 1; row
<= end
; row
++) {
1230 tem_safe_clear_chars(tem
, tems
.ts_c_dimension
.width
,
1231 row
, 0, credp
, called_from
);
1235 case TEM_SCROLL_DOWN
:
1236 if (count
< lines_affected
) {
1237 tem_safe_copy_area(tem
, 0, start
,
1238 tems
.ts_c_dimension
.width
- 1,
1239 end
- count
, 0, start
+ count
,
1240 credp
, called_from
);
1242 for (row
= start
; row
< start
+ count
; row
++) {
1243 tem_safe_clear_chars(tem
, tems
.ts_c_dimension
.width
,
1244 row
, 0, credp
, called_from
);
1251 tem_safe_copy_area(struct tem_vt_state
*tem
,
1252 screen_pos_t s_col
, screen_pos_t s_row
,
1253 screen_pos_t e_col
, screen_pos_t e_row
,
1254 screen_pos_t t_col
, screen_pos_t t_row
,
1255 cred_t
*credp
, enum called_from called_from
)
1260 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1261 called_from
== CALLED_FROM_STANDALONE
);
1263 if (s_col
< 0 || s_row
< 0 ||
1264 e_col
< 0 || e_row
< 0 ||
1265 t_col
< 0 || t_row
< 0 ||
1266 s_col
>= tems
.ts_c_dimension
.width
||
1267 e_col
>= tems
.ts_c_dimension
.width
||
1268 t_col
>= tems
.ts_c_dimension
.width
||
1269 s_row
>= tems
.ts_c_dimension
.height
||
1270 e_row
>= tems
.ts_c_dimension
.height
||
1271 t_row
>= tems
.ts_c_dimension
.height
)
1274 if (s_row
> e_row
|| s_col
> e_col
)
1277 rows
= e_row
- s_row
+ 1;
1278 cols
= e_col
- s_col
+ 1;
1279 if (t_row
+ rows
> tems
.ts_c_dimension
.height
||
1280 t_col
+ cols
> tems
.ts_c_dimension
.width
)
1283 tem_safe_virtual_copy(tem
,
1288 if (!tem
->tvs_isactive
)
1291 tem_safe_callback_copy(tem
, s_col
, s_row
,
1292 e_col
, e_row
, t_col
, t_row
, credp
, called_from
);
1296 tem_safe_clear_chars(struct tem_vt_state
*tem
, int count
, screen_pos_t row
,
1297 screen_pos_t col
, cred_t
*credp
, enum called_from called_from
)
1299 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1300 called_from
== CALLED_FROM_STANDALONE
);
1302 if (row
< 0 || row
>= tems
.ts_c_dimension
.height
||
1303 col
< 0 || col
>= tems
.ts_c_dimension
.width
||
1308 * Note that very large values of "count" could cause col+count
1309 * to overflow, so we check "count" independently.
1311 if (count
> tems
.ts_c_dimension
.width
||
1312 col
+ count
> tems
.ts_c_dimension
.width
)
1313 count
= tems
.ts_c_dimension
.width
- col
;
1315 tem_safe_virtual_cls(tem
, count
, row
, col
);
1317 if (!tem
->tvs_isactive
)
1320 tem_safe_callback_cls(tem
, count
, row
, col
, credp
, called_from
);
1325 tem_safe_text_display(struct tem_vt_state
*tem
, uchar_t
*string
,
1326 int count
, screen_pos_t row
, screen_pos_t col
,
1327 text_color_t fg_color
, text_color_t bg_color
,
1328 cred_t
*credp
, enum called_from called_from
)
1330 struct vis_consdisplay da
;
1332 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1333 called_from
== CALLED_FROM_STANDALONE
);
1336 da
.width
= (screen_size_t
)count
;
1340 da
.fg_color
= fg_color
;
1341 da
.bg_color
= bg_color
;
1343 tems_safe_display(&da
, credp
, called_from
);
1347 * This function is used to blit a rectangular color image,
1348 * unperturbed on the underlying framebuffer, to render
1349 * icons and pictures. The data is a pixel pattern that
1350 * fills a rectangle bounded to the width and height parameters.
1351 * The color pixel data must to be pre-adjusted by the caller
1352 * for the current video depth.
1354 * This function is unused now.
1358 tem_safe_image_display(struct tem_vt_state
*tem
, uchar_t
*image
,
1359 int height
, int width
, screen_pos_t row
, screen_pos_t col
,
1360 cred_t
*credp
, enum called_from called_from
)
1362 struct vis_consdisplay da
;
1364 mutex_enter(&tems
.ts_lock
);
1365 mutex_enter(&tem
->tvs_lock
);
1368 da
.width
= (screen_size_t
)width
;
1369 da
.height
= (screen_size_t
)height
;
1373 tems_safe_display(&da
, credp
, called_from
);
1375 mutex_exit(&tem
->tvs_lock
);
1376 mutex_exit(&tems
.ts_lock
);
1382 tem_safe_text_copy(struct tem_vt_state
*tem
,
1383 screen_pos_t s_col
, screen_pos_t s_row
,
1384 screen_pos_t e_col
, screen_pos_t e_row
,
1385 screen_pos_t t_col
, screen_pos_t t_row
,
1386 cred_t
*credp
, enum called_from called_from
)
1388 struct vis_conscopy da
;
1390 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1391 called_from
== CALLED_FROM_STANDALONE
);
1400 tems_safe_copy(&da
, credp
, called_from
);
1404 tem_safe_text_cls(struct tem_vt_state
*tem
,
1405 int count
, screen_pos_t row
, screen_pos_t col
, cred_t
*credp
,
1406 enum called_from called_from
)
1408 struct vis_consdisplay da
;
1410 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1411 called_from
== CALLED_FROM_STANDALONE
);
1413 da
.data
= tems
.ts_blank_line
;
1414 da
.width
= (screen_size_t
)count
;
1418 tem_safe_get_color(tem
, &da
.fg_color
, &da
.bg_color
,
1419 TEM_ATTR_SCREEN_REVERSE
);
1420 tems_safe_display(&da
, credp
, called_from
);
1426 tem_safe_pix_display(struct tem_vt_state
*tem
,
1427 uchar_t
*string
, int count
,
1428 screen_pos_t row
, screen_pos_t col
,
1429 text_color_t fg_color
, text_color_t bg_color
,
1430 cred_t
*credp
, enum called_from called_from
)
1432 struct vis_consdisplay da
;
1435 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1436 called_from
== CALLED_FROM_STANDALONE
);
1438 da
.data
= (uchar_t
*)tem
->tvs_pix_data
;
1439 da
.width
= tems
.ts_font
.width
;
1440 da
.height
= tems
.ts_font
.height
;
1441 da
.row
= (row
* da
.height
) + tems
.ts_p_offset
.y
;
1442 da
.col
= (col
* da
.width
) + tems
.ts_p_offset
.x
;
1444 for (i
= 0; i
< count
; i
++) {
1445 tem_safe_callback_bit2pix(tem
, string
[i
], fg_color
, bg_color
);
1446 tems_safe_display(&da
, credp
, called_from
);
1452 tem_safe_pix_copy(struct tem_vt_state
*tem
,
1453 screen_pos_t s_col
, screen_pos_t s_row
,
1454 screen_pos_t e_col
, screen_pos_t e_row
,
1455 screen_pos_t t_col
, screen_pos_t t_row
,
1457 enum called_from called_from
)
1459 struct vis_conscopy ma
;
1460 static boolean_t need_clear
= B_TRUE
;
1462 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1463 called_from
== CALLED_FROM_STANDALONE
);
1465 if (need_clear
&& tem
->tvs_first_line
> 0) {
1467 * Clear OBP output above our kernel console term
1468 * when our kernel console term begins to scroll up,
1469 * we hope it is user friendly.
1470 * (Also see comments on tem_safe_pix_clear_prom_output)
1472 * This is only one time call.
1474 tem_safe_pix_clear_prom_output(tem
, credp
, called_from
);
1476 need_clear
= B_FALSE
;
1478 ma
.s_row
= s_row
* tems
.ts_font
.height
+ tems
.ts_p_offset
.y
;
1479 ma
.e_row
= (e_row
+ 1) * tems
.ts_font
.height
+ tems
.ts_p_offset
.y
- 1;
1480 ma
.t_row
= t_row
* tems
.ts_font
.height
+ tems
.ts_p_offset
.y
;
1483 * Check if we're in process of clearing OBP's columns area,
1484 * which only happens when term scrolls up a whole line.
1486 if (tem
->tvs_first_line
> 0 && t_row
< s_row
&& t_col
== 0 &&
1487 e_col
== tems
.ts_c_dimension
.width
- 1) {
1489 * We need to clear OBP's columns area outside our kernel
1490 * console term. So that we set ma.e_col to entire row here.
1492 ma
.s_col
= s_col
* tems
.ts_font
.width
;
1493 ma
.e_col
= tems
.ts_p_dimension
.width
- 1;
1495 ma
.t_col
= t_col
* tems
.ts_font
.width
;
1497 ma
.s_col
= s_col
* tems
.ts_font
.width
+ tems
.ts_p_offset
.x
;
1498 ma
.e_col
= (e_col
+ 1) * tems
.ts_font
.width
+
1499 tems
.ts_p_offset
.x
- 1;
1500 ma
.t_col
= t_col
* tems
.ts_font
.width
+ tems
.ts_p_offset
.x
;
1503 tems_safe_copy(&ma
, credp
, called_from
);
1505 if (tem
->tvs_first_line
> 0 && t_row
< s_row
) {
1506 /* We have scrolled up (s_row - t_row) rows. */
1507 tem
->tvs_first_line
-= (s_row
- t_row
);
1508 if (tem
->tvs_first_line
<= 0) {
1509 /* All OBP rows have been cleared. */
1510 tem
->tvs_first_line
= 0;
1517 tem_safe_pix_bit2pix(struct tem_vt_state
*tem
, unsigned char c
,
1518 unsigned char fg
, unsigned char bg
)
1520 void (*fp
)(struct tem_vt_state
*, unsigned char,
1521 unsigned char, unsigned char);
1523 switch (tems
.ts_pdepth
) {
1540 * This function only clears count of columns in one row
1543 tem_safe_pix_cls(struct tem_vt_state
*tem
, int count
,
1544 screen_pos_t row
, screen_pos_t col
, cred_t
*credp
,
1545 enum called_from called_from
)
1547 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1548 called_from
== CALLED_FROM_STANDALONE
);
1550 tem_safe_pix_cls_range(tem
, row
, 1, tems
.ts_p_offset
.y
,
1551 col
, count
, tems
.ts_p_offset
.x
, B_FALSE
, credp
, called_from
);
1555 * This function clears OBP output above our kernel console term area
1556 * because OBP's term may have a bigger terminal window than that of
1557 * our kernel console term. So we need to clear OBP output garbage outside
1558 * of our kernel console term at a proper time, which is when the first
1559 * row output of our kernel console term scrolls at the first screen line.
1561 * _________________________________
1562 * | _____________________ | ---> OBP's bigger term window
1567 * |_|_|___________________|_______|
1568 * | | | ---> first line
1569 * | |___________________|---> our kernel console term window
1571 * |---> columns area to be cleared
1573 * This function only takes care of the output above our kernel console term,
1574 * and tem_prom_scroll_up takes care of columns area outside of our kernel
1578 tem_safe_pix_clear_prom_output(struct tem_vt_state
*tem
, cred_t
*credp
,
1579 enum called_from called_from
)
1581 int nrows
, ncols
, width
, height
;
1583 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1584 called_from
== CALLED_FROM_STANDALONE
);
1586 width
= tems
.ts_font
.width
;
1587 height
= tems
.ts_font
.height
;
1589 nrows
= (tems
.ts_p_offset
.y
+ (height
- 1))/ height
;
1590 ncols
= (tems
.ts_p_dimension
.width
+ (width
- 1))/ width
;
1592 tem_safe_pix_cls_range(tem
, 0, nrows
, 0, 0, ncols
, 0,
1593 B_FALSE
, credp
, called_from
);
1597 * clear the whole screen for pixel mode, just clear the
1601 tem_safe_pix_clear_entire_screen(struct tem_vt_state
*tem
, cred_t
*credp
,
1602 enum called_from called_from
)
1604 int nrows
, ncols
, width
, height
;
1606 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1607 called_from
== CALLED_FROM_STANDALONE
);
1609 width
= tems
.ts_font
.width
;
1610 height
= tems
.ts_font
.height
;
1612 nrows
= (tems
.ts_p_dimension
.height
+ (height
- 1))/ height
;
1613 ncols
= (tems
.ts_p_dimension
.width
+ (width
- 1))/ width
;
1615 tem_safe_pix_cls_range(tem
, 0, nrows
, 0, 0, ncols
, 0,
1616 B_FALSE
, credp
, called_from
);
1619 * Since the whole screen is cleared, we don't need
1620 * to clear OBP output later.
1622 if (tem
->tvs_first_line
> 0)
1623 tem
->tvs_first_line
= 0;
1627 * clear the whole screen, including the virtual screen buffer,
1628 * and reset the cursor to start point.
1631 tem_safe_cls(struct tem_vt_state
*tem
,
1632 cred_t
*credp
, enum called_from called_from
)
1636 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1637 called_from
== CALLED_FROM_STANDALONE
);
1639 if (tems
.ts_display_mode
== VIS_TEXT
) {
1640 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
1641 tem_safe_clear_chars(tem
, tems
.ts_c_dimension
.width
,
1642 row
, 0, credp
, called_from
);
1644 tem
->tvs_c_cursor
.row
= 0;
1645 tem
->tvs_c_cursor
.col
= 0;
1646 tem_safe_align_cursor(tem
);
1650 ASSERT(tems
.ts_display_mode
== VIS_PIXEL
);
1652 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
1653 tem_safe_virtual_cls(tem
, tems
.ts_c_dimension
.width
, row
, 0);
1655 tem
->tvs_c_cursor
.row
= 0;
1656 tem
->tvs_c_cursor
.col
= 0;
1657 tem_safe_align_cursor(tem
);
1659 if (!tem
->tvs_isactive
)
1662 tem_safe_pix_clear_entire_screen(tem
, credp
, called_from
);
1666 tem_safe_back_tab(struct tem_vt_state
*tem
,
1667 cred_t
*credp
, enum called_from called_from
)
1670 screen_pos_t tabstop
;
1672 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1673 called_from
== CALLED_FROM_STANDALONE
);
1677 for (i
= tem
->tvs_ntabs
- 1; i
>= 0; i
--) {
1678 if (tem
->tvs_tabs
[i
] < tem
->tvs_c_cursor
.col
) {
1679 tabstop
= tem
->tvs_tabs
[i
];
1684 tem_safe_mv_cursor(tem
, tem
->tvs_c_cursor
.row
,
1685 tabstop
, credp
, called_from
);
1689 tem_safe_tab(struct tem_vt_state
*tem
,
1690 cred_t
*credp
, enum called_from called_from
)
1693 screen_pos_t tabstop
;
1695 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1696 called_from
== CALLED_FROM_STANDALONE
);
1698 tabstop
= tems
.ts_c_dimension
.width
- 1;
1700 for (i
= 0; i
< tem
->tvs_ntabs
; i
++) {
1701 if (tem
->tvs_tabs
[i
] > tem
->tvs_c_cursor
.col
) {
1702 tabstop
= tem
->tvs_tabs
[i
];
1707 tem_safe_mv_cursor(tem
, tem
->tvs_c_cursor
.row
,
1708 tabstop
, credp
, called_from
);
1712 tem_safe_set_tab(struct tem_vt_state
*tem
)
1717 if (tem
->tvs_ntabs
== TEM_MAXTAB
)
1719 if (tem
->tvs_ntabs
== 0 ||
1720 tem
->tvs_tabs
[tem
->tvs_ntabs
] < tem
->tvs_c_cursor
.col
) {
1721 tem
->tvs_tabs
[tem
->tvs_ntabs
++] = tem
->tvs_c_cursor
.col
;
1724 for (i
= 0; i
< tem
->tvs_ntabs
; i
++) {
1725 if (tem
->tvs_tabs
[i
] == tem
->tvs_c_cursor
.col
)
1727 if (tem
->tvs_tabs
[i
] > tem
->tvs_c_cursor
.col
) {
1728 for (j
= tem
->tvs_ntabs
- 1; j
>= i
; j
--)
1729 tem
->tvs_tabs
[j
+ 1] = tem
->tvs_tabs
[j
];
1730 tem
->tvs_tabs
[i
] = tem
->tvs_c_cursor
.col
;
1738 tem_safe_clear_tabs(struct tem_vt_state
*tem
, int action
)
1744 case 3: /* clear all tabs */
1747 case 0: /* clr tab at cursor */
1749 for (i
= 0; i
< tem
->tvs_ntabs
; i
++) {
1750 if (tem
->tvs_tabs
[i
] == tem
->tvs_c_cursor
.col
) {
1752 for (j
= i
; j
< tem
->tvs_ntabs
; j
++)
1753 tem
->tvs_tabs
[j
] = tem
->tvs_tabs
[j
+ 1];
1762 tem_safe_mv_cursor(struct tem_vt_state
*tem
, int row
, int col
,
1763 cred_t
*credp
, enum called_from called_from
)
1765 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1766 called_from
== CALLED_FROM_STANDALONE
);
1769 * Sanity check and bounds enforcement. Out of bounds requests are
1770 * clipped to the screen boundaries. This seems to be what SPARC
1775 if (row
>= tems
.ts_c_dimension
.height
)
1776 row
= tems
.ts_c_dimension
.height
- 1;
1779 if (col
>= tems
.ts_c_dimension
.width
)
1780 col
= tems
.ts_c_dimension
.width
- 1;
1782 tem_safe_send_data(tem
, credp
, called_from
);
1783 tem
->tvs_c_cursor
.row
= (screen_pos_t
)row
;
1784 tem
->tvs_c_cursor
.col
= (screen_pos_t
)col
;
1785 tem_safe_align_cursor(tem
);
1790 tem_safe_reset_emulator(struct tem_vt_state
*tem
,
1791 cred_t
*credp
, enum called_from called_from
,
1792 boolean_t init_color
)
1796 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1797 called_from
== CALLED_FROM_STANDALONE
);
1799 tem
->tvs_c_cursor
.row
= 0;
1800 tem
->tvs_c_cursor
.col
= 0;
1801 tem
->tvs_r_cursor
.row
= 0;
1802 tem
->tvs_r_cursor
.col
= 0;
1803 tem
->tvs_s_cursor
.row
= 0;
1804 tem
->tvs_s_cursor
.col
= 0;
1805 tem
->tvs_outindex
= 0;
1806 tem
->tvs_state
= A_STATE_START
;
1807 tem
->tvs_gotparam
= B_FALSE
;
1808 tem
->tvs_curparam
= 0;
1809 tem
->tvs_paramval
= 0;
1810 tem
->tvs_nscroll
= 1;
1813 /* use initial settings */
1814 tem
->tvs_fg_color
= tems
.ts_init_color
.fg_color
;
1815 tem
->tvs_bg_color
= tems
.ts_init_color
.bg_color
;
1816 tem
->tvs_flags
= tems
.ts_init_color
.a_flags
;
1820 * set up the initial tab stops
1823 for (j
= 8; j
< tems
.ts_c_dimension
.width
; j
+= 8)
1824 tem
->tvs_tabs
[tem
->tvs_ntabs
++] = (screen_pos_t
)j
;
1826 for (j
= 0; j
< TEM_MAXPARAMS
; j
++)
1827 tem
->tvs_params
[j
] = 0;
1831 tem_safe_reset_display(struct tem_vt_state
*tem
,
1832 cred_t
*credp
, enum called_from called_from
,
1833 boolean_t clear_txt
, boolean_t init_color
)
1835 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1836 called_from
== CALLED_FROM_STANDALONE
);
1838 tem_safe_reset_emulator(tem
, credp
, called_from
, init_color
);
1841 if (tem
->tvs_isactive
)
1842 tem_safe_callback_cursor(tem
,
1843 VIS_HIDE_CURSOR
, credp
, called_from
);
1845 tem_safe_cls(tem
, credp
, called_from
);
1847 if (tem
->tvs_isactive
)
1848 tem_safe_callback_cursor(tem
,
1849 VIS_DISPLAY_CURSOR
, credp
, called_from
);
1855 struct tem_vt_state
*tem
,
1859 enum called_from called_from
)
1863 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1864 called_from
== CALLED_FROM_STANDALONE
);
1866 rest_of_line
= tems
.ts_c_dimension
.width
- tem
->tvs_c_cursor
.col
;
1867 if (count
> rest_of_line
)
1868 count
= rest_of_line
;
1873 switch (direction
) {
1874 case TEM_SHIFT_LEFT
:
1875 if (count
< rest_of_line
) {
1876 tem_safe_copy_area(tem
,
1877 tem
->tvs_c_cursor
.col
+ count
,
1878 tem
->tvs_c_cursor
.row
,
1879 tems
.ts_c_dimension
.width
- 1,
1880 tem
->tvs_c_cursor
.row
,
1881 tem
->tvs_c_cursor
.col
,
1882 tem
->tvs_c_cursor
.row
,
1883 credp
, called_from
);
1886 tem_safe_clear_chars(tem
, count
, tem
->tvs_c_cursor
.row
,
1887 (tems
.ts_c_dimension
.width
- count
), credp
,
1890 case TEM_SHIFT_RIGHT
:
1891 if (count
< rest_of_line
) {
1892 tem_safe_copy_area(tem
,
1893 tem
->tvs_c_cursor
.col
,
1894 tem
->tvs_c_cursor
.row
,
1895 tems
.ts_c_dimension
.width
- count
- 1,
1896 tem
->tvs_c_cursor
.row
,
1897 tem
->tvs_c_cursor
.col
+ count
,
1898 tem
->tvs_c_cursor
.row
,
1899 credp
, called_from
);
1902 tem_safe_clear_chars(tem
, count
, tem
->tvs_c_cursor
.row
,
1903 tem
->tvs_c_cursor
.col
, credp
, called_from
);
1909 tem_safe_text_cursor(struct tem_vt_state
*tem
, short action
,
1910 cred_t
*credp
, enum called_from called_from
)
1912 struct vis_conscursor ca
;
1914 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1915 called_from
== CALLED_FROM_STANDALONE
);
1917 ca
.row
= tem
->tvs_c_cursor
.row
;
1918 ca
.col
= tem
->tvs_c_cursor
.col
;
1921 tems_safe_cursor(&ca
, credp
, called_from
);
1923 if (action
== VIS_GET_CURSOR
) {
1924 tem
->tvs_c_cursor
.row
= ca
.row
;
1925 tem
->tvs_c_cursor
.col
= ca
.col
;
1930 tem_safe_pix_cursor(struct tem_vt_state
*tem
, short action
,
1931 cred_t
*credp
, enum called_from called_from
)
1933 struct vis_conscursor ca
;
1935 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
1936 called_from
== CALLED_FROM_STANDALONE
);
1938 ca
.row
= tem
->tvs_c_cursor
.row
* tems
.ts_font
.height
+
1940 ca
.col
= tem
->tvs_c_cursor
.col
* tems
.ts_font
.width
+
1942 ca
.width
= tems
.ts_font
.width
;
1943 ca
.height
= tems
.ts_font
.height
;
1944 if (tems
.ts_pdepth
== 8 || tems
.ts_pdepth
== 4) {
1945 if (tem
->tvs_flags
& TEM_ATTR_REVERSE
) {
1946 ca
.fg_color
.mono
= TEM_TEXT_WHITE
;
1947 ca
.bg_color
.mono
= TEM_TEXT_BLACK
;
1949 ca
.fg_color
.mono
= TEM_TEXT_BLACK
;
1950 ca
.bg_color
.mono
= TEM_TEXT_WHITE
;
1952 } else if (tems
.ts_pdepth
== 24 || tems
.ts_pdepth
== 32) {
1953 if (tem
->tvs_flags
& TEM_ATTR_REVERSE
) {
1954 ca
.fg_color
.twentyfour
[0] = TEM_TEXT_WHITE24_RED
;
1955 ca
.fg_color
.twentyfour
[1] = TEM_TEXT_WHITE24_GREEN
;
1956 ca
.fg_color
.twentyfour
[2] = TEM_TEXT_WHITE24_BLUE
;
1958 ca
.bg_color
.twentyfour
[0] = TEM_TEXT_BLACK24_RED
;
1959 ca
.bg_color
.twentyfour
[1] = TEM_TEXT_BLACK24_GREEN
;
1960 ca
.bg_color
.twentyfour
[2] = TEM_TEXT_BLACK24_BLUE
;
1962 ca
.fg_color
.twentyfour
[0] = TEM_TEXT_BLACK24_RED
;
1963 ca
.fg_color
.twentyfour
[1] = TEM_TEXT_BLACK24_GREEN
;
1964 ca
.fg_color
.twentyfour
[2] = TEM_TEXT_BLACK24_BLUE
;
1966 ca
.bg_color
.twentyfour
[0] = TEM_TEXT_WHITE24_RED
;
1967 ca
.bg_color
.twentyfour
[1] = TEM_TEXT_WHITE24_GREEN
;
1968 ca
.bg_color
.twentyfour
[2] = TEM_TEXT_WHITE24_BLUE
;
1974 tems_safe_cursor(&ca
, credp
, called_from
);
1977 #define BORDER_PIXELS 10
1979 set_font(struct font
*f
, short *rows
, short *cols
, short height
, short width
)
1981 bitmap_data_t
*font_selected
= NULL
;
1982 struct fontlist
*fl
;
1985 * Find best font for these dimensions, or use default
1987 * A 1 pixel border is the absolute minimum we could have
1988 * as a border around the text window (BORDER_PIXELS = 2),
1989 * however a slightly larger border not only looks better
1990 * but for the fonts currently statically built into the
1991 * emulator causes much better font selection for the
1992 * normal range of screen resolutions.
1994 for (fl
= fonts
; fl
->data
; fl
++) {
1995 if ((((*rows
* fl
->data
->height
) + BORDER_PIXELS
) <= height
) &&
1996 (((*cols
* fl
->data
->width
) + BORDER_PIXELS
) <= width
)) {
1997 font_selected
= fl
->data
;
2002 * The minus 2 is to make sure we have at least a 1 pixel
2003 * boarder around the entire screen.
2005 if (font_selected
== NULL
) {
2006 if (((*rows
* DEFAULT_FONT_DATA
.height
) > height
) ||
2007 ((*cols
* DEFAULT_FONT_DATA
.width
) > width
)) {
2008 *rows
= (height
- 2) / DEFAULT_FONT_DATA
.height
;
2009 *cols
= (width
- 2) / DEFAULT_FONT_DATA
.width
;
2011 font_selected
= &DEFAULT_FONT_DATA
;
2014 f
->width
= font_selected
->width
;
2015 f
->height
= font_selected
->height
;
2016 bcopy((caddr_t
)font_selected
->encoding
, (caddr_t
)f
->char_ptr
,
2017 sizeof (f
->char_ptr
));
2018 f
->image_data
= font_selected
->image
;
2023 * bit_to_pix4 is for 4-bit frame buffers. It will write one output byte
2024 * for each 2 bits of input bitmap. It inverts the input bits before
2025 * doing the output translation, for reverse video.
2027 * Assuming foreground is 0001 and background is 0000...
2028 * An input data byte of 0x53 will output the bit pattern
2029 * 00000001 00000001 00000000 00010001.
2034 struct tem_vt_state
*tem
,
2036 text_color_t fg_color
,
2037 text_color_t bg_color
)
2048 dest
= (uint8_t *)tem
->tvs_pix_data
;
2050 cp
= tems
.ts_font
.char_ptr
[c
];
2051 bytes_wide
= (tems
.ts_font
.width
+ 7) / 8;
2053 for (row
= 0; row
< tems
.ts_font
.height
; row
++) {
2054 for (byte
= 0; byte
< bytes_wide
; byte
++) {
2056 for (i
= 0; i
< 4; i
++) {
2057 nibblett
= (data
>> ((3-i
) * 2)) & 0x3;
2060 *dest
++ = bg_color
<< 4 | bg_color
;
2063 *dest
++ = bg_color
<< 4 | fg_color
;
2066 *dest
++ = fg_color
<< 4 | bg_color
;
2069 *dest
++ = fg_color
<< 4 | fg_color
;
2078 * bit_to_pix8 is for 8-bit frame buffers. It will write one output byte
2079 * for each bit of input bitmap. It inverts the input bits before
2080 * doing the output translation, for reverse video.
2082 * Assuming foreground is 00000001 and background is 00000000...
2083 * An input data byte of 0x53 will output the bit pattern
2084 * 0000000 000000001 00000000 00000001 00000000 00000000 00000001 00000001.
2089 struct tem_vt_state
*tem
,
2091 text_color_t fg_color
,
2092 text_color_t bg_color
)
2101 int bitsleft
, nbits
;
2104 dest
= (uint8_t *)tem
->tvs_pix_data
;
2106 cp
= tems
.ts_font
.char_ptr
[c
];
2107 bytes_wide
= (tems
.ts_font
.width
+ 7) / 8;
2109 for (row
= 0; row
< tems
.ts_font
.height
; row
++) {
2110 bitsleft
= tems
.ts_font
.width
;
2111 for (byte
= 0; byte
< bytes_wide
; byte
++) {
2114 nbits
= MIN(8, bitsleft
);
2116 for (i
= 0; i
< nbits
; i
++) {
2117 *dest
++ = (data
& mask
? fg_color
: bg_color
);
2125 * bit_to_pix24 is for 24-bit frame buffers. It will write four output bytes
2126 * for each bit of input bitmap. It inverts the input bits before
2127 * doing the output translation, for reverse video. Note that each
2128 * 24-bit RGB value is finally stored in a 32-bit unsigned int, with the
2129 * high-order byte set to zero.
2131 * Assuming foreground is 00000000 11111111 11111111 11111111
2132 * and background is 00000000 00000000 00000000 00000000
2133 * An input data byte of 0x53 will output the bit pattern
2135 * 00000000 00000000 00000000 00000000
2136 * 00000000 11111111 11111111 11111111
2137 * 00000000 00000000 00000000 00000000
2138 * 00000000 11111111 11111111 11111111
2139 * 00000000 00000000 00000000 00000000
2140 * 00000000 00000000 00000000 00000000
2141 * 00000000 11111111 11111111 11111111
2142 * 00000000 11111111 11111111 11111111
2145 typedef uint32_t pixel32_t
;
2149 struct tem_vt_state
*tem
,
2151 text_color_t fg_color4
,
2152 text_color_t bg_color4
)
2160 int bitsleft
, nbits
;
2162 pixel32_t fg_color32
, bg_color32
, *destp
;
2164 ASSERT(fg_color4
< 16 && bg_color4
< 16);
2166 fg_color32
= PIX4TO32(fg_color4
);
2167 bg_color32
= PIX4TO32(bg_color4
);
2169 destp
= (pixel32_t
*)tem
->tvs_pix_data
;
2170 cp
= tems
.ts_font
.char_ptr
[c
];
2171 bytes_wide
= (tems
.ts_font
.width
+ 7) / 8;
2173 for (row
= 0; row
< tems
.ts_font
.height
; row
++) {
2174 bitsleft
= tems
.ts_font
.width
;
2175 for (byte
= 0; byte
< bytes_wide
; byte
++) {
2177 nbits
= MIN(8, bitsleft
);
2179 for (i
= 0; i
< nbits
; i
++) {
2180 *destp
++ = ((data
<< i
) & 0x80 ?
2181 fg_color32
: bg_color32
);
2188 ansi_bg_to_solaris(struct tem_vt_state
*tem
, int ansi
)
2190 if (tem
->tvs_flags
& TEM_ATTR_BRIGHT_BG
)
2191 return (brt_xlate
[ansi
]);
2193 return (dim_xlate
[ansi
]);
2197 ansi_fg_to_solaris(struct tem_vt_state
*tem
, int ansi
)
2199 if (tem
->tvs_flags
& TEM_ATTR_BRIGHT_FG
||
2200 tem
->tvs_flags
& TEM_ATTR_BOLD
) {
2201 return (brt_xlate
[ansi
]);
2203 return (dim_xlate
[ansi
]);
2208 * flag: TEM_ATTR_SCREEN_REVERSE or TEM_ATTR_REVERSE
2211 tem_safe_get_color(struct tem_vt_state
*tem
, text_color_t
*fg
,
2212 text_color_t
*bg
, uint8_t flag
)
2214 if (tem
->tvs_flags
& flag
) {
2215 *fg
= ansi_fg_to_solaris(tem
,
2217 *bg
= ansi_bg_to_solaris(tem
,
2220 *fg
= ansi_fg_to_solaris(tem
,
2222 *bg
= ansi_bg_to_solaris(tem
,
2228 * Clear a rectangle of screen for pixel mode.
2232 * nrows: the number of rows to clear
2233 * offset_y: the offset of height in pixels to begin clear
2235 * ncols: the number of cols to clear
2236 * offset_x: the offset of width in pixels to begin clear
2237 * scroll_up: whether this function is called during sroll up,
2238 * which is called only once.
2241 tem_safe_pix_cls_range(struct tem_vt_state
*tem
,
2242 screen_pos_t row
, int nrows
, int offset_y
,
2243 screen_pos_t col
, int ncols
, int offset_x
,
2244 boolean_t sroll_up
, cred_t
*credp
,
2245 enum called_from called_from
)
2247 struct vis_consdisplay da
;
2250 text_color_t fg_color
;
2251 text_color_t bg_color
;
2253 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
2254 called_from
== CALLED_FROM_STANDALONE
);
2257 row_add
= tems
.ts_c_dimension
.height
- 1;
2259 da
.width
= tems
.ts_font
.width
;
2260 da
.height
= tems
.ts_font
.height
;
2262 tem_safe_get_color(tem
, &fg_color
, &bg_color
, TEM_ATTR_SCREEN_REVERSE
);
2264 tem_safe_callback_bit2pix(tem
, ' ', fg_color
, bg_color
);
2265 da
.data
= (uchar_t
*)tem
->tvs_pix_data
;
2267 for (i
= 0; i
< nrows
; i
++, row
++) {
2268 da
.row
= (row
+ row_add
) * da
.height
+ offset_y
;
2269 da
.col
= col
* da
.width
+ offset_x
;
2270 for (j
= 0; j
< ncols
; j
++) {
2271 tems_safe_display(&da
, credp
, called_from
);
2278 * virtual screen operations
2281 tem_safe_virtual_display(struct tem_vt_state
*tem
, unsigned char *string
,
2282 int count
, screen_pos_t row
, screen_pos_t col
,
2283 text_color_t fg_color
, text_color_t bg_color
)
2286 unsigned char *addr
;
2287 text_color_t
*pfgcolor
;
2288 text_color_t
*pbgcolor
;
2290 if (row
< 0 || row
>= tems
.ts_c_dimension
.height
||
2291 col
< 0 || col
>= tems
.ts_c_dimension
.width
||
2292 col
+ count
> tems
.ts_c_dimension
.width
)
2295 width
= tems
.ts_c_dimension
.width
;
2296 addr
= tem
->tvs_screen_buf
+ (row
* width
+ col
);
2297 pfgcolor
= tem
->tvs_fg_buf
+ (row
* width
+ col
);
2298 pbgcolor
= tem
->tvs_bg_buf
+ (row
* width
+ col
);
2299 for (i
= 0; i
< count
; i
++) {
2300 *addr
++ = string
[i
];
2301 *pfgcolor
++ = fg_color
;
2302 *pbgcolor
++ = bg_color
;
2307 i_virtual_copy(unsigned char *base
,
2308 screen_pos_t s_col
, screen_pos_t s_row
,
2309 screen_pos_t e_col
, screen_pos_t e_row
,
2310 screen_pos_t t_col
, screen_pos_t t_row
)
2312 unsigned char *from
;
2315 screen_size_t chars_per_row
;
2316 unsigned char *to_row_start
;
2317 unsigned char *from_row_start
;
2318 screen_size_t rows_to_move
;
2319 int cols
= tems
.ts_c_dimension
.width
;
2321 chars_per_row
= e_col
- s_col
+ 1;
2322 rows_to_move
= e_row
- s_row
+ 1;
2324 to_row_start
= base
+ ((t_row
* cols
) + t_col
);
2325 from_row_start
= base
+ ((s_row
* cols
) + s_col
);
2327 if (to_row_start
< from_row_start
) {
2328 while (rows_to_move
-- > 0) {
2330 from
= from_row_start
;
2331 to_row_start
+= cols
;
2332 from_row_start
+= cols
;
2333 for (cnt
= chars_per_row
; cnt
-- > 0; )
2338 * Offset to the end of the region and copy backwards.
2340 cnt
= rows_to_move
* cols
+ chars_per_row
;
2341 to_row_start
+= cnt
;
2342 from_row_start
+= cnt
;
2344 while (rows_to_move
-- > 0) {
2345 to_row_start
-= cols
;
2346 from_row_start
-= cols
;
2348 from
= from_row_start
;
2349 for (cnt
= chars_per_row
; cnt
-- > 0; )
2356 tem_safe_virtual_copy(struct tem_vt_state
*tem
,
2357 screen_pos_t s_col
, screen_pos_t s_row
,
2358 screen_pos_t e_col
, screen_pos_t e_row
,
2359 screen_pos_t t_col
, screen_pos_t t_row
)
2361 screen_size_t chars_per_row
;
2362 screen_size_t rows_to_move
;
2363 int rows
= tems
.ts_c_dimension
.height
;
2364 int cols
= tems
.ts_c_dimension
.width
;
2366 if (s_col
< 0 || s_col
>= cols
||
2367 s_row
< 0 || s_row
>= rows
||
2368 e_col
< 0 || e_col
>= cols
||
2369 e_row
< 0 || e_row
>= rows
||
2370 t_col
< 0 || t_col
>= cols
||
2371 t_row
< 0 || t_row
>= rows
||
2376 chars_per_row
= e_col
- s_col
+ 1;
2377 rows_to_move
= e_row
- s_row
+ 1;
2379 /* More sanity checks. */
2380 if (t_row
+ rows_to_move
> rows
||
2381 t_col
+ chars_per_row
> cols
)
2384 i_virtual_copy(tem
->tvs_screen_buf
, s_col
, s_row
,
2385 e_col
, e_row
, t_col
, t_row
);
2387 /* text_color_t is the same size as char */
2388 i_virtual_copy((unsigned char *)tem
->tvs_fg_buf
,
2389 s_col
, s_row
, e_col
, e_row
, t_col
, t_row
);
2390 i_virtual_copy((unsigned char *)tem
->tvs_bg_buf
,
2391 s_col
, s_row
, e_col
, e_row
, t_col
, t_row
);
2396 tem_safe_virtual_cls(struct tem_vt_state
*tem
,
2397 int count
, screen_pos_t row
, screen_pos_t col
)
2399 text_color_t fg_color
;
2400 text_color_t bg_color
;
2402 tem_safe_get_color(tem
, &fg_color
, &bg_color
, TEM_ATTR_SCREEN_REVERSE
);
2403 tem_safe_virtual_display(tem
, tems
.ts_blank_line
, count
, row
, col
,
2404 fg_color
, bg_color
);
2408 * only blank screen, not clear our screen buffer
2411 tem_safe_blank_screen(struct tem_vt_state
*tem
, cred_t
*credp
,
2412 enum called_from called_from
)
2416 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
2417 called_from
== CALLED_FROM_STANDALONE
);
2419 if (tems
.ts_display_mode
== VIS_PIXEL
) {
2420 tem_safe_pix_clear_entire_screen(tem
, credp
, called_from
);
2424 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
2425 tem_safe_callback_cls(tem
,
2426 tems
.ts_c_dimension
.width
,
2427 row
, 0, credp
, called_from
);
2432 * unblank screen with associated tem from its screen buffer
2435 tem_safe_unblank_screen(struct tem_vt_state
*tem
, cred_t
*credp
,
2436 enum called_from called_from
)
2438 text_color_t fg_color
, fg_last
;
2439 text_color_t bg_color
, bg_last
;
2440 size_t tc_size
= sizeof (text_color_t
);
2441 int row
, col
, count
, col_start
;
2445 ASSERT((MUTEX_HELD(&tems
.ts_lock
) && MUTEX_HELD(&tem
->tvs_lock
)) ||
2446 called_from
== CALLED_FROM_STANDALONE
);
2448 if (tems
.ts_display_mode
== VIS_PIXEL
)
2449 tem_safe_pix_clear_entire_screen(tem
, credp
, called_from
);
2451 tem_safe_callback_cursor(tem
, VIS_HIDE_CURSOR
, credp
, called_from
);
2453 width
= tems
.ts_c_dimension
.width
;
2456 * Display data in tvs_screen_buf to the actual framebuffer in a
2458 * When dealing with one row, output data with the same foreground
2459 * and background color all together.
2461 for (row
= 0; row
< tems
.ts_c_dimension
.height
; row
++) {
2462 buf
= tem
->tvs_screen_buf
+ (row
* width
);
2463 count
= col_start
= 0;
2464 for (col
= 0; col
< width
; col
++) {
2466 tem
->tvs_fg_buf
[(row
* width
+ col
) * tc_size
];
2468 tem
->tvs_bg_buf
[(row
* width
+ col
) * tc_size
];
2474 if ((fg_color
!= fg_last
) || (bg_color
!= bg_last
)) {
2476 * Call the primitive to render this data.
2478 tem_safe_callback_display(tem
,
2479 buf
, count
, row
, col_start
,
2480 fg_last
, bg_last
, credp
, called_from
);
2491 if (col_start
== (width
- 1))
2495 * Call the primitive to render this data.
2497 tem_safe_callback_display(tem
,
2498 buf
, count
, row
, col_start
,
2499 fg_last
, bg_last
, credp
, called_from
);
2502 tem_safe_callback_cursor(tem
, VIS_DISPLAY_CURSOR
, credp
, called_from
);