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/kern_cons.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-3-Clause
    3  *
    4  * Copyright (c) 1988 University of Utah.
    5  * Copyright (c) 1991 The Regents of the University of California.
    6  * Copyright (c) 1999 Michael Smith
    7  * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
    8  *
    9  * All rights reserved.
   10  *
   11  * This code is derived from software contributed to Berkeley by
   12  * the Systems Programming Group of the University of Utah Computer
   13  * Science Department.
   14  *
   15  * Redistribution and use in source and binary forms, with or without
   16  * modification, are permitted provided that the following conditions
   17  * are met:
   18  * 1. Redistributions of source code must retain the above copyright
   19  *    notice, this list of conditions and the following disclaimer.
   20  * 2. Redistributions in binary form must reproduce the above copyright
   21  *    notice, this list of conditions and the following disclaimer in the
   22  *    documentation and/or other materials provided with the distribution.
   23  * 3. Neither the name of the University nor the names of its contributors
   24  *    may be used to endorse or promote products derived from this software
   25  *    without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   37  * SUCH DAMAGE.
   38  *
   39  *      from: @(#)cons.c        7.2 (Berkeley) 5/9/91
   40  */
   41 
   42 #include <sys/cdefs.h>
   43 __FBSDID("$FreeBSD$");
   44 
   45 #include "opt_ddb.h"
   46 #include "opt_syscons.h"
   47 
   48 #include <sys/param.h>
   49 #include <sys/systm.h>
   50 #include <sys/lock.h>
   51 #include <sys/mutex.h>
   52 #include <sys/conf.h>
   53 #include <sys/cons.h>
   54 #include <sys/fcntl.h>
   55 #include <sys/kdb.h>
   56 #include <sys/kernel.h>
   57 #include <sys/malloc.h>
   58 #include <sys/msgbuf.h>
   59 #include <sys/namei.h>
   60 #include <sys/priv.h>
   61 #include <sys/proc.h>
   62 #include <sys/queue.h>
   63 #include <sys/reboot.h>
   64 #include <sys/sysctl.h>
   65 #include <sys/sbuf.h>
   66 #include <sys/tty.h>
   67 #include <sys/uio.h>
   68 #include <sys/vnode.h>
   69 
   70 #include <ddb/ddb.h>
   71 
   72 #include <machine/cpu.h>
   73 #include <machine/clock.h>
   74 
   75 static MALLOC_DEFINE(M_TTYCONS, "tty console", "tty console handling");
   76 
   77 struct cn_device {
   78         STAILQ_ENTRY(cn_device) cnd_next;
   79         struct          consdev *cnd_cn;
   80 };
   81 
   82 #define CNDEVPATHMAX    32
   83 #define CNDEVTAB_SIZE   4
   84 static struct cn_device cn_devtab[CNDEVTAB_SIZE];
   85 static STAILQ_HEAD(, cn_device) cn_devlist =
   86     STAILQ_HEAD_INITIALIZER(cn_devlist);
   87 
   88 int     cons_avail_mask = 0;    /* Bit mask. Each registered low level console
   89                                  * which is currently unavailable for inpit
   90                                  * (i.e., if it is in graphics mode) will have
   91                                  * this bit cleared.
   92                                  */
   93 
   94 static int cn_mute;
   95 SYSCTL_INT(_kern, OID_AUTO, consmute, CTLFLAG_RW, &cn_mute, 0,
   96     "State of the console muting");
   97 
   98 static char *consbuf;                   /* buffer used by `consmsgbuf' */
   99 static struct callout conscallout;      /* callout for outputting to constty */
  100 struct msgbuf consmsgbuf;               /* message buffer for console tty */
  101 static u_char console_pausing;          /* pause after each line during probe */
  102 static char *console_pausestr=
  103 "<pause; press any key to proceed to next line or '.' to end pause mode>";
  104 struct tty *constty;                    /* pointer to console "window" tty */
  105 static struct mtx cnputs_mtx;           /* Mutex for cnputs(). */
  106 static int use_cnputs_mtx = 0;          /* != 0 if cnputs_mtx locking reqd. */
  107 
  108 static void constty_timeout(void *arg);
  109 
  110 static struct consdev cons_consdev;
  111 DATA_SET(cons_set, cons_consdev);
  112 SET_DECLARE(cons_set, struct consdev);
  113 
  114 void
  115 cninit(void)
  116 {
  117         struct consdev *best_cn, *cn, **list;
  118 
  119         /*
  120          * Check if we should mute the console (for security reasons perhaps)
  121          * It can be changes dynamically using sysctl kern.consmute
  122          * once we are up and going.
  123          * 
  124          */
  125         cn_mute = ((boothowto & (RB_MUTE
  126                         |RB_SINGLE
  127                         |RB_VERBOSE
  128                         |RB_ASKNAME)) == RB_MUTE);
  129 
  130         /*
  131          * Find the first console with the highest priority.
  132          */
  133         best_cn = NULL;
  134         SET_FOREACH(list, cons_set) {
  135                 cn = *list;
  136                 cnremove(cn);
  137                 /* Skip cons_consdev. */
  138                 if (cn->cn_ops == NULL)
  139                         continue;
  140                 cn->cn_ops->cn_probe(cn);
  141                 if (cn->cn_pri == CN_DEAD)
  142                         continue;
  143                 if (best_cn == NULL || cn->cn_pri > best_cn->cn_pri)
  144                         best_cn = cn;
  145                 if (boothowto & RB_MULTIPLE) {
  146                         /*
  147                          * Initialize console, and attach to it.
  148                          */
  149                         cn->cn_ops->cn_init(cn);
  150                         cnadd(cn);
  151                 }
  152         }
  153         if (best_cn == NULL)
  154                 return;
  155         if ((boothowto & RB_MULTIPLE) == 0) {
  156                 best_cn->cn_ops->cn_init(best_cn);
  157                 cnadd(best_cn);
  158         }
  159         if (boothowto & RB_PAUSE)
  160                 console_pausing = 1;
  161         /*
  162          * Make the best console the preferred console.
  163          */
  164         cnselect(best_cn);
  165 
  166 #ifdef EARLY_PRINTF
  167         /*
  168          * Release early console.
  169          */
  170         early_putc = NULL;
  171 #endif
  172 }
  173 
  174 void
  175 cninit_finish(void)
  176 {
  177         console_pausing = 0;
  178 } 
  179 
  180 /* add a new physical console to back the virtual console */
  181 int
  182 cnadd(struct consdev *cn)
  183 {
  184         struct cn_device *cnd;
  185         int i;
  186 
  187         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next)
  188                 if (cnd->cnd_cn == cn)
  189                         return (0);
  190         for (i = 0; i < CNDEVTAB_SIZE; i++) {
  191                 cnd = &cn_devtab[i];
  192                 if (cnd->cnd_cn == NULL)
  193                         break;
  194         }
  195         if (cnd->cnd_cn != NULL)
  196                 return (ENOMEM);
  197         cnd->cnd_cn = cn;
  198         if (cn->cn_name[0] == '\0') {
  199                 /* XXX: it is unclear if/where this print might output */
  200                 printf("WARNING: console at %p has no name\n", cn);
  201         }
  202         STAILQ_INSERT_TAIL(&cn_devlist, cnd, cnd_next);
  203         if (STAILQ_FIRST(&cn_devlist) == cnd)
  204                 ttyconsdev_select(cnd->cnd_cn->cn_name);
  205 
  206         /* Add device to the active mask. */
  207         cnavailable(cn, (cn->cn_flags & CN_FLAG_NOAVAIL) == 0);
  208 
  209         return (0);
  210 }
  211 
  212 void
  213 cnremove(struct consdev *cn)
  214 {
  215         struct cn_device *cnd;
  216         int i;
  217 
  218         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
  219                 if (cnd->cnd_cn != cn)
  220                         continue;
  221                 if (STAILQ_FIRST(&cn_devlist) == cnd)
  222                         ttyconsdev_select(NULL);
  223                 STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next);
  224                 cnd->cnd_cn = NULL;
  225 
  226                 /* Remove this device from available mask. */
  227                 for (i = 0; i < CNDEVTAB_SIZE; i++) 
  228                         if (cnd == &cn_devtab[i]) {
  229                                 cons_avail_mask &= ~(1 << i);
  230                                 break;
  231                         }
  232 #if 0
  233                 /*
  234                  * XXX
  235                  * syscons gets really confused if console resources are
  236                  * freed after the system has initialized.
  237                  */
  238                 if (cn->cn_term != NULL)
  239                         cn->cn_ops->cn_term(cn);
  240 #endif
  241                 return;
  242         }
  243 }
  244 
  245 void
  246 cnselect(struct consdev *cn)
  247 {
  248         struct cn_device *cnd;
  249 
  250         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
  251                 if (cnd->cnd_cn != cn)
  252                         continue;
  253                 if (cnd == STAILQ_FIRST(&cn_devlist))
  254                         return;
  255                 STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next);
  256                 STAILQ_INSERT_HEAD(&cn_devlist, cnd, cnd_next);
  257                 ttyconsdev_select(cnd->cnd_cn->cn_name);
  258                 return;
  259         }
  260 }
  261 
  262 void
  263 cnavailable(struct consdev *cn, int available)
  264 {
  265         int i;
  266 
  267         for (i = 0; i < CNDEVTAB_SIZE; i++) {
  268                 if (cn_devtab[i].cnd_cn == cn)
  269                         break;
  270         }
  271         if (available) {
  272                 if (i < CNDEVTAB_SIZE)
  273                         cons_avail_mask |= (1 << i); 
  274                 cn->cn_flags &= ~CN_FLAG_NOAVAIL;
  275         } else {
  276                 if (i < CNDEVTAB_SIZE)
  277                         cons_avail_mask &= ~(1 << i);
  278                 cn->cn_flags |= CN_FLAG_NOAVAIL;
  279         }
  280 }
  281 
  282 int
  283 cnunavailable(void)
  284 {
  285 
  286         return (cons_avail_mask == 0);
  287 }
  288 
  289 /*
  290  * sysctl_kern_console() provides output parseable in conscontrol(1).
  291  */
  292 static int
  293 sysctl_kern_console(SYSCTL_HANDLER_ARGS)
  294 {
  295         struct cn_device *cnd;
  296         struct consdev *cp, **list;
  297         char *p;
  298         int delete, error;
  299         struct sbuf *sb;
  300 
  301         sb = sbuf_new(NULL, NULL, CNDEVPATHMAX * 2, SBUF_AUTOEXTEND |
  302             SBUF_INCLUDENUL);
  303         if (sb == NULL)
  304                 return (ENOMEM);
  305         sbuf_clear(sb);
  306         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next)
  307                 sbuf_printf(sb, "%s,", cnd->cnd_cn->cn_name);
  308         sbuf_printf(sb, "/");
  309         SET_FOREACH(list, cons_set) {
  310                 cp = *list;
  311                 if (cp->cn_name[0] != '\0')
  312                         sbuf_printf(sb, "%s,", cp->cn_name);
  313         }
  314         sbuf_finish(sb);
  315         error = sysctl_handle_string(oidp, sbuf_data(sb), sbuf_len(sb), req);
  316         if (error == 0 && req->newptr != NULL) {
  317                 p = sbuf_data(sb);
  318                 error = ENXIO;
  319                 delete = 0;
  320                 if (*p == '-') {
  321                         delete = 1;
  322                         p++;
  323                 }
  324                 SET_FOREACH(list, cons_set) {
  325                         cp = *list;
  326                         if (strcmp(p, cp->cn_name) != 0)
  327                                 continue;
  328                         if (delete) {
  329                                 cnremove(cp);
  330                                 error = 0;
  331                         } else {
  332                                 error = cnadd(cp);
  333                                 if (error == 0)
  334                                         cnselect(cp);
  335                         }
  336                         break;
  337                 }
  338         }
  339         sbuf_delete(sb);
  340         return (error);
  341 }
  342 
  343 SYSCTL_PROC(_kern, OID_AUTO, console, CTLTYPE_STRING|CTLFLAG_RW,
  344         0, 0, sysctl_kern_console, "A", "Console device control");
  345 
  346 void
  347 cngrab(void)
  348 {
  349         struct cn_device *cnd;
  350         struct consdev *cn;
  351 
  352         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
  353                 cn = cnd->cnd_cn;
  354                 if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG))
  355                         cn->cn_ops->cn_grab(cn);
  356         }
  357 }
  358 
  359 void
  360 cnungrab(void)
  361 {
  362         struct cn_device *cnd;
  363         struct consdev *cn;
  364 
  365         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
  366                 cn = cnd->cnd_cn;
  367                 if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG))
  368                         cn->cn_ops->cn_ungrab(cn);
  369         }
  370 }
  371 
  372 void
  373 cnresume(void)
  374 {
  375         struct cn_device *cnd;
  376         struct consdev *cn;
  377 
  378         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
  379                 cn = cnd->cnd_cn;
  380                 if (cn->cn_ops->cn_resume != NULL)
  381                         cn->cn_ops->cn_resume(cn);
  382         }
  383 }
  384 
  385 /*
  386  * Low level console routines.
  387  */
  388 int
  389 cngetc(void)
  390 {
  391         int c;
  392 
  393         if (cn_mute)
  394                 return (-1);
  395         while ((c = cncheckc()) == -1)
  396                 cpu_spinwait();
  397         if (c == '\r')
  398                 c = '\n';               /* console input is always ICRNL */
  399         return (c);
  400 }
  401 
  402 int
  403 cncheckc(void)
  404 {
  405         struct cn_device *cnd;
  406         struct consdev *cn;
  407         int c;
  408 
  409         if (cn_mute)
  410                 return (-1);
  411         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
  412                 cn = cnd->cnd_cn;
  413                 if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
  414                         c = cn->cn_ops->cn_getc(cn);
  415                         if (c != -1)
  416                                 return (c);
  417                 }
  418         }
  419         return (-1);
  420 }
  421 
  422 void
  423 cngets(char *cp, size_t size, int visible)
  424 {
  425         char *lp, *end;
  426         int c;
  427 
  428         cngrab();
  429 
  430         lp = cp;
  431         end = cp + size - 1;
  432         for (;;) {
  433                 c = cngetc() & 0177;
  434                 switch (c) {
  435                 case '\n':
  436                 case '\r':
  437                         cnputc(c);
  438                         *lp = '\0';
  439                         cnungrab();
  440                         return;
  441                 case '\b':
  442                 case '\177':
  443                         if (lp > cp) {
  444                                 if (visible)
  445                                         cnputs("\b \b");
  446                                 lp--;
  447                         }
  448                         continue;
  449                 case '\0':
  450                         continue;
  451                 default:
  452                         if (lp < end) {
  453                                 switch (visible) {
  454                                 case GETS_NOECHO:
  455                                         break;
  456                                 case GETS_ECHOPASS:
  457                                         cnputc('*');
  458                                         break;
  459                                 default:
  460                                         cnputc(c);
  461                                         break;
  462                                 }
  463                                 *lp++ = c;
  464                         }
  465                 }
  466         }
  467 }
  468 
  469 void
  470 cnputc(int c)
  471 {
  472         struct cn_device *cnd;
  473         struct consdev *cn;
  474         char *cp;
  475 
  476 #ifdef EARLY_PRINTF
  477         if (early_putc != NULL) {
  478                 if (c == '\n')
  479                         early_putc('\r');
  480                 early_putc(c);
  481                 return;
  482         }
  483 #endif
  484 
  485         if (cn_mute || c == '\0')
  486                 return;
  487         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
  488                 cn = cnd->cnd_cn;
  489                 if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
  490                         if (c == '\n')
  491                                 cn->cn_ops->cn_putc(cn, '\r');
  492                         cn->cn_ops->cn_putc(cn, c);
  493                 }
  494         }
  495         if (console_pausing && c == '\n' && !kdb_active) {
  496                 for (cp = console_pausestr; *cp != '\0'; cp++)
  497                         cnputc(*cp);
  498                 cngrab();
  499                 if (cngetc() == '.')
  500                         console_pausing = 0;
  501                 cnungrab();
  502                 cnputc('\r');
  503                 for (cp = console_pausestr; *cp != '\0'; cp++)
  504                         cnputc(' ');
  505                 cnputc('\r');
  506         }
  507 }
  508 
  509 void
  510 cnputs(char *p)
  511 {
  512         int c;
  513         int unlock_reqd = 0;
  514 
  515         if (use_cnputs_mtx) {
  516                 /*
  517                  * NOTE: Debug prints and/or witness printouts in
  518                  * console driver clients can cause the "cnputs_mtx"
  519                  * mutex to recurse. Simply return if that happens.
  520                  */
  521                 if (mtx_owned(&cnputs_mtx))
  522                         return;
  523                 mtx_lock_spin(&cnputs_mtx);
  524                 unlock_reqd = 1;
  525         }
  526 
  527         while ((c = *p++) != '\0')
  528                 cnputc(c);
  529 
  530         if (unlock_reqd)
  531                 mtx_unlock_spin(&cnputs_mtx);
  532 }
  533 
  534 static int consmsgbuf_size = 8192;
  535 SYSCTL_INT(_kern, OID_AUTO, consmsgbuf_size, CTLFLAG_RW, &consmsgbuf_size, 0,
  536     "Console tty buffer size");
  537 
  538 /*
  539  * Redirect console output to a tty.
  540  */
  541 void
  542 constty_set(struct tty *tp)
  543 {
  544         int size;
  545 
  546         KASSERT(tp != NULL, ("constty_set: NULL tp"));
  547         if (consbuf == NULL) {
  548                 size = consmsgbuf_size;
  549                 consbuf = malloc(size, M_TTYCONS, M_WAITOK);
  550                 msgbuf_init(&consmsgbuf, consbuf, size);
  551                 callout_init(&conscallout, 0);
  552         }
  553         constty = tp;
  554         constty_timeout(NULL);
  555 }
  556 
  557 /*
  558  * Disable console redirection to a tty.
  559  */
  560 void
  561 constty_clear(void)
  562 {
  563         int c;
  564 
  565         constty = NULL;
  566         if (consbuf == NULL)
  567                 return;
  568         callout_stop(&conscallout);
  569         while ((c = msgbuf_getchar(&consmsgbuf)) != -1)
  570                 cnputc(c);
  571         free(consbuf, M_TTYCONS);
  572         consbuf = NULL;
  573 }
  574 
  575 /* Times per second to check for pending console tty messages. */
  576 static int constty_wakeups_per_second = 5;
  577 SYSCTL_INT(_kern, OID_AUTO, constty_wakeups_per_second, CTLFLAG_RW,
  578     &constty_wakeups_per_second, 0,
  579     "Times per second to check for pending console tty messages");
  580 
  581 static void
  582 constty_timeout(void *arg)
  583 {
  584         int c;
  585 
  586         if (constty != NULL) {
  587                 tty_lock(constty);
  588                 while ((c = msgbuf_getchar(&consmsgbuf)) != -1) {
  589                         if (tty_putchar(constty, c) < 0) {
  590                                 tty_unlock(constty);
  591                                 constty = NULL;
  592                                 break;
  593                         }
  594                 }
  595 
  596                 if (constty != NULL)
  597                         tty_unlock(constty);
  598         }
  599         if (constty != NULL) {
  600                 callout_reset(&conscallout, hz / constty_wakeups_per_second,
  601                     constty_timeout, NULL);
  602         } else {
  603                 /* Deallocate the constty buffer memory. */
  604                 constty_clear();
  605         }
  606 }
  607 
  608 static void
  609 cn_drvinit(void *unused)
  610 {
  611 
  612         mtx_init(&cnputs_mtx, "cnputs_mtx", NULL, MTX_SPIN | MTX_NOWITNESS);
  613         use_cnputs_mtx = 1;
  614 }
  615 
  616 SYSINIT(cndev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, cn_drvinit, NULL);
  617 
  618 /*
  619  * Sysbeep(), if we have hardware for it
  620  */
  621 
  622 #ifdef HAS_TIMER_SPKR
  623 
  624 static int beeping;
  625 static struct callout beeping_timer;
  626 
  627 static void
  628 sysbeepstop(void *chan)
  629 {
  630 
  631         timer_spkr_release();
  632         beeping = 0;
  633 }
  634 
  635 int
  636 sysbeep(int pitch, int period)
  637 {
  638 
  639         if (timer_spkr_acquire()) {
  640                 if (!beeping) {
  641                         /* Something else owns it. */
  642                         return (EBUSY);
  643                 }
  644         }
  645         timer_spkr_setfreq(pitch);
  646         if (!beeping) {
  647                 beeping = period;
  648                 callout_reset(&beeping_timer, period, sysbeepstop, NULL);
  649         }
  650         return (0);
  651 }
  652 
  653 static void
  654 sysbeep_init(void *unused)
  655 {
  656 
  657         callout_init(&beeping_timer, 1);
  658 }
  659 SYSINIT(sysbeep, SI_SUB_SOFTINTR, SI_ORDER_ANY, sysbeep_init, NULL);
  660 #else
  661 
  662 /*
  663  * No hardware, no sound
  664  */
  665 
  666 int
  667 sysbeep(int pitch __unused, int period __unused)
  668 {
  669 
  670         return (ENODEV);
  671 }
  672 
  673 #endif
  674 
  675 /*
  676  * Temporary support for sc(4) to vt(4) transition.
  677  */
  678 static unsigned vty_prefer;
  679 static char vty_name[16];
  680 SYSCTL_STRING(_kern, OID_AUTO, vty, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, vty_name,
  681     0, "Console vty driver");
  682 
  683 int
  684 vty_enabled(unsigned vty)
  685 {
  686         static unsigned vty_selected = 0;
  687 
  688         if (vty_selected == 0) {
  689                 TUNABLE_STR_FETCH("kern.vty", vty_name, sizeof(vty_name));
  690                 do {
  691 #if defined(DEV_SC)
  692                         if (strcmp(vty_name, "sc") == 0) {
  693                                 vty_selected = VTY_SC;
  694                                 break;
  695                         }
  696 #endif
  697 #if defined(DEV_VT)
  698                         if (strcmp(vty_name, "vt") == 0) {
  699                                 vty_selected = VTY_VT;
  700                                 break;
  701                         }
  702 #endif
  703                         if (vty_prefer != 0) {
  704                                 vty_selected = vty_prefer;
  705                                 break;
  706                         }
  707 #if defined(DEV_VT)
  708                         vty_selected = VTY_VT;
  709 #elif defined(DEV_SC)
  710                         vty_selected = VTY_SC;
  711 #endif
  712                 } while (0);
  713 
  714                 if (vty_selected == VTY_VT)
  715                         strcpy(vty_name, "vt");
  716                 else if (vty_selected == VTY_SC)
  717                         strcpy(vty_name, "sc");
  718         }
  719         return ((vty_selected & vty) != 0);
  720 }
  721 
  722 void
  723 vty_set_preferred(unsigned vty)
  724 {
  725 
  726         vty_prefer = vty;
  727 #if !defined(DEV_SC)
  728         vty_prefer &= ~VTY_SC;
  729 #endif
  730 #if !defined(DEV_VT)
  731         vty_prefer &= ~VTY_VT;
  732 #endif
  733 }
  734 

Cache object: d9ce5054e30229908b12fd4f4c66979c


[ 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.