Skip to main content

os/drivers/
plic.rs

1#[allow(clippy::upper_case_acronyms)]
2pub struct PLIC {
3    base_addr: usize,
4}
5
6#[derive(Copy, Clone)]
7pub enum IntrTargetPriority {
8    Machine = 0,
9    Supervisor = 1,
10}
11
12impl IntrTargetPriority {
13    pub fn supported_number() -> usize {
14        2
15    }
16}
17
18impl PLIC {
19    fn priority_ptr(&self, intr_source_id: usize) -> *mut u32 {
20        assert!(intr_source_id > 0 && intr_source_id <= 132);
21        (self.base_addr + intr_source_id * 4) as *mut u32
22    }
23    fn hart_id_with_priority(hart_id: usize, target_priority: IntrTargetPriority) -> usize {
24        let priority_num = IntrTargetPriority::supported_number();
25        hart_id * priority_num + target_priority as usize
26    }
27    fn enable_ptr(
28        &self,
29        hart_id: usize,
30        target_priority: IntrTargetPriority,
31        intr_source_id: usize,
32    ) -> (*mut u32, usize) {
33        let id = Self::hart_id_with_priority(hart_id, target_priority);
34        let (reg_id, reg_shift) = (intr_source_id / 32, intr_source_id % 32);
35        (
36            (self.base_addr + 0x2000 + 0x80 * id + 0x4 * reg_id) as *mut u32,
37            reg_shift,
38        )
39    }
40    fn threshold_ptr_of_hart_with_priority(
41        &self,
42        hart_id: usize,
43        target_priority: IntrTargetPriority,
44    ) -> *mut u32 {
45        let id = Self::hart_id_with_priority(hart_id, target_priority);
46        (self.base_addr + 0x20_0000 + 0x1000 * id) as *mut u32
47    }
48    fn claim_comp_ptr_of_hart_with_priority(
49        &self,
50        hart_id: usize,
51        target_priority: IntrTargetPriority,
52    ) -> *mut u32 {
53        let id = Self::hart_id_with_priority(hart_id, target_priority);
54        (self.base_addr + 0x20_0004 + 0x1000 * id) as *mut u32
55    }
56    pub unsafe fn new(base_addr: usize) -> Self {
57        Self { base_addr }
58    }
59    pub fn set_priority(&mut self, intr_source_id: usize, priority: u32) {
60        assert!(priority < 8);
61        unsafe {
62            self.priority_ptr(intr_source_id).write_volatile(priority);
63        }
64    }
65    #[allow(unused)]
66    pub fn get_priority(&mut self, intr_source_id: usize) -> u32 {
67        unsafe { self.priority_ptr(intr_source_id).read_volatile() & 7 }
68    }
69    pub fn enable(
70        &mut self,
71        hart_id: usize,
72        target_priority: IntrTargetPriority,
73        intr_source_id: usize,
74    ) {
75        let (reg_ptr, shift) = self.enable_ptr(hart_id, target_priority, intr_source_id);
76        unsafe {
77            reg_ptr.write_volatile(reg_ptr.read_volatile() | 1 << shift);
78        }
79    }
80    #[allow(unused)]
81    pub fn disable(
82        &mut self,
83        hart_id: usize,
84        target_priority: IntrTargetPriority,
85        intr_source_id: usize,
86    ) {
87        let (reg_ptr, shift) = self.enable_ptr(hart_id, target_priority, intr_source_id);
88        unsafe {
89            reg_ptr.write_volatile(reg_ptr.read_volatile() & (!(1u32 << shift)));
90        }
91    }
92    pub fn set_threshold(
93        &mut self,
94        hart_id: usize,
95        target_priority: IntrTargetPriority,
96        threshold: u32,
97    ) {
98        assert!(threshold < 8);
99        let threshold_ptr = self.threshold_ptr_of_hart_with_priority(hart_id, target_priority);
100        unsafe {
101            threshold_ptr.write_volatile(threshold);
102        }
103    }
104    #[allow(unused)]
105    pub fn get_threshold(&mut self, hart_id: usize, target_priority: IntrTargetPriority) -> u32 {
106        let threshold_ptr = self.threshold_ptr_of_hart_with_priority(hart_id, target_priority);
107        unsafe { threshold_ptr.read_volatile() & 7 }
108    }
109    pub fn claim(&mut self, hart_id: usize, target_priority: IntrTargetPriority) -> u32 {
110        let claim_comp_ptr = self.claim_comp_ptr_of_hart_with_priority(hart_id, target_priority);
111        unsafe { claim_comp_ptr.read_volatile() }
112    }
113    pub fn complete(
114        &mut self,
115        hart_id: usize,
116        target_priority: IntrTargetPriority,
117        completion: u32,
118    ) {
119        let claim_comp_ptr = self.claim_comp_ptr_of_hart_with_priority(hart_id, target_priority);
120        unsafe {
121            claim_comp_ptr.write_volatile(completion);
122        }
123    }
124}