1use crate::{
2 error::Result,
3 sync::{self, spinlock::RwSpinLocked},
4 types::array::Vec,
5};
6
7pub use hal_api::IrqHandler;
9
10#[derive(Clone, Copy)]
11struct Handler {
12 func: IrqHandler,
13 userdata: Option<usize>,
14}
15
16static HANDLERS: [RwSpinLocked<Vec<Handler, 1>>; 240] =
18 [const { RwSpinLocked::new(Vec::new()) }; 240];
19
20pub unsafe fn register_irq(
30 vector: usize,
31 handler: IrqHandler,
32 userdata: Option<usize>,
33) -> Result<()> {
34 if vector >= HANDLERS.len() {
35 Err(kerr!(EINVAL, "Invalid IRQ vector."))?;
36 }
37
38 let handler = Handler {
39 func: handler,
40 userdata,
41 };
42
43 sync::atomic::irq_free(|| HANDLERS[vector].write_lock().push(handler))
46}
47
48pub fn register_irq_safe(
50 vector: usize,
51 handler: IrqHandler,
52 userdata: Option<usize>,
53) -> hal_api::Result<()> {
54 unsafe { register_irq(vector, handler, userdata) }.map_err(|e| e.kind)
55}
56
57pub unsafe fn unregister_irq(vector: usize) -> Result<()> {
64 if vector >= HANDLERS.len() {
65 Err(kerr!(EINVAL, "Invalid IRQ vector."))?;
66 }
67
68 sync::atomic::irq_free(|| {
69 HANDLERS[vector].write_lock().clear();
70 });
71
72 Ok(())
73}
74
75#[unsafe(no_mangle)]
76extern "C" fn kernel_irq_handler(ctx: *mut u8, vector: usize) {
77 if vector >= HANDLERS.len() {
78 warn!("Invalid IRQ vector {}", vector);
79 return;
80 }
81
82 let handler = HANDLERS[vector].read_lock();
84
85 if handler.is_empty() {
86 warn!("Unhandled IRQ {}", vector);
87 return;
88 }
89
90 for i in 0..handler.len() {
91 let handler = handler[i];
92 (handler.func)(ctx, vector, handler.userdata)
93 }
94}