summaryrefslogtreecommitdiffstats
path: root/sys/kern/tty_cons.c
diff options
context:
space:
mode:
authored <ed@FreeBSD.org>2008-11-01 08:35:28 +0000
committered <ed@FreeBSD.org>2008-11-01 08:35:28 +0000
commitc2c324d37976496417e7195d8daae3975be8eaa1 (patch)
tree92b387a3b5878c3317cf997130d7bc5769e5f6e5 /sys/kern/tty_cons.c
parentec4658731c7b03d16de04acf5f20aa4dc53635cb (diff)
downloadFreeBSD-src-c2c324d37976496417e7195d8daae3975be8eaa1.zip
FreeBSD-src-c2c324d37976496417e7195d8daae3975be8eaa1.tar.gz
Reimplement the /dev/console device node.
One of the pieces of code that I had left alone during the development of the MPSAFE TTY layer, was tty_cons.c. This file actually has two different functions: - It contains low-level console input/output routines (cnputc(), etc). - It creates /dev/console and wraps all its cdevsw calls to the appropriate TTY. This commit reimplements the second set of functions by moving it directly into the TTY layer. /dev/console is now a character device node that's basically a regular TTY, but does a lookup of `si_drv1' each time you open it. d_write has also been changed to call log_console(). d_close() is not present, because we must make sure we don't revoke the TTY after writing a log message to it. Even though I'm not convinced this is in line with the future directions of our console code, it is a good move for now. It removes recursive locking from the top half of the TTY layer. The previous implementation called into the TTY layer with Giant held. I'm renaming tty_cons.c to kern_cons.c now. The code hardly contains any TTY related bits, so we'd better give it a less misleading name. Tested by: Andrzej Tobola <ato iem pw edu pl>, Carlos A.M. dos Santos <unixmania gmail com>, Eygene Ryabinkin <rea-fbsd codelabs ru>
Diffstat (limited to 'sys/kern/tty_cons.c')
-rw-r--r--sys/kern/tty_cons.c796
1 files changed, 0 insertions, 796 deletions
diff --git a/sys/kern/tty_cons.c b/sys/kern/tty_cons.c
deleted file mode 100644
index 81e1708..0000000
--- a/sys/kern/tty_cons.c
+++ /dev/null
@@ -1,796 +0,0 @@
-/*-
- * Copyright (c) 1988 University of Utah.
- * Copyright (c) 1991 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * the Systems Programming Group of the University of Utah Computer
- * Science Department.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * from: @(#)cons.c 7.2 (Berkeley) 5/9/91
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_ddb.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/conf.h>
-#include <sys/cons.h>
-#include <sys/fcntl.h>
-#include <sys/kdb.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/msgbuf.h>
-#include <sys/namei.h>
-#include <sys/priv.h>
-#include <sys/proc.h>
-#include <sys/queue.h>
-#include <sys/reboot.h>
-#include <sys/sysctl.h>
-#include <sys/sbuf.h>
-#include <sys/tty.h>
-#include <sys/uio.h>
-#include <sys/vnode.h>
-
-#include <ddb/ddb.h>
-
-#include <machine/cpu.h>
-#include <machine/clock.h>
-
-static MALLOC_DEFINE(M_TTYCONS, "tty console", "tty console handling");
-
-static d_open_t cnopen;
-static d_close_t cnclose;
-static d_read_t cnread;
-static d_write_t cnwrite;
-static d_ioctl_t cnioctl;
-static d_poll_t cnpoll;
-static d_kqfilter_t cnkqfilter;
-
-static struct cdevsw cn_cdevsw = {
- .d_version = D_VERSION,
- .d_open = cnopen,
- .d_close = cnclose,
- .d_read = cnread,
- .d_write = cnwrite,
- .d_ioctl = cnioctl,
- .d_poll = cnpoll,
- .d_name = "console",
- .d_flags = D_TTY | D_NEEDGIANT,
- .d_kqfilter = cnkqfilter,
-};
-
-struct cn_device {
- STAILQ_ENTRY(cn_device) cnd_next;
- struct vnode *cnd_vp;
- struct consdev *cnd_cn;
-};
-
-#define CNDEVPATHMAX 32
-#define CNDEVTAB_SIZE 4
-static struct cn_device cn_devtab[CNDEVTAB_SIZE];
-static STAILQ_HEAD(, cn_device) cn_devlist =
- STAILQ_HEAD_INITIALIZER(cn_devlist);
-
-#define CND_INVALID(cnd, td) \
- (cnd == NULL || cnd->cnd_vp == NULL || \
- (cnd->cnd_vp->v_type == VBAD && !cn_devopen(cnd, td, 1)))
-
-static dev_t cn_udev_t;
-SYSCTL_OPAQUE(_machdep, OID_AUTO, consdev, CTLFLAG_RD,
- &cn_udev_t, sizeof cn_udev_t, "T,struct cdev *", "");
-
-int cons_avail_mask = 0; /* Bit mask. Each registered low level console
- * which is currently unavailable for inpit
- * (i.e., if it is in graphics mode) will have
- * this bit cleared.
- */
-static int cn_mute;
-static int openflag; /* how /dev/console was opened */
-static int cn_is_open;
-static char *consbuf; /* buffer used by `consmsgbuf' */
-static struct callout conscallout; /* callout for outputting to constty */
-struct msgbuf consmsgbuf; /* message buffer for console tty */
-static u_char console_pausing; /* pause after each line during probe */
-static char *console_pausestr=
-"<pause; press any key to proceed to next line or '.' to end pause mode>";
-struct tty *constty; /* pointer to console "window" tty */
-static struct mtx cnputs_mtx; /* Mutex for cnputs(). */
-static int use_cnputs_mtx = 0; /* != 0 if cnputs_mtx locking reqd. */
-
-static void constty_timeout(void *arg);
-
-static struct consdev cons_consdev;
-DATA_SET(cons_set, cons_consdev);
-SET_DECLARE(cons_set, struct consdev);
-
-void
-cninit(void)
-{
- struct consdev *best_cn, *cn, **list;
-
- /*
- * Check if we should mute the console (for security reasons perhaps)
- * It can be changes dynamically using sysctl kern.consmute
- * once we are up and going.
- *
- */
- cn_mute = ((boothowto & (RB_MUTE
- |RB_SINGLE
- |RB_VERBOSE
- |RB_ASKNAME)) == RB_MUTE);
-
- /*
- * Find the first console with the highest priority.
- */
- best_cn = NULL;
- SET_FOREACH(list, cons_set) {
- cn = *list;
- cnremove(cn);
- if (cn->cn_probe == NULL)
- continue;
- cn->cn_probe(cn);
- if (cn->cn_pri == CN_DEAD)
- continue;
- if (best_cn == NULL || cn->cn_pri > best_cn->cn_pri)
- best_cn = cn;
- if (boothowto & RB_MULTIPLE) {
- /*
- * Initialize console, and attach to it.
- */
- cn->cn_init(cn);
- cnadd(cn);
- }
- }
- if (best_cn == NULL)
- return;
- if ((boothowto & RB_MULTIPLE) == 0) {
- best_cn->cn_init(best_cn);
- cnadd(best_cn);
- }
- if (boothowto & RB_PAUSE)
- console_pausing = 1;
- /*
- * Make the best console the preferred console.
- */
- cnselect(best_cn);
-}
-
-void
-cninit_finish()
-{
- console_pausing = 0;
-}
-
-/* add a new physical console to back the virtual console */
-int
-cnadd(struct consdev *cn)
-{
- struct cn_device *cnd;
- int i;
-
- STAILQ_FOREACH(cnd, &cn_devlist, cnd_next)
- if (cnd->cnd_cn == cn)
- return (0);
- for (i = 0; i < CNDEVTAB_SIZE; i++) {
- cnd = &cn_devtab[i];
- if (cnd->cnd_cn == NULL)
- break;
- }
- if (cnd->cnd_cn != NULL)
- return (ENOMEM);
- cnd->cnd_cn = cn;
- if (cn->cn_name[0] == '\0') {
- /* XXX: it is unclear if/where this print might output */
- printf("WARNING: console at %p has no name\n", cn);
- }
- STAILQ_INSERT_TAIL(&cn_devlist, cnd, cnd_next);
-
- /* Add device to the active mask. */
- cnavailable(cn, (cn->cn_flags & CN_FLAG_NOAVAIL) == 0);
-
- return (0);
-}
-
-void
-cnremove(struct consdev *cn)
-{
- struct cn_device *cnd;
- int i;
-
- STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
- if (cnd->cnd_cn != cn)
- continue;
- STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next);
- if (cnd->cnd_vp != NULL)
- vn_close(cnd->cnd_vp, openflag, NOCRED, NULL);
- cnd->cnd_vp = NULL;
- cnd->cnd_cn = NULL;
-
- /* Remove this device from available mask. */
- for (i = 0; i < CNDEVTAB_SIZE; i++)
- if (cnd == &cn_devtab[i]) {
- cons_avail_mask &= ~(1 << i);
- break;
- }
-#if 0
- /*
- * XXX
- * syscons gets really confused if console resources are
- * freed after the system has initialized.
- */
- if (cn->cn_term != NULL)
- cn->cn_term(cn);
-#endif
- return;
- }
-}
-
-void
-cnselect(struct consdev *cn)
-{
- struct cn_device *cnd;
-
- STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
- if (cnd->cnd_cn != cn)
- continue;
- if (cnd == STAILQ_FIRST(&cn_devlist))
- return;
- STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next);
- STAILQ_INSERT_HEAD(&cn_devlist, cnd, cnd_next);
- return;
- }
-}
-
-void
-cnavailable(struct consdev *cn, int available)
-{
- int i;
-
- for (i = 0; i < CNDEVTAB_SIZE; i++) {
- if (cn_devtab[i].cnd_cn == cn)
- break;
- }
- if (available) {
- if (i < CNDEVTAB_SIZE)
- cons_avail_mask |= (1 << i);
- cn->cn_flags &= ~CN_FLAG_NOAVAIL;
- } else {
- if (i < CNDEVTAB_SIZE)
- cons_avail_mask &= ~(1 << i);
- cn->cn_flags |= CN_FLAG_NOAVAIL;
- }
-}
-
-int
-cnunavailable(void)
-{
-
- return (cons_avail_mask == 0);
-}
-
-/*
- * sysctl_kern_console() provides output parseable in conscontrol(1).
- */
-static int
-sysctl_kern_console(SYSCTL_HANDLER_ARGS)
-{
- struct cn_device *cnd;
- struct consdev *cp, **list;
- char *p;
- int delete, error;
- struct sbuf *sb;
-
- sb = sbuf_new(NULL, NULL, CNDEVPATHMAX * 2, SBUF_AUTOEXTEND);
- if (sb == NULL)
- return (ENOMEM);
- sbuf_clear(sb);
- STAILQ_FOREACH(cnd, &cn_devlist, cnd_next)
- sbuf_printf(sb, "%s,", cnd->cnd_cn->cn_name);
- sbuf_printf(sb, "/");
- SET_FOREACH(list, cons_set) {
- cp = *list;
- if (cp->cn_name[0] != '\0')
- sbuf_printf(sb, "%s,", cp->cn_name);
- }
- sbuf_finish(sb);
- error = sysctl_handle_string(oidp, sbuf_data(sb), sbuf_len(sb), req);
- if (error == 0 && req->newptr != NULL) {
- p = sbuf_data(sb);
- error = ENXIO;
- delete = 0;
- if (*p == '-') {
- delete = 1;
- p++;
- }
- SET_FOREACH(list, cons_set) {
- cp = *list;
- if (strcmp(p, cp->cn_name) != 0)
- continue;
- if (delete) {
- cnremove(cp);
- error = 0;
- } else {
- error = cnadd(cp);
- if (error == 0)
- cnselect(cp);
- }
- break;
- }
- }
- sbuf_delete(sb);
- return (error);
-}
-
-SYSCTL_PROC(_kern, OID_AUTO, console, CTLTYPE_STRING|CTLFLAG_RW,
- 0, 0, sysctl_kern_console, "A", "Console device control");
-
-/*
- * User has changed the state of the console muting.
- * This may require us to open or close the device in question.
- */
-static int
-sysctl_kern_consmute(SYSCTL_HANDLER_ARGS)
-{
- int error;
- int ocn_mute;
-
- ocn_mute = cn_mute;
- error = sysctl_handle_int(oidp, &cn_mute, 0, req);
- if (error != 0 || req->newptr == NULL)
- return (error);
- if (ocn_mute && !cn_mute && cn_is_open)
- error = cnopen(NULL, openflag, 0, curthread);
- else if (!ocn_mute && cn_mute && cn_is_open) {
- error = cnclose(NULL, openflag, 0, curthread);
- cn_is_open = 1; /* XXX hack */
- }
- return (error);
-}
-
-SYSCTL_PROC(_kern, OID_AUTO, consmute, CTLTYPE_INT|CTLFLAG_RW,
- 0, sizeof(cn_mute), sysctl_kern_consmute, "I", "");
-
-static int
-cn_devopen(struct cn_device *cnd, struct thread *td, int forceopen)
-{
- char path[CNDEVPATHMAX];
- struct nameidata nd;
- struct vnode *vp;
- struct cdev *dev;
- struct cdevsw *csw;
- int error;
-
- if ((vp = cnd->cnd_vp) != NULL) {
- if (!forceopen && vp->v_type != VBAD) {
- dev = vp->v_rdev;
- csw = dev_refthread(dev);
- if (csw == NULL)
- return (ENXIO);
- error = (*csw->d_open)(dev, openflag, 0, td);
- dev_relthread(dev);
- return (error);
- }
- cnd->cnd_vp = NULL;
- vn_close(vp, openflag, td->td_ucred, td);
- }
- snprintf(path, sizeof(path), "/dev/%s", cnd->cnd_cn->cn_name);
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td);
- error = vn_open(&nd, &openflag, 0, NULL);
- if (error == 0) {
- NDFREE(&nd, NDF_ONLY_PNBUF);
- VOP_UNLOCK(nd.ni_vp, 0);
- if (nd.ni_vp->v_type == VCHR)
- cnd->cnd_vp = nd.ni_vp;
- else
- vn_close(nd.ni_vp, openflag, td->td_ucred, td);
- }
- return (cnd->cnd_vp != NULL);
-}
-
-static int
-cnopen(struct cdev *dev, int flag, int mode, struct thread *td)
-{
- struct cn_device *cnd;
-
- openflag = flag | FWRITE; /* XXX */
- cn_is_open = 1; /* console is logically open */
- if (cn_mute)
- return (0);
- STAILQ_FOREACH(cnd, &cn_devlist, cnd_next)
- cn_devopen(cnd, td, 0);
- return (0);
-}
-
-static int
-cnclose(struct cdev *dev, int flag, int mode, struct thread *td)
-{
- struct cn_device *cnd;
- struct vnode *vp;
-
- STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
- if ((vp = cnd->cnd_vp) == NULL)
- continue;
- cnd->cnd_vp = NULL;
- vn_close(vp, openflag, td->td_ucred, td);
- }
- cn_is_open = 0;
- return (0);
-}
-
-static int
-cnread(struct cdev *dev, struct uio *uio, int flag)
-{
- struct cn_device *cnd;
- struct cdevsw *csw;
- int error;
-
- cnd = STAILQ_FIRST(&cn_devlist);
- if (cn_mute || CND_INVALID(cnd, curthread))
- return (0);
- dev = cnd->cnd_vp->v_rdev;
- csw = dev_refthread(dev);
- if (csw == NULL)
- return (ENXIO);
- error = (csw->d_read)(dev, uio, flag);
- dev_relthread(dev);
- return (error);
-}
-
-static int
-cnwrite(struct cdev *dev, struct uio *uio, int flag)
-{
- struct cn_device *cnd;
- struct cdevsw *csw;
- int error;
-
- cnd = STAILQ_FIRST(&cn_devlist);
- if (cn_mute || CND_INVALID(cnd, curthread))
- goto done;
- if (constty)
- dev = constty->t_dev;
- else
- dev = cnd->cnd_vp->v_rdev;
- if (dev != NULL) {
- log_console(uio);
- csw = dev_refthread(dev);
- if (csw == NULL)
- return (ENXIO);
- error = (csw->d_write)(dev, uio, flag);
- dev_relthread(dev);
- return (error);
- }
-done:
- uio->uio_resid = 0; /* dump the data */
- return (0);
-}
-
-static int
-cnioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
-{
- struct cn_device *cnd;
- struct cdevsw *csw;
- int error;
-
- cnd = STAILQ_FIRST(&cn_devlist);
- if (cn_mute || CND_INVALID(cnd, td))
- return (0);
- /*
- * Superuser can always use this to wrest control of console
- * output from the "virtual" console.
- */
- if (cmd == TIOCCONS && constty) {
- error = priv_check(td, PRIV_TTY_CONSOLE);
- if (error)
- return (error);
- constty = NULL;
- return (0);
- }
- dev = cnd->cnd_vp->v_rdev;
- if (dev == NULL)
- return (0); /* XXX : ENOTTY ? */
- csw = dev_refthread(dev);
- if (csw == NULL)
- return (ENXIO);
- error = (csw->d_ioctl)(dev, cmd, data, flag, td);
- dev_relthread(dev);
- return (error);
-}
-
-/*
- * XXX
- * poll/kqfilter do not appear to be correct
- */
-static int
-cnpoll(struct cdev *dev, int events, struct thread *td)
-{
- struct cn_device *cnd;
- struct cdevsw *csw;
- int error;
-
- cnd = STAILQ_FIRST(&cn_devlist);
- if (cn_mute || CND_INVALID(cnd, td))
- return (0);
- dev = cnd->cnd_vp->v_rdev;
- if (dev == NULL)
- return (0);
- csw = dev_refthread(dev);
- if (csw == NULL)
- return (ENXIO);
- error = (csw->d_poll)(dev, events, td);
- dev_relthread(dev);
- return (error);
-}
-
-static int
-cnkqfilter(struct cdev *dev, struct knote *kn)
-{
- struct cn_device *cnd;
- struct cdevsw *csw;
- int error;
-
- cnd = STAILQ_FIRST(&cn_devlist);
- if (cn_mute || CND_INVALID(cnd, curthread))
- return (EINVAL);
- dev = cnd->cnd_vp->v_rdev;
- if (dev == NULL)
- return (ENXIO);
- csw = dev_refthread(dev);
- if (csw == NULL)
- return (ENXIO);
- error = (csw->d_kqfilter)(dev, kn);
- dev_relthread(dev);
- return (error);
-}
-
-/*
- * Low level console routines.
- */
-int
-cngetc(void)
-{
- int c;
-
- if (cn_mute)
- return (-1);
- while ((c = cncheckc()) == -1)
- ;
- if (c == '\r')
- c = '\n'; /* console input is always ICRNL */
- return (c);
-}
-
-int
-cncheckc(void)
-{
- struct cn_device *cnd;
- struct consdev *cn;
- int c;
-
- if (cn_mute)
- return (-1);
- STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
- cn = cnd->cnd_cn;
- if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
- if (cn->cn_checkc != NULL)
- c = cn->cn_checkc(cn);
- else
- c = cn->cn_getc(cn);
- if (c != -1) {
- return (c);
- }
- }
- }
- return (-1);
-}
-
-void
-cnputc(int c)
-{
- struct cn_device *cnd;
- struct consdev *cn;
- char *cp;
-
- if (cn_mute || c == '\0')
- return;
- STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {
- cn = cnd->cnd_cn;
- if (!kdb_active || !(cn->cn_flags & CN_FLAG_NODEBUG)) {
- if (c == '\n')
- cn->cn_putc(cn, '\r');
- cn->cn_putc(cn, c);
- }
- }
- if (console_pausing && c == '\n' && !kdb_active) {
- for (cp = console_pausestr; *cp != '\0'; cp++)
- cnputc(*cp);
- if (cngetc() == '.')
- console_pausing = 0;
- cnputc('\r');
- for (cp = console_pausestr; *cp != '\0'; cp++)
- cnputc(' ');
- cnputc('\r');
- }
-}
-
-void
-cnputs(char *p)
-{
- int c;
- int unlock_reqd = 0;
-
- if (use_cnputs_mtx) {
- mtx_lock_spin(&cnputs_mtx);
- unlock_reqd = 1;
- }
-
- while ((c = *p++) != '\0')
- cnputc(c);
-
- if (unlock_reqd)
- mtx_unlock_spin(&cnputs_mtx);
-}
-
-static int consmsgbuf_size = 8192;
-SYSCTL_INT(_kern, OID_AUTO, consmsgbuf_size, CTLFLAG_RW, &consmsgbuf_size, 0,
- "");
-
-/*
- * Redirect console output to a tty.
- */
-void
-constty_set(struct tty *tp)
-{
- int size;
-
- KASSERT(tp != NULL, ("constty_set: NULL tp"));
- if (consbuf == NULL) {
- size = consmsgbuf_size;
- consbuf = malloc(size, M_TTYCONS, M_WAITOK);
- msgbuf_init(&consmsgbuf, consbuf, size);
- callout_init(&conscallout, 0);
- }
- constty = tp;
- constty_timeout(NULL);
-}
-
-/*
- * Disable console redirection to a tty.
- */
-void
-constty_clear(void)
-{
- int c;
-
- constty = NULL;
- if (consbuf == NULL)
- return;
- callout_stop(&conscallout);
- while ((c = msgbuf_getchar(&consmsgbuf)) != -1)
- cnputc(c);
- free(consbuf, M_TTYCONS);
- consbuf = NULL;
-}
-
-/* Times per second to check for pending console tty messages. */
-static int constty_wakeups_per_second = 5;
-SYSCTL_INT(_kern, OID_AUTO, constty_wakeups_per_second, CTLFLAG_RW,
- &constty_wakeups_per_second, 0, "");
-
-static void
-constty_timeout(void *arg)
-{
- int c;
-
- if (constty != NULL) {
- tty_lock(constty);
- while ((c = msgbuf_getchar(&consmsgbuf)) != -1) {
- if (tty_putchar(constty, c) < 0) {
- tty_unlock(constty);
- constty = NULL;
- break;
- }
- }
-
- if (constty != NULL)
- tty_unlock(constty);
- }
- if (constty != NULL) {
- callout_reset(&conscallout, hz / constty_wakeups_per_second,
- constty_timeout, NULL);
- } else {
- /* Deallocate the constty buffer memory. */
- constty_clear();
- }
-}
-
-static void
-cn_drvinit(void *unused)
-{
-
- make_dev(&cn_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "console");
-
- mtx_init(&cnputs_mtx, "cnputs_mtx", NULL, MTX_SPIN | MTX_NOWITNESS);
- use_cnputs_mtx = 1;
-}
-
-SYSINIT(cndev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, cn_drvinit, NULL);
-
-/*
- * Sysbeep(), if we have hardware for it
- */
-
-#ifdef HAS_TIMER_SPKR
-
-static int beeping;
-
-static void
-sysbeepstop(void *chan)
-{
-
- timer_spkr_release();
- beeping = 0;
-}
-
-int
-sysbeep(int pitch, int period)
-{
-
- if (timer_spkr_acquire()) {
- if (!beeping) {
- /* Something else owns it. */
- return (EBUSY);
- }
- }
- timer_spkr_setfreq(pitch);
- if (!beeping) {
- beeping = period;
- timeout(sysbeepstop, (void *)NULL, period);
- }
- return (0);
-}
-
-#else
-
-/*
- * No hardware, no sound
- */
-
-int
-sysbeep(int pitch __unused, int period __unused)
-{
-
- return (ENODEV);
-}
-
-#endif
-
OpenPOWER on IntegriCloud