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/11.0/sys/dev/ofw/ofw_console.c 270975 2014-09-02 18:57:19Z jhb $"); 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; 63270975Sjhbstatic struct callout ofw_timer; 6478346Sbenno 65225203Srwatson#if defined(KDB) 66110509Shartistatic int alt_break_state; 67110509Sharti#endif 68110509Sharti 6978346Sbennostatic void ofw_timeout(void *); 7078346Sbenno 71158964Sphkstatic cn_probe_t ofw_cnprobe; 72158964Sphkstatic cn_init_t ofw_cninit; 73158964Sphkstatic cn_term_t ofw_cnterm; 74158964Sphkstatic cn_getc_t ofw_cngetc; 75158964Sphkstatic cn_putc_t ofw_cnputc; 76228631Savgstatic cn_grab_t ofw_cngrab; 77228631Savgstatic cn_ungrab_t ofw_cnungrab; 7878346Sbenno 79159065SphkCONSOLE_DRIVER(ofw); 8078346Sbenno 8189115Sjakestatic void 8289115Sjakecn_drvinit(void *unused) 8389115Sjake{ 84107044Sjake phandle_t options; 85107044Sjake char output[32]; 86181905Sed struct tty *tp; 8789115Sjake 88120544Sjake if (ofw_consdev.cn_pri != CN_DEAD && 89120544Sjake ofw_consdev.cn_name[0] != '\0') { 90255424Snwhitehorn tp = tty_alloc(&ofw_ttydevsw, NULL); 91255424Snwhitehorn tty_makedev(tp, NULL, "%s", "ofwcons"); 92255424Snwhitehorn 93255424Snwhitehorn /* 94255424Snwhitehorn * XXX: This is a hack and it may result in two /dev/ttya 95255424Snwhitehorn * XXX: devices on platforms where the sab driver works. 96255424Snwhitehorn */ 97107044Sjake if ((options = OF_finddevice("/options")) == -1 || 98107044Sjake OF_getprop(options, "output-device", output, 99107044Sjake sizeof(output)) == -1) 100107044Sjake return; 101255424Snwhitehorn if (strlen(output) > 0) 102259398Snwhitehorn tty_makealias(tp, "%s", output); 103270975Sjhb callout_init_mtx(&ofw_timer, tty_getlock(tp), 0); 104107044Sjake } 10589115Sjake} 10689115Sjake 107177253SrwatsonSYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL); 10889115Sjake 109256966Snwhitehornstatic pcell_t stdin; 110256966Snwhitehornstatic 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 119270975Sjhb callout_reset(&ofw_timer, polltime, ofw_timeout, tp); 12078346Sbenno 121181905Sed return (0); 12278346Sbenno} 12378346Sbenno 124181905Sedstatic void 125181905Sedofwtty_close(struct tty *tp) 12678346Sbenno{ 12778346Sbenno 128270975Sjhb callout_stop(&ofw_timer); 12978346Sbenno} 13078346Sbenno 13178346Sbennostatic void 132181905Sedofwtty_outwakeup(struct tty *tp) 13378346Sbenno{ 134131016Sobrien int len; 135131016Sobrien u_char buf[OFBURSTLEN]; 13678346Sbenno 137181905Sed for (;;) { 138181905Sed len = ttydisc_getc(tp, buf, sizeof buf); 139181905Sed if (len == 0) 140181905Sed break; 141181905Sed OF_write(stdout, buf, len); 14278346Sbenno } 14378346Sbenno} 14478346Sbenno 14578346Sbennostatic void 14678346Sbennoofw_timeout(void *v) 14778346Sbenno{ 14878346Sbenno struct tty *tp; 14978346Sbenno int c; 15078346Sbenno 15178346Sbenno tp = (struct tty *)v; 15278346Sbenno 153270975Sjhb tty_lock_assert(tp, MA_OWNED); 154181905Sed while ((c = ofw_cngetc(NULL)) != -1) 155181905Sed ttydisc_rint(tp, c, 0); 156181905Sed ttydisc_rint_done(tp); 15778346Sbenno 158270975Sjhb callout_schedule(&ofw_timer, polltime); 15978346Sbenno} 16078346Sbenno 16178346Sbennostatic void 162159065Sphkofw_cnprobe(struct consdev *cp) 16378346Sbenno{ 16478346Sbenno int chosen; 16578346Sbenno 16678346Sbenno if ((chosen = OF_finddevice("/chosen")) == -1) { 16778346Sbenno cp->cn_pri = CN_DEAD; 16878346Sbenno return; 16978346Sbenno } 17078346Sbenno 171256966Snwhitehorn if (OF_getencprop(chosen, "stdin", &stdin, sizeof(stdin)) == -1) { 17278346Sbenno cp->cn_pri = CN_DEAD; 17378346Sbenno return; 17478346Sbenno } 17578346Sbenno 176256966Snwhitehorn if (OF_getencprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1) { 17778346Sbenno cp->cn_pri = CN_DEAD; 17878346Sbenno return; 17978346Sbenno } 18078346Sbenno 181120542Sjake cp->cn_pri = CN_LOW; 18278346Sbenno} 18378346Sbenno 18478346Sbennostatic void 185158964Sphkofw_cninit(struct consdev *cp) 18678346Sbenno{ 18778346Sbenno 188120467Sphk /* XXX: This is the alias, but that should be good enough */ 189184329Sed strcpy(cp->cn_name, "ofwcons"); 19078346Sbenno} 19178346Sbenno 192158964Sphkstatic void 193159065Sphkofw_cnterm(struct consdev *cp) 19478346Sbenno{ 19578346Sbenno} 19678346Sbenno 197228631Savgstatic void 198228631Savgofw_cngrab(struct consdev *cp) 199228631Savg{ 200228631Savg} 201228631Savg 202228631Savgstatic void 203228631Savgofw_cnungrab(struct consdev *cp) 204228631Savg{ 205228631Savg} 206228631Savg 20778346Sbennostatic int 208158964Sphkofw_cngetc(struct consdev *cp) 20978346Sbenno{ 21078346Sbenno unsigned char ch; 21178346Sbenno 21288792Sjake if (OF_read(stdin, &ch, 1) > 0) { 213225203Srwatson#if defined(KDB) 214225203Srwatson kdb_alt_break(ch, &alt_break_state); 215110509Sharti#endif 21678346Sbenno return (ch); 21778346Sbenno } 21878346Sbenno 21978346Sbenno return (-1); 22078346Sbenno} 22178346Sbenno 22278346Sbennostatic void 223158964Sphkofw_cnputc(struct consdev *cp, int c) 22478346Sbenno{ 22578346Sbenno char cbuf; 22678346Sbenno 22778346Sbenno if (c == '\n') { 22878346Sbenno cbuf = '\r'; 22978346Sbenno OF_write(stdout, &cbuf, 1); 23078346Sbenno } 23178346Sbenno 23278346Sbenno cbuf = c; 23378346Sbenno OF_write(stdout, &cbuf, 1); 23478346Sbenno} 235