?? zl5011xrtp.c
字號:
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 + -