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

📄 le1vefpgadma.c

📁 Zalink50114----TDMoIP芯片驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* le1veFpgaDma.c - LE1VE DMA(FPGA) controller libary file   
*
* Copyright     2004-2007 ZTE, Inc.
* author:       ZhengQishan
* date:         2004.03
*
* modification history
*------------------------------
*
*/
#include "le1veLib.h"
#include "le1veFpgaDma.h"
#include "Driver/drvLib/include/drv_comm.h"

#define  DRV_DEBUG_ALL   0xFF
#define  DRV_DEBUG_INT   0x01
#define  DRV_DEBUG_RX    0x02
#define  DRV_DEBUG_TX    0x04

int      le1veDebugFlag = 0;

#define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \
       if (le1veDebugFlag & FLG) \
            logMsg((char *)X0, (int)X1, (int)X2, (int)X3, (int)X4, \
                (int)X5, (int)X6);
       
#if INSTALL_ON_IXP1200
#define LE1VE_BUFFER_CACHE_INVALIDATE(address, len) \
        CACHE_DRV_INVALIDATE (&cacheUserFuncs, (address), (len))

#define LE1VE_BUFFER_CACHE_FLUSH(address, len) \
        CACHE_DRV_FLUSH (&cacheUserFuncs, (address), (len))
#else
#define LE1VE_BUFFER_CACHE_INVALIDATE(address, len)

#define LE1VE_BUFFER_CACHE_FLUSH(address, len)
#endif

extern struct net* if_search(GLOBAL_PORT gport);

LOCAL void cleanRmd(LE1VE_PCI_DRV_CTRL *pDrv);
LOCAL void cleanTmd(LE1VE_PCI_DRV_CTRL *pDrv);
LOCAL void le1veFpgaPciDevModInit(void);
LOCAL void le1veFpgaPciDevInt(LE1VE_PCI_DRV_CTRL  *pDrv);
LOCAL STATUS le1veMemInit(LE1VE_PCI_DRV_CTRL *pDrv);
LOCAL STATUS le1veMemConfig(LE1VE_PCI_DRV_CTRL *pDrv);
LOCAL LE1VE_RMD * le1veReadyRMDGet (LE1VE_PCI_DRV_CTRL *  pDrv);

void le1veFpgaPciDevRec(LE1VE_PCI_DRV_CTRL  *pDrv);
void le1ve_miiCtrlCrcCfg(LE1VE_PCI_DRV_CTRL *pDrv, int mode);
void le1ve_miiCtrlLoopBackCfg(LE1VE_PCI_DRV_CTRL *pDrv, int mode);
void le1ve_miiCtrlRxCfg(LE1VE_PCI_DRV_CTRL *pDrv, int mode);
void le1ve_miiCtrlTxCfg(LE1VE_PCI_DRV_CTRL *pDrv, int mode);
void le1ve_miiCtrlReset(LE1VE_PCI_DRV_CTRL *pDrv);
void le1ve_miiCtrlPreamCfg(LE1VE_PCI_DRV_CTRL *pDrv, int mode);
void le1ve_miiCtrlFullDuplexCfg(LE1VE_PCI_DRV_CTRL *pDrv, int mode);

/*LE1E设备指针与槽位号一一对应,中间不用转换*/
LE1VE_PCI_DRV_CTRL  *gpLe1veDrvCtrl[LE1VE_PCI_MAX_NUM] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};


/*-----------------------------
*le1veFpgaPciDevInit - 初始化LE1VE的PCI设备
*
*Argument: int slot - 槽位号
*
*Return:OK or ERROR if something is wrong
*/
STATUS le1veFpgaPciDevInit(int slot)
{
	LE1VE_PCI_DRV_CTRL  *pDrv;
	STATUS result = OK;
	static STATUS firstTime  = OK;
    UINT32  baseAddr;
    
	if (firstTime == OK)
	{
	    /*读取所有LE1VE PCI设备,并为每一个设备申请一个数据结构*/
		le1veFpgaPciDevModInit();
		firstTime = ERROR;
	}
	if (slot <= 0 || slot > LE1VE_PCI_MAX_NUM)
	{
		printf("le1veFpgaPciDevInit: slot Number Error!\n");
		return ERROR;
	}
	if (NULL == (pDrv = gpLe1veDrvCtrl[slot - 1]))
	{
		printf("No LE1VE FPGA PCI device!\n");
		return ERROR;
	}

	/*Init memory*/
	if (OK != le1veMemInit (pDrv))
	{
		printf("Memory init failed!\n");
		return ERROR;
	}
	le1veMemConfig(pDrv);

	/*connect and enable PCI interrupt*/
	b_pciUnitIntConnect((UINT8)pDrv->slotNo, (VOIDFUNCPTR)le1veFpgaPciDevInt, (int)pDrv);  
    b_pciUnitIntEnable((UINT8)pDrv->slotNo);

	/*Enable all PCI int*/
	pDrv->pMem->pciIntMask = Drv_Swap32(~LE1VE_INT_ALL_MASK);

    /*setup to little endian*/
    baseAddr = IF_CARD_CPU_REG_BASE(pDrv->slotNo);
    *((UINT32 *)(baseAddr + LE1VE_PCI_CONTROL_REG)) &= Drv_Swap32(~LE1VE_BIG_ENDIAN);
    
	#if 1
	le1ve_miiCtrlTxCfg(pDrv, LE1VE_CTRL_TX_ENABLE);
	le1ve_miiCtrlRxCfg(pDrv, LE1VE_CTRL_RX_ENABLE);
	#else
	le1ve_miiCtrlLoopBackCfg(pDrv, LE1VE_CTRL_LOOP_BACK);
	#endif
    
	le1ve_miiCtrlCrcCfg(pDrv, LE1VE_CTRL_CRC_ENABLE);
	return(result);
}

/*-----------------------------
*le1veFpgaPciDevInt - LE1VE的PCI设备中断处理函数
*
*Argument: LE1VE_PCI_DRV_CTRL  *pDrv - pointer to the LE1VE PCI Device
*
*Return:void
*/
LOCAL void le1veFpgaPciDevInt(LE1VE_PCI_DRV_CTRL  *pDrv)
{
	UINT32 intStatus;
	
	/*read PCI int state*/
	intStatus = pDrv->pMem->pciIntState;
        intStatus = Drv_Swap32(intStatus);
    
        DRV_LOG(DRV_DEBUG_INT, "isr: int state = 0x%x!\n", intStatus, 2, 3, 4, 5, 6);
        pDrv->le1vePciInt ++;
	if (0!= (intStatus & LE1VE_RX_PKT_INT))
	{
		pDrv->le1veRxInt++;
		if (pDrv->rxFlag != RX_PKT_JOB_ADDED)
		{
			if(fwdJobAdd ((FUNCPTR)le1veFpgaPciDevRec, (int)pDrv,0,0,0,0)==OK)
			{
				/*disable Rx int*/
				pDrv->pMem->pciIntMask &= Drv_Swap32(~LE1VE_RX_PKT_INT);
				pDrv->rxFlag = RX_PKT_JOB_ADDED;
			}
			else
			{
				pDrv->le1veErrorAddJob++;
			}
		}
	}
	/*接收BD表满,处理流程与收包中断相似,如果把它与接收中断放到一起处理会多一次判断,为了
	提高性能,所以将它们分开处理*/
	if (0!= (intStatus & LE1VE_RX_BD_FULL_INT))
	{	
		pDrv->pMem->pciIntMask &= Drv_Swap32(~LE1VE_RX_BD_FULL_INT);
		pDrv->le1vePciFpgaMode = LE1VE_RX_BD_FULL;
		pDrv->le1vePciRxFullInt++;
		if (pDrv->rxFlag != RX_PKT_JOB_ADDED)
		{
			if(fwdJobAdd ((FUNCPTR)le1veFpgaPciDevRec, (int)pDrv,0,0,0,0)==OK)
			{
				/*disable Rx int*/
				pDrv->pMem->pciIntMask &= Drv_Swap32(~LE1VE_RX_BD_FULL_INT);
				pDrv->rxFlag = RX_PKT_JOB_ADDED;
			}
			else
			{
				pDrv->le1veErrorAddJob++;
			}
		}
		
	}
	if(intStatus & LE1VE_TX_BD_OPT_ERR_INT)
	{
		pDrv->le1vePciTxEmptyInt++;
	}
    if(intStatus & LE1VE_TX_TRANS_ERR_INT)
        pDrv->le1vePciTxMemErr++;
    if(intStatus & LE1VE_RX_TRANS_ERR_INT)
        pDrv->le1vePciRxMemErr++;
}

/*-----------------------------
*le1vePktRcv - LE1VE的PCI设备收包处理函数
*
*Argument: 
*    LE1VE_PCI_DRV_CTRL *   pDrv - pointer to the PCI device
*    LE1VE_RMD *        pRmd - pointer to the Rx BD description
*
*Return:OK or ERROR if something is wrong
*/
STATUS le1vePktRcv(
    LE1VE_PCI_DRV_CTRL *   pDrv, /* device to be initialized */
    LE1VE_RMD *        pRmd )
{
    int             len;
    int		    	oldLevel;
    char            *pBuf;
    char            *pNewBuf;
	void 			*pNet = NULL;
	void            *pkt;
    UINT32          rmd0Tmp;
    UINT32			gPort;
	
    /* 检查接收的包有无错误 */
    rmd0Tmp = Drv_Swap32 (pRmd->RMD0);

    DRV_LOG(DRV_DEBUG_RX, "le1vePktRcv : rmd1 = %X index = %d\n", rmd0Tmp,
             pDrv->rmdIndex, 3, 4, 5, 6);
	
    /* If error flag OR if packet is not completely in one buffer */
    if (rmd0Tmp & RMD0_ERR)
    {
        DRV_LOG(DRV_DEBUG_RX, "le1vePktRcv: RMD error!\n", 1, 2, 3, 4, 5, 6);
        pDrv->le1vePciRxErrorPkt++;
        goto cleanLe1veRXD;
    }
    len = rmd0Tmp & RMD0_PKT_LEN;

    /*判断有没有收到包长为0*/
    if (len == 0)
    {
    	DRV_LOG(DRV_DEBUG_RX, "le1vePktRcv: recieve a length = 0 packer\n",1,2,3,4,5,6);
    	goto cleanLe1veRXD;
    }

	/*Alloc a new buffer for RX BD*/
    pNewBuf = (char*)endPktAlloc();
    if (pNewBuf == NULL)
    {
        DRV_LOG(DRV_DEBUG_RX, "le1vePktRcv: Cannot loan!\n", 1, 2, 3, 4, 5, 6);
        pDrv->le1veErrorAlloc++;
        goto cleanLe1veRXD;
    }

	pBuf = (char *)Drv_Swap32(mapPhysToVirt((UINT32)pRmd->RMD1));

    /* Give receiver a new buffer */
    pRmd->RMD1 = Drv_Swap32(mapVirtToPhys((UINT32)pNewBuf));

    gPort = Ros_GlobalPort(pDrv->slotNo, 5, 0);

    if (pDrv->pNet != NULL)
        pNet = pDrv->pNet;
    else
    {
        if (NULL != (pNet = (void *)if_search(gPort)))
            pDrv->pNet = pNet;
    }
    pDrv->le1vepciRx ++;
    drv_DebugRcvSndPkt(gPort, (char *)pBuf, len, RX_DIRECTION);
    #if 0   /*only for debug*/
		endPktFree(pBuf);
    #else
    
	if (pNet == NULL)
		endPktFree(pBuf);
	else
	{
            END_BUF_GET_PKT(pBuf, pkt);
            etherPktProcess(pkt, pBuf, pNet, len);
	}
	#endif

cleanLe1veRXD:
    LE1VE_CLEAN_RXD(pRmd);
    oldLevel = intLock();
    
    /* Advance our management index */
	pDrv->rmdIndex = (pDrv->rmdIndex + 1) & (pDrv->rringSize - 1);
	intUnlock(oldLevel);
    return (OK);
}

/*-----------------------------
* le1veFpgaPciDevRec - LE1VE的PCI设备中断收包处理函数
*
* 说明:将中断收包转换为任务进行处理,读取接收BD表,处理已经接收完成的
* 数据包
*
* Argument: 
*    LE1VE_PCI_DRV_CTRL *   pDrv - pointer to the PCI device
*   
*
* Return: 
*     void
*/
void le1veFpgaPciDevRec(LE1VE_PCI_DRV_CTRL  *pDrv)
{
	int rxCnt = 0;
	LE1VE_RMD *pRmd;
	
	while (NULL != (pRmd = le1veReadyRMDGet(pDrv)))
	{
		le1vePktRcv(pDrv, pRmd);
		rxCnt ++;
		if (rxCnt >= DEV_LE1VE_PCI_QLEN)
		{
			if(fwdJobAdd ((FUNCPTR)le1veFpgaPciDevRec, (int)pDrv,0,0,0,0)==OK)
			{
				return;
			}
			else
			{
				pDrv->le1veErrorAddJob++;
			}
		}
	}
    pDrv->rxFlag &= ~RX_PKT_JOB_ADDED;

    /*enable Recieve interrupt*/
	pDrv->pMem->pciIntMask |= Drv_Swap32(LE1VE_RX_PKT_INT);
	
    /*如果上行BD表满,FPGA处于阻塞状态,则取走一个包后重新启动FPGA上行*/
    if (pDrv->le1vePciFpgaMode == LE1VE_RX_BD_FULL)
    {
                pDrv->le1vePciFpgaMode &= (~LE1VE_RX_BD_FULL);
		pDrv->pMem->rxEnable |= Drv_Swap32(LE1VE_RX_PKT_ENABLE);
		pDrv->pMem->pciIntMask |= Drv_Swap32(LE1VE_RX_BD_FULL_INT);
	}
}

/*-----------------------------
* le1veFpgaPciDevSend - LE1VE的PCI设备发包处理函数
*
* Argument: 
*    UINT32 gPort - global port number
*    char *pBuf   - pointer to the send data buffer header
*    int size     - the size of send data
*    char *pData  - pointer to the manage buffer   
*
* Return: 
*     OK or ERROR if something is wrong
*/
STATUS le1veFpgaPciDevSend(UINT32 gPort, char *pBuf, int size, char *pData)
{
	int 			slot, oldLevel;
	int             nextIndex;
	UINT32          tmd0;
	void            **pParm;
	LE1VE_TMD       *pTmd;
	LE1VE_TMD       *pTmdFree;
	LE1VE_PCI_DRV_CTRL  *pDrv;

	slot = LE1VE_SLOT_NUM(gPort);
	pDrv = gpLe1veDrvCtrl[slot - 1];
	if ((slot < 1) || (slot > LE1VE_PCI_MAX_NUM) || 
        (pDrv == NULL) || (pBuf == NULL) ||
        (size > LE1VE_MTU) || (size <= 0))
	{
		DRV_LOG(DRV_DEBUG_TX, "%s: Error argument!!\n", __FUNCTION__, 2, 3, 4, 5, 6);
		return ERROR;
	}
	
	semTake(pDrv->TxSemaphore, WAIT_FOREVER);
	nextIndex = (pDrv->tmdIndex + 1) & (pDrv->tringSize - 1);
	pTmd = pDrv->pTring + pDrv->tmdIndex;
	tmd0= Drv_Swap32(pTmd->TMD0);
	
        LE1VE_BUFFER_CACHE_FLUSH ((pBuf), (size));
        
	/*队列已经满,要求释放BD表项*/
	if(nextIndex == pDrv->tmdIndexC)
	{
		pTmdFree = pDrv->pTring + nextIndex;

		if (!(Drv_Swap32 (pTmdFree->TMD0) & TMD0_OWN))
		{
			pParm = &(pDrv->freeData [nextIndex].arg2);
			if (*pParm != NULL)
			{
				endPktFree(*pParm);
				*pParm = NULL;
				DRV_LOG(DRV_DEBUG_TX, "%s:Free a memory space!!\n", __FUNCTION__, 2, 3, 4, 5, 6);
			}

			pDrv->tmdIndexC = (pDrv->tmdIndexC + 1) & (pDrv->tringSize - 1);
			LE1VE_TMD_CLR_ERR (pTmdFree);
		}
		else
		{
			semGive (pDrv->TxSemaphore);
			pDrv->le1vePciTxNoTmd++;
			DRV_LOG(DRV_DEBUG_TX, "%s:no Tmd!!\n", __FUNCTION__, 2, 3, 4, 5, 6);
			return (ERROR);
		}
	}
	pTmd->TMD1 = Drv_Swap32(mapVirtToPhys((UINT32)pBuf));

	tmd0 = size;
	tmd0 |= TMD0_OWN;
	
	/* write to actual register */
	pTmd->TMD0 = Drv_Swap32 (tmd0);

	oldLevel=intLock();
	pDrv->freeData [pDrv->tmdIndex].arg2 = pData;

	/* Advance our management index */
	pDrv->tmdIndex = nextIndex;
	intUnlock(oldLevel);
	pDrv->le1vepciTx++;

    drv_DebugRcvSndPkt(gPort, (char *)pBuf, size, TX_DIRECTION);

	/*enabe transmit*/
	pDrv->pMem->txEnable = Drv_Swap32(LE1VE_TX_PKT_ENABLE);

	/*释放信号量*/
	semGive (pDrv->TxSemaphore);

	return (OK);	
}

STATUS readFpgaDmaStatis(int slot, LE1VE_FPGA_CNT_CTRL_MODE mode, LE1VE_FPGA_DMA_STATIS *pCnt)
{
	volatile char *baseAddr;

	CHECK_CNT_CTRL_MODE(mode);
	baseAddr = (volatile char *)(IF_CARD_CPU_REG_BASE(slot));

	pCnt->MiiRxCnt 		= READ_CNT_REG(baseAddr + LE1VE_MII_RX_CNT_REG);
	pCnt->MiiRxErrCnt 	= READ_CNT_REG(baseAddr + LE1VE_MII_RX_ERR_CNT_REG);
	pCnt->MiiTxCnt 		= READ_CNT_REG(baseAddr + LE1VE_MII_TX_CNT_REG);
	pCnt->MiiTxErrCnt 	= READ_CNT_REG(baseAddr + LE1VE_MII_TX_ERR_CNT_REG);
	pCnt->PciRxCnt 		= READ_CNT_REG(baseAddr + LE1VE_PCI_RX_CNT_REG);
	pCnt->PciRxErrCnt 	= READ_CNT_REG(baseAddr + LE1VE_PCI_RX_ERR_CNT_REG);
	pCnt->PciTxCnt 		= READ_CNT_REG(baseAddr + LE1VE_PCI_TX_CNT_REG);
	pCnt->PciTxErrCnt 	= READ_CNT_REG(baseAddr + LE1VE_PCI_TX_ERR_CNT_REG);
    *(baseAddr + LE1VE_COUNT_CONTROL_REG)  |= Drv_Swap32(mode);
    *(baseAddr + LE1VE_COUNT_CONTROL_REG)  &= Drv_Swap32(~CLEAR_TO_ZERO);
	return(OK);
}

/*-----------------------------
*
* le1veReadyRMDGet - get next received message RMD
*
* Returns ptr to next Rx desc to process, or NULL if none ready.
*/
LOCAL LE1VE_RMD * le1veReadyRMDGet (LE1VE_PCI_DRV_CTRL *  pDrv)
{
    LE1VE_RMD *pRmd;

    pRmd = pDrv->pRring + pDrv->rmdIndex;  /* form ptr to Rx desc */

    /* If receive buffer has been released to us, return it */
    if ((Drv_Swap32 (pRmd->RMD0) & RMD0_OWN) != 0)/*OWN位为1,返回该描述符,否则NULL*/
        return (pRmd);
    else
        return ((LE1VE_RMD *) NULL);
}

/*------------------------------
* le1veMemInit - initialize memory
*
* Using data in the control structure, setup and initialize the memory
* areas needed.   allocate cache safe memory.
*
* Argument: LE1VE_PCI_DRV_CTRL *pDrv - pointer to the LE1VE PCI Device
*
* 此处只分配内存  并填充pDrv结构中的与描述符相关内容,
* 并不初始化描述符,初始化描述符在le1veMemConfig中进行
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS le1veMemInit(LE1VE_PCI_DRV_CTRL *pDrv)
{
	char *pBuf;

⌨️ 快捷键说明

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