1#![allow(non_snake_case, non_upper_case_globals)]
7
8use crate::{ral, vcell::VCell};
9
10#[repr(C)]
11pub struct Td {
12 NEXT: VCell<u32>,
13 TOKEN: VCell<u32>,
14 BUFFER_POINTERS: [VCell<u32>; 5],
15 last_transfer_size: usize,
17}
18
19impl Td {
20 pub const fn new() -> Self {
21 Td {
22 NEXT: VCell::new(0),
23 TOKEN: VCell::new(0),
24 BUFFER_POINTERS: [
25 VCell::new(0),
26 VCell::new(0),
27 VCell::new(0),
28 VCell::new(0),
29 VCell::new(0),
30 ],
31 last_transfer_size: 0,
32 }
33 }
34
35 pub fn set_buffer(&mut self, ptr: *mut u8, size: usize) {
41 ral::modify_reg!(crate::td, self, TOKEN, TOTAL_BYTES: size as u32);
42 self.last_transfer_size = size;
43
44 if size != 0 {
45 const PTR_ALIGNMENT: u32 = 4096;
46 const PTR_MASK: u32 = !(PTR_ALIGNMENT - 1);
47
48 self.BUFFER_POINTERS[0].write(ptr as u32);
49 for idx in 1..self.BUFFER_POINTERS.len() {
50 let mut ptr = self.BUFFER_POINTERS[idx - 1].read();
51 ptr &= PTR_MASK;
52 ptr += PTR_ALIGNMENT;
53 self.BUFFER_POINTERS[idx].write(ptr);
54 }
55 } else {
56 for buffer_pointer in self.BUFFER_POINTERS.iter_mut() {
57 buffer_pointer.write(0);
58 }
59 }
60 }
61
62 pub fn bytes_transferred(&self) -> usize {
64 let total_bytes = ral::read_reg!(crate::td, self, TOKEN, TOTAL_BYTES) as usize;
65 self.last_transfer_size - total_bytes
66 }
67
68 pub fn status(&self) -> Status {
70 let status = ral::read_reg!(crate::td, self, TOKEN, STATUS);
71 Status::from_bits_truncate(status)
72 }
73
74 pub fn clear_status(&mut self) {
76 ral::modify_reg!(crate::td, self, TOKEN, STATUS: 0);
77 }
78
79 pub fn set_terminate(&mut self) {
82 ral::write_reg!(crate::td, self, NEXT, 1);
83 }
84
85 pub fn set_next(&mut self, next: *const Td) {
87 ral::write_reg!(crate::td, self, NEXT, next as u32);
88 }
89
90 pub fn set_active(&mut self) {
92 ral::modify_reg!(crate::td, self, TOKEN, STATUS: ACTIVE);
93 }
94
95 pub fn set_interrupt_on_complete(&mut self, ioc: bool) {
98 ral::modify_reg!(crate::td, self, TOKEN, IOC: ioc as u32);
99 }
100
101 pub fn clean_invalidate_dcache(&self) {
103 crate::cache::clean_invalidate_dcache_by_address(
104 &self as *const _ as usize,
105 core::mem::size_of_val(self),
106 );
107 }
108}
109
110bitflags::bitflags! {
111 pub(crate) struct Status : u32 {
112 const ACTIVE = TOKEN::STATUS::RW::ACTIVE;
113 const HALTED = TOKEN::STATUS::RW::HALTED;
114 const DATA_BUFFER_ERROR = TOKEN::STATUS::RW::DATA_BUFFER_ERROR;
115 const TRANSACTION_ERROR = TOKEN::STATUS::RW::TRANSACTION_ERROR;
116 }
117}
118
119mod TOKEN {
120 pub mod STATUS {
121 pub const offset: u32 = 0;
122 pub const mask: u32 = 0xFF << offset;
123 pub mod RW {
124 pub const ACTIVE: u32 = 1 << 7;
125 pub const HALTED: u32 = 1 << 6;
126 pub const DATA_BUFFER_ERROR: u32 = 1 << 5;
127 pub const TRANSACTION_ERROR: u32 = 1 << 3;
128 }
129 pub mod R {}
130 pub mod W {}
131 }
132 pub mod IOC {
133 pub const offset: u32 = 15;
134 pub const mask: u32 = 1 << offset;
135 pub mod RW {}
136 pub mod R {}
137 pub mod W {}
138 }
139 pub mod TOTAL_BYTES {
140 pub const offset: u32 = 16;
141 pub const mask: u32 = 0x7FFF << offset;
142 pub mod RW {}
143 pub mod R {}
144 pub mod W {}
145 }
146}
147
148#[cfg(test)]
149mod test {
150 use super::Td;
151 use crate::ral;
152
153 #[test]
154 fn terminate() {
155 let mut td = Td::new();
156 td.set_terminate();
157 assert_eq!(td.NEXT.read(), 1);
158 }
159
160 #[test]
161 fn next() {
162 let mut td = Td::new();
163 td.set_terminate();
164
165 let other = u32::max_value() & !(31);
166 td.set_next(other as *const _);
167 assert_eq!(td.NEXT.read(), other);
168 }
169
170 #[test]
171 fn status() {
172 let mut td = Td::new();
173 ral::write_reg!(super, &mut td, TOKEN, STATUS: u32::max_value());
174 assert_eq!(td.TOKEN.read(), 0b11111111);
175 }
176
177 #[test]
178 fn ioc() {
179 let mut td = Td::new();
180 ral::write_reg!(super, &mut td, TOKEN, IOC: u32::max_value());
181 assert_eq!(td.TOKEN.read(), 1 << 15);
182 }
183
184 #[test]
185 fn total_bytes() {
186 let mut td = Td::new();
187 ral::write_reg!(super, &mut td, TOKEN, TOTAL_BYTES: u32::max_value());
188 assert_eq!(td.TOKEN.read(), 0x7FFF << 16);
189 }
190
191 #[test]
192 fn set_buffer() {
193 let mut td = Td::new();
194 let mut buffer = [0; 32];
195 td.set_buffer(buffer.as_mut_ptr(), buffer.len());
196 assert_eq!(td.NEXT.read(), 0);
197 assert_eq!(td.TOKEN.read(), (32 << 16));
198 assert!(td.status().is_empty());
199 for buffer_pointer in td.BUFFER_POINTERS.iter() {
200 assert!(buffer_pointer.read() != 0);
201 }
202 }
203}
204
205#[cfg(target_arch = "arm")]
206const _: [(); 1] = [(); (core::mem::size_of::<Td>() == 32) as usize];