#![no_std]
extern crate alloc;
use core::time::Duration;
pub use ax_errno::{AxError, AxResult};
pub use ax_memory_addr::{PhysAddr, VirtAddr};
pub use irq_framework::{
AutoEnable as IrqAutoEnable, BoxedIrqHandler, ConcurrentBoxedIrqHandler, CpuId as IrqCpuId,
CpuMask as IrqCpuMask, IrqAffinity, IrqContext, IrqError, IrqExecution, IrqHandle, IrqId,
IrqOutcome, IrqRequest, IrqReturn, IrqScope, IrqStatus, ShareMode as IrqShareMode,
};
use trait_ffi::*;
pub const LEGACY_IRQ_DOMAIN: irq_framework::IrqDomainId = irq_framework::IrqDomainId(0);
pub fn try_legacy_irq(raw: usize) -> Result<IrqId, IrqError> {
let hwirq = u32::try_from(raw).map_err(|_| IrqError::InvalidIrq)?;
Ok(IrqId::new(LEGACY_IRQ_DOMAIN, irq_framework::HwIrq(hwirq)))
}
pub fn legacy_irq(raw: usize) -> Result<IrqId, IrqError> {
try_legacy_irq(raw)
}
pub const fn legacy_irq_raw(irq: IrqId) -> Option<usize> {
if irq.domain.0 == LEGACY_IRQ_DOMAIN.0 {
Some(irq.hwirq.0 as usize)
} else {
None
}
}
#[allow(non_snake_case)]
pub fn IrqNumber(raw: usize) -> Result<IrqId, IrqError> {
legacy_irq(raw)
}
pub mod dma;
pub mod mmio;
#[def_extern_trait]
pub trait Klib {
fn mem_iomap(addr: PhysAddr, size: usize) -> AxResult<VirtAddr>;
fn mem_virt_to_phys(addr: VirtAddr) -> PhysAddr;
fn mem_make_dma_coherent_uncached(addr: VirtAddr, size: usize) -> AxResult;
fn mem_restore_dma_cached(addr: VirtAddr, size: usize) -> AxResult;
fn dma_alloc_pages(dma_mask: u64, num_pages: usize, align: usize) -> AxResult<VirtAddr>;
fn dma_dealloc_pages(addr: VirtAddr, num_pages: usize);
fn time_busy_wait(dur: Duration);
fn time_monotonic_nanos() -> u64;
fn time_try_init_epoch_offset(epoch_time_nanos: u64) -> bool;
fn irq_set_enable(irq: IrqId, enabled: bool) -> AxResult;
fn irq_request_shared(irq: IrqId, handler: BoxedIrqHandler) -> AxResult<IrqHandle>;
fn irq_request_shared_disabled(irq: IrqId, handler: BoxedIrqHandler) -> AxResult<IrqHandle>;
fn irq_request_percpu(
irq: IrqId,
cpus: IrqCpuMask,
handler: ConcurrentBoxedIrqHandler,
) -> AxResult<IrqHandle>;
fn irq_free(handle: IrqHandle) -> AxResult;
fn irq_enable(handle: IrqHandle) -> AxResult;
fn irq_disable(handle: IrqHandle) -> AxResult;
unsafe fn irq_run_on_cpu_sync(
cpu: IrqCpuId,
f: unsafe fn(*mut ()),
arg: *mut (),
) -> Result<(), IrqError> {
if cpu.0 == 0 {
unsafe { f(arg) };
Ok(())
} else {
Err(IrqError::Unsupported)
}
}
}
pub mod mem {
pub use super::klib::{
mem_iomap as iomap, mem_make_dma_coherent_uncached as make_dma_coherent_uncached,
mem_restore_dma_cached as restore_dma_cached, mem_virt_to_phys as virt_to_phys,
};
}
pub mod time {
pub use super::klib::{
time_busy_wait as busy_wait, time_monotonic_nanos as monotonic_nanos,
time_try_init_epoch_offset as try_init_epoch_offset,
};
}
pub mod irq {
pub use super::{
BoxedIrqHandler, ConcurrentBoxedIrqHandler, IrqAffinity, IrqAutoEnable as AutoEnable,
IrqContext, IrqCpuId as CpuId, IrqCpuMask as CpuMask, IrqError, IrqExecution, IrqHandle,
IrqId, IrqNumber, IrqOutcome, IrqRequest, IrqReturn, IrqScope, IrqShareMode as ShareMode,
IrqStatus,
klib::{
irq_disable as disable, irq_enable as enable, irq_free as free,
irq_run_on_cpu_sync as run_on_cpu_sync, irq_set_enable as set_enable,
},
legacy_irq, legacy_irq_raw, try_legacy_irq,
};
pub fn request_shared(
irq: IrqId,
handler: impl FnMut(IrqContext) -> IrqReturn + Send + 'static,
) -> super::AxResult<IrqHandle> {
super::klib::irq_request_shared(irq, alloc::boxed::Box::new(handler))
}
pub fn request_shared_disabled(
irq: IrqId,
handler: impl FnMut(IrqContext) -> IrqReturn + Send + 'static,
) -> super::AxResult<IrqHandle> {
super::klib::irq_request_shared_disabled(irq, alloc::boxed::Box::new(handler))
}
pub fn request_percpu(
irq: IrqId,
cpus: CpuMask,
handler: impl Fn(IrqContext) -> IrqReturn + Send + Sync + 'static,
) -> super::AxResult<IrqHandle> {
super::klib::irq_request_percpu(irq, cpus, alloc::boxed::Box::new(handler))
}
}