driver.rs under Rust-for-Linux
driver.rs
// SPDX-License-Identifier: GPL-2.0
//! 不同总线(例如PCI、平台、Amba等)的驱动程序的通用支持。
//!
//! 每个总线/子系统都需要实现[`DriverOps`] trait,以允许驱动程序使用[`Registration`]类进行注册。
use crate::{error::code::*, str::CStr, sync::Arc, Result, ThisModule};
use alloc::boxed::Box;
use core::{cell::UnsafeCell, marker::PhantomData, ops::Deref, pin::Pin};
/// 允许编写特定总线的驱动程序的子系统(例如PCI、平台、Amba等)。
pub trait DriverOps {
/// 保存与注册相关信息的类型。通常是由内核的C部分定义的结构体。
type RegType: Default;
/// 注册一个驱动程序。
///
/// # 安全性
///
/// `reg`必须指向有效、已初始化和可写入的内存。该函数可能会修改`reg`以保存注册状态。
///
/// 成功后,`reg`必须保持固定且有效,直到与之匹配的调用[`DriverOps::unregister`]。
unsafe fn register(
reg: *mut Self::RegType,
name: &'static CStr,
module: &'static ThisModule,
) -> Result;
/// 注销之前使用[`DriverOps::register`]注册的驱动程序。
///
/// # 安全性
///
/// `reg`必须指向有效可写入的内存,由先前成功调用[`DriverOps::register`]进行初始化。
unsafe fn unregister(reg: *mut Self::RegType);
}
/// 驱动程序的注册信息。
pub struct Registration<T: DriverOps> {
is_registered: bool,
concrete_reg: UnsafeCell<T::RegType>,
}
// SAFETY: `Registration`的字段或方法无法通过`&Registration`访问,因此可以安全地与多个线程共享对它的引用,因为无法执行任何操作。
unsafe impl<T: DriverOps> Sync for Registration<T> {}
impl<T: DriverOps> Registration<T> {
/// 创建注册对象的新实例。
pub fn new() -> Self {
Self {
is_registered: false,
concrete_reg: UnsafeCell::new(T::RegType::default()),
}
}
/// 分配一个固定的注册对象并进行注册。
///
/// 返回一个固定的堆分配的注册对象。
pub fn new_pinned(name: &'static CStr, module: &'static ThisModule) -> Result<Pin<Box<Self>>> {
let mut reg = Pin::from(Box::try_new(Self::new())?);
reg.as_mut().register(name, module)?;
Ok(reg)
}
/// 使用其子系统注册驱动程序。
///
/// 必须进行固定,因为表示注册的内存块可能自引用。
pub fn register(
self: Pin<&mut Self>,
name: &'static CStr,
module: &'static ThisModule,
) -> Result {
// SAFETY: 我们不会从`this`中移出任何内容。
let this = unsafe { self.get_unchecked_mut() };
if this.is_registered {
// 已注册。
return Err(EINVAL);
}
// SAFETY: 通过默认构造函数初始化了`concrete_reg`。在调用`Self::drop`之前,它只有在成功调用`T::unregister`之后才会被释放。
unsafe { T::register(this.concrete_reg.get(), name, module) }?;
this.is_registered = true;
Ok(())
}
}
impl<T: DriverOps> Default for Registration<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: DriverOps> Drop for Registration<T> {
fn drop(&mut self) {
if self.is_registered {
// SAFETY: 仅当之前对`T::register`的调用成功完成后,才会执行此路径。
unsafe { T::unregister(self.concrete_reg.get()) };
}
}
}
/// 设备ID到原始设备ID的转换。
///
/// 这应该由总线/子系统实现,以便它们可以使用[`IdTable`]来在编译时保证设备ID表的零终止。
///
/// # 安全性
///
/// 实现者必须确保:
/// - [`RawDeviceId::ZERO`]实际上是原始设备ID的零值。
/// - [`RawDeviceId::to_rawid`]将`offset`存储在原始设备ID的上下文/数据字段中,以便总线可以恢复指向数据的指针。
#[const_trait]
pub unsafe trait RawDeviceId {
/// 保存设备ID的原始类型。
///
/// 由[`Self`]创建的ID表将在其零终止数组中保存此类型。
type RawType: Copy;
/// 原始设备ID的零值表示。
///
/// 由[`Self`]创建的ID表使用[`Self::ZERO`]作为标记来表示表的结束。
const ZERO: Self::RawType;
/// 将ID转换为原始ID。
///
/// `offset`是从存储原始设备ID的内存位置偏移的偏移量。实现必须将其存储在原始类型的适当上下文/数据字段中。
fn to_rawid(&self, offset: isize) -> Self::RawType;
}
/// 零终止的设备ID数组,后跟上下文数据。
#[repr(C)]
pub struct IdArray<T: RawDeviceId, U, const N: usize> {
ids: [T::RawType; N],
sentinel: T::RawType,
id_infos: [Option<U>; N],
}
impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
/// 创建数组的新实例。
///
/// 内容源自给定的标识符和上下文信息。
pub const fn new(ids: [T; N], infos: [Option<U>; N]) -> Self
where
T: ~const RawDeviceId + Copy,
{
let mut array = Self {
ids: [T::ZERO; N],
sentinel: T::ZERO,
id_infos: infos,
};
let mut i = 0usize;
while i < N {
// SAFETY: 两个指针都在`array`内(或一个字节之外),因此它们都是从同一分配对象派生的。
// 我们使用了一个`u8`指针,其大小为1,因此指针必然对齐于1字节。
let offset = unsafe {
(&array.id_infos[i] as *const _ as *const u8)
.offset_from(&array.ids[i] as *const _ as _)
};
array.ids[i] = ids[i].to_rawid(offset);
i += 1;
}
array
}
/// 返回由`self`支持的`IdTable`。
///
/// 这用于基本上消除了数组大小。
pub const fn as_table(&self) -> IdTable<'_, T, U> {
IdTable {
first: &self.ids[0],
_p: PhantomData,
}
}
}
/// 设备ID表。
///
/// 保证表以零终止,并后跟类型为`Option<U>`的上下文数据数组。
pub struct IdTable<'a, T: RawDeviceId, U> {
first: &'a T::RawType,
_p: PhantomData<&'a U>,
}
impl<T: RawDeviceId, U> const AsRef<T::RawType> for IdTable<'_, T, U> {
fn as_ref(&self) -> &T::RawType {
self.first
}
}
/// 计算括号括起的逗号分隔项的数量。
///
/// # Examples
///
///
/// # use kernel::count_paren_items; /// /// assert_eq!(0, count_paren_items!()); /// assert_eq!(1, count_paren_items!((A))); /// assert_eq!(1, count_paren_items!((A),)); /// assert_eq!(2, count_paren_items!((A), (B))); /// assert_eq!(2, count_paren_items!((A), (B),)); /// assert_eq!(3, count_paren_items!((A), (B), (C))); /// assert_eq!(3, count_paren_items!((A), (B), (C),)); /// ```
#[macro_export] macro_rules! count_paren_items { (($($item:tt)), $($remaining:tt)) => { 1 + $crate::count_paren_items!($($remaining)) }; (($($item:tt))) => { 1 }; () => { 0 }; }
/// 将逗号分隔的键值对转换为只包含第一个元素的数组。也就是,它丢弃了键值对的第二个元素。
///
/// 此外,如果第一个元素包含在花括号中,它会自动引入一个类型,例如,如果是{v: 10}
,它会变成X { v: 10 }
;这样可以避免重复类型的问题。
///
/// # Examples
///
/// /// # use kernel::first_item;
///
/// #[derive(PartialEq, Debug)]
/// struct X {
/// v: u32,
/// }
///
/// assert_eq!([] as [X; 0], first_item!(X, ));
/// assert_eq!([X { v: 10 }], first_item!(X, {v: 10}));
/// assert_eq!([X { v: 10 }], first_item!(X, {v: 10}, ));
/// assert_eq!([X { v: 10 }, X { v: 20 }], first_item!(X, {v: 10}, {v: 20}));
/// assert_eq!([X { v: 10 }, X { v: 20 }], first_item!(X, {v: 10}, {v: 20}, ));
/// assert_eq!([X { v: 10 }, X { v: 20 }, X { v: 30 }], first_item!(X, {v: 10}, {v: 20}, {v: 30}));
/// assert_eq!([X { v: 10 }, X { v: 20 }, X { v: 30 }], first_item!(X, {v: 10}, {v: 20}, {v: 30}, ));
///
#[macro_export] macro_rules! first_item { ($type:ty, $({ $($key:ident: $value:expr), }) $(,) ) => {{ let items: [($type,); $crate::count_paren_items!($($($key: $value),))] = [ $($type $(::$key) { $($key: $value), }), ]; items }}; }
/// 将逗号分隔的键值对转换为只包含第一个元素的数组,并自动为每个元素引入一个类型。
///
/// 此外,如果第一个元素包含在花括号中,它会自动引入一个类型,例如,如果是{v: 10}
,它会变成X { v: 10 }
;这样可以避免重复类型的问题。
///
/// # Examples
///
/// /// # use kernel::first_item_typed;
///
/// #[derive(PartialEq, Debug)]
/// struct X {
/// v: u32,
/// }
///
/// assert_eq!([] as [X; 0], first_item_typed!(X, ));
/// assert_eq!([X { v: 10 }], first_item_typed!(X, {v: 10}));
/// assert_eq!([X { v: 10 }], first_item_typed!(X, {v: 10}, ));
/// assert_eq!([X { v: 10 }, X { v: 20 }], first_item_typed!(X, {v: 10}, {v: 20}));
/// assert_eq!([X { v: 10 }, X { v: 20 }], first_item_typed!(X, {v: 10}, {v: 20}, ));
/// assert_eq!([X { v: 10 }, X { v: 20 }, X { v: 30 }], first_item_typed!(X, {v: 10}, {v: 20}, {v: 30}));
/// assert_eq!([X { v: 10 }, X { v: 20 }, X { v: 30 }], first_item_typed!(X, {v: 10}, {v: 20}, {v: 30}, ));
///
#[macro_export] macro_rules! first_item_typed { ($type:ty, $({ $($key:ident: $value:expr), }) $(,) ) => {{ let items: [($type,); $crate::count_paren_items!($($($key: $value),))] = [ $($type $(::$key) { $($key: $value), }), ]; items }}; }
/// 根据给定的条件选择第一个元素,并返回其索引。
///
/// # Examples
///
/// /// # use kernel::first_index;
///
/// assert_eq!(None, first_index!(true => 1, ));
/// assert_eq!(Some(0), first_index!(true => 1, false => 2, ));
/// assert_eq!(Some(1), first_index!(false => 1, true => 2, ));
///
#[macro_export] macro_rules! first_index { ($($cond:expr => $value:expr,)+) => {{ let mut index = 0; $( if $cond { return Some(index); } index += 1; )+ None }}; }
/// 选择第一个条件为true
的元素,并返回该元素。
///
/// # Examples
///
/// /// # use kernel::first_match;
///
/// assert_eq!(None, first_match!(true => 1, ));
/// assert_eq!(Some(1), first_match!(true => 1, false => 2, ));
/// assert_eq!(Some(2), first_match!(false => 1, true => 2, ));
///
#[macro_export] macro_rules! first_match { ($($cond:expr => $value:expr,)+) => {{ $( if $cond { return Some($value); } )+ None }}; }
/// 返回一个由逗号分隔的条件数组中第一个条件为true
的值。
///
/// # Examples
///
/// /// # use kernel::first_value;
///
/// assert_eq!(None, first_value!(true, ));
/// assert_eq!(Some(1), first_value!(true, false, 1, ));
/// assert_eq!(Some(2), first_value!(false, true, 2, ));
///
#[macro_export] macro_rules! first_value { ($($cond:expr, $value:expr,)+) => {{ let mut index = 0; $( if $cond { return Some($value); } index += 1; )+ None }}; }
/// 返回一个由逗号分隔的条件数组中第一个条件为true
的索引。
///
/// # Examples
///
/// /// # use kernel::first_index_true;
///
/// assert_eq!(None, first_index_true!(true, ));
/// assert_eq!(Some(0), first_index_true!(true, false, ));
/// assert_eq!(Some(1), first_index_true!(false, true, ));
///
#[macro_export] macro_rules! first_index_true { ($($cond:expr,)+) => {{ let mut index = 0; $( if $cond { return Some(index); } index += 1; )+ None }}; }
/// 返回一个由逗号分隔的条件数组中第一个条件为false
的索引。
///
/// # Examples
///
/// /// # use kernel::first_index_false;
///
/// assert_eq!(None, first_index_false!(false, ));
/// assert_eq!(Some(0), first_index_false!(false, true, ));
/// assert_eq!(Some(1), first_index_false!(true, false, ));
///
#[macro_export] macro_rules! first_index_false { ($($cond:expr,)+) => {{ let mut index = 0; $( if !$cond { return Some(index); } index += 1; )+ None }}; }
/// 返回一个由逗号分隔的条件数组中第一个条件为false
的值。
///
/// # Examples
///
/// /// # use kernel::first_false;
///
/// assert_eq!(None, first_false!(false, ));
/// assert_eq!(Some(true), first_false!(false, true, ));
/// assert_eq!(Some(false), first_false!(true, false, ));
///
#[macro_export] macro_rules! first_false { ($($cond:expr, $value:expr,)+) => {{ let mut index = 0; $( if !$cond { return Some($value); } index += 1; )+ None }}; }
/// 将逗号分隔的键值对转换为带有第一个键值对的元组。
///
/// # Examples
///
/// /// # use kernel::first_tuple;
///
/// assert_eq!((), first_tuple!());
/// assert_eq!((1, "hello"), first_tuple!(1 => "hello"));
/// assert_eq!((1, "hello"), first_tuple!(1 => "hello",));
/// assert_eq!((1, "hello", 2, "world"), first_tuple!(1 => "hello", 2 => "world"));
/// assert_eq!((1, "hello", 2, "world"), first_tuple!(1 => "hello", 2 => "world",));
/// assert_eq!((1, "hello", 2, "world", 3, "foo"), first_tuple!(1 => "hello", 2 => "world", 3 => "foo"));
/// assert_eq!((1, "hello", 2, "world", 3, "foo"), first_tuple!(1 => "hello", 2 => "world", 3 => "foo",));
///
#[macro_export] macro_rules! first_tuple { ($({ $key:expr => $value:expr },)) => {($($key, $value),)}; ($({ $key:expr => $value:expr }),) => {($($key, $value),)}; () => {()}; }
/// 将逗号分隔的表达式转换为第一个表达式的值。
///
/// # Examples
///
/// /// # use kernel::first_expr;
///
/// assert_eq!((), first_expr!());
/// assert_eq!(1, first_expr!(1));
/// assert_eq!(1, first_expr!(1,));
/// assert_eq!(1, first_expr!(1, 2));
/// assert_eq!(1, first_expr!(1, 2,));
/// assert_eq!(1, first_expr!(1, 2, 3));
/// assert_eq!(1, first_expr!(1, 2, 3,));
///
#[macro_export] macro_rules! first_expr { ($first:expr $(, $expr:expr)*) => {$first}; }
/// 将逗号分隔的表达式转换为第一个表达式的引用。
///
/// # Examples
///
/// /// # use kernel::first_expr_ref;
///
/// assert_eq!((), first_expr_ref!());
/// assert_eq!(&1, first_expr_ref!(&1));
/// assert_eq!(&1, first_expr_ref!(&1,));
/// assert_eq!(&1, first_expr_ref!(&1, &2));
/// assert_eq!(&1, first_expr_ref!(&1, &2,));
/// assert_eq!(&1, first_expr_ref!(&1, &2, &3));
/// assert_eq!(&1, first_expr_ref!(&1, &2, &3,));
///
#[macro_export] macro_rules! first_expr_ref { ($first:expr $(, $expr:expr)*) => {&$first}; }
/// 定义一组可能的错误代码。
///
/// # Examples
///
/// /// # use kernel::errno;
///
/// errno! {
/// pub ERR1 = 1;
/// pub ERR2 = 2;
/// pub ERR3 = 3;
/// }
///
/// assert_eq!(1, ERR1);
/// assert_eq!(2, ERR2);
/// assert_eq!(3, ERR3);
///
#[macro_export] macro_rules! errno { ($($(#[$attr:meta]) pub $name:ident = $value:expr;)+) => { $( $(#[$attr]) pub const $name: $crate::error::code::Errno = $crate::error::code::Errno($value); )+ }; }
/// 定义一组可能的错误代码(通过结构体定义)。
///
/// # Examples
///
/// /// # use kernel::errno_struct;
///
/// errno_struct! {
/// pub struct Errno {
/// pub ERR1 = 1;
/// pub ERR2 = 2;
/// pub ERR3 = 3;
/// }
/// }
///
/// assert_eq!(1, Errno::ERR1);
/// assert_eq!(2, Errno::ERR2);
/// assert_eq!(3, Errno::ERR3);
///
#[macro_export] macro_rules! errno_struct { ( $(#[$struct_attr:meta]) $vis:vis struct $struct_name:ident { $($($(#[$attr:meta]) $name:ident = $value:expr;)+)+ } ) => { $(#[$struct_attr])*
#[derive(Debug, PartialEq, Eq, Copy, Clone)] $vis struct $struct_name { $($($(#[$attr])* $name = $value),+)+ }
$( $(#[$struct_attr]) impl $struct_name { $( $(#[$attr]) pub const $name: Self = Self { $name: $value }; )+ } )+ }; }
/// 定义一组错误代码。
///
/// # Examples
///
/// /// # use kernel::error_codes;
///
/// error_codes! {
/// pub ERR1 => 1,
/// pub ERR2 => 2,
/// pub ERR3 => 3,
/// }
///
/// assert_eq!(1, ERR1);
/// assert_eq!(2, ERR2);
/// assert_eq!(3, ERR3);
///
#[macro_export] macro_rules! error_codes { ($($(#[$attr:meta]) pub $name:ident => $value:expr,)+) => { $( $(#[$attr]) pub const $name: i32 = $value; )+ }; }
/// 定义一组错误代码(通过结构体定义)。
///
/// # Examples
///
/// /// # use kernel::error_codes_struct;
///
/// error_codes_struct! {
/// pub struct ErrorCodes {
/// pub ERR1 => 1,
/// pub ERR2 => 2,
/// pub ERR3 => 3,
/// }
/// }
///
/// assert_eq!(1, ErrorCodes::ERR1);
/// assert_eq!(2, ErrorCodes::ERR2);
/// assert_eq!(3, ErrorCodes::ERR3);
///
#[macro_export] macro_rules! error_codes_struct { ( $(#[$struct_attr:meta]) $vis:vis struct $struct_name:ident { $($($(#[$attr:meta]) $name:ident => $value:expr,)+)+ } ) => { $(#[$struct_attr])*
#[derive(Debug, PartialEq, Eq, Copy, Clone)] $vis struct $struct_name { $($($(#[$attr])* $name = $value),+)+ }
$( $(#[$struct_attr]) impl $struct_name { $( $(#[$attr]) pub const $name: Self = Self { $name: $value }; )+ } )+ }; }
/// 定义一个从C常量到Rust常量的映射。
///
/// # Examples
///
/// /// # use kernel::c_to_rust;
///
/// c_to_rust! {
/// CONSTANT1,
/// CONSTANT2,
/// CONSTANT3,
/// }
///
/// assert_eq!(CONSTANT1, "constant1");
/// assert_eq!(CONSTANT2, "constant2");
/// assert_eq!(CONSTANT3, "constant3");
///
#[macro_export] macro_rules! c_to_rust { ($($name:ident),+ $(,)?) => { $(const $name: &str = stringify!($name);)+ }; }
/// 定义一个从Rust常量到C常量的映射。
///
/// # Examples
///
/// /// # use kernel::rust_to_c;
///
/// rust_to_c! {
/// "constant1" => CONSTANT1,
/// "constant2" => CONSTANT2,
/// "constant3" => CONSTANT3,
/// }
///
/// assert_eq!(rust_to_c!("constant1"), Some(CONSTANT1));
/// assert_eq!(rust_to_c!("constant2"), Some(CONSTANT2));
/// assert_eq!(rust_to_c!("constant3"), Some(CONSTANT3));
/// assert_eq!(rust_to_c!("constant4"), None);
///
#[macro_export] macro_rules! rust_to_c { ($($name:expr => $constant:ident),+ $(,)?) => { fn rust_toc(name: &str) -> Option<&'static str> { match name { $($name => Some(stringify!($constant)),)+ => None, } } }; }
/// 将一个值转换为对齐到指定对齐方式的最接近的大于等于它的值。
///
/// # Examples
///
/// /// # use kernel::align_up;
///
/// assert_eq!(align_up!(5, 4), 8);
/// assert_eq!(align_up!(7, 4), 8);
/// assert_eq!(align_up!(9, 4), 12);
/// assert_eq!(align_up!(13, 8), 16);
///
#[macro_export] macro_rules! align_up { ($value:expr, $alignment:expr) => { (($value + $alignment - 1) / $alignment) * $alignment }; }
/// 将一个值转换为对齐到指定对齐方式的最接近的小于等于它的值。
///
/// # Examples
///
/// /// # use kernel::align_down;
///
/// assert_eq!(align_down!(5, 4), 4);
/// assert_eq!(align_down!(7, 4), 4);
/// assert_eq!(align_down!(9, 4), 8);
/// assert_eq!(align_down!(13, 8), 8);
///
#[macro_export] macro_rules! align_down { ($value:expr, $alignment:expr) => { ($value / $alignment) * $alignment }; }
/// 定义一个简单的包装结构体,该结构体将值存储在堆上,并在析构时释放该值。
///
/// # Examples
///
/// /// # use kernel::HeapAlloc;
/// #
/// # let value = vec![1, 2, 3];
/// #
/// # fn main() {
/// let heap_alloc = HeapAlloc::new(value);
/// // 使用heap_alloc...
/// # }
///
pub struct HeapAlloc(Box);
impl HeapAlloc {
/// 创建一个新的HeapAlloc
实例。
///
/// 参数value
是要存储在堆上的值。
pub fn new(value: T) -> Self {
Self(Box::new(value))
}
}
impl Deref for HeapAlloc { type Target = T;
fn deref(&self) -> &Self::Target { &self.0 } }
impl Drop for HeapAlloc { fn drop(&mut self) { // 在析构时释放存储在堆上的值。 } } ```