📄 en_util.c
字号:
/****************************************************************************
*****************************************************************************
**
** File Name
** ---------
**
** EN_UTIL.C
**
*****************************************************************************
*****************************************************************************
**
** Description
** -----------
**
** Common portion of the ethernet communications device interface.
**
*****************************************************************************
*****************************************************************************
**
** Source Change Indices
** ---------------------
**
** Porting: <none>0----<major> Customization: <none>0----<major>
**
*****************************************************************************
*****************************************************************************
** **
** ETHERNET/IP EXAMPLE CODE **
** COPYRIGHT (c) 2000-2005 ODVA (Open DeviceNet Vendor Association) **
** & ControlNet International Ltd. **
** **
** All rights reserved, except as specifically licensed in writing. **
** Use of the Ethernet/IP Example Protocol Software is subject to **
** ODVA's and ControlNet International's Terms of Use Agreement. **
** The following work constitutes example program code and is intended **
** merely to illustrate useful programming techniques. The user is **
** responsible for applying the code correctly. The code is provided **
** AS IS without warranty and is in no way guaranteed to be error-free. **
** **
*****************************************************************************
*****************************************************************************
*/
/*
** See if this object is to be included.
*/
#include "ab.h"
#ifdef CD_EN_OBJECTS
#include "cd.h" /* Communications Device public interfaces*/
#include "en.h" /* Communications Device public interfaces*/
#include "cd_util.h" /* Communications Device private interfaces*/
#include "en_util.h" /* Communications Device private interfaces*/
#include "en_xport.h" /* Communications Device private interfaces*/
#include "um.h" /* UCMM interfaces ( for rx packet pre-routing )*/
#include "cm.h" /* Connection Manager ( for rx packet pre-routing ) */
#include "ECInterface.h"
/****************************************************************************
**
** Public Globals
**
*****************************************************************************
*/
UINT32 iBadClass1Tx = 0;
cd_DataType en_cd_s;
extern ECE sClass1Ece;
CPFHDR sCpfHdr = {
ENCAP_VALUE_SHORT(2),
ENCAP_VALUE_SHORT(CPF_TAG_ADR_SEQUENCED),
ENCAP_VALUE_SHORT(8),
0, 0,
0, 0,
ENCAP_VALUE_SHORT(CPF_TAG_PKT_CONNECTED),
0
};
extern OE_Q_ID sClass1TxTaskMsgQueue;
extern cd_RadioactiveMaskType sRadioActiveMasks;
extern ENCAP_OBJ_TARGET list_target_data;
/****************************************************************************
**
** Public Services
**
*****************************************************************************
*/
/*---------------------------------------------------------------------------
** EN_CD_Init( )
**---------------------------------------------------------------------------
*/
StatusType EN_CD_Init( UINT16 iOptions )
{
GS_TaskSeedType sSeed;
UINT16 i;
/*
** Allocate/Create all resources ( except for tasks ).
*/
if( iOptions & AB_CREATE_RESOURCE )
{
/*
** Create the Config task's request queue.
*/
CD_s[CD_ETHERNET_PORT].xConfigQid = GS_NewMsgQueue( );
/*
** Create the TxUnscheduled task's request queue.
*/
CD_s[CD_ETHERNET_PORT].xTxUnschedLoQid = GS_NewMsgQueue( );
CD_s[CD_ETHERNET_PORT].xTxUnschedHiQid = GS_NewMsgQueue( );
}
/*
** Initialize all internal data structures.
*/
if( iOptions & AB_INIT_RESOURCE )
{
/*
** Fill in default configuration information.
*/
CD_s[CD_ETHERNET_PORT].nLinkTimeout = EN_CD_DEFAULT_LINK_TIMEOUT;
CD_s[CD_ETHERNET_PORT].bRetryLimit = EN_CD_RETRY_LIMIT;
CD_s[CD_ETHERNET_PORT].bUcmmCodeOverRide = UM_REQUEST_NO_RETRY;
CD_s[CD_ETHERNET_PORT].GetTransportBuffer = EN_CD_GetTransportBuffer;
CD_s[CD_ETHERNET_PORT].PutTransportBuffer = EN_CD_PutTransportBuffer;
CD_s[CD_ETHERNET_PORT].iNumTransports = EN_CD_NUM_TRANSPORTS;
CD_s[CD_ETHERNET_PORT].StopTransport = en_cd_StopTransport;
CD_s[CD_ETHERNET_PORT].StartTransport = en_cd_StartTransport;
CD_s[CD_ETHERNET_PORT].papTransportRecords = &en_cd_s.apTransportRecords[0];
/*
** Mark all transports as unused/unallocated.
*/
for( i = 0; i < sizeof en_cd_s.apTransportRecords / sizeof en_cd_s.apTransportRecords[0]; i++ )
{
en_cd_s.apTransportRecords[i] = NULL;
}
}
/*
** Create the tasks & associate it with the message queues created earlier.
*/
if( iOptions & AB_CREATE_TASK )
{
sSeed.pRoutine = EN_CD_ConfigTask;
sSeed.pParameter = NULL;
sSeed.pStack = NULL;
sSeed.iStackSize = EN_CD_CONFIG_STACK_SIZE;
sSeed.nPrio = EN_CD_CONFIG_TASK_PRIO;
sSeed.pTaskName = "encdCfg ";
GS_AssociateTaskAndQueues( GS_NewTask( &sSeed ), CD_s[CD_ETHERNET_PORT].xConfigQid, GS_NO_QUEUE );
sSeed.pRoutine = EN_CD_TxUnscheduledTask;
sSeed.pParameter = NULL;
sSeed.pStack = NULL;
sSeed.iStackSize = EN_CD_TX_UNSCHED_STACK_SIZE;
sSeed.nPrio = EN_CD_TX_UNSCHED_TASK_PRIO;
sSeed.pTaskName = "enTxUNSCH ";
GS_AssociateTaskAndQueues( GS_NewTask( &sSeed ),
CD_s[CD_ETHERNET_PORT].xTxUnschedHiQid,
CD_s[CD_ETHERNET_PORT].xTxUnschedLoQid );
}
/*
** Final initialization after tasks are running.
*/
if( iOptions & AB_INIT_TASK )
{
}
return ( SUCCESS );
} /* end of EN_CD_Init( ) */
/*---------------------------------------------------------------------------
** EN_CD_TxUnscheduledTask( )
**---------------------------------------------------------------------------
*/
TASKRETURN EN_CD_TxUnscheduledTask( TASKPARAM )
{
cd_TransportRecordType *pTranRec;
cd_upsTrrblType upsTrrbl;
CB_ComBufType *pCb;
StatusType eStatus;
/*
** Enter task loop. Get tribbles and transmit the attached ComBufs.
** Perform requested termination actions.
*/
while ( 1 )
{
/*
** Initially, assume successful completion of the request.
*/
eStatus = SUCCESS;
/*
** Take tribbles and process each one.
** Extract a convenience combuf pointer.
** Switch on the tribble request code.
*/
upsTrrbl.Generic = GS_TakeMsgQueuePair( CD_s[CD_ETHERNET_PORT].xTxUnschedHiQid,
CD_s[CD_ETHERNET_PORT].xTxUnschedLoQid,
NULL );
pCb = upsTrrbl.Packet->pComBuf;
switch ( upsTrrbl.Generic->eRequest )
{
case TREQ_TX_FIXED_TAG:
/*
** All other fixed tag packets.
*/
en_cd_TxFixedTagPacket( upsTrrbl.Packet );
break;
case TREQ_RX_CLASS3_PACKET:
case TREQ_RX_UNSCHEDULED_PACKET:
/*
** Class 3 packet returned from the application ( server only ).
** Save new data and initiate a Rx verify transmission.
*/
pTranRec = cd_LookupTransportRecord( CD_ETHERNET_PORT, upsTrrbl.Packet->iTransport );
if( pTranRec != NULL )
{
/*
** Toss the old freshest combuf and save the new one.
*/
if( pTranRec->pCbFreshest )
{
CB_DeleteComBuf( pTranRec->pCbFreshest );
}
pTranRec->pCbFreshest = upsTrrbl.Packet->pComBuf;
/*
** Consider this as a verification and
** initiate a transmission with the freshest data.
*/
pTranRec->fVerified = TRUE;
en_cd_TxClass3Packet( upsTrrbl.Packet, pTranRec );
}
else
{
/*
** If the connection timed out, toss the response.
*/
CB_DeleteComBuf( pCb );
}
break;
case TREQ_CLASS3_CLIENT_TIMEOUT:
/*
** Class 3 client timed out waiting for response.
** Retry until the connection times out.
*/
pTranRec = cd_LookupTransportRecord( CD_ETHERNET_PORT, upsTrrbl.Timeout->iId );
if( pTranRec != NULL )
{
if( pTranRec->pCbFreshest != NULL )
{
/*
** Send the latest data if there is any available.
** TxClass3Packet only loads the data into the ASIC.
** It does nothing to the combuf or the tribble.
*/
upsTrrbl.Packet->pComBuf = pTranRec->pCbFreshest;
en_cd_TxClass3Packet( upsTrrbl.Packet, pTranRec );
}
/*
** Reload the timeout tribble into the timer and get
** the timer going again.
*/
GS_ReloadLinkedMsgTimer( pTranRec->xRetryTimer, 0, pTranRec->pRetryTot );
/*
** Skip to the end of the while( 1 ) loop. This keeps us from
** deleting the tribble we just pulled off the queue which
** has just been reattached to the retry timer.
*/
continue;
}
break;
case TREQ_TX_CLASS3_REQUEST:
case TREQ_TX_CLASS3_RESPONSE:
/*
** Initiate a transmission.
** Request for clients, response for servers.
**
** Lookup the transport record. Bail if the transport is no longer
** active or there is no data to transmit.
*/
pTranRec = cd_LookupTransportRecord( CD_ETHERNET_PORT, upsTrrbl.Packet->iTransport );
if( ( pTranRec != NULL ) &&
( pTranRec->pCbFreshest != NULL ) )
{
if( pTranRec->fServerConsumer )
{
/*
** We're a server. Mark the request as verified.
*/
pTranRec->fVerified = TRUE;
}
else
{
/*
** We're a client. Retrigger the retry timer.
*/
GS_RetriggerTimer( pTranRec->xRetryTimer );
}
/*
** Send the latest data in any case.
*/
upsTrrbl.Packet->pComBuf = pTranRec->pCbFreshest;
en_cd_TxClass3Packet( upsTrrbl.Packet, pTranRec );
}
break;
case TREQ_WRITE_CLASS3_TX_DATA:
/*
** New class 3 transmit data for a
** request ( client ) or response ( server ).
*/
pTranRec = cd_LookupTransportRecord( CD_ETHERNET_PORT, upsTrrbl.Packet->iTransport );
if( pTranRec != NULL )
{
/*
** Toss the old freshest combuf ( if any ) and save the new one.
*/
if( pTranRec->pCbFreshest )
{
CB_DeleteComBuf( pTranRec->pCbFreshest );
}
pTranRec->pCbFreshest = upsTrrbl.Packet->pComBuf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -