📄 mx27fec.c
字号:
// set other hardware registers
OUTREG32(&g_FEC.REG->EIR, FEC_EIR_CLEARALL_MASK);
OUTREG32(&g_FEC.REG->IAUR, 0);
OUTREG32(&g_FEC.REG->IALR, 0);
OUTREG32(&g_FEC.REG->GAUR, 0);
OUTREG32(&g_FEC.REG->GALR, 0);
OUTREG32(&g_FEC.REG->EMRBR, PKT_MAXBLR_SIZE);
INSREG32BF(&g_FEC.REG->ECR, FEC_ECR_ETHEREN, FEC_ECR_ETHEREN_ENABLE);
INSREG32BF(&g_FEC.REG->RDAR, FEC_RDAR_ACTIVE, FEC_RDAR_ACTIVE_ACTIVE);
// Set the station address for the FEC Adapter
MACAdd = mac[0]&0xFF;
MACAdd = (MACAdd << 8) | (mac[0] >> 8);
MACAdd = (MACAdd << 8) | ( mac[1]&0xFF);
MACAdd = (MACAdd << 8) | ( mac[1]>>8);
OUTREG32(&g_FEC.REG->PALR, MACAdd);
MACAdd = mac[2]&0xFF;
MACAdd = (MACAdd << 8) | (mac[2] >> 8);
OUTREG32(&g_FEC.REG->PAUR, MACAdd << 16);
OUTREG32(&g_FEC.REG->RCR,
CSP_BITFVAL(FEC_RCR_MAXFL, PKT_MAXBUF_SIZE)|
CSP_BITFVAL(FEC_RCR_MIIMODE, FEC_RCR_MIIMODE_ENABLE));
OUTREG32(&g_FEC.REG->TCR, 0);
// setup MII interface
// Set MII speed to 2.5MHz
//MIIPhySpeed = 14;
OUTREG32(&g_FEC.REG->MSCR,
CSP_BITFVAL(FEC_MSCR_MIISPEED, 14));
// Enable MII interrupts
OUTREG32(&g_FEC.REG->EIMR, CSP_BITFVAL(FEC_EIMR_MII, FEC_EIMR_MII_UNMASK));
//Get the Transciver Vendor ID
while(g_FEC.MIIPhyAddr < PHY_MAX_COUNT)
{
PhyType = MIIREAD(MII_REG_PHYIR1);
//johnli debug
EdbgOutputDebugString("DEBUG:PhyType_ID1=%x\r\n",PhyType);
if(PhyType == 0)
{
//EdbgOutputDebugString( "MII_REG_PHYIR1 READ Failed \n\r" );
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"MII_REG_PHYIR1 READ Failed \r\n"));
g_FEC.MIIPhyAddr++ ;
}
else
break;
}
MIIPhyId = PhyType << 16;
PhyType = MIIREAD(MII_REG_PHYIR2);
//johnli debug
EdbgOutputDebugString("DEBUG:PhyType_ID2=%x\r\n",PhyType);
if(PhyType == 0)
{
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"MII_REG_PHYIR1 READ Failed \r\n"));
}
MIIPhyId |= (PhyType & 0xffff);;
//johnli debug
EdbgOutputDebugString("DEBUG:MIIPhyId=%x\r\n",MIIPhyId);
for(i = 0; PhyInfo[i] != NULL; i++)
{
if(PhyInfo[i]->PhyId == MIIPhyId)
break;
}
if(PhyInfo[i])
{
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"The name for the external PHY is %s\r\n", PhyInfo[i]->PhyName));
}
else
{
//johnli debug. go here
EdbgOutputDebugString( "Failed to get the external PHY\r\n");
rc = FALSE;
goto CleanUp;
}
//Enable/Restart Auto-Negotiation
MIIWRITE(MII_REG_CR, 0x1200);
//Wating for Link success
while (! MIIREAD(MII_REG_SR) & 0x0004);
//Get Link states
//johnli modify lenovo
/*
RegVal = MIIREAD(MII_AM79C874_DR);
if(RegVal & 0x0400)
{
EdbgOutputDebugString( "FEC is linked, Speed 100Mbps \r\n");
if(RegVal & 0x0800)
{
EdbgOutputDebugString( "Full Duplex\r\n");
}
else
EdbgOutputDebugString( "Half Duplex\r\n");
}
else
{
EdbgOutputDebugString( "FEC is linked, Speed 10Mbps \r\n");
if(RegVal & 0x0800)
{
EdbgOutputDebugString( "Full Duplex\r\n");
}
else
EdbgOutputDebugString( "Half Duplex\r\n");
}
*/
if(Am79c874==i)
{
RegVal = MIIREAD(MII_AM79C874_DR);
if(RegVal & 0x0400)
{
EdbgOutputDebugString( "FEC is linked, Speed 100Mbps \r\n");
if(RegVal & 0x0800)
{
EdbgOutputDebugString( "Full Duplex\r\n");
}
else
EdbgOutputDebugString( "Half Duplex\r\n");
}
else
{
EdbgOutputDebugString( "FEC is linked, Speed 10Mbps \r\n");
if(RegVal & 0x0800)
{
EdbgOutputDebugString( "Full Duplex\r\n");
}
else
EdbgOutputDebugString( "Half Duplex\r\n");
}
}else if(LAN8700==i)
{
RegVal = MIIREAD(MII_LAN8700_SCSR);
HcdSpeed=((RegVal & 0x001C)>>2);
if(1==HcdSpeed)
EdbgOutputDebugString( "FEC is linked, Speed 10Mbps , Half Duplex \r\n");
else if(5==HcdSpeed)
EdbgOutputDebugString( "FEC is linked, Speed 10Mbps , Full Duplex \r\n");
else if(2==HcdSpeed)
EdbgOutputDebugString( "FEC is linked, Speed 100Mbps , Half Duplex \r\n");
else if(6==HcdSpeed)
EdbgOutputDebugString( "FEC is linked, Speed 100Mbps , Full Duplex \r\n");
}
//johnli end
// Disable MII interrupts
OUTREG32(&g_FEC.REG->EIMR, CSP_BITFVAL(FEC_EIMR_MII, FEC_EIMR_MII_MASK));
//Enable FEC RX interrupt
FECEnableInts();
CleanUp:
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-FECInit(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: FECSendFrame
//
//------------------------------------------------------------------------------
UINT16 FECSendFrame(UINT8 *pData, UINT32 length)
{
BOOL rc = FALSE;
volatile PBUFFER_DESC BufferDescPointer;
PUCHAR MemAddr;
UINT32 index;
UINT32 start;
#if 0
EdbgOutputDebugString( "+S %X %u \n\r", pData, length );
#endif
OALMSGS(OAL_ETHER&&OAL_VERBOSE, ( L"+S (0x%08x, %d)\r\n", pData, length));
BufferDescPointer = g_FEC.CurrentTx;
start = OALGetTickCount();
while (BufferDescPointer->ControlStatus & BD_ENET_TX_READY)
{
if ((OALGetTickCount() - start) > 2000)
{
OALMSGS(OAL_ERROR, (L"ERROR: FECSendFrame: Send timeout\r\n"));
//EdbgOutputDebugString("!!!ERROR TX T buffers are full ControlStatus = %X\r\n", BufferDescPointer->ControlStatus);
return FALSE;
}
}
// Clear all of the status flags
BufferDescPointer->ControlStatus &= ~BD_ENET_TX_STATS;
index = BufferDescPointer - g_FEC.TxBufferDescBase;
MemAddr = g_FEC.TxBuffAddr[index];
//Copy Send frame to TA DMA buffer
memcpy(MemAddr, pData, length);
// set up the transmit buffer descriptor
BufferDescPointer->ControlStatus |= (BD_ENET_TX_READY | BD_ENET_TX_INTR |
BD_ENET_TX_LAST | BD_ENET_TX_TC);
BufferDescPointer->DataLen = (USHORT)length;
// Trigger transmission start
INSREG32BF(&g_FEC.REG->TDAR, FEC_TDAR_ACTIVE, FEC_TDAR_ACTIVE_ACTIVE);
// If this was the last BD in the ring, start at the begining again
if(BufferDescPointer->ControlStatus & BD_ENET_TX_WRAP)
{
BufferDescPointer = g_FEC.TxBufferDescBase;
}
else
{
BufferDescPointer++;
}
g_FEC.CurrentTx = (PBUFFER_DESC)BufferDescPointer;
rc = TRUE;
OALMSGS(OAL_ETHER&&OAL_VERBOSE, (L"-FECSendFrame(rc = %d)\r\n", !rc));
return !rc;
}
//------------------------------------------------------------------------------
//
// Function: FECGetFrame
//
//------------------------------------------------------------------------------
UINT16 FECGetFrame(UINT8 *pData, UINT16 *pLength)
{
USHORT PacketSize = 0;
volatile PBUFFER_DESC BufferDescPointer;
PUCHAR pReceiveBuffer;
USHORT ControlStatus;
// UINT32 IntStatues;
#if 0
EdbgOutputDebugString( "+FECGetFrame %X %u \n\r", pData, *pLength );
#endif
OALMSGS(OAL_ETHER&&OAL_VERBOSE, (L"+FECGetFrame(0x%08x, %d)\r\n", pData, *pLength));
BufferDescPointer = g_FEC.CurrentRx;
//EdbgOutputDebugString("The value of ControlStatus is = %X\r\n", BufferDescPointer->ControlStatus);
ControlStatus = BufferDescPointer->ControlStatus;
while(!(BufferDescPointer->ControlStatus & BD_ENET_RX_EMPTY))
{
// Get frame size of the received frame
PacketSize = BufferDescPointer->DataLen;
PacketSize -= 4; //Removed CRC
if((PacketSize > *pLength) ||
(BufferDescPointer->ControlStatus & (BD_ENET_RX_LG | BD_ENET_RX_SH |
BD_ENET_RX_NO | BD_ENET_RX_CR |
BD_ENET_RX_OV | BD_ENET_RX_CL )))
{
PacketSize = 0;
//EdbgOutputDebugString("!!!ERROR Rx ControlStatus is = %X\r\n", BufferDescPointer->ControlStatus);
}
else
{
// Assign a pointer to the receive buffer
pReceiveBuffer = g_FEC.RxBuffAddr[BufferDescPointer - g_FEC.RxBufferDescBase];
memcpy(pData, pReceiveBuffer, PacketSize);
}
// Clear the status flags for this BD
BufferDescPointer->ControlStatus &= ~BD_ENET_RX_STATS;
// Mark the buffer as empty
BufferDescPointer->ControlStatus |= BD_ENET_RX_EMPTY;
// Update BD pointer to next entry
if(BufferDescPointer->ControlStatus & BD_ENET_RX_WRAP)
BufferDescPointer = g_FEC.RxBufferDescBase;
else
BufferDescPointer++;
g_FEC.CurrentRx = (PBUFFER_DESC)BufferDescPointer;
INSREG32BF(&g_FEC.REG->RDAR, FEC_RDAR_ACTIVE, FEC_RDAR_ACTIVE_ACTIVE);
//clear for Rx interrupt
OUTREG32(&g_FEC.REG->EIR, INREG32(&g_FEC.REG->EIR));
if(PacketSize > 0) break;
}
*pLength = PacketSize;
OALMSGS(OAL_ETHER&&OAL_VERBOSE, ( L"-FECGetFrame(PacketSize = %d)\r\n", PacketSize));
#if 0
if(PacketSize != 0)
{
EdbgOutputDebugString( "-RX *pLength %u \n\r", *pLength );
EdbgOutputDebugString( "-RX ControlStatus %u \n\r", ControlStatus );
}
#endif
FECEnableInts();
// Return packet size
return PacketSize;
}
//------------------------------------------------------------------------------
//
// Function: FECCurrentPacketFilter
//
//------------------------------------------------------------------------------
VOID FECCurrentPacketFilter(UINT32 filter)
{
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+FECCurrentPacketFilter(0x%08x)\r\n", filter));
// First set hash functions
if ((filter & PACKET_TYPE_PROMISCUOUS) != 0 ||
(filter & PACKET_TYPE_ALL_MULTICAST) != 0
) {
OUTREG32(&g_FEC.REG->GALR, 0xFFFFFFFF);
OUTREG32(&g_FEC.REG->GAUR, 0xFFFFFFFF);
}
else if ((filter & PACKET_TYPE_MULTICAST) != 0)
{
OUTREG32(&g_FEC.REG->GAUR, g_FEC.hash[0]);
OUTREG32(&g_FEC.REG->GALR, g_FEC.hash[1]);
}
// Save actual filter
g_FEC.filter = filter;
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-FECCurrentPacketFilter\r\n"));
}
//------------------------------------------------------------------------------
//
// Function: FECMulticastList
//
//------------------------------------------------------------------------------
BOOL FECMulticastList(UINT8 *pAddresses, UINT32 count)
{
UCHAR HashValue = 0;
UINT32 i;
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+FECMulticastList(0x%08x, %d)\r\n", pAddresses, count));
memset(g_FEC.hash, 0, sizeof(g_FEC.hash));
for (i = 0; i < count; i++)
{
HashValue = CalculateHashValue( pAddresses );
if( HashValue > 31 )
g_FEC.hash[0] |= 1 << (HashValue-32);
else
g_FEC.hash[1] |= 1 << HashValue;
pAddresses += 6;
}
// But update only Multicast mode is active
if ((g_FEC.filter & PACKET_TYPE_MULTICAST) != 0 )
{
OUTREG32(&g_FEC.REG->GAUR, g_FEC.hash[0]);
OUTREG32(&g_FEC.REG->GALR, g_FEC.hash[1]);
}
else
{
CLRREG32(&g_FEC.REG->GAUR, 0xFFFFFFFF);
CLRREG32(&g_FEC.REG->GALR, 0xFFFFFFFF);
}
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-FECMulticastList(rc = 1)\r\n"));
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -