[SeaBIOS] [PATCH v2] serialio: Support for mmap serial ports

Ricardo Ribalda Delgado ricardo.ribalda at gmail.com
Tue Dec 20 19:03:58 CET 2016


Some chipsets have memory mapped serial ports. The protocol is the same
as an standard uart, but with memory read/write instead of inb/outb.

Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda at gmail.com>
---
v2: Fix typos

Suggested by: Kevin O'Connor <kevin at koconnor.net>:

-Only operate in 32bit mode if !MODESEGMENT

 src/Kconfig       |  3 +++
 src/hw/serialio.c | 32 +++++++++++++++++++++++++-------
 src/serial.c      |  2 +-
 3 files changed, 29 insertions(+), 8 deletions(-)

diff --git a/src/Kconfig b/src/Kconfig
index e767be1351c3..e53713f2c527 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -532,6 +532,9 @@ menu "Debugging"
         default 0x3f8
         help
             Base port for serial - generally 0x3f8, 0x2f8, 0x3e8, or 0x2e8.
+	    On some chipsets the serial port is memory mapped, in those cases
+	    provide the 32 bit address. E.g. 0xFEDC6000 for the AMD Kern
+	    (a.k.a Hudson UART).
 
     config DEBUG_IO
         depends on QEMU_HARDWARE && DEBUG_LEVEL != 0
diff --git a/src/hw/serialio.c b/src/hw/serialio.c
index 6486fc086b1c..6ed8e7b1880d 100644
--- a/src/hw/serialio.c
+++ b/src/hw/serialio.c
@@ -17,6 +17,24 @@
 
 #define DEBUG_TIMEOUT 100000
 
+static void
+serial_outb(u8 val, u32 port, u8 offset){
+	if (port < 0x10000)
+		return outb(val, port + offset);
+	if (MODESEGMENT)
+		return;
+	writeb((void *)port + 4*offset, val);
+}
+
+static u8
+serial_inb(u32 port, u8 offset){
+	if (port < 0x10000)
+		return inb(port + offset);
+	if (MODESEGMENT)
+		return 0xff;
+	return readb((void *)port + 4*offset);
+}
+
 // Setup the debug serial port for output.
 void
 serial_debug_preinit(void)
@@ -25,12 +43,12 @@ serial_debug_preinit(void)
         return;
     // setup for serial logging: 8N1
     u8 oldparam, newparam = 0x03;
-    oldparam = inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LCR);
-    outb(newparam, CONFIG_DEBUG_SERIAL_PORT+SEROFF_LCR);
+    oldparam = serial_inb(CONFIG_DEBUG_SERIAL_PORT, SEROFF_LCR);
+    serial_outb(newparam, CONFIG_DEBUG_SERIAL_PORT, SEROFF_LCR);
     // Disable irqs
     u8 oldier, newier = 0;
-    oldier = inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_IER);
-    outb(newier, CONFIG_DEBUG_SERIAL_PORT+SEROFF_IER);
+    oldier = serial_inb(CONFIG_DEBUG_SERIAL_PORT, SEROFF_IER);
+    serial_outb(newier, CONFIG_DEBUG_SERIAL_PORT, SEROFF_IER);
 
     if (oldparam != newparam || oldier != newier)
         dprintf(1, "Changing serial settings was %x/%x now %x/%x\n"
@@ -44,11 +62,11 @@ serial_debug(char c)
     if (!CONFIG_DEBUG_SERIAL)
         return;
     int timeout = DEBUG_TIMEOUT;
-    while ((inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LSR) & 0x20) != 0x20)
+    while ((serial_inb(CONFIG_DEBUG_SERIAL_PORT, SEROFF_LSR) & 0x20) != 0x20)
         if (!timeout--)
             // Ran out of time.
             return;
-    outb(c, CONFIG_DEBUG_SERIAL_PORT+SEROFF_DATA);
+    serial_outb(c, CONFIG_DEBUG_SERIAL_PORT, SEROFF_DATA);
 }
 
 void
@@ -66,7 +84,7 @@ serial_debug_flush(void)
     if (!CONFIG_DEBUG_SERIAL)
         return;
     int timeout = DEBUG_TIMEOUT;
-    while ((inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LSR) & 0x60) != 0x60)
+    while ((serial_inb(CONFIG_DEBUG_SERIAL_PORT, SEROFF_LSR) & 0x60) != 0x60)
         if (!timeout--)
             // Ran out of time.
             return;
diff --git a/src/serial.c b/src/serial.c
index 88349c8a9267..27710cb19af9 100644
--- a/src/serial.c
+++ b/src/serial.c
@@ -21,7 +21,7 @@
 static u16
 detect_serial(u16 port, u8 timeout, u8 count)
 {
-    if (CONFIG_DEBUG_SERIAL && port == CONFIG_DEBUG_SERIAL_PORT
+    if (CONFIG_DEBUG_SERIAL && port == (u16) CONFIG_DEBUG_SERIAL_PORT
         && !romfile_loadint("etc/advertise-serial-debug-port", 1))
         return 0;
     outb(0x02, port+SEROFF_IER);
-- 
2.10.2




More information about the SeaBIOS mailing list