PERFORCE change 207486 for review

Robert Watson rwatson at FreeBSD.org
Tue Mar 6 00:43:03 UTC 2012


http://p4web.freebsd.org/@@207486?ac=10

Change 207486 by rwatson at rwatson_svr_ctsrd_mipsbuild on 2012/03/06 00:42:10

	Add mocked up high-level TTY driver support to the Altera JTAG
	UART driver for the FreeBSD/BERI port.  This is under-tested as
	I am currently running into a possible cache bug that prevents
	me from getting to the point where it might be used.  However,
	low-level console support appears still to be working fine.
	The driver uses polled input on a timer, as is the case for a
	number of low-level hypervisor and debugging consoles -- in the
	longer term, we want to make this interrupt-driven instead, and
	perhaps hook it up to the uart(4) framework.  However, the JTAG
	UART is .. minimalist .. making much of that framework's
	functionality moot.

Affected files ...

.. //depot/projects/ctsrd/beribsd/src/sys/mips/beri/altera_jtag_uart.c#3 edit

Differences ...

==== //depot/projects/ctsrd/beribsd/src/sys/mips/beri/altera_jtag_uart.c#3 (text+ko) ====

@@ -34,9 +34,36 @@
 #include <sys/param.h>
 #include <sys/cons.h>
 #include <sys/endian.h>
+#include <sys/kdb.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/tty.h>
+
+#include <ddb/ddb.h>
+
+#define	AJU_LOCK_INIT()		mtx_init(&aj_uart_lock, "aj_uart_lock",	\
+				    NULL, MTX_SPIN)
+
+#define	AJU_LOCK() do {							\
+	if (!kdb_active)						\
+		mtx_lock_spin(&aj_uart_lock);				\
+} while (0)
 
+#define	AJU_LOCK_ASSERT() do {						\
+	if (!kdb_active)						\
+		mtx_assert(&aj_uart_lock, MA_OWNED);			\
+} while (0)
+
+#define	AJU_UNLOCK() do {						\
+	if (!kdb_active)						\
+		mtx_unlock_spin(&aj_uart_lock);				\
+} while (0)
+
+static struct mtx	aj_uart_lock;
+
+/*
+ * Low-level console driver functions.
+ */
 static cn_probe_t	aj_uart_cnprobe;
 static cn_init_t	aj_uart_cninit;
 static cn_term_t	aj_uart_cnterm;
@@ -46,6 +73,24 @@
 static cn_ungrab_t	aj_uart_cnungrab;
 
 /*
+ * TTY-level fields.
+ */
+static tsw_outwakeup_t	aj_uart_outwakeup;
+
+static struct ttydevsw aj_uart_ttydevsw = {
+	.tsw_flags	= TF_NOPREFIX,
+	.tsw_outwakeup	= aj_uart_outwakeup,
+};
+
+static struct callout	aj_uart_callout;
+static u_int		aj_uart_polltime = 1;
+#ifdef KDB
+static int		aj_uart_alt_break_state;
+#endif
+
+static void		aj_uart_timeout(void *);
+
+/*
  * I/O routines lifted from Deimos.
  *
  * XXXRW: Should be using FreeBSD's bus routines here.
@@ -208,6 +253,8 @@
 {
 	uint32_t v;
 
+	AJU_LOCK_ASSERT();
+
 	if (buffer_valid)
 		return (1);
 	v = aj_uart_data_read();
@@ -223,6 +270,8 @@
 aj_uart_write(char ch)
 {
 
+	AJU_LOCK_ASSERT();
+
 	while (!aj_uart_writable());
 	aj_uart_data_write(ch);
 }
@@ -231,6 +280,8 @@
 aj_uart_read(void)
 {
 
+	AJU_LOCK_ASSERT();
+
 	while (!aj_uart_readable());
 	buffer_valid = 0;
 	return (buffer_data);
@@ -251,6 +302,7 @@
 aj_uart_cninit(struct consdev *cp)
 {
 
+	AJU_LOCK_INIT();
 }
 
 static void
@@ -262,15 +314,21 @@
 static int
 aj_uart_cngetc(struct consdev *cp)
 {
+	int ret;
 
-	return (aj_uart_read());
+	AJU_LOCK();
+	ret = aj_uart_read();
+	AJU_UNLOCK();
+	return (ret);
 }
 
 static void
 aj_uart_cnputc(struct consdev *cp, int c)
 {
 
+	AJU_LOCK();
 	aj_uart_write(c);
+	AJU_UNLOCK();
 }
 
 static void
@@ -286,3 +344,66 @@
 }
 
 CONSOLE_DRIVER(aj_uart);
+
+/*
+ * TTY-level functions for aj_uart.
+ */
+static void
+aj_uart_ttyinit(void *unused)
+{
+	struct tty *tp;
+
+	tp = tty_alloc(&aj_uart_ttydevsw, NULL);
+	tty_init_console(tp, 0);
+	tty_makedev(tp, NULL, "%s", "ajuart");
+	callout_init(&aj_uart_callout, CALLOUT_MPSAFE);
+	callout_reset(&aj_uart_callout, aj_uart_polltime, aj_uart_timeout,
+	    tp);
+}
+SYSINIT(aj_uart_ttyinit, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, aj_uart_ttyinit,
+    NULL);
+
+static void
+aj_uart_outwakeup(struct tty *tp)
+{
+	int len;
+	u_char ch;
+
+	/*
+	 * XXXRW: Would be nice not to do blocking writes to the UART here,
+	 * rescheduling on our timer tick if work remains to be done.
+	 */
+	for (;;) {
+#ifdef KDB
+		kdb_alt_break(ch, &aj_uart_alt_break_state);
+#endif
+		len = ttydisc_getc(tp, &ch, sizeof(ch));
+		if (len == 0)
+			break;
+		AJU_LOCK();
+		aj_uart_write(ch);
+		AJU_UNLOCK();
+	}
+}
+
+static void
+aj_uart_timeout(void *v)
+{
+	struct tty *tp;
+	int c;
+
+	tp = v;
+	tty_lock(tp);
+	AJU_LOCK();
+	while (aj_uart_readable()) {
+		c = aj_uart_read();
+		AJU_UNLOCK();
+		ttydisc_rint(tp, c, 0);
+		AJU_LOCK();
+	}
+	AJU_UNLOCK();
+	ttydisc_rint_done(tp);
+	tty_unlock(tp);
+	callout_reset(&aj_uart_callout, aj_uart_polltime, aj_uart_timeout,
+	    tp);
+}


More information about the p4-projects mailing list