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

Cache object: 17f81edff8aefc8c5361a79fe2f99956


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