mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-05-25 22:14:34 +00:00
kernel/uart: Refactor code
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
parent
0807ea5a9a
commit
81af8a48cb
@ -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)
|
||||
|
@ -16,33 +16,22 @@
|
||||
*/
|
||||
|
||||
#include <uart.hpp>
|
||||
#include <io.h>
|
||||
|
||||
#include <debug.h>
|
||||
#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)
|
||||
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() {}
|
||||
}
|
||||
|
@ -20,70 +20,24 @@
|
||||
|
||||
#include <types.h>
|
||||
|
||||
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__
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include <ints.hpp>
|
||||
#include <printf.h>
|
||||
#include <lock.hpp>
|
||||
#include <uart.hpp>
|
||||
#include <kcon.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
@ -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)
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <time.hpp>
|
||||
#include <disk.hpp>
|
||||
#include <kcon.hpp>
|
||||
#include <uart.hpp>
|
||||
#include <tty.hpp>
|
||||
#include <pci.hpp>
|
||||
#include <smp.hpp>
|
||||
@ -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
|
||||
|
||||
|
@ -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, ...)
|
||||
|
@ -27,8 +27,6 @@ TODO: This code is a mess. It needs to be cleaned up.
|
||||
#include <printf.h>
|
||||
#include <lock.hpp>
|
||||
|
||||
using namespace UniversalAsynchronousReceiverTransmitter;
|
||||
|
||||
NewLock(netdbg_lock);
|
||||
|
||||
namespace NetDbg
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user