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 <sys/param.h> 31ae36cccdSWarner Losh #include <sys/kdb.h> 32ae36cccdSWarner Losh #include <sys/kernel.h> 33ae36cccdSWarner Losh #include <sys/priv.h> 34ae36cccdSWarner Losh #include <sys/systm.h> 35ae36cccdSWarner Losh #include <sys/types.h> 36ae36cccdSWarner Losh #include <sys/conf.h> 37ae36cccdSWarner Losh #include <sys/cons.h> 38ae36cccdSWarner Losh #include <sys/consio.h> 39ae36cccdSWarner Losh #include <sys/tty.h> 40ae36cccdSWarner Losh 41ae36cccdSWarner Losh #include <dev/cfe/cfe_api.h> 42ae36cccdSWarner Losh #include <dev/cfe/cfe_error.h> 43ae36cccdSWarner Losh 44ae36cccdSWarner Losh #include <ddb/ddb.h> 45ae36cccdSWarner Losh 46ae36cccdSWarner Losh #ifndef CFECONS_POLL_HZ 478e8ee9aaSWarner Losh #define CFECONS_POLL_HZ 4 48ae36cccdSWarner Losh #endif 49ae36cccdSWarner Losh #define CFEBURSTLEN 128 /* max number of bytes to write in one chunk */ 50ae36cccdSWarner Losh 516f079ba1SWarner Losh static tsw_open_t cfe_tty_open; 526f079ba1SWarner Losh static tsw_close_t cfe_tty_close; 536f079ba1SWarner Losh static tsw_outwakeup_t cfe_tty_outwakeup; 54ae36cccdSWarner Losh 556f079ba1SWarner Losh static struct ttydevsw cfe_ttydevsw = { 566f079ba1SWarner Losh .tsw_flags = TF_NOPREFIX, 576f079ba1SWarner Losh .tsw_open = cfe_tty_open, 586f079ba1SWarner Losh .tsw_close = cfe_tty_close, 596f079ba1SWarner Losh .tsw_outwakeup = cfe_tty_outwakeup, 60ae36cccdSWarner Losh }; 61ae36cccdSWarner Losh 62ae36cccdSWarner Losh static int conhandle = -1; 63ae36cccdSWarner Losh /* XXX does cfe have to poll? */ 64ae36cccdSWarner Losh static int polltime; 65*f1f7034dSJohn Baldwin static struct callout cfe_timer; 66ae36cccdSWarner Losh 674cf75455SRobert Watson #if defined(KDB) 68ae36cccdSWarner Losh static int alt_break_state; 69ae36cccdSWarner Losh #endif 70ae36cccdSWarner Losh 71ae36cccdSWarner Losh static void cfe_timeout(void *); 72ae36cccdSWarner Losh 73ae36cccdSWarner Losh static cn_probe_t cfe_cnprobe; 74ae36cccdSWarner Losh static cn_init_t cfe_cninit; 75ae36cccdSWarner Losh static cn_term_t cfe_cnterm; 76ae36cccdSWarner Losh static cn_getc_t cfe_cngetc; 77ae36cccdSWarner Losh static cn_putc_t cfe_cnputc; 789976156fSAndriy Gapon static cn_grab_t cfe_cngrab; 799976156fSAndriy Gapon static cn_ungrab_t cfe_cnungrab; 80ae36cccdSWarner Losh 81ae36cccdSWarner Losh CONSOLE_DRIVER(cfe); 82ae36cccdSWarner Losh 83ae36cccdSWarner Losh static void 84ae36cccdSWarner Losh cn_drvinit(void *unused) 85ae36cccdSWarner Losh { 866f079ba1SWarner Losh struct tty *tp; 87ae36cccdSWarner Losh 88ae36cccdSWarner Losh if (cfe_consdev.cn_pri != CN_DEAD && 89ae36cccdSWarner Losh cfe_consdev.cn_name[0] != '\0') { 90c5e30cc0SEd Schouten tp = tty_alloc(&cfe_ttydevsw, NULL); 91*f1f7034dSJohn Baldwin callout_init_mtx(&cfe_timer, tty_getlock(tp), 0); 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; 102*f1f7034dSJohn Baldwin callout_reset(&cfe_timer, polltime, cfe_timeout, tp); 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 111*f1f7034dSJohn Baldwin callout_stop(&cfe_timer); 112ae36cccdSWarner Losh } 113ae36cccdSWarner Losh 114ae36cccdSWarner Losh static void 1156f079ba1SWarner Losh cfe_tty_outwakeup(struct tty *tp) 116ae36cccdSWarner Losh { 11761f7c762SNeel Natu int len, written, rc; 118ae36cccdSWarner Losh u_char buf[CFEBURSTLEN]; 119ae36cccdSWarner Losh 1206f079ba1SWarner Losh for (;;) { 1216f079ba1SWarner Losh len = ttydisc_getc(tp, buf, sizeof buf); 1226f079ba1SWarner Losh if (len == 0) 1236f079ba1SWarner Losh break; 12461f7c762SNeel Natu 12561f7c762SNeel Natu written = 0; 12661f7c762SNeel Natu while (written < len) { 12761f7c762SNeel Natu rc = cfe_write(conhandle, &buf[written], len - written); 12861f7c762SNeel Natu if (rc < 0) 12961f7c762SNeel Natu break; 13061f7c762SNeel Natu written += rc; 13161f7c762SNeel Natu } 132ae36cccdSWarner Losh } 133ae36cccdSWarner Losh } 134ae36cccdSWarner Losh 135ae36cccdSWarner Losh static void 136ae36cccdSWarner Losh cfe_timeout(void *v) 137ae36cccdSWarner Losh { 138ae36cccdSWarner Losh struct tty *tp; 139ae36cccdSWarner Losh int c; 140ae36cccdSWarner Losh 141ae36cccdSWarner Losh tp = (struct tty *)v; 142ae36cccdSWarner Losh 143*f1f7034dSJohn Baldwin tty_lock_assert(tp, MA_OWNED); 1446f079ba1SWarner Losh while ((c = cfe_cngetc(NULL)) != -1) 1456f079ba1SWarner Losh ttydisc_rint(tp, c, 0); 1466f079ba1SWarner Losh ttydisc_rint_done(tp); 147ae36cccdSWarner Losh 148*f1f7034dSJohn Baldwin callout_reset(&cfe_timer, polltime, cfe_timeout, tp); 149ae36cccdSWarner Losh } 150ae36cccdSWarner Losh 151ae36cccdSWarner Losh static void 152ae36cccdSWarner Losh cfe_cnprobe(struct consdev *cp) 153ae36cccdSWarner Losh { 154ae36cccdSWarner Losh 155ae36cccdSWarner Losh conhandle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE); 156ae36cccdSWarner Losh if (conhandle < 0) { 157ae36cccdSWarner Losh cp->cn_pri = CN_DEAD; 158ae36cccdSWarner Losh return; 159ae36cccdSWarner Losh } 160ae36cccdSWarner Losh 161ae36cccdSWarner Losh /* XXX */ 162ae36cccdSWarner Losh if (bootverbose) { 163ae36cccdSWarner Losh char *bootmsg = "Using CFE firmware console.\n"; 164ae36cccdSWarner Losh int i; 165ae36cccdSWarner Losh 166ae36cccdSWarner Losh for (i = 0; i < strlen(bootmsg); i++) 167ae36cccdSWarner Losh cfe_cnputc(cp, bootmsg[i]); 168ae36cccdSWarner Losh } 169ae36cccdSWarner Losh 170ae36cccdSWarner Losh cp->cn_pri = CN_LOW; 171ae36cccdSWarner Losh } 172ae36cccdSWarner Losh 173ae36cccdSWarner Losh static void 174ae36cccdSWarner Losh cfe_cninit(struct consdev *cp) 175ae36cccdSWarner Losh { 176ae36cccdSWarner Losh 177c8978106SEd Schouten strcpy(cp->cn_name, "cfecons"); 178ae36cccdSWarner Losh } 179ae36cccdSWarner Losh 180ae36cccdSWarner Losh static void 181ae36cccdSWarner Losh cfe_cnterm(struct consdev *cp) 182ae36cccdSWarner Losh { 183ae36cccdSWarner Losh 184ae36cccdSWarner Losh } 185ae36cccdSWarner Losh 1869976156fSAndriy Gapon static void 1879976156fSAndriy Gapon cfe_cngrab(struct consdev *cp) 1889976156fSAndriy Gapon { 1899976156fSAndriy Gapon 1909976156fSAndriy Gapon } 1919976156fSAndriy Gapon 1929976156fSAndriy Gapon static void 1939976156fSAndriy Gapon cfe_cnungrab(struct consdev *cp) 1949976156fSAndriy Gapon { 1959976156fSAndriy Gapon 1969976156fSAndriy Gapon } 1979976156fSAndriy Gapon 198ae36cccdSWarner Losh static int 199ae36cccdSWarner Losh cfe_cngetc(struct consdev *cp) 200ae36cccdSWarner Losh { 201ae36cccdSWarner Losh unsigned char ch; 202ae36cccdSWarner Losh 20361f7c762SNeel Natu if (cfe_read(conhandle, &ch, 1) == 1) { 2044cf75455SRobert Watson #if defined(KDB) 2054cf75455SRobert Watson kdb_alt_break(ch, &alt_break_state); 206ae36cccdSWarner Losh #endif 207ae36cccdSWarner Losh return (ch); 208ae36cccdSWarner Losh } 209ae36cccdSWarner Losh 210ae36cccdSWarner Losh return (-1); 211ae36cccdSWarner Losh } 212ae36cccdSWarner Losh 213ae36cccdSWarner Losh static void 214ae36cccdSWarner Losh cfe_cnputc(struct consdev *cp, int c) 215ae36cccdSWarner Losh { 216ae36cccdSWarner Losh char cbuf; 217ae36cccdSWarner Losh 218ae36cccdSWarner Losh if (c == '\n') 219ae36cccdSWarner Losh cfe_cnputc(cp, '\r'); 220ae36cccdSWarner Losh 221ae36cccdSWarner Losh cbuf = c; 222ae36cccdSWarner Losh while (cfe_write(conhandle, &cbuf, 1) == 0) 223750595efSWarner Losh continue; 224ae36cccdSWarner Losh } 225ae36cccdSWarner Losh 2266f079ba1SWarner Losh SYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL); 227