Add documentation to x86/device

This commit is contained in:
Yuke Peng 2024-06-03 16:11:06 +08:00 committed by Tate, Hongliang Tian
parent c71ff237bc
commit 0970adb37b
5 changed files with 61 additions and 18 deletions

View File

@ -2,12 +2,12 @@
use core::sync::atomic::{AtomicU8, Ordering::Relaxed};
use ostd::arch::x86::device::cmos::{get_century_register, CMOS_ADDRESS, CMOS_DATA};
use ostd::arch::x86::device::cmos::{century_register, CMOS_ADDRESS, CMOS_DATA};
pub(crate) static CENTURY_REGISTER: AtomicU8 = AtomicU8::new(0);
pub fn init() {
let Some(century_register) = get_century_register() else {
let Some(century_register) = century_register() else {
return;
};
CENTURY_REGISTER.store(century_register, Relaxed);

View File

@ -96,7 +96,7 @@ fn handle_serial_input(trap_frame: &TrapFrame) {
}
fn line_sts() -> LineSts {
LineSts::from_bits_truncate(CONSOLE_COM1_PORT.line_status.read())
LineSts::from_bits_truncate(CONSOLE_COM1_PORT.line_status())
}
/// Sends a byte on the serial port.
@ -104,15 +104,15 @@ pub fn send(data: u8) {
match data {
8 | 0x7F => {
while !line_sts().contains(LineSts::OUTPUT_EMPTY) {}
CONSOLE_COM1_PORT.data.write(8);
CONSOLE_COM1_PORT.send(8);
while !line_sts().contains(LineSts::OUTPUT_EMPTY) {}
CONSOLE_COM1_PORT.data.write(b' ');
CONSOLE_COM1_PORT.send(b' ');
while !line_sts().contains(LineSts::OUTPUT_EMPTY) {}
CONSOLE_COM1_PORT.data.write(8);
CONSOLE_COM1_PORT.send(8);
}
_ => {
while !line_sts().contains(LineSts::OUTPUT_EMPTY) {}
CONSOLE_COM1_PORT.data.write(data);
CONSOLE_COM1_PORT.send(data);
}
}
}
@ -120,7 +120,7 @@ pub fn send(data: u8) {
/// Receives a byte on the serial port. non-blocking
pub fn receive_char() -> Option<u8> {
if line_sts().contains(LineSts::INPUT_FULL) {
Some(CONSOLE_COM1_PORT.data.read())
Some(CONSOLE_COM1_PORT.recv())
} else {
None
}

View File

@ -1,5 +1,12 @@
// SPDX-License-Identifier: MPL-2.0
//! Provides CMOS I/O port access.
//!
//! "CMOS" is a tiny bit of very low power static memory that lives on the same chip as the Real-Time Clock (RTC).
//!
//! Reference: <https://wiki.osdev.org/CMOS>
//!
#![allow(unused_variables)]
use acpi::{fadt::Fadt, sdt::Signature};
@ -8,10 +15,14 @@ use x86_64::instructions::port::{ReadOnlyAccess, WriteOnlyAccess};
use super::io_port::IoPort;
use crate::arch::x86::kernel::acpi::ACPI_TABLES;
/// CMOS address I/O port
pub static CMOS_ADDRESS: IoPort<u8, WriteOnlyAccess> = unsafe { IoPort::new(0x70) };
/// CMOS data I/O port
pub static CMOS_DATA: IoPort<u8, ReadOnlyAccess> = unsafe { IoPort::new(0x71) };
pub fn get_century_register() -> Option<u8> {
/// Gets the century register location. This function is used in RTC(Real Time Clock) module initialization.
pub fn century_register() -> Option<u8> {
if !ACPI_TABLES.is_completed() {
return None;
}

View File

@ -1,5 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
//! I/O port access.
use core::marker::PhantomData;
pub use x86_64::{
@ -29,7 +31,7 @@ pub struct IoPort<T, A> {
}
impl<T, A> IoPort<T, A> {
/// Create an I/O port.
/// Creates an I/O port.
///
/// # Safety
///
@ -45,6 +47,7 @@ impl<T, A> IoPort<T, A> {
}
impl<T: PortRead, A: IoPortReadAccess> IoPort<T, A> {
/// Reads from the I/O port
#[inline]
pub fn read(&self) -> T {
unsafe { PortRead::read_from_port(self.port) }
@ -52,6 +55,7 @@ impl<T: PortRead, A: IoPortReadAccess> IoPort<T, A> {
}
impl<T: PortWrite, A: IoPortWriteAccess> IoPort<T, A> {
/// Writes to the I/O port
#[inline]
pub fn write(&self, value: T) {
unsafe { PortWrite::write_to_port(self.port, value) }

View File

@ -2,6 +2,8 @@
//! A port-mapped UART. Copied from uart_16550.
#![allow(dead_code)]
use crate::arch::x86::device::io_port::{IoPort, ReadWriteAccess, WriteOnlyAccess};
/// A serial port.
@ -9,17 +11,24 @@ use crate::arch::x86::device::io_port::{IoPort, ReadWriteAccess, WriteOnlyAccess
/// Serial ports are a legacy communications port common on IBM-PC compatible computers.
/// Ref: <https://wiki.osdev.org/Serial_Ports>
pub struct SerialPort {
pub data: IoPort<u8, ReadWriteAccess>,
pub int_en: IoPort<u8, WriteOnlyAccess>,
pub fifo_ctrl: IoPort<u8, WriteOnlyAccess>,
pub line_ctrl: IoPort<u8, WriteOnlyAccess>,
pub modem_ctrl: IoPort<u8, WriteOnlyAccess>,
pub line_status: IoPort<u8, ReadWriteAccess>,
pub modem_status: IoPort<u8, ReadWriteAccess>,
/// Data Register
data: IoPort<u8, ReadWriteAccess>,
/// Interrupt Enable Register
int_en: IoPort<u8, WriteOnlyAccess>,
/// First In First Out Control Register
fifo_ctrl: IoPort<u8, WriteOnlyAccess>,
/// Line control Register
line_ctrl: IoPort<u8, WriteOnlyAccess>,
/// Modem Control Register
modem_ctrl: IoPort<u8, WriteOnlyAccess>,
/// Line status Register
line_status: IoPort<u8, ReadWriteAccess>,
/// Modem Status Register
modem_status: IoPort<u8, ReadWriteAccess>,
}
impl SerialPort {
/// Create a serial port.
/// Creates a serial port.
///
/// # Safety
///
@ -43,6 +52,7 @@ impl SerialPort {
}
}
/// Initializes the serial port.
pub fn init(&self) {
// Disable interrupts
self.int_en.write(0x00);
@ -62,4 +72,22 @@ impl SerialPort {
// Enable interrupts
self.int_en.write(0x01);
}
/// Sends data to the data port
#[inline]
pub fn send(&self, data: u8) {
self.data.write(data);
}
/// Receives data from the data port
#[inline]
pub fn recv(&self) -> u8 {
self.data.read()
}
/// Gets line status
#[inline]
pub fn line_status(&self) -> u8 {
self.line_status.read()
}
}