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