2 * Copyright (c) 2011-2012 Robert N. M. Watson
5 * This software was developed by SRI International and the University of
6 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7 * ("CTSRD"), as part of the DARPA CRASH research programme.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include <sys/param.h>
36 #include <sys/endian.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/reboot.h>
45 #include <machine/cpuregs.h>
47 #define GC_LOCK_INIT() mtx_init(&gc_lock, "gc_lock", NULL, MTX_SPIN)
49 #define GC_LOCK() do { \
51 mtx_lock_spin(&gc_lock); \
54 #define GC_LOCK_ASSERT() do { \
56 mtx_assert(&gc_lock, MA_OWNED); \
59 #define GC_UNLOCK() do { \
61 mtx_unlock_spin(&gc_lock); \
65 static struct mtx gc_lock;
68 * Low-level console driver functions.
70 static cn_probe_t gxemul_cons_cnprobe;
71 static cn_init_t gxemul_cons_cninit;
72 static cn_term_t gxemul_cons_cnterm;
73 static cn_getc_t gxemul_cons_cngetc;
74 static cn_putc_t gxemul_cons_cnputc;
75 static cn_grab_t gxemul_cons_cngrab;
76 static cn_ungrab_t gxemul_cons_cnungrab;
81 static tsw_outwakeup_t gxemul_cons_outwakeup;
83 static struct ttydevsw gxemul_cons_ttydevsw = {
84 .tsw_flags = TF_NOPREFIX,
85 .tsw_outwakeup = gxemul_cons_outwakeup,
88 static struct callout gxemul_cons_callout;
89 static u_int gxemul_cons_polltime = 10;
91 static int gxemul_cons_alt_break_state;
94 static void gxemul_cons_timeout(void *);
97 * I/O routines lifted from Deimos.
99 * XXXRW: Should be using FreeBSD's bus routines here, but they are not
100 * available until later in the boot.
103 static inline vm_offset_t
104 mips_phys_to_uncached(vm_paddr_t phys)
107 return (MIPS_PHYS_TO_DIRECT_UNCACHED(phys));
110 static inline uint8_t
111 mips_ioread_uint8(vm_offset_t vaddr)
115 __asm__ __volatile__ ("lbu %0, 0(%1)" : "=r" (v) : "r" (vaddr));
120 mips_iowrite_uint8(vm_offset_t vaddr, uint8_t v)
123 __asm__ __volatile__ ("sb %0, 0(%1)" : : "r" (v), "r" (vaddr));
127 * gxemul-specific constants.
129 #define GXEMUL_CONS_BASE 0x10000000 /* gxemul console device. */
132 * Routines for interacting with the gxemul test console. Programming details
133 * are a result of manually inspecting the source code for gxemul's
134 * dev_cons.cc and dev_cons.h.
136 * Offsets of I/O channels relative to the base.
138 #define GXEMUL_PUTGETCHAR_OFF 0x00000000
139 #define GXEMUL_CONS_HALT 0x00000010
142 * One-byte buffer as we can't check whether the console is readable without
143 * actually reading from it.
145 static char buffer_data;
146 static int buffer_valid;
149 * Low-level read and write routines.
151 static inline uint8_t
152 gxemul_cons_data_read(void)
155 return (mips_ioread_uint8(mips_phys_to_uncached(GXEMUL_CONS_BASE +
156 GXEMUL_PUTGETCHAR_OFF)));
160 gxemul_cons_data_write(uint8_t v)
163 mips_iowrite_uint8(mips_phys_to_uncached(GXEMUL_CONS_BASE +
164 GXEMUL_PUTGETCHAR_OFF), v);
168 gxemul_cons_writable(void)
175 gxemul_cons_readable(void)
183 v = gxemul_cons_data_read();
193 gxemul_cons_write(char ch)
198 while (!gxemul_cons_writable());
199 gxemul_cons_data_write(ch);
203 gxemul_cons_read(void)
208 while (!gxemul_cons_readable());
210 return (buffer_data);
214 * Implementation of a FreeBSD low-level, polled console driver.
217 gxemul_cons_cnprobe(struct consdev *cp)
220 sprintf(cp->cn_name, "ttyu0");
221 cp->cn_pri = (boothowto & RB_SERIAL) ? CN_REMOTE : CN_NORMAL;
225 gxemul_cons_cninit(struct consdev *cp)
232 gxemul_cons_cnterm(struct consdev *cp)
238 gxemul_cons_cngetc(struct consdev *cp)
243 ret = gxemul_cons_read();
249 gxemul_cons_cnputc(struct consdev *cp, int c)
253 gxemul_cons_write(c);
258 gxemul_cons_cngrab(struct consdev *cp)
264 gxemul_cons_cnungrab(struct consdev *cp)
269 CONSOLE_DRIVER(gxemul_cons);
272 * TTY-level functions for gxemul_cons.
275 gxemul_cons_ttyinit(void *unused)
279 tp = tty_alloc(&gxemul_cons_ttydevsw, NULL);
280 tty_init_console(tp, 0);
281 tty_makedev(tp, NULL, "%s", "ttyu0");
282 callout_init(&gxemul_cons_callout, 1);
283 callout_reset(&gxemul_cons_callout, gxemul_cons_polltime,
284 gxemul_cons_timeout, tp);
287 SYSINIT(gxemul_cons_ttyinit, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE,
288 gxemul_cons_ttyinit, NULL);
291 gxemul_cons_outwakeup(struct tty *tp)
297 * XXXRW: Would be nice not to do blocking writes to the console here,
298 * rescheduling on our timer tick if work remains to be done..
301 len = ttydisc_getc(tp, &ch, sizeof(ch));
305 gxemul_cons_write(ch);
311 gxemul_cons_timeout(void *v)
319 while (gxemul_cons_readable()) {
320 c = gxemul_cons_read();
323 kdb_alt_break(c, &gxemul_cons_alt_break_state);
325 ttydisc_rint(tp, c, 0);
329 ttydisc_rint_done(tp);
331 callout_reset(&gxemul_cons_callout, gxemul_cons_polltime,
332 gxemul_cons_timeout, tp);