xref: /DragonOS/kernel/src/arch/x86_64/driver/rtc.rs (revision f79998f626801329580c782fd05e36cb2027f474)
1 use core::any::Any;
2 
3 use alloc::{
4     string::{String, ToString},
5     sync::{Arc, Weak},
6 };
7 use log::error;
8 use system_error::SystemError;
9 use unified_init::macros::unified_init;
10 
11 use crate::{
12     arch::{io::PortIOArch, CurrentIrqArch, CurrentPortIOArch},
13     driver::{
14         base::{
15             class::Class,
16             device::{
17                 bus::Bus, device_manager, driver::Driver, Device, DeviceCommonData, DeviceState,
18                 DeviceType, IdTable,
19             },
20             kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
21             kset::KSet,
22             platform::platform_device::{platform_device_manager, PlatformDevice},
23         },
24         rtc::{RtcClassOps, RtcDevice, RtcTime},
25     },
26     exception::InterruptArch,
27     filesystem::kernfs::KernFSInode,
28     init::initcall::INITCALL_DEVICE,
29     libs::{
30         mutex::Mutex,
31         rwlock::{RwLockReadGuard, RwLockWriteGuard},
32         spinlock::{SpinLock, SpinLockGuard},
33     },
34 };
35 
36 #[derive(Debug)]
37 #[cast_to([sync] Device, PlatformDevice, RtcDevice)]
38 struct CmosRtcDevice {
39     inner: SpinLock<InnerCmosRtc>,
40     locked_kobjstate: LockedKObjectState,
41     ops_mutex: Mutex<()>,
42 }
43 
44 impl CmosRtcDevice {
45     const NAME: &str = "rtc_cmos";
46     pub fn new() -> Arc<Self> {
47         let r = CmosRtcDevice {
48             inner: SpinLock::new(InnerCmosRtc {
49                 device_common: DeviceCommonData::default(),
50                 kobject_common: KObjectCommonData::default(),
51                 device_state: DeviceState::NotInitialized,
52             }),
53             locked_kobjstate: LockedKObjectState::new(None),
54             ops_mutex: Mutex::new(()),
55         };
56 
57         r.inner().device_common.can_match = true;
58 
59         Arc::new(r)
60     }
61 
62     fn inner(&self) -> SpinLockGuard<InnerCmosRtc> {
63         self.inner.lock()
64     }
65 
66     ///置位0x70的第7位,禁止不可屏蔽中断
67     #[inline]
68     fn read_cmos(&self, addr: u8) -> u8 {
69         unsafe {
70             CurrentPortIOArch::out8(0x70, 0x80 | addr);
71             return CurrentPortIOArch::in8(0x71);
72         }
73     }
74 }
75 
76 #[derive(Debug)]
77 struct InnerCmosRtc {
78     device_common: DeviceCommonData,
79     kobject_common: KObjectCommonData,
80 
81     device_state: DeviceState,
82 }
83 
84 impl RtcDevice for CmosRtcDevice {
85     fn class_ops(&self) -> &'static dyn RtcClassOps {
86         &CmosRtcClassOps
87     }
88 }
89 
90 impl PlatformDevice for CmosRtcDevice {
91     fn pdev_name(&self) -> &str {
92         Self::NAME
93     }
94 
95     fn set_pdev_id(&self, _id: i32) {
96         todo!()
97     }
98 
99     fn set_pdev_id_auto(&self, _id_auto: bool) {
100         todo!()
101     }
102 
103     fn is_initialized(&self) -> bool {
104         self.inner().device_state == DeviceState::Initialized
105     }
106 
107     fn set_state(&self, set_state: DeviceState) {
108         self.inner().device_state = set_state;
109     }
110 }
111 
112 impl Device for CmosRtcDevice {
113     fn dev_type(&self) -> DeviceType {
114         DeviceType::Rtc
115     }
116 
117     fn id_table(&self) -> IdTable {
118         IdTable::new(Self::NAME.to_string(), None)
119     }
120 
121     fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
122         self.inner().device_common.bus = bus;
123     }
124 
125     fn set_class(&self, class: Option<Weak<dyn Class>>) {
126         self.inner().device_common.class = class;
127     }
128 
129     fn class(&self) -> Option<Arc<dyn Class>> {
130         self.inner()
131             .device_common
132             .get_class_weak_or_clear()
133             .and_then(|c| c.upgrade())
134     }
135 
136     fn driver(&self) -> Option<Arc<dyn Driver>> {
137         self.inner()
138             .device_common
139             .get_driver_weak_or_clear()
140             .and_then(|d| d.upgrade())
141     }
142 
143     fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
144         self.inner().device_common.driver = driver;
145     }
146 
147     fn is_dead(&self) -> bool {
148         self.inner().device_common.dead
149     }
150 
151     fn can_match(&self) -> bool {
152         self.inner().device_common.can_match
153     }
154 
155     fn set_can_match(&self, can_match: bool) {
156         self.inner().device_common.can_match = can_match;
157     }
158 
159     fn state_synced(&self) -> bool {
160         true
161     }
162 
163     fn bus(&self) -> Option<Weak<dyn Bus>> {
164         self.inner().device_common.get_bus_weak_or_clear()
165     }
166 }
167 
168 impl KObject for CmosRtcDevice {
169     fn as_any_ref(&self) -> &dyn Any {
170         self
171     }
172 
173     fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
174         self.inner().kobject_common.kern_inode = inode;
175     }
176 
177     fn inode(&self) -> Option<Arc<KernFSInode>> {
178         self.inner().kobject_common.kern_inode.clone()
179     }
180 
181     fn parent(&self) -> Option<Weak<dyn KObject>> {
182         self.inner().kobject_common.get_parent_or_clear_weak()
183     }
184 
185     fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
186         self.inner().kobject_common.parent = parent;
187     }
188 
189     fn kset(&self) -> Option<Arc<KSet>> {
190         self.inner().kobject_common.kset.clone()
191     }
192 
193     fn set_kset(&self, kset: Option<Arc<KSet>>) {
194         self.inner().kobject_common.kset = kset;
195     }
196 
197     fn kobj_type(&self) -> Option<&'static dyn KObjType> {
198         self.inner().kobject_common.kobj_type
199     }
200 
201     fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
202         self.inner().kobject_common.kobj_type = ktype;
203     }
204 
205     fn name(&self) -> String {
206         Self::NAME.to_string()
207     }
208 
209     fn set_name(&self, _name: String) {
210         // Do nothing
211     }
212 
213     fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
214         self.locked_kobjstate.read()
215     }
216 
217     fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
218         self.locked_kobjstate.write()
219     }
220 
221     fn set_kobj_state(&self, state: KObjectState) {
222         *self.locked_kobjstate.write() = state;
223     }
224 }
225 
226 #[derive(Debug)]
227 pub struct CmosRtcClassOps;
228 
229 impl RtcClassOps for CmosRtcClassOps {
230     fn read_time(&self, dev: &Arc<dyn RtcDevice>) -> Result<RtcTime, SystemError> {
231         // 检查是否为cmos rtc
232         let dev = dev
233             .as_any_ref()
234             .downcast_ref::<CmosRtcDevice>()
235             .ok_or(SystemError::EINVAL)?;
236 
237         let _guard = dev.ops_mutex.lock();
238 
239         // 为防止中断请求打断该过程,需要先关中断
240         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
241         //0x0B
242         let status_register_b: u8 = dev.read_cmos(0x0B); // 读取状态寄存器B
243         let is_24h: bool = (status_register_b & 0x02) != 0;
244         // 判断是否启用24小时模式
245         let is_binary: bool = (status_register_b & 0x04) != 0; // 判断是否为二进制码
246         let mut res = RtcTime::default();
247 
248         loop {
249             res.year = dev.read_cmos(CMOSTimeSelector::Year as u8) as i32;
250             res.month = dev.read_cmos(CMOSTimeSelector::Month as u8) as i32;
251             res.mday = dev.read_cmos(CMOSTimeSelector::Day as u8) as i32;
252             res.hour = dev.read_cmos(CMOSTimeSelector::Hour as u8) as i32;
253             res.minute = dev.read_cmos(CMOSTimeSelector::Minute as u8) as i32;
254             res.second = dev.read_cmos(CMOSTimeSelector::Second as u8) as i32;
255 
256             if res.second == dev.read_cmos(CMOSTimeSelector::Second as u8) as i32 {
257                 break;
258             } // 若读取时间过程中时间发生跳变则重新读取
259         }
260 
261         unsafe {
262             CurrentPortIOArch::out8(0x70, 0x00);
263         }
264 
265         if !is_binary
266         // 把BCD转为二进制
267         {
268             res.second = (res.second & 0xf) + (res.second >> 4) * 10;
269             res.minute = (res.minute & 0xf) + (res.minute >> 4) * 10;
270             res.hour = ((res.hour & 0xf) + ((res.hour & 0x70) >> 4) * 10) | (res.hour & 0x80);
271             res.mday = (res.mday & 0xf) + ((res.mday / 16) * 10);
272             res.month = (res.month & 0xf) + (res.month >> 4) * 10;
273             res.year = (res.year & 0xf) + (res.year >> 4) * 10;
274         }
275         res.year += 100;
276 
277         if (!is_24h) && (res.hour & 0x80) != 0 {
278             res.hour = ((res.hour & 0x7f) + 12) % 24;
279         } // 将十二小时制转为24小时
280 
281         res.month -= 1;
282 
283         drop(irq_guard);
284 
285         return Ok(res);
286     }
287 
288     fn set_time(&self, _dev: &Arc<dyn RtcDevice>, _time: &RtcTime) -> Result<(), SystemError> {
289         error!("set_time is not implemented for CmosRtcClassOps");
290         Err(SystemError::ENOSYS)
291     }
292 }
293 
294 /// used in the form of u8
295 #[repr(u8)]
296 enum CMOSTimeSelector {
297     Second = 0x00,
298     Minute = 0x02,
299     Hour = 0x04,
300     Day = 0x07,
301     Month = 0x08,
302     Year = 0x09,
303 }
304 
305 #[unified_init(INITCALL_DEVICE)]
306 pub fn cmos_rtc_device_init() -> Result<(), SystemError> {
307     let device = CmosRtcDevice::new();
308     device_manager().device_default_initialize(&(device.clone() as Arc<dyn Device>));
309     platform_device_manager().device_add(device)?;
310 
311     return Ok(());
312 }
313