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

📄 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 页
字号:

    g_FEC.REG = (PCSP_FEC_REGS)pAddress;
    g_FEC.MIIPhyAddr = 0;

    OALKitlFECBSPInit();
	
    // enable clock for FEC hardware
    FECClockSetGatingMode(DDK_CLOCK_GATE_INDEX_FEC, DDK_CLOCK_GATE_MODE_ENABLE);
    FECClockSetGatingMode(DDK_CLOCK_GATE_INDEX_HCLK_FEC, DDK_CLOCK_GATE_MODE_ENABLE);
	
    // issue a reset to the FEC hardware
    INSREG32BF(&g_FEC.REG->ECR, FEC_ECR_RESET, FEC_ECR_RESET_RESET);
    // wait for the hareware reset to complete
    while(EXTREG32BF(&g_FEC.REG->ECR, FEC_ECR_RESET));
	
    // set the receive and transmit BDs ring base to 
    // hardware registers(ERDSR & ETDSR)
    OUTREG32(&g_FEC.REG->ERDSR, g_FEC.RingPhysicalBase);
    OUTREG32(&g_FEC.REG->ETDSR, 
			g_FEC.RingPhysicalBase + FEC_RX_DMA_RING_SIZE*sizeof(BUFFER_DESC));
			
    // 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); 
        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);
    if(PhyType == 0)
    {
        OALMSGS(OAL_ETHER&&OAL_FUNC, (L"MII_REG_PHYIR1 READ Failed \r\n"));
    }
    MIIPhyId |=  (PhyType & 0xffff);;
       
    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
    {
        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
    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");
    }
	
    //  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 + -