95 lines
2.2 KiB
C++
95 lines
2.2 KiB
C++
#include "debug/debug.h"
|
|
|
|
#include "common/port.h"
|
|
#include "scheduler/scheduler.h"
|
|
|
|
#define COM1 0x3f8
|
|
|
|
#define BOCHS_DBG 1
|
|
|
|
namespace {
|
|
bool is_transmit_empty() { return (inb(COM1 + 5) & 0x20) != 0; }
|
|
|
|
void dbgputchar(char c) {
|
|
while (!is_transmit_empty());
|
|
|
|
outb(COM1, c);
|
|
#if BOCHS_DBG
|
|
outb(0xe9, c);
|
|
#endif
|
|
}
|
|
|
|
void dbg(const glcr::StringView& str) {
|
|
for (uint64_t i = 0; i < str.size(); i++) {
|
|
dbgputchar(str[i]);
|
|
}
|
|
}
|
|
|
|
void AddProcPrefix() {
|
|
if (gScheduler != nullptr) {
|
|
auto t = gScheduler->CurrentThread();
|
|
|
|
char buffer[16];
|
|
glcr::FixedStringBuilder builder(buffer, 16);
|
|
glcr::StrFormatIntoBuffer(builder, "[{}.{}] ", t->pid(), t->tid());
|
|
dbg(builder);
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void dbgln(const glcr::StringView& str) {
|
|
AddProcPrefix();
|
|
dbg(str);
|
|
dbg("\n");
|
|
}
|
|
|
|
namespace {
|
|
|
|
// Helper function to write a byte to a specified COM1 register offset
|
|
void write_serial_port(uint16_t offset, uint8_t value) {
|
|
outb(COM1 + offset, value);
|
|
}
|
|
|
|
// Helper function to read a byte from a specified COM1 register offset
|
|
uint8_t read_serial_port(uint16_t offset) { return inb(COM1 + offset); }
|
|
|
|
} // namespace
|
|
|
|
namespace serial {
|
|
|
|
// Function to initialize the serial port with a given baud rate
|
|
void initialize(uint32_t baud_rate) {
|
|
// Disable interrupts
|
|
write_serial_port(1, 0x00);
|
|
|
|
// Enable DLAB (Divisor Latch Access Bit) in Line Control Register (LCR)
|
|
write_serial_port(3, read_serial_port(3) | 0x80);
|
|
|
|
// Calculate the divisor
|
|
// Baud rate = 115200 / divisor (approximately)
|
|
uint16_t divisor = 115200 / baud_rate;
|
|
|
|
// Set the low byte of the divisor
|
|
write_serial_port(0, divisor & 0xFF);
|
|
|
|
// Set the high byte of the divisor
|
|
write_serial_port(1, (divisor >> 8) & 0xFF);
|
|
|
|
// Clear DLAB and set data bits, stop bits, and parity
|
|
// 8 data bits, 1 stop bit, no parity
|
|
write_serial_port(3, 0x03); // 00000011b
|
|
|
|
// Enable FIFO, clear buffers, set trigger level (e.g., 1 byte)
|
|
write_serial_port(2, 0xC7); // 11000111b
|
|
|
|
// Enable IRQs (optional, for interrupt-driven communication)
|
|
// write_serial_port(1, 0x01);
|
|
|
|
// Set Modem Control Register (MCR)
|
|
// Enable RTS, DTR, OUT1, OUT2, loopback off, IRQs enabled
|
|
write_serial_port(4, 0x0B); // 00001011b
|
|
}
|
|
|
|
} // namespace serial
|