kernel/uart: Refactor code

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
EnderIce2 2024-12-23 03:52:26 +02:00
parent 0807ea5a9a
commit 81af8a48cb
No known key found for this signature in database
GPG Key ID: 2EE20AF089811A5A
10 changed files with 102 additions and 249 deletions

View File

@ -27,48 +27,9 @@ NewLock(DebuggerLock);
extern bool serialports[8]; 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; uart.DebugWrite(c);
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);
} }
static inline NIF bool WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, va_list args) static inline NIF bool WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, va_list args)

View File

@ -16,33 +16,22 @@
*/ */
#include <uart.hpp> #include <uart.hpp>
#include <io.h>
#include <debug.h> namespace UART
#include <vector>
bool serialports[8] = {false, false, false, false, false, false, false, false};
std::vector<UniversalAsynchronousReceiverTransmitter::Events *> RegisteredEvents;
#if defined(__amd64__) || defined(__i386__)
NIF __always_inline inline uint8_t NoProfiler_inportb(uint16_t Port)
{ {
uint8_t Result; enum SerialPorts
asm("in %%dx, %%al" {
: "=a"(Result) COM1 = 0x3F8,
: "d"(Port)); COM2 = 0x2F8,
return Result; 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_ENABLE_DLAB 0x80
#define SERIAL_RATE_115200_LO 0x01 #define SERIAL_RATE_115200_LO 0x01
#define SERIAL_RATE_115200_HI 0x00 #define SERIAL_RATE_115200_HI 0x00
@ -52,137 +41,96 @@ namespace UniversalAsynchronousReceiverTransmitter
#define SERIAL_RATE_38400_HI 0x00 #define SERIAL_RATE_38400_HI 0x00
#define SERIAL_BUFFER_EMPTY 0x20 #define SERIAL_BUFFER_EMPTY 0x20
/* TODO: Serial Port implementation needs reword. https://wiki.osdev.org/Serial_Ports */ void Driver::DebugWrite(uint8_t Char)
nsa NIF UART::UART(SerialPorts Port)
{ {
#if defined(__amd64__) || defined(__i386__) if (!DebugAvailable)
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)
return; return;
#if defined(__amd64__) || defined(__i386__) #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 #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; return 0;
#if defined(__amd64__) || defined(__i386__) #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 #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__) #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 #endif
}
}
} }
nsa NIF Events::Events(SerialPorts Port) uint8_t Driver::TTYRead()
{ {
this->Port = Port; if (!TTYAvailable)
RegisteredEvents.push_back(this); 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) // Initialize the serial port
{ outb(s_cst(uint16_t, Port + 1), 0x00); // Disable all interrupts
RegisteredEvents.erase(itr); outb(s_cst(uint16_t, Port + 3), SERIAL_ENABLE_DLAB); // Enable DLAB (set baud rate divisor)
return; 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() {}
} }

View File

@ -20,70 +20,24 @@
#include <types.h> #include <types.h>
namespace UniversalAsynchronousReceiverTransmitter namespace UART
{ {
/** class Driver
* @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
{ {
private: private:
SerialPorts Port; bool DebugAvailable = false;
bool IsAvailable; bool TTYAvailable = false;
public: public:
UART(SerialPorts Port = COMNULL); Driver();
~UART(); ~Driver();
void Write(uint8_t Char);
uint8_t Read(); 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__ #endif // !__FENNIX_KERNEL_UART_H__

View File

@ -23,7 +23,6 @@
#include <ints.hpp> #include <ints.hpp>
#include <printf.h> #include <printf.h>
#include <lock.hpp> #include <lock.hpp>
#include <uart.hpp>
#include <kcon.hpp> #include <kcon.hpp>
#include <debug.h> #include <debug.h>
#include <smp.hpp> #include <smp.hpp>
@ -60,6 +59,7 @@ Time::time *TimeManager = nullptr;
Tasking::Task *TaskManager = nullptr; Tasking::Task *TaskManager = nullptr;
PCI::Manager *PCIManager = nullptr; PCI::Manager *PCIManager = nullptr;
Driver::Manager *DriverManager = nullptr; Driver::Manager *DriverManager = nullptr;
UART::Driver uart;
EXTERNC void putchar(char c) EXTERNC void putchar(char c)
{ {
@ -67,7 +67,7 @@ EXTERNC void putchar(char c)
if (vt != nullptr) if (vt != nullptr)
vt->Process(c); vt->Process(c);
else else
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(c); uart.DebugWrite(c);
} }
EXTERNC void _KPrint(const char *Format, va_list Args) EXTERNC void _KPrint(const char *Format, va_list Args)

View File

@ -33,6 +33,7 @@
#include <time.hpp> #include <time.hpp>
#include <disk.hpp> #include <disk.hpp>
#include <kcon.hpp> #include <kcon.hpp>
#include <uart.hpp>
#include <tty.hpp> #include <tty.hpp>
#include <pci.hpp> #include <pci.hpp>
#include <smp.hpp> #include <smp.hpp>
@ -51,8 +52,8 @@ extern Time::time *TimeManager;
extern PCI::Manager *PCIManager; extern PCI::Manager *PCIManager;
extern vfs::Virtual *fs; extern vfs::Virtual *fs;
extern Tasking::Task *TaskManager; extern Tasking::Task *TaskManager;
extern Driver::Manager *DriverManager; extern Driver::Manager *DriverManager;
extern UART::Driver uart;
#endif // __cplusplus #endif // __cplusplus

View File

@ -25,8 +25,6 @@
NewLock(DumperLock); NewLock(DumperLock);
using namespace UniversalAsynchronousReceiverTransmitter;
int vprintf_dumper(const char *format, va_list list) { return vfctprintf(uart_wrapper, NULL, format, list); } int vprintf_dumper(const char *format, va_list list) { return vfctprintf(uart_wrapper, NULL, format, list); }
void WriteRaw(const char *format, ...) void WriteRaw(const char *format, ...)

View File

@ -27,8 +27,6 @@ TODO: This code is a mess. It needs to be cleaned up.
#include <printf.h> #include <printf.h>
#include <lock.hpp> #include <lock.hpp>
using namespace UniversalAsynchronousReceiverTransmitter;
NewLock(netdbg_lock); NewLock(netdbg_lock);
namespace NetDbg namespace NetDbg

View File

@ -25,14 +25,11 @@ bool EnableProfiler = false;
bool Wait = false; bool Wait = false;
unsigned long long LogDepth = 0; unsigned long long LogDepth = 0;
unsigned int Level = 0; unsigned int Level = 0;
using namespace UniversalAsynchronousReceiverTransmitter;
UART com2(COM2);
static inline nsa NIF void profiler_uart_wrapper(char c, void *unused) static inline nsa NIF void profiler_uart_wrapper(char c, void *unused)
{ {
bool renable = EnableProfiler; bool renable = EnableProfiler;
EnableProfiler = false; EnableProfiler = false;
com2.Write(c);
UNUSED(unused); UNUSED(unused);
if (renable) if (renable)
EnableProfiler = true; EnableProfiler = true;

View File

@ -21,8 +21,6 @@
#include "../kernel.h" #include "../kernel.h"
using namespace UniversalAsynchronousReceiverTransmitter;
#if BITS_PER_LONG >= 64 #if BITS_PER_LONG >= 64
typedef long gcov_type; typedef long gcov_type;
#else #else
@ -57,7 +55,7 @@ struct gcov_info
static inline nsa NIF void gcov_uart_wrapper(char c, void *unused) static inline nsa NIF void gcov_uart_wrapper(char c, void *unused)
{ {
UART(COM2).Write(c); UNUSED(c);
UNUSED(unused); UNUSED(unused);
} }

View File

@ -21,11 +21,9 @@
#include "../kernel.h" #include "../kernel.h"
using namespace UniversalAsynchronousReceiverTransmitter;
static inline nsa NIF void gprof_uart_wrapper(char c, void *unused) static inline nsa NIF void gprof_uart_wrapper(char c, void *unused)
{ {
UART(COM2).Write(c); UNUSED(c);
UNUSED(unused); UNUSED(unused);
} }