xref: /DragonOS/kernel/src/exception/irqdata.rs (revision 0102d69fdd231e472d7bb3d609a41ae56a3799ee)
1ce5850adSLoGin use core::{any::Any, fmt::Debug};
2ce5850adSLoGin 
3ce5850adSLoGin use alloc::sync::{Arc, Weak};
4e2841179SLoGin use intertrait::CastFromSync;
5ce5850adSLoGin 
6e2841179SLoGin use crate::libs::{
7e2841179SLoGin     cpumask::CpuMask,
8e2841179SLoGin     rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
9e2841179SLoGin     spinlock::{SpinLock, SpinLockGuard},
10e2841179SLoGin };
11ce5850adSLoGin 
12ce5850adSLoGin use super::{
13ce5850adSLoGin     irqchip::{IrqChip, IrqChipData},
14f049d1afSLoGin     irqdesc::IrqDesc,
15ce5850adSLoGin     irqdomain::IrqDomain,
16ce5850adSLoGin     msi::MsiDesc,
17ce5850adSLoGin     HardwareIrqNumber, IrqNumber,
18ce5850adSLoGin };
19ce5850adSLoGin 
20ce5850adSLoGin /// per irq chip data passed down to chip functions
21ce5850adSLoGin ///
22ce5850adSLoGin /// 该结构体用于表示每个Irq的私有数据,且与具体的中断芯片绑定
23ce5850adSLoGin ///
24ce5850adSLoGin /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#179
25ce5850adSLoGin #[allow(dead_code)]
26ce5850adSLoGin #[derive(Debug)]
27ce5850adSLoGin pub struct IrqData {
28ce5850adSLoGin     /// 中断号, 用于表示软件逻辑视角的中断号,全局唯一
29ce5850adSLoGin     irq: IrqNumber,
303bc96fa4SLoGin     inner: SpinLock<InnerIrqData>,
31e2841179SLoGin 
32e2841179SLoGin     chip_info: RwLock<InnerIrqChipInfo>,
333bc96fa4SLoGin }
343bc96fa4SLoGin 
353bc96fa4SLoGin impl IrqData {
new( irq: IrqNumber, hwirq: HardwareIrqNumber, common_data: Arc<IrqCommonData>, chip: Arc<dyn IrqChip>, ) -> Self363bc96fa4SLoGin     pub fn new(
373bc96fa4SLoGin         irq: IrqNumber,
383bc96fa4SLoGin         hwirq: HardwareIrqNumber,
393bc96fa4SLoGin         common_data: Arc<IrqCommonData>,
403bc96fa4SLoGin         chip: Arc<dyn IrqChip>,
413bc96fa4SLoGin     ) -> Self {
423bc96fa4SLoGin         return IrqData {
433bc96fa4SLoGin             irq,
443bc96fa4SLoGin             inner: SpinLock::new(InnerIrqData {
453bc96fa4SLoGin                 hwirq,
463bc96fa4SLoGin                 common_data,
47f049d1afSLoGin                 desc: Weak::new(),
483bc96fa4SLoGin                 domain: None,
493bc96fa4SLoGin                 parent_data: None,
503bc96fa4SLoGin             }),
51e2841179SLoGin             chip_info: RwLock::new(InnerIrqChipInfo {
52e2841179SLoGin                 chip: Some(chip),
53e2841179SLoGin                 chip_data: None,
54e2841179SLoGin             }),
553bc96fa4SLoGin         };
563bc96fa4SLoGin     }
573bc96fa4SLoGin 
irqd_set(&self, status: IrqStatus)583bc96fa4SLoGin     pub fn irqd_set(&self, status: IrqStatus) {
593bc96fa4SLoGin         // clone是为了释放inner锁
60e2841179SLoGin         let common_data = self.inner.lock_irqsave().common_data.clone();
61e2841179SLoGin         common_data.insert_status(status);
623bc96fa4SLoGin     }
633bc96fa4SLoGin 
643bc96fa4SLoGin     #[allow(dead_code)]
irqd_clear(&self, status: IrqStatus)653bc96fa4SLoGin     pub fn irqd_clear(&self, status: IrqStatus) {
663bc96fa4SLoGin         // clone是为了释放inner锁
67e2841179SLoGin         let common_data = self.inner.lock_irqsave().common_data.clone();
68e2841179SLoGin         common_data.clear_status(status);
693bc96fa4SLoGin     }
703bc96fa4SLoGin 
irq(&self) -> IrqNumber713bc96fa4SLoGin     pub fn irq(&self) -> IrqNumber {
723bc96fa4SLoGin         self.irq
733bc96fa4SLoGin     }
74196b75dcSLoGin 
irq_desc(&self) -> Option<Arc<IrqDesc>>75f049d1afSLoGin     pub fn irq_desc(&self) -> Option<Arc<IrqDesc>> {
76f049d1afSLoGin         self.inner.lock_irqsave().desc.upgrade()
77f049d1afSLoGin     }
78f049d1afSLoGin 
set_irq_desc(&self, desc: Weak<IrqDesc>)79f049d1afSLoGin     pub fn set_irq_desc(&self, desc: Weak<IrqDesc>) {
80f049d1afSLoGin         self.inner.lock_irqsave().desc = desc;
81f049d1afSLoGin     }
82f049d1afSLoGin 
83*0102d69fSLoGin     #[allow(dead_code)]
clear_irq_desc(&self)84f049d1afSLoGin     pub fn clear_irq_desc(&self) {
85f049d1afSLoGin         self.inner.lock_irqsave().desc = Weak::new();
86f049d1afSLoGin     }
87f049d1afSLoGin 
hardware_irq(&self) -> HardwareIrqNumber88196b75dcSLoGin     pub fn hardware_irq(&self) -> HardwareIrqNumber {
89196b75dcSLoGin         self.inner.lock_irqsave().hwirq
90196b75dcSLoGin     }
91196b75dcSLoGin 
92196b75dcSLoGin     /// 是否为电平触发
is_level_type(&self) -> bool93196b75dcSLoGin     pub fn is_level_type(&self) -> bool {
94196b75dcSLoGin         self.inner
95196b75dcSLoGin             .lock_irqsave()
96196b75dcSLoGin             .common_data
97196b75dcSLoGin             .inner
98e2841179SLoGin             .lock_irqsave()
99196b75dcSLoGin             .state
100196b75dcSLoGin             .is_level_type()
101196b75dcSLoGin     }
102196b75dcSLoGin 
is_wakeup_set(&self) -> bool103196b75dcSLoGin     pub fn is_wakeup_set(&self) -> bool {
104196b75dcSLoGin         self.inner
105196b75dcSLoGin             .lock_irqsave()
106196b75dcSLoGin             .common_data
107196b75dcSLoGin             .inner
108e2841179SLoGin             .lock_irqsave()
109196b75dcSLoGin             .state
110196b75dcSLoGin             .is_wakeup_set()
111196b75dcSLoGin     }
112e2841179SLoGin 
common_data(&self) -> Arc<IrqCommonData>113e2841179SLoGin     pub fn common_data(&self) -> Arc<IrqCommonData> {
114e2841179SLoGin         self.inner.lock_irqsave().common_data.clone()
115e2841179SLoGin     }
116e2841179SLoGin 
domain(&self) -> Option<Arc<IrqDomain>>117e2841179SLoGin     pub fn domain(&self) -> Option<Arc<IrqDomain>> {
118e2841179SLoGin         self.inner.lock_irqsave().domain.clone()
119e2841179SLoGin     }
120e2841179SLoGin 
inner(&self) -> SpinLockGuard<InnerIrqData>121e2841179SLoGin     pub fn inner(&self) -> SpinLockGuard<InnerIrqData> {
122e2841179SLoGin         self.inner.lock_irqsave()
123e2841179SLoGin     }
124e2841179SLoGin 
chip_info_read(&self) -> RwLockReadGuard<InnerIrqChipInfo>125e2841179SLoGin     pub fn chip_info_read(&self) -> RwLockReadGuard<InnerIrqChipInfo> {
126e2841179SLoGin         self.chip_info.read()
127e2841179SLoGin     }
128e2841179SLoGin 
chip_info_read_irqsave(&self) -> RwLockReadGuard<InnerIrqChipInfo>129e2841179SLoGin     pub fn chip_info_read_irqsave(&self) -> RwLockReadGuard<InnerIrqChipInfo> {
130e2841179SLoGin         self.chip_info.read_irqsave()
131e2841179SLoGin     }
132e2841179SLoGin 
chip_info_write_irqsave(&self) -> RwLockWriteGuard<InnerIrqChipInfo>133e2841179SLoGin     pub fn chip_info_write_irqsave(&self) -> RwLockWriteGuard<InnerIrqChipInfo> {
134e2841179SLoGin         self.chip_info.write_irqsave()
135e2841179SLoGin     }
136e2841179SLoGin 
parent_data(&self) -> Option<Weak<IrqData>>137e2841179SLoGin     pub fn parent_data(&self) -> Option<Weak<IrqData>> {
138e2841179SLoGin         self.inner.lock_irqsave().parent_data.clone()
139e2841179SLoGin     }
1403bc96fa4SLoGin }
1413bc96fa4SLoGin 
1423bc96fa4SLoGin #[allow(dead_code)]
1433bc96fa4SLoGin #[derive(Debug)]
144e2841179SLoGin pub struct InnerIrqData {
145ce5850adSLoGin     /// 硬件中断号, 用于表示在某个IrqDomain中的中断号
146ce5850adSLoGin     hwirq: HardwareIrqNumber,
147ce5850adSLoGin     /// 涉及的所有irqchip之间共享的数据
148ce5850adSLoGin     common_data: Arc<IrqCommonData>,
149e2841179SLoGin 
150f049d1afSLoGin     desc: Weak<IrqDesc>,
151f049d1afSLoGin 
152ce5850adSLoGin     /// 中断域
1533bc96fa4SLoGin     domain: Option<Arc<IrqDomain>>,
154ce5850adSLoGin     /// 中断的父中断(如果具有中断域继承的话)
155ce5850adSLoGin     parent_data: Option<Weak<IrqData>>,
156ce5850adSLoGin }
157ce5850adSLoGin 
158e2841179SLoGin impl InnerIrqData {
set_hwirq(&mut self, hwirq: HardwareIrqNumber)159e2841179SLoGin     pub fn set_hwirq(&mut self, hwirq: HardwareIrqNumber) {
160e2841179SLoGin         self.hwirq = hwirq;
161e2841179SLoGin     }
162e2841179SLoGin 
163e2841179SLoGin     #[allow(dead_code)]
domain(&self) -> Option<Arc<IrqDomain>>164e2841179SLoGin     pub fn domain(&self) -> Option<Arc<IrqDomain>> {
165e2841179SLoGin         self.domain.clone()
166e2841179SLoGin     }
167e2841179SLoGin 
set_domain(&mut self, domain: Option<Arc<IrqDomain>>)168e2841179SLoGin     pub fn set_domain(&mut self, domain: Option<Arc<IrqDomain>>) {
169e2841179SLoGin         self.domain = domain;
170e2841179SLoGin     }
171e2841179SLoGin }
172e2841179SLoGin 
173e2841179SLoGin #[derive(Debug)]
174e2841179SLoGin pub struct InnerIrqChipInfo {
175e2841179SLoGin     /// 绑定到的中断芯片
176e2841179SLoGin     chip: Option<Arc<dyn IrqChip>>,
177e2841179SLoGin     /// 中断芯片的私有数据(与当前irq相关)
178e2841179SLoGin     chip_data: Option<Arc<dyn IrqChipData>>,
179e2841179SLoGin }
180e2841179SLoGin 
181e2841179SLoGin impl InnerIrqChipInfo {
set_chip(&mut self, chip: Option<Arc<dyn IrqChip>>)182e2841179SLoGin     pub fn set_chip(&mut self, chip: Option<Arc<dyn IrqChip>>) {
183e2841179SLoGin         self.chip = chip;
184e2841179SLoGin     }
185e2841179SLoGin 
set_chip_data(&mut self, chip_data: Option<Arc<dyn IrqChipData>>)186e2841179SLoGin     pub fn set_chip_data(&mut self, chip_data: Option<Arc<dyn IrqChipData>>) {
187e2841179SLoGin         self.chip_data = chip_data;
188e2841179SLoGin     }
189e2841179SLoGin 
chip(&self) -> Arc<dyn IrqChip>190e2841179SLoGin     pub fn chip(&self) -> Arc<dyn IrqChip> {
191e2841179SLoGin         self.chip.clone().unwrap()
192e2841179SLoGin     }
193e2841179SLoGin 
chip_data(&self) -> Option<Arc<dyn IrqChipData>>194e2841179SLoGin     pub fn chip_data(&self) -> Option<Arc<dyn IrqChipData>> {
195e2841179SLoGin         self.chip_data.clone()
196e2841179SLoGin     }
197e2841179SLoGin }
198e2841179SLoGin 
199ce5850adSLoGin /// per irq data shared by all irqchips
200ce5850adSLoGin ///
201ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#147
202ce5850adSLoGin #[derive(Debug)]
203ce5850adSLoGin pub struct IrqCommonData {
204ce5850adSLoGin     inner: SpinLock<InnerIrqCommonData>,
205ce5850adSLoGin }
206ce5850adSLoGin 
2073bc96fa4SLoGin impl IrqCommonData {
new() -> Self2083bc96fa4SLoGin     pub fn new() -> Self {
2093bc96fa4SLoGin         let inner = InnerIrqCommonData {
2103bc96fa4SLoGin             state: IrqStatus::empty(),
2113bc96fa4SLoGin             handler_data: None,
2123bc96fa4SLoGin             msi_desc: None,
213e2841179SLoGin             affinity: CpuMask::new(),
214*0102d69fSLoGin             effective_affinity: CpuMask::new(),
2153bc96fa4SLoGin         };
2163bc96fa4SLoGin         return IrqCommonData {
2173bc96fa4SLoGin             inner: SpinLock::new(inner),
2183bc96fa4SLoGin         };
2193bc96fa4SLoGin     }
2203bc96fa4SLoGin 
insert_status(&self, status: IrqStatus)221e2841179SLoGin     pub fn insert_status(&self, status: IrqStatus) {
222e2841179SLoGin         self.inner.lock_irqsave().irqd_insert(status);
2233bc96fa4SLoGin     }
2243bc96fa4SLoGin 
clear_status(&self, status: IrqStatus)225e2841179SLoGin     pub fn clear_status(&self, status: IrqStatus) {
2263bc96fa4SLoGin         self.inner.lock_irqsave().irqd_clear(status);
2273bc96fa4SLoGin     }
228e2841179SLoGin 
clear_managed_shutdown(&self)229e2841179SLoGin     pub fn clear_managed_shutdown(&self) {
230e2841179SLoGin         self.inner
231e2841179SLoGin             .lock_irqsave()
232e2841179SLoGin             .state
233e2841179SLoGin             .remove(IrqStatus::IRQD_MANAGED_SHUTDOWN);
234e2841179SLoGin     }
235e2841179SLoGin 
236e2841179SLoGin     #[allow(dead_code)]
masked(&self) -> bool237e2841179SLoGin     pub fn masked(&self) -> bool {
238e2841179SLoGin         self.inner.lock_irqsave().state.masked()
239e2841179SLoGin     }
240e2841179SLoGin 
set_masked(&self)241e2841179SLoGin     pub fn set_masked(&self) {
242e2841179SLoGin         self.inner
243e2841179SLoGin             .lock_irqsave()
244e2841179SLoGin             .state
245e2841179SLoGin             .insert(IrqStatus::IRQD_IRQ_MASKED);
246e2841179SLoGin     }
247e2841179SLoGin 
clear_masked(&self)248e2841179SLoGin     pub fn clear_masked(&self) {
249e2841179SLoGin         self.clear_status(IrqStatus::IRQD_IRQ_MASKED);
250e2841179SLoGin     }
251e2841179SLoGin 
set_inprogress(&self)252e2841179SLoGin     pub fn set_inprogress(&self) {
253e2841179SLoGin         self.inner
254e2841179SLoGin             .lock_irqsave()
255e2841179SLoGin             .state
256e2841179SLoGin             .insert(IrqStatus::IRQD_IRQ_INPROGRESS);
257e2841179SLoGin     }
258e2841179SLoGin 
clear_inprogress(&self)259e2841179SLoGin     pub fn clear_inprogress(&self) {
260e2841179SLoGin         self.inner
261e2841179SLoGin             .lock_irqsave()
262e2841179SLoGin             .state
263e2841179SLoGin             .remove(IrqStatus::IRQD_IRQ_INPROGRESS);
264e2841179SLoGin     }
265e2841179SLoGin 
disabled(&self) -> bool266e2841179SLoGin     pub fn disabled(&self) -> bool {
267e2841179SLoGin         self.inner.lock_irqsave().state.disabled()
268e2841179SLoGin     }
269e2841179SLoGin 
270e2841179SLoGin     #[allow(dead_code)]
set_disabled(&self)271e2841179SLoGin     pub fn set_disabled(&self) {
272e2841179SLoGin         self.inner
273e2841179SLoGin             .lock_irqsave()
274e2841179SLoGin             .state
275e2841179SLoGin             .insert(IrqStatus::IRQD_IRQ_DISABLED);
276e2841179SLoGin     }
277e2841179SLoGin 
clear_disabled(&self)278e2841179SLoGin     pub fn clear_disabled(&self) {
279e2841179SLoGin         self.clear_status(IrqStatus::IRQD_IRQ_DISABLED);
280e2841179SLoGin     }
281e2841179SLoGin 
status(&self) -> IrqStatus282e2841179SLoGin     pub fn status(&self) -> IrqStatus {
283e2841179SLoGin         self.inner.lock_irqsave().state
284e2841179SLoGin     }
285e2841179SLoGin 
trigger_type(&self) -> IrqLineStatus286e2841179SLoGin     pub fn trigger_type(&self) -> IrqLineStatus {
287e2841179SLoGin         self.inner.lock_irqsave().state.trigger_type()
288e2841179SLoGin     }
289e2841179SLoGin 
set_trigger_type(&self, trigger: IrqLineStatus)290e2841179SLoGin     pub fn set_trigger_type(&self, trigger: IrqLineStatus) {
291e2841179SLoGin         self.inner.lock_irqsave().state.set_trigger_type(trigger);
292e2841179SLoGin     }
293e2841179SLoGin 
set_started(&self)294e2841179SLoGin     pub fn set_started(&self) {
295e2841179SLoGin         self.inner
296e2841179SLoGin             .lock_irqsave()
297e2841179SLoGin             .state
298e2841179SLoGin             .insert(IrqStatus::IRQD_IRQ_STARTED);
299e2841179SLoGin     }
300e2841179SLoGin 
affinity(&self) -> CpuMask301e2841179SLoGin     pub fn affinity(&self) -> CpuMask {
302e2841179SLoGin         self.inner.lock_irqsave().affinity.clone()
303e2841179SLoGin     }
304e2841179SLoGin 
set_affinity(&self, affinity: CpuMask)305e2841179SLoGin     pub fn set_affinity(&self, affinity: CpuMask) {
306e2841179SLoGin         self.inner.lock_irqsave().affinity = affinity;
307e2841179SLoGin     }
308338f6903SLoGin 
set_effective_affinity(&self, affinity: CpuMask)309*0102d69fSLoGin     pub fn set_effective_affinity(&self, affinity: CpuMask) {
310*0102d69fSLoGin         self.inner.lock_irqsave().effective_affinity = affinity;
311*0102d69fSLoGin     }
312*0102d69fSLoGin 
inner(&self) -> SpinLockGuard<InnerIrqCommonData>313338f6903SLoGin     pub fn inner(&self) -> SpinLockGuard<InnerIrqCommonData> {
314338f6903SLoGin         self.inner.lock_irqsave()
315338f6903SLoGin     }
3163bc96fa4SLoGin }
3173bc96fa4SLoGin 
318ce5850adSLoGin #[allow(dead_code)]
319ce5850adSLoGin #[derive(Debug)]
320338f6903SLoGin pub struct InnerIrqCommonData {
321ce5850adSLoGin     /// status information for irq chip functions.
322ce5850adSLoGin     state: IrqStatus,
323ce5850adSLoGin     /// per-IRQ data for the irq_chip methods
324ce5850adSLoGin     handler_data: Option<Arc<dyn IrqHandlerData>>,
325ce5850adSLoGin     msi_desc: Option<Arc<MsiDesc>>,
326e2841179SLoGin     affinity: CpuMask,
327*0102d69fSLoGin     effective_affinity: CpuMask,
328ce5850adSLoGin }
329ce5850adSLoGin 
3303bc96fa4SLoGin impl InnerIrqCommonData {
irqd_insert(&mut self, status: IrqStatus)331e2841179SLoGin     pub fn irqd_insert(&mut self, status: IrqStatus) {
3323bc96fa4SLoGin         self.state.insert(status);
3333bc96fa4SLoGin     }
3343bc96fa4SLoGin 
irqd_clear(&mut self, status: IrqStatus)3353bc96fa4SLoGin     pub fn irqd_clear(&mut self, status: IrqStatus) {
3363bc96fa4SLoGin         self.state.remove(status);
3373bc96fa4SLoGin     }
338338f6903SLoGin 
339338f6903SLoGin     #[allow(dead_code)]
set_handler_data(&mut self, handler_data: Option<Arc<dyn IrqHandlerData>>)340338f6903SLoGin     pub fn set_handler_data(&mut self, handler_data: Option<Arc<dyn IrqHandlerData>>) {
341338f6903SLoGin         self.handler_data = handler_data;
342338f6903SLoGin     }
343338f6903SLoGin 
344338f6903SLoGin     #[allow(dead_code)]
handler_data(&self) -> Option<Arc<dyn IrqHandlerData>>345338f6903SLoGin     pub fn handler_data(&self) -> Option<Arc<dyn IrqHandlerData>> {
346338f6903SLoGin         self.handler_data.clone()
347338f6903SLoGin     }
348*0102d69fSLoGin 
effective_affinity(&self) -> &CpuMask349*0102d69fSLoGin     pub fn effective_affinity(&self) -> &CpuMask {
350*0102d69fSLoGin         &self.effective_affinity
351*0102d69fSLoGin     }
3523bc96fa4SLoGin }
3533bc96fa4SLoGin 
354e2841179SLoGin /// 中断处理函数传入的数据
355e2841179SLoGin pub trait IrqHandlerData: Send + Sync + Any + Debug + CastFromSync {}
356ce5850adSLoGin 
357ce5850adSLoGin bitflags! {
358ce5850adSLoGin     /// 中断线状态
359ce5850adSLoGin     /// https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h?fi=IRQ_TYPE_PROBE#77
360b5b571e0SLoGin     #[allow(clippy::bad_bit_mask)]
361ce5850adSLoGin     pub struct IrqLineStatus: u32 {
362ce5850adSLoGin         /// 默认,未指明类型
363ce5850adSLoGin         const IRQ_TYPE_NONE     = 0x00000000;
364ce5850adSLoGin         /// 上升沿触发
365ce5850adSLoGin         const IRQ_TYPE_EDGE_RISING  = 0x00000001;
366ce5850adSLoGin         /// 下降沿触发
367ce5850adSLoGin         const IRQ_TYPE_EDGE_FALLING = 0x00000002;
368ce5850adSLoGin         /// 上升沿和下降沿触发
369ce5850adSLoGin         const IRQ_TYPE_EDGE_BOTH    = Self::IRQ_TYPE_EDGE_RISING.bits | Self::IRQ_TYPE_EDGE_FALLING.bits;
370ce5850adSLoGin         /// 高电平触发
371ce5850adSLoGin         const IRQ_TYPE_LEVEL_HIGH   = 0x00000004;
372ce5850adSLoGin         /// 低电平触发
373ce5850adSLoGin         const IRQ_TYPE_LEVEL_LOW    = 0x00000008;
374ce5850adSLoGin         /// 过滤掉电平位的掩码
375ce5850adSLoGin         const IRQ_TYPE_LEVEL_MASK   = Self::IRQ_TYPE_LEVEL_LOW.bits | Self::IRQ_TYPE_LEVEL_HIGH.bits;
376ce5850adSLoGin         /// 上述位掩码的掩码
377ce5850adSLoGin         const IRQ_TYPE_SENSE_MASK   = 0x0000000f;
378ce5850adSLoGin         /// 某些PICs使用此类型要求 `IrqChip::irq_set_type()` 设置硬件到一个合理的默认值
379ce5850adSLoGin         /// (由irqdomain的map()回调使用,以便为新分配的描述符同步硬件状态和软件标志位)。
380ce5850adSLoGin         const IRQ_TYPE_DEFAULT      = Self::IRQ_TYPE_SENSE_MASK.bits;
381ce5850adSLoGin 
382ce5850adSLoGin         /// 特定于探测的过程中的特殊标志
383ce5850adSLoGin         const IRQ_TYPE_PROBE        = 0x00000010;
384ce5850adSLoGin 
385ce5850adSLoGin         /// 中断是电平类型。当上述触发位通过`IrqChip::irq_set_type()` 修改时,也会在代码中更新
386ce5850adSLoGin         const IRQ_LEVEL     = 1 << 8;
387ce5850adSLoGin         /// 标记一个PER_CPU的中断。将保护其免受亲和性设置的影响
388ce5850adSLoGin         const IRQ_PER_CPU       = 1 << 9;
389ce5850adSLoGin         /// 中断不能被自动探测
390ce5850adSLoGin         const IRQ_NOPROBE       = 1 << 10;
391ce5850adSLoGin         /// 中断不能通过request_irq()请求
392ce5850adSLoGin         const IRQ_NOREQUEST     = 1 << 11;
393ce5850adSLoGin         /// 中断在request/setup_irq()中不会自动启用
394ce5850adSLoGin         const IRQ_NOAUTOEN      = 1 << 12;
395ce5850adSLoGin         /// 中断不能被平衡(亲和性设置)
396ce5850adSLoGin         const IRQ_NO_BALANCING      = 1 << 13;
397ce5850adSLoGin         /// 中断可以从进程上下文中迁移
398ce5850adSLoGin         const IRQ_MOVE_PCNTXT       = 1 << 14;
399ce5850adSLoGin         /// 中断嵌套在另一个线程中
400ce5850adSLoGin         const IRQ_NESTED_THREAD = 1 << 15;
401ce5850adSLoGin         /// 中断不能被线程化
402ce5850adSLoGin         const IRQ_NOTHREAD      = 1 << 16;
403ce5850adSLoGin         /// Dev_id是一个per-CPU变量
404ce5850adSLoGin         const IRQ_PER_CPU_DEVID = 1 << 17;
405ce5850adSLoGin         /// 总是由另一个中断轮询。将其从错误的中断检测机制和核心侧轮询中排除
406ce5850adSLoGin         const IRQ_IS_POLLED     = 1 << 18;
407ce5850adSLoGin         /// 禁用延迟的中断禁用 (Disable lazy irq disable)
408ce5850adSLoGin         const IRQ_DISABLE_UNLAZY    = 1 << 19;
409ce5850adSLoGin         /// 在/proc/interrupts中不显示
410ce5850adSLoGin         const IRQ_HIDDEN        = 1 << 20;
411ce5850adSLoGin         /// 从note_interrupt()调试中排除
412ce5850adSLoGin         const IRQ_NO_DEBUG      = 1 << 21;
413ce5850adSLoGin     }
414ce5850adSLoGin 
415ce5850adSLoGin 
416ce5850adSLoGin 
417ce5850adSLoGin }
418e2841179SLoGin 
419e2841179SLoGin impl IrqLineStatus {
trigger_bits(&self) -> u32420e2841179SLoGin     pub const fn trigger_bits(&self) -> u32 {
421e2841179SLoGin         self.bits & Self::IRQ_TYPE_SENSE_MASK.bits
422e2841179SLoGin     }
423e2841179SLoGin 
trigger_type(&self) -> Self424e2841179SLoGin     pub fn trigger_type(&self) -> Self {
425e2841179SLoGin         *self & Self::IRQ_TYPE_SENSE_MASK
426e2841179SLoGin     }
427e2841179SLoGin 
is_level_type(&self) -> bool428e2841179SLoGin     pub fn is_level_type(&self) -> bool {
429e2841179SLoGin         self.contains(Self::IRQ_LEVEL)
430e2841179SLoGin     }
431e2841179SLoGin 
432e2841179SLoGin     /// 是否为高电平触发
433e2841179SLoGin     ///
434e2841179SLoGin     /// ## 返回
435e2841179SLoGin     ///
436e2841179SLoGin     /// - 如果不是电平触发类型,则返回None
437e2841179SLoGin     /// - 如果是电平触发类型,则返回Some(bool),当为true时表示高电平触发
438f049d1afSLoGin     #[allow(dead_code)]
is_level_high(&self) -> Option<bool>439e2841179SLoGin     pub fn is_level_high(&self) -> Option<bool> {
440e2841179SLoGin         if !self.is_level_type() {
441e2841179SLoGin             return None;
442e2841179SLoGin         }
443e2841179SLoGin         return Some(self.contains(Self::IRQ_TYPE_LEVEL_HIGH));
444e2841179SLoGin     }
445338f6903SLoGin 
446338f6903SLoGin     #[allow(dead_code)]
is_per_cpu_devid(&self) -> bool447338f6903SLoGin     pub fn is_per_cpu_devid(&self) -> bool {
448338f6903SLoGin         self.contains(Self::IRQ_PER_CPU_DEVID)
449338f6903SLoGin     }
450e2841179SLoGin }
451b5b571e0SLoGin 
452ce5850adSLoGin bitflags! {
453ce5850adSLoGin     /// 中断状态(存储在IrqCommonData)
454ce5850adSLoGin     ///
455ce5850adSLoGin     /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#227
456b5b571e0SLoGin     #[allow(clippy::bad_bit_mask)]
457ce5850adSLoGin     pub struct IrqStatus: u32 {
458e2841179SLoGin         const IRQD_TRIGGER_NONE = IrqLineStatus::IRQ_TYPE_NONE.bits();
459e2841179SLoGin         const IRQD_TRIGGER_RISING = IrqLineStatus::IRQ_TYPE_EDGE_RISING.bits();
460e2841179SLoGin         const IRQD_TRIGGER_FALLING = IrqLineStatus::IRQ_TYPE_EDGE_FALLING.bits();
461e2841179SLoGin         const IRQD_TRIGGER_HIGH = IrqLineStatus::IRQ_TYPE_LEVEL_HIGH.bits();
462e2841179SLoGin         const IRQD_TRIGGER_LOW = IrqLineStatus::IRQ_TYPE_LEVEL_LOW.bits();
463e2841179SLoGin 
464ce5850adSLoGin         /// 触发类型位的掩码
465ce5850adSLoGin         const IRQD_TRIGGER_MASK = 0xf;
466ce5850adSLoGin         /// 亲和性设置待处理
467ce5850adSLoGin         const IRQD_SETAFFINITY_PENDING = 1 << 8;
468ce5850adSLoGin         /// 中断已激活
469ce5850adSLoGin         const IRQD_ACTIVATED = 1 << 9;
470ce5850adSLoGin         /// 对此IRQ禁用平衡
471ce5850adSLoGin         const IRQD_NO_BALANCING = 1 << 10;
472ce5850adSLoGin         /// 中断是每个CPU特定的
473ce5850adSLoGin         const IRQD_PER_CPU = 1 << 11;
474ce5850adSLoGin         /// 中断亲和性已设置
475ce5850adSLoGin         const IRQD_AFFINITY_SET = 1 << 12;
476ce5850adSLoGin         /// 中断是电平触发
477ce5850adSLoGin         const IRQD_LEVEL = 1 << 13;
478ce5850adSLoGin         /// 中断配置为从挂起状态唤醒
479ce5850adSLoGin         const IRQD_WAKEUP_STATE = 1 << 14;
480ce5850adSLoGin         /// 中断可以在进程上下文中移动
481ce5850adSLoGin         const IRQD_MOVE_PCNTXT = 1 << 15;
482ce5850adSLoGin         /// 中断被禁用
483ce5850adSLoGin         const IRQD_IRQ_DISABLED = 1 << 16;
484ce5850adSLoGin         /// 中断被屏蔽
485ce5850adSLoGin         const IRQD_IRQ_MASKED = 1 << 17;
486ce5850adSLoGin         /// 中断正在处理中
487ce5850adSLoGin         const IRQD_IRQ_INPROGRESS = 1 << 18;
488ce5850adSLoGin         /// 唤醒模式已准备就绪
489ce5850adSLoGin         const IRQD_WAKEUP_ARMED = 1 << 19;
490ce5850adSLoGin         /// 中断被转发到一个虚拟CPU
491ce5850adSLoGin         const IRQD_FORWARDED_TO_VCPU = 1 << 20;
492ce5850adSLoGin         /// 亲和性由内核自动管理
493ce5850adSLoGin         const IRQD_AFFINITY_MANAGED = 1 << 21;
494ce5850adSLoGin         /// 中断已启动
495ce5850adSLoGin         const IRQD_IRQ_STARTED = 1 << 22;
496ce5850adSLoGin         /// 由于空亲和性掩码而关闭的中断。仅适用于亲和性管理的中断。
497ce5850adSLoGin         const IRQD_MANAGED_SHUTDOWN = 1 << 23;
498ce5850adSLoGin         /// IRQ只允许单个亲和性目标
499ce5850adSLoGin         const IRQD_SINGLE_TARGET = 1 << 24;
500e2841179SLoGin         /// 默认的触发器已设置
501ce5850adSLoGin         const IRQD_DEFAULT_TRIGGER_SET = 1 << 25;
502ce5850adSLoGin         /// 可以使用保留模式
503ce5850adSLoGin         const IRQD_CAN_RESERVE = 1 << 26;
504ce5850adSLoGin         /// Non-maskable MSI quirk for affinity change required
505ce5850adSLoGin         const IRQD_MSI_NOMASK_QUIRK = 1 << 27;
506ce5850adSLoGin         /// 强制要求`handle_irq_()`只能在真实的中断上下文中调用
507ce5850adSLoGin         const IRQD_HANDLE_ENFORCE_IRQCTX = 1 << 28;
508ce5850adSLoGin         /// 激活时设置亲和性。在禁用时不要调用irq_chip::irq_set_affinity()。
509ce5850adSLoGin         const IRQD_AFFINITY_ON_ACTIVATE = 1 << 29;
510ce5850adSLoGin         /// 如果irqpm具有标志 IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND,则在挂起时中断被启用。
511ce5850adSLoGin         const IRQD_IRQ_ENABLED_ON_SUSPEND = 1 << 30;
512ce5850adSLoGin     }
513ce5850adSLoGin }
514ce5850adSLoGin 
515ce5850adSLoGin #[allow(dead_code)]
516ce5850adSLoGin impl IrqStatus {
is_set_affinity_pending(&self) -> bool517ce5850adSLoGin     pub const fn is_set_affinity_pending(&self) -> bool {
518ce5850adSLoGin         self.contains(Self::IRQD_SETAFFINITY_PENDING)
519ce5850adSLoGin     }
520ce5850adSLoGin 
is_per_cpu(&self) -> bool521ce5850adSLoGin     pub const fn is_per_cpu(&self) -> bool {
522ce5850adSLoGin         self.contains(Self::IRQD_PER_CPU)
523ce5850adSLoGin     }
524ce5850adSLoGin 
can_balance(&self) -> bool525ce5850adSLoGin     pub const fn can_balance(&self) -> bool {
526b5b571e0SLoGin         (self.bits & (Self::IRQD_PER_CPU.bits | Self::IRQD_NO_BALANCING.bits)) == 0
527ce5850adSLoGin     }
528ce5850adSLoGin 
affinity_was_set(&self) -> bool529ce5850adSLoGin     pub const fn affinity_was_set(&self) -> bool {
530ce5850adSLoGin         self.contains(Self::IRQD_AFFINITY_SET)
531ce5850adSLoGin     }
532ce5850adSLoGin 
masked(&self) -> bool533e2841179SLoGin     pub fn masked(&self) -> bool {
534e2841179SLoGin         self.contains(Self::IRQD_IRQ_MASKED)
535e2841179SLoGin     }
536e2841179SLoGin 
disabled(&self) -> bool537e2841179SLoGin     pub fn disabled(&self) -> bool {
538e2841179SLoGin         self.contains(Self::IRQD_IRQ_DISABLED)
539e2841179SLoGin     }
540e2841179SLoGin 
mark_affinity_set(&mut self)541ce5850adSLoGin     pub fn mark_affinity_set(&mut self) {
542ce5850adSLoGin         self.insert(Self::IRQD_AFFINITY_SET);
543ce5850adSLoGin     }
544ce5850adSLoGin 
trigger_type_was_set(&self) -> bool545ce5850adSLoGin     pub const fn trigger_type_was_set(&self) -> bool {
546ce5850adSLoGin         self.contains(Self::IRQD_DEFAULT_TRIGGER_SET)
547ce5850adSLoGin     }
548ce5850adSLoGin 
mark_trigger_type_set(&mut self)549ce5850adSLoGin     pub fn mark_trigger_type_set(&mut self) {
550ce5850adSLoGin         self.insert(Self::IRQD_DEFAULT_TRIGGER_SET);
551ce5850adSLoGin     }
552ce5850adSLoGin 
trigger_type(&self) -> IrqLineStatus553ce5850adSLoGin     pub const fn trigger_type(&self) -> IrqLineStatus {
554ce5850adSLoGin         IrqLineStatus::from_bits_truncate(self.bits & Self::IRQD_TRIGGER_MASK.bits)
555ce5850adSLoGin     }
556ce5850adSLoGin 
557ce5850adSLoGin     /// Must only be called inside irq_chip.irq_set_type() functions or
558ce5850adSLoGin     /// from the DT/ACPI setup code.
set_trigger_type(&mut self, trigger: IrqLineStatus)559ce5850adSLoGin     pub const fn set_trigger_type(&mut self, trigger: IrqLineStatus) {
560ce5850adSLoGin         self.bits &= !Self::IRQD_TRIGGER_MASK.bits;
561ce5850adSLoGin         self.bits |= trigger.bits & Self::IRQD_TRIGGER_MASK.bits;
562ce5850adSLoGin 
563ce5850adSLoGin         self.bits |= Self::IRQD_DEFAULT_TRIGGER_SET.bits;
564ce5850adSLoGin     }
565ce5850adSLoGin 
is_level_type(&self) -> bool566ce5850adSLoGin     pub const fn is_level_type(&self) -> bool {
567ce5850adSLoGin         self.contains(Self::IRQD_LEVEL)
568ce5850adSLoGin     }
569ce5850adSLoGin 
570ce5850adSLoGin     /// Must only be called of irqchip.irq_set_affinity() or low level
571ce5850adSLoGin     /// hierarchy domain allocation functions.
set_single_target(&mut self)572ce5850adSLoGin     pub fn set_single_target(&mut self) {
573ce5850adSLoGin         self.insert(Self::IRQD_SINGLE_TARGET);
574ce5850adSLoGin     }
575ce5850adSLoGin 
is_single_target(&self) -> bool576ce5850adSLoGin     pub const fn is_single_target(&self) -> bool {
577ce5850adSLoGin         self.contains(Self::IRQD_SINGLE_TARGET)
578ce5850adSLoGin     }
579ce5850adSLoGin 
set_handle_enforce_irqctx(&mut self)580ce5850adSLoGin     pub fn set_handle_enforce_irqctx(&mut self) {
581ce5850adSLoGin         self.insert(Self::IRQD_HANDLE_ENFORCE_IRQCTX);
582ce5850adSLoGin     }
583ce5850adSLoGin 
is_handle_enforce_irqctx(&self) -> bool584ce5850adSLoGin     pub const fn is_handle_enforce_irqctx(&self) -> bool {
585ce5850adSLoGin         self.contains(Self::IRQD_HANDLE_ENFORCE_IRQCTX)
586ce5850adSLoGin     }
587ce5850adSLoGin 
is_enabled_on_suspend(&self) -> bool588ce5850adSLoGin     pub const fn is_enabled_on_suspend(&self) -> bool {
589ce5850adSLoGin         self.contains(Self::IRQD_IRQ_ENABLED_ON_SUSPEND)
590ce5850adSLoGin     }
591ce5850adSLoGin 
is_wakeup_set(&self) -> bool592ce5850adSLoGin     pub const fn is_wakeup_set(&self) -> bool {
593ce5850adSLoGin         self.contains(Self::IRQD_WAKEUP_STATE)
594ce5850adSLoGin     }
595ce5850adSLoGin 
can_move_in_process_context(&self) -> bool596ce5850adSLoGin     pub const fn can_move_in_process_context(&self) -> bool {
597ce5850adSLoGin         self.contains(Self::IRQD_MOVE_PCNTXT)
598ce5850adSLoGin     }
599ce5850adSLoGin 
is_irq_in_progress(&self) -> bool600ce5850adSLoGin     pub const fn is_irq_in_progress(&self) -> bool {
601ce5850adSLoGin         self.contains(Self::IRQD_IRQ_INPROGRESS)
602ce5850adSLoGin     }
603ce5850adSLoGin 
is_wakeup_armed(&self) -> bool604ce5850adSLoGin     pub const fn is_wakeup_armed(&self) -> bool {
605ce5850adSLoGin         self.contains(Self::IRQD_WAKEUP_ARMED)
606ce5850adSLoGin     }
607ce5850adSLoGin 
is_forwarded_to_vcpu(&self) -> bool608ce5850adSLoGin     pub const fn is_forwarded_to_vcpu(&self) -> bool {
609ce5850adSLoGin         self.contains(Self::IRQD_FORWARDED_TO_VCPU)
610ce5850adSLoGin     }
611ce5850adSLoGin 
set_forwarded_to_vcpu(&mut self)612ce5850adSLoGin     pub fn set_forwarded_to_vcpu(&mut self) {
613ce5850adSLoGin         self.insert(Self::IRQD_FORWARDED_TO_VCPU);
614ce5850adSLoGin     }
615ce5850adSLoGin 
affinity_managed(&self) -> bool616e2841179SLoGin     pub const fn affinity_managed(&self) -> bool {
617ce5850adSLoGin         self.contains(Self::IRQD_AFFINITY_MANAGED)
618ce5850adSLoGin     }
619ce5850adSLoGin 
is_activated(&self) -> bool620ce5850adSLoGin     pub const fn is_activated(&self) -> bool {
621ce5850adSLoGin         self.contains(Self::IRQD_ACTIVATED)
622ce5850adSLoGin     }
623ce5850adSLoGin 
set_activated(&mut self)624ce5850adSLoGin     pub fn set_activated(&mut self) {
625ce5850adSLoGin         self.insert(Self::IRQD_ACTIVATED);
626ce5850adSLoGin     }
627ce5850adSLoGin 
clear_activated(&mut self)628ce5850adSLoGin     pub fn clear_activated(&mut self) {
629ce5850adSLoGin         self.remove(Self::IRQD_ACTIVATED);
630ce5850adSLoGin     }
631ce5850adSLoGin 
is_started(&self) -> bool632ce5850adSLoGin     pub const fn is_started(&self) -> bool {
633ce5850adSLoGin         self.contains(Self::IRQD_IRQ_STARTED)
634ce5850adSLoGin     }
635ce5850adSLoGin 
is_managed_and_shutdown(&self) -> bool636ce5850adSLoGin     pub const fn is_managed_and_shutdown(&self) -> bool {
637ce5850adSLoGin         self.contains(Self::IRQD_MANAGED_SHUTDOWN)
638ce5850adSLoGin     }
639ce5850adSLoGin 
set_can_reserve(&mut self)640ce5850adSLoGin     pub fn set_can_reserve(&mut self) {
641ce5850adSLoGin         self.insert(Self::IRQD_CAN_RESERVE);
642ce5850adSLoGin     }
643ce5850adSLoGin 
can_reserve(&self) -> bool644ce5850adSLoGin     pub const fn can_reserve(&self) -> bool {
645ce5850adSLoGin         self.contains(Self::IRQD_CAN_RESERVE)
646ce5850adSLoGin     }
647ce5850adSLoGin 
clear_can_reserve(&mut self)648ce5850adSLoGin     pub fn clear_can_reserve(&mut self) {
649ce5850adSLoGin         self.remove(Self::IRQD_CAN_RESERVE);
650ce5850adSLoGin     }
651ce5850adSLoGin 
set_msi_nomask_quirk(&mut self)652ce5850adSLoGin     pub fn set_msi_nomask_quirk(&mut self) {
653ce5850adSLoGin         self.insert(Self::IRQD_MSI_NOMASK_QUIRK);
654ce5850adSLoGin     }
655ce5850adSLoGin 
clear_msi_nomask_quirk(&mut self)656ce5850adSLoGin     pub fn clear_msi_nomask_quirk(&mut self) {
657ce5850adSLoGin         self.remove(Self::IRQD_MSI_NOMASK_QUIRK);
658ce5850adSLoGin     }
659ce5850adSLoGin 
is_msi_nomask_quirk(&self) -> bool660ce5850adSLoGin     pub const fn is_msi_nomask_quirk(&self) -> bool {
661ce5850adSLoGin         self.contains(Self::IRQD_MSI_NOMASK_QUIRK)
662ce5850adSLoGin     }
663ce5850adSLoGin 
set_affinity_on_activate(&mut self)664ce5850adSLoGin     pub fn set_affinity_on_activate(&mut self) {
665ce5850adSLoGin         self.insert(Self::IRQD_AFFINITY_ON_ACTIVATE);
666ce5850adSLoGin     }
667ce5850adSLoGin 
is_affinity_on_activate(&self) -> bool668ce5850adSLoGin     pub const fn is_affinity_on_activate(&self) -> bool {
669ce5850adSLoGin         self.contains(Self::IRQD_AFFINITY_ON_ACTIVATE)
670ce5850adSLoGin     }
671e2841179SLoGin 
started(&self) -> bool672e2841179SLoGin     pub const fn started(&self) -> bool {
673e2841179SLoGin         self.contains(Self::IRQD_IRQ_STARTED)
674e2841179SLoGin     }
675ce5850adSLoGin }
676