sparreal_kernel/irq/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use alloc::{collections::btree_map::BTreeMap, sync::Arc, vec::Vec};
use driver_interface::{irq::Trigger, DeviceId};
use log::{debug, info, warn};

use crate::{
    driver::{irq_chip_by_id_or_first, irq_chip_list, DriverIrqChip},
    platform,
    sync::RwLock,
};

type Handler = Arc<dyn Fn(usize) -> IrqHandle>;

static IRQ_VECTOR: RwLock<Vector> = RwLock::new(Vector::new());

struct VectorPerIrq(BTreeMap<DeviceId, Handler>);
struct VectorPerCpu(BTreeMap<usize, VectorPerIrq>);
struct Vector(BTreeMap<usize, VectorPerCpu>);

unsafe impl Send for Vector {}
unsafe impl Sync for Vector {}

#[allow(unused)]
impl Vector {
    const fn new() -> Self {
        Self(BTreeMap::new())
    }

    fn insert(&mut self, cpu_id: usize, irq_num: usize, dev_id: DeviceId, handler: Handler) {
        self.0
            .entry(cpu_id)
            .or_insert(VectorPerCpu(BTreeMap::new()))
            .0
            .entry(irq_num)
            .or_insert(VectorPerIrq(BTreeMap::new()))
            .0
            .insert(dev_id, handler);
    }

    fn remove(&mut self, cpu_id: usize, irq_num: usize, dev_id: DeviceId) {
        self.0
            .get_mut(&cpu_id)
            .and_then(|one| one.0.get_mut(&irq_num))
            .and_then(|one| one.0.remove(&dev_id));
    }

    fn get_handle_stack(&self, irq_num: usize) -> Vec<Handler> {
        let cpu_id = unsafe { platform::cpu_id() } as usize;
        self.0
            .get(&cpu_id)
            .and_then(|map| map.0.get(&irq_num))
            .map(|map| map.0.iter().map(|(_, h)| h.clone()).collect::<Vec<_>>())
            .unwrap_or_default()
    }
}

fn vector_cpu_set_handle(cpu_id: usize, irq_num: usize, dev_id: DeviceId, handler: Handler) {
    IRQ_VECTOR.write().insert(cpu_id, irq_num, dev_id, handler);
}
pub fn irq_set_handle(
    irq_num: usize,
    dev_id: DeviceId,
    handler: impl Fn(usize) -> IrqHandle + 'static,
) {
    let handler = Arc::new(handler);
    vector_cpu_set_handle(unsafe { platform::cpu_id() } as _, irq_num, dev_id, handler);
}

pub enum IrqHandle {
    Handled,
    None,
}

#[derive(Debug, Clone)]
pub struct IrqConfig {
    pub irq: usize,
    pub trigger: Trigger,
    pub priority: usize,
    pub cpu_list: Vec<u64>,
}
pub fn irq_setup(irq: usize, dev_id: DeviceId, trigger: Trigger) {
    //TODO
    let controller_id = DeviceId::default();

    if let Some(chip) = irq_chip_by_id_or_first(controller_id) {
        info!(
            "[{}]Enable irq {} on chip: {} ",
            dev_id, irq, chip.desc.name
        );
        let mut c = chip.spec.write();
        c.irq_enable(irq);
        c.set_priority(irq, 0);
        c.set_trigger(irq, trigger);
    }
}

pub fn register_irq(
    cfg: IrqConfig,
    dev_id: DeviceId,
    handler: impl Fn(usize) -> IrqHandle + 'static,
) {
    irq_set_handle(cfg.irq, dev_id, handler);

    //TODO
    let controller_id = DeviceId::default();

    if let Some(chip) = irq_chip_by_id_or_first(controller_id) {
        info!(
            "[{}]Enable irq {} on chip: {} ",
            dev_id, cfg.irq, chip.desc.name
        );
        let mut c = chip.spec.write();
        c.irq_enable(cfg.irq);
        c.set_priority(cfg.irq, cfg.priority);
        c.set_trigger(cfg.irq, cfg.trigger);
    }
}

fn get_chip() -> Option<DriverIrqChip> {
    irq_chip_list().first().cloned()
}

pub fn handle_irq() {
    if let Some(chip) = get_chip() {
        let c = chip.spec.read();

        let irq_id = c.get_and_acknowledge_interrupt();
        if let Some(irq_id) = irq_id {
            handle_irq_by_id(irq_id);
            c.end_interrupt(irq_id);
        }
    }
}

fn handle_irq_by_id(irq_id: usize) {
    debug!("irq {}", irq_id);
    let stack = { IRQ_VECTOR.read().get_handle_stack(irq_id) };

    for handler in stack {
        match handler(irq_id) {
            IrqHandle::Handled => {
                return;
            }
            IrqHandle::None => {}
        }
    }

    warn!("Irq {} not handled", irq_id);
}