Skip to main content

gcrecomp_runtime/memory/
dma.rs

1// DMA (Direct Memory Access) system
2use anyhow::Result;
3use std::sync::atomic::{AtomicBool, Ordering};
4use std::sync::Arc;
5
6pub struct DmaSystem {
7    channels: Vec<DmaChannel>,
8}
9
10pub struct DmaChannel {
11    active: Arc<AtomicBool>,
12    source: u32,
13    destination: u32,
14    length: u32,
15    callback: Option<Box<dyn Fn() + Send + Sync>>,
16}
17
18impl DmaSystem {
19    pub fn new() -> Self {
20        Self {
21            channels: (0..4)
22                .map(|_| DmaChannel {
23                    active: Arc::new(AtomicBool::new(false)),
24                    source: 0,
25                    destination: 0,
26                    length: 0,
27                    callback: None,
28                })
29                .collect(),
30        }
31    }
32
33    pub fn start_transfer(
34        &mut self,
35        channel: usize,
36        source: u32,
37        destination: u32,
38        length: u32,
39    ) -> Result<()> {
40        if channel >= self.channels.len() {
41            anyhow::bail!("Invalid DMA channel: {}", channel);
42        }
43
44        let ch = &mut self.channels[channel];
45        ch.source = source;
46        ch.destination = destination;
47        ch.length = length;
48        ch.active.store(true, Ordering::SeqCst);
49
50        Ok(())
51    }
52
53    pub fn is_active(&self, channel: usize) -> bool {
54        if channel < self.channels.len() {
55            self.channels[channel].active.load(Ordering::SeqCst)
56        } else {
57            false
58        }
59    }
60
61    pub fn complete_transfer(&mut self, channel: usize) {
62        if channel < self.channels.len() {
63            self.channels[channel].active.store(false, Ordering::SeqCst);
64            if let Some(callback) = &self.channels[channel].callback {
65                callback();
66            }
67        }
68    }
69}
70
71impl DmaChannel {
72    pub fn set_callback<F: Fn() + Send + Sync + 'static>(&mut self, callback: F) {
73        self.callback = Some(Box::new(callback));
74    }
75}