1ae36cccdSWarner Losh /*- 2ae36cccdSWarner Losh * Copyright (c) 2007 Bruce M. Simpson. 3ae36cccdSWarner Losh * All rights reserved. 4ae36cccdSWarner Losh * 5ae36cccdSWarner Losh * Redistribution and use in source and binary forms, with or without 6ae36cccdSWarner Losh * modification, are permitted provided that the following conditions 7ae36cccdSWarner Losh * are met: 8ae36cccdSWarner Losh * 1. Redistributions of source code must retain the above copyright 9ae36cccdSWarner Losh * notice, this list of conditions and the following disclaimer. 10ae36cccdSWarner Losh * 2. Redistributions in binary form must reproduce the above copyright 11ae36cccdSWarner Losh * notice, this list of conditions and the following disclaimer in the 12ae36cccdSWarner Losh * documentation and/or other materials provided with the distribution. 13ae36cccdSWarner Losh * 14ae36cccdSWarner Losh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15ae36cccdSWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16ae36cccdSWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17ae36cccdSWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18ae36cccdSWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19ae36cccdSWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20ae36cccdSWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21ae36cccdSWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22ae36cccdSWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23ae36cccdSWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24ae36cccdSWarner Losh * SUCH DAMAGE. 25ae36cccdSWarner Losh */ 26ae36cccdSWarner Losh 27ae36cccdSWarner Losh #include <sys/cdefs.h> 28ae36cccdSWarner Losh __FBSDID("$FreeBSD$"); 29ae36cccdSWarner Losh 30ae36cccdSWarner Losh #include "opt_comconsole.h" 31ae36cccdSWarner Losh 32ae36cccdSWarner Losh #include <sys/param.h> 33ae36cccdSWarner Losh #include <sys/kdb.h> 34ae36cccdSWarner Losh #include <sys/kernel.h> 35ae36cccdSWarner Losh #include <sys/priv.h> 36ae36cccdSWarner Losh #include <sys/systm.h> 37ae36cccdSWarner Losh #include <sys/types.h> 38ae36cccdSWarner Losh #include <sys/conf.h> 39ae36cccdSWarner Losh #include <sys/cons.h> 40ae36cccdSWarner Losh #include <sys/consio.h> 41ae36cccdSWarner Losh #include <sys/tty.h> 42ae36cccdSWarner Losh 43ae36cccdSWarner Losh #include <dev/cfe/cfe_api.h> 44ae36cccdSWarner Losh #include <dev/cfe/cfe_error.h> 45ae36cccdSWarner Losh 46ae36cccdSWarner Losh #include <ddb/ddb.h> 47ae36cccdSWarner Losh 48ae36cccdSWarner Losh #ifndef CFECONS_POLL_HZ 498e8ee9aaSWarner Losh #define CFECONS_POLL_HZ 4 50ae36cccdSWarner Losh #endif 51ae36cccdSWarner Losh #define CFEBURSTLEN 128 /* max number of bytes to write in one chunk */ 52ae36cccdSWarner Losh 536f079ba1SWarner Losh static tsw_open_t cfe_tty_open; 546f079ba1SWarner Losh static tsw_close_t cfe_tty_close; 556f079ba1SWarner Losh static tsw_outwakeup_t cfe_tty_outwakeup; 56ae36cccdSWarner Losh 576f079ba1SWarner Losh static struct ttydevsw cfe_ttydevsw = { 586f079ba1SWarner Losh .tsw_flags = TF_NOPREFIX, 596f079ba1SWarner Losh .tsw_open = cfe_tty_open, 606f079ba1SWarner Losh .tsw_close = cfe_tty_close, 616f079ba1SWarner Losh .tsw_outwakeup = cfe_tty_outwakeup, 62ae36cccdSWarner Losh }; 63ae36cccdSWarner Losh 64ae36cccdSWarner Losh static int conhandle = -1; 65ae36cccdSWarner Losh /* XXX does cfe have to poll? */ 66ae36cccdSWarner Losh static int polltime; 67ae36cccdSWarner Losh static struct callout_handle cfe_timeouthandle 68ae36cccdSWarner Losh = CALLOUT_HANDLE_INITIALIZER(&cfe_timeouthandle); 69ae36cccdSWarner Losh 70ae36cccdSWarner Losh #if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER) 71ae36cccdSWarner Losh static int alt_break_state; 72ae36cccdSWarner Losh #endif 73ae36cccdSWarner Losh 74ae36cccdSWarner Losh static void cfe_timeout(void *); 75ae36cccdSWarner Losh 76ae36cccdSWarner Losh static cn_probe_t cfe_cnprobe; 77ae36cccdSWarner Losh static cn_init_t cfe_cninit; 78ae36cccdSWarner Losh static cn_term_t cfe_cnterm; 79ae36cccdSWarner Losh static cn_getc_t cfe_cngetc; 80ae36cccdSWarner Losh static cn_putc_t cfe_cnputc; 81ae36cccdSWarner Losh 82ae36cccdSWarner Losh CONSOLE_DRIVER(cfe); 83ae36cccdSWarner Losh 84ae36cccdSWarner Losh static void 85ae36cccdSWarner Losh cn_drvinit(void *unused) 86ae36cccdSWarner Losh { 876f079ba1SWarner Losh struct tty *tp; 88ae36cccdSWarner Losh 89ae36cccdSWarner Losh if (cfe_consdev.cn_pri != CN_DEAD && 90ae36cccdSWarner Losh cfe_consdev.cn_name[0] != '\0') { 91c5e30cc0SEd Schouten tp = tty_alloc(&cfe_ttydevsw, NULL); 9261f7c762SNeel Natu tty_makedev(tp, NULL, "cfecons"); 93ae36cccdSWarner Losh } 94ae36cccdSWarner Losh } 95ae36cccdSWarner Losh 96ae36cccdSWarner Losh static int 976f079ba1SWarner Losh cfe_tty_open(struct tty *tp) 98ae36cccdSWarner Losh { 99ae36cccdSWarner Losh polltime = hz / CFECONS_POLL_HZ; 1006f079ba1SWarner Losh if (polltime < 1) 101ae36cccdSWarner Losh polltime = 1; 102ae36cccdSWarner Losh cfe_timeouthandle = timeout(cfe_timeout, tp, polltime); 1036f079ba1SWarner Losh 1046f079ba1SWarner Losh return (0); 105ae36cccdSWarner Losh } 106ae36cccdSWarner Losh 1076f079ba1SWarner Losh static void 1086f079ba1SWarner Losh cfe_tty_close(struct tty *tp) 109ae36cccdSWarner Losh { 110ae36cccdSWarner Losh 111ae36cccdSWarner Losh /* XXX Should be replaced with callout_stop(9) */ 112ae36cccdSWarner Losh untimeout(cfe_timeout, tp, cfe_timeouthandle); 113ae36cccdSWarner Losh } 114ae36cccdSWarner Losh 115ae36cccdSWarner Losh static void 1166f079ba1SWarner Losh cfe_tty_outwakeup(struct tty *tp) 117ae36cccdSWarner Losh { 11861f7c762SNeel Natu int len, written, rc; 119ae36cccdSWarner Losh u_char buf[CFEBURSTLEN]; 120ae36cccdSWarner Losh 1216f079ba1SWarner Losh for (;;) { 1226f079ba1SWarner Losh len = ttydisc_getc(tp, buf, sizeof buf); 1236f079ba1SWarner Losh if (len == 0) 1246f079ba1SWarner Losh break; 12561f7c762SNeel Natu 12661f7c762SNeel Natu written = 0; 12761f7c762SNeel Natu while (written < len) { 12861f7c762SNeel Natu rc = cfe_write(conhandle, &buf[written], len - written); 12961f7c762SNeel Natu if (rc < 0) 13061f7c762SNeel Natu break; 13161f7c762SNeel Natu written += rc; 13261f7c762SNeel Natu } 133ae36cccdSWarner Losh } 134ae36cccdSWarner Losh } 135ae36cccdSWarner Losh 136ae36cccdSWarner Losh static void 137ae36cccdSWarner Losh cfe_timeout(void *v) 138ae36cccdSWarner Losh { 139ae36cccdSWarner Losh struct tty *tp; 140ae36cccdSWarner Losh int c; 141ae36cccdSWarner Losh 142ae36cccdSWarner Losh tp = (struct tty *)v; 143ae36cccdSWarner Losh 1446f079ba1SWarner Losh tty_lock(tp); 1456f079ba1SWarner Losh while ((c = cfe_cngetc(NULL)) != -1) 1466f079ba1SWarner Losh ttydisc_rint(tp, c, 0); 1476f079ba1SWarner Losh ttydisc_rint_done(tp); 1486f079ba1SWarner Losh tty_unlock(tp); 149ae36cccdSWarner Losh 150ae36cccdSWarner Losh cfe_timeouthandle = timeout(cfe_timeout, tp, polltime); 151ae36cccdSWarner Losh } 152ae36cccdSWarner Losh 153ae36cccdSWarner Losh static void 154ae36cccdSWarner Losh cfe_cnprobe(struct consdev *cp) 155ae36cccdSWarner Losh { 156ae36cccdSWarner Losh 157ae36cccdSWarner Losh conhandle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE); 158ae36cccdSWarner Losh if (conhandle < 0) { 159ae36cccdSWarner Losh cp->cn_pri = CN_DEAD; 160ae36cccdSWarner Losh return; 161ae36cccdSWarner Losh } 162ae36cccdSWarner Losh 163ae36cccdSWarner Losh /* XXX */ 164ae36cccdSWarner Losh if (bootverbose) { 165ae36cccdSWarner Losh char *bootmsg = "Using CFE firmware console.\n"; 166ae36cccdSWarner Losh int i; 167ae36cccdSWarner Losh 168ae36cccdSWarner Losh for (i = 0; i < strlen(bootmsg); i++) 169ae36cccdSWarner Losh cfe_cnputc(cp, bootmsg[i]); 170ae36cccdSWarner Losh } 171ae36cccdSWarner Losh 172ae36cccdSWarner Losh cp->cn_pri = CN_LOW; 173ae36cccdSWarner Losh } 174ae36cccdSWarner Losh 175ae36cccdSWarner Losh static void 176ae36cccdSWarner Losh cfe_cninit(struct consdev *cp) 177ae36cccdSWarner Losh { 178ae36cccdSWarner Losh 179c8978106SEd Schouten strcpy(cp->cn_name, "cfecons"); 180ae36cccdSWarner Losh } 181ae36cccdSWarner Losh 182ae36cccdSWarner Losh static void 183ae36cccdSWarner Losh cfe_cnterm(struct consdev *cp) 184ae36cccdSWarner Losh { 185ae36cccdSWarner Losh 186ae36cccdSWarner Losh } 187ae36cccdSWarner Losh 188ae36cccdSWarner Losh static int 189ae36cccdSWarner Losh cfe_cngetc(struct consdev *cp) 190ae36cccdSWarner Losh { 191ae36cccdSWarner Losh unsigned char ch; 192ae36cccdSWarner Losh 19361f7c762SNeel Natu if (cfe_read(conhandle, &ch, 1) == 1) { 194ae36cccdSWarner Losh #if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER) 1956f079ba1SWarner Losh int kdb_brk; 1966f079ba1SWarner Losh 1976f079ba1SWarner Losh if ((kdb_brk = kdb_alt_break(ch, &alt_break_state)) != 0) { 1986f079ba1SWarner Losh switch (kdb_brk) { 1996f079ba1SWarner Losh case KDB_REQ_DEBUGGER: 2006f079ba1SWarner Losh kdb_enter(KDB_WHY_BREAK, 2016f079ba1SWarner Losh "Break sequence on console"); 2026f079ba1SWarner Losh break; 2036f079ba1SWarner Losh case KDB_REQ_PANIC: 2046f079ba1SWarner Losh kdb_panic("Panic sequence on console"); 2056f079ba1SWarner Losh break; 2066f079ba1SWarner Losh case KDB_REQ_REBOOT: 2076f079ba1SWarner Losh kdb_reboot(); 2086f079ba1SWarner Losh break; 2096f079ba1SWarner Losh 2106f079ba1SWarner Losh } 2116f079ba1SWarner Losh } 212ae36cccdSWarner Losh #endif 213ae36cccdSWarner Losh return (ch); 214ae36cccdSWarner Losh } 215ae36cccdSWarner Losh 216ae36cccdSWarner Losh return (-1); 217ae36cccdSWarner Losh } 218ae36cccdSWarner Losh 219ae36cccdSWarner Losh static void 220ae36cccdSWarner Losh cfe_cnputc(struct consdev *cp, int c) 221ae36cccdSWarner Losh { 222ae36cccdSWarner Losh char cbuf; 223ae36cccdSWarner Losh 224ae36cccdSWarner Losh if (c == '\n') 225ae36cccdSWarner Losh cfe_cnputc(cp, '\r'); 226ae36cccdSWarner Losh 227ae36cccdSWarner Losh cbuf = c; 228ae36cccdSWarner Losh while (cfe_write(conhandle, &cbuf, 1) == 0) 229750595efSWarner Losh continue; 230ae36cccdSWarner Losh } 231ae36cccdSWarner Losh 2326f079ba1SWarner Losh SYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL); 233