kern_cons.c revision 111815
14Srgrimes/* 24Srgrimes * Copyright (c) 1988 University of Utah. 34Srgrimes * Copyright (c) 1991 The Regents of the University of California. 44Srgrimes * All rights reserved. 54Srgrimes * 64Srgrimes * This code is derived from software contributed to Berkeley by 74Srgrimes * the Systems Programming Group of the University of Utah Computer 84Srgrimes * Science Department. 94Srgrimes * 104Srgrimes * Redistribution and use in source and binary forms, with or without 114Srgrimes * modification, are permitted provided that the following conditions 124Srgrimes * are met: 134Srgrimes * 1. Redistributions of source code must retain the above copyright 144Srgrimes * notice, this list of conditions and the following disclaimer. 154Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 164Srgrimes * notice, this list of conditions and the following disclaimer in the 174Srgrimes * documentation and/or other materials provided with the distribution. 184Srgrimes * 3. All advertising materials mentioning features or use of this software 194Srgrimes * must display the following acknowledgement: 204Srgrimes * This product includes software developed by the University of 214Srgrimes * California, Berkeley and its contributors. 224Srgrimes * 4. Neither the name of the University nor the names of its contributors 234Srgrimes * may be used to endorse or promote products derived from this software 244Srgrimes * without specific prior written permission. 254Srgrimes * 264Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 274Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 284Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 294Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 304Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 314Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 324Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 334Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 344Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 354Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 364Srgrimes * SUCH DAMAGE. 374Srgrimes * 38620Srgrimes * from: @(#)cons.c 7.2 (Berkeley) 5/9/91 3950477Speter * $FreeBSD: head/sys/kern/tty_cons.c 111815 2003-03-03 12:15:54Z phk $ 404Srgrimes */ 414Srgrimes 4287649Sguido#include "opt_ddb.h" 4387649Sguido 442056Swollman#include <sys/param.h> 451549Srgrimes#include <sys/systm.h> 465764Sbde#include <sys/conf.h> 4756525Sbde#include <sys/cons.h> 4885448Sjlemon#include <sys/fcntl.h> 4912675Sjulian#include <sys/kernel.h> 5085373Sjlemon#include <sys/malloc.h> 5185373Sjlemon#include <sys/namei.h> 5269929Sobrien#include <sys/proc.h> 5385373Sjlemon#include <sys/queue.h> 5418951Sjulian#include <sys/reboot.h> 5512701Sphk#include <sys/sysctl.h> 562056Swollman#include <sys/tty.h> 5734924Sbde#include <sys/uio.h> 5885373Sjlemon#include <sys/vnode.h> 594Srgrimes 6087620Sguido#include <ddb/ddb.h> 6187620Sguido 6212701Sphk#include <machine/cpu.h> 634Srgrimes 6412675Sjulianstatic d_open_t cnopen; 6512675Sjulianstatic d_close_t cnclose; 6612675Sjulianstatic d_read_t cnread; 6712675Sjulianstatic d_write_t cnwrite; 6812675Sjulianstatic d_ioctl_t cnioctl; 6929368Speterstatic d_poll_t cnpoll; 7072521Sjlemonstatic d_kqfilter_t cnkqfilter; 7112675Sjulian 7238485Sbde#define CDEV_MAJOR 0 7347625Sphkstatic struct cdevsw cn_cdevsw = { 74111815Sphk .d_open = cnopen, 75111815Sphk .d_close = cnclose, 76111815Sphk .d_read = cnread, 77111815Sphk .d_write = cnwrite, 78111815Sphk .d_ioctl = cnioctl, 79111815Sphk .d_poll = cnpoll, 80111815Sphk .d_name = "console", 81111815Sphk .d_maj = CDEV_MAJOR, 82111815Sphk .d_flags = D_TTY | D_KQFILTER, 83111815Sphk .d_kqfilter = cnkqfilter, 8438485Sbde}; 8512675Sjulian 8685373Sjlemonstruct cn_device { 8785373Sjlemon STAILQ_ENTRY(cn_device) cnd_next; 8885373Sjlemon char cnd_name[16]; 8985373Sjlemon struct vnode *cnd_vp; 9085373Sjlemon struct consdev *cnd_cn; 9185373Sjlemon}; 9285373Sjlemon 9385373Sjlemon#define CNDEVPATHMAX 32 9485373Sjlemon#define CNDEVTAB_SIZE 4 9585373Sjlemonstatic struct cn_device cn_devtab[CNDEVTAB_SIZE]; 9685373Sjlemonstatic STAILQ_HEAD(, cn_device) cn_devlist = 9785373Sjlemon STAILQ_HEAD_INITIALIZER(cn_devlist); 9885373Sjlemon 9985373Sjlemon#define CND_INVALID(cnd, td) \ 10085373Sjlemon (cnd == NULL || cnd->cnd_vp == NULL || \ 10185373Sjlemon (cnd->cnd_vp->v_type == VBAD && !cn_devopen(cnd, td, 1))) 10285373Sjlemon 10349049Syokotastatic udev_t cn_udev_t; 10441612SeivindSYSCTL_OPAQUE(_machdep, CPU_CONSDEV, consdev, CTLFLAG_RD, 10549049Syokota &cn_udev_t, sizeof cn_udev_t, "T,dev_t", ""); 10627982Sjulian 1077680Sjoergint cons_unavail = 0; /* XXX: 1087680Sjoerg * physical console not available for 1097680Sjoerg * input (i.e., it is in graphics mode) 1107680Sjoerg */ 11185373Sjlemonstatic int cn_mute; 11285373Sjlemonstatic int openflag; /* how /dev/console was opened */ 11385373Sjlemonstatic int cn_is_open; 11487620Sguidostatic u_char console_pausing; /* pause after each line during probe */ 11587620Sguidostatic char *console_pausestr= 11687620Sguido"<pause; press any key to proceed to next line or '.' to end pause mode>"; 1175764Sbde 11885448Sjlemonvoid cndebug(char *); 11985448Sjlemon 12055823SyokotaCONS_DRIVER(cons, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 12178161SpeterSET_DECLARE(cons_set, struct consdev); 12242373Syokota 123798Swollmanvoid 12485373Sjlemoncninit(void) 1254Srgrimes{ 12685373Sjlemon struct consdev *best_cn, *cn, **list; 1274Srgrimes 1284Srgrimes /* 12918951Sjulian * Check if we should mute the console (for security reasons perhaps) 13018951Sjulian * It can be changes dynamically using sysctl kern.consmute 13118951Sjulian * once we are up and going. 13218951Sjulian * 13318951Sjulian */ 13418951Sjulian cn_mute = ((boothowto & (RB_MUTE 13518951Sjulian |RB_SINGLE 13618951Sjulian |RB_VERBOSE 13718951Sjulian |RB_ASKNAME 13818951Sjulian |RB_CONFIG)) == RB_MUTE); 13985373Sjlemon 14018951Sjulian /* 14185373Sjlemon * Find the first console with the highest priority. 1424Srgrimes */ 14385373Sjlemon best_cn = NULL; 14485373Sjlemon SET_FOREACH(list, cons_set) { 14585373Sjlemon cn = *list; 146101436Sjake cnremove(cn); 14785373Sjlemon if (cn->cn_probe == NULL) 14885373Sjlemon continue; 14985373Sjlemon cn->cn_probe(cn); 15085373Sjlemon if (cn->cn_pri == CN_DEAD) 15185373Sjlemon continue; 15285373Sjlemon if (best_cn == NULL || cn->cn_pri > best_cn->cn_pri) 15385373Sjlemon best_cn = cn; 15485373Sjlemon if (boothowto & RB_MULTIPLE) { 15585373Sjlemon /* 15685373Sjlemon * Initialize console, and attach to it. 15785373Sjlemon */ 15885373Sjlemon cnadd(cn); 15985373Sjlemon cn->cn_init(cn); 16085373Sjlemon } 16185373Sjlemon } 16285373Sjlemon if (best_cn == NULL) 1634Srgrimes return; 16485373Sjlemon if ((boothowto & RB_MULTIPLE) == 0) { 16585373Sjlemon cnadd(best_cn); 16685373Sjlemon best_cn->cn_init(best_cn); 16710665Sbde } 16887620Sguido if (boothowto & RB_PAUSE) 16987620Sguido console_pausing = 1; 1704Srgrimes /* 17185373Sjlemon * Make the best console the preferred console. 17210665Sbde */ 17385373Sjlemon cnselect(best_cn); 17485373Sjlemon} 17585373Sjlemon 17687620Sguidovoid 17787620Sguidocninit_finish() 17887620Sguido{ 17987620Sguido console_pausing = 0; 18087620Sguido} 18187620Sguido 18285373Sjlemon/* add a new physical console to back the virtual console */ 18385373Sjlemonint 18485373Sjlemoncnadd(struct consdev *cn) 18585373Sjlemon{ 18685373Sjlemon struct cn_device *cnd; 18785373Sjlemon int i; 18885373Sjlemon 18985373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) 19085373Sjlemon if (cnd->cnd_cn == cn) 19185373Sjlemon return (0); 19285373Sjlemon for (i = 0; i < CNDEVTAB_SIZE; i++) { 19385373Sjlemon cnd = &cn_devtab[i]; 19485373Sjlemon if (cnd->cnd_cn == NULL) 19585373Sjlemon break; 19648104Syokota } 19785373Sjlemon if (cnd->cnd_cn != NULL) 19885373Sjlemon return (ENOMEM); 19985373Sjlemon cnd->cnd_cn = cn; 20085373Sjlemon STAILQ_INSERT_TAIL(&cn_devlist, cnd, cnd_next); 20185373Sjlemon return (0); 20210665Sbde} 20310665Sbde 20410665Sbdevoid 20585373Sjlemoncnremove(struct consdev *cn) 20610665Sbde{ 20785373Sjlemon struct cn_device *cnd; 20810665Sbde 20985373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 21085373Sjlemon if (cnd->cnd_cn != cn) 21185373Sjlemon continue; 21285373Sjlemon STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next); 21385373Sjlemon if (cnd->cnd_vp != NULL) 21485373Sjlemon vn_close(cnd->cnd_vp, openflag, NOCRED, NULL); 21585373Sjlemon cnd->cnd_vp = NULL; 21685373Sjlemon cnd->cnd_cn = NULL; 21785373Sjlemon cnd->cnd_name[0] = '\0'; 21885373Sjlemon#if 0 21985373Sjlemon /* 22085373Sjlemon * XXX 22185373Sjlemon * syscons gets really confused if console resources are 22285373Sjlemon * freed after the system has initialized. 22385373Sjlemon */ 22485373Sjlemon if (cn->cn_term != NULL) 22585373Sjlemon cn->cn_term(cn); 22685373Sjlemon#endif 22710665Sbde return; 22856582Sbde } 2294Srgrimes} 2304Srgrimes 23185373Sjlemonvoid 23285373Sjlemoncnselect(struct consdev *cn) 23327982Sjulian{ 23485373Sjlemon struct cn_device *cnd; 23527982Sjulian 23685373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 23785373Sjlemon if (cnd->cnd_cn != cn) 23885373Sjlemon continue; 23985373Sjlemon if (cnd == STAILQ_FIRST(&cn_devlist)) 24085373Sjlemon return; 24185373Sjlemon STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next); 24285373Sjlemon STAILQ_INSERT_HEAD(&cn_devlist, cnd, cnd_next); 24327982Sjulian return; 24485373Sjlemon } 24585373Sjlemon} 24627982Sjulian 24785373Sjlemonvoid 24885373Sjlemoncndebug(char *str) 24985373Sjlemon{ 25085373Sjlemon int i, len; 25185373Sjlemon 25285373Sjlemon len = strlen(str); 25385373Sjlemon cnputc('>'); cnputc('>'); cnputc('>'); cnputc(' '); 25485373Sjlemon for (i = 0; i < len; i++) 25585373Sjlemon cnputc(str[i]); 25685373Sjlemon cnputc('\n'); 25785373Sjlemon} 25885373Sjlemon 25985373Sjlemonstatic int 26085373Sjlemonsysctl_kern_console(SYSCTL_HANDLER_ARGS) 26185373Sjlemon{ 26285373Sjlemon struct cn_device *cnd; 26385373Sjlemon struct consdev *cp, **list; 26485373Sjlemon char *name, *p; 26585373Sjlemon int delete, len, error; 26685373Sjlemon 26785373Sjlemon len = 2; 26885373Sjlemon SET_FOREACH(list, cons_set) { 26985373Sjlemon cp = *list; 27085373Sjlemon if (cp->cn_dev != NULL) 27185373Sjlemon len += strlen(devtoname(cp->cn_dev)) + 1; 27256582Sbde } 27385373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) 27485373Sjlemon len += strlen(devtoname(cnd->cnd_cn->cn_dev)) + 1; 27585373Sjlemon len = len > CNDEVPATHMAX ? len : CNDEVPATHMAX; 276111119Simp MALLOC(name, char *, len, M_TEMP, M_WAITOK | M_ZERO); 27785373Sjlemon p = name; 27885373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) 27985373Sjlemon p += sprintf(p, "%s,", devtoname(cnd->cnd_cn->cn_dev)); 28085373Sjlemon *p++ = '/'; 28185373Sjlemon SET_FOREACH(list, cons_set) { 28285373Sjlemon cp = *list; 28385373Sjlemon if (cp->cn_dev != NULL) 28485373Sjlemon p += sprintf(p, "%s,", devtoname(cp->cn_dev)); 28585373Sjlemon } 28685373Sjlemon error = sysctl_handle_string(oidp, name, len, req); 28785373Sjlemon if (error == 0 && req->newptr != NULL) { 28885373Sjlemon p = name; 28985373Sjlemon error = ENXIO; 29085373Sjlemon delete = 0; 29185373Sjlemon if (*p == '-') { 29285373Sjlemon delete = 1; 29385373Sjlemon p++; 29485373Sjlemon } 29585373Sjlemon SET_FOREACH(list, cons_set) { 29685373Sjlemon cp = *list; 29785373Sjlemon if (cp->cn_dev == NULL || 29885373Sjlemon strcmp(p, devtoname(cp->cn_dev)) != 0) 29985373Sjlemon continue; 30085373Sjlemon if (delete) { 30185373Sjlemon cnremove(cp); 30285373Sjlemon error = 0; 30385373Sjlemon } else { 30485373Sjlemon error = cnadd(cp); 30585373Sjlemon if (error == 0) 30685373Sjlemon cnselect(cp); 30785373Sjlemon } 30885373Sjlemon break; 30985373Sjlemon } 31085373Sjlemon } 31185373Sjlemon FREE(name, M_TEMP); 31285373Sjlemon return (error); 31327982Sjulian} 31427982Sjulian 31585373SjlemonSYSCTL_PROC(_kern, OID_AUTO, console, CTLTYPE_STRING|CTLFLAG_RW, 31685373Sjlemon 0, 0, sysctl_kern_console, "A", "Console device control"); 31785373Sjlemon 31827982Sjulian/* 31927982Sjulian * User has changed the state of the console muting. 32027982Sjulian * This may require us to open or close the device in question. 32127982Sjulian */ 32212675Sjulianstatic int 32362573Sphksysctl_kern_consmute(SYSCTL_HANDLER_ARGS) 32427982Sjulian{ 32527982Sjulian int error; 32627982Sjulian int ocn_mute; 32727982Sjulian 32827982Sjulian ocn_mute = cn_mute; 32927982Sjulian error = sysctl_handle_int(oidp, &cn_mute, 0, req); 33085373Sjlemon if (error != 0 || req->newptr == NULL) 33185373Sjlemon return (error); 33285373Sjlemon if (ocn_mute && !cn_mute && cn_is_open) 33385373Sjlemon error = cnopen(NODEV, openflag, 0, curthread); 33485373Sjlemon else if (!ocn_mute && cn_mute && cn_is_open) { 33585373Sjlemon error = cnclose(NODEV, openflag, 0, curthread); 33685373Sjlemon cn_is_open = 1; /* XXX hack */ 33727982Sjulian } 33827982Sjulian return (error); 33927982Sjulian} 34027982Sjulian 34127982SjulianSYSCTL_PROC(_kern, OID_AUTO, consmute, CTLTYPE_INT|CTLFLAG_RW, 34285373Sjlemon 0, sizeof(cn_mute), sysctl_kern_consmute, "I", ""); 34327982Sjulian 34427982Sjulianstatic int 34585373Sjlemoncn_devopen(struct cn_device *cnd, struct thread *td, int forceopen) 34685373Sjlemon{ 34785373Sjlemon char path[CNDEVPATHMAX]; 34885884Sjlemon struct nameidata nd; 34985884Sjlemon struct vnode *vp; 3504Srgrimes dev_t dev; 35185373Sjlemon int error; 3521007Sdg 35385884Sjlemon if ((vp = cnd->cnd_vp) != NULL) { 35485884Sjlemon if (!forceopen && vp->v_type != VBAD) { 35585884Sjlemon dev = vp->v_rdev; 35685373Sjlemon return ((*devsw(dev)->d_open)(dev, openflag, 0, td)); 35727982Sjulian } 35885373Sjlemon cnd->cnd_vp = NULL; 35991406Sjhb vn_close(vp, openflag, td->td_ucred, td); 3605764Sbde } 361105354Srobert if (cnd->cnd_name[0] == '\0') { 362105354Srobert strlcpy(cnd->cnd_name, devtoname(cnd->cnd_cn->cn_dev), 36385373Sjlemon sizeof(cnd->cnd_name)); 364105354Srobert } 36585373Sjlemon snprintf(path, sizeof(path), "/dev/%s", cnd->cnd_name); 36685373Sjlemon NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td); 36785373Sjlemon error = vn_open(&nd, &openflag, 0); 36885373Sjlemon if (error == 0) { 36985373Sjlemon NDFREE(&nd, NDF_ONLY_PNBUF); 37085373Sjlemon VOP_UNLOCK(nd.ni_vp, 0, td); 37185373Sjlemon if (nd.ni_vp->v_type == VCHR) 37285373Sjlemon cnd->cnd_vp = nd.ni_vp; 37385373Sjlemon else 37491406Sjhb vn_close(nd.ni_vp, openflag, td->td_ucred, td); 37585373Sjlemon } 37685373Sjlemon return (cnd->cnd_vp != NULL); 3774Srgrimes} 3788876Srgrimes 37912675Sjulianstatic int 38085373Sjlemoncnopen(dev_t dev, int flag, int mode, struct thread *td) 3814Srgrimes{ 38285373Sjlemon struct cn_device *cnd; 3831007Sdg 38485448Sjlemon openflag = flag | FWRITE; /* XXX */ 38585373Sjlemon cn_is_open = 1; /* console is logically open */ 38685373Sjlemon if (cn_mute) 3874Srgrimes return (0); 38885373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) 38985373Sjlemon cn_devopen(cnd, td, 0); 39085373Sjlemon return (0); 39185373Sjlemon} 39285373Sjlemon 39385373Sjlemonstatic int 39485373Sjlemoncnclose(dev_t dev, int flag, int mode, struct thread *td) 39585373Sjlemon{ 39685373Sjlemon struct cn_device *cnd; 39785458Sjlemon struct vnode *vp; 39885373Sjlemon 39985373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 40085458Sjlemon if ((vp = cnd->cnd_vp) == NULL) 40185373Sjlemon continue; 40285373Sjlemon cnd->cnd_vp = NULL; 40391406Sjhb vn_close(vp, openflag, td->td_ucred, td); 4045764Sbde } 40585373Sjlemon cn_is_open = 0; 40627982Sjulian return (0); 4074Srgrimes} 4088876Srgrimes 40912675Sjulianstatic int 41085373Sjlemoncnread(dev_t dev, struct uio *uio, int flag) 4114Srgrimes{ 41285373Sjlemon struct cn_device *cnd; 41356582Sbde 41485373Sjlemon cnd = STAILQ_FIRST(&cn_devlist); 41585373Sjlemon if (cn_mute || CND_INVALID(cnd, curthread)) 4164Srgrimes return (0); 41785373Sjlemon dev = cnd->cnd_vp->v_rdev; 41846676Sphk return ((*devsw(dev)->d_read)(dev, uio, flag)); 4194Srgrimes} 4208876Srgrimes 42112675Sjulianstatic int 42285373Sjlemoncnwrite(dev_t dev, struct uio *uio, int flag) 4234Srgrimes{ 42485373Sjlemon struct cn_device *cnd; 42556582Sbde 42685373Sjlemon cnd = STAILQ_FIRST(&cn_devlist); 42785373Sjlemon if (cn_mute || CND_INVALID(cnd, curthread)) 42885373Sjlemon goto done; 4291021Sdg if (constty) 4304Srgrimes dev = constty->t_dev; 4314Srgrimes else 43285373Sjlemon dev = cnd->cnd_vp->v_rdev; 43385373Sjlemon if (dev != NULL) { 43485373Sjlemon log_console(uio); 43585373Sjlemon return ((*devsw(dev)->d_write)(dev, uio, flag)); 43685373Sjlemon } 43785373Sjlemondone: 43885373Sjlemon uio->uio_resid = 0; /* dump the data */ 43985373Sjlemon return (0); 4404Srgrimes} 4418876Srgrimes 44212675Sjulianstatic int 44385373Sjlemoncnioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) 4444Srgrimes{ 44585373Sjlemon struct cn_device *cnd; 4464Srgrimes int error; 4474Srgrimes 44885373Sjlemon cnd = STAILQ_FIRST(&cn_devlist); 44985373Sjlemon if (cn_mute || CND_INVALID(cnd, td)) 4504Srgrimes return (0); 4514Srgrimes /* 4524Srgrimes * Superuser can always use this to wrest control of console 4534Srgrimes * output from the "virtual" console. 4544Srgrimes */ 4554Srgrimes if (cmd == TIOCCONS && constty) { 45693593Sjhb error = suser(td); 4574Srgrimes if (error) 4584Srgrimes return (error); 4594Srgrimes constty = NULL; 4604Srgrimes return (0); 4614Srgrimes } 46285373Sjlemon dev = cnd->cnd_vp->v_rdev; 46385373Sjlemon if (dev != NULL) 46485373Sjlemon return ((*devsw(dev)->d_ioctl)(dev, cmd, data, flag, td)); 46585373Sjlemon return (0); 4664Srgrimes} 4674Srgrimes 46885373Sjlemon/* 46985373Sjlemon * XXX 47085373Sjlemon * poll/kqfilter do not appear to be correct 47185373Sjlemon */ 47212675Sjulianstatic int 47385373Sjlemoncnpoll(dev_t dev, int events, struct thread *td) 4744Srgrimes{ 47585373Sjlemon struct cn_device *cnd; 4766712Spst 47785373Sjlemon cnd = STAILQ_FIRST(&cn_devlist); 47885373Sjlemon if (cn_mute || CND_INVALID(cnd, td)) 47985373Sjlemon return (0); 48085373Sjlemon dev = cnd->cnd_vp->v_rdev; 48185373Sjlemon if (dev != NULL) 48285373Sjlemon return ((*devsw(dev)->d_poll)(dev, events, td)); 48385373Sjlemon return (0); 4844Srgrimes} 4854Srgrimes 48672521Sjlemonstatic int 48785373Sjlemoncnkqfilter(dev_t dev, struct knote *kn) 48872521Sjlemon{ 48985373Sjlemon struct cn_device *cnd; 49085373Sjlemon 49185373Sjlemon cnd = STAILQ_FIRST(&cn_devlist); 49285373Sjlemon if (cn_mute || CND_INVALID(cnd, curthread)) 49372521Sjlemon return (1); 49485373Sjlemon dev = cnd->cnd_vp->v_rdev; 49585373Sjlemon if (dev != NULL) 49672521Sjlemon return ((*devsw(dev)->d_kqfilter)(dev, kn)); 49772521Sjlemon return (1); 49872521Sjlemon} 49972521Sjlemon 50085373Sjlemon/* 50185373Sjlemon * Low level console routines. 50285373Sjlemon */ 503798Swollmanint 50485373Sjlemoncngetc(void) 5054Srgrimes{ 5065160Sjoerg int c; 50785373Sjlemon 50885373Sjlemon if (cn_mute) 50919268Sjulian return (-1); 51085373Sjlemon while ((c = cncheckc()) == -1) 51185373Sjlemon ; 51285373Sjlemon if (c == '\r') 51385373Sjlemon c = '\n'; /* console input is always ICRNL */ 5145160Sjoerg return (c); 5154Srgrimes} 5164Srgrimes 5173728Sphkint 51885373Sjlemoncncheckc(void) 5193728Sphk{ 52085373Sjlemon struct cn_device *cnd; 52185373Sjlemon struct consdev *cn; 52285373Sjlemon int c; 52385373Sjlemon 52485373Sjlemon if (cn_mute) 52518287Sbde return (-1); 52685373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 52785373Sjlemon cn = cnd->cnd_cn; 528111194Sphk c = cn->cn_checkc(cn); 52985373Sjlemon if (c != -1) { 53085373Sjlemon return (c); 53185373Sjlemon } 53285373Sjlemon } 53385373Sjlemon return (-1); 5343728Sphk} 5353728Sphk 536798Swollmanvoid 53785373Sjlemoncnputc(int c) 5384Srgrimes{ 53985373Sjlemon struct cn_device *cnd; 54085373Sjlemon struct consdev *cn; 54187620Sguido char *cp; 54285373Sjlemon 54385373Sjlemon if (cn_mute || c == '\0') 5444Srgrimes return; 54585373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 54685373Sjlemon cn = cnd->cnd_cn; 5474Srgrimes if (c == '\n') 548111194Sphk cn->cn_putc(cn, '\r'); 549111194Sphk cn->cn_putc(cn, c); 5504Srgrimes } 55187649Sguido#ifdef DDB 55287620Sguido if (console_pausing && !db_active && (c == '\n')) { 55387649Sguido#else 55487649Sguido if (console_pausing && (c == '\n')) { 55587649Sguido#endif 55687620Sguido for (cp = console_pausestr; *cp != '\0'; cp++) 55787620Sguido cnputc(*cp); 55887620Sguido if (cngetc() == '.') 55987620Sguido console_pausing = 0; 56087620Sguido cnputc('\r'); 56187620Sguido for (cp = console_pausestr; *cp != '\0'; cp++) 56287620Sguido cnputc(' '); 56387620Sguido cnputc('\r'); 56487620Sguido } 5654Srgrimes} 5664Srgrimes 56755823Syokotavoid 56885373Sjlemoncndbctl(int on) 56955823Syokota{ 57085373Sjlemon struct cn_device *cnd; 57185373Sjlemon struct consdev *cn; 57255823Syokota static int refcount; 57355823Syokota 57455823Syokota if (!on) 57555823Syokota refcount--; 57685373Sjlemon if (refcount == 0) 57785373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 57885373Sjlemon cn = cnd->cnd_cn; 57985373Sjlemon if (cn->cn_dbctl != NULL) 580111194Sphk cn->cn_dbctl(cn, on); 58185373Sjlemon } 58255823Syokota if (on) 58355823Syokota refcount++; 58455823Syokota} 58555823Syokota 58612675Sjulianstatic void 58712675Sjuliancn_drvinit(void *unused) 58812517Sjulian{ 58912517Sjulian 590107984Sphk make_dev(&cn_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, 59156525Sbde "console"); 59212517Sjulian} 59312517Sjulian 59412517SjulianSYSINIT(cndev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,cn_drvinit,NULL) 595