svn commit: r261786 - in head/sys: arm/at91 kern sys

Ian Lepore ian at FreeBSD.org
Wed Feb 12 00:53:40 UTC 2014


Author: ian
Date: Wed Feb 12 00:53:38 2014
New Revision: 261786
URL: http://svnweb.freebsd.org/changeset/base/261786

Log:
  Rework the EARLY_PRINTF mechanism.  Instead of defining a special eprintf()
  routine, now a platform can provide a pointer to an early_putc() routine
  which is used instead of cn_putc().  Control can be handed off from early
  printf support to standard console support by NULLing out the pointer
  during standard console init.
  
  This leverages all the existing error reporting that uses printf calls,
  such as panic() which can now be usefully employed even in early
  platform init code (useful at least to those who maintain that code and
  build kernels with EARLY_PRINTF defined).
  
  Reviewed by:	imp, eadler

Modified:
  head/sys/arm/at91/uart_dev_at91usart.c
  head/sys/kern/kern_cons.c
  head/sys/kern/subr_prf.c
  head/sys/sys/systm.h

Modified: head/sys/arm/at91/uart_dev_at91usart.c
==============================================================================
--- head/sys/arm/at91/uart_dev_at91usart.c	Wed Feb 12 00:32:14 2014	(r261785)
+++ head/sys/arm/at91/uart_dev_at91usart.c	Wed Feb 12 00:53:38 2014	(r261786)
@@ -228,6 +228,27 @@ static struct uart_ops at91_usart_ops = 
 	.getc = at91_usart_getc,
 };
 
+#ifdef EARLY_PRINTF
+/*
+ * Early printf support. This assumes that we have the SoC "system" devices
+ * mapped into AT91_BASE. To use this before we adjust the boostrap tables,
+ * you'll need to define SOCDEV_VA to be 0xdc000000 and SOCDEV_PA to be
+ * 0xfc000000 in your config file where you define EARLY_PRINTF
+ */
+volatile uint32_t *at91_dbgu = (volatile uint32_t *)(AT91_BASE + AT91_DBGU0);
+
+static void
+eputc(int c)
+{
+
+	while (!(at91_dbgu[USART_CSR / 4] & USART_CSR_TXRDY))
+		continue;
+	at91_dbgu[USART_THR / 4] = c;
+}
+
+early_putc_t * early_putc = eputc;
+#endif
+
 static int
 at91_usart_probe(struct uart_bas *bas)
 {
@@ -244,6 +265,22 @@ at91_usart_init(struct uart_bas *bas, in
     int parity)
 {
 
+#ifdef EARLY_PRINTF
+	if (early_putc != NULL) {
+		printf("Early printf yielding control to the real console.\n");
+		early_putc = NULL;
+	}
+#endif
+
+	/*
+	 * This routine is called multiple times, sometimes right after writing
+	 * some output, and the last byte is still shifting out.  If that's the
+	 * case delay briefly before resetting, but don't loop on TXRDY because
+	 * we don't want to hang here forever if the hardware is in a bad state.
+	 */
+	if (!(RD4(bas, USART_CSR) & USART_CSR_TXRDY))
+	    DELAY(1000);
+
 	at91_usart_param(bas, baudrate, databits, stopbits, parity);
 
 	/* Reset the rx and tx buffers and turn on rx and tx */
@@ -276,28 +313,6 @@ at91_usart_putc(struct uart_bas *bas, in
 	WR4(bas, USART_THR, c);
 }
 
-#ifdef EARLY_PRINTF
-/*
- * Early printf support. This assumes that we have the SoC "system" devices
- * mapped into AT91_BASE. To use this before we adjust the boostrap tables,
- * You'll need to define SOCDEV_VA to be 0xdc000000 and SOCDEV_PA to be
- * 0xfc000000 in your config file where you define EARLY_PRINTF
- */
-volatile uint32_t *at91_dbgu = (volatile uint32_t *)(AT91_BASE + AT91_DBGU0);
-
-void
-eputc(int c)
-{
-
-	if (c == '\n')
-		eputc('\r');
-
-	while (!(at91_dbgu[USART_CSR / 4] & USART_CSR_TXRDY))
-		continue;
-	at91_dbgu[USART_THR / 4] = c;
-}
-#endif
-
 /*
  * Check for a character available.
  */

Modified: head/sys/kern/kern_cons.c
==============================================================================
--- head/sys/kern/kern_cons.c	Wed Feb 12 00:32:14 2014	(r261785)
+++ head/sys/kern/kern_cons.c	Wed Feb 12 00:53:38 2014	(r261786)
@@ -464,6 +464,15 @@ cnputc(int c)
 	struct consdev *cn;
 	char *cp;
 
+#ifdef EARLY_PRINTF
+	if (early_putc != NULL) {
+		if (c == '\n')
+			early_putc('\r');
+		early_putc(c);
+		return;
+	}
+#endif
+
 	if (cn_mute || c == '\0')
 		return;
 	STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) {

Modified: head/sys/kern/subr_prf.c
==============================================================================
--- head/sys/kern/subr_prf.c	Wed Feb 12 00:32:14 2014	(r261785)
+++ head/sys/kern/subr_prf.c	Wed Feb 12 00:53:38 2014	(r261786)
@@ -1137,25 +1137,3 @@ hexdump(const void *ptr, int length, con
 	}
 }
 
-#ifdef EARLY_PRINTF
-/*
- * Support for calling an alternate printf early in boot (like before
- * cn_init() can be called).  Platforms need to define eputc that want
- * to use this.
- */
-static void
-early_putc_func(int ch, void *arg __unused)
-{
-	eputc(ch);
-}
-
-void
-eprintf(const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	kvprintf(fmt, early_putc_func, NULL, 10, ap);
-	va_end(ap);
-}
-#endif

Modified: head/sys/sys/systm.h
==============================================================================
--- head/sys/sys/systm.h	Wed Feb 12 00:32:14 2014	(r261785)
+++ head/sys/sys/systm.h	Wed Feb 12 00:53:38 2014	(r261786)
@@ -197,8 +197,8 @@ void	init_param2(long physpages);
 void	init_static_kenv(char *, size_t);
 void	tablefull(const char *);
 #ifdef  EARLY_PRINTF
-void	eprintf(const char *, ...) __printflike(1, 2);
-void	eputc(int ch);
+typedef void early_putc_t(int ch);
+extern early_putc_t *early_putc;
 #endif
 int	kvprintf(char const *, void (*)(int, void*), void *, int,
 	    __va_list) __printflike(1, 0);


More information about the svn-src-head mailing list