ofw_console.c revision 93593
178346Sbenno/*
278346Sbenno * Copyright (C) 2001 Benno Rice.
378346Sbenno * All rights reserved.
478346Sbenno *
578346Sbenno * Redistribution and use in source and binary forms, with or without
678346Sbenno * modification, are permitted provided that the following conditions
778346Sbenno * are met:
878346Sbenno * 1. Redistributions of source code must retain the above copyright
978346Sbenno *    notice, this list of conditions and the following disclaimer.
1078346Sbenno * 2. Redistributions in binary form must reproduce the above copyright
1178346Sbenno *    notice, this list of conditions and the following disclaimer in the
1278346Sbenno *    documentation and/or other materials provided with the distribution.
1378346Sbenno *
1478346Sbenno * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
1578346Sbenno * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1678346Sbenno * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1778346Sbenno * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1878346Sbenno * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1978346Sbenno * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2078346Sbenno * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2178346Sbenno * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2278346Sbenno * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
2378346Sbenno * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2478346Sbenno */
2578346Sbenno
2678346Sbenno#ifndef lint
2778346Sbennostatic const char rcsid[] =
2878346Sbenno  "$FreeBSD: head/sys/dev/ofw/ofw_console.c 93593 2002-04-01 21:31:13Z jhb $";
2978346Sbenno#endif /* not lint */
3078346Sbenno
3178346Sbenno#include <sys/param.h>
3278346Sbenno#include <sys/kernel.h>
3378346Sbenno#include <sys/systm.h>
3478346Sbenno#include <sys/types.h>
3578346Sbenno#include <sys/conf.h>
3678346Sbenno#include <sys/cons.h>
3778346Sbenno#include <sys/consio.h>
3878346Sbenno#include <sys/tty.h>
3978346Sbenno
4078346Sbenno#include <dev/ofw/openfirm.h>
4178346Sbenno
4288792Sjake#define	OFW_POLL_HZ	4
4378346Sbenno
4478346Sbennostatic d_open_t		ofw_dev_open;
4578346Sbennostatic d_close_t	ofw_dev_close;
4678346Sbennostatic d_ioctl_t	ofw_dev_ioctl;
4778346Sbenno
4878346Sbenno#define	CDEV_MAJOR	97
4978346Sbenno
5078346Sbennostatic struct cdevsw ofw_cdevsw = {
5178346Sbenno	/* open */	ofw_dev_open,
5278346Sbenno	/* close */	ofw_dev_close,
5378346Sbenno	/* read */	ttyread,
5478346Sbenno	/* write */	ttywrite,
5578346Sbenno	/* ioctl */	ofw_dev_ioctl,
5678346Sbenno	/* poll */	ttypoll,
5778346Sbenno	/* mmap */	nommap,
5878346Sbenno	/* strategy */	nostrategy,
5978346Sbenno	/* name */	"ofw",
6078346Sbenno	/* major */	CDEV_MAJOR,
6178346Sbenno	/* dump */	nodump,
6278346Sbenno	/* psize */	nopsize,
6378346Sbenno	/* flags */	0,
6478346Sbenno};
6578346Sbenno
6678346Sbennostatic struct tty		*ofw_tp = NULL;
6778346Sbennostatic int			polltime;
6878346Sbennostatic struct callout_handle	ofw_timeouthandle
6978346Sbenno    = CALLOUT_HANDLE_INITIALIZER(&ofw_timeouthandle);
7078346Sbenno
7178346Sbennostatic void	ofw_tty_start(struct tty *);
7278346Sbennostatic int	ofw_tty_param(struct tty *, struct termios *);
7378346Sbennostatic void	ofw_tty_stop(struct tty *, int);
7478346Sbennostatic void	ofw_timeout(void *);
7578346Sbenno
7678346Sbennostatic cn_probe_t	ofw_cons_probe;
7778346Sbennostatic cn_init_t	ofw_cons_init;
7878346Sbennostatic cn_getc_t	ofw_cons_getc;
7978346Sbennostatic cn_checkc_t 	ofw_cons_checkc;
8078346Sbennostatic cn_putc_t	ofw_cons_putc;
8178346Sbenno
8278346SbennoCONS_DRIVER(ofw, ofw_cons_probe, ofw_cons_init, NULL, ofw_cons_getc,
8378346Sbenno    ofw_cons_checkc, ofw_cons_putc, NULL);
8478346Sbenno
8589115Sjakestatic void
8689115Sjakecn_drvinit(void *unused)
8789115Sjake{
8889115Sjake
8989115Sjake	make_dev(&ofw_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "ofwcons");
9089115Sjake}
9189115Sjake
9289115SjakeSYSINIT(cndev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,cn_drvinit,NULL)
9389115Sjake
9478346Sbennostatic int	stdin;
9578346Sbennostatic int	stdout;
9678346Sbenno
9778346Sbennostatic int
9883366Sjulianofw_dev_open(dev_t dev, int flag, int mode, struct thread *td)
9978346Sbenno{
10078346Sbenno	struct	tty *tp;
10178346Sbenno	int	unit;
10278346Sbenno	int	error, setuptimeout;
10378346Sbenno
10478346Sbenno	error = 0;
10578346Sbenno	setuptimeout = 0;
10678346Sbenno	unit = minor(dev);
10778346Sbenno
10878346Sbenno	tp = ofw_tp = dev->si_tty = ttymalloc(ofw_tp);
10978346Sbenno
11078346Sbenno	tp->t_oproc = ofw_tty_start;
11178346Sbenno	tp->t_param = ofw_tty_param;
11278346Sbenno	tp->t_stop = ofw_tty_stop;
11378346Sbenno	tp->t_dev = dev;
11478346Sbenno
11578346Sbenno	if ((tp->t_state & TS_ISOPEN) == 0) {
11678346Sbenno		tp->t_state |= TS_CARR_ON;
11778346Sbenno		ttychars(tp);
11878346Sbenno		tp->t_iflag = TTYDEF_IFLAG;
11978346Sbenno		tp->t_oflag = TTYDEF_OFLAG;
12078346Sbenno		tp->t_cflag = TTYDEF_CFLAG|CLOCAL;
12178346Sbenno		tp->t_lflag = TTYDEF_LFLAG;
12278346Sbenno		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
12378346Sbenno		ttsetwater(tp);
12478346Sbenno
12578346Sbenno		setuptimeout = 1;
12693593Sjhb	} else if ((tp->t_state & TS_XCLUDE) && suser(td)) {
12778346Sbenno		return (EBUSY);
12878346Sbenno	}
12978346Sbenno
13078346Sbenno	error = (*linesw[tp->t_line].l_open)(dev, tp);
13178346Sbenno
13278346Sbenno	if (error == 0 && setuptimeout) {
13378346Sbenno		polltime = hz / OFW_POLL_HZ;
13478346Sbenno		if (polltime < 1) {
13578346Sbenno			polltime = 1;
13678346Sbenno		}
13778346Sbenno
13878346Sbenno		ofw_timeouthandle = timeout(ofw_timeout, tp, polltime);
13978346Sbenno	}
14078346Sbenno
14178346Sbenno	return (error);
14278346Sbenno}
14378346Sbenno
14478346Sbennostatic int
14583366Sjulianofw_dev_close(dev_t dev, int flag, int mode, struct thread *td)
14678346Sbenno{
14778346Sbenno	int	unit;
14878346Sbenno	struct	tty *tp;
14978346Sbenno
15078346Sbenno	unit = minor(dev);
15178346Sbenno	tp = ofw_tp;
15278346Sbenno
15378346Sbenno	if (unit != 0) {
15478346Sbenno		return (ENXIO);
15578346Sbenno	}
15678346Sbenno
15778346Sbenno	(*linesw[tp->t_line].l_close)(tp, flag);
15878346Sbenno	ttyclose(tp);
15978346Sbenno
16078346Sbenno	return (0);
16178346Sbenno}
16278346Sbenno
16378346Sbennostatic int
16483366Sjulianofw_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
16578346Sbenno{
16678346Sbenno	int	unit;
16778346Sbenno	struct	tty *tp;
16878346Sbenno	int	error;
16978346Sbenno
17078346Sbenno	unit = minor(dev);
17180696Sjake	tp = ofw_tp;
17280696Sjake
17378346Sbenno	if (unit != 0) {
17478346Sbenno		return (ENXIO);
17578346Sbenno	}
17678346Sbenno
17783366Sjulian	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td);
17878346Sbenno	if (error != ENOIOCTL) {
17978346Sbenno		return (error);
18078346Sbenno	}
18178346Sbenno
18278346Sbenno	error = ttioctl(tp, cmd, data, flag);
18378346Sbenno	if (error != ENOIOCTL) {
18478346Sbenno		return (error);
18578346Sbenno	}
18678346Sbenno
18778346Sbenno	return (ENOTTY);
18878346Sbenno}
18978346Sbenno
19078346Sbennostatic int
19178346Sbennoofw_tty_param(struct tty *tp, struct termios *t)
19278346Sbenno{
19378346Sbenno
19478346Sbenno	return (0);
19578346Sbenno}
19678346Sbenno
19778346Sbennostatic void
19878346Sbennoofw_tty_start(struct tty *tp)
19978346Sbenno{
20078346Sbenno
20178346Sbenno	if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
20278346Sbenno		ttwwakeup(tp);
20378346Sbenno		return;
20478346Sbenno	}
20578346Sbenno
20678346Sbenno	tp->t_state |= TS_BUSY;
20778346Sbenno	while (tp->t_outq.c_cc != 0) {
20878346Sbenno		ofw_cons_putc(tp->t_dev, getc(&tp->t_outq));
20978346Sbenno	}
21078346Sbenno	tp->t_state &= ~TS_BUSY;
21178346Sbenno
21278346Sbenno	ttwwakeup(tp);
21378346Sbenno}
21478346Sbenno
21578346Sbennostatic void
21678346Sbennoofw_tty_stop(struct tty *tp, int flag)
21778346Sbenno{
21878346Sbenno
21978346Sbenno	if (tp->t_state & TS_BUSY) {
22078346Sbenno		if ((tp->t_state & TS_TTSTOP) == 0) {
22178346Sbenno			tp->t_state |= TS_FLUSH;
22278346Sbenno		}
22378346Sbenno	}
22478346Sbenno}
22578346Sbenno
22678346Sbennostatic void
22778346Sbennoofw_timeout(void *v)
22878346Sbenno{
22978346Sbenno	struct	tty *tp;
23078346Sbenno	int 	c;
23178346Sbenno
23278346Sbenno	tp = (struct tty *)v;
23378346Sbenno
23478346Sbenno	while ((c = ofw_cons_checkc(tp->t_dev)) != -1) {
23578346Sbenno		if (tp->t_state & TS_ISOPEN) {
23678346Sbenno			(*linesw[tp->t_line].l_rint)(c, tp);
23778346Sbenno		}
23878346Sbenno	}
23978346Sbenno
24078346Sbenno	ofw_timeouthandle = timeout(ofw_timeout, tp, polltime);
24178346Sbenno}
24278346Sbenno
24378346Sbennostatic void
24478346Sbennoofw_cons_probe(struct consdev *cp)
24578346Sbenno{
24678346Sbenno	int chosen;
24778346Sbenno
24878346Sbenno	if ((chosen = OF_finddevice("/chosen")) == -1) {
24978346Sbenno		cp->cn_pri = CN_DEAD;
25078346Sbenno		return;
25178346Sbenno	}
25278346Sbenno
25378346Sbenno	if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) == -1) {
25478346Sbenno		cp->cn_pri = CN_DEAD;
25578346Sbenno		return;
25678346Sbenno	}
25778346Sbenno
25878346Sbenno	if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1) {
25978346Sbenno		cp->cn_pri = CN_DEAD;
26078346Sbenno		return;
26178346Sbenno	}
26278346Sbenno
26378346Sbenno	cp->cn_dev = makedev(CDEV_MAJOR, 0);
26478346Sbenno	cp->cn_pri = CN_INTERNAL;
26578346Sbenno	cp->cn_tp = ofw_tp;
26678346Sbenno}
26778346Sbenno
26878346Sbennostatic void
26978346Sbennoofw_cons_init(struct consdev *cp)
27078346Sbenno{
27178346Sbenno
27278346Sbenno	return;
27378346Sbenno}
27478346Sbenno
27578346Sbennostatic int
27678346Sbennoofw_cons_getc(dev_t dev)
27778346Sbenno{
27878346Sbenno	unsigned char ch;
27978346Sbenno	int l;
28078346Sbenno
28178346Sbenno	ch = '\0';
28278346Sbenno
28378346Sbenno	while ((l = OF_read(stdin, &ch, 1)) != 1) {
28478346Sbenno		if (l != -2 && l != 0) {
28578346Sbenno			return (-1);
28678346Sbenno		}
28778346Sbenno	}
28878346Sbenno
28978346Sbenno	return (ch);
29078346Sbenno}
29178346Sbenno
29278346Sbennostatic int
29378346Sbennoofw_cons_checkc(dev_t dev)
29478346Sbenno{
29578346Sbenno	unsigned char ch;
29678346Sbenno
29788792Sjake	if (OF_read(stdin, &ch, 1) > 0) {
29878346Sbenno		return (ch);
29978346Sbenno	}
30078346Sbenno
30178346Sbenno	return (-1);
30278346Sbenno}
30378346Sbenno
30478346Sbennostatic void
30578346Sbennoofw_cons_putc(dev_t dev, int c)
30678346Sbenno{
30778346Sbenno	char cbuf;
30878346Sbenno
30978346Sbenno	if (c == '\n') {
31078346Sbenno		cbuf = '\r';
31178346Sbenno		OF_write(stdout, &cbuf, 1);
31278346Sbenno	}
31378346Sbenno
31478346Sbenno	cbuf = c;
31578346Sbenno	OF_write(stdout, &cbuf, 1);
31678346Sbenno}
317