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,
- }
|