⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lan9118.c

📁 wince 6.0下SMSC9118 100M网卡驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
	{
		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 + -