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