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

📄 at91emacend.c

📁 atmel9200 vxworks bsp
💻 C
📖 第 1 页 / 共 4 页
字号:
STATUS at91EndMemInit
    (
    at91end_device * pDrvCtrl	/* device to be initialized */
    )
{

    	UINT32 recvfdsize;
	UINT32 txbufsize;
	UINT32 rxbufsize;
	UINT32 tmp;
	/*
     * This is how we would set up and END netPool using netBufLib(1).
     * This code is pretty generic.
     */
    
    if ( (pDrvCtrl->end.pNetPool = (NET_POOL_ID) malloc (sizeof(NET_POOL))) == NULL )
        return (ERROR);

	/*
	 *	allocate the Trans desc buffer
	 */

    at91endMclConfig.mBlkNum =  END_MBLK_NUM;
    at91endClDescTbl[0].clNum = END_CL_NUM;
    at91endMclConfig.clBlkNum = at91endClDescTbl[0].clNum;

    /* Calculate the total memory for all the M-Blks and CL-Blks. */
    at91endMclConfig.memSize = 
		(at91endMclConfig.mBlkNum * (MSIZE + sizeof (long))) +
        (at91endMclConfig.clBlkNum * (CL_BLK_SZ + sizeof(long)));

	at91endMclConfig.memArea = 
		(char *) memalign (sizeof(UINT32), at91endMclConfig.memSize );
    if ( at91endMclConfig.memArea == NULL)
	{
		ENDLOGMSG(( " allocate m and cl block memory failure ", 1, 2, 3, 4, 5, 6 ));
        return (ERROR);
	}

	at91endClDescTbl[0].clSize = ROUND_UP( at91endClDescTbl[0].clSize, 4 );
    
    /* Calculate the memory size of all the clusters. */
    at91endClDescTbl[0].memSize = 
		ROUND_UP( (at91endClDescTbl[0].clNum) * (at91endClDescTbl[0].clSize+4)+sizeof(int), _CACHE_ALIGN_SIZE );
	/*
	 *	allocate Received Buffer Descriptor List memory space, this also should be 
	 *	none cached
	 sizeof(AT91_END_RECV_FD) )*2 is for align

	 */
	recvfdsize = ROUND_UP( RX_FD_NUM*( sizeof(AT91_END_RECV_FD) )*2, _CACHE_ALIGN_SIZE );
	rxbufsize  = ROUND_UP( RX_FD_NUM*at91endClDescTbl[0].clSize, _CACHE_ALIGN_SIZE );

	/*
	 *	allocate Tx fifo buffer space 
	 *	each block size same as receive buffer
	 */

	txbufsize = ROUND_UP( TX_FD_NUM*at91endClDescTbl[0].clSize, _CACHE_ALIGN_SIZE );

    /* Allocate the memory for the clusters , tx buffer and recv descriptor
	 * each memory is insert with a _CACHE_ALIGN_SIZE space for ascess safety
	 */
	at91endClDescTbl[0].memArea = (char*)malloc( at91endClDescTbl[0].memSize + _CACHE_ALIGN_SIZE );
/*
		= (char *) cacheDmaMalloc ( at91endClDescTbl[0].memSize + txbufsize + recvfdsize + _CACHE_ALIGN_SIZE*3 );
*/

    if ( at91endClDescTbl[0].memArea == NULL )
	{
		ENDLOGMSG(( " allocate none cached clusters memory failure ", 1, 2, 3, 4, 5, 6 ));
        return (ERROR);
	}

	/*
	 *	save the points
	 */

	pDrvCtrl ->TranFifoBuf = (char*)cacheDmaMalloc( txbufsize + recvfdsize + rxbufsize + _CACHE_ALIGN_SIZE*3 );
	if( pDrvCtrl ->TranFifoBuf == NULL )
	{
		ENDLOGMSG(( " allocate none cached recv and transmit failure ", 1, 2, 3, 4, 5, 6 ));
        return (ERROR);
	}
	
/*
	pDrvCtrl ->TranFifoBuf = 
		at91endClDescTbl[0].memArea + at91endClDescTbl[0].memSize + _CACHE_ALIGN_SIZE;
*/

	pDrvCtrl ->RecvFifoBuf = (char*)( pDrvCtrl ->TranFifoBuf + txbufsize + _CACHE_ALIGN_SIZE  );

	tmp = (UINT32)( (UINT32)(pDrvCtrl ->RecvFifoBuf) + rxbufsize + _CACHE_ALIGN_SIZE + (RX_FD_NUM*( sizeof(AT91_END_RECV_FD) )) -1 );
	tmp &= (~( (RX_FD_NUM*( sizeof(AT91_END_RECV_FD) )) -1) );

	pDrvCtrl ->RecvBufDesc = (AT91_END_RECV_FD*)( tmp );
	
	pDrvCtrl ->TranPkgNumber = TX_FD_NUM;
	pDrvCtrl ->TranPkgSize = at91endClDescTbl[0].clSize;
	bzero( (void*)(pDrvCtrl ->RecvBufDesc), RX_FD_NUM*sizeof(AT91_END_RECV_FD)  );


    /* Initialize the memory pool. */
    if ( netPoolInit(pDrvCtrl->end.pNetPool, &at91endMclConfig,
                    &at91endClDescTbl[0], endClDescTblNumEnt, NULL ) == ERROR )
    {
		ENDLOGMSG(( " initial net pool for at91 END failure ", 1, 2, 3, 4, 5, 6 ));
        return (ERROR);
    }

    pDrvCtrl->pClPoolId = clPoolIdGet ( pDrvCtrl->end.pNetPool,
		at91endClDescTbl[0].clSize, FALSE);
	
    return OK;
}
/*******************************************************************************
*
* at91EndStart - start the device
*
* This function calls BSP functions to connect interrupts and start the
* device running in interrupt mode.
*
* RETURNS: OK or ERROR
*
*/

LOCAL STATUS at91EndStart
    (
    at91end_device *pDrvCtrl	/* device to be started */
    )
{


	EMAC_S* pemac = (EMAC_S*)EMAC_BASE_ADDR;
	UINT32 dummy;
/*
	ENDLOGMSG ((" Enter at91EndStart...\n", 1, 2, 3, 4, 5, 6));	
*/
	/*
	 *	load control register: for back pressure we don't use, start here ?
	 */
	pemac ->EMAC_CTL = EMAC_CTL_RE | EMAC_CTL_TE ;

	pemac ->EMAC_IDR = 0xFFFFFFFF;
	dummy = pemac ->EMAC_ISR;
	/* Connect BDMA and MAC TX and RX interrupts */ /*modified by knp/nts 27/9/99 */ 
													
	intConnect ( (VOIDFUNCPTR *)INUM_TO_IVEC ( pDrvCtrl->level ), at91EndInt, (UINT32) pDrvCtrl );

	/* Enable all the four interrupts */ /*modified by knp/nts 27/9/9/99 */

	intEnable ( pDrvCtrl->level );

	
	/*
	 *	enable interrupt if not in polling mode.
	 */
	if ( (pDrvCtrl->flags & LS_POLLING) == 0 )
		pemac ->EMAC_IER = 	EMAC_ISR_RBNA /*| EMAC_ISR_TOVR*/ | EMAC_ISR_TUND | EMAC_ISR_RTRY
			/*| EMAC_ISR_TBRE */| EMAC_ISR_TCOM | EMAC_ISR_ROVR | EMAC_ISR_HRESP | EMAC_ISR_RCOM;
	
	
	/* Set the flags to indicate that the device is up */
	END_FLAGS_SET (&pDrvCtrl->end, IFF_UP | IFF_RUNNING);
	
/*
	ENDLOGMSG ((" leave at91EndStart...\n", 1, 2, 3, 4, 5, 6));
*/
	
    return (OK);
}



/*******************************************************************************
* at91EndBdmaRxInt - handle controller interrupt
*
* This routine is called at interrupt level in response to an interrupt from
* the BdmaTx controller.
*
* RETURNS: N/A.
*/

LOCAL void TranNextPackage( at91end_device* pDrvCtrl )
{
	EMAC_S* pemac = (EMAC_S*)EMAC_BASE_ADDR;	

	if( 
		  ( (pDrvCtrl ->TxPtr) != (pDrvCtrl ->TxTailPtr) )
			|| ( pDrvCtrl ->TXFifoStat == TXFIFOFULL )  
	  )
	{
/*
		ENDLOGMSG ((" END:Interrupt pack sended ...\n", 1, 2, 3, 4, 5, 6));
*/
		pemac ->EMAC_TAR = (UINT32)((pDrvCtrl ->pTxBufStart[pDrvCtrl ->TxPtr]).bufaddr);
		/*
		 *	write a length start the tans
		 */
		pemac ->EMAC_TCR = ( pDrvCtrl ->pTxBufStart[pDrvCtrl ->TxPtr]).len&(0x7FF) ;
		
		if( pDrvCtrl ->TxPtr == (TX_FD_NUM - 1) )
			pDrvCtrl ->TxPtr = 0;
		else
			pDrvCtrl ->TxPtr ++;
			
		if( pDrvCtrl ->TxPtr == pDrvCtrl ->TxTailPtr )
		{
			pDrvCtrl ->TXFifoStat = TXFIFOEMPTY;
		}
		else
			pDrvCtrl ->TXFifoStat = TXFIFONORMAL;
	}
}


LOCAL void at91EndInt
    (
    at91end_device  *pDrvCtrl	/* interrupting device */
    )
{
	UINT32 status, txstatus;
	EMAC_S* pemac = (EMAC_S*)(EMAC_BASE_ADDR);
	char *nextp;

	
	/*
	 *	read the Int status register, clear ISR status at same time
	 */
	status = pemac ->EMAC_ISR;

	if( status & 
		( EMAC_ISR_RBNA | EMAC_ISR_TOVR | EMAC_ISR_TUND | EMAC_ISR_TBRE 
			| EMAC_ISR_ROVR | EMAC_ISR_HRESP  ) )
	{
		logMsg( "END: error occured, interrupt status reg is %x", status, 2,3,4,5,6 );
	}

	/*
	 *	avoid dead lock of receive buf if not available
	 */
/*
	if( status & EMAC_ISR_RBNA )
	{
		pemac ->EMAC_CTL &= ( ~EMAC_CTL_RE );
		pemac ->EMAC_CTL |= EMAC_CTL_RE;
	}
*/

	/*
	 *	reflash error counter
	 */
	 
	pDrvCtrl ->statistics.ESTAT_FRA += pemac ->ESTAT.EMAC_FRA;
	pDrvCtrl ->statistics.ESTAT_SCOL+= pemac ->ESTAT.EMAC_SCOL;  
	pDrvCtrl ->statistics.ESTAT_MCOL+= pemac ->ESTAT.EMAC_MCOL;  
	pDrvCtrl ->statistics.ESTAT_OK 	+= pemac ->ESTAT.EMAC_OK; 	
	pDrvCtrl ->statistics.ESTAT_SEQE+= pemac ->ESTAT.EMAC_SEQE;  
	pDrvCtrl ->statistics.ESTAT_ALE	+= pemac ->ESTAT.EMAC_ALE;   
	pDrvCtrl ->statistics.ESTAT_DTE	+= pemac ->ESTAT.EMAC_DTE;   
	pDrvCtrl ->statistics.ESTAT_LCOL+= pemac ->ESTAT.EMAC_LCOL;  
	pDrvCtrl ->statistics.ESTAT_ECOL+= pemac ->ESTAT.EMAC_ECOL;  
	pDrvCtrl ->statistics.ESTAT_CSE += pemac ->ESTAT.EMAC_CSE;   
	pDrvCtrl ->statistics.ESTAT_TUE	+= pemac ->ESTAT.EMAC_TUE;   
	pDrvCtrl ->statistics.ESTAT_CDE += pemac ->ESTAT.EMAC_CDE;   
	pDrvCtrl ->statistics.ESTAT_ELR += pemac ->ESTAT.EMAC_ELR;   
	pDrvCtrl ->statistics.ESTAT_RJB	+= pemac ->ESTAT.EMAC_RJB;   
	pDrvCtrl ->statistics.ESTAT_USF += pemac ->ESTAT.EMAC_USF;   
	pDrvCtrl ->statistics.ESTAT_SQEE+= pemac ->ESTAT.EMAC_SQEE;  
	pDrvCtrl ->statistics.ESTAT_DRFC+= pemac ->ESTAT.EMAC_DRFC;  

	/*
	 *	do receive job
	 */
	if( (pDrvCtrl ->NetJobDoing == FALSE) && ( status & EMAC_ISR_RCOM ) )
	{
		ENDLOGMSG ((" END:Interrupt pack received ...\n", 1, 2, 3, 4, 5, 6));

		netJobAdd ((FUNCPTR)at91EndHandleRcvInt, (int)pDrvCtrl, status, 0 , 0 , 0 );
		pDrvCtrl ->NetJobDoing = TRUE;
	}

	/*
	 *	do transmit job
	 */
	txstatus = pemac ->EMAC_TSR;

	if(  /*(status&EMAC_ISR_TCOM )&&*/( txstatus & EMAC_TSR_BNQ ) )
	{
		/*
		 *	TxPtr ->next ready to send package
		 *	TxTailPtr ->Next to accept transmit package
		 */
		TranNextPackage( pDrvCtrl );
	}
}



/*******************************************************************************
*
* at91EndHandleRcvInt - task level interrupt service for input packets
*
* This routine is called at task level indirectly by the interrupt
* service routine to do any message received processing.
*
* RETURNS: N/A.

*/


LOCAL void at91EndHandleRcvInt
    (
    at91end_device *pDrvCtrl,	/* interrupting device */
	UINT32 stat	/* receive status */
    )
{
	EMAC_S* pemac = (EMAC_S*)EMAC_BASE_ADDR;
	AT91_END_RECV_FD* startadd = pDrvCtrl->RecvBufDesc;

	ENDLOGMSG ((" Enter at91EndHandleRcvInt routine...\n", 1, 2, 3, 4, 5, 6));

	pDrvCtrl ->NetJobDoing = FALSE;
	
	while( (startadd[pDrvCtrl ->rxBufPtr].bufaddr) & EMAC_RECV_DESC_HAVE_DATA	 )
	{
		at91EndRecv ( pDrvCtrl, pDrvCtrl ->rxBufPtr );
		
/*
		if( pDrvCtrl ->rxBufPtr == (RX_FD_NUM -1) )
		{
			pDrvCtrl ->rxBufPtr = 0;
		}
		else
			pDrvCtrl ->rxBufPtr ++;
*/
	}
	ENDLOGMSG ((" Leave at91EndHandleRcvInt routine...\n", 1, 2, 3, 4, 5, 6));
}


/*******************************************************************************
*
* at91EndRecv - process the next incoming packet
*
* Handle one incoming packet.  The packet is checked for errors.
*
* RETURNS: N/A.
*/

LOCAL STATUS at91EndRecv
    (
    at91end_device *pDrvCtrl,	/* device structure */
	UINT32 recvdescptr
    )
{
    M_BLK_ID 	pMblk;
    char*       pNewCluster;
    CL_BLK_ID	pClBlk;
	UINT32 tmp;
	UINT32 len;

    /* Add one to our unicast data. */
	END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);

    /*
     * We implicitly are loaning here, if copying is necessary this
     * step may be skipped, but the data must be copied before being
     * passed up to the protocols.
     */
    pNewCluster = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId );

    if (pNewCluster == NULL)
    {
		END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
		goto cleanRXD;
    }

	if( ((UINT32)pNewCluster)&3 )
	{
		ENDLOGMSG(( "END:handle recv get clust buffer not word aligned",(UINT32)pNewCluster,2,3,4,5,6  ));
	}

    /* Grab a cluster block to marry to the cluster we received. */

    if ( (pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT) ) == NULL)
    {
        netClFree ( pDrvCtrl->end.pNetPool, pNewCluster );
		END_ERR_ADD ( &pDrvCtrl->end, MIB2_IN_ERRS, +1 );
		goto cleanRXD;
    }


    /*
     * OK we've got a spare, let's get an M_BLK_ID and marry it to the
     * one in the ring.
     */

    if ((pMblk = mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL)
    {
        netClBlkFree ( pDrvCtrl->end.pNetPool, pClBlk ); 
        netClFree ( pDrvCtrl->end.pNetPool, pNewCluster );
		END_ERR_ADD ( &pDrvCtrl->end, MIB2_IN_ERRS, +1 );
		goto cleanRXD;
    }

    END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
	
	
    /* Join the cluster to the MBlock */
	len = (pDrvCtrl ->RecvBufDesc[recvdescptr].recvstatus&(0x7ff));
	
	bcopy (  pDrvCtrl ->clPointBuf[recvdescptr], pNewCluster+2, len  );
/*
    netClBlkJoin ( pClBlk, pDrvCtrl ->clPointBuf[recvdescptr], at91endClDescTbl[0].clSize, NULL, 0, 0, 0);

*/
	netClBlkJoin ( pClBlk, pNewCluster, at91endClDescTbl[0].clSize, NULL, 0, 0, 0);
	
	netMblkClJoin (pMblk, pClBlk);

	tmp = 2;
	/*
	( ((pDrvCtrl ->RecvBufDesc)[recvdescptr].bufaddr&0xFFFFFFFC) 
			- (UINT32)(pDrvCtrl ->clPointBuf[recvdescptr]) );*/
	

	pMblk->mBlkHdr.mData += tmp;

    pMblk->mBlkHdr.mLen = len;
    pMblk->mBlkHdr.mFlags |= M_PKTHDR;
    pMblk->mBlkPktHdr.len = pMblk->mBlkHdr.mLen;

	(pDrvCtrl ->RecvBufDesc)[recvdescptr].bufaddr &= 0xFFFFFFFE;
	if( pDrvCtrl ->rxBufPtr == (RX_FD_NUM -1) )
	{
		pDrvCtrl ->rxBufPtr = 0;
	}
	else
		pDrvCtrl ->rxBufPtr ++;
	

    /* Call the upper layer's receive routine. */
    END_RCV_RTN_CALL( &pDrvCtrl->end, pMblk );

/*
	(pDrvCtrl ->clPointBuf)[recvdescptr] = pNewCluster;
	tmp = ( ( (UINT32)pNewCluster+3 )&0xFFFFFFFC );
	if( recvdescptr == (RX_FD_NUM -1) )
		tmp |= EMAC_RECV_DESC_WRAP;

	(pDrvCtrl ->RecvBufDesc)[recvdescptr].bufaddr = tmp;
*/
	ENDLOGMSG( ( "END: leave at91EndRecv *******.\n", 1,2,3,4,5,6) );
	return (OK);


cleanRXD:
	ENDLOGMSG( ( "END: packet lost because of get cl or m or clust buffer failure.\n", 1,2,3,4,5,6) );
	(pDrvCtrl ->RecvBufDesc)[recvdescptr].bufaddr &= 0xFFFFFFFE;
    return (OK);
}

/*******************************************************************************
*
* at91EndSend - the driver send routine
*
* This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
* The buffer must already have the addressing information properly installed
* in it.  This is done by a higher layer.  The last arguments are a free
* routine to be called when the device is done with the buffer and a pointer
* to the argument to pass to the free routine.  
*
* RETURNS: OK or ERROR.
*/

⌨️ 快捷键说明

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