xref: /DragonOS/kernel/src/exception/irqdomain.rs (revision 338f6903262c5031abad3c8e361813355a27fcdb)
1ce5850adSLoGin use core::fmt::Debug;
2ce5850adSLoGin 
3ce5850adSLoGin use alloc::{
4e2841179SLoGin     string::{String, ToString},
5ce5850adSLoGin     sync::{Arc, Weak},
6ce5850adSLoGin     vec::Vec,
7ce5850adSLoGin };
8ce5850adSLoGin use hashbrown::HashMap;
9ce5850adSLoGin use system_error::SystemError;
10ce5850adSLoGin 
11ce5850adSLoGin use crate::{
12ce5850adSLoGin     driver::{base::device::Device, open_firmware::device_node::DeviceNode},
13e2841179SLoGin     exception::{irqdata::IrqLineStatus, irqdesc::irq_desc_manager, manage::irq_manager},
14ce5850adSLoGin     libs::{rwlock::RwLock, spinlock::SpinLock},
15ce5850adSLoGin };
16ce5850adSLoGin 
17ce5850adSLoGin use super::{
18*338f6903SLoGin     dummychip::no_irq_chip,
19*338f6903SLoGin     irqchip::{IrqChip, IrqChipData, IrqChipGeneric, IrqGcFlags},
20*338f6903SLoGin     irqdata::{IrqData, IrqHandlerData},
21*338f6903SLoGin     irqdesc::IrqFlowHandler,
22ce5850adSLoGin     HardwareIrqNumber, IrqNumber,
23ce5850adSLoGin };
24ce5850adSLoGin 
25e2841179SLoGin static mut IRQ_DOMAIN_MANAGER: Option<Arc<IrqDomainManager>> = None;
26e2841179SLoGin 
27e2841179SLoGin /// 获取中断域管理器的引用
28e2841179SLoGin #[inline(always)]
29e2841179SLoGin pub fn irq_domain_manager() -> &'static Arc<IrqDomainManager> {
30e2841179SLoGin     unsafe { IRQ_DOMAIN_MANAGER.as_ref().unwrap() }
31e2841179SLoGin }
32e2841179SLoGin 
33e2841179SLoGin pub(super) fn irq_domain_manager_init() {
34e2841179SLoGin     unsafe {
35e2841179SLoGin         IRQ_DOMAIN_MANAGER = Some(Arc::new(IrqDomainManager::new()));
36e2841179SLoGin     }
37e2841179SLoGin }
38e2841179SLoGin /// 中断域管理器
39e2841179SLoGin pub struct IrqDomainManager {
40e2841179SLoGin     domains: SpinLock<Vec<Arc<IrqDomain>>>,
41e2841179SLoGin     inner: RwLock<InnerIrqDomainManager>,
42e2841179SLoGin }
43e2841179SLoGin 
44e2841179SLoGin impl IrqDomainManager {
45e2841179SLoGin     pub fn new() -> IrqDomainManager {
46e2841179SLoGin         IrqDomainManager {
47e2841179SLoGin             domains: SpinLock::new(Vec::new()),
48e2841179SLoGin             inner: RwLock::new(InnerIrqDomainManager {
49e2841179SLoGin                 default_domain: None,
50e2841179SLoGin             }),
51e2841179SLoGin         }
52e2841179SLoGin     }
53e2841179SLoGin 
54*338f6903SLoGin     /// 创建一个新的线性映射的irqdomain, 并将其添加到irqdomain管理器中
55*338f6903SLoGin     ///
56*338f6903SLoGin     /// 创建的irqdomain,中断号是线性的,即从0开始,依次递增
57*338f6903SLoGin     ///
58*338f6903SLoGin     /// ## 参数
59*338f6903SLoGin     ///
60*338f6903SLoGin     /// - `name` - 中断域的名字
61*338f6903SLoGin     /// - `ops` - 中断域的操作
62*338f6903SLoGin     /// - `irq_size` - 中断号的数量
63*338f6903SLoGin     #[allow(dead_code)]
64*338f6903SLoGin     pub fn create_and_add_linear(
65*338f6903SLoGin         &self,
66*338f6903SLoGin         name: String,
67*338f6903SLoGin         ops: &'static dyn IrqDomainOps,
68*338f6903SLoGin         irq_size: u32,
69*338f6903SLoGin     ) -> Option<Arc<IrqDomain>> {
70*338f6903SLoGin         self.create_and_add(
71*338f6903SLoGin             name,
72*338f6903SLoGin             ops,
73*338f6903SLoGin             IrqNumber::new(0),
74*338f6903SLoGin             HardwareIrqNumber::new(0),
75*338f6903SLoGin             irq_size,
76*338f6903SLoGin         )
77*338f6903SLoGin     }
78*338f6903SLoGin 
79e2841179SLoGin     /// 创建一个新的irqdomain, 并将其添加到irqdomain管理器中
80e2841179SLoGin     ///
81e2841179SLoGin     /// ## 参数
82e2841179SLoGin     ///
83e2841179SLoGin     /// - `name` - 中断域的名字
84e2841179SLoGin     /// - `ops` - 中断域的操作
85e2841179SLoGin     /// - `first_irq` - 起始软件中断号
86e2841179SLoGin     /// - `first_hwirq` - 起始硬件中断号
87e2841179SLoGin     /// - `irq_size` - 中断号的数量
88e2841179SLoGin     ///
89e2841179SLoGin     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdomain.c?fi=__irq_domain_add#139
90e2841179SLoGin     pub fn create_and_add(
91e2841179SLoGin         &self,
92e2841179SLoGin         name: String,
93e2841179SLoGin         ops: &'static dyn IrqDomainOps,
94e2841179SLoGin         first_irq: IrqNumber,
95e2841179SLoGin         first_hwirq: HardwareIrqNumber,
96e2841179SLoGin         irq_size: u32,
97e2841179SLoGin     ) -> Option<Arc<IrqDomain>> {
98e2841179SLoGin         let domain = IrqDomain::new(
99e2841179SLoGin             None,
100e2841179SLoGin             Some(name),
101e2841179SLoGin             ops,
102e2841179SLoGin             IrqDomainFlags::NAME_ALLOCATED,
103e2841179SLoGin             IrqDomainBusToken::Any,
104e2841179SLoGin             first_irq + irq_size,
105e2841179SLoGin             first_hwirq + irq_size,
106e2841179SLoGin         )?;
107e2841179SLoGin 
108e2841179SLoGin         self.add_domain(domain.clone());
109e2841179SLoGin 
110e2841179SLoGin         self.domain_associate_many(&domain, first_irq, first_hwirq, irq_size);
111e2841179SLoGin 
112e2841179SLoGin         return Some(domain);
113e2841179SLoGin     }
114e2841179SLoGin 
115e2841179SLoGin     fn add_domain(&self, domain: Arc<IrqDomain>) {
116e2841179SLoGin         self.domains.lock_irqsave().push(domain);
117e2841179SLoGin     }
118e2841179SLoGin 
119e2841179SLoGin     #[allow(dead_code)]
120e2841179SLoGin     pub fn remove_domain(&self, domain: &Arc<IrqDomain>) {
121e2841179SLoGin         let mut domains = self.domains.lock_irqsave();
122e2841179SLoGin         let index = domains
123e2841179SLoGin             .iter()
124e2841179SLoGin             .position(|x| Arc::ptr_eq(x, domain))
125e2841179SLoGin             .expect("domain not found");
126e2841179SLoGin         domains.remove(index);
127e2841179SLoGin     }
128e2841179SLoGin 
129e2841179SLoGin     /// 获取默认的中断域
130e2841179SLoGin     #[allow(dead_code)]
131e2841179SLoGin     pub fn default_domain(&self) -> Option<Arc<IrqDomain>> {
132e2841179SLoGin         self.inner.read().default_domain.clone()
133e2841179SLoGin     }
134e2841179SLoGin 
135e2841179SLoGin     /// 设置默认的中断域
136e2841179SLoGin     ///
137e2841179SLoGin     /// 在创建IRQ映射的时候,如果没有指定中断域,就会使用默认的中断域
138e2841179SLoGin     pub fn set_default_domain(&self, domain: Arc<IrqDomain>) {
139e2841179SLoGin         self.inner.write_irqsave().default_domain = Some(domain);
140e2841179SLoGin     }
141e2841179SLoGin 
142e2841179SLoGin     /// 将指定范围的硬件中断号与软件中断号一一对应的关联起来
143e2841179SLoGin     ///
144e2841179SLoGin     /// ## 参数
145e2841179SLoGin     ///
146e2841179SLoGin     /// - `domain` - 中断域
147e2841179SLoGin     /// - `first_irq` - 起始软件中断号
148e2841179SLoGin     /// - `first_hwirq` - 起始硬件中断号
149e2841179SLoGin     /// - `count` - 数量
150e2841179SLoGin     pub fn domain_associate_many(
151e2841179SLoGin         &self,
152e2841179SLoGin         domain: &Arc<IrqDomain>,
153e2841179SLoGin         first_irq: IrqNumber,
154e2841179SLoGin         first_hwirq: HardwareIrqNumber,
155e2841179SLoGin         count: u32,
156e2841179SLoGin     ) {
157e2841179SLoGin         for i in 0..count {
158e2841179SLoGin             if let Err(e) = self.domain_associate(domain, first_irq + i, first_hwirq + i) {
159e2841179SLoGin                 kwarn!("domain associate failed: {:?}, domain '{:?}' didn't like hwirq {} to virq {} mapping.", e, domain.name(), (first_hwirq + i).data(), (first_irq + i).data());
160e2841179SLoGin             }
161e2841179SLoGin         }
162e2841179SLoGin     }
163e2841179SLoGin 
164e2841179SLoGin     /// 将一个硬件中断号与一个软件中断号关联起来
165e2841179SLoGin     ///
166e2841179SLoGin     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdomain.c#562
167e2841179SLoGin     pub fn domain_associate(
168e2841179SLoGin         &self,
169e2841179SLoGin         domain: &Arc<IrqDomain>,
170e2841179SLoGin         irq: IrqNumber,
171e2841179SLoGin         hwirq: HardwareIrqNumber,
172e2841179SLoGin     ) -> Result<(), SystemError> {
173e2841179SLoGin         if hwirq >= domain.revmap.read_irqsave().hwirq_max {
174e2841179SLoGin             kwarn!(
175e2841179SLoGin                 "hwirq {} is out of range for domain {:?}",
176e2841179SLoGin                 hwirq.data(),
177e2841179SLoGin                 domain.name()
178e2841179SLoGin             );
179e2841179SLoGin             return Err(SystemError::EINVAL);
180e2841179SLoGin         }
181e2841179SLoGin         let irq_data = irq_desc_manager()
182e2841179SLoGin             .lookup(irq)
183e2841179SLoGin             .ok_or_else(|| {
184e2841179SLoGin                 kwarn!("irq_desc not found for irq {}", irq.data());
185e2841179SLoGin                 SystemError::EINVAL
186e2841179SLoGin             })?
187e2841179SLoGin             .irq_data();
188e2841179SLoGin         if irq_data.domain().is_some() {
189e2841179SLoGin             kwarn!(
190e2841179SLoGin                 "irq {} is already associated with domain {:?}",
191e2841179SLoGin                 irq.data(),
192e2841179SLoGin                 irq_data.domain().unwrap().name()
193e2841179SLoGin             );
194e2841179SLoGin             return Err(SystemError::EINVAL);
195e2841179SLoGin         }
196e2841179SLoGin 
197e2841179SLoGin         let mut irq_data_guard = irq_data.inner();
198e2841179SLoGin         irq_data_guard.set_hwirq(hwirq);
199e2841179SLoGin         irq_data_guard.set_domain(Some(domain.clone()));
200e2841179SLoGin         drop(irq_data_guard);
201e2841179SLoGin         let r = domain.ops.map(&domain, hwirq, irq);
202e2841179SLoGin         if let Err(e) = r {
203e2841179SLoGin             if e != SystemError::ENOSYS {
204e2841179SLoGin                 if e != SystemError::EPERM {
205e2841179SLoGin                     kinfo!("domain associate failed: {:?}, domain '{:?}' didn't like hwirq {} to virq {} mapping.", e, domain.name(), hwirq.data(), irq.data());
206e2841179SLoGin                 }
207e2841179SLoGin                 let mut irq_data_guard = irq_data.inner();
208e2841179SLoGin                 irq_data_guard.set_domain(None);
209e2841179SLoGin                 irq_data_guard.set_hwirq(HardwareIrqNumber::new(0));
210e2841179SLoGin                 return Err(e);
211e2841179SLoGin             }
212e2841179SLoGin         }
213e2841179SLoGin 
214e2841179SLoGin         if domain.name().is_none() {
215e2841179SLoGin             let chip = irq_data.chip_info_read_irqsave().chip();
216e2841179SLoGin             domain.set_name(chip.name().to_string());
217e2841179SLoGin         }
218e2841179SLoGin 
219e2841179SLoGin         self.irq_domain_set_mapping(&domain, hwirq, irq_data);
220e2841179SLoGin 
221e2841179SLoGin         irq_manager().irq_clear_status_flags(irq, IrqLineStatus::IRQ_NOREQUEST)?;
222e2841179SLoGin 
223e2841179SLoGin         return Ok(());
224e2841179SLoGin     }
225e2841179SLoGin 
226e2841179SLoGin     fn irq_domain_set_mapping(
227e2841179SLoGin         &self,
228e2841179SLoGin         domain: &Arc<IrqDomain>,
229e2841179SLoGin         hwirq: HardwareIrqNumber,
230e2841179SLoGin         irq_data: Arc<IrqData>,
231e2841179SLoGin     ) {
232e2841179SLoGin         if domain.no_map() {
233e2841179SLoGin             return;
234e2841179SLoGin         }
235e2841179SLoGin 
236e2841179SLoGin         domain.revmap.write_irqsave().insert(hwirq, irq_data);
237e2841179SLoGin     }
238e2841179SLoGin     /// 递归调用 domain_ops->activate 以激活中断
239e2841179SLoGin     ///
240e2841179SLoGin     /// ## 参数
241e2841179SLoGin     ///
242e2841179SLoGin     /// - irq_data: 与中断关联的最外层 irq_data
243e2841179SLoGin     /// - reserve: 如果为true,则仅预留一个中断向量,而不是分配一个
244e2841179SLoGin     ///
245e2841179SLoGin     /// 这是调用 domain_ops->activate 以编程中断控制器的第二步,以便中断实际上可以被传递。
246e2841179SLoGin     pub fn activate_irq(&self, irq_data: &Arc<IrqData>, reserve: bool) -> Result<(), SystemError> {
247e2841179SLoGin         let mut r = Ok(());
248e2841179SLoGin         if !irq_data.common_data().status().is_activated() {
249e2841179SLoGin             r = self.do_activate_irq(Some(irq_data.clone()), reserve);
250e2841179SLoGin         }
251e2841179SLoGin 
252e2841179SLoGin         if !r.is_ok() {
253e2841179SLoGin             irq_data.common_data().status().set_activated();
254e2841179SLoGin         }
255e2841179SLoGin 
256e2841179SLoGin         return r;
257e2841179SLoGin     }
258e2841179SLoGin 
259e2841179SLoGin     #[inline(never)]
260e2841179SLoGin     fn do_activate_irq(
261e2841179SLoGin         &self,
262e2841179SLoGin         irq_data: Option<Arc<IrqData>>,
263e2841179SLoGin         reserve: bool,
264e2841179SLoGin     ) -> Result<(), SystemError> {
265e2841179SLoGin         let mut r = Ok(());
266e2841179SLoGin 
267e2841179SLoGin         if irq_data.is_some() && irq_data.as_ref().unwrap().domain().is_some() {
268e2841179SLoGin             let domain = irq_data.as_ref().unwrap().domain().unwrap();
269e2841179SLoGin 
270e2841179SLoGin             let irq_data = irq_data.unwrap();
271e2841179SLoGin 
272e2841179SLoGin             let parent_data = irq_data.parent_data().map(|x| x.upgrade()).flatten();
273e2841179SLoGin             if let Some(parent_data) = parent_data.clone() {
274e2841179SLoGin                 r = self.do_activate_irq(Some(parent_data), reserve);
275e2841179SLoGin             }
276e2841179SLoGin 
277e2841179SLoGin             if r.is_err() {
278e2841179SLoGin                 let tmpr = domain.ops.activate(&domain, &irq_data, reserve);
279e2841179SLoGin                 if let Err(e) = tmpr {
280e2841179SLoGin                     if e != SystemError::ENOSYS && parent_data.is_some() {
281e2841179SLoGin                         self.do_deactivate_irq(parent_data);
282e2841179SLoGin                     }
283e2841179SLoGin                 }
284e2841179SLoGin             }
285e2841179SLoGin         }
286e2841179SLoGin 
287e2841179SLoGin         return r;
288e2841179SLoGin     }
289e2841179SLoGin 
290e2841179SLoGin     fn do_deactivate_irq(&self, irq_data: Option<Arc<IrqData>>) {
291e2841179SLoGin         if let Some(irq_data) = irq_data {
292e2841179SLoGin             if let Some(domain) = irq_data.domain() {
293e2841179SLoGin                 domain.ops.deactivate(&domain, &irq_data);
294e2841179SLoGin                 let pp = irq_data.parent_data().map(|x| x.upgrade()).flatten();
295e2841179SLoGin 
296e2841179SLoGin                 if pp.is_some() {
297e2841179SLoGin                     self.do_deactivate_irq(pp);
298e2841179SLoGin                 }
299e2841179SLoGin             }
300e2841179SLoGin         }
301e2841179SLoGin     }
302*338f6903SLoGin 
303*338f6903SLoGin     /// `irq_domain_set_info` - 在 @domain 中为 @virq 设置完整的数据
304*338f6903SLoGin     ///
305*338f6903SLoGin     /// ## 参数
306*338f6903SLoGin     ///
307*338f6903SLoGin     /// - `domain`: 要匹配的中断域
308*338f6903SLoGin     /// - `virq`: IRQ号
309*338f6903SLoGin     /// - `hwirq`: 硬件中断号
310*338f6903SLoGin     /// - `chip`: 相关的中断芯片
311*338f6903SLoGin     /// - `chip_data`: 相关的中断芯片数据
312*338f6903SLoGin     /// - `handler`: 中断流处理器
313*338f6903SLoGin     /// - `handler_data`: 中断流处理程序数据
314*338f6903SLoGin     /// - `handler_name`: 中断处理程序名称
315*338f6903SLoGin     pub fn domain_set_info(
316*338f6903SLoGin         &self,
317*338f6903SLoGin         domain: &Arc<IrqDomain>,
318*338f6903SLoGin         virq: IrqNumber,
319*338f6903SLoGin         hwirq: HardwareIrqNumber,
320*338f6903SLoGin         chip: Arc<dyn IrqChip>,
321*338f6903SLoGin         chip_data: Option<Arc<dyn IrqChipData>>,
322*338f6903SLoGin         flow_handler: &'static dyn IrqFlowHandler,
323*338f6903SLoGin         handler_data: Option<Arc<dyn IrqHandlerData>>,
324*338f6903SLoGin         handler_name: Option<String>,
325*338f6903SLoGin     ) {
326*338f6903SLoGin         let r = self.domain_set_hwirq_and_chip(domain, virq, hwirq, Some(chip), chip_data);
327*338f6903SLoGin         if r.is_err() {
328*338f6903SLoGin             return;
329*338f6903SLoGin         }
330*338f6903SLoGin         irq_manager().__irq_set_handler(virq, flow_handler, false, handler_name);
331*338f6903SLoGin         irq_manager().irq_set_handler_data(virq, handler_data).ok();
332*338f6903SLoGin     }
333*338f6903SLoGin 
334*338f6903SLoGin     /// `domain_set_hwirq_and_chip` - 在 @domain 中为 @virq 设置 hwirq 和 irqchip
335*338f6903SLoGin     ///
336*338f6903SLoGin     /// ## 参数
337*338f6903SLoGin     ///
338*338f6903SLoGin     /// - `domain`: 要匹配的中断域
339*338f6903SLoGin     /// - `virq`: IRQ号
340*338f6903SLoGin     /// - `hwirq`: hwirq号
341*338f6903SLoGin     /// - `chip`: 相关的中断芯片
342*338f6903SLoGin     /// - `chip_data`: 相关的芯片数据
343*338f6903SLoGin     pub fn domain_set_hwirq_and_chip(
344*338f6903SLoGin         &self,
345*338f6903SLoGin         domain: &Arc<IrqDomain>,
346*338f6903SLoGin         virq: IrqNumber,
347*338f6903SLoGin         hwirq: HardwareIrqNumber,
348*338f6903SLoGin         chip: Option<Arc<dyn IrqChip>>,
349*338f6903SLoGin         chip_data: Option<Arc<dyn IrqChipData>>,
350*338f6903SLoGin     ) -> Result<(), SystemError> {
351*338f6903SLoGin         let irq_data: Arc<IrqData> = self
352*338f6903SLoGin             .domain_get_irq_data(domain, virq)
353*338f6903SLoGin             .ok_or(SystemError::ENOENT)?;
354*338f6903SLoGin         let mut inner = irq_data.inner();
355*338f6903SLoGin         let mut chip_info = irq_data.chip_info_write_irqsave();
356*338f6903SLoGin 
357*338f6903SLoGin         inner.set_hwirq(hwirq);
358*338f6903SLoGin         if let Some(chip) = chip {
359*338f6903SLoGin             chip_info.set_chip(Some(chip));
360*338f6903SLoGin         } else {
361*338f6903SLoGin             chip_info.set_chip(Some(no_irq_chip()));
362*338f6903SLoGin         };
363*338f6903SLoGin 
364*338f6903SLoGin         chip_info.set_chip_data(chip_data);
365*338f6903SLoGin 
366*338f6903SLoGin         return Ok(());
367*338f6903SLoGin     }
368*338f6903SLoGin 
369*338f6903SLoGin     /// `irq_domain_get_irq_data` - 获取与 @virq 和 @domain 关联的 irq_data
370*338f6903SLoGin     ///
371*338f6903SLoGin     /// ## 参数
372*338f6903SLoGin     ///
373*338f6903SLoGin     /// - `domain`: 要匹配的域
374*338f6903SLoGin     /// - `virq`: 要获取 irq_data 的IRQ号
375*338f6903SLoGin     pub fn domain_get_irq_data(
376*338f6903SLoGin         &self,
377*338f6903SLoGin         domain: &Arc<IrqDomain>,
378*338f6903SLoGin         virq: IrqNumber,
379*338f6903SLoGin     ) -> Option<Arc<IrqData>> {
380*338f6903SLoGin         let desc = irq_desc_manager().lookup(virq)?;
381*338f6903SLoGin         let mut irq_data = Some(desc.irq_data());
382*338f6903SLoGin 
383*338f6903SLoGin         while irq_data.is_some() {
384*338f6903SLoGin             let dt = irq_data.unwrap();
385*338f6903SLoGin             if dt.domain().is_some() && Arc::ptr_eq(dt.domain().as_ref().unwrap(), domain) {
386*338f6903SLoGin                 return Some(dt);
387*338f6903SLoGin             }
388*338f6903SLoGin             irq_data = dt.parent_data().map(|x| x.upgrade()).flatten();
389*338f6903SLoGin         }
390*338f6903SLoGin 
391*338f6903SLoGin         return None;
392*338f6903SLoGin     }
393e2841179SLoGin }
394e2841179SLoGin 
395e2841179SLoGin struct InnerIrqDomainManager {
396e2841179SLoGin     default_domain: Option<Arc<IrqDomain>>,
397e2841179SLoGin }
398e2841179SLoGin 
399ce5850adSLoGin /// 中断域
400ce5850adSLoGin ///
401ce5850adSLoGin /// 用于把硬件中断号翻译为软件中断号的映射的对象
402ce5850adSLoGin ///
403ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#164
404ce5850adSLoGin #[allow(dead_code)]
405ce5850adSLoGin #[derive(Debug)]
406ce5850adSLoGin pub struct IrqDomain {
407ce5850adSLoGin     /// 中断域的名字 (二选一)
408ce5850adSLoGin     name: Option<&'static str>,
409e2841179SLoGin     allocated_name: SpinLock<Option<String>>,
410ce5850adSLoGin     /// 中断域的操作
411ce5850adSLoGin     ops: &'static dyn IrqDomainOps,
412ce5850adSLoGin     inner: SpinLock<InnerIrqDomain>,
413ce5850adSLoGin     /// 中断号反向映射
414ce5850adSLoGin     revmap: RwLock<IrqDomainRevMap>,
415ce5850adSLoGin }
416ce5850adSLoGin 
417ce5850adSLoGin #[allow(dead_code)]
418ce5850adSLoGin #[derive(Debug)]
419ce5850adSLoGin struct InnerIrqDomain {
420*338f6903SLoGin     /// this field not touched by the core code
421*338f6903SLoGin     host_data: Option<Arc<dyn IrqChipData>>,
422ce5850adSLoGin     /// host per irq_domain flags
423ce5850adSLoGin     flags: IrqDomainFlags,
424ce5850adSLoGin     /// The number of mapped interrupts
425ce5850adSLoGin     mapcount: u32,
426ce5850adSLoGin     bus_token: IrqDomainBusToken,
427ce5850adSLoGin     /// 指向 generic chip 列表的指针。
428ce5850adSLoGin     /// 有一个辅助函数用于为中断控制器驱动程序设置一个或
429ce5850adSLoGin     /// 多个 generic chip,该函数使用此指针并依赖于 generic chip 库。
430ce5850adSLoGin     generic_chip: Option<Arc<IrqDomainChipGeneric>>,
431ce5850adSLoGin     /// Pointer to a device that the domain represent, and that will be
432ce5850adSLoGin     /// used for power management purposes.
433ce5850adSLoGin     device: Option<Arc<dyn Device>>,
434ce5850adSLoGin     /// Pointer to parent irq_domain to support hierarchy irq_domains
435ce5850adSLoGin     parent: Option<Weak<IrqDomain>>,
436ce5850adSLoGin }
437ce5850adSLoGin 
438ce5850adSLoGin impl IrqDomain {
439ce5850adSLoGin     #[allow(dead_code)]
440ce5850adSLoGin     pub fn new(
441ce5850adSLoGin         name: Option<&'static str>,
442ce5850adSLoGin         allocated_name: Option<String>,
443ce5850adSLoGin         ops: &'static dyn IrqDomainOps,
444ce5850adSLoGin         flags: IrqDomainFlags,
445ce5850adSLoGin         bus_token: IrqDomainBusToken,
446e2841179SLoGin         irq_max: IrqNumber,
447e2841179SLoGin         hwirq_max: HardwareIrqNumber,
448ce5850adSLoGin     ) -> Option<Arc<Self>> {
449ce5850adSLoGin         if name.is_none() && allocated_name.is_none() {
450ce5850adSLoGin             return None;
451ce5850adSLoGin         }
452ce5850adSLoGin 
453ce5850adSLoGin         let x = IrqDomain {
454ce5850adSLoGin             name,
455e2841179SLoGin             allocated_name: SpinLock::new(allocated_name),
456ce5850adSLoGin             ops,
457ce5850adSLoGin             inner: SpinLock::new(InnerIrqDomain {
458*338f6903SLoGin                 host_data: None,
459ce5850adSLoGin                 flags,
460ce5850adSLoGin                 mapcount: 0,
461ce5850adSLoGin                 bus_token,
462ce5850adSLoGin                 generic_chip: None,
463ce5850adSLoGin                 device: None,
464ce5850adSLoGin                 parent: None,
465ce5850adSLoGin             }),
466ce5850adSLoGin             revmap: RwLock::new(IrqDomainRevMap {
467ce5850adSLoGin                 map: HashMap::new(),
468e2841179SLoGin                 hwirq_max,
469e2841179SLoGin                 irq_max,
470ce5850adSLoGin             }),
471ce5850adSLoGin         };
472ce5850adSLoGin 
473ce5850adSLoGin         return Some(Arc::new(x));
474ce5850adSLoGin     }
475e2841179SLoGin 
476e2841179SLoGin     /// 中断域是否不对中断号进行转换
477e2841179SLoGin     pub fn no_map(&self) -> bool {
478e2841179SLoGin         self.inner
479e2841179SLoGin             .lock_irqsave()
480e2841179SLoGin             .flags
481e2841179SLoGin             .contains(IrqDomainFlags::NO_MAP)
482e2841179SLoGin     }
483e2841179SLoGin 
484e2841179SLoGin     #[allow(dead_code)]
485e2841179SLoGin     fn set_hwirq_max(&self, hwirq_max: HardwareIrqNumber) {
486e2841179SLoGin         self.revmap.write_irqsave().hwirq_max = hwirq_max;
487e2841179SLoGin     }
488e2841179SLoGin 
489e2841179SLoGin     pub fn name(&self) -> Option<String> {
490e2841179SLoGin         if let Some(name) = self.name {
491e2841179SLoGin             return Some(name.to_string());
492e2841179SLoGin         }
493e2841179SLoGin         return self.allocated_name.lock_irqsave().clone();
494e2841179SLoGin     }
495e2841179SLoGin 
496e2841179SLoGin     pub fn set_name(&self, name: String) {
497e2841179SLoGin         *self.allocated_name.lock_irqsave() = Some(name);
498e2841179SLoGin     }
499e2841179SLoGin 
500e2841179SLoGin     /// The number of mapped interrupts
501e2841179SLoGin     pub fn map_count(&self) -> u32 {
502e2841179SLoGin         self.revmap.read().map.len() as u32
503e2841179SLoGin     }
504*338f6903SLoGin 
505*338f6903SLoGin     pub fn host_data(&self) -> Option<Arc<dyn IrqChipData>> {
506*338f6903SLoGin         self.inner.lock_irqsave().host_data.clone()
507*338f6903SLoGin     }
508*338f6903SLoGin 
509*338f6903SLoGin     pub fn set_host_data(&self, host_data: Option<Arc<dyn IrqChipData>>) {
510*338f6903SLoGin         self.inner.lock_irqsave().host_data = host_data;
511*338f6903SLoGin     }
512ce5850adSLoGin }
513ce5850adSLoGin 
514ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#190
515ce5850adSLoGin #[allow(dead_code)]
516ce5850adSLoGin #[derive(Debug)]
517ce5850adSLoGin struct IrqDomainRevMap {
518e2841179SLoGin     map: HashMap<HardwareIrqNumber, Arc<IrqData>>,
519ce5850adSLoGin     hwirq_max: HardwareIrqNumber,
520e2841179SLoGin     irq_max: IrqNumber,
521e2841179SLoGin }
522e2841179SLoGin 
523e2841179SLoGin impl IrqDomainRevMap {
524e2841179SLoGin     fn insert(&mut self, hwirq: HardwareIrqNumber, irq_data: Arc<IrqData>) {
525e2841179SLoGin         self.map.insert(hwirq, irq_data);
526e2841179SLoGin     }
527e2841179SLoGin 
528e2841179SLoGin     #[allow(dead_code)]
529e2841179SLoGin     fn remove(&mut self, hwirq: HardwareIrqNumber) {
530e2841179SLoGin         self.map.remove(&hwirq);
531e2841179SLoGin     }
532e2841179SLoGin 
533e2841179SLoGin     #[allow(dead_code)]
534e2841179SLoGin     fn lookup(&self, hwirq: HardwareIrqNumber) -> Option<Arc<IrqData>> {
535e2841179SLoGin         self.map.get(&hwirq).cloned()
536e2841179SLoGin     }
537ce5850adSLoGin }
538ce5850adSLoGin 
539ce5850adSLoGin bitflags! {
540ce5850adSLoGin     pub struct IrqDomainFlags: u32 {
541ce5850adSLoGin         /// Irq domain is hierarchical
542ce5850adSLoGin         const HIERARCHY = (1 << 0);
543ce5850adSLoGin         /// Irq domain name was allocated dynamically
544ce5850adSLoGin         const NAME_ALLOCATED = (1 << 1);
545ce5850adSLoGin         /// Irq domain is an IPI domain with virq per cpu
546ce5850adSLoGin         const IPI_PER_CPU = (1 << 2);
547ce5850adSLoGin         /// Irq domain is an IPI domain with single virq
548ce5850adSLoGin         const IPI_SINGLE = (1 << 3);
549ce5850adSLoGin         /// Irq domain implements MSIs
550ce5850adSLoGin         const MSI = (1 << 4);
551ce5850adSLoGin         /// Irq domain implements MSI remapping
552ce5850adSLoGin         const MSI_REMAP = (1 << 5);
553ce5850adSLoGin         /// Quirk to handle MSI implementations which do not provide masking
554ce5850adSLoGin         const MSI_NOMASK_QUIRK = (1 << 6);
555ce5850adSLoGin         /// Irq domain doesn't translate anything
556ce5850adSLoGin         const NO_MAP = (1 << 7);
557ce5850adSLoGin         /// Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved
558ce5850adSLoGin         /// for implementation specific purposes and ignored by the core code
559ce5850adSLoGin         const NONCORE = (1 << 16);
560ce5850adSLoGin     }
561ce5850adSLoGin }
562ce5850adSLoGin 
563ce5850adSLoGin /// 如果多个域有相同的设备节点,但服务于不同的目的(例如,一个域用于PCI/MSI,另一个用于有线IRQs),
564ce5850adSLoGin /// 它们可以使用特定于总线的token进行区分。预计大多数域只会携带`DomainBusAny`。
565ce5850adSLoGin ///
566ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#78
567ce5850adSLoGin #[allow(dead_code)]
568ce5850adSLoGin #[derive(Debug, Clone, Copy, PartialEq, Eq)]
569ce5850adSLoGin pub enum IrqDomainBusToken {
570ce5850adSLoGin     Any = 0,
571ce5850adSLoGin     Wired,
572ce5850adSLoGin     GenericMsi,
573ce5850adSLoGin     PciMsi,
574ce5850adSLoGin     PlatformMsi,
575ce5850adSLoGin     Nexus,
576ce5850adSLoGin     Ipi,
577ce5850adSLoGin     FslMcMsi,
578ce5850adSLoGin     TiSciIntaMsi,
579ce5850adSLoGin     Wakeup,
580ce5850adSLoGin     VmdMsi,
581ce5850adSLoGin }
582ce5850adSLoGin 
583ce5850adSLoGin /// IrqDomain的操作方法
584ce5850adSLoGin ///
585ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#107
5863bc96fa4SLoGin pub trait IrqDomainOps: Debug + Send + Sync {
587ce5850adSLoGin     /// 匹配一个中断控制器设备节点到一个主机。
588ce5850adSLoGin     fn match_node(
589ce5850adSLoGin         &self,
590*338f6903SLoGin         _irq_domain: &Arc<IrqDomain>,
591*338f6903SLoGin         _device_node: &Arc<DeviceNode>,
592*338f6903SLoGin         _bus_token: IrqDomainBusToken,
593*338f6903SLoGin     ) -> bool {
594*338f6903SLoGin         false
595*338f6903SLoGin     }
596ce5850adSLoGin 
597ce5850adSLoGin     /// 创建或更新一个虚拟中断号与一个硬件中断号之间的映射。
598ce5850adSLoGin     /// 对于给定的映射,这只会被调用一次。
599e2841179SLoGin     ///
600e2841179SLoGin     /// 如果没有实现这个方法,那么就会返回`ENOSYS`
601ce5850adSLoGin     fn map(
602ce5850adSLoGin         &self,
603e2841179SLoGin         _irq_domain: &Arc<IrqDomain>,
604e2841179SLoGin         _hwirq: HardwareIrqNumber,
605e2841179SLoGin         _virq: IrqNumber,
606e2841179SLoGin     ) -> Result<(), SystemError> {
607e2841179SLoGin         Err(SystemError::ENOSYS)
608e2841179SLoGin     }
609ce5850adSLoGin 
610ce5850adSLoGin     /// 删除一个虚拟中断号与一个硬件中断号之间的映射。
611ce5850adSLoGin     fn unmap(&self, irq_domain: &Arc<IrqDomain>, virq: IrqNumber);
612e2841179SLoGin 
613e2841179SLoGin     fn activate(
614e2841179SLoGin         &self,
615e2841179SLoGin         _domain: &Arc<IrqDomain>,
616e2841179SLoGin         _irq_data: &Arc<IrqData>,
617e2841179SLoGin         _reserve: bool,
618e2841179SLoGin     ) -> Result<(), SystemError> {
619e2841179SLoGin         Err(SystemError::ENOSYS)
620e2841179SLoGin     }
621e2841179SLoGin 
622e2841179SLoGin     fn deactivate(&self, _domain: &Arc<IrqDomain>, _irq_data: &Arc<IrqData>) {}
623ce5850adSLoGin }
624ce5850adSLoGin 
625ce5850adSLoGin #[allow(dead_code)]
626ce5850adSLoGin #[derive(Debug)]
627ce5850adSLoGin pub struct IrqDomainChipGeneric {
628ce5850adSLoGin     inner: SpinLock<InnerIrqDomainChipGeneric>,
629ce5850adSLoGin }
630ce5850adSLoGin 
631ce5850adSLoGin #[allow(dead_code)]
632ce5850adSLoGin #[derive(Debug)]
633ce5850adSLoGin struct InnerIrqDomainChipGeneric {
634ce5850adSLoGin     irqs_per_chip: u32,
635ce5850adSLoGin     flags_to_clear: IrqGcFlags,
636ce5850adSLoGin     flags_to_set: IrqGcFlags,
637ce5850adSLoGin     gc_flags: IrqGcFlags,
638ce5850adSLoGin     gc: Vec<Arc<IrqChipGeneric>>,
639ce5850adSLoGin }
640