ofw_console.c revision 120491
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 120491 2003-09-26 19:35:50Z phk $"); 2878346Sbenno 29119418Sobrien#include <sys/cdefs.h> 30119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/ofw/ofw_console.c 120491 2003-09-26 19:35:50Z 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#define CDEV_MAJOR 97 5578346Sbenno 5678346Sbennostatic struct cdevsw ofw_cdevsw = { 57111815Sphk .d_open = ofw_dev_open, 58111815Sphk .d_close = ofw_dev_close, 59111815Sphk .d_read = ttyread, 60111815Sphk .d_write = ttywrite, 61111815Sphk .d_ioctl = ofw_dev_ioctl, 62111815Sphk .d_poll = ttypoll, 63111815Sphk .d_name = "ofw", 64111815Sphk .d_maj = CDEV_MAJOR, 6578346Sbenno}; 6678346Sbenno 6778346Sbennostatic struct tty *ofw_tp = NULL; 6878346Sbennostatic int polltime; 6978346Sbennostatic struct callout_handle ofw_timeouthandle 7078346Sbenno = CALLOUT_HANDLE_INITIALIZER(&ofw_timeouthandle); 7178346Sbenno 72110509Sharti#if defined(DDB) && defined(ALT_BREAK_TO_DEBUGGER) 73110509Shartistatic int alt_break_state; 74110509Sharti#endif 75110509Sharti 7678346Sbennostatic void ofw_tty_start(struct tty *); 7778346Sbennostatic int ofw_tty_param(struct tty *, struct termios *); 7878346Sbennostatic void ofw_tty_stop(struct tty *, int); 7978346Sbennostatic void ofw_timeout(void *); 8078346Sbenno 8178346Sbennostatic cn_probe_t ofw_cons_probe; 8278346Sbennostatic cn_init_t ofw_cons_init; 8378346Sbennostatic cn_getc_t ofw_cons_getc; 8478346Sbennostatic cn_checkc_t ofw_cons_checkc; 8578346Sbennostatic cn_putc_t ofw_cons_putc; 8678346Sbenno 8778346SbennoCONS_DRIVER(ofw, ofw_cons_probe, ofw_cons_init, NULL, ofw_cons_getc, 8878346Sbenno ofw_cons_checkc, ofw_cons_putc, NULL); 8978346Sbenno 9089115Sjakestatic void 9189115Sjakecn_drvinit(void *unused) 9289115Sjake{ 93107044Sjake phandle_t options; 94107044Sjake char output[32]; 95120491Sphk dev_t dev; 9689115Sjake 97120491Sphk if (ofw_consdev.cn_pri != CN_DEAD) { 98107044Sjake if ((options = OF_finddevice("/options")) == -1 || 99107044Sjake OF_getprop(options, "output-device", output, 100107044Sjake sizeof(output)) == -1) 101107044Sjake return; 102120491Sphk dev = make_dev(&ofw_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "%s", 103109921Sjake output); 104120491Sphk make_dev_alias(dev, "ofwcons"); 105107044Sjake } 10689115Sjake} 10789115Sjake 108107044SjakeSYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE + CDEV_MAJOR, cn_drvinit, NULL) 10989115Sjake 11078346Sbennostatic int stdin; 11178346Sbennostatic int stdout; 11278346Sbenno 11378346Sbennostatic int 11483366Sjulianofw_dev_open(dev_t dev, int flag, int mode, struct thread *td) 11578346Sbenno{ 11678346Sbenno struct tty *tp; 11778346Sbenno int unit; 11878346Sbenno int error, setuptimeout; 11978346Sbenno 12078346Sbenno error = 0; 12178346Sbenno setuptimeout = 0; 12278346Sbenno unit = minor(dev); 12378346Sbenno 12478346Sbenno tp = ofw_tp = dev->si_tty = ttymalloc(ofw_tp); 12578346Sbenno 12678346Sbenno tp->t_oproc = ofw_tty_start; 12778346Sbenno tp->t_param = ofw_tty_param; 12878346Sbenno tp->t_stop = ofw_tty_stop; 12978346Sbenno tp->t_dev = dev; 13078346Sbenno 13178346Sbenno if ((tp->t_state & TS_ISOPEN) == 0) { 13278346Sbenno tp->t_state |= TS_CARR_ON; 13378346Sbenno ttychars(tp); 13478346Sbenno tp->t_iflag = TTYDEF_IFLAG; 13578346Sbenno tp->t_oflag = TTYDEF_OFLAG; 13678346Sbenno tp->t_cflag = TTYDEF_CFLAG|CLOCAL; 13778346Sbenno tp->t_lflag = TTYDEF_LFLAG; 13878346Sbenno tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 13978346Sbenno ttsetwater(tp); 14078346Sbenno 14178346Sbenno setuptimeout = 1; 14293593Sjhb } else if ((tp->t_state & TS_XCLUDE) && suser(td)) { 14378346Sbenno return (EBUSY); 14478346Sbenno } 14578346Sbenno 14678346Sbenno error = (*linesw[tp->t_line].l_open)(dev, tp); 14778346Sbenno 14878346Sbenno if (error == 0 && setuptimeout) { 14978346Sbenno polltime = hz / OFW_POLL_HZ; 15078346Sbenno if (polltime < 1) { 15178346Sbenno polltime = 1; 15278346Sbenno } 15378346Sbenno 15478346Sbenno ofw_timeouthandle = timeout(ofw_timeout, tp, polltime); 15578346Sbenno } 15678346Sbenno 15778346Sbenno return (error); 15878346Sbenno} 15978346Sbenno 16078346Sbennostatic int 16183366Sjulianofw_dev_close(dev_t dev, int flag, int mode, struct thread *td) 16278346Sbenno{ 16378346Sbenno int unit; 16478346Sbenno struct tty *tp; 16578346Sbenno 16678346Sbenno unit = minor(dev); 16778346Sbenno tp = ofw_tp; 16878346Sbenno 16978346Sbenno if (unit != 0) { 17078346Sbenno return (ENXIO); 17178346Sbenno } 17278346Sbenno 17378346Sbenno (*linesw[tp->t_line].l_close)(tp, flag); 17478346Sbenno ttyclose(tp); 17578346Sbenno 17678346Sbenno return (0); 17778346Sbenno} 17878346Sbenno 17978346Sbennostatic int 18083366Sjulianofw_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) 18178346Sbenno{ 18278346Sbenno int unit; 18378346Sbenno struct tty *tp; 18478346Sbenno int error; 18578346Sbenno 18678346Sbenno unit = minor(dev); 18780696Sjake tp = ofw_tp; 18880696Sjake 18978346Sbenno if (unit != 0) { 19078346Sbenno return (ENXIO); 19178346Sbenno } 19278346Sbenno 19383366Sjulian error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td); 19478346Sbenno if (error != ENOIOCTL) { 19578346Sbenno return (error); 19678346Sbenno } 19778346Sbenno 19878346Sbenno error = ttioctl(tp, cmd, data, flag); 19978346Sbenno if (error != ENOIOCTL) { 20078346Sbenno return (error); 20178346Sbenno } 20278346Sbenno 20378346Sbenno return (ENOTTY); 20478346Sbenno} 20578346Sbenno 20678346Sbennostatic int 20778346Sbennoofw_tty_param(struct tty *tp, struct termios *t) 20878346Sbenno{ 20978346Sbenno 21078346Sbenno return (0); 21178346Sbenno} 21278346Sbenno 21378346Sbennostatic void 21478346Sbennoofw_tty_start(struct tty *tp) 21578346Sbenno{ 21678346Sbenno 21778346Sbenno if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { 21878346Sbenno ttwwakeup(tp); 21978346Sbenno return; 22078346Sbenno } 22178346Sbenno 22278346Sbenno tp->t_state |= TS_BUSY; 22378346Sbenno while (tp->t_outq.c_cc != 0) { 224111194Sphk ofw_cons_putc(NULL, getc(&tp->t_outq)); 22578346Sbenno } 22678346Sbenno tp->t_state &= ~TS_BUSY; 22778346Sbenno 22878346Sbenno ttwwakeup(tp); 22978346Sbenno} 23078346Sbenno 23178346Sbennostatic void 23278346Sbennoofw_tty_stop(struct tty *tp, int flag) 23378346Sbenno{ 23478346Sbenno 23578346Sbenno if (tp->t_state & TS_BUSY) { 23678346Sbenno if ((tp->t_state & TS_TTSTOP) == 0) { 23778346Sbenno tp->t_state |= TS_FLUSH; 23878346Sbenno } 23978346Sbenno } 24078346Sbenno} 24178346Sbenno 24278346Sbennostatic void 24378346Sbennoofw_timeout(void *v) 24478346Sbenno{ 24578346Sbenno struct tty *tp; 24678346Sbenno int c; 24778346Sbenno 24878346Sbenno tp = (struct tty *)v; 24978346Sbenno 250111194Sphk while ((c = ofw_cons_checkc(NULL)) != -1) { 25178346Sbenno if (tp->t_state & TS_ISOPEN) { 25278346Sbenno (*linesw[tp->t_line].l_rint)(c, tp); 25378346Sbenno } 25478346Sbenno } 25578346Sbenno 25678346Sbenno ofw_timeouthandle = timeout(ofw_timeout, tp, polltime); 25778346Sbenno} 25878346Sbenno 25978346Sbennostatic void 26078346Sbennoofw_cons_probe(struct consdev *cp) 26178346Sbenno{ 26278346Sbenno int chosen; 26378346Sbenno 26478346Sbenno if ((chosen = OF_finddevice("/chosen")) == -1) { 26578346Sbenno cp->cn_pri = CN_DEAD; 26678346Sbenno return; 26778346Sbenno } 26878346Sbenno 26978346Sbenno if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) == -1) { 27078346Sbenno cp->cn_pri = CN_DEAD; 27178346Sbenno return; 27278346Sbenno } 27378346Sbenno 27478346Sbenno if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1) { 27578346Sbenno cp->cn_pri = CN_DEAD; 27678346Sbenno return; 27778346Sbenno } 27878346Sbenno 27978346Sbenno cp->cn_pri = CN_INTERNAL; 28078346Sbenno} 28178346Sbenno 28278346Sbennostatic void 28378346Sbennoofw_cons_init(struct consdev *cp) 28478346Sbenno{ 28578346Sbenno 286120467Sphk /* XXX: This is the alias, but that should be good enough */ 287120467Sphk sprintf(cp->cn_name, "ofwcons"); 288107044Sjake cp->cn_tp = ofw_tp; 28978346Sbenno} 29078346Sbenno 29178346Sbennostatic int 292111194Sphkofw_cons_getc(struct consdev *cp) 29378346Sbenno{ 29478346Sbenno unsigned char ch; 29578346Sbenno int l; 29678346Sbenno 29778346Sbenno ch = '\0'; 29878346Sbenno 29978346Sbenno while ((l = OF_read(stdin, &ch, 1)) != 1) { 30078346Sbenno if (l != -2 && l != 0) { 30178346Sbenno return (-1); 30278346Sbenno } 30378346Sbenno } 30478346Sbenno 305110509Sharti#if defined(DDB) && defined(ALT_BREAK_TO_DEBUGGER) 306110509Sharti if (db_alt_break(ch, &alt_break_state)) 307110509Sharti breakpoint(); 308110509Sharti#endif 309110509Sharti 31078346Sbenno return (ch); 31178346Sbenno} 31278346Sbenno 31378346Sbennostatic int 314111194Sphkofw_cons_checkc(struct consdev *cp) 31578346Sbenno{ 31678346Sbenno unsigned char ch; 31778346Sbenno 31888792Sjake if (OF_read(stdin, &ch, 1) > 0) { 319110509Sharti#if defined(DDB) && defined(ALT_BREAK_TO_DEBUGGER) 320110509Sharti if (db_alt_break(ch, &alt_break_state)) 321110509Sharti breakpoint(); 322110509Sharti#endif 32378346Sbenno return (ch); 32478346Sbenno } 32578346Sbenno 32678346Sbenno return (-1); 32778346Sbenno} 32878346Sbenno 32978346Sbennostatic void 330111194Sphkofw_cons_putc(struct consdev *cp, int c) 33178346Sbenno{ 33278346Sbenno char cbuf; 33378346Sbenno 33478346Sbenno if (c == '\n') { 33578346Sbenno cbuf = '\r'; 33678346Sbenno OF_write(stdout, &cbuf, 1); 33778346Sbenno } 33878346Sbenno 33978346Sbenno cbuf = c; 34078346Sbenno OF_write(stdout, &cbuf, 1); 34178346Sbenno} 342