1 use core::{any::Any, fmt::Debug, intrinsics::unlikely};
2
3 use alloc::{
4 string::{String, ToString},
5 sync::{Arc, Weak},
6 vec::Vec,
7 };
8 use system_error::SystemError;
9
10 use crate::{
11 exception::{
12 dummychip::no_irq_chip,
13 handle::{bad_irq_handler, mask_ack_irq},
14 irqdata::IrqStatus,
15 irqdesc::irq_desc_manager,
16 manage::irq_manager,
17 },
18 libs::{
19 cpumask::CpuMask,
20 once::Once,
21 spinlock::{SpinLock, SpinLockGuard},
22 },
23 mm::VirtAddr,
24 smp::cpu::ProcessorId,
25 };
26
27 use super::{
28 irqdata::{IrqData, IrqHandlerData, IrqLineStatus},
29 irqdesc::{InnerIrqDesc, IrqAction, IrqDesc, IrqFlowHandler, IrqHandler, IrqReturn},
30 irqdomain::IrqDomain,
31 manage::IrqManager,
32 msi::MsiMsg,
33 IrqNumber,
34 };
35
36 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#506
37 pub trait IrqChip: Sync + Send + Any + Debug {
name(&self) -> &'static str38 fn name(&self) -> &'static str;
39 /// start up the interrupt (defaults to ->enable if ENOSYS)
irq_startup(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError>40 fn irq_startup(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
41 Err(SystemError::ENOSYS)
42 }
43
44 /// shut down the interrupt (defaults to ->disable if ENOSYS)
irq_shutdown(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError>45 fn irq_shutdown(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
46 Err(SystemError::ENOSYS)
47 }
48
49 /// enable the interrupt
50 ///
51 /// (defaults to ->unmask if ENOSYS)
irq_enable(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError>52 fn irq_enable(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
53 Err(SystemError::ENOSYS)
54 }
55
56 /// disable the interrupt
irq_disable(&self, irq: &Arc<IrqData>)57 fn irq_disable(&self, irq: &Arc<IrqData>);
58
59 /// start of a new interrupt
irq_ack(&self, irq: &Arc<IrqData>)60 fn irq_ack(&self, irq: &Arc<IrqData>);
61
62 /// mask an interrupt source
63 ///
64 /// 用于屏蔽中断
65 ///
66 /// 如果返回ENOSYS,则表明irq_mask()不支持. 那么中断机制代码将调用irq_disable()。
67 ///
68 /// 如果返回错误,那么中断的屏蔽状态将不会改变。
irq_mask(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError>69 fn irq_mask(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
70 Err(SystemError::ENOSYS)
71 }
72
73 /// 指示当前芯片是否实现了`irq_mask_ack`函数
can_mask_ack(&self) -> bool74 fn can_mask_ack(&self) -> bool;
75
76 /// ack and mask an interrupt source
irq_mask_ack(&self, _irq: &Arc<IrqData>)77 fn irq_mask_ack(&self, _irq: &Arc<IrqData>) {}
78
79 /// unmask an interrupt source
80 ///
81 /// 用于取消屏蔽中断
82 ///
83 /// 如果返回ENOSYS,则表明irq_unmask()不支持.
irq_unmask(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError>84 fn irq_unmask(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
85 Err(SystemError::ENOSYS)
86 }
87 /// end of interrupt
irq_eoi(&self, _irq: &Arc<IrqData>)88 fn irq_eoi(&self, _irq: &Arc<IrqData>) {}
89
90 /// 指示当前芯片是否可以设置中断亲和性。
can_set_affinity(&self) -> bool91 fn can_set_affinity(&self) -> bool;
92
93 /// 在SMP机器上设置CPU亲和性。
94 ///
95 /// 如果force参数为真,它告诉驱动程序无条件地应用亲和性设置。
96 /// 不需要对提供的亲和性掩码进行完整性检查。这用于CPU热插拔,其中目标CPU尚未在cpu_online_mask中设置。
irq_set_affinity( &self, _irq: &Arc<IrqData>, _cpu: &CpuMask, _force: bool, ) -> Result<IrqChipSetMaskResult, SystemError>97 fn irq_set_affinity(
98 &self,
99 _irq: &Arc<IrqData>,
100 _cpu: &CpuMask,
101 _force: bool,
102 ) -> Result<IrqChipSetMaskResult, SystemError> {
103 Err(SystemError::ENOSYS)
104 }
105
106 /// retrigger an IRQ to the CPU
retrigger(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError>107 fn retrigger(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
108 Err(SystemError::ENOSYS)
109 }
110
111 /// 指示当前芯片是否可以设置中断流类型。
112 ///
113 /// 如果返回true,则可以调用irq_set_type()。
can_set_flow_type(&self) -> bool114 fn can_set_flow_type(&self) -> bool;
115
116 /// set the flow type of an interrupt
117 ///
118 /// flow_type: the flow type to set
119 ///
irq_set_type( &self, _irq: &Arc<IrqData>, _flow_type: IrqLineStatus, ) -> Result<IrqChipSetMaskResult, SystemError>120 fn irq_set_type(
121 &self,
122 _irq: &Arc<IrqData>,
123 _flow_type: IrqLineStatus,
124 ) -> Result<IrqChipSetMaskResult, SystemError> {
125 Err(SystemError::ENOSYS)
126 }
127
128 /// enable/disable power management wake-on of an interrupt
irq_set_wake(&self, _irq: &Arc<IrqData>, _on: bool) -> Result<(), SystemError>129 fn irq_set_wake(&self, _irq: &Arc<IrqData>, _on: bool) -> Result<(), SystemError> {
130 Err(SystemError::ENOSYS)
131 }
132
133 /// function to lock access to slow bus (i2c) chips
irq_bus_lock(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError>134 fn irq_bus_lock(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
135 Ok(())
136 }
137
138 /// function to sync and unlock slow bus (i2c) chips
irq_bus_sync_unlock(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError>139 fn irq_bus_sync_unlock(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
140 Ok(())
141 }
142
143 /// function called from core code on suspend once per
144 /// chip, when one or more interrupts are installed
irq_suspend(&self, _irq: &Arc<IrqData>)145 fn irq_suspend(&self, _irq: &Arc<IrqData>) {}
146
147 /// function called from core code on resume once per chip,
148 /// when one ore more interrupts are installed
irq_resume(&self, _irq: &Arc<IrqData>)149 fn irq_resume(&self, _irq: &Arc<IrqData>) {}
150
151 /// function called from core code on shutdown once per chip
irq_pm_shutdown(&self, _irq: &Arc<IrqData>)152 fn irq_pm_shutdown(&self, _irq: &Arc<IrqData>) {}
153
154 /// Optional function to set irq_data.mask for special cases
irq_calc_mask(&self, _irq: &Arc<IrqData>)155 fn irq_calc_mask(&self, _irq: &Arc<IrqData>) {}
156
157 // todo: print chip
158
159 /// optional to request resources before calling
160 /// any other callback related to this irq
irq_request_resources(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError>161 fn irq_request_resources(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
162 Ok(())
163 }
164
165 /// optional to release resources acquired with
166 /// irq_request_resources
irq_release_resources(&self, _irq: &Arc<IrqData>)167 fn irq_release_resources(&self, _irq: &Arc<IrqData>) {}
168
169 /// optional to compose message content for MSI
170 ///
171 /// 组装MSI消息并返回到msg中
irq_compose_msi_msg(&self, _irq: &Arc<IrqData>, _msg: &mut MsiMsg)172 fn irq_compose_msi_msg(&self, _irq: &Arc<IrqData>, _msg: &mut MsiMsg) {}
173
174 /// optional to write message content for MSI
irq_write_msi_msg(&self, _irq: &Arc<IrqData>, _msg: &MsiMsg)175 fn irq_write_msi_msg(&self, _irq: &Arc<IrqData>, _msg: &MsiMsg) {}
176
177 /// return the internal state of an interrupt
irqchip_state( &self, _irq: &Arc<IrqData>, _which: IrqChipState, ) -> Result<bool, SystemError>178 fn irqchip_state(
179 &self,
180 _irq: &Arc<IrqData>,
181 _which: IrqChipState,
182 ) -> Result<bool, SystemError> {
183 Err(SystemError::ENOSYS)
184 }
185
186 /// set the internal state of an interrupt
set_irqchip_state( &self, _irq: &Arc<IrqData>, _which: IrqChipState, _state: bool, ) -> Result<(), SystemError>187 fn set_irqchip_state(
188 &self,
189 _irq: &Arc<IrqData>,
190 _which: IrqChipState,
191 _state: bool,
192 ) -> Result<(), SystemError> {
193 Err(SystemError::ENOSYS)
194 }
195
196 // todo: set vcpu affinity
197
198 /// send a single IPI to destination cpus
send_single_ipi(&self, _irq: &Arc<IrqData>, _cpu: u32)199 fn send_single_ipi(&self, _irq: &Arc<IrqData>, _cpu: u32) {}
200
201 // todo: send ipi with cpu mask
202
203 /// function called from core code before enabling an NMI
irq_nmi_setup(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError>204 fn irq_nmi_setup(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
205 Err(SystemError::ENOSYS)
206 }
207
208 /// function called from core code after disabling an NMI
irq_nmi_teardown(&self, _irq: &Arc<IrqData>)209 fn irq_nmi_teardown(&self, _irq: &Arc<IrqData>) {}
210
flags(&self) -> IrqChipFlags211 fn flags(&self) -> IrqChipFlags;
212 }
213
214 #[allow(dead_code)]
215 #[derive(Debug, Clone, Copy)]
216 pub enum IrqChipState {
217 /// Is the interrupt pending?
218 Pending,
219 /// Is the interrupt in progress?
220 Active,
221 /// Is the interrupt masked?
222 Masked,
223 /// Is Irq line high?
224 LineLevel,
225 }
226
227 /// 中断芯片的数据(per-irq的)
228 pub trait IrqChipData: Sync + Send + Any + Debug {
as_any_ref(&self) -> &dyn Any229 fn as_any_ref(&self) -> &dyn Any;
230 }
231
232 bitflags! {
233 /// 定义 IrqGcFlags 位标志
234 pub struct IrqGcFlags: u32 {
235 /// 通过读取mask reg来初始化mask_cache
236 const IRQ_GC_INIT_MASK_CACHE = 1 << 0;
237 /// 对于需要在父irq上调用irq_set_wake()的irq芯片, 将irqs的锁类设置为嵌套。Usually GPIO implementations
238 const IRQ_GC_INIT_NESTED_LOCK = 1 << 1;
239 /// Mask cache是芯片类型私有的
240 const IRQ_GC_MASK_CACHE_PER_TYPE = 1 << 2;
241 /// 不计算irqData->mask
242 const IRQ_GC_NO_MASK = 1 << 3;
243 /// 使用大端字节序的寄存器访问(默认:小端LE)
244 const IRQ_GC_BE_IO = 1 << 4;
245 }
246 }
247
248 #[allow(dead_code)]
249 #[derive(Debug)]
250 pub struct IrqChipGeneric {
251 inner: SpinLock<InnerIrqChipGeneric>,
252 }
253
254 #[allow(dead_code)]
255 #[derive(Debug)]
256 struct InnerIrqChipGeneric {
257 /// Register base address
258 reg_base: VirtAddr,
259 ops: &'static dyn IrqChipGenericOps,
260 /// Interrupt base num for this chip
261 irq_base: u32,
262 /// Number of interrupts handled by this chip
263 irq_cnt: u32,
264 /// Cached mask register shared between all chip types
265 mask_cache: u32,
266 /// Cached type register
267 type_cache: u32,
268 /// Cached polarity register
269 polarity_cache: u32,
270 /// Interrupt can wakeup from suspend
271 wake_enabled: bool,
272 /// Interrupt is marked as an wakeup from suspend source
273 wake_active: bool,
274 /// Number of available irq_chip_type instances (usually 1)
275 num_chip_type: u32,
276 private_data: Option<Arc<dyn IrqChipGenericPrivateData>>,
277 installed: u64,
278 unused: u64,
279 domain: Weak<IrqDomain>,
280 chip_types: Vec<IrqChipType>,
281 }
282
283 pub trait IrqChipGenericOps: Debug + Send + Sync {
284 /// Alternate I/O accessor (defaults to readl if NULL)
reg_readl(&self, addr: VirtAddr) -> u32285 unsafe fn reg_readl(&self, addr: VirtAddr) -> u32;
286
287 /// Alternate I/O accessor (defaults to writel if NULL)
reg_writel(&self, addr: VirtAddr, val: u32)288 unsafe fn reg_writel(&self, addr: VirtAddr, val: u32);
289
290 /// Function called from core code on suspend once per
291 /// chip; can be useful instead of irq_chip::suspend to
292 /// handle chip details even when no interrupts are in use
suspend(&self, gc: &Arc<IrqChipGeneric>)293 fn suspend(&self, gc: &Arc<IrqChipGeneric>);
294 /// Function called from core code on resume once per chip;
295 /// can be useful instead of irq_chip::resume to handle chip
296 /// details even when no interrupts are in use
resume(&self, gc: &Arc<IrqChipGeneric>)297 fn resume(&self, gc: &Arc<IrqChipGeneric>);
298 }
299
300 pub trait IrqChipGenericPrivateData: Sync + Send + Any + Debug {}
301
302 #[derive(Debug)]
303 pub struct IrqChipType {
304 // todo https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#1024
305 }
306
307 #[allow(dead_code)]
308 #[derive(Debug)]
309 pub enum IrqChipSetMaskResult {
310 /// core updates mask ok.
311 SetMaskOk,
312 /// core updates mask ok. No change.
313 SetMaskOkNoChange,
314 /// core updates mask ok. Done.(same as SetMaskOk)
315 ///
316 /// 支持堆叠irq芯片的特殊代码, 表示跳过所有子irq芯片。
317 SetMaskOkDone,
318 }
319
320 bitflags! {
321 /// IrqChip specific flags
322 pub struct IrqChipFlags: u32 {
323 /// 在调用chip.irq_set_type()之前屏蔽中断
324 const IRQCHIP_SET_TYPE_MASKED = 1 << 0;
325 /// 只有在irq被处理时才发出irq_eoi()
326 const IRQCHIP_EOI_IF_HANDLED = 1 << 1;
327 /// 在挂起路径中屏蔽非唤醒irq
328 const IRQCHIP_MASK_ON_SUSPEND = 1 << 2;
329 /// 只有在irq启用时才调用irq_on/off_line回调
330 const IRQCHIP_ONOFFLINE_ENABLED = 1 << 3;
331 /// 跳过chip.irq_set_wake(),对于这个irq芯片
332 const IRQCHIP_SKIP_SET_WAKE = 1 << 4;
333 /// 单次触发不需要屏蔽/取消屏蔽
334 const IRQCHIP_ONESHOT_SAFE = 1 << 5;
335 /// 芯片在线程模式下需要在取消屏蔽时eoi()
336 const IRQCHIP_EOI_THREADED = 1 << 6;
337 /// 芯片可以为Level MSIs提供两个门铃
338 const IRQCHIP_SUPPORTS_LEVEL_MSI = 1 << 7;
339 /// 芯片可以传递NMIs,仅适用于根irqchips
340 const IRQCHIP_SUPPORTS_NMI = 1 << 8;
341 /// 在挂起路径中,如果它们处于禁用状态,则调用__enable_irq()/__disable_irq()以唤醒irq
342 const IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND = 1 << 9;
343 /// 在启动前更新默认亲和性
344 const IRQCHIP_AFFINITY_PRE_STARTUP = 1 << 10;
345 /// 不要在这个芯片中改变任何东西
346 const IRQCHIP_IMMUTABLE = 1 << 11;
347 }
348 }
349
350 impl IrqManager {
351 /// Acknowledge the parent interrupt
352 #[allow(dead_code)]
irq_chip_ack_parent(&self, irq_data: &Arc<IrqData>)353 pub fn irq_chip_ack_parent(&self, irq_data: &Arc<IrqData>) {
354 let parent_data = irq_data.parent_data().map(|p| p.upgrade()).flatten();
355
356 if let Some(parent_data) = parent_data {
357 let parent_chip = parent_data.chip_info_read_irqsave().chip();
358 parent_chip.irq_ack(&parent_data);
359 }
360 }
361
362 /// 在硬件中重新触发中断
363 ///
364 /// 遍历中断域的层次结构,并检查是否存在一个硬件重新触发函数。如果存在则调用它
irq_chip_retrigger_hierarchy(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError>365 pub fn irq_chip_retrigger_hierarchy(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
366 let mut data: Option<Arc<IrqData>> = Some(irq_data.clone());
367 loop {
368 if let Some(d) = data {
369 if let Err(e) = d.chip_info_read_irqsave().chip().retrigger(&d) {
370 if e == SystemError::ENOSYS {
371 data = d.parent_data().map(|p| p.upgrade()).flatten();
372 } else {
373 return Err(e);
374 }
375 } else {
376 return Ok(());
377 }
378 } else {
379 break;
380 }
381 }
382
383 return Ok(());
384 }
385
__irq_set_handler( &self, irq: IrqNumber, handler: &'static dyn IrqFlowHandler, is_chained: bool, name: Option<String>, )386 pub(super) fn __irq_set_handler(
387 &self,
388 irq: IrqNumber,
389 handler: &'static dyn IrqFlowHandler,
390 is_chained: bool,
391 name: Option<String>,
392 ) {
393 let r = irq_desc_manager().lookup_and_lock_bus(irq, false, false);
394 if r.is_none() {
395 return;
396 }
397
398 let irq_desc = r.unwrap();
399
400 let mut desc_inner = irq_desc.inner();
401 self.__irq_do_set_handler(&irq_desc, &mut desc_inner, Some(handler), is_chained, name);
402
403 drop(desc_inner);
404 irq_desc.chip_bus_sync_unlock();
405 }
406
__irq_do_set_handler( &self, desc: &Arc<IrqDesc>, desc_inner: &mut SpinLockGuard<'_, InnerIrqDesc>, mut handler: Option<&'static dyn IrqFlowHandler>, is_chained: bool, name: Option<String>, )407 fn __irq_do_set_handler(
408 &self,
409 desc: &Arc<IrqDesc>,
410 desc_inner: &mut SpinLockGuard<'_, InnerIrqDesc>,
411 mut handler: Option<&'static dyn IrqFlowHandler>,
412 is_chained: bool,
413 name: Option<String>,
414 ) {
415 if handler.is_none() {
416 handler = Some(bad_irq_handler());
417 } else {
418 let mut irq_data = Some(desc_inner.irq_data().clone());
419
420 /*
421 * 在具有中断域继承的domain中,我们可能会遇到这样的情况,
422 * 最外层的芯片还没有设置好,但是内部的芯片已经存在了。
423 * 我们选择安装处理程序,而不是退出,
424 * 但显然我们此时无法启用/启动中断。
425 */
426 while irq_data.is_some() {
427 let dt = irq_data.as_ref().unwrap().clone();
428
429 let chip_info = dt.chip_info_read_irqsave();
430
431 if !Arc::ptr_eq(&chip_info.chip(), &no_irq_chip()) {
432 break;
433 }
434
435 /*
436 * 如果最外层的芯片没有设置好,并且预期立即开始中断,
437 * 则放弃。
438 */
439 if unlikely(is_chained) {
440 kwarn!(
441 "Chained handler for irq {} is not supported",
442 dt.irq().data()
443 );
444 return;
445 }
446
447 // try the parent
448 let parent_data = dt.parent_data().map(|p| p.upgrade()).flatten();
449
450 irq_data = parent_data;
451 }
452
453 if unlikely(
454 irq_data.is_none()
455 || Arc::ptr_eq(
456 &irq_data.as_ref().unwrap().chip_info_read_irqsave().chip(),
457 &no_irq_chip(),
458 ),
459 ) {
460 kwarn!("No irq chip for irq {}", desc_inner.irq_data().irq().data());
461 return;
462 }
463 }
464 let handler = handler.unwrap();
465 if core::ptr::eq(handler, bad_irq_handler()) {
466 if Arc::ptr_eq(
467 &desc_inner.irq_data().chip_info_read_irqsave().chip(),
468 &no_irq_chip(),
469 ) {
470 let irq_data = desc_inner.irq_data();
471 mask_ack_irq(irq_data);
472
473 irq_data.irqd_set(IrqStatus::IRQD_IRQ_DISABLED);
474
475 if is_chained {
476 desc_inner.clear_actions();
477 }
478 desc_inner.set_depth(1);
479 }
480 }
481 let chip = desc_inner.irq_data().chip_info_read_irqsave().chip();
482 desc.set_handler_no_lock_inner(handler, desc_inner.irq_data(), &chip);
483 desc_inner.set_name(name);
484
485 if !core::ptr::eq(handler, bad_irq_handler()) && is_chained {
486 let trigger_type = desc_inner.common_data().trigger_type();
487
488 /*
489 * 我们即将立即启动这个中断,
490 * 因此需要设置触发配置。
491 * 但是 .irq_set_type 回调可能已经覆盖了
492 * irqflowhandler,忽略了我们正在处理的
493 * 是一个链式中断。立即重置它,因为我们
494 * 确实知道更好的处理方式。
495 */
496
497 if trigger_type != IrqLineStatus::IRQ_TYPE_NONE {
498 irq_manager()
499 .do_set_irq_trigger(desc.clone(), desc_inner, trigger_type)
500 .ok();
501 desc.set_handler(handler);
502 }
503
504 desc_inner.set_noprobe();
505 desc_inner.set_norequest();
506 desc_inner.set_nothread();
507
508 desc_inner.clear_actions();
509 desc_inner.add_action(chained_action());
510
511 irq_manager()
512 .irq_activate_and_startup(desc, desc_inner, IrqManager::IRQ_RESEND)
513 .ok();
514 }
515
516 return;
517 }
518
irq_set_handler_data( &self, irq: IrqNumber, data: Option<Arc<dyn IrqHandlerData>>, ) -> Result<(), SystemError>519 pub fn irq_set_handler_data(
520 &self,
521 irq: IrqNumber,
522 data: Option<Arc<dyn IrqHandlerData>>,
523 ) -> Result<(), SystemError> {
524 let desc = irq_desc_manager().lookup(irq).ok_or(SystemError::EINVAL)?;
525 desc.inner().common_data().inner().set_handler_data(data);
526
527 return Ok(());
528 }
529
irq_percpu_disable( &self, desc: &Arc<IrqDesc>, irq_data: &Arc<IrqData>, irq_chip: &Arc<dyn IrqChip>, cpu: ProcessorId, )530 pub fn irq_percpu_disable(
531 &self,
532 desc: &Arc<IrqDesc>,
533 irq_data: &Arc<IrqData>,
534 irq_chip: &Arc<dyn IrqChip>,
535 cpu: ProcessorId,
536 ) {
537 if let Err(e) = irq_chip.irq_mask(irq_data) {
538 if e == SystemError::ENOSYS {
539 irq_chip.irq_disable(irq_data);
540 }
541 }
542
543 desc.inner()
544 .percpu_enabled_mut()
545 .as_mut()
546 .unwrap()
547 .set(cpu, false);
548 }
549 }
550
551 lazy_static! {
552 pub(super) static ref CHAINED_ACTION: Arc<IrqAction> = IrqAction::new(
553 IrqNumber::new(0),
554 "".to_string(),
555 Some(&ChainedActionHandler),
556 None,
557 );
558 }
559
560 #[allow(dead_code)]
chained_action() -> Arc<IrqAction>561 pub(super) fn chained_action() -> Arc<IrqAction> {
562 CHAINED_ACTION.clone()
563 }
564
565 /// Chained handlers 永远不应该在它们的IRQ上调用irqaction。如果发生这种情况,
566 /// 这个默认irqaction将发出警告。
567 #[derive(Debug)]
568 struct ChainedActionHandler;
569
570 impl IrqHandler for ChainedActionHandler {
handle( &self, irq: IrqNumber, _static_data: Option<&dyn IrqHandlerData>, _dynamic_data: Option<Arc<dyn IrqHandlerData>>, ) -> Result<IrqReturn, SystemError>571 fn handle(
572 &self,
573 irq: IrqNumber,
574 _static_data: Option<&dyn IrqHandlerData>,
575 _dynamic_data: Option<Arc<dyn IrqHandlerData>>,
576 ) -> Result<IrqReturn, SystemError> {
577 static ONCE: Once = Once::new();
578 ONCE.call_once(|| {
579 kwarn!("Chained irq {} should not call an action.", irq.data());
580 });
581
582 Ok(IrqReturn::NotHandled)
583 }
584 }
585