kern_cons.c revision 87620
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 87620 2001-12-10 20:02:22Z guido $ 404Srgrimes */ 414Srgrimes 422056Swollman#include <sys/param.h> 431549Srgrimes#include <sys/systm.h> 445764Sbde#include <sys/conf.h> 4556525Sbde#include <sys/cons.h> 4685448Sjlemon#include <sys/fcntl.h> 4712675Sjulian#include <sys/kernel.h> 4885373Sjlemon#include <sys/malloc.h> 4985373Sjlemon#include <sys/namei.h> 5069929Sobrien#include <sys/proc.h> 5185373Sjlemon#include <sys/queue.h> 5218951Sjulian#include <sys/reboot.h> 5312701Sphk#include <sys/sysctl.h> 542056Swollman#include <sys/tty.h> 5534924Sbde#include <sys/uio.h> 5685373Sjlemon#include <sys/vnode.h> 574Srgrimes 5887620Sguido#include <ddb/ddb.h> 5987620Sguido 6012701Sphk#include <machine/cpu.h> 614Srgrimes 6212675Sjulianstatic d_open_t cnopen; 6312675Sjulianstatic d_close_t cnclose; 6412675Sjulianstatic d_read_t cnread; 6512675Sjulianstatic d_write_t cnwrite; 6612675Sjulianstatic d_ioctl_t cnioctl; 6729368Speterstatic d_poll_t cnpoll; 6872521Sjlemonstatic d_kqfilter_t cnkqfilter; 6912675Sjulian 7038485Sbde#define CDEV_MAJOR 0 7147625Sphkstatic struct cdevsw cn_cdevsw = { 7247625Sphk /* open */ cnopen, 7347625Sphk /* close */ cnclose, 7447625Sphk /* read */ cnread, 7547625Sphk /* write */ cnwrite, 7647625Sphk /* ioctl */ cnioctl, 7747625Sphk /* poll */ cnpoll, 7847625Sphk /* mmap */ nommap, 7947625Sphk /* strategy */ nostrategy, 8047625Sphk /* name */ "console", 8147625Sphk /* maj */ CDEV_MAJOR, 8247625Sphk /* dump */ nodump, 8347625Sphk /* psize */ nopsize, 8472521Sjlemon /* flags */ D_TTY | D_KQFILTER, 8572521Sjlemon /* kqfilter */ cnkqfilter, 8638485Sbde}; 8712675Sjulian 8885373Sjlemonstruct cn_device { 8985373Sjlemon STAILQ_ENTRY(cn_device) cnd_next; 9085373Sjlemon char cnd_name[16]; 9185373Sjlemon struct vnode *cnd_vp; 9285373Sjlemon struct consdev *cnd_cn; 9385373Sjlemon}; 9485373Sjlemon 9585373Sjlemon#define CNDEVPATHMAX 32 9685373Sjlemon#define CNDEVTAB_SIZE 4 9785373Sjlemonstatic struct cn_device cn_devtab[CNDEVTAB_SIZE]; 9885373Sjlemonstatic STAILQ_HEAD(, cn_device) cn_devlist = 9985373Sjlemon STAILQ_HEAD_INITIALIZER(cn_devlist); 10085373Sjlemon 10185373Sjlemon#define CND_INVALID(cnd, td) \ 10285373Sjlemon (cnd == NULL || cnd->cnd_vp == NULL || \ 10385373Sjlemon (cnd->cnd_vp->v_type == VBAD && !cn_devopen(cnd, td, 1))) 10485373Sjlemon 10549049Syokotastatic udev_t cn_udev_t; 10641612SeivindSYSCTL_OPAQUE(_machdep, CPU_CONSDEV, consdev, CTLFLAG_RD, 10749049Syokota &cn_udev_t, sizeof cn_udev_t, "T,dev_t", ""); 10827982Sjulian 1097680Sjoergint cons_unavail = 0; /* XXX: 1107680Sjoerg * physical console not available for 1117680Sjoerg * input (i.e., it is in graphics mode) 1127680Sjoerg */ 11385373Sjlemonstatic int cn_mute; 11485373Sjlemonstatic int openflag; /* how /dev/console was opened */ 11585373Sjlemonstatic int cn_is_open; 11656525Sbdestatic dev_t cn_devfsdev; /* represents the device private info */ 11787620Sguidostatic u_char console_pausing; /* pause after each line during probe */ 11887620Sguidostatic char *console_pausestr= 11987620Sguido"<pause; press any key to proceed to next line or '.' to end pause mode>"; 1205764Sbde 12185448Sjlemonvoid cndebug(char *); 12285448Sjlemon 12355823SyokotaCONS_DRIVER(cons, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 12478161SpeterSET_DECLARE(cons_set, struct consdev); 12542373Syokota 126798Swollmanvoid 12785373Sjlemoncninit(void) 1284Srgrimes{ 12985373Sjlemon struct consdev *best_cn, *cn, **list; 1304Srgrimes 1314Srgrimes /* 13218951Sjulian * Check if we should mute the console (for security reasons perhaps) 13318951Sjulian * It can be changes dynamically using sysctl kern.consmute 13418951Sjulian * once we are up and going. 13518951Sjulian * 13618951Sjulian */ 13718951Sjulian cn_mute = ((boothowto & (RB_MUTE 13818951Sjulian |RB_SINGLE 13918951Sjulian |RB_VERBOSE 14018951Sjulian |RB_ASKNAME 14118951Sjulian |RB_CONFIG)) == RB_MUTE); 14285373Sjlemon 14318951Sjulian /* 14485373Sjlemon * Find the first console with the highest priority. 1454Srgrimes */ 14685373Sjlemon best_cn = NULL; 14785373Sjlemon SET_FOREACH(list, cons_set) { 14885373Sjlemon cn = *list; 14985373Sjlemon if (cn->cn_probe == NULL) 15085373Sjlemon continue; 15185373Sjlemon cn->cn_probe(cn); 15285373Sjlemon if (cn->cn_pri == CN_DEAD) 15385373Sjlemon continue; 15485373Sjlemon if (best_cn == NULL || cn->cn_pri > best_cn->cn_pri) 15585373Sjlemon best_cn = cn; 15685373Sjlemon if (boothowto & RB_MULTIPLE) { 15785373Sjlemon /* 15885373Sjlemon * Initialize console, and attach to it. 15985373Sjlemon */ 16085373Sjlemon cnadd(cn); 16185373Sjlemon cn->cn_init(cn); 16285373Sjlemon } 16385373Sjlemon } 16485373Sjlemon if (best_cn == NULL) 1654Srgrimes return; 16685373Sjlemon if ((boothowto & RB_MULTIPLE) == 0) { 16785373Sjlemon cnadd(best_cn); 16885373Sjlemon best_cn->cn_init(best_cn); 16910665Sbde } 17087620Sguido if (boothowto & RB_PAUSE) 17187620Sguido console_pausing = 1; 1724Srgrimes /* 17385373Sjlemon * Make the best console the preferred console. 17410665Sbde */ 17585373Sjlemon cnselect(best_cn); 17685373Sjlemon} 17785373Sjlemon 17887620Sguidovoid 17987620Sguidocninit_finish() 18087620Sguido{ 18187620Sguido console_pausing = 0; 18287620Sguido} 18387620Sguido 18485373Sjlemon/* add a new physical console to back the virtual console */ 18585373Sjlemonint 18685373Sjlemoncnadd(struct consdev *cn) 18785373Sjlemon{ 18885373Sjlemon struct cn_device *cnd; 18985373Sjlemon int i; 19085373Sjlemon 19185373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) 19285373Sjlemon if (cnd->cnd_cn == cn) 19385373Sjlemon return (0); 19485373Sjlemon for (i = 0; i < CNDEVTAB_SIZE; i++) { 19585373Sjlemon cnd = &cn_devtab[i]; 19685373Sjlemon if (cnd->cnd_cn == NULL) 19785373Sjlemon break; 19848104Syokota } 19985373Sjlemon if (cnd->cnd_cn != NULL) 20085373Sjlemon return (ENOMEM); 20185373Sjlemon cnd->cnd_cn = cn; 20285373Sjlemon STAILQ_INSERT_TAIL(&cn_devlist, cnd, cnd_next); 20385373Sjlemon return (0); 20410665Sbde} 20510665Sbde 20610665Sbdevoid 20785373Sjlemoncnremove(struct consdev *cn) 20810665Sbde{ 20985373Sjlemon struct cn_device *cnd; 21010665Sbde 21185373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 21285373Sjlemon if (cnd->cnd_cn != cn) 21385373Sjlemon continue; 21485373Sjlemon STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next); 21585373Sjlemon if (cnd->cnd_vp != NULL) 21685373Sjlemon vn_close(cnd->cnd_vp, openflag, NOCRED, NULL); 21785373Sjlemon cnd->cnd_vp = NULL; 21885373Sjlemon cnd->cnd_cn = NULL; 21985373Sjlemon cnd->cnd_name[0] = '\0'; 22085373Sjlemon#if 0 22185373Sjlemon /* 22285373Sjlemon * XXX 22385373Sjlemon * syscons gets really confused if console resources are 22485373Sjlemon * freed after the system has initialized. 22585373Sjlemon */ 22685373Sjlemon if (cn->cn_term != NULL) 22785373Sjlemon cn->cn_term(cn); 22885373Sjlemon#endif 22910665Sbde return; 23056582Sbde } 2314Srgrimes} 2324Srgrimes 23385373Sjlemonvoid 23485373Sjlemoncnselect(struct consdev *cn) 23527982Sjulian{ 23685373Sjlemon struct cn_device *cnd; 23727982Sjulian 23885373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 23985373Sjlemon if (cnd->cnd_cn != cn) 24085373Sjlemon continue; 24185373Sjlemon if (cnd == STAILQ_FIRST(&cn_devlist)) 24285373Sjlemon return; 24385373Sjlemon STAILQ_REMOVE(&cn_devlist, cnd, cn_device, cnd_next); 24485373Sjlemon STAILQ_INSERT_HEAD(&cn_devlist, cnd, cnd_next); 24527982Sjulian return; 24685373Sjlemon } 24785373Sjlemon} 24827982Sjulian 24985373Sjlemonvoid 25085373Sjlemoncndebug(char *str) 25185373Sjlemon{ 25285373Sjlemon int i, len; 25385373Sjlemon 25485373Sjlemon len = strlen(str); 25585373Sjlemon cnputc('>'); cnputc('>'); cnputc('>'); cnputc(' '); 25685373Sjlemon for (i = 0; i < len; i++) 25785373Sjlemon cnputc(str[i]); 25885373Sjlemon cnputc('\n'); 25985373Sjlemon} 26085373Sjlemon 26185373Sjlemonstatic int 26285373Sjlemonsysctl_kern_console(SYSCTL_HANDLER_ARGS) 26385373Sjlemon{ 26485373Sjlemon struct cn_device *cnd; 26585373Sjlemon struct consdev *cp, **list; 26685373Sjlemon char *name, *p; 26785373Sjlemon int delete, len, error; 26885373Sjlemon 26985373Sjlemon len = 2; 27085373Sjlemon SET_FOREACH(list, cons_set) { 27185373Sjlemon cp = *list; 27285373Sjlemon if (cp->cn_dev != NULL) 27385373Sjlemon len += strlen(devtoname(cp->cn_dev)) + 1; 27456582Sbde } 27585373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) 27685373Sjlemon len += strlen(devtoname(cnd->cnd_cn->cn_dev)) + 1; 27785373Sjlemon len = len > CNDEVPATHMAX ? len : CNDEVPATHMAX; 27885373Sjlemon MALLOC(name, char *, len, M_TEMP, M_WAITOK | M_ZERO); 27985373Sjlemon p = name; 28085373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) 28185373Sjlemon p += sprintf(p, "%s,", devtoname(cnd->cnd_cn->cn_dev)); 28285373Sjlemon *p++ = '/'; 28385373Sjlemon SET_FOREACH(list, cons_set) { 28485373Sjlemon cp = *list; 28585373Sjlemon if (cp->cn_dev != NULL) 28685373Sjlemon p += sprintf(p, "%s,", devtoname(cp->cn_dev)); 28785373Sjlemon } 28885373Sjlemon error = sysctl_handle_string(oidp, name, len, req); 28985373Sjlemon if (error == 0 && req->newptr != NULL) { 29085373Sjlemon p = name; 29185373Sjlemon error = ENXIO; 29285373Sjlemon delete = 0; 29385373Sjlemon if (*p == '-') { 29485373Sjlemon delete = 1; 29585373Sjlemon p++; 29685373Sjlemon } 29785373Sjlemon SET_FOREACH(list, cons_set) { 29885373Sjlemon cp = *list; 29985373Sjlemon if (cp->cn_dev == NULL || 30085373Sjlemon strcmp(p, devtoname(cp->cn_dev)) != 0) 30185373Sjlemon continue; 30285373Sjlemon if (delete) { 30385373Sjlemon cnremove(cp); 30485373Sjlemon error = 0; 30585373Sjlemon } else { 30685373Sjlemon error = cnadd(cp); 30785373Sjlemon if (error == 0) 30885373Sjlemon cnselect(cp); 30985373Sjlemon } 31085373Sjlemon break; 31185373Sjlemon } 31285373Sjlemon } 31385373Sjlemon FREE(name, M_TEMP); 31485373Sjlemon return (error); 31527982Sjulian} 31627982Sjulian 31785373SjlemonSYSCTL_PROC(_kern, OID_AUTO, console, CTLTYPE_STRING|CTLFLAG_RW, 31885373Sjlemon 0, 0, sysctl_kern_console, "A", "Console device control"); 31985373Sjlemon 32027982Sjulian/* 32127982Sjulian * User has changed the state of the console muting. 32227982Sjulian * This may require us to open or close the device in question. 32327982Sjulian */ 32412675Sjulianstatic int 32562573Sphksysctl_kern_consmute(SYSCTL_HANDLER_ARGS) 32627982Sjulian{ 32727982Sjulian int error; 32827982Sjulian int ocn_mute; 32927982Sjulian 33027982Sjulian ocn_mute = cn_mute; 33127982Sjulian error = sysctl_handle_int(oidp, &cn_mute, 0, req); 33285373Sjlemon if (error != 0 || req->newptr == NULL) 33385373Sjlemon return (error); 33485373Sjlemon if (ocn_mute && !cn_mute && cn_is_open) 33585373Sjlemon error = cnopen(NODEV, openflag, 0, curthread); 33685373Sjlemon else if (!ocn_mute && cn_mute && cn_is_open) { 33785373Sjlemon error = cnclose(NODEV, openflag, 0, curthread); 33885373Sjlemon cn_is_open = 1; /* XXX hack */ 33927982Sjulian } 34027982Sjulian return (error); 34127982Sjulian} 34227982Sjulian 34327982SjulianSYSCTL_PROC(_kern, OID_AUTO, consmute, CTLTYPE_INT|CTLFLAG_RW, 34485373Sjlemon 0, sizeof(cn_mute), sysctl_kern_consmute, "I", ""); 34527982Sjulian 34627982Sjulianstatic int 34785373Sjlemoncn_devopen(struct cn_device *cnd, struct thread *td, int forceopen) 34885373Sjlemon{ 34985373Sjlemon char path[CNDEVPATHMAX]; 35085884Sjlemon struct nameidata nd; 35185884Sjlemon struct vnode *vp; 3524Srgrimes dev_t dev; 35385373Sjlemon int error; 3541007Sdg 35585884Sjlemon if ((vp = cnd->cnd_vp) != NULL) { 35685884Sjlemon if (!forceopen && vp->v_type != VBAD) { 35785884Sjlemon dev = vp->v_rdev; 35885373Sjlemon return ((*devsw(dev)->d_open)(dev, openflag, 0, td)); 35927982Sjulian } 36085373Sjlemon cnd->cnd_vp = NULL; 36185884Sjlemon vn_close(vp, openflag, td->td_proc->p_ucred, td); 3625764Sbde } 36385373Sjlemon if (cnd->cnd_name[0] == '\0') 36485373Sjlemon strncpy(cnd->cnd_name, devtoname(cnd->cnd_cn->cn_dev), 36585373Sjlemon sizeof(cnd->cnd_name)); 36685373Sjlemon snprintf(path, sizeof(path), "/dev/%s", cnd->cnd_name); 36785373Sjlemon NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td); 36885373Sjlemon error = vn_open(&nd, &openflag, 0); 36985373Sjlemon if (error == 0) { 37085373Sjlemon NDFREE(&nd, NDF_ONLY_PNBUF); 37185373Sjlemon VOP_UNLOCK(nd.ni_vp, 0, td); 37285373Sjlemon if (nd.ni_vp->v_type == VCHR) 37385373Sjlemon cnd->cnd_vp = nd.ni_vp; 37485373Sjlemon else 37585373Sjlemon vn_close(nd.ni_vp, openflag, td->td_proc->p_ucred, td); 37685373Sjlemon } 37785373Sjlemon return (cnd->cnd_vp != NULL); 3784Srgrimes} 3798876Srgrimes 38012675Sjulianstatic int 38185373Sjlemoncnopen(dev_t dev, int flag, int mode, struct thread *td) 3824Srgrimes{ 38385373Sjlemon struct cn_device *cnd; 3841007Sdg 38585448Sjlemon openflag = flag | FWRITE; /* XXX */ 38685373Sjlemon cn_is_open = 1; /* console is logically open */ 38785373Sjlemon if (cn_mute) 3884Srgrimes return (0); 38985373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) 39085373Sjlemon cn_devopen(cnd, td, 0); 39185373Sjlemon return (0); 39285373Sjlemon} 39385373Sjlemon 39485373Sjlemonstatic int 39585373Sjlemoncnclose(dev_t dev, int flag, int mode, struct thread *td) 39685373Sjlemon{ 39785373Sjlemon struct cn_device *cnd; 39885458Sjlemon struct vnode *vp; 39985373Sjlemon 40085373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 40185458Sjlemon if ((vp = cnd->cnd_vp) == NULL) 40285373Sjlemon continue; 40385373Sjlemon cnd->cnd_vp = NULL; 40485458Sjlemon vn_close(vp, openflag, td->td_proc->p_ucred, td); 4055764Sbde } 40685373Sjlemon cn_is_open = 0; 40727982Sjulian return (0); 4084Srgrimes} 4098876Srgrimes 41012675Sjulianstatic int 41185373Sjlemoncnread(dev_t dev, struct uio *uio, int flag) 4124Srgrimes{ 41385373Sjlemon struct cn_device *cnd; 41456582Sbde 41585373Sjlemon cnd = STAILQ_FIRST(&cn_devlist); 41685373Sjlemon if (cn_mute || CND_INVALID(cnd, curthread)) 4174Srgrimes return (0); 41885373Sjlemon dev = cnd->cnd_vp->v_rdev; 41946676Sphk return ((*devsw(dev)->d_read)(dev, uio, flag)); 4204Srgrimes} 4218876Srgrimes 42212675Sjulianstatic int 42385373Sjlemoncnwrite(dev_t dev, struct uio *uio, int flag) 4244Srgrimes{ 42585373Sjlemon struct cn_device *cnd; 42656582Sbde 42785373Sjlemon cnd = STAILQ_FIRST(&cn_devlist); 42885373Sjlemon if (cn_mute || CND_INVALID(cnd, curthread)) 42985373Sjlemon goto done; 4301021Sdg if (constty) 4314Srgrimes dev = constty->t_dev; 4324Srgrimes else 43385373Sjlemon dev = cnd->cnd_vp->v_rdev; 43485373Sjlemon if (dev != NULL) { 43585373Sjlemon log_console(uio); 43685373Sjlemon return ((*devsw(dev)->d_write)(dev, uio, flag)); 43785373Sjlemon } 43885373Sjlemondone: 43985373Sjlemon uio->uio_resid = 0; /* dump the data */ 44085373Sjlemon return (0); 4414Srgrimes} 4428876Srgrimes 44312675Sjulianstatic int 44485373Sjlemoncnioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) 4454Srgrimes{ 44685373Sjlemon struct cn_device *cnd; 4474Srgrimes int error; 4484Srgrimes 44985373Sjlemon cnd = STAILQ_FIRST(&cn_devlist); 45085373Sjlemon if (cn_mute || CND_INVALID(cnd, td)) 4514Srgrimes return (0); 4524Srgrimes /* 4534Srgrimes * Superuser can always use this to wrest control of console 4544Srgrimes * output from the "virtual" console. 4554Srgrimes */ 4564Srgrimes if (cmd == TIOCCONS && constty) { 45783366Sjulian error = suser_td(td); 4584Srgrimes if (error) 4594Srgrimes return (error); 4604Srgrimes constty = NULL; 4614Srgrimes return (0); 4624Srgrimes } 46385373Sjlemon dev = cnd->cnd_vp->v_rdev; 46485373Sjlemon if (dev != NULL) 46585373Sjlemon return ((*devsw(dev)->d_ioctl)(dev, cmd, data, flag, td)); 46685373Sjlemon return (0); 4674Srgrimes} 4684Srgrimes 46985373Sjlemon/* 47085373Sjlemon * XXX 47185373Sjlemon * poll/kqfilter do not appear to be correct 47285373Sjlemon */ 47312675Sjulianstatic int 47485373Sjlemoncnpoll(dev_t dev, int events, struct thread *td) 4754Srgrimes{ 47685373Sjlemon struct cn_device *cnd; 4776712Spst 47885373Sjlemon cnd = STAILQ_FIRST(&cn_devlist); 47985373Sjlemon if (cn_mute || CND_INVALID(cnd, td)) 48085373Sjlemon return (0); 48185373Sjlemon dev = cnd->cnd_vp->v_rdev; 48285373Sjlemon if (dev != NULL) 48385373Sjlemon return ((*devsw(dev)->d_poll)(dev, events, td)); 48485373Sjlemon return (0); 4854Srgrimes} 4864Srgrimes 48772521Sjlemonstatic int 48885373Sjlemoncnkqfilter(dev_t dev, struct knote *kn) 48972521Sjlemon{ 49085373Sjlemon struct cn_device *cnd; 49185373Sjlemon 49285373Sjlemon cnd = STAILQ_FIRST(&cn_devlist); 49385373Sjlemon if (cn_mute || CND_INVALID(cnd, curthread)) 49472521Sjlemon return (1); 49585373Sjlemon dev = cnd->cnd_vp->v_rdev; 49685373Sjlemon if (dev != NULL) 49772521Sjlemon return ((*devsw(dev)->d_kqfilter)(dev, kn)); 49872521Sjlemon return (1); 49972521Sjlemon} 50072521Sjlemon 50185373Sjlemon/* 50285373Sjlemon * Low level console routines. 50385373Sjlemon */ 504798Swollmanint 50585373Sjlemoncngetc(void) 5064Srgrimes{ 5075160Sjoerg int c; 50885373Sjlemon 50985373Sjlemon if (cn_mute) 51019268Sjulian return (-1); 51185373Sjlemon while ((c = cncheckc()) == -1) 51285373Sjlemon ; 51385373Sjlemon if (c == '\r') 51485373Sjlemon c = '\n'; /* console input is always ICRNL */ 5155160Sjoerg return (c); 5164Srgrimes} 5174Srgrimes 5183728Sphkint 51985373Sjlemoncncheckc(void) 5203728Sphk{ 52185373Sjlemon struct cn_device *cnd; 52285373Sjlemon struct consdev *cn; 52385373Sjlemon int c; 52485373Sjlemon 52585373Sjlemon if (cn_mute) 52618287Sbde return (-1); 52785373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 52885373Sjlemon cn = cnd->cnd_cn; 52985373Sjlemon c = cn->cn_checkc(cn->cn_dev); 53085373Sjlemon if (c != -1) { 53185373Sjlemon return (c); 53285373Sjlemon } 53385373Sjlemon } 53485373Sjlemon return (-1); 5353728Sphk} 5363728Sphk 537798Swollmanvoid 53885373Sjlemoncnputc(int c) 5394Srgrimes{ 54085373Sjlemon struct cn_device *cnd; 54185373Sjlemon struct consdev *cn; 54287620Sguido char *cp; 54385373Sjlemon 54485373Sjlemon if (cn_mute || c == '\0') 5454Srgrimes return; 54685373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 54785373Sjlemon cn = cnd->cnd_cn; 5484Srgrimes if (c == '\n') 54985373Sjlemon cn->cn_putc(cn->cn_dev, '\r'); 55085373Sjlemon cn->cn_putc(cn->cn_dev, c); 5514Srgrimes } 55287620Sguido if (console_pausing && !db_active && (c == '\n')) { 55387620Sguido for (cp = console_pausestr; *cp != '\0'; cp++) 55487620Sguido cnputc(*cp); 55587620Sguido if (cngetc() == '.') 55687620Sguido console_pausing = 0; 55787620Sguido cnputc('\r'); 55887620Sguido for (cp = console_pausestr; *cp != '\0'; cp++) 55987620Sguido cnputc(' '); 56087620Sguido cnputc('\r'); 56187620Sguido } 5624Srgrimes} 5634Srgrimes 56455823Syokotavoid 56585373Sjlemoncndbctl(int on) 56655823Syokota{ 56785373Sjlemon struct cn_device *cnd; 56885373Sjlemon struct consdev *cn; 56955823Syokota static int refcount; 57055823Syokota 57155823Syokota if (!on) 57255823Syokota refcount--; 57385373Sjlemon if (refcount == 0) 57485373Sjlemon STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { 57585373Sjlemon cn = cnd->cnd_cn; 57685373Sjlemon if (cn->cn_dbctl != NULL) 57785373Sjlemon cn->cn_dbctl(cn->cn_dev, on); 57885373Sjlemon } 57955823Syokota if (on) 58055823Syokota refcount++; 58155823Syokota} 58255823Syokota 58312675Sjulianstatic void 58412675Sjuliancn_drvinit(void *unused) 58512517Sjulian{ 58612517Sjulian 58756525Sbde cn_devfsdev = make_dev(&cn_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, 58856525Sbde "console"); 58912517Sjulian} 59012517Sjulian 59112517SjulianSYSINIT(cndev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,cn_drvinit,NULL) 592