twizzler_driver/dma/
pin.rs1use std::ops::Index;
2
3use crate::arch::DMA_PAGE_SIZE;
4
5#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Hash, Default)]
6pub struct PhysAddr(pub u64);
8
9#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Hash)]
10pub struct PhysInfo {
12 addr: PhysAddr,
13}
14
15pub struct DmaPinIter<'a> {
17 pin: &'a [PhysInfo],
18 idx: usize,
19}
20
21pub struct DmaPin<'a> {
23 pub backing: &'a [PhysInfo],
24}
25
26impl<'a> DmaPin<'a> {
27 pub(super) fn new(backing: &'a [PhysInfo]) -> Self {
28 Self { backing }
29 }
30
31 pub fn len(&self) -> usize {
32 self.backing.len()
33 }
34}
35
36impl PhysInfo {
37 pub fn new(addr: PhysAddr) -> Self {
38 Self { addr }
39 }
40
41 pub fn addr(&self) -> PhysAddr {
43 self.addr
44 }
45}
46
47impl From<PhysInfo> for u64 {
48 fn from(p: PhysInfo) -> Self {
49 p.addr.into()
50 }
51}
52
53impl From<&PhysInfo> for u64 {
54 fn from(p: &PhysInfo) -> Self {
55 p.addr.into()
56 }
57}
58
59impl From<PhysAddr> for u64 {
60 fn from(p: PhysAddr) -> Self {
61 p.0
62 }
63}
64
65impl TryFrom<u64> for PhysAddr {
66 type Error = ();
67
68 fn try_from(value: u64) -> Result<Self, Self::Error> {
69 if value & (DMA_PAGE_SIZE as u64 - 1) != 0 {
70 return Err(());
71 }
72 Ok(Self(value))
73 }
74}
75
76impl<'a> IntoIterator for DmaPin<'a> {
77 type Item = PhysInfo;
78
79 type IntoIter = DmaPinIter<'a>;
80
81 fn into_iter(self) -> Self::IntoIter {
82 DmaPinIter {
83 pin: self.backing,
84 idx: 0,
85 }
86 }
87}
88
89impl<'a> Iterator for DmaPinIter<'a> {
90 type Item = PhysInfo;
91
92 fn next(&mut self) -> Option<Self::Item> {
93 if self.idx >= self.pin.len() {
94 None
95 } else {
96 let ret = self.pin[self.idx];
97 self.idx += 1;
98 Some(ret)
99 }
100 }
101}
102
103impl<'a> Index<usize> for DmaPin<'a> {
104 type Output = PhysInfo;
105
106 fn index(&self, index: usize) -> &Self::Output {
107 &self.backing[index]
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use crate::dma::{Access, DmaOptions, DmaPool};
114
115 #[test]
116 fn pin_kaction() {
117 let pool = DmaPool::new(
118 DmaPool::default_spec(),
119 Access::BiDirectional,
120 DmaOptions::default(),
121 );
122 let mut reg = pool.allocate(0u32).unwrap();
123 let pin = reg.pin().unwrap();
124 for phys in pin {
125 let addr = phys.addr();
126 let addr: u64 = addr.into();
127 assert!(addr & 0xfff == 0);
128 assert_ne!(addr, 0);
129 }
130 }
131}