diff options
Diffstat (limited to 'roms/seabios-hppa/src/hw/serialio.c')
-rw-r--r-- | roms/seabios-hppa/src/hw/serialio.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/roms/seabios-hppa/src/hw/serialio.c b/roms/seabios-hppa/src/hw/serialio.c new file mode 100644 index 000000000..07958b300 --- /dev/null +++ b/roms/seabios-hppa/src/hw/serialio.c @@ -0,0 +1,129 @@ +// Low-level serial (and serial-like) device access. +// +// Copyright (C) 2008-1013 Kevin O'Connor <kevin@koconnor.net> +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "config.h" // CONFIG_DEBUG_SERIAL +#include "fw/paravirt.h" // RunningOnQEMU +#include "output.h" // dprintf +#include "serialio.h" // serial_debug_preinit +#include "x86.h" // outb + + +/**************************************************************** + * Serial port debug output + ****************************************************************/ + +#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 && (!CONFIG_DEBUG_SERIAL_MMIO || MODESEGMENT)) + return; + // setup for serial logging: 8N1 + u8 oldparam, newparam = 0x03; + oldparam = serial_debug_read(SEROFF_LCR); + serial_debug_write(SEROFF_LCR, newparam); + // Disable irqs + u8 oldier, newier = 0; + 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" + , oldparam, oldier, newparam, newier); +} + +// Write a character to the serial port. +static void +serial_debug(char c) +{ + if (!CONFIG_DEBUG_SERIAL && (!CONFIG_DEBUG_SERIAL_MMIO || MODESEGMENT)) + return; + int timeout = DEBUG_TIMEOUT; + while ((serial_debug_read(SEROFF_LSR) & 0x20) != 0x20) + if (!timeout--) + // Ran out of time. + return; + serial_debug_write(SEROFF_DATA, c); +} + +void +serial_debug_putc(char c) +{ + if (c == '\n') + serial_debug('\r'); + serial_debug(c); +} + +// Make sure all serial port writes have been completely sent. +void +serial_debug_flush(void) +{ + if (!CONFIG_DEBUG_SERIAL && (!CONFIG_DEBUG_SERIAL_MMIO || MODESEGMENT)) + return; + int timeout = DEBUG_TIMEOUT; + while ((serial_debug_read(SEROFF_LSR) & 0x60) != 0x60) + if (!timeout--) + // Ran out of time. + return; +} + + +/**************************************************************** + * QEMU debug port + ****************************************************************/ + +portaddr_t DebugOutputPort VARFSEG = 0x402; + +void +qemu_debug_preinit(void) +{ + /* Xen doesn't support checking if debug output is active. */ + if (runningOnXen()) + return; + + /* Check if the QEMU debug output port is active */ + if (CONFIG_DEBUG_IO && + inb(GET_GLOBAL(DebugOutputPort)) != QEMU_DEBUGCON_READBACK) + DebugOutputPort = 0; +} + +// Write a character to the special debugging port. +void +qemu_debug_putc(char c) +{ + if (!CONFIG_DEBUG_IO || !runningOnQEMU()) + return; + u16 port = GET_GLOBAL(DebugOutputPort); + if (port) + // Send character to debug port. + outb(c, port); +} |