📄 mx27fec.c
字号:
//------------------------------------------------------------------------------
//
// Copyright (C) 2004-2007, 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: fec.c
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <ceddk.h>
#include <ethdbg.h>
#include <oal.h>
#include "csp.h"
#include "Mx27FEC.h"
//------------------------------------------------------------------------------
// Defines
#define FEC_RX_DMA_RING_SIZE 4
#define FEC_TX_DMA_RING_SIZE 4
#define FEC_DMA_RX_FRSIZE 2048
#define FEC_DMA_TX_FRSIZE 2048
#define PKT_MAXBLR_SIZE 1520
#define PKT_MAXBUF_SIZE 1518
//------------------------------------------------------------------------------
// Types
typedef struct
{
PCSP_FEC_REGS REG;
UINT32 MIIPhyAddr;
// virtual address and physical address for BDs
PBYTE RingBase;
UINT32 RingPhysicalBase;
// virtual address for receive and transmit buffers
PVOID RxBufferBase;
PVOID TxBufferBase;
PBUFFER_DESC RxBufferDescBase;
PBUFFER_DESC TxBufferDescBase;
PUCHAR RxBuffAddr[FEC_RX_DMA_RING_SIZE];
PUCHAR TxBuffAddr[FEC_TX_DMA_RING_SIZE];
PBUFFER_DESC CurrentRx;
PBUFFER_DESC CurrentTx;
UINT32 hash[2];
UINT32 filter;
}FEC;
//------------------------------------------------------------------------------
// Global Variables
//------------------------------------------------------------------------------
// Local Variables
static FEC g_FEC;
//------------------------------------------------------------------------------
// Local Functions
// External Variables
//-----------------------------------------------------------------------------
// External Functions
extern void EdbgOutputDebugString (LPCSTR sz, ...);
extern UINT32 OALGetTickCount(void);
extern void OALKitlFECBSPInit(void);
//------------------------------------------------------------------------------
//
// Function: FECClockSetGatingMode
//
// Sets the clock gating mode of the peripheral.
//
// Parameters:
// index
// [in] Index for referencing peripheral clock gating control bits.
// mode
// [in] Requested clock gating mode for the peripheral.
//
// Returns:
// Returns TRUE if the clock gating mode was set successfully, otherwise
// returns FALSE.
//
//------------------------------------------------------------------------------
BOOL FECClockSetGatingMode(DDK_CLOCK_GATE_INDEX index, DDK_CLOCK_GATE_MODE mode)
{
UINT32 pccrValOld, pccrValNew, pccrIndex, pccrShift, pccrMask;
PCSP_PLLCRC_REGS pPLLCRC;
//EdbgOutputDebugString("+FECClockSetGatingMode\r\n");
//Map access to CRM
pPLLCRC = (PCSP_PLLCRC_REGS)OALPAtoUA(CSP_BASE_REG_PA_CRM);
// Divide clock gating index by 32 to determine PCCR register index
pccrIndex = index >> 5;
// Calculate shift for PCCR bits by using the index
pccrShift = index % 32;
// Calculate bitmask for PCCR bits
pccrMask = PLLCRC_PCCR_CG_MASK << pccrShift;
// Keep trying until the shared register access to the PCCR succeeds
do {
pccrValOld = INREG32(&pPLLCRC->PCCR0 + pccrIndex);
pccrValNew = (pccrValOld & (~pccrMask)) | (mode << pccrShift);
OUTREG32(&pPLLCRC->PCCR0 + pccrIndex, pccrValNew);
} while (INREG32(&pPLLCRC->PCCR0 + pccrIndex) != pccrValNew);
//EdbgOutputDebugString("-FECClockSetGatingMode PCCR0+%X Value=%X\r\n", pccrIndex, INREG32(&pPLLCRC->PCCR0 + pccrIndex));
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: MIIREAD
//
UINT16 MIIREAD(UINT32 Reg)
{
UINT32 PhyData, MIIReg;
UINT32 RegValue;
volatile UINT32 IntStatues;
//EdbgOutputDebugString("+MIIREAD\r\n");
RegValue = MII_READ_COMMAND(Reg) | CSP_BITFVAL(FEC_MMFR_PA, g_FEC.MIIPhyAddr);
OUTREG32(&g_FEC.REG->MMFR, RegValue);
IntStatues = 0;
while((IntStatues & CSP_BITFVAL(FEC_EIR_MII, 1)) == 0 )
{
IntStatues = INREG32(&g_FEC.REG->EIR) ;
}
OUTREG32(&g_FEC.REG->EIR, INREG32(&g_FEC.REG->EIR));
MIIReg = INREG32(&g_FEC.REG->MMFR);
if(((PhyData = (MIIReg & 0xffff)) != 0xffff) && (PhyData != 0))
return PhyData;
//Read failed
return 0;
}
//------------------------------------------------------------------------------
//
// Function: MIIWRITE
//
VOID MIIWRITE(UINT32 Reg, UINT16 Data)
{
volatile UINT32 IntStatues;
//EdbgOutputDebugString("+MIIWRITE\r\n");
OUTREG32(&g_FEC.REG->MMFR, MII_WRITE_COMMAND(Reg, Data));
IntStatues = 0;
while((IntStatues & CSP_BITFVAL(FEC_EIR_MII, 1)) == 0 )
{
IntStatues = INREG32(&g_FEC.REG->EIR) ;
}
//EdbgOutputDebugString("-MIIWRITE\r\n");
}
//------------------------------------------------------------------------------
//
// Function: CalculateHashValue
//
// This function calculates the Hash value for multicasting.
//
// Parameters:
// pAddr
// [in] pointer to a ethernet address
//
// Returns:
// Returns the calculated Hash value.
//
//------------------------------------------------------------------------------
UCHAR CalculateHashValue(UCHAR *pAddr)
{
ULONG CRC;
UCHAR HashValue = 0;
UCHAR AddrByte;
int byte, bit;
// 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);
return HashValue;
}
//------------------------------------------------------------------------------
//
// Function: FECEnableInts
//------------------------------------------------------------------------------
VOID FECEnableInts()
{
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+FECEnableInts\r\n"));
// We are only interested in RX interrupts, Enable RxF
OUTREG32(&g_FEC.REG->EIMR, CSP_BITFVAL(FEC_EIMR_RXF, FEC_EIMR_RXF_UNMASK) );
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-FECEnableInts\r\n"));
}
//------------------------------------------------------------------------------
//
// Function: FECDisableInts
//
//------------------------------------------------------------------------------
VOID FECDisableInts()
{
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+FECDisableInts\r\n"));
// Disable RxF interrupts
OUTREG32(&g_FEC.REG->EIMR, CSP_BITFVAL(FEC_EIMR_RXF, FEC_EIMR_RXF_MASK) );
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-FECDisableInts\r\n"));
}
//------------------------------------------------------------------------------
//
// Function: FECInitDMABuffer
//
// This function is used to inform this library on where the buffer for
// Tx/Rx DMA is. Driver needs at least:
//
//
//------------------------------------------------------------------------------
BOOL FECInitDMABuffer(UINT32 address, UINT32 size)
{
BOOL rc = FALSE;
volatile PBUFFER_DESC BufferDescPointer;
PBUFFER_DESC DescriptorBase;
UINT32 BufferOffset;
UINT32 ph,i;
//EdbgOutputDebugString("+FECInitDMABuffer(0x%X, 0x%X)\r\n", address, size);
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+FECInitDMABuffer(0x%X, 0x%X)\r\n", address, size));
ph = OALVAtoPA((VOID*)address);
//128bit align
if ((ph & 0x0f) != 0)
{
size -= 16 - (ph & 0x0f);
ph = (ph + 0x0f) & ~0x0f;
}
//Check DAM buffer size
if(size < 16 * 1024 )
{
EdbgOutputDebugString("FECInitDMABuffer DMA Buffer too small\r\n");
OALMSGS(OAL_ERROR, (L"ERROR: FECInitDMABuffer: DMA Buffer too small\r\n" ));
return rc;
}
g_FEC.RingPhysicalBase = ph;
g_FEC.RingBase = (PBYTE)OALPAtoUA(ph);
DescriptorBase = (PBUFFER_DESC)g_FEC.RingBase;
// Set receive and transmit descriptor base
g_FEC.RxBufferDescBase = DescriptorBase;
g_FEC.TxBufferDescBase = DescriptorBase + FEC_RX_DMA_RING_SIZE; //128bit align
g_FEC.CurrentTx = g_FEC.TxBufferDescBase;
g_FEC.CurrentRx = g_FEC.RxBufferDescBase;
// allocate receive buffers and initialize the receive buffer descriptors
BufferDescPointer = g_FEC.RxBufferDescBase;
BufferOffset = sizeof(BUFFER_DESC) * (FEC_RX_DMA_RING_SIZE + FEC_TX_DMA_RING_SIZE);
for(i = 0; i < FEC_RX_DMA_RING_SIZE; i++)
{
BufferDescPointer->ControlStatus = BD_ENET_RX_EMPTY;
BufferDescPointer->BufferAddr = g_FEC.RingPhysicalBase + BufferOffset + i * FEC_DMA_RX_FRSIZE;
g_FEC.RxBuffAddr[BufferDescPointer - g_FEC.RxBufferDescBase] = g_FEC.RingBase + BufferOffset +i*FEC_DMA_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 = g_FEC.TxBufferDescBase;
BufferOffset += FEC_TX_DMA_RING_SIZE * FEC_DMA_TX_FRSIZE;
for(i = 0; i < FEC_TX_DMA_RING_SIZE; i++)
{
BufferDescPointer->ControlStatus = 0;
BufferDescPointer->BufferAddr = g_FEC.RingPhysicalBase + BufferOffset + i * FEC_DMA_TX_FRSIZE;
g_FEC.TxBuffAddr[BufferDescPointer - g_FEC.TxBufferDescBase] = g_FEC.RingBase + BufferOffset +i*FEC_DMA_TX_FRSIZE;
BufferDescPointer++;
}
// set the last buffer to wrap
BufferDescPointer--;
BufferDescPointer->ControlStatus |= BD_SC_WRAP;
OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-FECInitDMABuffer(rc = %d)\r\n", rc));
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: FECInit
//
//------------------------------------------------------------------------------
BOOL FECInit(UINT8 *pAddress, UINT32 offset, UINT16 mac[3])
{
BOOL rc = TRUE;
UINT32 MIIPhyId;
UINT16 PhyType, RegVal;
UINT32 i;
UINT32 MACAdd;
//EdbgOutputDebugString("+FECInit pAddress 0x%x, offset %d\r\n", pAddress, offset);
EdbgOutputDebugString("FECInit MAC ADDR %x:%x:%x:%x:%x:%x\r\n",
mac[0]&0xFF, mac[0]>>8, mac[1]&0xFF, mac[1]>>8, mac[2]&0xFF, mac[2]>>8);
OALMSGS(OAL_ETHER&&OAL_FUNC, (
L"FECInit(0x%08x, 0x%08x, %02x:%02x:%02x:%02x:%02x:%02x)\r\n",
pAddress, offset, mac[0]&0xFF, mac[0]>>8, mac[1]&0xFF, mac[1]>>8,
mac[2]&0xFF, mac[2]>>8 ));
g_FEC.filter = PACKET_TYPE_DIRECTED | PACKET_TYPE_BROADCAST;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -