1use core::ptr::NonNull;
2
3#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
5pub struct IrqNumber(pub usize);
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
9pub struct CpuId(pub usize);
10
11#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
13pub struct CpuMask {
14 bits: u128,
15}
16
17impl CpuMask {
18 pub const fn empty() -> Self {
20 Self { bits: 0 }
21 }
22
23 pub fn from_cpu(cpu: CpuId) -> Self {
25 let mut mask = Self::empty();
26 mask.insert(cpu);
27 mask
28 }
29
30 pub fn first_n(cpu_count: usize) -> Self {
32 let mut mask = Self::empty();
33 let end = cpu_count.min(u128::BITS as usize);
34 for cpu in 0..end {
35 mask.insert(CpuId(cpu));
36 }
37 mask
38 }
39
40 pub fn insert(&mut self, cpu: CpuId) {
42 if cpu.0 < u128::BITS as usize {
43 self.bits |= 1u128 << cpu.0;
44 }
45 }
46
47 pub fn remove(&mut self, cpu: CpuId) {
49 if cpu.0 < u128::BITS as usize {
50 self.bits &= !(1u128 << cpu.0);
51 }
52 }
53
54 pub const fn contains(self, cpu: CpuId) -> bool {
56 cpu.0 < u128::BITS as usize && (self.bits & (1u128 << cpu.0)) != 0
57 }
58
59 pub const fn is_empty(self) -> bool {
61 self.bits == 0
62 }
63
64 pub fn iter(self) -> CpuMaskIter {
66 CpuMaskIter { bits: self.bits }
67 }
68}
69
70pub struct CpuMaskIter {
72 bits: u128,
73}
74
75impl Iterator for CpuMaskIter {
76 type Item = CpuId;
77
78 fn next(&mut self) -> Option<Self::Item> {
79 if self.bits == 0 {
80 return None;
81 }
82 let cpu = self.bits.trailing_zeros() as usize;
83 self.bits &= !(1u128 << cpu);
84 Some(CpuId(cpu))
85 }
86}
87
88#[derive(Clone, Copy, Debug, Eq, PartialEq)]
90pub enum IrqScope {
91 Global,
93 PerCpu {
95 cpus: CpuMask,
97 },
98}
99
100#[derive(Clone, Copy, Debug, Eq, PartialEq)]
102pub enum ShareMode {
103 Exclusive,
105 Shared,
107}
108
109#[derive(Clone, Copy, Debug, Eq, PartialEq)]
111pub enum AutoEnable {
112 No,
114 Yes,
116}
117
118#[derive(Clone, Copy, Debug, Eq, PartialEq)]
120pub enum IrqReturn {
121 Unhandled,
123 Handled,
125 Wake,
127}
128
129#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
131pub struct IrqOutcome {
132 pub handled: bool,
134 pub wake: bool,
136 pub called: usize,
138}
139
140#[derive(Clone, Copy, Debug, Eq, PartialEq)]
142pub struct IrqStatus {
143 pub action_enabled: bool,
145 pub line_enabled: bool,
147 pub pending: bool,
149 pub in_service: bool,
151 pub in_flight: usize,
153}
154
155#[derive(Clone, Copy, Debug, Eq, PartialEq)]
157pub enum IrqError {
158 InvalidIrq,
160 InvalidCpu,
162 CpuOffline,
164 Busy,
166 NoMemory,
168 NotFound,
170 InIrqContext,
172 Unsupported,
174 Controller,
176}
177
178#[derive(Clone, Copy, Debug, Eq, PartialEq)]
180pub struct IrqContext {
181 pub irq: IrqNumber,
183 pub cpu: CpuId,
185}
186
187pub type RawIrqHandler = unsafe fn(ctx: IrqContext, data: NonNull<()>) -> IrqReturn;
189
190pub trait IrqOps {
192 type LocalIrqState: Copy;
194
195 fn current_cpu(&self) -> CpuId;
197
198 fn cpu_online(&self, cpu: CpuId) -> bool;
200
201 fn in_irq_context(&self) -> bool;
203
204 fn local_irq_save(&self) -> Self::LocalIrqState;
206
207 fn local_irq_restore(&self, state: Self::LocalIrqState);
209
210 fn run_on_cpu_sync(
212 &self,
213 cpu: CpuId,
214 f: unsafe fn(*mut ()),
215 arg: *mut (),
216 ) -> Result<(), IrqError>;
217
218 fn set_enabled(
220 &self,
221 irq: IrqNumber,
222 cpu: Option<CpuId>,
223 enabled: bool,
224 ) -> Result<(), IrqError>;
225
226 fn is_enabled(&self, irq: IrqNumber, cpu: Option<CpuId>) -> Result<bool, IrqError>;
228
229 fn is_pending(&self, irq: IrqNumber, cpu: Option<CpuId>) -> Result<bool, IrqError>;
231
232 fn is_in_service(&self, irq: IrqNumber, cpu: Option<CpuId>) -> Result<bool, IrqError>;
234
235 fn relax(&self);
237}
238
239#[derive(Clone, Copy, Debug)]
241pub struct IrqRequest {
242 pub(crate) handler: RawIrqHandler,
243 pub(crate) data: NonNull<()>,
244 pub(crate) scope: IrqScope,
245 pub(crate) share_mode: ShareMode,
246 pub(crate) auto_enable: AutoEnable,
247}
248
249impl IrqRequest {
250 pub const fn new(handler: RawIrqHandler, data: NonNull<()>) -> Self {
252 Self {
253 handler,
254 data,
255 scope: IrqScope::Global,
256 share_mode: ShareMode::Exclusive,
257 auto_enable: AutoEnable::Yes,
258 }
259 }
260
261 pub const fn scope(mut self, scope: IrqScope) -> Self {
263 self.scope = scope;
264 self
265 }
266
267 pub const fn share_mode(mut self, share_mode: ShareMode) -> Self {
269 self.share_mode = share_mode;
270 self
271 }
272
273 pub const fn auto_enable(mut self, auto_enable: AutoEnable) -> Self {
275 self.auto_enable = auto_enable;
276 self
277 }
278}
279
280#[derive(Clone, Copy, Debug, Eq, PartialEq)]
282pub struct IrqHandle {
283 pub(crate) irq: IrqNumber,
284 pub(crate) id: u64,
285}
286
287impl IrqHandle {
288 pub const fn irq(self) -> IrqNumber {
290 self.irq
291 }
292
293 pub const fn id(self) -> u64 {
295 self.id
296 }
297}