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

📄 zl5011xrtp.c

📁 Zalink50114----TDMoIP芯片驱动源码
💻 C
📖 第 1 页 / 共 4 页
字号:

   ZL5011X_TRACE_CONTEXT(ZL5011X_RTP_FN_ID, context,
         "zl5011xRtpUpdateStatistics: ctxt %d, flags %08X",
         context, rollOverFlags, 0, 0, 0, 0);

   /* Update s/w counters */
   if (status == ZL5011X_OK)
   {
      if ((rollOverFlags & ZL5011X_RTP_TX_BYTE_ROLLOVER_MASK) != 0)
      {
         zl5011xParams->rtp.rtpSwCounts[context].txByteCount += ZL5011X_RTP_TX_BYTE_CARRY_MASK;
      }

      if ((rollOverFlags & ZL5011X_RTP_TX_PACKET_ROLLOVER_MASK) != 0)
      {
         zl5011xParams->rtp.rtpSwCounts[context].txPacketCount += ZL5011X_RTP_TX_PACKET_CARRY_MASK;
      }

      if ((rollOverFlags & ZL5011X_RTP_RX_PACKET_ROLLOVER_MASK) != 0)
      {
         zl5011xParams->rtp.rtpSwCounts[context].rxPacketCount += ZL5011X_RTP_RX_PACKET_CARRY_MASK;
      }

      if ((rollOverFlags & ZL5011X_RTP_RX_SEQ_NUM_ROLLOVER_MASK) != 0)
      {
         zl5011xParams->rtp.rtpSwCounts[context].rxSequenceNumber += ZL5011X_RTP_SEQ_NUM_CARRY_MASK;
      }
   }

   return status;
}

/*******************************************************************************
 Function:
    zl5011xRtpReadCounters

 Description:
   Reads the statistics counters from the RTP block. The high order bits
   are maintained by software using an interrupt. To ensure consistency of the
   data due to this, the read sequence is as follows:
      1) disable interrupts
      2) read counters from the device
      3) check the interrupt status. If an interrupt is pending then update the
         counters for that context.
      4) If an interrupt occurred and it was for the context under inspection,
         then re-read the counters from the device.

 Inputs:
   zl5011xParams   Pointer to the structure for this device instance
   context        Context for which counts are to be collected

 Outputs:
   counts         array of words to represent the statistics table
                  locations from the device

 Returns:
  zlStatusE

 Remarks:
   None

*******************************************************************************/

extern zlStatusE  zl5011xRtpReadCounters(zl5011xParamsS *zl5011xParams, Uint32T context,
      Uint32T *counts)
{
   zlStatusE status = ZL5011X_OK;
   Uint32T statsAddress;
   Uint32T intContext, rollOverFlags;
   Uint32T loop;
   Uint32T interruptStatus;

   ZL5011X_TRACE_CONTEXT(ZL5011X_RTP_FN_ID, context,
         "zl5011xRtpReadCounters: ctxt %d",
         context, 0, 0, 0, 0, 0);

   /* Get statistics address for context */
   if (status == ZL5011X_OK)
   {
      status = zl5011xRtpGetStatisticsAddress(zl5011xParams, context,
            &statsAddress);
   }

   for (loop = 0; loop < (ZL5011X_RTP_STATS_SIZE / sizeof(Uint32T)); loop++)
   {
      /* read the stats words from the device */
      if (status != ZL5011X_OK)
      {
         break;
      }

      status = zl5011xRead(zl5011xParams, statsAddress + (loop * sizeof(Uint32T)), counts + loop);
   }

   if (status == ZL5011X_OK)
   {
      status = zl5011xAdmGetInterruptStatus(zl5011xParams, &interruptStatus);
   }

   if (status == ZL5011X_OK)
   {
      /* check if an RTP interrupt is pending */
      if ((interruptStatus & (ZL5011X_1BIT_MASK << ZL5011X_ADM_RTP_STATS_INTERRUPT))
                                                                           != 0)
      {
         /* since the interrupt is pending, find out which context it is for */
         status = zl5011xRtpGetInterruptStatus(zl5011xParams, &intContext,
               &rollOverFlags);

         if (status == ZL5011X_OK)
         {
            status = zl5011xRtpUpdateStatistics(zl5011xParams,
                  intContext, rollOverFlags);

            /* if the update was successful, then clear the interrupt source.
               Otherwise leave the interrupt enabled, so that the ISR can do the
               interrogation again and then log the error */
            if (status == ZL5011X_OK)
            {
               /* ignore the return from the clear interrupt function */
               (void)zl5011xAdmClearInterruptSource(zl5011xParams,
                              ZL5011X_1BIT_MASK << ZL5011X_ADM_RTP_STATS_INTERRUPT);

               /* if the pending interrupt is for the current context, then
                  will have to read the counts from the device again */
               if (context == intContext)
               {
                  for (loop = 0; loop < (ZL5011X_RTP_STATS_SIZE /sizeof(Uint32T));
                                                                        loop++)
                  {
                     /* read the stats words from the device */
                     if (status != ZL5011X_OK)
                     {
                        break;
                     }

                     status = zl5011xRead(zl5011xParams,
                                       statsAddress + (loop * sizeof(Uint32T)),
                                       counts + loop);
                  }
               }
            }
            else
            {
               /* if the update statistics failed, then ignore the error code, since
                  the interrupt will log this failure later on. */
               status = ZL5011X_OK;
            }

         }
         else
         {
            /* if there was an error reading from the interrupt queue, then leave
               the interrupt set and continue on with this function.
               The ISR can do the interrogation again and then log the error */
            status = ZL5011X_OK;
         }
      }
   }

   return status;
}

/*******************************************************************************
 Function:
    zl5011xRtpGetStatistics

 Description:
   Returns the RTP statistics for the context, using the low order bits from
   the device and the high order bits from a s/w count held in the device
   structure.

 Inputs:
   zl5011xParams   Pointer to the structure for this device instance
   context        selected context
   mode           collect statistics Rx, Tx or both

 Outputs:
   stats          structure used to return the stats to the calling function
                  Rx stats are :
                              rxFirstSequenceNumber, rxPacketCount,
                              rxSequenceNumber, interArrivalJitter
                  Tx stats are :
                              txByteCount, txPacketCount,

 Returns:
  zlStatusE

 Remarks:
   The RTP interrupt must be enabled for the high order bits of the counts to
   be maintained by s/w.

*******************************************************************************/

extern zlStatusE  zl5011xRtpGetStatistics(zl5011xParamsS *zl5011xParams, Uint32T context,
      zl5011xGetRtpStatsModeE mode, zl5011xRtpStatsS *stats)
{
   zlStatusE status = ZL5011X_OK;
   zl5011xBooleanE disabledInts = ZL5011X_FALSE;
   Uint32T readValue[ZL5011X_RTP_STATS_SIZE / sizeof(Uint32T)];

   ZL5011X_TRACE_CONTEXT(ZL5011X_RTP_FN_ID, context,
         "zl5011xRtpGetStatistics: ctxt %d, mode %d",
         context, mode, 0, 0, 0, 0);

   status = ZL5011X_CHECK_GET_RTP_STATS_MODE(mode);

   /* Disable interrupts */
   if (status == ZL5011X_OK)
   {
      status = zl5011xHostInterruptDisable();

      if (status == ZL5011X_OK)
      {
         disabledInts = ZL5011X_TRUE;
      }
   }

   /* Get statistics counts from the device for the context */
   if (status == ZL5011X_OK)
   {
      status = zl5011xRtpReadCounters(zl5011xParams, context, readValue);
   }

   /* Calculate statistics using the s/w counts and device counts */
   if (status == ZL5011X_OK)
   {
      if ((mode == ZL5011X_RTP_GET_RX_TX_STATS) || (mode == ZL5011X_RTP_GET_TX_STATS))
      {
         /* construct the stats values from the device data */
         stats->txByteCount = zl5011xParams->rtp.rtpSwCounts[context].txByteCount |
               (readValue[ZL5011X_RTP_TX_BYTE_COUNT_INDEX] &
               (ZL5011X_RTP_TX_BYTE_CARRY_MASK | ZL5011X_RTP_TX_BYTE_COUNT_MASK));

         stats->txPacketCount = zl5011xParams->rtp.rtpSwCounts[context].txPacketCount |
               (readValue[ZL5011X_RTP_TX_PACKET_COUNT_INDEX] &
               (ZL5011X_RTP_TX_PACKET_CARRY_MASK | ZL5011X_RTP_TX_PACKET_COUNT_MASK));
      }

      if ((mode == ZL5011X_RTP_GET_RX_TX_STATS) || (mode == ZL5011X_RTP_GET_RX_STATS))
      {
         stats->rxFirstSequenceNumber = zl5011xParams->rtp.rtpSwCounts[context].rxFirstSequenceNumber;

         /* construct the stats values from the device data */
         stats->rxPacketCount = zl5011xParams->rtp.rtpSwCounts[context].rxPacketCount |
               (readValue[ZL5011X_RTP_RX_PACKET_COUNT_INDEX] &
               (ZL5011X_RTP_RX_PACKET_CARRY_MASK | ZL5011X_RTP_RX_PACKET_COUNT_MASK));

         stats->rxSequenceNumber = zl5011xParams->rtp.rtpSwCounts[context].rxSequenceNumber |
               (readValue[ZL5011X_RTP_RX_SEQ_NUM_INDEX] &
               (ZL5011X_RTP_SEQ_NUM_CARRY_MASK | ZL5011X_RTP_SEQ_NUM_MASK));

         stats->interArrivalJitter = (readValue[ZL5011X_RTP_RX_SEQ_NUM_INDEX] >> ZL5011X_RTP_RX_JITTER_BITS)
               & ZL5011X_RTP_RX_JITTER_MASK;
      }
   }

   /* Enable interrupts */
   if (disabledInts == ZL5011X_TRUE)
   {
      status = zl5011xHostInterruptEnable();
   }

   return status;

}

/*******************************************************************************
 Function:
    zl5011xRtpGetHeaderAddress

 Description:
   Gets the start address of the RTP header.

 Inputs:
    zl5011xParams        Pointer to the structure for this device instance
    context             Selected context
    primaryOrSecondary  Get the address of the ZL5011X_PRIMARY_HEADER or
                        the ZL5011X_SECONDARY_HEADER header

 Outputs:
   pAddress             Start address of the header

 Returns:
   zlStatusE

 Remarks:
   None

*******************************************************************************/

extern zlStatusE zl5011xRtpGetHeaderAddress(zl5011xParamsS *zl5011xParams,
      Uint32T context,
      zl5011xContextHeaderSwitchE primaryOrSecondary,
      Uint32T *pAddress)
{
   zlStatusE status = ZL5011X_OK;

   ZL5011X_TRACE_CONTEXT(ZL5011X_RTP_FN_ID, context,
         "zl5011xRtpGetHeaderAddress: ctxt %3d, header %d",
         context, primaryOrSecondary, 0, 0, 0, 0);

   /* the primary headers are arranged one after the other from the base
      address for the headers. i.e. header(n) base = base + (n * header size) */
   *pAddress = zl5011xParams->rtp.rtpTxHeaderBaseAddress + (context * ZL5011X_RTP_HEADER_SIZE);

   /* if using the secondary header, then these are located after the
      primary headers in the memory map. So add in an offset for the total
      header size */
   if (primaryOrSecondary == ZL5011X_SECONDARY_HEADER)
   {
      *pAddress += ZL5011X_RTP_SHADOW_HEADER_OFFSET;
   }

   ZL5011X_TRACE_CONTEXT(ZL5011X_RTP_FN_ID, context,
         "zl5011xRtpGetHeaderAddress: ctxt %3d, header %d, addr 0x%08X",
         context, primaryOrSecondary, *pAddress, 0, 0, 0);

   return status;
}

/*******************************************************************************
 Function:
    zl5011xRtpGetStatisticsAddress

 Description:
   Gets the base address of the statistics for the given context.

 Inputs:
   zl5011xParams    Pointer to the structure for this device instance
   context         Selected context

 Outputs:
   address   The base address of the statistics data base held
                            within external memory.

 Returns:
  zlStatusE

 Remarks:
   None
*******************************************************************************/

extern zlStatusE  zl5011xRtpGetStatisticsAddress(zl5011xParamsS *zl5011xParams,
      Uint32T context, Uint32T *address)
{
   zlStatusE status = ZL5011X_OK;

   ZL5011X_TRACE_CONTEXT(ZL5011X_RTP_FN_ID, context,
         "zl5011xRtpGetStatisticsAddress: ctxt %d",
         context, 0, 0, 0, 0, 0);

   *address = zl5011xParams -> rtp.rtpStatsBaseAddress + (context * ZL5011X_RTP_STATS_SIZE);

   return status;
}

/*******************************************************************************
 Function:
    zl5011xRtpGetTxSeqNum

 Description:
      Returns the sequence number from the currently active RTP Tx header.
      This is the sequence number used for the last Tx packet.

 Inputs:
   zl5011xParams      pointer to the structure for this device instance
   context           selected context
   activeHeader      the header to fetch the sequence number from

 Outputs:
   seqNum            sequence number from the RTP Tx header as used for the
                     last Tx packet

 Returns:
   zlStatusE

 Remarks:
   None

*******************************************************************************/

extern zlStatusE zl5011xRtpGetTxSeqNum(zl5011xParamsS *zl5011xParams,
      Uint32T context, Uint16T *pSeqNum, zl5011xContextHeaderSwitchE activeHeader)
{
   zlStatusE status = ZL5011X_OK;
   Uint32T seqAddress;
   Uint32T position= 0;
   Uint32T shiftTemp = 0;
   Uint32T rtpData;
   Uint16T temp;

   ZL5011X_TRACE_CONTEXT(ZL5011X_RTP_FN_ID, context, "zl5011xRtpGetTxSeqNum: ctxt %3d, ",
              context, 0, 0, 0, 0, 0);

   /* get sequence number if enabled */
   if ( zl5011xParams->packetIf.packetTx.txHeader[context].highHeader[activeHeader].layer5SequenceNumEnable == ZL5011X_TRUE)
   {
      /* Get the active header address for this context */
      status = zl5011xRtpGetHeaderAddress(zl5011xParams, context, activeHeader, &seqAddress);

      if (status == ZL5011X_OK)
      {
         /* get the position of the sequence number in the header */
         position = zl5011xParams->packetIf.packetTx.txHeader[context].highHeader[activeHeader].layer5SequenceNumPos;

         /* mask off the bottom bits of the position, to get the address of a 32-bit word */
         seqAddress += position & ~ ZL5011X_2BIT_MASK;

         /* read 32-bit word containing sequence number */
         status = zl5011xRead(zl5011xParams, seqAddress, &rtpData);
      }

      if (status == ZL5011X_OK)
      {
         /* Determine the shift required within the word */
         shiftTemp = (position & ZL5011X_2BIT_MASK) * 8;

         temp = (Uint16T)((rtpData >> shiftTemp) & ZL5011X_8BIT_MASK);

         if (zl5011xParams->packetIf.packetTx.txHeader[context].highHeader[activeHeader].layer5SequenceNum16bit == ZL5011X_TRUE)
         {
            /* extract another byte for 16 bit sequence numbers */
            temp = (Uint16T)((rtpData >> (shiftTemp + 8)) & ZL5011X_8BIT_MASK) | (temp << 8);
         }

         *pSeqNum = temp;

         ZL5011X_TRACE(ZL5011X_RTP_FN_ID, "zl5011xRtpGetTxSeqNum: ctxt %3d, seq num 0x%.4X ",
              context, *pSeqNum, 0, 0, 0, 0);
      }
   }
   else  /* Seq num not enabled */
   {
      *pSeqNum = 0;
      status = ZL5011X_PKT_INCOMPATIBLE_HEADER_ERROR;

      ZL5011X_TRACE(ZL5011X_RTP_FN_ID, "zl5011xRtpGetTxSeqNum: ctxt %3d, seq num not enabled",
              context, 0, 0, 0, 0, 0);
   }

   return status;
}

/*****************   END   ****************************************************/

⌨️ 快捷键说明

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