gcrecomp_runtime/memory/
dma.rs1use 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}