1098ca2bdSWarner Losh /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3718cf2ccSPedro F. Giffuni * 4707fed20SBenno Rice * Copyright (C) 2001 Benno Rice. 5707fed20SBenno Rice * All rights reserved. 6707fed20SBenno Rice * 7707fed20SBenno Rice * Redistribution and use in source and binary forms, with or without 8707fed20SBenno Rice * modification, are permitted provided that the following conditions 9707fed20SBenno Rice * are met: 10707fed20SBenno Rice * 1. Redistributions of source code must retain the above copyright 11707fed20SBenno Rice * notice, this list of conditions and the following disclaimer. 12707fed20SBenno Rice * 2. Redistributions in binary form must reproduce the above copyright 13707fed20SBenno Rice * notice, this list of conditions and the following disclaimer in the 14707fed20SBenno Rice * documentation and/or other materials provided with the distribution. 15707fed20SBenno Rice * 16707fed20SBenno Rice * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 17707fed20SBenno Rice * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18707fed20SBenno Rice * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19707fed20SBenno Rice * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20707fed20SBenno Rice * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21707fed20SBenno Rice * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22707fed20SBenno Rice * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23707fed20SBenno Rice * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24707fed20SBenno Rice * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25707fed20SBenno Rice * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26707fed20SBenno Rice */ 27707fed20SBenno Rice 288368cf8fSDavid E. O'Brien #include <sys/cdefs.h> 298368cf8fSDavid E. O'Brien __FBSDID("$FreeBSD$"); 30707fed20SBenno Rice 31a82b25f9SDavid E. O'Brien #include "opt_ofw.h" 32761f89f9SHartmut Brandt 33707fed20SBenno Rice #include <sys/param.h> 348cabb94fSMarcel Moolenaar #include <sys/kdb.h> 35707fed20SBenno Rice #include <sys/kernel.h> 3643593547SRobert Watson #include <sys/priv.h> 37707fed20SBenno Rice #include <sys/systm.h> 38707fed20SBenno Rice #include <sys/types.h> 39707fed20SBenno Rice #include <sys/conf.h> 40707fed20SBenno Rice #include <sys/cons.h> 41707fed20SBenno Rice #include <sys/consio.h> 42707fed20SBenno Rice #include <sys/tty.h> 43707fed20SBenno Rice 44707fed20SBenno Rice #include <dev/ofw/openfirm.h> 45707fed20SBenno Rice 46761f89f9SHartmut Brandt #include <ddb/ddb.h> 47761f89f9SHartmut Brandt 48a82b25f9SDavid E. O'Brien #ifndef OFWCONS_POLL_HZ 49a82b25f9SDavid E. O'Brien #define OFWCONS_POLL_HZ 4 /* 50-100 works best on Ultra2 */ 50a82b25f9SDavid E. O'Brien #endif 51a82b25f9SDavid E. O'Brien #define OFBURSTLEN 128 /* max number of bytes to write in one chunk */ 52707fed20SBenno Rice 53bc093719SEd Schouten static tsw_open_t ofwtty_open; 54bc093719SEd Schouten static tsw_close_t ofwtty_close; 55bc093719SEd Schouten static tsw_outwakeup_t ofwtty_outwakeup; 56707fed20SBenno Rice 57bc093719SEd Schouten static struct ttydevsw ofw_ttydevsw = { 58bc093719SEd Schouten .tsw_flags = TF_NOPREFIX, 59bc093719SEd Schouten .tsw_open = ofwtty_open, 60bc093719SEd Schouten .tsw_close = ofwtty_close, 61bc093719SEd Schouten .tsw_outwakeup = ofwtty_outwakeup, 62707fed20SBenno Rice }; 63707fed20SBenno Rice 64707fed20SBenno Rice static int polltime; 65a272a813SJohn Baldwin static struct callout ofw_timer; 66707fed20SBenno Rice 674cf75455SRobert Watson #if defined(KDB) 68761f89f9SHartmut Brandt static int alt_break_state; 69761f89f9SHartmut Brandt #endif 70761f89f9SHartmut Brandt 71707fed20SBenno Rice static void ofw_timeout(void *); 72707fed20SBenno Rice 7305c3592eSPoul-Henning Kamp static cn_probe_t ofw_cnprobe; 7405c3592eSPoul-Henning Kamp static cn_init_t ofw_cninit; 7505c3592eSPoul-Henning Kamp static cn_term_t ofw_cnterm; 7605c3592eSPoul-Henning Kamp static cn_getc_t ofw_cngetc; 7705c3592eSPoul-Henning Kamp static cn_putc_t ofw_cnputc; 789976156fSAndriy Gapon static cn_grab_t ofw_cngrab; 799976156fSAndriy Gapon static cn_ungrab_t ofw_cnungrab; 80707fed20SBenno Rice 8177dfeeadSPoul-Henning Kamp CONSOLE_DRIVER(ofw); 82707fed20SBenno Rice 8347a1c915SJake Burkholder static void 8447a1c915SJake Burkholder cn_drvinit(void *unused) 8547a1c915SJake Burkholder { 86a121cb6aSJake Burkholder phandle_t options; 87a121cb6aSJake Burkholder char output[32]; 88bc093719SEd Schouten struct tty *tp; 8947a1c915SJake Burkholder 90278667afSJake Burkholder if (ofw_consdev.cn_pri != CN_DEAD && 91278667afSJake Burkholder ofw_consdev.cn_name[0] != '\0') { 9222b256dfSNathan Whitehorn tp = tty_alloc(&ofw_ttydevsw, NULL); 9322b256dfSNathan Whitehorn tty_makedev(tp, NULL, "%s", "ofwcons"); 9422b256dfSNathan Whitehorn 95c5c5a2adSPoul-Henning Kamp /* 96c5c5a2adSPoul-Henning Kamp * XXX: This is a hack and it may result in two /dev/ttya 97c5c5a2adSPoul-Henning Kamp * XXX: devices on platforms where the sab driver works. 98c5c5a2adSPoul-Henning Kamp */ 9922b256dfSNathan Whitehorn if ((options = OF_finddevice("/options")) == -1 || 10022b256dfSNathan Whitehorn OF_getprop(options, "output-device", output, 10122b256dfSNathan Whitehorn sizeof(output)) == -1) 10222b256dfSNathan Whitehorn return; 10322b256dfSNathan Whitehorn if (strlen(output) > 0) 104e14376e4SNathan Whitehorn tty_makealias(tp, "%s", output); 105a272a813SJohn Baldwin callout_init_mtx(&ofw_timer, tty_getlock(tp), 0); 106a121cb6aSJake Burkholder } 10747a1c915SJake Burkholder } 10847a1c915SJake Burkholder 109237fdd78SRobert Watson SYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL); 11047a1c915SJake Burkholder 111d3a0a0f3SNathan Whitehorn static pcell_t stdin; 112d3a0a0f3SNathan Whitehorn static pcell_t stdout; 113707fed20SBenno Rice 114707fed20SBenno Rice static int 115bc093719SEd Schouten ofwtty_open(struct tty *tp) 116707fed20SBenno Rice { 117a82b25f9SDavid E. O'Brien polltime = hz / OFWCONS_POLL_HZ; 118bc093719SEd Schouten if (polltime < 1) 119707fed20SBenno Rice polltime = 1; 120707fed20SBenno Rice 121a272a813SJohn Baldwin callout_reset(&ofw_timer, polltime, ofw_timeout, tp); 122bc093719SEd Schouten 123bc093719SEd Schouten return (0); 124707fed20SBenno Rice } 125707fed20SBenno Rice 126bc093719SEd Schouten static void 127bc093719SEd Schouten ofwtty_close(struct tty *tp) 128707fed20SBenno Rice { 129707fed20SBenno Rice 130a272a813SJohn Baldwin callout_stop(&ofw_timer); 131707fed20SBenno Rice } 132707fed20SBenno Rice 133707fed20SBenno Rice static void 134bc093719SEd Schouten ofwtty_outwakeup(struct tty *tp) 135707fed20SBenno Rice { 136a82b25f9SDavid E. O'Brien int len; 137a82b25f9SDavid E. O'Brien u_char buf[OFBURSTLEN]; 138707fed20SBenno Rice 139bc093719SEd Schouten for (;;) { 140bc093719SEd Schouten len = ttydisc_getc(tp, buf, sizeof buf); 141bc093719SEd Schouten if (len == 0) 142bc093719SEd Schouten break; 143a82b25f9SDavid E. O'Brien OF_write(stdout, buf, len); 144707fed20SBenno Rice } 145707fed20SBenno Rice } 146707fed20SBenno Rice 147707fed20SBenno Rice static void 148707fed20SBenno Rice ofw_timeout(void *v) 149707fed20SBenno Rice { 150707fed20SBenno Rice struct tty *tp; 151707fed20SBenno Rice int c; 152707fed20SBenno Rice 153707fed20SBenno Rice tp = (struct tty *)v; 154707fed20SBenno Rice 15523d53268SKyle Evans tty_assert_locked(tp); 156bc093719SEd Schouten while ((c = ofw_cngetc(NULL)) != -1) 157bc093719SEd Schouten ttydisc_rint(tp, c, 0); 158bc093719SEd Schouten ttydisc_rint_done(tp); 159707fed20SBenno Rice 160a272a813SJohn Baldwin callout_schedule(&ofw_timer, polltime); 161707fed20SBenno Rice } 162707fed20SBenno Rice 163707fed20SBenno Rice static void 16477dfeeadSPoul-Henning Kamp ofw_cnprobe(struct consdev *cp) 165707fed20SBenno Rice { 166707fed20SBenno Rice int chosen; 167707fed20SBenno Rice 168707fed20SBenno Rice if ((chosen = OF_finddevice("/chosen")) == -1) { 169707fed20SBenno Rice cp->cn_pri = CN_DEAD; 170707fed20SBenno Rice return; 171707fed20SBenno Rice } 172707fed20SBenno Rice 173d3a0a0f3SNathan Whitehorn if (OF_getencprop(chosen, "stdin", &stdin, sizeof(stdin)) == -1) { 174707fed20SBenno Rice cp->cn_pri = CN_DEAD; 175707fed20SBenno Rice return; 176707fed20SBenno Rice } 177707fed20SBenno Rice 178d3a0a0f3SNathan Whitehorn if (OF_getencprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1) { 179707fed20SBenno Rice cp->cn_pri = CN_DEAD; 180707fed20SBenno Rice return; 181707fed20SBenno Rice } 182707fed20SBenno Rice 1835dbb0622SJake Burkholder cp->cn_pri = CN_LOW; 184707fed20SBenno Rice } 185707fed20SBenno Rice 186707fed20SBenno Rice static void 18705c3592eSPoul-Henning Kamp ofw_cninit(struct consdev *cp) 188707fed20SBenno Rice { 189707fed20SBenno Rice 1902f06c3e7SPoul-Henning Kamp /* XXX: This is the alias, but that should be good enough */ 191c8978106SEd Schouten strcpy(cp->cn_name, "ofwcons"); 192707fed20SBenno Rice } 193707fed20SBenno Rice 19405c3592eSPoul-Henning Kamp static void 19577dfeeadSPoul-Henning Kamp ofw_cnterm(struct consdev *cp) 196707fed20SBenno Rice { 197707fed20SBenno Rice } 198707fed20SBenno Rice 1999976156fSAndriy Gapon static void 2009976156fSAndriy Gapon ofw_cngrab(struct consdev *cp) 2019976156fSAndriy Gapon { 2029976156fSAndriy Gapon } 2039976156fSAndriy Gapon 2049976156fSAndriy Gapon static void 2059976156fSAndriy Gapon ofw_cnungrab(struct consdev *cp) 2069976156fSAndriy Gapon { 2079976156fSAndriy Gapon } 2089976156fSAndriy Gapon 209707fed20SBenno Rice static int 21005c3592eSPoul-Henning Kamp ofw_cngetc(struct consdev *cp) 211707fed20SBenno Rice { 212707fed20SBenno Rice unsigned char ch; 213707fed20SBenno Rice 214cbecdd57SJake Burkholder if (OF_read(stdin, &ch, 1) > 0) { 2154cf75455SRobert Watson #if defined(KDB) 2164cf75455SRobert Watson kdb_alt_break(ch, &alt_break_state); 217761f89f9SHartmut Brandt #endif 218707fed20SBenno Rice return (ch); 219707fed20SBenno Rice } 220707fed20SBenno Rice 221707fed20SBenno Rice return (-1); 222707fed20SBenno Rice } 223707fed20SBenno Rice 224707fed20SBenno Rice static void 22505c3592eSPoul-Henning Kamp ofw_cnputc(struct consdev *cp, int c) 226707fed20SBenno Rice { 227707fed20SBenno Rice char cbuf; 228707fed20SBenno Rice 229707fed20SBenno Rice if (c == '\n') { 230707fed20SBenno Rice cbuf = '\r'; 231707fed20SBenno Rice OF_write(stdout, &cbuf, 1); 232707fed20SBenno Rice } 233707fed20SBenno Rice 234707fed20SBenno Rice cbuf = c; 235707fed20SBenno Rice OF_write(stdout, &cbuf, 1); 236707fed20SBenno Rice } 237