📄 lan9118.c
字号:
{
DWORD dwTxCmdA=0UL;
DWORD dwTxCmdB=0UL;
DWORD dwStatus=0UL;
DWORD dwPacketLength=0UL;
//zero-out Rx Packet memory
memset(pLan9118Data->LoopBackRxPacket,0,(UINT)MIN_PACKET_SIZE);
//write Tx Packet to 118
dwTxCmdA=
((((DWORD)(pLan9118Data->LoopBackTxPacket))&0x03UL)<<16) | //DWORD alignment adjustment
TX_CMD_A_INT_FIRST_SEG_ | TX_CMD_A_INT_LAST_SEG_ |
((MIN_PACKET_SIZE));
dwTxCmdB=
(((DWORD)(MIN_PACKET_SIZE))<<16) |
((DWORD)(MIN_PACKET_SIZE));
SetRegDW(pLan9118Data->dwLanBase,TX_DATA_FIFO_PORT,dwTxCmdA);
SetRegDW(pLan9118Data->dwLanBase,TX_DATA_FIFO_PORT,dwTxCmdB);
Lan_WriteTxFifo(
pLan9118Data->dwLanBase,
(DWORD *)(((DWORD)(pLan9118Data->LoopBackTxPacket))&0xFFFFFFFCUL),
(((DWORD)(MIN_PACKET_SIZE))+3UL+
(((DWORD)(pLan9118Data->LoopBackTxPacket))&0x03UL))>>2);
//wait till transmit is done
dwLoopCount=60UL;
while(((dwStatus=Phy_LBT_GetTxStatus(pLan9118Data))==0UL)&&(dwLoopCount>0UL)) {
SMSC_MICRO_DELAY(5U);
dwLoopCount--;
}
if(dwStatus==0UL) {
SMSC_WARNING0("Failed to Transmit during Loop Back Test\r\n");
continue;
}
if(dwStatus&0x00008000UL) {
SMSC_WARNING0("Transmit encountered errors during Loop Back Test\r\n");
continue;
}
//wait till receive is done
dwLoopCount=60UL;
while(((dwStatus=Phy_LBT_GetRxStatus(pLan9118Data))==0UL)&&(dwLoopCount>0UL))
{
SMSC_MICRO_DELAY(5U);
dwLoopCount--;
}
if(dwStatus==0UL) {
SMSC_WARNING0("Failed to Receive during Loop Back Test\r\n");
continue;
}
if(dwStatus&RX_STS_ES)
{
SMSC_WARNING0("Receive encountered errors during Loop Back Test\r\n");
continue;
}
dwPacketLength=((dwStatus&0x3FFF0000UL)>>16);
Lan_ReadRxFifo(
pLan9118Data->dwLanBase,
((DWORD *)(pLan9118Data->LoopBackRxPacket)),
(dwPacketLength+3UL+(((DWORD)(pLan9118Data->LoopBackRxPacket))&0x03UL))>>2);
if(dwPacketLength!=(MIN_PACKET_SIZE+4UL)) {
SMSC_TRACE1(DBG_INIT, "Unexpected packet size during loop back test, size=%ld, will retry",dwPacketLength);
} else {
DWORD byteIndex=0UL;
BOOLEAN foundMissMatch=(BOOLEAN)FALSE;
for(byteIndex=0UL;byteIndex<MIN_PACKET_SIZE;byteIndex++) {
if(pLan9118Data->LoopBackTxPacket[byteIndex]!=pLan9118Data->LoopBackRxPacket[byteIndex])
{
foundMissMatch=(BOOLEAN)TRUE;
break;
}
}
if(foundMissMatch != TRUE) {
SMSC_TRACE0(DBG_PHY, "Successfully verified Loop Back Packet\n\r");
result=(BOOLEAN)TRUE;
goto DONE;
} else {
SMSC_WARNING0("Data miss match during loop back test, will retry.\r\n");
}
}
}
DONE:
return result;
}
BOOLEAN Phy_LoopBackTest(LAN9118_DATA * const pLan9118Data)
{
BOOLEAN result=(BOOLEAN)FALSE;
DWORD byteIndex=0UL;
DWORD tryCount=0UL;
// DWORD failed=0;
//Initialize Tx Packet
for(byteIndex=0UL;byteIndex<6UL;byteIndex++) {
//use broadcast destination address
pLan9118Data->LoopBackTxPacket[byteIndex]=(BYTE)0xFF;
}
for(byteIndex=6UL;byteIndex<12UL;byteIndex++) {
//use incrementing source address
pLan9118Data->LoopBackTxPacket[byteIndex]=(BYTE)byteIndex;
}
//Set length type field
pLan9118Data->LoopBackTxPacket[12]=(BYTE)0x00;
pLan9118Data->LoopBackTxPacket[13]=(BYTE)0x00;
for(byteIndex=14UL;byteIndex<MIN_PACKET_SIZE;byteIndex++)
{
pLan9118Data->LoopBackTxPacket[byteIndex]=(BYTE)byteIndex;
}
//TRY_AGAIN:
{
DWORD dwRegVal=GetRegDW(pLan9118Data->dwLanBase, HW_CFG);
dwRegVal&=HW_CFG_TX_FIF_SZ_;
dwRegVal|=HW_CFG_SF_;
SetRegDW(pLan9118Data->dwLanBase,HW_CFG,dwRegVal);
}
SetRegDW(pLan9118Data->dwLanBase,TX_CFG,TX_CFG_TX_ON_);
SetRegDW(pLan9118Data->dwLanBase,RX_CFG,(((DWORD)(pLan9118Data->LoopBackRxPacket))&0x03UL)<<8);
{
#if 1
//Set Phy to 10/FD, no ANEG,
LanWritePhy(PHY_BCR,(WORD)0x0100);
//enable MAC Tx/Rx, FD
LanWriteMac(MAC_CR,MAC_CR_FDPX_|MAC_CR_TXEN_|MAC_CR_RXEN_);
// Phy_TransmitTestPacket(privateData);
//set Phy to loopback mode
LanWritePhy(PHY_BCR,(WORD)0x4100);
#endif
for(tryCount=0UL;tryCount<10UL;tryCount++) {
if(Phy_CheckLoopBackPacket(pLan9118Data) == TRUE)
{
result=(BOOLEAN)TRUE;
goto DONE;
}
#if 0
DumpSIMRegs(pLan9118Data);
DumpPHYRegs(pLan9118Data);
#endif
pLan9118Data->dwResetCount++;
#if 1
//disable MAC rx
LanWriteMac(MAC_CR,0UL);
result = Phy_Reset(pLan9118Data);
//Set Phy to 10/FD, no ANEG, and Loopbackmode
LanWritePhy(PHY_BCR,(WORD)0x4100);
//enable MAC Tx/Rx, FD
LanWriteMac(MAC_CR,MAC_CR_FDPX_|MAC_CR_TXEN_|MAC_CR_RXEN_);
#endif
}
DONE:
//disable MAC
LanWriteMac(MAC_CR,0UL);
//Cancel Phy loopback mode
LanWritePhy(PHY_BCR,(WORD)0U);
}
SetRegDW(pLan9118Data->dwLanBase,TX_CFG,0UL);
SetRegDW(pLan9118Data->dwLanBase,RX_CFG,0UL);
return result;
}
#endif //USE_PHY_WORK_AROUND
/*
FUNCTION: Lan_InitializePhy
This function should be called after Lan_InitializeInterrupts.
Continues to initialize the LAN9118_DATA structure.
It reads some phy ID values from the phy
It resets the phy.
It initializes phy interrupts
RETURN VALUE:
returns TRUE on Success,
returns FALSE on Failure
*/
BOOL Lan_InitializePhy(PLAN9118_DATA pLan9118Data, BYTE bPhyAddress)
{
BOOL result = FALSE;
BOOL ExtPhy = FALSE;
DWORD dwTemp = 0UL;
DWORD dwLoopCount = 0UL;
DWORD dwPhyId = 0UL;
BYTE bPhyModel = (BYTE)0;
BYTE bPhyRev = (BYTE)0;
WORD wPhyID1, wPhyID2;
SMSC_TRACE2(DBG_INIT, "+Lan_InitializePhy(pLan9118Data=0x%08lX, bPhyAddress=%d)\r\n", (DWORD)pLan9118Data,bPhyAddress);
SMSC_ASSERT(pLan9118Data);
if (pLan9118Data == NULL)
{
return FALSE;
}
SMSC_ASSERT(pLan9118Data->dwLanBase != 0UL);
SMSC_ASSERT(pLan9118Data->dwIdRev != 0UL);
SMSC_ASSERT(pLan9118Data->LanInitialized == (BOOLEAN)TRUE);
SMSC_ASSERT(pLan9118Data->InterruptsInitialized == (BOOLEAN)TRUE);
if (bPhyAddress == 0xFF)
{
/* Use Internal Phy */
SMSC_TRACE0(DBG_PHY, "Use IntPhy\r\n");
RETAILMSG(1, (TEXT("Use IntPhy\r\n")));
/* verify phy ID */
bPhyAddress = (BYTE)1; // internal address
ExtPhy = FALSE;
}
else
{
/* Using External Phy */
/* Check ID */
switch (pLan9118Data->dwIdRev & 0xFFFF0000UL)
{
case 0x01150000UL:
case 0x01170000UL:
if (pLan9118Data->dwIdRev & 0x0000FFFFUL)
{
dwTemp = GetRegDW(pLan9118Data->dwLanBase, HW_CFG);
if (dwTemp & HW_CFG_EXT_PHY_DET_)
{
dwTemp &= ~HW_CFG_PHY_CLK_SEL_;
dwTemp |= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
SMSC_MICRO_DELAY(10U);
dwTemp |= HW_CFG_EXT_PHY_EN_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
dwTemp &= ~HW_CFG_PHY_CLK_SEL_;
dwTemp |= HW_CFG_PHY_CLK_SEL_EXT_PHY_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
SMSC_MICRO_DELAY(10U);
dwTemp |= HW_CFG_SMI_SEL_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
if (bPhyAddress < 32)
{
// Use specified PhyAddress
SMSC_TRACE1(DBG_PHY, "Use 0x%x ExtPhy\r\n", bPhyAddress);
wPhyID1 = Lan_GetPhyRegW(pLan9118Data->dwLanBase, (DWORD)bPhyAddress, PHY_ID_1);
wPhyID2 = Lan_GetPhyRegW(pLan9118Data->dwLanBase, (DWORD)bPhyAddress, PHY_ID_2);
ExtPhy = TRUE;
}
else
{
DWORD dwAddr;
for (dwAddr = 0UL;dwAddr < 32UL;dwAddr++)
{
wPhyID1 = Lan_GetPhyRegW(pLan9118Data->dwLanBase, dwAddr, PHY_ID_1);
wPhyID2 = Lan_GetPhyRegW(pLan9118Data->dwLanBase, dwAddr, PHY_ID_2);
if ((wPhyID1 != (WORD)0xFFFFU) ||
(wPhyID2 != (WORD)0xFFFFU))
{
SMSC_TRACE1(DBG_PHY, "Detect Phy at Address 0x%x\r\n", dwAddr);
RETAILMSG(1, (TEXT("Detect Phy at Address 0x%x\r\n"), dwAddr));
bPhyAddress = (BYTE)dwAddr;
ExtPhy = TRUE;
break;
}
}
if (dwAddr == 32UL)
{
SMSC_WARNING0("Error! Failed to detect External Phy\r\n");
ExtPhy = FALSE;
}
}
if ((wPhyID1 == (WORD)0xFFFF) &&
(wPhyID2 == (WORD)0xFFFF))
{
SMSC_WARNING0("Error! External Phy is not accessible. Switch to Internal Phy\r\n");
// revert back to Internal Phy
bPhyAddress = (BYTE)1; // internal address
dwTemp &= ~HW_CFG_PHY_CLK_SEL_;
dwTemp |= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
SMSC_MICRO_DELAY(10U);
dwTemp &= ~HW_CFG_EXT_PHY_EN_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
dwTemp &= ~HW_CFG_PHY_CLK_SEL_;
dwTemp |= HW_CFG_PHY_CLK_SEL_EXT_PHY_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
SMSC_MICRO_DELAY(10U);
dwTemp &= ~HW_CFG_SMI_SEL_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
ExtPhy = FALSE;
}
}
else
{
/* Use Internal Phy */
SMSC_WARNING0("ExtPhy is not detected. Switch to Internal Phy\r\n");
ExtPhy = FALSE;
bPhyAddress = (BYTE)1; // internal address
}
}
else
{
SMSC_WARNING2("Error! Chip Id = 0x%x and Rev = 0x%x doesn't seem to be right combination.\r\n", (pLan9118Data->dwIdRev >> 16) & 0xFFFFUL, pLan9118Data->dwIdRev & 0xFFFFUL);
}
break;
case 0x115A0000UL:
case 0x117A0000UL:
dwTemp = GetRegDW(pLan9118Data->dwLanBase, HW_CFG);
if (dwTemp & HW_CFG_EXT_PHY_DET_)
{
dwTemp &= ~HW_CFG_PHY_CLK_SEL_;
dwTemp |= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
SMSC_MICRO_DELAY(10U);
dwTemp |= HW_CFG_EXT_PHY_EN_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
dwTemp &= ~HW_CFG_PHY_CLK_SEL_;
dwTemp |= HW_CFG_PHY_CLK_SEL_EXT_PHY_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
SMSC_MICRO_DELAY(10U);
dwTemp |= HW_CFG_SMI_SEL_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
if (bPhyAddress < 32)
{
// Use specified PhyAddress
SMSC_TRACE1(DBG_PHY, "Use 0x%x ExtPhy\r\n", bPhyAddress);
RETAILMSG(1, (TEXT("Use 0x%x ExtPhy\r\n"), bPhyAddress));
wPhyID1 = Lan_GetPhyRegW(pLan9118Data->dwLanBase, (DWORD)bPhyAddress, PHY_ID_1);
wPhyID2 = Lan_GetPhyRegW(pLan9118Data->dwLanBase, (DWORD)bPhyAddress, PHY_ID_2);
ExtPhy = TRUE;
}
else
{
DWORD dwAddr;
for (dwAddr = 0UL;dwAddr < 32UL;dwAddr++)
{
wPhyID1 = Lan_GetPhyRegW(pLan9118Data->dwLanBase, dwAddr, PHY_ID_1);
wPhyID2 = Lan_GetPhyRegW(pLan9118Data->dwLanBase, dwAddr, PHY_ID_2);
if ((wPhyID1 != (WORD)0xFFFFU) ||
(wPhyID2 != (WORD)0xFFFFU))
{
SMSC_TRACE1(DBG_PHY, "Detect Phy at Address 0x%x\r\n", dwAddr);
RETAILMSG(1, (TEXT("Detect Phy at Address 0x%x\r\n"), dwAddr));
bPhyAddress = (BYTE)dwAddr;
ExtPhy = TRUE;
break;
}
}
if (dwAddr == 32UL)
{
SMSC_WARNING0("Error! Failed to detect External Phy\r\n");
ExtPhy = FALSE;
}
}
if ((wPhyID1 == (WORD)0xFFFF) &&
(wPhyID2 == (WORD)0xFFFF))
{
SMSC_WARNING0("Error! External Phy is not accessible. Switch to Internal Phy\r\n");
// revert back to Internal Phy
bPhyAddress = (BYTE)1; // internal address
dwTemp &= ~HW_CFG_PHY_CLK_SEL_;
dwTemp |= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
SMSC_MICRO_DELAY(10U);
dwTemp &= ~HW_CFG_EXT_PHY_EN_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
dwTemp &= ~HW_CFG_PHY_CLK_SEL_;
dwTemp |= HW_CFG_PHY_CLK_SEL_EXT_PHY_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
SMSC_MICRO_DELAY(10U);
dwTemp &= ~HW_CFG_SMI_SEL_;
SetRegDW(pLan9118Data->dwLanBase, HW_CFG, dwTemp);
ExtPhy = FALSE;
}
}
else
{
/* Use Internal Phy */
SMSC_WARNING0("ExtPhy is not detected. Switch to Internal Phy\r\n");
bPhyAddress = (BYTE)1; // internal address
ExtPhy = FALSE;
}
break;
default:
/* Use Internal Phy */
SMSC_TRACE0(DBG_PHY, "Use IntPhy\r\n");
RETAILMSG(1, (TEXT("Use IntPhy\r\n")));
bPhyAddress = (BYTE)1; // internal address
ExtPhy = FALSE;
break;
}
}
dwTemp = (DWORD)Lan_GetPhyRegW(pLan9118Data->dwLanBase, (DWORD)bPhyAddress, PHY_ID_2);
bPhyRev = ((BYTE)(dwTemp & (0x0FUL)));
bPhyModel = ((BYTE)((dwTemp>>4) & (0x3FUL)));
dwPhyId = dwTemp << 16;
dwTemp = (DWORD)Lan_GetPhyRegW(pLan9118Data->dwLanBase, (DWORD)bPhyAddress, PHY_ID_1);
dwPhyId |= ((dwTemp & (0x0000FFFFUL))<<2);
pLan9118Data->bPhyAddress = bPhyAddress;
pLan9118Data->dwPhyId = dwPhyId;
pLan9118Data->bPhyModel = bPhyModel;
pLan9118Data->bPhyRev = bPhyRev;
pLan9118Data->dwLinkMode = LINK_NO_LINK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -