📄 ixhssacccodeletchan.c
字号:
/** * @file IxHssAccCodeletChan.c * * @date 21 May 2002 * * @brief This file contains the channelised implementation of the HSS * Access Codelet. * * * @par * IXP400 SW Release version 2.3 * * -- Copyright Notice -- * * @par * Copyright (c) 2001-2005, Intel Corporation. * All rights reserved. * * @par * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Intel Corporation nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * * @par * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * * @par * -- End of Copyright Notice -- * @sa IxHssAccCodelet.h * @sa IxHssAccCodeletChan.h *//* * Put the system defined include files required. *//* * Put the user defined include files required. */#include "IxOsal.h"#include "IxHssAcc.h"#include "IxHssAccCodelet.h"#include "IxHssAccCodeletChan.h"#include "IxHssAccCodeletCom.h"#include "IxHssAccCodeletConfig.h"#if defined(__wince) && defined(IX_USE_SERCONSOLE)#include "IxSerConsole.h"#define printf ixSerPrintf#endif/* * #defines and macros used in this file. */#define MESSAGE_Q_SIZE \ (IX_HSSACC_CODELET_CHAN_RX_BUFSIZE_PERCHAN / \ IX_HSSACC_CODELET_CHAN_BYTES_PER_TS_TRIG)#define MEMSET_AND_FLUSH(s, c, n) \do { \ ixOsalMemSet (s, c, n); \ IX_OSAL_CACHE_FLUSH (s, n); \} while (0)/* * Typedefs whose scope is limited to this file. */typedef struct{ unsigned rxOffset; unsigned txOffset; unsigned numHssErrs;} CallbackParams;typedef enum{ RxCallback} MessageType;typedef struct{ MessageType type; CallbackParams params;} Message;typedef struct{ /** are we receiving non-idle data? */ BOOL receivingNonIdleData; /** channelised TX sample data - source of data for TX */ UINT8 txSampleData; /** channelised RX sample data - to verify against TX data */ UINT8 rxSampleData;} ChannelInfo;/** channelised RX buffers */typedef UINT8 (*RxBuffers) [IX_HSSACC_CODELET_CHAN_NUM_CHANS] [IX_HSSACC_CODELET_CHAN_RX_BUFSIZE_PERCHAN];/** channelised TX buffers */typedef UINT8 (*TxBuffers) [IX_HSSACC_CODELET_CHAN_NUM_CHANS] [IX_HSSACC_CODELET_CHAN_TX_LATENCY_FACTOR] [IX_HSSACC_CODELET_CHAN_BYTES_PER_SAMPLE];/** channelised TX pointer lists */typedef UINT8 *(*TxPointers) [IX_HSSACC_CODELET_CHAN_TX_LATENCY_FACTOR] [IX_HSSACC_CODELET_CHAN_NUM_CHANS];typedef struct{ IxHssAccHssPort hssPortId; IxOsalThread threadId; IxOsalSemaphore messageSem; Message messageQ[MESSAGE_Q_SIZE]; unsigned qHead; unsigned qTail; /** the last offset we TX'ed from */ int lastTxOffset; /** the last offset we RX'ed to */ int lastRxOffset; /** the next offset we will RX to */ int nextRxOffset; RxBuffers rxBuffers; TxBuffers txBuffers; TxPointers txPointers; /** set if we have a full set of samples Rx'ed */ BOOL readyToLoopback; /** for recording channelised rx callback parameters */ ChannelInfo channelInfo[IX_HSSACC_CODELET_CHAN_NUM_CHANS];} ClientInfo;/* * Variable declarations global to this file only. Externs are followed by * static variables. */static ClientInfo clientInfo [IX_HSSACC_HSS_PORT_MAX];static BOOL verify = TRUE;/* * Extern function prototypes. *//* * Static function prototypes. */PRIVATE voidixHssAccCodeletChannelisedDataSampleCreate ( IxHssAccHssPort hssPortId, unsigned channelIndex, UINT8 *sample);PRIVATE voidixHssAccCodeletChannelisedDataSampleTransmit ( IxHssAccHssPort hssPortId, unsigned channelIndex, UINT8 *sample);PRIVATE voidixHssAccCodeletChannelisedDataTransmit ( IxHssAccHssPort hssPortId, unsigned txOffset);PRIVATE voidixHssAccCodeletChannelisedDataSampleVerify ( IxHssAccHssPort hssPortId, unsigned channelIndex, UINT8 *sample);PRIVATE voidixHssAccCodeletChannelisedDataSampleReceive ( IxHssAccHssPort hssPortId, unsigned channelIndex, UINT8 *sample);PRIVATE voidixHssAccCodeletChannelisedDataReceive ( IxHssAccHssPort hssPortId, unsigned rxOffset);PRIVATE voidixHssAccCodeletChanRxCallback ( IxHssAccHssPort hssPortId, unsigned rxOffset, unsigned txOffset, unsigned numHssErrs);PRIVATE voidixHssAccCodeletChanRxCallbackProcess ( IxHssAccHssPort hssPortId, unsigned rxOffset, unsigned txOffset, unsigned numHssErrs);PRIVATE IX_STATUSixHssAccCodeletChanThreadMain ( void* arg, void** ptrRetObj);/** * @fn void ixHssAccCodeletChannelisedDataSampleCreate ( IxHssAccHssPort hssPortId, unsigned channelIndex, UINT8 *sample) * * @param IxHssAccHssPort hssPortId (in) - the HSS port ID (0 or 1). * @param unsigned channelIndex (in) - the channel (0-31) to create the * data sample for. * @param UINT8 *sample (out) - a pointer to a data sample of size * CHAN_BYTES_PER_SAMPLE. * * This function creates a data sample for the specified port/channel. The * sample is filled with an incrementing byte value. The byte value begins * as the channel number and increases with each invocation: * * <TABLE> * <TR><TD> <TD>1st Value<TD>2nd Value<TD>3rd Value<TD>...</TR> * <TR><TD>Channel 0<TD> 0x01<TD> 0x02<TD> 0x03<TD>...</TR> * <TR><TD>Channel 1<TD> 0x02<TD> 0x03<TD> 0x04<TD>...</TR> * <TR><TD>Channel 2<TD> 0x03<TD> 0x04<TD> 0x05<TD>...</TR> * <TR><TD> ...<TD> ...<TD> ...<TD> ...<TD>...</TR> * </TABLE> */PRIVATEvoidixHssAccCodeletChannelisedDataSampleCreate ( IxHssAccHssPort hssPortId, unsigned channelIndex, UINT8 *sample){ unsigned byteIndex; ClientInfo *pClientInfo = &clientInfo[hssPortId]; ChannelInfo *pChannelInfo = &pClientInfo->channelInfo[channelIndex]; /* if the codelet is acting as data source/sink */ if (!ixHssAccCodeletCodeletLoopbackGet ()) { /* for each byte in the data sample */ for (byteIndex = 0; byteIndex < IX_HSSACC_CODELET_CHAN_BYTES_PER_SAMPLE; byteIndex++) { /* get/update the value to transmit */ sample[byteIndex] = pChannelInfo->txSampleData++; } } else /* codelet is performing loopback, but nothing to loopback */ { /* transmit an idle pattern */ /* to allow for caching, we request a cache flush after memset */ MEMSET_AND_FLUSH ( sample, IX_HSSACC_CODELET_CHAN_IDLE_PATTERN, IX_HSSACC_CODELET_CHAN_BYTES_PER_SAMPLE); }}/** * @fn void ixHssAccCodeletChannelisedDataSampleTransmit ( IxHssAccHssPort hssPortId, unsigned channelIndex, UINT8 *sample) * * @param IxHssAccHssPort hssPortId (in) - the HSS port ID (0 or 1). * @param unsigned channelIndex (in) - the channel (0-31) to transmit the * data sample on. * @param UINT8 *sample (in) - a pointer to a data sample of size * CHAN_BYTES_PER_SAMPLE. * * This function transmits a data sample on the specified port/channel. It * maintains the current TX offset for each channel and stores the sample * pointer in the appropriate pointer list. This function also updates TX * statistics. */PRIVATEvoidixHssAccCodeletChannelisedDataSampleTransmit ( IxHssAccHssPort hssPortId, unsigned channelIndex, UINT8 *sample){ ClientInfo *pClientInfo = &clientInfo[hssPortId]; UINT8 *temp = NULL; /* to allow for caching, we request a cache flush before tx */ IX_OSAL_CACHE_FLUSH ( sample, IX_HSSACC_CODELET_CHAN_BYTES_PER_SAMPLE); /* update the pointer in the pointer list to point to the sample */ /* endianess conversion on txPointers */ temp = (UINT8 *) IX_OSAL_MMU_VIRT_TO_PHYS((UINT32)sample); (*pClientInfo->txPointers)[pClientInfo->lastTxOffset][channelIndex] = (UINT8 *) IX_OSAL_SWAP_BE_SHARED_LONG((UINT32) temp); IX_OSAL_CACHE_FLUSH ( &(*pClientInfo->txPointers)[pClientInfo->lastTxOffset][channelIndex], sizeof((*pClientInfo->txPointers)[pClientInfo->lastTxOffset][channelIndex])); /* update TX stats */ stats[hssPortId].chan.txSamples++; stats[hssPortId].chan.txBytes += IX_HSSACC_CODELET_CHAN_BYTES_PER_SAMPLE;}/** * @fn void ixHssAccCodeletChannelisedDataTransmit ( IxHssAccHssPort hssPortId, unsigned txOffset) * * @param IxHssAccHssPort hssPortId (in) - the HSS port ID (0 or 1). * @param unsigned txOffset (in) - an offset indicating from where within * the txPtrList the NPE is currently transmitting from or will transmit * from next. * * This function examines the txOffset parameter to determine if data needs * to be transmitted to the NPE or not. If data needs to be transmitted * then data samples are created if necessary and transmitted for each * channel. */PRIVATEvoidixHssAccCodeletChannelisedDataTransmit ( IxHssAccHssPort hssPortId, unsigned txOffset){ unsigned channelIndex; UINT8 *txSample; UINT8 *rxSample; ClientInfo *pClientInfo = &clientInfo[hssPortId]; /* the NPE tells us where it is currently transmitting from or will */ /* transmit from next. We want to update the txPtrList once we know */ /* the NPE has completed transmitted it. We can only be sure that */ /* the NPE has completed transmitted the txPtrList corresponding to */ /* (txOffset - 2), as the NPE may still be transmitting from */ /* (txOffset - 1). */ /* if we last transmitted to 2 slots prior to txOffset then we do */ /* nothing, otherwise we transmit data. In this way we will keep */ /* updating the tx data as soon as we know the NPE has finished */ /* transmitting it. */ if ((pClientInfo->lastTxOffset + 2) % (UINT32) IX_HSSACC_CODELET_CHAN_TX_LATENCY_FACTOR == txOffset) { return; } /* increment our TX offset to remember where we last transmitted to */ pClientInfo->lastTxOffset++; pClientInfo->lastTxOffset %= IX_HSSACC_CODELET_CHAN_TX_LATENCY_FACTOR; /* for each channel */ for (channelIndex = 0; channelIndex < IX_HSSACC_CODELET_CHAN_NUM_CHANS; channelIndex++) { /* get the pointer to the data sample for this offset/channel */ txSample = (*pClientInfo->txBuffers) [channelIndex][pClientInfo->lastTxOffset]; /* codelet will loop back last data samples received */ if (ixHssAccCodeletCodeletLoopbackGet () && pClientInfo->readyToLoopback) { /* get pointer to the data sample for this offset/channel */ rxSample = &(*pClientInfo->rxBuffers) [channelIndex][pClientInfo->lastRxOffset]; /* loopback rx data to tx data */ /* note: important to copy data here, if we add rx sample */ /* pointer to the tx pointer list then we are relying on the */ /* rx sample not being overwritten before sample is tx'ed */ /* - not safe when rx and tx latencies differ */ ixOsalMemCopy ( txSample, rxSample, IX_HSSACC_CODELET_CHAN_BYTES_PER_SAMPLE); } else /* we create new data to transmit */ { /* fill in the data sample */ ixHssAccCodeletChannelisedDataSampleCreate ( hssPortId, channelIndex, txSample); } /* transmit the data sample */ ixHssAccCodeletChannelisedDataSampleTransmit ( hssPortId, channelIndex, txSample); } /* for (channelIndex ... */}/** * @fn void ixHssAccCodeletChannelisedDataSampleVerify ( IxHssAccHssPort hssPortId, unsigned channelIndex, UINT8 *sample) * * @param IxHssAccHssPort hssPortId (in) - the HSS port ID (0 or 1). * @param unsigned channelIndex (in) - the channel (0-31) to verify the * data sample for. * @param UINT8 *sample (in) - a pointer to a data sample of size * CHAN_BYTES_PER_SAMPLE. * * This function verifies the contents of a data sample for the specified * port/channel. On transmit the sample is filled with an incrementing * byte value. The byte value begins as the channel number and increases * with each invocation: * * <TABLE> * <TR><TD> <TD>1st Value<TD>2nd Value<TD>3rd Value<TD>...</TR> * <TR><TD>Channel 0<TD> 0x01<TD> 0x02<TD> 0x03<TD>...</TR> * <TR><TD>Channel 1<TD> 0x02<TD> 0x03<TD> 0x04<TD>...</TR> * <TR><TD>Channel 2<TD> 0x03<TD> 0x04<TD> 0x05<TD>...</TR> * <TR><TD> ...<TD> ...<TD> ...<TD> ...<TD>...</TR> * </TABLE> */PRIVATEvoidixHssAccCodeletChannelisedDataSampleVerify ( IxHssAccHssPort hssPortId, unsigned channelIndex, UINT8 *sample){ unsigned byteIndex; UINT8 expectedValue; ClientInfo *pClientInfo = &clientInfo[hssPortId]; ChannelInfo *pChannelInfo = &pClientInfo->channelInfo[channelIndex]; IxHssAccTdmSlotUsage tsUsage = ixHssAccCodeletChannelisedTimeslotGet (channelIndex); /* if the timeslot is assigned to 56K voice then bit 7 is unused */ UINT32 mask = (tsUsage == IX_HSSACC_TDMMAP_VOICE56K ? 0x7F : 0xFF); /* for each byte in the data sample */ for (byteIndex = 0; byteIndex < IX_HSSACC_CODELET_CHAN_BYTES_PER_SAMPLE; byteIndex++) { /* if we haven't started receiving non-idle data yet */ if (!pChannelInfo->receivingNonIdleData) { /* check to see if we're receiving the idle pattern */ if ((sample[byteIndex] & mask) == (IX_HSSACC_CODELET_CHAN_IDLE_PATTERN & mask)) { stats[hssPortId].chan.rxIdles++; continue; } /* not receiving idle pattern, i.e. receiving non-idle data */ pChannelInfo->receivingNonIdleData = TRUE; } /* get/update the value we are expecting to receive */ expectedValue = pChannelInfo->rxSampleData++; /* verify that the data is as expected */ if ((sample[byteIndex] & mask) != (expectedValue & mask)) { stats[hssPortId].chan.rxVerifyFails++; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -