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)