📄 chip.c
字号:
pFEC->DirtyTx = pFEC->CurrentTx = pFEC->TxBufferDescBase;
pFEC->CurrentRx = pFEC->RxBufferDescBase;
// allocate receive buffers and initialize the receive buffer descriptors
BufferDescPointer = pFEC->RxBufferDescBase;
MemAddr = (PUCHAR)HalAllocateCommonBuffer(
&Adapter,
FEC_RX_RING_SIZE * FEC_ENET_RX_FRSIZE,
&MemPhysicalBase,
FALSE);
if(MemAddr == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("FECEnetInit: Allocate DMA memory for receive buffers failed\r\n")));
return FALSE;
}
else
{
pFEC->RxBufferBase = (PVOID)MemAddr;
}
for(i = 0; i < FEC_RX_RING_SIZE; i++)
{
BufferDescPointer->ControlStatus = BD_ENET_RX_EMPTY;
BufferDescPointer->BufferAddr = (ULONG)MemPhysicalBase.QuadPart + i*FEC_ENET_RX_FRSIZE;
pFEC->RxBuffAddr[BufferDescPointer - pFEC->RxBufferDescBase] = MemAddr + i*FEC_ENET_RX_FRSIZE;
BufferDescPointer++;
}
// set the last buffer to wrap
BufferDescPointer--;
BufferDescPointer->ControlStatus |= BD_SC_WRAP;
// allocate transmit buffers and initialize the transmit buffer descriptors
BufferDescPointer = pFEC->TxBufferDescBase;
MemAddr = (PUCHAR)HalAllocateCommonBuffer(
&Adapter,
FEC_TX_RING_SIZE * FEC_ENET_TX_FRSIZE,
&MemPhysicalBase,
FALSE);
if(MemAddr == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("FECEnetInit: Allocate DMA memory for transmit buffers failed\r\n")));
return FALSE;
}
else
{
pFEC->TxBufferBase = (PVOID)MemAddr;
}
for(i = 0; i < FEC_TX_RING_SIZE; i++)
{
BufferDescPointer->ControlStatus = 0;
BufferDescPointer->BufferAddr = (ULONG)MemPhysicalBase.QuadPart + i*FEC_ENET_TX_FRSIZE;
pFEC->TxBuffAddr[BufferDescPointer - pFEC->TxBufferDescBase] = MemAddr + i*FEC_ENET_TX_FRSIZE;
BufferDescPointer++;
}
// set the last buffer to wrap
BufferDescPointer--;
BufferDescPointer->ControlStatus |= BD_SC_WRAP;
// issue a reset to the FEC hardware
INSREG32BF(&gpFECReg->ECR, FEC_ECR_RESET, FEC_ECR_RESET_RESET);
// wait for the hareware reset to complete
while(EXTREG32BF(&gpFECReg->ECR, FEC_ECR_RESET));
// set the receive and transmit BDs ring base to
// hardware registers(ERDSR & ETDSR)
OUTREG32(&gpFECReg->ERDSR, (ULONG)pFEC->RingPhysicalBase.QuadPart);
OUTREG32(&gpFECReg->ETDSR,
(ULONG)pFEC->RingPhysicalBase.QuadPart + FEC_RX_RING_SIZE*sizeof(BUFFER_DESC));
// set other hardware registers
OUTREG32(&gpFECReg->EIR, FEC_EIR_CLEARALL_MASK);
#if 0
OUTREG32(&gpFECReg->EIMR,
CSP_BITFVAL(FEC_EIMR_TXF, FEC_EIMR_TXF_UNMASK) |
CSP_BITFVAL(FEC_EIMR_RXF, FEC_EIMR_RXF_UNMASK) |
CSP_BITFVAL(FEC_EIMR_MII, FEC_EIMR_MII_UNMASK));
#endif
OUTREG32(&gpFECReg->IAUR, 0);
OUTREG32(&gpFECReg->IALR, 0);
OUTREG32(&gpFECReg->GAUR, 0);
OUTREG32(&gpFECReg->GALR, 0);
OUTREG32(&gpFECReg->EMRBR, PKT_MAXBLR_SIZE);
// enable the FEC
INSREG32BF(&gpFECReg->ECR, FEC_ECR_ETHEREN, FEC_ECR_ETHEREN_ENABLE);
INSREG32BF(&gpFECReg->RDAR, FEC_RDAR_ACTIVE, FEC_RDAR_ACTIVE_ACTIVE);
// Set the station address for the FEC Adapter
OUTREG32(&gpFECReg->PALR, pEthernet->FecMacAddress[3] |
pEthernet->FecMacAddress[2]<<8 |
pEthernet->FecMacAddress[1]<<16 |
pEthernet->FecMacAddress[0]<<24);
OUTREG32(&gpFECReg->PAUR, pEthernet->FecMacAddress[5]<<16 |
pEthernet->FecMacAddress[4]<<24);
for(i = 0; i < FEC_MII_COUNT-1; i++)
{
gMIICmds[i].MIINext = &gMIICmds[i+1];
}
gMIIFree = gMIICmds;
// setup MII interface
FECSetMII(pFEC);
// Queue up command to detect the PHY and initialize the remainder of
// the interface
pFEC->TxFull = FALSE;
pFEC->MIIPhyIdDone = FALSE;
pFEC->MIIPhyAddr = 0;
pFEC->MIISeqDone = FALSE;
pFEC->LinkStatus = FALSE;
pFEC->MIIPhy = NULL;
FECQueueMII( pFEC, MII_READ_COMMAND(MII_REG_PHYIR1), FECGetPHYId );
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -FECEnetInit\r\n")));
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: FECEnetDeinit
//
// This function Deinitialize the FEC hardware. It will free the DMA buffers and
// disable the GPIO and CLK for FEC.
//
// Parameters:
// pEthernet
// [in] the FEC driver context area allocated in function FECInitialize
//
// Return Value:
// None.
//
//------------------------------------------------------------------------------
void FECEnetDeinit(pFEC_t pEthernet)
{
PHYSICAL_ADDRESS MemPhysicalBase;
PFEC_ENET_PRIVATE pFEC = &(pEthernet->FECPrivateInfo);
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +FECEnetDeinit\r\n")));
MemPhysicalBase.QuadPart = 0;
// Free DMA buffers allocated(Note: only virtual address is needed)
HalFreeCommonBuffer(NULL, 0, MemPhysicalBase, pFEC->RingBase, FALSE);
HalFreeCommonBuffer(NULL, 0, MemPhysicalBase, pFEC->RxBufferBase, FALSE);
HalFreeCommonBuffer(NULL, 0, MemPhysicalBase, pFEC->TxBufferBase, FALSE);
// disable GPIO and CLK for FEC
BSPFECIomuxConfig( FALSE );
BSPFECClockConfig( FALSE );
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -FECEnetDeinit\r\n")));
}
//------------------------------------------------------------------------------
//
// Function: FECEnetAutoNego
//
// This function issues the auto-negotiation sequences to the external PHY device
//
// Parameters:
// pEthernet
// [in] the FEC driver context area allocated in function FECInitialize
//
// Return value
// None
//
//------------------------------------------------------------------------------
void FECEnetAutoNego(pFEC_t pEthernet)
{
PFEC_ENET_PRIVATE pFEC = &(pEthernet->FECPrivateInfo);
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +FECEnetAutoNego\r\n")));
// Wait for MII interrupt to set to TURE
while(pFEC->MIIPhyIdDone != TRUE);
// Sleep(10);
if(pFEC->MIIPhy)
{
// Set to auto-negotiation mode and restart the
// auto-negotiation process
FECDoMIICmd(pFEC, pFEC->MIIPhy->PhyActint);
FECDoMIICmd(pFEC, pFEC->MIIPhy->PhyConfig);
FECDoMIICmd(pFEC, PHYCmdCfg);
// wait for the auto-negotiation process to complete
// while(pFEC->MIISeqDone != TRUE);
//Sleep(10);
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -FECEnetAutoNego\r\n")));
}
//------------------------------------------------------------------------------
//
// Function: FECEnetReset
//
// This function is called to restart the FEC hardware. Linking status change
// or switching between half and full duplex mode will cause this function to
// be called.
//
// Parameters:
// MiniportAdapterHandle
// [in] Specifies the handle to the driver allocated context area in
// which the driver maintains FEC adapter state, set up by
// FECInitialize
//
// DuplexMode
// [in] TRUE for full duplex mode, FALSE for half duplex mode
//
// Return Value:
// None
//
//------------------------------------------------------------------------------
void FECEnetReset(
IN NDIS_HANDLE MiniportAdapterHandle,
IN BOOL DuplexMode
)
{
volatile PBUFFER_DESC BufferDescPointer;
UINT i;
pFEC_t pEthernet = ((pFEC_t)(MiniportAdapterHandle));
PFEC_ENET_PRIVATE pFEC = &(pEthernet->FECPrivateInfo);
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +FECEnetReset\r\n")));
// Issues a hardware reset, we should wait for this
INSREG32BF(&gpFECReg->ECR, FEC_ECR_RESET, FEC_ECR_RESET_RESET);
while(EXTREG32BF(&gpFECReg->ECR, FEC_ECR_RESET));
// Enable RxF, TxF and MII interrupts
OUTREG32(&gpFECReg->EIMR,
CSP_BITFVAL(FEC_EIMR_TXF, FEC_EIMR_TXF_UNMASK) |
CSP_BITFVAL(FEC_EIMR_RXF, FEC_EIMR_RXF_UNMASK) |
CSP_BITFVAL(FEC_EIMR_MII, FEC_EIMR_MII_UNMASK));
// Clear all pending interrupts
OUTREG32(&gpFECReg->EIR, FEC_EIR_CLEARALL_MASK);
// Set the station MAC address
//FECSetAddr(MiniportAdapterHandle);
// Reset all multicast hashtable and individual hashtable
// NIDS library will restore this by calling
// FECSetInformation() function
OUTREG32(&gpFECReg->IAUR, 0);
OUTREG32(&gpFECReg->IALR, 0);
OUTREG32(&gpFECReg->GAUR, 0);
OUTREG32(&gpFECReg->GALR, 0);
// Set maximum receive buffer size, the size must be aligned with
// 16 bytes
OUTREG32(&gpFECReg->EMRBR, PKT_MAXBLR_SIZE);
// Set receive and transmit descriptor base
OUTREG32(&gpFECReg->ERDSR, (ULONG)pFEC->RingPhysicalBase.QuadPart);
OUTREG32(&gpFECReg->ETDSR,
(ULONG)pFEC->RingPhysicalBase.QuadPart + FEC_RX_RING_SIZE*sizeof(BUFFER_DESC));
pFEC->DirtyTx = pFEC->CurrentTx = pFEC->TxBufferDescBase;
pFEC->CurrentRx = pFEC->RxBufferDescBase;
// Initialize the receive buffer descriptors
BufferDescPointer = pFEC->RxBufferDescBase;
for(i = 0; i < FEC_RX_RING_SIZE; i++)
{
BufferDescPointer->ControlStatus = BD_ENET_RX_EMPTY;
BufferDescPointer++;
}
BufferDescPointer--;
BufferDescPointer->ControlStatus |= BD_SC_WRAP;
// Initialize the transmit buffer descriptor
BufferDescPointer = pFEC->TxBufferDescBase;
for(i = 0; i < FEC_TX_RING_SIZE; i++)
{
BufferDescPointer->ControlStatus = 0;
BufferDescPointer++;
}
BufferDescPointer--;
BufferDescPointer->ControlStatus |= BD_SC_WRAP;
// Enable MII mode and set the Duplex mode
if(DuplexMode)
{
// MII mode enable and FD(Full Duplex) enable
OUTREG32(&gpFECReg->RCR,
CSP_BITFVAL(FEC_RCR_MAXFL, PKT_MAXBUF_SIZE)|
CSP_BITFVAL(FEC_RCR_MIIMODE, FEC_RCR_MIIMODE_ENABLE));
OUTREG32(&gpFECReg->TCR,
CSP_BITFVAL(FEC_TCR_FDEN, FEC_TCR_FDEN_ENABLE));
}
else
{
// MII mode enable and FD disable
OUTREG32(&gpFECReg->RCR,
CSP_BITFVAL(FEC_RCR_MAXFL, PKT_MAXBUF_SIZE)|
CSP_BITFVAL(FEC_RCR_MIIMODE, FEC_RCR_MIIMODE_ENABLE)|
CSP_BITFVAL(FEC_RCR_DRT, FEC_RCR_DRT_ENABLE));
OUTREG32(&gpFECReg->TCR, 0);
}
pFEC->FullDuplex = DuplexMode;
// Set MII speed
OUTREG32(&gpFECReg->MSCR,
CSP_BITFVAL(FEC_MSCR_MIISPEED, pFEC->MIIPhySpeed));
// Finally, enable the fec and enable receive/transmit processing
INSREG32BF(&gpFECReg->ECR, FEC_ECR_ETHEREN, FEC_ECR_ETHEREN_ENABLE);
INSREG32BF(&gpFECReg->RDAR, FEC_RDAR_ACTIVE, FEC_RDAR_ACTIVE_ACTIVE);
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -FECEnetReset\r\n")));
return;
}
//------------------------------------------------------------------------------
//
// Function: CalculateHashValue
//
// This function calculates the 6-bit Hash value for multicasting.
//
// Parameters:
// pAddr
// [in] pointer to a ethernet address
//
// Returns:
// Returns the calculated 6-bit Hash value.
//
//------------------------------------------------------------------------------
UCHAR CalculateHashValue(UCHAR *pAddr)
{
ULONG CRC;
UCHAR HashValue = 0;
UCHAR AddrByte;
int byte, bit;
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +CalculateHashValue\r\n")));
// calculate CRC32 value of MAC address
CRC = CRC_PRIME;
for(byte=0; byte < ETHER_ADDR_SIZE; byte++)
{
AddrByte = *pAddr++;
for(bit = 0; bit < 8; bit++, AddrByte >>= 1)
{
CRC = (CRC >> 1) ^
(((CRC ^ AddrByte) & 1) ? CRC_POLYNOMIAL : 0);
}
}
// only upper 6 bits (HASH_BITS) are used which point to specific
// bit in the hash registers
HashValue = (UCHAR)((CRC >> (32 - HASH_BITS)) & 0x3f);
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -CalculateHashValue [0x%.8X]\r\n"), HashValue));
return HashValue;
}
//------------------------------------------------------------------------------
//
// Function: AddMultiCast
//
// This function adds the Hash value to the Hash table(GAUR and GALR).
//
// Parameters:
// pAddr
// [in] pointer to a ethernet address.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
void AddMultiCast( UCHAR *pAddr )
{
UCHAR HashValue = 0;
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +AddMultiCast\r\n")));
HashValue = CalculateHashValue( pAddr );
if( HashValue > 31 )
SETREG32(&gpFECReg->GAUR, 1 << (HashValue-32));
else
SETREG32(&gpFECReg->GALR, 1 << HashValue);
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -AddMultiCast\r\n")));
}
//------------------------------------------------------------------------------
//
// Function: ClearAllMultiCast
//
// This function clears the Hash table(GAUR and GALR).
//
// Parameters:
// None.
//
// Returns:
// None.
//
//------------------------------------------------------------------------------
void ClearAllMultiCast()
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: +ClearAllMultiCast\r\n")));
// clear all GAUR and GALR bits
CLRREG32(&gpFECReg->GAUR, 0xFFFFFFFF);
CLRREG32(&gpFECReg->GALR, 0xFFFFFFFF);
DEBUGMSG(ZONE_FUNCTION, (TEXT("FEC: -ClearAllMultiCast\r\n")));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -