PERFORCE change 208337 for review
Robert Watson
rwatson at FreeBSD.org
Wed Mar 21 22:00:47 UTC 2012
http://p4web.freebsd.org/@@208337?ac=10
Change 208337 by rwatson at 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);
+}
More information about the p4-projects
mailing list