use alloc::vec::Vec;
use crate::{VgicError, VgicResult};
pub const LPI_INTID_BASE: u32 = 8192;
pub const LPI_INTID_MAX: u32 = 0x00ff_ffff;
macro_rules! bounded_id {
($name:ident, $inner:ty, $start:expr, $end:expr, $description:literal) => {
#[doc = $description]
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct $name($inner);
impl $name {
pub fn new(raw: $inner) -> VgicResult<Self> {
if ($start..$end).contains(&raw) {
Ok(Self(raw))
} else {
Err(VgicError::InvalidIntId { raw: raw as u32 })
}
}
pub const fn raw(self) -> $inner {
self.0
}
}
};
}
bounded_id!(SgiId, u8, 0, 16, "Software-generated interrupt identifier.");
bounded_id!(
PpiId,
u8,
16,
32,
"Private peripheral interrupt identifier."
);
bounded_id!(
SpiId,
u32,
32,
1020,
"Shared peripheral interrupt identifier."
);
bounded_id!(
LpiId,
u32,
LPI_INTID_BASE,
LPI_INTID_MAX + 1,
"Locality-specific peripheral interrupt identifier."
);
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum IntId {
Sgi(SgiId),
Ppi(PpiId),
Spi(SpiId),
Lpi(LpiId),
}
impl IntId {
pub fn new(raw: u32) -> VgicResult<Self> {
match raw {
0..=15 => Ok(Self::Sgi(SgiId(raw as u8))),
16..=31 => Ok(Self::Ppi(PpiId(raw as u8))),
32..=1019 => Ok(Self::Spi(SpiId(raw))),
LPI_INTID_BASE..=LPI_INTID_MAX => Ok(Self::Lpi(LpiId(raw))),
_ => Err(VgicError::InvalidIntId { raw }),
}
}
pub const fn raw(self) -> u32 {
match self {
Self::Sgi(id) => id.raw() as u32,
Self::Ppi(id) => id.raw() as u32,
Self::Spi(id) => id.raw(),
Self::Lpi(id) => id.raw(),
}
}
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct GicVcpuId(usize);
impl GicVcpuId {
pub const fn new(raw: usize) -> Self {
Self(raw)
}
pub const fn raw(self) -> usize {
self.0
}
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct GicAffinity {
aff3: u8,
aff2: u8,
aff1: u8,
aff0: u8,
}
impl GicAffinity {
pub const fn new(aff3: u8, aff2: u8, aff1: u8, aff0: u8) -> Self {
Self {
aff3,
aff2,
aff1,
aff0,
}
}
pub const fn from_mpidr(mpidr: u64) -> Self {
Self::new(
((mpidr >> 32) & 0xff) as u8,
((mpidr >> 16) & 0xff) as u8,
((mpidr >> 8) & 0xff) as u8,
(mpidr & 0xff) as u8,
)
}
pub const fn mpidr(self) -> u64 {
((self.aff3 as u64) << 32)
| ((self.aff2 as u64) << 16)
| ((self.aff1 as u64) << 8)
| self.aff0 as u64
}
pub const fn aff3(self) -> u8 {
self.aff3
}
pub const fn aff2(self) -> u8 {
self.aff2
}
pub const fn aff1(self) -> u8 {
self.aff1
}
pub const fn aff0(self) -> u8 {
self.aff0
}
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct Priority(u8);
impl Priority {
pub const DEFAULT: Self = Self(0x80);
pub const fn new(raw: u8) -> Self {
Self(raw)
}
pub const fn raw(self) -> u8 {
self.0
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TriggerMode {
Edge,
Level,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum InterruptState {
Inactive,
Pending,
Active,
ActivePending,
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct ItsDeviceId(u32);
impl ItsDeviceId {
pub const fn new(raw: u32) -> Self {
Self(raw)
}
pub const fn raw(self) -> u32 {
self.0
}
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct EventId(u32);
impl EventId {
pub const fn new(raw: u32) -> Self {
Self(raw)
}
pub const fn raw(self) -> u32 {
self.0
}
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct CollectionId(u16);
impl CollectionId {
pub const fn new(raw: u16) -> Self {
Self(raw)
}
pub const fn raw(self) -> u16 {
self.0
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum SgiTarget {
Affinities(Vec<GicAffinity>),
AllExceptSelf,
SelfOnly,
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct PhysicalIrqId(u64);
impl PhysicalIrqId {
pub const fn new(raw: u64) -> Self {
Self(raw)
}
pub const fn raw(self) -> u64 {
self.0
}
}