1 use crate::{
2     arch::interrupt::{cli, sti},
3     include::bindings::bindings::{io_in8, io_out8},
4 };
5 
6 pub struct RtcTime {
7     pub second: i32,
8     pub minute: i32,
9     pub hour: i32,
10     pub day: i32,
11     pub month: i32,
12     pub year: i32,
13 }
14 
15 impl Default for RtcTime {
default() -> Self16     fn default() -> Self {
17         Self {
18             second: (0),
19             minute: (0),
20             hour: (0),
21             day: (0),
22             month: (0),
23             year: (0),
24         }
25     }
26 }
27 
28 impl RtcTime {
29     ///@brief 从主板cmos中获取时间
30     ///
31     ///@param self time结构体
32     ///@return int 成功则为0
get(&mut self) -> Result<i32, i32>33     pub fn get(&mut self) -> Result<i32, i32> {
34         // 为防止中断请求打断该过程,需要先关中断
35         cli();
36         //0x0B
37         let status_register_b: u8 = read_cmos(0x0B); // 读取状态寄存器B
38         let is_24h: bool = if (status_register_b & 0x02) != 0 {
39             true
40         } else {
41             false
42         }; // 判断是否启用24小时模式
43 
44         let is_binary: bool = if (status_register_b & 0x04) != 0 {
45             true
46         } else {
47             false
48         }; // 判断是否为二进制码
49 
50         loop {
51             self.year = read_cmos(CMOSTimeSelector::Year as u8) as i32;
52             self.month = read_cmos(CMOSTimeSelector::Month as u8) as i32;
53             self.day = read_cmos(CMOSTimeSelector::Day as u8) as i32;
54             self.hour = read_cmos(CMOSTimeSelector::Hour as u8) as i32;
55             self.minute = read_cmos(CMOSTimeSelector::Minute as u8) as i32;
56             self.second = read_cmos(CMOSTimeSelector::Second as u8) as i32;
57 
58             if self.second == read_cmos(CMOSTimeSelector::Second as u8) as i32 {
59                 break;
60             } // 若读取时间过程中时间发生跳变则重新读取
61         }
62 
63         unsafe {
64             io_out8(0x70, 0x00);
65         }
66 
67         if !is_binary
68         // 把BCD转为二进制
69         {
70             self.second = (self.second & 0xf) + (self.second >> 4) * 10;
71             self.minute = (self.minute & 0xf) + (self.minute >> 4) * 10;
72             self.hour = ((self.hour & 0xf) + ((self.hour & 0x70) >> 4) * 10) | (self.hour & 0x80);
73             self.day = (self.day & 0xf) + ((self.day / 16) * 10);
74             self.month = (self.month & 0xf) + (self.month >> 4) * 10;
75             self.year = (self.year & 0xf) + (self.year >> 4) * 10;
76         }
77         self.year += 2000;
78 
79         if (!is_24h) && (self.hour & 0x80) != 0 {
80             self.hour = ((self.hour & 0x7f) + 12) % 24;
81         } // 将十二小时制转为24小时
82 
83         sti();
84 
85         return Ok(0);
86     }
87 }
88 
89 ///置位0x70的第7位,禁止不可屏蔽中断
90 #[inline]
read_cmos(addr: u8) -> u891 fn read_cmos(addr: u8) -> u8 {
92     unsafe {
93         io_out8(0x70, 0x80 | addr);
94         return io_in8(0x71);
95     }
96 }
97 
98 /// used in the form of u8
99 #[repr(u8)]
100 enum CMOSTimeSelector {
101     Second = 0x00,
102     Minute = 0x02,
103     Hour = 0x04,
104     Day = 0x07,
105     Month = 0x08,
106     Year = 0x09,
107 }
108