pub mod id; use id::{identify_phy, PhyIdentifier}; mod status; pub use status::Status; mod control; pub use control::Control; pub trait PhyAccess { fn read_phy(&mut self, addr: u8, reg: u8) -> u16; fn write_phy(&mut self, addr: u8, reg: u8, data: u16); } #[derive(Clone)] pub struct Phy { pub addr: u8, device: PhyDevice, } #[derive(Clone, Copy)] pub enum PhyDevice { Marvel88E1116R, Rtl8211E, } const OUI_MARVEL: u32 = 0x005043; 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) { Some(PhyIdentifier { oui: OUI_MARVEL, model: 36, .. }) => Some(PhyDevice::Marvel88E1116R), Some(PhyIdentifier { oui: OUI_REALTEK, model: 0b010001, rev: 0b0101, }) => Some(PhyDevice::Rtl8211E), _ => None, }; match device { Some(device) => return Some(Phy { addr, device }), None => {} } } None } pub fn name(&self) -> &'static str { match self.device { PhyDevice::Marvel88E1116R => &"Marvel 88E1116R", PhyDevice::Rtl8211E => &"RTL8211E", } } pub fn read_reg(&self, pa: &mut PA) -> PR where PA: PhyAccess, PR: PhyRegister + From, { pa.read_phy(self.addr, PR::addr()).into() } pub fn modify_reg(&self, pa: &mut PA, mut f: F) where PA: PhyAccess, PR: PhyRegister + From + Into, F: FnMut(PR) -> PR, { let reg = pa.read_phy(self.addr, PR::addr()).into(); let reg = f(reg); pa.write_phy(self.addr, PR::addr(), reg.into()) } pub fn modify_control(&self, pa: &mut PA, f: F) where PA: PhyAccess, F: FnMut(Control) -> Control, { self.modify_reg(pa, f) } pub fn get_control(&self, pa: &mut PA) -> Control { self.read_reg(pa) } pub fn get_status(&self, pa: &mut PA) -> Status { self.read_reg(pa) } } pub trait PhyRegister { fn addr() -> u8; }