kernel/logging/x86_64/
serial.rs1use core::sync::atomic::{AtomicBool, Ordering};
7use x86_64::instructions::port::Port;
8use crate::logging::_serial::{SerialPort, _Serial};
9
10static COM1_BASE_ADDRESS: u16 = 0x03F8;
11static COM2_BASE_ADDRESS: u16 = 0x02F8;
12static COM3_BASE_ADDRESS: u16 = 0x03E8;
13static COM4_BASE_ADDRESS: u16 = 0x02E8;
14
15pub struct Serial {
17 initialized: AtomicBool,
18 base_addr: u16,
20}
21
22impl _Serial for Serial {
23 fn new(port: SerialPort) -> Self {
24 let base_address = match port {
25 SerialPort::Serial1 => { COM1_BASE_ADDRESS }
26 SerialPort::Serial2 => { COM2_BASE_ADDRESS }
27 SerialPort::Serial3 => { COM3_BASE_ADDRESS }
28 SerialPort::Serial4 => { COM4_BASE_ADDRESS }
29 };
30
31 Self {
32 initialized: AtomicBool::new(false),
33 base_addr: base_address,
34 }
35 }
36
37 fn init(&self) -> Result<(), &'static str> {
38 unsafe {
46 if self.initialized.load(Ordering::Acquire) {
47 return Err("Serial is already initialized");
48 }
49
50 self.initialized.store(true, Ordering::Relaxed);
51
52 at_offset(self.base_addr, 1).write(0x00); at_offset(self.base_addr, 3).write(0x80); at_offset(self.base_addr, 0).write(0x01); at_offset(self.base_addr, 1).write(0x00); at_offset(self.base_addr, 3).write(0x03); at_offset(self.base_addr, 2).write(0xC7); at_offset(self.base_addr, 4).write(0x0B); Ok(())
61 }
62 }
63
64 fn write(&self, string: &str) {
65 let mut port: Port<u8> = Port::new(self.base_addr);
66
67 for byte in string.bytes() {
68 unsafe {
71 while at_offset(self.base_addr, 5).read() & 0x20 == 0 {
73 core::hint::spin_loop();
74 }
75 port.write(byte);
76 }
77 }
78 }
79}
80
81fn at_offset(base_addr: u16, offset: u16) -> Port<u8> {
83 Port::new(base_addr + offset)
84}