📄 cd_util.c
字号:
GS_UseCritical();
/*
** Lookup the transport record. Bail if it's invalid.
*/
pTr = cd_LookupTransportRecord( iPort, iTransport );
if ( pTr == NULL )
{
return( CD_INVALID_TRANSPORT );
}
/*
** Unlink and make sure no other connections are linked to this
** transport before disposing of it.
*/
/*
** start edits: October,11th 2005, H.F.
**
if( cd_UnlinkConnSnFromTransport( iConnectionSn, pTr ) == 0 )
**
*/
if( !( iNumConnectionsLeft = cd_UnlinkConnSnFromTransport( iConnectionSn, pTr ) ) )
/*
** end edits: October,11th 2005, H.F.
*/
{
/*
** If we have a receive watchdog timer, shut it down.
** Nullify or delete the timeout tribble as appropriate.
*/
/*
** jjw check the timer in the critical region, possible
** it could expire between when it was checked and
** when it was actually deleted otherwise
*/
GS_EnterCritical( );
{
if ( pTr->xRxTimer != NULL )
{
/*
** The timer is not null, so delete it.
**
** If 0 is returned by GS_DeleteTimer(), it indicates
** that the timer has expired. Thus a timeout TRRBL
** (pRxTot) has been tossed to CD.
**
** ( GS_DeleteTimer( pTr->xRxTimer ) == 0 ) ==> Timer expired.
*/
if ( GS_DeleteTimer( pTr->xRxTimer ) == 0 )
{
if ( pTr->pRxTot != NULL )
{
pTr->pRxTot->iId = 0;
}
}
else
{
GS_DeleteTrrbl( pTr->pRxTot );
}
pTr->xRxTimer = NULL;
pTr->pRxTot = NULL;
}
}
GS_ExitCritical( );
/*
** If we have a class 3 client retry timer, shut it down.
** Nullify or delete the timeout tribble as appropriate.
*/
if ( pTr->xRetryTimer != NULL )
{
GS_EnterCritical( );
{
if ( GS_DeleteTimer( pTr->xRetryTimer ) == 0 )
{
pTr->pRetryTot->iId = 0;
}
else
{
GS_DeleteTrrbl( pTr->pRetryTot );
}
pTr->xRetryTimer = NULL;
pTr->pRetryTot = NULL;
}
GS_ExitCritical( );
}
/*
** Do any ASIC specific shutdown and buffer freeing.
*/
(CD_s[ iPort ].StopTransport)( pTr );
/*
** For class 3's, delete the combuf holding the freshest transmit data.
*/
if( pTr->pCbFreshest != NULL )
{
CB_DeleteComBuf( pTr->pCbFreshest );
}
/*
** All cleaned up. Toss the transport record itself.
*/
GS_EnterCritical( );
{
/*
** Do the NULL in a critical region in case it takes more than one
** asm language instruction. We don't want access when only half
** the 32 bit field is NULL'd out.
*/
( CD_s[ iPort ].papTransportRecords )[ iTransport - 1 ] = NULL;
}
GS_ExitCritical( );
GS_Free( pTr );
} /* end if( cd_UnlinkConnSnFromTransport( iConnectionSn, pTr ) == 0 ) */
/*
** start edits: October,11th 2005, H.F.
**
** if there are other connections linked to this transport (i.e.
** Producer Connection Point) determine the now lowest RPI to apply
** to the API timer
*/
else /* there are other connections linked to this transport */
{
/*
** Scan the connection record list for connections with the
** same Producer Connection Point, but different Serial Numbers
*/
psParallelConnRecord = LL_FirstEntry( &cm_s.sRecordList );
while( iNumConnectionsLeft &&
!LL_EndOfList( &cm_s.sRecordList, psParallelConnRecord ) )
{
if( (psParallelConnRecord->sPublic.iProConnPoint == psConnRecord->iProConnPoint)
&& (psParallelConnRecord->sPublic.iConnectionSn != iConnectionSn) )
{
/*
** Found another connection with the same Producer
** Connection Point, check its RPI
*/
if( psParallelConnRecord->sPublic.lProApi < lNewProApi )
{
/* store relevant parameters for API Timer */
lNewProApi = psParallelConnRecord->sPublic.lProApi;
lNewProInhib = psParallelConnRecord->sPublic.lProInhib;
}
iNumConnectionsLeft--;
}
psParallelConnRecord = LL_NextEntry( psParallelConnRecord );
}
/*
** check, if the determined API is greater than the current
** API
*/
if( lNewProApi > pTr->lProApi )
{
/* ...apply new (slower) APIs */
pTr->lProApi = pTr->lConApi = lNewProApi;
pTr->lProInhib = lNewProInhib;
/* adjust the API timer */
pTr->xAPITimer->nRetrigger = pTr->lProApi/1000;
/* retrigger API timer */
GS_RetriggerTimer(pTr->xAPITimer);
en_cd_Class1TxPacket( pTr->pBufA, pTr);
/*
** start edits: October,13th 2005, H.F.:
**
** update data after transmission
** (NOTE: An ad_ResyncCommAndAppBufs() call before executing
** en_cd_Class1TxPacket() does not work!)
*/
GS_PutMsgQueueBits( AD_xQid, AD_BIT_MSG_SENT_PRO );
/*
** end edits: October,13th 2005, H.F.
*/
}
}
/*
** end edits: October,11th 2005, H.F.
*/
return( SUCCESS );
} /* End of cd_DeleteTransport() */
/*---------------------------------------------------------------------------
** cd_LinkConnSnToTransport()
**---------------------------------------------------------------------------
*/
INT8 cd_LinkConnSnToTransport( UINT16 iConnSn, cd_TransportRecordType *pTr, UINT16 iPort )
{
INT8 i;
i = 0;
while( i < (iPort == CD_CONTROLNET_PORT ? CN_CD_MAX_MULTICAST :EN_CD_MAX_MULTICAST) )
{
if( pTr->aiConnectionSn[ i ] == iConnSn )
{
/*
** Already linked, so just report number linked.
*/
return( cd_NumConnSnLinkedToTransport( pTr ) );
}
else if( pTr->aiConnectionSn[ i ] == 0 )
{
/*
** Space is available, so link and report number linked.
*/
pTr->aiConnectionSn[ i ] = iConnSn;
return( cd_NumConnSnLinkedToTransport( pTr ) );
}
i++;
}
/*
** No space is available, so report error.
*/
return( ( INT8 ) -1 );
} /* End of cd_LinkConnSnToTransport() */
/*---------------------------------------------------------------------------
** cd_LookupTransportRecord()
**---------------------------------------------------------------------------
*/
void cd_OpenTransportCount( int *theClass1Count, int *theClass3Count )
{
CD_DataType aCD;
int i;
/* ! */
*theClass1Count = *theClass3Count = 0;
/* ! */
aCD = CD_s[CD_ETHERNET_PORT];
for( i=0; i<aCD.iNumTransports; i++ ){
/* ! */
struct cd_TransportRecordType *aTR = aCD.papTransportRecords[i];
if( aTR!=NULL )
if( (aTR->iState & CD_TS_STARTED) && !(aTR->iState & CD_TS_CLOSING)){
/* ! */
if( (aTR->iClass & CM_TCT_CLASS_MASK)==CM_TCT_CLASS_1 ) (*theClass1Count)++;
if( (aTR->iClass & CM_TCT_CLASS_MASK)==CM_TCT_CLASS_3 ) (*theClass3Count)++;
}
}
}
cd_TransportRecordType *cd_LookupTransportRecord( UINT16 iPort, UINT16 iTransport )
{
if( !CD_ValidPortNum( iPort ) )
{
GS_LogEvent( CD_FAULT_TYPE, iPort, NULL, FATAL );
}
iTransport &= sRadioActiveMasks.nTransportMask;
if( iTransport == 0 )
{
return( NULL );
}
if( iTransport > CD_s[ iPort ].iNumTransports )
{
return( NULL );
}
return( ( CD_s[ iPort ].papTransportRecords )[ iTransport - 1 ] );
}
/*---------------------------------------------------------------------------
** cd_NumConnSnLinkedToTransport()
**---------------------------------------------------------------------------
*/
INT8 cd_NumConnSnLinkedToTransport( cd_TransportRecordType *pTr )
{
INT8 i;
INT8 iNumConnectionsLeft;
iNumConnectionsLeft = 0;
i = 0;
while( i < (CN_CD_MAX_MULTICAST > EN_CD_MAX_MULTICAST ? CN_CD_MAX_MULTICAST : EN_CD_MAX_MULTICAST) )
{
if( pTr->aiConnectionSn[ i ] != 0 )
{
/*
** Link found.
*/
iNumConnectionsLeft++;
}
i++;
}
/*
** Report number left.
*/
return( iNumConnectionsLeft );
} /* End of cd_NumConnSnLinkedToTransport() */
/*---------------------------------------------------------------------------
** cd_ProcessTimer()
**---------------------------------------------------------------------------
*/
void cd_ProcessTimer( CD_TimeoutTrrblType *pTrrbl )
{
cd_TransportRecordType *pTr;
CM_CloseTrrblType *pTrrblClose;
INT8 i;
i = 0;
/*
** If the TOT has been nullified, just toss it.
*/
if( pTrrbl->iId == 0 )
{
GS_DeleteTrrbl( pTrrbl );
return;
}
/*
** Lookup the transport record. Bail if it's invalid.
*/
pTr = cd_LookupTransportRecord( pTrrbl->iPort, pTrrbl->iId );
if ( pTr == NULL )
{
GS_DeleteTrrbl( pTrrbl );
return;
}
/*
** Valid timeout tribble (TOT).
** Issue close connection requests to the connection manager.
*/
while( i < (CN_CD_MAX_MULTICAST > EN_CD_MAX_MULTICAST ? CN_CD_MAX_MULTICAST :EN_CD_MAX_MULTICAST) )
{
if( pTr->aiConnectionSn[ i ] != 0 )
{
/*
** Found a linked connection, tell CM to close it.
*/
pTrrblClose = GS_NewTrrbl( CM_CloseTrrblType );
pTrrblClose->eRequest = TREQ_TIMEOUT_CONNECTION;
pTrrblClose->xUserHandle = NULL;
pTrrblClose->iConnectionSn = pTr->aiConnectionSn[ i ];
pTrrblClose->fUnrequestedClose = FALSE;
pTrrblClose->pCombuf = NULL;
GS_PutTrrbl( CM_xQid, pTrrblClose );
}
i++;
}
/*
** Delete the TOT & erase all references to it.
*/
GS_DeleteTrrbl( pTrrbl );
pTr->pRxTot = NULL;
} /* end of cd_ProcessTimer() */
/*---------------------------------------------------------------------------
** cd_RouteClass3Packet()
**---------------------------------------------------------------------------
*/
void cd_RouteClass3Packet( CD_PacketTrrblType *pTrrbl )
{
cd_TransportRecordType *pTr;
LeUINT16 iLeSeqCount;
/*
** Look up the transport record.
*/
GS_UseCritical();
pTr = cd_LookupTransportRecord( pTrrbl->iPort, pTrrbl->iTransport );
if( pTr == NULL )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -