1 use alloc::sync::Arc; 2 use hashbrown::HashMap; 3 use system_error::SystemError; 4 use unified_init::macros::unified_init; 5 6 use crate::{driver::base::device::DeviceId, init::initcall::INITCALL_CORE, libs::rwlock::RwLock}; 7 8 use super::VirtIODevice; 9 10 static mut VIRTIO_IRQ_MANAGER: Option<VirtIOIrqManager> = None; 11 12 #[inline(always)] 13 pub fn virtio_irq_manager() -> &'static VirtIOIrqManager { 14 unsafe { VIRTIO_IRQ_MANAGER.as_ref().unwrap() } 15 } 16 17 pub struct VirtIOIrqManager { 18 map: RwLock<HashMap<Arc<DeviceId>, Arc<dyn VirtIODevice>>>, 19 } 20 21 impl VirtIOIrqManager { 22 fn new() -> Self { 23 VirtIOIrqManager { 24 map: RwLock::new(HashMap::new()), 25 } 26 } 27 28 /// 注册一个新的设备到virtio中断请求(IRQ)映射中。 29 /// 30 /// # 参数 31 /// 32 /// - `device` - 实现了 `VirtIODevice` trait 的设备对象,被封装在 `Arc` 智能指针中。 33 /// 34 /// # 返回值 35 /// 36 /// - 如果设备成功注册,返回 `Ok(())`。 37 /// - 如果设备ID已经存在于映射中,返回 `Err(SystemError::EEXIST)`。 38 pub fn register_device(&self, device: Arc<dyn VirtIODevice>) -> Result<(), SystemError> { 39 let mut map = self.map.write_irqsave(); 40 41 if map.contains_key(device.dev_id()) { 42 return Err(SystemError::EEXIST); 43 } 44 45 map.insert(device.dev_id().clone(), device); 46 47 return Ok(()); 48 } 49 50 /// 取消注册设备 51 /// 52 /// 这个函数会从内部映射中移除指定的设备。设备是通过设备ID来识别的。 53 /// 54 /// # 参数 55 /// 56 /// - `device` - 需要被取消注册的设备,它是一个实现了 `VirtIODevice` trait 的智能指针。 57 #[allow(dead_code)] 58 pub fn unregister_device(&self, dev_id: &Arc<DeviceId>) { 59 let mut map = self.map.write_irqsave(); 60 map.remove(dev_id); 61 } 62 63 /// 查找并返回指定设备ID的设备。 64 /// 65 /// # 参数 66 /// - `dev_id` - 我们要查找的设备的设备ID。 67 /// 68 /// # 返回 69 /// - 如果找到了设备,返回一个包含设备的`Option<Arc<dyn VirtIODevice>>`。 70 /// - 如果没有找到设备,返回`None`。 71 72 pub fn lookup_device(&self, dev_id: &Arc<DeviceId>) -> Option<Arc<dyn VirtIODevice>> { 73 let map = self.map.read_irqsave(); 74 map.get(dev_id).map(|x| x.clone()) 75 } 76 } 77 78 #[unified_init(INITCALL_CORE)] 79 fn init_virtio_irq_manager() -> Result<(), SystemError> { 80 let manager = VirtIOIrqManager::new(); 81 unsafe { 82 VIRTIO_IRQ_MANAGER = Some(manager); 83 } 84 return Ok(()); 85 } 86