📄 cd_util.c
字号:
case CD_XPORT_TYPE_PROVIDE_BUFFER:
case CD_XPORT_TYPE_ACCESS_BUFFER:
/*
** These cases are not currently implemented for a consumer
** transport. So fall through and report error.
*/
default:
eStatus = CD_UNSUPPORTED_TRANSPORT;
psConnRecord->iERC = CM_ERC_BAD_TRANSPORT;
goto Bailout;
} /* end switch */
} /* end if Reserve */
} /* end if Class 1 */
} /* end if( ( pTr->iState & CD_TS_RESERVED ) == 0 ) */
/*
**********************************************************
** Start of START_TRANSPORTS Section for the Consumer
*********************************************************
*/
if( ( psTrrbl->eRequest == TREQ_START_TRANSPORTS )
&& ( ( pTr->iState & CD_TS_STARTED ) == 0 ) )
{
pTr->iState |= CD_TS_STARTED;
if( iClass == CM_TCT_CLASS_1 )
{
/*
** Always pick up the size.
*/
pTr->iDataSize = psConnRecord->iConAppSize;
/* For Consumer Transport */
switch( psConnRecord->bConTransportType & CD_XPORT_TYPE_MASK )
{
case CD_XPORT_TYPE_PROVIDE_FUNCTION:
/*
** Provide a copy function that will be called whenever new
** data is ready to be Consumed. That is, the transport
** stores the data until the application needs to consume it.
**
** This case is valid for the NetLinx Dualport, which should
** have it's own transport commission function.
** It is not valid for either ControlNet ASIC, so flag an error.
*/
eStatus = CD_UNSUPPORTED_TRANSPORT;
psConnRecord->iERC = CM_ERC_BAD_TRANSPORT;
goto Bailout;
case CD_XPORT_TYPE_DEFAULT:
case CD_XPORT_TYPE_CALL_FUNCTION:
/*
** This case is how the Consumer Xports have worked in the past.
**
** Store pointer to function to call and handle to pass back.
*/
if( pTr->fBridged )
{
pTr->pRxCopyFunction = psConnRecord->psOtherConnRecord->pProCopyFunction;
pTr->xRxAppHandle = psConnRecord->psOtherConnRecord->xProAppHandle;
}
else
{
pTr->pRxCopyFunction = psConnRecord->pConCopyFunction;
pTr->xRxAppHandle = psConnRecord->xConAppHandle;
}
break;
case CD_XPORT_TYPE_PROVIDE_BUFFER:
case CD_XPORT_TYPE_ACCESS_BUFFER:
/*
** These cases are not currently implemented for a consumer
** transport. So fall through and report error.
*/
default:
eStatus = CD_UNSUPPORTED_TRANSPORT;
psConnRecord->iERC = CM_ERC_BAD_TRANSPORT;
goto Bailout;
} /* end switch */
#ifdef CD_EN_OBJECTS
/*
** We need to setup the multicast group that we will be listening on
*/
if ( psConnRecord->iPort == CD_ETHERNET_PORT )
{
if( ( psConnRecord->iConConnParams & CM_CP_TYPE_MASK ) == CM_CP_TYPE_MULTICAST )
{
/*
** Join the multicast listening group for this multicast address
*/
*( UINT32 * ) &pTr->abRxTag[0] = UC_lLeTOl( psConnRecord->lLeConConnId );
iError = en_cd_JoinMulticast(&psConnRecord->sEce.psMcast->sMc_addr);
if ( iError != OK)
{
eStatus = EN_NO_MULTICAST;
goto Bailout;
}
}
pTr->sEce = psTrrbl->psConnRecord->sEce;
} /* End if an ethernet port */
#endif
} /* end if Class 1 */
/*
** Since we're a class 1 consumer or a class 3, create the Rx watchdog timer.
**
** But first, check to see if it is already done.
*/
if( pTr->pRxTot == NULL )
{
/*
** Build the timeout tribble.
*/
pTr->pRxTot = GS_NewTrrbl( CD_TimeoutTrrblType );
pTr->pRxTot->eRequest = TREQ_TIMER_EXPIRED;
pTr->pRxTot->iId = psConnRecord->iConTransportId;
pTr->pRxTot->iPort = psConnRecord->iPort;
/*
** Now build the timer itself.
*/
pTr->xRxTimer = GS_NewLinkedMsgTimer( TIMER_ONE_SHOT,
( psConnRecord->lTimeout < 10000L ) ? 10000L : psConnRecord->lTimeout,
psConnRecord->lTimeout,
CD_s[ psConnRecord->iPort ].xConfigQid,
pTr->pRxTot );
if( pTr->xRxTimer == NULL )
{
GS_DeleteTrrbl( pTr->pRxTot );
eStatus = CD_RESOURCE_UNAVAILABLE;
psConnRecord->iERC = CM_ERC_NO_BUFFER;
goto Bailout;
}
}
if( pTr->fBridged )
{
if( iClass == CM_TCT_CLASS_3 )
{
/*
** If bridged class 3, the connection records should be cross-linked
** so cross-link the transports.
*/
if( ( psConnRecord->psOtherConnRecord )
&& ( psConnRecord->psOtherConnRecord->iConTransportId ) )
{
pTr->iOtherTransportId = psConnRecord->psOtherConnRecord->iConTransportId;
}
else
{
/*
** This should never happen. The system could be unstable,
** so log a fatal fault.
*/
GS_LogEvent( CM_INCONSISTENT_STATE, 0, psTrrbl, FATAL );
}
}
else
{
/*
** If bridged class 1, the connection records should be cross-linked
** so cross-link the transports.
*/
if( ( psConnRecord->psOtherConnRecord )
&& ( psConnRecord->psOtherConnRecord->iProTransportId ) )
{
pTr->iOtherTransportId = psConnRecord->psOtherConnRecord->iProTransportId;
}
else
{
/*
** This should never happen. The system could be unstable,
** so log a fatal fault.
*/
GS_LogEvent( CM_INCONSISTENT_STATE, 0, psTrrbl, FATAL );
}
}
}
/*
** Now do the ASIC specific initialization and start up the transport.
*/
#ifdef CD_EN_OBJECTS
/* For tcpip we have to verify that messages for a given cip connection match the
** encap session that it was created on. We do that by copying the encap session
** information into the cip record.
*/
if ( psConnRecord->iPort == CD_ETHERNET_PORT )
{
pTr->sEce = psTrrbl->psConnRecord->sEce;
}
#endif
eStatus = (CD_s[ psConnRecord->iPort ].StartTransport)( pTr );
if( eStatus != SUCCESS )
{
eStatus = CD_TRANSPORT_ALLOC_FAIL;
psConnRecord->iERC = CM_ERC_BAD_TRANSPORT;
goto Bailout;
}
/*
** Now start any allocated timers
*/
if( pTr->xRetryTimer != NULL )
{
GS_StartTimer( pTr->xRetryTimer );
}
if( pTr->xRxTimer != NULL )
{
GS_StartTimer( pTr->xRxTimer );
}
}
return( SUCCESS );
Bailout:
/*
** Some sort of problem detected during setup.
** Clean things up and log a fault.
** If the failure was in the ASIC specific portion, that cleanup
** is already done. If the failure was anywhere in the general portion,
** the ASIC specific startup was not called.
*/
if( psTrrbl->psConnRecord != NULL )
{
psConnRecord->bGRC = CI_GRC_FAILURE;
if( psConnRecord->iProTransportId != 0 )
{
iTransport = psConnRecord->iProTransportId & sRadioActiveMasks.nTransportMask;
pTr = cd_LookupTransportRecord( psConnRecord->iPort, psConnRecord->iProTransportId );
if( pTr != NULL )
{
/*
** Unlink and make sure no other connections are linked to this
** transport before disposing of it.
*/
if( cd_UnlinkConnSnFromTransport( psConnRecord->iConnectionSn, pTr ) == 0 )
{
if( pTr->pRetryTot != NULL )
{
GS_DeleteTrrbl( pTr->pRetryTot );
}
if( pTr->xRetryTimer != NULL )
{
GS_DeleteTimer( pTr->xRetryTimer );
}
if( pTr->pRxTot != NULL )
{
GS_DeleteTrrbl( pTr->pRxTot );
}
if( pTr->xRxTimer != NULL )
{
GS_DeleteTimer( pTr->xRxTimer );
}
GS_Free( pTr );
( CD_s[ psConnRecord->iPort ].papTransportRecords )[ iTransport - 1 ] = NULL;
}
}
GS_LogEvent( eStatus, iTransport, 0, WARNING );
psConnRecord->iProTransportId = 0;
}
if( psConnRecord->iConTransportId != 0 )
{
iTransport = psConnRecord->iConTransportId & sRadioActiveMasks.nTransportMask;
pTr = cd_LookupTransportRecord( psConnRecord->iPort, iTransport );
if( pTr != NULL )
{
/*
** Unlink and make sure no other connections are linked to this
** transport before disposing of it.
*/
if( cd_UnlinkConnSnFromTransport( psConnRecord->iConnectionSn, pTr ) == 0 )
{
if( pTr->pRetryTot != NULL )
{
GS_DeleteTrrbl( pTr->pRetryTot );
}
if( pTr->xRetryTimer != NULL )
{
GS_DeleteTimer( pTr->xRetryTimer );
}
if( pTr->pRxTot != NULL )
{
GS_DeleteTrrbl( pTr->pRxTot );
}
if( pTr->xRxTimer != NULL )
{
GS_DeleteTimer( pTr->xRxTimer );
}
GS_Free( pTr );
( CD_s[ psConnRecord->iPort ].papTransportRecords )[ iTransport - 1 ] = NULL;
}
}
GS_LogEvent( eStatus, iTransport, 0, WARNING );
psConnRecord->iConTransportId = 0;
}
#ifdef CD_EN_OBJECTS
/*
** Free the mcast IP address if allocated
*/
if( psConnRecord->iPort == CD_ETHERNET_PORT )
{
en_cd_FreeIpMcastAddress( psConnRecord );
}
#endif
}
return( eStatus );
} /* End of cd_CommissionTransports() */
/*---------------------------------------------------------------------------
** cd_DecommissionTransports()
**---------------------------------------------------------------------------
*/
StatusType cd_DecommissionTransports( CD_TransportTrrblType *psTrrbl )
{
StatusType eStatusPro;
StatusType eStatusCon;
CM_ConnectionRecordType *psConnRecord;
psConnRecord = psTrrbl->psConnRecord;
/*
** Delete transports if this is the last connection linked to them.
*/
/*
** start edits: October,11th 2005, H.F.
**
** additional input variable in cd_DeleteTransport
**
eStatusPro = cd_DeleteTransport( psConnRecord->iPort, psConnRecord->iProTransportId, psConnRecord->iConnectionSn );
eStatusCon = cd_DeleteTransport( psConnRecord->iPort, psConnRecord->iConTransportId, psConnRecord->iConnectionSn );
**
*/
eStatusPro = cd_DeleteTransport( psConnRecord->iPort, psConnRecord->iProTransportId, psConnRecord->iConnectionSn, psConnRecord );
eStatusCon = cd_DeleteTransport( psConnRecord->iPort, psConnRecord->iConTransportId, psConnRecord->iConnectionSn, psConnRecord );
/*
** end edits: October,11th 2005, H.F.
*/
if( eStatusPro != SUCCESS )
{
return( eStatusPro );
}
return( eStatusCon );
} /* end of cd_DecommissionTransports() */
/*---------------------------------------------------------------------------
** cd_DeleteTransport()
**---------------------------------------------------------------------------
*/
StatusType cd_DeleteTransport( UINT16 iPort, UINT16 iTransport, UINT16 iConnectionSn, CM_ConnectionRecordType * psConnRecord )
{
cd_TransportRecordType *pTr;
/*
** start edits: October,11th 2005, H.F.
*/
cm_ConnectionRecordType *psParallelConnRecord;
INT8 iNumConnectionsLeft;
UINT32 lNewProApi = 0xFFFFFFFF; /* initialization */
UINT32 lNewProInhib;
/*
** end edits: October,11th 2005, H.F.
*/
iTransport &= sRadioActiveMasks.nTransportMask;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -