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: releng/11.0/sys/dev/cfe/cfe_console.c 266891 2014-05-30 15:46:10Z jhb $"); 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; 65266891Sjhbstatic struct callout cfe_timer; 66183370Simp 67225203Srwatson#if defined(KDB) 68183370Simpstatic int alt_break_state; 69183370Simp#endif 70183370Simp 71183370Simpstatic void cfe_timeout(void *); 72183370Simp 73183370Simpstatic cn_probe_t cfe_cnprobe; 74183370Simpstatic cn_init_t cfe_cninit; 75183370Simpstatic cn_term_t cfe_cnterm; 76183370Simpstatic cn_getc_t cfe_cngetc; 77183370Simpstatic cn_putc_t cfe_cnputc; 78228631Savgstatic cn_grab_t cfe_cngrab; 79228631Savgstatic cn_ungrab_t cfe_cnungrab; 80183370Simp 81183370SimpCONSOLE_DRIVER(cfe); 82183370Simp 83183370Simpstatic void 84183370Simpcn_drvinit(void *unused) 85183370Simp{ 86183376Simp struct tty *tp; 87183370Simp 88183370Simp if (cfe_consdev.cn_pri != CN_DEAD && 89183370Simp cfe_consdev.cn_name[0] != '\0') { 90193018Sed tp = tty_alloc(&cfe_ttydevsw, NULL); 91266891Sjhb callout_init_mtx(&cfe_timer, tty_getlock(tp), 0); 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; 102266891Sjhb callout_reset(&cfe_timer, polltime, cfe_timeout, tp); 103183370Simp 104183376Simp return (0); 105183370Simp} 106183370Simp 107183376Simpstatic void 108183376Simpcfe_tty_close(struct tty *tp) 109183370Simp{ 110183370Simp 111266891Sjhb callout_stop(&cfe_timer); 112183370Simp} 113183370Simp 114183370Simpstatic void 115183376Simpcfe_tty_outwakeup(struct tty *tp) 116183370Simp{ 117203001Sneel int len, written, rc; 118183370Simp u_char buf[CFEBURSTLEN]; 119183370Simp 120183376Simp for (;;) { 121183376Simp len = ttydisc_getc(tp, buf, sizeof buf); 122183376Simp if (len == 0) 123183376Simp break; 124203001Sneel 125203001Sneel written = 0; 126203001Sneel while (written < len) { 127203001Sneel rc = cfe_write(conhandle, &buf[written], len - written); 128203001Sneel if (rc < 0) 129203001Sneel break; 130203001Sneel written += rc; 131203001Sneel } 132183370Simp } 133183370Simp} 134183370Simp 135183370Simpstatic void 136183370Simpcfe_timeout(void *v) 137183370Simp{ 138183370Simp struct tty *tp; 139183370Simp int c; 140183370Simp 141183370Simp tp = (struct tty *)v; 142183370Simp 143266891Sjhb tty_lock_assert(tp, MA_OWNED); 144183376Simp while ((c = cfe_cngetc(NULL)) != -1) 145183376Simp ttydisc_rint(tp, c, 0); 146183376Simp ttydisc_rint_done(tp); 147183370Simp 148266891Sjhb callout_reset(&cfe_timer, polltime, cfe_timeout, tp); 149183370Simp} 150183370Simp 151183370Simpstatic void 152183370Simpcfe_cnprobe(struct consdev *cp) 153183370Simp{ 154183370Simp 155183370Simp conhandle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE); 156183370Simp if (conhandle < 0) { 157183370Simp cp->cn_pri = CN_DEAD; 158183370Simp return; 159183370Simp } 160183370Simp 161183370Simp /* XXX */ 162183370Simp if (bootverbose) { 163183370Simp char *bootmsg = "Using CFE firmware console.\n"; 164183370Simp int i; 165183370Simp 166183370Simp for (i = 0; i < strlen(bootmsg); i++) 167183370Simp cfe_cnputc(cp, bootmsg[i]); 168183370Simp } 169183370Simp 170183370Simp cp->cn_pri = CN_LOW; 171183370Simp} 172183370Simp 173183370Simpstatic void 174183370Simpcfe_cninit(struct consdev *cp) 175183370Simp{ 176183370Simp 177184329Sed strcpy(cp->cn_name, "cfecons"); 178183370Simp} 179183370Simp 180183370Simpstatic void 181183370Simpcfe_cnterm(struct consdev *cp) 182183370Simp{ 183183370Simp 184183370Simp} 185183370Simp 186228631Savgstatic void 187228631Savgcfe_cngrab(struct consdev *cp) 188228631Savg{ 189228631Savg 190228631Savg} 191228631Savg 192228631Savgstatic void 193228631Savgcfe_cnungrab(struct consdev *cp) 194228631Savg{ 195228631Savg 196228631Savg} 197228631Savg 198183370Simpstatic int 199183370Simpcfe_cngetc(struct consdev *cp) 200183370Simp{ 201183370Simp unsigned char ch; 202183370Simp 203203001Sneel if (cfe_read(conhandle, &ch, 1) == 1) { 204225203Srwatson#if defined(KDB) 205225203Srwatson kdb_alt_break(ch, &alt_break_state); 206183370Simp#endif 207183370Simp return (ch); 208183370Simp } 209183370Simp 210183370Simp return (-1); 211183370Simp} 212183370Simp 213183370Simpstatic void 214183370Simpcfe_cnputc(struct consdev *cp, int c) 215183370Simp{ 216183370Simp char cbuf; 217183370Simp 218183370Simp if (c == '\n') 219183370Simp cfe_cnputc(cp, '\r'); 220183370Simp 221183370Simp cbuf = c; 222183370Simp while (cfe_write(conhandle, &cbuf, 1) == 0) 223183424Simp continue; 224183370Simp} 225183370Simp 226183376SimpSYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL); 227