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

📄 swpkt.c

📁 source code of armboot for s3c4510
💻 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(__DEVICE_H__)
#include "device.h"
#endif
#if !defined(__PLATFORM_H__)
#include "platform.h"
#endif
#if !defined(__ISR_H__)
#include "isr.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
#include "armboot.h"
/*---------------------  Static Definitions  ------------------------*/

#define DEBUG_PKT           0	/*used to print msg, 1 : yes; 0 : no*/
#define DEBUG_PKT_TX        0
#if DEBUG_PKT
#define DBG_PRN_PKT         printf
#else
#define DBG_PRN_PKT(...)    FUNC_NULL()
#endif
#if DEBUG_PKT_TX
#define DBG_PRN_PKT_TX      printf
#else
#define DBG_PRN_PKT_TX(...) FUNC_NULL()
#endif

#define MAC_ADDR_SIZE       6           // 6 bytes

#define RBUF_RX_BUF_NUM     4
#define RBUF_TX_BUF_NUM     1

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


#define ETH_PKT_MAX_LEN     1518        // max packet length, with vlan tag, w/o CRC

#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)
{
	//DBG_PRN_PKT("enter ISR_vRecvPkt...\n");
#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


  	DBG_PRN_PKT(" ISR_vRecvPkt:  clear IRQ status.");
   	 // clear IRQ status
    	SWREG_vWriteU16(CPUIF_IRQ_STATUS, IRQ_STATUS_PKT_RX);
  	DBG_PRN_PKT(" ISR_vRecvPkt:  check if packet is ready to receives.");
    	// 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;
    	}
	// s_vDmaStartRecv(&sg_aRBufRx[0]);
	// return;
	DBG_PRN_PKT(" ISR_vRecvPkt:  rx queue is full.");
    // 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
	DBG_PRN_PKT(" ISR_vRecvPkt:  s_vDmaStartRecv");
    s_vDmaStartRecv(sg_NetDev.apRBufRx[sg_NetDev.u32RxBufEnque]);
#else
	DBG_PRN_PKT(" ISR_vRecvPkt:  s_wRecvPktPIO");
      	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
}
#if 0

//
// 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);
printf("clear IRQ status\n");
    // if tx queue is empty
    if (sg_NetDev.u32TxBufQueueNum == 0) {
#if !__PKT_PIO
        sg_bMuxWrPktInDma = FALSE;
#endif
        return;
    }
printf(" check if CPUIO ready to write packet into\n");
    // check if CPUIO ready to write packet into
    if (SWREG_bIsBitsOffU8(CPUPORT_INPUT_PORT_STATUS, WR_PKT_STATUS_RDY)) {
        // drop this tx packet
        printf("  drop this tx packet\n");
        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
	printf(" s_vDmaStartSend\n");
    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
}
#endif
#if 0
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
printf("Timer_vSendPkt check  tx queue is empty\n");
    // if tx queue is empty
    if (sg_NetDev.u32TxBufQueueNum == 0) {
#if !__PKT_PIO
        sg_bMuxWrPktInDma = FALSE;
#endif
        return;
    }
printf("Timer_vSendPkt check if CPUIO ready to write packet into\n");
    // 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;
    }
printf("Timer_vSendPkt s_vDmaStartSend\n");
#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
}
#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.");
        //
        // 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

⌨️ 快捷键说明

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