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