[syslinux:pathbased] dprintf: make usable on hardware

syslinux-bot for H. Peter Anvin hpa at zytor.com
Sun Feb 28 19:30:04 PST 2010


Commit-ID:  9383b42b123bc99c1740ab643ad20a76403abeb0
Gitweb:     http://syslinux.zytor.com/commit/9383b42b123bc99c1740ab643ad20a76403abeb0
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Sun, 28 Feb 2010 18:53:47 -0800
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Sun, 28 Feb 2010 18:53:47 -0800

dprintf: make usable on hardware

Actually configure the serial port used for dprintf, so we can
actually use it on real hardware.

Signed-off-by: H. Peter Anvin <hpa at zytor.com>


---
 com32/lib/vdprintf.c |   77 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 71 insertions(+), 6 deletions(-)

diff --git a/com32/lib/vdprintf.c b/com32/lib/vdprintf.c
index ea9e048..330279b 100644
--- a/com32/lib/vdprintf.c
+++ b/com32/lib/vdprintf.c
@@ -14,15 +14,41 @@
 #define DEBUG 1
 #include <dprintf.h>
 
-#define BUFFER_SIZE	32768
+#define BUFFER_SIZE	4096
 
+enum serial_port_regs {
+    THR = 0,
+    RBR = 0,
+    DLL = 0,
+    DLM = 1,
+    IER = 1,
+    IIR = 2,
+    FCR = 2,
+    LCR = 3,
+    MCR = 4,
+    LSR = 5,
+    MSR = 6,
+    SCR = 7,
+};
 static const uint16_t debug_base = 0x03f8; /* I/O base address */
 
+static void debug_putc(char c)
+{
+    if (c == '\n')
+	debug_putc('\r');
+
+    while ((inb(debug_base + LSR) & 0x20) == 0)
+	cpu_relax();
+    outb(c, debug_base + THR);
+}
+
 void vdprintf(const char *format, va_list ap)
 {
     int rv;
     char buffer[BUFFER_SIZE];
     char *p;
+    static bool debug_init = false;
+    static bool debug_ok   = false;
 
     rv = vsnprintf(buffer, BUFFER_SIZE, format, ap);
 
@@ -37,10 +63,49 @@ void vdprintf(const char *format, va_list ap)
      * if one is enabled or not (this means we don't have to enable the real
      * serial console and therefore get conflicting output.)
      */
-    p = buffer;
-    while (rv--) {
-	while ((inb(debug_base+5) & 0x20) == 0)
-	    cpu_relax();
-	outb(*p++, debug_base);
+    if (__unlikely(!debug_init)) {
+	uint8_t dll, dlm, lcr;
+
+	debug_init = true;
+
+	cli();
+
+	/* Initialize the serial port to 115200 n81 with FIFOs enabled */
+	outb(0x83, debug_base + LCR);
+	outb(0x01, debug_base + DLL);
+	outb(0x00, debug_base + DLM);
+	(void)inb(debug_base + IER);	/* Synchronize */
+	dll = inb(debug_base + DLL);
+	dlm = inb(debug_base + DLM);
+	lcr = inb(debug_base + LCR);
+	
+	outb(0x03, debug_base + LCR);
+	(void)inb(debug_base + IER);	/* Synchronize */
+
+	outb(0x00, debug_base + IER);
+	(void)inb(debug_base + IER);	/* Synchronize */
+
+	sti();
+
+	if (dll != 0x01 || dlm != 0x00 || lcr != 0x83) {
+	    /* No serial port present */
+	    return;
+	}
+
+	outb(0x01, debug_base + FCR);
+	(void)inb(debug_base + IER);	/* Synchronize */
+	if (inb(debug_base + IIR) < 0xc0) {
+	    outb(0x00, debug_base + FCR); /* Disable non-functional FIFOs */
+	    (void)inb(debug_base + IER);	/* Synchronize */
+	}
+
+	debug_ok = true;
     }
+
+    if (!debug_ok)
+	return;
+
+    p = buffer;
+    while (rv--)
+	debug_putc(*p++);
 }



More information about the Syslinux-commits mailing list