Nothing to see here, move along meow
1use crate::sync::IrqMutex;
2
3use crate::arch::idt::IrqVector;
4use crate::cap::object::IrqSource;
5use crate::cap::pool::POOL;
6use crate::ipc::notification;
7use crate::proc::PROCESSES;
8use crate::types::{Generation, NotificationBit, ObjPhys};
9
10const MAX_IRQ_HANDLERS: usize = 32;
11
12#[derive(Clone, Copy)]
13struct IrqBinding {
14 vector: IrqVector,
15 notification_phys: ObjPhys,
16 notification_gen: Generation,
17 bit: NotificationBit,
18}
19
20static BINDINGS: IrqMutex<[Option<IrqBinding>; MAX_IRQ_HANDLERS], 2> =
21 IrqMutex::new([None; MAX_IRQ_HANDLERS]);
22
23pub fn bind(
24 vector: IrqVector,
25 source: IrqSource,
26 notification_phys: ObjPhys,
27 notification_gen: Generation,
28 bit: NotificationBit,
29) -> Result<(), crate::error::KernelError> {
30 let mut bindings = BINDINGS.lock();
31 let slot = bindings
32 .iter()
33 .enumerate()
34 .find(|(_, b)| b.is_none())
35 .map(|(i, _)| i);
36
37 match slot {
38 Some(i) => {
39 bindings[i] = Some(IrqBinding {
40 vector,
41 notification_phys,
42 notification_gen,
43 bit,
44 });
45 match source {
46 IrqSource::Ioapic { gsi } => {
47 crate::arch::ioapic::route_irq(gsi, vector, 0);
48 crate::arch::ioapic::mask_irq(gsi);
49 }
50 IrqSource::Msix { .. } => {}
51 }
52 Ok(())
53 }
54 None => Err(crate::error::KernelError::ResourceExhausted),
55 }
56}
57
58pub fn unbind_by_vector(vector: IrqVector) {
59 let mut bindings = BINDINGS.lock();
60 bindings.iter_mut().for_each(|slot| {
61 if slot.as_ref().is_some_and(|b| b.vector == vector) {
62 *slot = None;
63 }
64 });
65}
66
67pub fn handle_irq(vector: IrqVector) {
68 let bindings = BINDINGS.lock();
69 let found = bindings
70 .iter()
71 .find_map(|b| b.as_ref().filter(|binding| binding.vector == vector));
72
73 if let Some(binding) = found {
74 let bits = binding.bit.mask();
75 let obj_id = binding.notification_phys;
76 let obj_gen = binding.notification_gen;
77 drop(bindings);
78
79 let mut ptable = PROCESSES.lock();
80 let mut pool = POOL.lock_after(&ptable);
81 if let Ok(notif) =
82 pool.write_as::<lancer_core::object_layout::NotificationObject>(obj_id, obj_gen)
83 {
84 notif.word |= bits;
85 match notif.waiter_count > 0 {
86 true => notification::drain_and_wake(notif, &mut ptable),
87 false => {}
88 }
89 }
90 }
91}