kern_cons.c revision 10665
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 3910665Sbde * $Id: cons.c,v 1.32 1995/09/09 18:09:44 davidg 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 518023Sbde/* XXX this should be config(8)ed. */ 528047Sbde#include "sc.h" 538047Sbde#include "vt.h" 548047Sbde#include "sio.h" 555764Sbdestatic struct consdev constab[] = { 565161Sjoerg#if NSC > 0 || NVT > 0 573728Sphk { pccnprobe, pccninit, pccngetc, pccncheckc, pccnputc }, 582423Sdg#endif 59849Sdg#if NSIO > 0 603728Sphk { siocnprobe, siocninit, siocngetc, siocncheckc, siocnputc }, 61849Sdg#endif 624Srgrimes { 0 }, 634Srgrimes}; 644Srgrimes 654Srgrimesstruct tty *constty = 0; /* virtual console output device */ 664Srgrimesstruct tty *cn_tty; /* XXX: console tty struct for tprintf */ 677680Sjoergint cons_unavail = 0; /* XXX: 687680Sjoerg * physical console not available for 697680Sjoerg * input (i.e., it is in graphics mode) 707680Sjoerg */ 714Srgrimes 726731Sbdestatic u_char cn_is_open; /* nonzero if logical console is open */ 736731Sbdestatic u_char cn_phys_is_open; /* nonzero if physical console is open */ 745764Sbdestatic d_close_t *cn_phys_close; /* physical device close function */ 755764Sbdestatic d_open_t *cn_phys_open; /* physical device open function */ 765764Sbdestatic struct consdev *cn_tab; /* physical console device info */ 777588Sjoergstatic struct tty *cn_tp; /* physical console tty struct */ 785764Sbde 7910665Sbde#ifdef DEVFS 8010665Sbde#include <sys/kernel.h> 8110537Sjulian#include <sys/devfsext.h> 8210537Sjulian 8310665Sbdestatic void cndev_init __P((void *)); 8410665SbdeSYSINIT(cndev, SI_SUB_DEVFS, SI_ORDER_ANY, cndev_init, NULL) 8510665Sbde 8610665Sbdestatic void 8710665Sbdecndev_init(dummy) 8810665Sbde void *dummy; 8910537Sjulian{ 9010537Sjulian void * x; 9110537Sjulian/* path name devsw minor type uid gid perm*/ 9210537Sjulian x=dev_add("/misc", "console", cnopen, 0, DV_CHR, 0, 0, 0640); 9310537Sjulian} 9410665Sbde#endif /* DEVFS */ 9510537Sjulian 96798Swollmanvoid 974Srgrimescninit() 984Srgrimes{ 9910665Sbde struct consdev *best_cp, *cp; 1004Srgrimes 1014Srgrimes /* 10210665Sbde * Find the first console with the highest priority. 1034Srgrimes */ 10410665Sbde best_cp = NULL; 1054Srgrimes for (cp = constab; cp->cn_probe; cp++) { 1064Srgrimes (*cp->cn_probe)(cp); 1074Srgrimes if (cp->cn_pri > CN_DEAD && 10810665Sbde (best_cp == NULL || cp->cn_pri > best_cp->cn_pri)) 10910665Sbde best_cp = cp; 1104Srgrimes } 11110665Sbde 1124Srgrimes /* 11310665Sbde * If no console, give up. 1144Srgrimes */ 11510665Sbde if (best_cp == NULL) { 11610665Sbde cn_tab = best_cp; 1174Srgrimes return; 11810665Sbde } 11910665Sbde 1204Srgrimes /* 12110665Sbde * Initialize console, then attach to it. This ordering allows 12210665Sbde * debugging using the previous console, if any. 12310665Sbde * XXX if there was a previous console, then its driver should 12410665Sbde * be informed when we forget about it. 12510665Sbde */ 12610665Sbde (*best_cp->cn_init)(best_cp); 12710665Sbde cn_tab = best_cp; 12810665Sbde} 12910665Sbde 13010665Sbdevoid 13110665Sbdecninit_finish() 13210665Sbde{ 13310665Sbde struct cdevsw *cdp; 13410665Sbde 13510665Sbde if (cn_tab == NULL) 13610665Sbde return; 13710665Sbde 13810665Sbde /* 1395764Sbde * Hook the open and close functions. 1405764Sbde */ 1415764Sbde cdp = &cdevsw[major(cn_tab->cn_dev)]; 1425764Sbde cn_phys_close = cdp->d_close; 1435764Sbde cdp->d_close = cnclose; 1445764Sbde cn_phys_open = cdp->d_open; 1455764Sbde cdp->d_open = cnopen; 1467588Sjoerg cn_tp = (*cdp->d_devtotty)(cn_tab->cn_dev); 1475764Sbde /* 1489326Sbde * XXX there are too many tty pointers. cn_tty is only used for 1499326Sbde * sysctl(CPU_CONSDEV) (not for tprintf like the above comment 1509326Sbde * says). cn_tp in struct consdev hasn't been initialized 1519326Sbde * (except statically to NULL) or used (except to initialize 1529326Sbde * cn_tty to the wrong value) for a year or two. 1539326Sbde */ 1549326Sbde cn_tty = cn_tp; 1554Srgrimes} 1564Srgrimes 157798Swollmanint 1584Srgrimescnopen(dev, flag, mode, p) 1594Srgrimes dev_t dev; 1604Srgrimes int flag, mode; 1614Srgrimes struct proc *p; 1624Srgrimes{ 1635764Sbde dev_t cndev, physdev; 1645764Sbde int retval; 1651007Sdg 1664Srgrimes if (cn_tab == NULL) 1674Srgrimes return (0); 1685764Sbde cndev = cn_tab->cn_dev; 1695764Sbde physdev = (major(dev) == major(cndev) ? dev : cndev); 1705764Sbde retval = (*cn_phys_open)(physdev, flag, mode, p); 1715764Sbde if (retval == 0) { 1725764Sbde if (dev == cndev) 1735764Sbde cn_phys_is_open = 1; 1745764Sbde else if (physdev == cndev) 1755764Sbde cn_is_open = 1; 1765764Sbde } 1775764Sbde return (retval); 1784Srgrimes} 1798876Srgrimes 180798Swollmanint 1814Srgrimescnclose(dev, flag, mode, p) 1824Srgrimes dev_t dev; 1834Srgrimes int flag, mode; 1844Srgrimes struct proc *p; 1854Srgrimes{ 1865764Sbde dev_t cndev; 1871007Sdg 1884Srgrimes if (cn_tab == NULL) 1894Srgrimes return (0); 1905764Sbde cndev = cn_tab->cn_dev; 1915764Sbde if (dev == cndev) { 1927588Sjoerg /* the physical device is about to be closed */ 1935764Sbde cn_phys_is_open = 0; 1947588Sjoerg if (cn_is_open) { 1957588Sjoerg if (cn_tp) { 1967588Sjoerg /* perform a ttyhalfclose() */ 1977588Sjoerg /* reset session and proc group */ 1987588Sjoerg cn_tp->t_pgrp = NULL; 1997588Sjoerg cn_tp->t_session = NULL; 2007588Sjoerg } 2015764Sbde return (0); 2027588Sjoerg } 2035764Sbde } else if (major(dev) != major(cndev)) { 2047588Sjoerg /* the logical console is about to be closed */ 2055764Sbde cn_is_open = 0; 2065764Sbde if (cn_phys_is_open) 2075764Sbde return (0); 2085764Sbde dev = cndev; 2095764Sbde } 2105764Sbde return ((*cn_phys_close)(dev, flag, mode, p)); 2114Srgrimes} 2128876Srgrimes 213798Swollmanint 2144Srgrimescnread(dev, uio, flag) 2154Srgrimes dev_t dev; 2164Srgrimes struct uio *uio; 217798Swollman int flag; 2184Srgrimes{ 2194Srgrimes if (cn_tab == NULL) 2204Srgrimes return (0); 2214Srgrimes dev = cn_tab->cn_dev; 2224Srgrimes return ((*cdevsw[major(dev)].d_read)(dev, uio, flag)); 2234Srgrimes} 2248876Srgrimes 225798Swollmanint 2264Srgrimescnwrite(dev, uio, flag) 2274Srgrimes dev_t dev; 2284Srgrimes struct uio *uio; 229798Swollman int flag; 2304Srgrimes{ 2314Srgrimes if (cn_tab == NULL) 2324Srgrimes return (0); 2331021Sdg if (constty) 2344Srgrimes dev = constty->t_dev; 2354Srgrimes else 2364Srgrimes dev = cn_tab->cn_dev; 2374Srgrimes return ((*cdevsw[major(dev)].d_write)(dev, uio, flag)); 2384Srgrimes} 2398876Srgrimes 240798Swollmanint 2414Srgrimescnioctl(dev, cmd, data, flag, p) 2424Srgrimes dev_t dev; 243798Swollman int cmd; 2444Srgrimes caddr_t data; 245798Swollman int flag; 2464Srgrimes struct proc *p; 2474Srgrimes{ 2484Srgrimes int error; 2494Srgrimes 2504Srgrimes if (cn_tab == NULL) 2514Srgrimes return (0); 2524Srgrimes /* 2534Srgrimes * Superuser can always use this to wrest control of console 2544Srgrimes * output from the "virtual" console. 2554Srgrimes */ 2564Srgrimes if (cmd == TIOCCONS && constty) { 2574Srgrimes error = suser(p->p_ucred, (u_short *) NULL); 2584Srgrimes if (error) 2594Srgrimes return (error); 2604Srgrimes constty = NULL; 2614Srgrimes return (0); 2624Srgrimes } 2634Srgrimes dev = cn_tab->cn_dev; 2644Srgrimes return ((*cdevsw[major(dev)].d_ioctl)(dev, cmd, data, flag, p)); 2654Srgrimes} 2664Srgrimes 267798Swollmanint 2684Srgrimescnselect(dev, rw, p) 2694Srgrimes dev_t dev; 2704Srgrimes int rw; 2714Srgrimes struct proc *p; 2724Srgrimes{ 2734Srgrimes if (cn_tab == NULL) 2744Srgrimes return (1); 2756712Spst 2766712Spst dev = cn_tab->cn_dev; 2776712Spst 2786712Spst return ((*cdevsw[major(dev)].d_select)(dev, rw, p)); 2794Srgrimes} 2804Srgrimes 281798Swollmanint 2824Srgrimescngetc() 2834Srgrimes{ 2845160Sjoerg int c; 2854Srgrimes if (cn_tab == NULL) 2864Srgrimes return (0); 2875160Sjoerg c = (*cn_tab->cn_getc)(cn_tab->cn_dev); 2885160Sjoerg if (c == '\r') c = '\n'; /* console input is always ICRNL */ 2895160Sjoerg return (c); 2904Srgrimes} 2914Srgrimes 2923728Sphkint 2933728Sphkcncheckc() 2943728Sphk{ 2953728Sphk if (cn_tab == NULL) 2963728Sphk return (0); 2973728Sphk return ((*cn_tab->cn_checkc)(cn_tab->cn_dev)); 2983728Sphk} 2993728Sphk 300798Swollmanvoid 3014Srgrimescnputc(c) 3024Srgrimes register int c; 3034Srgrimes{ 3044Srgrimes if (cn_tab == NULL) 3054Srgrimes return; 3064Srgrimes if (c) { 3074Srgrimes if (c == '\n') 3084Srgrimes (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r'); 3099217Sbde (*cn_tab->cn_putc)(cn_tab->cn_dev, c); 3104Srgrimes } 3114Srgrimes} 3124Srgrimes 313718Swollmanint 314718Swollmanpg(const char *p, ...) { 315718Swollman va_list args; 316718Swollman va_start(args, p); 317718Swollman printf("%r\n>", p, args); 318718Swollman return(cngetc()); 3194Srgrimes} 3204Srgrimes 3214Srgrimes 322