moana_std 0.1.2

moana 用户标准库
Documentation
//! device / irq 系列 syscall 用户态接口

use core::mem::MaybeUninit;

use moa_uapi::{
    channel::ChanHandle,
    device::{DeviceInfo, IrqHandle},
    error::{ERR_BUSY, ERR_FAULT, ERR_INVAL, ERR_NO_RESOURCE, ERR_NOT_FOUND, ERR_PERM},
    mem::MemHandle,
    sysnr::{
        SYSNR_DEVICE_ACQUIRE, SYSNR_DEVICE_COUNT, SYSNR_DEVICE_GET_PROP, SYSNR_DEVICE_QUERY,
        SYSNR_DEVICE_RELEASE, SYSNR_IRQ_ACK, SYSNR_IRQ_BIND, SYSNR_IRQ_UNBIND,
    },
};

/// device / irq 系列 syscall 返回类型
pub type Result<T> = core::result::Result<T, DeviceError>;

define_syscall_error! {
    /// device / irq 系列 syscall 错误
    pub enum DeviceError {
        /// 权限不足
        Perm = ERR_PERM,
        /// 设备或属性不存在
        NotFound = ERR_NOT_FOUND,
        /// 无效参数
        Inval = ERR_INVAL,
        /// 资源配额耗尽
        NoResource = ERR_NO_RESOURCE,
        /// 无效指针
        Fault = ERR_FAULT,
        /// 设备资源未完全释放
        Busy = ERR_BUSY,
    }
}

/// 返回平台设备总数
#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
pub fn device_count() -> Result<u32> {
    let ret = unsafe { super::arch::syscall0(SYSNR_DEVICE_COUNT) };
    if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(ret as u32) }
}

/// 查询第 `index` 个设备的基本信息
pub fn device_query(index: u32) -> Result<DeviceInfo> {
    let mut info = MaybeUninit::<DeviceInfo>::uninit();
    let ret = unsafe {
        super::arch::syscall2(SYSNR_DEVICE_QUERY, index as usize, info.as_mut_ptr() as usize)
    };
    if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(unsafe { info.assume_init() }) }
}

/// 查询第 `index` 个设备的 DTB 属性
///
/// 返回属性实际长度。超过 `buf` 大小时数据被截断,但返回值仍为实际长度。
/// 属性不存在时返回 `Err(NotFound)`。
#[allow(clippy::cast_sign_loss)]
pub fn device_get_prop(index: u32, name: &str, buf: &mut [u8]) -> Result<usize> {
    let ret = unsafe {
        super::arch::syscall5(
            SYSNR_DEVICE_GET_PROP,
            index as usize,
            name.as_ptr() as usize,
            name.len(),
            buf.as_mut_ptr() as usize,
            buf.len(),
        )
    };
    if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(ret as usize) }
}

/// 独占获取设备资源
///
/// 调用者根据 `DeviceInfo` 的 `mmio_count` / `irq_count` 预分配 slice。
pub fn device_acquire(index: u32, mems: &mut [MemHandle], irqs: &mut [IrqHandle]) -> Result<()> {
    let ret = unsafe {
        super::arch::syscall5(
            SYSNR_DEVICE_ACQUIRE,
            index as usize,
            mems.as_mut_ptr() as usize,
            mems.len(),
            irqs.as_mut_ptr() as usize,
            irqs.len(),
        )
    };
    if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(()) }
}

/// 释放设备独占权
///
/// 需先释放关联的 `MemHandle`(`mem_release`)和解绑 IRQ(`irq_unbind`)。
pub fn device_release(index: u32) -> Result<()> {
    let ret = unsafe { super::arch::syscall1(SYSNR_DEVICE_RELEASE, index as usize) };
    if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(()) }
}

/// 中断绑定到通道
///
/// 中断触发时内核发送 pulse 到指定 channel。
pub fn irq_bind(irq: IrqHandle, chan: ChanHandle) -> Result<()> {
    let ret =
        unsafe { super::arch::syscall2(SYSNR_IRQ_BIND, irq.raw() as usize, chan.raw() as usize) };
    if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(()) }
}

/// 解绑中断
pub fn irq_unbind(irq: IrqHandle) -> Result<()> {
    let ret = unsafe { super::arch::syscall1(SYSNR_IRQ_UNBIND, irq.raw() as usize) };
    if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(()) }
}

/// 确认中断处理完成,允许下一次中断触发
pub fn irq_ack(irq: IrqHandle) -> Result<()> {
    let ret = unsafe { super::arch::syscall1(SYSNR_IRQ_ACK, irq.raw() as usize) };
    if ret < 0 { Err(DeviceError::from_raw(ret)) } else { Ok(()) }
}