ofw_console.c revision 126076
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 26113038Sobrien#include <sys/cdefs.h> 27113038Sobrien__FBSDID("$FreeBSD: head/sys/dev/ofw/ofw_console.c 126076 2004-02-21 19:42:58Z phk $"); 2878346Sbenno 29119418Sobrien#include <sys/cdefs.h> 30119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/ofw/ofw_console.c 126076 2004-02-21 19:42:58Z phk $"); 31119418Sobrien 32110509Sharti#include "opt_ddb.h" 33110509Sharti#include "opt_comconsole.h" 34110509Sharti 3578346Sbenno#include <sys/param.h> 3678346Sbenno#include <sys/kernel.h> 3778346Sbenno#include <sys/systm.h> 3878346Sbenno#include <sys/types.h> 3978346Sbenno#include <sys/conf.h> 4078346Sbenno#include <sys/cons.h> 4178346Sbenno#include <sys/consio.h> 4278346Sbenno#include <sys/tty.h> 4378346Sbenno 4478346Sbenno#include <dev/ofw/openfirm.h> 4578346Sbenno 46110509Sharti#include <ddb/ddb.h> 47110509Sharti 4888792Sjake#define OFW_POLL_HZ 4 4978346Sbenno 5078346Sbennostatic d_open_t ofw_dev_open; 5178346Sbennostatic d_close_t ofw_dev_close; 5278346Sbennostatic d_ioctl_t ofw_dev_ioctl; 5378346Sbenno 5478346Sbenno 5578346Sbennostatic struct cdevsw ofw_cdevsw = { 56111815Sphk .d_open = ofw_dev_open, 57111815Sphk .d_close = ofw_dev_close, 58111815Sphk .d_read = ttyread, 59111815Sphk .d_write = ttywrite, 60111815Sphk .d_ioctl = ofw_dev_ioctl, 61111815Sphk .d_poll = ttypoll, 62111815Sphk .d_name = "ofw", 6378346Sbenno}; 6478346Sbenno 6578346Sbennostatic struct tty *ofw_tp = NULL; 6678346Sbennostatic int polltime; 6778346Sbennostatic struct callout_handle ofw_timeouthandle 6878346Sbenno = CALLOUT_HANDLE_INITIALIZER(&ofw_timeouthandle); 6978346Sbenno 70110509Sharti#if defined(DDB) && defined(ALT_BREAK_TO_DEBUGGER) 71110509Shartistatic int alt_break_state; 72110509Sharti#endif 73110509Sharti 7478346Sbennostatic void ofw_tty_start(struct tty *); 7578346Sbennostatic int ofw_tty_param(struct tty *, struct termios *); 7678346Sbennostatic void ofw_tty_stop(struct tty *, int); 7778346Sbennostatic void ofw_timeout(void *); 7878346Sbenno 7978346Sbennostatic cn_probe_t ofw_cons_probe; 8078346Sbennostatic cn_init_t ofw_cons_init; 8178346Sbennostatic cn_getc_t ofw_cons_getc; 8278346Sbennostatic cn_checkc_t ofw_cons_checkc; 8378346Sbennostatic cn_putc_t ofw_cons_putc; 8478346Sbenno 8578346SbennoCONS_DRIVER(ofw, ofw_cons_probe, ofw_cons_init, NULL, ofw_cons_getc, 8678346Sbenno ofw_cons_checkc, ofw_cons_putc, NULL); 8778346Sbenno 8889115Sjakestatic void 8989115Sjakecn_drvinit(void *unused) 9089115Sjake{ 91107044Sjake phandle_t options; 92107044Sjake char output[32]; 93120491Sphk dev_t dev; 9489115Sjake 95120544Sjake if (ofw_consdev.cn_pri != CN_DEAD && 96120544Sjake ofw_consdev.cn_name[0] != '\0') { 97107044Sjake if ((options = OF_finddevice("/options")) == -1 || 98107044Sjake OF_getprop(options, "output-device", output, 99107044Sjake sizeof(output)) == -1) 100107044Sjake return; 101120491Sphk dev = make_dev(&ofw_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "%s", 102109921Sjake output); 103120491Sphk make_dev_alias(dev, "ofwcons"); 104107044Sjake } 10589115Sjake} 10689115Sjake 107126076SphkSYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL) 10889115Sjake 10978346Sbennostatic int stdin; 11078346Sbennostatic int stdout; 11178346Sbenno 11278346Sbennostatic int 11383366Sjulianofw_dev_open(dev_t dev, int flag, int mode, struct thread *td) 11478346Sbenno{ 11578346Sbenno struct tty *tp; 11678346Sbenno int unit; 11778346Sbenno int error, setuptimeout; 11878346Sbenno 11978346Sbenno error = 0; 12078346Sbenno setuptimeout = 0; 12178346Sbenno unit = minor(dev); 12278346Sbenno 12378346Sbenno tp = ofw_tp = dev->si_tty = ttymalloc(ofw_tp); 12478346Sbenno 12578346Sbenno tp->t_oproc = ofw_tty_start; 12678346Sbenno tp->t_param = ofw_tty_param; 12778346Sbenno tp->t_stop = ofw_tty_stop; 12878346Sbenno tp->t_dev = dev; 12978346Sbenno 13078346Sbenno if ((tp->t_state & TS_ISOPEN) == 0) { 13178346Sbenno tp->t_state |= TS_CARR_ON; 13278346Sbenno ttychars(tp); 13378346Sbenno tp->t_iflag = TTYDEF_IFLAG; 13478346Sbenno tp->t_oflag = TTYDEF_OFLAG; 13578346Sbenno tp->t_cflag = TTYDEF_CFLAG|CLOCAL; 13678346Sbenno tp->t_lflag = TTYDEF_LFLAG; 13778346Sbenno tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 13878346Sbenno ttsetwater(tp); 13978346Sbenno 14078346Sbenno setuptimeout = 1; 14193593Sjhb } else if ((tp->t_state & TS_XCLUDE) && suser(td)) { 14278346Sbenno return (EBUSY); 14378346Sbenno } 14478346Sbenno 14578346Sbenno error = (*linesw[tp->t_line].l_open)(dev, tp); 14678346Sbenno 14778346Sbenno if (error == 0 && setuptimeout) { 14878346Sbenno polltime = hz / OFW_POLL_HZ; 14978346Sbenno if (polltime < 1) { 15078346Sbenno polltime = 1; 15178346Sbenno } 15278346Sbenno 15378346Sbenno ofw_timeouthandle = timeout(ofw_timeout, tp, polltime); 15478346Sbenno } 15578346Sbenno 15678346Sbenno return (error); 15778346Sbenno} 15878346Sbenno 15978346Sbennostatic int 16083366Sjulianofw_dev_close(dev_t dev, int flag, int mode, struct thread *td) 16178346Sbenno{ 16278346Sbenno int unit; 16378346Sbenno struct tty *tp; 16478346Sbenno 16578346Sbenno unit = minor(dev); 16678346Sbenno tp = ofw_tp; 16778346Sbenno 16878346Sbenno if (unit != 0) { 16978346Sbenno return (ENXIO); 17078346Sbenno } 17178346Sbenno 17278346Sbenno (*linesw[tp->t_line].l_close)(tp, flag); 17378346Sbenno ttyclose(tp); 17478346Sbenno 17578346Sbenno return (0); 17678346Sbenno} 17778346Sbenno 17878346Sbennostatic int 17983366Sjulianofw_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) 18078346Sbenno{ 18178346Sbenno int unit; 18278346Sbenno struct tty *tp; 18378346Sbenno int error; 18478346Sbenno 18578346Sbenno unit = minor(dev); 18680696Sjake tp = ofw_tp; 18780696Sjake 18878346Sbenno if (unit != 0) { 18978346Sbenno return (ENXIO); 19078346Sbenno } 19178346Sbenno 19283366Sjulian error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td); 19378346Sbenno if (error != ENOIOCTL) { 19478346Sbenno return (error); 19578346Sbenno } 19678346Sbenno 19778346Sbenno error = ttioctl(tp, cmd, data, flag); 19878346Sbenno if (error != ENOIOCTL) { 19978346Sbenno return (error); 20078346Sbenno } 20178346Sbenno 20278346Sbenno return (ENOTTY); 20378346Sbenno} 20478346Sbenno 20578346Sbennostatic int 20678346Sbennoofw_tty_param(struct tty *tp, struct termios *t) 20778346Sbenno{ 20878346Sbenno 20978346Sbenno return (0); 21078346Sbenno} 21178346Sbenno 21278346Sbennostatic void 21378346Sbennoofw_tty_start(struct tty *tp) 21478346Sbenno{ 21578346Sbenno 21678346Sbenno if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 21778346Sbenno ttwwakeup(tp); 21878346Sbenno return; 21978346Sbenno } 22078346Sbenno 22178346Sbenno tp->t_state |= TS_BUSY; 22278346Sbenno while (tp->t_outq.c_cc != 0) { 223111194Sphk ofw_cons_putc(NULL, getc(&tp->t_outq)); 22478346Sbenno } 22578346Sbenno tp->t_state &= ~TS_BUSY; 22678346Sbenno 22778346Sbenno ttwwakeup(tp); 22878346Sbenno} 22978346Sbenno 23078346Sbennostatic void 23178346Sbennoofw_tty_stop(struct tty *tp, int flag) 23278346Sbenno{ 23378346Sbenno 23478346Sbenno if (tp->t_state & TS_BUSY) { 23578346Sbenno if ((tp->t_state & TS_TTSTOP) == 0) { 23678346Sbenno tp->t_state |= TS_FLUSH; 23778346Sbenno } 23878346Sbenno } 23978346Sbenno} 24078346Sbenno 24178346Sbennostatic void 24278346Sbennoofw_timeout(void *v) 24378346Sbenno{ 24478346Sbenno struct tty *tp; 24578346Sbenno int c; 24678346Sbenno 24778346Sbenno tp = (struct tty *)v; 24878346Sbenno 249111194Sphk while ((c = ofw_cons_checkc(NULL)) != -1) { 25078346Sbenno if (tp->t_state & TS_ISOPEN) { 25178346Sbenno (*linesw[tp->t_line].l_rint)(c, tp); 25278346Sbenno } 25378346Sbenno } 25478346Sbenno 25578346Sbenno ofw_timeouthandle = timeout(ofw_timeout, tp, polltime); 25678346Sbenno} 25778346Sbenno 25878346Sbennostatic void 25978346Sbennoofw_cons_probe(struct consdev *cp) 26078346Sbenno{ 26178346Sbenno int chosen; 26278346Sbenno 26378346Sbenno if ((chosen = OF_finddevice("/chosen")) == -1) { 26478346Sbenno cp->cn_pri = CN_DEAD; 26578346Sbenno return; 26678346Sbenno } 26778346Sbenno 26878346Sbenno if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) == -1) { 26978346Sbenno cp->cn_pri = CN_DEAD; 27078346Sbenno return; 27178346Sbenno } 27278346Sbenno 27378346Sbenno if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1) { 27478346Sbenno cp->cn_pri = CN_DEAD; 27578346Sbenno return; 27678346Sbenno } 27778346Sbenno 278120542Sjake cp->cn_pri = CN_LOW; 27978346Sbenno} 28078346Sbenno 28178346Sbennostatic void 28278346Sbennoofw_cons_init(struct consdev *cp) 28378346Sbenno{ 28478346Sbenno 285120467Sphk /* XXX: This is the alias, but that should be good enough */ 286120467Sphk sprintf(cp->cn_name, "ofwcons"); 287107044Sjake cp->cn_tp = ofw_tp; 28878346Sbenno} 28978346Sbenno 29078346Sbennostatic int 291111194Sphkofw_cons_getc(struct consdev *cp) 29278346Sbenno{ 29378346Sbenno unsigned char ch; 29478346Sbenno int l; 29578346Sbenno 29678346Sbenno ch = '\0'; 29778346Sbenno 29878346Sbenno while ((l = OF_read(stdin, &ch, 1)) != 1) { 29978346Sbenno if (l != -2 && l != 0) { 30078346Sbenno return (-1); 30178346Sbenno } 30278346Sbenno } 30378346Sbenno 304110509Sharti#if defined(DDB) && defined(ALT_BREAK_TO_DEBUGGER) 305110509Sharti if (db_alt_break(ch, &alt_break_state)) 306110509Sharti breakpoint(); 307110509Sharti#endif 308110509Sharti 30978346Sbenno return (ch); 31078346Sbenno} 31178346Sbenno 31278346Sbennostatic int 313111194Sphkofw_cons_checkc(struct consdev *cp) 31478346Sbenno{ 31578346Sbenno unsigned char ch; 31678346Sbenno 31788792Sjake if (OF_read(stdin, &ch, 1) > 0) { 318110509Sharti#if defined(DDB) && defined(ALT_BREAK_TO_DEBUGGER) 319110509Sharti if (db_alt_break(ch, &alt_break_state)) 320110509Sharti breakpoint(); 321110509Sharti#endif 32278346Sbenno return (ch); 32378346Sbenno } 32478346Sbenno 32578346Sbenno return (-1); 32678346Sbenno} 32778346Sbenno 32878346Sbennostatic void 329111194Sphkofw_cons_putc(struct consdev *cp, int c) 33078346Sbenno{ 33178346Sbenno char cbuf; 33278346Sbenno 33378346Sbenno if (c == '\n') { 33478346Sbenno cbuf = '\r'; 33578346Sbenno OF_write(stdout, &cbuf, 1); 33678346Sbenno } 33778346Sbenno 33878346Sbenno cbuf = c; 33978346Sbenno OF_write(stdout, &cbuf, 1); 34078346Sbenno} 341