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