⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cd_util.c

📁 基于EthernetIP协议的应用程序,可以读取AB公司Controllogix系列Ethernetip协议PLC数据. 此软件代码可用于工业控制.
💻 C
📖 第 1 页 / 共 5 页
字号:
   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 + -