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";
new() -> Arc<Self>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
inner(&self) -> SpinLockGuard<InnerCmosRtc>62 fn inner(&self) -> SpinLockGuard<InnerCmosRtc> {
63 self.inner.lock()
64 }
65
66 ///置位0x70的第7位,禁止不可屏蔽中断
67 #[inline]
read_cmos(&self, addr: u8) -> u868 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 {
class_ops(&self) -> &'static dyn RtcClassOps85 fn class_ops(&self) -> &'static dyn RtcClassOps {
86 &CmosRtcClassOps
87 }
88 }
89
90 impl PlatformDevice for CmosRtcDevice {
pdev_name(&self) -> &str91 fn pdev_name(&self) -> &str {
92 Self::NAME
93 }
94
set_pdev_id(&self, _id: i32)95 fn set_pdev_id(&self, _id: i32) {
96 todo!()
97 }
98
set_pdev_id_auto(&self, _id_auto: bool)99 fn set_pdev_id_auto(&self, _id_auto: bool) {
100 todo!()
101 }
102
is_initialized(&self) -> bool103 fn is_initialized(&self) -> bool {
104 self.inner().device_state == DeviceState::Initialized
105 }
106
set_state(&self, set_state: DeviceState)107 fn set_state(&self, set_state: DeviceState) {
108 self.inner().device_state = set_state;
109 }
110 }
111
112 impl Device for CmosRtcDevice {
dev_type(&self) -> DeviceType113 fn dev_type(&self) -> DeviceType {
114 DeviceType::Rtc
115 }
116
id_table(&self) -> IdTable117 fn id_table(&self) -> IdTable {
118 IdTable::new(Self::NAME.to_string(), None)
119 }
120
set_bus(&self, bus: Option<Weak<dyn Bus>>)121 fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
122 self.inner().device_common.bus = bus;
123 }
124
set_class(&self, class: Option<Weak<dyn Class>>)125 fn set_class(&self, class: Option<Weak<dyn Class>>) {
126 self.inner().device_common.class = class;
127 }
128
class(&self) -> Option<Arc<dyn Class>>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
driver(&self) -> Option<Arc<dyn Driver>>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
set_driver(&self, driver: Option<Weak<dyn Driver>>)143 fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
144 self.inner().device_common.driver = driver;
145 }
146
is_dead(&self) -> bool147 fn is_dead(&self) -> bool {
148 self.inner().device_common.dead
149 }
150
can_match(&self) -> bool151 fn can_match(&self) -> bool {
152 self.inner().device_common.can_match
153 }
154
set_can_match(&self, can_match: bool)155 fn set_can_match(&self, can_match: bool) {
156 self.inner().device_common.can_match = can_match;
157 }
158
state_synced(&self) -> bool159 fn state_synced(&self) -> bool {
160 true
161 }
162
bus(&self) -> Option<Weak<dyn Bus>>163 fn bus(&self) -> Option<Weak<dyn Bus>> {
164 self.inner().device_common.get_bus_weak_or_clear()
165 }
166
dev_parent(&self) -> Option<Weak<dyn Device>>167 fn dev_parent(&self) -> Option<Weak<dyn Device>> {
168 self.inner().device_common.get_parent_weak_or_clear()
169 }
170
set_dev_parent(&self, parent: Option<Weak<dyn Device>>)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 {
as_any_ref(&self) -> &dyn Any177 fn as_any_ref(&self) -> &dyn Any {
178 self
179 }
180
set_inode(&self, inode: Option<Arc<KernFSInode>>)181 fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
182 self.inner().kobject_common.kern_inode = inode;
183 }
184
inode(&self) -> Option<Arc<KernFSInode>>185 fn inode(&self) -> Option<Arc<KernFSInode>> {
186 self.inner().kobject_common.kern_inode.clone()
187 }
188
parent(&self) -> Option<Weak<dyn KObject>>189 fn parent(&self) -> Option<Weak<dyn KObject>> {
190 self.inner().kobject_common.get_parent_or_clear_weak()
191 }
192
set_parent(&self, parent: Option<Weak<dyn KObject>>)193 fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
194 self.inner().kobject_common.parent = parent;
195 }
196
kset(&self) -> Option<Arc<KSet>>197 fn kset(&self) -> Option<Arc<KSet>> {
198 self.inner().kobject_common.kset.clone()
199 }
200
set_kset(&self, kset: Option<Arc<KSet>>)201 fn set_kset(&self, kset: Option<Arc<KSet>>) {
202 self.inner().kobject_common.kset = kset;
203 }
204
kobj_type(&self) -> Option<&'static dyn KObjType>205 fn kobj_type(&self) -> Option<&'static dyn KObjType> {
206 self.inner().kobject_common.kobj_type
207 }
208
set_kobj_type(&self, ktype: Option<&'static dyn KObjType>)209 fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
210 self.inner().kobject_common.kobj_type = ktype;
211 }
212
name(&self) -> String213 fn name(&self) -> String {
214 Self::NAME.to_string()
215 }
216
set_name(&self, _name: String)217 fn set_name(&self, _name: String) {
218 // Do nothing
219 }
220
kobj_state(&self) -> RwLockReadGuard<KObjectState>221 fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
222 self.locked_kobjstate.read()
223 }
224
kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState>225 fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
226 self.locked_kobjstate.write()
227 }
228
set_kobj_state(&self, state: KObjectState)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 {
read_time(&self, dev: &Arc<dyn RtcDevice>) -> Result<RtcTime, SystemError>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
set_time(&self, _dev: &Arc<dyn RtcDevice>, _time: &RtcTime) -> Result<(), SystemError>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)]
cmos_rtc_device_init() -> Result<(), SystemError>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