subr_terminal.c revision 263817
1319780Sdim/*- 2319780Sdim * Copyright (c) 2009 The FreeBSD Foundation 3319780Sdim * All rights reserved. 4319780Sdim * 5319780Sdim * This software was developed by Ed Schouten under sponsorship from the 6319780Sdim * FreeBSD Foundation. 7319780Sdim * 8319780Sdim * Redistribution and use in source and binary forms, with or without 9319780Sdim * modification, are permitted provided that the following conditions 10319780Sdim * are met: 11319780Sdim * 1. Redistributions of source code must retain the above copyright 12319780Sdim * notice, this list of conditions and the following disclaimer. 13319780Sdim * 2. Redistributions in binary form must reproduce the above copyright 14319780Sdim * notice, this list of conditions and the following disclaimer in the 15319780Sdim * documentation and/or other materials provided with the distribution. 16319780Sdim * 17320397Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18319780Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19320397Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20319780Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21319780Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22319780Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23319780Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24319780Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25319780Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26319780Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27319780Sdim * SUCH DAMAGE. 28319780Sdim */ 29319780Sdim 30319780Sdim#include <sys/cdefs.h> 31319780Sdim__FBSDID("$FreeBSD: stable/9/sys/kern/subr_terminal.c 263817 2014-03-27 15:58:18Z ray $"); 32319780Sdim 33319780Sdim#include <sys/param.h> 34319780Sdim#include <sys/cons.h> 35319780Sdim#include <sys/consio.h> 36319780Sdim#include <sys/kernel.h> 37319780Sdim#include <sys/lock.h> 38319780Sdim#include <sys/malloc.h> 39320041Sdim#include <sys/mutex.h> 40319780Sdim#include <sys/systm.h> 41319780Sdim#include <sys/terminal.h> 42319780Sdim#include <sys/tty.h> 43319780Sdim 44319780Sdim#include <machine/stdarg.h> 45319780Sdim 46319780Sdimstatic MALLOC_DEFINE(M_TERMINAL, "terminal", "terminal device"); 47319780Sdim 48319780Sdim/* 49319780Sdim * Locking. 50319780Sdim * 51319780Sdim * Normally we don't need to lock down the terminal emulator, because 52319780Sdim * the TTY lock is already held when calling teken_input(). 53319780Sdim * Unfortunately this is not the case when the terminal acts as a 54319780Sdim * console device, because cnputc() can be called at the same time. 55319780Sdim * This means terminals may need to be locked down using a spin lock. 56319780Sdim */ 57319780Sdim#define TERMINAL_LOCK(tm) do { \ 58319780Sdim if ((tm)->tm_flags & TF_CONS) \ 59319780Sdim mtx_lock_spin(&(tm)->tm_mtx); \ 60319780Sdim else if ((tm)->tm_tty != NULL) \ 61319780Sdim tty_lock((tm)->tm_tty); \ 62319780Sdim} while (0) 63319780Sdim#define TERMINAL_UNLOCK(tm) do { \ 64319780Sdim if ((tm)->tm_flags & TF_CONS) \ 65319780Sdim mtx_unlock_spin(&(tm)->tm_mtx); \ 66319780Sdim else if ((tm)->tm_tty != NULL) \ 67319780Sdim tty_unlock((tm)->tm_tty); \ 68319780Sdim} while (0) 69319780Sdim#define TERMINAL_LOCK_TTY(tm) do { \ 70319780Sdim if ((tm)->tm_flags & TF_CONS) \ 71319780Sdim mtx_lock_spin(&(tm)->tm_mtx); \ 72319780Sdim} while (0) 73319780Sdim#define TERMINAL_UNLOCK_TTY(tm) do { \ 74319780Sdim if ((tm)->tm_flags & TF_CONS) \ 75319780Sdim mtx_unlock_spin(&(tm)->tm_mtx); \ 76319780Sdim} while (0) 77319780Sdim#define TERMINAL_LOCK_CONS(tm) mtx_lock_spin(&(tm)->tm_mtx) 78319780Sdim#define TERMINAL_UNLOCK_CONS(tm) mtx_unlock_spin(&(tm)->tm_mtx) 79319780Sdim 80319780Sdim/* 81319780Sdim * TTY routines. 82319780Sdim */ 83319780Sdim 84319780Sdimstatic tsw_open_t termtty_open; 85319780Sdimstatic tsw_close_t termtty_close; 86319780Sdimstatic tsw_outwakeup_t termtty_outwakeup; 87319780Sdimstatic tsw_ioctl_t termtty_ioctl; 88319780Sdimstatic tsw_mmap_t termtty_mmap; 89319780Sdim 90320397Sdimstatic struct ttydevsw terminal_tty_class = { 91320397Sdim .tsw_open = termtty_open, 92320397Sdim .tsw_close = termtty_close, 93319780Sdim .tsw_outwakeup = termtty_outwakeup, 94319780Sdim .tsw_ioctl = termtty_ioctl, 95319780Sdim .tsw_mmap = termtty_mmap, 96319780Sdim}; 97319780Sdim 98319780Sdim/* 99319780Sdim * Terminal emulator routines. 100319780Sdim */ 101319780Sdim 102319780Sdimstatic tf_bell_t termteken_bell; 103319780Sdimstatic tf_cursor_t termteken_cursor; 104319780Sdimstatic tf_putchar_t termteken_putchar; 105319780Sdimstatic tf_fill_t termteken_fill; 106319780Sdimstatic tf_copy_t termteken_copy; 107319780Sdimstatic tf_param_t termteken_param; 108319780Sdimstatic tf_respond_t termteken_respond; 109319780Sdim 110319780Sdimstatic teken_funcs_t terminal_drawmethods = { 111319780Sdim .tf_bell = termteken_bell, 112319780Sdim .tf_cursor = termteken_cursor, 113319780Sdim .tf_putchar = termteken_putchar, 114319780Sdim .tf_fill = termteken_fill, 115319780Sdim .tf_copy = termteken_copy, 116319780Sdim .tf_param = termteken_param, 117320397Sdim .tf_respond = termteken_respond, 118320397Sdim}; 119320397Sdim 120320397Sdim/* Kernel message formatting. */ 121320397Sdimstatic const teken_attr_t kernel_message = { 122320397Sdim .ta_fgcolor = TC_WHITE, 123320397Sdim .ta_bgcolor = TC_BLACK, 124320397Sdim .ta_format = TF_BOLD, 125320397Sdim}; 126320397Sdim 127320397Sdimstatic const teken_attr_t default_message = { 128320397Sdim .ta_fgcolor = TC_WHITE, 129320397Sdim .ta_bgcolor = TC_BLACK, 130320397Sdim}; 131320397Sdim 132320397Sdim#define TCHAR_CREATE(c, a) ((c) | \ 133320397Sdim (a)->ta_format << 21 | \ 134320397Sdim teken_256to8((a)->ta_fgcolor) << 26 | \ 135320397Sdim teken_256to8((a)->ta_bgcolor) << 29) 136320397Sdim 137320397Sdimstatic void 138320397Sdimterminal_init(struct terminal *tm) 139320397Sdim{ 140320397Sdim 141320397Sdim if (tm->tm_flags & TF_CONS) 142319780Sdim mtx_init(&tm->tm_mtx, "trmlck", NULL, MTX_SPIN); 143319780Sdim teken_init(&tm->tm_emulator, &terminal_drawmethods, tm); 144319780Sdim teken_set_defattr(&tm->tm_emulator, &default_message); 145319780Sdim} 146319780Sdim 147319780Sdimstruct terminal * 148319780Sdimterminal_alloc(const struct terminal_class *tc, void *softc) 149319780Sdim{ 150319780Sdim struct terminal *tm; 151319780Sdim 152319780Sdim tm = malloc(sizeof(struct terminal), M_TERMINAL, M_WAITOK|M_ZERO); 153319780Sdim terminal_init(tm); 154319780Sdim 155319780Sdim tm->tm_class = tc; 156319780Sdim tm->tm_softc = softc; 157319780Sdim 158319780Sdim return (tm); 159319780Sdim} 160319780Sdim 161319780Sdimstatic void 162319780Sdimterminal_sync_ttysize(struct terminal *tm) 163319780Sdim{ 164319780Sdim struct tty *tp; 165319780Sdim 166319780Sdim tp = tm->tm_tty; 167319780Sdim if (tp == NULL) 168319780Sdim return; 169319780Sdim 170319780Sdim tty_lock(tp); 171319780Sdim tty_set_winsize(tp, &tm->tm_winsize); 172319780Sdim tty_unlock(tp); 173319780Sdim} 174319780Sdim 175319780Sdimvoid 176319780Sdimterminal_maketty(struct terminal *tm, const char *fmt, ...) 177319780Sdim{ 178319780Sdim struct tty *tp; 179319780Sdim char name[8]; 180319780Sdim va_list ap; 181319780Sdim 182319780Sdim va_start(ap, fmt); 183319780Sdim vsnrprintf(name, sizeof name, 32, fmt, ap); 184319780Sdim va_end(ap); 185319780Sdim 186319780Sdim tp = tty_alloc(&terminal_tty_class, tm); 187319780Sdim tty_makedev(tp, NULL, "%s", name); 188319780Sdim tm->tm_tty = tp; 189319780Sdim terminal_sync_ttysize(tm); 190319780Sdim} 191319780Sdim 192319780Sdimvoid 193319780Sdimterminal_set_winsize_blank(struct terminal *tm, const struct winsize *size, 194319780Sdim int blank) 195319780Sdim{ 196319780Sdim term_rect_t r; 197319780Sdim 198319780Sdim tm->tm_winsize = *size; 199319780Sdim 200319780Sdim r.tr_begin.tp_row = r.tr_begin.tp_col = 0; 201319780Sdim r.tr_end.tp_row = size->ws_row; 202319780Sdim r.tr_end.tp_col = size->ws_col; 203319780Sdim 204319780Sdim TERMINAL_LOCK(tm); 205319780Sdim if (blank == 0) 206319780Sdim teken_set_winsize_noreset(&tm->tm_emulator, &r.tr_end); 207319780Sdim else 208319780Sdim teken_set_winsize(&tm->tm_emulator, &r.tr_end); 209319780Sdim TERMINAL_UNLOCK(tm); 210319780Sdim 211319780Sdim if (blank != 0) 212319780Sdim tm->tm_class->tc_fill(tm, &r, TCHAR_CREATE((teken_char_t)' ', 213319780Sdim &default_message)); 214319780Sdim 215319780Sdim terminal_sync_ttysize(tm); 216319780Sdim} 217319780Sdim 218319780Sdimvoid 219319780Sdimterminal_set_winsize(struct terminal *tm, const struct winsize *size) 220319780Sdim{ 221319780Sdim 222319780Sdim terminal_set_winsize_blank(tm, size, 1); 223319780Sdim} 224319780Sdim 225319780Sdim/* 226319780Sdim * XXX: This function is a kludge. Drivers like vt(4) need to 227319780Sdim * temporarily stop input when resizing, etc. This should ideally be 228319780Sdim * handled within the driver. 229319780Sdim */ 230319780Sdim 231319780Sdimvoid 232319780Sdimterminal_mute(struct terminal *tm, int yes) 233319780Sdim{ 234319780Sdim 235319780Sdim TERMINAL_LOCK(tm); 236319780Sdim if (yes) 237319780Sdim tm->tm_flags |= TF_MUTE; 238319780Sdim else 239319780Sdim tm->tm_flags &= ~TF_MUTE; 240319780Sdim TERMINAL_UNLOCK(tm); 241319780Sdim} 242319780Sdim 243319780Sdimvoid 244319780Sdimterminal_input_char(struct terminal *tm, term_char_t c) 245319780Sdim{ 246319780Sdim struct tty *tp; 247319780Sdim 248319780Sdim tp = tm->tm_tty; 249319780Sdim if (tp == NULL) 250319780Sdim return; 251319780Sdim 252319780Sdim /* 253319780Sdim * Strip off any attributes. Also ignore input of second part of 254319780Sdim * CJK fullwidth characters, as we don't want to return these 255319780Sdim * characters twice. 256319780Sdim */ 257319780Sdim if (TCHAR_FORMAT(c) & TF_CJK_RIGHT) 258319780Sdim return; 259319780Sdim c = TCHAR_CHARACTER(c); 260319780Sdim 261319780Sdim tty_lock(tp); 262319780Sdim /* 263319780Sdim * Conversion to UTF-8. 264319780Sdim */ 265319780Sdim if (c < 0x80) { 266319780Sdim ttydisc_rint(tp, c, 0); 267319780Sdim } else if (c < 0x800) { 268319780Sdim char str[2] = { 269319780Sdim 0xc0 | (c >> 6), 270319780Sdim 0x80 | (c & 0x3f) 271319780Sdim }; 272319780Sdim 273319780Sdim ttydisc_rint_simple(tp, str, sizeof str); 274319780Sdim } else if (c < 0x10000) { 275319780Sdim char str[3] = { 276319780Sdim 0xe0 | (c >> 12), 277319780Sdim 0x80 | ((c >> 6) & 0x3f), 278319780Sdim 0x80 | (c & 0x3f) 279319780Sdim }; 280319780Sdim 281319780Sdim ttydisc_rint_simple(tp, str, sizeof str); 282319780Sdim } else { 283319780Sdim char str[4] = { 284319780Sdim 0xf0 | (c >> 18), 285319780Sdim 0x80 | ((c >> 12) & 0x3f), 286319780Sdim 0x80 | ((c >> 6) & 0x3f), 287320970Sdim 0x80 | (c & 0x3f) 288320970Sdim }; 289320970Sdim 290320970Sdim ttydisc_rint_simple(tp, str, sizeof str); 291320970Sdim } 292320970Sdim ttydisc_rint_done(tp); 293320970Sdim tty_unlock(tp); 294320970Sdim} 295320970Sdim 296320970Sdimvoid 297320970Sdimterminal_input_raw(struct terminal *tm, char c) 298320970Sdim{ 299320970Sdim struct tty *tp; 300320970Sdim 301320970Sdim tp = tm->tm_tty; 302320970Sdim if (tp == NULL) 303320970Sdim return; 304320970Sdim 305320970Sdim tty_lock(tp); 306320970Sdim ttydisc_rint(tp, c, 0); 307320970Sdim ttydisc_rint_done(tp); 308320970Sdim tty_unlock(tp); 309320970Sdim} 310320970Sdim 311320970Sdimvoid 312320970Sdimterminal_input_special(struct terminal *tm, unsigned int k) 313319780Sdim{ 314319780Sdim struct tty *tp; 315320041Sdim const char *str; 316320041Sdim 317320397Sdim tp = tm->tm_tty; 318320397Sdim if (tp == NULL) 319320397Sdim return; 320320397Sdim 321320397Sdim str = teken_get_sequence(&tm->tm_emulator, k); 322320397Sdim if (str == NULL) 323319780Sdim return; 324320397Sdim 325320397Sdim tty_lock(tp); 326320397Sdim ttydisc_rint_simple(tp, str, strlen(str)); 327320397Sdim ttydisc_rint_done(tp); 328320397Sdim tty_unlock(tp); 329320397Sdim} 330320397Sdim 331320397Sdim/* 332320397Sdim * Binding with the TTY layer. 333320397Sdim */ 334320397Sdim 335320397Sdimstatic int 336320397Sdimtermtty_open(struct tty *tp) 337320397Sdim{ 338320397Sdim struct terminal *tm = tty_softc(tp); 339320397Sdim 340320397Sdim tm->tm_class->tc_opened(tm, 1); 341320397Sdim return (0); 342320397Sdim} 343320397Sdim 344320397Sdimstatic void 345320397Sdimtermtty_close(struct tty *tp) 346320397Sdim{ 347320397Sdim struct terminal *tm = tty_softc(tp); 348320397Sdim 349320397Sdim tm->tm_class->tc_opened(tm, 0); 350320397Sdim} 351320397Sdim 352320397Sdimstatic void 353320397Sdimtermtty_outwakeup(struct tty *tp) 354320397Sdim{ 355320397Sdim struct terminal *tm = tty_softc(tp); 356320397Sdim char obuf[128]; 357320397Sdim size_t olen; 358320397Sdim unsigned int flags = 0; 359320397Sdim 360320397Sdim while ((olen = ttydisc_getc(tp, obuf, sizeof obuf)) > 0) { 361320397Sdim TERMINAL_LOCK_TTY(tm); 362320397Sdim if (!(tm->tm_flags & TF_MUTE)) { 363320397Sdim tm->tm_flags &= ~TF_BELL; 364320397Sdim teken_input(&tm->tm_emulator, obuf, olen); 365320397Sdim flags |= tm->tm_flags; 366320397Sdim } 367320397Sdim TERMINAL_UNLOCK_TTY(tm); 368320397Sdim } 369320397Sdim 370320397Sdim tm->tm_class->tc_done(tm); 371320397Sdim if (flags & TF_BELL) 372320397Sdim tm->tm_class->tc_bell(tm); 373320397Sdim} 374320397Sdim 375320397Sdimstatic int 376320397Sdimtermtty_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) 377320397Sdim{ 378320397Sdim struct terminal *tm = tty_softc(tp); 379320397Sdim int error; 380320397Sdim 381320397Sdim switch (cmd) { 382320397Sdim case CONS_GETINFO: { 383320397Sdim vid_info_t *vi = (vid_info_t *)data; 384320397Sdim const teken_pos_t *p; 385320397Sdim int fg, bg; 386320397Sdim 387320397Sdim if (vi->size != sizeof(vid_info_t)) 388320397Sdim return (EINVAL); 389320397Sdim 390320397Sdim /* Already help the console driver by filling in some data. */ 391320397Sdim p = teken_get_cursor(&tm->tm_emulator); 392320397Sdim vi->mv_row = p->tp_row; 393320397Sdim vi->mv_col = p->tp_col; 394320397Sdim 395319780Sdim p = teken_get_winsize(&tm->tm_emulator); 396319780Sdim vi->mv_rsz = p->tp_row; 397319780Sdim vi->mv_csz = p->tp_col; 398319780Sdim 399319780Sdim teken_get_defattr_cons25(&tm->tm_emulator, &fg, &bg); 400319780Sdim vi->mv_norm.fore = fg; 401320041Sdim vi->mv_norm.back = bg; 402320397Sdim /* XXX: keep vidcontrol happy; bold backgrounds. */ 403320041Sdim vi->mv_rev.fore = bg; 404320041Sdim vi->mv_rev.back = fg & 0x7; 405320397Sdim break; 406320397Sdim } 407320397Sdim } 408320397Sdim 409320397Sdim /* 410319780Sdim * Unlike various other drivers, this driver will never 411319780Sdim * deallocate TTYs. This means it's safe to temporarily unlock 412320041Sdim * the TTY when handling ioctls. 413320041Sdim */ 414320397Sdim tty_unlock(tp); 415320041Sdim error = tm->tm_class->tc_ioctl(tm, cmd, data, td); 416320041Sdim tty_lock(tp); 417319780Sdim return (error); 418320397Sdim} 419320041Sdim 420320041Sdimstatic int 421320041Sdimtermtty_mmap(struct tty *tp, vm_ooffset_t offset, vm_paddr_t * paddr, 422320397Sdim int nprot, vm_memattr_t *memattr) 423320041Sdim{ 424320397Sdim struct terminal *tm = tty_softc(tp); 425320970Sdim 426320397Sdim return (tm->tm_class->tc_mmap(tm, offset, paddr, nprot, memattr)); 427320397Sdim} 428320397Sdim 429320041Sdim/* 430320041Sdim * Binding with the kernel and debug console. 431320397Sdim */ 432319780Sdim 433320041Sdimstatic cn_probe_t termcn_cnprobe; 434320041Sdimstatic cn_init_t termcn_cninit; 435320397Sdimstatic cn_term_t termcn_cnterm; 436319780Sdimstatic cn_getc_t termcn_cngetc; 437320041Sdimstatic cn_putc_t termcn_cnputc; 438320041Sdimstatic cn_grab_t termcn_cngrab; 439320397Sdimstatic cn_ungrab_t termcn_cnungrab; 440320397Sdim 441320970Sdimconst struct consdev_ops termcn_cnops = { 442320397Sdim .cn_probe = termcn_cnprobe, 443320397Sdim .cn_init = termcn_cninit, 444320041Sdim .cn_term = termcn_cnterm, 445320572Sdim .cn_getc = termcn_cngetc, 446320572Sdim .cn_putc = termcn_cnputc, 447320572Sdim .cn_grab = termcn_cngrab, 448320572Sdim .cn_ungrab = termcn_cnungrab, 449320572Sdim}; 450320572Sdim 451320572Sdimvoid 452319780Sdimtermcn_cnregister(struct terminal *tm) 453319780Sdim{ 454320397Sdim struct consdev *cp; 455320041Sdim 456320397Sdim cp = tm->consdev; 457320041Sdim if (cp == NULL) { 458319780Sdim cp = malloc(sizeof(struct consdev), M_TERMINAL, 459320041Sdim M_WAITOK|M_ZERO); 460319780Sdim cp->cn_ops = &termcn_cnops; 461320397Sdim cp->cn_arg = tm; 462319780Sdim cp->cn_pri = CN_INTERNAL; 463320041Sdim sprintf(cp->cn_name, "ttyv0"); 464320041Sdim 465320397Sdim tm->tm_flags = TF_CONS; 466320041Sdim tm->consdev = cp; 467320041Sdim 468320041Sdim terminal_init(tm); 469320397Sdim } 470320041Sdim 471320041Sdim /* Attach terminal as console. */ 472320041Sdim cnadd(cp); 473320397Sdim} 474320041Sdim 475320041Sdimstatic void 476320041Sdimtermcn_cngrab(struct consdev *cp) 477320397Sdim{ 478320041Sdim 479320041Sdim} 480320041Sdim 481320041Sdimstatic void 482320397Sdimtermcn_cnungrab(struct consdev *cp) 483320041Sdim{ 484320041Sdim 485320041Sdim} 486320041Sdim 487320397Sdimstatic void 488320041Sdimtermcn_cnprobe(struct consdev *cp) 489319780Sdim{ 490319780Sdim struct terminal *tm = cp->cn_arg; 491320397Sdim 492319780Sdim if (tm == NULL) { 493319780Sdim cp->cn_pri = CN_DEAD; 494319780Sdim return; 495320397Sdim } 496320397Sdim 497319780Sdim tm->consdev = cp; 498320397Sdim terminal_init(tm); 499319780Sdim 500319780Sdim tm->tm_class->tc_cnprobe(tm, cp); 501320397Sdim} 502319780Sdim 503319780Sdimstatic void 504319780Sdimtermcn_cninit(struct consdev *cp) 505320397Sdim{ 506319780Sdim 507319780Sdim} 508319780Sdim 509319780Sdimstatic void 510319780Sdimtermcn_cnterm(struct consdev *cp) 511319780Sdim{ 512319780Sdim 513319780Sdim} 514319780Sdim 515319780Sdimstatic int 516319780Sdimtermcn_cngetc(struct consdev *cp) 517319780Sdim{ 518319780Sdim struct terminal *tm = cp->cn_arg; 519319780Sdim 520319780Sdim return (tm->tm_class->tc_cngetc(tm)); 521319780Sdim} 522319780Sdim 523319780Sdimstatic void 524319780Sdimtermcn_cnputc(struct consdev *cp, int c) 525319780Sdim{ 526319780Sdim struct terminal *tm = cp->cn_arg; 527319780Sdim teken_attr_t backup; 528319780Sdim char cv = c; 529319780Sdim 530319780Sdim TERMINAL_LOCK_CONS(tm); 531319780Sdim if (!(tm->tm_flags & TF_MUTE)) { 532319780Sdim backup = *teken_get_curattr(&tm->tm_emulator); 533319780Sdim teken_set_curattr(&tm->tm_emulator, &kernel_message); 534319780Sdim teken_input(&tm->tm_emulator, &cv, 1); 535319780Sdim teken_set_curattr(&tm->tm_emulator, &backup); 536319780Sdim } 537319780Sdim TERMINAL_UNLOCK_CONS(tm); 538319780Sdim 539319780Sdim tm->tm_class->tc_done(tm); 540319780Sdim} 541319780Sdim 542319780Sdim/* 543319780Sdim * Binding with the terminal emulator. 544319780Sdim */ 545319780Sdim 546319780Sdimstatic void 547319780Sdimtermteken_bell(void *softc) 548319780Sdim{ 549319780Sdim struct terminal *tm = softc; 550319780Sdim 551319780Sdim tm->tm_flags |= TF_BELL; 552319780Sdim} 553319780Sdim 554319780Sdimstatic void 555319780Sdimtermteken_cursor(void *softc, const teken_pos_t *p) 556319780Sdim{ 557319780Sdim struct terminal *tm = softc; 558320041Sdim 559319780Sdim tm->tm_class->tc_cursor(tm, p); 560320041Sdim} 561319780Sdim 562319780Sdimstatic void 563319780Sdimtermteken_putchar(void *softc, const teken_pos_t *p, teken_char_t c, 564320397Sdim const teken_attr_t *a) 565320041Sdim{ 566319780Sdim struct terminal *tm = softc; 567320041Sdim 568319780Sdim tm->tm_class->tc_putchar(tm, p, TCHAR_CREATE(c, a)); 569319780Sdim} 570320041Sdim 571320041Sdimstatic void 572320041Sdimtermteken_fill(void *softc, const teken_rect_t *r, teken_char_t c, 573320041Sdim const teken_attr_t *a) 574320041Sdim{ 575319780Sdim struct terminal *tm = softc; 576319780Sdim 577319780Sdim tm->tm_class->tc_fill(tm, r, TCHAR_CREATE(c, a)); 578319780Sdim} 579319780Sdim 580319780Sdimstatic void 581319780Sdimtermteken_copy(void *softc, const teken_rect_t *r, const teken_pos_t *p) 582319780Sdim{ 583319780Sdim struct terminal *tm = softc; 584319780Sdim 585319780Sdim tm->tm_class->tc_copy(tm, r, p); 586319780Sdim} 587319780Sdim 588319780Sdimstatic void 589319780Sdimtermteken_param(void *softc, int cmd, unsigned int arg) 590319780Sdim{ 591319780Sdim struct terminal *tm = softc; 592319780Sdim 593319780Sdim tm->tm_class->tc_param(tm, cmd, arg); 594319780Sdim} 595319780Sdim 596319780Sdimstatic void 597319780Sdimtermteken_respond(void *softc, const void *buf, size_t len) 598319780Sdim{ 599319780Sdim#if 0 600319780Sdim struct terminal *tm = softc; 601319780Sdim struct tty *tp; 602319780Sdim 603319780Sdim /* 604319780Sdim * Only inject a response into the TTY if the data actually 605319780Sdim * originated from the TTY. 606319780Sdim * 607319780Sdim * XXX: This cannot be done right now. The TTY could pick up 608319780Sdim * other locks. It could also in theory cause loops, when the 609319780Sdim * TTY performs echoing of a command that generates even more 610319780Sdim * input. 611319780Sdim */ 612319780Sdim tp = tm->tm_tty; 613319780Sdim if (tp == NULL) 614319780Sdim return; 615319780Sdim 616319780Sdim ttydisc_rint_simple(tp, buf, len); 617319780Sdim ttydisc_rint_done(tp); 618319780Sdim#endif 619319780Sdim} 620319780Sdim