cfe_console.c revision 203001
11590Srgrimes/*- 21590Srgrimes * Copyright (c) 2007 Bruce M. Simpson. 31590Srgrimes * All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 141590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241590Srgrimes * SUCH DAMAGE. 251590Srgrimes */ 261590Srgrimes 271590Srgrimes#include <sys/cdefs.h> 281590Srgrimes__FBSDID("$FreeBSD: head/sys/dev/cfe/cfe_console.c 203001 2010-01-26 03:42:34Z neel $"); 291590Srgrimes 301590Srgrimes#include "opt_comconsole.h" 311590Srgrimes 321590Srgrimes#include <sys/param.h> 331590Srgrimes#include <sys/kdb.h> 3474769Smikeh#include <sys/kernel.h> 3574769Smikeh#include <sys/priv.h> 361590Srgrimes#include <sys/systm.h> 371590Srgrimes#include <sys/types.h> 381590Srgrimes#include <sys/conf.h> 391590Srgrimes#include <sys/cons.h> 401590Srgrimes#include <sys/consio.h> 411590Srgrimes#include <sys/tty.h> 421590Srgrimes 431590Srgrimes#include <dev/cfe/cfe_api.h> 441590Srgrimes#include <dev/cfe/cfe_error.h> 451590Srgrimes 461590Srgrimes#include <ddb/ddb.h> 471590Srgrimes 481590Srgrimes#ifndef CFECONS_POLL_HZ 491590Srgrimes#define CFECONS_POLL_HZ 4 501590Srgrimes#endif 511590Srgrimes#define CFEBURSTLEN 128 /* max number of bytes to write in one chunk */ 521590Srgrimes 531590Srgrimesstatic tsw_open_t cfe_tty_open; 541590Srgrimesstatic tsw_close_t cfe_tty_close; 551590Srgrimesstatic tsw_outwakeup_t cfe_tty_outwakeup; 561590Srgrimes 571590Srgrimesstatic struct ttydevsw cfe_ttydevsw = { 581590Srgrimes .tsw_flags = TF_NOPREFIX, 591590Srgrimes .tsw_open = cfe_tty_open, 601590Srgrimes .tsw_close = cfe_tty_close, 611590Srgrimes .tsw_outwakeup = cfe_tty_outwakeup, 621590Srgrimes}; 631590Srgrimes 641590Srgrimesstatic int conhandle = -1; 651590Srgrimes/* XXX does cfe have to poll? */ 661590Srgrimesstatic int polltime; 671590Srgrimesstatic struct callout_handle cfe_timeouthandle 681590Srgrimes = CALLOUT_HANDLE_INITIALIZER(&cfe_timeouthandle); 691590Srgrimes 701590Srgrimes#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER) 711590Srgrimesstatic int alt_break_state; 721590Srgrimes#endif 731590Srgrimes 741590Srgrimesstatic void cfe_timeout(void *); 751590Srgrimes 761590Srgrimesstatic cn_probe_t cfe_cnprobe; 771590Srgrimesstatic cn_init_t cfe_cninit; 781590Srgrimesstatic cn_term_t cfe_cnterm; 791590Srgrimesstatic cn_getc_t cfe_cngetc; 801590Srgrimesstatic cn_putc_t cfe_cnputc; 8132189Sjoerg 8232189SjoergCONSOLE_DRIVER(cfe); 831590Srgrimes 841590Srgrimesstatic void 851590Srgrimescn_drvinit(void *unused) 861590Srgrimes{ 871590Srgrimes struct tty *tp; 881590Srgrimes 8974769Smikeh if (cfe_consdev.cn_pri != CN_DEAD && 901590Srgrimes cfe_consdev.cn_name[0] != '\0') { 911590Srgrimes tp = tty_alloc(&cfe_ttydevsw, NULL); 921590Srgrimes tty_makedev(tp, NULL, "cfecons"); 931590Srgrimes } 941590Srgrimes} 951590Srgrimes 961590Srgrimesstatic int 971590Srgrimescfe_tty_open(struct tty *tp) 981590Srgrimes{ 991590Srgrimes polltime = hz / CFECONS_POLL_HZ; 1001590Srgrimes if (polltime < 1) 1011590Srgrimes polltime = 1; 1021590Srgrimes cfe_timeouthandle = timeout(cfe_timeout, tp, polltime); 1031590Srgrimes 1041590Srgrimes return (0); 1051590Srgrimes} 1061590Srgrimes 1071590Srgrimesstatic void 1081590Srgrimescfe_tty_close(struct tty *tp) 1091590Srgrimes{ 1101590Srgrimes 1111590Srgrimes /* XXX Should be replaced with callout_stop(9) */ 1121590Srgrimes untimeout(cfe_timeout, tp, cfe_timeouthandle); 1131590Srgrimes} 1141590Srgrimes 1151590Srgrimesstatic void 1161590Srgrimescfe_tty_outwakeup(struct tty *tp) 1171590Srgrimes{ 1181590Srgrimes int len, written, rc; 1191590Srgrimes u_char buf[CFEBURSTLEN]; 1201590Srgrimes 1211590Srgrimes for (;;) { 1221590Srgrimes len = ttydisc_getc(tp, buf, sizeof buf); 12374769Smikeh if (len == 0) 1241590Srgrimes break; 1251590Srgrimes 1261590Srgrimes written = 0; 1271590Srgrimes while (written < len) { 12874769Smikeh rc = cfe_write(conhandle, &buf[written], len - written); 1291590Srgrimes if (rc < 0) 1301590Srgrimes break; 1311590Srgrimes written += rc; 13274769Smikeh } 1331590Srgrimes } 1341590Srgrimes} 1351590Srgrimes 1361590Srgrimesstatic void 1371590Srgrimescfe_timeout(void *v) 1381590Srgrimes{ 1391590Srgrimes struct tty *tp; 1401590Srgrimes int c; 1411590Srgrimes 1421590Srgrimes tp = (struct tty *)v; 1431590Srgrimes 1441590Srgrimes tty_lock(tp); 1451590Srgrimes while ((c = cfe_cngetc(NULL)) != -1) 1461590Srgrimes ttydisc_rint(tp, c, 0); 1471590Srgrimes ttydisc_rint_done(tp); 1481590Srgrimes tty_unlock(tp); 1491590Srgrimes 1501590Srgrimes cfe_timeouthandle = timeout(cfe_timeout, tp, polltime); 1511590Srgrimes} 1521590Srgrimes 1531590Srgrimesstatic void 1541590Srgrimescfe_cnprobe(struct consdev *cp) 1551590Srgrimes{ 1561590Srgrimes 15774769Smikeh conhandle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE); 1581590Srgrimes if (conhandle < 0) { 1591590Srgrimes cp->cn_pri = CN_DEAD; 1601590Srgrimes return; 1611590Srgrimes } 1621590Srgrimes 1631590Srgrimes /* XXX */ 16432189Sjoerg if (bootverbose) { 1651590Srgrimes char *bootmsg = "Using CFE firmware console.\n"; 1661590Srgrimes int i; 1671590Srgrimes 1681590Srgrimes for (i = 0; i < strlen(bootmsg); i++) 1691590Srgrimes cfe_cnputc(cp, bootmsg[i]); 1701590Srgrimes } 1711590Srgrimes 1721590Srgrimes cp->cn_pri = CN_LOW; 1731590Srgrimes} 1741590Srgrimes 1751590Srgrimesstatic void 1761590Srgrimescfe_cninit(struct consdev *cp) 1771590Srgrimes{ 1781590Srgrimes 1791590Srgrimes strcpy(cp->cn_name, "cfecons"); 1801590Srgrimes} 1811590Srgrimes 1821590Srgrimesstatic void 1831590Srgrimescfe_cnterm(struct consdev *cp) 1841590Srgrimes{ 1851590Srgrimes 1861590Srgrimes} 1871590Srgrimes 1881590Srgrimesstatic int 1891590Srgrimescfe_cngetc(struct consdev *cp) 1901590Srgrimes{ 1911590Srgrimes unsigned char ch; 1921590Srgrimes 1931590Srgrimes if (cfe_read(conhandle, &ch, 1) == 1) { 1941590Srgrimes#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER) 1951590Srgrimes int kdb_brk; 1961590Srgrimes 1971590Srgrimes if ((kdb_brk = kdb_alt_break(ch, &alt_break_state)) != 0) { 1981590Srgrimes switch (kdb_brk) { 1991590Srgrimes case KDB_REQ_DEBUGGER: 2001590Srgrimes kdb_enter(KDB_WHY_BREAK, 2011590Srgrimes "Break sequence on console"); 2021590Srgrimes break; 2031590Srgrimes case KDB_REQ_PANIC: 2041590Srgrimes kdb_panic("Panic sequence on console"); 2051590Srgrimes break; 2061590Srgrimes case KDB_REQ_REBOOT: 2071590Srgrimes kdb_reboot(); 2081590Srgrimes break; 2091590Srgrimes 2101590Srgrimes } 2111590Srgrimes } 2121590Srgrimes#endif 2131590Srgrimes return (ch); 21474769Smikeh } 2151590Srgrimes 2161590Srgrimes return (-1); 2171590Srgrimes} 2181590Srgrimes 2191590Srgrimesstatic void 2201590Srgrimescfe_cnputc(struct consdev *cp, int c) 2211590Srgrimes{ 2221590Srgrimes char cbuf; 2231590Srgrimes 2241590Srgrimes if (c == '\n') 2251590Srgrimes cfe_cnputc(cp, '\r'); 2261590Srgrimes 2271590Srgrimes cbuf = c; 2281590Srgrimes while (cfe_write(conhandle, &cbuf, 1) == 0) 2291590Srgrimes continue; 2301590Srgrimes} 2311590Srgrimes 2321590SrgrimesSYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL); 2331590Srgrimes