📄 at91emacend.c
字号:
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 + -