diff options
| author | Clément Sibille <claymeuns@protonmail.com> | 2021-10-07 21:13:55 +0200 |
|---|---|---|
| committer | Clément Sibille <claymeuns@protonmail.com> | 2021-10-07 21:14:05 +0200 |
| commit | 06d819c3e8e94972bd4261069d2c5239297bba65 (patch) | |
| tree | d14619fccb52246945212d9d75135225a020fd5d /kernel/src/serial.rs | |
| parent | 6277cf1e4fef810d08af1e1f8d64778c94007236 (diff) | |
Add support for serial port output
Diffstat (limited to 'kernel/src/serial.rs')
| -rw-r--r-- | kernel/src/serial.rs | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/kernel/src/serial.rs b/kernel/src/serial.rs new file mode 100644 index 0000000..77c15cb --- /dev/null +++ b/kernel/src/serial.rs @@ -0,0 +1,66 @@ +use crate::io::{in8, out8}; +use crate::serial::SerialError::SerialPortInitializationFailed; + +const COM1_PORT: u16 = 0x3F8; +const OFFSET_DATA_REGISTER: u8 = 0; +const OFFSET_INTERRUPT_ENABLE_REGISTER: u8 = 1; +const OFFSET_INTERRUPT_IDENTIFICATION_AND_FIFO_CONTROL_REGISTER: u8 = 2; +const OFFSET_LINE_CONTROL_REGISTER: u8 = 3; +const OFFSET_MODEM_CONTROL_REGISTER: u8 = 4; +const OFFSET_LINE_STATUS_REGISTER: u8 = 5; + +#[derive(Debug)] +pub enum SerialError { + SerialPortInitializationFailed, +} + +pub fn initialize_serial_port() -> Result<(), SerialError> { + // Safety: + // These instructions read and write data on valid COM ports + unsafe { + out8(COM1_PORT + OFFSET_INTERRUPT_ENABLE_REGISTER as u16, 0x00); + out8(COM1_PORT + OFFSET_LINE_CONTROL_REGISTER as u16, 0x80); + out8(COM1_PORT + OFFSET_DATA_REGISTER as u16, 0x03); + out8(COM1_PORT + OFFSET_INTERRUPT_ENABLE_REGISTER as u16, 0x00); + out8(COM1_PORT + OFFSET_LINE_CONTROL_REGISTER as u16, 0x03); + out8( + COM1_PORT + OFFSET_INTERRUPT_IDENTIFICATION_AND_FIFO_CONTROL_REGISTER as u16, + 0xC7, + ); + out8(COM1_PORT + OFFSET_MODEM_CONTROL_REGISTER as u16, 0x0B); + + // Testing the serial chip + out8(COM1_PORT + OFFSET_MODEM_CONTROL_REGISTER as u16, 0x1E); // Enable loopback mode + out8(COM1_PORT + OFFSET_DATA_REGISTER as u16, 0xAE); + if in8(COM1_PORT + OFFSET_DATA_REGISTER as u16) != 0xAE { + return Err(SerialPortInitializationFailed); + } + + out8(COM1_PORT + OFFSET_MODEM_CONTROL_REGISTER as u16, 0x0F); // Enable normal mode + } + + Ok(()) +} + +pub fn write(byte: u8) { + while !is_ready_to_send_data() {} + // Safety: the value is sent on a valid port address, which is the COM port + // data register address + unsafe { + out8(COM1_PORT, byte); + } +} + +pub fn write_bytes(bytes: &[u8]) { + for &byte in bytes { + write(byte); + } +} + +fn is_ready_to_send_data() -> bool { + const THRE_BIT: u8 = 0x20; + + // Safety: the value is sent on a valid port address, which is the COM port + // line status register address + return unsafe { in8(COM1_PORT + OFFSET_LINE_STATUS_REGISTER as u16) } & THRE_BIT != 0; +} |
