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