📄 swpkt.c
字号:
sg_NetDev.apRBufTx[sg_NetDev.u32TxBufEnque]->pkb_bTagged = pPktBuf->pkb_bTagged;
sg_NetDev.apRBufTx[sg_NetDev.u32TxBufEnque]->pkb_u16VID = pPktBuf->pkb_u16VID;
sg_NetDev.apRBufTx[sg_NetDev.u32TxBufEnque]->pkb_u8Priority = pPktBuf->pkb_u8Priority;
sg_NetDev.apRBufTx[sg_NetDev.u32TxBufEnque]->pkb_u32TxMbrPrtMsk = pPktBuf->pkb_u32TxMbrPrtMsk;
sg_NetDev.apRBufTx[sg_NetDev.u32TxBufEnque]->pkb_u32TxTagPrtMsk = pPktBuf->pkb_u32TxTagPrtMsk;
ADD_ONE_WITH_WRAP_AROUND(sg_NetDev.u32TxBufEnque, RBUF_TX_BUF_NUM);
sg_NetDev.u32TxBufQueueNum++;
PLAT_vCpuCriticalExit();
// if this is the first packet in the tx queue, have to trigger it
if ((sg_NetDev.u32TxBufQueueNum <= 1) || sg_bFirstTxFail) {
sg_bFirstTxFail = FALSE;
if (TMR_iSetTimer(1, (PFN_CALLBACK_TIMER)Timer_vSendPkt, NULL) == FAILED)
Timer_vSendPkt();
}
return TRUE;
}
#if !__PKT_PIO
#ifdef __SWITCH_CPUIF_PCI
/*
* Description : s_vDmaStartRecv only used by Rx Packet Tag Remove Disable(Reg0x0100 bit[2] is 0).
* Packet include 4 bytes CRC.
* Packet also include 4 bytes vlan tag if tagged packet.
*/
static void s_vDmaStartRecv (SRBuf* pRBuf)
{
UINT8 u8HCICsr;
// Get RX vlan tag
SWREG_vReadU16(CPUPORT_RD_PKT_VLAN_TAG, &pRBuf->pkb_u16VID);
pRBuf->pkb_u8Priority = (pRBuf->pkb_u16VID & 0xE000) >> 13;
pRBuf->pkb_u16VID = pRBuf->pkb_u16VID & 0x0FFF;
// Get source port id
SWREG_vReadU8(CPUPORT_RD_PKT_ATTRIB, &pRBuf->pkb_u8SrcPortId);
pRBuf->pkb_bTagged = (pRBuf->pkb_u8SrcPortId & RD_PKT_ATTRIB_TAGGED) != 0;
pRBuf->pkb_u8SrcPortId = pRBuf->pkb_u8SrcPortId & RD_PKT_ATTRIB_PORTID_MSK;
// Get packet size (if larger than ETH_PKT_MAX_LEN, truncate it)
SWREG_vReadU16(CPUPORT_RD_PKT_BYTE_CNT, &pRBuf->pkb_u16BufLen);
pRBuf->pkb_u16BufLen = (pRBuf->pkb_u16BufLen <= (ETH_PKT_MAX_LEN+4)) ? pRBuf->pkb_u16BufLen : (ETH_PKT_MAX_LEN+4);
// +4 is 4 bytes CRC
//
// master read packet procedure:
//
// After all initialize setting finished, trigger the master packet read
// by writing the HCI CSR 0x08h (PS2H_GO = 1).
u8HCICsr = DCR0_PS2H_GO;
PCIIO_Write8((g_u32SwIoBA + DCR0_OFF), u8HCICsr);
//Remove 4 bytes CRC, because Tag Remove Disable
pRBuf->pkb_u16BufLen -= 4;
}
static void s_vDmaStartSend (SRBuf* pRBuf)
{
UINT8 u8HCICsr;
UINT16 u16BlkSize;
UINT32 u32Bnry;
UINT16 u16VlanTag;
// Set Tag rule
SWREG_vWriteU32(CPUPORT_WR_PKT_EGRS_RULE, pRBuf->pkb_u32TxTagPrtMsk);
// Set TX vlan tag
u16VlanTag = pRBuf->pkb_u16VID | (pRBuf->pkb_u8Priority << 13);
SWREG_vWriteU16(CPUPORT_WR_PKT_VLAN_TAG, u16VlanTag);
// Set TX port mask
SWREG_vWriteU32(CPUPORT_WR_PKT_PM, pRBuf->pkb_u32TxMbrPrtMsk);
// Proc. of TX
// Copy packet to page
SWPCICSR_vReadU32(TD_PKT_BNRY_ADDR, &u32Bnry );
// Check if return to page0
if ((u32Bnry + pRBuf->pkb_u16BufLen) > g_u32TdStopPageAddr )
{
u16BlkSize = g_u32TdStopPageAddr - u32Bnry;
STR_pvMemcpy((void *)u32Bnry, (void *)pRBuf->pkb_au8Buffer, u16BlkSize);
STR_pvMemcpy((void *)g_u32TdStrtPageAddr, (void *)(pRBuf->pkb_au8Buffer + u16BlkSize), pRBuf->pkb_u16BufLen - u16BlkSize);
}
else
STR_pvMemcpy((void *)u32Bnry, (void *)pRBuf->pkb_au8Buffer, pRBuf->pkb_u16BufLen);
// Program the HCI CSR 0x5Ch (TD_PKT_BC) the packet byte count.
SWPCICSR_vWriteU16(TD_PKT_BC, pRBuf->pkb_u16BufLen);
// After all initialize setting finished, trigger the master packet read
// by writing the HCI CSR 0x08h (PH2S_GO = 1).
u8HCICsr = DCR0_PH2S_GO;
PCIIO_Write8((g_u32SwIoBA + DCR0_OFF), u8HCICsr);
}
#else // not __SWITCH_CPUIF_PCI
/*
* Description : s_vDmaStartRecv only used by Rx Packet Tag Remove Disable(Reg0x0100 bit[2] is 0).
* Packet include 4 bytes CRC.
* Packet also include 4 bytes vlan tag if tagged packet.
*/
static void s_vDmaStartRecv(SRBuf* pRBuf)
{
UINT8 u8PadCnt;
// Get RX vlan tag
SWREG_vReadU16(CPUPORT_RD_PKT_VLAN_TAG, &pRBuf->pkb_u16VID);
pRBuf->pkb_u8Priority = (pRBuf->pkb_u16VID & 0xE000) >> 13;
pRBuf->pkb_u16VID = pRBuf->pkb_u16VID & 0x0FFF;
// Get source port id
SWREG_vReadU8(CPUPORT_RD_PKT_ATTRIB, &pRBuf->pkb_u8SrcPortId);
pRBuf->pkb_bTagged = (pRBuf->pkb_u8SrcPortId & RD_PKT_ATTRIB_TAGGED) != 0;
pRBuf->pkb_u8SrcPortId = pRBuf->pkb_u8SrcPortId & RD_PKT_ATTRIB_PORTID_MSK;
// Get packet size (if larger than ETH_PKT_MAX_LEN, truncate it)
SWREG_vReadU16(CPUPORT_RD_PKT_BYTE_CNT, &pRBuf->pkb_u16BufLen);
pRBuf->pkb_u16BufLen = (pRBuf->pkb_u16BufLen <= (ETH_PKT_MAX_LEN+4)) ? pRBuf->pkb_u16BufLen : (ETH_PKT_MAX_LEN+4);
// +4 means 4 bytes CRC
// Proc. of RX
SWREG_vWriteU8(CPUIF_RD_PKT_DMA_MODE, DMA_MODE_DEMAND | RP_DMA_CH);
// Set transfer counter, and write packet length to Switch register
u8PadCnt = (4 - (pRBuf->pkb_u16BufLen % 4)) % 4;
SWREG_vWriteU16(CPUIF_RD_PKT_DMA_TRANS_CNT, pRBuf->pkb_u16BufLen + u8PadCnt);
// Set channel ready to Switch register, and let CPU start DMA
PLAT_vDma0GenIntr(FALSE);
PLAT_vDma0TrigRx(pRBuf->pkb_au8Buffer, (pRBuf->pkb_u16BufLen + u8PadCnt) / 2, (UINT32)sg_pioCpuPktData16);
SWREG_vWriteU8(CPUIF_RD_PKT_DMA_CH_RDY, DMA_CH_RDY);
//Remove 4 bytes CRC, because Tag Remove Disable
pRBuf->pkb_u16BufLen -= 4;
}
static void s_vDmaStartSend(SRBuf* pRBuf)
{
UINT8 u8PadCnt;
BOOL bTxTagged;
UINT8 u8TxPort;
UINT16 u16VlanTag;
// check TX is tag/untag by bit-7
bTxTagged = pRBuf->pkb_bTagged;
u8TxPort = pRBuf->pkb_u8SrcPortId;
// Set Tag rule
SWREG_vWriteU32(CPUPORT_WR_PKT_EGRS_RULE, pRBuf->pkb_u32TxTagPrtMsk);
// Set TX vlan tag
u16VlanTag = pRBuf->pkb_u16VID | (pRBuf->pkb_u8Priority << 13);
SWREG_vWriteU16(CPUPORT_WR_PKT_VLAN_TAG, u16VlanTag);
// Set TX port mask
SWREG_vWriteU32(CPUPORT_WR_PKT_PM, pRBuf->pkb_u32TxMbrPrtMsk);
// Proc. of TX
// Set DMA mode, padding count and channel select.
SWREG_vWriteU8(CPUIF_WR_PKT_DMA_MODE, ((pRBuf->pkb_u16BufLen % 4)<<2) | DMA_MODE_DEMAND | WP_DMA_CH);
// Set transfer counter, and write packet length to Switch register
u8PadCnt = (4 - (pRBuf->pkb_u16BufLen % 4)) % 4;
SWREG_vWriteU16(CPUIF_WR_PKT_DMA_TRANS_CNT, pRBuf->pkb_u16BufLen + u8PadCnt);
// Set channel ready to Switch register, and let CPU start DMA
#if __PBUS_DMA_2_CHNNL
PLAT_vDma1GenIntr(FALSE);
PLAT_vDma1TrigTx(pRBuf->pkb_au8Buffer, (pRBuf->pkb_u16BufLen + u8PadCnt) / 2, (UINT32)sg_pioCpuPktData16);
#else
PLAT_vDma0GenIntr(FALSE);
PLAT_vDma0TrigTx(pRBuf->pkb_au8Buffer, (pRBuf->pkb_u16BufLen + u8PadCnt) / 2, (UINT32)sg_pioCpuPktData16);
#endif
SWREG_vWriteU8(CPUIF_WR_PKT_DMA_CH_RDY, DMA_CH_RDY);
}
#endif
#else //#if __PKT_PIO
/*
* Description : s_wRecvPktOp only used by Rx Packet Tag Remove Disable(Reg0x0100 bit[2] is 0).
* Packet include 4 bytes CRC.
* Packet also include 4 bytes vlan tag if tagged packet.
*/
static UINT16 s_wRecvPktPIO (PUINT8 pu8RxBuf, PUINT8 pu8SrcPortId, PBOOL pbTagged, PUINT16 pu16VID, PUINT8 pu8Priority)
{
UINT16 wRxIndex;
UINT16 u16RxLen;
UINT8 u8PadCnt;
// Get RX vlan tag
SWREG_vReadU16(CPUPORT_RD_PKT_VLAN_TAG, pu16VID);
*pu8Priority = (*pu16VID & 0xE000) >> 13;
*pu16VID = *pu16VID & 0x0FFF;
// Get source port id
SWREG_vReadU8(CPUPORT_RD_PKT_ATTRIB, pu8SrcPortId);
*pbTagged = (*pu8SrcPortId & RD_PKT_ATTRIB_TAGGED) != 0;
*pu8SrcPortId = *pu8SrcPortId & RD_PKT_ATTRIB_PORTID_MSK;
// Get packet size (if larger than ETH_PKT_MAX_LEN, truncate it)
SWREG_vReadU16(CPUPORT_RD_PKT_BYTE_CNT, &u16RxLen);
u16RxLen = (u16RxLen <= (ETH_PKT_MAX_LEN+4)) ? u16RxLen : (ETH_PKT_MAX_LEN+4);
// +4 is 4 bytes CRC
//
// Packet Rx Routine:
//
// Packet is transferred in 4-bytes block.
// The packet transfer count should add some padding to be multiple of 4-bytes if the original packet size is not the multiple of block.
u8PadCnt = (4 - (u16RxLen % 4)) % 4;
#ifdef __SWITCH_CPUIF_PCI
// PCI transaction is DW-based(4 bytes), read 4 byte once
for (wRxIndex = 0; wRxIndex < ((u16RxLen+u8PadCnt) / 4); wRxIndex++) {
PCIIO_Read32( (g_u32SwIoBA + PDP_OFF), (PUINT32)(pu8RxBuf + (wRxIndex * 4)));
}
#else // not __SWITCH_CPUIF_PCI
#if __SWITCH_CPUIF_PKT8
// CPU IF is 8-bit width, read 1 byte once,
for (wRxIndex = 0; wRxIndex < (u16RxLen+u8PadCnt); wRxIndex++) {
PKTvReadB(pu8RxBuf + wRxIndex);
}
#else
// CPU IF is 16-bit width, read 2 byte once
for (wRxIndex = 0; wRxIndex < ((u16RxLen+u8PadCnt) / 2); wRxIndex++) {
PKTvReadW(((PUINT16)pu8RxBuf) + wRxIndex);
}
#endif
#endif
// check RD_PKT_STATUS
if (SWREG_bIsBitsOnU8(CPUPORT_OUTPUT_PORT_STATUS, RD_PKT_TRANS_OK)) {
g_NetStat.u32PktRxGood++;
DBG_PRN_PKT(" PKT: good packet.");
//Remove 4 bytes CRC, because Tag Remove Disable
u16RxLen -= 4;
return u16RxLen;
}
// if not OK, it maybe bad packet.
g_NetStat.u32PktRxBad++;
DBG_PRN_PKT(" PKT: error, bad packet.");
return 0;
}
static void s_vSendPktPIO(SRBuf* pRBuf)
{
BOOL bTxTagged;
UINT8 u8TxPort;
UINT16 u16VlanTag;
PUINT8 pu8TxBuf;
UINT16 u16TxLen;
UINT16 u16TxIndex;
UINT8 u8PadCnt;
UINT16 u16Block;
// check TX is tag/untag by bit-7
bTxTagged = pRBuf->pkb_bTagged;
u8TxPort = pRBuf->pkb_u8SrcPortId;
// set Tag rule
SWREG_vWriteU32(CPUPORT_WR_PKT_EGRS_RULE, pRBuf->pkb_u32TxTagPrtMsk);
// Set TX vlan tag
u16VlanTag = pRBuf->pkb_u16VID | (pRBuf->pkb_u8Priority << 13);
SWREG_vWriteU16(CPUPORT_WR_PKT_VLAN_TAG, u16VlanTag);
// Set TX port mask
SWREG_vWriteU32(CPUPORT_WR_PKT_PM, pRBuf->pkb_u32TxMbrPrtMsk);
//
// Packet Tx Routine:
//
pu8TxBuf = pRBuf->pkb_au8Buffer;
u16TxLen = pRBuf->pkb_u16BufLen;
u16TxIndex = 0;
u8PadCnt = (4 - (u16TxLen % 4)) % 4;
u16Block = (u16TxLen + u8PadCnt) / 4;
// Program Write Packet Command to 1 to transmit the first block of packet data.
SWREG_vWriteU8(CPUIF_CPU_PKT_CMD, CPU_PKT_CMD_WR_PKT_START);
#ifdef __SWITCH_CPUIF_PCI
PCIIO_Write32( (g_u32SwIoBA + PDP_OFF), *((PUINT32)pu8TxBuf) );
pu8TxBuf += 4;
u16TxIndex += 4;
#else // not __SWITCH_CPUIF_PCI
PKTvWriteBlock();
#endif
// Program Write Packet Command to 2 to transmit the rest of the packet except the last block.
SWREG_vWriteU8(CPUIF_CPU_PKT_CMD, CPU_PKT_CMD_WR_PKT_MIDDLE);
for (; u16TxIndex < (u16Block - 1)*4 ; ) { //-1 means last block
if ((pRBuf->pu8AppData != NULL) && (u16TxIndex == pRBuf->u16AppDataOffset))
pu8TxBuf = pRBuf->pu8AppData;
#ifdef __SWITCH_CPUIF_PCI
PCIIO_Write32( (g_u32SwIoBA + PDP_OFF), *((PUINT32)pu8TxBuf) );
pu8TxBuf += 4;
u16TxIndex += 4;
#else // not __SWITCH_CPUIF_PCI
#if __SWITCH_CPUIF_PKT8
PKTvWriteB();
#else
PKTvWriteW();
#endif
#endif
}
// Program Write Packet Command to one of the end of frame command to transmit the last block of the packet.
// If the byte count of the actual packet data in the last block is 1, program the command to 4.
// Similarly, if the byte count of the actual packet data in the last block is 2, 3, or 4,
// program the command to 5, 6, or 7 respectively.
SWREG_vWriteU8(CPUIF_CPU_PKT_CMD, CPU_PKT_CMD_WR_PKT_4_VALID - u8PadCnt);
for (; u16TxIndex < (u16Block*4) ; ) {
if ((pRBuf->pu8AppData != NULL) && (u16TxIndex == pRBuf->u16AppDataOffset))
pu8TxBuf = pRBuf->pu8AppData;
#ifdef __SWITCH_CPUIF_PCI
PCIIO_Write32( (g_u32SwIoBA + PDP_OFF), *((PUINT32)pu8TxBuf) );
pu8TxBuf += 4;
u16TxIndex += 4;
#else // not __SWITCH_CPUIF_PCI
#if __SWITCH_CPUIF_PKT8
PKTvWriteB();
#else
PKTvWriteW();
#endif
#endif
}
// check WR_PKT_STATUS
if (SWREG_bIsBitsOnU8(CPUPORT_INPUT_PORT_STATUS, WR_PKT_STATUS_TRANS_OK)) {
g_NetStat.u32PktTxGood++;
DBG_PRN_PKT_TX(" PKTTX: tx ok.");
}
else {
// it maybe send failed, but we don't do re-send now
g_NetStat.u32PktTxBad++;
DBG_PRN_PKT_TX(" PKTTX: error, tx fail.");
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -