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