xref: /DragonOS/kernel/src/driver/pci/pci_irq.rs (revision 8d94ea66a3eb3e02039730c8d08e9bead8c344b8)
1 #![allow(dead_code)]
2 
3 use core::mem::size_of;
4 use core::ptr::NonNull;
5 
6 use alloc::ffi::CString;
7 use alloc::vec::Vec;
8 
9 use super::pci::{PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError};
10 use crate::arch::msi::{ia64_pci_get_arch_msi_message_address, ia64_pci_get_arch_msi_message_data};
11 use crate::arch::{PciArch, TraitPciArch};
12 use crate::include::bindings::bindings::{
13     c_irq_install, c_irq_uninstall, pt_regs, ul, EAGAIN, EINVAL,
14 };
15 use crate::libs::volatile::{volread, volwrite, Volatile, VolatileReadable, VolatileWritable};
16 
17 /// MSIX表的一项
18 #[repr(C)]
19 struct MsixEntry {
20     vector_control: Volatile<u32>,
21     msg_data: Volatile<u32>,
22     msg_upper_addr: Volatile<u32>,
23     msg_addr: Volatile<u32>,
24 }
25 /// Pending表的一项
26 #[repr(C)]
27 struct PendingEntry {
28     entry: Volatile<u64>,
29 }
30 /// PCI设备中断错误
31 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
32 pub enum PciIrqError {
33     IrqTypeNotSupported,
34     PciDeviceNotSupportIrq,
35     IrqTypeUnmatch,
36     InvalidIrqIndex(u16),
37     InvalidIrqNum(u16),
38     IrqNumOccupied(u16),
39     DeviceIrqOverflow,
40     MxiIrqNumWrong,
41     PciBarNotInited,
42     BarGetVaddrFailed,
43     MaskNotSupported,
44     IrqNotInited,
45 }
46 /// PCI设备的中断类型
47 #[derive(Copy, Clone, Debug)]
48 pub enum IrqType {
49     Msi {
50         address_64: bool,
51         maskable: bool,
52         irq_max_num: u16,
53         cap_offset: u8,
54     },
55     Msix {
56         msix_table_bar: u8,
57         msix_table_offset: u32,
58         pending_table_bar: u8,
59         pending_table_offset: u32,
60         irq_max_num: u16,
61         cap_offset: u8,
62     },
63     Legacy,
64     Unused,
65 }
66 // PCI设备install中断时需要传递的参数
67 #[derive(Clone, Debug)]
68 pub struct IrqMsg {
69     irq_common_message: IrqCommonMsg,
70     irq_specific_message: IrqSpecificMsg,
71 }
72 // PCI设备install中断时需要传递的共同参数
73 #[derive(Clone, Debug)]
74 pub struct IrqCommonMsg {
75     irq_index: u16,     //要install的中断号在PCI设备中的irq_vector的index
76     irq_name: CString,  //中断名字
77     irq_parameter: u16, //中断额外参数,可传入中断处理函数
78     irq_hander: unsafe extern "C" fn(irq_num: ul, parameter: ul, regs: *mut pt_regs), // 中断处理函数
79     irq_ack: Option<unsafe extern "C" fn(irq_num: ul)>, // 中断的ack,可为None,若为None则中断处理中会正常通知中断结束,不为None则调用传入的函数进行回复
80 }
81 // PCI设备install中断时需要传递的特有参数,Msi代表MSI与MSIX
82 #[derive(Clone, Debug)]
83 pub enum IrqSpecificMsg {
84     Legacy,
85     Msi {
86         processor: u16,
87         trigger_mode: TriggerMode,
88     },
89 }
90 impl IrqSpecificMsg {
91     fn msi_default() -> Self {
92         IrqSpecificMsg::Msi {
93             processor: 0,
94             trigger_mode: TriggerMode::EdgeTrigger,
95         }
96     }
97 }
98 // 申请中断的触发模式,MSI默认为边沿触发
99 #[derive(Copy, Clone, Debug)]
100 pub enum TriggerMode {
101     EdgeTrigger,
102     AssertHigh,
103     AssertLow,
104 }
105 bitflags! {
106     /// 设备中断类型,使用bitflag使得中断类型的选择更多元化
107     pub struct IRQ: u8{
108         const PCI_IRQ_LEGACY = 1 << 0;
109         const PCI_IRQ_MSI = 1 << 1;
110         const PCI_IRQ_MSIX = 1 << 2;
111         const PCI_IRQ_ALL_TYPES=IRQ::PCI_IRQ_LEGACY.bits|IRQ::PCI_IRQ_MSI.bits|IRQ::PCI_IRQ_MSIX.bits;
112     }
113 }
114 /// PciDeviceStructure的子trait,使用继承以直接使用PciDeviceStructure里的接口
115 pub trait PciInterrupt: PciDeviceStructure {
116     /// @brief PCI设备调用该函数选择中断类型
117     /// @param self PCI设备的可变引用
118     /// @param flag 选择的中断类型(支持多个选择),如PCI_IRQ_ALL_TYPES表示所有中断类型均可,让系统按顺序进行选择
119     /// @return Option<IrqType> 失败返回None,成功则返回对应中断类型
120     fn irq_init(&mut self, flag: IRQ) -> Option<IrqType> {
121         // MSIX中断优先
122         if flag.contains(IRQ::PCI_IRQ_MSIX) {
123             if let Some(cap_offset) = self.msix_capability_offset() {
124                 let data =
125                     PciArch::read_config(&self.common_header().bus_device_function, cap_offset + 4);
126                 let irq_max_num = ((data >> 16) & 0x07ff) as u16;
127                 let data =
128                     PciArch::read_config(&self.common_header().bus_device_function, cap_offset + 4);
129                 let msix_table_bar = (data & 0x01) as u8;
130                 let msix_table_offset = data & 0xfffe;
131                 let data =
132                     PciArch::read_config(&self.common_header().bus_device_function, cap_offset + 8);
133                 let pending_table_bar = (data & 0x01) as u8;
134                 let pending_table_offset = data & 0xfffe;
135                 *self.irq_type_mut()? = IrqType::Msix {
136                     msix_table_bar,
137                     msix_table_offset,
138                     pending_table_bar,
139                     pending_table_offset,
140                     irq_max_num,
141                     cap_offset,
142                 };
143                 return Some(IrqType::Msix {
144                     msix_table_bar,
145                     msix_table_offset,
146                     pending_table_bar,
147                     pending_table_offset,
148                     irq_max_num,
149                     cap_offset,
150                 });
151             }
152         }
153         // 其次MSI
154         if flag.contains(IRQ::PCI_IRQ_MSI) {
155             if let Some(cap_offset) = self.msi_capability_offset() {
156                 let data =
157                     PciArch::read_config(&self.common_header().bus_device_function, cap_offset);
158                 let message_control = (data >> 16) as u16;
159                 let maskable = (message_control & 0x0100) != 0;
160                 let address_64 = (message_control & 0x0080) != 0;
161                 let irq_max_num = (1 << (((message_control & 0x000e) >> 1) + 1)) as u16;
162                 *self.irq_type_mut()? = IrqType::Msi {
163                     address_64,
164                     maskable,
165                     irq_max_num,
166                     cap_offset,
167                 };
168                 return Some(IrqType::Msi {
169                     address_64,
170                     maskable,
171                     irq_max_num,
172                     cap_offset,
173                 });
174             }
175         }
176         // 最后选择legacy#
177         if flag.contains(IRQ::PCI_IRQ_LEGACY) {
178             *self.irq_type_mut()? = IrqType::Legacy;
179             return Some(IrqType::Legacy);
180         }
181         None
182     }
183 
184     /// @brief 启动/关闭设备中断
185     /// @param self PCI设备的可变引用
186     /// @param enable 开启/关闭
187     fn irq_enable(&mut self, enable: bool) -> Result<u8, PciError> {
188         if let Some(irq_type) = self.irq_type_mut() {
189             match *irq_type {
190                 IrqType::Msix { .. } => {
191                     return self.msix_enable(enable);
192                 }
193                 IrqType::Msi { .. } => {
194                     return self.msi_enable(enable);
195                 }
196                 IrqType::Legacy => {
197                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeNotSupported));
198                 }
199                 IrqType::Unused => {
200                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
201                 }
202             }
203         }
204         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
205     }
206     /// @brief 启动/关闭设备MSIX中断
207     /// @param self PCI设备的可变引用
208     /// @param enable 开启/关闭
209     fn msix_enable(&mut self, enable: bool) -> Result<u8, PciError> {
210         if let Some(irq_type) = self.irq_type_mut() {
211             match *irq_type {
212                 IrqType::Msix { cap_offset, .. } => {
213                     let mut message =
214                         PciArch::read_config(&self.common_header().bus_device_function, cap_offset);
215                     if enable {
216                         message |= 1 << 31;
217                     } else {
218                         message &= !(1 << 31);
219                     }
220                     PciArch::write_config(
221                         &self.common_header().bus_device_function,
222                         cap_offset,
223                         message,
224                     );
225                     return Ok(0);
226                 }
227                 IrqType::Unused => {
228                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
229                 }
230                 _ => {
231                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch));
232                 }
233             }
234         }
235         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
236     }
237     /// @brief 启动/关闭设备MSI中断
238     /// @param self PCI设备的可变引用
239     /// @param enable 开启/关闭
240     fn msi_enable(&mut self, enable: bool) -> Result<u8, PciError> {
241         if let Some(irq_type) = self.irq_type_mut() {
242             match *irq_type {
243                 IrqType::Msi { cap_offset, .. } => {
244                     let mut message =
245                         PciArch::read_config(&self.common_header().bus_device_function, cap_offset);
246                     if enable {
247                         message |= 1 << 16;
248                     } else {
249                         message &= !(1 << 16);
250                     }
251                     PciArch::write_config(
252                         &self.common_header().bus_device_function,
253                         cap_offset,
254                         message,
255                     );
256                     return Ok(0);
257                 }
258                 IrqType::Unused => {
259                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
260                 }
261                 _ => {
262                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch));
263                 }
264             }
265         }
266         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
267     }
268     /// @brief 获取指定数量的中断号 todo 需要中断重构支持
269     fn irq_alloc(_num: u16) -> Option<Vec<u16>> {
270         None
271     }
272     /// @brief 进行PCI设备中断的安装
273     /// @param self PCI设备的可变引用
274     /// @param msg PCI设备install中断时需要传递的共同参数
275     /// @return 一切正常返回Ok(0),有错误返回对应错误原因
276     fn irq_install(&mut self, msg: IrqMsg) -> Result<u8, PciError> {
277         if let Some(irq_vector) = self.irq_vector_mut() {
278             if msg.irq_common_message.irq_index as usize > irq_vector.len() {
279                 return Err(PciError::PciIrqError(PciIrqError::InvalidIrqIndex(
280                     msg.irq_common_message.irq_index,
281                 )));
282             }
283         }
284         self.irq_enable(false)?; //中断设置更改前先关闭对应PCI设备的中断
285         if let Some(irq_type) = self.irq_type_mut() {
286             match *irq_type {
287                 IrqType::Msix { .. } => {
288                     return self.msix_install(msg);
289                 }
290                 IrqType::Msi { .. } => {
291                     return self.msi_install(msg);
292                 }
293                 IrqType::Unused => {
294                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
295                 }
296                 _ => {
297                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeNotSupported));
298                 }
299             }
300         }
301         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
302     }
303     /// @brief 进行PCI设备中断的安装(MSI)
304     /// @param self PCI设备的可变引用
305     /// @param msg PCI设备install中断时需要传递的共同参数
306     /// @return 一切正常返回Ok(0),有错误返回对应错误原因
307     fn msi_install(&mut self, msg: IrqMsg) -> Result<u8, PciError> {
308         if let Some(irq_type) = self.irq_type_mut() {
309             match *irq_type {
310                 IrqType::Msi {
311                     address_64,
312                     irq_max_num,
313                     cap_offset,
314                     ..
315                 } => {
316                     // 注意:MSI中断分配的中断号必须连续且大小为2的倍数
317                     if self.irq_vector_mut().unwrap().len() > irq_max_num as usize {
318                         return Err(PciError::PciIrqError(PciIrqError::DeviceIrqOverflow));
319                     }
320                     let irq_num =
321                         self.irq_vector_mut().unwrap()[msg.irq_common_message.irq_index as usize];
322                     let common_msg = &msg.irq_common_message;
323                     let result = unsafe {
324                         c_irq_install(
325                             irq_num as u64,
326                             Some(common_msg.irq_hander),
327                             common_msg.irq_parameter as u64,
328                             common_msg.irq_name.as_ptr(),
329                             common_msg.irq_ack,
330                         )
331                     };
332                     match result as u32 {
333                         EINVAL => {
334                             return Err(PciError::PciIrqError(PciIrqError::InvalidIrqNum(irq_num)));
335                         }
336                         EAGAIN => {
337                             return Err(PciError::PciIrqError(PciIrqError::IrqNumOccupied(
338                                 irq_num,
339                             )));
340                         }
341                         _ => {}
342                     }
343                     //MSI中断只需配置一次PCI寄存器
344                     if common_msg.irq_index == 0 {
345                         let msg_address = ia64_pci_get_arch_msi_message_address(0);
346                         let trigger = match msg.irq_specific_message {
347                             IrqSpecificMsg::Legacy => {
348                                 return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch));
349                             }
350                             IrqSpecificMsg::Msi { trigger_mode, .. } => trigger_mode,
351                         };
352                         let msg_data = ia64_pci_get_arch_msi_message_data(irq_num, 0, trigger);
353                         //写入Message Data和Message Address
354                         if address_64 {
355                             PciArch::write_config(
356                                 &self.common_header().bus_device_function,
357                                 cap_offset + 4,
358                                 msg_address,
359                             );
360                             PciArch::write_config(
361                                 &self.common_header().bus_device_function,
362                                 cap_offset + 8,
363                                 0,
364                             );
365                             PciArch::write_config(
366                                 &self.common_header().bus_device_function,
367                                 cap_offset + 12,
368                                 msg_data,
369                             );
370                         } else {
371                             PciArch::write_config(
372                                 &self.common_header().bus_device_function,
373                                 cap_offset + 4,
374                                 msg_address,
375                             );
376                             PciArch::write_config(
377                                 &self.common_header().bus_device_function,
378                                 cap_offset + 8,
379                                 msg_data,
380                             );
381                         }
382                         let data = PciArch::read_config(
383                             &self.common_header().bus_device_function,
384                             cap_offset,
385                         );
386                         let message_control = (data >> 16) as u16;
387                         match self.irq_vector_mut().unwrap().len() {
388                             1 => {
389                                 let temp = message_control & (!0x0070);
390                                 PciArch::write_config(
391                                     &self.common_header().bus_device_function,
392                                     cap_offset,
393                                     (temp as u32) << 16,
394                                 );
395                             }
396                             2 => {
397                                 let temp = message_control & (!0x0070);
398                                 PciArch::write_config(
399                                     &self.common_header().bus_device_function,
400                                     cap_offset,
401                                     ((temp | (0x0001 << 4)) as u32) << 16,
402                                 );
403                             }
404                             4 => {
405                                 let temp = message_control & (!0x0070);
406                                 PciArch::write_config(
407                                     &self.common_header().bus_device_function,
408                                     cap_offset,
409                                     ((temp | (0x0002 << 4)) as u32) << 16,
410                                 );
411                             }
412                             8 => {
413                                 let temp = message_control & (!0x0070);
414                                 PciArch::write_config(
415                                     &self.common_header().bus_device_function,
416                                     cap_offset,
417                                     ((temp | (0x0003 << 4)) as u32) << 16,
418                                 );
419                             }
420                             16 => {
421                                 let temp = message_control & (!0x0070);
422                                 PciArch::write_config(
423                                     &self.common_header().bus_device_function,
424                                     cap_offset,
425                                     ((temp | (0x0004 << 4)) as u32) << 16,
426                                 );
427                             }
428                             32 => {
429                                 let temp = message_control & (!0x0070);
430                                 PciArch::write_config(
431                                     &self.common_header().bus_device_function,
432                                     cap_offset,
433                                     ((temp | (0x0005 << 4)) as u32) << 16,
434                                 );
435                             }
436                             _ => {
437                                 return Err(PciError::PciIrqError(PciIrqError::MxiIrqNumWrong));
438                             }
439                         }
440                     }
441                     return Ok(0);
442                 }
443                 IrqType::Unused => {
444                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
445                 }
446                 _ => {
447                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch));
448                 }
449             }
450         }
451         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
452     }
453     /// @brief 进行PCI设备中断的安装(MSIX)
454     /// @param self PCI设备的可变引用
455     /// @param msg PCI设备install中断时需要传递的共同参数
456     /// @return 一切正常返回Ok(0),有错误返回对应错误原因
457     fn msix_install(&mut self, msg: IrqMsg) -> Result<u8, PciError> {
458         if let Some(irq_type) = self.irq_type_mut() {
459             match *irq_type {
460                 IrqType::Msix {
461                     irq_max_num,
462                     msix_table_bar,
463                     msix_table_offset,
464                     ..
465                 } => {
466                     if self.irq_vector_mut().unwrap().len() > irq_max_num as usize {
467                         return Err(PciError::PciIrqError(PciIrqError::DeviceIrqOverflow));
468                     }
469                     let irq_num =
470                         self.irq_vector_mut().unwrap()[msg.irq_common_message.irq_index as usize];
471                     let common_msg = &msg.irq_common_message;
472                     let result = unsafe {
473                         c_irq_install(
474                             irq_num as u64,
475                             Some(common_msg.irq_hander),
476                             common_msg.irq_parameter as u64,
477                             common_msg.irq_name.as_ptr(),
478                             common_msg.irq_ack,
479                         )
480                     };
481                     match result as u32 {
482                         EINVAL => {
483                             return Err(PciError::PciIrqError(PciIrqError::InvalidIrqNum(irq_num)));
484                         }
485                         EAGAIN => {
486                             return Err(PciError::PciIrqError(PciIrqError::IrqNumOccupied(
487                                 irq_num,
488                             )));
489                         }
490                         _ => {}
491                     }
492 
493                     let msg_address = ia64_pci_get_arch_msi_message_address(0);
494                     let trigger = match msg.irq_specific_message {
495                         IrqSpecificMsg::Legacy => {
496                             return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch));
497                         }
498                         IrqSpecificMsg::Msi { trigger_mode, .. } => trigger_mode,
499                     };
500                     let msg_data = ia64_pci_get_arch_msi_message_data(irq_num, 0, trigger);
501                     //写入Message Data和Message Address
502                     let pcistandardbar = self
503                         .bar()
504                         .ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited))?;
505                     let msix_bar = pcistandardbar.get_bar(msix_table_bar)?;
506                     let vaddr = msix_bar
507                         .virtual_address()
508                         .ok_or(PciError::PciIrqError(PciIrqError::BarGetVaddrFailed))?
509                         as usize
510                         + msix_table_offset as usize
511                         + msg.irq_common_message.irq_index as usize * size_of::<MsixEntry>();
512                     let msix_entry = NonNull::new(vaddr as *mut MsixEntry).unwrap();
513                     unsafe {
514                         volwrite!(msix_entry, vector_control, 0);
515                         volwrite!(msix_entry, msg_data, msg_data);
516                         volwrite!(msix_entry, msg_upper_addr, 0);
517                         volwrite!(msix_entry, msg_addr, msg_address);
518                     }
519                     return Ok(0);
520                 }
521                 IrqType::Unused => {
522                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
523                 }
524                 _ => {
525                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch));
526                 }
527             }
528         }
529         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
530     }
531     /// @brief 进行PCI设备中断的卸载
532     /// @param self PCI设备的可变引用
533     fn irq_uninstall(&mut self) -> Result<u8, PciError> {
534         self.irq_enable(false)?; //中断设置更改前先关闭对应PCI设备的中断
535         if let Some(irq_type) = self.irq_type_mut() {
536             match *irq_type {
537                 IrqType::Msix { .. } => {
538                     return self.msix_uninstall();
539                 }
540                 IrqType::Msi { .. } => {
541                     return self.msi_uninstall();
542                 }
543                 IrqType::Unused => {
544                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
545                 }
546                 _ => {
547                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeNotSupported));
548                 }
549             }
550         }
551         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
552     }
553     /// @brief 进行PCI设备中断的卸载(MSI)
554     /// @param self PCI设备的可变引用
555     fn msi_uninstall(&mut self) -> Result<u8, PciError> {
556         if let Some(irq_type) = self.irq_type_mut() {
557             match *irq_type {
558                 IrqType::Msi {
559                     address_64,
560                     cap_offset,
561                     ..
562                 } => {
563                     for vector in self.irq_vector_mut().unwrap() {
564                         unsafe {
565                             c_irq_uninstall(vector.clone() as u64);
566                         }
567                     }
568                     PciArch::write_config(&self.common_header().bus_device_function, cap_offset, 0);
569                     PciArch::write_config(
570                         &self.common_header().bus_device_function,
571                         cap_offset + 4,
572                         0,
573                     );
574                     PciArch::write_config(
575                         &self.common_header().bus_device_function,
576                         cap_offset + 8,
577                         0,
578                     );
579                     if address_64 {
580                         PciArch::write_config(
581                             &self.common_header().bus_device_function,
582                             cap_offset + 12,
583                             0,
584                         );
585                     }
586                     return Ok(0);
587                 }
588                 IrqType::Unused => {
589                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
590                 }
591                 _ => {
592                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch));
593                 }
594             }
595         }
596         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
597     }
598     /// @brief 进行PCI设备中断的卸载(MSIX)
599     /// @param self PCI设备的可变引用
600     fn msix_uninstall(&mut self) -> Result<u8, PciError> {
601         if let Some(irq_type) = self.irq_type_mut() {
602             match *irq_type {
603                 IrqType::Msix {
604                     irq_max_num,
605                     cap_offset,
606                     msix_table_bar,
607                     msix_table_offset,
608                     ..
609                 } => {
610                     for vector in self.irq_vector_mut().unwrap() {
611                         unsafe {
612                             c_irq_uninstall(vector.clone() as u64);
613                         }
614                     }
615                     PciArch::write_config(&self.common_header().bus_device_function, cap_offset, 0);
616                     let pcistandardbar = self
617                         .bar()
618                         .ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited))
619                         .unwrap();
620                     let msix_bar = pcistandardbar.get_bar(msix_table_bar).unwrap();
621                     for index in 0..irq_max_num {
622                         let vaddr = msix_bar
623                             .virtual_address()
624                             .ok_or(PciError::PciIrqError(PciIrqError::BarGetVaddrFailed))
625                             .unwrap() as usize
626                             + msix_table_offset as usize
627                             + index as usize * size_of::<MsixEntry>();
628                         let msix_entry = NonNull::new(vaddr as *mut MsixEntry).unwrap();
629                         unsafe {
630                             volwrite!(msix_entry, vector_control, 0);
631                             volwrite!(msix_entry, msg_data, 0);
632                             volwrite!(msix_entry, msg_upper_addr, 0);
633                             volwrite!(msix_entry, msg_addr, 0);
634                         }
635                     }
636                     return Ok(0);
637                 }
638                 IrqType::Unused => {
639                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
640                 }
641                 _ => {
642                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch));
643                 }
644             }
645         }
646         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
647     }
648     /// @brief 屏蔽相应位置的中断
649     /// @param self PCI设备的可变引用
650     /// @param irq_index 中断的位置(在vec中的index和安装的index相同)
651     fn irq_mask(&mut self, irq_index: u16) -> Result<u8, PciError> {
652         if let Some(irq_type) = self.irq_type_mut() {
653             match *irq_type {
654                 IrqType::Msix { .. } => {
655                     return self.msix_mask(irq_index);
656                 }
657                 IrqType::Msi { .. } => {
658                     return self.msi_mask(irq_index);
659                 }
660                 IrqType::Unused => {
661                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
662                 }
663                 _ => {
664                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeNotSupported));
665                 }
666             }
667         }
668         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
669     }
670     /// @brief 屏蔽相应位置的中断(MSI)
671     /// @param self PCI设备的可变引用
672     /// @param irq_index 中断的位置(在vec中的index和安装的index相同)
673     fn msi_mask(&mut self, irq_index: u16) -> Result<u8, PciError> {
674         if let Some(irq_type) = self.irq_type_mut() {
675             match *irq_type {
676                 IrqType::Msi {
677                     maskable,
678                     address_64,
679                     cap_offset,
680                     irq_max_num,
681                 } => {
682                     if irq_index >= irq_max_num {
683                         return Err(PciError::PciIrqError(PciIrqError::InvalidIrqIndex(
684                             irq_index,
685                         )));
686                     }
687                     if maskable {
688                         match address_64 {
689                             true => {
690                                 let mut mask = PciArch::read_config(
691                                     &self.common_header().bus_device_function,
692                                     cap_offset + 16,
693                                 );
694                                 mask |= 1 << irq_index;
695                                 PciArch::write_config(
696                                     &self.common_header().bus_device_function,
697                                     cap_offset,
698                                     mask,
699                                 );
700                             }
701                             false => {
702                                 let mut mask = PciArch::read_config(
703                                     &self.common_header().bus_device_function,
704                                     cap_offset + 12,
705                                 );
706                                 mask |= 1 << irq_index;
707                                 PciArch::write_config(
708                                     &self.common_header().bus_device_function,
709                                     cap_offset,
710                                     mask,
711                                 );
712                             }
713                         }
714                         return Ok(0);
715                     }
716                     return Err(PciError::PciIrqError(PciIrqError::MaskNotSupported));
717                 }
718                 IrqType::Unused => {
719                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
720                 }
721                 _ => {
722                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch));
723                 }
724             }
725         }
726         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
727     }
728     /// @brief 屏蔽相应位置的中断(MSIX)
729     /// @param self PCI设备的可变引用
730     /// @param irq_index 中断的位置(在vec中的index和安装的index相同)
731     fn msix_mask(&mut self, irq_index: u16) -> Result<u8, PciError> {
732         if let Some(irq_type) = self.irq_type_mut() {
733             match *irq_type {
734                 IrqType::Msix {
735                     irq_max_num,
736                     msix_table_bar,
737                     msix_table_offset,
738                     ..
739                 } => {
740                     if irq_index >= irq_max_num {
741                         return Err(PciError::PciIrqError(PciIrqError::InvalidIrqIndex(
742                             irq_index,
743                         )));
744                     }
745                     let pcistandardbar = self
746                         .bar()
747                         .ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited))
748                         .unwrap();
749                     let msix_bar = pcistandardbar.get_bar(msix_table_bar).unwrap();
750                     let vaddr = msix_bar.virtual_address().unwrap() as usize
751                         + msix_table_offset as usize
752                         + irq_index as usize * size_of::<MsixEntry>();
753                     let msix_entry = NonNull::new(vaddr as *mut MsixEntry).unwrap();
754                     unsafe {
755                         volwrite!(msix_entry, vector_control, 1);
756                     }
757                     return Ok(0);
758                 }
759                 IrqType::Unused => {
760                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
761                 }
762                 _ => {
763                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch));
764                 }
765             }
766         }
767         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
768     }
769     /// @brief 解除屏蔽相应位置的中断
770     /// @param self PCI设备的可变引用
771     /// @param irq_index 中断的位置(在vec中的index和安装的index相同)
772     fn irq_unmask(&mut self, irq_index: u16) -> Result<u8, PciError> {
773         if let Some(irq_type) = self.irq_type_mut() {
774             match *irq_type {
775                 IrqType::Msix { .. } => {
776                     return self.msix_unmask(irq_index);
777                 }
778                 IrqType::Msi { .. } => {
779                     return self.msi_unmask(irq_index);
780                 }
781                 IrqType::Unused => {
782                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
783                 }
784                 _ => {
785                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeNotSupported));
786                 }
787             }
788         }
789         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
790     }
791     /// @brief 解除屏蔽相应位置的中断(MSI)
792     /// @param self PCI设备的可变引用
793     /// @param irq_index 中断的位置(在vec中的index和安装的index相同)
794     fn msi_unmask(&mut self, irq_index: u16) -> Result<u8, PciError> {
795         if let Some(irq_type) = self.irq_type_mut() {
796             match *irq_type {
797                 IrqType::Msi {
798                     maskable,
799                     address_64,
800                     cap_offset,
801                     irq_max_num,
802                 } => {
803                     if irq_index >= irq_max_num {
804                         return Err(PciError::PciIrqError(PciIrqError::InvalidIrqIndex(
805                             irq_index,
806                         )));
807                     }
808                     if maskable {
809                         match address_64 {
810                             true => {
811                                 let mut mask = PciArch::read_config(
812                                     &self.common_header().bus_device_function,
813                                     cap_offset + 16,
814                                 );
815                                 mask &= !(1 << irq_index);
816                                 PciArch::write_config(
817                                     &self.common_header().bus_device_function,
818                                     cap_offset,
819                                     mask,
820                                 );
821                             }
822                             false => {
823                                 let mut mask = PciArch::read_config(
824                                     &self.common_header().bus_device_function,
825                                     cap_offset + 12,
826                                 );
827                                 mask &= !(1 << irq_index);
828                                 PciArch::write_config(
829                                     &self.common_header().bus_device_function,
830                                     cap_offset,
831                                     mask,
832                                 );
833                             }
834                         }
835                     }
836                     return Err(PciError::PciIrqError(PciIrqError::MaskNotSupported));
837                 }
838                 IrqType::Unused => {
839                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
840                 }
841                 _ => {
842                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch));
843                 }
844             }
845         }
846         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
847     }
848     /// @brief 解除屏蔽相应位置的中断(MSIX)
849     /// @param self PCI设备的可变引用
850     /// @param irq_index 中断的位置(在vec中的index和安装的index相同)
851     fn msix_unmask(&mut self, irq_index: u16) -> Result<u8, PciError> {
852         if let Some(irq_type) = self.irq_type_mut() {
853             match *irq_type {
854                 IrqType::Msix {
855                     irq_max_num,
856                     msix_table_bar,
857                     msix_table_offset,
858                     ..
859                 } => {
860                     if irq_index >= irq_max_num {
861                         return Err(PciError::PciIrqError(PciIrqError::InvalidIrqIndex(
862                             irq_index,
863                         )));
864                     }
865                     let pcistandardbar = self
866                         .bar()
867                         .ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited))
868                         .unwrap();
869                     let msix_bar = pcistandardbar.get_bar(msix_table_bar).unwrap();
870                     let vaddr = msix_bar.virtual_address().unwrap() as usize
871                         + msix_table_offset as usize
872                         + irq_index as usize * size_of::<MsixEntry>();
873                     let msix_entry = NonNull::new(vaddr as *mut MsixEntry).unwrap();
874                     unsafe {
875                         volwrite!(msix_entry, vector_control, 0);
876                     }
877                     return Ok(0);
878                 }
879                 IrqType::Unused => {
880                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
881                 }
882                 _ => {
883                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch));
884                 }
885             }
886         }
887         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
888     }
889     /// @brief 检查被挂起的中断是否在挂起的时候产生了
890     /// @param self PCI设备的可变引用
891     /// @param irq_index 中断的位置(在vec中的index和安装的index相同)
892     /// @return 是否在挂起过程中产生中断(异常情况也返回false)
893     fn irq_check_pending(&mut self, irq_index: u16) -> Result<bool, PciError> {
894         if let Some(irq_type) = self.irq_type_mut() {
895             match *irq_type {
896                 IrqType::Msix { .. } => {
897                     return self.msix_check_pending(irq_index);
898                 }
899                 IrqType::Msi { .. } => {
900                     return self.msi_check_pending(irq_index);
901                 }
902                 IrqType::Unused => {
903                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
904                 }
905                 _ => {
906                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeNotSupported));
907                 }
908             }
909         }
910         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
911     }
912     /// @brief 检查被挂起的中断是否在挂起的时候产生了(MSI)
913     /// @param self PCI设备的可变引用
914     /// @param irq_index 中断的位置(在vec中的index和安装的index相同)
915     /// @return 是否在挂起过程中产生中断(异常情况也返回false)
916     fn msi_check_pending(&mut self, irq_index: u16) -> Result<bool, PciError> {
917         if let Some(irq_type) = self.irq_type_mut() {
918             match *irq_type {
919                 IrqType::Msi {
920                     maskable,
921                     address_64,
922                     cap_offset,
923                     irq_max_num,
924                 } => {
925                     if irq_index >= irq_max_num {
926                         return Err(PciError::PciIrqError(PciIrqError::InvalidIrqIndex(
927                             irq_index,
928                         )));
929                     }
930                     if maskable {
931                         match address_64 {
932                             true => {
933                                 let mut pend = PciArch::read_config(
934                                     &self.common_header().bus_device_function,
935                                     cap_offset + 20,
936                                 );
937                                 pend &= 1 << irq_index;
938                                 return Ok(pend != 0);
939                             }
940                             false => {
941                                 let mut pend = PciArch::read_config(
942                                     &self.common_header().bus_device_function,
943                                     cap_offset + 16,
944                                 );
945                                 pend &= 1 << irq_index;
946                                 return Ok(pend != 0);
947                             }
948                         }
949                     }
950                 }
951                 IrqType::Unused => {
952                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
953                 }
954                 _ => {
955                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch));
956                 }
957             }
958         }
959         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
960     }
961     /// @brief 检查被挂起的中断是否在挂起的时候产生了(MSIX)
962     /// @param self PCI设备的可变引用
963     /// @param irq_index 中断的位置(在vec中的index和安装的index相同)
964     /// @return 是否在挂起过程中产生中断(异常情况也返回false)
965     fn msix_check_pending(&mut self, irq_index: u16) -> Result<bool, PciError> {
966         if let Some(irq_type) = self.irq_type_mut() {
967             match *irq_type {
968                 IrqType::Msix {
969                     irq_max_num,
970                     pending_table_bar,
971                     pending_table_offset,
972                     ..
973                 } => {
974                     if irq_index >= irq_max_num {
975                         return Err(PciError::PciIrqError(PciIrqError::InvalidIrqIndex(
976                             irq_index,
977                         )));
978                     }
979                     let pcistandardbar = self
980                         .bar()
981                         .ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited))
982                         .unwrap();
983                     let pending_bar = pcistandardbar.get_bar(pending_table_bar).unwrap();
984                     let vaddr = pending_bar.virtual_address().unwrap() as usize
985                         + pending_table_offset as usize
986                         + (irq_index as usize / 64) * size_of::<PendingEntry>();
987                     let pending_entry = NonNull::new(vaddr as *mut PendingEntry).unwrap();
988                     let pending_entry = unsafe { volread!(pending_entry, entry) };
989                     return Ok(pending_entry & (1 << (irq_index as u64 % 64)) != 0);
990                 }
991                 IrqType::Unused => {
992                     return Err(PciError::PciIrqError(PciIrqError::IrqNotInited));
993                 }
994                 _ => {
995                     return Err(PciError::PciIrqError(PciIrqError::IrqTypeUnmatch));
996                 }
997             }
998         }
999         return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
1000     }
1001 }
1002 /// PCI标准设备的msi/msix中断相关函数块
1003 impl PciInterrupt for PciDeviceStructureGeneralDevice {}
1004