1139749Simp/*- 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: releng/10.3/sys/dev/ofw/ofw_console.c 265967 2014-05-13 17:59:17Z ian $"); 2878346Sbenno 29131016Sobrien#include "opt_ofw.h" 30110509Sharti 3178346Sbenno#include <sys/param.h> 32131916Smarcel#include <sys/kdb.h> 3378346Sbenno#include <sys/kernel.h> 34164049Srwatson#include <sys/priv.h> 3578346Sbenno#include <sys/systm.h> 3678346Sbenno#include <sys/types.h> 3778346Sbenno#include <sys/conf.h> 3878346Sbenno#include <sys/cons.h> 3978346Sbenno#include <sys/consio.h> 4078346Sbenno#include <sys/tty.h> 4178346Sbenno 4278346Sbenno#include <dev/ofw/openfirm.h> 4378346Sbenno 44110509Sharti#include <ddb/ddb.h> 45110509Sharti 46131016Sobrien#ifndef OFWCONS_POLL_HZ 47131016Sobrien#define OFWCONS_POLL_HZ 4 /* 50-100 works best on Ultra2 */ 48131016Sobrien#endif 49131016Sobrien#define OFBURSTLEN 128 /* max number of bytes to write in one chunk */ 5078346Sbenno 51181905Sedstatic tsw_open_t ofwtty_open; 52181905Sedstatic tsw_close_t ofwtty_close; 53181905Sedstatic tsw_outwakeup_t ofwtty_outwakeup; 5478346Sbenno 55181905Sedstatic struct ttydevsw ofw_ttydevsw = { 56181905Sed .tsw_flags = TF_NOPREFIX, 57181905Sed .tsw_open = ofwtty_open, 58181905Sed .tsw_close = ofwtty_close, 59181905Sed .tsw_outwakeup = ofwtty_outwakeup, 6078346Sbenno}; 6178346Sbenno 6278346Sbennostatic int polltime; 6378346Sbennostatic struct callout_handle ofw_timeouthandle 6478346Sbenno = CALLOUT_HANDLE_INITIALIZER(&ofw_timeouthandle); 6578346Sbenno 66225203Srwatson#if defined(KDB) 67110509Shartistatic int alt_break_state; 68110509Sharti#endif 69110509Sharti 7078346Sbennostatic void ofw_timeout(void *); 7178346Sbenno 72158964Sphkstatic cn_probe_t ofw_cnprobe; 73158964Sphkstatic cn_init_t ofw_cninit; 74158964Sphkstatic cn_term_t ofw_cnterm; 75158964Sphkstatic cn_getc_t ofw_cngetc; 76158964Sphkstatic cn_putc_t ofw_cnputc; 77228631Savgstatic cn_grab_t ofw_cngrab; 78228631Savgstatic cn_ungrab_t ofw_cnungrab; 7978346Sbenno 80159065SphkCONSOLE_DRIVER(ofw); 8178346Sbenno 8289115Sjakestatic void 8389115Sjakecn_drvinit(void *unused) 8489115Sjake{ 85107044Sjake phandle_t options; 86107044Sjake char output[32]; 87181905Sed struct tty *tp; 8889115Sjake 89120544Sjake if (ofw_consdev.cn_pri != CN_DEAD && 90120544Sjake ofw_consdev.cn_name[0] != '\0') { 91255424Snwhitehorn tp = tty_alloc(&ofw_ttydevsw, NULL); 92255424Snwhitehorn tty_makedev(tp, NULL, "%s", "ofwcons"); 93255424Snwhitehorn 94255424Snwhitehorn /* 95255424Snwhitehorn * XXX: This is a hack and it may result in two /dev/ttya 96255424Snwhitehorn * XXX: devices on platforms where the sab driver works. 97255424Snwhitehorn */ 98107044Sjake if ((options = OF_finddevice("/options")) == -1 || 99107044Sjake OF_getprop(options, "output-device", output, 100107044Sjake sizeof(output)) == -1) 101107044Sjake return; 102255424Snwhitehorn if (strlen(output) > 0) 103255424Snwhitehorn tty_makealias(tp, output); 104107044Sjake } 10589115Sjake} 10689115Sjake 107177253SrwatsonSYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL); 10889115Sjake 109265967Sianstatic pcell_t stdin; 110265967Sianstatic pcell_t stdout; 11178346Sbenno 11278346Sbennostatic int 113181905Sedofwtty_open(struct tty *tp) 11478346Sbenno{ 115181905Sed polltime = hz / OFWCONS_POLL_HZ; 116181905Sed if (polltime < 1) 117181905Sed polltime = 1; 11878346Sbenno 119181905Sed ofw_timeouthandle = timeout(ofw_timeout, tp, polltime); 12078346Sbenno 121181905Sed return (0); 12278346Sbenno} 12378346Sbenno 124181905Sedstatic void 125181905Sedofwtty_close(struct tty *tp) 12678346Sbenno{ 12778346Sbenno 128131016Sobrien /* XXX Should be replaced with callout_stop(9) */ 129131016Sobrien untimeout(ofw_timeout, tp, ofw_timeouthandle); 13078346Sbenno} 13178346Sbenno 13278346Sbennostatic void 133181905Sedofwtty_outwakeup(struct tty *tp) 13478346Sbenno{ 135131016Sobrien int len; 136131016Sobrien u_char buf[OFBURSTLEN]; 13778346Sbenno 138181905Sed for (;;) { 139181905Sed len = ttydisc_getc(tp, buf, sizeof buf); 140181905Sed if (len == 0) 141181905Sed break; 142181905Sed OF_write(stdout, buf, len); 14378346Sbenno } 14478346Sbenno} 14578346Sbenno 14678346Sbennostatic void 14778346Sbennoofw_timeout(void *v) 14878346Sbenno{ 14978346Sbenno struct tty *tp; 15078346Sbenno int c; 15178346Sbenno 15278346Sbenno tp = (struct tty *)v; 15378346Sbenno 154181905Sed tty_lock(tp); 155181905Sed while ((c = ofw_cngetc(NULL)) != -1) 156181905Sed ttydisc_rint(tp, c, 0); 157181905Sed ttydisc_rint_done(tp); 158181905Sed tty_unlock(tp); 15978346Sbenno 16078346Sbenno ofw_timeouthandle = timeout(ofw_timeout, tp, polltime); 16178346Sbenno} 16278346Sbenno 16378346Sbennostatic void 164159065Sphkofw_cnprobe(struct consdev *cp) 16578346Sbenno{ 16678346Sbenno int chosen; 16778346Sbenno 16878346Sbenno if ((chosen = OF_finddevice("/chosen")) == -1) { 16978346Sbenno cp->cn_pri = CN_DEAD; 17078346Sbenno return; 17178346Sbenno } 17278346Sbenno 173265967Sian if (OF_getencprop(chosen, "stdin", &stdin, sizeof(stdin)) == -1) { 17478346Sbenno cp->cn_pri = CN_DEAD; 17578346Sbenno return; 17678346Sbenno } 17778346Sbenno 178265967Sian if (OF_getencprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1) { 17978346Sbenno cp->cn_pri = CN_DEAD; 18078346Sbenno return; 18178346Sbenno } 18278346Sbenno 183120542Sjake cp->cn_pri = CN_LOW; 18478346Sbenno} 18578346Sbenno 18678346Sbennostatic void 187158964Sphkofw_cninit(struct consdev *cp) 18878346Sbenno{ 18978346Sbenno 190120467Sphk /* XXX: This is the alias, but that should be good enough */ 191184329Sed strcpy(cp->cn_name, "ofwcons"); 19278346Sbenno} 19378346Sbenno 194158964Sphkstatic void 195159065Sphkofw_cnterm(struct consdev *cp) 19678346Sbenno{ 19778346Sbenno} 19878346Sbenno 199228631Savgstatic void 200228631Savgofw_cngrab(struct consdev *cp) 201228631Savg{ 202228631Savg} 203228631Savg 204228631Savgstatic void 205228631Savgofw_cnungrab(struct consdev *cp) 206228631Savg{ 207228631Savg} 208228631Savg 20978346Sbennostatic int 210158964Sphkofw_cngetc(struct consdev *cp) 21178346Sbenno{ 21278346Sbenno unsigned char ch; 21378346Sbenno 21488792Sjake if (OF_read(stdin, &ch, 1) > 0) { 215225203Srwatson#if defined(KDB) 216225203Srwatson kdb_alt_break(ch, &alt_break_state); 217110509Sharti#endif 21878346Sbenno return (ch); 21978346Sbenno } 22078346Sbenno 22178346Sbenno return (-1); 22278346Sbenno} 22378346Sbenno 22478346Sbennostatic void 225158964Sphkofw_cnputc(struct consdev *cp, int c) 22678346Sbenno{ 22778346Sbenno char cbuf; 22878346Sbenno 22978346Sbenno if (c == '\n') { 23078346Sbenno cbuf = '\r'; 23178346Sbenno OF_write(stdout, &cbuf, 1); 23278346Sbenno } 23378346Sbenno 23478346Sbenno cbuf = c; 23578346Sbenno OF_write(stdout, &cbuf, 1); 23678346Sbenno} 237