📄 csend.c
字号:
{
/* Reset the threshold counter */
pCS->TxUnderruns = 0;
/* Select the next TxStartCommand */
if( pCS->TxStartCMD == TX_CMD_START_5 )
pCS->TxStartCMD = TX_CMD_START_381;
else if( pCS->TxStartCMD == TX_CMD_START_381 )
pCS->TxStartCMD = TX_CMD_START_1021;
else pCS->TxStartCMD = TX_CMD_START_ALL;
}
/* Try to TX the frame again */
if ( pCS->InMemoryMode )
{
csWritePacketPage( pCS, PKTPG_TX_CMD, pCS->TxStartCMD );
csWritePacketPage( pCS, PKTPG_TX_LENGTH, BYTE_SWAP(pCS->TxLength) );
}
else /* In IO mode */
{
SYS_ENET_OUT_WORD( (pCS->IOAddr)+PORT_TX_CMD, pCS->TxStartCMD );
SYS_ENET_OUT_WORD( (pCS->IOAddr)+PORT_TX_LENGTH,
BYTE_SWAP(pCS->TxLength));
}
/* Read BusStatus register which indicates success of the request */
BusStatus = csReadPacketPage( pCS, PKTPG_BUS_ST );
if ( BusStatus & BUS_ST_RDY4TXNOW )
{
/* On-chip buffer space available -- start transmission */
csCopyTxFrame( pCS, pCS->pTxFrameChain );
}
pCS->TotalTxUnderruns++;
#ifdef CS_DEBUG_ENABLE
logMsg("csBufferEvent: CS_END_DEVICE %d, Total Tx underrun=%d\n",
pCS->unit, pCS->TotalTxUnderruns,0,0,0,0 );
#endif
}
else if ( BufEvent & BUF_EVENT_RDY4TX )
{
(pCS->Rdy4TxInts) += 1;
/* The chip is ready for transmission now */
/* If a TX is pending, copy the frame to the chip to start transmission */
if( pCS->pTxFrameChain != NULL )
{
csCopyTxFrame( pCS, pCS->pTxFrameChain );
}
}
}
/*******************************************************************************
*
* csTransmitEvent -
*
* This routine is called whenever the transmission of a packet has completed
* successfully or unsuccessfully. If the transmission was not successful,
* then the output error count is incremented. If there are more packets in the
* transmit queue, then the next packet is started immediately.
*
*/
LOCAL void csTransmitEvent( CS_END_DEVICE *pCS, USHORT TxEvent )
{
/* WE only get here if the transmit in progress has completed, either
* successfully or due to an error condition. In any event, queue the
* mbuf chain for freeing at task level and NULL the frame pointer to mark
* the TX no longer in progress.
*/
csEnqueue( pCS->pTxBuffFreeList, pCS->pTxFrameChain );
pCS->pTxFrameChain = NULL;
pCS->TxInProgress = FALSE;
/* If there were any errors transmitting this frame */
if ( TxEvent & (TX_EVENT_LOSS_CRS | TX_EVENT_SQE_ERR | TX_EVENT_OUT_WIN |
TX_EVENT_JABBER | TX_EVENT_16_COLL) )
{
/* Increment the output error count */
/* @kml The definition of the MIB-II variable ifOutUcastPkts in Interface
group from RFC 1158 is "The total number of packets that higher-level
protocols requested be transmitted to a subnetwork-unicast address,
INCLUDE those that were discarded or not sent."*/
END_ERR_ADD (&pCS->end, MIB2_OUT_ERRS, +1);
/* If debugging is enabled then log error messages */
#ifdef CS_DEBUG_ENABLE
if ( TxEvent & TX_EVENT_LOSS_CRS )
{
logMsg("csTransmitEvent: CS_END_DEVICE %d, Loss of carrier\n",
pCS->unit, 0,0,0,0,0 );
}
if ( TxEvent & TX_EVENT_SQE_ERR )
{
logMsg("csTransmitEvent: CS_END_DEVICE %d, SQE error\n",
pCS->unit, 0,0,0,0,0 );
}
if ( TxEvent & TX_EVENT_OUT_WIN )
{
logMsg("csTransmitEvent: CS_END_DEVICE %d, Out-of-window collision\n",
pCS->unit, 0,0,0,0,0 );
}
if ( TxEvent & TX_EVENT_JABBER )
{
logMsg("csTransmitEvent: CS_END_DEVICE %d, Jabber\n",
pCS->unit, 0,0,0,0,0 );
}
if ( TxEvent & TX_EVENT_16_COLL )
{
logMsg("csTransmitEvent: CS_END_DEVICE %d, 16 collisions\n",
pCS->unit, 0,0,0,0,0 );
}
#endif
}
/* Previous TX complete so start the next TX now if more to transmit */
csTxNextFrame( pCS );
}
/*******************************************************************************
*
* csReceiveEvent -
*
* This routine is called whenever a packet is received at the chip. If the
* packet is received with errors, then the input error count is incremented.
* If the packet is received OK, then the data is copied to an internal receive
* buffer and processed at task level (in csEventHandler).
*
* RETURNS: Nothing
*/
LOCAL void csReceiveEvent( CS_END_DEVICE *pCS, USHORT RxEvent )
{
M_BLK_ID pMblk;
CL_BLK_ID pClBlk;
char *pData;
int DataLen;
/* If the frame was not received OK */
if ( !(RxEvent & RX_EVENT_RX_OK) )
{
/* Increment the input error count */
/*pIf->if_ierrors++;*/
END_ERR_ADD (&pCS->end, MIB2_IN_ERRS, +1);
/* If debugging is enabled then log error messages */
#ifdef CS_DEBUG_ENABLE
/* If an error bit is set */
if ( RxEvent != REG_NUM_RX_EVENT )
{
if ( RxEvent & RX_EVENT_RUNT )
{
logMsg("csReceiveEvent: CS_END_DEVICE %d, Runt\n",
pCS->unit, 0,0,0,0,0 );
}
if ( RxEvent & RX_EVENT_X_DATA )
{
logMsg("csReceiveEvent: CS_END_DEVICE %d, Extra data\n",
pCS->unit, 0,0,0,0,0 );
}
if ( RxEvent & RX_EVENT_CRC_ERR )
{
if ( RxEvent & RX_EVENT_DRIBBLE )
{
logMsg("csReceiveEvent: CS_END_DEVICE %d, Alignment error\n",
pCS->unit, 0,0,0,0,0 );
}
else
{
logMsg("csReceiveEvent: CS_END_DEVICE %d, CRC Error\n",
pCS->unit, 0,0,0,0,0 );
}
}
else if ( RxEvent & RX_EVENT_DRIBBLE )
{
logMsg("csReceiveEvent: CS_END_DEVICE %d, Dribble bits\n",
pCS->unit, 0,0,0,0,0 );
}
}
#endif
/* Skip this error frame */
csReadPacketPage( pCS, PKTPG_RX_LENGTH );
csWritePacketPage( pCS, PKTPG_RX_CFG,
csReadPacketPage(pCS,PKTPG_RX_CFG) | RX_CFG_SKIP );
return;
}
/* Get a receive frame buffer */
pData = netClusterGet(pCS->end.pNetPool, pCS->pClPoolId);
/* Grab a cluster block to marry to the cluster we received. */
pClBlk = netClBlkGet (pCS->end.pNetPool, M_DONTWAIT);
/*
* OK we've got a spare, let's get an M_BLK_ID and marry it to the
* one in the ring.
*/
pMblk = mBlkGet (pCS->end.pNetPool, M_DONTWAIT, MT_DATA);
if ( pData == NULL || pClBlk == NULL || pMblk == NULL) /* If no buffer available */
{
if (pData) {
netClFree (pCS->end.pNetPool, pData);
}
if (pClBlk) {
netClBlkFree (pCS->end.pNetPool, pClBlk);
}
if ( pMblk ) {
netMblkFree (pCS->end.pNetPool, pMblk);
}
/* Increment the input error count */
/*pIf->if_ierrors++;*/
END_ERR_ADD (&pCS->end, MIB2_IN_ERRS, +1);
#ifdef CS_DEBUG_ENABLE
logMsg("csReceiveEvent(): unit=%d, No receive buffer available!\n",
pCS->unit, 0,0,0,0,0 );
#endif
/* Must read the length of all received frames */
csReadPacketPage( pCS, PKTPG_RX_LENGTH );
/* Skip the received frame */
csWritePacketPage( pCS, PKTPG_RX_CFG,
csReadPacketPage(pCS,PKTPG_RX_CFG) | RX_CFG_SKIP );
return;
}
/* Copy the received frame from the chip to the buffer */
/* Set offset 2 to the receiving buffer pointer so that the IP heater starts the
17th bytes for 32-bits alignment*/
DataLen=csCopyRxFrame( pCS, pData+2);
/* Join the cluster to the MBlock */
netClBlkJoin (pClBlk, pData, DataLen, NULL, 0, 0, 0);
netMblkClJoin (pMblk, pClBlk);
/* Set offset 2 to the receiving buffer pointer so that the IP heater starts the
17th bytes for 32-bits alignment*/
/*pMblk->mBlkHdr.mData += pDrvCtrl->offset;*/
pMblk->mBlkHdr.mData += 2;
pMblk->mBlkHdr.mLen = DataLen;
pMblk->mBlkHdr.mFlags |= M_PKTHDR;
pMblk->mBlkPktHdr.len = DataLen;
/* Queue a pointer to the buffer to be processed at task level */
csEnqueue( pCS->pRxBuffProcessList, pMblk );
}
/*******************************************************************************
* csEventHandler -
*
* This routine runs at the task level to processes RX frames and frees TX'd
* mbuf chains queued at the ISR level. Up to two instances of this
* routine may be queued to tNetTask to prevent a race condition between final
* checking of a queue here and an enqueue at the ISR level. A netJob
* "counter" is decremented each time this routine starts.
*
* RETURNS: Nothing.
*
*/
LOCAL void csEventHandler( CS_END_DEVICE *pCS )
{
void *pBuff;
if( pCS->NetJobDepth > 0 )
pCS->NetJobDepth--;
while( !csQueueEmpty( pCS->pRxBuffProcessList ) )
{
/* Process an RX frame */
pBuff = csDequeue( pCS->pRxBuffProcessList );
csProcessReceive( pCS, pBuff );
}
while( !csQueueEmpty( pCS->pTxBuffFreeList ) )
{
/* Free up the TX'd mbuf chains */
pBuff = csDequeue( pCS->pTxBuffFreeList );
netMblkClChainFree (pBuff);
}
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
* Transmit-releated Routines *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*******************************************************************************
*
* csStartOutput -
*
* This routine is called to start the transmission of the packet at the head
* of the transmit queue. This routine is called by the ether_output() routine
* when a new packet is added to the transmit queue.
*
* RETURNS: Nothing
*
*/
LOCAL void csStartOutput( CS_END_DEVICE *pCS, M_BLK_ID pMBuf)
{
BOOL QError;
END_TX_SEM_TAKE(&pCS->end, WAIT_FOREVER);
QError = csEnqueue( pCS->pTxQueue, pMBuf );
END_TX_SEM_GIVE(&pCS->end);
if ( QError )
{
/* TxQueue is full -- dump the frame and exit loop */
netMblkClChainFree (pMBuf);
/* Update output stats */
END_ERR_ADD (&pCS->end, MIB2_OUT_ERRS, +1);
#ifdef CS_DEBUG_ENABLE
logMsg("csStartOutput: CS_END_DEVICE %d, Transmit queue overflow\n",
pCS->unit, 0,0,0,0,0 );
#endif
}
#ifdef CS_DEBUG_ENABLE
pCS->TxQueueDepth++;
if ( pCS->TxQueueDepth > pCS->MaxTxQueueDepth )
pCS->MaxTxQueueDepth = pCS->TxQueueDepth;
#endif
/* Update output stats */
END_ERR_ADD (&pCS->end, MIB2_OUT_UCAST, +1);
/* Transmit another frame if a TX is not currently in progress */
if ( !pCS->TxInProgress )
{
csTxNextFrame( pCS );
}
}
/*******************************************************************************
* csTxNextFrame -
*
* This routine start the TX of the next frame in the local TX send queue.
* If an error occurs, the output error count is incremented and the mbuf chain
* is freed, either by immediately calling mfree_m() if we are at task level,
* or queueing the mbuf chain for release at the task level if we are currently
* at the ISR level.
*
* RETURNS: Nothing
*
*/
LOCAL void csTxNextFrame ( CS_END_DEVICE *pCS )
{
USHORT BusStatus;
M_BLK_ID pMbuf;
int State = 0;
/* Transmit the next frame in the local TxQueue */
while( !csQueueEmpty( pCS->pTxQueue ) )
{
#ifdef CS_DEBUG_ENABLE
pCS->TxQueueDepth--;
#endif
if ( !pCS->InISR )
{
/* Ensure the transmit bid and copy to chip is atomic */
State = INT_LOCK( );
}
pCS->pTxFrameChain = csDequeue( pCS->pTxQueue );
/* Find the total length of the data to transmit */
pCS->TxLength = 0;
for ( pMbuf = pCS->pTxFrameChain; pMbuf!=NULL; pMbuf=pMbuf->mBlkHdr.mNext )
{
pCS->TxLength += pMbuf->mBlkHdr.mLen;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -