1use core::ops::{Deref, DerefMut};
2
3use super::*;
4use crate::{
5 DError,
6 descriptor::{AdvRxDesc, AdvRxDescRead},
7};
8use alloc::sync::Arc;
9use log::{error, trace};
10
11struct RingInner {
12 base: Ring<AdvRxDesc>,
13}
14
15impl RingInner {
16 fn new(ring: Ring<AdvRxDesc>) -> Result<Self, DError> {
17 Ok(Self { base: ring })
18 }
19
20 fn init(&mut self) -> Result<(), DError> {
21 let bus_addr = self.bus_addr();
22 let size_bytes = self.size_bytes();
23
24 self.reg_write(RDBAL, (bus_addr & 0xFFFFFFFF) as u32);
26 self.reg_write(RDBAH, (bus_addr >> 32) as u32);
27
28 self.reg_write(RDLEN, size_bytes as u32);
30
31 let pkt_size_kb = self.pkt_size / 1024;
32
33 self.reg_write(
35 SRRCTL,
36 (SRRCTL::DESCTYPE::AdvancedOneBuffer + SRRCTL::BSIZEPACKET.val(pkt_size_kb as _)).value,
37 );
38
39 self.reg_write(RDH, 0);
44 self.reg_write(RDT, 0);
45
46 self.enable_queue();
50
51 wait_for(
55 || self.reg_read(RXDCTL) & RXDCTL::ENABLE::Enabled.value > 0,
56 Duration::from_millis(1),
57 Some(1000),
58 )?;
59
60 Ok(())
67 }
68
69 pub fn enable_queue(&mut self) {
70 self.reg_write(
72 RXDCTL,
73 (RXDCTL::PTHRESH.val(8)
74 + RXDCTL::HTHRESH.val(8)
75 + RXDCTL::WTHRESH.val(1)
76 + RXDCTL::ENABLE::Enabled)
77 .value,
78 );
79 }
80
81 pub fn disable_queue(&mut self) {
82 self.reg_write(
84 RXDCTL,
85 (RXDCTL::PTHRESH.val(8)
86 + RXDCTL::HTHRESH.val(8)
87 + RXDCTL::WTHRESH.val(1)
88 + RXDCTL::ENABLE::Disabled)
89 .value,
90 );
91 }
92
93 pub fn get_head(&self) -> u32 {
108 self.reg_read(RDH)
109 }
110
111 pub fn get_tail(&self) -> u32 {
113 self.reg_read(RDT)
114 }
115
116 pub fn update_tail(&mut self, mut tail: usize) {
118 if tail == self.descriptors.len() {
119 tail = 0;
120 }
121 self.reg_write(RDT, tail as u32);
122 }
123}
124impl Deref for RingInner {
125 type Target = super::Ring<AdvRxDesc>;
126
127 fn deref(&self) -> &Self::Target {
128 &self.base
129 }
130}
131
132impl DerefMut for RingInner {
133 fn deref_mut(&mut self) -> &mut Self::Target {
134 &mut self.base
135 }
136}
137
138pub struct RxRing(Arc<UnsafeCell<RingInner>>);
139
140unsafe impl Send for RxRing {}
141
142impl RxRing {
143 #[allow(clippy::arc_with_non_send_sync)]
144 pub(crate) fn new(idx: usize, mmio_base: NonNull<u8>, size: usize) -> Result<Self, DError> {
145 let base = Ring::new(idx, mmio_base, size, PACKET_SIZE as usize)?;
146 let mut ring_inner = RingInner::new(base)?;
147 ring_inner.init()?;
148 let ring = Arc::new(UnsafeCell::new(ring_inner));
149 Ok(Self(ring))
150 }
151
152 fn this(&self) -> &RingInner {
153 unsafe { &*self.0.get() }
154 }
155 fn this_mut(&mut self) -> &mut RingInner {
156 unsafe { &mut *self.0.get() }
157 }
158
159 pub fn packet_size(&self) -> usize {
160 self.this().pkt_size
161 }
162
163 pub fn next_pkt(&mut self) -> Option<RxPacket<'_>> {
164 let index = self.next_index();
165 let head = self.this().get_head() as usize;
166 if head == index {
167 return None; }
169 let len;
170 unsafe {
171 let desc = &self.this().descriptors[index];
172 if !desc.write.is_done() {
174 trace!("RxRing: next_pkt descriptor not done at index: {index}");
175 return None; }
177 len = desc.write.packet_length() as usize;
178 }
179
180 trace!("RxRing: next_pkt index: {index}");
181 let request = self.this_mut().meta_ls[index]
182 .request
183 .take()
184 .expect("Request should be set");
185
186 Some(RxPacket {
187 ring: self,
188 request,
189 len,
190 })
191 }
192
193 pub fn submit(&mut self, request: Request) -> Result<(), DError> {
194 let index = self.this_mut().get_tail() as usize;
195 let ring = self.this_mut();
196 if index + 1 == ring.get_head() as usize {
197 error!("RxRing: submit no available buffer at index: {index}");
198 return Err(DError::NoMemory); }
200
201 let desc = AdvRxDesc {
203 read: AdvRxDescRead::new(request.bus_addr(), 0, false),
204 };
205 ring.descriptors.set(index, desc);
206 ring.meta_ls[index].request = Some(request);
207
208 ring.update_tail(index + 1);
210
211 Ok(())
212 }
213
214 fn next_index(&self) -> usize {
215 let ring = self.this();
216 (ring.get_tail() as usize + 1) % ring.count()
217 }
218
219 pub fn request_max_count(&self) -> usize {
220 self.this().count() - 1
221 }
222}
223
224impl Drop for RxRing {
225 fn drop(&mut self) {
226 self.this_mut().disable_queue();
228 }
229}
230
231pub struct RxPacket<'a> {
232 pub request: Request,
233 ring: &'a mut RxRing,
234 len: usize,
235}
236
237impl<'a> RxPacket<'a> {
238 pub fn re_submit(self) -> Result<(), DError> {
239 self.ring.submit(self.request)
240 }
241}
242
243impl Deref for RxPacket<'_> {
244 type Target = [u8];
245
246 fn deref(&self) -> &Self::Target {
247 &self.request.deref()[..self.len]
248 }
249}