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

📄 en_cd.c

📁 基于EthernetIP协议的应用程序,可以读取AB公司Controllogix系列Ethernetip协议PLC数据. 此软件代码可用于工业控制.
💻 C
📖 第 1 页 / 共 2 页
字号:
      }
      pBuffer = pTr->pBufA;
      /*
      ** Point over the sequence count,  The application will write to the data,
      ** then when it does a putbuffer we will increment the sequence count
      */

      return( pBuffer + 2 );
   }
   return NULL;
} /* End of EN_CD_GetTransportBuffer() */



/*---------------------------------------------------------------------------
** EN_CD_ReleaseTransportBuffer()
**
** Releases the semaphore associated with the transport buffer
**---------------------------------------------------------------------------
*/
void EN_CD_ReleaseTransportBuffer( UINT16 iTransport )
{
   cd_TransportRecordType *pTr;

   if ( ( pTr = cd_LookupTransportRecord( CD_ETHERNET_PORT, iTransport ) ) != NULL )
   {
      GS_SetSemaphore( pTr->xSBufAccess );
   }
}

/*---------------------------------------------------------------------------
** EN_CD_PutTransportBuffer()
**---------------------------------------------------------------------------
*/

void EN_CD_PutTransportBuffer( UINT16 iTransport )
{
   cd_TransportRecordType *pTr;
   UINT32                  iPrevBufState;

   if ( ( pTr = cd_LookupTransportRecord( CD_ETHERNET_PORT, iTransport ) ) != NULL )
   {
      iPrevBufState = pTr->iBufState;

      /*
      ** As currently written, it is the responsibility of the bridged
      ** device to put in the transport sequence count.  This is because
      ** at the device level we have no knowledge of changed data or not
      */
      if( !pTr->fBridged )
      {
     /* Sneak in the sequence count for the tpu */
         *((UINT16 *) pTr->pBufA) =  ENCAP_VALUE_SHORT(pTr->iLeSeqCount);
          pTr->iLeSeqCount += 1;
      }

     /*
     ** Make sure the frequency is lower than that specified by the production
     ** inhibit time.  For cyclic connections let the API determine when new
     ** data is transmitted.
     */
      if ( ((( pTr->bClassTrigger & CM_TCT_TRIGGER_MASK ) == CM_TCT_TRIGGER_CYCLIC ) ||
           ((IS_GT( pTr->lProInhib, ( gs_sTimers.sSysTime.iMSecTime - pTr->iMsecLastSent ))))) &&
          (iPrevBufState == A_CURRENT_B_FREE))
      {
        GS_SetSemaphore( pTr->xSBufAccess );
        return;
      }
      /*
      ** We sent a message based on a change of state.  Retrigger the
      ** timer to handle the next API.
      */

	  
	  /*
	  ** start edits: October,10th 2005, H.F.
	  **
	  ** write to Log-File, if bad API Timer
	  */

	  if( !(pTr->xAPITimer) )
	  {
		 GS_LogEvent( CD_BAD_API_TIMER, 0, 0, FATAL );
	  }

	  /*
	  ** end edits: October,10th 2005, H.F.
	  */

      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.
	  */


      /*
      ** jjw 02/07/01 Update the buffer state after the class 1 send.  Class 1
      ** send will use this as a flag to determine it is the first data being sent on
      ** a new connection and copy the data regardless of serial number
      */

      pTr->iBufState = A_CURRENT_B_FREE;

   }  /* end - if */

} /* End of EN_CD_PutTransportBuffer() */



/****************************************************************************
**
** Private Services
**
*****************************************************************************
*/


/*---------------------------------------------------------------------------
** en_cd_FreeIpMcastAddress()
**---------------------------------------------------------------------------
*/

void en_cd_FreeIpMcastAddress( CM_ConnectionRecordType  *psConnRecord )
{
   UINT16                   iClass;

   iClass = psConnRecord->bClassTrigger & CM_TCT_CLASS_MASK;

   if ( ( iClass == CM_TCT_CLASS_1 ) &&
        ( psConnRecord->sEce.psMcast ) )
   {
      if( ( psConnRecord->iProConnParams & CM_CP_TYPE_MASK ) == CM_CP_TYPE_MULTICAST )
      {
         FREE_MCAST_ADDRESS( psConnRecord->sEce.psMcast );
      }
      else
      {
         /*
         ** Consumer must be mcast, which is allocated with a simple GS_Malloc()
         */

         GS_Free( psConnRecord->sEce.psMcast );
      }
   }

}  /* End of en_cd_FreeIpMcastAddress() */


/*---------------------------------------------------------------------------
** en_cd_TxFixedTagPacket()
**---------------------------------------------------------------------------
*/

void                en_cd_TxFixedTagPacket(CD_PacketTrrblType * pTrrbl)
{
   UINT16              iSize;
   PKTBUF             *msg;
   EnCdMessageType     EnCdMessage;    /* Message to be sent out via tcpip */
   UINT32              Status;

   /*
   ** We only accept packets with an open socket.  If the application wants to
   ** send packets to its own node, let it open a socket to it
   */

   if (pTrrbl->bRequest != 0)
   {
      /*
      ** This request originated from a client on another machine.  Lookup the correct
      ** information so we can send the buffer out. Collect the header information for
      ** the packet from the tribble. This gets loaded into the buffer ahead of the packet.
      **
      ** Recover the pointer to the original message and insure non-zero!
      */

      msg = pTrrbl->xCdHandle;
      if (msg == NULL)
      {
         GS_LogEvent( EN_NO_RESP_TRRBL,
                      0,
                      0,
                      FATAL );
         return;
      }
   }
   else
   {
      /*
      ** Message is originating on this board.  Allocate message dynamically
      */

      msg = PktBufAlloc();
      if (msg == NULL)
      {
         /*
         ** We haven't enough memory to get this message.  Don't
         ** fatal because we may recover.
         */

         GS_LogEvent( EN_RESOURCE,
                      0,
                      0,
                      WARNING );
         return;
      }  /* End if message == NULL */

      /*
      ** Transfer host name in case we need to connect. Send this message on to the management task.
      ** Depending on whether this host has a session set up or not, we may need to do a lot of pre-processing.
      */

      EnCdMessage.pcbDestHost = pTrrbl->pCbDestHost;
      msg->sOutputQ = MngOutgoingEncapQueue;
      msg->sEncap.sHdr.iEncaph_command = ENCAP_CMD_SEND_RRDATA;
      msg->sEncap.sHdr.lEncaph_session = 0;
      msg->sEncap.sHdr.lEncaph_status = 0;
      msg->sEncap.sHdr.lEncaph_opt = 0;
      msg->sEncap.sDt_hdr.lDt_target = 0;
      msg->sEncap.sDt_hdr.iDt_timeout = 0;
      msg->sEncap.sAdr_tag.sTag.iTag_length = 0;
      msg->sEncap.sAdr_tag.sTag.iTag_type = 0;
      msg->sEncap.sObj_list.iO_count = 2; /* Address and unconnected message only */
      msg->sEncap.sPkt_tag.sTag.iTag_type = CPF_TAG_PKT_UCMM;
      msg->sEncap.lValid = PKTBUF_ENCAPV_DT |	/* Data transfer field is valid */
                           PKTBUF_ENCAPV_OBJ |  /* Object list field is valid */
                           PKTBUF_ENCAPV_ADR |  /* CPF Address tag is valid */
                           PKTBUF_ENCAPV_PKT;   /* CPF packet tag is valid */

      /*
      ** Decided not to save the Cd Packet tribble handle in the context.  This would have
      ** required us to save the tribble, and then create some way of recovering the tribbles
      ** should the return message not be sent.  Instead we will only save the xUmHandle in the
      ** context and let the UCMM worry about how to handle unreturned responses
      */

      msg->sEncap.sHdr.alEncaph_context[ 1 ] = (UINT32) pTrrbl->xUmHandle;

      /*
      ** Encode our IP address into the 0 context field.  This will help
      ** determine that the incoming message is a reply to us and not an
      ** illegal request from an originator coming in on the wrong socket.
      */
      msg->sEncap.sHdr.alEncaph_context[ 0 ] = list_target_data.sS.s_sock.lSin_addr;

      msg->pData = &msg->abData[0]; /* used by en_cd_SetSocketAddresses() */
      msg->lLength = 0;             /* used by en_cd_SetSocketAddresses() */

   }  /* End message originating on this board */

   /*
   ** setup the SockAddr Info Data types in the packet addenda if needed
   */

   en_cd_SetSocketAddresses( msg, &msg->sEce.sSa );


   /*
   ** msg should still have the original command, and options (both in host order) in it.
   ** Context is also preserved, though the order was never changed
   */

   iSize = CB_GetDataSizeComBuf(pTrrbl->pComBuf);
   msg->sEncap.sPkt_tag.sTag.iTag_length = iSize;
   msg->lLength = iSize;

   /*
   ** Instead of copying the data to a new buffer, just attach the combuff and send it to the
   ** transmission task
   */
   msg->pData = pTrrbl->pComBuf->pData; /* point the datapointer to the combuffer */
   msg->pCb = pTrrbl->pComBuf;
   EnCdMessage.Command = SENDCOMMBUF;   /* Send the attached message using a combuf */
   EnCdMessage.PacketBuf = msg;         /* Tcpip message to be sent.  It will be deleted by the send task */

   /*
   ** Send to queue the message at the send task, or the management task depending on connection state
   */

   Status = OE_MsgQSend(msg->sOutputQ,
                       (char *) &EnCdMessage.Command,
                       sizeof EnCdMessage,
                       WAIT_FOREVER,
                       MSG_PRI_NORMAL);

   /*
   ** Send failed, we need to delete the packet here lest we loose it
   */

   if (Status == OE_ERROR)
   {
      CB_DeleteComBuf( msg->pCb );
      PktBufFree(msg);
   }

}  /* end of en_cd_TxFixedTagPacket() */



/*---------------------------------------------------------------------------
** en_cd_LoadUnschedTxPacket()
**---------------------------------------------------------------------------
*/

void en_cd_LoadUnschedTxPacket( CD_PacketTrrblType *pTrrbl, UINT8 *pabHeader, cd_TransportRecordType  *pTranRec,
                           UINT16 iHeaderSize, UINT16 iTotalSize, BOOL fConfig )
    {
    UINT16              iSize;
    PKTBUF             *msg;
    EnCdMessageType     EnCdMessage;
    UINT32              Status;

    /*
    ** Allocate message dynamically. If wee haven't enough memory to get this message.
    ** Don'tfatal because we may recover.
    */

    msg = PktBufAlloc();
    if (msg == NULL)
    {
       GS_LogEvent( EN_RESOURCE,
                    0,
                    0,
                    WARNING );
       return;
    }

    msg->sEncap.sHdr.iEncaph_command = ENCAP_CMD_SEND_UNITDATA; /* We are not yet connected */
    msg->sEncap.sHdr.lEncaph_status = 0;
    msg->sEncap.sHdr.lEncaph_opt = 0;
    msg->sEncap.sDt_hdr.lDt_target = 0;
    msg->sEncap.sDt_hdr.iDt_timeout = 0;
    msg->sEncap.sAdr_tag.sTag.iTag_type = CPF_TAG_ADR_CONNECTED;
    msg->sEncap.sObj_list.iO_count = 2;
    msg->sEncap.sPkt_tag.sTag.iTag_type = CPF_TAG_PKT_CONNECTED;  /* unconnected message */
    msg->sEncap.lValid = PKTBUF_ENCAPV_DT | /* Data transfer field is valid */
                      PKTBUF_ENCAPV_OBJ |   /* Object list field is valid */
                      PKTBUF_ENCAPV_ADR |   /* CPF Address tag is valid */
                      PKTBUF_ENCAPV_PKT;    /* CPF packet tag is valid */

    /*
    ** We are in a bit of a bind here.  In the original control net the sequence number was not part of the
    ** message.  In TCPIP it is.  If we simply prepend the sequence number on we will get into
    ** trouble with re-transmits.  A re-transmit reuses the original combuf.  IF we modify it here, then
    ** get it back as a re-transmit we will unknowingly modify it again with the sequence number resulting in
    ** a corrupt message.  The only thing we can do is rebuild the message in the buffer space
    ** provided in msg->data and include the sequence count.
    */

    UC_CopyMem( msg->abData, &pabHeader[ 7 ], 2 );  /* First put the sequence count in */
    iSize = CB_GetDataSizeComBuf( pTrrbl->pComBuf );
    UC_CopyMem( &msg->abData[ 2 ], pTrrbl->pComBuf->pData, iSize ); /* Now copy the body of the message */
    msg->sEncap.sAdr_tag.sTag.iTag_length = sizeof msg->sEncap.sAdr_tag.data.sC.lCid;
    msg->sEncap.sPkt_tag.sTag.iTag_length = iSize + 2; /* Don't forget the 2 byte sequence we added */
    msg->lLength = iSize + 2;
    msg->sEncap.sAdr_tag.data.sC.lCid = UC_lTOlLe(*(UINT32 *) &pabHeader[ 3 ]);
    msg->pData = msg->abData;    /* point the datapointer to the combuffer */

    /*
    ** Send this message on to the xmit task. The session is already open so we can send it immediately
    */

    msg->sOutputQ = pTranRec->sEce.sOutputQ;
    EnCdMessage.Command = SENDINCORPMESSAGE;    /* Send the attached data in the msg packet */

    /*
    ** Tcpip message to be sent.  It will be deleted by the send task
    ** Send to queue the message at the send task, or the management task depending on connection state
    */

    EnCdMessage.PacketBuf = msg;
    Status = OE_MsgQSend(msg->sOutputQ,
                        (char *) &EnCdMessage.Command,
                        sizeof EnCdMessage,
                        WAIT_FOREVER,
                        MSG_PRI_NORMAL);

    /*
    **  Send failed, we need to delete the packet here lest we loose it
    */

    if (Status == OE_ERROR)
    {
        PktBufFree(msg);
    }
 }


#endif /* #ifdef CD_EN_OBJECTS */





/****************************************************************************
**
** End of EN_CD.C
**
*****************************************************************************
*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -