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

📄 c3eth.c

📁 这是交换机或路由器的交换软件部分
💻 C
📖 第 1 页 / 共 5 页
字号:
            {
                //AOS_ASSERT(0);
                break;
            }

            ret= iad_queue_get( p_ethCfgBlk->ethResources.SentQHnd,
                                &PktSent,sizeof(iad_pktQBlk));
            if (ret != IAD_SUCCESS )
            {
                //AOS_ASSERT(0);
                break;
            }
            
            pBufSent = PktSent.pData;
            if( AOS_ADDR_VALID(pBufSent) )
            {
                aos_dmem_free((S8*)mem_obj_head(pBufSent));
            }
            else
            {
                aos_printf(0,"Forward Tx Free Queue Pointer=0x%x",pBufSent);
            }    
        }
        
        p_ethCfgBlk->ethStatSum.ulForwardFrames++;
        p_ethCfgBlk->ethStatSum.ulForwardBytes+=ulLen;  
        
        p_ethCfgBlk->ethStatSum.ulTxTotalFrames++;
        p_ethCfgBlk->ethStatSum.ulTxTotalBytes+=ulLen;   
        
        return AOS_SUCC;
    }

    // 队列满的时候,避免内存吊死,应该主动释放
    p_ethCfgBlk->ethStatSum.ulPacketTxBDFull++;
    aos_dmem_free(mem_obj_head(pBuf));    
    return AOS_FAIL;
}

U32 eth_stream_up(U32 ethnum, char *pBuf, U32 ulLen)
{
    MBUF_S      *pMBuf;
    ETH_DRV_IF  *pDrv;
    IFNET_S     *pIf; 
    ENQUEUE_PF   pf_Enqueue;
    iad_eth_CfgBlk *p_ethCfgBlk;

    if( g_bEthBridgeFlag )
    {
        // 桥模式下,软件刷新DstMAC-EthPort的一张地址表,用于二层转发
        
        // 桥模式下,从LAN口进来的报文也认为是WAN口的,此时只有一个网口
        ethnum = SERVICE_WAN_PORT;
    }
    
    p_ethCfgBlk = &ethCfgBlk[ethnum];
    pDrv        = &EthIfDrv[ethnum];
    
    pIf = pDrv->pIf;             
    MBUF_CREATE_BY_DATA_BLOCK( pMBuf, mem_obj_head(pBuf), mem_obj_size(pBuf),
                               pBuf, ulLen, pIf->if_ulIfIndex, MPE_ETH );
                               
    if( pMBuf  )
    {    
         /* put into queue */
         pf_Enqueue=(ENQUEUE_PF)(pIf->if_pfReceived(pIf,pMBuf));
         pf_Enqueue(pMBuf);      
    }
    else
    {
         AOS_ASSERT(0);   
         aos_dmem_free((S8*)mem_obj_head(pBuf));
    }                              

    return AOS_SUCC;
}


/*******************************************************************************
*
* eth_ioctl - the driver I/O control routine
*
* Process an ioctl request.
*
* RETURNS: A command specific response, usually OK or AOS_FAIL.
*/
U32 eth_ioctl(U32 ulPhyLink, U32 ulCmdIndex, S8*pData)
{
     ETH_DRV_IF *pDrv;
     IFNET_S *pIf ;
     U32  ethnum; 
     
     pDrv= (ETH_DRV_IF *)ulPhyLink;
     if( NULL == pDrv )
     {
         AOS_ASSERT(0);
         return AOS_FAIL;
     }
 
     pIf = pDrv->pIf;
     if( NULL == pIf )
     {
         AOS_ASSERT(0);
         return AOS_FAIL;
     }
 
    ethnum = pIf->if_ulPortNum;
       
	switch(ulCmdIndex)
	{	
        case PHY_POWERUP:                          
             /* 通知链路层底层UP ,把MAC地址递交给链路层*/
              pIf->if_pfLinkIOCtl(pIf,ISLSETMAC,
                                 (S8 *)(ethCfgBlk[ethnum].ethResources.szUniMac));
              pIf->if_pfLinkIOCtl(pIf,ISLUP,NULL);
              eth_start(ethnum);
      		  break;
   		      
		case PHY_SHUTDOWN:
              //eth_phy_close(&EthDrvCtrl);
		      pIf->if_pfLinkIOCtl(pIf,ISLDOWN,NULL);
		      break;
			
		case PHY_NO_SHUT:
              //eth_phy_open(&EthDrvCtrl);
		      pIf->if_pfLinkIOCtl(pIf,ISLUP,NULL);
	          break;
			  
		case PHY_GETINFO:
			  break;
		default:
              AOS_ASSERT(0);
			  return AOS_FAIL;
	}

    return AOS_SUCC;
}


// 秒定时器周期检测网口口状态,状态变化时同步MAC和外部PHY的设置
// 桥接模式下:当两个网口同时LinkUP时,桥接模式下将启动SoftBridge,此时MAC设置为混杂模式
//            当两个网口有一个LinkDown的时候,设置MAC为标准模式
U32 eth_set_switch_mode( void )
{
    static U32 wan_status =FALSE;
    static U32 lan_status =FALSE;

    // 检查WAN端口链路情况
    eth_get_port_status( SERVICE_WAN_PORT, &g_ulWanLinkStatus);
    if( g_ulWanLinkStatus != wan_status )
    {
        // 如果端口状态发生了变化,进行MAC和PHY同步 
        aos_printf( MPE_ETH, " wan eth port link changed to %s",
                    (g_ulWanLinkStatus?"Up":"Down"));
        wan_status = g_ulWanLinkStatus;                
        eth_sync_phy(SERVICE_WAN_PORT);
    }

    // 检查LAN端口链路情况
    eth_get_port_status( SERVICE_LAN_PORT, &g_ulLanLinkStatus);
    if( g_ulLanLinkStatus != lan_status )
    {
        // 如果端口状态发生了变化,进行MAC和PHY同步                           
        aos_printf( MPE_ETH, " lan eth port link changed to %s",
                    (g_ulLanLinkStatus?"Up":"Down"));  
        lan_status = g_ulLanLinkStatus;                    
        eth_sync_phy(SERVICE_LAN_PORT);
    }

    // 桥接模式下:当两个网口同时LinkUP时,桥接模式下将启动SoftBridge,此时MAC设置为混杂模式
    //            当两个网口有一个LinkDown的时候,设置MAC为标准模式
    if( g_bEthBridgeFlag )
    {
        // 对于双口SoftBridge,如果WAN口和LAN口同时LinkUP的时候才需要进行SoftBridge
        if(  g_ulWanLinkStatus &&  g_ulLanLinkStatus )
        {
            if( g_bSoftBirdgeFlag == FALSE )
            {
                g_bSoftBirdgeFlag = TRUE;
                aos_printf( MPE_ETH,"eth soft bridge function enabled.");
                // 打开SoftBridge的时候,将两个MAC设置为混杂模式,这样可以才能接收目的地址不是本机的以太网报文
                iad_eth_setParam( ethCfgBlk[0].iadEthHnd,IAD_ETH_PARAM_ADDR_FLTR_EN,
                     (iad_ethParamData)FALSE);

                iad_eth_setParam( ethCfgBlk[1].iadEthHnd,IAD_ETH_PARAM_ADDR_FLTR_EN,
                     (iad_ethParamData)FALSE);
            }
        }
        else
        {
            if( g_bSoftBirdgeFlag )
            {
                g_bSoftBirdgeFlag = FALSE;
                aos_printf( MPE_ETH,"eth soft bridge function disabled.");                
                // 关闭SoftBridge的时候,将两个MAC设置为单播过滤模式,这样可以减少大量的无用报文被接收,
                // 从而提高系统工作效率
                iad_eth_setParam( ethCfgBlk[0].iadEthHnd,IAD_ETH_PARAM_ADDR_FLTR_EN,
                     (iad_ethParamData)TRUE);

                iad_eth_setParam( ethCfgBlk[1].iadEthHnd,IAD_ETH_PARAM_ADDR_FLTR_EN,
                     (iad_ethParamData)TRUE);
            }
        }          
    }
    
    return AOS_SUCC;
}

U32 eth_read_phy(iad_ethHnd ethHnd,U8 phyaddr,U8 reg ,U16 *pRegValue)
{
    iad_Error       errCode; 
    U32             cnt=0;
    
retryphy:
    errCode = iad_eth_phyReadCmd(ethHnd,phyaddr,reg);
    if( errCode == IAD_SUCCESS )
    {
        errCode = iad_eth_phyReadVal(ethHnd, pRegValue);
        if ( errCode != IAD_SUCCESS)
        {
            AOS_ASSERT(0);
            return AOS_FAIL;
        }  
    }
    else if( errCode == ETH_MDIO_BUSY_ERROR )
    {
        cnt++;
        if( cnt > 100 )
        {
            aos_printf(0,"eth phy read busy,wait...");
            return AOS_FAIL;            
        }
        goto retryphy;
    }
    else
    {
        AOS_ASSERT(0);
        aos_printf(0,"eth phy read err=0x%x",errCode);
        return AOS_FAIL;        
    }

    return AOS_SUCC;
}

int eth_get_port_status( U16 ethnum, U32 *pLinkStatus )
{
    iad_eth_CfgBlk *p_ethCfgBlk;
    iad_ethHnd      ethHnd;
    U8              ucHwVer;
    U8              phyaddr;
    unsigned int    eth_phy_link;
    unsigned char   eth_ctrl_reg;
    U16             regValue;
    
    drv_get_pcb_ver(&ucHwVer);

    //注意 IP175C的硬件MDC/MDIO控制线接在eth0上
    p_ethCfgBlk = &ethCfgBlk[ethnum];
    ethHnd      = ethCfgBlk[0].iadEthHnd;

    if( ucHwVer == EIAV7_EVD )
    {
        eth_phy_link = IADB_ETH_PHY_KS_STATUS_LINK_UP;
        eth_ctrl_reg = IADB_ETH_PHY_KS8721B_STATUS_REG; 
        phyaddr = ( ethnum?IADB_ETH_PHY1_ADDR: IADB_ETH_PHY0_ADDR);
    }
    else if( ucHwVer == EIAV7_2001 )
    {
        eth_phy_link = IADB_ETH_PHY_RTL8201BL_LINK_VALID;
        eth_ctrl_reg = IADB_ETH_PHY_RTL8201BL_STATUS_REG;
        phyaddr = ( ethnum?IADB_ETH_PHY1_ADDR: IADB_ETH_PHY0_ADDR);        
    }
    else 
    {
        // 175C eth switch 
        eth_phy_link = IADB_ETH_PHY_175C_LINK_VALID;
        eth_ctrl_reg = PHY_STATUS_REG;
        
        if( ethnum == SERVICE_WAN_PORT )
        {
            phyaddr = IP175C_PHYAD_WAN;
        } 
        else
        {
            // 交换网LAN端口全部down才认为LAN口down
            for( phyaddr=0; phyaddr< IP175C_PHYAD_WAN;phyaddr++)
            {
                if( AOS_SUCC == eth_read_phy(ethHnd,phyaddr,eth_ctrl_reg,&regValue) )
                {
                    if( regValue&eth_phy_link )
                    {
                        // link UP
                        // aos_printf( 0,"LAN %d LinkUp.",phyaddr);
                        p_ethCfgBlk->ethPhyLnkBlk.ethPhyLnkState = IADB_ETH_PHY_LINK_UP;
                        *pLinkStatus = TRUE; 
                        return AOS_SUCC;
                    }  
                    //aos_printf( 0,"LAN %d LinkDown.",phyaddr);
                }
            }

            // link down
            p_ethCfgBlk->ethPhyLnkBlk.ethPhyLnkState = IADB_ETH_PHY_LINK_DOWN; 
            *pLinkStatus = FALSE;        
            return AOS_SUCC;
        }        
    }

    if( AOS_SUCC == eth_read_phy(ethHnd,phyaddr,eth_ctrl_reg,&regValue) )
    {
        //aos_printf(0," port=%d reg=%x",ethnum,regValue);
        if( regValue&eth_phy_link )
        {
            // link UP
            p_ethCfgBlk->ethPhyLnkBlk.ethPhyLnkState = IADB_ETH_PHY_LINK_UP;
            *pLinkStatus = TRUE;   
        }
        else
        {   
            // link down
            p_ethCfgBlk->ethPhyLnkBlk.ethPhyLnkState = IADB_ETH_PHY_LINK_DOWN; 
           *pLinkStatus = FALSE;    
        }
        return AOS_SUCC;        
    }                                          

    return AOS_FAIL;
}

// bridge <on|off>
VOID eth_set_softbridge_mode(U32 argc, S8 *argv[])
{
    U32 ulUserIndex = 0;
    S8  szBuf[100] = {0};

    //参数合法性检查
    if( NULL == argv )
    {
        AOS_ASSERT(0);
        return ;
    }

    if (0 == aos_stricmp(argv[2],"?"))
    {
        aos_sprintf(szBuf,"\r\n bridge <on|off> ");
        cli_out_string(ulUserIndex, szBuf);
        return;
    }

    if(0 == aos_stricmp(argv[2],"on"))
    {
        g_bSoftBirdgeFlag = TRUE;
    }
    else if(0 == aos_stricmp(argv[2],"off"))
    {
        g_bSoftBirdgeFlag = FALSE;
    }
    else
    {
        aos_sprintf(szBuf,"\r\n invalid cmd, bridge <on|off> ");
        cli_out_string(ulUserIndex, szBuf);
        return;
    }
             
      
    cfm_set_parameter( CMD_SOFT_BRIDGE_FLAG, 
                      &g_bSoftBirdgeFlag, 
                      sizeof(U32));

    aos_sprintf(szBuf,"\r\n software bridge forwarding is %s  ",
                      (g_bSoftBirdgeFlag?"on":"off") );
    cli_out_string(ulUserIndex, szBuf);                      
    return;
    
}

int eth_set_led_mode(U32 mode)
{   
   return AOS_SUCC;
}

/*Only 10M/Half and 10M/full is valid, 
 This routine is called before PHY_POWERUP*/
U32 eth_set_workmode( U32 num, U32 ulWorkMode )
{
   U8              ucHwVer;
   U8              phyaddr;
   iad_ethHnd      ethHnd;
   iad_Error       errCode; 
   unsigned short  regValue;

   ethHnd = ethCfgBlk[num].iadEthHnd;

   drv_get_pcb_ver(&ucHwVer);

   if( ucHwVer == EIAV7_2002 )
   {
        if( num == SERVICE_WAN_PORT )
        {
            iad_eth_phyReadCmd(ethHnd,IP175C_PHYAD_WAN,PHY_CNTL_REG);
        }
        else
        {
            // 0,1,2,3 LAN中任取一个端口
            iad_eth_phyReadCmd(ethHnd,0,PHY_CNTL_REG);
        }
        errCode = iad_eth_phyReadVal(ethHnd, &regValue);
        if ( errCode != IAD_SUCCESS)
        {
            AOS_ASSERT(0);
            r

⌨️ 快捷键说明

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