cfe_console.c revision 228631
1183370Simp/*- 2183370Simp * Copyright (c) 2007 Bruce M. Simpson. 3183370Simp * All rights reserved. 4183370Simp * 5183370Simp * Redistribution and use in source and binary forms, with or without 6183370Simp * modification, are permitted provided that the following conditions 7183370Simp * are met: 8183370Simp * 1. Redistributions of source code must retain the above copyright 9183370Simp * notice, this list of conditions and the following disclaimer. 10183370Simp * 2. Redistributions in binary form must reproduce the above copyright 11183370Simp * notice, this list of conditions and the following disclaimer in the 12183370Simp * documentation and/or other materials provided with the distribution. 13183370Simp * 14183370Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15183370Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16183370Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17183370Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18183370Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19183370Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20183370Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21183370Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22183370Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23183370Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24183370Simp * SUCH DAMAGE. 25183370Simp */ 26183370Simp 27183370Simp#include <sys/cdefs.h> 28183370Simp__FBSDID("$FreeBSD: head/sys/dev/cfe/cfe_console.c 228631 2011-12-17 15:08:43Z avg $"); 29183370Simp 30183370Simp#include <sys/param.h> 31183370Simp#include <sys/kdb.h> 32183370Simp#include <sys/kernel.h> 33183370Simp#include <sys/priv.h> 34183370Simp#include <sys/systm.h> 35183370Simp#include <sys/types.h> 36183370Simp#include <sys/conf.h> 37183370Simp#include <sys/cons.h> 38183370Simp#include <sys/consio.h> 39183370Simp#include <sys/tty.h> 40183370Simp 41183370Simp#include <dev/cfe/cfe_api.h> 42183370Simp#include <dev/cfe/cfe_error.h> 43183370Simp 44183370Simp#include <ddb/ddb.h> 45183370Simp 46183370Simp#ifndef CFECONS_POLL_HZ 47183374Simp#define CFECONS_POLL_HZ 4 48183370Simp#endif 49183370Simp#define CFEBURSTLEN 128 /* max number of bytes to write in one chunk */ 50183370Simp 51183376Simpstatic tsw_open_t cfe_tty_open; 52183376Simpstatic tsw_close_t cfe_tty_close; 53183376Simpstatic tsw_outwakeup_t cfe_tty_outwakeup; 54183370Simp 55183376Simpstatic struct ttydevsw cfe_ttydevsw = { 56183376Simp .tsw_flags = TF_NOPREFIX, 57183376Simp .tsw_open = cfe_tty_open, 58183376Simp .tsw_close = cfe_tty_close, 59183376Simp .tsw_outwakeup = cfe_tty_outwakeup, 60183370Simp}; 61183370Simp 62183370Simpstatic int conhandle = -1; 63183370Simp/* XXX does cfe have to poll? */ 64183370Simpstatic int polltime; 65183370Simpstatic struct callout_handle cfe_timeouthandle 66183370Simp = CALLOUT_HANDLE_INITIALIZER(&cfe_timeouthandle); 67183370Simp 68225203Srwatson#if defined(KDB) 69183370Simpstatic int alt_break_state; 70183370Simp#endif 71183370Simp 72183370Simpstatic void cfe_timeout(void *); 73183370Simp 74183370Simpstatic cn_probe_t cfe_cnprobe; 75183370Simpstatic cn_init_t cfe_cninit; 76183370Simpstatic cn_term_t cfe_cnterm; 77183370Simpstatic cn_getc_t cfe_cngetc; 78183370Simpstatic cn_putc_t cfe_cnputc; 79228631Savgstatic cn_grab_t cfe_cngrab; 80228631Savgstatic cn_ungrab_t cfe_cnungrab; 81183370Simp 82183370SimpCONSOLE_DRIVER(cfe); 83183370Simp 84183370Simpstatic void 85183370Simpcn_drvinit(void *unused) 86183370Simp{ 87183376Simp struct tty *tp; 88183370Simp 89183370Simp if (cfe_consdev.cn_pri != CN_DEAD && 90183370Simp cfe_consdev.cn_name[0] != '\0') { 91193018Sed tp = tty_alloc(&cfe_ttydevsw, NULL); 92203001Sneel tty_makedev(tp, NULL, "cfecons"); 93183370Simp } 94183370Simp} 95183370Simp 96183370Simpstatic int 97183376Simpcfe_tty_open(struct tty *tp) 98183370Simp{ 99183376Simp polltime = hz / CFECONS_POLL_HZ; 100183376Simp if (polltime < 1) 101183376Simp polltime = 1; 102183376Simp cfe_timeouthandle = timeout(cfe_timeout, tp, polltime); 103183370Simp 104183376Simp return (0); 105183370Simp} 106183370Simp 107183376Simpstatic void 108183376Simpcfe_tty_close(struct tty *tp) 109183370Simp{ 110183370Simp 111183370Simp /* XXX Should be replaced with callout_stop(9) */ 112183370Simp untimeout(cfe_timeout, tp, cfe_timeouthandle); 113183370Simp} 114183370Simp 115183370Simpstatic void 116183376Simpcfe_tty_outwakeup(struct tty *tp) 117183370Simp{ 118203001Sneel int len, written, rc; 119183370Simp u_char buf[CFEBURSTLEN]; 120183370Simp 121183376Simp for (;;) { 122183376Simp len = ttydisc_getc(tp, buf, sizeof buf); 123183376Simp if (len == 0) 124183376Simp break; 125203001Sneel 126203001Sneel written = 0; 127203001Sneel while (written < len) { 128203001Sneel rc = cfe_write(conhandle, &buf[written], len - written); 129203001Sneel if (rc < 0) 130203001Sneel break; 131203001Sneel written += rc; 132203001Sneel } 133183370Simp } 134183370Simp} 135183370Simp 136183370Simpstatic void 137183370Simpcfe_timeout(void *v) 138183370Simp{ 139183370Simp struct tty *tp; 140183370Simp int c; 141183370Simp 142183370Simp tp = (struct tty *)v; 143183370Simp 144183376Simp tty_lock(tp); 145183376Simp while ((c = cfe_cngetc(NULL)) != -1) 146183376Simp ttydisc_rint(tp, c, 0); 147183376Simp ttydisc_rint_done(tp); 148183376Simp tty_unlock(tp); 149183370Simp 150183370Simp cfe_timeouthandle = timeout(cfe_timeout, tp, polltime); 151183370Simp} 152183370Simp 153183370Simpstatic void 154183370Simpcfe_cnprobe(struct consdev *cp) 155183370Simp{ 156183370Simp 157183370Simp conhandle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE); 158183370Simp if (conhandle < 0) { 159183370Simp cp->cn_pri = CN_DEAD; 160183370Simp return; 161183370Simp } 162183370Simp 163183370Simp /* XXX */ 164183370Simp if (bootverbose) { 165183370Simp char *bootmsg = "Using CFE firmware console.\n"; 166183370Simp int i; 167183370Simp 168183370Simp for (i = 0; i < strlen(bootmsg); i++) 169183370Simp cfe_cnputc(cp, bootmsg[i]); 170183370Simp } 171183370Simp 172183370Simp cp->cn_pri = CN_LOW; 173183370Simp} 174183370Simp 175183370Simpstatic void 176183370Simpcfe_cninit(struct consdev *cp) 177183370Simp{ 178183370Simp 179184329Sed strcpy(cp->cn_name, "cfecons"); 180183370Simp} 181183370Simp 182183370Simpstatic void 183183370Simpcfe_cnterm(struct consdev *cp) 184183370Simp{ 185183370Simp 186183370Simp} 187183370Simp 188228631Savgstatic void 189228631Savgcfe_cngrab(struct consdev *cp) 190228631Savg{ 191228631Savg 192228631Savg} 193228631Savg 194228631Savgstatic void 195228631Savgcfe_cnungrab(struct consdev *cp) 196228631Savg{ 197228631Savg 198228631Savg} 199228631Savg 200183370Simpstatic int 201183370Simpcfe_cngetc(struct consdev *cp) 202183370Simp{ 203183370Simp unsigned char ch; 204183370Simp 205203001Sneel if (cfe_read(conhandle, &ch, 1) == 1) { 206225203Srwatson#if defined(KDB) 207225203Srwatson kdb_alt_break(ch, &alt_break_state); 208183370Simp#endif 209183370Simp return (ch); 210183370Simp } 211183370Simp 212183370Simp return (-1); 213183370Simp} 214183370Simp 215183370Simpstatic void 216183370Simpcfe_cnputc(struct consdev *cp, int c) 217183370Simp{ 218183370Simp char cbuf; 219183370Simp 220183370Simp if (c == '\n') 221183370Simp cfe_cnputc(cp, '\r'); 222183370Simp 223183370Simp cbuf = c; 224183370Simp while (cfe_write(conhandle, &cbuf, 1) == 0) 225183424Simp continue; 226183370Simp} 227183370Simp 228183376SimpSYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL); 229