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