Files
bsb2/kernel/arch/serial.cc
Niklas Gollenstede 174fe17e89 Handout
2025-10-31 22:37:36 +01:00

56 lines
1.7 KiB
C++

#include "serial.h"
#include "ioport.h"
Serial::Serial(ComPort port, BaudRate baud_rate, DataBits data_bits,
StopBits stop_bits, Parity parity)
: port(port) {
// initialize FIFO mode, no irqs for sending, irq if first byte was received
// line control, select r/w of divisor latch register
writeReg(RegisterIndex::LINE_CONTROL,
static_cast<uint8_t>(RegisterMask::DIVISOR_LATCH_ACCESS_BIT));
// config divisor
uint16_t divisor = static_cast<uint16_t>(baud_rate);
// write low byte of divisor latch
writeReg(RegisterIndex::DIVISOR_LOW, divisor & 0xff);
// write high byte
writeReg(RegisterIndex::DIVISOR_HIGH, (divisor >> 8) & 0xff);
// deselect r/w of divisor latch register
// configure line control
writeReg(RegisterIndex::LINE_CONTROL, static_cast<uint8_t>(data_bits) |
static_cast<uint8_t>(stop_bits) |
static_cast<uint8_t>(parity));
// FIFO: Enable & clear buffers
writeReg(RegisterIndex::FIFO_CONTROL,
static_cast<uint8_t>(RegisterMask::ENABLE_FIFO) |
static_cast<uint8_t>(RegisterMask::CLEAR_RECEIVE_FIFO) |
static_cast<uint8_t>(RegisterMask::CLEAR_TRANSMIT_FIFO));
// Modem Control: OUT2 (0000 1000) must be set for interrupt
writeReg(RegisterIndex::MODEM_CONTROL,
static_cast<uint8_t>(RegisterMask::OUT_2));
}
void Serial::writeReg(RegisterIndex reg, uint8_t out) {
IOPort p(static_cast<uint16_t>(port) + static_cast<uint16_t>(reg));
p.outb(out);
}
uint8_t Serial::readReg(RegisterIndex reg) {
IOPort p(static_cast<uint16_t>(port) + static_cast<uint16_t>(reg));
return p.inb();
}
int Serial::write(uint8_t out) {
while ((readReg(RegisterIndex::LINE_STATUS) &
static_cast<uint8_t>(RegisterMask::TRANSMITTER_EMPTY)) == 0) {
}
writeReg(RegisterIndex::TRANSMIT_BUFFER, out);
return out;
}