eth_igb/ring/
rx.rs

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        // Program the descriptor base address with the address of the region.
25        self.reg_write(RDBAL, (bus_addr & 0xFFFFFFFF) as u32);
26        self.reg_write(RDBAH, (bus_addr >> 32) as u32);
27
28        // Set the length register to the size of the descriptor ring.
29        self.reg_write(RDLEN, size_bytes as u32);
30
31        let pkt_size_kb = self.pkt_size / 1024;
32
33        // Program SRRCTL of the queue according to the size of the buffers and the required header handling.
34        self.reg_write(
35            SRRCTL,
36            (SRRCTL::DESCTYPE::AdvancedOneBuffer + SRRCTL::BSIZEPACKET.val(pkt_size_kb as _)).value,
37        );
38
39        // If header split or header replication is required for this queue,
40        // program the PSRTYPE register according to the required headers.
41        // 暂时不需要头部分割
42
43        self.reg_write(RDH, 0);
44        self.reg_write(RDT, 0);
45
46        // Enable the queue by setting RXDCTL.ENABLE. In the case of queue zero,
47        // the enable bit is set by default - so the ring parameters should be set before RCTL.RXEN is set.
48        // 使用推荐的阈值:PTHRESH=8, HTHRESH=8, WTHRESH=1
49        self.enable_queue();
50
51        // Poll the RXDCTL register until the ENABLE bit is set.
52        // The tail should not be bumped before this bit was read as one.
53
54        wait_for(
55            || self.reg_read(RXDCTL) & RXDCTL::ENABLE::Enabled.value > 0,
56            Duration::from_millis(1),
57            Some(1000),
58        )?;
59
60        // Program the direction of packets to this queue according to the mode select in MRQC.
61        // Packets directed to a disabled queue is dropped.
62        // 暂时不配置 MRQC
63
64        // Note: The tail register of the queue (RDT[n]) should not be bumped until the queue is enabled.
65        // self.update_tail(self.descriptors.len() - 1);
66        Ok(())
67    }
68
69    pub fn enable_queue(&mut self) {
70        // 启用队列
71        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        // 禁用队列
83        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 flush_descriptors(&mut self) {
94    //     // 触发描述符写回刷新
95    //     self.reg_write(
96    //         RXDCTL,
97    //         (RXDCTL::PTHRESH.val(8)
98    //             + RXDCTL::HTHRESH.val(8)
99    //             + RXDCTL::WTHRESH.val(1)
100    //             + RXDCTL::ENABLE::Enabled
101    //             + RXDCTL::SWFLUSH.val(1))
102    //         .value,
103    //     );
104    // }
105
106    /// 获取当前头部指针值
107    pub fn get_head(&self) -> u32 {
108        self.reg_read(RDH)
109    }
110
111    /// 获取当前尾部指针值
112    pub fn get_tail(&self) -> u32 {
113        self.reg_read(RDT)
114    }
115
116    /// 更新尾部指针
117    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; // 没有可用的缓冲区
168        }
169        let len;
170        unsafe {
171            let desc = &self.this().descriptors[index];
172            // 检查描述符是否已完成
173            if !desc.write.is_done() {
174                trace!("RxRing: next_pkt descriptor not done at index: {index}");
175                return None; // 描述符未完成,无法获取数据
176            }
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); // 没有可用的缓冲区
199        }
200
201        // 更新描述符
202        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        // 更新尾部指针
209        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        // 在释放时禁用队列
227        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}