1use std::io::{Error, Result};
10use std::sync::atomic::{AtomicU32, Ordering};
11use std::sync::Arc;
12
13use dbs_device::resources::DeviceResources;
14
15#[cfg(feature = "legacy-irq")]
16use super::LegacyIrqSourceConfig;
17#[cfg(feature = "msi-irq")]
18use super::MsiIrqSourceConfig;
19use super::{InterruptManager, InterruptSourceConfig, InterruptSourceGroup, InterruptSourceType};
20
21pub const MSI_DEVICE_ID_SHIFT: u8 = 3;
25
26#[cfg(feature = "legacy-irq")]
27const LEGACY_CONFIGS: [InterruptSourceConfig; 1] =
28 [InterruptSourceConfig::LegacyIrq(LegacyIrqSourceConfig {})];
29
30#[cfg(feature = "msi-irq")]
31const MSI_INT_MASK_BIT: u8 = 0;
32#[cfg(feature = "msi-irq")]
33const MSI_INT_MASK: u32 = (1 << MSI_INT_MASK_BIT) as u32;
34
35#[derive(Copy, Clone, Debug, Eq, PartialEq)]
37pub enum DeviceInterruptMode {
38 Disabled = 0,
40 LegacyIrq = 1,
42 GenericMsiIrq = 2,
44 PciMsiIrq = 3,
46 PciMsixIrq = 4,
48}
49
50pub struct DeviceInterruptManager<T: InterruptManager> {
60 mode: DeviceInterruptMode,
61 activated: bool,
62 current_idx: usize,
63 mode2idx: [usize; 5],
64 intr_mgr: T,
65 intr_groups: Vec<Arc<Box<dyn InterruptSourceGroup>>>,
66 #[cfg(feature = "msi-irq")]
67 msi_config: Vec<InterruptSourceConfig>,
68 device_id: Option<u32>,
70}
71
72impl<T: InterruptManager> DeviceInterruptManager<T> {
73 pub fn new(intr_mgr: T, resources: &DeviceResources) -> Result<Self> {
79 let mut mgr = DeviceInterruptManager {
80 mode: DeviceInterruptMode::Disabled,
81 activated: false,
82 current_idx: usize::MAX,
83 mode2idx: [usize::MAX; 5],
84 intr_mgr,
85 intr_groups: Vec::new(),
86 #[cfg(feature = "msi-irq")]
87 msi_config: Vec::new(),
88 device_id: None,
89 };
90
91 #[cfg(feature = "legacy-irq")]
92 {
93 if let Some(irq) = resources.get_legacy_irq() {
94 let group = mgr
95 .intr_mgr
96 .create_group(InterruptSourceType::LegacyIrq, irq, 1)?;
97 mgr.mode2idx[DeviceInterruptMode::LegacyIrq as usize] = mgr.intr_groups.len();
98 mgr.intr_groups.push(group);
99 }
100 }
101
102 #[cfg(feature = "msi-irq")]
103 {
104 if let Some(msi) = resources.get_generic_msi_irqs() {
105 let group = mgr
106 .intr_mgr
107 .create_group(InterruptSourceType::MsiIrq, msi.0, msi.1)?;
108 mgr.resize_msi_config_space(group.len());
109 mgr.mode2idx[DeviceInterruptMode::GenericMsiIrq as usize] = mgr.intr_groups.len();
110 mgr.intr_groups.push(group);
111 }
112
113 if let Some(msi) = resources.get_pci_msi_irqs() {
114 let group = mgr
115 .intr_mgr
116 .create_group(InterruptSourceType::MsiIrq, msi.0, msi.1)?;
117 mgr.resize_msi_config_space(group.len());
118 mgr.mode2idx[DeviceInterruptMode::PciMsiIrq as usize] = mgr.intr_groups.len();
119 mgr.intr_groups.push(group);
120 }
121
122 if let Some(msi) = resources.get_pci_msix_irqs() {
123 let group = mgr
124 .intr_mgr
125 .create_group(InterruptSourceType::MsiIrq, msi.0, msi.1)?;
126 mgr.resize_msi_config_space(group.len());
127 mgr.mode2idx[DeviceInterruptMode::PciMsixIrq as usize] = mgr.intr_groups.len();
128 mgr.intr_groups.push(group);
129 }
130 }
131
132 Ok(mgr)
133 }
134
135 pub fn set_device_id(&mut self, device_id: Option<u32>) {
137 self.device_id = device_id;
138 }
139
140 pub fn is_enabled(&self) -> bool {
142 self.activated
143 }
144
145 pub fn enable(&mut self) -> Result<()> {
153 if self.activated {
154 return Ok(());
155 }
156
157 if self.mode == DeviceInterruptMode::Disabled
159 && self.mode2idx[DeviceInterruptMode::LegacyIrq as usize] != usize::MAX
160 {
161 self.set_working_mode(DeviceInterruptMode::LegacyIrq)?;
162 }
163 if self.mode == DeviceInterruptMode::Disabled {
164 return Err(Error::from_raw_os_error(libc::EINVAL));
165 }
166
167 self.intr_groups[self.current_idx].enable(self.get_configs(self.mode))?;
168 self.activated = true;
169
170 Ok(())
171 }
172
173 pub fn reset(&mut self) -> Result<()> {
179 if self.activated {
180 self.activated = false;
181 self.intr_groups[self.current_idx].disable()?;
182 }
183 self.set_working_mode(DeviceInterruptMode::Disabled)?;
184
185 Ok(())
186 }
187
188 pub fn get_working_mode(&mut self) -> DeviceInterruptMode {
190 self.mode
191 }
192
193 pub fn set_working_mode(&mut self, mode: DeviceInterruptMode) -> Result<()> {
211 if self.activated {
213 return Err(Error::from_raw_os_error(libc::EINVAL));
214 }
215
216 if mode != self.mode {
217 if self.mode != DeviceInterruptMode::Disabled
223 && self.mode != DeviceInterruptMode::LegacyIrq
224 && mode != DeviceInterruptMode::LegacyIrq
225 && mode != DeviceInterruptMode::Disabled
226 {
227 return Err(Error::from_raw_os_error(libc::EINVAL));
228 }
229
230 if mode != DeviceInterruptMode::Disabled {
232 self.current_idx = self.mode2idx[mode as usize];
233 } else {
234 self.reset_configs(mode);
236 }
237 self.mode = mode;
238 }
239
240 Ok(())
241 }
242
243 pub fn get_group(&self) -> Option<Arc<Box<dyn InterruptSourceGroup>>> {
246 if !self.activated || self.mode == DeviceInterruptMode::Disabled {
247 None
248 } else {
249 Some(self.intr_groups[self.current_idx].clone())
250 }
251 }
252
253 pub fn get_group_unchecked(&self) -> Arc<Box<dyn InterruptSourceGroup>> {
255 self.intr_groups[self.current_idx].clone()
256 }
257
258 #[allow(unused_variables)]
263 pub fn update(&mut self, index: u32) -> Result<()> {
264 if !self.activated {
265 return Err(Error::from_raw_os_error(libc::EINVAL));
266 }
267
268 match self.mode {
269 #[cfg(feature = "msi-irq")]
270 DeviceInterruptMode::GenericMsiIrq
271 | DeviceInterruptMode::PciMsiIrq
272 | DeviceInterruptMode::PciMsixIrq => {
273 let group = &self.intr_groups[self.current_idx];
274 if index >= group.len() || index >= self.msi_config.len() as u32 {
275 return Err(Error::from_raw_os_error(libc::EINVAL));
276 }
277 group.update(index, &self.msi_config[index as usize])?;
278 Ok(())
279 }
280 _ => Err(Error::from_raw_os_error(libc::EINVAL)),
281 }
282 }
283
284 fn get_configs(&self, mode: DeviceInterruptMode) -> &[InterruptSourceConfig] {
285 match mode {
286 #[cfg(feature = "legacy-irq")]
287 DeviceInterruptMode::LegacyIrq => &LEGACY_CONFIGS[..],
288 #[cfg(feature = "msi-irq")]
289 DeviceInterruptMode::GenericMsiIrq
290 | DeviceInterruptMode::PciMsiIrq
291 | DeviceInterruptMode::PciMsixIrq => {
292 let idx = self.mode2idx[mode as usize];
293 let group_len = self.intr_groups[idx].len() as usize;
294 &self.msi_config[0..group_len]
295 }
296 _ => panic!("unhandled interrupt type in get_configs()"),
297 }
298 }
299
300 fn reset_configs(&mut self, mode: DeviceInterruptMode) {
301 match mode {
302 #[cfg(feature = "msi-irq")]
303 DeviceInterruptMode::GenericMsiIrq
304 | DeviceInterruptMode::PciMsiIrq
305 | DeviceInterruptMode::PciMsixIrq => {
306 self.msi_config = vec![
307 InterruptSourceConfig::MsiIrq(MsiIrqSourceConfig::default());
308 self.msi_config.len()
309 ];
310 }
311 _ => {}
312 }
313 }
314}
315
316#[cfg(feature = "msi-irq")]
317impl<T: InterruptManager> DeviceInterruptManager<T> {
318 #[allow(irrefutable_let_patterns)]
320 pub fn set_msi_high_address(&mut self, index: u32, data: u32) -> Result<()> {
321 if (index as usize) < self.msi_config.len() {
322 if let InterruptSourceConfig::MsiIrq(ref mut msi) = self.msi_config[index as usize] {
323 msi.high_addr = data;
324 return Ok(());
325 }
326 }
327 Err(Error::from_raw_os_error(libc::EINVAL))
328 }
329
330 #[allow(irrefutable_let_patterns)]
332 pub fn set_msi_low_address(&mut self, index: u32, data: u32) -> Result<()> {
333 if (index as usize) < self.msi_config.len() {
334 if let InterruptSourceConfig::MsiIrq(ref mut msi) = self.msi_config[index as usize] {
335 msi.low_addr = data;
336 return Ok(());
337 }
338 }
339 Err(Error::from_raw_os_error(libc::EINVAL))
340 }
341
342 #[allow(irrefutable_let_patterns)]
344 pub fn set_msi_data(&mut self, index: u32, data: u32) -> Result<()> {
345 if (index as usize) < self.msi_config.len() {
346 if let InterruptSourceConfig::MsiIrq(ref mut msi) = self.msi_config[index as usize] {
347 msi.data = data;
348 return Ok(());
349 }
350 }
351 Err(Error::from_raw_os_error(libc::EINVAL))
352 }
353
354 #[allow(irrefutable_let_patterns)]
356 pub fn set_msi_mask(&mut self, index: u32, mask: bool) -> Result<()> {
357 if (index as usize) < self.msi_config.len() {
358 if let InterruptSourceConfig::MsiIrq(ref mut msi) = self.msi_config[index as usize] {
359 let mut msg_ctl = msi.msg_ctl;
360 msg_ctl &= !MSI_INT_MASK;
361 if mask {
362 msg_ctl |= MSI_INT_MASK;
363 }
364 msi.msg_ctl = msg_ctl;
365 return Ok(());
366 }
367 }
368 Err(Error::from_raw_os_error(libc::EINVAL))
369 }
370
371 #[allow(irrefutable_let_patterns)]
373 pub fn get_msi_mask(&self, index: u32) -> Result<bool> {
374 if (index as usize) < self.msi_config.len() {
375 if let InterruptSourceConfig::MsiIrq(ref msi) = self.msi_config[index as usize] {
376 return Ok((msi.msg_ctl & MSI_INT_MASK) == MSI_INT_MASK);
377 }
378 }
379 Err(Error::from_raw_os_error(libc::EINVAL))
380 }
381
382 #[cfg(target_arch = "aarch64")]
383 pub fn set_msi_device_id(&mut self, index: u32) -> Result<()> {
385 if (index as usize) < self.msi_config.len() {
386 if let InterruptSourceConfig::MsiIrq(ref mut msi) = self.msi_config[index as usize] {
387 msi.device_id = self.device_id.map(|dev_id| {
388 dev_id << MSI_DEVICE_ID_SHIFT
393 });
394 return Ok(());
395 }
396 }
397 Err(Error::from_raw_os_error(libc::EINVAL))
398 }
399
400 fn resize_msi_config_space(&mut self, size: u32) {
401 if self.msi_config.len() < size as usize {
402 self.msi_config =
403 vec![InterruptSourceConfig::MsiIrq(MsiIrqSourceConfig::default()); size as usize];
404 }
405 }
406}
407
408#[derive(Default, Debug)]
410pub struct InterruptStatusRegister32 {
411 status: AtomicU32,
412}
413
414impl InterruptStatusRegister32 {
415 pub fn new() -> Self {
417 InterruptStatusRegister32 {
418 status: AtomicU32::new(0),
419 }
420 }
421
422 pub fn read(&self) -> u32 {
424 self.status.load(Ordering::SeqCst)
425 }
426
427 pub fn write(&self, value: u32) {
429 self.status.store(value, Ordering::SeqCst);
430 }
431
432 pub fn read_and_clear(&self) -> u32 {
434 self.status.swap(0, Ordering::SeqCst)
435 }
436
437 pub fn set_bits(&self, value: u32) {
439 self.status.fetch_or(value, Ordering::SeqCst);
440 }
441
442 pub fn clear_bits(&self, value: u32) {
444 self.status.fetch_and(!value, Ordering::SeqCst);
445 }
446}
447
448#[cfg(all(test, feature = "kvm-legacy-irq", feature = "kvm-msi-irq"))]
449pub(crate) mod tests {
450 use std::sync::Arc;
451
452 use dbs_device::resources::{DeviceResources, MsiIrqType, Resource};
453 use kvm_ioctls::{Kvm, VmFd};
454
455 use super::*;
456 use crate::KvmIrqManager;
457
458 pub(crate) fn create_vm_fd() -> VmFd {
459 let kvm = Kvm::new().unwrap();
460 kvm.create_vm().unwrap()
461 }
462
463 fn create_init_resources() -> DeviceResources {
464 let mut resources = DeviceResources::new();
465
466 resources.append(Resource::MmioAddressRange {
467 base: 0xd000_0000,
468 size: 0x10_0000,
469 });
470 resources.append(Resource::LegacyIrq(0));
471 resources.append(Resource::MsiIrq {
472 ty: MsiIrqType::GenericMsi,
473 base: 0x200,
474 size: 0x10,
475 });
476 resources.append(Resource::MsiIrq {
477 ty: MsiIrqType::PciMsi,
478 base: 0x100,
479 size: 0x20,
480 });
481 resources.append(Resource::MsiIrq {
482 ty: MsiIrqType::PciMsix,
483 base: 0x300,
484 size: 0x30,
485 });
486
487 resources
488 }
489
490 fn create_interrupt_manager() -> DeviceInterruptManager<Arc<KvmIrqManager>> {
491 let vmfd = Arc::new(create_vm_fd());
492 #[cfg(target_arch = "x86_64")]
493 vmfd.create_irq_chip().unwrap();
494 #[cfg(target_arch = "aarch64")]
495 let _ = dbs_arch::gic::create_gic(&vmfd, 1);
496 let intr_mgr = Arc::new(KvmIrqManager::new(vmfd));
497
498 let resource = create_init_resources();
499 intr_mgr.initialize().unwrap();
500 DeviceInterruptManager::new(intr_mgr, &resource).unwrap()
501 }
502
503 #[test]
504 fn test_create_device_interrupt_manager() {
505 let mut mgr = create_interrupt_manager();
506
507 assert_eq!(mgr.mode, DeviceInterruptMode::Disabled);
508 assert!(!mgr.activated);
509 assert_eq!(mgr.current_idx, usize::MAX);
510 assert_eq!(mgr.intr_groups.len(), 4);
511 assert!(!mgr.is_enabled());
512 assert!(mgr.get_group().is_none());
513
514 mgr.enable().unwrap();
516 assert!(mgr.is_enabled());
517 assert_eq!(
518 mgr.mode2idx[DeviceInterruptMode::LegacyIrq as usize],
519 mgr.current_idx
520 );
521 assert!(mgr.get_group().is_some());
522 assert_eq!(
523 mgr.get_group_unchecked().interrupt_type(),
524 InterruptSourceType::LegacyIrq
525 );
526
527 mgr.reset().unwrap();
529 assert!(!mgr.is_enabled());
530 assert_eq!(
531 mgr.mode2idx[DeviceInterruptMode::LegacyIrq as usize],
532 mgr.current_idx
533 );
534 assert_eq!(mgr.get_working_mode(), DeviceInterruptMode::Disabled);
535 assert!(mgr.get_group().is_none());
536 }
537
538 #[test]
539 fn test_device_interrupt_manager_switch_mode() {
540 let mut mgr = create_interrupt_manager();
541
542 mgr.enable().unwrap();
544 mgr.set_working_mode(DeviceInterruptMode::PciMsiIrq)
545 .unwrap_err();
546 mgr.set_working_mode(DeviceInterruptMode::PciMsixIrq)
547 .unwrap_err();
548 mgr.set_working_mode(DeviceInterruptMode::GenericMsiIrq)
549 .unwrap_err();
550 mgr.reset().unwrap();
551
552 mgr.set_working_mode(DeviceInterruptMode::LegacyIrq)
554 .unwrap();
555 mgr.set_working_mode(DeviceInterruptMode::LegacyIrq)
556 .unwrap();
557 mgr.set_working_mode(DeviceInterruptMode::PciMsiIrq)
558 .unwrap();
559 mgr.set_working_mode(DeviceInterruptMode::PciMsiIrq)
560 .unwrap();
561 mgr.set_working_mode(DeviceInterruptMode::PciMsixIrq)
562 .unwrap_err();
563 mgr.set_working_mode(DeviceInterruptMode::GenericMsiIrq)
564 .unwrap_err();
565
566 mgr.set_working_mode(DeviceInterruptMode::LegacyIrq)
568 .unwrap();
569 mgr.set_working_mode(DeviceInterruptMode::PciMsixIrq)
570 .unwrap();
571 mgr.set_working_mode(DeviceInterruptMode::PciMsixIrq)
572 .unwrap();
573 mgr.set_working_mode(DeviceInterruptMode::PciMsiIrq)
574 .unwrap_err();
575 mgr.set_working_mode(DeviceInterruptMode::GenericMsiIrq)
576 .unwrap_err();
577
578 mgr.set_working_mode(DeviceInterruptMode::LegacyIrq)
580 .unwrap();
581 mgr.set_working_mode(DeviceInterruptMode::GenericMsiIrq)
582 .unwrap();
583 mgr.set_working_mode(DeviceInterruptMode::GenericMsiIrq)
584 .unwrap();
585 mgr.set_working_mode(DeviceInterruptMode::PciMsiIrq)
586 .unwrap_err();
587 mgr.set_working_mode(DeviceInterruptMode::PciMsixIrq)
588 .unwrap_err();
589
590 mgr.set_working_mode(DeviceInterruptMode::Disabled).unwrap();
592 mgr.set_working_mode(DeviceInterruptMode::Disabled).unwrap();
593 mgr.set_working_mode(DeviceInterruptMode::PciMsiIrq)
594 .unwrap();
595 mgr.set_working_mode(DeviceInterruptMode::PciMsixIrq)
596 .unwrap_err();
597 mgr.set_working_mode(DeviceInterruptMode::GenericMsiIrq)
598 .unwrap_err();
599
600 mgr.set_working_mode(DeviceInterruptMode::Disabled).unwrap();
602 mgr.set_working_mode(DeviceInterruptMode::PciMsixIrq)
603 .unwrap();
604 mgr.set_working_mode(DeviceInterruptMode::PciMsiIrq)
605 .unwrap_err();
606 mgr.set_working_mode(DeviceInterruptMode::GenericMsiIrq)
607 .unwrap_err();
608
609 mgr.set_working_mode(DeviceInterruptMode::Disabled).unwrap();
611 mgr.set_working_mode(DeviceInterruptMode::GenericMsiIrq)
612 .unwrap();
613 mgr.set_working_mode(DeviceInterruptMode::PciMsiIrq)
614 .unwrap_err();
615 mgr.set_working_mode(DeviceInterruptMode::PciMsixIrq)
616 .unwrap_err();
617
618 mgr.set_working_mode(DeviceInterruptMode::Disabled).unwrap();
619 mgr.set_working_mode(DeviceInterruptMode::Disabled).unwrap();
620 }
621
622 #[test]
623 fn test_msi_config() {
624 let mut interrupt_manager = create_interrupt_manager();
625
626 assert!(interrupt_manager.set_msi_data(512, 0).is_err());
627 interrupt_manager.set_msi_data(0, 0).unwrap();
628 assert!(interrupt_manager.set_msi_high_address(512, 0).is_err());
629 interrupt_manager.set_msi_high_address(0, 0).unwrap();
630 assert!(interrupt_manager.set_msi_low_address(512, 0).is_err());
631 interrupt_manager.set_msi_low_address(0, 0).unwrap();
632 assert!(interrupt_manager.get_msi_mask(512).is_err());
633 assert!(!interrupt_manager.get_msi_mask(0).unwrap());
634 assert!(interrupt_manager.set_msi_mask(512, true).is_err());
635 interrupt_manager.set_msi_mask(0, true).unwrap();
636 assert!(interrupt_manager.get_msi_mask(0).unwrap());
637 }
638
639 #[test]
640 fn test_set_working_mode_after_activated() {
641 let mut interrupt_manager = create_interrupt_manager();
642 interrupt_manager.activated = true;
643 assert!(interrupt_manager
644 .set_working_mode(DeviceInterruptMode::Disabled)
645 .is_err());
646 assert!(interrupt_manager
647 .set_working_mode(DeviceInterruptMode::GenericMsiIrq)
648 .is_err());
649 assert!(interrupt_manager
650 .set_working_mode(DeviceInterruptMode::LegacyIrq)
651 .is_err());
652 assert!(interrupt_manager
653 .set_working_mode(DeviceInterruptMode::PciMsiIrq)
654 .is_err());
655 assert!(interrupt_manager
656 .set_working_mode(DeviceInterruptMode::PciMsixIrq)
657 .is_err());
658 }
659
660 #[test]
661 fn test_disable2legacy() {
662 let mut interrupt_manager = create_interrupt_manager();
663 interrupt_manager.activated = false;
664 interrupt_manager.mode = DeviceInterruptMode::Disabled;
665 interrupt_manager
666 .set_working_mode(DeviceInterruptMode::LegacyIrq)
667 .unwrap();
668 }
669
670 #[test]
671 fn test_disable2nonlegacy() {
672 let mut interrupt_manager = create_interrupt_manager();
673 interrupt_manager.activated = false;
674 interrupt_manager.mode = DeviceInterruptMode::Disabled;
675 interrupt_manager
676 .set_working_mode(DeviceInterruptMode::GenericMsiIrq)
677 .unwrap();
678 }
679
680 #[test]
681 fn test_legacy2nonlegacy() {
682 let mut interrupt_manager = create_interrupt_manager();
683 interrupt_manager.activated = false;
684 interrupt_manager.mode = DeviceInterruptMode::Disabled;
685 interrupt_manager
686 .set_working_mode(DeviceInterruptMode::LegacyIrq)
687 .unwrap();
688 interrupt_manager
689 .set_working_mode(DeviceInterruptMode::GenericMsiIrq)
690 .unwrap();
691 }
692
693 #[test]
694 fn test_nonlegacy2legacy() {
695 let mut interrupt_manager = create_interrupt_manager();
696 interrupt_manager.activated = false;
697 interrupt_manager.mode = DeviceInterruptMode::Disabled;
698 interrupt_manager
699 .set_working_mode(DeviceInterruptMode::GenericMsiIrq)
700 .unwrap();
701 interrupt_manager
702 .set_working_mode(DeviceInterruptMode::LegacyIrq)
703 .unwrap();
704 }
705
706 #[test]
707 fn test_update() {
708 let mut interrupt_manager = create_interrupt_manager();
709 interrupt_manager
710 .set_working_mode(DeviceInterruptMode::GenericMsiIrq)
711 .unwrap();
712 interrupt_manager.enable().unwrap();
713 assert!(interrupt_manager.update(0x10).is_err());
714 interrupt_manager.update(0x01).unwrap();
715 interrupt_manager.reset().unwrap();
716 interrupt_manager
717 .set_working_mode(DeviceInterruptMode::LegacyIrq)
718 .unwrap();
719 assert!(interrupt_manager.update(0x10).is_err());
720 }
721
722 #[test]
723 fn test_get_configs() {
724 {
726 let interrupt_manager = create_interrupt_manager();
727
728 let legacy_config = interrupt_manager.get_configs(DeviceInterruptMode::LegacyIrq);
729 assert_eq!(legacy_config, LEGACY_CONFIGS);
730 }
731
732 {
734 let mut interrupt_manager = create_interrupt_manager();
735 interrupt_manager
736 .set_working_mode(DeviceInterruptMode::GenericMsiIrq)
737 .unwrap();
738 let msi_config = interrupt_manager.get_configs(DeviceInterruptMode::GenericMsiIrq);
739 assert_eq!(msi_config.len(), 0x10);
740 }
741
742 {
744 let mut interrupt_manager = create_interrupt_manager();
745 interrupt_manager
746 .set_working_mode(DeviceInterruptMode::PciMsiIrq)
747 .unwrap();
748 let msi_config = interrupt_manager.get_configs(DeviceInterruptMode::PciMsiIrq);
749 assert_eq!(msi_config.len(), 0x20);
750 }
751
752 {
754 let mut interrupt_manager = create_interrupt_manager();
755 interrupt_manager
756 .set_working_mode(DeviceInterruptMode::PciMsixIrq)
757 .unwrap();
758 let msi_config = interrupt_manager.get_configs(DeviceInterruptMode::PciMsixIrq);
759 assert_eq!(msi_config.len(), 0x30);
760 }
761 }
762
763 #[test]
764 fn test_reset_configs() {
765 let mut interrupt_manager = create_interrupt_manager();
766
767 interrupt_manager.reset_configs(DeviceInterruptMode::LegacyIrq);
768 interrupt_manager.reset_configs(DeviceInterruptMode::LegacyIrq);
769
770 interrupt_manager.set_msi_data(0, 100).unwrap();
771 interrupt_manager.set_msi_high_address(0, 200).unwrap();
772 interrupt_manager.set_msi_low_address(0, 300).unwrap();
773
774 interrupt_manager.reset_configs(DeviceInterruptMode::GenericMsiIrq);
775 assert_eq!(
776 interrupt_manager.msi_config[0],
777 InterruptSourceConfig::MsiIrq(MsiIrqSourceConfig::default())
778 );
779 }
780
781 #[test]
782 fn test_interrupt_status_register() {
783 let status = InterruptStatusRegister32::new();
784
785 assert_eq!(status.read(), 0);
786 status.write(0x13);
787 assert_eq!(status.read(), 0x13);
788 status.clear_bits(0x11);
789 assert_eq!(status.read(), 0x2);
790 status.set_bits(0x100);
791 assert_eq!(status.read_and_clear(), 0x102);
792 assert_eq!(status.read(), 0);
793 }
794}