On Tue, Dec 20, 2016 at 07:03:58PM +0100, Ricardo Ribalda Delgado wrote:
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@gmail.com
v2: Fix typos
Suggested by: Kevin O'Connor kevin@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).
Thanks. I'm a little concerned about overloading the meaning of CONFIG_DEBUG_SERIAL_PORT to mean either port or memory address. How about the modified patch below instead?
-Kevin
From 9968b2ef2bbfaf7271cd2d27302161e141200738 Mon Sep 17 00:00:00 2001
From: Ricardo Ribalda Delgado ricardo.ribalda@gmail.com Date: Tue, 20 Dec 2016 19:03:58 +0100 Subject: [PATCH] serialio: Support for mmap serial ports
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@gmail.com Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/Kconfig | 13 +++++++++++++ src/hw/serialio.c | 44 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/src/Kconfig b/src/Kconfig index e767be1..457d082 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -532,6 +532,19 @@ menu "Debugging" default 0x3f8 help Base port for serial - generally 0x3f8, 0x2f8, 0x3e8, or 0x2e8. + config DEBUG_SERIAL_MMIO + depends on DEBUG_LEVEL != 0 && !DEBUG_SERIAL + bool "Serial port debugging via memory mapped IO" + default n + help + Send debugging information to serial port mapped in memory. + config DEBUG_SERIAL_MEM_ADDRESS + depends on DEBUG_SERIAL_MMIO + hex "Serial port memory mapped IO address" + help + 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 6486fc0..319a85c 100644 --- a/src/hw/serialio.c +++ b/src/hw/serialio.c @@ -17,20 +17,44 @@
#define DEBUG_TIMEOUT 100000
+// Write to a serial port register +static void +serial_debug_write(u8 offset, u8 val) +{ + if (CONFIG_DEBUG_SERIAL) { + outb(val, CONFIG_DEBUG_SERIAL_PORT + offset); + } else if (CONFIG_DEBUG_SERIAL_MMIO) { + ASSERT32FLAT(); + writeb((void*)CONFIG_DEBUG_SERIAL_MEM_ADDRESS + 4*offset, val); + } +} + +// Read from a serial port register +static u8 +serial_debug_read(u8 offset) +{ + if (CONFIG_DEBUG_SERIAL) + return inb(CONFIG_DEBUG_SERIAL_PORT + offset); + if (CONFIG_DEBUG_SERIAL_MMIO) { + ASSERT32FLAT(); + return readb((void*)CONFIG_DEBUG_SERIAL_MEM_ADDRESS + 4*offset); + } +} + // Setup the debug serial port for output. void serial_debug_preinit(void) { - if (!CONFIG_DEBUG_SERIAL) + if (!CONFIG_DEBUG_SERIAL && (!CONFIG_DEBUG_SERIAL_MMIO || MODESEGMENT)) 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_debug_read(SEROFF_LCR); + serial_debug_write(SEROFF_LCR, newparam); // Disable irqs u8 oldier, newier = 0; - oldier = inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_IER); - outb(newier, CONFIG_DEBUG_SERIAL_PORT+SEROFF_IER); + oldier = serial_debug_read(SEROFF_IER); + serial_debug_write(SEROFF_IER, newier);
if (oldparam != newparam || oldier != newier) dprintf(1, "Changing serial settings was %x/%x now %x/%x\n" @@ -41,14 +65,14 @@ serial_debug_preinit(void) static void serial_debug(char c) { - if (!CONFIG_DEBUG_SERIAL) + if (!CONFIG_DEBUG_SERIAL && (!CONFIG_DEBUG_SERIAL_MMIO || MODESEGMENT)) return; int timeout = DEBUG_TIMEOUT; - while ((inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LSR) & 0x20) != 0x20) + while ((serial_debug_read(SEROFF_LSR) & 0x20) != 0x20) if (!timeout--) // Ran out of time. return; - outb(c, CONFIG_DEBUG_SERIAL_PORT+SEROFF_DATA); + serial_debug_write(SEROFF_DATA, c); }
void @@ -63,10 +87,10 @@ serial_debug_putc(char c) void serial_debug_flush(void) { - if (!CONFIG_DEBUG_SERIAL) + if (!CONFIG_DEBUG_SERIAL && (!CONFIG_DEBUG_SERIAL_MMIO || MODESEGMENT)) return; int timeout = DEBUG_TIMEOUT; - while ((inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LSR) & 0x60) != 0x60) + while ((serial_debug_read(SEROFF_LSR) & 0x60) != 0x60) if (!timeout--) // Ran out of time. return;