📄 c3eth.c
字号:
{
//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 = ðCfgBlk[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 = ðCfgBlk[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,®Value) )
{
if( regValueð_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,®Value) )
{
//aos_printf(0," port=%d reg=%x",ethnum,regValue);
if( regValueð_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, ®Value);
if ( errCode != IAD_SUCCESS)
{
AOS_ASSERT(0);
r
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -