📄 c3eth.c
字号:
}
eth_sync_phy(EthNum);
eth_add_freeq_buff(EthNum);
return AOS_SUCC;
}
U32 eth_init(U16 usEthNum)
{
void *pBuf;
int Qid;
iad_queueHnd qHandle;
iad_ethHnd iadEthHnd;
iad_Error errCode = IAD_SUCCESS;
iad_queueReqPar qParam;
iad_eth_CfgBlk *p_ethCfgBlk;
p_ethCfgBlk = ðCfgBlk[usEthNum];
//分配的硬件队列内存必须按Queue Size内存对齐,硬件队列的长度为1024,2048,4096,....
// 发送后的报文缓冲软件队列,解决C3 MAC的一个BUG ,luke
pBuf = eth_get_aligned_quebuf();
if( pBuf == NULL )
{
AOS_ASSERT(0);
return AOS_FAIL;
}
qParam.qType = IAD_QUEUE_SW;
qParam.qBase = pBuf;
qParam.qLen = ALIGN_SIZE;
qParam.elmLen= sizeof(iad_pktQBlk);
if( (errCode = iad_queue_request( &qParam, &qHandle)) != IAD_SUCCESS )
{
aos_printf(MPE_SYS,"c3eth Sent sw queue error=0x%x",errCode);
AOS_ASSERT(0);
return AOS_FAIL;
}
else
{
p_ethCfgBlk->ethResources.SentQHnd = qHandle;
}
iad_queue_setMinMax(p_ethCfgBlk->ethResources.SentQHnd,
0,
128 );
// requesting transmit queue
pBuf = eth_get_aligned_quebuf();
if( pBuf == NULL )
{
AOS_ASSERT(0);
return AOS_FAIL;
}
p_ethCfgBlk->ethResources.pTxQMem = pBuf;
qParam.qType = IAD_QUEUE_HW;
qParam.qBase = pBuf;
qParam.qLen = ALIGN_SIZE;
qParam.elmLen= sizeof(iad_pktQBlk);
if( (errCode = iad_queue_request( &qParam, &qHandle)) != IAD_SUCCESS )
{
aos_printf(MPE_SYS,"c3eth tx hardware queue error=0x%x",errCode);
AOS_ASSERT(0);
return AOS_FAIL;
}
else
{
iad_queue_id(qHandle, &Qid);
p_ethCfgBlk->ethResources.TxQHnd = qHandle;
p_ethCfgBlk->ethResources.TxQid = Qid;
}
iad_queue_setMinMax(p_ethCfgBlk->ethResources.TxQHnd,
ETH_TX_MIN_Q_COUNT,
ETH_TX_MAX_Q_COUNT );
// 分配的硬件队列内存必须按Queue Size内存对齐,硬件队列的长度为1024,2048,4096,...
pBuf = eth_get_aligned_quebuf();
if( pBuf == NULL )
{
AOS_ASSERT(0);
return AOS_FAIL;
}
// requesting receive queue
p_ethCfgBlk->ethResources.pRxQMem = pBuf;
qParam.qType = IAD_QUEUE_HW;
qParam.qBase = pBuf;
qParam.qLen = ALIGN_SIZE;
qParam.elmLen = sizeof(iad_pktQBlk);
if ( (errCode = iad_queue_request(&qParam, &qHandle))!= IAD_SUCCESS )
{
aos_printf(MPE_SYS,"c3eth rx hardware queue error=0x%x",errCode);
AOS_ASSERT(0);
return errCode;
}
else
{
iad_queue_id(qHandle, &Qid);
p_ethCfgBlk->ethResources.RxQHnd = qHandle;
p_ethCfgBlk->ethResources.RxQid = Qid;
}
iad_queue_setMinMax(p_ethCfgBlk->ethResources.RxQHnd,
ETH_RX_MIN_Q_COUNT,
ETH_RX_MAX_Q_COUNT );
// requesting receive free queue
pBuf = eth_get_aligned_quebuf();
if( pBuf == NULL )
{
AOS_ASSERT(0);
return AOS_FAIL;
}
p_ethCfgBlk->ethResources.pRxFreeQMem = (U8*)pBuf;
qParam.qType = IAD_QUEUE_HW;
qParam.qBase = pBuf;
qParam.qLen = ALIGN_SIZE;
qParam.elmLen = sizeof(void*);
if ( (errCode = iad_queue_request( &qParam,&qHandle))!= IAD_SUCCESS )
{
aos_printf(MPE_SYS,"c3eth free hardware queue error=0x%x",errCode);
AOS_ASSERT(0);
return AOS_FAIL;
}
else
{
iad_queue_id(qHandle, &Qid);
p_ethCfgBlk->ethResources.RxFreeQHnd = qHandle;
p_ethCfgBlk->ethResources.RxFreeQid = Qid;
}
iad_queue_setMinMax(p_ethCfgBlk->ethResources.RxFreeQHnd,
FREEQ_ACCESS_MIN_LIMIT,
FREEQ_ACCESS_MAX_LIMIT );
// requesting transmit free queue
pBuf = eth_get_aligned_quebuf();
if( pBuf == NULL )
{
AOS_ASSERT(0);
return AOS_FAIL;
}
p_ethCfgBlk->ethResources.pTxFreeQMem = pBuf;
qParam.qType = IAD_QUEUE_HW;
qParam.qBase = pBuf;
qParam.qLen = ALIGN_SIZE;
qParam.elmLen = sizeof(void*);
if ( (errCode = iad_queue_request( &qParam,&qHandle))!= IAD_SUCCESS )
{
aos_printf(MPE_SYS,"c3eth free tx hardware queue error=0x%x",errCode);
AOS_ASSERT(0);
return AOS_FAIL;
}
else
{
iad_queue_id(qHandle, &Qid);
p_ethCfgBlk->ethResources.TxFreeQHnd = qHandle;
p_ethCfgBlk->ethResources.TxFreeQid = Qid;
}
if( IAD_SUCCESS != iad_eth_init_rmii( usEthNum,
p_ethCfgBlk->ethResources.TxQHnd,
p_ethCfgBlk->ethResources.RxQHnd,
p_ethCfgBlk->ethResources.TxFreeQHnd,
p_ethCfgBlk->ethResources.RxFreeQHnd,
&iadEthHnd) )
{
AOS_ASSERT(0);
return AOS_FAIL;
}
else
{
p_ethCfgBlk->iadEthHnd = iadEthHnd;
}
return AOS_SUCC;
}
/*L2 MAC hash表处理*/
// 目前方式效率低,对小规模网络问题不大,如果使用空闲队列可以提高效率
L2_MAC_TABLE_S *eth_get_idle_l2mac(void)
{
U32 i;
for(i=0; i< L2MAC_HASH_MAX_NUM; i++ )
{
if( g_L2MacTable[i].flag )
continue;
return (g_L2MacTable+i);
}
return NULL;
}
void eth_l2mac_hash_add(U8 * pMac,L2_MAC_TABLE_S *pL2MacTableItem )
{
U32 ulHashVal;
HASH_NODE_S * pstHashNode;
ulHashVal = L2MAC_HASH_GET_VAL(pMac);
//先找到控制块
pstHashNode = (HASH_NODE_S *)aos_dmem_alloc(MPE_ETH,SID_ETH_L2MAC,sizeof(HASH_NODE_S));
if (AOS_ADDR_INVALID(pstHashNode))
{
AOS_ASSERT(0);
return;
}
pstHashNode->ulHandle = (U32)pL2MacTableItem;
//加入到hash中去
hash_add_node(g_pstL2MacHashTbl, pstHashNode, ulHashVal, NULL);
return;
}
S32 eth_l2mac_hash_match(VOID *pstData, HASH_NODE_S *pstHash)
{
L2_MAC_TABLE_S *pL2MacTable;
if(AOS_ADDR_INVALID(pstData)
|| AOS_ADDR_INVALID(pstHash))
{
return -1;
}
pL2MacTable = (L2_MAC_TABLE_S *)pstHash->ulHandle;
if( 0 == aos_memcmp( pL2MacTable->mac, (U8*)pstData,6 ) )
{
return 0;
}
return -1;
}
void eth_l2mac_hash_remove(L2_MAC_TABLE_S *pL2MacItem)
{
U32 ulHashVal;
HASH_NODE_S * pstHashNode;
if (AOS_ADDR_INVALID(pL2MacItem))
{
return;
}
ulHashVal = L2MAC_HASH_GET_VAL(pL2MacItem->mac);
//先找到控制块
pstHashNode = hash_find_node( g_pstL2MacHashTbl, ulHashVal,
(VOID *)pL2MacItem->mac, eth_l2mac_hash_match);
if (AOS_ADDR_INVALID(pstHashNode))
{
return;
}
//这里只是简单的从hash表中去除,并不释放,在外面释放
hash_delete_node(g_pstL2MacHashTbl, pstHashNode, ulHashVal);
aos_dmem_free(pstHashNode);
return ;
}
L2_MAC_TABLE_S * eth_l2mac_hash_find(U8 *pMac)
{
HASH_NODE_S *pstHashNode;
U32 ulHashVal;
L2_MAC_TABLE_S *pstL2MacItem;
ulHashVal = L2MAC_HASH_GET_VAL(pMac);
//先找到控制块
pstHashNode = hash_find_node(g_pstL2MacHashTbl, ulHashVal,
(VOID *)pMac, eth_l2mac_hash_match);
if (AOS_ADDR_INVALID(pstHashNode))
{
return NULL;
}
pstL2MacItem = (L2_MAC_TABLE_S *)pstHashNode->ulHandle;
if(AOS_ADDR_INVALID(pstL2MacItem))
{
return NULL;
}
return pstL2MacItem;
}
//根据报文的dstMac查找L2_MAC_TABLE的hash索引表,得到此报文的输出端口
U32 eth_get_l2_dstport(U8 *dstmac, U32 *pDstport )
{
L2_MAC_TABLE_S *pstL2MacItem;
// 广播地址的报文需要在两个出口都发送,查找肯定失败
if( 0 == aos_memcmp( g_szBcastPacket,dstmac,6) )
{
return AOS_FAIL;
}
pstL2MacItem = eth_l2mac_hash_find(dstmac);
if( pstL2MacItem == NULL )
{
return AOS_FAIL;
}
*pDstport = pstL2MacItem->port;
if( *pDstport > SERVICE_WAN_PORT )
{
AOS_ASSERT(0);
*pDstport = SERVICE_LAN_PORT;
}
return AOS_SUCC;
}
void eth_send_packet( U32 dstport,U8 *pBuf,U32 ulLen,U32 bFlag )
{
iad_eth_CfgBlk *p_ethCfgBlk;
iad_pktDesc pktDesc;
unsigned int count=0;
U32 ret,i;
U8 *pBufSent;
iad_pktQBlk PktSent;
p_ethCfgBlk = ðCfgBlk[dstport];
pktDesc.pBase = pBuf;
pktDesc.pData = pBuf;
pktDesc.len = ulLen;
//aos_printf(0,"send a packet base=0x%x data=0x%x len=%d",
// pktDesc.pBase,pktDesc.pData,pktDesc.len);
// 待发送的报文的地址压入SentQue软件队列,因为C3的硬件入队列非2048对齐的报文
// 入TxFreeQHnd可能出错!! luke
iad_queue_put(p_ethCfgBlk->ethResources.SentQHnd,
(iad_pktQBlk*)&pktDesc.pData,
sizeof(iad_pktQBlk));
if( IAD_SUCCESS == iad_eth_pktSend(p_ethCfgBlk->iadEthHnd,&pktDesc))
{
ret = iad_queue_count(p_ethCfgBlk->ethResources.TxFreeQHnd,
&count);
if (ret != IAD_SUCCESS )
{
AOS_ASSERT(0);
}
//将已经发送完成的缓冲区释放
for(i=0; i<count; i++)
{
ret= iad_queue_get( p_ethCfgBlk->ethResources.TxFreeQHnd,
&pBuf,sizeof(void*));
if (ret != IAD_SUCCESS )
{
//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,"Tx Free Queue Pointer=0x%x",pBufSent);
}
}
if( bFlag == ETH_NORMAL_SEND )
{
p_ethCfgBlk->ethStatSum.ulTxTotalFrames++;
p_ethCfgBlk->ethStatSum.ulTxTotalBytes+=ulLen;
}
else if( bFlag == ETH_FORWARD_SEND )
{
p_ethCfgBlk->ethStatSum.ulForwardFrames++;
p_ethCfgBlk->ethStatSum.ulForwardBytes+=ulLen;
}
return;
}
// 队列满时跳转到这里
// 队列满的时候,避免内存吊死,应该主动释放
p_ethCfgBlk->ethStatSum.ulPacketTxBDFull++;
aos_dmem_free(mem_obj_head(pBuf));
return;
}
U32 eth_send_mbuf_packet(U32 dstport,MBUF_S *pMBuf)
{
U8 *pBuf,*pBufCopy;
U32 ulLen;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -