1/*- 2 * Copyright (c) 2015-2017 Ruslan Bukin <br@bsdpad.com> 3 * All rights reserved. 4 * 5 * Portions of this software were developed by SRI International and the 6 * University of Cambridge Computer Laboratory under DARPA/AFRL contract 7 * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme. 8 * 9 * Portions of this software were developed by the University of Cambridge 10 * Computer Laboratory as part of the CTSRD Project, with support from the 11 * UK Higher Education Innovation Fund (HEIF). 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35#include <sys/cdefs.h> 36__FBSDID("$FreeBSD$"); 37 38#include <sys/param.h> 39#include <sys/kdb.h> 40#include <sys/kernel.h> 41#include <sys/priv.h> 42#include <sys/systm.h> 43#include <sys/types.h> 44#include <sys/conf.h> 45#include <sys/cons.h> 46#include <sys/consio.h> 47#include <sys/tty.h> 48#include <sys/bus.h> 49#include <sys/module.h> 50#include <sys/rman.h> 51 52#include <dev/ofw/openfirm.h> 53#include <ddb/ddb.h> 54 55#include <vm/vm.h> 56#include <vm/pmap.h> 57 58#include <dev/fdt/fdt_common.h> 59#include <dev/ofw/openfirm.h> 60#include <dev/ofw/ofw_bus.h> 61#include <dev/ofw/ofw_bus_subr.h> 62 63#include <machine/bus.h> 64#include <machine/cpu.h> 65#include <machine/intr.h> 66#include <machine/asm.h> 67#include <machine/trap.h> 68#include <machine/vmparam.h> 69#include <machine/sbi.h> 70 71/* bus softc */ 72struct rcons_softc { 73 struct resource *res[1]; 74 void *ihl[1]; 75 device_t dev; 76}; 77 78/* CN Console interface */ 79 80static tsw_outwakeup_t riscvtty_outwakeup; 81 82static struct ttydevsw riscv_ttydevsw = { 83 .tsw_flags = TF_NOPREFIX, 84 .tsw_outwakeup = riscvtty_outwakeup, 85}; 86 87static int polltime; 88static struct callout riscv_callout; 89static struct tty *tp = NULL; 90 91#if defined(KDB) 92static int alt_break_state; 93#endif 94 95static void riscv_timeout(void *); 96 97static cn_probe_t riscv_cnprobe; 98static cn_init_t riscv_cninit; 99static cn_term_t riscv_cnterm; 100static cn_getc_t riscv_cngetc; 101static cn_putc_t riscv_cnputc; 102static cn_grab_t riscv_cngrab; 103static cn_ungrab_t riscv_cnungrab; 104 105CONSOLE_DRIVER(riscv); 106 107#define MAX_BURST_LEN 1 108 109static void 110riscv_putc(int c) 111{ 112 113 sbi_console_putchar(c); 114} 115 116#ifdef EARLY_PRINTF 117early_putc_t *early_putc = riscv_putc; 118#endif 119 120static void 121cn_drvinit(void *unused) 122{ 123 124 if (riscv_consdev.cn_pri != CN_DEAD && 125 riscv_consdev.cn_name[0] != '\0') { 126 tp = tty_alloc(&riscv_ttydevsw, NULL); 127 tty_init_console(tp, 0); 128 tty_makedev(tp, NULL, "%s", "rcons"); 129 130 polltime = 1; 131 132 callout_init(&riscv_callout, 1); 133 callout_reset(&riscv_callout, polltime, riscv_timeout, NULL); 134 } 135} 136 137SYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL); 138 139static void 140riscvtty_outwakeup(struct tty *tp) 141{ 142 u_char buf[MAX_BURST_LEN]; 143 int len; 144 int i; 145 146 for (;;) { 147 len = ttydisc_getc(tp, buf, sizeof(buf)); 148 if (len == 0) 149 break; 150 151 KASSERT(len == 1, ("tty error")); 152 153 for (i = 0; i < len; i++) 154 riscv_putc(buf[i]); 155 } 156} 157 158static void 159riscv_timeout(void *v) 160{ 161 int c; 162 163 tty_lock(tp); 164 while ((c = riscv_cngetc(NULL)) != -1) 165 ttydisc_rint(tp, c, 0); 166 ttydisc_rint_done(tp); 167 tty_unlock(tp); 168 169 callout_reset(&riscv_callout, polltime, riscv_timeout, NULL); 170} 171 172static void 173riscv_cnprobe(struct consdev *cp) 174{ 175 176 cp->cn_pri = CN_NORMAL; 177} 178 179static void 180riscv_cninit(struct consdev *cp) 181{ 182 183 strcpy(cp->cn_name, "rcons"); 184} 185 186static void 187riscv_cnterm(struct consdev *cp) 188{ 189 190} 191 192static void 193riscv_cngrab(struct consdev *cp) 194{ 195 196} 197 198static void 199riscv_cnungrab(struct consdev *cp) 200{ 201 202} 203 204static int 205riscv_cngetc(struct consdev *cp) 206{ 207 int ch; 208 209 ch = sbi_console_getchar(); 210 if (ch > 0 && ch < 0xff) { 211#if defined(KDB) 212 kdb_alt_break(ch, &alt_break_state); 213#endif 214 return (ch); 215 } 216 217 return (-1); 218} 219 220static void 221riscv_cnputc(struct consdev *cp, int c) 222{ 223 224 riscv_putc(c); 225} 226 227/* Bus interface */ 228 229static int 230rcons_probe(device_t dev) 231{ 232 233 device_set_desc(dev, "RISC-V console"); 234 235 return (BUS_PROBE_DEFAULT); 236} 237 238static int 239rcons_attach(device_t dev) 240{ 241 struct rcons_softc *sc; 242 243 if (device_get_unit(dev) != 0) 244 return (ENXIO); 245 246 sc = device_get_softc(dev); 247 sc->dev = dev; 248 249 csr_set(sie, SIE_SSIE); 250 251 bus_generic_attach(sc->dev); 252 253 return (0); 254} 255 256static device_method_t rcons_methods[] = { 257 DEVMETHOD(device_probe, rcons_probe), 258 DEVMETHOD(device_attach, rcons_attach), 259 260 DEVMETHOD_END 261}; 262 263static driver_t rcons_driver = { 264 "rcons", 265 rcons_methods, 266 sizeof(struct rcons_softc) 267}; 268 269static devclass_t rcons_devclass; 270 271DRIVER_MODULE(rcons, nexus, rcons_driver, rcons_devclass, 0, 0); 272