LoGin da15231979
实现了rtc的抽象,并且把x86的cmos rtc接入到设备驱动模型 (#674)
* 实现了rtc的抽象,并且把x86的cmos rtc接入到设备驱动模型。
2024-03-28 00:28:13 +08:00

283 lines
7.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use core::{any::Any, fmt::Debug, hash::Hash, ops::Deref};
use alloc::{
string::String,
sync::{Arc, Weak},
};
use driver_base_macros::get_weak_or_clear;
use intertrait::CastFromSync;
use crate::{
filesystem::{
kernfs::KernFSInode,
sysfs::{sysfs_instance, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport},
},
kerror,
libs::{
casting::DowncastArc,
rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
},
};
use system_error::SystemError;
use super::kset::KSet;
pub trait KObject: Any + Send + Sync + Debug + CastFromSync {
fn as_any_ref(&self) -> &dyn core::any::Any;
/// 设置当前kobject对应的sysfs inode(类型为KernFSInode)
fn set_inode(&self, inode: Option<Arc<KernFSInode>>);
/// 获取当前kobject对应的sysfs inode(类型为KernFSInode)
fn inode(&self) -> Option<Arc<KernFSInode>>;
fn parent(&self) -> Option<Weak<dyn KObject>>;
/// 设置当前kobject的parent kobject不一定与kset相同
fn set_parent(&self, parent: Option<Weak<dyn KObject>>);
/// 当前kobject属于哪个kset
fn kset(&self) -> Option<Arc<KSet>>;
/// 设置当前kobject所属的kset
fn set_kset(&self, kset: Option<Arc<KSet>>);
fn kobj_type(&self) -> Option<&'static dyn KObjType>;
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>);
fn name(&self) -> String;
fn set_name(&self, name: String);
fn kobj_state(&self) -> RwLockReadGuard<KObjectState>;
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState>;
fn set_kobj_state(&self, state: KObjectState);
}
impl dyn KObject {
/// 更新kobject的状态
pub fn update_kobj_state(&self, insert: Option<KObjectState>, remove: Option<KObjectState>) {
let insert = insert.unwrap_or(KObjectState::empty());
let remove = remove.unwrap_or(KObjectState::empty());
let mut state = self.kobj_state_mut();
*state = (*state | insert) & !remove;
}
}
impl DowncastArc for dyn KObject {
fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any> {
self
}
}
/// 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>) {}
fn sysfs_ops(&self) -> Option<&dyn SysFSOps>;
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]>;
}
bitflags! {
pub struct KObjectState: u32 {
const IN_SYSFS = 1 << 0;
const ADD_UEVENT_SENT = 1 << 1;
const REMOVE_UEVENT_SENT = 1 << 2;
const INITIALIZED = 1 << 3;
}
}
#[derive(Debug)]
pub struct LockedKObjectState(RwLock<KObjectState>);
impl LockedKObjectState {
pub fn new(state: Option<KObjectState>) -> LockedKObjectState {
let state = state.unwrap_or(KObjectState::empty());
LockedKObjectState(RwLock::new(state))
}
}
impl Deref for LockedKObjectState {
type Target = RwLock<KObjectState>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Default for LockedKObjectState {
fn default() -> Self {
LockedKObjectState::new(None)
}
}
#[derive(Debug)]
pub struct KObjectSysFSOps;
impl SysFSOps for KObjectSysFSOps {
fn support(&self, attr: &dyn Attribute) -> SysFSOpsSupport {
return attr.support();
}
fn show(
&self,
kobj: Arc<dyn KObject>,
attr: &dyn Attribute,
buf: &mut [u8],
) -> Result<usize, SystemError> {
let r = attr.show(kobj, buf).map_err(|e| {
if e == SystemError::EOPNOTSUPP_OR_ENOTSUP {
SystemError::EIO
} else {
e
}
});
return r;
}
fn store(
&self,
kobj: Arc<dyn KObject>,
attr: &dyn Attribute,
buf: &[u8],
) -> Result<usize, SystemError> {
let r = attr.store(kobj, buf).map_err(|e| {
if e == SystemError::EOPNOTSUPP_OR_ENOTSUP {
SystemError::EIO
} else {
e
}
});
return r;
}
}
#[derive(Debug)]
pub struct KObjectManager;
impl KObjectManager {
#[allow(dead_code)]
pub fn init_and_add_kobj(
kobj: Arc<dyn KObject>,
join_kset: Option<Arc<KSet>>,
) -> Result<(), SystemError> {
Self::kobj_init(&kobj);
Self::add_kobj(kobj, join_kset)
}
#[allow(dead_code)]
pub fn kobj_init(kobj: &Arc<dyn KObject>) {
kobj.set_kobj_type(Some(&DynamicKObjKType));
}
pub fn add_kobj(
kobj: Arc<dyn KObject>,
join_kset: Option<Arc<KSet>>,
) -> Result<(), SystemError> {
if let Some(kset) = join_kset {
kset.join(&kobj);
// 如果kobject没有parent那么就将这个kset作为parent
if kobj.parent().is_none() {
kobj.set_parent(Some(Arc::downgrade(&(kset as Arc<dyn KObject>))));
}
}
let r = Self::create_dir(kobj.clone());
if let Err(e) = r {
// https://code.dragonos.org.cn/xref/linux-6.1.9/lib/kobject.c?r=&mo=10426&fi=394#224
if let Some(kset) = kobj.kset() {
kset.leave(&kobj);
}
kobj.set_parent(None);
if e == SystemError::EEXIST {
kerror!("KObjectManager::add_kobj() failed with error: {e:?}, kobj:{kobj:?}");
}
return Err(e);
}
kobj.update_kobj_state(Some(KObjectState::IN_SYSFS), None);
return Ok(());
}
fn create_dir(kobj: Arc<dyn KObject>) -> Result<(), SystemError> {
// create dir in sysfs
sysfs_instance().create_dir(kobj.clone())?;
// create default attributes in sysfs
if let Some(ktype) = kobj.kobj_type() {
let groups = ktype.attribute_groups();
if let Some(groups) = groups {
let r = sysfs_instance().create_groups(&kobj, groups);
if let Err(e) = r {
sysfs_instance().remove_dir(&kobj);
return Err(e);
}
}
}
return Ok(());
}
/// 从sysfs中移除kobject
pub fn remove_kobj(kobj: Arc<dyn KObject>) {
let ktype = kobj.kobj_type();
if let Some(ktype) = ktype {
if let Some(groups) = ktype.attribute_groups() {
sysfs_instance().remove_groups(&kobj, groups);
}
}
// todo: 发送uevent: KOBJ_REMOVE
sysfs_instance().remove_dir(&kobj);
kobj.update_kobj_state(None, Some(KObjectState::IN_SYSFS));
let kset = kobj.kset();
if let Some(kset) = kset {
kset.leave(&kobj);
}
kobj.set_parent(None);
}
}
/// 动态创建的kobject对象的ktype
#[derive(Debug)]
pub struct DynamicKObjKType;
impl KObjType for DynamicKObjKType {
fn release(&self, kobj: Arc<dyn KObject>) {
kdebug!("DynamicKObjKType::release() kobj:{:?}", kobj.name());
}
fn sysfs_ops(&self) -> Option<&dyn SysFSOps> {
Some(&KObjectSysFSOps)
}
fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> {
None
}
}