实现了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
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 1441 additions and 156 deletions

View File

@ -31,6 +31,7 @@ bit_field = "=0.10"
bitfield-struct = "=0.5.3"
bitflags = "=1.3.2"
bitmap = { path = "crates/bitmap" }
driver_base_macros = { "path" = "crates/driver_base_macros" }
# 一个no_std的hashmap、hashset
elf = { version = "=0.7.2", default-features = false }
hashbrown = "=0.13.2"

View File

@ -0,0 +1,8 @@
[package]
name = "driver_base_macros"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@ -0,0 +1,20 @@
#![no_std]
/// 获取指定字段
///
/// 当weak指针的strong count为0的时候清除弱引用
#[macro_export]
macro_rules! get_weak_or_clear {
($field:expr) => {{
if let Some(x) = $field.clone() {
if x.strong_count() == 0 {
$field = None;
None
} else {
Some(x)
}
} else {
None
}
}};
}

View File

@ -1,4 +1,5 @@
pub mod apic;
pub mod hpet;
pub mod rtc;
pub mod tsc;
pub mod video;

View File

@ -0,0 +1,312 @@
use core::any::Any;
use alloc::{
string::{String, ToString},
sync::{Arc, Weak},
};
use system_error::SystemError;
use unified_init::macros::unified_init;
use crate::{
arch::{io::PortIOArch, CurrentIrqArch, CurrentPortIOArch},
driver::{
base::{
class::Class,
device::{
bus::Bus, device_manager, driver::Driver, Device, DeviceCommonData, DeviceState,
DeviceType, IdTable,
},
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet,
platform::platform_device::{platform_device_manager, PlatformDevice},
},
rtc::{RtcClassOps, RtcDevice, RtcTime},
},
exception::InterruptArch,
filesystem::kernfs::KernFSInode,
init::initcall::INITCALL_DEVICE,
kerror,
libs::{
mutex::Mutex,
rwlock::{RwLockReadGuard, RwLockWriteGuard},
spinlock::{SpinLock, SpinLockGuard},
},
};
#[derive(Debug)]
#[cast_to([sync] Device, PlatformDevice, RtcDevice)]
struct CmosRtcDevice {
inner: SpinLock<InnerCmosRtc>,
locked_kobjstate: LockedKObjectState,
ops_mutex: Mutex<()>,
}
impl CmosRtcDevice {
const NAME: &str = "rtc_cmos";
pub fn new() -> Arc<Self> {
let r = CmosRtcDevice {
inner: SpinLock::new(InnerCmosRtc {
device_common: DeviceCommonData::default(),
kobject_common: KObjectCommonData::default(),
device_state: DeviceState::NotInitialized,
}),
locked_kobjstate: LockedKObjectState::new(None),
ops_mutex: Mutex::new(()),
};
r.inner().device_common.can_match = true;
Arc::new(r)
}
fn inner(&self) -> SpinLockGuard<InnerCmosRtc> {
self.inner.lock()
}
///置位0x70的第7位禁止不可屏蔽中断
#[inline]
fn read_cmos(&self, addr: u8) -> u8 {
unsafe {
CurrentPortIOArch::out8(0x70, 0x80 | addr);
return CurrentPortIOArch::in8(0x71);
}
}
}
#[derive(Debug)]
struct InnerCmosRtc {
device_common: DeviceCommonData,
kobject_common: KObjectCommonData,
device_state: DeviceState,
}
impl RtcDevice for CmosRtcDevice {
fn class_ops(&self) -> &'static dyn RtcClassOps {
&CmosRtcClassOps
}
}
impl PlatformDevice for CmosRtcDevice {
fn pdev_name(&self) -> &str {
Self::NAME
}
fn set_pdev_id(&self, _id: i32) {
todo!()
}
fn set_pdev_id_auto(&self, _id_auto: bool) {
todo!()
}
fn is_initialized(&self) -> bool {
self.inner().device_state == DeviceState::Initialized
}
fn set_state(&self, set_state: DeviceState) {
self.inner().device_state = set_state;
}
}
impl Device for CmosRtcDevice {
fn dev_type(&self) -> DeviceType {
DeviceType::Rtc
}
fn id_table(&self) -> IdTable {
IdTable::new(Self::NAME.to_string(), None)
}
fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
self.inner().device_common.bus = bus;
}
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(|c| c.upgrade())
}
fn driver(&self) -> Option<Arc<dyn Driver>> {
self.inner()
.device_common
.get_driver_weak_or_clear()
.and_then(|d| d.upgrade())
}
fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
self.inner().device_common.driver = driver;
}
fn is_dead(&self) -> bool {
self.inner().device_common.dead
}
fn can_match(&self) -> bool {
self.inner().device_common.can_match
}
fn set_can_match(&self, can_match: bool) {
self.inner().device_common.can_match = can_match;
}
fn state_synced(&self) -> bool {
true
}
fn bus(&self) -> Option<Weak<dyn Bus>> {
self.inner().device_common.get_bus_weak_or_clear()
}
}
impl KObject for CmosRtcDevice {
fn as_any_ref(&self) -> &dyn 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.get_parent_or_clear_weak()
}
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;
}
}
#[derive(Debug)]
pub struct CmosRtcClassOps;
impl RtcClassOps for CmosRtcClassOps {
fn read_time(&self, dev: &Arc<dyn RtcDevice>) -> Result<RtcTime, SystemError> {
// 检查是否为cmos rtc
let dev = dev
.as_any_ref()
.downcast_ref::<CmosRtcDevice>()
.ok_or(SystemError::EINVAL)?;
let _guard = dev.ops_mutex.lock();
// 为防止中断请求打断该过程,需要先关中断
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
//0x0B
let status_register_b: u8 = dev.read_cmos(0x0B); // 读取状态寄存器B
let is_24h: bool = (status_register_b & 0x02) != 0;
// 判断是否启用24小时模式
let is_binary: bool = (status_register_b & 0x04) != 0; // 判断是否为二进制码
let mut res = RtcTime::default();
loop {
res.year = dev.read_cmos(CMOSTimeSelector::Year as u8) as i32;
res.month = dev.read_cmos(CMOSTimeSelector::Month as u8) as i32;
res.mday = dev.read_cmos(CMOSTimeSelector::Day as u8) as i32;
res.hour = dev.read_cmos(CMOSTimeSelector::Hour as u8) as i32;
res.minute = dev.read_cmos(CMOSTimeSelector::Minute as u8) as i32;
res.second = dev.read_cmos(CMOSTimeSelector::Second as u8) as i32;
if res.second == dev.read_cmos(CMOSTimeSelector::Second as u8) as i32 {
break;
} // 若读取时间过程中时间发生跳变则重新读取
}
unsafe {
CurrentPortIOArch::out8(0x70, 0x00);
}
if !is_binary
// 把BCD转为二进制
{
res.second = (res.second & 0xf) + (res.second >> 4) * 10;
res.minute = (res.minute & 0xf) + (res.minute >> 4) * 10;
res.hour = ((res.hour & 0xf) + ((res.hour & 0x70) >> 4) * 10) | (res.hour & 0x80);
res.mday = (res.mday & 0xf) + ((res.mday / 16) * 10);
res.month = (res.month & 0xf) + (res.month >> 4) * 10;
res.year = (res.year & 0xf) + (res.year >> 4) * 10;
}
res.year += 100;
if (!is_24h) && (res.hour & 0x80) != 0 {
res.hour = ((res.hour & 0x7f) + 12) % 24;
} // 将十二小时制转为24小时
res.month -= 1;
drop(irq_guard);
return Ok(res);
}
fn set_time(&self, _dev: &Arc<dyn RtcDevice>, _time: &RtcTime) -> Result<(), SystemError> {
kerror!("set_time is not implemented for CmosRtcClassOps");
Err(SystemError::ENOSYS)
}
}
/// used in the form of u8
#[repr(u8)]
enum CMOSTimeSelector {
Second = 0x00,
Minute = 0x02,
Hour = 0x04,
Day = 0x07,
Month = 0x08,
Year = 0x09,
}
#[unified_init(INITCALL_DEVICE)]
pub fn cmos_rtc_device_init() -> Result<(), SystemError> {
let device = CmosRtcDevice::new();
device_manager().device_default_initialize(&(device.clone() as Arc<dyn Device>));
platform_device_manager().device_add(device)?;
return Ok(());
}

View File

@ -404,10 +404,13 @@ impl VirtAddr {
}
unsafe fn allocator_init() {
let virt_offset = BOOTSTRAP_MM_INFO.unwrap().start_brk;
let phy_offset =
unsafe { MMArch::virt_2_phys(VirtAddr::new(page_align_up(virt_offset))) }.unwrap();
let virt_offset = VirtAddr::new(page_align_up(BOOTSTRAP_MM_INFO.unwrap().start_brk));
let phy_offset = unsafe { MMArch::virt_2_phys(virt_offset) }.unwrap();
mem_block_manager()
.reserve_block(PhysAddr::new(0), phy_offset.data())
.expect("Failed to reserve block");
let mut bump_allocator = BumpAllocator::<X86_64MMArch>::new(phy_offset.data());
kdebug!(
"BumpAllocator created, offset={:?}",

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
}

View File

@ -16,6 +16,7 @@ pub mod timeconv;
pub mod timekeep;
pub mod timekeeping;
pub mod timer;
/* Time structures. (Partitially taken from smoltcp)
The `time` module contains structures used to represent both
@ -124,6 +125,61 @@ pub struct Instant {
impl Instant {
pub const ZERO: Instant = Instant::from_micros_const(0);
/// mktime64 - 将日期转换为秒。
///
/// ## 参数
///
/// - year0: 要转换的年份
/// - mon0: 要转换的月份
/// - day: 要转换的天
/// - hour: 要转换的小时
/// - min: 要转换的分钟
/// - sec: 要转换的秒
///
/// 将公历日期转换为1970-01-01 00:00:00以来的秒数。
/// 假设输入为正常的日期格式即1980-12-31 23:59:59 => 年份=1980, 月=12, 日=31, 时=23, 分=59, 秒=59。
///
/// [For the Julian calendar俄罗斯在1917年之前使用英国及其殖民地在大西洋1752年之前使用
/// 其他地方在1582年之前使用某些社区仍然在使用省略-year/100+year/400项
/// 并在结果上加10。]
///
/// 这个算法最初由高斯(我认为是)发表。
///
/// 要表示闰秒可以通过将sec设为60在ISO 8601允许来调用此函数。
/// 闰秒与随后的秒一样处理因为它们在UNIX时间中不存在。
///
/// 支持将午夜作为当日末尾的24:00:00编码 - 即明天的午夜在ISO 8601允许
///
/// ## 返回
///
/// 返回给定输入日期自1970-01-01 00:00:00以来的秒数
pub fn mktime64(year0: u32, mon0: u32, day: u32, hour: u32, min: u32, sec: u32) -> Self {
let mut mon: i64 = mon0.into();
let mut year: u64 = year0.into();
let day: u64 = day.into();
let hour: u64 = hour.into();
let min: u64 = min.into();
let sec: u64 = sec.into();
mon -= 2;
/* 1..12 -> 11,12,1..10 */
if mon <= 0 {
/* Puts Feb last since it has leap day */
mon += 12;
year -= 1;
}
let mon = mon as u64;
let secs = ((((year / 4 - year / 100 + year / 400 + 367 * mon / 12 + day) + year * 365
- 719499)
* 24 + hour) /* now have hours - midnight tomorrow handled here */
* 60 + min)/* now have minutes */
* 60
+ sec; /* finally seconds */
Self::from_secs(secs as i64)
}
/// Create a new `Instant` from a number of microseconds.
pub fn from_micros<T: Into<i64>>(micros: T) -> Instant {
Instant {

View File

@ -1,6 +1,10 @@
#![allow(dead_code)]
use crate::driver::timers::rtc::rtc::RtcTime;
use system_error::SystemError;
use crate::driver::rtc::interface::rtc_read_time_default;
use super::TimeSpec;
#[allow(non_camel_case_types)]
pub type ktime_t = i64;
@ -14,48 +18,16 @@ fn ktime_to_ns(kt: ktime_t) -> i64 {
/// @brief 从RTC获取当前时间然后计算时间戳。
/// 时间戳为从UTC+0 1970-01-01 00:00到当前UTC+0时间所经过的纳秒数。
/// 注意由于当前未引入时区因此本函数默认时区为UTC+8来计算
fn ktime_get_real() -> ktime_t {
let mut rtc_time: RtcTime = RtcTime::default();
{
let r = rtc_time.get();
// 返回错误码
if let Err(e) = r {
return e as ktime_t;
}
}
let mut day_count: i32 = 0;
for year in 1970..rtc_time.year {
let leap: bool = (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
if leap {
day_count += 366;
} else {
day_count += 365;
}
}
for month in 1..rtc_time.month {
match month {
1 | 3 | 5 | 7 | 8 | 10 | 12 => day_count += 31,
2 => day_count += 28,
4 | 6 | 9 | 11 => day_count += 30,
_ => day_count += 0,
}
}
day_count += rtc_time.day - 1;
//转换成纳秒
let timestamp: ktime_t = day_count as i64 * 86_400_000_000_000i64
+ (rtc_time.hour - 8) as i64 * 3_600_000_000_000i64
+ rtc_time.minute as i64 * 60_000_000_000i64
+ rtc_time.second as i64 * 1_000_000_000u64 as ktime_t;
return timestamp;
fn ktime_get_real() -> Result<ktime_t, SystemError> {
let rtc_time = rtc_read_time_default()?;
let time_spec: TimeSpec = rtc_time.into();
let r = time_spec.tv_sec * 1_000_000_000 + time_spec.tv_nsec;
return Ok(r);
}
/// @brief 暴露给外部使用的接口,返回一个时间戳
#[inline]
pub fn ktime_get_real_ns() -> i64 {
let kt: ktime_t = ktime_get_real();
let kt: ktime_t = ktime_get_real().unwrap_or(0);
return ktime_to_ns(kt);
}

View File

@ -1,5 +1,6 @@
use alloc::sync::Arc;
use core::sync::atomic::{compiler_fence, AtomicBool, AtomicI64, Ordering};
use system_error::SystemError;
use crate::{
arch::CurrentIrqArch,
@ -207,6 +208,13 @@ pub fn do_gettimeofday() -> PosixTimeval {
};
}
pub fn do_settimeofday64(time: TimeSpec) -> Result<(), SystemError> {
timekeeper().0.write_irqsave().xtime = time;
// todo: 模仿linux实现时间误差校准。
// https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/time/timekeeping.c?fi=do_settimeofday64#1312
return Ok(());
}
/// # 初始化timekeeping模块
#[inline(never)]
pub fn timekeeping_init() {