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