kern_cons.c revision 7680
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 397680Sjoerg * $Id: cons.c,v 1.24 1995/04/02 16:14:51 joerg Exp $ 404Srgrimes */ 414Srgrimes 422056Swollman#include <sys/param.h> 431549Srgrimes#include <sys/systm.h> 445764Sbde#include <sys/conf.h> 452056Swollman#include <sys/proc.h> 462056Swollman#include <sys/tty.h> 474Srgrimes 482056Swollman#include <machine/cons.h> 495764Sbde#include <machine/stdarg.h> 504Srgrimes 514Srgrimes/* XXX - all this could be autoconfig()ed */ 522423Sdg#include "sc.h" 534031Sjoerg#include "vt.h" 544031Sjoerg#if NSC > 0 || NVT > 0 553728Sphkint pccnprobe(), pccninit(), pccngetc(), pccncheckc(), pccnputc(); 562423Sdg#endif 57849Sdg 58849Sdg#include "sio.h" 59849Sdg#if NSIO > 0 603728Sphkint siocnprobe(), siocninit(), siocngetc(), siocncheckc(), siocnputc(); 61849Sdg#endif 62849Sdg 635764Sbdestatic struct consdev constab[] = { 645161Sjoerg#if NSC > 0 || NVT > 0 653728Sphk { pccnprobe, pccninit, pccngetc, pccncheckc, pccnputc }, 662423Sdg#endif 67849Sdg#if NSIO > 0 683728Sphk { siocnprobe, siocninit, siocngetc, siocncheckc, siocnputc }, 69849Sdg#endif 704Srgrimes { 0 }, 714Srgrimes}; 724Srgrimes/* end XXX */ 734Srgrimes 744Srgrimesstruct tty *constty = 0; /* virtual console output device */ 754Srgrimesstruct tty *cn_tty; /* XXX: console tty struct for tprintf */ 767680Sjoergint cons_unavail = 0; /* XXX: 777680Sjoerg * physical console not available for 787680Sjoerg * input (i.e., it is in graphics mode) 797680Sjoerg */ 804Srgrimes 816731Sbdestatic u_char cn_is_open; /* nonzero if logical console is open */ 826731Sbdestatic u_char cn_phys_is_open; /* nonzero if physical console is open */ 835764Sbdestatic d_close_t *cn_phys_close; /* physical device close function */ 845764Sbdestatic d_open_t *cn_phys_open; /* physical device open function */ 855764Sbdestatic struct consdev *cn_tab; /* physical console device info */ 867588Sjoergstatic struct tty *cn_tp; /* physical console tty struct */ 875764Sbde 88798Swollmanvoid 894Srgrimescninit() 904Srgrimes{ 914Srgrimes register struct consdev *cp; 925764Sbde struct cdevsw *cdp; 934Srgrimes 944Srgrimes /* 954Srgrimes * Collect information about all possible consoles 964Srgrimes * and find the one with highest priority 974Srgrimes */ 984Srgrimes for (cp = constab; cp->cn_probe; cp++) { 994Srgrimes (*cp->cn_probe)(cp); 1004Srgrimes if (cp->cn_pri > CN_DEAD && 1014Srgrimes (cn_tab == NULL || cp->cn_pri > cn_tab->cn_pri)) 1024Srgrimes cn_tab = cp; 1034Srgrimes } 1044Srgrimes /* 1055764Sbde * No console, give up. 1064Srgrimes */ 1074Srgrimes if ((cp = cn_tab) == NULL) 1084Srgrimes return; 1094Srgrimes /* 1105764Sbde * Hook the open and close functions. 1115764Sbde */ 1125764Sbde cdp = &cdevsw[major(cn_tab->cn_dev)]; 1135764Sbde cn_phys_close = cdp->d_close; 1145764Sbde cdp->d_close = cnclose; 1155764Sbde cn_phys_open = cdp->d_open; 1165764Sbde cdp->d_open = cnopen; 1177588Sjoerg cn_tp = (*cdp->d_devtotty)(cn_tab->cn_dev); 1185764Sbde /* 1194Srgrimes * Turn on console 1204Srgrimes */ 1214Srgrimes cn_tty = cp->cn_tp; 1224Srgrimes (*cp->cn_init)(cp); 1234Srgrimes} 1244Srgrimes 125798Swollmanint 1264Srgrimescnopen(dev, flag, mode, p) 1274Srgrimes dev_t dev; 1284Srgrimes int flag, mode; 1294Srgrimes struct proc *p; 1304Srgrimes{ 1315764Sbde dev_t cndev, physdev; 1325764Sbde int retval; 1331007Sdg 1344Srgrimes if (cn_tab == NULL) 1354Srgrimes return (0); 1365764Sbde cndev = cn_tab->cn_dev; 1375764Sbde physdev = (major(dev) == major(cndev) ? dev : cndev); 1385764Sbde retval = (*cn_phys_open)(physdev, flag, mode, p); 1395764Sbde if (retval == 0) { 1405764Sbde if (dev == cndev) 1415764Sbde cn_phys_is_open = 1; 1425764Sbde else if (physdev == cndev) 1435764Sbde cn_is_open = 1; 1445764Sbde } 1455764Sbde return (retval); 1464Srgrimes} 1474Srgrimes 148798Swollmanint 1494Srgrimescnclose(dev, flag, mode, p) 1504Srgrimes dev_t dev; 1514Srgrimes int flag, mode; 1524Srgrimes struct proc *p; 1534Srgrimes{ 1545764Sbde dev_t cndev; 1551007Sdg 1564Srgrimes if (cn_tab == NULL) 1574Srgrimes return (0); 1585764Sbde cndev = cn_tab->cn_dev; 1595764Sbde if (dev == cndev) { 1607588Sjoerg /* the physical device is about to be closed */ 1615764Sbde cn_phys_is_open = 0; 1627588Sjoerg if (cn_is_open) { 1637588Sjoerg if (cn_tp) { 1647588Sjoerg /* perform a ttyhalfclose() */ 1657588Sjoerg /* reset session and proc group */ 1667588Sjoerg cn_tp->t_pgrp = NULL; 1677588Sjoerg cn_tp->t_session = NULL; 1687588Sjoerg } 1695764Sbde return (0); 1707588Sjoerg } 1715764Sbde } else if (major(dev) != major(cndev)) { 1727588Sjoerg /* the logical console is about to be closed */ 1735764Sbde cn_is_open = 0; 1745764Sbde if (cn_phys_is_open) 1755764Sbde return (0); 1765764Sbde dev = cndev; 1775764Sbde } 1785764Sbde return ((*cn_phys_close)(dev, flag, mode, p)); 1794Srgrimes} 1804Srgrimes 181798Swollmanint 1824Srgrimescnread(dev, uio, flag) 1834Srgrimes dev_t dev; 1844Srgrimes struct uio *uio; 185798Swollman int flag; 1864Srgrimes{ 1874Srgrimes if (cn_tab == NULL) 1884Srgrimes return (0); 1894Srgrimes dev = cn_tab->cn_dev; 1904Srgrimes return ((*cdevsw[major(dev)].d_read)(dev, uio, flag)); 1914Srgrimes} 1924Srgrimes 193798Swollmanint 1944Srgrimescnwrite(dev, uio, flag) 1954Srgrimes dev_t dev; 1964Srgrimes struct uio *uio; 197798Swollman int flag; 1984Srgrimes{ 1994Srgrimes if (cn_tab == NULL) 2004Srgrimes return (0); 2011021Sdg if (constty) 2024Srgrimes dev = constty->t_dev; 2034Srgrimes else 2044Srgrimes dev = cn_tab->cn_dev; 2054Srgrimes return ((*cdevsw[major(dev)].d_write)(dev, uio, flag)); 2064Srgrimes} 2074Srgrimes 208798Swollmanint 2094Srgrimescnioctl(dev, cmd, data, flag, p) 2104Srgrimes dev_t dev; 211798Swollman int cmd; 2124Srgrimes caddr_t data; 213798Swollman int flag; 2144Srgrimes struct proc *p; 2154Srgrimes{ 2164Srgrimes int error; 2174Srgrimes 2184Srgrimes if (cn_tab == NULL) 2194Srgrimes return (0); 2204Srgrimes /* 2214Srgrimes * Superuser can always use this to wrest control of console 2224Srgrimes * output from the "virtual" console. 2234Srgrimes */ 2244Srgrimes if (cmd == TIOCCONS && constty) { 2254Srgrimes error = suser(p->p_ucred, (u_short *) NULL); 2264Srgrimes if (error) 2274Srgrimes return (error); 2284Srgrimes constty = NULL; 2294Srgrimes return (0); 2304Srgrimes } 2314Srgrimes dev = cn_tab->cn_dev; 2324Srgrimes return ((*cdevsw[major(dev)].d_ioctl)(dev, cmd, data, flag, p)); 2334Srgrimes} 2344Srgrimes 2354Srgrimes/*ARGSUSED*/ 236798Swollmanint 2374Srgrimescnselect(dev, rw, p) 2384Srgrimes dev_t dev; 2394Srgrimes int rw; 2404Srgrimes struct proc *p; 2414Srgrimes{ 2424Srgrimes if (cn_tab == NULL) 2434Srgrimes return (1); 2446712Spst 2456712Spst dev = cn_tab->cn_dev; 2466712Spst 2476712Spst return ((*cdevsw[major(dev)].d_select)(dev, rw, p)); 2484Srgrimes} 2494Srgrimes 250798Swollmanint 2514Srgrimescngetc() 2524Srgrimes{ 2535160Sjoerg int c; 2544Srgrimes if (cn_tab == NULL) 2554Srgrimes return (0); 2565160Sjoerg c = (*cn_tab->cn_getc)(cn_tab->cn_dev); 2575160Sjoerg if (c == '\r') c = '\n'; /* console input is always ICRNL */ 2585160Sjoerg return (c); 2594Srgrimes} 2604Srgrimes 2613728Sphkint 2623728Sphkcncheckc() 2633728Sphk{ 2643728Sphk if (cn_tab == NULL) 2653728Sphk return (0); 2663728Sphk return ((*cn_tab->cn_checkc)(cn_tab->cn_dev)); 2673728Sphk} 2683728Sphk 269798Swollmanvoid 2704Srgrimescnputc(c) 2714Srgrimes register int c; 2724Srgrimes{ 2734Srgrimes if (cn_tab == NULL) 2744Srgrimes return; 2754Srgrimes if (c) { 2764Srgrimes (*cn_tab->cn_putc)(cn_tab->cn_dev, c); 2774Srgrimes if (c == '\n') 2784Srgrimes (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r'); 2794Srgrimes } 2804Srgrimes} 2814Srgrimes 282718Swollmanint 283718Swollmanpg(const char *p, ...) { 284718Swollman va_list args; 285718Swollman va_start(args, p); 286718Swollman printf("%r\n>", p, args); 287718Swollman return(cngetc()); 2884Srgrimes} 2894Srgrimes 2904Srgrimes 291