From a02c9c956926bfacd8973624b52573606e9b5341 Mon Sep 17 00:00:00 2001 From: Liav A Date: Fri, 2 Sep 2022 13:15:27 +0300 Subject: [PATCH] Kernel: Abstract platform-specific serial port access from kprintf kprintf should not really care about the hardware-specific details of each UART or serial port out there, so instead of using x86 specific instructions, let's ensure that we will compile only the relevant code for debug output for a targeted-specific platform. --- Kernel/Arch/DebugOutput.h | 13 ++++++ Kernel/Arch/aarch64/RPi/DebugOutput.cpp | 17 ++++++++ Kernel/Arch/x86/common/BochsDebugOutput.h | 13 ++++++ Kernel/Arch/x86/common/DebugOutput.cpp | 48 +++++++++++++++++++++++ Kernel/CMakeLists.txt | 2 + Kernel/kprintf.cpp | 44 ++++++++------------- 6 files changed, 109 insertions(+), 28 deletions(-) create mode 100644 Kernel/Arch/DebugOutput.h create mode 100644 Kernel/Arch/aarch64/RPi/DebugOutput.cpp create mode 100644 Kernel/Arch/x86/common/BochsDebugOutput.h create mode 100644 Kernel/Arch/x86/common/DebugOutput.cpp diff --git a/Kernel/Arch/DebugOutput.h b/Kernel/Arch/DebugOutput.h new file mode 100644 index 0000000000..6f77446343 --- /dev/null +++ b/Kernel/Arch/DebugOutput.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +namespace Kernel { + +void debug_output(char ch); + +} diff --git a/Kernel/Arch/aarch64/RPi/DebugOutput.cpp b/Kernel/Arch/aarch64/RPi/DebugOutput.cpp new file mode 100644 index 0000000000..87a3b35a6f --- /dev/null +++ b/Kernel/Arch/aarch64/RPi/DebugOutput.cpp @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +namespace Kernel { + +void debug_output(char ch) +{ + RPi::UART::the().send(ch); +} + +} diff --git a/Kernel/Arch/x86/common/BochsDebugOutput.h b/Kernel/Arch/x86/common/BochsDebugOutput.h new file mode 100644 index 0000000000..624b26dcb4 --- /dev/null +++ b/Kernel/Arch/x86/common/BochsDebugOutput.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +namespace Kernel { + +void bochs_debug_output(char ch); + +} diff --git a/Kernel/Arch/x86/common/DebugOutput.cpp b/Kernel/Arch/x86/common/DebugOutput.cpp new file mode 100644 index 0000000000..22e5485e30 --- /dev/null +++ b/Kernel/Arch/x86/common/DebugOutput.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace Kernel { + +static constexpr u16 serial_com1_io_port = 0x3F8; + +void bochs_debug_output(char ch) +{ + IO::out8(IO::BOCHS_DEBUG_PORT, ch); +} + +void debug_output(char ch) +{ + static bool serial_ready = false; + static bool was_cr = false; + + if (!serial_ready) { + IO::out8(serial_com1_io_port + 1, 0x00); + IO::out8(serial_com1_io_port + 3, 0x80); + IO::out8(serial_com1_io_port + 0, 0x02); + IO::out8(serial_com1_io_port + 1, 0x00); + IO::out8(serial_com1_io_port + 3, 0x03); + IO::out8(serial_com1_io_port + 2, 0xC7); + IO::out8(serial_com1_io_port + 4, 0x0B); + + serial_ready = true; + } + + while ((IO::in8(serial_com1_io_port + 5) & 0x20) == 0) + ; + + if (ch == '\n' && !was_cr) + IO::out8(serial_com1_io_port, '\r'); + + IO::out8(serial_com1_io_port, ch); + + was_cr = ch == '\r'; +} + +} diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index a2e3bc2bf5..bdb935fc84 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -332,6 +332,7 @@ if ("${SERENITY_ARCH}" STREQUAL "i686" OR "${SERENITY_ARCH}" STREQUAL "x86_64") Arch/Processor.cpp Arch/x86/common/CMOS.cpp + Arch/x86/common/DebugOutput.cpp Arch/x86/common/Delay.cpp Arch/x86/common/I8042Reboot.cpp Arch/x86/common/RTC.cpp @@ -437,6 +438,7 @@ if (NOT "${SERENITY_ARCH}" STREQUAL "aarch64") ) else() set(RPI_SOURCES + Arch/aarch64/RPi/DebugOutput.cpp Arch/aarch64/RPi/Framebuffer.cpp Arch/aarch64/RPi/GPIO.cpp Arch/aarch64/RPi/InterruptController.cpp diff --git a/Kernel/kprintf.cpp b/Kernel/kprintf.cpp index 94fb169e90..e244a2d80f 100644 --- a/Kernel/kprintf.cpp +++ b/Kernel/kprintf.cpp @@ -7,7 +7,10 @@ #include #include #include -#include +#include +#if ARCH(I386) || ARCH(X86_64) +# include +#endif #include #include #include @@ -43,39 +46,20 @@ static void serial_putch(char ch) if (PCISerialDevice::is_available()) return PCISerialDevice::the().put_char(ch); - static bool serial_ready = false; - static bool was_cr = false; - - if (!serial_ready) { - IO::out8(0x3F8 + 1, 0x00); - IO::out8(0x3F8 + 3, 0x80); - IO::out8(0x3F8 + 0, 0x02); - IO::out8(0x3F8 + 1, 0x00); - IO::out8(0x3F8 + 3, 0x03); - IO::out8(0x3F8 + 2, 0xC7); - IO::out8(0x3F8 + 4, 0x0B); - - serial_ready = true; - } - - while ((IO::in8(0x3F8 + 5) & 0x20) == 0) - ; - - if (ch == '\n' && !was_cr) - IO::out8(0x3F8, '\r'); - - IO::out8(0x3F8, ch); - - was_cr = ch == '\r'; + debug_output(ch); } static void critical_console_out(char ch) { if (s_serial_debug_enabled) serial_putch(ch); + +#if ARCH(I386) || ARCH(X86_64) // No need to output things to the real ConsoleDevice as no one is likely // to read it (because we are in a fatal situation, so only print things and halt) - IO::out8(IO::BOCHS_DEBUG_PORT, ch); + bochs_debug_output(ch); +#endif + // We emit chars directly to the string. this is necessary in few cases, // especially when we want to avoid any memory allocations... if (GraphicsManagement::is_initialized() && GraphicsManagement::the().console()) { @@ -95,7 +79,9 @@ static void console_out(char ch) if (DeviceManagement::the().is_console_device_attached()) { DeviceManagement::the().console_device().put_char(ch); } else { - IO::out8(IO::BOCHS_DEBUG_PORT, ch); +#if ARCH(I386) || ARCH(X86_64) + bochs_debug_output(ch); +#endif } if (ConsoleManagement::is_initialized()) { ConsoleManagement::the().debug_tty()->emit_char(ch); @@ -153,7 +139,9 @@ static inline void internal_dbgputch(char ch) { if (s_serial_debug_enabled) serial_putch(ch); - IO::out8(IO::BOCHS_DEBUG_PORT, ch); +#if ARCH(I386) || ARCH(X86_64) + bochs_debug_output(ch); +#endif } extern "C" void dbgputstr(char const* characters, size_t length)