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;
92eab6dd7S曾俊 use log::{info, warn};
10ce5850adSLoGin use system_error::SystemError;
11ce5850adSLoGin
12ce5850adSLoGin use crate::{
13ce5850adSLoGin driver::{base::device::Device, open_firmware::device_node::DeviceNode},
14e2841179SLoGin exception::{irqdata::IrqLineStatus, irqdesc::irq_desc_manager, manage::irq_manager},
15f049d1afSLoGin libs::{
16f049d1afSLoGin rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
17f049d1afSLoGin spinlock::SpinLock,
18f049d1afSLoGin },
19ce5850adSLoGin };
20ce5850adSLoGin
21ce5850adSLoGin use super::{
22338f6903SLoGin dummychip::no_irq_chip,
23338f6903SLoGin irqchip::{IrqChip, IrqChipData, IrqChipGeneric, IrqGcFlags},
24338f6903SLoGin irqdata::{IrqData, IrqHandlerData},
25f049d1afSLoGin irqdesc::{IrqDesc, IrqFlowHandler},
26ce5850adSLoGin HardwareIrqNumber, IrqNumber,
27ce5850adSLoGin };
28ce5850adSLoGin
29e2841179SLoGin static mut IRQ_DOMAIN_MANAGER: Option<Arc<IrqDomainManager>> = None;
30e2841179SLoGin
31e2841179SLoGin /// 获取中断域管理器的引用
32e2841179SLoGin #[inline(always)]
irq_domain_manager() -> &'static Arc<IrqDomainManager>33e2841179SLoGin pub fn irq_domain_manager() -> &'static Arc<IrqDomainManager> {
34e2841179SLoGin unsafe { IRQ_DOMAIN_MANAGER.as_ref().unwrap() }
35e2841179SLoGin }
36e2841179SLoGin
irq_domain_manager_init()37e2841179SLoGin pub(super) fn irq_domain_manager_init() {
38e2841179SLoGin unsafe {
39e2841179SLoGin IRQ_DOMAIN_MANAGER = Some(Arc::new(IrqDomainManager::new()));
40e2841179SLoGin }
41e2841179SLoGin }
42e2841179SLoGin /// 中断域管理器
43e2841179SLoGin pub struct IrqDomainManager {
44e2841179SLoGin domains: SpinLock<Vec<Arc<IrqDomain>>>,
45e2841179SLoGin inner: RwLock<InnerIrqDomainManager>,
46e2841179SLoGin }
47e2841179SLoGin
48e2841179SLoGin impl IrqDomainManager {
new() -> IrqDomainManager49e2841179SLoGin pub fn new() -> IrqDomainManager {
50e2841179SLoGin IrqDomainManager {
51e2841179SLoGin domains: SpinLock::new(Vec::new()),
52e2841179SLoGin inner: RwLock::new(InnerIrqDomainManager {
53e2841179SLoGin default_domain: None,
54e2841179SLoGin }),
55e2841179SLoGin }
56e2841179SLoGin }
57e2841179SLoGin
58338f6903SLoGin /// 创建一个新的线性映射的irqdomain, 并将其添加到irqdomain管理器中
59338f6903SLoGin ///
60338f6903SLoGin /// 创建的irqdomain,中断号是线性的,即从0开始,依次递增
61338f6903SLoGin ///
62338f6903SLoGin /// ## 参数
63338f6903SLoGin ///
64338f6903SLoGin /// - `name` - 中断域的名字
65338f6903SLoGin /// - `ops` - 中断域的操作
66338f6903SLoGin /// - `irq_size` - 中断号的数量
67338f6903SLoGin #[allow(dead_code)]
create_and_add_linear( &self, name: String, ops: &'static dyn IrqDomainOps, irq_size: u32, ) -> Option<Arc<IrqDomain>>68338f6903SLoGin pub fn create_and_add_linear(
69338f6903SLoGin &self,
70338f6903SLoGin name: String,
71338f6903SLoGin ops: &'static dyn IrqDomainOps,
72338f6903SLoGin irq_size: u32,
73338f6903SLoGin ) -> Option<Arc<IrqDomain>> {
74338f6903SLoGin self.create_and_add(
75338f6903SLoGin name,
76338f6903SLoGin ops,
77338f6903SLoGin IrqNumber::new(0),
78338f6903SLoGin HardwareIrqNumber::new(0),
79338f6903SLoGin irq_size,
80338f6903SLoGin )
81338f6903SLoGin }
82338f6903SLoGin
83e2841179SLoGin /// 创建一个新的irqdomain, 并将其添加到irqdomain管理器中
84e2841179SLoGin ///
85e2841179SLoGin /// ## 参数
86e2841179SLoGin ///
87e2841179SLoGin /// - `name` - 中断域的名字
88e2841179SLoGin /// - `ops` - 中断域的操作
89e2841179SLoGin /// - `first_irq` - 起始软件中断号
90e2841179SLoGin /// - `first_hwirq` - 起始硬件中断号
91e2841179SLoGin /// - `irq_size` - 中断号的数量
92e2841179SLoGin ///
93e2841179SLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdomain.c?fi=__irq_domain_add#139
create_and_add( &self, name: String, ops: &'static dyn IrqDomainOps, first_irq: IrqNumber, first_hwirq: HardwareIrqNumber, irq_size: u32, ) -> Option<Arc<IrqDomain>>94e2841179SLoGin pub fn create_and_add(
95e2841179SLoGin &self,
96e2841179SLoGin name: String,
97e2841179SLoGin ops: &'static dyn IrqDomainOps,
98e2841179SLoGin first_irq: IrqNumber,
99e2841179SLoGin first_hwirq: HardwareIrqNumber,
100e2841179SLoGin irq_size: u32,
101e2841179SLoGin ) -> Option<Arc<IrqDomain>> {
102e2841179SLoGin let domain = IrqDomain::new(
103e2841179SLoGin None,
104e2841179SLoGin Some(name),
105e2841179SLoGin ops,
106e2841179SLoGin IrqDomainFlags::NAME_ALLOCATED,
107e2841179SLoGin IrqDomainBusToken::Any,
108e2841179SLoGin first_irq + irq_size,
109e2841179SLoGin first_hwirq + irq_size,
110e2841179SLoGin )?;
111e2841179SLoGin
112e2841179SLoGin self.add_domain(domain.clone());
113e2841179SLoGin
114e2841179SLoGin return Some(domain);
115e2841179SLoGin }
116e2841179SLoGin
add_domain(&self, domain: Arc<IrqDomain>)117e2841179SLoGin fn add_domain(&self, domain: Arc<IrqDomain>) {
118e2841179SLoGin self.domains.lock_irqsave().push(domain);
119e2841179SLoGin }
120e2841179SLoGin
121e2841179SLoGin #[allow(dead_code)]
remove_domain(&self, domain: &Arc<IrqDomain>)122e2841179SLoGin pub fn remove_domain(&self, domain: &Arc<IrqDomain>) {
123e2841179SLoGin let mut domains = self.domains.lock_irqsave();
124e2841179SLoGin let index = domains
125e2841179SLoGin .iter()
126e2841179SLoGin .position(|x| Arc::ptr_eq(x, domain))
127e2841179SLoGin .expect("domain not found");
128e2841179SLoGin domains.remove(index);
129e2841179SLoGin }
130e2841179SLoGin
131e2841179SLoGin /// 获取默认的中断域
132e2841179SLoGin #[allow(dead_code)]
default_domain(&self) -> Option<Arc<IrqDomain>>133e2841179SLoGin pub fn default_domain(&self) -> Option<Arc<IrqDomain>> {
134e2841179SLoGin self.inner.read().default_domain.clone()
135e2841179SLoGin }
136e2841179SLoGin
137e2841179SLoGin /// 设置默认的中断域
138e2841179SLoGin ///
139e2841179SLoGin /// 在创建IRQ映射的时候,如果没有指定中断域,就会使用默认的中断域
set_default_domain(&self, domain: Arc<IrqDomain>)140e2841179SLoGin pub fn set_default_domain(&self, domain: Arc<IrqDomain>) {
141e2841179SLoGin self.inner.write_irqsave().default_domain = Some(domain);
142e2841179SLoGin }
143e2841179SLoGin
144e2841179SLoGin /// 将指定范围的硬件中断号与软件中断号一一对应的关联起来
145e2841179SLoGin ///
146e2841179SLoGin /// ## 参数
147e2841179SLoGin ///
148e2841179SLoGin /// - `domain` - 中断域
149e2841179SLoGin /// - `first_irq` - 起始软件中断号
150e2841179SLoGin /// - `first_hwirq` - 起始硬件中断号
151e2841179SLoGin /// - `count` - 数量
domain_associate_many( &self, domain: &Arc<IrqDomain>, first_irq: IrqNumber, first_hwirq: HardwareIrqNumber, count: u32, )152e2841179SLoGin pub fn domain_associate_many(
153e2841179SLoGin &self,
154e2841179SLoGin domain: &Arc<IrqDomain>,
155e2841179SLoGin first_irq: IrqNumber,
156e2841179SLoGin first_hwirq: HardwareIrqNumber,
157e2841179SLoGin count: u32,
158e2841179SLoGin ) {
159e2841179SLoGin for i in 0..count {
160e2841179SLoGin if let Err(e) = self.domain_associate(domain, first_irq + i, first_hwirq + i) {
1612eab6dd7S曾俊 warn!("domain associate failed: {:?}, domain '{:?}' didn't like hwirq {} to virq {} mapping.", e, domain.name(), (first_hwirq + i).data(), (first_irq + i).data());
162e2841179SLoGin }
163e2841179SLoGin }
164e2841179SLoGin }
165e2841179SLoGin
166e2841179SLoGin /// 将一个硬件中断号与一个软件中断号关联起来
167e2841179SLoGin ///
168e2841179SLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdomain.c#562
domain_associate( &self, domain: &Arc<IrqDomain>, irq: IrqNumber, hwirq: HardwareIrqNumber, ) -> Result<(), SystemError>169e2841179SLoGin pub fn domain_associate(
170e2841179SLoGin &self,
171e2841179SLoGin domain: &Arc<IrqDomain>,
172e2841179SLoGin irq: IrqNumber,
173e2841179SLoGin hwirq: HardwareIrqNumber,
174e2841179SLoGin ) -> Result<(), SystemError> {
175e2841179SLoGin if hwirq >= domain.revmap.read_irqsave().hwirq_max {
1762eab6dd7S曾俊 warn!(
177e2841179SLoGin "hwirq {} is out of range for domain {:?}",
178e2841179SLoGin hwirq.data(),
179e2841179SLoGin domain.name()
180e2841179SLoGin );
181e2841179SLoGin return Err(SystemError::EINVAL);
182e2841179SLoGin }
183e2841179SLoGin let irq_data = irq_desc_manager()
184e2841179SLoGin .lookup(irq)
185e2841179SLoGin .ok_or_else(|| {
1862eab6dd7S曾俊 warn!("irq_desc not found for irq {}", irq.data());
187e2841179SLoGin SystemError::EINVAL
188e2841179SLoGin })?
189e2841179SLoGin .irq_data();
190e2841179SLoGin if irq_data.domain().is_some() {
1912eab6dd7S曾俊 warn!(
192e2841179SLoGin "irq {} is already associated with domain {:?}",
193e2841179SLoGin irq.data(),
194e2841179SLoGin irq_data.domain().unwrap().name()
195e2841179SLoGin );
196e2841179SLoGin return Err(SystemError::EINVAL);
197e2841179SLoGin }
198e2841179SLoGin
199e2841179SLoGin let mut irq_data_guard = irq_data.inner();
200e2841179SLoGin irq_data_guard.set_hwirq(hwirq);
201e2841179SLoGin irq_data_guard.set_domain(Some(domain.clone()));
202e2841179SLoGin drop(irq_data_guard);
203b5b571e0SLoGin let r = domain.ops.map(domain, hwirq, irq);
204e2841179SLoGin if let Err(e) = r {
205e2841179SLoGin if e != SystemError::ENOSYS {
206e2841179SLoGin if e != SystemError::EPERM {
2072eab6dd7S曾俊 info!("domain associate failed: {:?}, domain '{:?}' didn't like hwirq {} to virq {} mapping.", e, domain.name(), hwirq.data(), irq.data());
208e2841179SLoGin }
209e2841179SLoGin let mut irq_data_guard = irq_data.inner();
210e2841179SLoGin irq_data_guard.set_domain(None);
211e2841179SLoGin irq_data_guard.set_hwirq(HardwareIrqNumber::new(0));
212e2841179SLoGin return Err(e);
213e2841179SLoGin }
214e2841179SLoGin }
215e2841179SLoGin
216e2841179SLoGin if domain.name().is_none() {
217e2841179SLoGin let chip = irq_data.chip_info_read_irqsave().chip();
218e2841179SLoGin domain.set_name(chip.name().to_string());
219e2841179SLoGin }
220e2841179SLoGin
221b5b571e0SLoGin self.irq_domain_set_mapping(domain, hwirq, irq_data);
222e2841179SLoGin
223e2841179SLoGin irq_manager().irq_clear_status_flags(irq, IrqLineStatus::IRQ_NOREQUEST)?;
224e2841179SLoGin
225e2841179SLoGin return Ok(());
226e2841179SLoGin }
227e2841179SLoGin
irq_domain_set_mapping( &self, domain: &Arc<IrqDomain>, hwirq: HardwareIrqNumber, irq_data: Arc<IrqData>, )228e2841179SLoGin fn irq_domain_set_mapping(
229e2841179SLoGin &self,
230e2841179SLoGin domain: &Arc<IrqDomain>,
231e2841179SLoGin hwirq: HardwareIrqNumber,
232e2841179SLoGin irq_data: Arc<IrqData>,
233e2841179SLoGin ) {
234e2841179SLoGin if domain.no_map() {
235e2841179SLoGin return;
236e2841179SLoGin }
237e2841179SLoGin
238e2841179SLoGin domain.revmap.write_irqsave().insert(hwirq, irq_data);
239e2841179SLoGin }
240e2841179SLoGin /// 递归调用 domain_ops->activate 以激活中断
241e2841179SLoGin ///
242e2841179SLoGin /// ## 参数
243e2841179SLoGin ///
244e2841179SLoGin /// - irq_data: 与中断关联的最外层 irq_data
245e2841179SLoGin /// - reserve: 如果为true,则仅预留一个中断向量,而不是分配一个
246e2841179SLoGin ///
247e2841179SLoGin /// 这是调用 domain_ops->activate 以编程中断控制器的第二步,以便中断实际上可以被传递。
activate_irq(&self, irq_data: &Arc<IrqData>, reserve: bool) -> Result<(), SystemError>248e2841179SLoGin pub fn activate_irq(&self, irq_data: &Arc<IrqData>, reserve: bool) -> Result<(), SystemError> {
249e2841179SLoGin let mut r = Ok(());
2502eab6dd7S曾俊 // debug!(
2510102d69fSLoGin // "activate_irq: irq_data.common_data().status().is_activated()={}",
2520102d69fSLoGin // irq_data.common_data().status().is_activated()
2530102d69fSLoGin // );
254e2841179SLoGin if !irq_data.common_data().status().is_activated() {
255e2841179SLoGin r = self.do_activate_irq(Some(irq_data.clone()), reserve);
256e2841179SLoGin }
257e2841179SLoGin
258b5b571e0SLoGin if r.is_err() {
259e2841179SLoGin irq_data.common_data().status().set_activated();
260e2841179SLoGin }
261e2841179SLoGin
262e2841179SLoGin return r;
263e2841179SLoGin }
264e2841179SLoGin
265e2841179SLoGin #[inline(never)]
do_activate_irq( &self, irq_data: Option<Arc<IrqData>>, reserve: bool, ) -> Result<(), SystemError>266e2841179SLoGin fn do_activate_irq(
267e2841179SLoGin &self,
268e2841179SLoGin irq_data: Option<Arc<IrqData>>,
269e2841179SLoGin reserve: bool,
270e2841179SLoGin ) -> Result<(), SystemError> {
271e2841179SLoGin let mut r = Ok(());
272e2841179SLoGin
273b5b571e0SLoGin if let Some(irq_data) = irq_data {
2742eab6dd7S曾俊 // debug!("do_activate_irq: irq_data={:?}", irq_data);
275b5b571e0SLoGin if let Some(domain) = irq_data.domain() {
2762eab6dd7S曾俊 // debug!("do_activate_irq: domain={:?}", domain.name());
277b5b571e0SLoGin let parent_data = irq_data.parent_data().and_then(|x| x.upgrade());
278e2841179SLoGin if let Some(parent_data) = parent_data.clone() {
279e2841179SLoGin r = self.do_activate_irq(Some(parent_data), reserve);
280e2841179SLoGin }
281e2841179SLoGin
282e2841179SLoGin if r.is_err() {
283e2841179SLoGin let tmpr = domain.ops.activate(&domain, &irq_data, reserve);
284e2841179SLoGin if let Err(e) = tmpr {
285e2841179SLoGin if e != SystemError::ENOSYS && parent_data.is_some() {
286e2841179SLoGin self.do_deactivate_irq(parent_data);
287e2841179SLoGin }
288e2841179SLoGin }
289e2841179SLoGin }
290e2841179SLoGin }
291b5b571e0SLoGin }
292e2841179SLoGin
293e2841179SLoGin return r;
294e2841179SLoGin }
295b5b571e0SLoGin #[allow(clippy::only_used_in_recursion)]
do_deactivate_irq(&self, irq_data: Option<Arc<IrqData>>)296e2841179SLoGin fn do_deactivate_irq(&self, irq_data: Option<Arc<IrqData>>) {
297e2841179SLoGin if let Some(irq_data) = irq_data {
298e2841179SLoGin if let Some(domain) = irq_data.domain() {
299e2841179SLoGin domain.ops.deactivate(&domain, &irq_data);
300b5b571e0SLoGin let pp = irq_data.parent_data().and_then(|x| x.upgrade());
301e2841179SLoGin
302e2841179SLoGin if pp.is_some() {
303e2841179SLoGin self.do_deactivate_irq(pp);
304e2841179SLoGin }
305e2841179SLoGin }
306e2841179SLoGin }
307e2841179SLoGin }
308338f6903SLoGin
309338f6903SLoGin /// `irq_domain_set_info` - 在 @domain 中为 @virq 设置完整的数据
310338f6903SLoGin ///
311338f6903SLoGin /// ## 参数
312338f6903SLoGin ///
313338f6903SLoGin /// - `domain`: 要匹配的中断域
314338f6903SLoGin /// - `virq`: IRQ号
315338f6903SLoGin /// - `hwirq`: 硬件中断号
316338f6903SLoGin /// - `chip`: 相关的中断芯片
317338f6903SLoGin /// - `chip_data`: 相关的中断芯片数据
318338f6903SLoGin /// - `handler`: 中断流处理器
319338f6903SLoGin /// - `handler_data`: 中断流处理程序数据
320338f6903SLoGin /// - `handler_name`: 中断处理程序名称
321b5b571e0SLoGin #[allow(clippy::too_many_arguments)]
domain_set_info( &self, domain: &Arc<IrqDomain>, virq: IrqNumber, hwirq: HardwareIrqNumber, chip: Arc<dyn IrqChip>, chip_data: Option<Arc<dyn IrqChipData>>, flow_handler: &'static dyn IrqFlowHandler, handler_data: Option<Arc<dyn IrqHandlerData>>, handler_name: Option<String>, )322338f6903SLoGin pub fn domain_set_info(
323338f6903SLoGin &self,
324338f6903SLoGin domain: &Arc<IrqDomain>,
325338f6903SLoGin virq: IrqNumber,
326338f6903SLoGin hwirq: HardwareIrqNumber,
327338f6903SLoGin chip: Arc<dyn IrqChip>,
328338f6903SLoGin chip_data: Option<Arc<dyn IrqChipData>>,
329338f6903SLoGin flow_handler: &'static dyn IrqFlowHandler,
330338f6903SLoGin handler_data: Option<Arc<dyn IrqHandlerData>>,
331338f6903SLoGin handler_name: Option<String>,
332338f6903SLoGin ) {
333338f6903SLoGin let r = self.domain_set_hwirq_and_chip(domain, virq, hwirq, Some(chip), chip_data);
334338f6903SLoGin if r.is_err() {
335338f6903SLoGin return;
336338f6903SLoGin }
337338f6903SLoGin irq_manager().__irq_set_handler(virq, flow_handler, false, handler_name);
338338f6903SLoGin irq_manager().irq_set_handler_data(virq, handler_data).ok();
339338f6903SLoGin }
340338f6903SLoGin
341338f6903SLoGin /// `domain_set_hwirq_and_chip` - 在 @domain 中为 @virq 设置 hwirq 和 irqchip
342338f6903SLoGin ///
343338f6903SLoGin /// ## 参数
344338f6903SLoGin ///
345338f6903SLoGin /// - `domain`: 要匹配的中断域
346338f6903SLoGin /// - `virq`: IRQ号
347338f6903SLoGin /// - `hwirq`: hwirq号
348338f6903SLoGin /// - `chip`: 相关的中断芯片
349338f6903SLoGin /// - `chip_data`: 相关的芯片数据
domain_set_hwirq_and_chip( &self, domain: &Arc<IrqDomain>, virq: IrqNumber, hwirq: HardwareIrqNumber, chip: Option<Arc<dyn IrqChip>>, chip_data: Option<Arc<dyn IrqChipData>>, ) -> Result<(), SystemError>350338f6903SLoGin pub fn domain_set_hwirq_and_chip(
351338f6903SLoGin &self,
352338f6903SLoGin domain: &Arc<IrqDomain>,
353338f6903SLoGin virq: IrqNumber,
354338f6903SLoGin hwirq: HardwareIrqNumber,
355338f6903SLoGin chip: Option<Arc<dyn IrqChip>>,
356338f6903SLoGin chip_data: Option<Arc<dyn IrqChipData>>,
357338f6903SLoGin ) -> Result<(), SystemError> {
358338f6903SLoGin let irq_data: Arc<IrqData> = self
359338f6903SLoGin .domain_get_irq_data(domain, virq)
360338f6903SLoGin .ok_or(SystemError::ENOENT)?;
361338f6903SLoGin let mut inner = irq_data.inner();
362338f6903SLoGin let mut chip_info = irq_data.chip_info_write_irqsave();
363338f6903SLoGin
364338f6903SLoGin inner.set_hwirq(hwirq);
365338f6903SLoGin if let Some(chip) = chip {
366338f6903SLoGin chip_info.set_chip(Some(chip));
367338f6903SLoGin } else {
368338f6903SLoGin chip_info.set_chip(Some(no_irq_chip()));
369338f6903SLoGin };
370338f6903SLoGin
371338f6903SLoGin chip_info.set_chip_data(chip_data);
372338f6903SLoGin
373338f6903SLoGin return Ok(());
374338f6903SLoGin }
375338f6903SLoGin
376338f6903SLoGin /// `irq_domain_get_irq_data` - 获取与 @virq 和 @domain 关联的 irq_data
377338f6903SLoGin ///
378338f6903SLoGin /// ## 参数
379338f6903SLoGin ///
380338f6903SLoGin /// - `domain`: 要匹配的域
381338f6903SLoGin /// - `virq`: 要获取 irq_data 的IRQ号
domain_get_irq_data( &self, domain: &Arc<IrqDomain>, virq: IrqNumber, ) -> Option<Arc<IrqData>>382338f6903SLoGin pub fn domain_get_irq_data(
383338f6903SLoGin &self,
384338f6903SLoGin domain: &Arc<IrqDomain>,
385338f6903SLoGin virq: IrqNumber,
386338f6903SLoGin ) -> Option<Arc<IrqData>> {
387338f6903SLoGin let desc = irq_desc_manager().lookup(virq)?;
388338f6903SLoGin let mut irq_data = Some(desc.irq_data());
389338f6903SLoGin
390338f6903SLoGin while irq_data.is_some() {
391338f6903SLoGin let dt = irq_data.unwrap();
392338f6903SLoGin if dt.domain().is_some() && Arc::ptr_eq(dt.domain().as_ref().unwrap(), domain) {
393338f6903SLoGin return Some(dt);
394338f6903SLoGin }
395b5b571e0SLoGin irq_data = dt.parent_data().and_then(|x| x.upgrade());
396338f6903SLoGin }
397338f6903SLoGin
398338f6903SLoGin return None;
399338f6903SLoGin }
400f049d1afSLoGin
401f049d1afSLoGin /// `resolve_irq_mapping` - 从硬件中断号找到中断号。
402f049d1afSLoGin ///
403f049d1afSLoGin /// ## 参数
404f049d1afSLoGin ///
405f049d1afSLoGin /// - `domain`: 拥有此硬件中断的域
406f049d1afSLoGin /// - `hwirq`: 该域空间中的硬件中断号
407f049d1afSLoGin /// - `irq`: 如果需要,可选的指针以返回Linux中断
408f049d1afSLoGin ///
409f049d1afSLoGin /// ## 返回
410f049d1afSLoGin ///
411f049d1afSLoGin /// 返回一个元组,包含中断描述符和中断号
resolve_irq_mapping( &self, mut domain: Option<Arc<IrqDomain>>, hwirq: HardwareIrqNumber, ) -> Result<(Arc<IrqDesc>, IrqNumber), SystemError>412f049d1afSLoGin pub fn resolve_irq_mapping(
413f049d1afSLoGin &self,
414f049d1afSLoGin mut domain: Option<Arc<IrqDomain>>,
415f049d1afSLoGin hwirq: HardwareIrqNumber,
416f049d1afSLoGin ) -> Result<(Arc<IrqDesc>, IrqNumber), SystemError> {
417f049d1afSLoGin if domain.is_none() {
418f049d1afSLoGin domain = Some(self.default_domain().ok_or(SystemError::EINVAL)?);
419f049d1afSLoGin }
420f049d1afSLoGin
421f049d1afSLoGin let domain = domain.unwrap();
422f049d1afSLoGin
423f049d1afSLoGin if domain.no_map() {
424f049d1afSLoGin if hwirq < domain.revmap_read_irqsave().hwirq_max {
425f049d1afSLoGin let irq_desc = irq_desc_manager()
426f049d1afSLoGin .lookup(IrqNumber::new(hwirq.data()))
427f049d1afSLoGin .ok_or(SystemError::EINVAL)?;
428f049d1afSLoGin if irq_desc.irq_data().hardware_irq() == hwirq {
429f049d1afSLoGin let irq = irq_desc.irq_data().irq();
430f049d1afSLoGin return Ok((irq_desc, irq));
431f049d1afSLoGin }
432f049d1afSLoGin }
433f049d1afSLoGin
434f049d1afSLoGin return Err(SystemError::EINVAL);
435f049d1afSLoGin }
436f049d1afSLoGin
437f049d1afSLoGin let revmap = domain.revmap_read_irqsave();
438f049d1afSLoGin let irq_data = revmap.lookup(hwirq).ok_or(SystemError::EINVAL)?;
439f049d1afSLoGin let irq_desc = irq_data.irq_desc().unwrap();
440f049d1afSLoGin return Ok((irq_desc, irq_data.irq()));
441f049d1afSLoGin }
442e2841179SLoGin }
443e2841179SLoGin
444e2841179SLoGin struct InnerIrqDomainManager {
445e2841179SLoGin default_domain: Option<Arc<IrqDomain>>,
446e2841179SLoGin }
447e2841179SLoGin
448ce5850adSLoGin /// 中断域
449ce5850adSLoGin ///
450ce5850adSLoGin /// 用于把硬件中断号翻译为软件中断号的映射的对象
451ce5850adSLoGin ///
452ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#164
453ce5850adSLoGin #[allow(dead_code)]
454ce5850adSLoGin #[derive(Debug)]
455ce5850adSLoGin pub struct IrqDomain {
456ce5850adSLoGin /// 中断域的名字 (二选一)
457ce5850adSLoGin name: Option<&'static str>,
458e2841179SLoGin allocated_name: SpinLock<Option<String>>,
459ce5850adSLoGin /// 中断域的操作
460ce5850adSLoGin ops: &'static dyn IrqDomainOps,
461ce5850adSLoGin inner: SpinLock<InnerIrqDomain>,
462ce5850adSLoGin /// 中断号反向映射
463ce5850adSLoGin revmap: RwLock<IrqDomainRevMap>,
464ce5850adSLoGin }
465ce5850adSLoGin
466ce5850adSLoGin #[allow(dead_code)]
467ce5850adSLoGin #[derive(Debug)]
468ce5850adSLoGin struct InnerIrqDomain {
469338f6903SLoGin /// this field not touched by the core code
470338f6903SLoGin host_data: Option<Arc<dyn IrqChipData>>,
471ce5850adSLoGin /// host per irq_domain flags
472ce5850adSLoGin flags: IrqDomainFlags,
473ce5850adSLoGin /// The number of mapped interrupts
474ce5850adSLoGin mapcount: u32,
475ce5850adSLoGin bus_token: IrqDomainBusToken,
476ce5850adSLoGin /// 指向 generic chip 列表的指针。
477ce5850adSLoGin /// 有一个辅助函数用于为中断控制器驱动程序设置一个或
478ce5850adSLoGin /// 多个 generic chip,该函数使用此指针并依赖于 generic chip 库。
479ce5850adSLoGin generic_chip: Option<Arc<IrqDomainChipGeneric>>,
480ce5850adSLoGin /// Pointer to a device that the domain represent, and that will be
481ce5850adSLoGin /// used for power management purposes.
482ce5850adSLoGin device: Option<Arc<dyn Device>>,
483ce5850adSLoGin /// Pointer to parent irq_domain to support hierarchy irq_domains
484ce5850adSLoGin parent: Option<Weak<IrqDomain>>,
485ce5850adSLoGin }
486ce5850adSLoGin
487ce5850adSLoGin impl IrqDomain {
488ce5850adSLoGin #[allow(dead_code)]
new( name: Option<&'static str>, allocated_name: Option<String>, ops: &'static dyn IrqDomainOps, flags: IrqDomainFlags, bus_token: IrqDomainBusToken, irq_max: IrqNumber, hwirq_max: HardwareIrqNumber, ) -> Option<Arc<Self>>489ce5850adSLoGin pub fn new(
490ce5850adSLoGin name: Option<&'static str>,
491ce5850adSLoGin allocated_name: Option<String>,
492ce5850adSLoGin ops: &'static dyn IrqDomainOps,
493ce5850adSLoGin flags: IrqDomainFlags,
494ce5850adSLoGin bus_token: IrqDomainBusToken,
495e2841179SLoGin irq_max: IrqNumber,
496e2841179SLoGin hwirq_max: HardwareIrqNumber,
497ce5850adSLoGin ) -> Option<Arc<Self>> {
498ce5850adSLoGin if name.is_none() && allocated_name.is_none() {
499ce5850adSLoGin return None;
500ce5850adSLoGin }
501ce5850adSLoGin
502ce5850adSLoGin let x = IrqDomain {
503ce5850adSLoGin name,
504e2841179SLoGin allocated_name: SpinLock::new(allocated_name),
505ce5850adSLoGin ops,
506ce5850adSLoGin inner: SpinLock::new(InnerIrqDomain {
507338f6903SLoGin host_data: None,
508ce5850adSLoGin flags,
509ce5850adSLoGin mapcount: 0,
510ce5850adSLoGin bus_token,
511ce5850adSLoGin generic_chip: None,
512ce5850adSLoGin device: None,
513ce5850adSLoGin parent: None,
514ce5850adSLoGin }),
515ce5850adSLoGin revmap: RwLock::new(IrqDomainRevMap {
516ce5850adSLoGin map: HashMap::new(),
517e2841179SLoGin hwirq_max,
518e2841179SLoGin irq_max,
519ce5850adSLoGin }),
520ce5850adSLoGin };
521ce5850adSLoGin
522ce5850adSLoGin return Some(Arc::new(x));
523ce5850adSLoGin }
524e2841179SLoGin
525e2841179SLoGin /// 中断域是否不对中断号进行转换
no_map(&self) -> bool526e2841179SLoGin pub fn no_map(&self) -> bool {
527e2841179SLoGin self.inner
528e2841179SLoGin .lock_irqsave()
529e2841179SLoGin .flags
530e2841179SLoGin .contains(IrqDomainFlags::NO_MAP)
531e2841179SLoGin }
532e2841179SLoGin
533e2841179SLoGin #[allow(dead_code)]
revmap_read_irqsave(&self) -> RwLockReadGuard<IrqDomainRevMap>534f049d1afSLoGin fn revmap_read_irqsave(&self) -> RwLockReadGuard<IrqDomainRevMap> {
535f049d1afSLoGin self.revmap.read_irqsave()
536f049d1afSLoGin }
537f049d1afSLoGin
538f049d1afSLoGin #[allow(dead_code)]
revmap_write_irqsave(&self) -> RwLockWriteGuard<IrqDomainRevMap>539f049d1afSLoGin fn revmap_write_irqsave(&self) -> RwLockWriteGuard<IrqDomainRevMap> {
540f049d1afSLoGin self.revmap.write_irqsave()
541f049d1afSLoGin }
542f049d1afSLoGin
543f049d1afSLoGin #[allow(dead_code)]
set_hwirq_max(&self, hwirq_max: HardwareIrqNumber)544e2841179SLoGin fn set_hwirq_max(&self, hwirq_max: HardwareIrqNumber) {
545f049d1afSLoGin self.revmap_write_irqsave().hwirq_max = hwirq_max;
546e2841179SLoGin }
547e2841179SLoGin
name(&self) -> Option<String>548e2841179SLoGin pub fn name(&self) -> Option<String> {
549e2841179SLoGin if let Some(name) = self.name {
550e2841179SLoGin return Some(name.to_string());
551e2841179SLoGin }
552e2841179SLoGin return self.allocated_name.lock_irqsave().clone();
553e2841179SLoGin }
554e2841179SLoGin
set_name(&self, name: String)555e2841179SLoGin pub fn set_name(&self, name: String) {
556e2841179SLoGin *self.allocated_name.lock_irqsave() = Some(name);
557e2841179SLoGin }
558e2841179SLoGin
559e2841179SLoGin /// The number of mapped interrupts
map_count(&self) -> u32560e2841179SLoGin pub fn map_count(&self) -> u32 {
561f049d1afSLoGin self.revmap_read_irqsave().map.len() as u32
562e2841179SLoGin }
563338f6903SLoGin
host_data(&self) -> Option<Arc<dyn IrqChipData>>564338f6903SLoGin pub fn host_data(&self) -> Option<Arc<dyn IrqChipData>> {
565338f6903SLoGin self.inner.lock_irqsave().host_data.clone()
566338f6903SLoGin }
567338f6903SLoGin
set_host_data(&self, host_data: Option<Arc<dyn IrqChipData>>)568338f6903SLoGin pub fn set_host_data(&self, host_data: Option<Arc<dyn IrqChipData>>) {
569338f6903SLoGin self.inner.lock_irqsave().host_data = host_data;
570338f6903SLoGin }
571ce5850adSLoGin }
572ce5850adSLoGin
573ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#190
574ce5850adSLoGin #[allow(dead_code)]
575ce5850adSLoGin #[derive(Debug)]
576ce5850adSLoGin struct IrqDomainRevMap {
577e2841179SLoGin map: HashMap<HardwareIrqNumber, Arc<IrqData>>,
578ce5850adSLoGin hwirq_max: HardwareIrqNumber,
579e2841179SLoGin irq_max: IrqNumber,
580e2841179SLoGin }
581e2841179SLoGin
582e2841179SLoGin impl IrqDomainRevMap {
insert(&mut self, hwirq: HardwareIrqNumber, irq_data: Arc<IrqData>)583e2841179SLoGin fn insert(&mut self, hwirq: HardwareIrqNumber, irq_data: Arc<IrqData>) {
584e2841179SLoGin self.map.insert(hwirq, irq_data);
585e2841179SLoGin }
586e2841179SLoGin
587e2841179SLoGin #[allow(dead_code)]
remove(&mut self, hwirq: HardwareIrqNumber)588e2841179SLoGin fn remove(&mut self, hwirq: HardwareIrqNumber) {
589e2841179SLoGin self.map.remove(&hwirq);
590e2841179SLoGin }
591e2841179SLoGin
592e2841179SLoGin #[allow(dead_code)]
lookup(&self, hwirq: HardwareIrqNumber) -> Option<Arc<IrqData>>593e2841179SLoGin fn lookup(&self, hwirq: HardwareIrqNumber) -> Option<Arc<IrqData>> {
594e2841179SLoGin self.map.get(&hwirq).cloned()
595e2841179SLoGin }
596ce5850adSLoGin }
597ce5850adSLoGin
598ce5850adSLoGin bitflags! {
599ce5850adSLoGin pub struct IrqDomainFlags: u32 {
600ce5850adSLoGin /// Irq domain is hierarchical
601ce5850adSLoGin const HIERARCHY = (1 << 0);
602ce5850adSLoGin /// Irq domain name was allocated dynamically
603ce5850adSLoGin const NAME_ALLOCATED = (1 << 1);
604ce5850adSLoGin /// Irq domain is an IPI domain with virq per cpu
605ce5850adSLoGin const IPI_PER_CPU = (1 << 2);
606ce5850adSLoGin /// Irq domain is an IPI domain with single virq
607ce5850adSLoGin const IPI_SINGLE = (1 << 3);
608ce5850adSLoGin /// Irq domain implements MSIs
609ce5850adSLoGin const MSI = (1 << 4);
610ce5850adSLoGin /// Irq domain implements MSI remapping
611ce5850adSLoGin const MSI_REMAP = (1 << 5);
612ce5850adSLoGin /// Quirk to handle MSI implementations which do not provide masking
613ce5850adSLoGin const MSI_NOMASK_QUIRK = (1 << 6);
614ce5850adSLoGin /// Irq domain doesn't translate anything
615ce5850adSLoGin const NO_MAP = (1 << 7);
616ce5850adSLoGin /// Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved
617ce5850adSLoGin /// for implementation specific purposes and ignored by the core code
618ce5850adSLoGin const NONCORE = (1 << 16);
619ce5850adSLoGin }
620ce5850adSLoGin }
621ce5850adSLoGin
622ce5850adSLoGin /// 如果多个域有相同的设备节点,但服务于不同的目的(例如,一个域用于PCI/MSI,另一个用于有线IRQs),
623ce5850adSLoGin /// 它们可以使用特定于总线的token进行区分。预计大多数域只会携带`DomainBusAny`。
624ce5850adSLoGin ///
625ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#78
626ce5850adSLoGin #[allow(dead_code)]
627ce5850adSLoGin #[derive(Debug, Clone, Copy, PartialEq, Eq)]
628ce5850adSLoGin pub enum IrqDomainBusToken {
629ce5850adSLoGin Any = 0,
630ce5850adSLoGin Wired,
631ce5850adSLoGin GenericMsi,
632ce5850adSLoGin PciMsi,
633ce5850adSLoGin PlatformMsi,
634ce5850adSLoGin Nexus,
635ce5850adSLoGin Ipi,
636ce5850adSLoGin FslMcMsi,
637ce5850adSLoGin TiSciIntaMsi,
638ce5850adSLoGin Wakeup,
639ce5850adSLoGin VmdMsi,
640ce5850adSLoGin }
641ce5850adSLoGin
642ce5850adSLoGin /// IrqDomain的操作方法
643ce5850adSLoGin ///
644ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#107
6453bc96fa4SLoGin pub trait IrqDomainOps: Debug + Send + Sync {
646ce5850adSLoGin /// 匹配一个中断控制器设备节点到一个主机。
647*bd70d2d1SLoGin #[allow(dead_code)]
match_node( &self, _irq_domain: &Arc<IrqDomain>, _device_node: &Arc<DeviceNode>, _bus_token: IrqDomainBusToken, ) -> bool648ce5850adSLoGin fn match_node(
649ce5850adSLoGin &self,
650338f6903SLoGin _irq_domain: &Arc<IrqDomain>,
651338f6903SLoGin _device_node: &Arc<DeviceNode>,
652338f6903SLoGin _bus_token: IrqDomainBusToken,
653338f6903SLoGin ) -> bool {
654338f6903SLoGin false
655338f6903SLoGin }
656ce5850adSLoGin
657ce5850adSLoGin /// 创建或更新一个虚拟中断号与一个硬件中断号之间的映射。
658ce5850adSLoGin /// 对于给定的映射,这只会被调用一次。
659e2841179SLoGin ///
660e2841179SLoGin /// 如果没有实现这个方法,那么就会返回`ENOSYS`
map( &self, _irq_domain: &Arc<IrqDomain>, _hwirq: HardwareIrqNumber, _virq: IrqNumber, ) -> Result<(), SystemError>661ce5850adSLoGin fn map(
662ce5850adSLoGin &self,
663e2841179SLoGin _irq_domain: &Arc<IrqDomain>,
664e2841179SLoGin _hwirq: HardwareIrqNumber,
665e2841179SLoGin _virq: IrqNumber,
666e2841179SLoGin ) -> Result<(), SystemError> {
667e2841179SLoGin Err(SystemError::ENOSYS)
668e2841179SLoGin }
669ce5850adSLoGin
670ce5850adSLoGin /// 删除一个虚拟中断号与一个硬件中断号之间的映射。
671*bd70d2d1SLoGin #[allow(dead_code)]
unmap(&self, irq_domain: &Arc<IrqDomain>, virq: IrqNumber)672ce5850adSLoGin fn unmap(&self, irq_domain: &Arc<IrqDomain>, virq: IrqNumber);
673e2841179SLoGin
activate( &self, _domain: &Arc<IrqDomain>, _irq_data: &Arc<IrqData>, _reserve: bool, ) -> Result<(), SystemError>674e2841179SLoGin fn activate(
675e2841179SLoGin &self,
676e2841179SLoGin _domain: &Arc<IrqDomain>,
677e2841179SLoGin _irq_data: &Arc<IrqData>,
678e2841179SLoGin _reserve: bool,
679e2841179SLoGin ) -> Result<(), SystemError> {
680e2841179SLoGin Err(SystemError::ENOSYS)
681e2841179SLoGin }
682e2841179SLoGin
deactivate(&self, _domain: &Arc<IrqDomain>, _irq_data: &Arc<IrqData>)683e2841179SLoGin fn deactivate(&self, _domain: &Arc<IrqDomain>, _irq_data: &Arc<IrqData>) {}
684ce5850adSLoGin }
685ce5850adSLoGin
686ce5850adSLoGin #[allow(dead_code)]
687ce5850adSLoGin #[derive(Debug)]
688ce5850adSLoGin pub struct IrqDomainChipGeneric {
689ce5850adSLoGin inner: SpinLock<InnerIrqDomainChipGeneric>,
690ce5850adSLoGin }
691ce5850adSLoGin
692ce5850adSLoGin #[allow(dead_code)]
693ce5850adSLoGin #[derive(Debug)]
694ce5850adSLoGin struct InnerIrqDomainChipGeneric {
695ce5850adSLoGin irqs_per_chip: u32,
696ce5850adSLoGin flags_to_clear: IrqGcFlags,
697ce5850adSLoGin flags_to_set: IrqGcFlags,
698ce5850adSLoGin gc_flags: IrqGcFlags,
699ce5850adSLoGin gc: Vec<Arc<IrqChipGeneric>>,
700ce5850adSLoGin }
701