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

📄 swpkt.c

📁 vt6528芯片交换机API函数和文档运行程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
 * All rights reserved.
 *
 * This software is copyrighted by and is the sole property of
 * VIA Networking Technologies, Inc. This software may only be used
 * in accordance with the corresponding license agreement. Any unauthorized
 * use, duplication, transmission, distribution, or disclosure of this
 * software is expressly forbidden.
 *
 * This software is provided by VIA Networking Technologies, Inc. "as is"
 * and any express or implied warranties, including, but not limited to, the
 * implied warranties of merchantability and fitness for a particular purpose
 * are disclaimed. In no event shall VIA Networking Technologies, Inc.
 * be liable for any direct, indirect, incidental, special, exemplary, or
 * consequential damages.
 *
 *
 * File:    swpkt.c
 *
 * Purpose:
 *
 * Author:  Henry Lin
 *
 * Date:    May 05, 2005
 *
 * Functions:
 *
 * Revision History:
 *
 */


#if !defined(__STR_H__)
#include "str.h"
#endif
#if !defined(__PLATFORM_H__)
#include "platform.h"
#endif
#if !defined(__TIMER_H__)
#include "timer.h"
#endif
#if !defined(__SWCFG_H__)
#include "swcfg.h"
#endif
#if !defined(__SWITCH_H__)
#include "switch.h"
#endif
#if !defined(__SWREG_H__)
#include "swreg.h"
#endif
#if !defined(__SWSYS_H__)
#include "swsys.h"
#endif
#if !defined(__SWPKT_H__)
#include "swpkt.h"
#endif
#if !defined(__MACRO_H__)
#include "macro.h"
#endif



/*---------------------  Static Definitions  ------------------------*/

#define DEBUG_PKT           0
#define DEBUG_PKT_TX        0

#if DEBUG_PKT
#if !defined(__UASSERT_H__)
#include "uassert.h"
#endif
#define DBG_PRN_PKT         DBG_PRN
#else
#define DBG_PRN_PKT(...)    FUNC_NULL()
#endif

#if DEBUG_PKT_TX
#if !defined(__UASSERT_H__)
#include "uassert.h"
#endif
#define DBG_PRN_PKT_TX      DBG_PRN
#else
#define DBG_PRN_PKT_TX(...) FUNC_NULL()
#endif

#define MAC_ADDR_SIZE       6           // 6 bytes

#define RBUF_RX_BUF_NUM     64
#define RBUF_TX_BUF_NUM     64

#define ETH_PKT_MIN_LEN     60          // w/o CRC, w/o vlan tag
#define ETH_TYPE_OFST       12          // ethernet type offset


#define DEF_RP_DMA_WRR_CNT  0x04
#define DEF_WP_DMA_WRR_CNT  0x04

#if __PBUS_DMA_2_CHNNL
#define RP_DMA_CH   DMA_CH0
#define WP_DMA_CH   DMA_CH1
#else
#define RP_DMA_CH   DMA_CH0
#define WP_DMA_CH   DMA_CH0
#endif

#define REQ_EN      (CPUIF_REQ0_EN | CPUIF_REQ1_EN)

/*---------------------  Static Types  ------------------------------*/
struct tagSNetDev {
    UINT32          u32RxBufEnque;
    UINT32          u32RxBufDeque;
    volatile UINT32 u32RxBufQueueNum;

    UINT32          u32TxBufEnque;
    UINT32          u32TxBufDeque;
    volatile UINT32 u32TxBufQueueNum;

    PSRBuf          apRBufRx[RBUF_RX_BUF_NUM];
    PSRBuf          apRBufTx[RBUF_TX_BUF_NUM];
};
typedef struct tagSNetDev       SNetDev;

/*---------------------  Static Macros  -----------------------------*/
#if __SWITCH_CPUIF_PKT8
    #define PKTvReadB(pbyData)      do { *(pbyData) = *sg_pioCpuPktData; } while (0)
    #define PKTvWriteB()            do { *sg_pioCpuPktData = *pu8TxBuf; pu8TxBuf++; u16TxIndex++; } while (0)
    #define PKTvWriteBlock()        do { PKTvWriteB(); PKTvWriteB(); PKTvWriteB(); PKTvWriteB();} while (0)
#else   //cpu bus 16 bit 
    #if defined(__BIG_ENDIAN) && !defined(__CPU_S3C2510A)
        // only for Samsung4510b big endian mode
        #define PKTvReadW(pwData)       do { *((PUINT16)(pwData)) = *sg_pioCpuPktData16; *((PUINT16)(pwData)) = REV_WORD(*((PUINT16)(pwData))); } while (0)
        #define PKTvWriteW()            do { *((PUINT16)pu8TxBuf) = REV_WORD(*((PUINT16)pu8TxBuf)); *sg_pioCpuPktData16 = *((PUINT16)pu8TxBuf); pu8TxBuf += 2; u16TxIndex += 2; } while (0)
#else
        #define PKTvReadW(pwData)       do { *((PUINT16)(pwData)) = *sg_pioCpuPktData16; } while (0)
        #define PKTvWriteW()            do { *sg_pioCpuPktData16 = *((PUINT16)pu8TxBuf); pu8TxBuf += 2; u16TxIndex += 2; } while (0)
    #endif
    #define PKTvWriteBlock()        do { PKTvWriteW(); PKTvWriteW();} while (0)
#endif


#define SWPKT_vSwitchImrEnable(u16IrqBit) do {      \
    UINT16  u16IrqMask;                             \
    SWREG_vReadU16(CPUIF_IRQ_MASK, &u16IrqMask);    \
    u16IrqMask |= (u16IrqBit);                      \
    SWREG_vWriteU16(CPUIF_IRQ_MASK, u16IrqMask);    \
} while (0)


#define SWPKT_vSwitchImrDisable(u16IrqBit) do {     \
    UINT16  u16IrqMask;                             \
    SWREG_vReadU16(CPUIF_IRQ_MASK, &u16IrqMask);    \
    u16IrqMask &= ~(u16IrqBit);                     \
    SWREG_vWriteU16(CPUIF_IRQ_MASK, u16IrqMask);    \
} while (0)


#define ADD_ONE_WITH_WRAP_AROUND(uVar, uModulo) do {    \
    if ((uVar) >= ((uModulo) - 1))                      \
        (uVar) = 0;                                     \
    else                                                \
        (uVar)++;                                       \
} while (0)

/*---------------------  Static Classes  ----------------------------*/

/*---------------------  Static Variables  --------------------------*/
#if __SWITCH_CPUIF_PKT8
volatile UINT8      *sg_pioCpuPktData = (volatile UINT8 *)PLAT_ASIC_CPUIF_BASE_ADDR;
#else
volatile UINT16     *sg_pioCpuPktData16 = (volatile UINT16 *)PLAT_ASIC_CPUIF_BASE_ADDR;
#endif

#if !__PKT_PIO
    #if __PBUS_DMA_2_CHNNL || defined(__SWITCH_CPUIF_PCI)
    static BOOL         sg_bMuxRdPktInDma = FALSE;
    static BOOL         sg_bMuxWrPktInDma = FALSE;
    #else
    static BOOL         sg_bMuxPktInDma = FALSE;
    #define             sg_bMuxRdPktInDma   sg_bMuxPktInDma
    #define             sg_bMuxWrPktInDma   sg_bMuxPktInDma
    #endif
#endif

static PFN_HOOK_PV  sg_pfnHookRecv;
static SNetDev      sg_NetDev;
static BOOL         sg_bFirstTxFail = FALSE;

static SRBuf   sg_aRBufRx[RBUF_RX_BUF_NUM];
static SRBuf   sg_aRBufTx[RBUF_TX_BUF_NUM];

/*---------------------  Static Functions  --------------------------*/
#if !__PKT_PIO
static void s_vDmaStartRecv(SRBuf* pRBuf);
static void s_vDmaStartSend(SRBuf* pRBuf);
#else
static UINT16 s_wRecvPktPIO(PUINT8 pu8RxBuf, PUINT8 pu8SrcPortId, PBOOL pbTagged, PUINT16 pu16VID, PUINT8 pu8Priority);
static void s_vSendPktPIO(SRBuf* pRBuf);
#endif

/*---------------------  Export Variables  --------------------------*/
SNetStat    g_NetStat;

/*---------------------  Import Functions  --------------------------*/




//
// Interrupt Service Routines: Rx Packet
//
void ISR_vRecvPkt (void)
{
#if !__PKT_PIO
    // because we do not clear IRQ status yet, if the interrupt mask open again
    // this interrupt service routine will be called again
    if (sg_bMuxRdPktInDma)
        return;
    sg_bMuxRdPktInDma = TRUE;
#endif

    // clear IRQ status
    SWREG_vWriteU16(CPUIF_IRQ_STATUS, IRQ_STATUS_PKT_RX);

    // check if packet is ready to receive
    if (SWREG_bIsBitsOffU8(CPUPORT_OUTPUT_PORT_STATUS, RD_PKT_RDY)) {
#if !__PKT_PIO
        sg_bMuxRdPktInDma = FALSE;
#endif
        return;
    }

    // rx queue is full
    if (sg_NetDev.u32RxBufQueueNum >= RBUF_RX_BUF_NUM) {
        // drop this rx packet
        SWREG_vBitsOnU8(CPUIF_CPU_PKT_CMD, CPU_PKT_CMD_RD_PKT_ABORT);
        // Need to Read Clear this CPU_PKT_CMD_RD_PKT_ABORT bit. Otherwise, no packet will be received.
        SWREG_bWaitStatus(CPUIF_CPU_PKT_CMD, CPU_PKT_CMD_RD_PKT_ABORT, FALSE);
        g_NetStat.u32ErrorRxBufDrop++;
        DBG_PRN_PKT(" PKT: no rx buffer, drop packet.");
#if !__PKT_PIO
        sg_bMuxRdPktInDma = FALSE;
#endif
        return;
    }

#if !__PKT_PIO
    s_vDmaStartRecv(sg_NetDev.apRBufRx[sg_NetDev.u32RxBufEnque]);
#else
    sg_NetDev.apRBufRx[sg_NetDev.u32RxBufEnque]->pkb_u16BufLen =
            s_wRecvPktPIO(sg_NetDev.apRBufRx[sg_NetDev.u32RxBufEnque]->pkb_au8Buffer,
                    &sg_NetDev.apRBufRx[sg_NetDev.u32RxBufEnque]->pkb_u8SrcPortId,
                    &sg_NetDev.apRBufRx[sg_NetDev.u32RxBufEnque]->pkb_bTagged,
                    &sg_NetDev.apRBufRx[sg_NetDev.u32RxBufEnque]->pkb_u16VID,
                    &sg_NetDev.apRBufRx[sg_NetDev.u32RxBufEnque]->pkb_u8Priority);
    ADD_ONE_WITH_WRAP_AROUND(sg_NetDev.u32RxBufEnque, RBUF_RX_BUF_NUM);
    sg_NetDev.u32RxBufQueueNum++;
#endif
}


//
// Interrupt Service Routines: Tx Packet
//
void ISR_vSendPkt (void)
{
#if !__PKT_PIO
    // because we do not clear IRQ status yet, if the interrupt mask open again
    // this interrupt service routine will be called again
    if (sg_bMuxWrPktInDma)
        return;
    sg_bMuxWrPktInDma = TRUE;
#endif

    // clear IRQ status
    SWREG_vWriteU16(CPUIF_IRQ_STATUS, IRQ_STATUS_PKT_TX);

    // if tx queue is empty
    if (sg_NetDev.u32TxBufQueueNum == 0) {
#if !__PKT_PIO
        sg_bMuxWrPktInDma = FALSE;
#endif
        return;
    }

    // check if CPUIO ready to write packet into
    if (SWREG_bIsBitsOffU8(CPUPORT_INPUT_PORT_STATUS, WR_PKT_STATUS_RDY)) {
        // drop this tx packet
        ADD_ONE_WITH_WRAP_AROUND(sg_NetDev.u32TxBufDeque, RBUF_TX_BUF_NUM);
        sg_NetDev.u32TxBufQueueNum--;
        g_NetStat.u32ErrorTxMacDrop++;
        DBG_PRN_PKT_TX(" PKTTX: error, cpuio not ready to write packet.");
#if !__PKT_PIO
        sg_bMuxWrPktInDma = FALSE;
#endif
        return;
    }

#if !__PKT_PIO
    s_vDmaStartSend(sg_NetDev.apRBufTx[sg_NetDev.u32TxBufDeque]);
#else
    // send next packet
    s_vSendPktPIO(sg_NetDev.apRBufTx[sg_NetDev.u32TxBufDeque]);

    // packet already sent, deque it
    ADD_ONE_WITH_WRAP_AROUND(sg_NetDev.u32TxBufDeque, RBUF_TX_BUF_NUM);
    sg_NetDev.u32TxBufQueueNum--;
#endif
}


void Timer_vSendPkt (void)
{
#if !__PKT_PIO
    // because we do not clear IRQ status yet, if the interrupt mask open again
    // this interrupt service routine will be called again
    if (sg_bMuxWrPktInDma) {
        sg_bFirstTxFail = TRUE;
        return;
    }
    sg_bMuxWrPktInDma = TRUE;
#endif

    // if tx queue is empty
    if (sg_NetDev.u32TxBufQueueNum == 0) {
#if !__PKT_PIO
        sg_bMuxWrPktInDma = FALSE;
#endif
        return;
    }

    // check if CPUIO ready to write packet into
    if (SWREG_bIsBitsOffU8(CPUPORT_INPUT_PORT_STATUS, WR_PKT_STATUS_RDY)) {
        // drop this tx packet
        ADD_ONE_WITH_WRAP_AROUND(sg_NetDev.u32TxBufDeque, RBUF_TX_BUF_NUM);
        sg_NetDev.u32TxBufQueueNum--;
        g_NetStat.u32ErrorTxMacDrop++;
        DBG_PRN_PKT_TX(" PKTTX: error, cpuio not ready to write packet.");
#if !__PKT_PIO
        sg_bMuxWrPktInDma = FALSE;
#endif
        return;
    }

#if !__PKT_PIO
    s_vDmaStartSend(sg_NetDev.apRBufTx[sg_NetDev.u32TxBufDeque]);
#else
    // send next packet
    s_vSendPktPIO(sg_NetDev.apRBufTx[sg_NetDev.u32TxBufDeque]);

    // packet already sent, deque it
    ADD_ONE_WITH_WRAP_AROUND(sg_NetDev.u32TxBufDeque, RBUF_TX_BUF_NUM);
    sg_NetDev.u32TxBufQueueNum--;
#endif
}


#if !__PKT_PIO

#ifdef __SWITCH_CPUIF_PCI

//
// Interrupt Service Routines: Read/Write Packet DMA Completed
//
void ISR_vRdPktDmaCompleted (void)
{
    UINT16 u16PktLen, u16BlkSize;
    PUINT8 pu8PktBuf;


    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 {
        g_NetStat.u32PktRxGood++;
        DBG_PRN_PKT(" PKT: rx good packet.");
        //

⌨️ 快捷键说明

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