xref: /DragonOS/kernel/src/arch/x86_64/driver/rtc.rs (revision 55e6f0b65f91b32638fd56581f711a816eccdcd1)
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     fn dev_parent(&self) -> Option<Weak<dyn Device>> {
168         self.inner().device_common.get_parent_weak_or_clear()
169     }
170 
171     fn set_dev_parent(&self, parent: Option<Weak<dyn Device>>) {
172         self.inner().device_common.parent = parent;
173     }
174 }
175 
176 impl KObject for CmosRtcDevice {
177     fn as_any_ref(&self) -> &dyn Any {
178         self
179     }
180 
181     fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
182         self.inner().kobject_common.kern_inode = inode;
183     }
184 
185     fn inode(&self) -> Option<Arc<KernFSInode>> {
186         self.inner().kobject_common.kern_inode.clone()
187     }
188 
189     fn parent(&self) -> Option<Weak<dyn KObject>> {
190         self.inner().kobject_common.get_parent_or_clear_weak()
191     }
192 
193     fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
194         self.inner().kobject_common.parent = parent;
195     }
196 
197     fn kset(&self) -> Option<Arc<KSet>> {
198         self.inner().kobject_common.kset.clone()
199     }
200 
201     fn set_kset(&self, kset: Option<Arc<KSet>>) {
202         self.inner().kobject_common.kset = kset;
203     }
204 
205     fn kobj_type(&self) -> Option<&'static dyn KObjType> {
206         self.inner().kobject_common.kobj_type
207     }
208 
209     fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
210         self.inner().kobject_common.kobj_type = ktype;
211     }
212 
213     fn name(&self) -> String {
214         Self::NAME.to_string()
215     }
216 
217     fn set_name(&self, _name: String) {
218         // Do nothing
219     }
220 
221     fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
222         self.locked_kobjstate.read()
223     }
224 
225     fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
226         self.locked_kobjstate.write()
227     }
228 
229     fn set_kobj_state(&self, state: KObjectState) {
230         *self.locked_kobjstate.write() = state;
231     }
232 }
233 
234 #[derive(Debug)]
235 pub struct CmosRtcClassOps;
236 
237 impl RtcClassOps for CmosRtcClassOps {
238     fn read_time(&self, dev: &Arc<dyn RtcDevice>) -> Result<RtcTime, SystemError> {
239         // 检查是否为cmos rtc
240         let dev = dev
241             .as_any_ref()
242             .downcast_ref::<CmosRtcDevice>()
243             .ok_or(SystemError::EINVAL)?;
244 
245         let _guard = dev.ops_mutex.lock();
246 
247         // 为防止中断请求打断该过程,需要先关中断
248         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
249         //0x0B
250         let status_register_b: u8 = dev.read_cmos(0x0B); // 读取状态寄存器B
251         let is_24h: bool = (status_register_b & 0x02) != 0;
252         // 判断是否启用24小时模式
253         let is_binary: bool = (status_register_b & 0x04) != 0; // 判断是否为二进制码
254         let mut res = RtcTime::default();
255 
256         loop {
257             res.year = dev.read_cmos(CMOSTimeSelector::Year as u8) as i32;
258             res.month = dev.read_cmos(CMOSTimeSelector::Month as u8) as i32;
259             res.mday = dev.read_cmos(CMOSTimeSelector::Day as u8) as i32;
260             res.hour = dev.read_cmos(CMOSTimeSelector::Hour as u8) as i32;
261             res.minute = dev.read_cmos(CMOSTimeSelector::Minute as u8) as i32;
262             res.second = dev.read_cmos(CMOSTimeSelector::Second as u8) as i32;
263 
264             if res.second == dev.read_cmos(CMOSTimeSelector::Second as u8) as i32 {
265                 break;
266             } // 若读取时间过程中时间发生跳变则重新读取
267         }
268 
269         unsafe {
270             CurrentPortIOArch::out8(0x70, 0x00);
271         }
272 
273         if !is_binary
274         // 把BCD转为二进制
275         {
276             res.second = (res.second & 0xf) + (res.second >> 4) * 10;
277             res.minute = (res.minute & 0xf) + (res.minute >> 4) * 10;
278             res.hour = ((res.hour & 0xf) + ((res.hour & 0x70) >> 4) * 10) | (res.hour & 0x80);
279             res.mday = (res.mday & 0xf) + ((res.mday / 16) * 10);
280             res.month = (res.month & 0xf) + (res.month >> 4) * 10;
281             res.year = (res.year & 0xf) + (res.year >> 4) * 10;
282         }
283         res.year += 100;
284 
285         if (!is_24h) && (res.hour & 0x80) != 0 {
286             res.hour = ((res.hour & 0x7f) + 12) % 24;
287         } // 将十二小时制转为24小时
288 
289         res.month -= 1;
290 
291         drop(irq_guard);
292 
293         return Ok(res);
294     }
295 
296     fn set_time(&self, _dev: &Arc<dyn RtcDevice>, _time: &RtcTime) -> Result<(), SystemError> {
297         error!("set_time is not implemented for CmosRtcClassOps");
298         Err(SystemError::ENOSYS)
299     }
300 }
301 
302 /// used in the form of u8
303 #[repr(u8)]
304 enum CMOSTimeSelector {
305     Second = 0x00,
306     Minute = 0x02,
307     Hour = 0x04,
308     Day = 0x07,
309     Month = 0x08,
310     Year = 0x09,
311 }
312 
313 #[unified_init(INITCALL_DEVICE)]
314 pub fn cmos_rtc_device_init() -> Result<(), SystemError> {
315     let device = CmosRtcDevice::new();
316     device_manager().device_default_initialize(&(device.clone() as Arc<dyn Device>));
317     platform_device_manager().device_add(device)?;
318 
319     return Ok(());
320 }
321