use super::{
Frames, IdRevision, Lan7800, Rx, Tx, AN_100_FULL, AN_10_FULL, BMCR_ANEG_ENABLE,
BMCR_ANEG_RESTART, BMCR_ISOLATE, BMCR_POWER_DOWN, BMSR_LINK_UP, FCT_RX_CTL_EN, FCT_TX_CTL_EN,
HW_CFG_CLK125_EN, HW_CFG_LED0_EN, HW_CFG_LED1_EN, HW_CFG_LRST, HW_CFG_MEF, HW_CFG_REFCLK25_EN,
MAC_CR_AUTO_DUPLEX, MAC_CR_AUTO_SPEED, MAC_CR_EEE_EN, MAC_CR_GMII_EN, MAC_RX_MAX_FRAME_SIZE,
MAC_RX_MAX_SIZE_MASK, MAC_RX_MAX_SIZE_SHIFT, MAC_RX_RXEN, MAC_TX_TXEN, MAF_HI_VALID,
MII_ACC_BUSY, MII_ACC_PHY_ADDR_SHIFT, MII_ACC_REG_SHIFT, MII_ACC_WRITE, MII_TIMEOUT_US,
PHY_ID_INTERNAL, PHY_REG_ADVERTISE, PHY_REG_CONTROL, PHY_REG_GIGABIT_CONTROL,
PHY_REG_LINK_PARTNER, PHY_REG_STATUS, PMT_CTL_PHY_RST, PMT_CTL_READY, READ_REGISTER,
REG_FCT_FLOW, REG_FCT_RX_CTL, REG_FCT_TX_CTL, REG_FLOW, REG_HW_CFG, REG_ID_REV, REG_INT_STS,
REG_MAC_CR, REG_MAC_RX, REG_MAC_TX, REG_MAF_HI0, REG_MAF_LO0, REG_MII_ACC, REG_MII_DATA,
REG_PMT_CTL, REG_RFE_CTL, REG_RX_ADDRH, REG_RX_ADDRL, REG_USB_CFG0, RESET_TIMEOUT_US,
RFE_CTL_BCAST_EN, RFE_CTL_DA_PERFECT, RFE_CTL_MCAST_EN, RFE_CTL_UCAST_EN, USB_CFG_BIR,
WRITE_REGISTER,
};
use crate::timer::Timer;
use crate::usb::control::{vendor_in_async, vendor_out_async};
use crate::usb::dwc2::{Channel, ControlEndpoint, TransferError};
pub struct Lan7800Rx<'a> {
endpoint: ControlEndpoint,
rx: &'a mut Rx,
}
pub struct Lan7800Tx<'a> {
endpoint: ControlEndpoint,
tx: &'a mut Tx,
}
impl Rx {
async fn receive_async(
&mut self,
device: ControlEndpoint,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<Frames<'_>, TransferError> {
let endpoint = self.endpoint(device);
let number = self.bulk_in.number;
let received = match channel
.bulk_in_async(
endpoint,
number,
&mut self.bulk_in.toggle,
&mut self.buffer.0,
timer,
)
.await
{
Ok(received) => received,
Err(TransferError::Nak) => 0,
Err(error) => return Err(error),
};
Ok(self.frames(received))
}
}
impl Tx {
async fn send_async(
&mut self,
device: ControlEndpoint,
channel: &mut Channel<'_>,
timer: &Timer,
frame: &[u8],
) -> Result<(), TransferError> {
let staged = self.stage(frame);
let endpoint = self.endpoint(device);
let number = self.bulk_out.number;
channel
.bulk_out_async(
endpoint,
number,
&mut self.bulk_out.toggle,
&self.buffer.0[..staged],
timer,
)
.await?;
Ok(())
}
}
impl Lan7800Rx<'_> {
pub async fn receive_frames_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<Frames<'_>, TransferError> {
self.rx.receive_async(self.endpoint, channel, timer).await
}
}
impl Lan7800Tx<'_> {
pub async fn send_frame_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
frame: &[u8],
) -> Result<(), TransferError> {
self.tx
.send_async(self.endpoint, channel, timer, frame)
.await
}
}
impl Lan7800 {
pub async fn read_register_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
register: u16,
) -> Result<u32, TransferError> {
let mut value = [0u8; 4];
vendor_in_async(
channel,
timer,
self.endpoint,
READ_REGISTER,
0,
register,
&mut value,
)
.await?;
Ok(u32::from_le_bytes(value))
}
pub async fn write_register_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
register: u16,
value: u32,
) -> Result<(), TransferError> {
vendor_out_async(
channel,
timer,
self.endpoint,
WRITE_REGISTER,
0,
register,
&value.to_le_bytes(),
)
.await
}
pub async fn id_revision_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<IdRevision, TransferError> {
let id_rev = self.read_register_async(channel, timer, REG_ID_REV).await?;
Ok(IdRevision {
id: (id_rev >> 16) as u16,
revision: id_rev as u16,
})
}
pub async fn set_mac_address_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
mac: [u8; 6],
) -> Result<(), TransferError> {
let low = u32::from_le_bytes([mac[0], mac[1], mac[2], mac[3]]);
let high = u16::from_le_bytes([mac[4], mac[5]]) as u32;
self.write_register_async(channel, timer, REG_RX_ADDRL, low)
.await?;
self.write_register_async(channel, timer, REG_RX_ADDRH, high)
.await?;
self.write_register_async(channel, timer, REG_MAF_LO0, low)
.await?;
self.write_register_async(channel, timer, REG_MAF_HI0, high | MAF_HI_VALID)
.await?;
Ok(())
}
pub async fn mac_address_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<[u8; 6], TransferError> {
let low = self
.read_register_async(channel, timer, REG_RX_ADDRL)
.await?
.to_le_bytes();
let high = (self
.read_register_async(channel, timer, REG_RX_ADDRH)
.await? as u16)
.to_le_bytes();
Ok([low[0], low[1], low[2], low[3], high[0], high[1]])
}
pub async fn reset_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<(), TransferError> {
let hw_cfg = self.read_register_async(channel, timer, REG_HW_CFG).await?;
self.write_register_async(channel, timer, REG_HW_CFG, hw_cfg | HW_CFG_LRST)
.await?;
self.wait_clear_async(channel, timer, REG_HW_CFG, HW_CFG_LRST)
.await?;
let usb_cfg = self
.read_register_async(channel, timer, REG_USB_CFG0)
.await?;
self.write_register_async(channel, timer, REG_USB_CFG0, usb_cfg | USB_CFG_BIR)
.await?;
let hw_cfg = self.read_register_async(channel, timer, REG_HW_CFG).await?;
self.write_register_async(
channel,
timer,
REG_HW_CFG,
(hw_cfg | HW_CFG_CLK125_EN | HW_CFG_REFCLK25_EN | HW_CFG_LED0_EN | HW_CFG_LED1_EN)
& !HW_CFG_MEF,
)
.await?;
self.write_register_async(channel, timer, REG_INT_STS, u32::MAX)
.await?;
self.write_register_async(channel, timer, REG_FLOW, 0)
.await?;
self.write_register_async(channel, timer, REG_FCT_FLOW, 0)
.await?;
self.write_register_async(
channel,
timer,
REG_RFE_CTL,
RFE_CTL_BCAST_EN | RFE_CTL_DA_PERFECT,
)
.await?;
let pmt_ctl = self
.read_register_async(channel, timer, REG_PMT_CTL)
.await?;
self.write_register_async(channel, timer, REG_PMT_CTL, pmt_ctl | PMT_CTL_PHY_RST)
.await?;
self.wait_phy_ready_async(channel, timer).await?;
let mac_cr = self.read_register_async(channel, timer, REG_MAC_CR).await?;
self.write_register_async(
channel,
timer,
REG_MAC_CR,
(mac_cr | MAC_CR_AUTO_DUPLEX | MAC_CR_AUTO_SPEED | MAC_CR_GMII_EN) & !MAC_CR_EEE_EN,
)
.await?;
let mac_rx = self.read_register_async(channel, timer, REG_MAC_RX).await?;
self.write_register_async(
channel,
timer,
REG_MAC_RX,
(mac_rx & !MAC_RX_MAX_SIZE_MASK)
| ((MAC_RX_MAX_FRAME_SIZE << MAC_RX_MAX_SIZE_SHIFT) & MAC_RX_MAX_SIZE_MASK),
)
.await?;
self.start_autonegotiation_async(channel, timer).await?;
Ok(())
}
pub async fn start_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
mac: [u8; 6],
) -> Result<(), TransferError> {
self.reset_async(channel, timer).await?;
self.set_mac_address_async(channel, timer, mac).await?;
let fct_rx = self
.read_register_async(channel, timer, REG_FCT_RX_CTL)
.await?;
self.write_register_async(channel, timer, REG_FCT_RX_CTL, fct_rx | FCT_RX_CTL_EN)
.await?;
let fct_tx = self
.read_register_async(channel, timer, REG_FCT_TX_CTL)
.await?;
self.write_register_async(channel, timer, REG_FCT_TX_CTL, fct_tx | FCT_TX_CTL_EN)
.await?;
let mac_rx = self.read_register_async(channel, timer, REG_MAC_RX).await?;
self.write_register_async(channel, timer, REG_MAC_RX, mac_rx | MAC_RX_RXEN)
.await?;
let mac_tx = self.read_register_async(channel, timer, REG_MAC_TX).await?;
self.write_register_async(channel, timer, REG_MAC_TX, mac_tx | MAC_TX_TXEN)
.await?;
Ok(())
}
pub async fn is_link_up_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<bool, TransferError> {
Ok(self.phy_read_async(channel, timer, PHY_REG_STATUS).await? & BMSR_LINK_UP != 0)
}
pub async fn is_full_duplex_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<bool, TransferError> {
let ours = self
.phy_read_async(channel, timer, PHY_REG_ADVERTISE)
.await?;
let theirs = self
.phy_read_async(channel, timer, PHY_REG_LINK_PARTNER)
.await?;
Ok(ours & theirs & (AN_100_FULL | AN_10_FULL) != 0)
}
pub async fn set_all_multicast_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
pass: bool,
) -> Result<(), TransferError> {
let rfe_ctl = self
.read_register_async(channel, timer, REG_RFE_CTL)
.await?;
let rfe_ctl = if pass {
rfe_ctl | RFE_CTL_MCAST_EN
} else {
rfe_ctl & !RFE_CTL_MCAST_EN
};
self.write_register_async(channel, timer, REG_RFE_CTL, rfe_ctl)
.await
}
pub async fn set_promiscuous_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
pass: bool,
) -> Result<(), TransferError> {
let rfe_ctl = self
.read_register_async(channel, timer, REG_RFE_CTL)
.await?;
let rfe_ctl = if pass {
rfe_ctl | RFE_CTL_UCAST_EN
} else {
rfe_ctl & !RFE_CTL_UCAST_EN
};
self.write_register_async(channel, timer, REG_RFE_CTL, rfe_ctl)
.await
}
pub fn split(&mut self) -> (Lan7800Rx<'_>, Lan7800Tx<'_>) {
let endpoint = self.endpoint;
(
Lan7800Rx {
endpoint,
rx: &mut self.rx,
},
Lan7800Tx {
endpoint,
tx: &mut self.tx,
},
)
}
pub async fn send_frame_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
frame: &[u8],
) -> Result<(), TransferError> {
self.tx
.send_async(self.endpoint, channel, timer, frame)
.await
}
pub async fn receive_frames_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<Frames<'_>, TransferError> {
self.rx.receive_async(self.endpoint, channel, timer).await
}
pub async fn phy_read_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
index: u8,
) -> Result<u16, TransferError> {
self.phy_wait_not_busy_async(channel, timer).await?;
let access = (PHY_ID_INTERNAL << MII_ACC_PHY_ADDR_SHIFT)
| ((index as u32) << MII_ACC_REG_SHIFT)
| MII_ACC_BUSY;
self.write_register_async(channel, timer, REG_MII_ACC, access)
.await?;
self.phy_wait_not_busy_async(channel, timer).await?;
Ok(self
.read_register_async(channel, timer, REG_MII_DATA)
.await? as u16)
}
pub async fn phy_write_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
index: u8,
value: u16,
) -> Result<(), TransferError> {
self.phy_wait_not_busy_async(channel, timer).await?;
self.write_register_async(channel, timer, REG_MII_DATA, value as u32)
.await?;
let access = (PHY_ID_INTERNAL << MII_ACC_PHY_ADDR_SHIFT)
| ((index as u32) << MII_ACC_REG_SHIFT)
| MII_ACC_WRITE
| MII_ACC_BUSY;
self.write_register_async(channel, timer, REG_MII_ACC, access)
.await?;
self.phy_wait_not_busy_async(channel, timer).await
}
async fn start_autonegotiation_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<(), TransferError> {
self.phy_write_async(channel, timer, PHY_REG_GIGABIT_CONTROL, 0)
.await?;
let control = self.phy_read_async(channel, timer, PHY_REG_CONTROL).await?;
let control =
(control | BMCR_ANEG_ENABLE | BMCR_ANEG_RESTART) & !(BMCR_POWER_DOWN | BMCR_ISOLATE);
self.phy_write_async(channel, timer, PHY_REG_CONTROL, control)
.await
}
async fn phy_wait_not_busy_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<(), TransferError> {
let start = timer.now_micros();
while self
.read_register_async(channel, timer, REG_MII_ACC)
.await?
& MII_ACC_BUSY
!= 0
{
if timer.now_micros() - start > MII_TIMEOUT_US {
return Err(TransferError::Timeout);
}
}
Ok(())
}
async fn wait_clear_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
register: u16,
bits: u32,
) -> Result<(), TransferError> {
let start = timer.now_micros();
while self.read_register_async(channel, timer, register).await? & bits != 0 {
if timer.now_micros() - start > RESET_TIMEOUT_US {
return Err(TransferError::Timeout);
}
}
Ok(())
}
async fn wait_phy_ready_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<(), TransferError> {
let start = timer.now_micros();
loop {
let pmt_ctl = self
.read_register_async(channel, timer, REG_PMT_CTL)
.await?;
if pmt_ctl & PMT_CTL_PHY_RST == 0 && pmt_ctl & PMT_CTL_READY != 0 {
return Ok(());
}
if timer.now_micros() - start > RESET_TIMEOUT_US {
return Err(TransferError::Timeout);
}
}
}
}
impl crate::usb::ethernet::EthernetAsync for Lan7800 {
type Rx<'a> = Lan7800Rx<'a>;
type Tx<'a> = Lan7800Tx<'a>;
fn split(&mut self) -> (Self::Rx<'_>, Self::Tx<'_>) {
Lan7800::split(self)
}
async fn start_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
mac: [u8; 6],
) -> Result<(), TransferError> {
Lan7800::start_async(self, channel, timer, mac).await
}
async fn is_link_up_async(
&self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<bool, TransferError> {
Lan7800::is_link_up_async(self, channel, timer).await
}
async fn set_all_multicast_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
pass: bool,
) -> Result<(), TransferError> {
Lan7800::set_all_multicast_async(self, channel, timer, pass).await
}
}
impl crate::usb::ethernet::EthernetRx for Lan7800Rx<'_> {
type Frames<'a>
= Frames<'a>
where
Self: 'a;
async fn receive_frames_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
) -> Result<Self::Frames<'_>, TransferError> {
Lan7800Rx::receive_frames_async(self, channel, timer).await
}
}
impl crate::usb::ethernet::EthernetTx for Lan7800Tx<'_> {
async fn send_frame_async(
&mut self,
channel: &mut Channel<'_>,
timer: &Timer,
frame: &[u8],
) -> Result<(), TransferError> {
Lan7800Tx::send_frame_async(self, channel, timer, frame).await
}
}