Date: Wed, 21 Mar 2012 22:00:46 GMT From: Robert Watson <rwatson@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 208337 for review Message-ID: <201203212200.q2LM0kP5050061@skunkworks.freebsd.org>
index | next in thread | raw e-mail
http://p4web.freebsd.org/@@208337?ac=10 Change 208337 by rwatson@rwatson_svr_ctsrd_mipsbuild on 2012/03/21 21:59:50 Implement a rudimentary FreeBSD tty driver by polling the gxemul debug console; modeled on a similar driver for the Altera JTAG UART, and likely has the same bugs. Not yet well-exercised. Affected files ... .. //depot/projects/ctsrd/beribsd/src/sys/mips/beri/gxemul_cons.c#2 edit Differences ... ==== //depot/projects/ctsrd/beribsd/src/sys/mips/beri/gxemul_cons.c#2 (text+ko) ==== @@ -41,6 +41,26 @@ #include <ddb/ddb.h> +#define GC_LOCK_INIT() mtx_init(&gc_lock, "gc_lock", NULL, MTX_SPIN) + +#define GC_LOCK() do { \ + if (!kdb_active) \ + mtx_lock_spin(&gc_lock); \ +} while (0) + +#define GC_LOCK_ASSERT() do { \ + if (!kdb_active) \ + mtx_assert(&gc_lock, MA_OWNED); \ +} while (0) + +#define GC_UNLOCK() do { \ + if (!kdb_active) \ + mtx_unlock_spin(&gc_lock); \ +} while (0) + + +static struct mtx gc_lock; + /* * Low-level console driver functions. */ @@ -53,6 +73,24 @@ static cn_ungrab_t gxemul_cons_cnungrab; /* + * TTY-level fields. + */ +static tsw_outwakeup_t gxemul_cons_outwakeup; + +static struct ttydevsw gxemul_cons_ttydevsw = { + .tsw_flags = TF_NOPREFIX, + .tsw_outwakeup = gxemul_cons_outwakeup, +}; + +static struct callout gxemul_cons_callout; +static u_int gxemul_cons_polltime = 10; +#ifdef KDB +static int gxemul_cons_alt_break_state; +#endif + +static void gxemul_cons_timeout(void *); + +/* * I/O routines lifted from Deimos. * * XXXRW: Should be using FreeBSD's bus routines here. @@ -138,6 +176,8 @@ { uint32_t v; + GC_LOCK_ASSERT(); + if (buffer_valid) return (1); v = gxemul_cons_data_read(); @@ -153,6 +193,8 @@ gxemul_cons_write(char ch) { + GC_LOCK_ASSERT(); + while (!gxemul_cons_writable()); gxemul_cons_data_write(ch); } @@ -161,6 +203,8 @@ gxemul_cons_read(void) { + GC_LOCK_ASSERT(); + while (!gxemul_cons_readable()); buffer_valid = 0; return (buffer_data); @@ -181,6 +225,7 @@ gxemul_cons_cninit(struct consdev *cp) { + GC_LOCK_INIT(); } static void @@ -194,7 +239,9 @@ { int ret; + GC_LOCK(); ret = gxemul_cons_read(); + GC_UNLOCK(); return (ret); } @@ -202,7 +249,9 @@ gxemul_cons_cnputc(struct consdev *cp, int c) { + GC_LOCK(); gxemul_cons_write(c); + GC_UNLOCK(); } static void @@ -218,3 +267,67 @@ } CONSOLE_DRIVER(gxemul_cons); + +/* + * TTY-level functions for gxemul_cons. + */ +static void +gxemul_cons_ttyinit(void *unused) +{ + struct tty *tp; + + tp = tty_alloc(&gxemul_cons_ttydevsw, NULL); + tty_init_console(tp, 0); + tty_makedev(tp, NULL, "%s", "gcons"); + callout_init(&gxemul_cons_callout, CALLOUT_MPSAFE); + callout_reset(&gxemul_cons_callout, gxemul_cons_polltime, + gxemul_cons_timeout, tp); + +} +SYSINIT(gxemul_cons_ttyinit, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, + gxemul_cons_ttyinit, NULL); + +static void +gxemul_cons_outwakeup(struct tty *tp) +{ + int len; + u_char ch; + + /* + * XXXRW: Would be nice not to do blocking writes to the console here, + * rescheduling on our timer tick if work remains to be done.. + */ + for (;;) { +#ifdef KDB + kdb_alt_break(ch, &gxemul_cons_alt_break_state); +#endif + len = ttydisc_getc(tp, &ch, sizeof(ch)); + if (len == 0) + break; + GC_LOCK(); + gxemul_cons_write(ch); + GC_UNLOCK(); + } +} + +static void +gxemul_cons_timeout(void *v) +{ + struct tty *tp; + int c; + + tp = v; + tty_lock(tp); + GC_LOCK(); + while (gxemul_cons_readable()) { + c = gxemul_cons_read(); + GC_UNLOCK(); + ttydisc_rint(tp, c, 0); + GC_LOCK(); + } + GC_UNLOCK(); + ttydisc_rint_done(tp); + tty_unlock(tp); + callout_reset(&gxemul_cons_callout, gxemul_cons_polltime, + gxemul_cons_timeout, tp); +}home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203212200.q2LM0kP5050061>
