mod base;
mod time;
mod spi;
mod rfnc;
mod hsm;
mod srst;
mod pmu;
#[cfg(feature = "legacy")]
use crate::{
ipi::send_ipi, legacy_stdio_getchar, legacy_stdio_putchar, reset::legacy_reset, HartMask,
};
use sbi_spec::{self as spec, binary::SbiRet};
#[inline]
pub fn handle_ecall(extension: usize, function: usize, param: [usize; 6]) -> SbiRet {
match extension {
spec::rfnc::EID_RFNC => {
rfnc::handle_ecall(function, param[0], param[1], param[2], param[3], param[4])
}
spec::time::EID_TIME => match () {
#[cfg(target_pointer_width = "64")]
() => time::handle_ecall(function, param[0]),
#[cfg(target_pointer_width = "32")]
() => time::handle_ecall(function, param[0], param[1]),
},
spec::spi::EID_SPI => spi::handle_ecall(function, param[0], param[1]),
spec::base::EID_BASE => base::handle_ecall(function, param[0]),
spec::hsm::EID_HSM => hsm::handle_ecall(function, param[0], param[1], param[2]),
spec::srst::EID_SRST => srst::handle_ecall(function, param[0], param[1]),
spec::pmu::EID_PMU => match () {
#[cfg(target_pointer_width = "64")]
() => pmu::handle_ecall(function, param[0], param[1], param[2], param[3], param[4]),
#[cfg(target_pointer_width = "32")]
() => pmu::handle_ecall(
function, param[0], param[1], param[2], param[3], param[4], param[5],
),
},
#[cfg(feature = "legacy")]
spec::legacy::LEGACY_SET_TIMER => {
match () {
#[cfg(target_pointer_width = "64")]
() => crate::timer::set_timer(param[0] as _),
#[cfg(target_pointer_width = "32")]
() => crate::timer::set_timer(concat_u32(param[1] as _, param[0] as _)),
};
SbiRet {
error: param[0],
value: param[1],
}
}
#[cfg(feature = "legacy")]
spec::legacy::LEGACY_CONSOLE_PUTCHAR => {
legacy_stdio_putchar(param[0] as _);
SbiRet {
error: param[0],
value: param[1],
}
}
#[cfg(feature = "legacy")]
spec::legacy::LEGACY_CONSOLE_GETCHAR => SbiRet {
error: legacy_stdio_getchar(),
value: param[1],
},
#[cfg(feature = "legacy")]
spec::legacy::LEGACY_SEND_IPI => {
send_ipi(unsafe { HartMask::legacy_from_addr(param[0]) });
SbiRet {
error: param[0],
value: param[1],
}
}
#[cfg(feature = "legacy")]
spec::legacy::LEGACY_CLEAR_IPI => {
unsafe {
riscv::register::mip::clear_ssoft();
}
SbiRet {
error: param[0],
value: param[1],
}
}
#[cfg(feature = "legacy")]
spec::legacy::LEGACY_SHUTDOWN => legacy_reset(),
_ => SbiRet::not_supported(),
}
}
#[cfg(target_pointer_width = "32")]
#[inline]
const fn concat_u32(h: usize, l: usize) -> u64 {
((h as u64) << 32) | (l as u64)
}