xref: /freebsd/sys/kern/subr_terminal.c (revision ef1eabca)
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