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