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

📄 c3eth.c

📁 这是交换机或路由器的交换软件部分
💻 C
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************
        (c) COPYRIGHT 2002- by Shenzhen Allywll Information Co.,Ltd
                          All rights reserved.
File:    c3eth.c
Desc:    2*100M ethernet Port is used by centillium A100
Modification history(no, author, date, desc)
1 luke 04-04-01 create file
2 luke 06-11-10 for centillium A100 eth Mac
******************************************************************************/

#include "syscfg.h"

#ifdef _EIA2000V7

#ifdef    __cplusplus
extern "C"{
#endif

#include "aos.h"
#include "ifnet/if_pub.h"
#include "dev/dev_prot.h"
#include "cfm/cfm_pub.h"
#include "drv/eth_pub.h"

#include "iad.h"
#include "iad_packet.h"
#include "iad_chiron_defs.h"
#include "iad_brd_defs.h"
#include "iad_brd_ethphy.h"
#include "iad_queue.h"
#include "iad_ethernet.h"
#include "iad_php.h"
#include "iad_osal.h"
#include "iad_gpio.h"
#include "iad_utils.h"
#include "c3eth.h"

//#define ETH_PHP_ENABLE

ETH_DRV_IF  EthIfDrv[CPU_ETH_PORT_NUM];
iad_eth_CfgBlk  ethCfgBlk[CPU_ETH_PORT_NUM]; 

U32 g_ulEthPollTaskId = 0;
volatile U32 g_bEthPollMode = FALSE;
U32 g_ulEthHiRate  = 35000; // 200字节的报文在100M以太网的流速为625000
U32 g_ulEthLowRate = 30000; // HiRate,lowRate漏桶流速阈值,避免抖动

U32 g_bMirrorFlag    = FALSE;
U32 g_ulWanLinkStatus =FALSE;
U32 g_ulLanLinkStatus =FALSE;
BOOL_T g_bSoftBirdgeFlag = FALSE;

#ifdef ETH_PHP_ENABLE
iad_queueHnd g_hPhpFreeHnd,g_hPhpOverHnd,g_hPhpTaskHnd,g_hResultHnd;
#endif

/* 
 C3ETH 硬件队列需要ALIGN_SIZE对齐的内存块
 2个网口一共8个硬件队列, 多申请一个单位内存块,用于边缘对齐
 2个软件队列
*/ 
#define ALIGN_SIZE  1024
#define HW_QUE_MEM_SIZE  (ALIGN_SIZE*10+ALIGN_SIZE)
U8 g_ucHwQueBlk[HW_QUE_MEM_SIZE];
U8 g_szBcastPacket[6]= { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF };

#define L2MAC_HASH_MAX_NUM   96
#define L2MAC_HASH_GET_VAL(Mac) ((Mac[0]+Mac[5])%L2MAC_HASH_MAX_NUM);
#define L2MAC_AGE_TIME       40  // 90s 在公司局域网很容易L2 FULL
#define L2_AGING_PERIOD      5

//这个hash表是为了快速查找L2-MAC-DstPort二层交换表对应的DstPort
HASH_TABLE_S * g_pstL2MacHashTbl;
// L2-MAC-DstPort二层交换表
L2_MAC_TABLE_S g_L2MacTable[L2MAC_HASH_MAX_NUM];
TMR g_L2AgeTmr;

/* external functions reference*/
extern U32 g_bEthBridgeFlag;
extern U32 cli_out_string ( U32  ulIndex,S8 * szString );

void *eth_get_aligned_quebuf(void)
{
   void *pBuf;
   static U8 ucIndex =0;

   pBuf = g_ucHwQueBlk + ucIndex*ALIGN_SIZE;
   // 硬件队列要求Queue Size对齐
   pBuf += ALIGN_SIZE;

   if( (U8*)pBuf > g_ucHwQueBlk + HW_QUE_MEM_SIZE )
   {
        AOS_ASSERT(0);
        return NULL;
   }
   
   ucIndex++;
   
   if( (U32)pBuf%ALIGN_SIZE )
   {   
       // not alligned 补齐
       (U32)pBuf &=(~(ALIGN_SIZE-1));
   }

   return pBuf;
}

void *eth_get_aligned_buff(void)
{
    U8 *pbuf;

    #ifdef  ALIGN_2048_BUFF
    pbuf = aos_dmem_alloc( MPE_ETH, SID_ETH_RBUF ,4096 );
    if( pbuf )
    {
        pbuf += 2048;
        (U32)pbuf &= (~2047);
    }
    #else
    pbuf = aos_dmem_alloc( MPE_ETH, SID_ETH_RBUF , ETH_RECV_BUF_LEN);
    #endif
    
    return pbuf;
}

/**** ALIGNED MEM TEST ,luke ************************
U8 g_ucHwEthMem[2*N_FREE_PKTS+1][PKT_BUFFER_SIZE];

void *eth_get_aligned_mem(void)
{
   void *pBaseBuf,*pbuf;
   static U8 ucIndex =0;                   

   pBaseBuf = (void*)IAD_ENFORCE_ALIGNMENT(g_ucHwEthMem,PKT_BUFFER_SIZE);
   pbuf = pBaseBuf + ucIndex*PKT_BUFFER_SIZE;

   if( ucIndex > 2*N_FREE_PKTS )
   {
        AOS_ASSERT(0);
        return NULL;
   }

   ucIndex++;
   return pbuf;
}
**************************************/

U32 eth_add_freeq_buff( U32 EthNum )
{
    U32  ix;
    U8   *pRxBuf;
    iad_eth_CfgBlk *p_ethCfgBlk;

    p_ethCfgBlk = &ethCfgBlk[EthNum];
    
    // 在FreeRxQueue中填满预先分配的以太网接收缓冲区 FREEQ_ACCESS_MAX_LIMIT
    p_ethCfgBlk->ethResources.pRxFreeQMem = NULL;
    ///p_ethCfgBlk->RxBDIndex = 0;
    for( ix=0; ix< FREEQ_ACCESS_MAX_LIMIT ; ix++ )
    {
        pRxBuf = eth_get_aligned_buff();
        if( pRxBuf == NULL )
        {
            AOS_ASSERT(0);
            return AOS_FAIL;
        }
        // rx buff
        // p_ethCfgBlk->RxBuff[ix] = pRxBuf;
        if( IAD_SUCCESS != iad_queue_put(p_ethCfgBlk->ethResources.RxFreeQHnd,
                                         &pRxBuf,sizeof(void*)) )
        {
            AOS_ASSERT(0);
            return AOS_FAIL;
        }
    }  

    return AOS_SUCC;
}

U32 eth_sync_phy( U32 ethnum )
{
    iad_Error errCode; 
    unsigned int       eth_phy_link;
    unsigned int       eth_phy_stat;
    unsigned char      eth_ctrl_reg;
    unsigned short     regValue;
    iad_ethHnd         ethHnd;
    iad_eth_CfgBlk     *p_ethCfgBlk;
    U8                 ucHwVer; 
    U8                 phyaddr;
    static BOOL_T      bInit = FALSE;
    
    p_ethCfgBlk = &ethCfgBlk[ethnum];
    ethHnd = p_ethCfgBlk->iadEthHnd;

    // setup Ethernet MAC to Sync with PHY 
    drv_get_pcb_ver(&ucHwVer);
    
    if( ucHwVer == EIAV7_EVD )
    {
        eth_phy_link = IADB_ETH_PHY_KS_STATUS_FULL_DUP;
        eth_phy_stat = IADB_ETH_PHY_KS_STATUS_100_MBPS;
        eth_ctrl_reg = IADB_ETH_PHY_STATUS_KS_REG; 
        phyaddr = ( ethnum?IADB_ETH_PHY1_ADDR: IADB_ETH_PHY0_ADDR);
    }
    else if( ucHwVer == EIAV7_2001 )
    {
        eth_phy_link = IADB_ETH_PHY_RTL8201BL_DUPLEX_EN;
        eth_phy_stat = IADB_ETH_PHY_RTL8201BL_SPEED_100MB;
        eth_ctrl_reg = IADB_ETH_PHY_STATUS_REG;
        phyaddr = ( ethnum?IADB_ETH_PHY1_ADDR: IADB_ETH_PHY0_ADDR);        
    }
    else 
    {
        if( bInit == FALSE )
        {
            bInit = TRUE;   

            // IP175C缺省为175A模式,第一次使用前需要切换为175C模式! luke
            if( IAD_SUCCESS != iad_eth_phyWriteCmd(ethHnd, PHY_29_REG, 31,0x175C ))
            {           
               // 5980 == 175C
               AOS_ASSERT(0);
            }
        }
    
        // EIAV7_2002 EIAV7_2004 IP175C switch LAN固定使用100M全双工
        // WAN根据PHY来确定
        if( ethnum == SERVICE_LAN_PORT )
        {
            iad_eth_setParam (ethHnd, IAD_ETH_PARAM_TX_HALF_DUP_EN, (iad_ethParamData)FALSE);        
            iad_eth_setParam (ethHnd, IAD_ETH_PARAM_TX_DFL_BITTIMES1, (iad_ethParamData)IPG_CLK_FOR_100_MB);
    		iad_eth_setRmiiSpeed(ethHnd, IAD_ETH_RMII_CTRL_USE_100_BASE_T);            		
            return AOS_SUCC;
        }
        else
        {   
            // WAN口MAC与PHY直接连接
            eth_phy_link = IADB_ETH_PHY_IP175C_DUPLEX_EN;   // 5.8 6
            eth_phy_stat = IADB_ETH_PHY_IP175C_SPEED_100MB; // 5.8 7
            eth_ctrl_reg = IADB_ETH_PHY_IP175C_STATUS_REG;
            phyaddr      = IP175C_PHYAD_WAN;
        }
    }

    // call ethPhy_getStatus(...) to get the PHY chip status 
    if( IAD_SUCCESS != iad_eth_phyReadCmd(ethHnd,phyaddr,eth_ctrl_reg) )
    {
        AOS_ASSERT(0);
    }
    
    errCode = iad_eth_phyReadVal(ethHnd, &regValue);
    if ( errCode != IAD_SUCCESS)
    {
        AOS_ASSERT(0);
        return AOS_FAIL;
    }
        
    // set the MAC to proper Duplex Mode by calling Ethernet set param API 
    if ( regValue & eth_phy_link )
    {
        p_ethCfgBlk->ethPhyLnkBlk.ethPhyDuplexMode = TRUE;
        iad_eth_setParam (ethHnd, IAD_ETH_PARAM_TX_HALF_DUP_EN, (iad_ethParamData)FALSE);
    }	
    else
    {
        p_ethCfgBlk->ethPhyLnkBlk.ethPhyDuplexMode = FALSE;
    	iad_eth_setParam(ethHnd, IAD_ETH_PARAM_TX_RANDOM_SEED, (iad_ethParamData)0xAA);		
	    iad_eth_setParam(ethHnd, IAD_ETH_PARAM_TX_RETRY_COL_EN, (iad_ethParamData)TRUE);
        iad_eth_setParam(ethHnd, IAD_ETH_PARAM_TX_COL_MAX_RETRY, (iad_ethParamData)15);
	    iad_eth_setParam(ethHnd, IAD_ETH_PARAM_TX_SLOT_TIME, (iad_ethParamData)0xff);
	    iad_eth_setParam (ethHnd, IAD_ETH_PARAM_TX_HALF_DUP_EN, (iad_ethParamData)TRUE);
    }
    aos_printf( MPE_ETH, " eth port[%d] Duplex changed to %s",
                ethnum,
                (p_ethCfgBlk->ethPhyLnkBlk.ethPhyDuplexMode?"Full":"Half"));

    if ( regValue & eth_phy_stat )
	{
        p_ethCfgBlk->ethPhyLnkBlk.ethPhyLnkSpeed = TRUE;	
        iad_eth_setParam (ethHnd, IAD_ETH_PARAM_TX_DFL_BITTIMES1, (iad_ethParamData)IPG_CLK_FOR_100_MB);
		iad_eth_setRmiiSpeed(ethHnd, IAD_ETH_RMII_CTRL_USE_100_BASE_T);
	}
    else
	{
        p_ethCfgBlk->ethPhyLnkBlk.ethPhyLnkSpeed = FALSE;
        iad_eth_setParam (ethHnd, IAD_ETH_PARAM_TX_DFL_BITTIMES1, (iad_ethParamData)IPG_CLK_FOR_10_MB);
		iad_eth_setRmiiSpeed(ethHnd, IAD_ETH_RMII_CTRL_USE_10_BASE_T);
	}        

    aos_printf( MPE_ETH, " eth port[%d] Speed changed to %s",
                ethnum,
                (p_ethCfgBlk->ethPhyLnkBlk.ethPhyLnkSpeed?"100Mb":"10Mb"));

    return AOS_SUCC;
    
}

// EIA2000V6 have two 100M RMII ethernet Port 
U32 eth_interface_init(DEVLINK_S *pDev,U32 *pIfIndex )
{
    ETH_DRV_IF        *pDrv;
    IFNET_S           *pIf;
    U32                EthNum;
    iad_eth_CfgBlk     *p_ethCfgBlk;
    iad_ethHnd         ethHnd;
    
    if( NULL == pDev || NULL == pIfIndex )
    {
        AOS_ASSERT(0);
        return AOS_FAIL;
    }
    
    pIf                 = (IFNET_S *)if_get_if_by_index(*pIfIndex);
    EthNum              = pIf->if_ulPortNum;
    pIf->if_ulPhyLink   = (U32)&EthIfDrv[EthNum];
    pDrv                = ( ETH_DRV_IF  *) pIf->if_ulPhyLink;
    pDrv->pIf           = pIf;
    pDrv->chan_usSlot   =  pDev->dev_usSlot;
    pDrv->chan_usChan   =  pDev->dev_usChan;
    pDrv->chan_usPort   =  pDev->dev_usPort;
        
    pIf->if_pfPhyTransmit  = eth_send;
    pIf->if_pfReceived     = pIf->if_pfLinkReceived;
    pIf->if_pfPhyIOCtl     = eth_ioctl;
    
    p_ethCfgBlk = &ethCfgBlk[EthNum];

    p_ethCfgBlk->initCfgDone = FALSE;
        
    // setup Ethernet hardware 
    if ( eth_init(EthNum)!= AOS_SUCC )
    {
        AOS_ASSERT(0);
        return AOS_FAIL;
    }

    ethHnd = p_ethCfgBlk->iadEthHnd;
    // 设置以太网参数
    // TxFreeQueue 4字节长度对齐 掩码长度为4,2048为11
    iad_eth_setParam (ethHnd,IAD_ETH_PARAM_PKT_BUF_SIZE,
                      (iad_ethParamData)2048);
    iad_eth_setParam (ethHnd,IAD_ETH_PARAM_ADDR_MASK,
                      (iad_ethParamData)0x4);
                      
    // 以太网打开短帧自动填充
    iad_eth_setParam (ethHnd, IAD_ETH_PARAM_TX_PAD_EN,
                      (iad_ethParamData)TRUE);
    iad_eth_setParam (ethHnd, IAD_ETH_PARAM_RX_PAD_STRIP_EN,
                      (iad_ethParamData)TRUE);

    // 以太网打开16位CRC校验和                      
    iad_eth_setParam (ethHnd, IAD_ETH_PARAM_TX_FCS_EN,
                      (iad_ethParamData)TRUE);

    // 接收报文前面保留96字节,保留用作协议层添加额外字段,ETH_HEADER_RESERV_LEN
    iad_eth_setParam (ethHnd, IAD_ETH_PARAM_PKT_BUF_OFFSET,
                      (iad_ethParamData)ETH_HEADER_RESERV_LEN );


    // 802.3X流控开
    iad_eth_setParam (ethHnd, IAD_ETH_PARAM_PAUSE_EN,
                     (iad_ethParamData)TRUE);
                     
    iad_eth_setParam (ethHnd, IAD_ETH_PARAM_RX_RUNT_EN,
                      (iad_ethParamData)TRUE);

    // 以太网半双工模式自动重发     
    iad_eth_setParam (ethHnd, IAD_ETH_PARAM_TX_RETRY_COL_EN,
                      (iad_ethParamData)TRUE);
    iad_eth_setParam (ethHnd, IAD_ETH_REG_TX_DFL_PARAMS_1,
                      (iad_ethParamData)24);  
    
    // 当前网口的广播报文接收允许 
    iad_eth_setParam( ethHnd,IAD_ETH_PARAM_BCAST_EN,
                      (iad_ethParamData)TRUE);
                      
    // 设置当前网口的单播MAC地址
    cfm_get_mac( EthNum, (U8 *)(p_ethCfgBlk->ethResources.szUniMac) ); 
    /********
    aos_printf(0,"eth=%d macaddr=%x:%x:%x:%x:%x:%x ",
                  ulPortNum,
                  p_ethCfgBlk->ethResources.szUniMac[0],
                  p_ethCfgBlk->ethResources.szUniMac[1],
                  p_ethCfgBlk->ethResources.szUniMac[2],
                  p_ethCfgBlk->ethResources.szUniMac[3],
                  p_ethCfgBlk->ethResources.szUniMac[4],
                  p_ethCfgBlk->ethResources.szUniMac[5]);
    ***************/   
    iad_eth_setParam(ethHnd, IAD_ETH_PARAM_UCAST_ADDR,
                    (iad_ethParamData)(p_ethCfgBlk->ethResources.szUniMac));    

    // 确定EIA工作在桥模式还是在路由器模式
    cfm_get_parameter(CMD_EIA_WORK_MODE,(VOID *)&g_bEthBridgeFlag, sizeof(U32) );
    //g_bSoftBirdgeFlag = g_bEthBridgeFlag;
    // EIA2000V7的处理能力强,Bridge模式下,缺省启动SoftBridge,luke  
    /*
    cfm_get_parameter(CMD_SOFT_BRIDGE_FLAG, 
                      (VOID*)&g_bSoftBirdgeFlag, 
                      sizeof(U32));
    */  
    
    // 软件桥接功能,需要将两个网口的MAC设置为混杂模式                    
    // MAC prosmicuous/unicast模式设置
    if( g_bEthBridgeFlag )
    {
        iad_eth_setParam( ethHnd,IAD_ETH_PARAM_ADDR_FLTR_EN,
                         (iad_ethParamData)FALSE);
    }
    else
    {
        iad_eth_setParam( ethHnd,IAD_ETH_PARAM_ADDR_FLTR_EN,
                     (iad_ethParamData)TRUE);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -