blob: 9c9fc5787924a6e95b7e5a4eda0d0b35e91ce7be [file]
// Copyright 2026 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
/// The maximum number of interrupts supported in the system.
pub const MAX_INTERRUPTS: usize = 1024;
/// The maximum number of MSI IRQs.
pub const MAX_MSI_IRQS: usize = 32;
/// Represents an interrupt vector number.
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct InterruptVector(pub u32);
impl InterruptVector {
/// Creates a new `InterruptVector` from a raw `u32`.
#[inline]
pub const fn from_raw(vector: u32) -> Self {
Self(vector)
}
/// Converts this `InterruptVector` to its underlying `u32` value.
#[inline]
pub const fn raw(self) -> u32 {
self.0
}
}
impl From<u32> for InterruptVector {
#[inline]
fn from(vector: u32) -> Self {
Self(vector)
}
}
impl From<InterruptVector> for u32 {
#[inline]
fn from(vector: InterruptVector) -> u32 {
vector.0
}
}
impl From<InterruptVector> for usize {
#[inline]
fn from(vector: InterruptVector) -> usize {
vector.0 as usize
}
}
impl core::ops::Deref for InterruptVector {
type Target = u32;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
pub struct InterruptHandler {
pub cookie: *mut core::ffi::c_void,
pub r#fn: Option<extern "C" fn(*mut core::ffi::c_void) -> ()>,
}
zr::static_assert_size_and_align!(InterruptHandler, 16, 8);
impl InterruptHandler {
pub const DEFAULT: Self = Self { cookie: core::ptr::null_mut(), r#fn: None };
pub fn present(&self) -> bool {
self.r#fn.is_some()
}
pub fn invoke(&self) {
debug_assert!(self.present());
(self.r#fn.unwrap())(self.cookie)
}
}
/// The trigger mode of an interrupt.
#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InterruptTriggerMode {
/// Edge triggered interrupt.
Edge = 0,
/// Level triggered interrupt.
Level = 1,
}
impl InterruptTriggerMode {
/// Returns a string representation of the trigger mode.
pub fn string(self) -> &'static str {
match self {
InterruptTriggerMode::Edge => "edge",
InterruptTriggerMode::Level => "level",
}
}
}
/// The polarity of an interrupt.
#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InterruptPolarity {
/// Active high or rising edge polarity.
High = 0,
/// Active low or falling edge polarity.
Low = 1,
}
impl InterruptPolarity {
/// Returns a string representation of the polarity.
pub fn string(self) -> &'static str {
match self {
InterruptPolarity::High => "high",
InterruptPolarity::Low => "low",
}
}
}
/// A structure which holds the state of a block of IRQs allocated by the
/// platform to be used for delivering MSI or MSI-X interrupts.
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct MsiBlock {
/// The target write transaction physical address.
pub tgt_addr: u64,
/// The data which the device should write when triggering an IRQ. Note,
/// only the lower 16 bits are used when the block has been allocated for MSI
/// instead of MSI-X.
pub tgt_data: u32,
/// The first IRQ id in the allocated block.
pub base_irq_id: u32,
/// The number of irqs in the allocated block.
pub num_irq: u32,
/// Whether or not this block has been allocated.
pub allocated: bool,
/// 32 bit if true, 64 bit otherwise.
pub is_32bit: bool,
}
const _: () = assert!(core::mem::size_of::<InterruptVector>() == 4);
const _: () = assert!(core::mem::align_of::<InterruptVector>() == 4);
const _: () = assert!(core::mem::size_of::<InterruptTriggerMode>() == 4);
const _: () = assert!(core::mem::align_of::<InterruptTriggerMode>() == 4);
const _: () = assert!(core::mem::size_of::<InterruptPolarity>() == 4);
const _: () = assert!(core::mem::align_of::<InterruptPolarity>() == 4);
const _: () = assert!(core::mem::size_of::<MsiBlock>() == 24);
const _: () = assert!(core::mem::align_of::<MsiBlock>() == 8);