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