From 81af8a48cb7ad8dbae1713da5a6a0fa73b9a6f8c Mon Sep 17 00:00:00 2001 From: EnderIce2 Date: Mon, 23 Dec 2024 03:52:26 +0200 Subject: [PATCH] kernel/uart: Refactor code Signed-off-by: EnderIce2 --- Kernel/core/debugger.cpp | 43 +------- Kernel/core/uart.cpp | 216 ++++++++++++++----------------------- Kernel/include/uart.hpp | 70 +++--------- Kernel/kernel.cpp | 4 +- Kernel/kernel.h | 3 +- Kernel/library/dumper.cpp | 2 - Kernel/network/net_dbg.cpp | 2 - Kernel/profiling/cyg.cpp | 3 - Kernel/profiling/gcov.cpp | 4 +- Kernel/profiling/gprof.cpp | 4 +- 10 files changed, 102 insertions(+), 249 deletions(-) diff --git a/Kernel/core/debugger.cpp b/Kernel/core/debugger.cpp index 8c6d0e1e..0deac1c1 100644 --- a/Kernel/core/debugger.cpp +++ b/Kernel/core/debugger.cpp @@ -27,48 +27,9 @@ NewLock(DebuggerLock); extern bool serialports[8]; -EXTERNC NIF void uart_wrapper(char c, void *unused) +EXTERNC NIF void uart_wrapper(char c, void *) { - static int once = 0; - if (unlikely(!once++)) - { - uint8_t com = inb(0x3F8); - if (com != 0xFF) - { - outb(s_cst(uint16_t, 0x3F8 + 1), 0x00); // Disable all interrupts - outb(s_cst(uint16_t, 0x3F8 + 3), 0x80); // Enable DLAB (set baud rate divisor) - outb(s_cst(uint16_t, 0x3F8 + 0), 0x1); // Set divisor to 1 (lo byte) 115200 baud - outb(s_cst(uint16_t, 0x3F8 + 1), 0x0); // (hi byte) - outb(s_cst(uint16_t, 0x3F8 + 3), 0x03); // 8 bits, no parity, one stop bit - outb(s_cst(uint16_t, 0x3F8 + 2), 0xC7); // Enable FIFO, clear them, with 14-byte threshold - outb(s_cst(uint16_t, 0x3F8 + 4), 0x0B); // IRQs enabled, RTS/DSR set - - /* FIXME https://wiki.osdev.org/Serial_Ports */ - // outb(s_cst(uint16_t, 0x3F8 + 0), 0x1E); - // outb(s_cst(uint16_t, 0x3F8 + 0), 0xAE); - // Check if the serial port is faulty. - // if (inb(s_cst(uint16_t, 0x3F8 + 0)) != 0xAE) - // { - // static int once = 0; - // if (!once++) - // warn("Serial port %#llx is faulty.", 0x3F8); - // // serialports[0x3F8] = false; // ignore for now - // // return; - // } - - // Set to normal operation mode. - outb(s_cst(uint16_t, 0x3F8 + 4), 0x0F); - serialports[0] = true; - } - } - - if (likely(serialports[0])) - { - while ((inb(s_cst(uint16_t, 0x3F8 + 5)) & 0x20) == 0) - ; - outb(0x3F8, c); - } - UNUSED(unused); + uart.DebugWrite(c); } static inline NIF bool WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, va_list args) diff --git a/Kernel/core/uart.cpp b/Kernel/core/uart.cpp index add8bc2b..005c74c9 100644 --- a/Kernel/core/uart.cpp +++ b/Kernel/core/uart.cpp @@ -16,33 +16,22 @@ */ #include +#include -#include -#include - -bool serialports[8] = {false, false, false, false, false, false, false, false}; -std::vector RegisteredEvents; - -#if defined(__amd64__) || defined(__i386__) -NIF __always_inline inline uint8_t NoProfiler_inportb(uint16_t Port) +namespace UART { - uint8_t Result; - asm("in %%dx, %%al" - : "=a"(Result) - : "d"(Port)); - return Result; -} + enum SerialPorts + { + COM1 = 0x3F8, + COM2 = 0x2F8, + COM3 = 0x3E8, + COM4 = 0x2E8, + COM5 = 0x5F8, + COM6 = 0x4F8, + COM7 = 0x5E8, + COM8 = 0x4E8 + }; -NIF __always_inline inline void NoProfiler_outportb(uint16_t Port, uint8_t Data) -{ - asmv("out %%al, %%dx" - : - : "a"(Data), "d"(Port)); -} -#endif - -namespace UniversalAsynchronousReceiverTransmitter -{ #define SERIAL_ENABLE_DLAB 0x80 #define SERIAL_RATE_115200_LO 0x01 #define SERIAL_RATE_115200_HI 0x00 @@ -52,137 +41,96 @@ namespace UniversalAsynchronousReceiverTransmitter #define SERIAL_RATE_38400_HI 0x00 #define SERIAL_BUFFER_EMPTY 0x20 - /* TODO: Serial Port implementation needs reword. https://wiki.osdev.org/Serial_Ports */ - - nsa NIF UART::UART(SerialPorts Port) + void Driver::DebugWrite(uint8_t Char) { -#if defined(__amd64__) || defined(__i386__) - if (Port == COMNULL) - return; - - uint8_t com = NoProfiler_inportb(Port); - if (com == 0xFF) - { - error("Serial port %#lx is not available.", Port); - return; - } - - this->Port = Port; - int PortNumber = 0; - - switch (Port) - { - case COM1: - PortNumber = 0; - break; - case COM2: - PortNumber = 1; - break; - case COM3: - PortNumber = 2; - break; - case COM4: - PortNumber = 3; - break; - case COM5: - PortNumber = 4; - break; - case COM6: - PortNumber = 5; - break; - case COM7: - PortNumber = 6; - break; - case COM8: - PortNumber = 7; - break; - default: - return; - } - - if (serialports[PortNumber]) - return; - - // Initialize the serial port - NoProfiler_outportb(s_cst(uint16_t, Port + 1), 0x00); // Disable all interrupts - NoProfiler_outportb(s_cst(uint16_t, Port + 3), SERIAL_ENABLE_DLAB); // Enable DLAB (set baud rate divisor) - NoProfiler_outportb(s_cst(uint16_t, Port + 0), SERIAL_RATE_115200_LO); // Set divisor to 1 (lo byte) 115200 baud - NoProfiler_outportb(s_cst(uint16_t, Port + 1), SERIAL_RATE_115200_HI); // (hi byte) - NoProfiler_outportb(s_cst(uint16_t, Port + 3), 0x03); // 8 bits, no parity, one stop bit - NoProfiler_outportb(s_cst(uint16_t, Port + 2), 0xC7); // Enable FIFO, clear them, with 14-byte threshold - NoProfiler_outportb(s_cst(uint16_t, Port + 4), 0x0B); // IRQs enabled, RTS/DSR set - - /* FIXME https://wiki.osdev.org/Serial_Ports */ - // NoProfiler_outportb(s_cst(uint16_t, Port + 0), 0x1E); - // NoProfiler_outportb(s_cst(uint16_t, Port + 0), 0xAE); - // Check if the serial port is faulty. - // if (NoProfiler_inportb(s_cst(uint16_t, Port + 0)) != 0xAE) - // { - // static int once = 0; - // if (!once++) - // warn("Serial port %#lx is faulty.", Port); - // // serialports[Port] = false; // ignore for now - // // return; - // } - - // Set to normal operation mode. - NoProfiler_outportb(s_cst(uint16_t, Port + 4), 0x0F); - serialports[PortNumber] = true; - this->IsAvailable = true; -#endif - } - - nsa NIF UART::~UART() {} - - nsa NIF void UART::Write(uint8_t Char) - { - if (!this->IsAvailable) + if (!DebugAvailable) return; #if defined(__amd64__) || defined(__i386__) - while ((NoProfiler_inportb(s_cst(uint16_t, Port + 5)) & SERIAL_BUFFER_EMPTY) == 0) + while ((inb(s_cst(uint16_t, COM1 + 5)) & SERIAL_BUFFER_EMPTY) == 0) ; - NoProfiler_outportb(Port, Char); + outb(COM1, Char); #endif - foreach (auto e in RegisteredEvents) - if (e->GetRegisteredPort() == Port || e->GetRegisteredPort() == COMNULL) - e->OnSent(Char); } - nsa NIF uint8_t UART::Read() + uint8_t Driver::DebugRead() { - if (!this->IsAvailable) + if (!DebugAvailable) return 0; #if defined(__amd64__) || defined(__i386__) - while ((NoProfiler_inportb(s_cst(uint16_t, Port + 5)) & 1) == 0) + while ((inb(s_cst(uint16_t, COM1 + 5)) & 1) == 0) ; - return NoProfiler_inportb(Port); + return inb(COM1); #endif - foreach (auto e in RegisteredEvents) - { - if (e->GetRegisteredPort() == Port || e->GetRegisteredPort() == COMNULL) - { + } + + void Driver::TTYWrite(uint8_t Char) + { + if (!TTYAvailable) + return; #if defined(__amd64__) || defined(__i386__) - e->OnReceived(NoProfiler_inportb(Port)); + while ((inb(s_cst(uint16_t, COM4 + 5)) & SERIAL_BUFFER_EMPTY) == 0) + ; + outb(COM4, Char); #endif - } - } } - nsa NIF Events::Events(SerialPorts Port) + uint8_t Driver::TTYRead() { - this->Port = Port; - RegisteredEvents.push_back(this); + if (!TTYAvailable) + return 0; +#if defined(__amd64__) || defined(__i386__) + while ((inb(s_cst(uint16_t, COM4 + 5)) & 1) == 0) + ; + return inb(COM4); +#endif } - nsa NIF Events::~Events() + Driver::Driver() { - forItr(itr, RegisteredEvents) +#if defined(__amd64__) || defined(__i386__) + auto initPort = [](uint16_t Port) { - if (*itr == this) - { - RegisteredEvents.erase(itr); - return; - } + // Initialize the serial port + outb(s_cst(uint16_t, Port + 1), 0x00); // Disable all interrupts + outb(s_cst(uint16_t, Port + 3), SERIAL_ENABLE_DLAB); // Enable DLAB (set baud rate divisor) + outb(s_cst(uint16_t, Port + 0), SERIAL_RATE_115200_LO); // Set divisor to 1 (lo byte) 115200 baud + outb(s_cst(uint16_t, Port + 1), SERIAL_RATE_115200_HI); // (hi byte) + outb(s_cst(uint16_t, Port + 3), 0x03); // 8 bits, no parity, one stop bit + outb(s_cst(uint16_t, Port + 2), 0xC7); // Enable FIFO, clear them, with 14-byte threshold + outb(s_cst(uint16_t, Port + 4), 0x0B); // IRQs enabled, RTS/DSR set + + /* FIXME https://wiki.osdev.org/Serial_Ports */ + // outb(s_cst(uint16_t, Port + 0), 0x1E); + // outb(s_cst(uint16_t, Port + 0), 0xAE); + // Check if the serial port is faulty. + // if (inb(s_cst(uint16_t, Port + 0)) != 0xAE) + // { + // static int once = 0; + // if (!once++) + // warn("Serial port %#lx is faulty.", Port); + // // serialports[Port] = false; // ignore for now + // // return; + // } + + // Set to normal operation mode. + outb(s_cst(uint16_t, Port + 4), 0x0F); + }; + + uint8_t com = inb(COM1); + if (com != 0xFF) + { + initPort(COM1); + DebugAvailable = true; } + + com = inb(COM4); + if (com != 0xFF) + { + initPort(COM4); + TTYAvailable = true; + } +#endif } + + Driver::~Driver() {} } diff --git a/Kernel/include/uart.hpp b/Kernel/include/uart.hpp index a218ef76..149576ae 100644 --- a/Kernel/include/uart.hpp +++ b/Kernel/include/uart.hpp @@ -20,70 +20,24 @@ #include -namespace UniversalAsynchronousReceiverTransmitter +namespace UART { - /** - * @brief Serial ports. (if available) - */ - enum SerialPorts - { - COMNULL = 0, - COM1 = 0x3F8, - COM2 = 0x2F8, - COM3 = 0x3E8, - COM4 = 0x2E8, - COM5 = 0x5F8, - COM6 = 0x4F8, - COM7 = 0x5E8, - COM8 = 0x4E8 - }; - - class UART + class Driver { private: - SerialPorts Port; - bool IsAvailable; + bool DebugAvailable = false; + bool TTYAvailable = false; public: - UART(SerialPorts Port = COMNULL); - ~UART(); - void Write(uint8_t Char); - uint8_t Read(); + Driver(); + ~Driver(); + + void DebugWrite(uint8_t Char); + uint8_t DebugRead(); + + void TTYWrite(uint8_t Char); + uint8_t TTYRead(); }; - - class Events - { - private: - SerialPorts Port; - - protected: - /** - * @brief UART events. - * @param Port if none, all ports are registered for events. - */ - Events(SerialPorts Port = COMNULL); - ~Events(); - - public: - /** - * @brief Get the Registered Port object - * @return SerialPorts - */ - nsa NIF SerialPorts GetRegisteredPort() { return this->Port; } - - /** - * @brief Called when a character is sent. - * @param Char the sent character. - */ - - virtual void OnSent(uint8_t Char) { UNUSED(Char); } - /** - * @brief Called when a character is received. - * @param Char the received character. - */ - virtual void OnReceived(uint8_t Char) { UNUSED(Char); } - }; - } #endif // !__FENNIX_KERNEL_UART_H__ diff --git a/Kernel/kernel.cpp b/Kernel/kernel.cpp index 9594e96e..a52708a7 100644 --- a/Kernel/kernel.cpp +++ b/Kernel/kernel.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -60,6 +59,7 @@ Time::time *TimeManager = nullptr; Tasking::Task *TaskManager = nullptr; PCI::Manager *PCIManager = nullptr; Driver::Manager *DriverManager = nullptr; +UART::Driver uart; EXTERNC void putchar(char c) { @@ -67,7 +67,7 @@ EXTERNC void putchar(char c) if (vt != nullptr) vt->Process(c); else - UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(c); + uart.DebugWrite(c); } EXTERNC void _KPrint(const char *Format, va_list Args) diff --git a/Kernel/kernel.h b/Kernel/kernel.h index 85368eec..e67d21b1 100644 --- a/Kernel/kernel.h +++ b/Kernel/kernel.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -51,8 +52,8 @@ extern Time::time *TimeManager; extern PCI::Manager *PCIManager; extern vfs::Virtual *fs; extern Tasking::Task *TaskManager; - extern Driver::Manager *DriverManager; +extern UART::Driver uart; #endif // __cplusplus diff --git a/Kernel/library/dumper.cpp b/Kernel/library/dumper.cpp index 6fcccf03..2649da40 100644 --- a/Kernel/library/dumper.cpp +++ b/Kernel/library/dumper.cpp @@ -25,8 +25,6 @@ NewLock(DumperLock); -using namespace UniversalAsynchronousReceiverTransmitter; - int vprintf_dumper(const char *format, va_list list) { return vfctprintf(uart_wrapper, NULL, format, list); } void WriteRaw(const char *format, ...) diff --git a/Kernel/network/net_dbg.cpp b/Kernel/network/net_dbg.cpp index da6b7b1b..32d5aaf7 100644 --- a/Kernel/network/net_dbg.cpp +++ b/Kernel/network/net_dbg.cpp @@ -27,8 +27,6 @@ TODO: This code is a mess. It needs to be cleaned up. #include #include -using namespace UniversalAsynchronousReceiverTransmitter; - NewLock(netdbg_lock); namespace NetDbg diff --git a/Kernel/profiling/cyg.cpp b/Kernel/profiling/cyg.cpp index dc56f077..f5e291d8 100644 --- a/Kernel/profiling/cyg.cpp +++ b/Kernel/profiling/cyg.cpp @@ -25,14 +25,11 @@ bool EnableProfiler = false; bool Wait = false; unsigned long long LogDepth = 0; unsigned int Level = 0; -using namespace UniversalAsynchronousReceiverTransmitter; -UART com2(COM2); static inline nsa NIF void profiler_uart_wrapper(char c, void *unused) { bool renable = EnableProfiler; EnableProfiler = false; - com2.Write(c); UNUSED(unused); if (renable) EnableProfiler = true; diff --git a/Kernel/profiling/gcov.cpp b/Kernel/profiling/gcov.cpp index 7bb47eef..c9b4fa44 100644 --- a/Kernel/profiling/gcov.cpp +++ b/Kernel/profiling/gcov.cpp @@ -21,8 +21,6 @@ #include "../kernel.h" -using namespace UniversalAsynchronousReceiverTransmitter; - #if BITS_PER_LONG >= 64 typedef long gcov_type; #else @@ -57,7 +55,7 @@ struct gcov_info static inline nsa NIF void gcov_uart_wrapper(char c, void *unused) { - UART(COM2).Write(c); + UNUSED(c); UNUSED(unused); } diff --git a/Kernel/profiling/gprof.cpp b/Kernel/profiling/gprof.cpp index 3f20ffd7..d7692862 100644 --- a/Kernel/profiling/gprof.cpp +++ b/Kernel/profiling/gprof.cpp @@ -21,11 +21,9 @@ #include "../kernel.h" -using namespace UniversalAsynchronousReceiverTransmitter; - static inline nsa NIF void gprof_uart_wrapper(char c, void *unused) { - UART(COM2).Write(c); + UNUSED(c); UNUSED(unused); }