From 79dc9a4fee613c8e930d94da8700c92e2417e314 Mon Sep 17 00:00:00 2001 From: Alex M Date: Tue, 11 Aug 2020 17:25:05 -0700 Subject: [PATCH] Add method to read PHY configuration. --- src/device.rs | 7 +++ src/register.rs | 123 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 126 insertions(+), 4 deletions(-) diff --git a/src/device.rs b/src/device.rs index 869520b..ee92e05 100644 --- a/src/device.rs +++ b/src/device.rs @@ -62,6 +62,13 @@ impl Device { None } + pub fn phy_config(&mut self) -> Result { + let mut phy = [0u8]; + self.bus + .read_frame(register::COMMON, register::common::PHY_CONFIG, &mut phy)?; + Ok(phy[0].into()) + } + pub fn into_interface(self) -> Interface { self.into() } diff --git a/src/register.rs b/src/register.rs index adfd64d..0c16deb 100644 --- a/src/register.rs +++ b/src/register.rs @@ -1,11 +1,126 @@ pub const COMMON: u8 = 0; pub mod common { + use bit_field::BitArray; + pub const MODE: u16 = 0x0; - pub const GATEWAY: u16 = 0x1; - pub const SUBNET_MASK: u16 = 0x5; - pub const MAC: u16 = 0x9; - pub const IP: u16 = 0xF; + pub const GATEWAY: u16 = 0x01; + pub const SUBNET_MASK: u16 = 0x05; + pub const MAC: u16 = 0x09; + pub const IP: u16 = 0x0F; + pub const PHY_CONFIG: u16 = 0x2E; pub const VERSION: u16 = 0x39; + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] + #[repr(u8)] + pub enum PhyOperationMode { + /// 10BT half-duplex. Auto-negotiation disabled. + HalfDuplex10bt = 0b000_000, + /// 10BT full-duplex. Auto-negotiation disabled. + FullDuplex10bt = 0b001_000, + /// 100BT half-duplex. Auto-negotiation disabled. + HalfDuplex100bt = 0b010_000, + /// 100BT full-duplex. Auto-negotiation disabled. + FullDuplex100bt = 0b011_000, + /// 100BT half-duplex. Auto-negotiation enabled. + HalfDuplex100btAuto = 0b100_000, + /// Power down mode. + PowerDown = 0b110_000, + /// All capable. Auto-negotiation enabled. + Auto = 0b111_000, + } + + impl From for u8 { + fn from(val: PhyOperationMode) -> u8 { + val as u8 + } + } + + impl Default for PhyOperationMode { + fn default() -> PhyOperationMode { + PhyOperationMode::Auto + } + } + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] + #[repr(u8)] + pub enum PhySpeedStatus { + /// 10Mbps based. + Mbps10 = 0, + /// 100Mbps based. + Mbps100 = 1, + } + + #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] + #[repr(u8)] + pub enum PhyDuplexStatus { + /// Half duplex. + HalfDuplex = 0, + /// Full duplex. + FullDuplex = 1, + } + + #[derive(Debug, Copy, Clone, Eq, PartialEq)] + pub struct PhyConfig([u8; 1]); + + impl PhyConfig { + // Link status bit position. + const LNK_POS: usize = 7; + // Speed status bit position. + const SPD_POS: usize = 6; + // Duplex status bit position. + const DPX_POS: usize = 5; + // Operation mode bit position. + // const OPMDC_POS = 2; + // Configure PHY opeartion mode bit position. + // const OPMD_POS = 1; + // Reset bit position. + // const RST_POS = 0; + + /// PHY link status. + /// + /// `true` if the link is up, `false` if the link is down. + pub fn link_up(&self) -> bool { + self.0.get_bit(Self::LNK_POS) + } + + /// PHY speed status. + pub fn speed(&self) -> PhySpeedStatus { + if !self.0.get_bit(Self::SPD_POS) { + PhySpeedStatus::Mbps10 + } else { + PhySpeedStatus::Mbps100 + } + } + + /// PHY duplex status. + pub fn duplex(&self) -> PhyDuplexStatus { + if !self.0.get_bit(Self::DPX_POS) { + PhyDuplexStatus::HalfDuplex + } else { + PhyDuplexStatus::FullDuplex + } + } + + /// PHY operation mode. + pub fn operation_mode(&self) -> PhyOperationMode { + match self.0[0] & 0b111_000u8 { + 0b000_000 => PhyOperationMode::HalfDuplex10bt, + 0b001_000 => PhyOperationMode::FullDuplex10bt, + 0b010_000 => PhyOperationMode::HalfDuplex100bt, + 0b011_000 => PhyOperationMode::FullDuplex100bt, + 0b100_000 => PhyOperationMode::HalfDuplex100btAuto, + 0b110_000 => PhyOperationMode::PowerDown, + 0b111_000 => PhyOperationMode::Auto, + _ => unreachable!(), + } + } + } + + impl core::convert::From for PhyConfig { + fn from(val: u8) -> Self { + PhyConfig([val]) + } + } } pub const SOCKET0: u8 = 0b000_00001;