use super::config::FlowControlConfig;
use super::emac::Emac;
use crate::internal::register::mac::MacRegs;
impl<const RX_BUFS: usize, const TX_BUFS: usize, const BUF_SIZE: usize>
Emac<RX_BUFS, TX_BUFS, BUF_SIZE>
{
fn apply_flow_control(&mut self, enable: bool) {
if enable {
let fc = &self.config.flow_control;
MacRegs::configure_flow_control(
fc.pause_time,
fc.pause_low_threshold as u8,
fc.unicast_pause_detect,
true, true, );
} else {
MacRegs::configure_flow_control(0, 0, false, false, false);
self.flow_control_active = false;
}
}
pub fn enable_flow_control(&mut self, enable: bool) {
self.config.flow_control.enabled = enable;
self.apply_flow_control(enable && self.peer_pause_ability);
}
pub fn set_peer_pause_ability(&mut self, ability: bool) {
self.peer_pause_ability = ability;
self.apply_flow_control(self.config.flow_control.enabled && ability);
}
pub fn check_flow_control(&mut self) -> bool {
if !self.config.flow_control.enabled || !self.peer_pause_ability {
return false;
}
let fc = &self.config.flow_control;
let free_descriptors = self.dma.rx_free_count();
let frames_remain = self.rx_frames_waiting() > 0;
if !self.flow_control_active && free_descriptors < fc.low_water_mark && frames_remain {
MacRegs::send_pause_frame(true);
self.flow_control_active = true;
return true;
}
if self.flow_control_active && (free_descriptors > fc.high_water_mark || !frames_remain) {
MacRegs::send_pause_frame(false);
self.flow_control_active = false;
return true;
}
false
}
#[inline(always)]
pub fn is_flow_control_active(&self) -> bool {
self.flow_control_active
}
#[inline(always)]
pub fn flow_control_config(&self) -> &FlowControlConfig {
&self.config.flow_control
}
#[inline(always)]
pub fn peer_pause_ability(&self) -> bool {
self.peer_pause_ability
}
}