From owner-p4-projects@FreeBSD.ORG Tue Mar 6 00:43:03 2012 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 20D7A1065673; Tue, 6 Mar 2012 00:43:03 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D7B59106566B for ; Tue, 6 Mar 2012 00:43:02 +0000 (UTC) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id BF9458FC22 for ; Tue, 6 Mar 2012 00:43:02 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.4/8.14.4) with ESMTP id q260h2gp071554 for ; Tue, 6 Mar 2012 00:43:02 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id q260h2fJ071551 for perforce@freebsd.org; Tue, 6 Mar 2012 00:43:02 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Date: Tue, 6 Mar 2012 00:43:02 GMT Message-Id: <201203060043.q260h2fJ071551@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to bb+lists.freebsd.perforce@cyrus.watson.org using -f From: Robert Watson To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 207486 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 06 Mar 2012 00:43:03 -0000 http://p4web.freebsd.org/@@207486?ac=10 Change 207486 by rwatson@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 #include #include +#include #include #include +#include + +#include + +#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); +}