forked from M-Labs/zynq-rs
eth rx: error handling
This commit is contained in:
parent
98947961c6
commit
6757ceb76c
|
@ -265,8 +265,12 @@ impl<RX, TX> Eth<RX, TX> {
|
||||||
.speed(true)
|
.speed(true)
|
||||||
.no_broadcast(false)
|
.no_broadcast(false)
|
||||||
.multi_hash_en(true)
|
.multi_hash_en(true)
|
||||||
// Promiscuous mode
|
// Promiscuous mode (TODO?)
|
||||||
.copy_all(true)
|
.copy_all(true)
|
||||||
|
// Remove 4-byte Frame CheckSum
|
||||||
|
.fcs_remove(true)
|
||||||
|
// One of the slower speeds
|
||||||
|
// TODO: calculate properly
|
||||||
.mdc_clk_div(0b110)
|
.mdc_clk_div(0b110)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -327,14 +331,73 @@ impl<RX, TX> Eth<RX, TX> {
|
||||||
new_self
|
new_self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pub fn start_tx<'tx>(self, tx_buffers: [&'tx [u8]; tx::DESCS]) -> Eth<RX, tx::DescList<'tx>> {
|
||||||
|
// let new_self = Eth {
|
||||||
|
// regs: self.regs,
|
||||||
|
// rx: self.rx,
|
||||||
|
// tx: tx::DescList::new(tx_buffers),
|
||||||
|
// };
|
||||||
|
// let list_addr = &new_self.tx as *const _ as u32;
|
||||||
|
// assert!(list_addr & 0b11 == 0);
|
||||||
|
// new_self.regs.tx_qbar.write(
|
||||||
|
// regs::TxQbar::zeroed()
|
||||||
|
// .tx_q_baseaddr(list_addr >> 2)
|
||||||
|
// );
|
||||||
|
// new_self.regs.net_ctrl.modify(|_, w|
|
||||||
|
// w.tx_en(true)
|
||||||
|
// );
|
||||||
|
// new_self
|
||||||
|
// }
|
||||||
|
|
||||||
fn wait_phy_idle(&self) {
|
fn wait_phy_idle(&self) {
|
||||||
while !self.regs.net_status.read().phy_mgmt_idle() {}
|
while !self.regs.net_status.read().phy_mgmt_idle() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'rx, TX> Eth<rx::DescList<'rx>, TX> {
|
impl<'rx, TX> Eth<rx::DescList<'rx>, TX> {
|
||||||
pub fn recv_next(&mut self) -> Option<rx::PktRef> {
|
pub fn recv_next(&mut self) -> Result<Option<rx::PktRef>, rx::Error> {
|
||||||
self.rx.recv_next()
|
let status = self.regs.rx_status.read();
|
||||||
|
if status.hresp_not_ok() {
|
||||||
|
// Clear
|
||||||
|
self.regs.rx_status.write(
|
||||||
|
regs::RxStatus::zeroed()
|
||||||
|
.hresp_not_ok(true)
|
||||||
|
);
|
||||||
|
return Err(rx::Error::HrespNotOk);
|
||||||
|
}
|
||||||
|
if status.rx_overrun() {
|
||||||
|
// Clear
|
||||||
|
self.regs.rx_status.write(
|
||||||
|
regs::RxStatus::zeroed()
|
||||||
|
.rx_overrun(true)
|
||||||
|
);
|
||||||
|
return Err(rx::Error::RxOverrun);
|
||||||
|
}
|
||||||
|
if status.buffer_not_avail() {
|
||||||
|
// Clear
|
||||||
|
self.regs.rx_status.write(
|
||||||
|
regs::RxStatus::zeroed()
|
||||||
|
.buffer_not_avail(true)
|
||||||
|
);
|
||||||
|
return Err(rx::Error::BufferNotAvail);
|
||||||
|
}
|
||||||
|
|
||||||
|
if status.frame_recd() {
|
||||||
|
let result = self.rx.recv_next();
|
||||||
|
match result {
|
||||||
|
Ok(None) => {
|
||||||
|
// No packet, clear status bit
|
||||||
|
self.regs.rx_status.write(
|
||||||
|
regs::RxStatus::zeroed()
|
||||||
|
.frame_recd(true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
use crate::{register, register_bit, register_bits, register_bits_typed, regs::*};
|
use crate::{register, register_bit, register_bits, register_bits_typed, regs::*};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
HrespNotOk,
|
||||||
|
RxOverrun,
|
||||||
|
BufferNotAvail,
|
||||||
|
Truncated,
|
||||||
|
}
|
||||||
|
|
||||||
/// Descriptor entry
|
/// Descriptor entry
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct DescEntry {
|
pub struct DescEntry {
|
||||||
|
@ -44,7 +52,6 @@ impl<'a> DescList<'a> {
|
||||||
let last = list.len().min(buffers.len()) - 1;
|
let last = list.len().min(buffers.len()) - 1;
|
||||||
for (i, (entry, buffer)) in list.iter_mut().zip(buffers.iter_mut()).enumerate() {
|
for (i, (entry, buffer)) in list.iter_mut().zip(buffers.iter_mut()).enumerate() {
|
||||||
let is_last = i == last;
|
let is_last = i == last;
|
||||||
assert!(buffer.len() >= 1536);
|
|
||||||
let buffer_addr = &mut buffer[0] as *mut _ as u32;
|
let buffer_addr = &mut buffer[0] as *mut _ as u32;
|
||||||
assert!(buffer_addr & 0b11 == 0);
|
assert!(buffer_addr & 0b11 == 0);
|
||||||
entry.word0.write(
|
entry.word0.write(
|
||||||
|
@ -69,13 +76,12 @@ impl<'a> DescList<'a> {
|
||||||
&self.list[0] as *const _ as u32
|
&self.list[0] as *const _ as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv_next<'s: 'p, 'p>(&'s mut self) -> Option<PktRef<'p>> {
|
pub fn recv_next<'s: 'p, 'p>(&'s mut self) -> Result<Option<PktRef<'p>>, Error> {
|
||||||
let list_len = self.list.len();
|
let list_len = self.list.len();
|
||||||
let entry = &mut self.list[self.next];
|
let entry = &mut self.list[self.next];
|
||||||
if entry.word0.read().used() {
|
if entry.word0.read().used() {
|
||||||
let len = entry.word1.read()
|
let word1 = entry.word1.read();
|
||||||
.frame_length_lsbs().into();
|
let len = word1.frame_length_lsbs().into();
|
||||||
// TODO: check no split pkt across multiple buffers
|
|
||||||
let buffer = &self.buffers[self.next][0..len];
|
let buffer = &self.buffers[self.next][0..len];
|
||||||
|
|
||||||
self.next += 1;
|
self.next += 1;
|
||||||
|
@ -83,9 +89,14 @@ impl<'a> DescList<'a> {
|
||||||
self.next = 0;
|
self.next = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(PktRef { entry, buffer })
|
let pkt = PktRef { entry, buffer };
|
||||||
|
if word1.start_of_frame() && word1.end_of_frame() {
|
||||||
|
Ok(Some(pkt))
|
||||||
|
} else {
|
||||||
|
Err(Error::Truncated)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
src/main.rs
13
src/main.rs
|
@ -98,9 +98,16 @@ fn main() {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match eth.recv_next() {
|
match eth.recv_next() {
|
||||||
None => {}
|
Ok(Some(pkt)) => {
|
||||||
Some(pkt) => {
|
print!("eth: rx {} bytes", pkt.len());
|
||||||
println!("eth: received {} bytes", pkt.len());
|
for b in pkt.iter() {
|
||||||
|
print!(" {:02X}", b);
|
||||||
|
}
|
||||||
|
println!("");
|
||||||
|
}
|
||||||
|
Ok(None) => {}
|
||||||
|
Err(e) => {
|
||||||
|
println!("eth rx error: {:?}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue