📄 chip.c
字号:
//------------------------------------------------------------------------------
//
// Copyright (C) 2006, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------
//
// File: chip.c
//
// Implementation of FEC Driver
//
// This file implements hardware related functions for FEC.
//
//-----------------------------------------------------------------------------
#include "fec.h"
#include "phys.h"
//------------------------------------------------------------------------------
// Defines
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// External Variables
//------------------------------------------------------------------------------
extern PCSP_FEC_REGS gpFECReg;
extern CRITICAL_SECTION gFECBufCs;
//------------------------------------------------------------------------------
// Global Variables
//------------------------------------------------------------------------------
FEC_MII_LIST gMIICmds[FEC_MII_COUNT];
PFEC_MII_LIST gMIIFree = NULL;
PFEC_MII_LIST gMIIHead = NULL;
PFEC_MII_LIST gMIITail = NULL;
//------------------------------------------------------------------------------
// File-local(static) Variables
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// External Functions
//------------------------------------------------------------------------------
extern BOOL BSPFECIomuxConfig( IN BOOL Enable );
extern BOOL BSPFECClockConfig( IN BOOL Enable );
//------------------------------------------------------------------------------
// Local Functions
//------------------------------------------------------------------------------
void FECSetMII(IN PFEC_ENET_PRIVATE pFEC);
BOOL FECQueueMII(
IN PFEC_ENET_PRIVATE pFEC,
IN UINT RegValue,
IN void (*OpFunc)(UINT, NDIS_HANDLE)
);
void FECDoMIICmd(
IN PFEC_ENET_PRIVATE pFEC,
IN PFEC_PHY_CMD pCmd
);
void FECGetPHYId2(
IN UINT MIIReg,
IN NDIS_HANDLE MiniportAdapterHandle
);
//------------------------------------------------------------------------------
// Functions implementation
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// Function: FECStartXmit
//
// This function gets the transmit data and sets the transmit buffer descriptors
// for transmitting process.
//
// Parameters:
// pEthernet
// [in] Specifies the driver allocated context area in which the driver
// maintains FEC adapter state, set up by FECInitialize.
//
// Return value:
// TRUE for success, FALSE for failure.
//
//------------------------------------------------------------------------------
BOOL FECStartXmit(pFEC_t pEthernet)
{
volatile PBUFFER_DESC BufferDescPointer;
UINT index;
PUCHAR MemAddr;
// Packet size of the packet
UINT PacketSize;
UINT CurrenSize = 0;
PNDIS_BUFFER pNDISBuffer;
// Holds virtual address of the current buffer
PUCHAR CurrentBufAddress;
// Holds the length of the current buffer of the packet
DWORD BufferLength;
PFEC_ENET_PRIVATE pFEC = &(pEthernet->FECPrivateInfo);
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +FECStartXmit\r\n")));
//if(pFEC->LinkStatus == FALSE)
//{
// Link is down or autonegotiation is in progress
// return FALSE;
//}
BufferDescPointer = pFEC->CurrentTx;
if(BufferDescPointer->ControlStatus & BD_ENET_TX_READY)
{
// Transmit buffers are full
return FALSE;
}
// Clear all of the status flags
BufferDescPointer->ControlStatus &= ~BD_ENET_TX_STATS;
index = BufferDescPointer - pFEC->TxBufferDescBase;
MemAddr = pFEC->TxBuffAddr[index];
// Check whether the first packet is NULL
if(pEthernet->HeadPacket == NULL)
{
return FALSE;
}
// Get the length of the packet and the pointer to NDIS Buffer
NdisQueryPacket(pEthernet->HeadPacket, NULL, NULL, &pNDISBuffer, &PacketSize);
NdisQueryBuffer(pNDISBuffer, (PVOID *)&CurrentBufAddress, &BufferLength);
while(pNDISBuffer)
{
if((BufferLength != 0) && (CurrentBufAddress != NULL))
{
memcpy(MemAddr, CurrentBufAddress, BufferLength);
MemAddr += BufferLength;
CurrenSize += BufferLength;
}
NdisGetNextBuffer(pNDISBuffer, &pNDISBuffer);
if (pNDISBuffer)
{
NdisQueryBuffer(pNDISBuffer, (PVOID *)&CurrentBufAddress, &BufferLength);
}
}
// 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)PacketSize;
// Trigger transmission start
INSREG32BF(&gpFECReg->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 = pFEC->TxBufferDescBase;
}
else
{
BufferDescPointer++;
}
if(BufferDescPointer == pFEC->DirtyTx)
{
pFEC->TxFull = TRUE;
}
pFEC->CurrentTx = (PBUFFER_DESC)BufferDescPointer;
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -FECStartXmit\r\n")));
return TRUE;
}
//------------------------------------------------------------------------------
// MII management related functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// Function: FECSetMII
//
// This function sets the clock for the MII interface
//
// Parameters:
// pFEC
// [in] Pointer to a structure which contains the status and control
// information for the FEC controller and MII
// Return Value:
// None.
//
//------------------------------------------------------------------------------
void FECSetMII( IN PFEC_ENET_PRIVATE pFEC )
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +FECSetMII\r\n")));
OUTREG32(&gpFECReg->RCR,
CSP_BITFVAL(FEC_RCR_MAXFL, PKT_MAXBUF_SIZE)|
CSP_BITFVAL(FEC_RCR_MIIMODE, FEC_RCR_MIIMODE_ENABLE));
OUTREG32(&gpFECReg->TCR, 0);
// Set MII speed to 2.5MHz
pFEC->MIIPhySpeed = 14;
OUTREG32(&gpFECReg->MSCR,
CSP_BITFVAL(FEC_MSCR_MIISPEED, pFEC->MIIPhySpeed));
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -FECSetMII\r\n")));
}
//------------------------------------------------------------------------------
//
// Function: FECQueueMII
//
// This function adds a MII management command to the MII command list
//
// Parameters:
// pFEC
// [in] Pointer to a structure which contains the status and control
// information for the FEC controller and MII
// RegValue
// [in] The MII command which will be added to the MII command list
//
// OpFunc
// [in] An optional function which will be performed when the MII interrupt
// arrived.
// Return Value:
// TRUE if the MII command has been added to the command list successfully,
// FALSE if the command list is full.
//
//------------------------------------------------------------------------------
BOOL FECQueueMII(
IN PFEC_ENET_PRIVATE pFEC,
IN UINT RegValue,
IN void (*OpFunc)(UINT, NDIS_HANDLE)
)
{
BOOL RetVal = TRUE;
PFEC_MII_LIST MIIPoint;
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +FECQueueMII\r\n")));
// add PHY address to the MII command
RegValue |= CSP_BITFVAL(FEC_MMFR_PA, pFEC->MIIPhyAddr);
if((MIIPoint = gMIIFree) != NULL)
{
gMIIFree = MIIPoint->MIINext;
MIIPoint->MIIRegVal = RegValue;
MIIPoint->MIIFunction = OpFunc;
MIIPoint->MIINext = NULL;
if(gMIIHead)
{
gMIITail->MIINext = MIIPoint;
gMIITail = MIIPoint;
}
else
{
gMIIHead = gMIITail = MIIPoint;
OUTREG32(&gpFECReg->MMFR, RegValue);
}
}
else
{
RetVal = FALSE;
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -FECQueueMII\r\n")));
return RetVal;
}
//------------------------------------------------------------------------------
//
// Function: FECDoMIICmd
//
// This function will call FECQueueMII to queue all the requested MII management
// commands to the sending list.
//
// Parameters:
// pFEC
// [in] Points to a structure which contains the status and control
// information for the FEC controller and MII
//
// pCmd
// [in] Points to a FEC_PHY_CMD array which specifies the MII management
// commands and the parsing functions
// Return Value:
// None
//
//------------------------------------------------------------------------------
void FECDoMIICmd(
IN PFEC_ENET_PRIVATE pFEC,
IN PFEC_PHY_CMD pCmd
)
{
UINT i;
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +FECDoMIICmd\r\n")));
if(!pCmd)
return;
for(i = 0; (pCmd + i)->MIIData != FEC_MII_END; i++ )
{
FECQueueMII(pFEC, (pCmd + i)->MIIData, (pCmd + i)->MIIFunct);
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -FECDoMIICmd\r\n")));
}
//------------------------------------------------------------------------------
//
// Function: FECParseMIISr
//
// This function parses the status register data of the external MII compatible
// PHY(s).
//
// Parameters:
// RegVal
// [in] the status register value get from external MII compatible
// PHY(s)
//
// MiniportAdapterHandle
// [in] Specifies the handle to the driver allocated context area in
// which the driver maintains FEC adapter state, set up by
// FECInitialize
//
// Return Value:
// None
//
//------------------------------------------------------------------------------
void FECParseMIISr(
IN UINT RegVal,
IN NDIS_HANDLE MiniportAdapterHandle
)
{
UINT Status;
volatile UINT *s;
pFEC_t pEthernet = ((pFEC_t)(MiniportAdapterHandle));
PFEC_ENET_PRIVATE pFEC = &(pEthernet->FECPrivateInfo);
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +FECParseMIISr\r\n")));
s = &(pFEC->MIIPhyStatus);
Status = *s & ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
if(RegVal & 0x0004)
Status |= PHY_STAT_LINK;
if(RegVal & 0x0010)
Status |= PHY_STAT_FAULT;
if(RegVal & 0x0020)
Status |= PHY_STAT_ANC;
*s = Status;
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -FECParseMIISr\r\n")));
}
//------------------------------------------------------------------------------
//
// Function: FECParseMIICr
//
// This function parses the control register data of the external MII compatible
// PHY(s).
//
// Parameters:
// RegVal
// [in] the control register value get from external MII compatible
// PHY(s)
//
// MiniportAdapterHandle
// [in] Specifies the handle to the driver allocated context area in
// which the driver maintains FEC adapter state, set up by
// FECInitialize
//
// Return Value:
// None
//
//------------------------------------------------------------------------------
void FECParseMIICr(
IN UINT RegVal,
IN NDIS_HANDLE MiniportAdapterHandle
)
{
UINT Status;
volatile UINT *s;
pFEC_t pEthernet = ((pFEC_t)(MiniportAdapterHandle));
PFEC_ENET_PRIVATE pFEC = &(pEthernet->FECPrivateInfo);
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +FECParseMIICr\r\n")));
s = &(pFEC->MIIPhyStatus);
Status = *s & ~(PHY_CONF_ANE | PHY_CONF_LOOP);
if(RegVal & 0x1000)
Status |= PHY_CONF_ANE;
if(RegVal & 0x4000)
Status |= PHY_CONF_LOOP;
*s = Status;
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -FECParseMIICr\r\n")));
}
//------------------------------------------------------------------------------
//
// Function: FECParseMIIAnar
//
// This function parses the Auto-Negotiation Advertisement Register data of the
// external MII compatible PHY(s).
//
// Parameters:
// RegVal
// [in] the Auto-Negotiation Advertisement Register value get from
// external MII compatible PHY(s)
//
// MiniportAdapterHandle
// [in] Specifies the handle to the driver allocated context area in
// which the driver maintains FEC adapter state, set up by
// FECInitialize
//
// Return Value:
// None
//
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -