1 use alloc::sync::Arc; 2 use hashbrown::HashMap; 3 use log::warn; 4 use system_error::SystemError; 5 use unified_init::macros::unified_init; 6 7 use crate::{ 8 driver::base::device::DeviceId, 9 exception::{ 10 irqdata::IrqHandlerData, 11 irqdesc::{IrqHandler, IrqReturn}, 12 IrqNumber, 13 }, 14 init::initcall::INITCALL_CORE, 15 libs::rwlock::RwLock, 16 }; 17 18 use super::VirtIODevice; 19 20 static mut VIRTIO_IRQ_MANAGER: Option<VirtIOIrqManager> = None; 21 22 #[inline(always)] 23 pub fn virtio_irq_manager() -> &'static VirtIOIrqManager { 24 unsafe { VIRTIO_IRQ_MANAGER.as_ref().unwrap() } 25 } 26 27 pub struct VirtIOIrqManager { 28 map: RwLock<HashMap<Arc<DeviceId>, Arc<dyn VirtIODevice>>>, 29 } 30 31 impl VirtIOIrqManager { 32 fn new() -> Self { 33 VirtIOIrqManager { 34 map: RwLock::new(HashMap::new()), 35 } 36 } 37 38 /// 注册一个新的设备到virtio中断请求(IRQ)映射中。 39 /// 40 /// # 参数 41 /// 42 /// - `device` - 实现了 `VirtIODevice` trait 的设备对象,被封装在 `Arc` 智能指针中。 43 /// 44 /// # 返回值 45 /// 46 /// - 如果设备成功注册,返回 `Ok(())`。 47 /// - 如果设备ID已经存在于映射中,返回 `Err(SystemError::EEXIST)`。 48 pub fn register_device(&self, device: Arc<dyn VirtIODevice>) -> Result<(), SystemError> { 49 let mut map = self.map.write_irqsave(); 50 51 if map.contains_key(device.dev_id()) { 52 return Err(SystemError::EEXIST); 53 } 54 55 map.insert(device.dev_id().clone(), device); 56 57 return Ok(()); 58 } 59 60 /// 取消注册设备 61 /// 62 /// 这个函数会从内部映射中移除指定的设备。设备是通过设备ID来识别的。 63 /// 64 /// # 参数 65 /// 66 /// - `device` - 需要被取消注册的设备,它是一个实现了 `VirtIODevice` trait 的智能指针。 67 #[allow(dead_code)] 68 pub fn unregister_device(&self, dev_id: &Arc<DeviceId>) { 69 let mut map = self.map.write_irqsave(); 70 map.remove(dev_id); 71 } 72 73 /// 查找并返回指定设备ID的设备。 74 /// 75 /// # 参数 76 /// - `dev_id` - 我们要查找的设备的设备ID。 77 /// 78 /// # 返回 79 /// - 如果找到了设备,返回一个包含设备的`Option<Arc<dyn VirtIODevice>>`。 80 /// - 如果没有找到设备,返回`None`。 81 82 pub fn lookup_device(&self, dev_id: &Arc<DeviceId>) -> Option<Arc<dyn VirtIODevice>> { 83 let map = self.map.read_irqsave(); 84 map.get(dev_id).cloned() 85 } 86 } 87 88 #[unified_init(INITCALL_CORE)] 89 fn init_virtio_irq_manager() -> Result<(), SystemError> { 90 let manager = VirtIOIrqManager::new(); 91 unsafe { 92 VIRTIO_IRQ_MANAGER = Some(manager); 93 } 94 return Ok(()); 95 } 96 97 /// `DefaultVirtioIrqHandler` 是一个默认的virtio设备中断处理程序。 98 /// 99 /// 当虚拟设备产生中断时,该处理程序会被调用。 100 /// 101 /// 它首先检查设备ID是否存在,然后尝试查找与设备ID关联的设备。 102 /// 如果找到设备,它会调用设备的 `handle_irq` 方法来处理中断。 103 /// 如果没有找到设备,它会记录一条警告并返回 `IrqReturn::NotHandled`,表示中断未被处理。 104 #[derive(Debug)] 105 pub(super) struct DefaultVirtioIrqHandler; 106 107 impl IrqHandler for DefaultVirtioIrqHandler { 108 fn handle( 109 &self, 110 irq: IrqNumber, 111 _static_data: Option<&dyn IrqHandlerData>, 112 dev_id: Option<Arc<dyn IrqHandlerData>>, 113 ) -> Result<IrqReturn, SystemError> { 114 let dev_id = dev_id.ok_or(SystemError::EINVAL)?; 115 let dev_id = dev_id 116 .arc_any() 117 .downcast::<DeviceId>() 118 .map_err(|_| SystemError::EINVAL)?; 119 120 if let Some(dev) = virtio_irq_manager().lookup_device(&dev_id) { 121 return dev.handle_irq(irq); 122 } else { 123 // 未绑定具体设备,因此无法处理中断 124 warn!("No device found for IRQ: {:?}", irq); 125 return Ok(IrqReturn::NotHandled); 126 } 127 } 128 } 129