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)]
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#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Hash)]
112pub enum PinError {
114 InternalError,
116 Exhausted,
118}
119
120#[cfg(test)]
121mod tests {
122 use crate::dma::{Access, DmaOptions, DmaPool};
123
124 #[test]
125 fn pin_kaction() {
126 let pool = DmaPool::new(
127 DmaPool::default_spec(),
128 Access::BiDirectional,
129 DmaOptions::default(),
130 );
131 let mut reg = pool.allocate(0u32).unwrap();
132 let pin = reg.pin().unwrap();
133 for phys in pin {
134 let addr = phys.addr();
135 let addr: u64 = addr.into();
136 assert!(addr & 0xfff == 0);
137 assert_ne!(addr, 0);
138 }
139 }
140}