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

📄 mx27fec.c

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 C
📖 第 1 页 / 共 2 页
字号:
//------------------------------------------------------------------------------
//
// 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 + -