#![allow(dead_code)]
use core::fmt::Debug;
use crate::{
arch::irq::{self, IrqCallbackHandle, IRQ_ALLOCATOR},
prelude::*,
trap::TrapFrame,
Error,
};
pub type IrqCallbackFunction = dyn Fn(&TrapFrame) + Sync + Send + 'static;
#[derive(Debug)]
#[must_use]
pub struct IrqLine {
irq_num: u8,
#[allow(clippy::redundant_allocation)]
irq: Arc<&'static irq::IrqLine>,
callbacks: Vec<IrqCallbackHandle>,
}
impl IrqLine {
pub fn alloc_specific(irq: u8) -> Result<Self> {
IRQ_ALLOCATOR
.get()
.unwrap()
.lock()
.alloc_specific(irq as usize)
.map(|irq_num| Self::new(irq_num as u8))
.ok_or(Error::NotEnoughResources)
}
pub fn alloc() -> Result<Self> {
let Some(irq_num) = IRQ_ALLOCATOR.get().unwrap().lock().alloc() else {
return Err(Error::NotEnoughResources);
};
Ok(Self::new(irq_num as u8))
}
fn new(irq_num: u8) -> Self {
Self {
irq_num,
irq: unsafe { irq::IrqLine::acquire(irq_num) },
callbacks: Vec::new(),
}
}
pub fn num(&self) -> u8 {
self.irq_num
}
pub fn on_active<F>(&mut self, callback: F)
where
F: Fn(&TrapFrame) + Sync + Send + 'static,
{
self.callbacks.push(self.irq.on_active(callback))
}
pub fn is_empty(&self) -> bool {
self.callbacks.is_empty()
}
}
impl Clone for IrqLine {
fn clone(&self) -> Self {
Self {
irq_num: self.irq_num,
irq: self.irq.clone(),
callbacks: Vec::new(),
}
}
}
impl Drop for IrqLine {
fn drop(&mut self) {
if Arc::strong_count(&self.irq) == 1 {
IRQ_ALLOCATOR
.get()
.unwrap()
.lock()
.free(self.irq_num as usize);
}
}
}
pub fn disable_local() -> DisabledLocalIrqGuard {
DisabledLocalIrqGuard::new()
}
#[clippy::has_significant_drop]
#[must_use]
pub struct DisabledLocalIrqGuard {
was_enabled: bool,
}
impl !Send for DisabledLocalIrqGuard {}
impl DisabledLocalIrqGuard {
fn new() -> Self {
let was_enabled = irq::is_local_enabled();
if was_enabled {
irq::disable_local();
}
Self { was_enabled }
}
pub fn transfer_to(&mut self) -> Self {
let was_enabled = self.was_enabled;
self.was_enabled = false;
Self { was_enabled }
}
}
impl Drop for DisabledLocalIrqGuard {
fn drop(&mut self) {
if self.was_enabled {
irq::enable_local();
}
}
}