aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRicardo Ribalda Delgado <ricardo.ribalda@gmail.com>2016-12-20 19:03:58 +0100
committerKevin O'Connor <kevin@koconnor.net>2016-12-30 11:29:08 -0500
commit9332965e1c46ddf4e19d7050f1e957a195c703fa (patch)
tree363f10c8fcdeaff1821bf7e2e09f7bfa46454381
parent7b7b49e2898613dd6cf82473fa9b702541f218d6 (diff)
downloadseabios-9332965e1c46ddf4e19d7050f1e957a195c703fa.tar.gz
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. Tested-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r--src/Kconfig13
-rw-r--r--src/hw/serialio.c44
2 files changed, 47 insertions, 10 deletions
diff --git a/src/Kconfig b/src/Kconfig
index e767be13..457d082c 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 6486fc08..319a85c1 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;