11253Slq150181 /* 21253Slq150181 * CDDL HEADER START 31253Slq150181 * 41253Slq150181 * The contents of this file are subject to the terms of the 51253Slq150181 * Common Development and Distribution License (the "License"). 61253Slq150181 * You may not use this file except in compliance with the License. 71253Slq150181 * 81253Slq150181 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91253Slq150181 * or http://www.opensolaris.org/os/licensing. 101253Slq150181 * See the License for the specific language governing permissions 111253Slq150181 * and limitations under the License. 121253Slq150181 * 131253Slq150181 * When distributing Covered Code, include this CDDL HEADER in each 141253Slq150181 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151253Slq150181 * If applicable, add the following below this CDDL HEADER, with the 161253Slq150181 * fields enclosed by brackets "[]" replaced with your own identifying 171253Slq150181 * information: Portions Copyright [yyyy] [name of copyright owner] 181253Slq150181 * 191253Slq150181 * CDDL HEADER END 201253Slq150181 */ 211253Slq150181 221253Slq150181 /* 23*7688SAaron.Zang@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 241253Slq150181 * Use is subject to license terms. 251253Slq150181 */ 261253Slq150181 271253Slq150181 /* 281253Slq150181 * Polled I/O safe ANSI terminal emulator module; 291253Slq150181 * Supporting TERM types 'sun' and 'sun-color, parsing 301253Slq150181 * ANSI x3.64 escape sequences, and the like. (See wscons(7d) 311253Slq150181 * for more information). 321253Slq150181 * 331253Slq150181 * IMPORTANT: 341253Slq150181 * 351253Slq150181 * The functions in this file *must* be able to function in 361253Slq150181 * standalone mode, ie. on a quiesced system. In that state, 371253Slq150181 * access is single threaded, only one CPU is running. 381253Slq150181 * System services are NOT available. 391253Slq150181 * 401253Slq150181 * The following restrictions pertain to every function 411253Slq150181 * in this file: 421253Slq150181 * 431253Slq150181 * - CANNOT use the DDI or LDI interfaces 441253Slq150181 * - CANNOT call system services 451253Slq150181 * - CANNOT use mutexes 461253Slq150181 * - CANNOT wait for interrupts 471253Slq150181 * - CANNOT allocate memory 481253Slq150181 * 49*7688SAaron.Zang@Sun.COM * All non-static functions in this file which: 50*7688SAaron.Zang@Sun.COM * - Operates on tems and tem_vt_state 51*7688SAaron.Zang@Sun.COM * - Not only called from standalone mode, i.e. has 52*7688SAaron.Zang@Sun.COM * a "calledfrom" argument 53*7688SAaron.Zang@Sun.COM * should assert this at the beginning: 54*7688SAaron.Zang@Sun.COM * 55*7688SAaron.Zang@Sun.COM * ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 56*7688SAaron.Zang@Sun.COM * called_from == CALLED_FROM_STANDALONE); 571253Slq150181 */ 581253Slq150181 591253Slq150181 #include <sys/types.h> 601253Slq150181 #include <sys/ascii.h> 611253Slq150181 #include <sys/visual_io.h> 621253Slq150181 #include <sys/font.h> 631253Slq150181 #include <sys/tem.h> 641253Slq150181 #include <sys/tem_impl.h> 651253Slq150181 #include <sys/ksynch.h> 661253Slq150181 #include <sys/sysmacros.h> 671253Slq150181 #include <sys/mutex.h> 68*7688SAaron.Zang@Sun.COM #include <sys/note.h> 69*7688SAaron.Zang@Sun.COM #include <sys/t_lock.h> 701253Slq150181 71*7688SAaron.Zang@Sun.COM tem_safe_callbacks_t tem_safe_text_callbacks = { 72*7688SAaron.Zang@Sun.COM &tem_safe_text_display, 73*7688SAaron.Zang@Sun.COM &tem_safe_text_copy, 74*7688SAaron.Zang@Sun.COM &tem_safe_text_cursor, 75*7688SAaron.Zang@Sun.COM NULL, 76*7688SAaron.Zang@Sun.COM &tem_safe_text_cls 77*7688SAaron.Zang@Sun.COM }; 78*7688SAaron.Zang@Sun.COM tem_safe_callbacks_t tem_safe_pix_callbacks = { 79*7688SAaron.Zang@Sun.COM &tem_safe_pix_display, 80*7688SAaron.Zang@Sun.COM &tem_safe_pix_copy, 81*7688SAaron.Zang@Sun.COM &tem_safe_pix_cursor, 82*7688SAaron.Zang@Sun.COM &tem_safe_pix_bit2pix, 83*7688SAaron.Zang@Sun.COM &tem_safe_pix_cls 84*7688SAaron.Zang@Sun.COM }; 85*7688SAaron.Zang@Sun.COM 86*7688SAaron.Zang@Sun.COM 87*7688SAaron.Zang@Sun.COM static void tem_safe_control(struct tem_vt_state *, uchar_t, 881253Slq150181 cred_t *, enum called_from); 89*7688SAaron.Zang@Sun.COM static void tem_safe_setparam(struct tem_vt_state *, int, int); 90*7688SAaron.Zang@Sun.COM static void tem_safe_selgraph(struct tem_vt_state *); 91*7688SAaron.Zang@Sun.COM static void tem_safe_chkparam(struct tem_vt_state *, uchar_t, 921253Slq150181 cred_t *, enum called_from); 93*7688SAaron.Zang@Sun.COM static void tem_safe_getparams(struct tem_vt_state *, uchar_t, 941253Slq150181 cred_t *, enum called_from); 95*7688SAaron.Zang@Sun.COM static void tem_safe_outch(struct tem_vt_state *, uchar_t, 961253Slq150181 cred_t *, enum called_from); 97*7688SAaron.Zang@Sun.COM static void tem_safe_parse(struct tem_vt_state *, uchar_t, 981253Slq150181 cred_t *, enum called_from); 991253Slq150181 100*7688SAaron.Zang@Sun.COM static void tem_safe_new_line(struct tem_vt_state *, 1011253Slq150181 cred_t *, enum called_from); 102*7688SAaron.Zang@Sun.COM static void tem_safe_cr(struct tem_vt_state *); 103*7688SAaron.Zang@Sun.COM static void tem_safe_lf(struct tem_vt_state *, 1041253Slq150181 cred_t *, enum called_from); 105*7688SAaron.Zang@Sun.COM static void tem_safe_send_data(struct tem_vt_state *, cred_t *, 1061253Slq150181 enum called_from); 107*7688SAaron.Zang@Sun.COM static void tem_safe_cls(struct tem_vt_state *, 1081253Slq150181 cred_t *, enum called_from); 109*7688SAaron.Zang@Sun.COM static void tem_safe_tab(struct tem_vt_state *, 1101253Slq150181 cred_t *, enum called_from); 111*7688SAaron.Zang@Sun.COM static void tem_safe_back_tab(struct tem_vt_state *, 1121253Slq150181 cred_t *, enum called_from); 113*7688SAaron.Zang@Sun.COM static void tem_safe_clear_tabs(struct tem_vt_state *, int); 114*7688SAaron.Zang@Sun.COM static void tem_safe_set_tab(struct tem_vt_state *); 115*7688SAaron.Zang@Sun.COM static void tem_safe_mv_cursor(struct tem_vt_state *, int, int, 1161253Slq150181 cred_t *, enum called_from); 117*7688SAaron.Zang@Sun.COM static void tem_safe_shift(struct tem_vt_state *, int, int, 1181253Slq150181 cred_t *, enum called_from); 119*7688SAaron.Zang@Sun.COM static void tem_safe_scroll(struct tem_vt_state *, int, int, 1201253Slq150181 int, int, cred_t *, enum called_from); 121*7688SAaron.Zang@Sun.COM static void tem_safe_clear_chars(struct tem_vt_state *tem, 1221253Slq150181 int count, screen_pos_t row, screen_pos_t col, 1231253Slq150181 cred_t *credp, enum called_from called_from); 124*7688SAaron.Zang@Sun.COM static void tem_safe_copy_area(struct tem_vt_state *tem, 1251253Slq150181 screen_pos_t s_col, screen_pos_t s_row, 1261253Slq150181 screen_pos_t e_col, screen_pos_t e_row, 1271253Slq150181 screen_pos_t t_col, screen_pos_t t_row, 1281253Slq150181 cred_t *credp, enum called_from called_from); 129*7688SAaron.Zang@Sun.COM static void tem_safe_image_display(struct tem_vt_state *, uchar_t *, 1301253Slq150181 int, int, screen_pos_t, screen_pos_t, 1311253Slq150181 cred_t *, enum called_from); 132*7688SAaron.Zang@Sun.COM static void tem_safe_bell(struct tem_vt_state *tem, 1331253Slq150181 enum called_from called_from); 134*7688SAaron.Zang@Sun.COM static void tem_safe_pix_clear_prom_output(struct tem_vt_state *tem, 1351253Slq150181 cred_t *credp, enum called_from called_from); 1361253Slq150181 137*7688SAaron.Zang@Sun.COM static void tem_safe_virtual_cls(struct tem_vt_state *, int, screen_pos_t, 138*7688SAaron.Zang@Sun.COM screen_pos_t); 139*7688SAaron.Zang@Sun.COM static void tem_safe_virtual_display(struct tem_vt_state *, 140*7688SAaron.Zang@Sun.COM unsigned char *, int, screen_pos_t, screen_pos_t, 141*7688SAaron.Zang@Sun.COM text_color_t, text_color_t); 142*7688SAaron.Zang@Sun.COM static void tem_safe_virtual_copy(struct tem_vt_state *, screen_pos_t, 143*7688SAaron.Zang@Sun.COM screen_pos_t, screen_pos_t, screen_pos_t, 144*7688SAaron.Zang@Sun.COM screen_pos_t, screen_pos_t); 145*7688SAaron.Zang@Sun.COM static void tem_safe_align_cursor(struct tem_vt_state *tem); 146*7688SAaron.Zang@Sun.COM static void bit_to_pix4(struct tem_vt_state *tem, uchar_t c, 147*7688SAaron.Zang@Sun.COM text_color_t fg_color, text_color_t bg_color); 148*7688SAaron.Zang@Sun.COM static void bit_to_pix8(struct tem_vt_state *tem, uchar_t c, 149*7688SAaron.Zang@Sun.COM text_color_t fg_color, text_color_t bg_color); 150*7688SAaron.Zang@Sun.COM static void bit_to_pix24(struct tem_vt_state *tem, uchar_t c, 151*7688SAaron.Zang@Sun.COM text_color_t fg_color, text_color_t bg_color); 152*7688SAaron.Zang@Sun.COM 1531253Slq150181 /* BEGIN CSTYLED */ 1541253Slq150181 /* Bk Rd Gr Br Bl Mg Cy Wh */ 1551253Slq150181 static text_color_t fg_dim_xlate[] = { 1, 5, 3, 7, 2, 6, 4, 8 }; 1561253Slq150181 static text_color_t fg_brt_xlate[] = { 9, 13, 11, 15, 10, 14, 12, 0 }; 1571253Slq150181 static text_color_t bg_xlate[] = { 1, 5, 3, 7, 2, 6, 4, 0 }; 1581253Slq150181 /* END CSTYLED */ 1591253Slq150181 1601253Slq150181 1611253Slq150181 text_cmap_t cmap4_to_24 = { 1621253Slq150181 /* BEGIN CSTYLED */ 1631253Slq150181 /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1641253Slq150181 Wh+ Bk Bl Gr Cy Rd Mg Br Wh Bk+ Bl+ Gr+ Cy+ Rd+ Mg+ Yw */ 1651253Slq150181 0xff,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x40,0x00,0x00,0x00,0xff,0xff,0xff, 1661253Slq150181 0xff,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x40,0x00,0xff,0xff,0x00,0x00,0xff, 1671253Slq150181 0xff,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x40,0xff,0x00,0xff,0x00,0xff,0x00 1681253Slq150181 /* END CSTYLED */ 1691253Slq150181 }; 1701253Slq150181 1711253Slq150181 #define PIX4TO32(pix4) (pixel32_t)( \ 1721253Slq150181 cmap4_to_24.red[pix4] << 16 | \ 1731253Slq150181 cmap4_to_24.green[pix4] << 8 | \ 1741253Slq150181 cmap4_to_24.blue[pix4]) 1751253Slq150181 1761253Slq150181 /* 1771253Slq150181 * Fonts are statically linked with this module. At some point an 1781253Slq150181 * RFE might be desireable to allow dynamic font loading. The 1791253Slq150181 * original intention to facilitate dynamic fonts can be seen 1801253Slq150181 * by examining the data structures and set_font(). As much of 1811253Slq150181 * the original code is retained but modified to be suited to 1821253Slq150181 * traversing a list of static fonts. 1831253Slq150181 */ 1841253Slq150181 extern struct fontlist fonts[]; 1851253Slq150181 1861253Slq150181 #define DEFAULT_FONT_DATA font_data_12x22 1871253Slq150181 1881253Slq150181 extern bitmap_data_t font_data_12x22; 1891253Slq150181 extern bitmap_data_t font_data_7x14; 1901253Slq150181 extern bitmap_data_t font_data_6x10; 1911253Slq150181 /* 1921253Slq150181 * Must be sorted by font size in descending order 1931253Slq150181 */ 1941253Slq150181 struct fontlist fonts[] = { 1951253Slq150181 { &font_data_12x22, NULL }, 1961253Slq150181 { &font_data_7x14, NULL }, 1971253Slq150181 { &font_data_6x10, NULL }, 1981253Slq150181 { NULL, NULL } 1991253Slq150181 }; 2001253Slq150181 2011253Slq150181 #define INVERSE(ch) (ch ^ 0xff) 2021253Slq150181 203*7688SAaron.Zang@Sun.COM #define tem_safe_callback_display (*tems.ts_callbacks->tsc_display) 204*7688SAaron.Zang@Sun.COM #define tem_safe_callback_copy (*tems.ts_callbacks->tsc_copy) 205*7688SAaron.Zang@Sun.COM #define tem_safe_callback_cursor (*tems.ts_callbacks->tsc_cursor) 206*7688SAaron.Zang@Sun.COM #define tem_safe_callback_cls (*tems.ts_callbacks->tsc_cls) 207*7688SAaron.Zang@Sun.COM #define tem_safe_callback_bit2pix(tem, c, fg, bg) { \ 208*7688SAaron.Zang@Sun.COM ASSERT(tems.ts_callbacks->tsc_bit2pix != NULL); \ 209*7688SAaron.Zang@Sun.COM (void) (*tems.ts_callbacks->tsc_bit2pix)((tem), (c), (fg), (bg));\ 2101253Slq150181 } 2111253Slq150181 2121253Slq150181 void 213*7688SAaron.Zang@Sun.COM tem_safe_check_first_time( 214*7688SAaron.Zang@Sun.COM struct tem_vt_state *tem, 2151253Slq150181 cred_t *credp, 2161253Slq150181 enum called_from called_from) 2171253Slq150181 { 2181253Slq150181 static int first_time = 1; 2191253Slq150181 220*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 221*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 222*7688SAaron.Zang@Sun.COM 2231253Slq150181 /* 2241253Slq150181 * Realign the console cursor. We did this in tem_init(). 2251253Slq150181 * However, drivers in the console stream may emit additional 2261253Slq150181 * messages before we are ready. This causes text overwrite 2271253Slq150181 * on the screen. This is a workaround. 2281253Slq150181 */ 229*7688SAaron.Zang@Sun.COM if (!first_time) 230*7688SAaron.Zang@Sun.COM return; 231*7688SAaron.Zang@Sun.COM 232*7688SAaron.Zang@Sun.COM first_time = 0; 233*7688SAaron.Zang@Sun.COM if (tems.ts_display_mode == VIS_TEXT) { 234*7688SAaron.Zang@Sun.COM tem_safe_text_cursor(tem, VIS_GET_CURSOR, credp, called_from); 235*7688SAaron.Zang@Sun.COM tem_safe_align_cursor(tem); 2361253Slq150181 } 2371253Slq150181 } 2381253Slq150181 2391253Slq150181 /* 2401253Slq150181 * This entry point handles output requests from restricted contexts like 2411253Slq150181 * kmdb, where services like mutexes are not available. This function 2421253Slq150181 * is entered when OBP or when a kernel debugger (such as kmdb) 2431253Slq150181 * are generating console output. In those cases, power management 2441253Slq150181 * concerns are handled by the abort sequence initiation (ie. when 2451253Slq150181 * the user hits L1+A or the equivalent to enter OBP or the debugger.). 2461253Slq150181 * It is also entered when the kernel is panicing. 2471253Slq150181 */ 2481253Slq150181 void 249*7688SAaron.Zang@Sun.COM tem_safe_polled_write( 250*7688SAaron.Zang@Sun.COM tem_vt_state_t tem_arg, 2511253Slq150181 uchar_t *buf, 2521253Slq150181 int len) 2531253Slq150181 { 254*7688SAaron.Zang@Sun.COM struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg; 2551253Slq150181 256*7688SAaron.Zang@Sun.COM #ifdef __lock_lint 257*7688SAaron.Zang@Sun.COM _NOTE(NO_COMPETING_THREADS_NOW) 258*7688SAaron.Zang@Sun.COM _NOTE(NO_COMPETING_THREADS_AS_SIDE_EFFECT) 259*7688SAaron.Zang@Sun.COM #endif 2601253Slq150181 261*7688SAaron.Zang@Sun.COM if (!tem->tvs_initialized) { 262*7688SAaron.Zang@Sun.COM return; 263*7688SAaron.Zang@Sun.COM } 264*7688SAaron.Zang@Sun.COM 265*7688SAaron.Zang@Sun.COM tem_safe_check_first_time(tem, kcred, CALLED_FROM_STANDALONE); 266*7688SAaron.Zang@Sun.COM tem_safe_terminal_emulate(tem, buf, len, NULL, CALLED_FROM_STANDALONE); 2671253Slq150181 } 2681253Slq150181 2691253Slq150181 2701253Slq150181 /* 2711253Slq150181 * This is the main entry point into the terminal emulator. 2721253Slq150181 * 2731253Slq150181 * For each data message coming downstream, ANSI assumes that it is composed 2741253Slq150181 * of ASCII characters, which are treated as a byte-stream input to the 2751253Slq150181 * parsing state machine. All data is parsed immediately -- there is 2761253Slq150181 * no enqueing. 2771253Slq150181 */ 2781253Slq150181 void 279*7688SAaron.Zang@Sun.COM tem_safe_terminal_emulate( 280*7688SAaron.Zang@Sun.COM struct tem_vt_state *tem, 2811253Slq150181 uchar_t *buf, 2821253Slq150181 int len, 2831253Slq150181 cred_t *credp, 2841253Slq150181 enum called_from called_from) 2851253Slq150181 { 2861253Slq150181 287*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 288*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 2891253Slq150181 290*7688SAaron.Zang@Sun.COM if (tem->tvs_isactive) 291*7688SAaron.Zang@Sun.COM tem_safe_callback_cursor(tem, 292*7688SAaron.Zang@Sun.COM VIS_HIDE_CURSOR, credp, called_from); 2931253Slq150181 294*7688SAaron.Zang@Sun.COM for (; len > 0; len--, buf++) 295*7688SAaron.Zang@Sun.COM tem_safe_parse(tem, *buf, credp, called_from); 2961253Slq150181 2971253Slq150181 /* 2981253Slq150181 * Send the data we just got to the framebuffer. 2991253Slq150181 */ 300*7688SAaron.Zang@Sun.COM tem_safe_send_data(tem, credp, called_from); 3011253Slq150181 302*7688SAaron.Zang@Sun.COM if (tem->tvs_isactive) 303*7688SAaron.Zang@Sun.COM tem_safe_callback_cursor(tem, 304*7688SAaron.Zang@Sun.COM VIS_DISPLAY_CURSOR, credp, called_from); 3051253Slq150181 } 3061253Slq150181 3071253Slq150181 /* 3081253Slq150181 * Display an rectangular image on the frame buffer using the 3091253Slq150181 * mechanism appropriate for the system state being called 3101253Slq150181 * from quiesced or normal (ie. use polled I/O vs. layered ioctls) 3111253Slq150181 */ 3121253Slq150181 static void 313*7688SAaron.Zang@Sun.COM tems_safe_display( 3141253Slq150181 struct vis_consdisplay *pda, 3151253Slq150181 cred_t *credp, 3161253Slq150181 enum called_from called_from) 3171253Slq150181 { 3181253Slq150181 if (called_from == CALLED_FROM_STANDALONE) 319*7688SAaron.Zang@Sun.COM tems.ts_fb_polledio->display(tems.ts_fb_polledio->arg, pda); 3201253Slq150181 else 321*7688SAaron.Zang@Sun.COM tems_display_layered(pda, credp); 3221253Slq150181 } 3231253Slq150181 3241253Slq150181 /* 3251253Slq150181 * Copy a rectangle from one location to another on the frame buffer 3261253Slq150181 * using the mechanism appropriate for the system state being called 3271253Slq150181 * from, quiesced or normal (ie. use polled I/O vs. layered ioctls) 3281253Slq150181 */ 3291253Slq150181 void 330*7688SAaron.Zang@Sun.COM tems_safe_copy( 3311253Slq150181 struct vis_conscopy *pca, 3321253Slq150181 cred_t *credp, 3331253Slq150181 enum called_from called_from) 3341253Slq150181 { 3351253Slq150181 if (called_from == CALLED_FROM_STANDALONE) 336*7688SAaron.Zang@Sun.COM tems.ts_fb_polledio->copy(tems.ts_fb_polledio->arg, pca); 3371253Slq150181 else 338*7688SAaron.Zang@Sun.COM tems_copy_layered(pca, credp); 3391253Slq150181 } 3401253Slq150181 3411253Slq150181 /* 3421253Slq150181 * Display or hide a rectangular block text cursor of a specificsize 3431253Slq150181 * at a specific location on frame buffer* using the mechanism 3441253Slq150181 * appropriate for the system state being called from, quisced or 3451253Slq150181 * normal (ie. use polled I/O vs. layered ioctls). 3461253Slq150181 */ 3471253Slq150181 static void 348*7688SAaron.Zang@Sun.COM tems_safe_cursor( 3491253Slq150181 struct vis_conscursor *pca, 3501253Slq150181 cred_t *credp, 3511253Slq150181 enum called_from called_from) 3521253Slq150181 { 3531253Slq150181 if (called_from == CALLED_FROM_STANDALONE) 354*7688SAaron.Zang@Sun.COM tems.ts_fb_polledio->cursor(tems.ts_fb_polledio->arg, pca); 3551253Slq150181 else 356*7688SAaron.Zang@Sun.COM tems_cursor_layered(pca, credp); 3571253Slq150181 } 3581253Slq150181 3591253Slq150181 /* 3601253Slq150181 * send the appropriate control message or set state based on the 3611253Slq150181 * value of the control character ch 3621253Slq150181 */ 3631253Slq150181 3641253Slq150181 static void 365*7688SAaron.Zang@Sun.COM tem_safe_control( 366*7688SAaron.Zang@Sun.COM struct tem_vt_state *tem, 3671253Slq150181 uchar_t ch, 3681253Slq150181 cred_t *credp, 3691253Slq150181 enum called_from called_from) 3701253Slq150181 { 371*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_START; 3721253Slq150181 switch (ch) { 3731253Slq150181 case A_BEL: 374*7688SAaron.Zang@Sun.COM tem_safe_bell(tem, called_from); 3751253Slq150181 break; 3761253Slq150181 3771253Slq150181 case A_BS: 378*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, 379*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 380*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col - 1, 3811253Slq150181 credp, called_from); 3821253Slq150181 break; 3831253Slq150181 3841253Slq150181 case A_HT: 385*7688SAaron.Zang@Sun.COM tem_safe_tab(tem, credp, called_from); 3861253Slq150181 break; 3871253Slq150181 3881253Slq150181 case A_NL: 3891253Slq150181 /* 390*7688SAaron.Zang@Sun.COM * tem_safe_send_data(tem, credp, called_from); 391*7688SAaron.Zang@Sun.COM * tem_safe_new_line(tem, credp, called_from); 3921253Slq150181 * break; 3931253Slq150181 */ 3941253Slq150181 3951253Slq150181 case A_VT: 396*7688SAaron.Zang@Sun.COM tem_safe_send_data(tem, credp, called_from); 397*7688SAaron.Zang@Sun.COM tem_safe_lf(tem, credp, called_from); 3981253Slq150181 break; 3991253Slq150181 4001253Slq150181 case A_FF: 401*7688SAaron.Zang@Sun.COM tem_safe_send_data(tem, credp, called_from); 402*7688SAaron.Zang@Sun.COM tem_safe_cls(tem, credp, called_from); 4031253Slq150181 break; 4041253Slq150181 4051253Slq150181 case A_CR: 406*7688SAaron.Zang@Sun.COM tem_safe_send_data(tem, credp, called_from); 407*7688SAaron.Zang@Sun.COM tem_safe_cr(tem); 4081253Slq150181 break; 4091253Slq150181 4101253Slq150181 case A_ESC: 411*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_ESC; 4121253Slq150181 break; 4131253Slq150181 4141253Slq150181 case A_CSI: 4151253Slq150181 { 4161253Slq150181 int i; 417*7688SAaron.Zang@Sun.COM tem->tvs_curparam = 0; 418*7688SAaron.Zang@Sun.COM tem->tvs_paramval = 0; 419*7688SAaron.Zang@Sun.COM tem->tvs_gotparam = B_FALSE; 4201253Slq150181 /* clear the parameters */ 4211253Slq150181 for (i = 0; i < TEM_MAXPARAMS; i++) 422*7688SAaron.Zang@Sun.COM tem->tvs_params[i] = -1; 423*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_CSI; 4241253Slq150181 } 4251253Slq150181 break; 4261253Slq150181 4271253Slq150181 case A_GS: 428*7688SAaron.Zang@Sun.COM tem_safe_back_tab(tem, credp, called_from); 4291253Slq150181 break; 4301253Slq150181 4311253Slq150181 default: 4321253Slq150181 break; 4331253Slq150181 } 4341253Slq150181 } 4351253Slq150181 4361253Slq150181 4371253Slq150181 /* 4381253Slq150181 * if parameters [0..count - 1] are not set, set them to the value 4391253Slq150181 * of newparam. 4401253Slq150181 */ 4411253Slq150181 4421253Slq150181 static void 443*7688SAaron.Zang@Sun.COM tem_safe_setparam(struct tem_vt_state *tem, int count, int newparam) 4441253Slq150181 { 4451253Slq150181 int i; 4461253Slq150181 4471253Slq150181 for (i = 0; i < count; i++) { 448*7688SAaron.Zang@Sun.COM if (tem->tvs_params[i] == -1) 449*7688SAaron.Zang@Sun.COM tem->tvs_params[i] = newparam; 4501253Slq150181 } 4511253Slq150181 } 4521253Slq150181 4531253Slq150181 4541253Slq150181 /* 4551253Slq150181 * select graphics mode based on the param vals stored in a_params 4561253Slq150181 */ 4571253Slq150181 static void 458*7688SAaron.Zang@Sun.COM tem_safe_selgraph(struct tem_vt_state *tem) 4591253Slq150181 { 4601253Slq150181 int curparam; 4611253Slq150181 int count = 0; 4621253Slq150181 int param; 4631253Slq150181 464*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_START; 465*7688SAaron.Zang@Sun.COM 466*7688SAaron.Zang@Sun.COM curparam = tem->tvs_curparam; 4671253Slq150181 do { 468*7688SAaron.Zang@Sun.COM param = tem->tvs_params[count]; 4691253Slq150181 4701253Slq150181 switch (param) { 4711253Slq150181 case -1: 4721253Slq150181 case 0: 473*7688SAaron.Zang@Sun.COM /* reset to initial normal settings */ 474*7688SAaron.Zang@Sun.COM tem->tvs_fg_color = tems.ts_init_color.fg_color; 475*7688SAaron.Zang@Sun.COM tem->tvs_bg_color = tems.ts_init_color.bg_color; 476*7688SAaron.Zang@Sun.COM tem->tvs_flags = tems.ts_init_color.a_flags; 4771253Slq150181 break; 4781253Slq150181 4791253Slq150181 case 1: /* Bold Intense */ 480*7688SAaron.Zang@Sun.COM tem->tvs_flags |= TEM_ATTR_BOLD; 4811253Slq150181 break; 4821253Slq150181 4833994Slq150181 case 2: /* Faint Intense */ 484*7688SAaron.Zang@Sun.COM tem->tvs_flags &= ~TEM_ATTR_BOLD; 4853994Slq150181 break; 4863994Slq150181 4871253Slq150181 case 5: /* Blink */ 488*7688SAaron.Zang@Sun.COM tem->tvs_flags |= TEM_ATTR_BLINK; 4891253Slq150181 break; 4901253Slq150181 4911253Slq150181 case 7: /* Reverse video */ 492*7688SAaron.Zang@Sun.COM if (tem->tvs_flags & TEM_ATTR_SCREEN_REVERSE) { 493*7688SAaron.Zang@Sun.COM tem->tvs_flags &= ~TEM_ATTR_REVERSE; 4941253Slq150181 } else { 495*7688SAaron.Zang@Sun.COM tem->tvs_flags |= TEM_ATTR_REVERSE; 4961253Slq150181 } 4971253Slq150181 break; 4981253Slq150181 4991253Slq150181 case 30: /* black (grey) foreground */ 5001253Slq150181 case 31: /* red (light red) foreground */ 5011253Slq150181 case 32: /* green (light green) foreground */ 5021253Slq150181 case 33: /* brown (yellow) foreground */ 5031253Slq150181 case 34: /* blue (light blue) foreground */ 5041253Slq150181 case 35: /* magenta (light magenta) foreground */ 5051253Slq150181 case 36: /* cyan (light cyan) foreground */ 5061253Slq150181 case 37: /* white (bright white) foreground */ 507*7688SAaron.Zang@Sun.COM tem->tvs_fg_color = param - 30; 5081253Slq150181 break; 5091253Slq150181 5101253Slq150181 case 40: /* black (grey) background */ 5111253Slq150181 case 41: /* red (light red) background */ 5121253Slq150181 case 42: /* green (light green) background */ 5131253Slq150181 case 43: /* brown (yellow) background */ 5141253Slq150181 case 44: /* blue (light blue) background */ 5151253Slq150181 case 45: /* magenta (light magenta) background */ 5161253Slq150181 case 46: /* cyan (light cyan) background */ 5171253Slq150181 case 47: /* white (bright white) background */ 518*7688SAaron.Zang@Sun.COM tem->tvs_bg_color = param - 40; 5191253Slq150181 break; 5201253Slq150181 5211253Slq150181 default: 5221253Slq150181 break; 5231253Slq150181 } 5241253Slq150181 count++; 5251253Slq150181 curparam--; 5261253Slq150181 5271253Slq150181 } while (curparam > 0); 5281253Slq150181 } 5291253Slq150181 5301253Slq150181 /* 5311253Slq150181 * perform the appropriate action for the escape sequence 5321253Slq150181 * 5331253Slq150181 * General rule: This code does not validate the arguments passed. 5341253Slq150181 * It assumes that the next lower level will do so. 5351253Slq150181 */ 5361253Slq150181 static void 537*7688SAaron.Zang@Sun.COM tem_safe_chkparam( 538*7688SAaron.Zang@Sun.COM struct tem_vt_state *tem, 5391253Slq150181 uchar_t ch, 5401253Slq150181 cred_t *credp, 5411253Slq150181 enum called_from called_from) 5421253Slq150181 { 5431253Slq150181 int i; 5441253Slq150181 int row; 5451253Slq150181 int col; 5461253Slq150181 5471253Slq150181 ASSERT((called_from == CALLED_FROM_STANDALONE) || 548*7688SAaron.Zang@Sun.COM MUTEX_HELD(&tem->tvs_lock)); 5491253Slq150181 550*7688SAaron.Zang@Sun.COM row = tem->tvs_c_cursor.row; 551*7688SAaron.Zang@Sun.COM col = tem->tvs_c_cursor.col; 5521253Slq150181 5531253Slq150181 switch (ch) { 5541253Slq150181 5551253Slq150181 case 'm': /* select terminal graphics mode */ 556*7688SAaron.Zang@Sun.COM tem_safe_send_data(tem, credp, called_from); 557*7688SAaron.Zang@Sun.COM tem_safe_selgraph(tem); 5581253Slq150181 break; 5591253Slq150181 5601253Slq150181 case '@': /* insert char */ 561*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 562*7688SAaron.Zang@Sun.COM tem_safe_shift(tem, tem->tvs_params[0], TEM_SHIFT_RIGHT, 5631253Slq150181 credp, called_from); 5641253Slq150181 break; 5651253Slq150181 5661253Slq150181 case 'A': /* cursor up */ 567*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 568*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, row - tem->tvs_params[0], col, 5691253Slq150181 credp, called_from); 5701253Slq150181 break; 5711253Slq150181 5721253Slq150181 case 'd': /* VPA - vertical position absolute */ 573*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 574*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, tem->tvs_params[0] - 1, col, 5751253Slq150181 credp, called_from); 5761253Slq150181 break; 5771253Slq150181 5781253Slq150181 case 'e': /* VPR - vertical position relative */ 5791253Slq150181 case 'B': /* cursor down */ 580*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 581*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, row + tem->tvs_params[0], col, 5821253Slq150181 credp, called_from); 5831253Slq150181 break; 5841253Slq150181 5851253Slq150181 case 'a': /* HPR - horizontal position relative */ 5861253Slq150181 case 'C': /* cursor right */ 587*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 588*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, row, col + tem->tvs_params[0], 5891253Slq150181 credp, called_from); 5901253Slq150181 break; 5911253Slq150181 5921253Slq150181 case '`': /* HPA - horizontal position absolute */ 593*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 594*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, row, tem->tvs_params[0] - 1, 5951253Slq150181 credp, called_from); 5961253Slq150181 break; 5971253Slq150181 5981253Slq150181 case 'D': /* cursor left */ 599*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 600*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, row, col - tem->tvs_params[0], 6011253Slq150181 credp, called_from); 6021253Slq150181 break; 6031253Slq150181 6041253Slq150181 case 'E': /* CNL cursor next line */ 605*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 606*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, row + tem->tvs_params[0], 0, 6071253Slq150181 credp, called_from); 6081253Slq150181 break; 6091253Slq150181 6101253Slq150181 case 'F': /* CPL cursor previous line */ 611*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 612*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, row - tem->tvs_params[0], 0, 6131253Slq150181 credp, called_from); 6141253Slq150181 break; 6151253Slq150181 6161253Slq150181 case 'G': /* cursor horizontal position */ 617*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 618*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, row, tem->tvs_params[0] - 1, 6191253Slq150181 credp, called_from); 6201253Slq150181 break; 6211253Slq150181 6221253Slq150181 case 'g': /* clear tabs */ 623*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 0); 624*7688SAaron.Zang@Sun.COM tem_safe_clear_tabs(tem, tem->tvs_params[0]); 6251253Slq150181 break; 6261253Slq150181 6271253Slq150181 case 'f': /* HVP Horizontal and Vertical Position */ 6281253Slq150181 case 'H': /* CUP position cursor */ 629*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 2, 1); 630*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, 631*7688SAaron.Zang@Sun.COM tem->tvs_params[0] - 1, 632*7688SAaron.Zang@Sun.COM tem->tvs_params[1] - 1, 6331253Slq150181 credp, called_from); 6341253Slq150181 break; 6351253Slq150181 6361253Slq150181 case 'I': /* CHT - Cursor Horizontal Tab */ 6371253Slq150181 /* Not implemented */ 6381253Slq150181 break; 6391253Slq150181 6401253Slq150181 case 'J': /* ED - Erase in Display */ 641*7688SAaron.Zang@Sun.COM tem_safe_send_data(tem, credp, called_from); 642*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 0); 643*7688SAaron.Zang@Sun.COM switch (tem->tvs_params[0]) { 6441253Slq150181 case 0: 6451253Slq150181 /* erase cursor to end of screen */ 6461253Slq150181 /* FIRST erase cursor to end of line */ 647*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(tem, 648*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.width - 649*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col, 650*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 651*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col, credp, called_from); 6521253Slq150181 6531253Slq150181 /* THEN erase lines below the cursor */ 654*7688SAaron.Zang@Sun.COM for (row = tem->tvs_c_cursor.row + 1; 655*7688SAaron.Zang@Sun.COM row < tems.ts_c_dimension.height; 6565129Smarx row++) { 657*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(tem, 658*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.width, 6591253Slq150181 row, 0, credp, called_from); 6601253Slq150181 } 6611253Slq150181 break; 6621253Slq150181 6631253Slq150181 case 1: 6641253Slq150181 /* erase beginning of screen to cursor */ 6651253Slq150181 /* FIRST erase lines above the cursor */ 6661253Slq150181 for (row = 0; 667*7688SAaron.Zang@Sun.COM row < tem->tvs_c_cursor.row; 6685129Smarx row++) { 669*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(tem, 670*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.width, 6711253Slq150181 row, 0, credp, called_from); 6721253Slq150181 } 6731253Slq150181 /* THEN erase beginning of line to cursor */ 674*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(tem, 675*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col + 1, 676*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 6775129Smarx 0, credp, called_from); 6781253Slq150181 break; 6791253Slq150181 6801253Slq150181 case 2: 6811253Slq150181 /* erase whole screen */ 6821253Slq150181 for (row = 0; 683*7688SAaron.Zang@Sun.COM row < tems.ts_c_dimension.height; 6841253Slq150181 row++) { 685*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(tem, 686*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.width, 6875129Smarx row, 0, credp, called_from); 6881253Slq150181 } 6891253Slq150181 break; 6901253Slq150181 } 6911253Slq150181 break; 6921253Slq150181 6931253Slq150181 case 'K': /* EL - Erase in Line */ 694*7688SAaron.Zang@Sun.COM tem_safe_send_data(tem, credp, called_from); 695*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 0); 696*7688SAaron.Zang@Sun.COM switch (tem->tvs_params[0]) { 6971253Slq150181 case 0: 6981253Slq150181 /* erase cursor to end of line */ 699*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(tem, 700*7688SAaron.Zang@Sun.COM (tems.ts_c_dimension.width - 701*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col), 702*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 703*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col, 7041253Slq150181 credp, called_from); 7051253Slq150181 break; 7061253Slq150181 7071253Slq150181 case 1: 7081253Slq150181 /* erase beginning of line to cursor */ 709*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(tem, 710*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col + 1, 711*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 7121253Slq150181 0, credp, called_from); 7131253Slq150181 break; 7141253Slq150181 7151253Slq150181 case 2: 7161253Slq150181 /* erase whole line */ 717*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(tem, 718*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.width, 719*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 7201253Slq150181 0, credp, called_from); 7211253Slq150181 break; 7221253Slq150181 } 7231253Slq150181 break; 7241253Slq150181 7251253Slq150181 case 'L': /* insert line */ 726*7688SAaron.Zang@Sun.COM tem_safe_send_data(tem, credp, called_from); 727*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 728*7688SAaron.Zang@Sun.COM tem_safe_scroll(tem, 729*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 730*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.height - 1, 731*7688SAaron.Zang@Sun.COM tem->tvs_params[0], TEM_SCROLL_DOWN, 7325129Smarx credp, called_from); 7331253Slq150181 break; 7341253Slq150181 7351253Slq150181 case 'M': /* delete line */ 736*7688SAaron.Zang@Sun.COM tem_safe_send_data(tem, credp, called_from); 737*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 738*7688SAaron.Zang@Sun.COM tem_safe_scroll(tem, 739*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 740*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.height - 1, 741*7688SAaron.Zang@Sun.COM tem->tvs_params[0], TEM_SCROLL_UP, 7425129Smarx credp, called_from); 7431253Slq150181 break; 7441253Slq150181 7451253Slq150181 case 'P': /* DCH - delete char */ 746*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 747*7688SAaron.Zang@Sun.COM tem_safe_shift(tem, tem->tvs_params[0], TEM_SHIFT_LEFT, 7481253Slq150181 credp, called_from); 7491253Slq150181 break; 7501253Slq150181 7511253Slq150181 case 'S': /* scroll up */ 752*7688SAaron.Zang@Sun.COM tem_safe_send_data(tem, credp, called_from); 753*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 754*7688SAaron.Zang@Sun.COM tem_safe_scroll(tem, 0, 755*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.height - 1, 756*7688SAaron.Zang@Sun.COM tem->tvs_params[0], TEM_SCROLL_UP, 7575129Smarx credp, called_from); 7581253Slq150181 break; 7591253Slq150181 7601253Slq150181 case 'T': /* scroll down */ 761*7688SAaron.Zang@Sun.COM tem_safe_send_data(tem, credp, called_from); 762*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 763*7688SAaron.Zang@Sun.COM tem_safe_scroll(tem, 0, 764*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.height - 1, 765*7688SAaron.Zang@Sun.COM tem->tvs_params[0], TEM_SCROLL_DOWN, 7665129Smarx credp, called_from); 7671253Slq150181 break; 7681253Slq150181 7691253Slq150181 case 'X': /* erase char */ 770*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 771*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(tem, 772*7688SAaron.Zang@Sun.COM tem->tvs_params[0], 773*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 774*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col, 7755129Smarx credp, called_from); 7761253Slq150181 break; 7771253Slq150181 7781253Slq150181 case 'Z': /* cursor backward tabulation */ 779*7688SAaron.Zang@Sun.COM tem_safe_setparam(tem, 1, 1); 7801253Slq150181 7811253Slq150181 /* 7821253Slq150181 * Rule exception - We do sanity checking here. 7831253Slq150181 * 7841253Slq150181 * Restrict the count to a sane value to keep from 7851253Slq150181 * looping for a long time. There can't be more than one 7861253Slq150181 * tab stop per column, so use that as a limit. 7871253Slq150181 */ 788*7688SAaron.Zang@Sun.COM if (tem->tvs_params[0] > tems.ts_c_dimension.width) 789*7688SAaron.Zang@Sun.COM tem->tvs_params[0] = tems.ts_c_dimension.width; 7901253Slq150181 791*7688SAaron.Zang@Sun.COM for (i = 0; i < tem->tvs_params[0]; i++) 792*7688SAaron.Zang@Sun.COM tem_safe_back_tab(tem, credp, called_from); 7931253Slq150181 break; 7941253Slq150181 } 795*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_START; 7961253Slq150181 } 7971253Slq150181 7981253Slq150181 7991253Slq150181 /* 8001253Slq150181 * Gather the parameters of an ANSI escape sequence 8011253Slq150181 */ 8021253Slq150181 static void 803*7688SAaron.Zang@Sun.COM tem_safe_getparams(struct tem_vt_state *tem, uchar_t ch, 8041253Slq150181 cred_t *credp, enum called_from called_from) 8051253Slq150181 { 8061253Slq150181 ASSERT((called_from == CALLED_FROM_STANDALONE) || 807*7688SAaron.Zang@Sun.COM MUTEX_HELD(&tem->tvs_lock)); 8081253Slq150181 8092216Slt200341 if (ch >= '0' && ch <= '9') { 810*7688SAaron.Zang@Sun.COM tem->tvs_paramval = ((tem->tvs_paramval * 10) + (ch - '0')); 811*7688SAaron.Zang@Sun.COM tem->tvs_gotparam = B_TRUE; /* Remember got parameter */ 8121253Slq150181 return; /* Return immediately */ 813*7688SAaron.Zang@Sun.COM } else if (tem->tvs_state == A_STATE_CSI_EQUAL || 814*7688SAaron.Zang@Sun.COM tem->tvs_state == A_STATE_CSI_QMARK) { 815*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_START; 8162216Slt200341 } else { 817*7688SAaron.Zang@Sun.COM if (tem->tvs_curparam < TEM_MAXPARAMS) { 818*7688SAaron.Zang@Sun.COM if (tem->tvs_gotparam) { 8192216Slt200341 /* get the parameter value */ 820*7688SAaron.Zang@Sun.COM tem->tvs_params[tem->tvs_curparam] = 821*7688SAaron.Zang@Sun.COM tem->tvs_paramval; 8221253Slq150181 } 823*7688SAaron.Zang@Sun.COM tem->tvs_curparam++; 8241253Slq150181 } 8251253Slq150181 8261253Slq150181 if (ch == ';') { 8271253Slq150181 /* Restart parameter search */ 828*7688SAaron.Zang@Sun.COM tem->tvs_gotparam = B_FALSE; 829*7688SAaron.Zang@Sun.COM tem->tvs_paramval = 0; /* No parame value yet */ 8302216Slt200341 } else { 8311253Slq150181 /* Handle escape sequence */ 832*7688SAaron.Zang@Sun.COM tem_safe_chkparam(tem, ch, credp, called_from); 8332216Slt200341 } 8341253Slq150181 } 8351253Slq150181 } 8361253Slq150181 8371253Slq150181 /* 8381253Slq150181 * Add character to internal buffer. 8391253Slq150181 * When its full, send it to the next layer. 8401253Slq150181 */ 8411253Slq150181 8421253Slq150181 static void 843*7688SAaron.Zang@Sun.COM tem_safe_outch(struct tem_vt_state *tem, uchar_t ch, 8441253Slq150181 cred_t *credp, enum called_from called_from) 8451253Slq150181 { 8461253Slq150181 847*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 848*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 8491253Slq150181 8501253Slq150181 /* buffer up the character until later */ 8511253Slq150181 852*7688SAaron.Zang@Sun.COM tem->tvs_outbuf[tem->tvs_outindex++] = ch; 853*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col++; 854*7688SAaron.Zang@Sun.COM if (tem->tvs_c_cursor.col >= tems.ts_c_dimension.width) { 855*7688SAaron.Zang@Sun.COM tem_safe_send_data(tem, credp, called_from); 856*7688SAaron.Zang@Sun.COM tem_safe_new_line(tem, credp, called_from); 8571253Slq150181 } 8581253Slq150181 } 8591253Slq150181 8601253Slq150181 static void 861*7688SAaron.Zang@Sun.COM tem_safe_new_line(struct tem_vt_state *tem, 8621253Slq150181 cred_t *credp, enum called_from called_from) 8631253Slq150181 { 864*7688SAaron.Zang@Sun.COM tem_safe_cr(tem); 865*7688SAaron.Zang@Sun.COM tem_safe_lf(tem, credp, called_from); 8661253Slq150181 } 8671253Slq150181 8681253Slq150181 static void 869*7688SAaron.Zang@Sun.COM tem_safe_cr(struct tem_vt_state *tem) 8701253Slq150181 { 871*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col = 0; 872*7688SAaron.Zang@Sun.COM tem_safe_align_cursor(tem); 8731253Slq150181 } 8741253Slq150181 8751253Slq150181 static void 876*7688SAaron.Zang@Sun.COM tem_safe_lf(struct tem_vt_state *tem, 8771253Slq150181 cred_t *credp, enum called_from called_from) 8781253Slq150181 { 8791253Slq150181 int row; 8801253Slq150181 8811253Slq150181 ASSERT((called_from == CALLED_FROM_STANDALONE) || 882*7688SAaron.Zang@Sun.COM MUTEX_HELD(&tem->tvs_lock)); 8831253Slq150181 8841253Slq150181 /* 8851253Slq150181 * Sanity checking notes: 8861253Slq150181 * . a_nscroll was validated when it was set. 887*7688SAaron.Zang@Sun.COM * . Regardless of that, tem_safe_scroll and tem_safe_mv_cursor 888*7688SAaron.Zang@Sun.COM * will prevent anything bad from happening. 8891253Slq150181 */ 890*7688SAaron.Zang@Sun.COM row = tem->tvs_c_cursor.row + 1; 8911253Slq150181 892*7688SAaron.Zang@Sun.COM if (row >= tems.ts_c_dimension.height) { 893*7688SAaron.Zang@Sun.COM if (tem->tvs_nscroll != 0) { 894*7688SAaron.Zang@Sun.COM tem_safe_scroll(tem, 0, 895*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.height - 1, 896*7688SAaron.Zang@Sun.COM tem->tvs_nscroll, TEM_SCROLL_UP, 8971253Slq150181 credp, called_from); 898*7688SAaron.Zang@Sun.COM row = tems.ts_c_dimension.height - 899*7688SAaron.Zang@Sun.COM tem->tvs_nscroll; 9001253Slq150181 } else { /* no scroll */ 9011253Slq150181 /* 9021253Slq150181 * implement Esc[#r when # is zero. This means no 9031253Slq150181 * scroll but just return cursor to top of screen, 9041253Slq150181 * do not clear screen. 9051253Slq150181 */ 9061253Slq150181 row = 0; 9071253Slq150181 } 9081253Slq150181 } 9091253Slq150181 910*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, row, tem->tvs_c_cursor.col, 9115129Smarx credp, called_from); 9121253Slq150181 913*7688SAaron.Zang@Sun.COM if (tem->tvs_nscroll == 0) { 9141253Slq150181 /* erase rest of cursor line */ 915*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(tem, 916*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.width - 917*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col, 918*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 919*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col, 9201253Slq150181 credp, called_from); 9211253Slq150181 9221253Slq150181 } 9231253Slq150181 924*7688SAaron.Zang@Sun.COM tem_safe_align_cursor(tem); 9251253Slq150181 } 9261253Slq150181 9271253Slq150181 static void 928*7688SAaron.Zang@Sun.COM tem_safe_send_data(struct tem_vt_state *tem, cred_t *credp, 9291253Slq150181 enum called_from called_from) 9301253Slq150181 { 9311253Slq150181 text_color_t fg_color; 9321253Slq150181 text_color_t bg_color; 9331253Slq150181 9341253Slq150181 ASSERT((called_from == CALLED_FROM_STANDALONE) || 935*7688SAaron.Zang@Sun.COM MUTEX_HELD(&tem->tvs_lock)); 9361253Slq150181 937*7688SAaron.Zang@Sun.COM if (tem->tvs_outindex == 0) { 938*7688SAaron.Zang@Sun.COM tem_safe_align_cursor(tem); 939*7688SAaron.Zang@Sun.COM return; 940*7688SAaron.Zang@Sun.COM } 9411253Slq150181 942*7688SAaron.Zang@Sun.COM tem_safe_get_color(tem, &fg_color, &bg_color, TEM_ATTR_REVERSE); 943*7688SAaron.Zang@Sun.COM tem_safe_virtual_display(tem, 944*7688SAaron.Zang@Sun.COM tem->tvs_outbuf, tem->tvs_outindex, 945*7688SAaron.Zang@Sun.COM tem->tvs_s_cursor.row, tem->tvs_s_cursor.col, 946*7688SAaron.Zang@Sun.COM fg_color, bg_color); 9471253Slq150181 948*7688SAaron.Zang@Sun.COM if (tem->tvs_isactive) { 9491253Slq150181 /* 9501253Slq150181 * Call the primitive to render this data. 9511253Slq150181 */ 952*7688SAaron.Zang@Sun.COM tem_safe_callback_display(tem, 953*7688SAaron.Zang@Sun.COM tem->tvs_outbuf, tem->tvs_outindex, 954*7688SAaron.Zang@Sun.COM tem->tvs_s_cursor.row, tem->tvs_s_cursor.col, 9555129Smarx fg_color, bg_color, 9565129Smarx credp, called_from); 9571253Slq150181 } 958*7688SAaron.Zang@Sun.COM 959*7688SAaron.Zang@Sun.COM tem->tvs_outindex = 0; 960*7688SAaron.Zang@Sun.COM 961*7688SAaron.Zang@Sun.COM tem_safe_align_cursor(tem); 9621253Slq150181 } 9631253Slq150181 9641253Slq150181 9651253Slq150181 /* 9661253Slq150181 * We have just done something to the current output point. Reset the start 9671253Slq150181 * point for the buffered data in a_outbuf. There shouldn't be any data 9681253Slq150181 * buffered yet. 9691253Slq150181 */ 970*7688SAaron.Zang@Sun.COM static void 971*7688SAaron.Zang@Sun.COM tem_safe_align_cursor(struct tem_vt_state *tem) 9721253Slq150181 { 973*7688SAaron.Zang@Sun.COM tem->tvs_s_cursor.row = tem->tvs_c_cursor.row; 974*7688SAaron.Zang@Sun.COM tem->tvs_s_cursor.col = tem->tvs_c_cursor.col; 9751253Slq150181 } 9761253Slq150181 9771253Slq150181 /* 9781253Slq150181 * State machine parser based on the current state and character input 9791253Slq150181 * major terminations are to control character or normal character 9801253Slq150181 */ 9811253Slq150181 9821253Slq150181 static void 983*7688SAaron.Zang@Sun.COM tem_safe_parse(struct tem_vt_state *tem, uchar_t ch, 9841253Slq150181 cred_t *credp, enum called_from called_from) 9851253Slq150181 { 9861253Slq150181 int i; 9871253Slq150181 9881253Slq150181 ASSERT((called_from == CALLED_FROM_STANDALONE) || 989*7688SAaron.Zang@Sun.COM MUTEX_HELD(&tem->tvs_lock)); 9901253Slq150181 991*7688SAaron.Zang@Sun.COM if (tem->tvs_state == A_STATE_START) { /* Normal state? */ 992*7688SAaron.Zang@Sun.COM if (ch == A_CSI || ch == A_ESC || ch < ' ') { 993*7688SAaron.Zang@Sun.COM /* Control */ 994*7688SAaron.Zang@Sun.COM tem_safe_control(tem, ch, credp, called_from); 995*7688SAaron.Zang@Sun.COM } else { 9961253Slq150181 /* Display */ 997*7688SAaron.Zang@Sun.COM tem_safe_outch(tem, ch, credp, called_from); 998*7688SAaron.Zang@Sun.COM } 9991253Slq150181 return; 10001253Slq150181 } 10011253Slq150181 10021253Slq150181 /* In <ESC> sequence */ 1003*7688SAaron.Zang@Sun.COM if (tem->tvs_state != A_STATE_ESC) { /* Need to get parameters? */ 1004*7688SAaron.Zang@Sun.COM if (tem->tvs_state != A_STATE_CSI) { 1005*7688SAaron.Zang@Sun.COM tem_safe_getparams(tem, ch, credp, called_from); 10061253Slq150181 return; 10071253Slq150181 } 10081253Slq150181 10091253Slq150181 switch (ch) { 10101253Slq150181 case '?': 1011*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_CSI_QMARK; 10121253Slq150181 return; 10131253Slq150181 case '=': 1014*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_CSI_EQUAL; 10151253Slq150181 return; 10161253Slq150181 case 's': 10171253Slq150181 /* 10181253Slq150181 * As defined below, this sequence 10191253Slq150181 * saves the cursor. However, Sun 10201253Slq150181 * defines ESC[s as reset. We resolved 10211253Slq150181 * the conflict by selecting reset as it 10221253Slq150181 * is exported in the termcap file for 10231253Slq150181 * sun-mon, while the "save cursor" 10241253Slq150181 * definition does not exist anywhere in 10251253Slq150181 * /etc/termcap. 10261253Slq150181 * However, having no coherent 10271253Slq150181 * definition of reset, we have not 10281253Slq150181 * implemented it. 10291253Slq150181 */ 10301253Slq150181 10311253Slq150181 /* 10321253Slq150181 * Original code 1033*7688SAaron.Zang@Sun.COM * tem->tvs_r_cursor.row = tem->tvs_c_cursor.row; 1034*7688SAaron.Zang@Sun.COM * tem->tvs_r_cursor.col = tem->tvs_c_cursor.col; 1035*7688SAaron.Zang@Sun.COM * tem->tvs_state = A_STATE_START; 10361253Slq150181 */ 10371253Slq150181 1038*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_START; 10391253Slq150181 return; 10401253Slq150181 case 'u': 1041*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, tem->tvs_r_cursor.row, 1042*7688SAaron.Zang@Sun.COM tem->tvs_r_cursor.col, credp, called_from); 1043*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_START; 10441253Slq150181 return; 10451253Slq150181 case 'p': /* sunbow */ 1046*7688SAaron.Zang@Sun.COM tem_safe_send_data(tem, credp, called_from); 10471253Slq150181 /* 10481253Slq150181 * Don't set anything if we are 10491253Slq150181 * already as we want to be. 10501253Slq150181 */ 1051*7688SAaron.Zang@Sun.COM if (tem->tvs_flags & TEM_ATTR_SCREEN_REVERSE) { 1052*7688SAaron.Zang@Sun.COM tem->tvs_flags &= ~TEM_ATTR_SCREEN_REVERSE; 10531253Slq150181 /* 10541253Slq150181 * If we have switched the characters to be the 10551253Slq150181 * inverse from the screen, then switch them as 10561253Slq150181 * well to keep them the inverse of the screen. 10571253Slq150181 */ 1058*7688SAaron.Zang@Sun.COM if (tem->tvs_flags & TEM_ATTR_REVERSE) 1059*7688SAaron.Zang@Sun.COM tem->tvs_flags &= ~TEM_ATTR_REVERSE; 1060*7688SAaron.Zang@Sun.COM else 1061*7688SAaron.Zang@Sun.COM tem->tvs_flags |= TEM_ATTR_REVERSE; 10621253Slq150181 } 1063*7688SAaron.Zang@Sun.COM tem_safe_cls(tem, credp, called_from); 1064*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_START; 10651253Slq150181 return; 10661253Slq150181 case 'q': /* sunwob */ 1067*7688SAaron.Zang@Sun.COM tem_safe_send_data(tem, credp, called_from); 10681253Slq150181 /* 10691253Slq150181 * Don't set anything if we are 10701253Slq150181 * already where as we want to be. 10711253Slq150181 */ 1072*7688SAaron.Zang@Sun.COM if (!(tem->tvs_flags & TEM_ATTR_SCREEN_REVERSE)) { 1073*7688SAaron.Zang@Sun.COM tem->tvs_flags |= TEM_ATTR_SCREEN_REVERSE; 10741253Slq150181 /* 10751253Slq150181 * If we have switched the characters to be the 10761253Slq150181 * inverse from the screen, then switch them as 10771253Slq150181 * well to keep them the inverse of the screen. 10781253Slq150181 */ 1079*7688SAaron.Zang@Sun.COM if (!(tem->tvs_flags & TEM_ATTR_REVERSE)) 1080*7688SAaron.Zang@Sun.COM tem->tvs_flags |= TEM_ATTR_REVERSE; 1081*7688SAaron.Zang@Sun.COM else 1082*7688SAaron.Zang@Sun.COM tem->tvs_flags &= ~TEM_ATTR_REVERSE; 10831253Slq150181 } 10841253Slq150181 1085*7688SAaron.Zang@Sun.COM tem_safe_cls(tem, credp, called_from); 1086*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_START; 10871253Slq150181 return; 10881253Slq150181 case 'r': /* sunscrl */ 10891253Slq150181 /* 10901253Slq150181 * Rule exception: check for validity here. 10911253Slq150181 */ 1092*7688SAaron.Zang@Sun.COM tem->tvs_nscroll = tem->tvs_paramval; 1093*7688SAaron.Zang@Sun.COM if (tem->tvs_nscroll > tems.ts_c_dimension.height) 1094*7688SAaron.Zang@Sun.COM tem->tvs_nscroll = tems.ts_c_dimension.height; 1095*7688SAaron.Zang@Sun.COM if (tem->tvs_nscroll < 0) 1096*7688SAaron.Zang@Sun.COM tem->tvs_nscroll = 1; 1097*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_START; 10981253Slq150181 return; 10991253Slq150181 default: 1100*7688SAaron.Zang@Sun.COM tem_safe_getparams(tem, ch, credp, called_from); 11011253Slq150181 return; 11021253Slq150181 } 11031253Slq150181 } 11041253Slq150181 11051253Slq150181 /* Previous char was <ESC> */ 11061253Slq150181 if (ch == '[') { 1107*7688SAaron.Zang@Sun.COM tem->tvs_curparam = 0; 1108*7688SAaron.Zang@Sun.COM tem->tvs_paramval = 0; 1109*7688SAaron.Zang@Sun.COM tem->tvs_gotparam = B_FALSE; 11101253Slq150181 /* clear the parameters */ 11111253Slq150181 for (i = 0; i < TEM_MAXPARAMS; i++) 1112*7688SAaron.Zang@Sun.COM tem->tvs_params[i] = -1; 1113*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_CSI; 11141253Slq150181 } else if (ch == 'Q') { /* <ESC>Q ? */ 1115*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_START; 11161253Slq150181 } else if (ch == 'C') { /* <ESC>C ? */ 1117*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_START; 11181253Slq150181 } else { 1119*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_START; 1120*7688SAaron.Zang@Sun.COM if (ch == 'c') { 11211253Slq150181 /* ESC c resets display */ 1122*7688SAaron.Zang@Sun.COM tem_safe_reset_display(tem, credp, called_from, 1123*7688SAaron.Zang@Sun.COM B_TRUE, B_TRUE); 1124*7688SAaron.Zang@Sun.COM } else if (ch == 'H') { 11251253Slq150181 /* ESC H sets a tab */ 1126*7688SAaron.Zang@Sun.COM tem_safe_set_tab(tem); 1127*7688SAaron.Zang@Sun.COM } else if (ch == '7') { 11281253Slq150181 /* ESC 7 Save Cursor position */ 1129*7688SAaron.Zang@Sun.COM tem->tvs_r_cursor.row = tem->tvs_c_cursor.row; 1130*7688SAaron.Zang@Sun.COM tem->tvs_r_cursor.col = tem->tvs_c_cursor.col; 1131*7688SAaron.Zang@Sun.COM } else if (ch == '8') { 11321253Slq150181 /* ESC 8 Restore Cursor position */ 1133*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, tem->tvs_r_cursor.row, 1134*7688SAaron.Zang@Sun.COM tem->tvs_r_cursor.col, credp, called_from); 11351253Slq150181 /* check for control chars */ 1136*7688SAaron.Zang@Sun.COM } else if (ch < ' ') { 1137*7688SAaron.Zang@Sun.COM tem_safe_control(tem, ch, credp, called_from); 1138*7688SAaron.Zang@Sun.COM } else { 1139*7688SAaron.Zang@Sun.COM tem_safe_outch(tem, ch, credp, called_from); 1140*7688SAaron.Zang@Sun.COM } 11411253Slq150181 } 11421253Slq150181 } 11431253Slq150181 11441253Slq150181 /* ARGSUSED */ 11451253Slq150181 static void 1146*7688SAaron.Zang@Sun.COM tem_safe_bell(struct tem_vt_state *tem, enum called_from called_from) 11471253Slq150181 { 11481253Slq150181 if (called_from == CALLED_FROM_STANDALONE) 11495129Smarx (void) beep_polled(BEEP_CONSOLE); 11501253Slq150181 else 11515129Smarx (void) beep(BEEP_CONSOLE); 11521253Slq150181 } 11531253Slq150181 11541253Slq150181 11551253Slq150181 static void 1156*7688SAaron.Zang@Sun.COM tem_safe_scroll(struct tem_vt_state *tem, int start, int end, int count, 1157*7688SAaron.Zang@Sun.COM int direction, 11581253Slq150181 cred_t *credp, enum called_from called_from) 11591253Slq150181 { 11601253Slq150181 int row; 11611253Slq150181 int lines_affected; 11621253Slq150181 1163*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1164*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 11651253Slq150181 11661253Slq150181 lines_affected = end - start + 1; 11671253Slq150181 if (count > lines_affected) 11681253Slq150181 count = lines_affected; 11691253Slq150181 if (count <= 0) 11701253Slq150181 return; 11711253Slq150181 11721253Slq150181 switch (direction) { 11731253Slq150181 case TEM_SCROLL_UP: 11741253Slq150181 if (count < lines_affected) { 1175*7688SAaron.Zang@Sun.COM tem_safe_copy_area(tem, 0, start + count, 1176*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.width - 1, end, 11771253Slq150181 0, start, credp, called_from); 11781253Slq150181 } 11791253Slq150181 for (row = (end - count) + 1; row <= end; row++) { 1180*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(tem, tems.ts_c_dimension.width, 11811253Slq150181 row, 0, credp, called_from); 11821253Slq150181 } 11831253Slq150181 break; 11841253Slq150181 11851253Slq150181 case TEM_SCROLL_DOWN: 11861253Slq150181 if (count < lines_affected) { 1187*7688SAaron.Zang@Sun.COM tem_safe_copy_area(tem, 0, start, 1188*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.width - 1, 11891253Slq150181 end - count, 0, start + count, 11901253Slq150181 credp, called_from); 11911253Slq150181 } 11921253Slq150181 for (row = start; row < start + count; row++) { 1193*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(tem, tems.ts_c_dimension.width, 11941253Slq150181 row, 0, credp, called_from); 11951253Slq150181 } 11961253Slq150181 break; 11971253Slq150181 } 11981253Slq150181 } 11991253Slq150181 12001253Slq150181 static void 1201*7688SAaron.Zang@Sun.COM tem_safe_copy_area(struct tem_vt_state *tem, 12021253Slq150181 screen_pos_t s_col, screen_pos_t s_row, 12031253Slq150181 screen_pos_t e_col, screen_pos_t e_row, 12041253Slq150181 screen_pos_t t_col, screen_pos_t t_row, 12051253Slq150181 cred_t *credp, enum called_from called_from) 12061253Slq150181 { 12071253Slq150181 int rows; 12081253Slq150181 int cols; 12091253Slq150181 1210*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1211*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 12121253Slq150181 12131253Slq150181 if (s_col < 0 || s_row < 0 || 12141253Slq150181 e_col < 0 || e_row < 0 || 12151253Slq150181 t_col < 0 || t_row < 0 || 1216*7688SAaron.Zang@Sun.COM s_col >= tems.ts_c_dimension.width || 1217*7688SAaron.Zang@Sun.COM e_col >= tems.ts_c_dimension.width || 1218*7688SAaron.Zang@Sun.COM t_col >= tems.ts_c_dimension.width || 1219*7688SAaron.Zang@Sun.COM s_row >= tems.ts_c_dimension.height || 1220*7688SAaron.Zang@Sun.COM e_row >= tems.ts_c_dimension.height || 1221*7688SAaron.Zang@Sun.COM t_row >= tems.ts_c_dimension.height) 12221253Slq150181 return; 12231253Slq150181 12241253Slq150181 if (s_row > e_row || s_col > e_col) 12251253Slq150181 return; 12261253Slq150181 12271253Slq150181 rows = e_row - s_row + 1; 12281253Slq150181 cols = e_col - s_col + 1; 1229*7688SAaron.Zang@Sun.COM if (t_row + rows > tems.ts_c_dimension.height || 1230*7688SAaron.Zang@Sun.COM t_col + cols > tems.ts_c_dimension.width) 12311253Slq150181 return; 12321253Slq150181 1233*7688SAaron.Zang@Sun.COM tem_safe_virtual_copy(tem, 1234*7688SAaron.Zang@Sun.COM s_col, s_row, 1235*7688SAaron.Zang@Sun.COM e_col, e_row, 1236*7688SAaron.Zang@Sun.COM t_col, t_row); 1237*7688SAaron.Zang@Sun.COM 1238*7688SAaron.Zang@Sun.COM if (!tem->tvs_isactive) 1239*7688SAaron.Zang@Sun.COM return; 1240*7688SAaron.Zang@Sun.COM 1241*7688SAaron.Zang@Sun.COM tem_safe_callback_copy(tem, s_col, s_row, 12425129Smarx e_col, e_row, t_col, t_row, credp, called_from); 12431253Slq150181 } 12441253Slq150181 12451253Slq150181 static void 1246*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(struct tem_vt_state *tem, int count, screen_pos_t row, 12471253Slq150181 screen_pos_t col, cred_t *credp, enum called_from called_from) 12481253Slq150181 { 1249*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1250*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 12511253Slq150181 1252*7688SAaron.Zang@Sun.COM if (row < 0 || row >= tems.ts_c_dimension.height || 1253*7688SAaron.Zang@Sun.COM col < 0 || col >= tems.ts_c_dimension.width || 12541253Slq150181 count < 0) 12551253Slq150181 return; 12561253Slq150181 12571253Slq150181 /* 12581253Slq150181 * Note that very large values of "count" could cause col+count 12591253Slq150181 * to overflow, so we check "count" independently. 12601253Slq150181 */ 1261*7688SAaron.Zang@Sun.COM if (count > tems.ts_c_dimension.width || 1262*7688SAaron.Zang@Sun.COM col + count > tems.ts_c_dimension.width) 1263*7688SAaron.Zang@Sun.COM count = tems.ts_c_dimension.width - col; 12641253Slq150181 1265*7688SAaron.Zang@Sun.COM tem_safe_virtual_cls(tem, count, row, col); 1266*7688SAaron.Zang@Sun.COM 1267*7688SAaron.Zang@Sun.COM if (!tem->tvs_isactive) 1268*7688SAaron.Zang@Sun.COM return; 1269*7688SAaron.Zang@Sun.COM 1270*7688SAaron.Zang@Sun.COM tem_safe_callback_cls(tem, count, row, col, credp, called_from); 12711253Slq150181 } 12721253Slq150181 1273*7688SAaron.Zang@Sun.COM /*ARGSUSED*/ 12741253Slq150181 void 1275*7688SAaron.Zang@Sun.COM tem_safe_text_display(struct tem_vt_state *tem, uchar_t *string, 12761253Slq150181 int count, screen_pos_t row, screen_pos_t col, 12771253Slq150181 text_color_t fg_color, text_color_t bg_color, 12781253Slq150181 cred_t *credp, enum called_from called_from) 12791253Slq150181 { 12801253Slq150181 struct vis_consdisplay da; 12811253Slq150181 1282*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1283*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 1284*7688SAaron.Zang@Sun.COM 12851253Slq150181 da.data = string; 1286*7688SAaron.Zang@Sun.COM da.width = (screen_size_t)count; 12871253Slq150181 da.row = row; 12881253Slq150181 da.col = col; 12891253Slq150181 12901253Slq150181 da.fg_color = fg_color; 12911253Slq150181 da.bg_color = bg_color; 12921253Slq150181 1293*7688SAaron.Zang@Sun.COM tems_safe_display(&da, credp, called_from); 12941253Slq150181 } 12951253Slq150181 12961253Slq150181 /* 12971253Slq150181 * This function is used to blit a rectangular color image, 12981253Slq150181 * unperturbed on the underlying framebuffer, to render 12991253Slq150181 * icons and pictures. The data is a pixel pattern that 13001253Slq150181 * fills a rectangle bounded to the width and height parameters. 13011253Slq150181 * The color pixel data must to be pre-adjusted by the caller 13021253Slq150181 * for the current video depth. 13031253Slq150181 * 13041253Slq150181 * This function is unused now. 13051253Slq150181 */ 1306*7688SAaron.Zang@Sun.COM /*ARGSUSED*/ 1307*7688SAaron.Zang@Sun.COM static void 1308*7688SAaron.Zang@Sun.COM tem_safe_image_display(struct tem_vt_state *tem, uchar_t *image, 13091253Slq150181 int height, int width, screen_pos_t row, screen_pos_t col, 13101253Slq150181 cred_t *credp, enum called_from called_from) 13111253Slq150181 { 13121253Slq150181 struct vis_consdisplay da; 13131253Slq150181 1314*7688SAaron.Zang@Sun.COM mutex_enter(&tems.ts_lock); 1315*7688SAaron.Zang@Sun.COM mutex_enter(&tem->tvs_lock); 1316*7688SAaron.Zang@Sun.COM 13171253Slq150181 da.data = image; 1318*7688SAaron.Zang@Sun.COM da.width = (screen_size_t)width; 1319*7688SAaron.Zang@Sun.COM da.height = (screen_size_t)height; 13201253Slq150181 da.row = row; 13211253Slq150181 da.col = col; 13221253Slq150181 1323*7688SAaron.Zang@Sun.COM tems_safe_display(&da, credp, called_from); 1324*7688SAaron.Zang@Sun.COM 1325*7688SAaron.Zang@Sun.COM mutex_exit(&tem->tvs_lock); 1326*7688SAaron.Zang@Sun.COM mutex_exit(&tems.ts_lock); 13271253Slq150181 } 13281253Slq150181 13291253Slq150181 1330*7688SAaron.Zang@Sun.COM /*ARGSUSED*/ 13311253Slq150181 void 1332*7688SAaron.Zang@Sun.COM tem_safe_text_copy(struct tem_vt_state *tem, 13331253Slq150181 screen_pos_t s_col, screen_pos_t s_row, 13341253Slq150181 screen_pos_t e_col, screen_pos_t e_row, 13351253Slq150181 screen_pos_t t_col, screen_pos_t t_row, 13361253Slq150181 cred_t *credp, enum called_from called_from) 13371253Slq150181 { 13381253Slq150181 struct vis_conscopy da; 13391253Slq150181 1340*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1341*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 1342*7688SAaron.Zang@Sun.COM 13431253Slq150181 da.s_row = s_row; 13441253Slq150181 da.s_col = s_col; 13451253Slq150181 da.e_row = e_row; 13461253Slq150181 da.e_col = e_col; 13471253Slq150181 da.t_row = t_row; 13481253Slq150181 da.t_col = t_col; 13491253Slq150181 1350*7688SAaron.Zang@Sun.COM tems_safe_copy(&da, credp, called_from); 13511253Slq150181 } 13521253Slq150181 13531253Slq150181 void 1354*7688SAaron.Zang@Sun.COM tem_safe_text_cls(struct tem_vt_state *tem, 13551253Slq150181 int count, screen_pos_t row, screen_pos_t col, cred_t *credp, 13561253Slq150181 enum called_from called_from) 13571253Slq150181 { 13581253Slq150181 struct vis_consdisplay da; 13591253Slq150181 1360*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1361*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 1362*7688SAaron.Zang@Sun.COM 1363*7688SAaron.Zang@Sun.COM da.data = tems.ts_blank_line; 1364*7688SAaron.Zang@Sun.COM da.width = (screen_size_t)count; 13651253Slq150181 da.row = row; 13661253Slq150181 da.col = col; 13671253Slq150181 1368*7688SAaron.Zang@Sun.COM tem_safe_get_color(tem, &da.fg_color, &da.bg_color, 1369*7688SAaron.Zang@Sun.COM TEM_ATTR_SCREEN_REVERSE); 1370*7688SAaron.Zang@Sun.COM tems_safe_display(&da, credp, called_from); 13711253Slq150181 } 13721253Slq150181 13731253Slq150181 13741253Slq150181 13751253Slq150181 void 1376*7688SAaron.Zang@Sun.COM tem_safe_pix_display(struct tem_vt_state *tem, 13771253Slq150181 uchar_t *string, int count, 13781253Slq150181 screen_pos_t row, screen_pos_t col, 13791253Slq150181 text_color_t fg_color, text_color_t bg_color, 13801253Slq150181 cred_t *credp, enum called_from called_from) 13811253Slq150181 { 13821253Slq150181 struct vis_consdisplay da; 13831253Slq150181 int i; 1384*7688SAaron.Zang@Sun.COM 1385*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1386*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 1387*7688SAaron.Zang@Sun.COM 1388*7688SAaron.Zang@Sun.COM da.data = (uchar_t *)tem->tvs_pix_data; 1389*7688SAaron.Zang@Sun.COM da.width = tems.ts_font.width; 1390*7688SAaron.Zang@Sun.COM da.height = tems.ts_font.height; 1391*7688SAaron.Zang@Sun.COM da.row = (row * da.height) + tems.ts_p_offset.y; 1392*7688SAaron.Zang@Sun.COM da.col = (col * da.width) + tems.ts_p_offset.x; 13931253Slq150181 13941253Slq150181 for (i = 0; i < count; i++) { 1395*7688SAaron.Zang@Sun.COM tem_safe_callback_bit2pix(tem, string[i], fg_color, bg_color); 1396*7688SAaron.Zang@Sun.COM tems_safe_display(&da, credp, called_from); 13971253Slq150181 da.col += da.width; 13981253Slq150181 } 13991253Slq150181 } 14001253Slq150181 14011253Slq150181 void 1402*7688SAaron.Zang@Sun.COM tem_safe_pix_copy(struct tem_vt_state *tem, 14031253Slq150181 screen_pos_t s_col, screen_pos_t s_row, 14041253Slq150181 screen_pos_t e_col, screen_pos_t e_row, 14051253Slq150181 screen_pos_t t_col, screen_pos_t t_row, 14061253Slq150181 cred_t *credp, 14071253Slq150181 enum called_from called_from) 14081253Slq150181 { 14091253Slq150181 struct vis_conscopy ma; 14101253Slq150181 static boolean_t need_clear = B_TRUE; 14111253Slq150181 1412*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1413*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 14141253Slq150181 1415*7688SAaron.Zang@Sun.COM if (need_clear && tem->tvs_first_line > 0) { 14161253Slq150181 /* 14171253Slq150181 * Clear OBP output above our kernel console term 14181253Slq150181 * when our kernel console term begins to scroll up, 14191253Slq150181 * we hope it is user friendly. 1420*7688SAaron.Zang@Sun.COM * (Also see comments on tem_safe_pix_clear_prom_output) 14211253Slq150181 * 14221253Slq150181 * This is only one time call. 14231253Slq150181 */ 1424*7688SAaron.Zang@Sun.COM tem_safe_pix_clear_prom_output(tem, credp, called_from); 14251253Slq150181 } 14261253Slq150181 need_clear = B_FALSE; 14271253Slq150181 1428*7688SAaron.Zang@Sun.COM ma.s_row = s_row * tems.ts_font.height + tems.ts_p_offset.y; 1429*7688SAaron.Zang@Sun.COM ma.e_row = (e_row + 1) * tems.ts_font.height + tems.ts_p_offset.y - 1; 1430*7688SAaron.Zang@Sun.COM ma.t_row = t_row * tems.ts_font.height + tems.ts_p_offset.y; 14311253Slq150181 14321253Slq150181 /* 14331253Slq150181 * Check if we're in process of clearing OBP's columns area, 14341253Slq150181 * which only happens when term scrolls up a whole line. 14351253Slq150181 */ 1436*7688SAaron.Zang@Sun.COM if (tem->tvs_first_line > 0 && t_row < s_row && t_col == 0 && 1437*7688SAaron.Zang@Sun.COM e_col == tems.ts_c_dimension.width - 1) { 14381253Slq150181 /* 14391253Slq150181 * We need to clear OBP's columns area outside our kernel 14401253Slq150181 * console term. So that we set ma.e_col to entire row here. 14411253Slq150181 */ 1442*7688SAaron.Zang@Sun.COM ma.s_col = s_col * tems.ts_font.width; 1443*7688SAaron.Zang@Sun.COM ma.e_col = tems.ts_p_dimension.width - 1; 14441253Slq150181 1445*7688SAaron.Zang@Sun.COM ma.t_col = t_col * tems.ts_font.width; 14461253Slq150181 } else { 1447*7688SAaron.Zang@Sun.COM ma.s_col = s_col * tems.ts_font.width + tems.ts_p_offset.x; 1448*7688SAaron.Zang@Sun.COM ma.e_col = (e_col + 1) * tems.ts_font.width + 1449*7688SAaron.Zang@Sun.COM tems.ts_p_offset.x - 1; 1450*7688SAaron.Zang@Sun.COM ma.t_col = t_col * tems.ts_font.width + tems.ts_p_offset.x; 14511253Slq150181 } 14521253Slq150181 1453*7688SAaron.Zang@Sun.COM tems_safe_copy(&ma, credp, called_from); 14541253Slq150181 1455*7688SAaron.Zang@Sun.COM if (tem->tvs_first_line > 0 && t_row < s_row) { 14561253Slq150181 /* We have scrolled up (s_row - t_row) rows. */ 1457*7688SAaron.Zang@Sun.COM tem->tvs_first_line -= (s_row - t_row); 1458*7688SAaron.Zang@Sun.COM if (tem->tvs_first_line <= 0) { 14591253Slq150181 /* All OBP rows have been cleared. */ 1460*7688SAaron.Zang@Sun.COM tem->tvs_first_line = 0; 14611253Slq150181 } 14621253Slq150181 } 14631253Slq150181 14641253Slq150181 } 14651253Slq150181 1466*7688SAaron.Zang@Sun.COM void 1467*7688SAaron.Zang@Sun.COM tem_safe_pix_bit2pix(struct tem_vt_state *tem, unsigned char c, 1468*7688SAaron.Zang@Sun.COM unsigned char fg, unsigned char bg) 1469*7688SAaron.Zang@Sun.COM { 1470*7688SAaron.Zang@Sun.COM void (*fp)(struct tem_vt_state *, unsigned char, 1471*7688SAaron.Zang@Sun.COM unsigned char, unsigned char); 1472*7688SAaron.Zang@Sun.COM 1473*7688SAaron.Zang@Sun.COM switch (tems.ts_pdepth) { 1474*7688SAaron.Zang@Sun.COM case 4: 1475*7688SAaron.Zang@Sun.COM fp = bit_to_pix4; 1476*7688SAaron.Zang@Sun.COM break; 1477*7688SAaron.Zang@Sun.COM case 8: 1478*7688SAaron.Zang@Sun.COM fp = bit_to_pix8; 1479*7688SAaron.Zang@Sun.COM break; 1480*7688SAaron.Zang@Sun.COM case 24: 1481*7688SAaron.Zang@Sun.COM case 32: 1482*7688SAaron.Zang@Sun.COM fp = bit_to_pix24; 1483*7688SAaron.Zang@Sun.COM } 1484*7688SAaron.Zang@Sun.COM 1485*7688SAaron.Zang@Sun.COM fp(tem, c, fg, bg); 1486*7688SAaron.Zang@Sun.COM } 1487*7688SAaron.Zang@Sun.COM 1488*7688SAaron.Zang@Sun.COM 14891253Slq150181 /* 14901253Slq150181 * This function only clears count of columns in one row 14911253Slq150181 */ 14921253Slq150181 void 1493*7688SAaron.Zang@Sun.COM tem_safe_pix_cls(struct tem_vt_state *tem, int count, 14941253Slq150181 screen_pos_t row, screen_pos_t col, cred_t *credp, 14951253Slq150181 enum called_from called_from) 14961253Slq150181 { 1497*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1498*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 14991253Slq150181 1500*7688SAaron.Zang@Sun.COM tem_safe_pix_cls_range(tem, row, 1, tems.ts_p_offset.y, 1501*7688SAaron.Zang@Sun.COM col, count, tems.ts_p_offset.x, B_FALSE, credp, called_from); 15021253Slq150181 } 15031253Slq150181 15041253Slq150181 /* 15051253Slq150181 * This function clears OBP output above our kernel console term area 15061253Slq150181 * because OBP's term may have a bigger terminal window than that of 15071253Slq150181 * our kernel console term. So we need to clear OBP output garbage outside 15081253Slq150181 * of our kernel console term at a proper time, which is when the first 15091253Slq150181 * row output of our kernel console term scrolls at the first screen line. 15101253Slq150181 * 15111253Slq150181 * _________________________________ 15121253Slq150181 * | _____________________ | ---> OBP's bigger term window 15131253Slq150181 * | | | | 15141253Slq150181 * |___| | | 15151253Slq150181 * | | | | | 15161253Slq150181 * | | | | | 15171253Slq150181 * |_|_|___________________|_______| 15181253Slq150181 * | | | ---> first line 15191253Slq150181 * | |___________________|---> our kernel console term window 15201253Slq150181 * | 15211253Slq150181 * |---> columns area to be cleared 15221253Slq150181 * 15231253Slq150181 * This function only takes care of the output above our kernel console term, 15241253Slq150181 * and tem_prom_scroll_up takes care of columns area outside of our kernel 15251253Slq150181 * console term. 15261253Slq150181 */ 15271253Slq150181 static void 1528*7688SAaron.Zang@Sun.COM tem_safe_pix_clear_prom_output(struct tem_vt_state *tem, cred_t *credp, 15291253Slq150181 enum called_from called_from) 15301253Slq150181 { 15311253Slq150181 int nrows, ncols, width, height; 15321253Slq150181 1533*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1534*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 15351253Slq150181 1536*7688SAaron.Zang@Sun.COM width = tems.ts_font.width; 1537*7688SAaron.Zang@Sun.COM height = tems.ts_font.height; 15381253Slq150181 1539*7688SAaron.Zang@Sun.COM nrows = (tems.ts_p_offset.y + (height - 1))/ height; 1540*7688SAaron.Zang@Sun.COM ncols = (tems.ts_p_dimension.width + (width - 1))/ width; 15411253Slq150181 1542*7688SAaron.Zang@Sun.COM tem_safe_pix_cls_range(tem, 0, nrows, 0, 0, ncols, 0, 15431253Slq150181 B_FALSE, credp, called_from); 15441253Slq150181 } 15451253Slq150181 15461253Slq150181 /* 1547*7688SAaron.Zang@Sun.COM * clear the whole screen for pixel mode, just clear the 1548*7688SAaron.Zang@Sun.COM * physical screen. 15491253Slq150181 */ 1550*7688SAaron.Zang@Sun.COM void 1551*7688SAaron.Zang@Sun.COM tem_safe_pix_clear_entire_screen(struct tem_vt_state *tem, cred_t *credp, 15521253Slq150181 enum called_from called_from) 15531253Slq150181 { 15541253Slq150181 int nrows, ncols, width, height; 15551253Slq150181 1556*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1557*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 15581253Slq150181 1559*7688SAaron.Zang@Sun.COM width = tems.ts_font.width; 1560*7688SAaron.Zang@Sun.COM height = tems.ts_font.height; 15611253Slq150181 1562*7688SAaron.Zang@Sun.COM nrows = (tems.ts_p_dimension.height + (height - 1))/ height; 1563*7688SAaron.Zang@Sun.COM ncols = (tems.ts_p_dimension.width + (width - 1))/ width; 15641253Slq150181 1565*7688SAaron.Zang@Sun.COM tem_safe_pix_cls_range(tem, 0, nrows, 0, 0, ncols, 0, 15661253Slq150181 B_FALSE, credp, called_from); 15671253Slq150181 15681253Slq150181 /* 15691253Slq150181 * Since the whole screen is cleared, we don't need 15701253Slq150181 * to clear OBP output later. 15711253Slq150181 */ 1572*7688SAaron.Zang@Sun.COM if (tem->tvs_first_line > 0) 1573*7688SAaron.Zang@Sun.COM tem->tvs_first_line = 0; 15741253Slq150181 } 15751253Slq150181 15761253Slq150181 /* 1577*7688SAaron.Zang@Sun.COM * clear the whole screen, including the virtual screen buffer, 1578*7688SAaron.Zang@Sun.COM * and reset the cursor to start point. 15791253Slq150181 */ 15801253Slq150181 static void 1581*7688SAaron.Zang@Sun.COM tem_safe_cls(struct tem_vt_state *tem, 15821253Slq150181 cred_t *credp, enum called_from called_from) 15831253Slq150181 { 15841253Slq150181 int row; 15851253Slq150181 1586*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1587*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 15881253Slq150181 1589*7688SAaron.Zang@Sun.COM if (tems.ts_display_mode == VIS_TEXT) { 1590*7688SAaron.Zang@Sun.COM for (row = 0; row < tems.ts_c_dimension.height; row++) { 1591*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(tem, tems.ts_c_dimension.width, 15925129Smarx row, 0, credp, called_from); 15931253Slq150181 } 1594*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row = 0; 1595*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col = 0; 1596*7688SAaron.Zang@Sun.COM tem_safe_align_cursor(tem); 15971253Slq150181 return; 15981253Slq150181 } 15991253Slq150181 1600*7688SAaron.Zang@Sun.COM ASSERT(tems.ts_display_mode == VIS_PIXEL); 16011253Slq150181 1602*7688SAaron.Zang@Sun.COM for (row = 0; row < tems.ts_c_dimension.height; row++) { 1603*7688SAaron.Zang@Sun.COM tem_safe_virtual_cls(tem, tems.ts_c_dimension.width, row, 0); 1604*7688SAaron.Zang@Sun.COM } 1605*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row = 0; 1606*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col = 0; 1607*7688SAaron.Zang@Sun.COM tem_safe_align_cursor(tem); 1608*7688SAaron.Zang@Sun.COM 1609*7688SAaron.Zang@Sun.COM if (!tem->tvs_isactive) 1610*7688SAaron.Zang@Sun.COM return; 1611*7688SAaron.Zang@Sun.COM 1612*7688SAaron.Zang@Sun.COM tem_safe_pix_clear_entire_screen(tem, credp, called_from); 16131253Slq150181 } 16141253Slq150181 16151253Slq150181 static void 1616*7688SAaron.Zang@Sun.COM tem_safe_back_tab(struct tem_vt_state *tem, 16171253Slq150181 cred_t *credp, enum called_from called_from) 16181253Slq150181 { 16191253Slq150181 int i; 16201253Slq150181 screen_pos_t tabstop; 16211253Slq150181 1622*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1623*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 16241253Slq150181 16251253Slq150181 tabstop = 0; 16261253Slq150181 1627*7688SAaron.Zang@Sun.COM for (i = tem->tvs_ntabs - 1; i >= 0; i--) { 1628*7688SAaron.Zang@Sun.COM if (tem->tvs_tabs[i] < tem->tvs_c_cursor.col) { 1629*7688SAaron.Zang@Sun.COM tabstop = tem->tvs_tabs[i]; 16301253Slq150181 break; 16311253Slq150181 } 16321253Slq150181 } 16331253Slq150181 1634*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, tem->tvs_c_cursor.row, 16355129Smarx tabstop, credp, called_from); 16361253Slq150181 } 16371253Slq150181 16381253Slq150181 static void 1639*7688SAaron.Zang@Sun.COM tem_safe_tab(struct tem_vt_state *tem, 16401253Slq150181 cred_t *credp, enum called_from called_from) 16411253Slq150181 { 16421253Slq150181 int i; 16431253Slq150181 screen_pos_t tabstop; 16441253Slq150181 1645*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1646*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 16471253Slq150181 1648*7688SAaron.Zang@Sun.COM tabstop = tems.ts_c_dimension.width - 1; 16491253Slq150181 1650*7688SAaron.Zang@Sun.COM for (i = 0; i < tem->tvs_ntabs; i++) { 1651*7688SAaron.Zang@Sun.COM if (tem->tvs_tabs[i] > tem->tvs_c_cursor.col) { 1652*7688SAaron.Zang@Sun.COM tabstop = tem->tvs_tabs[i]; 16531253Slq150181 break; 16541253Slq150181 } 16551253Slq150181 } 16561253Slq150181 1657*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(tem, tem->tvs_c_cursor.row, 16581253Slq150181 tabstop, credp, called_from); 16591253Slq150181 } 16601253Slq150181 16611253Slq150181 static void 1662*7688SAaron.Zang@Sun.COM tem_safe_set_tab(struct tem_vt_state *tem) 16631253Slq150181 { 16641253Slq150181 int i; 16651253Slq150181 int j; 16661253Slq150181 1667*7688SAaron.Zang@Sun.COM if (tem->tvs_ntabs == TEM_MAXTAB) 16681253Slq150181 return; 1669*7688SAaron.Zang@Sun.COM if (tem->tvs_ntabs == 0 || 1670*7688SAaron.Zang@Sun.COM tem->tvs_tabs[tem->tvs_ntabs] < tem->tvs_c_cursor.col) { 1671*7688SAaron.Zang@Sun.COM tem->tvs_tabs[tem->tvs_ntabs++] = tem->tvs_c_cursor.col; 1672*7688SAaron.Zang@Sun.COM return; 16731253Slq150181 } 1674*7688SAaron.Zang@Sun.COM for (i = 0; i < tem->tvs_ntabs; i++) { 1675*7688SAaron.Zang@Sun.COM if (tem->tvs_tabs[i] == tem->tvs_c_cursor.col) 16761253Slq150181 return; 1677*7688SAaron.Zang@Sun.COM if (tem->tvs_tabs[i] > tem->tvs_c_cursor.col) { 1678*7688SAaron.Zang@Sun.COM for (j = tem->tvs_ntabs - 1; j >= i; j--) 1679*7688SAaron.Zang@Sun.COM tem->tvs_tabs[j+ 1] = tem->tvs_tabs[j]; 1680*7688SAaron.Zang@Sun.COM tem->tvs_tabs[i] = tem->tvs_c_cursor.col; 1681*7688SAaron.Zang@Sun.COM tem->tvs_ntabs++; 16821253Slq150181 return; 16831253Slq150181 } 16841253Slq150181 } 16851253Slq150181 } 16861253Slq150181 16871253Slq150181 static void 1688*7688SAaron.Zang@Sun.COM tem_safe_clear_tabs(struct tem_vt_state *tem, int action) 16891253Slq150181 { 16901253Slq150181 int i; 16911253Slq150181 int j; 16921253Slq150181 16931253Slq150181 switch (action) { 16941253Slq150181 case 3: /* clear all tabs */ 1695*7688SAaron.Zang@Sun.COM tem->tvs_ntabs = 0; 16961253Slq150181 break; 16971253Slq150181 case 0: /* clr tab at cursor */ 16981253Slq150181 1699*7688SAaron.Zang@Sun.COM for (i = 0; i < tem->tvs_ntabs; i++) { 1700*7688SAaron.Zang@Sun.COM if (tem->tvs_tabs[i] == tem->tvs_c_cursor.col) { 1701*7688SAaron.Zang@Sun.COM tem->tvs_ntabs--; 1702*7688SAaron.Zang@Sun.COM for (j = i; j < tem->tvs_ntabs; j++) 1703*7688SAaron.Zang@Sun.COM tem->tvs_tabs[j] = tem->tvs_tabs[j + 1]; 17041253Slq150181 return; 17051253Slq150181 } 17061253Slq150181 } 17071253Slq150181 break; 17081253Slq150181 } 17091253Slq150181 } 17101253Slq150181 17111253Slq150181 static void 1712*7688SAaron.Zang@Sun.COM tem_safe_mv_cursor(struct tem_vt_state *tem, int row, int col, 17131253Slq150181 cred_t *credp, enum called_from called_from) 17141253Slq150181 { 1715*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1716*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 17171253Slq150181 17181253Slq150181 /* 17191253Slq150181 * Sanity check and bounds enforcement. Out of bounds requests are 17201253Slq150181 * clipped to the screen boundaries. This seems to be what SPARC 17211253Slq150181 * does. 17221253Slq150181 */ 17231253Slq150181 if (row < 0) 17241253Slq150181 row = 0; 1725*7688SAaron.Zang@Sun.COM if (row >= tems.ts_c_dimension.height) 1726*7688SAaron.Zang@Sun.COM row = tems.ts_c_dimension.height - 1; 17271253Slq150181 if (col < 0) 17281253Slq150181 col = 0; 1729*7688SAaron.Zang@Sun.COM if (col >= tems.ts_c_dimension.width) 1730*7688SAaron.Zang@Sun.COM col = tems.ts_c_dimension.width - 1; 17311253Slq150181 1732*7688SAaron.Zang@Sun.COM tem_safe_send_data(tem, credp, called_from); 1733*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row = (screen_pos_t)row; 1734*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col = (screen_pos_t)col; 1735*7688SAaron.Zang@Sun.COM tem_safe_align_cursor(tem); 17361253Slq150181 } 17371253Slq150181 17381253Slq150181 /* ARGSUSED */ 17391253Slq150181 void 1740*7688SAaron.Zang@Sun.COM tem_safe_reset_emulator(struct tem_vt_state *tem, 17413994Slq150181 cred_t *credp, enum called_from called_from, 1742*7688SAaron.Zang@Sun.COM boolean_t init_color) 17431253Slq150181 { 17441253Slq150181 int j; 17451253Slq150181 1746*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1747*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 17481253Slq150181 1749*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row = 0; 1750*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col = 0; 1751*7688SAaron.Zang@Sun.COM tem->tvs_r_cursor.row = 0; 1752*7688SAaron.Zang@Sun.COM tem->tvs_r_cursor.col = 0; 1753*7688SAaron.Zang@Sun.COM tem->tvs_s_cursor.row = 0; 1754*7688SAaron.Zang@Sun.COM tem->tvs_s_cursor.col = 0; 1755*7688SAaron.Zang@Sun.COM tem->tvs_outindex = 0; 1756*7688SAaron.Zang@Sun.COM tem->tvs_state = A_STATE_START; 1757*7688SAaron.Zang@Sun.COM tem->tvs_gotparam = B_FALSE; 1758*7688SAaron.Zang@Sun.COM tem->tvs_curparam = 0; 1759*7688SAaron.Zang@Sun.COM tem->tvs_paramval = 0; 1760*7688SAaron.Zang@Sun.COM tem->tvs_nscroll = 1; 17613994Slq150181 1762*7688SAaron.Zang@Sun.COM if (init_color) { 17633994Slq150181 /* use initial settings */ 1764*7688SAaron.Zang@Sun.COM tem->tvs_fg_color = tems.ts_init_color.fg_color; 1765*7688SAaron.Zang@Sun.COM tem->tvs_bg_color = tems.ts_init_color.bg_color; 1766*7688SAaron.Zang@Sun.COM tem->tvs_flags = tems.ts_init_color.a_flags; 17673994Slq150181 } 17681253Slq150181 17691253Slq150181 /* 17701253Slq150181 * set up the initial tab stops 17711253Slq150181 */ 1772*7688SAaron.Zang@Sun.COM tem->tvs_ntabs = 0; 1773*7688SAaron.Zang@Sun.COM for (j = 8; j < tems.ts_c_dimension.width; j += 8) 1774*7688SAaron.Zang@Sun.COM tem->tvs_tabs[tem->tvs_ntabs++] = (screen_pos_t)j; 17751253Slq150181 17761253Slq150181 for (j = 0; j < TEM_MAXPARAMS; j++) 1777*7688SAaron.Zang@Sun.COM tem->tvs_params[j] = 0; 17781253Slq150181 } 17791253Slq150181 17801253Slq150181 void 1781*7688SAaron.Zang@Sun.COM tem_safe_reset_display(struct tem_vt_state *tem, 1782*7688SAaron.Zang@Sun.COM cred_t *credp, enum called_from called_from, 1783*7688SAaron.Zang@Sun.COM boolean_t clear_txt, boolean_t init_color) 17841253Slq150181 { 1785*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1786*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 17871253Slq150181 1788*7688SAaron.Zang@Sun.COM tem_safe_reset_emulator(tem, credp, called_from, init_color); 17891253Slq150181 17901253Slq150181 if (clear_txt) { 1791*7688SAaron.Zang@Sun.COM if (tem->tvs_isactive) 1792*7688SAaron.Zang@Sun.COM tem_safe_callback_cursor(tem, 1793*7688SAaron.Zang@Sun.COM VIS_HIDE_CURSOR, credp, called_from); 17941253Slq150181 1795*7688SAaron.Zang@Sun.COM tem_safe_cls(tem, credp, called_from); 1796*7688SAaron.Zang@Sun.COM 1797*7688SAaron.Zang@Sun.COM if (tem->tvs_isactive) 1798*7688SAaron.Zang@Sun.COM tem_safe_callback_cursor(tem, 1799*7688SAaron.Zang@Sun.COM VIS_DISPLAY_CURSOR, credp, called_from); 18001253Slq150181 } 18011253Slq150181 } 18021253Slq150181 18031253Slq150181 static void 1804*7688SAaron.Zang@Sun.COM tem_safe_shift( 1805*7688SAaron.Zang@Sun.COM struct tem_vt_state *tem, 18061253Slq150181 int count, 18071253Slq150181 int direction, 18081253Slq150181 cred_t *credp, 18091253Slq150181 enum called_from called_from) 18101253Slq150181 { 18111253Slq150181 int rest_of_line; 18121253Slq150181 1813*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1814*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 18151253Slq150181 1816*7688SAaron.Zang@Sun.COM rest_of_line = tems.ts_c_dimension.width - tem->tvs_c_cursor.col; 18171253Slq150181 if (count > rest_of_line) 18181253Slq150181 count = rest_of_line; 18191253Slq150181 18201253Slq150181 if (count <= 0) 18211253Slq150181 return; 18221253Slq150181 18231253Slq150181 switch (direction) { 18241253Slq150181 case TEM_SHIFT_LEFT: 18251253Slq150181 if (count < rest_of_line) { 1826*7688SAaron.Zang@Sun.COM tem_safe_copy_area(tem, 1827*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col + count, 1828*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 1829*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.width - 1, 1830*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 1831*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col, 1832*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 18335129Smarx credp, called_from); 18341253Slq150181 } 18351253Slq150181 1836*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(tem, count, tem->tvs_c_cursor.row, 1837*7688SAaron.Zang@Sun.COM (tems.ts_c_dimension.width - count), credp, 18385129Smarx called_from); 18391253Slq150181 break; 18401253Slq150181 case TEM_SHIFT_RIGHT: 18411253Slq150181 if (count < rest_of_line) { 1842*7688SAaron.Zang@Sun.COM tem_safe_copy_area(tem, 1843*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col, 1844*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 1845*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.width - count - 1, 1846*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 1847*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col + count, 1848*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row, 18495129Smarx credp, called_from); 18501253Slq150181 } 18511253Slq150181 1852*7688SAaron.Zang@Sun.COM tem_safe_clear_chars(tem, count, tem->tvs_c_cursor.row, 1853*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col, credp, called_from); 18541253Slq150181 break; 18551253Slq150181 } 18561253Slq150181 } 18571253Slq150181 18581253Slq150181 void 1859*7688SAaron.Zang@Sun.COM tem_safe_text_cursor(struct tem_vt_state *tem, short action, 18601253Slq150181 cred_t *credp, enum called_from called_from) 18611253Slq150181 { 18621253Slq150181 struct vis_conscursor ca; 18631253Slq150181 1864*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1865*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 18661253Slq150181 1867*7688SAaron.Zang@Sun.COM ca.row = tem->tvs_c_cursor.row; 1868*7688SAaron.Zang@Sun.COM ca.col = tem->tvs_c_cursor.col; 18691253Slq150181 ca.action = action; 18701253Slq150181 1871*7688SAaron.Zang@Sun.COM tems_safe_cursor(&ca, credp, called_from); 18721253Slq150181 18731253Slq150181 if (action == VIS_GET_CURSOR) { 1874*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.row = ca.row; 1875*7688SAaron.Zang@Sun.COM tem->tvs_c_cursor.col = ca.col; 18761253Slq150181 } 18771253Slq150181 } 18781253Slq150181 18791253Slq150181 void 1880*7688SAaron.Zang@Sun.COM tem_safe_pix_cursor(struct tem_vt_state *tem, short action, 18811253Slq150181 cred_t *credp, enum called_from called_from) 18821253Slq150181 { 18831253Slq150181 struct vis_conscursor ca; 18841253Slq150181 1885*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 1886*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 18871253Slq150181 1888*7688SAaron.Zang@Sun.COM ca.row = tem->tvs_c_cursor.row * tems.ts_font.height + 1889*7688SAaron.Zang@Sun.COM tems.ts_p_offset.y; 1890*7688SAaron.Zang@Sun.COM ca.col = tem->tvs_c_cursor.col * tems.ts_font.width + 1891*7688SAaron.Zang@Sun.COM tems.ts_p_offset.x; 1892*7688SAaron.Zang@Sun.COM ca.width = tems.ts_font.width; 1893*7688SAaron.Zang@Sun.COM ca.height = tems.ts_font.height; 1894*7688SAaron.Zang@Sun.COM if (tems.ts_pdepth == 8 || tems.ts_pdepth == 4) { 1895*7688SAaron.Zang@Sun.COM if (tem->tvs_flags & TEM_ATTR_REVERSE) { 18961253Slq150181 ca.fg_color.mono = TEM_TEXT_WHITE; 18971253Slq150181 ca.bg_color.mono = TEM_TEXT_BLACK; 18981253Slq150181 } else { 18991253Slq150181 ca.fg_color.mono = TEM_TEXT_BLACK; 19001253Slq150181 ca.bg_color.mono = TEM_TEXT_WHITE; 19011253Slq150181 } 1902*7688SAaron.Zang@Sun.COM } else if (tems.ts_pdepth == 24 || tems.ts_pdepth == 32) { 1903*7688SAaron.Zang@Sun.COM if (tem->tvs_flags & TEM_ATTR_REVERSE) { 19041253Slq150181 ca.fg_color.twentyfour[0] = TEM_TEXT_WHITE24_RED; 19051253Slq150181 ca.fg_color.twentyfour[1] = TEM_TEXT_WHITE24_GREEN; 19061253Slq150181 ca.fg_color.twentyfour[2] = TEM_TEXT_WHITE24_BLUE; 19071253Slq150181 19081253Slq150181 ca.bg_color.twentyfour[0] = TEM_TEXT_BLACK24_RED; 19091253Slq150181 ca.bg_color.twentyfour[1] = TEM_TEXT_BLACK24_GREEN; 19101253Slq150181 ca.bg_color.twentyfour[2] = TEM_TEXT_BLACK24_BLUE; 19111253Slq150181 } else { 19121253Slq150181 ca.fg_color.twentyfour[0] = TEM_TEXT_BLACK24_RED; 19131253Slq150181 ca.fg_color.twentyfour[1] = TEM_TEXT_BLACK24_GREEN; 19141253Slq150181 ca.fg_color.twentyfour[2] = TEM_TEXT_BLACK24_BLUE; 19151253Slq150181 19161253Slq150181 ca.bg_color.twentyfour[0] = TEM_TEXT_WHITE24_RED; 19171253Slq150181 ca.bg_color.twentyfour[1] = TEM_TEXT_WHITE24_GREEN; 19181253Slq150181 ca.bg_color.twentyfour[2] = TEM_TEXT_WHITE24_BLUE; 19191253Slq150181 } 19201253Slq150181 } 19211253Slq150181 19221253Slq150181 ca.action = action; 19231253Slq150181 1924*7688SAaron.Zang@Sun.COM tems_safe_cursor(&ca, credp, called_from); 19251253Slq150181 } 19261253Slq150181 19271253Slq150181 #define BORDER_PIXELS 10 19281253Slq150181 void 19291253Slq150181 set_font(struct font *f, short *rows, short *cols, short height, short width) 19301253Slq150181 { 19311253Slq150181 bitmap_data_t *font_selected = NULL; 19321253Slq150181 struct fontlist *fl; 19331253Slq150181 19341253Slq150181 /* 19351253Slq150181 * Find best font for these dimensions, or use default 19361253Slq150181 * 19371253Slq150181 * A 1 pixel border is the absolute minimum we could have 19381253Slq150181 * as a border around the text window (BORDER_PIXELS = 2), 19391253Slq150181 * however a slightly larger border not only looks better 19401253Slq150181 * but for the fonts currently statically built into the 19411253Slq150181 * emulator causes much better font selection for the 19421253Slq150181 * normal range of screen resolutions. 19431253Slq150181 */ 19441253Slq150181 for (fl = fonts; fl->data; fl++) { 19451253Slq150181 if ((((*rows * fl->data->height) + BORDER_PIXELS) <= height) && 19461253Slq150181 (((*cols * fl->data->width) + BORDER_PIXELS) <= width)) { 19471253Slq150181 font_selected = fl->data; 19481253Slq150181 break; 19491253Slq150181 } 19501253Slq150181 } 19511253Slq150181 /* 19521253Slq150181 * The minus 2 is to make sure we have at least a 1 pixel 19531253Slq150181 * boarder around the entire screen. 19541253Slq150181 */ 19551253Slq150181 if (font_selected == NULL) { 19561253Slq150181 if (((*rows * DEFAULT_FONT_DATA.height) > height) || 19571253Slq150181 ((*cols * DEFAULT_FONT_DATA.width) > width)) { 19581253Slq150181 *rows = (height - 2) / DEFAULT_FONT_DATA.height; 19591253Slq150181 *cols = (width - 2) / DEFAULT_FONT_DATA.width; 19601253Slq150181 } 19611253Slq150181 font_selected = &DEFAULT_FONT_DATA; 19621253Slq150181 } 19631253Slq150181 19641253Slq150181 f->width = font_selected->width; 19651253Slq150181 f->height = font_selected->height; 19661253Slq150181 bcopy((caddr_t)font_selected->encoding, (caddr_t)f->char_ptr, 19675129Smarx sizeof (f->char_ptr)); 19681253Slq150181 f->image_data = font_selected->image; 19691253Slq150181 19701253Slq150181 } 19711253Slq150181 19721253Slq150181 /* 19731253Slq150181 * bit_to_pix4 is for 4-bit frame buffers. It will write one output byte 19741253Slq150181 * for each 2 bits of input bitmap. It inverts the input bits before 19751253Slq150181 * doing the output translation, for reverse video. 19761253Slq150181 * 19771253Slq150181 * Assuming foreground is 0001 and background is 0000... 19781253Slq150181 * An input data byte of 0x53 will output the bit pattern 19791253Slq150181 * 00000001 00000001 00000000 00010001. 19801253Slq150181 */ 19811253Slq150181 1982*7688SAaron.Zang@Sun.COM static void 19831253Slq150181 bit_to_pix4( 1984*7688SAaron.Zang@Sun.COM struct tem_vt_state *tem, 19851253Slq150181 uchar_t c, 19861253Slq150181 text_color_t fg_color, 19871253Slq150181 text_color_t bg_color) 19881253Slq150181 { 19891253Slq150181 int row; 19901253Slq150181 int byte; 19911253Slq150181 int i; 19921253Slq150181 uint8_t *cp; 19931253Slq150181 uint8_t data; 19941253Slq150181 uint8_t nibblett; 19951253Slq150181 int bytes_wide; 19961253Slq150181 uint8_t *dest; 19971253Slq150181 1998*7688SAaron.Zang@Sun.COM dest = (uint8_t *)tem->tvs_pix_data; 19991253Slq150181 2000*7688SAaron.Zang@Sun.COM cp = tems.ts_font.char_ptr[c]; 2001*7688SAaron.Zang@Sun.COM bytes_wide = (tems.ts_font.width + 7) / 8; 20021253Slq150181 2003*7688SAaron.Zang@Sun.COM for (row = 0; row < tems.ts_font.height; row++) { 20041253Slq150181 for (byte = 0; byte < bytes_wide; byte++) { 20051253Slq150181 data = *cp++; 20061253Slq150181 for (i = 0; i < 4; i++) { 20071253Slq150181 nibblett = (data >> ((3-i) * 2)) & 0x3; 20081253Slq150181 switch (nibblett) { 20091253Slq150181 case 0x0: 20101253Slq150181 *dest++ = bg_color << 4 | bg_color; 20111253Slq150181 break; 20121253Slq150181 case 0x1: 20131253Slq150181 *dest++ = bg_color << 4 | fg_color; 20141253Slq150181 break; 20151253Slq150181 case 0x2: 20161253Slq150181 *dest++ = fg_color << 4 | bg_color; 20171253Slq150181 break; 20181253Slq150181 case 0x3: 20191253Slq150181 *dest++ = fg_color << 4 | fg_color; 20201253Slq150181 break; 20211253Slq150181 } 20221253Slq150181 } 20231253Slq150181 } 20241253Slq150181 } 20251253Slq150181 } 20261253Slq150181 20271253Slq150181 /* 20281253Slq150181 * bit_to_pix8 is for 8-bit frame buffers. It will write one output byte 20291253Slq150181 * for each bit of input bitmap. It inverts the input bits before 20301253Slq150181 * doing the output translation, for reverse video. 20311253Slq150181 * 20321253Slq150181 * Assuming foreground is 00000001 and background is 00000000... 20331253Slq150181 * An input data byte of 0x53 will output the bit pattern 20341253Slq150181 * 0000000 000000001 00000000 00000001 00000000 00000000 00000001 00000001. 20351253Slq150181 */ 20361253Slq150181 2037*7688SAaron.Zang@Sun.COM static void 20381253Slq150181 bit_to_pix8( 2039*7688SAaron.Zang@Sun.COM struct tem_vt_state *tem, 20401253Slq150181 uchar_t c, 20411253Slq150181 text_color_t fg_color, 20421253Slq150181 text_color_t bg_color) 20431253Slq150181 { 20441253Slq150181 int row; 20451253Slq150181 int byte; 20461253Slq150181 int i; 20471253Slq150181 uint8_t *cp; 20481253Slq150181 uint8_t data; 20491253Slq150181 int bytes_wide; 20501253Slq150181 uint8_t mask; 20511253Slq150181 int bitsleft, nbits; 20521253Slq150181 uint8_t *dest; 20531253Slq150181 2054*7688SAaron.Zang@Sun.COM dest = (uint8_t *)tem->tvs_pix_data; 20551253Slq150181 2056*7688SAaron.Zang@Sun.COM cp = tems.ts_font.char_ptr[c]; 2057*7688SAaron.Zang@Sun.COM bytes_wide = (tems.ts_font.width + 7) / 8; 20581253Slq150181 2059*7688SAaron.Zang@Sun.COM for (row = 0; row < tems.ts_font.height; row++) { 2060*7688SAaron.Zang@Sun.COM bitsleft = tems.ts_font.width; 20611253Slq150181 for (byte = 0; byte < bytes_wide; byte++) { 20621253Slq150181 data = *cp++; 20631253Slq150181 mask = 0x80; 20641253Slq150181 nbits = MIN(8, bitsleft); 20651253Slq150181 bitsleft -= nbits; 20661253Slq150181 for (i = 0; i < nbits; i++) { 20671253Slq150181 *dest++ = (data & mask ? fg_color: bg_color); 20681253Slq150181 mask = mask >> 1; 20691253Slq150181 } 20701253Slq150181 } 20711253Slq150181 } 20721253Slq150181 } 20731253Slq150181 20741253Slq150181 /* 20751253Slq150181 * bit_to_pix24 is for 24-bit frame buffers. It will write four output bytes 20761253Slq150181 * for each bit of input bitmap. It inverts the input bits before 20771253Slq150181 * doing the output translation, for reverse video. Note that each 20781253Slq150181 * 24-bit RGB value is finally stored in a 32-bit unsigned int, with the 20791253Slq150181 * high-order byte set to zero. 20801253Slq150181 * 20811253Slq150181 * Assuming foreground is 00000000 11111111 11111111 11111111 20821253Slq150181 * and background is 00000000 00000000 00000000 00000000 20831253Slq150181 * An input data byte of 0x53 will output the bit pattern 20841253Slq150181 * 20851253Slq150181 * 00000000 00000000 00000000 00000000 20861253Slq150181 * 00000000 11111111 11111111 11111111 20871253Slq150181 * 00000000 00000000 00000000 00000000 20881253Slq150181 * 00000000 11111111 11111111 11111111 20891253Slq150181 * 00000000 00000000 00000000 00000000 20901253Slq150181 * 00000000 00000000 00000000 00000000 20911253Slq150181 * 00000000 11111111 11111111 11111111 20921253Slq150181 * 00000000 11111111 11111111 11111111 20931253Slq150181 * 20941253Slq150181 */ 20951253Slq150181 typedef uint32_t pixel32_t; 20961253Slq150181 2097*7688SAaron.Zang@Sun.COM static void 20981253Slq150181 bit_to_pix24( 2099*7688SAaron.Zang@Sun.COM struct tem_vt_state *tem, 21001253Slq150181 uchar_t c, 21011253Slq150181 text_color_t fg_color4, 21021253Slq150181 text_color_t bg_color4) 21031253Slq150181 { 21041253Slq150181 int row; 21051253Slq150181 int byte; 21061253Slq150181 int i; 21071253Slq150181 uint8_t *cp; 21081253Slq150181 uint8_t data; 21091253Slq150181 int bytes_wide; 21101253Slq150181 int bitsleft, nbits; 21111253Slq150181 21121253Slq150181 pixel32_t fg_color32, bg_color32, *destp; 21131253Slq150181 21141253Slq150181 ASSERT(fg_color4 < 16 && bg_color4 < 16); 21151253Slq150181 21161253Slq150181 fg_color32 = PIX4TO32(fg_color4); 21171253Slq150181 bg_color32 = PIX4TO32(bg_color4); 21181253Slq150181 2119*7688SAaron.Zang@Sun.COM destp = (pixel32_t *)tem->tvs_pix_data; 2120*7688SAaron.Zang@Sun.COM cp = tems.ts_font.char_ptr[c]; 2121*7688SAaron.Zang@Sun.COM bytes_wide = (tems.ts_font.width + 7) / 8; 21221253Slq150181 2123*7688SAaron.Zang@Sun.COM for (row = 0; row < tems.ts_font.height; row++) { 2124*7688SAaron.Zang@Sun.COM bitsleft = tems.ts_font.width; 21251253Slq150181 for (byte = 0; byte < bytes_wide; byte++) { 21261253Slq150181 data = *cp++; 21271253Slq150181 nbits = MIN(8, bitsleft); 21281253Slq150181 bitsleft -= nbits; 21291253Slq150181 for (i = 0; i < nbits; i++) { 21305129Smarx *destp++ = ((data << i) & 0x80 ? 21315129Smarx fg_color32 : bg_color32); 21321253Slq150181 } 21331253Slq150181 } 21341253Slq150181 } 21351253Slq150181 } 21361253Slq150181 21371253Slq150181 /* ARGSUSED */ 2138*7688SAaron.Zang@Sun.COM static text_color_t 2139*7688SAaron.Zang@Sun.COM ansi_bg_to_solaris(struct tem_vt_state *tem, int ansi) 21401253Slq150181 { 21411253Slq150181 return (bg_xlate[ansi]); 21421253Slq150181 } 21431253Slq150181 2144*7688SAaron.Zang@Sun.COM static text_color_t 2145*7688SAaron.Zang@Sun.COM ansi_fg_to_solaris(struct tem_vt_state *tem, int ansi) 21461253Slq150181 { 2147*7688SAaron.Zang@Sun.COM if (tem->tvs_flags & TEM_ATTR_BOLD) 21485129Smarx return (fg_brt_xlate[ansi]); 21491253Slq150181 else 21505129Smarx return (fg_dim_xlate[ansi]); 21511253Slq150181 } 21521253Slq150181 2153*7688SAaron.Zang@Sun.COM /* 2154*7688SAaron.Zang@Sun.COM * flag: TEM_ATTR_SCREEN_REVERSE or TEM_ATTR_REVERSE 2155*7688SAaron.Zang@Sun.COM */ 2156*7688SAaron.Zang@Sun.COM void 2157*7688SAaron.Zang@Sun.COM tem_safe_get_color(struct tem_vt_state *tem, text_color_t *fg, 2158*7688SAaron.Zang@Sun.COM text_color_t *bg, uint8_t flag) 21591253Slq150181 { 2160*7688SAaron.Zang@Sun.COM if (tem->tvs_flags & flag) { 21611253Slq150181 *fg = ansi_fg_to_solaris(tem, 2162*7688SAaron.Zang@Sun.COM tem->tvs_bg_color); 21631253Slq150181 *bg = ansi_bg_to_solaris(tem, 2164*7688SAaron.Zang@Sun.COM tem->tvs_fg_color); 21651253Slq150181 } else { 21661253Slq150181 *fg = ansi_fg_to_solaris(tem, 2167*7688SAaron.Zang@Sun.COM tem->tvs_fg_color); 21681253Slq150181 *bg = ansi_bg_to_solaris(tem, 2169*7688SAaron.Zang@Sun.COM tem->tvs_bg_color); 21701253Slq150181 } 21711253Slq150181 } 21721253Slq150181 21731253Slq150181 /* 21741253Slq150181 * Clear a rectangle of screen for pixel mode. 21751253Slq150181 * 21761253Slq150181 * arguments: 21771253Slq150181 * row: start row# 21781253Slq150181 * nrows: the number of rows to clear 21791253Slq150181 * offset_y: the offset of height in pixels to begin clear 21801253Slq150181 * col: start col# 21811253Slq150181 * ncols: the number of cols to clear 21821253Slq150181 * offset_x: the offset of width in pixels to begin clear 21831253Slq150181 * scroll_up: whether this function is called during sroll up, 21841253Slq150181 * which is called only once. 21851253Slq150181 */ 21861253Slq150181 void 2187*7688SAaron.Zang@Sun.COM tem_safe_pix_cls_range(struct tem_vt_state *tem, 21881253Slq150181 screen_pos_t row, int nrows, int offset_y, 21891253Slq150181 screen_pos_t col, int ncols, int offset_x, 21901253Slq150181 boolean_t sroll_up, cred_t *credp, 21911253Slq150181 enum called_from called_from) 21921253Slq150181 { 21931253Slq150181 struct vis_consdisplay da; 21941253Slq150181 int i, j; 21951253Slq150181 int row_add = 0; 21961253Slq150181 text_color_t fg_color; 21971253Slq150181 text_color_t bg_color; 21981253Slq150181 2199*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 2200*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 22011253Slq150181 22021253Slq150181 if (sroll_up) 2203*7688SAaron.Zang@Sun.COM row_add = tems.ts_c_dimension.height - 1; 22041253Slq150181 2205*7688SAaron.Zang@Sun.COM da.width = tems.ts_font.width; 2206*7688SAaron.Zang@Sun.COM da.height = tems.ts_font.height; 22071253Slq150181 2208*7688SAaron.Zang@Sun.COM tem_safe_get_color(tem, &fg_color, &bg_color, TEM_ATTR_SCREEN_REVERSE); 22091253Slq150181 2210*7688SAaron.Zang@Sun.COM tem_safe_callback_bit2pix(tem, ' ', fg_color, bg_color); 2211*7688SAaron.Zang@Sun.COM da.data = (uchar_t *)tem->tvs_pix_data; 22121253Slq150181 22131253Slq150181 for (i = 0; i < nrows; i++, row++) { 22141253Slq150181 da.row = (row + row_add) * da.height + offset_y; 22151253Slq150181 da.col = col * da.width + offset_x; 22161253Slq150181 for (j = 0; j < ncols; j++) { 2217*7688SAaron.Zang@Sun.COM tems_safe_display(&da, credp, called_from); 22181253Slq150181 da.col += da.width; 22191253Slq150181 } 22201253Slq150181 } 22211253Slq150181 } 2222*7688SAaron.Zang@Sun.COM 2223*7688SAaron.Zang@Sun.COM /* 2224*7688SAaron.Zang@Sun.COM * virtual screen operations 2225*7688SAaron.Zang@Sun.COM */ 2226*7688SAaron.Zang@Sun.COM static void 2227*7688SAaron.Zang@Sun.COM tem_safe_virtual_display(struct tem_vt_state *tem, unsigned char *string, 2228*7688SAaron.Zang@Sun.COM int count, screen_pos_t row, screen_pos_t col, 2229*7688SAaron.Zang@Sun.COM text_color_t fg_color, text_color_t bg_color) 2230*7688SAaron.Zang@Sun.COM { 2231*7688SAaron.Zang@Sun.COM int i, width; 2232*7688SAaron.Zang@Sun.COM unsigned char *addr; 2233*7688SAaron.Zang@Sun.COM text_color_t *pfgcolor; 2234*7688SAaron.Zang@Sun.COM text_color_t *pbgcolor; 2235*7688SAaron.Zang@Sun.COM 2236*7688SAaron.Zang@Sun.COM if (row < 0 || row >= tems.ts_c_dimension.height || 2237*7688SAaron.Zang@Sun.COM col < 0 || col >= tems.ts_c_dimension.width || 2238*7688SAaron.Zang@Sun.COM col + count > tems.ts_c_dimension.width) 2239*7688SAaron.Zang@Sun.COM return; 2240*7688SAaron.Zang@Sun.COM 2241*7688SAaron.Zang@Sun.COM width = tems.ts_c_dimension.width; 2242*7688SAaron.Zang@Sun.COM addr = tem->tvs_screen_buf + (row * width + col); 2243*7688SAaron.Zang@Sun.COM pfgcolor = tem->tvs_fg_buf + (row * width + col); 2244*7688SAaron.Zang@Sun.COM pbgcolor = tem->tvs_bg_buf + (row * width + col); 2245*7688SAaron.Zang@Sun.COM for (i = 0; i < count; i++) { 2246*7688SAaron.Zang@Sun.COM *addr++ = string[i]; 2247*7688SAaron.Zang@Sun.COM *pfgcolor++ = fg_color; 2248*7688SAaron.Zang@Sun.COM *pbgcolor++ = bg_color; 2249*7688SAaron.Zang@Sun.COM } 2250*7688SAaron.Zang@Sun.COM } 2251*7688SAaron.Zang@Sun.COM 2252*7688SAaron.Zang@Sun.COM static void 2253*7688SAaron.Zang@Sun.COM i_virtual_copy(unsigned char *base, 2254*7688SAaron.Zang@Sun.COM screen_pos_t s_col, screen_pos_t s_row, 2255*7688SAaron.Zang@Sun.COM screen_pos_t e_col, screen_pos_t e_row, 2256*7688SAaron.Zang@Sun.COM screen_pos_t t_col, screen_pos_t t_row) 2257*7688SAaron.Zang@Sun.COM { 2258*7688SAaron.Zang@Sun.COM unsigned char *from; 2259*7688SAaron.Zang@Sun.COM unsigned char *to; 2260*7688SAaron.Zang@Sun.COM int cnt; 2261*7688SAaron.Zang@Sun.COM screen_size_t chars_per_row; 2262*7688SAaron.Zang@Sun.COM unsigned char *to_row_start; 2263*7688SAaron.Zang@Sun.COM unsigned char *from_row_start; 2264*7688SAaron.Zang@Sun.COM screen_size_t rows_to_move; 2265*7688SAaron.Zang@Sun.COM int cols = tems.ts_c_dimension.width; 2266*7688SAaron.Zang@Sun.COM 2267*7688SAaron.Zang@Sun.COM chars_per_row = e_col - s_col + 1; 2268*7688SAaron.Zang@Sun.COM rows_to_move = e_row - s_row + 1; 2269*7688SAaron.Zang@Sun.COM 2270*7688SAaron.Zang@Sun.COM to_row_start = base + ((t_row * cols) + t_col); 2271*7688SAaron.Zang@Sun.COM from_row_start = base + ((s_row * cols) + s_col); 2272*7688SAaron.Zang@Sun.COM 2273*7688SAaron.Zang@Sun.COM if (to_row_start < from_row_start) { 2274*7688SAaron.Zang@Sun.COM while (rows_to_move-- > 0) { 2275*7688SAaron.Zang@Sun.COM to = to_row_start; 2276*7688SAaron.Zang@Sun.COM from = from_row_start; 2277*7688SAaron.Zang@Sun.COM to_row_start += cols; 2278*7688SAaron.Zang@Sun.COM from_row_start += cols; 2279*7688SAaron.Zang@Sun.COM for (cnt = chars_per_row; cnt-- > 0; ) 2280*7688SAaron.Zang@Sun.COM *to++ = *from++; 2281*7688SAaron.Zang@Sun.COM } 2282*7688SAaron.Zang@Sun.COM } else { 2283*7688SAaron.Zang@Sun.COM /* 2284*7688SAaron.Zang@Sun.COM * Offset to the end of the region and copy backwards. 2285*7688SAaron.Zang@Sun.COM */ 2286*7688SAaron.Zang@Sun.COM cnt = rows_to_move * cols + chars_per_row; 2287*7688SAaron.Zang@Sun.COM to_row_start += cnt; 2288*7688SAaron.Zang@Sun.COM from_row_start += cnt; 2289*7688SAaron.Zang@Sun.COM 2290*7688SAaron.Zang@Sun.COM while (rows_to_move-- > 0) { 2291*7688SAaron.Zang@Sun.COM to_row_start -= cols; 2292*7688SAaron.Zang@Sun.COM from_row_start -= cols; 2293*7688SAaron.Zang@Sun.COM to = to_row_start; 2294*7688SAaron.Zang@Sun.COM from = from_row_start; 2295*7688SAaron.Zang@Sun.COM for (cnt = chars_per_row; cnt-- > 0; ) 2296*7688SAaron.Zang@Sun.COM *--to = *--from; 2297*7688SAaron.Zang@Sun.COM } 2298*7688SAaron.Zang@Sun.COM } 2299*7688SAaron.Zang@Sun.COM } 2300*7688SAaron.Zang@Sun.COM 2301*7688SAaron.Zang@Sun.COM static void 2302*7688SAaron.Zang@Sun.COM tem_safe_virtual_copy(struct tem_vt_state *tem, 2303*7688SAaron.Zang@Sun.COM screen_pos_t s_col, screen_pos_t s_row, 2304*7688SAaron.Zang@Sun.COM screen_pos_t e_col, screen_pos_t e_row, 2305*7688SAaron.Zang@Sun.COM screen_pos_t t_col, screen_pos_t t_row) 2306*7688SAaron.Zang@Sun.COM { 2307*7688SAaron.Zang@Sun.COM screen_size_t chars_per_row; 2308*7688SAaron.Zang@Sun.COM screen_size_t rows_to_move; 2309*7688SAaron.Zang@Sun.COM int rows = tems.ts_c_dimension.height; 2310*7688SAaron.Zang@Sun.COM int cols = tems.ts_c_dimension.width; 2311*7688SAaron.Zang@Sun.COM 2312*7688SAaron.Zang@Sun.COM if (s_col < 0 || s_col >= cols || 2313*7688SAaron.Zang@Sun.COM s_row < 0 || s_row >= rows || 2314*7688SAaron.Zang@Sun.COM e_col < 0 || e_col >= cols || 2315*7688SAaron.Zang@Sun.COM e_row < 0 || e_row >= rows || 2316*7688SAaron.Zang@Sun.COM t_col < 0 || t_col >= cols || 2317*7688SAaron.Zang@Sun.COM t_row < 0 || t_row >= rows || 2318*7688SAaron.Zang@Sun.COM s_col > e_col || 2319*7688SAaron.Zang@Sun.COM s_row > e_row) 2320*7688SAaron.Zang@Sun.COM return; 2321*7688SAaron.Zang@Sun.COM 2322*7688SAaron.Zang@Sun.COM chars_per_row = e_col - s_col + 1; 2323*7688SAaron.Zang@Sun.COM rows_to_move = e_row - s_row + 1; 2324*7688SAaron.Zang@Sun.COM 2325*7688SAaron.Zang@Sun.COM /* More sanity checks. */ 2326*7688SAaron.Zang@Sun.COM if (t_row + rows_to_move > rows || 2327*7688SAaron.Zang@Sun.COM t_col + chars_per_row > cols) 2328*7688SAaron.Zang@Sun.COM return; 2329*7688SAaron.Zang@Sun.COM 2330*7688SAaron.Zang@Sun.COM i_virtual_copy(tem->tvs_screen_buf, s_col, s_row, 2331*7688SAaron.Zang@Sun.COM e_col, e_row, t_col, t_row); 2332*7688SAaron.Zang@Sun.COM 2333*7688SAaron.Zang@Sun.COM /* text_color_t is the same size as char */ 2334*7688SAaron.Zang@Sun.COM i_virtual_copy((unsigned char *)tem->tvs_fg_buf, 2335*7688SAaron.Zang@Sun.COM s_col, s_row, e_col, e_row, t_col, t_row); 2336*7688SAaron.Zang@Sun.COM i_virtual_copy((unsigned char *)tem->tvs_bg_buf, 2337*7688SAaron.Zang@Sun.COM s_col, s_row, e_col, e_row, t_col, t_row); 2338*7688SAaron.Zang@Sun.COM 2339*7688SAaron.Zang@Sun.COM } 2340*7688SAaron.Zang@Sun.COM 2341*7688SAaron.Zang@Sun.COM static void 2342*7688SAaron.Zang@Sun.COM tem_safe_virtual_cls(struct tem_vt_state *tem, 2343*7688SAaron.Zang@Sun.COM int count, screen_pos_t row, screen_pos_t col) 2344*7688SAaron.Zang@Sun.COM { 2345*7688SAaron.Zang@Sun.COM text_color_t fg_color; 2346*7688SAaron.Zang@Sun.COM text_color_t bg_color; 2347*7688SAaron.Zang@Sun.COM 2348*7688SAaron.Zang@Sun.COM tem_safe_get_color(tem, &fg_color, &bg_color, TEM_ATTR_SCREEN_REVERSE); 2349*7688SAaron.Zang@Sun.COM tem_safe_virtual_display(tem, tems.ts_blank_line, count, row, col, 2350*7688SAaron.Zang@Sun.COM fg_color, bg_color); 2351*7688SAaron.Zang@Sun.COM } 2352*7688SAaron.Zang@Sun.COM 2353*7688SAaron.Zang@Sun.COM /* 2354*7688SAaron.Zang@Sun.COM * only blank screen, not clear our screen buffer 2355*7688SAaron.Zang@Sun.COM */ 2356*7688SAaron.Zang@Sun.COM void 2357*7688SAaron.Zang@Sun.COM tem_safe_blank_screen(struct tem_vt_state *tem, cred_t *credp, 2358*7688SAaron.Zang@Sun.COM enum called_from called_from) 2359*7688SAaron.Zang@Sun.COM { 2360*7688SAaron.Zang@Sun.COM int row; 2361*7688SAaron.Zang@Sun.COM 2362*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 2363*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 2364*7688SAaron.Zang@Sun.COM 2365*7688SAaron.Zang@Sun.COM if (tems.ts_display_mode == VIS_PIXEL) { 2366*7688SAaron.Zang@Sun.COM tem_safe_pix_clear_entire_screen(tem, credp, called_from); 2367*7688SAaron.Zang@Sun.COM return; 2368*7688SAaron.Zang@Sun.COM } 2369*7688SAaron.Zang@Sun.COM 2370*7688SAaron.Zang@Sun.COM for (row = 0; row < tems.ts_c_dimension.height; row++) { 2371*7688SAaron.Zang@Sun.COM tem_safe_callback_cls(tem, 2372*7688SAaron.Zang@Sun.COM tems.ts_c_dimension.width, 2373*7688SAaron.Zang@Sun.COM row, 0, credp, called_from); 2374*7688SAaron.Zang@Sun.COM } 2375*7688SAaron.Zang@Sun.COM } 2376*7688SAaron.Zang@Sun.COM 2377*7688SAaron.Zang@Sun.COM /* 2378*7688SAaron.Zang@Sun.COM * unblank screen with associated tem from its screen buffer 2379*7688SAaron.Zang@Sun.COM */ 2380*7688SAaron.Zang@Sun.COM void 2381*7688SAaron.Zang@Sun.COM tem_safe_unblank_screen(struct tem_vt_state *tem, cred_t *credp, 2382*7688SAaron.Zang@Sun.COM enum called_from called_from) 2383*7688SAaron.Zang@Sun.COM { 2384*7688SAaron.Zang@Sun.COM text_color_t fg_color, fg_last; 2385*7688SAaron.Zang@Sun.COM text_color_t bg_color, bg_last; 2386*7688SAaron.Zang@Sun.COM size_t tc_size = sizeof (text_color_t); 2387*7688SAaron.Zang@Sun.COM int row, col, count, col_start; 2388*7688SAaron.Zang@Sun.COM int width; 2389*7688SAaron.Zang@Sun.COM unsigned char *buf; 2390*7688SAaron.Zang@Sun.COM 2391*7688SAaron.Zang@Sun.COM ASSERT((MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock)) || 2392*7688SAaron.Zang@Sun.COM called_from == CALLED_FROM_STANDALONE); 2393*7688SAaron.Zang@Sun.COM 2394*7688SAaron.Zang@Sun.COM if (tems.ts_display_mode == VIS_PIXEL) 2395*7688SAaron.Zang@Sun.COM tem_safe_pix_clear_entire_screen(tem, credp, called_from); 2396*7688SAaron.Zang@Sun.COM 2397*7688SAaron.Zang@Sun.COM tem_safe_callback_cursor(tem, VIS_HIDE_CURSOR, credp, called_from); 2398*7688SAaron.Zang@Sun.COM 2399*7688SAaron.Zang@Sun.COM width = tems.ts_c_dimension.width; 2400*7688SAaron.Zang@Sun.COM 2401*7688SAaron.Zang@Sun.COM /* 2402*7688SAaron.Zang@Sun.COM * Display data in tvs_screen_buf to the actual framebuffer in a 2403*7688SAaron.Zang@Sun.COM * row by row way. 2404*7688SAaron.Zang@Sun.COM * When dealing with one row, output data with the same foreground 2405*7688SAaron.Zang@Sun.COM * and background color all together. 2406*7688SAaron.Zang@Sun.COM */ 2407*7688SAaron.Zang@Sun.COM for (row = 0; row < tems.ts_c_dimension.height; row++) { 2408*7688SAaron.Zang@Sun.COM buf = tem->tvs_screen_buf + (row * width); 2409*7688SAaron.Zang@Sun.COM count = col_start = 0; 2410*7688SAaron.Zang@Sun.COM for (col = 0; col < width; col++) { 2411*7688SAaron.Zang@Sun.COM fg_color = 2412*7688SAaron.Zang@Sun.COM tem->tvs_fg_buf[(row * width + col) * tc_size]; 2413*7688SAaron.Zang@Sun.COM bg_color = 2414*7688SAaron.Zang@Sun.COM tem->tvs_bg_buf[(row * width + col) * tc_size]; 2415*7688SAaron.Zang@Sun.COM if (col == 0) { 2416*7688SAaron.Zang@Sun.COM fg_last = fg_color; 2417*7688SAaron.Zang@Sun.COM bg_last = bg_color; 2418*7688SAaron.Zang@Sun.COM } 2419*7688SAaron.Zang@Sun.COM 2420*7688SAaron.Zang@Sun.COM if ((fg_color != fg_last) || (bg_color != bg_last)) { 2421*7688SAaron.Zang@Sun.COM /* 2422*7688SAaron.Zang@Sun.COM * Call the primitive to render this data. 2423*7688SAaron.Zang@Sun.COM */ 2424*7688SAaron.Zang@Sun.COM tem_safe_callback_display(tem, 2425*7688SAaron.Zang@Sun.COM buf, count, row, col_start, 2426*7688SAaron.Zang@Sun.COM fg_last, bg_last, credp, called_from); 2427*7688SAaron.Zang@Sun.COM buf += count; 2428*7688SAaron.Zang@Sun.COM count = 1; 2429*7688SAaron.Zang@Sun.COM col_start = col; 2430*7688SAaron.Zang@Sun.COM fg_last = fg_color; 2431*7688SAaron.Zang@Sun.COM bg_last = bg_color; 2432*7688SAaron.Zang@Sun.COM } else { 2433*7688SAaron.Zang@Sun.COM count++; 2434*7688SAaron.Zang@Sun.COM } 2435*7688SAaron.Zang@Sun.COM } 2436*7688SAaron.Zang@Sun.COM 2437*7688SAaron.Zang@Sun.COM if (col_start == (width - 1)) 2438*7688SAaron.Zang@Sun.COM continue; 2439*7688SAaron.Zang@Sun.COM 2440*7688SAaron.Zang@Sun.COM /* 2441*7688SAaron.Zang@Sun.COM * Call the primitive to render this data. 2442*7688SAaron.Zang@Sun.COM */ 2443*7688SAaron.Zang@Sun.COM tem_safe_callback_display(tem, 2444*7688SAaron.Zang@Sun.COM buf, count, row, col_start, 2445*7688SAaron.Zang@Sun.COM fg_last, bg_last, credp, called_from); 2446*7688SAaron.Zang@Sun.COM } 2447*7688SAaron.Zang@Sun.COM 2448*7688SAaron.Zang@Sun.COM tem_safe_callback_cursor(tem, VIS_DISPLAY_CURSOR, credp, called_from); 2449*7688SAaron.Zang@Sun.COM } 2450