实现了rtc的抽象,并且把x86的cmos rtc接入到设备驱动模型 (#674)

* 实现了rtc的抽象,并且把x86的cmos rtc接入到设备驱动模型。
This commit is contained in:
LoGin
2024-03-28 00:28:13 +08:00
committed by GitHub
parent 597ecc08c2
commit da15231979
28 changed files with 1441 additions and 156 deletions

View File

@ -277,16 +277,14 @@ impl DriverManager {
.and_then(|bus| bus.upgrade())
.ok_or(SystemError::EINVAL)?;
for dev in bus.subsystem().devices().iter() {
if self.do_driver_attach(dev, driver) {
// 匹配成功
return Ok(());
}
self.do_driver_attach(dev, driver);
}
return Ok(());
}
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c?fi=driver_attach#1134
#[inline(never)]
fn do_driver_attach(&self, device: &Arc<dyn Device>, driver: &Arc<dyn Driver>) -> bool {
let r = self.match_device(driver, device).unwrap_or(false);
if !r {

View File

@ -109,6 +109,24 @@ pub trait Driver: Sync + Send + Debug + KObject {
}
}
#[derive(Debug, Default)]
pub struct DriverCommonData {
pub devices: Vec<Arc<dyn Device>>,
pub bus: Option<Weak<dyn Bus>>,
}
impl DriverCommonData {
pub fn push_device(&mut self, device: Arc<dyn Device>) {
if !self.devices.iter().any(|d| Arc::ptr_eq(d, &device)) {
self.devices.push(device);
}
}
pub fn delete_device(&mut self, device: &Arc<dyn Device>) {
self.devices.retain(|d| !Arc::ptr_eq(d, device));
}
}
impl dyn Driver {
pub fn allows_async_probing(&self) -> bool {
match self.probe_type() {

View File

@ -201,6 +201,51 @@ impl dyn Device {
}
}
/// 实现了Device trait的设备需要拥有的数据
#[derive(Debug)]
pub struct DeviceCommonData {
pub bus: Option<Weak<dyn Bus>>,
pub class: Option<Weak<dyn Class>>,
pub driver: Option<Weak<dyn Driver>>,
pub dead: bool,
pub can_match: bool,
}
impl Default for DeviceCommonData {
fn default() -> Self {
Self {
bus: None,
class: None,
driver: None,
dead: false,
can_match: true,
}
}
}
impl DeviceCommonData {
/// 获取bus字段
///
/// 当weak指针的strong count为0的时候清除弱引用
pub fn get_bus_weak_or_clear(&mut self) -> Option<Weak<dyn Bus>> {
driver_base_macros::get_weak_or_clear!(self.bus)
}
/// 获取class字段
///
/// 当weak指针的strong count为0的时候清除弱引用
pub fn get_class_weak_or_clear(&mut self) -> Option<Weak<dyn Class>> {
driver_base_macros::get_weak_or_clear!(self.class)
}
/// 获取driver字段
///
/// 当weak指针的strong count为0的时候清除弱引用
pub fn get_driver_weak_or_clear(&mut self) -> Option<Weak<dyn Driver>> {
driver_base_macros::get_weak_or_clear!(self.driver)
}
}
// 暂定是不可修改的,在初始化的时候就要确定。以后可能会包括例如硬件中断包含的信息
#[allow(dead_code)]
#[derive(Debug, Clone)]

View File

@ -4,6 +4,7 @@ use alloc::{
string::String,
sync::{Arc, Weak},
};
use driver_base_macros::get_weak_or_clear;
use intertrait::CastFromSync;
use crate::{
@ -73,6 +74,21 @@ impl DowncastArc for dyn KObject {
}
}
/// kobject的公共数据
#[derive(Debug, Default)]
pub struct KObjectCommonData {
pub kern_inode: Option<Arc<KernFSInode>>,
pub parent: Option<Weak<dyn KObject>>,
pub kset: Option<Arc<KSet>>,
pub kobj_type: Option<&'static dyn KObjType>,
}
impl KObjectCommonData {
pub fn get_parent_or_clear_weak(&mut self) -> Option<Weak<dyn KObject>> {
get_weak_or_clear!(self.parent)
}
}
pub trait KObjType: Debug + Send + Sync {
/// 当指定的kobject被释放时设备驱动模型会调用此方法
fn release(&self, _kobj: Arc<dyn KObject>) {}

View File

@ -61,7 +61,6 @@ pub trait PlatformDevice: Device {
/// 设置id是否为自动分配
fn set_pdev_id_auto(&self, id_auto: bool);
fn compatible_table(&self) -> CompatibleTable;
/// @brief: 判断设备是否初始化
/// @parameter: None
/// @return: 如果已经初始化返回true否则返回false

View File

@ -9,7 +9,7 @@ use crate::{
device::{bus::Bus, driver::Driver, Device, DeviceState, DeviceType, IdTable},
kobject::{KObjType, KObject, KObjectState, LockedKObjectState},
kset::KSet,
platform::{platform_device::PlatformDevice, CompatibleTable},
platform::platform_device::PlatformDevice,
},
filesystem::kernfs::KernFSInode,
libs::{
@ -184,10 +184,6 @@ impl PlatformDevice for I8042PlatformDevice {
self.inner.lock().pdev_id_auto = id_auto;
}
fn compatible_table(&self) -> CompatibleTable {
todo!()
}
fn is_initialized(&self) -> bool {
self.inner.lock().device_state == DeviceState::Initialized
}

View File

@ -8,6 +8,7 @@ pub mod keyboard;
pub mod net;
pub mod open_firmware;
pub mod pci;
pub mod rtc;
pub mod serial;
pub mod timers;
pub mod tty;

View File

@ -0,0 +1,109 @@
use alloc::{
string::ToString,
sync::{Arc, Weak},
};
use system_error::SystemError;
use unified_init::macros::unified_init;
use crate::{
driver::base::{
class::{class_manager, Class},
device::{device_manager, sys_dev_char_kset},
kobject::KObject,
subsys::SubSysPrivate,
},
init::initcall::INITCALL_SUBSYS,
time::{timekeeping::do_settimeofday64, TimeSpec},
};
use super::{interface::rtc_read_time, register_default_rtc, sysfs::RtcGeneralDevice};
/// `/sys/class/rtc` 的 class 实例
static mut CLASS_RTC_INSTANCE: Option<Arc<RtcClass>> = None;
/// 获取 `/sys/class/rtc` 的 class 实例
#[inline(always)]
#[allow(dead_code)]
pub fn sys_class_rtc_instance() -> Option<&'static Arc<RtcClass>> {
unsafe { CLASS_RTC_INSTANCE.as_ref() }
}
/// 初始化帧缓冲区子系统
#[unified_init(INITCALL_SUBSYS)]
pub fn fbmem_init() -> Result<(), SystemError> {
let rtc_class = RtcClass::new();
class_manager().class_register(&(rtc_class.clone() as Arc<dyn Class>))?;
unsafe {
CLASS_RTC_INSTANCE = Some(rtc_class);
}
return Ok(());
}
/// `/sys/class/rtc` 类
#[derive(Debug)]
pub struct RtcClass {
subsystem: SubSysPrivate,
}
impl RtcClass {
const NAME: &'static str = "rtc";
pub fn new() -> Arc<Self> {
let r = Self {
subsystem: SubSysPrivate::new(Self::NAME.to_string(), None, None, &[]),
};
let r = Arc::new(r);
r.subsystem()
.set_class(Some(Arc::downgrade(&r) as Weak<dyn Class>));
return r;
}
}
impl Class for RtcClass {
fn name(&self) -> &'static str {
return Self::NAME;
}
fn dev_kobj(&self) -> Option<Arc<dyn KObject>> {
Some(sys_dev_char_kset() as Arc<dyn KObject>)
}
fn set_dev_kobj(&self, _kobj: Arc<dyn KObject>) {
unimplemented!("RtcClass::set_dev_kobj");
}
fn subsystem(&self) -> &SubSysPrivate {
return &self.subsystem;
}
}
/// 注册rtc通用设备
pub(super) fn rtc_register_device(dev: &Arc<RtcGeneralDevice>) -> Result<(), SystemError> {
device_manager().add_device(dev.clone())?;
register_default_rtc(dev.clone());
// 把硬件时间同步到系统时间
rtc_hctosys(dev);
return Ok(());
}
fn rtc_hctosys(dev: &Arc<RtcGeneralDevice>) {
let r = rtc_read_time(dev);
if let Err(e) = r {
dev.set_hc2sys_result(Err(e));
return;
}
let time = r.unwrap();
let timespec64: TimeSpec = time.into();
let r = do_settimeofday64(timespec64);
dev.set_hc2sys_result(r);
kinfo!(
"Setting system clock to {} {} UTC ({})",
time.date_string(),
time.time_string(),
timespec64.tv_sec
);
}

View File

@ -0,0 +1,31 @@
use alloc::sync::Arc;
use system_error::SystemError;
use crate::driver::base::kobject::KObject;
use super::{global_default_rtc, sysfs::RtcGeneralDevice, utils::kobj2rtc_device, RtcTime};
/// 根据rtc general device, 读取真实时间
pub fn rtc_read_time(general_dev: &Arc<RtcGeneralDevice>) -> Result<RtcTime, SystemError> {
let class_ops = general_dev.class_ops().ok_or(SystemError::EINVAL)?;
let real_dev = general_dev
.parent()
.and_then(|p| p.upgrade())
.ok_or(SystemError::ENODEV)?;
let real_dev = kobj2rtc_device(real_dev).ok_or(SystemError::EINVAL)?;
let time = class_ops.read_time(&real_dev)?;
if !time.valid() {
return Err(SystemError::EINVAL);
}
return Ok(time);
}
/// 从全局默认的rtc时钟那里读取时间
pub fn rtc_read_time_default() -> Result<RtcTime, SystemError> {
rtc_read_time(&global_default_rtc().ok_or(SystemError::ENODEV)?)
}

View File

@ -0,0 +1,169 @@
use core::fmt::Debug;
use alloc::{string::String, sync::Arc};
use system_error::SystemError;
use crate::{
libs::rwlock::RwLock,
time::{Instant, TimeSpec, NSEC_PER_SEC},
};
use self::sysfs::RtcGeneralDevice;
use super::base::device::Device;
pub mod class;
pub mod interface;
pub mod rtc_cmos;
mod sysfs;
mod utils;
/// 全局默认rtc
static GLOBAL_DEFAULT_RTC: RwLock<Option<Arc<RtcGeneralDevice>>> = RwLock::new(None);
/// 获取全局的默认的rtc
fn global_default_rtc() -> Option<Arc<RtcGeneralDevice>> {
GLOBAL_DEFAULT_RTC.read().clone()
}
/// 注册默认的rtc
fn register_default_rtc(general_device: Arc<RtcGeneralDevice>) -> bool {
let upg = GLOBAL_DEFAULT_RTC.upgradeable_read();
if let Some(old_dev) = upg.as_ref() {
if old_dev.priority() >= general_device.priority() {
return false;
}
}
let mut write = upg.upgrade();
write.replace(general_device);
return true;
}
/// RTC设备的trait
pub trait RtcDevice: Device {
fn class_ops(&self) -> &'static dyn RtcClassOps;
}
pub trait RtcClassOps: Send + Sync + Debug {
fn read_time(&self, dev: &Arc<dyn RtcDevice>) -> Result<RtcTime, SystemError>;
fn set_time(&self, dev: &Arc<dyn RtcDevice>, time: &RtcTime) -> Result<(), SystemError>;
}
#[derive(Default, Debug, Clone, Copy)]
pub struct RtcTime {
/// `second`: 秒,范围从 0 到 59
pub second: i32,
/// `minute`: 分钟,范围从 0 到 59
pub minute: i32,
/// `hour`: 小时,范围从 0 到 23
pub hour: i32,
/// `mday`: 一个月中的第几天,范围从 1 到 31
pub mday: i32,
/// `month`: 月份,范围从 0 到 11
pub month: i32,
/// `year`: 年份(相对于1900年)
pub year: i32,
/// `wday`: 一周中的第几天,范围从 0周日到 6周六
pub wday: i32,
/// `yday`: 一年中的第几天,范围从 1 到 366
pub yday: i32,
/// `isdst`: 表示是否为夏令时,通常如果是夏令时,此值为正,否则为零或负
pub isdst: i32,
}
impl RtcTime {
/// 返回一个格式化的日期字符串
///
/// 例如如果日期为2021年1月1日则返回"2021-01-01"
pub fn date_string(&self) -> String {
format!(
"{:04}-{:02}-{:02}",
self.year_real(),
self.month_real(),
self.mday
)
}
/// 返回一个格式化的时间字符串
///
/// 例如如果时间为12:00:00则返回"12:00:00"
pub fn time_string(&self) -> String {
format!("{:02}:{:02}:{:02}", self.hour, self.minute, self.second)
}
pub fn valid(&self) -> bool {
!(self.year < 70
|| self.year > (i32::MAX - 1900)
|| self.month >= 12
|| self.month < 0
|| self.mday < 1
|| self.mday > self.month_days()
|| self.hour >= 24
|| self.hour < 0
|| self.minute >= 60
|| self.minute < 0
|| self.second >= 60
|| self.second < 0)
}
/// 获取当月有多少天
pub fn month_days(&self) -> i32 {
let days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
let month = self.month as usize;
let mut days = days_in_month[month];
if month == 1 && self.is_leap_year() {
days += 1;
}
days
}
/// 判断当前是否为闰年
pub fn is_leap_year(&self) -> bool {
let year = self.year + 1900;
(year % 4 == 0 && year % 100 != 0) || year % 400 == 0
}
pub fn year_real(&self) -> i32 {
self.year + 1900
}
pub fn month_real(&self) -> i32 {
self.month + 1
}
}
impl From<RtcTime> for TimeSpec {
fn from(val: RtcTime) -> Self {
let instant = Instant::mktime64(
val.year_real() as u32,
(val.month + 1) as u32,
(val.mday) as u32,
val.hour as u32,
val.minute as u32,
val.second as u32,
);
/* 注意RTC 仅存储完整的秒数。它是任意的,它存储的是最接近的值还是
* 分割秒数截断的值。然而,重要的是我们使用它来存储截断的值。这是因为
* 否则在 RTC 同步函数中,需要读取 both xtime.tv_sec 和 xtime.tv_nsec。
* 在某些处理器上(例如 ARM对 >32位的原子读取是不可行的。所以
* 存储最接近的值会减慢同步 API 的速度。因此,这里我们存储截断的值
* 并在后面加上 0.5s 的最佳猜测。
*/
TimeSpec::new(instant.secs(), (NSEC_PER_SEC >> 1).into())
}
}
/// 全局默认rtc的优先级
#[allow(dead_code)]
#[derive(Debug, Default, PartialEq, PartialOrd, Clone, Copy)]
pub enum GeneralRtcPriority {
#[default]
L0 = 0,
L1,
}

View File

@ -0,0 +1,227 @@
use alloc::{
string::{String, ToString},
sync::{Arc, Weak},
vec::Vec,
};
use intertrait::cast::CastArc;
use system_error::SystemError;
use unified_init::macros::unified_init;
use super::{
class::rtc_register_device,
sysfs::{rtc_general_device_create, RtcGeneralDevice},
RtcClassOps, RtcDevice, RtcTime,
};
use crate::{
driver::base::{
device::{
bus::Bus,
driver::{Driver, DriverCommonData},
Device, IdTable,
},
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet,
platform::{
platform_device::PlatformDevice,
platform_driver::{platform_driver_manager, PlatformDriver},
},
},
filesystem::kernfs::KernFSInode,
init::initcall::INITCALL_DEVICE,
libs::{
rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
spinlock::{SpinLock, SpinLockGuard},
},
};
static CMOS_RTC_GENERAL_DEVICE: RwLock<Option<Arc<RtcGeneralDevice>>> = RwLock::new(None);
#[derive(Debug)]
#[cast_to([sync] Driver, PlatformDriver)]
struct CmosPlatformDriver {
inner: SpinLock<InnerCmosPlatformDriver>,
locked_kobjstate: LockedKObjectState,
}
impl CmosPlatformDriver {
const NAME: &str = "rtc_cmos";
fn new() -> Arc<Self> {
Arc::new(CmosPlatformDriver {
inner: SpinLock::new(InnerCmosPlatformDriver {
driver_common: DriverCommonData::default(),
kobject_common: KObjectCommonData::default(),
}),
locked_kobjstate: LockedKObjectState::new(None),
})
}
fn inner(&self) -> SpinLockGuard<InnerCmosPlatformDriver> {
self.inner.lock()
}
}
#[derive(Debug)]
struct InnerCmosPlatformDriver {
driver_common: DriverCommonData,
kobject_common: KObjectCommonData,
}
impl PlatformDriver for CmosPlatformDriver {
fn probe(&self, device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
let dev = device
.clone()
.arc_any()
.cast::<dyn RtcDevice>()
.map_err(|_| SystemError::ENODEV)?;
if dev.id_table() != self.id_table().unwrap() {
return Err(SystemError::ENODEV);
}
if CMOS_RTC_GENERAL_DEVICE.read().is_some() {
return Err(SystemError::EBUSY);
}
let mut guard = CMOS_RTC_GENERAL_DEVICE.write();
// 再次检查
if guard.is_some() {
return Err(SystemError::EBUSY);
}
let general_rtc_device: Arc<RtcGeneralDevice> = rtc_general_device_create(&dev, None);
guard.replace(general_rtc_device.clone());
general_rtc_device.set_class_ops(&CmosRtcClassOps);
drop(guard);
rtc_register_device(&general_rtc_device)
.expect("cmos_rtc: register general rtc device failed");
return Ok(());
}
fn remove(&self, _device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
// todo: remove
Err(SystemError::ENOSYS)
}
fn shutdown(&self, _device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
unimplemented!("cmos platform driver shutdown")
}
fn suspend(&self, _device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
todo!("cmos platform driver suspend")
}
fn resume(&self, _device: &Arc<dyn PlatformDevice>) -> Result<(), SystemError> {
todo!("cmos platform driver resume")
}
}
impl Driver for CmosPlatformDriver {
fn id_table(&self) -> Option<IdTable> {
Some(IdTable::new(Self::NAME.to_string(), None))
}
fn devices(&self) -> Vec<Arc<dyn Device>> {
self.inner().driver_common.devices.clone()
}
fn add_device(&self, device: Arc<dyn Device>) {
self.inner().driver_common.push_device(device);
}
fn delete_device(&self, device: &Arc<dyn Device>) {
self.inner().driver_common.delete_device(device);
}
fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
self.inner().driver_common.bus = bus;
}
fn bus(&self) -> Option<Weak<dyn Bus>> {
self.inner().driver_common.bus.clone()
}
}
impl KObject for CmosPlatformDriver {
fn as_any_ref(&self) -> &dyn core::any::Any {
self
}
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
self.inner().kobject_common.kern_inode = inode;
}
fn inode(&self) -> Option<Arc<KernFSInode>> {
self.inner().kobject_common.kern_inode.clone()
}
fn parent(&self) -> Option<Weak<dyn KObject>> {
self.inner().kobject_common.parent.clone()
}
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
self.inner().kobject_common.parent = parent;
}
fn kset(&self) -> Option<Arc<KSet>> {
self.inner().kobject_common.kset.clone()
}
fn set_kset(&self, kset: Option<Arc<KSet>>) {
self.inner().kobject_common.kset = kset;
}
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
self.inner().kobject_common.kobj_type
}
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
self.inner().kobject_common.kobj_type = ktype;
}
fn name(&self) -> String {
Self::NAME.to_string()
}
fn set_name(&self, _name: String) {
// do nothing
}
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
self.locked_kobjstate.read()
}
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
self.locked_kobjstate.write()
}
fn set_kobj_state(&self, state: KObjectState) {
*self.locked_kobjstate.write() = state;
}
}
#[unified_init(INITCALL_DEVICE)]
pub fn cmos_rtc_driver_init() -> Result<(), SystemError> {
let driver = CmosPlatformDriver::new();
platform_driver_manager().register(driver)?;
return Ok(());
}
#[derive(Debug)]
struct CmosRtcClassOps;
impl RtcClassOps for CmosRtcClassOps {
fn read_time(&self, dev: &Arc<dyn RtcDevice>) -> Result<RtcTime, SystemError> {
dev.class_ops().read_time(dev)
}
fn set_time(&self, dev: &Arc<dyn RtcDevice>, time: &RtcTime) -> Result<(), SystemError> {
dev.class_ops().set_time(dev, time)
}
}

View File

@ -0,0 +1,379 @@
use alloc::{
string::String,
sync::{Arc, Weak},
};
use ida::IdAllocator;
use system_error::SystemError;
use crate::{
driver::base::{
class::Class,
device::{
bus::Bus, device_manager, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable,
},
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet,
},
filesystem::{
kernfs::KernFSInode,
sysfs::{
file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOpsSupport, SYSFS_ATTR_MODE_RO,
},
vfs::syscall::ModeType,
},
libs::{
rwlock::{RwLockReadGuard, RwLockWriteGuard},
spinlock::{SpinLock, SpinLockGuard},
},
};
use super::{
class::sys_class_rtc_instance,
interface::rtc_read_time,
utils::{kobj2rtc_device, kobj2rtc_general_device},
GeneralRtcPriority, RtcClassOps, RtcDevice,
};
static RTC_GENERAL_DEVICE_IDA: IdAllocator = IdAllocator::new(0, usize::MAX);
pub(super) const RTC_HCTOSYS_DEVICE: &str = "rtc0";
#[derive(Debug)]
#[cast_to([sync] KObject, Device, RtcDevice)]
pub struct RtcGeneralDevice {
name: String,
id: usize,
inner: SpinLock<InnerRtcGeneralDevice>,
kobj_state: LockedKObjectState,
priority: GeneralRtcPriority,
}
#[derive(Debug)]
struct InnerRtcGeneralDevice {
device_common: DeviceCommonData,
kobject_common: KObjectCommonData,
class_ops: Option<&'static dyn RtcClassOps>,
/// 上一次调用`rtc_hctosys()`把时间同步到timekeeper的时候的返回值
hc2sysfs_result: Result<(), SystemError>,
}
impl RtcGeneralDevice {
/// 创建一个新的通用RTC设备实例
///
/// 注意,由于还需要进行其他的初始化操作,因此这个函数并不是公开的构造函数。
fn new(priority: GeneralRtcPriority) -> Arc<Self> {
let id = RTC_GENERAL_DEVICE_IDA.alloc().unwrap();
let name = format!("rtc{}", id);
Arc::new(Self {
name,
id,
inner: SpinLock::new(InnerRtcGeneralDevice {
device_common: DeviceCommonData::default(),
kobject_common: KObjectCommonData::default(),
class_ops: None,
hc2sysfs_result: Err(SystemError::ENODEV),
}),
kobj_state: LockedKObjectState::new(None),
priority,
})
}
fn inner(&self) -> SpinLockGuard<InnerRtcGeneralDevice> {
self.inner.lock()
}
pub fn set_class_ops(&self, class_ops: &'static dyn RtcClassOps) {
self.inner().class_ops = Some(class_ops);
}
pub fn class_ops(&self) -> Option<&'static dyn RtcClassOps> {
self.inner().class_ops
}
pub fn priority(&self) -> GeneralRtcPriority {
self.priority
}
pub(super) fn set_hc2sys_result(&self, val: Result<(), SystemError>) {
self.inner().hc2sysfs_result = val;
}
pub(super) fn hc2sysfs_result(&self) -> Result<(), SystemError> {
self.inner().hc2sysfs_result.clone()
}
}
impl Drop for RtcGeneralDevice {
fn drop(&mut self) {
RTC_GENERAL_DEVICE_IDA.free(self.id);
}
}
impl RtcDevice for RtcGeneralDevice {
fn class_ops(&self) -> &'static dyn super::RtcClassOps {
todo!()
}
}
impl Device for RtcGeneralDevice {
fn dev_type(&self) -> DeviceType {
DeviceType::Rtc
}
fn id_table(&self) -> IdTable {
IdTable::new(self.name.clone(), None)
}
fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
self.inner().device_common.bus = bus;
}
fn bus(&self) -> Option<Weak<dyn Bus>> {
self.inner().device_common.get_bus_weak_or_clear()
}
fn set_class(&self, class: Option<Weak<dyn Class>>) {
self.inner().device_common.class = class;
}
fn class(&self) -> Option<Arc<dyn Class>> {
self.inner()
.device_common
.get_class_weak_or_clear()
.and_then(|x| x.upgrade())
}
fn driver(&self) -> Option<Arc<dyn Driver>> {
self.inner()
.device_common
.get_driver_weak_or_clear()
.and_then(|x| x.upgrade())
}
fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
self.inner().device_common.driver = driver;
}
fn is_dead(&self) -> bool {
false
}
fn can_match(&self) -> bool {
false
}
fn set_can_match(&self, _can_match: bool) {
// do nothing
}
fn state_synced(&self) -> bool {
true
}
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
Some(&[&RtcAttrGroup])
}
}
impl KObject for RtcGeneralDevice {
fn as_any_ref(&self) -> &dyn core::any::Any {
self
}
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
self.inner().kobject_common.kern_inode = inode;
}
fn inode(&self) -> Option<Arc<KernFSInode>> {
self.inner().kobject_common.kern_inode.clone()
}
fn parent(&self) -> Option<Weak<dyn KObject>> {
self.inner().kobject_common.parent.clone()
}
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
self.inner().kobject_common.parent = parent;
}
fn kset(&self) -> Option<Arc<KSet>> {
self.inner().kobject_common.kset.clone()
}
fn set_kset(&self, kset: Option<Arc<KSet>>) {
self.inner().kobject_common.kset = kset;
}
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
self.inner().kobject_common.kobj_type
}
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
self.inner().kobject_common.kobj_type = ktype;
}
fn name(&self) -> String {
self.name.clone()
}
fn set_name(&self, _name: String) {
// do nothing
}
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
self.kobj_state.read()
}
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
self.kobj_state.write()
}
fn set_kobj_state(&self, state: KObjectState) {
*self.kobj_state_mut() = state;
}
}
///
/// 用于创建一个通用的RTC设备实例。
///
/// ## 参数
///
/// - `real_dev`: 一个对实际RTC设备的引用这个设备将作为通用RTC设备的父设备。
pub fn rtc_general_device_create(
real_dev: &Arc<dyn RtcDevice>,
priority: Option<GeneralRtcPriority>,
) -> Arc<RtcGeneralDevice> {
let dev = RtcGeneralDevice::new(priority.unwrap_or_default());
device_manager().device_default_initialize(&(dev.clone() as Arc<dyn Device>));
dev.set_parent(Some(Arc::downgrade(real_dev) as Weak<dyn KObject>));
dev.set_class(Some(Arc::downgrade(
&(sys_class_rtc_instance().cloned().unwrap() as Arc<dyn Class>),
)));
return dev;
}
#[derive(Debug)]
struct RtcAttrGroup;
impl AttributeGroup for RtcAttrGroup {
fn name(&self) -> Option<&str> {
None
}
fn attrs(&self) -> &[&'static dyn Attribute] {
&[&AttrName, &AttrDate, &AttrTime, &AttrHcToSys]
}
fn is_visible(
&self,
_kobj: Arc<dyn KObject>,
attr: &'static dyn Attribute,
) -> Option<ModeType> {
// todo: https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/rtc/sysfs.c#280
return Some(attr.mode());
}
}
#[derive(Debug)]
struct AttrName;
impl Attribute for AttrName {
fn name(&self) -> &str {
"name"
}
fn mode(&self) -> ModeType {
SYSFS_ATTR_MODE_RO
}
fn support(&self) -> SysFSOpsSupport {
SysFSOpsSupport::ATTR_SHOW
}
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
let rtc_device = kobj
.parent()
.and_then(|x| x.upgrade())
.ok_or(SystemError::ENODEV)?;
let rtc_device = kobj2rtc_device(rtc_device).ok_or(SystemError::EINVAL)?;
let driver_name = rtc_device.driver().ok_or(SystemError::ENODEV)?.name();
let device_name = rtc_device.name();
sysfs_emit_str(buf, &format!("{} {}\n", driver_name, device_name))
}
}
#[derive(Debug)]
struct AttrDate;
impl Attribute for AttrDate {
fn name(&self) -> &str {
"date"
}
fn mode(&self) -> ModeType {
SYSFS_ATTR_MODE_RO
}
fn support(&self) -> SysFSOpsSupport {
SysFSOpsSupport::ATTR_SHOW
}
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
let rtc_device: Arc<RtcGeneralDevice> =
kobj2rtc_general_device(kobj).ok_or(SystemError::EINVAL)?;
let time = rtc_read_time(&rtc_device)?;
sysfs_emit_str(buf, &time.date_string())
}
}
#[derive(Debug)]
struct AttrTime;
impl Attribute for AttrTime {
fn name(&self) -> &str {
"time"
}
fn mode(&self) -> ModeType {
SYSFS_ATTR_MODE_RO
}
fn support(&self) -> SysFSOpsSupport {
SysFSOpsSupport::ATTR_SHOW
}
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
let rtc_device = kobj2rtc_general_device(kobj).ok_or(SystemError::EINVAL)?;
let time = rtc_read_time(&rtc_device)?;
sysfs_emit_str(buf, &time.time_string())
}
}
#[derive(Debug)]
struct AttrHcToSys;
impl Attribute for AttrHcToSys {
fn name(&self) -> &str {
"hctosys"
}
fn mode(&self) -> ModeType {
SYSFS_ATTR_MODE_RO
}
fn support(&self) -> SysFSOpsSupport {
SysFSOpsSupport::ATTR_SHOW
}
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
let rtc_device = kobj2rtc_general_device(kobj).ok_or(SystemError::EINVAL)?;
if rtc_device.hc2sysfs_result().is_ok() && rtc_device.name().eq(RTC_HCTOSYS_DEVICE) {
return sysfs_emit_str(buf, "1\n");
}
return sysfs_emit_str(buf, "0\n");
}
}

View File

@ -0,0 +1,16 @@
use alloc::sync::Arc;
use intertrait::cast::CastArc;
use crate::driver::base::kobject::KObject;
use super::{sysfs::RtcGeneralDevice, RtcDevice};
#[inline]
pub fn kobj2rtc_device(kobj: Arc<dyn KObject>) -> Option<Arc<dyn RtcDevice>> {
kobj.arc_any().cast::<dyn RtcDevice>().ok()
}
#[inline]
pub fn kobj2rtc_general_device(kobj: Arc<dyn KObject>) -> Option<Arc<RtcGeneralDevice>> {
kobj.arc_any().downcast().ok()
}

View File

@ -177,10 +177,6 @@ impl Serial8250ISADevices {
}
impl PlatformDevice for Serial8250ISADevices {
fn compatible_table(&self) -> crate::driver::base::platform::CompatibleTable {
unimplemented!()
}
fn pdev_id(&self) -> (i32, bool) {
return (
self.id.load(Ordering::SeqCst),

View File

@ -1,2 +1 @@
pub mod hpet;
pub mod rtc;

View File

@ -1,2 +0,0 @@
#[allow(clippy::module_inception)]
pub mod rtc;

View File

@ -1,90 +0,0 @@
use system_error::SystemError;
use crate::{
arch::{io::PortIOArch, CurrentIrqArch, CurrentPortIOArch},
exception::InterruptArch,
};
#[derive(Default)]
pub struct RtcTime {
pub second: i32,
pub minute: i32,
pub hour: i32,
pub day: i32,
pub month: i32,
pub year: i32,
}
impl RtcTime {
///@brief 从主板cmos中获取时间
///
///@param self time结构体
///@return int 成功则为0
pub fn get(&mut self) -> Result<i32, SystemError> {
// 为防止中断请求打断该过程,需要先关中断
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
//0x0B
let status_register_b: u8 = read_cmos(0x0B); // 读取状态寄存器B
let is_24h: bool = (status_register_b & 0x02) != 0;
// 判断是否启用24小时模式
let is_binary: bool = (status_register_b & 0x04) != 0; // 判断是否为二进制码
loop {
self.year = read_cmos(CMOSTimeSelector::Year as u8) as i32;
self.month = read_cmos(CMOSTimeSelector::Month as u8) as i32;
self.day = read_cmos(CMOSTimeSelector::Day as u8) as i32;
self.hour = read_cmos(CMOSTimeSelector::Hour as u8) as i32;
self.minute = read_cmos(CMOSTimeSelector::Minute as u8) as i32;
self.second = read_cmos(CMOSTimeSelector::Second as u8) as i32;
if self.second == read_cmos(CMOSTimeSelector::Second as u8) as i32 {
break;
} // 若读取时间过程中时间发生跳变则重新读取
}
unsafe {
CurrentPortIOArch::out8(0x70, 0x00);
}
if !is_binary
// 把BCD转为二进制
{
self.second = (self.second & 0xf) + (self.second >> 4) * 10;
self.minute = (self.minute & 0xf) + (self.minute >> 4) * 10;
self.hour = ((self.hour & 0xf) + ((self.hour & 0x70) >> 4) * 10) | (self.hour & 0x80);
self.day = (self.day & 0xf) + ((self.day / 16) * 10);
self.month = (self.month & 0xf) + (self.month >> 4) * 10;
self.year = (self.year & 0xf) + (self.year >> 4) * 10;
}
self.year += 2000;
if (!is_24h) && (self.hour & 0x80) != 0 {
self.hour = ((self.hour & 0x7f) + 12) % 24;
} // 将十二小时制转为24小时
drop(irq_guard);
return Ok(0);
}
}
///置位0x70的第7位禁止不可屏蔽中断
#[inline]
fn read_cmos(addr: u8) -> u8 {
unsafe {
CurrentPortIOArch::out8(0x70, 0x80 | addr);
return CurrentPortIOArch::in8(0x71);
}
}
/// used in the form of u8
#[repr(u8)]
enum CMOSTimeSelector {
Second = 0x00,
Minute = 0x02,
Hour = 0x04,
Day = 0x07,
Month = 0x08,
Year = 0x09,
}

View File

@ -26,11 +26,13 @@ lazy_static! {
/// 是否已经添加了软光标
pub(super) static ref SOFTCURSOR_ORIGINAL: RwLock<Option<VcCursor>> = RwLock::new(None);
pub static ref CURRENT_VCNUM: AtomicIsize = AtomicIsize::new(-1);
pub static ref CONSOLE_BLANKED: AtomicBool = AtomicBool::new(false);
}
pub static CURRENT_VCNUM: AtomicIsize = AtomicIsize::new(-1);
pub static CONSOLE_BLANKED: AtomicBool = AtomicBool::new(false);
/// ## 虚拟控制台的信息
#[derive(Debug, Clone)]
pub struct VirtualConsoleData {

View File

@ -25,7 +25,6 @@ use crate::{
platform::{
platform_device::{platform_device_manager, PlatformDevice},
platform_driver::{platform_driver_manager, PlatformDriver},
CompatibleTable,
},
},
serial::serial8250::send_to_default_serial8250_port,
@ -159,10 +158,6 @@ impl PlatformDevice for VesaFb {
self.inner.lock().pdev_id_auto = id_auto;
}
fn compatible_table(&self) -> CompatibleTable {
todo!()
}
fn is_initialized(&self) -> bool {
self.inner.lock().device_state == DeviceState::Initialized
}