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: releng/12.0/sys/kern/kern_cons.c 334340 2018-05-29 16:16:24Z avg $");
   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 static int cn_mute;
   94 static char *consbuf;                   /* buffer used by `consmsgbuf' */
   95 static struct callout conscallout;      /* callout for outputting to constty */
   96 struct msgbuf consmsgbuf;               /* message buffer for console tty */
   97 static u_char console_pausing;          /* pause after each line during probe */
   98 static char *console_pausestr=
   99 "<pause; press any key to proceed to next line or '.' to end pause mode>";
  100 struct tty *constty;                    /* pointer to console "window" tty */
  101 static struct mtx cnputs_mtx;           /* Mutex for cnputs(). */
  102 static int use_cnputs_mtx = 0;          /* != 0 if cnputs_mtx locking reqd. */
  103 
  104 static void constty_timeout(void *arg);
  105 
  106 static struct consdev cons_consdev;
  107 DATA_SET(cons_set, cons_consdev);
  108 SET_DECLARE(cons_set, struct consdev);
  109 
  110 void
  111 cninit(void)
  112 {
  113         struct consdev *best_cn, *cn, **list;
  114 
  115         /*
  116          * Check if we should mute the console (for security reasons perhaps)
  117          * It can be changes dynamically using sysctl kern.consmute
  118          * once we are up and going.
  119          * 
  120          */
  121         cn_mute = ((boothowto & (RB_MUTE
  122                         |RB_SINGLE
  123                         |RB_VERBOSE
  124                         |RB_ASKNAME)) == RB_MUTE);
  125 
  126         /*
  127          * Find the first console with the highest priority.
  128          */
  129         best_cn = NULL;
  130         SET_FOREACH(list, cons_set) {
  131                 cn = *list;
  132                 cnremove(cn);
  133                 /* Skip cons_consdev. */
  134                 if (cn->cn_ops == NULL)
  135                         continue;
  136                 cn->cn_ops->cn_probe(cn);
  137                 if (cn->cn_pri == CN_DEAD)
  138                         continue;
  139                 if (best_cn == NULL || cn->cn_pri > best_cn->cn_pri)
  140                         best_cn = cn;
  141                 if (boothowto & RB_MULTIPLE) {
  142                         /*
  143                          * Initialize console, and attach to it.
  144                          */
  145                         cn->cn_ops->cn_init(cn);
  146                         cnadd(cn);
  147                 }
  148         }
  149         if (best_cn == NULL)
  150                 return;
  151         if ((boothowto & RB_MULTIPLE) == 0) {
  152                 best_cn->cn_ops->cn_init(best_cn);
  153                 cnadd(best_cn);
  154         }
  155         if (boothowto & RB_PAUSE)
  156                 console_pausing = 1;
  157         /*
  158          * Make the best console the preferred console.
  159          */
  160         cnselect(best_cn);
  161 
  162 #ifdef EARLY_PRINTF
  163         /*
  164          * Release early console.
  165          */
  166         early_putc = NULL;
  167 #endif
  168 }
  169 
  170 void
  171 cninit_finish()
  172 {
  173         console_pausing = 0;
  174 } 
  175 
  176 /* add a new physical console to back the virtual console */
  177 int
  178 cnadd(struct consdev *cn)
  179 {
  180         struct cn_device *cnd;
  181         int i;
  182 
  183         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next)
  184                 if (cnd->cnd_cn == cn)
  185                         return (0);
  186         for (i = 0; i < CNDEVTAB_SIZE; i++) {
  187                 cnd = &cn_devtab[i];
  188                 if (cnd->cnd_cn == NULL)
  189                         break;
  190         }
  191         if (cnd->cnd_cn != NULL)
  192                 return (ENOMEM);
  193         cnd->cnd_cn = cn;
  194         if (cn->cn_name[0] == '\0') {
  195                 /* XXX: it is unclear if/where this print might output */
  196                 printf("WARNING: console at %p has no name\n", cn);
  197         }
  198         STAILQ_INSERT_TAIL(&cn_devlist, cnd, cnd_next);
  199         if (STAILQ_FIRST(&cn_devlist) == cnd)
  200                 ttyconsdev_select(cnd->cnd_cn->cn_name);
  201 
  202         /* Add device to the active mask. */
  203         cnavailable(cn, (cn->cn_flags & CN_FLAG_NOAVAIL) == 0);
  204 
  205         return (0);
  206 }
  207 
  208 void
  209 cnremove(struct consdev *cn)
  210 {
  211         struct cn_device *cnd;
  212         int i;
  213 
  214         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
  215                 if (cnd->cnd_cn != cn)
  216                         continue;
  217                 if (STAILQ_FIRST(&cn_devlist) == cnd)
  218                         ttyconsdev_select(NULL);
  219                 STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next);
  220                 cnd->cnd_cn = NULL;
  221 
  222                 /* Remove this device from available mask. */
  223                 for (i = 0; i < CNDEVTAB_SIZE; i++) 
  224                         if (cnd == &cn_devtab[i]) {
  225                                 cons_avail_mask &= ~(1 << i);
  226                                 break;
  227                         }
  228 #if 0
  229                 /*
  230                  * XXX
  231                  * syscons gets really confused if console resources are
  232                  * freed after the system has initialized.
  233                  */
  234                 if (cn->cn_term != NULL)
  235                         cn->cn_ops->cn_term(cn);
  236 #endif
  237                 return;
  238         }
  239 }
  240 
  241 void
  242 cnselect(struct consdev *cn)
  243 {
  244         struct cn_device *cnd;
  245 
  246         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
  247                 if (cnd->cnd_cn != cn)
  248                         continue;
  249                 if (cnd == STAILQ_FIRST(&cn_devlist))
  250                         return;
  251                 STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next);
  252                 STAILQ_INSERT_HEAD(&cn_devlist, cnd, cnd_next);
  253                 ttyconsdev_select(cnd->cnd_cn->cn_name);
  254                 return;
  255         }
  256 }
  257 
  258 void
  259 cnavailable(struct consdev *cn, int available)
  260 {
  261         int i;
  262 
  263         for (i = 0; i < CNDEVTAB_SIZE; i++) {
  264                 if (cn_devtab[i].cnd_cn == cn)
  265                         break;
  266         }
  267         if (available) {
  268                 if (i < CNDEVTAB_SIZE)
  269                         cons_avail_mask |= (1 << i); 
  270                 cn->cn_flags &= ~CN_FLAG_NOAVAIL;
  271         } else {
  272                 if (i < CNDEVTAB_SIZE)
  273                         cons_avail_mask &= ~(1 << i);
  274                 cn->cn_flags |= CN_FLAG_NOAVAIL;
  275         }
  276 }
  277 
  278 int
  279 cnunavailable(void)
  280 {
  281 
  282         return (cons_avail_mask == 0);
  283 }
  284 
  285 /*
  286  * sysctl_kern_console() provides output parseable in conscontrol(1).
  287  */
  288 static int
  289 sysctl_kern_console(SYSCTL_HANDLER_ARGS)
  290 {
  291         struct cn_device *cnd;
  292         struct consdev *cp, **list;
  293         char *p;
  294         int delete, error;
  295         struct sbuf *sb;
  296 
  297         sb = sbuf_new(NULL, NULL, CNDEVPATHMAX * 2, SBUF_AUTOEXTEND |
  298             SBUF_INCLUDENUL);
  299         if (sb == NULL)
  300                 return (ENOMEM);
  301         sbuf_clear(sb);
  302         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next)
  303                 sbuf_printf(sb, "%s,", cnd->cnd_cn->cn_name);
  304         sbuf_printf(sb, "/");
  305         SET_FOREACH(list, cons_set) {
  306                 cp = *list;
  307                 if (cp->cn_name[0] != '\0')
  308                         sbuf_printf(sb, "%s,", cp->cn_name);
  309         }
  310         sbuf_finish(sb);
  311         error = sysctl_handle_string(oidp, sbuf_data(sb), sbuf_len(sb), req);
  312         if (error == 0 && req->newptr != NULL) {
  313                 p = sbuf_data(sb);
  314                 error = ENXIO;
  315                 delete = 0;
  316                 if (*p == '-') {
  317                         delete = 1;
  318                         p++;
  319                 }
  320                 SET_FOREACH(list, cons_set) {
  321                         cp = *list;
  322                         if (strcmp(p, cp->cn_name) != 0)
  323                                 continue;
  324                         if (delete) {
  325                                 cnremove(cp);
  326                                 error = 0;
  327                         } else {
  328                                 error = cnadd(cp);
  329                                 if (error == 0)
  330                                         cnselect(cp);
  331                         }
  332                         break;
  333                 }
  334         }
  335         sbuf_delete(sb);
  336         return (error);
  337 }
  338 
  339 SYSCTL_PROC(_kern, OID_AUTO, console, CTLTYPE_STRING|CTLFLAG_RW,
  340         0, 0, sysctl_kern_console, "A", "Console device control");
  341 
  342 /*
  343  * User has changed the state of the console muting.
  344  * This may require us to open or close the device in question.
  345  */
  346 static int
  347 sysctl_kern_consmute(SYSCTL_HANDLER_ARGS)
  348 {
  349         int error;
  350 
  351         error = sysctl_handle_int(oidp, &cn_mute, 0, req);
  352         if (error != 0 || req->newptr == NULL)
  353                 return (error);
  354         return (error);
  355 }
  356 
  357 SYSCTL_PROC(_kern, OID_AUTO, consmute, CTLTYPE_INT|CTLFLAG_RW,
  358         0, sizeof(cn_mute), sysctl_kern_consmute, "I",
  359         "State of the console muting");
  360 
  361 void
  362 cngrab()
  363 {
  364         struct cn_device *cnd;
  365         struct consdev *cn;
  366 
  367         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
  368                 cn = cnd->cnd_cn;
  369                 if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG))
  370                         cn->cn_ops->cn_grab(cn);
  371         }
  372 }
  373 
  374 void
  375 cnungrab()
  376 {
  377         struct cn_device *cnd;
  378         struct consdev *cn;
  379 
  380         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
  381                 cn = cnd->cnd_cn;
  382                 if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG))
  383                         cn->cn_ops->cn_ungrab(cn);
  384         }
  385 }
  386 
  387 void
  388 cnresume()
  389 {
  390         struct cn_device *cnd;
  391         struct consdev *cn;
  392 
  393         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
  394                 cn = cnd->cnd_cn;
  395                 if (cn->cn_ops->cn_resume != NULL)
  396                         cn->cn_ops->cn_resume(cn);
  397         }
  398 }
  399 
  400 /*
  401  * Low level console routines.
  402  */
  403 int
  404 cngetc(void)
  405 {
  406         int c;
  407 
  408         if (cn_mute)
  409                 return (-1);
  410         while ((c = cncheckc()) == -1)
  411                 cpu_spinwait();
  412         if (c == '\r')
  413                 c = '\n';               /* console input is always ICRNL */
  414         return (c);
  415 }
  416 
  417 int
  418 cncheckc(void)
  419 {
  420         struct cn_device *cnd;
  421         struct consdev *cn;
  422         int c;
  423 
  424         if (cn_mute)
  425                 return (-1);
  426         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
  427                 cn = cnd->cnd_cn;
  428                 if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
  429                         c = cn->cn_ops->cn_getc(cn);
  430                         if (c != -1)
  431                                 return (c);
  432                 }
  433         }
  434         return (-1);
  435 }
  436 
  437 void
  438 cngets(char *cp, size_t size, int visible)
  439 {
  440         char *lp, *end;
  441         int c;
  442 
  443         cngrab();
  444 
  445         lp = cp;
  446         end = cp + size - 1;
  447         for (;;) {
  448                 c = cngetc() & 0177;
  449                 switch (c) {
  450                 case '\n':
  451                 case '\r':
  452                         cnputc(c);
  453                         *lp = '\0';
  454                         cnungrab();
  455                         return;
  456                 case '\b':
  457                 case '\177':
  458                         if (lp > cp) {
  459                                 if (visible)
  460                                         cnputs("\b \b");
  461                                 lp--;
  462                         }
  463                         continue;
  464                 case '\0':
  465                         continue;
  466                 default:
  467                         if (lp < end) {
  468                                 switch (visible) {
  469                                 case GETS_NOECHO:
  470                                         break;
  471                                 case GETS_ECHOPASS:
  472                                         cnputc('*');
  473                                         break;
  474                                 default:
  475                                         cnputc(c);
  476                                         break;
  477                                 }
  478                                 *lp++ = c;
  479                         }
  480                 }
  481         }
  482 }
  483 
  484 void
  485 cnputc(int c)
  486 {
  487         struct cn_device *cnd;
  488         struct consdev *cn;
  489         char *cp;
  490 
  491 #ifdef EARLY_PRINTF
  492         if (early_putc != NULL) {
  493                 if (c == '\n')
  494                         early_putc('\r');
  495                 early_putc(c);
  496                 return;
  497         }
  498 #endif
  499 
  500         if (cn_mute || c == '\0')
  501                 return;
  502         STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
  503                 cn = cnd->cnd_cn;
  504                 if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
  505                         if (c == '\n')
  506                                 cn->cn_ops->cn_putc(cn, '\r');
  507                         cn->cn_ops->cn_putc(cn, c);
  508                 }
  509         }
  510         if (console_pausing && c == '\n' && !kdb_active) {
  511                 for (cp = console_pausestr; *cp != '\0'; cp++)
  512                         cnputc(*cp);
  513                 cngrab();
  514                 if (cngetc() == '.')
  515                         console_pausing = 0;
  516                 cnungrab();
  517                 cnputc('\r');
  518                 for (cp = console_pausestr; *cp != '\0'; cp++)
  519                         cnputc(' ');
  520                 cnputc('\r');
  521         }
  522 }
  523 
  524 void
  525 cnputs(char *p)
  526 {
  527         int c;
  528         int unlock_reqd = 0;
  529 
  530         if (use_cnputs_mtx) {
  531                 /*
  532                  * NOTE: Debug prints and/or witness printouts in
  533                  * console driver clients can cause the "cnputs_mtx"
  534                  * mutex to recurse. Simply return if that happens.
  535                  */
  536                 if (mtx_owned(&cnputs_mtx))
  537                         return;
  538                 mtx_lock_spin(&cnputs_mtx);
  539                 unlock_reqd = 1;
  540         }
  541 
  542         while ((c = *p++) != '\0')
  543                 cnputc(c);
  544 
  545         if (unlock_reqd)
  546                 mtx_unlock_spin(&cnputs_mtx);
  547 }
  548 
  549 static int consmsgbuf_size = 8192;
  550 SYSCTL_INT(_kern, OID_AUTO, consmsgbuf_size, CTLFLAG_RW, &consmsgbuf_size, 0,
  551     "Console tty buffer size");
  552 
  553 /*
  554  * Redirect console output to a tty.
  555  */
  556 void
  557 constty_set(struct tty *tp)
  558 {
  559         int size;
  560 
  561         KASSERT(tp != NULL, ("constty_set: NULL tp"));
  562         if (consbuf == NULL) {
  563                 size = consmsgbuf_size;
  564                 consbuf = malloc(size, M_TTYCONS, M_WAITOK);
  565                 msgbuf_init(&consmsgbuf, consbuf, size);
  566                 callout_init(&conscallout, 0);
  567         }
  568         constty = tp;
  569         constty_timeout(NULL);
  570 }
  571 
  572 /*
  573  * Disable console redirection to a tty.
  574  */
  575 void
  576 constty_clear(void)
  577 {
  578         int c;
  579 
  580         constty = NULL;
  581         if (consbuf == NULL)
  582                 return;
  583         callout_stop(&conscallout);
  584         while ((c = msgbuf_getchar(&consmsgbuf)) != -1)
  585                 cnputc(c);
  586         free(consbuf, M_TTYCONS);
  587         consbuf = NULL;
  588 }
  589 
  590 /* Times per second to check for pending console tty messages. */
  591 static int constty_wakeups_per_second = 5;
  592 SYSCTL_INT(_kern, OID_AUTO, constty_wakeups_per_second, CTLFLAG_RW,
  593     &constty_wakeups_per_second, 0,
  594     "Times per second to check for pending console tty messages");
  595 
  596 static void
  597 constty_timeout(void *arg)
  598 {
  599         int c;
  600 
  601         if (constty != NULL) {
  602                 tty_lock(constty);
  603                 while ((c = msgbuf_getchar(&consmsgbuf)) != -1) {
  604                         if (tty_putchar(constty, c) < 0) {
  605                                 tty_unlock(constty);
  606                                 constty = NULL;
  607                                 break;
  608                         }
  609                 }
  610 
  611                 if (constty != NULL)
  612                         tty_unlock(constty);
  613         }
  614         if (constty != NULL) {
  615                 callout_reset(&conscallout, hz / constty_wakeups_per_second,
  616                     constty_timeout, NULL);
  617         } else {
  618                 /* Deallocate the constty buffer memory. */
  619                 constty_clear();
  620         }
  621 }
  622 
  623 static void
  624 cn_drvinit(void *unused)
  625 {
  626 
  627         mtx_init(&cnputs_mtx, "cnputs_mtx", NULL, MTX_SPIN | MTX_NOWITNESS);
  628         use_cnputs_mtx = 1;
  629 }
  630 
  631 SYSINIT(cndev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, cn_drvinit, NULL);
  632 
  633 /*
  634  * Sysbeep(), if we have hardware for it
  635  */
  636 
  637 #ifdef HAS_TIMER_SPKR
  638 
  639 static int beeping;
  640 static struct callout beeping_timer;
  641 
  642 static void
  643 sysbeepstop(void *chan)
  644 {
  645 
  646         timer_spkr_release();
  647         beeping = 0;
  648 }
  649 
  650 int
  651 sysbeep(int pitch, int period)
  652 {
  653 
  654         if (timer_spkr_acquire()) {
  655                 if (!beeping) {
  656                         /* Something else owns it. */
  657                         return (EBUSY);
  658                 }
  659         }
  660         timer_spkr_setfreq(pitch);
  661         if (!beeping) {
  662                 beeping = period;
  663                 callout_reset(&beeping_timer, period, sysbeepstop, NULL);
  664         }
  665         return (0);
  666 }
  667 
  668 static void
  669 sysbeep_init(void *unused)
  670 {
  671 
  672         callout_init(&beeping_timer, 1);
  673 }
  674 SYSINIT(sysbeep, SI_SUB_SOFTINTR, SI_ORDER_ANY, sysbeep_init, NULL);
  675 #else
  676 
  677 /*
  678  * No hardware, no sound
  679  */
  680 
  681 int
  682 sysbeep(int pitch __unused, int period __unused)
  683 {
  684 
  685         return (ENODEV);
  686 }
  687 
  688 #endif
  689 
  690 /*
  691  * Temporary support for sc(4) to vt(4) transition.
  692  */
  693 static unsigned vty_prefer;
  694 static char vty_name[16];
  695 SYSCTL_STRING(_kern, OID_AUTO, vty, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, vty_name,
  696     0, "Console vty driver");
  697 
  698 int
  699 vty_enabled(unsigned vty)
  700 {
  701         static unsigned vty_selected = 0;
  702 
  703         if (vty_selected == 0) {
  704                 TUNABLE_STR_FETCH("kern.vty", vty_name, sizeof(vty_name));
  705                 do {
  706 #if defined(DEV_SC)
  707                         if (strcmp(vty_name, "sc") == 0) {
  708                                 vty_selected = VTY_SC;
  709                                 break;
  710                         }
  711 #endif
  712 #if defined(DEV_VT)
  713                         if (strcmp(vty_name, "vt") == 0) {
  714                                 vty_selected = VTY_VT;
  715                                 break;
  716                         }
  717 #endif
  718                         if (vty_prefer != 0) {
  719                                 vty_selected = vty_prefer;
  720                                 break;
  721                         }
  722 #if defined(DEV_VT)
  723                         vty_selected = VTY_VT;
  724 #elif defined(DEV_SC)
  725                         vty_selected = VTY_SC;
  726 #endif
  727                 } while (0);
  728 
  729                 if (vty_selected == VTY_VT)
  730                         strcpy(vty_name, "vt");
  731                 else if (vty_selected == VTY_SC)
  732                         strcpy(vty_name, "sc");
  733         }
  734         return ((vty_selected & vty) != 0);
  735 }
  736 
  737 void
  738 vty_set_preferred(unsigned vty)
  739 {
  740 
  741         vty_prefer = vty;
  742 #if !defined(DEV_SC)
  743         vty_prefer &= ~VTY_SC;
  744 #endif
  745 #if !defined(DEV_VT)
  746         vty_prefer &= ~VTY_VT;
  747 #endif
  748 }
  749 

Cache object: eb3d5e62f73278e341ed75baccc5064b


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