Skip to content

Commit

Permalink
Add try_create and loopback_test for SerialPort
Browse files Browse the repository at this point in the history
  • Loading branch information
Wasabi375 committed Oct 5, 2023
1 parent 378d468 commit 6c5e129
Showing 1 changed file with 59 additions and 0 deletions.
59 changes: 59 additions & 0 deletions src/port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,65 @@ impl SerialPort {
Self(base)
}

/// Creates a new serial port interface on the given I/O base port and initializes it.
///
/// This function returns `Err(())` if the serial port fails a simple loopback test.
///
/// This function is unsafe because the caller must ensure that the given base address
/// really points to a serial port device and that the caller has the necessary rights
/// to perform the I/O operation.
pub unsafe fn try_create(base: u16) -> Result<Self, ()> {
let mut port = unsafe { Self::new(base) };

port.init();

port.loopback_test()?;

Ok(port)
}

/// Tests that the serial port is working.
///
/// This function temporarily sets the serial port into loopback mode and
/// performse a simple write and read, checking that the same
/// value is read. If not this function returns `Err(())`.
pub fn loopback_test(&mut self) -> Result<(), ()> {
self.loopback_test_with(0xae)
}

/// Tests that the serial port is working.
///
/// This function temporarily sets the serial port into loopback mode and
/// performse a simple write of `data` and read, checking that the same
/// value is read. If not this function returns `Err(())`.
pub fn loopback_test_with(&mut self, data: u8) -> Result<(), ()> {
unsafe {
// Disable interrupts
x86::io::outb(self.port_int_en(), 0x00);

// Set the serial port into loopback mode
x86::io::outb(self.port_modem_ctrl(), 0x1e);

// write `data` to the data port
x86::io::outb(self.port_data(), data);

// read back the value we just wrote
let loopback = x86::io::inb(self.port_data());
if loopback != data {
return Err(());
}

// Mark data terminal ready, signal request to send
// and enable auxilliary output #2 (used as interrupt line for CPU)
x86::io::outb(self.port_modem_ctrl(), 0x0b);

// Enable interrupts
x86::io::outb(self.port_int_en(), 0x01);
}

Ok(())
}

/// Initializes the serial port.
///
/// The default configuration of [38400/8-N-1](https://en.wikipedia.org/wiki/8-N-1) is used.
Expand Down

0 comments on commit 6c5e129

Please sign in to comment.