127cf7d04SAleksandr Rybalko /*- 28a36da99SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 38a36da99SPedro F. Giffuni * 427cf7d04SAleksandr Rybalko * Copyright (c) 2009 The FreeBSD Foundation 527cf7d04SAleksandr Rybalko * All rights reserved. 627cf7d04SAleksandr Rybalko * 727cf7d04SAleksandr Rybalko * This software was developed by Ed Schouten under sponsorship from the 827cf7d04SAleksandr Rybalko * FreeBSD Foundation. 927cf7d04SAleksandr Rybalko * 1027cf7d04SAleksandr Rybalko * Redistribution and use in source and binary forms, with or without 1127cf7d04SAleksandr Rybalko * modification, are permitted provided that the following conditions 1227cf7d04SAleksandr Rybalko * are met: 1327cf7d04SAleksandr Rybalko * 1. Redistributions of source code must retain the above copyright 1427cf7d04SAleksandr Rybalko * notice, this list of conditions and the following disclaimer. 1527cf7d04SAleksandr Rybalko * 2. Redistributions in binary form must reproduce the above copyright 1627cf7d04SAleksandr Rybalko * notice, this list of conditions and the following disclaimer in the 1727cf7d04SAleksandr Rybalko * documentation and/or other materials provided with the distribution. 1827cf7d04SAleksandr Rybalko * 1927cf7d04SAleksandr Rybalko * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2027cf7d04SAleksandr Rybalko * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2127cf7d04SAleksandr Rybalko * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2227cf7d04SAleksandr Rybalko * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2327cf7d04SAleksandr Rybalko * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2427cf7d04SAleksandr Rybalko * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2527cf7d04SAleksandr Rybalko * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2627cf7d04SAleksandr Rybalko * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2727cf7d04SAleksandr Rybalko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2827cf7d04SAleksandr Rybalko * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2927cf7d04SAleksandr Rybalko * SUCH DAMAGE. 3027cf7d04SAleksandr Rybalko */ 3127cf7d04SAleksandr Rybalko 3227cf7d04SAleksandr Rybalko #include <sys/cdefs.h> 3327cf7d04SAleksandr Rybalko __FBSDID("$FreeBSD$"); 3427cf7d04SAleksandr Rybalko 3527cf7d04SAleksandr Rybalko #include <sys/param.h> 3627cf7d04SAleksandr Rybalko #include <sys/cons.h> 3727cf7d04SAleksandr Rybalko #include <sys/consio.h> 3827cf7d04SAleksandr Rybalko #include <sys/kernel.h> 3927cf7d04SAleksandr Rybalko #include <sys/lock.h> 4027cf7d04SAleksandr Rybalko #include <sys/malloc.h> 4127cf7d04SAleksandr Rybalko #include <sys/mutex.h> 4227cf7d04SAleksandr Rybalko #include <sys/systm.h> 4327cf7d04SAleksandr Rybalko #include <sys/terminal.h> 4427cf7d04SAleksandr Rybalko #include <sys/tty.h> 4527cf7d04SAleksandr Rybalko 4627cf7d04SAleksandr Rybalko #include <machine/stdarg.h> 4727cf7d04SAleksandr Rybalko 4827cf7d04SAleksandr Rybalko static MALLOC_DEFINE(M_TERMINAL, "terminal", "terminal device"); 4927cf7d04SAleksandr Rybalko 5027cf7d04SAleksandr Rybalko /* 5127cf7d04SAleksandr Rybalko * Locking. 5227cf7d04SAleksandr Rybalko * 5327cf7d04SAleksandr Rybalko * Normally we don't need to lock down the terminal emulator, because 5427cf7d04SAleksandr Rybalko * the TTY lock is already held when calling teken_input(). 5527cf7d04SAleksandr Rybalko * Unfortunately this is not the case when the terminal acts as a 5627cf7d04SAleksandr Rybalko * console device, because cnputc() can be called at the same time. 5727cf7d04SAleksandr Rybalko * This means terminals may need to be locked down using a spin lock. 5827cf7d04SAleksandr Rybalko */ 5927cf7d04SAleksandr Rybalko #define TERMINAL_LOCK(tm) do { \ 6027cf7d04SAleksandr Rybalko if ((tm)->tm_flags & TF_CONS) \ 6127cf7d04SAleksandr Rybalko mtx_lock_spin(&(tm)->tm_mtx); \ 6227cf7d04SAleksandr Rybalko else if ((tm)->tm_tty != NULL) \ 6327cf7d04SAleksandr Rybalko tty_lock((tm)->tm_tty); \ 6427cf7d04SAleksandr Rybalko } while (0) 6527cf7d04SAleksandr Rybalko #define TERMINAL_UNLOCK(tm) do { \ 6627cf7d04SAleksandr Rybalko if ((tm)->tm_flags & TF_CONS) \ 6727cf7d04SAleksandr Rybalko mtx_unlock_spin(&(tm)->tm_mtx); \ 6827cf7d04SAleksandr Rybalko else if ((tm)->tm_tty != NULL) \ 6927cf7d04SAleksandr Rybalko tty_unlock((tm)->tm_tty); \ 7027cf7d04SAleksandr Rybalko } while (0) 7127cf7d04SAleksandr Rybalko #define TERMINAL_LOCK_TTY(tm) do { \ 7227cf7d04SAleksandr Rybalko if ((tm)->tm_flags & TF_CONS) \ 7327cf7d04SAleksandr Rybalko mtx_lock_spin(&(tm)->tm_mtx); \ 7427cf7d04SAleksandr Rybalko } while (0) 7527cf7d04SAleksandr Rybalko #define TERMINAL_UNLOCK_TTY(tm) do { \ 7627cf7d04SAleksandr Rybalko if ((tm)->tm_flags & TF_CONS) \ 7727cf7d04SAleksandr Rybalko mtx_unlock_spin(&(tm)->tm_mtx); \ 7827cf7d04SAleksandr Rybalko } while (0) 7927cf7d04SAleksandr Rybalko #define TERMINAL_LOCK_CONS(tm) mtx_lock_spin(&(tm)->tm_mtx) 8027cf7d04SAleksandr Rybalko #define TERMINAL_UNLOCK_CONS(tm) mtx_unlock_spin(&(tm)->tm_mtx) 8127cf7d04SAleksandr Rybalko 8227cf7d04SAleksandr Rybalko /* 8327cf7d04SAleksandr Rybalko * TTY routines. 8427cf7d04SAleksandr Rybalko */ 8527cf7d04SAleksandr Rybalko 8627cf7d04SAleksandr Rybalko static tsw_open_t termtty_open; 8727cf7d04SAleksandr Rybalko static tsw_close_t termtty_close; 8827cf7d04SAleksandr Rybalko static tsw_outwakeup_t termtty_outwakeup; 8927cf7d04SAleksandr Rybalko static tsw_ioctl_t termtty_ioctl; 907a1a32c4SAleksandr Rybalko static tsw_mmap_t termtty_mmap; 9127cf7d04SAleksandr Rybalko 9227cf7d04SAleksandr Rybalko static struct ttydevsw terminal_tty_class = { 9327cf7d04SAleksandr Rybalko .tsw_open = termtty_open, 9427cf7d04SAleksandr Rybalko .tsw_close = termtty_close, 9527cf7d04SAleksandr Rybalko .tsw_outwakeup = termtty_outwakeup, 9627cf7d04SAleksandr Rybalko .tsw_ioctl = termtty_ioctl, 977a1a32c4SAleksandr Rybalko .tsw_mmap = termtty_mmap, 9827cf7d04SAleksandr Rybalko }; 9927cf7d04SAleksandr Rybalko 10027cf7d04SAleksandr Rybalko /* 10127cf7d04SAleksandr Rybalko * Terminal emulator routines. 10227cf7d04SAleksandr Rybalko */ 10327cf7d04SAleksandr Rybalko 10427cf7d04SAleksandr Rybalko static tf_bell_t termteken_bell; 10527cf7d04SAleksandr Rybalko static tf_cursor_t termteken_cursor; 10627cf7d04SAleksandr Rybalko static tf_putchar_t termteken_putchar; 10727cf7d04SAleksandr Rybalko static tf_fill_t termteken_fill; 10827cf7d04SAleksandr Rybalko static tf_copy_t termteken_copy; 109547e74a8SJean-Sébastien Pédron static tf_pre_input_t termteken_pre_input; 110547e74a8SJean-Sébastien Pédron static tf_post_input_t termteken_post_input; 11127cf7d04SAleksandr Rybalko static tf_param_t termteken_param; 11227cf7d04SAleksandr Rybalko static tf_respond_t termteken_respond; 11327cf7d04SAleksandr Rybalko 11427cf7d04SAleksandr Rybalko static teken_funcs_t terminal_drawmethods = { 11527cf7d04SAleksandr Rybalko .tf_bell = termteken_bell, 11627cf7d04SAleksandr Rybalko .tf_cursor = termteken_cursor, 11727cf7d04SAleksandr Rybalko .tf_putchar = termteken_putchar, 11827cf7d04SAleksandr Rybalko .tf_fill = termteken_fill, 11927cf7d04SAleksandr Rybalko .tf_copy = termteken_copy, 120547e74a8SJean-Sébastien Pédron .tf_pre_input = termteken_pre_input, 121547e74a8SJean-Sébastien Pédron .tf_post_input = termteken_post_input, 12227cf7d04SAleksandr Rybalko .tf_param = termteken_param, 12327cf7d04SAleksandr Rybalko .tf_respond = termteken_respond, 12427cf7d04SAleksandr Rybalko }; 12527cf7d04SAleksandr Rybalko 12627cf7d04SAleksandr Rybalko /* Kernel message formatting. */ 1273001e0c9SToomas Soome static teken_attr_t kernel_message = { 1287344ee18SMarius Strobl .ta_fgcolor = TCHAR_FGCOLOR(TERMINAL_KERN_ATTR), 1297344ee18SMarius Strobl .ta_bgcolor = TCHAR_BGCOLOR(TERMINAL_KERN_ATTR), 1307344ee18SMarius Strobl .ta_format = TCHAR_FORMAT(TERMINAL_KERN_ATTR) 13127cf7d04SAleksandr Rybalko }; 13227cf7d04SAleksandr Rybalko 1333001e0c9SToomas Soome static teken_attr_t default_message = { 1347344ee18SMarius Strobl .ta_fgcolor = TCHAR_FGCOLOR(TERMINAL_NORM_ATTR), 1357344ee18SMarius Strobl .ta_bgcolor = TCHAR_BGCOLOR(TERMINAL_NORM_ATTR), 1367344ee18SMarius Strobl .ta_format = TCHAR_FORMAT(TERMINAL_NORM_ATTR) 13727cf7d04SAleksandr Rybalko }; 13827cf7d04SAleksandr Rybalko 1394eb235fbSBruce Evans /* Fudge fg brightness as TF_BOLD (shifted). */ 1404eb235fbSBruce Evans #define TCOLOR_FG_FUDGED(color) __extension__ ({ \ 1414eb235fbSBruce Evans teken_color_t _c; \ 1424eb235fbSBruce Evans \ 1434eb235fbSBruce Evans _c = (color); \ 1444eb235fbSBruce Evans TCOLOR_FG(_c & 7) | ((_c & 8) << 18); \ 1454eb235fbSBruce Evans }) 1464eb235fbSBruce Evans 1474eb235fbSBruce Evans /* Fudge bg brightness as TF_BLINK (shifted). */ 1484eb235fbSBruce Evans #define TCOLOR_BG_FUDGED(color) __extension__ ({ \ 1494eb235fbSBruce Evans teken_color_t _c; \ 1504eb235fbSBruce Evans \ 1514eb235fbSBruce Evans _c = (color); \ 1524eb235fbSBruce Evans TCOLOR_BG(_c & 7) | ((_c & 8) << 20); \ 1534eb235fbSBruce Evans }) 1544eb235fbSBruce Evans 1551370fa33SBruce Evans #define TCOLOR_256TO16(color) __extension__ ({ \ 1561370fa33SBruce Evans teken_color_t _c; \ 1571370fa33SBruce Evans \ 1581370fa33SBruce Evans _c = (color); \ 1591370fa33SBruce Evans if (_c >= 16) \ 1601370fa33SBruce Evans _c = teken_256to16(_c); \ 1611370fa33SBruce Evans _c; \ 1621370fa33SBruce Evans }) 1631370fa33SBruce Evans 1647344ee18SMarius Strobl #define TCHAR_CREATE(c, a) ((c) | TFORMAT((a)->ta_format) | \ 1651370fa33SBruce Evans TCOLOR_FG_FUDGED(TCOLOR_256TO16((a)->ta_fgcolor)) | \ 1661370fa33SBruce Evans TCOLOR_BG_FUDGED(TCOLOR_256TO16((a)->ta_bgcolor))) 16727cf7d04SAleksandr Rybalko 16827cf7d04SAleksandr Rybalko static void 16927cf7d04SAleksandr Rybalko terminal_init(struct terminal *tm) 17027cf7d04SAleksandr Rybalko { 1713001e0c9SToomas Soome int fg, bg; 17227cf7d04SAleksandr Rybalko 17327cf7d04SAleksandr Rybalko if (tm->tm_flags & TF_CONS) 17427cf7d04SAleksandr Rybalko mtx_init(&tm->tm_mtx, "trmlck", NULL, MTX_SPIN); 1753001e0c9SToomas Soome 17627cf7d04SAleksandr Rybalko teken_init(&tm->tm_emulator, &terminal_drawmethods, tm); 1773001e0c9SToomas Soome 17811fc80a0SToomas Soome fg = bg = -1; 1793001e0c9SToomas Soome TUNABLE_INT_FETCH("teken.fg_color", &fg); 1803001e0c9SToomas Soome TUNABLE_INT_FETCH("teken.bg_color", &bg); 1813001e0c9SToomas Soome 1823001e0c9SToomas Soome if (fg != -1) { 1833001e0c9SToomas Soome default_message.ta_fgcolor = fg; 1843001e0c9SToomas Soome kernel_message.ta_fgcolor = fg; 1853001e0c9SToomas Soome } 1863001e0c9SToomas Soome if (bg != -1) { 1873001e0c9SToomas Soome default_message.ta_bgcolor = bg; 1883001e0c9SToomas Soome kernel_message.ta_bgcolor = bg; 1893001e0c9SToomas Soome } 1903001e0c9SToomas Soome 1913001e0c9SToomas Soome if (default_message.ta_bgcolor == TC_WHITE) { 1923001e0c9SToomas Soome default_message.ta_bgcolor |= TC_LIGHT; 1933001e0c9SToomas Soome kernel_message.ta_bgcolor |= TC_LIGHT; 1943001e0c9SToomas Soome } 1953001e0c9SToomas Soome 1963001e0c9SToomas Soome if (default_message.ta_bgcolor == TC_BLACK && 1973001e0c9SToomas Soome default_message.ta_fgcolor < TC_NCOLORS) 1983001e0c9SToomas Soome kernel_message.ta_fgcolor |= TC_LIGHT; 19927cf7d04SAleksandr Rybalko teken_set_defattr(&tm->tm_emulator, &default_message); 20027cf7d04SAleksandr Rybalko } 20127cf7d04SAleksandr Rybalko 20227cf7d04SAleksandr Rybalko struct terminal * 20327cf7d04SAleksandr Rybalko terminal_alloc(const struct terminal_class *tc, void *softc) 20427cf7d04SAleksandr Rybalko { 20527cf7d04SAleksandr Rybalko struct terminal *tm; 20627cf7d04SAleksandr Rybalko 20727cf7d04SAleksandr Rybalko tm = malloc(sizeof(struct terminal), M_TERMINAL, M_WAITOK|M_ZERO); 20827cf7d04SAleksandr Rybalko terminal_init(tm); 20927cf7d04SAleksandr Rybalko 21027cf7d04SAleksandr Rybalko tm->tm_class = tc; 21127cf7d04SAleksandr Rybalko tm->tm_softc = softc; 21227cf7d04SAleksandr Rybalko 21327cf7d04SAleksandr Rybalko return (tm); 21427cf7d04SAleksandr Rybalko } 21527cf7d04SAleksandr Rybalko 21627cf7d04SAleksandr Rybalko static void 21727cf7d04SAleksandr Rybalko terminal_sync_ttysize(struct terminal *tm) 21827cf7d04SAleksandr Rybalko { 21927cf7d04SAleksandr Rybalko struct tty *tp; 22027cf7d04SAleksandr Rybalko 22127cf7d04SAleksandr Rybalko tp = tm->tm_tty; 22227cf7d04SAleksandr Rybalko if (tp == NULL) 22327cf7d04SAleksandr Rybalko return; 22427cf7d04SAleksandr Rybalko 22527cf7d04SAleksandr Rybalko tty_lock(tp); 22627cf7d04SAleksandr Rybalko tty_set_winsize(tp, &tm->tm_winsize); 22727cf7d04SAleksandr Rybalko tty_unlock(tp); 22827cf7d04SAleksandr Rybalko } 22927cf7d04SAleksandr Rybalko 23027cf7d04SAleksandr Rybalko void 23127cf7d04SAleksandr Rybalko terminal_maketty(struct terminal *tm, const char *fmt, ...) 23227cf7d04SAleksandr Rybalko { 23327cf7d04SAleksandr Rybalko struct tty *tp; 23427cf7d04SAleksandr Rybalko char name[8]; 23527cf7d04SAleksandr Rybalko va_list ap; 23627cf7d04SAleksandr Rybalko 23727cf7d04SAleksandr Rybalko va_start(ap, fmt); 23827cf7d04SAleksandr Rybalko vsnrprintf(name, sizeof name, 32, fmt, ap); 23927cf7d04SAleksandr Rybalko va_end(ap); 24027cf7d04SAleksandr Rybalko 24127cf7d04SAleksandr Rybalko tp = tty_alloc(&terminal_tty_class, tm); 24227cf7d04SAleksandr Rybalko tty_makedev(tp, NULL, "%s", name); 24327cf7d04SAleksandr Rybalko tm->tm_tty = tp; 24427cf7d04SAleksandr Rybalko terminal_sync_ttysize(tm); 24527cf7d04SAleksandr Rybalko } 24627cf7d04SAleksandr Rybalko 24727cf7d04SAleksandr Rybalko void 248da49f6bcSJean-Sébastien Pédron terminal_set_cursor(struct terminal *tm, const term_pos_t *pos) 249da49f6bcSJean-Sébastien Pédron { 250da49f6bcSJean-Sébastien Pédron 251da49f6bcSJean-Sébastien Pédron teken_set_cursor(&tm->tm_emulator, pos); 252da49f6bcSJean-Sébastien Pédron } 253da49f6bcSJean-Sébastien Pédron 254da49f6bcSJean-Sébastien Pédron void 25527cf7d04SAleksandr Rybalko terminal_set_winsize_blank(struct terminal *tm, const struct winsize *size, 2567344ee18SMarius Strobl int blank, const term_attr_t *attr) 25727cf7d04SAleksandr Rybalko { 25827cf7d04SAleksandr Rybalko term_rect_t r; 25927cf7d04SAleksandr Rybalko 26027cf7d04SAleksandr Rybalko tm->tm_winsize = *size; 26127cf7d04SAleksandr Rybalko 26227cf7d04SAleksandr Rybalko r.tr_begin.tp_row = r.tr_begin.tp_col = 0; 26327cf7d04SAleksandr Rybalko r.tr_end.tp_row = size->ws_row; 26427cf7d04SAleksandr Rybalko r.tr_end.tp_col = size->ws_col; 26527cf7d04SAleksandr Rybalko 26627cf7d04SAleksandr Rybalko TERMINAL_LOCK(tm); 26727cf7d04SAleksandr Rybalko if (blank == 0) 26827cf7d04SAleksandr Rybalko teken_set_winsize_noreset(&tm->tm_emulator, &r.tr_end); 26927cf7d04SAleksandr Rybalko else 27027cf7d04SAleksandr Rybalko teken_set_winsize(&tm->tm_emulator, &r.tr_end); 27127cf7d04SAleksandr Rybalko TERMINAL_UNLOCK(tm); 27227cf7d04SAleksandr Rybalko 27319fbe1eaSAleksandr Rybalko if ((blank != 0) && !(tm->tm_flags & TF_MUTE)) 2747344ee18SMarius Strobl tm->tm_class->tc_fill(tm, &r, 2757344ee18SMarius Strobl TCHAR_CREATE((teken_char_t)' ', attr)); 27627cf7d04SAleksandr Rybalko 27727cf7d04SAleksandr Rybalko terminal_sync_ttysize(tm); 27827cf7d04SAleksandr Rybalko } 27927cf7d04SAleksandr Rybalko 28027cf7d04SAleksandr Rybalko void 28127cf7d04SAleksandr Rybalko terminal_set_winsize(struct terminal *tm, const struct winsize *size) 28227cf7d04SAleksandr Rybalko { 28327cf7d04SAleksandr Rybalko 2847344ee18SMarius Strobl terminal_set_winsize_blank(tm, size, 1, 2857344ee18SMarius Strobl (const term_attr_t *)&default_message); 28627cf7d04SAleksandr Rybalko } 28727cf7d04SAleksandr Rybalko 28827cf7d04SAleksandr Rybalko /* 28927cf7d04SAleksandr Rybalko * XXX: This function is a kludge. Drivers like vt(4) need to 29027cf7d04SAleksandr Rybalko * temporarily stop input when resizing, etc. This should ideally be 29127cf7d04SAleksandr Rybalko * handled within the driver. 29227cf7d04SAleksandr Rybalko */ 29327cf7d04SAleksandr Rybalko 29427cf7d04SAleksandr Rybalko void 29527cf7d04SAleksandr Rybalko terminal_mute(struct terminal *tm, int yes) 29627cf7d04SAleksandr Rybalko { 29727cf7d04SAleksandr Rybalko 29827cf7d04SAleksandr Rybalko TERMINAL_LOCK(tm); 29927cf7d04SAleksandr Rybalko if (yes) 30027cf7d04SAleksandr Rybalko tm->tm_flags |= TF_MUTE; 30127cf7d04SAleksandr Rybalko else 30227cf7d04SAleksandr Rybalko tm->tm_flags &= ~TF_MUTE; 30327cf7d04SAleksandr Rybalko TERMINAL_UNLOCK(tm); 30427cf7d04SAleksandr Rybalko } 30527cf7d04SAleksandr Rybalko 30627cf7d04SAleksandr Rybalko void 30727cf7d04SAleksandr Rybalko terminal_input_char(struct terminal *tm, term_char_t c) 30827cf7d04SAleksandr Rybalko { 30927cf7d04SAleksandr Rybalko struct tty *tp; 31027cf7d04SAleksandr Rybalko 31127cf7d04SAleksandr Rybalko tp = tm->tm_tty; 31227cf7d04SAleksandr Rybalko if (tp == NULL) 31327cf7d04SAleksandr Rybalko return; 31427cf7d04SAleksandr Rybalko 315a3da01fcSEd Schouten /* 316a3da01fcSEd Schouten * Strip off any attributes. Also ignore input of second part of 317a3da01fcSEd Schouten * CJK fullwidth characters, as we don't want to return these 318a3da01fcSEd Schouten * characters twice. 319a3da01fcSEd Schouten */ 320a3da01fcSEd Schouten if (TCHAR_FORMAT(c) & TF_CJK_RIGHT) 321a3da01fcSEd Schouten return; 32227cf7d04SAleksandr Rybalko c = TCHAR_CHARACTER(c); 32327cf7d04SAleksandr Rybalko 32427cf7d04SAleksandr Rybalko tty_lock(tp); 32527cf7d04SAleksandr Rybalko /* 32627cf7d04SAleksandr Rybalko * Conversion to UTF-8. 32727cf7d04SAleksandr Rybalko */ 32827cf7d04SAleksandr Rybalko if (c < 0x80) { 32927cf7d04SAleksandr Rybalko ttydisc_rint(tp, c, 0); 33027cf7d04SAleksandr Rybalko } else if (c < 0x800) { 33127cf7d04SAleksandr Rybalko char str[2] = { 33227cf7d04SAleksandr Rybalko 0xc0 | (c >> 6), 33327cf7d04SAleksandr Rybalko 0x80 | (c & 0x3f) 33427cf7d04SAleksandr Rybalko }; 33527cf7d04SAleksandr Rybalko 33627cf7d04SAleksandr Rybalko ttydisc_rint_simple(tp, str, sizeof str); 33727cf7d04SAleksandr Rybalko } else if (c < 0x10000) { 33827cf7d04SAleksandr Rybalko char str[3] = { 33927cf7d04SAleksandr Rybalko 0xe0 | (c >> 12), 34027cf7d04SAleksandr Rybalko 0x80 | ((c >> 6) & 0x3f), 34127cf7d04SAleksandr Rybalko 0x80 | (c & 0x3f) 34227cf7d04SAleksandr Rybalko }; 34327cf7d04SAleksandr Rybalko 34427cf7d04SAleksandr Rybalko ttydisc_rint_simple(tp, str, sizeof str); 34527cf7d04SAleksandr Rybalko } else { 34627cf7d04SAleksandr Rybalko char str[4] = { 34727cf7d04SAleksandr Rybalko 0xf0 | (c >> 18), 34827cf7d04SAleksandr Rybalko 0x80 | ((c >> 12) & 0x3f), 34927cf7d04SAleksandr Rybalko 0x80 | ((c >> 6) & 0x3f), 35027cf7d04SAleksandr Rybalko 0x80 | (c & 0x3f) 35127cf7d04SAleksandr Rybalko }; 35227cf7d04SAleksandr Rybalko 35327cf7d04SAleksandr Rybalko ttydisc_rint_simple(tp, str, sizeof str); 35427cf7d04SAleksandr Rybalko } 35527cf7d04SAleksandr Rybalko ttydisc_rint_done(tp); 35627cf7d04SAleksandr Rybalko tty_unlock(tp); 35727cf7d04SAleksandr Rybalko } 35827cf7d04SAleksandr Rybalko 35927cf7d04SAleksandr Rybalko void 36027cf7d04SAleksandr Rybalko terminal_input_raw(struct terminal *tm, char c) 36127cf7d04SAleksandr Rybalko { 36227cf7d04SAleksandr Rybalko struct tty *tp; 36327cf7d04SAleksandr Rybalko 36427cf7d04SAleksandr Rybalko tp = tm->tm_tty; 36527cf7d04SAleksandr Rybalko if (tp == NULL) 36627cf7d04SAleksandr Rybalko return; 36727cf7d04SAleksandr Rybalko 36827cf7d04SAleksandr Rybalko tty_lock(tp); 36927cf7d04SAleksandr Rybalko ttydisc_rint(tp, c, 0); 37027cf7d04SAleksandr Rybalko ttydisc_rint_done(tp); 37127cf7d04SAleksandr Rybalko tty_unlock(tp); 37227cf7d04SAleksandr Rybalko } 37327cf7d04SAleksandr Rybalko 37427cf7d04SAleksandr Rybalko void 37527cf7d04SAleksandr Rybalko terminal_input_special(struct terminal *tm, unsigned int k) 37627cf7d04SAleksandr Rybalko { 37727cf7d04SAleksandr Rybalko struct tty *tp; 37827cf7d04SAleksandr Rybalko const char *str; 37927cf7d04SAleksandr Rybalko 38027cf7d04SAleksandr Rybalko tp = tm->tm_tty; 38127cf7d04SAleksandr Rybalko if (tp == NULL) 38227cf7d04SAleksandr Rybalko return; 38327cf7d04SAleksandr Rybalko 38427cf7d04SAleksandr Rybalko str = teken_get_sequence(&tm->tm_emulator, k); 38527cf7d04SAleksandr Rybalko if (str == NULL) 38627cf7d04SAleksandr Rybalko return; 38727cf7d04SAleksandr Rybalko 38827cf7d04SAleksandr Rybalko tty_lock(tp); 38927cf7d04SAleksandr Rybalko ttydisc_rint_simple(tp, str, strlen(str)); 39027cf7d04SAleksandr Rybalko ttydisc_rint_done(tp); 39127cf7d04SAleksandr Rybalko tty_unlock(tp); 39227cf7d04SAleksandr Rybalko } 39327cf7d04SAleksandr Rybalko 39427cf7d04SAleksandr Rybalko /* 39527cf7d04SAleksandr Rybalko * Binding with the TTY layer. 39627cf7d04SAleksandr Rybalko */ 39727cf7d04SAleksandr Rybalko 39827cf7d04SAleksandr Rybalko static int 39927cf7d04SAleksandr Rybalko termtty_open(struct tty *tp) 40027cf7d04SAleksandr Rybalko { 40127cf7d04SAleksandr Rybalko struct terminal *tm = tty_softc(tp); 40227cf7d04SAleksandr Rybalko 40327cf7d04SAleksandr Rybalko tm->tm_class->tc_opened(tm, 1); 40427cf7d04SAleksandr Rybalko return (0); 40527cf7d04SAleksandr Rybalko } 40627cf7d04SAleksandr Rybalko 40727cf7d04SAleksandr Rybalko static void 40827cf7d04SAleksandr Rybalko termtty_close(struct tty *tp) 40927cf7d04SAleksandr Rybalko { 41027cf7d04SAleksandr Rybalko struct terminal *tm = tty_softc(tp); 41127cf7d04SAleksandr Rybalko 41227cf7d04SAleksandr Rybalko tm->tm_class->tc_opened(tm, 0); 41327cf7d04SAleksandr Rybalko } 41427cf7d04SAleksandr Rybalko 41527cf7d04SAleksandr Rybalko static void 41627cf7d04SAleksandr Rybalko termtty_outwakeup(struct tty *tp) 41727cf7d04SAleksandr Rybalko { 41827cf7d04SAleksandr Rybalko struct terminal *tm = tty_softc(tp); 41927cf7d04SAleksandr Rybalko char obuf[128]; 42027cf7d04SAleksandr Rybalko size_t olen; 42127cf7d04SAleksandr Rybalko unsigned int flags = 0; 42227cf7d04SAleksandr Rybalko 42327cf7d04SAleksandr Rybalko while ((olen = ttydisc_getc(tp, obuf, sizeof obuf)) > 0) { 42427cf7d04SAleksandr Rybalko TERMINAL_LOCK_TTY(tm); 42527cf7d04SAleksandr Rybalko if (!(tm->tm_flags & TF_MUTE)) { 42627cf7d04SAleksandr Rybalko tm->tm_flags &= ~TF_BELL; 42727cf7d04SAleksandr Rybalko teken_input(&tm->tm_emulator, obuf, olen); 42827cf7d04SAleksandr Rybalko flags |= tm->tm_flags; 42927cf7d04SAleksandr Rybalko } 43027cf7d04SAleksandr Rybalko TERMINAL_UNLOCK_TTY(tm); 43127cf7d04SAleksandr Rybalko } 43227cf7d04SAleksandr Rybalko 433c9cde825SJonathan T. Looney TERMINAL_LOCK_TTY(tm); 434c9cde825SJonathan T. Looney if (!(tm->tm_flags & TF_MUTE)) 43527cf7d04SAleksandr Rybalko tm->tm_class->tc_done(tm); 436c9cde825SJonathan T. Looney TERMINAL_UNLOCK_TTY(tm); 43727cf7d04SAleksandr Rybalko if (flags & TF_BELL) 43827cf7d04SAleksandr Rybalko tm->tm_class->tc_bell(tm); 43927cf7d04SAleksandr Rybalko } 44027cf7d04SAleksandr Rybalko 44127cf7d04SAleksandr Rybalko static int 44227cf7d04SAleksandr Rybalko termtty_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) 44327cf7d04SAleksandr Rybalko { 44427cf7d04SAleksandr Rybalko struct terminal *tm = tty_softc(tp); 44527cf7d04SAleksandr Rybalko int error; 44627cf7d04SAleksandr Rybalko 44727cf7d04SAleksandr Rybalko switch (cmd) { 44827cf7d04SAleksandr Rybalko case CONS_GETINFO: { 44927cf7d04SAleksandr Rybalko vid_info_t *vi = (vid_info_t *)data; 45027cf7d04SAleksandr Rybalko const teken_pos_t *p; 45127cf7d04SAleksandr Rybalko int fg, bg; 45227cf7d04SAleksandr Rybalko 45327cf7d04SAleksandr Rybalko if (vi->size != sizeof(vid_info_t)) 45427cf7d04SAleksandr Rybalko return (EINVAL); 45527cf7d04SAleksandr Rybalko 45627cf7d04SAleksandr Rybalko /* Already help the console driver by filling in some data. */ 45727cf7d04SAleksandr Rybalko p = teken_get_cursor(&tm->tm_emulator); 45827cf7d04SAleksandr Rybalko vi->mv_row = p->tp_row; 45927cf7d04SAleksandr Rybalko vi->mv_col = p->tp_col; 46027cf7d04SAleksandr Rybalko 46127cf7d04SAleksandr Rybalko p = teken_get_winsize(&tm->tm_emulator); 46227cf7d04SAleksandr Rybalko vi->mv_rsz = p->tp_row; 46327cf7d04SAleksandr Rybalko vi->mv_csz = p->tp_col; 46427cf7d04SAleksandr Rybalko 46527cf7d04SAleksandr Rybalko teken_get_defattr_cons25(&tm->tm_emulator, &fg, &bg); 46627cf7d04SAleksandr Rybalko vi->mv_norm.fore = fg; 46727cf7d04SAleksandr Rybalko vi->mv_norm.back = bg; 46827cf7d04SAleksandr Rybalko /* XXX: keep vidcontrol happy; bold backgrounds. */ 46927cf7d04SAleksandr Rybalko vi->mv_rev.fore = bg; 47027cf7d04SAleksandr Rybalko vi->mv_rev.back = fg & 0x7; 47127cf7d04SAleksandr Rybalko break; 47227cf7d04SAleksandr Rybalko } 47327cf7d04SAleksandr Rybalko } 47427cf7d04SAleksandr Rybalko 47527cf7d04SAleksandr Rybalko /* 47627cf7d04SAleksandr Rybalko * Unlike various other drivers, this driver will never 47727cf7d04SAleksandr Rybalko * deallocate TTYs. This means it's safe to temporarily unlock 47827cf7d04SAleksandr Rybalko * the TTY when handling ioctls. 47927cf7d04SAleksandr Rybalko */ 48027cf7d04SAleksandr Rybalko tty_unlock(tp); 48127cf7d04SAleksandr Rybalko error = tm->tm_class->tc_ioctl(tm, cmd, data, td); 48227cf7d04SAleksandr Rybalko tty_lock(tp); 483ef1eabcaSJason A. Harmening if ((error == 0) && (cmd == CONS_CLRHIST)) { 484ef1eabcaSJason A. Harmening /* 485ef1eabcaSJason A. Harmening * Scrollback history has been successfully cleared, 486ef1eabcaSJason A. Harmening * so reset the cursor position to the top left of the screen. 487ef1eabcaSJason A. Harmening */ 488ef1eabcaSJason A. Harmening teken_pos_t p; 489ef1eabcaSJason A. Harmening p.tp_row = 0; 490ef1eabcaSJason A. Harmening p.tp_col = 0; 491ef1eabcaSJason A. Harmening teken_set_cursor(&tm->tm_emulator, &p); 492ef1eabcaSJason A. Harmening } 49327cf7d04SAleksandr Rybalko return (error); 49427cf7d04SAleksandr Rybalko } 49527cf7d04SAleksandr Rybalko 4967a1a32c4SAleksandr Rybalko static int 4977a1a32c4SAleksandr Rybalko termtty_mmap(struct tty *tp, vm_ooffset_t offset, vm_paddr_t * paddr, 4987a1a32c4SAleksandr Rybalko int nprot, vm_memattr_t *memattr) 4997a1a32c4SAleksandr Rybalko { 5007a1a32c4SAleksandr Rybalko struct terminal *tm = tty_softc(tp); 5017a1a32c4SAleksandr Rybalko 5027a1a32c4SAleksandr Rybalko return (tm->tm_class->tc_mmap(tm, offset, paddr, nprot, memattr)); 5037a1a32c4SAleksandr Rybalko } 5047a1a32c4SAleksandr Rybalko 50527cf7d04SAleksandr Rybalko /* 50627cf7d04SAleksandr Rybalko * Binding with the kernel and debug console. 50727cf7d04SAleksandr Rybalko */ 50827cf7d04SAleksandr Rybalko 50927cf7d04SAleksandr Rybalko static cn_probe_t termcn_cnprobe; 51027cf7d04SAleksandr Rybalko static cn_init_t termcn_cninit; 51127cf7d04SAleksandr Rybalko static cn_term_t termcn_cnterm; 51227cf7d04SAleksandr Rybalko static cn_getc_t termcn_cngetc; 51327cf7d04SAleksandr Rybalko static cn_putc_t termcn_cnputc; 51427cf7d04SAleksandr Rybalko static cn_grab_t termcn_cngrab; 51527cf7d04SAleksandr Rybalko static cn_ungrab_t termcn_cnungrab; 51627cf7d04SAleksandr Rybalko 51727cf7d04SAleksandr Rybalko const struct consdev_ops termcn_cnops = { 51827cf7d04SAleksandr Rybalko .cn_probe = termcn_cnprobe, 51927cf7d04SAleksandr Rybalko .cn_init = termcn_cninit, 52027cf7d04SAleksandr Rybalko .cn_term = termcn_cnterm, 52127cf7d04SAleksandr Rybalko .cn_getc = termcn_cngetc, 52227cf7d04SAleksandr Rybalko .cn_putc = termcn_cnputc, 52327cf7d04SAleksandr Rybalko .cn_grab = termcn_cngrab, 52427cf7d04SAleksandr Rybalko .cn_ungrab = termcn_cnungrab, 52527cf7d04SAleksandr Rybalko }; 52627cf7d04SAleksandr Rybalko 52727cf7d04SAleksandr Rybalko void 52827cf7d04SAleksandr Rybalko termcn_cnregister(struct terminal *tm) 52927cf7d04SAleksandr Rybalko { 53027cf7d04SAleksandr Rybalko struct consdev *cp; 53127cf7d04SAleksandr Rybalko 53227cf7d04SAleksandr Rybalko cp = tm->consdev; 53327cf7d04SAleksandr Rybalko if (cp == NULL) { 53427cf7d04SAleksandr Rybalko cp = malloc(sizeof(struct consdev), M_TERMINAL, 53527cf7d04SAleksandr Rybalko M_WAITOK|M_ZERO); 53627cf7d04SAleksandr Rybalko cp->cn_ops = &termcn_cnops; 53727cf7d04SAleksandr Rybalko cp->cn_arg = tm; 53827cf7d04SAleksandr Rybalko cp->cn_pri = CN_INTERNAL; 53927cf7d04SAleksandr Rybalko sprintf(cp->cn_name, "ttyv0"); 54027cf7d04SAleksandr Rybalko 54127cf7d04SAleksandr Rybalko tm->tm_flags = TF_CONS; 54227cf7d04SAleksandr Rybalko tm->consdev = cp; 54327cf7d04SAleksandr Rybalko 54427cf7d04SAleksandr Rybalko terminal_init(tm); 54527cf7d04SAleksandr Rybalko } 54627cf7d04SAleksandr Rybalko 54727cf7d04SAleksandr Rybalko /* Attach terminal as console. */ 54827cf7d04SAleksandr Rybalko cnadd(cp); 54927cf7d04SAleksandr Rybalko } 55027cf7d04SAleksandr Rybalko 55127cf7d04SAleksandr Rybalko static void 55227cf7d04SAleksandr Rybalko termcn_cngrab(struct consdev *cp) 55327cf7d04SAleksandr Rybalko { 5543e206539SJean-Sébastien Pédron struct terminal *tm = cp->cn_arg; 55527cf7d04SAleksandr Rybalko 5563e206539SJean-Sébastien Pédron tm->tm_class->tc_cngrab(tm); 55727cf7d04SAleksandr Rybalko } 55827cf7d04SAleksandr Rybalko 55927cf7d04SAleksandr Rybalko static void 56027cf7d04SAleksandr Rybalko termcn_cnungrab(struct consdev *cp) 56127cf7d04SAleksandr Rybalko { 5623e206539SJean-Sébastien Pédron struct terminal *tm = cp->cn_arg; 56327cf7d04SAleksandr Rybalko 5643e206539SJean-Sébastien Pédron tm->tm_class->tc_cnungrab(tm); 56527cf7d04SAleksandr Rybalko } 56627cf7d04SAleksandr Rybalko 56727cf7d04SAleksandr Rybalko static void 56827cf7d04SAleksandr Rybalko termcn_cnprobe(struct consdev *cp) 56927cf7d04SAleksandr Rybalko { 57027cf7d04SAleksandr Rybalko struct terminal *tm = cp->cn_arg; 57127cf7d04SAleksandr Rybalko 57227cf7d04SAleksandr Rybalko if (tm == NULL) { 57327cf7d04SAleksandr Rybalko cp->cn_pri = CN_DEAD; 57427cf7d04SAleksandr Rybalko return; 57527cf7d04SAleksandr Rybalko } 57627cf7d04SAleksandr Rybalko 57727cf7d04SAleksandr Rybalko tm->consdev = cp; 57827cf7d04SAleksandr Rybalko terminal_init(tm); 57927cf7d04SAleksandr Rybalko 58027cf7d04SAleksandr Rybalko tm->tm_class->tc_cnprobe(tm, cp); 58127cf7d04SAleksandr Rybalko } 58227cf7d04SAleksandr Rybalko 58327cf7d04SAleksandr Rybalko static void 58427cf7d04SAleksandr Rybalko termcn_cninit(struct consdev *cp) 58527cf7d04SAleksandr Rybalko { 58627cf7d04SAleksandr Rybalko 58727cf7d04SAleksandr Rybalko } 58827cf7d04SAleksandr Rybalko 58927cf7d04SAleksandr Rybalko static void 59027cf7d04SAleksandr Rybalko termcn_cnterm(struct consdev *cp) 59127cf7d04SAleksandr Rybalko { 59227cf7d04SAleksandr Rybalko 59327cf7d04SAleksandr Rybalko } 59427cf7d04SAleksandr Rybalko 59527cf7d04SAleksandr Rybalko static int 59627cf7d04SAleksandr Rybalko termcn_cngetc(struct consdev *cp) 59727cf7d04SAleksandr Rybalko { 59827cf7d04SAleksandr Rybalko struct terminal *tm = cp->cn_arg; 59927cf7d04SAleksandr Rybalko 60027cf7d04SAleksandr Rybalko return (tm->tm_class->tc_cngetc(tm)); 60127cf7d04SAleksandr Rybalko } 60227cf7d04SAleksandr Rybalko 60327cf7d04SAleksandr Rybalko static void 60427cf7d04SAleksandr Rybalko termcn_cnputc(struct consdev *cp, int c) 60527cf7d04SAleksandr Rybalko { 60627cf7d04SAleksandr Rybalko struct terminal *tm = cp->cn_arg; 60727cf7d04SAleksandr Rybalko teken_attr_t backup; 60827cf7d04SAleksandr Rybalko char cv = c; 60927cf7d04SAleksandr Rybalko 61027cf7d04SAleksandr Rybalko TERMINAL_LOCK_CONS(tm); 61127cf7d04SAleksandr Rybalko if (!(tm->tm_flags & TF_MUTE)) { 61227cf7d04SAleksandr Rybalko backup = *teken_get_curattr(&tm->tm_emulator); 61327cf7d04SAleksandr Rybalko teken_set_curattr(&tm->tm_emulator, &kernel_message); 61427cf7d04SAleksandr Rybalko teken_input(&tm->tm_emulator, &cv, 1); 61527cf7d04SAleksandr Rybalko teken_set_curattr(&tm->tm_emulator, &backup); 616c9cde825SJonathan T. Looney tm->tm_class->tc_done(tm); 61727cf7d04SAleksandr Rybalko } 61827cf7d04SAleksandr Rybalko TERMINAL_UNLOCK_CONS(tm); 61927cf7d04SAleksandr Rybalko } 62027cf7d04SAleksandr Rybalko 62127cf7d04SAleksandr Rybalko /* 62227cf7d04SAleksandr Rybalko * Binding with the terminal emulator. 62327cf7d04SAleksandr Rybalko */ 62427cf7d04SAleksandr Rybalko 62527cf7d04SAleksandr Rybalko static void 62627cf7d04SAleksandr Rybalko termteken_bell(void *softc) 62727cf7d04SAleksandr Rybalko { 62827cf7d04SAleksandr Rybalko struct terminal *tm = softc; 62927cf7d04SAleksandr Rybalko 63027cf7d04SAleksandr Rybalko tm->tm_flags |= TF_BELL; 63127cf7d04SAleksandr Rybalko } 63227cf7d04SAleksandr Rybalko 63327cf7d04SAleksandr Rybalko static void 63427cf7d04SAleksandr Rybalko termteken_cursor(void *softc, const teken_pos_t *p) 63527cf7d04SAleksandr Rybalko { 63627cf7d04SAleksandr Rybalko struct terminal *tm = softc; 63727cf7d04SAleksandr Rybalko 63827cf7d04SAleksandr Rybalko tm->tm_class->tc_cursor(tm, p); 63927cf7d04SAleksandr Rybalko } 64027cf7d04SAleksandr Rybalko 64127cf7d04SAleksandr Rybalko static void 64227cf7d04SAleksandr Rybalko termteken_putchar(void *softc, const teken_pos_t *p, teken_char_t c, 64327cf7d04SAleksandr Rybalko const teken_attr_t *a) 64427cf7d04SAleksandr Rybalko { 64527cf7d04SAleksandr Rybalko struct terminal *tm = softc; 64627cf7d04SAleksandr Rybalko 64727cf7d04SAleksandr Rybalko tm->tm_class->tc_putchar(tm, p, TCHAR_CREATE(c, a)); 64827cf7d04SAleksandr Rybalko } 64927cf7d04SAleksandr Rybalko 65027cf7d04SAleksandr Rybalko static void 65127cf7d04SAleksandr Rybalko termteken_fill(void *softc, const teken_rect_t *r, teken_char_t c, 65227cf7d04SAleksandr Rybalko const teken_attr_t *a) 65327cf7d04SAleksandr Rybalko { 65427cf7d04SAleksandr Rybalko struct terminal *tm = softc; 65527cf7d04SAleksandr Rybalko 65627cf7d04SAleksandr Rybalko tm->tm_class->tc_fill(tm, r, TCHAR_CREATE(c, a)); 65727cf7d04SAleksandr Rybalko } 65827cf7d04SAleksandr Rybalko 65927cf7d04SAleksandr Rybalko static void 66027cf7d04SAleksandr Rybalko termteken_copy(void *softc, const teken_rect_t *r, const teken_pos_t *p) 66127cf7d04SAleksandr Rybalko { 66227cf7d04SAleksandr Rybalko struct terminal *tm = softc; 66327cf7d04SAleksandr Rybalko 66427cf7d04SAleksandr Rybalko tm->tm_class->tc_copy(tm, r, p); 66527cf7d04SAleksandr Rybalko } 66627cf7d04SAleksandr Rybalko 66727cf7d04SAleksandr Rybalko static void 668547e74a8SJean-Sébastien Pédron termteken_pre_input(void *softc) 669547e74a8SJean-Sébastien Pédron { 670547e74a8SJean-Sébastien Pédron struct terminal *tm = softc; 671547e74a8SJean-Sébastien Pédron 672547e74a8SJean-Sébastien Pédron tm->tm_class->tc_pre_input(tm); 673547e74a8SJean-Sébastien Pédron } 674547e74a8SJean-Sébastien Pédron 675547e74a8SJean-Sébastien Pédron static void 676547e74a8SJean-Sébastien Pédron termteken_post_input(void *softc) 677547e74a8SJean-Sébastien Pédron { 678547e74a8SJean-Sébastien Pédron struct terminal *tm = softc; 679547e74a8SJean-Sébastien Pédron 680547e74a8SJean-Sébastien Pédron tm->tm_class->tc_post_input(tm); 681547e74a8SJean-Sébastien Pédron } 682547e74a8SJean-Sébastien Pédron 683547e74a8SJean-Sébastien Pédron static void 68427cf7d04SAleksandr Rybalko termteken_param(void *softc, int cmd, unsigned int arg) 68527cf7d04SAleksandr Rybalko { 68627cf7d04SAleksandr Rybalko struct terminal *tm = softc; 68727cf7d04SAleksandr Rybalko 68827cf7d04SAleksandr Rybalko tm->tm_class->tc_param(tm, cmd, arg); 68927cf7d04SAleksandr Rybalko } 69027cf7d04SAleksandr Rybalko 69127cf7d04SAleksandr Rybalko static void 69227cf7d04SAleksandr Rybalko termteken_respond(void *softc, const void *buf, size_t len) 69327cf7d04SAleksandr Rybalko { 69427cf7d04SAleksandr Rybalko #if 0 69527cf7d04SAleksandr Rybalko struct terminal *tm = softc; 69627cf7d04SAleksandr Rybalko struct tty *tp; 69727cf7d04SAleksandr Rybalko 69827cf7d04SAleksandr Rybalko /* 69927cf7d04SAleksandr Rybalko * Only inject a response into the TTY if the data actually 70027cf7d04SAleksandr Rybalko * originated from the TTY. 70127cf7d04SAleksandr Rybalko * 70227cf7d04SAleksandr Rybalko * XXX: This cannot be done right now. The TTY could pick up 70327cf7d04SAleksandr Rybalko * other locks. It could also in theory cause loops, when the 70427cf7d04SAleksandr Rybalko * TTY performs echoing of a command that generates even more 70527cf7d04SAleksandr Rybalko * input. 70627cf7d04SAleksandr Rybalko */ 70727cf7d04SAleksandr Rybalko tp = tm->tm_tty; 70827cf7d04SAleksandr Rybalko if (tp == NULL) 70927cf7d04SAleksandr Rybalko return; 71027cf7d04SAleksandr Rybalko 71127cf7d04SAleksandr Rybalko ttydisc_rint_simple(tp, buf, len); 71227cf7d04SAleksandr Rybalko ttydisc_rint_done(tp); 71327cf7d04SAleksandr Rybalko #endif 71427cf7d04SAleksandr Rybalko } 715