diff --git a/libboard_zynq/src/eth/mod.rs b/libboard_zynq/src/eth/mod.rs index e329053..5bd49c3 100644 --- a/libboard_zynq/src/eth/mod.rs +++ b/libboard_zynq/src/eth/mod.rs @@ -610,17 +610,15 @@ impl EthInner { Some(link) => { info!("eth: got {:?}", link); - use phy::LinkSpeed::*; + use phy::{LinkDuplex::Full, LinkSpeed::*}; let txclock = match link.speed { S10 => TX_10, S100 => TX_100, S1000 => TX_1000, }; GEM::setup_clock(txclock); - /* .full_duplex(false) doesn't work even if - half duplex has been negotiated. */ GEM::regs().net_cfg.modify(|_, w| w - .full_duplex(true) + .full_duplex(link.duplex == Full) .gige_en(link.speed == S1000) .speed(link.speed != S10) ); diff --git a/libboard_zynq/src/eth/phy/extended_status.rs b/libboard_zynq/src/eth/phy/extended_status.rs deleted file mode 100644 index b6c132b..0000000 --- a/libboard_zynq/src/eth/phy/extended_status.rs +++ /dev/null @@ -1,59 +0,0 @@ -use bit_field::BitField; -use super::{PhyRegister, Link, LinkDuplex, LinkSpeed}; - -#[derive(Clone, Copy, Debug)] -/// 1000Base-T Extended Status Register -pub struct ExtendedStatus(pub u16); - -impl ExtendedStatus { - pub fn cap_1000base_t_half(&self) -> bool { - self.0.get_bit(12) - } - pub fn cap_1000base_t_full(&self) -> bool { - self.0.get_bit(13) - } - pub fn cap_1000base_x_half(&self) -> bool { - self.0.get_bit(14) - } - pub fn cap_1000base_x_full(&self) -> bool { - self.0.get_bit(15) - } - - pub fn get_link(&self) -> Option { - if self.cap_1000base_t_half() { - Some(Link { - speed: LinkSpeed::S1000, - duplex: LinkDuplex::Half, - }) - } else if self.cap_1000base_t_full() { - Some(Link { - speed: LinkSpeed::S1000, - duplex: LinkDuplex::Full, - }) - } else if self.cap_1000base_x_half() { - Some(Link { - speed: LinkSpeed::S1000, - duplex: LinkDuplex::Half, - }) - } else if self.cap_1000base_x_full() { - Some(Link { - speed: LinkSpeed::S1000, - duplex: LinkDuplex::Full, - }) - } else { - None - } - } -} - -impl PhyRegister for ExtendedStatus { - fn addr() -> u8 { - 0xF - } -} - -impl From for ExtendedStatus { - fn from(value: u16) -> Self { - ExtendedStatus(value) - } -} diff --git a/libboard_zynq/src/eth/phy/mod.rs b/libboard_zynq/src/eth/phy/mod.rs index e3ff0f8..e9c0923 100644 --- a/libboard_zynq/src/eth/phy/mod.rs +++ b/libboard_zynq/src/eth/phy/mod.rs @@ -2,10 +2,10 @@ pub mod id; use id::{identify_phy, PhyIdentifier}; mod status; pub use status::Status; -mod extended_status; -pub use extended_status::ExtendedStatus; mod control; pub use control::Control; +mod pssr; +pub use pssr::PSSR; #[derive(Clone, Debug, PartialEq)] pub struct Link { @@ -49,8 +49,8 @@ const OUI_REALTEK: u32 = 0x000732; impl Phy { /// Probe all addresses on MDIO for a known PHY pub fn find(pa: &mut PA) -> Option { - for addr in 1..32 { - let device = match identify_phy(pa, addr) { + (1..32).filter_map(|addr| { + match identify_phy(pa, addr) { Some(PhyIdentifier { oui: OUI_MARVELL, model: 36, @@ -62,15 +62,8 @@ impl Phy { rev: 0b0101, }) => Some(PhyDevice::Rtl8211E), _ => None, - }; - match device { - Some(device) => - return Some(Phy { addr, device }), - None => {} - } - } - - None + }.map(|device| Phy { addr, device }) + }).next() } pub fn name(&self) -> &'static str { @@ -120,12 +113,8 @@ impl Phy { if !status.link_status() { None } else if status.cap_1000base_t_extended_status() { - let ext_status: ExtendedStatus = self.read_reg(pa); - if let Some(link) = ext_status.get_link() { - Some(link) - } else { - status.get_link() - } + let phy_status: PSSR = self.read_reg(pa); + phy_status.get_link() } else { status.get_link() } diff --git a/libboard_zynq/src/eth/phy/pssr.rs b/libboard_zynq/src/eth/phy/pssr.rs new file mode 100644 index 0000000..8af525e --- /dev/null +++ b/libboard_zynq/src/eth/phy/pssr.rs @@ -0,0 +1,52 @@ +use bit_field::BitField; +use super::{PhyRegister, Link, LinkDuplex, LinkSpeed}; + +#[derive(Clone, Copy, Debug)] +/// PHY-Specific Status Register +pub struct PSSR(pub u16); + +impl PSSR { + pub fn link(&self) -> bool { + self.0.get_bit(10) + } + + pub fn duplex(&self) -> LinkDuplex { + if self.0.get_bit(13) { + LinkDuplex::Full + } else { + LinkDuplex::Half + } + } + + pub fn speed(&self) -> Option { + match self.0.get_bits(14..=15) { + 0b00 => Some(LinkSpeed::S10), + 0b01 => Some(LinkSpeed::S100), + 0b10 => Some(LinkSpeed::S1000), + _ => None, + } + } + + pub fn get_link(&self) -> Option { + if self.link() { + Some(Link { + speed: self.speed()?, + duplex: self.duplex(), + }) + } else { + None + } + } +} + +impl PhyRegister for PSSR { + fn addr() -> u8 { + 0x11 + } +} + +impl From for PSSR { + fn from(value: u16) -> Self { + PSSR(value) + } +}