📄 swpkt.c
字号:
// Copy packet from page
//
u16PktLen = sg_NetDev.apRBufRx[sg_NetDev.u32RxBufEnque]->pkb_u16BufLen;
pu8PktBuf = sg_NetDev.apRBufRx[sg_NetDev.u32RxBufEnque]->pkb_au8Buffer;
// Check if return to page0
if ((g_u32RdPktCurr + u16PktLen) > g_u32RdStopPageAddr ) {
u16BlkSize = g_u32RdStopPageAddr - g_u32RdPktCurr;
STR_pvMemcpy(pu8PktBuf, (void *)g_u32RdPktCurr, u16BlkSize);
STR_pvMemcpy(pu8PktBuf + u16BlkSize, (void *)g_u32RdStrtPageAddr, u16PktLen - u16BlkSize);
}
else
STR_pvMemcpy(pu8PktBuf, (void *)g_u32RdPktCurr, u16PktLen);
// Next free page start address
SWPCICSR_vReadU32(RD_PKT_CURR_ADDR, &g_u32RdPktCurr );
// at this moment, data is really valid on the buffer, so increase rx queue counter here
ADD_ONE_WITH_WRAP_AROUND(sg_NetDev.u32RxBufEnque, RBUF_RX_BUF_NUM);
sg_NetDev.u32RxBufQueueNum++;
}
sg_bMuxRdPktInDma = FALSE;
}
void ISR_vWrPktDmaCompleted (void)
{
if (SWREG_bIsBitsOnU8(CPUIF_WR_PKT_DMA_STATUS, DMA_STATUS_FAIL)) {
g_NetStat.u32PktTxBad++;
// it maybe send failed, but we don't do re-send now
DBG_PRN_PKT_TX(" PKTTX: error, DMA fail.");
}
else {
DBG_PRN_PKT_TX(" PKTTX: DMA ok.");
if (SWREG_bIsBitsOnU8(CPUPORT_INPUT_PORT_STATUS, WR_PKT_STATUS_TRANS_OK)) {
g_NetStat.u32PktTxGood++;
DBG_PRN_PKT_TX(" PKTTX: tx ok.");
}
else {
g_NetStat.u32PktTxBad++;
// it maybe send failed, but we don't do re-send now
DBG_PRN_PKT_TX(" PKTTX: error, tx fail.");
}
}
// no matter tx is ok or failed, decrease tx queue
ADD_ONE_WITH_WRAP_AROUND(sg_NetDev.u32TxBufDeque, RBUF_TX_BUF_NUM);
sg_NetDev.u32TxBufQueueNum--;
sg_bMuxWrPktInDma = FALSE;
}
#else // !__SWITCH_CPUIF_PCI
//
// Interrupt Service Routines: Read Packet DMA Completed
//
void ISR_vRdPktDmaCompleted (void)
{
if (SWREG_bIsBitsOnU8(CPUIF_RD_PKT_DMA_STATUS, DMA_STATUS_FAIL)) {
// if not OK, it maybe bad packet.
g_NetStat.u32PktRxBad++;
DBG_PRN_PKT(" PKT: error, rx bad packet.");
}
else {
// at this moment, data is really valid on the buffer, so increase rx queue counter here
ADD_ONE_WITH_WRAP_AROUND(sg_NetDev.u32RxBufEnque, RBUF_RX_BUF_NUM);
sg_NetDev.u32RxBufQueueNum++;
g_NetStat.u32PktRxGood++;
DBG_PRN_PKT(" PKT: rx good packet.");
}
sg_bMuxRdPktInDma = FALSE;
}
//
// Interrupt Service Routines: Write Packet DMA Completed
//
void ISR_vWrPktDmaCompleted (void)
{
if (SWREG_bIsBitsOnU8(CPUIF_WR_PKT_DMA_STATUS, DMA_STATUS_FAIL)) {
g_NetStat.u32PktTxBad++;
// it maybe send failed, but we don't do re-send now
DBG_PRN_PKT_TX(" PKTTX: error, DMA fail.");
}
else {
DBG_PRN_PKT_TX(" PKTTX: DMA ok.");
if (SWREG_bIsBitsOnU8(CPUPORT_INPUT_PORT_STATUS, WR_PKT_STATUS_TRANS_OK)) {
g_NetStat.u32PktTxGood++;
DBG_PRN_PKT_TX(" PKTTX: tx ok.");
}
else {
g_NetStat.u32PktTxBad++;
// it maybe send failed, but we don't do re-send now
DBG_PRN_PKT_TX(" PKTTX: error, tx fail.");
}
}
// no matter tx is ok or failed, decrease tx queue
ADD_ONE_WITH_WRAP_AROUND(sg_NetDev.u32TxBufDeque, RBUF_TX_BUF_NUM);
sg_NetDev.u32TxBufQueueNum--;
sg_bMuxWrPktInDma = FALSE;
}
#endif // !__SWITCH_CPUIF_PCI
#else // __PKT_PIO
void ISR_vRdPktDmaCompleted (void)
{
}
void ISR_vWrPktDmaCompleted (void)
{
}
#endif // __PKT_PIO
void SWPKT_vDrvOpen (void)
{
UINT uu;
UINT8 u8Cfg = 0;
sg_NetDev.u32RxBufEnque = 0;
sg_NetDev.u32RxBufDeque = 0;
sg_NetDev.u32RxBufQueueNum = 0;
sg_NetDev.u32TxBufEnque = 0;
sg_NetDev.u32TxBufDeque = 0;
sg_NetDev.u32TxBufQueueNum = 0;
sg_pfnHookRecv = NULL;
for (uu = 0; uu < RBUF_RX_BUF_NUM; uu++)
sg_NetDev.apRBufRx[uu] = &sg_aRBufRx[uu];
for (uu = 0; uu < RBUF_TX_BUF_NUM; uu++)
sg_NetDev.apRBufTx[uu] = &sg_aRBufTx[uu];
#ifdef __SWITCH_CPUIF_PCI
// PCI packet buffer configuration
SWPCI_vMstrInit();
#endif
#if !__PKT_PIO
sg_bMuxRdPktInDma = FALSE;
sg_bMuxWrPktInDma = FALSE;
#endif
STR_pvMemset((PUINT8)&g_NetStat, 0, sizeof(SNetStat));
// Forwarding ARP to CPU
// Patch : none IP SNAP with tag packet will always be ARP packet
// Disable forward ARP to CPU port
#if 0
SWREG_vWriteU8(FWDCTL_ARP_CFG, ARP_CFG_REQ_TO_CPU);
#endif
// enable CPU IO
SWREG_vBitsOnU8(CPUPORT_CFG, CPU_CFG_RX_ENABLE | CPU_CFG_TX_ENABLE);
// set CPU bus width, interface, and bus endian
#if !__SWITCH_CPUIF_PKT8
SWREG_vReadU8(CPUIF_HOSTIF_CFG, &u8Cfg);
#ifdef __BIG_ENDIAN
#if !__PKT_PIO
#ifdef __CPU_S3C2510A
u8Cfg |= (HOSTIF_BUS_WIDTH16 | HOSTIF_TRANS_DMA); //why not use HOSTIF_BUS_ENDIAN_BIG TBD?
#else
u8Cfg |= (HOSTIF_BUS_ENDIAN_BIG | HOSTIF_BUS_WIDTH16 | HOSTIF_TRANS_DMA);
#endif
#else //pio
u8Cfg = (u8Cfg & ~(HOSTIF_TRANS_DMA)) | HOSTIF_BUS_WIDTH16;
#endif
#else //Little endian
u8Cfg |= HOSTIF_BUS_WIDTH16;
#if !__PKT_PIO
u8Cfg |= HOSTIF_TRANS_DMA;
#else //pio
u8Cfg &= ~(HOSTIF_TRANS_DMA);
#endif
#endif
SWREG_vWriteU8(CPUIF_HOSTIF_CFG, u8Cfg);
#else //8bit, pio
u8Cfg = 0;
SWREG_vBitsOffU8(CPUIF_HOSTIF_CFG, HOSTIF_BUS_WIDTH16 | HOSTIF_TRANS_DMA | HOSTIF_BUS_ENDIAN_BIG);
#endif
#if !__PKT_PIO
//enable DMA channel
SWREG_vWriteU8(CPUIF_REQ_CFG, REQ_EN);
//set the DMA data transfer count
SWREG_vWriteU16(CPUIF_DMA_ABT_WP_WRR_CNT, DEF_WP_DMA_WRR_CNT);
SWREG_vWriteU16(CPUIF_DMA_ABT_RP_WRR_CNT, DEF_RP_DMA_WRR_CNT);
//set DMA arbitration policy
SWREG_vWriteU8(CPUIF_DMA_ABT_POLICY, DMA_ABT_POLICY_RR);
PLAT_vDma0Enable();
PLAT_vDma1Enable();
#endif
#ifdef __SWITCH_CPUIF_PCI
// clear all interrupt
SWPCICSR_vWriteU32(ISR0_OFF, ISR_STATUS_ALL);
// enable HCI interrupt mask, ISR0/ISR1/ISR2 interrupts
SWPCICSR_vWriteU32(IMR_OFF, ( (((UINT32)ISR3_ALL) << 24) | ( ((UINT32)ISR2_ALL) << 16) |
(((UINT32)ISR1_ALL) << 8) | ((UINT32)ISR0_ALL) )
);
#endif
// clear all interrupt
SWREG_vWriteU16(CPUIF_IRQ_STATUS, IRQ_STATUS_ALL);
// enable switch interrupt mask, Tx/Rx/LinkChange/TxComp/RxComp interrupts
SWREG_vWriteU8(CPUIF_IRQ_MASK, IRQ_STATUS_LINK_CHG | IRQ_STATUS_PKT_RX | IRQ_STATUS_PKT_TX |
IRQ_STATUS_WRPKT_DMA_DONE | IRQ_STATUS_RDPKT_DMA_DONE);
}
void SWPKT_vDrvClose (void)
{
// disable switch interrupt mask
SWREG_vWriteU8(CPUIF_IRQ_MASK, 0);
// disable CPU IO
SWREG_vBitsOffU8(CPUPORT_CFG, CPU_CFG_RX_ENABLE | CPU_CFG_TX_ENABLE);
// stop forwarding ARP to CPU
SWREG_vWriteU8(FWDCTL_ARP_CFG, 0);
}
void SWPKT_vSetHookFnRx (PFN_HOOK_PV pfnHook)
{
PLAT_vCpuCriticalEnter();
sg_pfnHookRecv = pfnHook;
PLAT_vCpuCriticalExit();
}
void SWPKT_vGetMacAddress (UINT8* pu8MacAddr)
{
UINT uu;
for (uu = 0; uu < MAC_ADDR_SIZE; uu++)
if (uu >= 2)
SWREG_vReadU8(FWDCTL_SWITCH_MAC_ADDR0 + (5 - uu), pu8MacAddr + uu);
else
SWREG_vReadU8(FWDCTL_SWITCH_MAC_ADDR1 + (1 - uu), pu8MacAddr + uu);
}
void SWPKT_vSetMacAddress (UINT8* pu8MacAddr)
{
UINT uu;
for (uu = 0; uu < MAC_ADDR_SIZE; uu++)
if (uu >= 2)
SWREG_vWriteU8(FWDCTL_SWITCH_MAC_ADDR0 + (5 - uu), pu8MacAddr[uu]);
else
SWREG_vWriteU8(FWDCTL_SWITCH_MAC_ADDR1 + (1 - uu), pu8MacAddr[uu]);
}
/*
* Description : SWPKT_bRecvPkt only used by Rx Packet Tag Remove Disable(Reg0x0100 bit[2] is 0).
* Packet include 4 bytes vlan tag if tagged packet.
*/
BOOL SWPKT_bRecvPkt (SRBuf* pPktBuf)
{
PUINT8 pu8NonCacheBuf;
// protect the whole section prevent variables ruined by other threads
PLAT_vCpuCriticalEnter();
// if rx buffer is empty, get packet failed
if (sg_NetDev.u32RxBufQueueNum == 0) {
PLAT_vCpuCriticalExit();
return FALSE;
}
DBG_PRN_PKT(" PKT: received packet.");
// copy structure
#if !__PKT_PIO
// Because the cache has the old data, we read from non-cache address
pu8NonCacheBuf = (PUINT8)(((UINT32)sg_NetDev.apRBufRx[sg_NetDev.u32RxBufDeque]->pkb_au8Buffer) | PLAT_ASIC_NON_CACHE_ADDR);
#else
pu8NonCacheBuf = sg_NetDev.apRBufRx[sg_NetDev.u32RxBufDeque]->pkb_au8Buffer;
#endif
//Packet Tag Remove Disable. Remove tag information from packet content
if (sg_NetDev.apRBufRx[sg_NetDev.u32RxBufDeque]->pkb_bTagged){
pPktBuf->pkb_u16BufLen = sg_NetDev.apRBufRx[sg_NetDev.u32RxBufDeque]->pkb_u16BufLen - 4; //-4 means 4 bytes tag
STR_pvMemcpy(pPktBuf->pkb_au8Buffer, pu8NonCacheBuf , 12);
STR_pvMemcpy(pPktBuf->pkb_au8Buffer + 12, pu8NonCacheBuf + 16, pPktBuf->pkb_u16BufLen - 12); // +16 means 6 bytes DMAC, 6 bytes SMAC, and 4 bytes Tag
}
else{
pPktBuf->pkb_u16BufLen = sg_NetDev.apRBufRx[sg_NetDev.u32RxBufDeque]->pkb_u16BufLen;
STR_pvMemcpy(pPktBuf->pkb_au8Buffer, pu8NonCacheBuf, pPktBuf->pkb_u16BufLen);
}
pPktBuf->pu8AppData = NULL;
pPktBuf->u16AppDataOffset = 0;
pPktBuf->pkb_u8SrcPortId = sg_NetDev.apRBufRx[sg_NetDev.u32RxBufDeque]->pkb_u8SrcPortId;
pPktBuf->pkb_bTagged = sg_NetDev.apRBufRx[sg_NetDev.u32RxBufDeque]->pkb_bTagged;
pPktBuf->pkb_u16VID = sg_NetDev.apRBufRx[sg_NetDev.u32RxBufDeque]->pkb_u16VID;
pPktBuf->pkb_u8Priority = sg_NetDev.apRBufRx[sg_NetDev.u32RxBufDeque]->pkb_u8Priority;
ADD_ONE_WITH_WRAP_AROUND(sg_NetDev.u32RxBufDeque, RBUF_RX_BUF_NUM);
sg_NetDev.u32RxBufQueueNum--;
PLAT_vCpuCriticalExit();
return TRUE;
}
BOOL SWPKT_bSendPkt (SRBuf* pPktBuf)
{
BOOL bTxTagged;
UINT8 u8TxPort;
UINT16 u16TxIndex;
PUINT8 pu8TxPktBuf;
UINT16 u16TxPktLen;
u16TxPktLen = pPktBuf->pkb_u16BufLen;
// check if valid packet length
if ((u16TxPktLen == 0) || (ETH_PKT_MAX_LEN < u16TxPktLen)) {
g_NetStat.u32ErrorTxSize++;
DBG_PRN_PKT_TX(" PKTTX: packet size error.");
return FALSE;
}
// protect the whole section prevent variables ruined by other threads
PLAT_vCpuCriticalEnter();
// tx queue is full, not to send
if (sg_NetDev.u32TxBufQueueNum >= RBUF_TX_BUF_NUM) {
PLAT_vCpuCriticalExit();
g_NetStat.u32ErrorTxBufDrop++;
DBG_PRN_PKT_TX(" PKTTX: Drop packet due to no tx buffer.");
return FALSE;
}
// check TX is tag/untag by bit-7
bTxTagged = pPktBuf->pkb_bTagged;
u8TxPort = pPktBuf->pkb_u8SrcPortId;
pu8TxPktBuf = sg_NetDev.apRBufTx[sg_NetDev.u32TxBufEnque]->pkb_au8Buffer;
if (pPktBuf->pu8AppData == NULL) {
STR_pvMemcpy(pu8TxPktBuf, pPktBuf->pkb_au8Buffer, u16TxPktLen);
}
else {
u16TxIndex = pPktBuf->u16AppDataOffset;
STR_pvMemcpy(pu8TxPktBuf, pPktBuf->pkb_au8Buffer, u16TxIndex);
// Copy APP_DATA
STR_pvMemcpy(pu8TxPktBuf + u16TxIndex, pPktBuf->pu8AppData, u16TxPktLen - u16TxIndex);
}
// VT3268 need TX packet >=64 ( i.e. 60 w/o FCS)
if (u16TxPktLen < ETH_PKT_MIN_LEN ) {
STR_pvMemset(pu8TxPktBuf + u16TxPktLen, 0x0, ETH_PKT_MIN_LEN - u16TxPktLen);
u16TxPktLen = pPktBuf->pkb_u16BufLen = ETH_PKT_MIN_LEN;
}
// copy structure
sg_NetDev.apRBufTx[sg_NetDev.u32TxBufEnque]->pkb_u16BufLen = u16TxPktLen;
sg_NetDev.apRBufTx[sg_NetDev.u32TxBufEnque]->pu8AppData = pPktBuf->pu8AppData; //TOCHECK
sg_NetDev.apRBufTx[sg_NetDev.u32TxBufEnque]->u16AppDataOffset = pPktBuf->u16AppDataOffset; //TOCHECK
sg_NetDev.apRBufTx[sg_NetDev.u32TxBufEnque]->pkb_u8SrcPortId = pPktBuf->pkb_u8SrcPortId;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -