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 */ 72 struct rcons_softc { 73 struct resource *res[1]; 74 void *ihl[1]; 75 device_t dev; 76 }; 77 78 /* CN Console interface */ 79 80 static tsw_outwakeup_t riscvtty_outwakeup; 81 82 static struct ttydevsw riscv_ttydevsw = { 83 .tsw_flags = TF_NOPREFIX, 84 .tsw_outwakeup = riscvtty_outwakeup, 85 }; 86 87 static int polltime; 88 static struct callout riscv_callout; 89 static struct tty *tp = NULL; 90 91 #if defined(KDB) 92 static int alt_break_state; 93 #endif 94 95 static void riscv_timeout(void *); 96 97 static cn_probe_t riscv_cnprobe; 98 static cn_init_t riscv_cninit; 99 static cn_term_t riscv_cnterm; 100 static cn_getc_t riscv_cngetc; 101 static cn_putc_t riscv_cnputc; 102 static cn_grab_t riscv_cngrab; 103 static cn_ungrab_t riscv_cnungrab; 104 105 CONSOLE_DRIVER(riscv); 106 107 #define MAX_BURST_LEN 1 108 109 static void 110 riscv_putc(int c) 111 { 112 113 sbi_console_putchar(c); 114 } 115 116 #ifdef EARLY_PRINTF 117 early_putc_t *early_putc = riscv_putc; 118 #endif 119 120 static void 121 cn_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 137 SYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL); 138 139 static void 140 riscvtty_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 158 static void 159 riscv_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 172 static void 173 riscv_cnprobe(struct consdev *cp) 174 { 175 176 cp->cn_pri = CN_NORMAL; 177 } 178 179 static void 180 riscv_cninit(struct consdev *cp) 181 { 182 183 strcpy(cp->cn_name, "rcons"); 184 } 185 186 static void 187 riscv_cnterm(struct consdev *cp) 188 { 189 190 } 191 192 static void 193 riscv_cngrab(struct consdev *cp) 194 { 195 196 } 197 198 static void 199 riscv_cnungrab(struct consdev *cp) 200 { 201 202 } 203 204 static int 205 riscv_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 220 static void 221 riscv_cnputc(struct consdev *cp, int c) 222 { 223 224 riscv_putc(c); 225 } 226 227 /* Bus interface */ 228 229 static int 230 rcons_probe(device_t dev) 231 { 232 233 device_set_desc(dev, "RISC-V console"); 234 235 return (BUS_PROBE_DEFAULT); 236 } 237 238 static int 239 rcons_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 256 static device_method_t rcons_methods[] = { 257 DEVMETHOD(device_probe, rcons_probe), 258 DEVMETHOD(device_attach, rcons_attach), 259 260 DEVMETHOD_END 261 }; 262 263 static driver_t rcons_driver = { 264 "rcons", 265 rcons_methods, 266 sizeof(struct rcons_softc) 267 }; 268 269 DRIVER_MODULE(rcons, nexus, rcons_driver, 0, 0); 270