The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/subr_terminal.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2009 The FreeBSD Foundation
    5  *
    6  * This software was developed by Ed Schouten under sponsorship from the
    7  * FreeBSD Foundation.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include <sys/param.h>
   35 #include <sys/cons.h>
   36 #include <sys/consio.h>
   37 #include <sys/kernel.h>
   38 #include <sys/lock.h>
   39 #include <sys/malloc.h>
   40 #include <sys/mutex.h>
   41 #include <sys/systm.h>
   42 #include <sys/terminal.h>
   43 #include <sys/tty.h>
   44 
   45 #include <machine/stdarg.h>
   46 
   47 static MALLOC_DEFINE(M_TERMINAL, "terminal", "terminal device");
   48 
   49 /*
   50  * Locking.
   51  *
   52  * Normally we don't need to lock down the terminal emulator, because
   53  * the TTY lock is already held when calling teken_input().
   54  * Unfortunately this is not the case when the terminal acts as a
   55  * console device, because cnputc() can be called at the same time.
   56  * This means terminals may need to be locked down using a spin lock.
   57  */
   58 #define TERMINAL_LOCK(tm)       do {                                    \
   59         if ((tm)->tm_flags & TF_CONS)                                   \
   60                 mtx_lock_spin(&(tm)->tm_mtx);                           \
   61         else if ((tm)->tm_tty != NULL)                                  \
   62                 tty_lock((tm)->tm_tty);                                 \
   63 } while (0)
   64 #define TERMINAL_UNLOCK(tm)     do {                                    \
   65         if ((tm)->tm_flags & TF_CONS)                                   \
   66                 mtx_unlock_spin(&(tm)->tm_mtx);                         \
   67         else if ((tm)->tm_tty != NULL)                                  \
   68                 tty_unlock((tm)->tm_tty);                               \
   69 } while (0)
   70 #define TERMINAL_LOCK_TTY(tm)   do {                                    \
   71         if ((tm)->tm_flags & TF_CONS)                                   \
   72                 mtx_lock_spin(&(tm)->tm_mtx);                           \
   73 } while (0)
   74 #define TERMINAL_UNLOCK_TTY(tm) do {                                    \
   75         if ((tm)->tm_flags & TF_CONS)                                   \
   76                 mtx_unlock_spin(&(tm)->tm_mtx);                         \
   77 } while (0)
   78 #define TERMINAL_LOCK_CONS(tm)          mtx_lock_spin(&(tm)->tm_mtx)
   79 #define TERMINAL_UNLOCK_CONS(tm)        mtx_unlock_spin(&(tm)->tm_mtx)
   80 
   81 /*
   82  * TTY routines.
   83  */
   84 
   85 static tsw_open_t       termtty_open;
   86 static tsw_close_t      termtty_close;
   87 static tsw_outwakeup_t  termtty_outwakeup;
   88 static tsw_ioctl_t      termtty_ioctl;
   89 static tsw_mmap_t       termtty_mmap;
   90 
   91 static struct ttydevsw terminal_tty_class = {
   92         .tsw_open       = termtty_open,
   93         .tsw_close      = termtty_close,
   94         .tsw_outwakeup  = termtty_outwakeup,
   95         .tsw_ioctl      = termtty_ioctl,
   96         .tsw_mmap       = termtty_mmap,
   97 };
   98 
   99 /*
  100  * Terminal emulator routines.
  101  */
  102 
  103 static tf_bell_t        termteken_bell;
  104 static tf_cursor_t      termteken_cursor;
  105 static tf_putchar_t     termteken_putchar;
  106 static tf_fill_t        termteken_fill;
  107 static tf_copy_t        termteken_copy;
  108 static tf_pre_input_t   termteken_pre_input;
  109 static tf_post_input_t  termteken_post_input;
  110 static tf_param_t       termteken_param;
  111 static tf_respond_t     termteken_respond;
  112 
  113 static teken_funcs_t terminal_drawmethods = {
  114         .tf_bell        = termteken_bell,
  115         .tf_cursor      = termteken_cursor,
  116         .tf_putchar     = termteken_putchar,
  117         .tf_fill        = termteken_fill,
  118         .tf_copy        = termteken_copy,
  119         .tf_pre_input   = termteken_pre_input,
  120         .tf_post_input  = termteken_post_input,
  121         .tf_param       = termteken_param,
  122         .tf_respond     = termteken_respond,
  123 };
  124 
  125 /* Kernel message formatting. */
  126 static teken_attr_t kernel_message = {
  127         .ta_fgcolor     = TCHAR_FGCOLOR(TERMINAL_KERN_ATTR),
  128         .ta_bgcolor     = TCHAR_BGCOLOR(TERMINAL_KERN_ATTR),
  129         .ta_format      = TCHAR_FORMAT(TERMINAL_KERN_ATTR)
  130 };
  131 
  132 static teken_attr_t default_message = {
  133         .ta_fgcolor     = TCHAR_FGCOLOR(TERMINAL_NORM_ATTR),
  134         .ta_bgcolor     = TCHAR_BGCOLOR(TERMINAL_NORM_ATTR),
  135         .ta_format      = TCHAR_FORMAT(TERMINAL_NORM_ATTR)
  136 };
  137 
  138 /* Fudge fg brightness as TF_BOLD (shifted). */
  139 #define TCOLOR_FG_FUDGED(color) __extension__ ({                        \
  140         teken_color_t _c;                                               \
  141                                                                         \
  142         _c = (color);                                                   \
  143         TCOLOR_FG(_c & 7) | ((_c & 8) << 18);                           \
  144 })
  145 
  146 /* Fudge bg brightness as TF_BLINK (shifted). */
  147 #define TCOLOR_BG_FUDGED(color) __extension__ ({                        \
  148         teken_color_t _c;                                               \
  149                                                                         \
  150         _c = (color);                                                   \
  151         TCOLOR_BG(_c & 7) | ((_c & 8) << 20);                           \
  152 })
  153 
  154 #define TCOLOR_256TO16(color) __extension__ ({                          \
  155         teken_color_t _c;                                               \
  156                                                                         \
  157         _c = (color);                                                   \
  158         if (_c >= 16)                                                   \
  159                 _c = teken_256to16(_c);                                 \
  160         _c;                                                             \
  161 })
  162 
  163 #define TCHAR_CREATE(c, a)      ((c) | TFORMAT((a)->ta_format) |        \
  164         TCOLOR_FG_FUDGED(TCOLOR_256TO16((a)->ta_fgcolor)) |             \
  165         TCOLOR_BG_FUDGED(TCOLOR_256TO16((a)->ta_bgcolor)))
  166 
  167 static void
  168 terminal_init(struct terminal *tm)
  169 {
  170         int fg, bg;
  171 
  172         if (tm->tm_flags & TF_CONS)
  173                 mtx_init(&tm->tm_mtx, "trmlck", NULL, MTX_SPIN);
  174 
  175         teken_init(&tm->tm_emulator, &terminal_drawmethods, tm);
  176 
  177         fg = bg = -1;
  178         TUNABLE_INT_FETCH("teken.fg_color", &fg);
  179         TUNABLE_INT_FETCH("teken.bg_color", &bg);
  180 
  181         if (fg != -1) {
  182                 default_message.ta_fgcolor = fg;
  183                 kernel_message.ta_fgcolor = fg;
  184         }
  185         if (bg != -1) {
  186                 default_message.ta_bgcolor = bg;
  187                 kernel_message.ta_bgcolor = bg;
  188         }
  189 
  190         if (default_message.ta_bgcolor == TC_WHITE) {
  191                 default_message.ta_bgcolor |= TC_LIGHT;
  192                 kernel_message.ta_bgcolor |= TC_LIGHT;
  193         }
  194 
  195         if (default_message.ta_bgcolor == TC_BLACK &&
  196             default_message.ta_fgcolor < TC_NCOLORS)
  197                 kernel_message.ta_fgcolor |= TC_LIGHT;
  198         teken_set_defattr(&tm->tm_emulator, &default_message);
  199 }
  200 
  201 struct terminal *
  202 terminal_alloc(const struct terminal_class *tc, void *softc)
  203 {
  204         struct terminal *tm;
  205 
  206         tm = malloc(sizeof(struct terminal), M_TERMINAL, M_WAITOK|M_ZERO);
  207         terminal_init(tm);
  208 
  209         tm->tm_class = tc;
  210         tm->tm_softc = softc;
  211 
  212         return (tm);
  213 }
  214 
  215 static void
  216 terminal_sync_ttysize(struct terminal *tm)
  217 {
  218         struct tty *tp;
  219 
  220         tp = tm->tm_tty;
  221         if (tp == NULL)
  222                 return;
  223 
  224         tty_lock(tp);
  225         tty_set_winsize(tp, &tm->tm_winsize);
  226         tty_unlock(tp);
  227 }
  228 
  229 void
  230 terminal_maketty(struct terminal *tm, const char *fmt, ...)
  231 {
  232         struct tty *tp;
  233         char name[8];
  234         va_list ap;
  235 
  236         va_start(ap, fmt);
  237         vsnrprintf(name, sizeof name, 32, fmt, ap);
  238         va_end(ap);
  239 
  240         tp = tty_alloc(&terminal_tty_class, tm);
  241         tty_makedev(tp, NULL, "%s", name);
  242         tm->tm_tty = tp;
  243         terminal_sync_ttysize(tm);
  244 }
  245 
  246 void
  247 terminal_set_cursor(struct terminal *tm, const term_pos_t *pos)
  248 {
  249 
  250         teken_set_cursor(&tm->tm_emulator, pos);
  251 }
  252 
  253 void
  254 terminal_set_winsize_blank(struct terminal *tm, const struct winsize *size,
  255     int blank, const term_attr_t *attr)
  256 {
  257         term_rect_t r;
  258 
  259         tm->tm_winsize = *size;
  260 
  261         r.tr_begin.tp_row = r.tr_begin.tp_col = 0;
  262         r.tr_end.tp_row = size->ws_row;
  263         r.tr_end.tp_col = size->ws_col;
  264 
  265         TERMINAL_LOCK(tm);
  266         if (blank == 0)
  267                 teken_set_winsize_noreset(&tm->tm_emulator, &r.tr_end);
  268         else
  269                 teken_set_winsize(&tm->tm_emulator, &r.tr_end);
  270         TERMINAL_UNLOCK(tm);
  271 
  272         if ((blank != 0) && !(tm->tm_flags & TF_MUTE))
  273                 tm->tm_class->tc_fill(tm, &r,
  274                     TCHAR_CREATE((teken_char_t)' ', attr));
  275 
  276         terminal_sync_ttysize(tm);
  277 }
  278 
  279 void
  280 terminal_set_winsize(struct terminal *tm, const struct winsize *size)
  281 {
  282 
  283         terminal_set_winsize_blank(tm, size, 1,
  284             (const term_attr_t *)&default_message);
  285 }
  286 
  287 /*
  288  * XXX: This function is a kludge.  Drivers like vt(4) need to
  289  * temporarily stop input when resizing, etc.  This should ideally be
  290  * handled within the driver.
  291  */
  292 
  293 void
  294 terminal_mute(struct terminal *tm, int yes)
  295 {
  296 
  297         TERMINAL_LOCK(tm);
  298         if (yes)
  299                 tm->tm_flags |= TF_MUTE;
  300         else
  301                 tm->tm_flags &= ~TF_MUTE;
  302         TERMINAL_UNLOCK(tm);
  303 }
  304 
  305 void
  306 terminal_input_char(struct terminal *tm, term_char_t c)
  307 {
  308         struct tty *tp;
  309 
  310         tp = tm->tm_tty;
  311         if (tp == NULL)
  312                 return;
  313 
  314         /*
  315          * Strip off any attributes. Also ignore input of second part of
  316          * CJK fullwidth characters, as we don't want to return these
  317          * characters twice.
  318          */
  319         if (TCHAR_FORMAT(c) & TF_CJK_RIGHT)
  320                 return;
  321         c = TCHAR_CHARACTER(c);
  322 
  323         tty_lock(tp);
  324         /*
  325          * Conversion to UTF-8.
  326          */
  327         if (c < 0x80) {
  328                 ttydisc_rint(tp, c, 0);
  329         } else if (c < 0x800) {
  330                 char str[2] = {
  331                         0xc0 | (c >> 6),
  332                         0x80 | (c & 0x3f)
  333                 };
  334 
  335                 ttydisc_rint_simple(tp, str, sizeof str);
  336         } else if (c < 0x10000) {
  337                 char str[3] = {
  338                         0xe0 | (c >> 12),
  339                         0x80 | ((c >> 6) & 0x3f),
  340                         0x80 | (c & 0x3f)
  341                 };
  342 
  343                 ttydisc_rint_simple(tp, str, sizeof str);
  344         } else {
  345                 char str[4] = {
  346                         0xf0 | (c >> 18),
  347                         0x80 | ((c >> 12) & 0x3f),
  348                         0x80 | ((c >> 6) & 0x3f),
  349                         0x80 | (c & 0x3f)
  350                 };
  351 
  352                 ttydisc_rint_simple(tp, str, sizeof str);
  353         }
  354         ttydisc_rint_done(tp);
  355         tty_unlock(tp);
  356 }
  357 
  358 void
  359 terminal_input_raw(struct terminal *tm, char c)
  360 {
  361         struct tty *tp;
  362 
  363         tp = tm->tm_tty;
  364         if (tp == NULL)
  365                 return;
  366 
  367         tty_lock(tp);
  368         ttydisc_rint(tp, c, 0);
  369         ttydisc_rint_done(tp);
  370         tty_unlock(tp);
  371 }
  372 
  373 void
  374 terminal_input_special(struct terminal *tm, unsigned int k)
  375 {
  376         struct tty *tp;
  377         const char *str;
  378 
  379         tp = tm->tm_tty;
  380         if (tp == NULL)
  381                 return;
  382 
  383         str = teken_get_sequence(&tm->tm_emulator, k);
  384         if (str == NULL)
  385                 return;
  386 
  387         tty_lock(tp);
  388         ttydisc_rint_simple(tp, str, strlen(str));
  389         ttydisc_rint_done(tp);
  390         tty_unlock(tp);
  391 }
  392 
  393 /*
  394  * Binding with the TTY layer.
  395  */
  396 
  397 static int
  398 termtty_open(struct tty *tp)
  399 {
  400         struct terminal *tm = tty_softc(tp);
  401 
  402         tm->tm_class->tc_opened(tm, 1);
  403         return (0);
  404 }
  405 
  406 static void
  407 termtty_close(struct tty *tp)
  408 {
  409         struct terminal *tm = tty_softc(tp);
  410 
  411         tm->tm_class->tc_opened(tm, 0);
  412 }
  413 
  414 static void
  415 termtty_outwakeup(struct tty *tp)
  416 {
  417         struct terminal *tm = tty_softc(tp);
  418         char obuf[128];
  419         size_t olen;
  420         unsigned int flags = 0;
  421 
  422         while ((olen = ttydisc_getc(tp, obuf, sizeof obuf)) > 0) {
  423                 TERMINAL_LOCK_TTY(tm);
  424                 if (!(tm->tm_flags & TF_MUTE)) {
  425                         tm->tm_flags &= ~TF_BELL;
  426                         teken_input(&tm->tm_emulator, obuf, olen);
  427                         flags |= tm->tm_flags;
  428                 }
  429                 TERMINAL_UNLOCK_TTY(tm);
  430         }
  431 
  432         TERMINAL_LOCK_TTY(tm);
  433         if (!(tm->tm_flags & TF_MUTE))
  434                 tm->tm_class->tc_done(tm);
  435         TERMINAL_UNLOCK_TTY(tm);
  436         if (flags & TF_BELL)
  437                 tm->tm_class->tc_bell(tm);
  438 }
  439 
  440 static int
  441 termtty_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
  442 {
  443         struct terminal *tm = tty_softc(tp);
  444         int error;
  445 
  446         switch (cmd) {
  447         case CONS_GETINFO: {
  448                 vid_info_t *vi = (vid_info_t *)data;
  449                 const teken_pos_t *p;
  450                 int fg, bg;
  451 
  452                 if (vi->size != sizeof(vid_info_t))
  453                         return (EINVAL);
  454 
  455                 /* Already help the console driver by filling in some data. */
  456                 p = teken_get_cursor(&tm->tm_emulator);
  457                 vi->mv_row = p->tp_row;
  458                 vi->mv_col = p->tp_col;
  459 
  460                 p = teken_get_winsize(&tm->tm_emulator);
  461                 vi->mv_rsz = p->tp_row;
  462                 vi->mv_csz = p->tp_col;
  463 
  464                 teken_get_defattr_cons25(&tm->tm_emulator, &fg, &bg);
  465                 vi->mv_norm.fore = fg;
  466                 vi->mv_norm.back = bg;
  467                 /* XXX: keep vidcontrol happy; bold backgrounds. */
  468                 vi->mv_rev.fore = bg;
  469                 vi->mv_rev.back = fg & 0x7;
  470                 break;
  471         }
  472         }
  473 
  474         /*
  475          * Unlike various other drivers, this driver will never
  476          * deallocate TTYs.  This means it's safe to temporarily unlock
  477          * the TTY when handling ioctls.
  478          */
  479         tty_unlock(tp);
  480         error = tm->tm_class->tc_ioctl(tm, cmd, data, td);
  481         tty_lock(tp);
  482         if ((error == 0) && (cmd == CONS_CLRHIST)) {
  483                 /*
  484                  * Scrollback history has been successfully cleared,
  485                  * so reset the cursor position to the top left of the screen.
  486                  */
  487                 teken_pos_t p;
  488                 p.tp_row = 0;
  489                 p.tp_col = 0;
  490                 teken_set_cursor(&tm->tm_emulator, &p);
  491         }
  492         return (error);
  493 }
  494 
  495 static int
  496 termtty_mmap(struct tty *tp, vm_ooffset_t offset, vm_paddr_t * paddr,
  497     int nprot, vm_memattr_t *memattr)
  498 {
  499         struct terminal *tm = tty_softc(tp);
  500 
  501         return (tm->tm_class->tc_mmap(tm, offset, paddr, nprot, memattr));
  502 }
  503 
  504 /*
  505  * Binding with the kernel and debug console.
  506  */
  507 
  508 static cn_probe_t       termcn_cnprobe;
  509 static cn_init_t        termcn_cninit;
  510 static cn_term_t        termcn_cnterm;
  511 static cn_getc_t        termcn_cngetc;
  512 static cn_putc_t        termcn_cnputc;
  513 static cn_grab_t        termcn_cngrab;
  514 static cn_ungrab_t      termcn_cnungrab;
  515 
  516 const struct consdev_ops termcn_cnops = {
  517         .cn_probe       = termcn_cnprobe,
  518         .cn_init        = termcn_cninit,
  519         .cn_term        = termcn_cnterm,
  520         .cn_getc        = termcn_cngetc,
  521         .cn_putc        = termcn_cnputc,
  522         .cn_grab        = termcn_cngrab,
  523         .cn_ungrab      = termcn_cnungrab,
  524 };
  525 
  526 void
  527 termcn_cnregister(struct terminal *tm)
  528 {
  529         struct consdev *cp;
  530 
  531         cp = tm->consdev;
  532         if (cp == NULL) {
  533                 cp = malloc(sizeof(struct consdev), M_TERMINAL,
  534                     M_WAITOK|M_ZERO);
  535                 cp->cn_ops = &termcn_cnops;
  536                 cp->cn_arg = tm;
  537                 cp->cn_pri = CN_INTERNAL;
  538                 sprintf(cp->cn_name, "ttyv0");
  539 
  540                 tm->tm_flags = TF_CONS;
  541                 tm->consdev = cp;
  542 
  543                 terminal_init(tm);
  544         }
  545 
  546         /* Attach terminal as console. */
  547         cnadd(cp);
  548 }
  549 
  550 static void
  551 termcn_cngrab(struct consdev *cp)
  552 {
  553         struct terminal *tm = cp->cn_arg;
  554 
  555         tm->tm_class->tc_cngrab(tm);
  556 }
  557 
  558 static void
  559 termcn_cnungrab(struct consdev *cp)
  560 {
  561         struct terminal *tm = cp->cn_arg;
  562 
  563         tm->tm_class->tc_cnungrab(tm);
  564 }
  565 
  566 static void
  567 termcn_cnprobe(struct consdev *cp)
  568 {
  569         struct terminal *tm = cp->cn_arg;
  570 
  571         if (tm == NULL) {
  572                 cp->cn_pri = CN_DEAD;
  573                 return;
  574         }
  575 
  576         tm->consdev = cp;
  577         terminal_init(tm);
  578 
  579         tm->tm_class->tc_cnprobe(tm, cp);
  580 }
  581 
  582 static void
  583 termcn_cninit(struct consdev *cp)
  584 {
  585 
  586 }
  587 
  588 static void
  589 termcn_cnterm(struct consdev *cp)
  590 {
  591 
  592 }
  593 
  594 static int
  595 termcn_cngetc(struct consdev *cp)
  596 {
  597         struct terminal *tm = cp->cn_arg;
  598 
  599         return (tm->tm_class->tc_cngetc(tm));
  600 }
  601 
  602 static void
  603 termcn_cnputc(struct consdev *cp, int c)
  604 {
  605         struct terminal *tm = cp->cn_arg;
  606         teken_attr_t backup;
  607         char cv = c;
  608 
  609         TERMINAL_LOCK_CONS(tm);
  610         if (!(tm->tm_flags & TF_MUTE)) {
  611                 backup = *teken_get_curattr(&tm->tm_emulator);
  612                 teken_set_curattr(&tm->tm_emulator, &kernel_message);
  613                 teken_input(&tm->tm_emulator, &cv, 1);
  614                 teken_set_curattr(&tm->tm_emulator, &backup);
  615                 tm->tm_class->tc_done(tm);
  616         }
  617         TERMINAL_UNLOCK_CONS(tm);
  618 }
  619 
  620 /*
  621  * Binding with the terminal emulator.
  622  */
  623 
  624 static void
  625 termteken_bell(void *softc)
  626 {
  627         struct terminal *tm = softc;
  628 
  629         tm->tm_flags |= TF_BELL;
  630 }
  631 
  632 static void
  633 termteken_cursor(void *softc, const teken_pos_t *p)
  634 {
  635         struct terminal *tm = softc;
  636 
  637         tm->tm_class->tc_cursor(tm, p);
  638 }
  639 
  640 static void
  641 termteken_putchar(void *softc, const teken_pos_t *p, teken_char_t c,
  642     const teken_attr_t *a)
  643 {
  644         struct terminal *tm = softc;
  645 
  646         tm->tm_class->tc_putchar(tm, p, TCHAR_CREATE(c, a));
  647 }
  648 
  649 static void
  650 termteken_fill(void *softc, const teken_rect_t *r, teken_char_t c,
  651     const teken_attr_t *a)
  652 {
  653         struct terminal *tm = softc;
  654 
  655         tm->tm_class->tc_fill(tm, r, TCHAR_CREATE(c, a));
  656 }
  657 
  658 static void
  659 termteken_copy(void *softc, const teken_rect_t *r, const teken_pos_t *p)
  660 {
  661         struct terminal *tm = softc;
  662 
  663         tm->tm_class->tc_copy(tm, r, p);
  664 }
  665 
  666 static void
  667 termteken_pre_input(void *softc)
  668 {
  669         struct terminal *tm = softc;
  670 
  671         tm->tm_class->tc_pre_input(tm);
  672 }
  673 
  674 static void
  675 termteken_post_input(void *softc)
  676 {
  677         struct terminal *tm = softc;
  678 
  679         tm->tm_class->tc_post_input(tm);
  680 }
  681 
  682 static void
  683 termteken_param(void *softc, int cmd, unsigned int arg)
  684 {
  685         struct terminal *tm = softc;
  686 
  687         tm->tm_class->tc_param(tm, cmd, arg);
  688 }
  689 
  690 static void
  691 termteken_respond(void *softc, const void *buf, size_t len)
  692 {
  693 #if 0
  694         struct terminal *tm = softc;
  695         struct tty *tp;
  696 
  697         /*
  698          * Only inject a response into the TTY if the data actually
  699          * originated from the TTY.
  700          *
  701          * XXX: This cannot be done right now.  The TTY could pick up
  702          * other locks.  It could also in theory cause loops, when the
  703          * TTY performs echoing of a command that generates even more
  704          * input.
  705          */
  706         tp = tm->tm_tty;
  707         if (tp == NULL)
  708                 return;
  709 
  710         ttydisc_rint_simple(tp, buf, len);
  711         ttydisc_rint_done(tp);
  712 #endif
  713 }

Cache object: e48c9fb11764928cb44c0e23133e166c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.