📄 cd_util.c
字号:
CM_ConnectionRecordType *psConnRecord;
UINT32 lConnId;
INT8 bNumLinked;
/*
** Basic sanity check
*/
if( psTrrbl->psConnRecord == NULL )
{
eStatus = CD_FAULT_TYPE;
goto Bailout;
}
/*
** Is this a class 1 or class 3 connection?
** For class 1 connections, both the Pro & Con transports are used.
** For class 3 connections, only the Con transport is used.
*/
psConnRecord = psTrrbl->psConnRecord;
iClass = psConnRecord->bClassTrigger & CM_TCT_CLASS_MASK;
/*
** If this is a Class 4 or Class 5 bridged connection, pretend that
** it is a class 3 as far as the transports are concerned.
*/
if( ( ( iClass == CM_TCT_CLASS_4 ) || ( iClass == CM_TCT_CLASS_5 ) )
&& ( ( psConnRecord->bProTransportType & CD_XPORT_BRIDGED_MASK )
||( psConnRecord->bConTransportType & CD_XPORT_BRIDGED_MASK ) ) )
{
iClass = CM_TCT_CLASS_3;
}
if( ( ( iClass != CM_TCT_CLASS_1 ) && ( iClass != CM_TCT_CLASS_3 ) ) ||
( ( iClass == CM_TCT_CLASS_3 ) &&
( ( ( psConnRecord->iConConnParams & CM_CP_TYPE_MASK ) == CM_CP_TYPE_MULTICAST ) ||
( ( psConnRecord->iProConnParams & CM_CP_TYPE_MASK ) == CM_CP_TYPE_MULTICAST ) ) ) )
{
/*
** Unsupported transport class.
*/
eStatus = CD_UNSUPPORTED_TRANSPORT;
psConnRecord->iERC = CM_ERC_BAD_TRANSPORT;
goto Bailout;
}
if( iClass == CM_TCT_CLASS_1 )
{
/*
** Verify scheduled production and cyclic trigger.
*/
}
if( iClass == CM_TCT_CLASS_3 )
{
/*
** Validate unscheduled production.
** Allow all triggers. Trigger OK is up to the application object.
*/
if( psConnRecord->iProConnParams & CM_CP_PRIORITY_SCHEDULED )
{
eStatus = CD_UNSUPPORTED_BANDWIDTH;
psConnRecord->iERC = CM_ERC_NO_BANDWIDTH;
goto Bailout;
}
}
/*
**--------------------------------------------------------------------
** Reserve a producer transport for this connection record, if Class 1
**--------------------------------------------------------------------
*/
if( iClass == CM_TCT_CLASS_1 )
{
/*
** Note: Class 3 does not use a producer transport
**
** However, it does use the TxTag in the consumer
** transport. See below.
*/
/*
** Allocate a transport, if not yet done
*/
if( psConnRecord->iProTransportId == 0 )
{
if( ( eStatus = cd_AllocateTransport( psTrrbl, TRUE ) ) != SUCCESS )
{
eStatus = CD_TRANSPORT_ALLOC_FAIL;
psConnRecord->iERC = CM_ERC_NO_BUFFER;
goto Bailout;
}
}
else
{
/*
** Note that this area is being re-visited. The patch included here
** works for adapters only. Bridge connections, and originators work
** differently and this routine needs to be re-written to handle
** those scenarios
*/
/*
** See if this is a multicast
*/
if( psConnRecord->iProConnParams & CM_CP_TYPE_MULTICAST )
{
if( !psConnRecord->fOriginator )
{
/*
** We are not an originator, so see if we were requested to use
** a different transport than the one we had allocated earlier.
** The other side of the bridge, or the application will overwrite
** psConnRecord->iProTransportId with the id of the transport which
** is being multicast. psConnRecord->lLeProConnId is still the
** same as when we put our id in it when we originally reserved.
*/
}
else
{
/*
** We are an originator
*/
/* TO DO */
/*
** First need to determine whether we are already producing on the
** conn id that was returned. If so, then do the steps necessary
** to re-use the transport on the other side of the bridge.
/* if( producer_in_use )
**
** psConnRecord->psOtherConnRecord->iConTransportId = pTr->iOtherTransportId;
*/
}
}
}
pTr = cd_LookupTransportRecord( psConnRecord->iPort, psConnRecord->iProTransportId );
if( pTr == NULL )
{
eStatus = CD_TRANSPORT_ALLOC_FAIL;
psConnRecord->iERC = CM_ERC_NO_BUFFER;
goto Bailout;
}
/*
** Link the connection serial number to the transport record.
** Error out if too many multicast connections.
*/
bNumLinked = cd_LinkConnSnToTransport( psConnRecord->iConnectionSn, pTr, psConnRecord->iPort);
if( bNumLinked < 0 )
{
eStatus = CD_TRANSPORT_ALLOC_FAIL;
psConnRecord->iERC = CM_ERC_NO_BUFFER;
goto Bailout;
}
/*
** If reserve has not been done or if only one connection record
** is linked to the transport, do the reserve.
**
** Note that a second pass is allowed here in case we need to pick
** up information that has changed in the connection record.
** (e.g. connection ID's that were returned in a FO request)
*/
if( ( ( pTr->iState & CD_TS_RESERVED ) == 0 )
|| ( bNumLinked == 1 ) )
{
pTr->iState |= CD_TS_RESERVED;
/*
** Save the transport type.
*/
pTr->bTransportType = psConnRecord->bProTransportType;
/*
** Fill in any tags that we select
** with our mac id and the transport id number.
*/
if( ( psConnRecord->iProConnParams & CM_CP_TYPE_MASK ) == CM_CP_TYPE_MULTICAST )
{
#ifdef CD_EN_OBJECTS
/*
** Ethernet uses the module incarnation count for the upper half of
** the 32 bit connection ID
*/
/*
** jjw note change of using the transport record transport id rather
** than the connection record transport ID. The connection record id
** does not have the radioactive bits, the transport id does.
*/
if( psConnRecord->iPort == CD_ETHERNET_PORT )
{
lConnId = pTr->iTransportId | /* was psConnRecord->iProTransportId | */
( ( UINT32 ) sRadioActiveMasks.nIncarnation << 16 );
}
else
#endif
{
lConnId = pTr->iTransportId | /* was psConnRecord->iProTransportId | */
( ( UINT32 ) CD_s[ psConnRecord->iPort ].bMacId << 16 );
}
psConnRecord->lLeProConnId = UC_lTOlLe( lConnId );
}
else
{
lConnId = UC_lLeTOl( psConnRecord->lLeProConnId );
}
/*
** Copy MacId and Transport Id from the connection id
*/
if ( psConnRecord->iPort == CD_ETHERNET_PORT )
{
/*
** Use 4 byte connection record
*/
*( UINT32 * ) &pTr->abTxTag[0] = UC_lLeTOl( psConnRecord->lLeProConnId );
}
else
{
pTr->abTxTag[ 0 ] = ( UINT8 ) (lConnId >> 16);
pTr->abTxTag[ 1 ] = ( UINT8 ) lConnId;
pTr->abTxTag[ 2 ] = ( UINT8 ) (lConnId >> 8);
}
/*
** Final initialization based on transport type
*/
/*
** Since we are in the producer section we can't be a consumer
*/
pTr->fServerConsumer = FALSE;
/*
** If this is and explicit transport reserve request, put information
** into the connection record that may be used latter during the
** start phase of transport comissioning.
**
** For example, if this is a class 1 bridged connection, a copy
** function could be placed into the connection record at this time
** and later, during the strart phase, retrived and used,
** by the other transport on the other side of the bridge.
*/
if( psTrrbl->eRequest == TREQ_RESERVE_TRANSPORTS )
{
/* For Producer Transport */
switch( psConnRecord->bProTransportType & CD_XPORT_TYPE_MASK )
{
case CD_XPORT_TYPE_PROVIDE_FUNCTION:
/*
** Provide a copy function that will be called (by the application
** or the other side of the bridge) whenever new
** data is ready to be produced.
**
** This case is valid for the SMAC, CNA10, and ENET.
**
** Current implementation include CNET-to-CNET bridging using the
** CNA10 ASIC or SMAC ASICs (NOTE: SMACs has not been tried and
** there is, therefore, no cd_ProducerCopyFunction for the
** SMAC CD) or ENET-to-ICP. Therefore, we currently return an
** error if this case is invoked for anything but the CNA10 ASIC
** and ENET.
*/
#ifdef CD_EN_OBJECTS
psConnRecord->pProCopyFunction = en_cd_ProducerCopyFunction;
/*
** Assign a pointer to the transport record to the producer
** handle for use in the en_cd_ProducerCopyFunction() calls
** for this connection.
*/
psConnRecord->xProAppHandle = (void*) pTr;
eStatus = CD_UNSUPPORTED_TRANSPORT;
psConnRecord->iERC = CM_ERC_BAD_TRANSPORT;
goto Bailout;
#endif
break;
case CD_XPORT_TYPE_CALL_FUNCTION:
/*
** Do nothing here. Wait for start of transport to get pointer
** to function to call.
** This case is valid for the SMAC but not the CNA10 ASIC.
** This is also valid for the NetLinx DualPort.
*/
break;
case CD_XPORT_TYPE_DEFAULT:
case CD_XPORT_TYPE_PROVIDE_BUFFER:
/*
** This case is how the Producer Xports have worked in the past.
** So, do nothing new.
*/
break;
case CD_XPORT_TYPE_ACCESS_BUFFER:
/*
** This case is not implemented yet, and may never be.
** So fall through.
*/
default:
psConnRecord->iERC = CM_ERC_BAD_TRANSPORT;
eStatus = CD_UNSUPPORTED_TRANSPORT;
goto Bailout;
} /* end switch */
} /* end if TREQ_RESERVE_TRANSPORTS */
} /* end if( ( pTr->iState & CD_TS_RESERVED ) == 0 ) */
else if( bNumLinked > 1 )
{
if( ( psConnRecord->iProConnParams & CM_CP_TYPE_MASK ) == CM_CP_TYPE_MULTICAST )
{
/*
** Need to copy the transport ID from the existing transport
** to the new connection record that is going to receive
** multicast data using that ID
*/
psConnRecord->lLeProConnId = UC_lLeTOl( *( UINT32 * ) &pTr->abTxTag[0] );
}
}
/*
**********************************************************
** Start of START_TRANSPORTS Section for the Producer
**********************************************************
*/
if( ( psTrrbl->eRequest == TREQ_START_TRANSPORTS )
&& ( ( pTr->iState & CD_TS_STARTED ) == 0 ) )
{
pTr->iState |= CD_TS_STARTED;
/*
** Always pick up the size.
*/
pTr->iDataSize = psConnRecord->iProAppSize;
/* For Producer Transport */
switch( psConnRecord->bProTransportType & CD_XPORT_TYPE_MASK )
{
case CD_XPORT_TYPE_PROVIDE_FUNCTION:
break;
case CD_XPORT_TYPE_CALL_FUNCTION:
/*
** Store pointer to function to call and handle to pass back.
**
** This case is valid for the SMAC and the NetLinx DualPort,
** but not a CNA10 ASIC producer transport.
*/
pTr->pTxCopyFunction = psConnRecord->psOtherConnRecord->pConCopyFunction;
pTr->xTxAppHandle = psConnRecord->psOtherConnRecord->xConAppHandle;
break;
case CD_XPORT_TYPE_DEFAULT:
case CD_XPORT_TYPE_PROVIDE_BUFFER:
/*
** This case is how the Producer Xports have worked in the past.
** So, do nothing new.
*/
break;
case CD_XPORT_TYPE_ACCESS_BUFFER:
/*
** This case is not implemented yet, and may never be.
** So fall through.
*/
default:
eStatus = CD_UNSUPPORTED_TRANSPORT;
psConnRecord->iERC = CM_ERC_BAD_TRANSPORT;
goto Bailout;
}
/*
** If bridged, then connect the other consumer to this producer
*/
if( pTr->fBridged )
{
/*
** Class 1 should hook other producer to this consumer
*/
if( ( psConnRecord->psOtherConnRecord )
&& ( psConnRecord->psOtherConnRecord->iConTransportId ) )
{
pTr->iOtherTransportId = psConnRecord->psOtherConnRecord->iConTransportId;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -