| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 | use crate::{    arch::{io::PortIOArch, CurrentIrqArch, CurrentPortIOArch},    exception::InterruptArch,    syscall::SystemError,};pub struct RtcTime {    pub second: i32,    pub minute: i32,    pub hour: i32,    pub day: i32,    pub month: i32,    pub year: i32,}impl Default for RtcTime {    fn default() -> Self {        Self {            second: (0),            minute: (0),            hour: (0),            day: (0),            month: (0),            year: (0),        }    }}impl RtcTime {    ///@brief 从主板cmos中获取时间    ///    ///@param self time结构体    ///@return int 成功则为0    pub fn get(&mut self) -> Result<i32, SystemError> {        // 为防止中断请求打断该过程,需要先关中断        let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };        //0x0B        let status_register_b: u8 = read_cmos(0x0B); // 读取状态寄存器B        let is_24h: bool = if (status_register_b & 0x02) != 0 {            true        } else {            false        }; // 判断是否启用24小时模式        let is_binary: bool = if (status_register_b & 0x04) != 0 {            true        } else {            false        }; // 判断是否为二进制码        loop {            self.year = read_cmos(CMOSTimeSelector::Year as u8) as i32;            self.month = read_cmos(CMOSTimeSelector::Month as u8) as i32;            self.day = read_cmos(CMOSTimeSelector::Day as u8) as i32;            self.hour = read_cmos(CMOSTimeSelector::Hour as u8) as i32;            self.minute = read_cmos(CMOSTimeSelector::Minute as u8) as i32;            self.second = read_cmos(CMOSTimeSelector::Second as u8) as i32;            if self.second == read_cmos(CMOSTimeSelector::Second as u8) as i32 {                break;            } // 若读取时间过程中时间发生跳变则重新读取        }        unsafe {            CurrentPortIOArch::out8(0x70, 0x00);        }        if !is_binary        // 把BCD转为二进制        {            self.second = (self.second & 0xf) + (self.second >> 4) * 10;            self.minute = (self.minute & 0xf) + (self.minute >> 4) * 10;            self.hour = ((self.hour & 0xf) + ((self.hour & 0x70) >> 4) * 10) | (self.hour & 0x80);            self.day = (self.day & 0xf) + ((self.day / 16) * 10);            self.month = (self.month & 0xf) + (self.month >> 4) * 10;            self.year = (self.year & 0xf) + (self.year >> 4) * 10;        }        self.year += 2000;        if (!is_24h) && (self.hour & 0x80) != 0 {            self.hour = ((self.hour & 0x7f) + 12) % 24;        } // 将十二小时制转为24小时        drop(irq_guard);        return Ok(0);    }}///置位0x70的第7位,禁止不可屏蔽中断#[inline]fn read_cmos(addr: u8) -> u8 {    unsafe {        CurrentPortIOArch::out8(0x70, 0x80 | addr);        return CurrentPortIOArch::in8(0x71);    }}/// used in the form of u8#[repr(u8)]enum CMOSTimeSelector {    Second = 0x00,    Minute = 0x02,    Hour = 0x04,    Day = 0x07,    Month = 0x08,    Year = 0x09,}
 |