summaryrefslogtreecommitdiffstats
path: root/kernel/src/serial.rs
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/src/serial.rs')
-rw-r--r--kernel/src/serial.rs66
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;
+}
Go back to lisible.xyz