[SeaBIOS] [PATCH 2/3] Add Intel Quark UART support

David Woodhouse dwmw2 at infradead.org
Fri Dec 6 15:23:14 CET 2013


This includes generic support for MMIO serial which can be used for
other PCI (or non-PCI) serial ports too.

Only outputs to the serial port in 32-bit mode, unless we're lucky
enough that it's at an address below 1MiB.

Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
---
 src/Kconfig       | 15 ++++++++++++++-
 src/hw/serialio.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/src/Kconfig b/src/Kconfig
index 92c3102..696ab46 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -477,8 +477,21 @@ menu "Debugging"
         default n
         help
             Send debugging information to serial port.
-    config DEBUG_SERIAL_PORT
+    config DEBUG_SERIAL_MMIO
         depends on DEBUG_SERIAL
+        bool
+        default n
+        help
+            Send debugging information to PCI serial port.
+    config DEBUG_SERIAL_QUARK
+        bool "Intel Quark serial port debugging"
+	depends on DEBUG_SERIAL
+        select DEBUG_SERIAL_MMIO
+        default n
+        help
+            Use Quark UART1 (PCI device 0x14, function 5) for serial debug.
+    config DEBUG_SERIAL_PORT
+        depends on DEBUG_SERIAL && !DEBUG_SERIAL_MMIO
         hex "Serial port base address"
         default 0x3f8
         help
diff --git a/src/hw/serialio.c b/src/hw/serialio.c
index 8ec36c2..b2bc68f 100644
--- a/src/hw/serialio.c
+++ b/src/hw/serialio.c
@@ -9,6 +9,9 @@
 #include "output.h" // dprintf
 #include "serialio.h" // serial_debug_preinit
 #include "x86.h" // outb
+#include "hw/pci_regs.h" // PCI_VENDOR_ID, PCI_BASE_ADDRESS_0
+#include "hw/pci.h" // pci_config_readl
+#include "stacks.h" // call32
 

 /****************************************************************
@@ -17,8 +20,42 @@
 
 #define DEBUG_TIMEOUT 100000
 
+#if CONFIG_DEBUG_SERIAL_MMIO
+static u32 serial_addr;
+static u8 serial_stride;
+#define serial_out(d, ofs) writeb((void *)(serial_addr + (ofs)*serial_stride), (d))
+#define serial_in(ofs) readb((void *)(serial_addr + (ofs)*serial_stride))
+// Debug output only in 32-bit mode, or when MMIO address < 1MiB
+#define serial_valid() (serial_addr && (!MODE16 || serial_addr < 0x100000))
+#define set_serial_addr(adr, str) do { serial_addr = (adr); \
+                                       serial_stride = (str); } while (0)
+#else
 #define serial_out(d, reg) outb(d, CONFIG_DEBUG_SERIAL_PORT+(reg))
 #define serial_in(reg) inb(CONFIG_DEBUG_SERIAL_PORT+(reg))
+#define serial_valid() (1)
+#define set_serial_addr(adr, str) do { ; } while (0)
+#endif
+
+static int
+find_mmio_serial(void)
+{
+    if (CONFIG_DEBUG_SERIAL_QUARK) {
+        // debug port is bus 0, device 0x14, function 5.
+        u16 uart_bdf = pci_to_bdf(0, 0x14, 5);
+
+        // If it isn't a Quark UART...
+        if (pci_config_readl(uart_bdf, PCI_VENDOR_ID) != 0x09368086)
+            return -1;
+
+        u32 bar0 = pci_config_readl(uart_bdf, PCI_BASE_ADDRESS_0);
+        if (!(bar0 & 0xf)) {
+            set_serial_addr(bar0, 4);
+            return 0;
+        }
+    }
+
+    return -1;
+}
 
 // Setup the debug serial port for output.
 void
@@ -26,6 +63,21 @@ serial_debug_preinit(void)
 {
     if (!CONFIG_DEBUG_SERIAL)
         return;
+
+    if (CONFIG_DEBUG_SERIAL_MMIO) {
+        // Need to discover serial port MMIO address
+        if (MODE16) {
+            // Needs to be done in 32-bit mode.
+            extern void _cfunc32flat_serial_debug_preinit(void);
+            call32(_cfunc32flat_serial_debug_preinit, 0, -1);
+            return;
+        }
+
+        // Find the PCI device or whatever provides the serial port
+        if (find_mmio_serial())
+            return;
+    }
+
     // setup for serial logging: 8N1
     u8 oldparam, newparam = 0x03;
     oldparam = serial_in(SEROFF_LCR);
@@ -46,6 +98,8 @@ serial_debug(char c)
 {
     if (!CONFIG_DEBUG_SERIAL)
         return;
+    if (!serial_valid())
+        return;
     int timeout = DEBUG_TIMEOUT;
     while ((serial_in(SEROFF_LSR) & 0x20) != 0x20)
         if (!timeout--)
@@ -68,6 +122,8 @@ serial_debug_flush(void)
 {
     if (!CONFIG_DEBUG_SERIAL)
         return;
+    if (!serial_valid())
+        return;
     int timeout = DEBUG_TIMEOUT;
     while ((serial_in(SEROFF_LSR) & 0x60) != 0x60)
         if (!timeout--)
-- 
1.8.3.1


-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse at intel.com                              Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 5745 bytes
Desc: not available
URL: <http://www.seabios.org/pipermail/seabios/attachments/20131206/826b4cf8/attachment-0001.bin>


More information about the SeaBIOS mailing list