1use core::sync::atomic::{Ordering, fence};
8
9use crate::{dma::aligned::InternalMemory, reg_access::VolatileCell};
10
11pub const MAX_FRAME_SIZE: usize = 1524;
13pub const MIN_RX_FRAME_SIZE: usize = 14;
15
16pub const TDES0_OWN: u32 = 1 << 31;
20pub const TDES0_IC: u32 = 1 << 30;
22pub const TDES0_LS: u32 = 1 << 29;
24pub const TDES0_FS: u32 = 1 << 28;
26pub const TDES0_CIC_FULL: u32 = 3 << 22;
29pub const TDES0_CHAINED: u32 = 1 << 20;
31
32pub const RDES0_OWN: u32 = 1 << 31;
36pub const RDES0_FL_SHIFT: u32 = 16;
38pub const RDES0_FL_MASK: u32 = 0x3fff << RDES0_FL_SHIFT;
40pub const RDES0_ES: u32 = 1 << 15;
42pub const RDES0_FS: u32 = 1 << 9;
44pub const RDES0_LS: u32 = 1 << 8;
46
47pub const RDES1_BUF1_SIZE_MASK: u32 = 0x1fff;
49pub const RDES1_CHAINED: u32 = 1 << 14;
51
52cfg_select! {
58 esp32p4 => {
59 pub const RDES0_ESA: u32 = 1 << 0;
61 pub const RDES4_IP_HEADER_ERROR: u32 = 1 << 3;
63 pub const RDES4_IP_PAYLOAD_ERROR: u32 = 1 << 4;
65 pub const RDES4_IP_CHECKSUM_BYPASSED: u32 = 1 << 5;
67 pub const RDES4_IPV4_PACKET: u32 = 1 << 6;
69 pub const RDES4_IPV6_PACKET: u32 = 1 << 7;
71 }
72 _ => {}
73}
74
75#[derive(Clone, Copy, Debug, Eq, PartialEq)]
79pub enum OwnedBy {
80 Cpu,
82 Dma,
84}
85
86#[repr(C)]
91pub struct TDes {
92 pub(super) tdes0: VolatileCell<u32>,
93 pub(super) tdes1: VolatileCell<u32>,
94 pub(super) buf_addr: VolatileCell<u32>,
95 pub(super) next_desc: VolatileCell<u32>,
96 _tdes4: VolatileCell<u32>,
98 _tdes5: VolatileCell<u32>,
99 _tdes6: VolatileCell<u32>,
100 _tdes7: VolatileCell<u32>,
101}
102
103impl TDes {
104 pub const fn new_zeroed() -> Self {
106 Self {
107 tdes0: VolatileCell::new(0),
108 tdes1: VolatileCell::new(0),
109 buf_addr: VolatileCell::new(0),
110 next_desc: VolatileCell::new(0),
111 _tdes4: VolatileCell::new(0),
112 _tdes5: VolatileCell::new(0),
113 _tdes6: VolatileCell::new(0),
114 _tdes7: VolatileCell::new(0),
115 }
116 }
117
118 pub fn owned_by(&self) -> OwnedBy {
120 if self.tdes0.get() & TDES0_OWN != 0 {
121 OwnedBy::Dma
122 } else {
123 OwnedBy::Cpu
124 }
125 }
126
127 pub fn set_owned_by(&mut self, owner: OwnedBy) {
129 let v = self.tdes0.get();
130 self.tdes0.set(match owner {
131 OwnedBy::Cpu => v & !TDES0_OWN,
132 OwnedBy::Dma => v | TDES0_OWN,
133 });
134 }
135
136 fn set_chained(&mut self) {
137 self.tdes0.set(self.tdes0.get() | TDES0_CHAINED);
138 }
139
140 fn set_len_and_flags(&mut self, len: usize) {
141 self.tdes1.set(len as u32 & RDES1_BUF1_SIZE_MASK);
142 self.tdes0.set(
143 (self.tdes0.get() & TDES0_CHAINED) | TDES0_FS | TDES0_LS | TDES0_IC | TDES0_CIC_FULL,
144 );
145 }
146
147 fn set_buffer_addr(&mut self, addr: *const u8) {
148 self.buf_addr.set(addr as u32);
149 }
150
151 fn set_next_desc(&mut self, addr: *const TDes) {
152 self.next_desc.set(addr as u32);
153 }
154}
155
156#[repr(C)]
160pub struct RDes {
161 pub(super) rdes0: VolatileCell<u32>,
162 pub(super) rdes1: VolatileCell<u32>,
163 pub(super) buf_addr: VolatileCell<u32>,
164 pub(super) next_desc: VolatileCell<u32>,
165 #[cfg_attr(
167 not(esp32p4),
168 allow(dead_code, reason = "only read for P4 RX checksum offload")
169 )]
170 rdes4: VolatileCell<u32>,
171 _rdes5: VolatileCell<u32>,
172 _rdes6: VolatileCell<u32>,
173 _rdes7: VolatileCell<u32>,
174}
175
176impl RDes {
177 pub const fn new_zeroed() -> Self {
179 Self {
180 rdes0: VolatileCell::new(0),
181 rdes1: VolatileCell::new(0),
182 buf_addr: VolatileCell::new(0),
183 next_desc: VolatileCell::new(0),
184 rdes4: VolatileCell::new(0),
185 _rdes5: VolatileCell::new(0),
186 _rdes6: VolatileCell::new(0),
187 _rdes7: VolatileCell::new(0),
188 }
189 }
190
191 pub fn owned_by(&self) -> OwnedBy {
193 if self.rdes0.get() & RDES0_OWN != 0 {
194 OwnedBy::Dma
195 } else {
196 OwnedBy::Cpu
197 }
198 }
199
200 fn set_rdes0(&mut self, value: u32) {
201 self.rdes0.set(value);
202 }
203
204 fn set_owned_by(&mut self, owner: OwnedBy) {
205 let v = self.rdes0.get();
206 self.set_rdes0(match owner {
207 OwnedBy::Cpu => v & !RDES0_OWN,
208 OwnedBy::Dma => v | RDES0_OWN,
209 });
210 }
211
212 fn is_complete_frame(&self) -> bool {
213 let s = self.rdes0.get();
214 s & RDES0_FS != 0 && s & RDES0_LS != 0
215 }
216
217 fn frame_len(&self) -> usize {
218 ((self.rdes0.get() & RDES0_FL_MASK) >> RDES0_FL_SHIFT) as usize
219 }
220
221 #[cfg(esp32p4)]
229 fn checksum_error(&self) -> bool {
230 if self.rdes0.get() & RDES0_ESA == 0 {
232 return false;
233 }
234
235 let ext = self.rdes4.get();
236
237 let is_ip = ext & (RDES4_IPV4_PACKET | RDES4_IPV6_PACKET) != 0;
239 let bypassed = ext & RDES4_IP_CHECKSUM_BYPASSED != 0;
241
242 is_ip && !bypassed && ext & (RDES4_IP_HEADER_ERROR | RDES4_IP_PAYLOAD_ERROR) != 0
243 }
244
245 fn configure_buffer(&mut self, size: usize) {
246 self.rdes1.set(
247 (self.rdes1.get() & !RDES1_BUF1_SIZE_MASK)
248 | (size as u32 & RDES1_BUF1_SIZE_MASK)
249 | RDES1_CHAINED,
250 );
251 }
252
253 fn set_buffer_addr(&mut self, addr: *const u8) {
254 self.buf_addr.set(addr as u32);
255 }
256
257 fn set_next_desc(&mut self, addr: *const RDes) {
258 self.next_desc.set(addr as u32);
259 }
260}
261
262pub struct EthernetDmaStorage<const RX: usize, const TX: usize> {
269 pub(super) rx_descs: [InternalMemory<RDes>; RX],
270 pub(super) tx_descs: [InternalMemory<TDes>; TX],
271 pub(super) rx_bufs: [InternalMemory<[u8; MAX_FRAME_SIZE]>; RX],
272 pub(super) tx_bufs: [InternalMemory<[u8; MAX_FRAME_SIZE]>; TX],
273}
274
275impl<const RX: usize, const TX: usize> Default for EthernetDmaStorage<RX, TX> {
276 fn default() -> Self {
277 Self::new()
278 }
279}
280
281impl<const RX: usize, const TX: usize> EthernetDmaStorage<RX, TX> {
282 pub const fn new() -> Self {
284 Self {
285 rx_descs: [const { InternalMemory::new(RDes::new_zeroed()) }; RX],
286 tx_descs: [const { InternalMemory::new(TDes::new_zeroed()) }; TX],
287 rx_bufs: [const { InternalMemory::new([0u8; MAX_FRAME_SIZE]) }; RX],
288 tx_bufs: [const { InternalMemory::new([0u8; MAX_FRAME_SIZE]) }; TX],
289 }
290 }
291}
292
293unsafe impl<const RX: usize, const TX: usize> Send for EthernetDmaStorage<RX, TX> {}
296unsafe impl<const RX: usize, const TX: usize> Sync for EthernetDmaStorage<RX, TX> {}
297
298pub struct TDesRing<'a> {
302 descriptors: &'a mut [InternalMemory<TDes>],
303 buffers: &'a mut [InternalMemory<[u8; MAX_FRAME_SIZE]>],
304 index: usize,
305}
306
307impl<'a> TDesRing<'a> {
308 pub fn new(
310 descriptors: &'a mut [InternalMemory<TDes>],
311 buffers: &'a mut [InternalMemory<[u8; MAX_FRAME_SIZE]>],
312 ) -> Self {
313 assert!(!descriptors.is_empty());
314 assert_eq!(descriptors.len(), buffers.len());
315
316 let mut ring = Self {
317 descriptors,
318 buffers,
319 index: 0,
320 };
321 ring.reset();
322 ring
323 }
324
325 pub(crate) fn len(&self) -> usize {
326 self.descriptors.len()
327 }
328
329 pub fn reset(&mut self) {
333 let n = self.descriptors.len();
334 for i in 0..n {
335 let next = self.descriptors[(i + 1) % n].as_ptr();
336 let buf_addr = self.buffers[i].as_ptr().cast::<u8>();
337
338 let mut desc = self.descriptors[i].get_mut();
339 desc.tdes0.set(0);
340 desc.tdes1.set(0);
341 desc.set_chained();
342 desc.set_buffer_addr(buf_addr);
343 desc.set_next_desc(next);
344 desc.set_owned_by(OwnedBy::Cpu);
345 #[cfg(soc_internal_memory_cached)]
346 self.descriptors[i].get_mut().writeback();
347 }
348 self.index = 0;
349 fence(Ordering::Release);
350 }
351
352 pub fn base_ptr(&self) -> *const TDes {
354 self.descriptors[0].as_ptr()
355 }
356
357 pub fn transmit(&mut self, frame: &[u8]) -> Result<(), TxError> {
362 if frame.len() > MAX_FRAME_SIZE {
363 return Err(TxError::FrameTooLarge);
364 }
365
366 if let Some(buf) = self.available_buf() {
367 buf[..frame.len()].copy_from_slice(frame);
368 self.commit(frame.len());
369 Ok(())
370 } else {
371 Err(TxError::RingFull)
372 }
373 }
374
375 pub fn has_capacity(&self) -> bool {
377 let desc = self.descriptors[self.index].get_ref();
378 #[cfg(soc_internal_memory_cached)]
379 desc.invalidate();
380 fence(Ordering::Acquire);
381 desc.owned_by() == OwnedBy::Cpu
382 }
383
384 pub fn available_buf(&mut self) -> Option<&mut [u8; MAX_FRAME_SIZE]> {
389 if self.has_capacity() {
390 let idx = self.index;
391 Some(self.buffers[idx].get_mut().into_inner())
392 } else {
393 None
394 }
395 }
396
397 pub fn commit(&mut self, len: usize) {
403 let idx = self.index;
404 let n = self.descriptors.len();
405
406 #[cfg(soc_internal_memory_cached)]
407 self.buffers[idx].get_mut().writeback();
408
409 let mut desc = self.descriptors[idx].get_mut();
410 desc.set_len_and_flags(len);
411 desc.set_owned_by(OwnedBy::Dma);
412
413 #[cfg(soc_internal_memory_cached)]
414 desc.writeback();
415
416 fence(Ordering::Release);
417 self.index = (idx + 1) % n;
418 }
419}
420
421#[derive(Clone, Copy, Debug, Eq, PartialEq)]
423pub enum TxError {
424 RingFull,
426 FrameTooLarge,
428}
429
430pub struct RDesRing<'a> {
434 descriptors: &'a mut [InternalMemory<RDes>],
435 buffers: &'a mut [InternalMemory<[u8; MAX_FRAME_SIZE]>],
436 index: usize,
437}
438
439impl<'a> RDesRing<'a> {
440 pub fn new(
442 descriptors: &'a mut [InternalMemory<RDes>],
443 buffers: &'a mut [InternalMemory<[u8; MAX_FRAME_SIZE]>],
444 ) -> Self {
445 assert!(!descriptors.is_empty());
446 assert_eq!(descriptors.len(), buffers.len());
447
448 let mut ring = Self {
449 descriptors,
450 buffers,
451 index: 0,
452 };
453 ring.reset();
454 ring
455 }
456
457 pub fn reset(&mut self) {
461 let n = self.descriptors.len();
462 for i in 0..n {
463 let next = self.descriptors[(i + 1) % n].as_ptr();
464 let buf_addr = self.buffers[i].as_ptr().cast::<u8>();
465
466 #[cfg(soc_internal_memory_cached)]
467 self.buffers[i].get_mut().invalidate();
468
469 let mut desc = self.descriptors[i].get_mut();
470 desc.rdes0.set(0);
471 desc.configure_buffer(MAX_FRAME_SIZE);
472 desc.set_buffer_addr(buf_addr);
473 desc.set_next_desc(next);
474 desc.set_owned_by(OwnedBy::Dma);
475 #[cfg(soc_internal_memory_cached)]
476 desc.writeback();
477 }
478 self.index = 0;
479 fence(Ordering::Release);
480 }
481
482 pub fn base_ptr(&self) -> *const RDes {
484 self.descriptors[0].as_ptr()
485 }
486
487 pub fn receive(&mut self) -> Option<&mut [u8]> {
494 loop {
495 let idx = self.index;
496
497 let len = {
501 let desc = self.descriptors[idx].get_ref();
502 #[cfg(soc_internal_memory_cached)]
503 desc.invalidate();
504 fence(Ordering::Acquire);
505 if desc.owned_by() != OwnedBy::Cpu {
506 return None;
507 }
508
509 let status = desc.rdes0.get();
510 let is_complete = desc.is_complete_frame();
511 let frame_len = desc.frame_len();
512
513 let checksum_bad = cfg_select! {
517 esp32p4 => desc.checksum_error(),
518 _ => false,
519 };
520
521 if status & RDES0_ES != 0 || !is_complete || checksum_bad {
522 None
523 } else {
524 let len = frame_len.saturating_sub(4);
526 if (MIN_RX_FRAME_SIZE..=MAX_FRAME_SIZE).contains(&len) {
527 Some(len)
528 } else {
529 None
530 }
531 }
532 };
533
534 let Some(len) = len else {
535 self.recycle_current();
536 continue;
537 };
538
539 #[cfg(soc_internal_memory_cached)]
540 self.buffers[idx].get_mut().invalidate();
541 fence(Ordering::Acquire);
542 return Some(&mut self.buffers[idx].get_mut().into_inner()[..len]);
543 }
544 }
545
546 pub fn pop(&mut self) {
550 self.recycle_current();
551 }
552
553 pub fn has_packet(&self) -> bool {
555 let desc = self.descriptors[self.index].get_ref();
556 #[cfg(soc_internal_memory_cached)]
557 desc.invalidate();
558 fence(Ordering::Acquire);
559 desc.owned_by() == OwnedBy::Cpu
560 }
561
562 fn recycle_current(&mut self) {
563 let idx = self.index;
564 let n = self.descriptors.len();
565 let mut desc = self.descriptors[idx].get_mut();
566 desc.set_rdes0(RDES0_OWN);
567 #[cfg(soc_internal_memory_cached)]
568 desc.writeback();
569 fence(Ordering::Release);
570 self.index = (idx + 1) % n;
571 }
572}