📄 dm9161.c
字号:
PIO_Configure(pEmacPins, nbEmacPins);
rc = EMAC_SetMdcClock( mck );
if (!rc) {
trace_LOG(trace_FATAL, "E: No Valid MDC clock\n\r");
return 0;
}
// Check PHY Address
phy = DM9161_FindValidPhy(pDm);
if (phy == 0xFF) {
trace_LOG(trace_ERROR, "E: PHY Access fail\n\r");
return 0;
}
if(phy != pDm->phyAddress) {
pDm->phyAddress = phy;
DM9161_ResetPhy(pDm);
}
}
else {
trace_LOG(trace_ERROR, "E: PHY Reset Timeout\n\r");
}
return rc;
}
//-----------------------------------------------------------------------------
/// Issue a Auto Negotiation of the PHY
/// Return 1 if successfully, 0 if timeout.
/// \param pDm Pointer to the Dm9161 instance
//-----------------------------------------------------------------------------
unsigned char DM9161_AutoNegotiate(Dm9161 *pDm)
{
unsigned int retryMax;
unsigned int value;
unsigned int phyAnar;
unsigned int phyAnalpar;
unsigned int retryCount= 0;
unsigned char phyAddress;
unsigned char rc = 1;
ASSERT(pDm, "F: DM9161_AutoNegotiate\n\r");
phyAddress = pDm->phyAddress;
retryMax = pDm->retryMax;
EMAC_EnableMdio();
if (!EMAC_ReadPhy(phyAddress, DM9161_PHYID1, &value, retryMax)) {
trace_LOG(trace_DEBUG, "Pb EMAC_ReadPhy Id1\n\r");
rc = 0;
goto AutoNegotiateExit;
}
trace_LOG(trace_DEBUG, "ReadPhy Id1 0x%X, addresse: %d\n\r", value, phyAddress);
if (!EMAC_ReadPhy(phyAddress, DM9161_PHYID2, &phyAnar, retryMax)) {
trace_LOG(trace_DEBUG, "Pb EMAC_ReadPhy Id2\n\r");
rc = 0;
goto AutoNegotiateExit;
}
trace_LOG(trace_DEBUG, "ReadPhy Id2 0x%X\n\r", phyAnar);
if( ( value == DM9161_OUI_MSB )
&& ( ((phyAnar>>10)&DM9161_LSB_MASK) == DM9161_OUI_LSB ) ) {
trace_LOG(trace_DEBUG, "Vendor Number Model = 0x%X\n\r", ((phyAnar>>4)&0x3F));
trace_LOG(trace_DEBUG, "Model Revision Number = 0x%X\n\r", (phyAnar&0x7));
}
else {
trace_LOG(trace_ERROR, "Problem OUI value\n\r");
}
// Setup control register
rc = EMAC_ReadPhy(phyAddress, DM9161_BMCR, &value, retryMax);
if (rc == 0) {
goto AutoNegotiateExit;
}
value &= ~DM9161_AUTONEG; // Remove autonegotiation enable
value &= ~(DM9161_LOOPBACK|DM9161_POWER_DOWN);
value |= DM9161_ISOLATE; // Electrically isolate PHY
rc = EMAC_WritePhy(phyAddress, DM9161_BMCR, value, retryMax);
if (rc == 0) {
goto AutoNegotiateExit;
}
// Set the Auto_negotiation Advertisement Register
// MII advertising for Next page
// 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3
phyAnar = DM9161_NP | DM9161_TX_FDX | DM9161_TX_HDX |
DM9161_10_FDX | DM9161_10_HDX | DM9161_AN_IEEE_802_3;
rc = EMAC_WritePhy(phyAddress, DM9161_ANAR, phyAnar, retryMax);
if (rc == 0) {
goto AutoNegotiateExit;
}
// Read & modify control register
rc = EMAC_ReadPhy(phyAddress, DM9161_BMCR, &value, retryMax);
if (rc == 0) {
goto AutoNegotiateExit;
}
value |= DM9161_SPEED_SELECT | DM9161_AUTONEG | DM9161_DUPLEX_MODE;
rc = EMAC_WritePhy(phyAddress, DM9161_BMCR, value, retryMax);
if (rc == 0) {
goto AutoNegotiateExit;
}
// Restart Auto_negotiation
value |= DM9161_RESTART_AUTONEG;
value &= ~DM9161_ISOLATE;
rc = EMAC_WritePhy(phyAddress, DM9161_BMCR, value, retryMax);
if (rc == 0) {
goto AutoNegotiateExit;
}
trace_LOG(trace_DEBUG, " _BMCR: 0x%X\n\r", value);
// Check AutoNegotiate complete
while (1) {
rc = EMAC_ReadPhy(phyAddress, DM9161_BMSR, &value, retryMax);
if (rc == 0) {
trace_LOG(trace_DEBUG, "rc==0\n\r");
goto AutoNegotiateExit;
}
// Done successfully
if (value & DM9161_AUTONEG_COMP) {
trace_LOG(trace_INFO, "AutoNegotiate complete\n\r");
break;
}
// Timeout check
if (retryMax) {
if (++ retryCount >= retryMax) {
DM9161_DumpRegisters(pDm);
trace_LOG(trace_DEBUG, "TimeOut\n\r");
goto AutoNegotiateExit;
}
}
}
// Get the AutoNeg Link partner base page
rc = EMAC_ReadPhy(phyAddress, DM9161_ANLPAR, &phyAnalpar, retryMax);
if (rc == 0) {
goto AutoNegotiateExit;
}
// Setup the EMAC link speed
if ((phyAnar & phyAnalpar) & DM9161_TX_FDX) {
// set MII for 100BaseTX and Full Duplex
EMAC_SetLinkSpeed(1, 1);
}
else if ((phyAnar & phyAnalpar) & DM9161_10_FDX) {
// set MII for 10BaseT and Full Duplex
EMAC_SetLinkSpeed(0, 1);
}
else if ((phyAnar & phyAnalpar) & DM9161_TX_HDX) {
// set MII for 100BaseTX and half Duplex
EMAC_SetLinkSpeed(1, 0);
}
else if ((phyAnar & phyAnalpar) & DM9161_10_HDX) {
// set MII for 10BaseT and half Duplex
EMAC_SetLinkSpeed(0, 0);
}
// Setup EMAC mode
#if BOARD_EMAC_MODE_RMII != 1
EMAC_EnableMII();
#else
EMAC_EnableRMII();
#endif
AutoNegotiateExit:
EMAC_DisableMdio();
return rc;
}
//-----------------------------------------------------------------------------
/// Get the Link & speed settings, and automatically setup the EMAC with the
/// settings.
/// Return 1 if link found, 0 if no ethernet link.
/// \param pDm Pointer to the Dm9161 instance
/// \param applySetting Apply the settings to EMAC interface
//-----------------------------------------------------------------------------
unsigned char DM9161_GetLinkSpeed(Dm9161 *pDm, unsigned char applySetting)
{
unsigned int retryMax;
unsigned int stat1;
unsigned int stat2;
unsigned char phyAddress;
unsigned char rc = 1;
trace_LOG(trace_DEBUG, "DM9161_GetLinkSpeed\n\r");
ASSERT(pDm, "F: DM9161_GetLinkSpeed\n\r");
EMAC_EnableMdio();
phyAddress = pDm->phyAddress;
retryMax = pDm->retryMax;
rc = EMAC_ReadPhy(phyAddress, DM9161_BMSR, &stat1, retryMax);
if (rc == 0) {
goto GetLinkSpeedExit;
}
if ((stat1 & DM9161_LINK_STATUS) == 0) {
trace_LOG(trace_DEBUG, "Pb: LinkStat: 0x%x\n\r", stat1);
rc = 0;
goto GetLinkSpeedExit;
}
if (applySetting == 0) {
trace_LOG(trace_DEBUG, "Pb: applySetting: 0x%x\n\r", applySetting);
goto GetLinkSpeedExit;
}
// Re-configure Link speed
rc = EMAC_ReadPhy(phyAddress, DM9161_DSCSR, &stat2, retryMax);
if (rc == 0) {
trace_LOG(trace_DEBUG, "Pb: rc: 0x%x\n\r", rc);
goto GetLinkSpeedExit;
}
if ((stat1 & DM9161_100BASE_TX_FD) && (stat2 & DM9161_100FDX)) {
// set Emac for 100BaseTX and Full Duplex
EMAC_SetLinkSpeed(1, 1);
}
if ((stat1 & DM9161_10BASE_T_FD) && (stat2 & DM9161_10FDX)) {
// set MII for 10BaseT and Full Duplex
EMAC_SetLinkSpeed(0, 1);
}
if ((stat1 & DM9161_100BASE_T4_HD) && (stat2 & DM9161_100HDX)) {
// set MII for 100BaseTX and Half Duplex
EMAC_SetLinkSpeed(1, 0);
}
if ((stat1 & DM9161_10BASE_T_HD) && (stat2 & DM9161_10HDX)) {
// set MII for 10BaseT and Half Duplex
EMAC_SetLinkSpeed(0, 0);
}
// Start the EMAC transfers
trace_LOG(trace_DEBUG, "DM9161_GetLinkSpeed passed\n\r");
GetLinkSpeedExit:
EMAC_DisableMdio();
return rc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -