axhal/
irq.rs

1//! Interrupt management.
2
3use handler_table::HandlerTable;
4
5use crate::platform::irq::{MAX_IRQ_COUNT, dispatch_irq};
6use crate::trap::{IRQ, register_trap_handler};
7
8pub use crate::platform::irq::{register_handler, set_enable};
9
10/// The type if an IRQ handler.
11pub type IrqHandler = handler_table::Handler;
12
13static IRQ_HANDLER_TABLE: HandlerTable<MAX_IRQ_COUNT> = HandlerTable::new();
14
15/// Platform-independent IRQ dispatching.
16#[allow(dead_code)]
17pub(crate) fn dispatch_irq_common(irq_num: usize) {
18    trace!("IRQ {}", irq_num);
19    if !IRQ_HANDLER_TABLE.handle(irq_num) {
20        warn!("Unhandled IRQ {}", irq_num);
21    }
22}
23
24/// Platform-independent IRQ handler registration.
25///
26/// It also enables the IRQ if the registration succeeds. It returns `false` if
27/// the registration failed.
28#[allow(dead_code)]
29pub(crate) fn register_handler_common(irq_num: usize, handler: IrqHandler) -> bool {
30    if irq_num < MAX_IRQ_COUNT && IRQ_HANDLER_TABLE.register_handler(irq_num, handler) {
31        set_enable(irq_num, true);
32        return true;
33    }
34    warn!("register handler for IRQ {} failed", irq_num);
35    false
36}
37
38#[register_trap_handler(IRQ)]
39fn handler_irq(irq_num: usize) -> bool {
40    let guard = kernel_guard::NoPreempt::new();
41    dispatch_irq(irq_num);
42    drop(guard); // rescheduling may occur when preemption is re-enabled.
43    true
44}