/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_adpcm_chan.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains functions used to open and close ADPCM channels. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 15 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "apilib/octapi_largmath.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "oct6100api/oct6100_apiud.h" #include "apilib/octapi_llman.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_channel_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_adpcm_chan_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_adpcm_chan_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_memory_priv.h" #include "oct6100_tsst_priv.h" #include "oct6100_channel_priv.h" #include "oct6100_adpcm_chan_priv.h" #include #include /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetAdpcmChanSwSizes Description: Gets the sizes of all portions of the API instance pertinent to the management of the ADPCM memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pOpenChip Pointer to chip configuration struct. f_pInstSizes Pointer to struct containing instance sizes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiGetAdpcmChanSwSizes( IN tPOCT6100_CHIP_OPEN f_pOpenChip, OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) { UINT32 ulTempVar; UINT32 ulResult; /* Determine the amount of memory required for the API ADPCM channel list.*/ f_pInstSizes->ulAdpcmChannelList = f_pOpenChip->ulMaxAdpcmChannels * sizeof( tOCT6100_API_ADPCM_CHAN ); if ( f_pOpenChip->ulMaxAdpcmChannels > 0 ) { /* Calculate memory needed for ADPCM memory allocation */ ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxAdpcmChannels, &f_pInstSizes->ulAdpcmChannelAlloc ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_48; } else { f_pInstSizes->ulAdpcmChannelAlloc = 0; } mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulAdpcmChannelList, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulAdpcmChannelAlloc, ulTempVar ) return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiAdpcmChanSwInit Description: Initializes all elements of the instance structure associated to the ADPCM memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiAdpcmChanSwInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_API_ADPCM_CHAN pChannelsTsiList; tPOCT6100_SHARED_INFO pSharedInfo; UINT32 ulMaxAdpcmChannels; PVOID pAdpcmChannelsAlloc; UINT32 ulResult; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Initialize the ADPCM channel API list.*/ ulMaxAdpcmChannels = pSharedInfo->ChipConfig.usMaxAdpcmChannels; /* Set all entries in the ADPCM channel list to unused. */ mOCT6100_GET_ADPCM_CHAN_LIST_PNT( pSharedInfo, pChannelsTsiList ) /* Clear the memory */ Oct6100UserMemSet( pChannelsTsiList, 0x00, sizeof(tOCT6100_API_ADPCM_CHAN) * ulMaxAdpcmChannels ); /* Initialize the ADPCM channel allocation structures to "all free". */ if ( ulMaxAdpcmChannels > 0 ) { mOCT6100_GET_ADPCM_CHAN_ALLOC_PNT( pSharedInfo, pAdpcmChannelsAlloc ) ulResult = OctapiLlmAllocInit( &pAdpcmChannelsAlloc, ulMaxAdpcmChannels ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_BD; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_channel.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains functions used to open, modify and close echo cancellation channels. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 449 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "oct6100api/oct6100_apiud.h" #include "apilib/octapi_llman.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_mixer_inst.h" #include "oct6100api/oct6100_tsi_cnct_inst.h" #include "oct6100api/oct6100_conf_bridge_inst.h" #include "oct6100api/oct6100_tone_detection_inst.h" #include "oct6100api/oct6100_phasing_tsst_inst.h" #include "oct6100api/oct6100_tsst_inst.h" #include "oct6100api/oct6100_channel_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100api/oct6100_tsi_cnct_pub.h" #include "oct6100api/oct6100_playout_buf_pub.h" #include "oct6100api/oct6100_phasing_tsst_pub.h" #include "oct6100api/oct6100_mixer_pub.h" #include "oct6100api/oct6100_conf_bridge_pub.h" #include "oct6100api/oct6100_tone_detection_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_memory_priv.h" #include "oct6100_tsst_priv.h" #include "oct6100_mixer_priv.h" #include "oct6100_phasing_tsst_priv.h" #include "oct6100_tsi_cnct_priv.h" #include "oct6100_playout_buf_priv.h" #include "oct6100_conf_bridge_priv.h" #include "oct6100_tone_detection_priv.h" #include "oct6100_channel_priv.h" /**************************** PUBLIC FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ChannelOpen Description: This function opens a echo cancellation channel. An echo cancellation channel is constituted of two voice stream (RIN/ROUT and SIN/SOUT), and an echo cancelling core. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelOpen Pointer to echo channel open structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ChannelOpenDef( IN OUT tPOCT6100_CHANNEL_OPEN f_pChannelOpen ) { f_pChannelOpen->pulChannelHndl = NULL; f_pChannelOpen->ulUserChanId = cOCT6100_INVALID_VALUE; f_pChannelOpen->ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_POWER_DOWN; f_pChannelOpen->fEnableToneDisabler = FALSE; f_pChannelOpen->fEnableExtToneDetection = FALSE; /* VQE configuration.*/ f_pChannelOpen->VqeConfig.fSinDcOffsetRemoval = TRUE; f_pChannelOpen->VqeConfig.fRinDcOffsetRemoval = TRUE; f_pChannelOpen->VqeConfig.fRinLevelControl = FALSE; f_pChannelOpen->VqeConfig.lRinLevelControlGainDb = 0; f_pChannelOpen->VqeConfig.fSoutLevelControl = FALSE; f_pChannelOpen->VqeConfig.lSoutLevelControlGainDb = 0; f_pChannelOpen->VqeConfig.fRinAutomaticLevelControl = FALSE; f_pChannelOpen->VqeConfig.lRinAutomaticLevelControlTargetDb = -20; f_pChannelOpen->VqeConfig.fSoutAutomaticLevelControl = FALSE; f_pChannelOpen->VqeConfig.lSoutAutomaticLevelControlTargetDb = -20; f_pChannelOpen->VqeConfig.fRinHighLevelCompensation = FALSE; f_pChannelOpen->VqeConfig.lRinHighLevelCompensationThresholdDb = -10; f_pChannelOpen->VqeConfig.fSoutAdaptiveNoiseReduction = FALSE; f_pChannelOpen->VqeConfig.fSoutNoiseBleaching = FALSE; f_pChannelOpen->VqeConfig.fSoutConferencingNoiseReduction = FALSE; f_pChannelOpen->VqeConfig.ulComfortNoiseMode = cOCT6100_COMFORT_NOISE_NORMAL; f_pChannelOpen->VqeConfig.fEnableNlp = TRUE; f_pChannelOpen->VqeConfig.fEnableTailDisplacement = FALSE; f_pChannelOpen->VqeConfig.ulTailDisplacement = cOCT6100_AUTO_SELECT_TAIL; f_pChannelOpen->VqeConfig.ulTailLength = cOCT6100_AUTO_SELECT_TAIL; f_pChannelOpen->VqeConfig.fDtmfToneRemoval = FALSE; f_pChannelOpen->VqeConfig.fAcousticEcho = FALSE; f_pChannelOpen->VqeConfig.lDefaultErlDb = -6; f_pChannelOpen->VqeConfig.ulAecTailLength = 128; f_pChannelOpen->VqeConfig.lAecDefaultErlDb = 0; f_pChannelOpen->VqeConfig.ulNonLinearityBehaviorA = 1; f_pChannelOpen->VqeConfig.ulNonLinearityBehaviorB = 0; f_pChannelOpen->VqeConfig.ulDoubleTalkBehavior = cOCT6100_DOUBLE_TALK_BEH_NORMAL; f_pChannelOpen->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = 0; f_pChannelOpen->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = 0; f_pChannelOpen->VqeConfig.fSoutNaturalListenerEnhancement = FALSE; f_pChannelOpen->VqeConfig.fRoutNoiseReduction = FALSE; f_pChannelOpen->VqeConfig.lAnrSnrEnhancementDb = -18; f_pChannelOpen->VqeConfig.ulAnrVoiceNoiseSegregation = 6; f_pChannelOpen->VqeConfig.ulToneDisablerVqeActivationDelay = 300; f_pChannelOpen->VqeConfig.fEnableMusicProtection = FALSE; /* Older images have idle code detection hard-coded to enabled. */ f_pChannelOpen->VqeConfig.fIdleCodeDetection = TRUE; /* TDM configuration.*/ f_pChannelOpen->TdmConfig.ulRinNumTssts = 1; f_pChannelOpen->TdmConfig.ulSinNumTssts = 1; f_pChannelOpen->TdmConfig.ulRoutNumTssts = 1; f_pChannelOpen->TdmConfig.ulSoutNumTssts = 1; f_pChannelOpen->TdmConfig.ulRinTimeslot = cOCT6100_UNASSIGNED; f_pChannelOpen->TdmConfig.ulRinStream = cOCT6100_UNASSIGNED; f_pChannelOpen->TdmConfig.ulRinPcmLaw = cOCT6100_PCM_U_LAW; f_pChannelOpen->TdmConfig.ulSinTimeslot = cOCT6100_UNASSIGNED; f_pChannelOpen->TdmConfig.ulSinStream = cOCT6100_UNASSIGNED; f_pChannelOpen->TdmConfig.ulSinPcmLaw = cOCT6100_PCM_U_LAW; f_pChannelOpen->TdmConfig.ulRoutTimeslot = cOCT6100_UNASSIGNED; f_pChannelOpen->TdmConfig.ulRoutStream = cOCT6100_UNASSIGNED; f_pChannelOpen->TdmConfig.ulRoutPcmLaw = cOCT6100_PCM_U_LAW; f_pChannelOpen->TdmConfig.ulSoutTimeslot = cOCT6100_UNASSIGNED; f_pChannelOpen->TdmConfig.ulSoutStream = cOCT6100_UNASSIGNED; f_pChannelOpen->TdmConfig.ulSoutPcmLaw = cOCT6100_PCM_U_LAW; /* CODEC configuration.*/ f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition = cOCT6100_ADPCM_IN_LOW_BITS; f_pChannelOpen->CodecConfig.ulEncoderPort = cOCT6100_CHANNEL_PORT_SOUT; f_pChannelOpen->CodecConfig.ulEncodingRate = cOCT6100_G711_64KBPS; f_pChannelOpen->CodecConfig.ulDecoderPort = cOCT6100_CHANNEL_PORT_RIN; f_pChannelOpen->CodecConfig.ulDecodingRate = cOCT6100_G711_64KBPS; f_pChannelOpen->CodecConfig.fEnableSilenceSuppression = FALSE; f_pChannelOpen->CodecConfig.ulPhasingTsstHndl = cOCT6100_INVALID_HANDLE; f_pChannelOpen->CodecConfig.ulPhase = 0; f_pChannelOpen->CodecConfig.ulPhasingType = cOCT6100_NO_PHASING; return cOCT6100_ERR_OK; } static UINT32 Oct6100ChannelOpen( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN OUT tPOCT6100_CHANNEL_OPEN f_pChannelOpen ) { tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; UINT32 ulSerRes = cOCT6100_ERR_OK; UINT32 ulFncRes = cOCT6100_ERR_OK; /* Set the process context of the serialize structure.*/ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; /* Seize all list semaphores needed by this function. */ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); if ( ulSerRes == cOCT6100_ERR_OK ) { /* Call the serialized function. */ ulFncRes = Oct6100ChannelOpenSer( f_pApiInstance, f_pChannelOpen ); } else { return ulSerRes; } /* Release the seized semaphores. */ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); /* If an error occured then return the error code. */ if ( ulSerRes != cOCT6100_ERR_OK ) return ulSerRes; if ( ulFncRes != cOCT6100_ERR_OK ) return ulFncRes; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ChannelModify Description: This function will modify the parameter of an echo channel. If the call to this channel allows the channel to go from power down to enable, the API will activate it. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelModify Pointer to echo channel change structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ChannelModifyDef( IN OUT tPOCT6100_CHANNEL_MODIFY f_pChannelModify ) { f_pChannelModify->ulChannelHndl = cOCT6100_INVALID_HANDLE; f_pChannelModify->ulUserChanId = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->ulEchoOperationMode = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->fEnableToneDisabler = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->fApplyToAllChannels = FALSE; f_pChannelModify->fDisableToneDetection = FALSE; f_pChannelModify->fStopBufferPlayout = FALSE; f_pChannelModify->fRemoveConfBridgeParticipant = FALSE; f_pChannelModify->fRemoveBroadcastTssts = FALSE; f_pChannelModify->fTdmConfigModified = FALSE; f_pChannelModify->fVqeConfigModified = FALSE; f_pChannelModify->fCodecConfigModified = FALSE; /* VQE config. */ f_pChannelModify->VqeConfig.fSinDcOffsetRemoval = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fRinDcOffsetRemoval = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fRinLevelControl = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.lRinLevelControlGainDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fSoutLevelControl = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.lSoutLevelControlGainDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fRinAutomaticLevelControl = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.lRinAutomaticLevelControlTargetDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fSoutAutomaticLevelControl = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.lSoutAutomaticLevelControlTargetDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fRinHighLevelCompensation = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.lRinHighLevelCompensationThresholdDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fSoutAdaptiveNoiseReduction = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fSoutNoiseBleaching = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fSoutConferencingNoiseReduction = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.ulComfortNoiseMode = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fEnableNlp = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fEnableTailDisplacement = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.ulTailDisplacement = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fDtmfToneRemoval = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fAcousticEcho = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.lDefaultErlDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.ulAecTailLength = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.lAecDefaultErlDb = (INT32)cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.ulNonLinearityBehaviorA = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.ulNonLinearityBehaviorB = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.ulDoubleTalkBehavior = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fSoutNaturalListenerEnhancement = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fRoutNoiseReduction = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.lAnrSnrEnhancementDb = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.ulAnrVoiceNoiseSegregation = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.ulToneDisablerVqeActivationDelay = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fEnableMusicProtection = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->VqeConfig.fIdleCodeDetection = cOCT6100_KEEP_PREVIOUS_SETTING; /* TDM config. */ f_pChannelModify->TdmConfig.ulRinNumTssts = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->TdmConfig.ulSinNumTssts = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->TdmConfig.ulRoutNumTssts = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->TdmConfig.ulSoutNumTssts = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->TdmConfig.ulRinTimeslot = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->TdmConfig.ulRinStream = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->TdmConfig.ulRinPcmLaw = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->TdmConfig.ulSinTimeslot = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->TdmConfig.ulSinStream = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->TdmConfig.ulSinPcmLaw = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->TdmConfig.ulRoutTimeslot = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->TdmConfig.ulRoutStream = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->TdmConfig.ulRoutPcmLaw = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->TdmConfig.ulSoutTimeslot = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->TdmConfig.ulSoutStream = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->TdmConfig.ulSoutPcmLaw = cOCT6100_KEEP_PREVIOUS_SETTING; /* CODEC config. */ f_pChannelModify->CodecConfig.ulEncoderPort = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->CodecConfig.ulEncodingRate = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->CodecConfig.ulDecoderPort = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->CodecConfig.ulDecodingRate = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->CodecConfig.fEnableSilenceSuppression = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->CodecConfig.ulPhasingTsstHndl = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->CodecConfig.ulPhase = cOCT6100_KEEP_PREVIOUS_SETTING; f_pChannelModify->CodecConfig.ulPhasingType = cOCT6100_KEEP_PREVIOUS_SETTING; return cOCT6100_ERR_OK; } static UINT32 Oct6100ChannelModify( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN OUT tPOCT6100_CHANNEL_MODIFY f_pChannelModify ) { tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; UINT32 ulSerRes = cOCT6100_ERR_OK; UINT32 ulFncRes = cOCT6100_ERR_OK; /* Set the process context of the serialize structure.*/ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; /* Seize all list semaphores needed by this function. */ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); if ( ulSerRes == cOCT6100_ERR_OK ) { /* Check the apply to all channels flag first. */ if ( f_pChannelModify->fApplyToAllChannels != TRUE && f_pChannelModify->fApplyToAllChannels != FALSE ) return cOCT6100_ERR_CHANNEL_APPLY_TO_ALL_CHANNELS; /* Check if must apply modification to all channels. */ if ( f_pChannelModify->fApplyToAllChannels == TRUE ) { tPOCT6100_API_CHANNEL pChanEntry; UINT16 usChanIndex; /* Loop through all channels and look for the opened ones. */ for ( usChanIndex = 0; usChanIndex < f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels; usChanIndex++ ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, usChanIndex ); /* Check if this one is opened. */ if ( pChanEntry->fReserved == TRUE ) { /* Channel is opened. Form handle and call actual modify function. */ f_pChannelModify->ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | usChanIndex; /* Call the serialized function. */ ulFncRes = Oct6100ChannelModifySer( f_pApiInstance, f_pChannelModify ); if ( ulFncRes != cOCT6100_ERR_OK ) break; } } } else /* if ( f_pChannelModify->fApplyToAllChannels == FALSE ) */ { /* Call the serialized function. */ ulFncRes = Oct6100ChannelModifySer( f_pApiInstance, f_pChannelModify ); } } else { return ulSerRes; } /* Release the seized semaphores. */ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); /* If an error occured then return the error code. */ if ( ulSerRes != cOCT6100_ERR_OK ) return ulSerRes; if ( ulFncRes != cOCT6100_ERR_OK ) return ulFncRes; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ChannelBroadcastTsstRemove Description: This function removes a TSST from one of the two output ports of a channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelBroadcastTsstRemove Pointer to the a Remove Broadcast TSST structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ChannelBroadcastTsstRemoveDef( tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelBroadcastTsstRemove ) { f_pChannelBroadcastTsstRemove->ulChannelHndl = cOCT6100_INVALID_HANDLE; f_pChannelBroadcastTsstRemove->ulPort = cOCT6100_INVALID_PORT; f_pChannelBroadcastTsstRemove->ulTimeslot = cOCT6100_INVALID_TIMESLOT; f_pChannelBroadcastTsstRemove->ulStream = cOCT6100_INVALID_STREAM; f_pChannelBroadcastTsstRemove->fRemoveAll = FALSE; return cOCT6100_ERR_OK; } #if 0 /* unused functions */ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ChannelMute Description: This function mutes some or all of the ports designated by ulChannelHndl. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelMute Pointer to a tPOCT6100_CHANNEL_MUTE structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ChannelMuteDef( IN OUT tPOCT6100_CHANNEL_MUTE f_pChannelMute ) { f_pChannelMute->ulChannelHndl = cOCT6100_INVALID_HANDLE; f_pChannelMute->ulPortMask = cOCT6100_CHANNEL_MUTE_PORT_NONE; return cOCT6100_ERR_OK; } static UINT32 Oct6100ChannelMute( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN OUT tPOCT6100_CHANNEL_MUTE f_pChannelMute ) { tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; UINT32 ulSerRes = cOCT6100_ERR_OK; UINT32 ulFncRes = cOCT6100_ERR_OK; /* Set the process context of the serialize structure.*/ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; /* Seize all list semaphores needed by this function. */ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); if ( ulSerRes == cOCT6100_ERR_OK ) { /* Call the serialized function. */ ulFncRes = Oct6100ChannelMuteSer( f_pApiInstance, f_pChannelMute ); } else { return ulSerRes; } /* Release the seized semaphores. */ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); /* If an error occured then return the error code. */ if ( ulSerRes != cOCT6100_ERR_OK ) return ulSerRes; if ( ulFncRes != cOCT6100_ERR_OK ) return ulFncRes; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ChannelUnMute Description: This function unmutes some or all of the ports designated by ulChannelHndl. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelUnMute Pointer to a tPOCT6100_CHANNEL_UNMUTE structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ChannelUnMuteDef( IN OUT tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute ) { f_pChannelUnMute->ulChannelHndl = cOCT6100_INVALID_HANDLE; f_pChannelUnMute->ulPortMask = cOCT6100_CHANNEL_MUTE_PORT_NONE; return cOCT6100_ERR_OK; } static UINT32 Oct6100ChannelUnMute( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN OUT tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute ) { tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; UINT32 ulSerRes = cOCT6100_ERR_OK; UINT32 ulFncRes = cOCT6100_ERR_OK; /* Set the process context of the serialize structure.*/ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; /* Seize all list semaphores needed by this function. */ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); if ( ulSerRes == cOCT6100_ERR_OK ) { /* Call the serialized function. */ ulFncRes = Oct6100ChannelUnMuteSer( f_pApiInstance, f_pChannelUnMute ); } else { return ulSerRes; } /* Release the seized semaphores. */ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); /* If an error occured then return the error code. */ if ( ulSerRes != cOCT6100_ERR_OK ) return ulSerRes; if ( ulFncRes != cOCT6100_ERR_OK ) return ulFncRes; return cOCT6100_ERR_OK; } #endif /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetChannelsEchoSwSizes Description: Gets the sizes of all portions of the API instance pertinent to the management of the ECHO memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pOpenChip Pointer to chip configuration struct. f_pInstSizes Pointer to struct containing instance sizes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiGetChannelsEchoSwSizes( IN tPOCT6100_CHIP_OPEN f_pOpenChip, OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) { UINT32 ulTempVar; UINT32 ulResult; UINT32 ulMaxChannels; ulMaxChannels = f_pOpenChip->ulMaxChannels; if ( f_pOpenChip->fEnableChannelRecording == TRUE && ulMaxChannels != 672 ) ulMaxChannels++; /* Determine the amount of memory required for the API echo channel list.*/ f_pInstSizes->ulChannelList = ulMaxChannels * sizeof( tOCT6100_API_CHANNEL ); /* Add one for the record channel.*/ f_pInstSizes->ulBiDirChannelList = f_pOpenChip->ulMaxBiDirChannels * sizeof( tOCT6100_API_BIDIR_CHANNEL ); if ( ulMaxChannels > 0 ) { /* Calculate memory needed for ECHO memory allocation */ ulResult = OctapiLlmAllocGetSize( ulMaxChannels, &f_pInstSizes->ulChannelAlloc ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_0; } else { f_pInstSizes->ulChannelAlloc = 0; } if ( f_pOpenChip->ulMaxBiDirChannels > 0 ) { /* Calculate memory needed for ECHO memory allocation */ ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxBiDirChannels, &f_pInstSizes->ulBiDirChannelAlloc ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_0; } else { f_pInstSizes->ulBiDirChannelAlloc = 0; } mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulChannelList, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulChannelAlloc, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulBiDirChannelList, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulBiDirChannelAlloc, ulTempVar ) return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiChannelsEchoSwInit Description: Initializes all elements of the instance structure associated to the ECHO memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiChannelsEchoSwInit( IN tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_API_CHANNEL pChannelsEchoList; tPOCT6100_API_BIDIR_CHANNEL pBiDirChannelsList; tPOCT6100_SHARED_INFO pSharedInfo; UINT16 usMaxChannels; PVOID pEchoChanAlloc; PVOID pBiDirChanAlloc; UINT32 ulResult; /* Get local pointer to shared portion of the API instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Initialize the ECHO channel API list.*/ usMaxChannels = pSharedInfo->ChipConfig.usMaxChannels; /* add a channel to initialize if the recording is activated. */ if ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) usMaxChannels++; /* Set all entries in the ADCPM channel list to unused. */ mOCT6100_GET_CHANNEL_LIST_PNT( pSharedInfo, pChannelsEchoList ); /* Initialize the API ECHO channels allocation software to "all free". */ if ( usMaxChannels > 0 ) { /* Clear the memory */ Oct6100UserMemSet( pChannelsEchoList, 0x00, sizeof(tOCT6100_API_CHANNEL) * usMaxChannels ); mOCT6100_GET_CHANNEL_ALLOC_PNT( pSharedInfo, pEchoChanAlloc ) ulResult = OctapiLlmAllocInit( &pEchoChanAlloc, usMaxChannels ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_1; } mOCT6100_GET_BIDIR_CHANNEL_LIST_PNT( pSharedInfo, pBiDirChannelsList ); if ( pSharedInfo->ChipConfig.usMaxBiDirChannels > 0 ) { /* Clear the memory */ Oct6100UserMemSet( pBiDirChannelsList, 0x00, sizeof(tOCT6100_API_BIDIR_CHANNEL) * pSharedInfo->ChipConfig.usMaxBiDirChannels ); mOCT6100_GET_BIDIR_CHANNEL_ALLOC_PNT( pSharedInfo, pBiDirChanAlloc ) ulResult = OctapiLlmAllocInit( &pBiDirChanAlloc, pSharedInfo->ChipConfig.usMaxBiDirChannels ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_A9; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ChannelOpenSer Description: Opens a echo cancellation channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelOpen Pointer to channel configuration structure. Then handle identifying the buffer in all future function calls is returned in this structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ChannelOpenSer( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN OUT tPOCT6100_CHANNEL_OPEN f_pChannelOpen ) { tOCT6100_API_ECHO_CHAN_INDEX ChannelIndexConf; UINT32 ulResult; /* Check the user's configuration of the echo cancellation channel for errors. */ ulResult = Oct6100ApiCheckChannelParams( f_pApiInstance, f_pChannelOpen, &ChannelIndexConf ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Reserve all resources needed by the echo cancellation channel. */ ulResult = Oct6100ApiReserveChannelResources( f_pApiInstance, f_pChannelOpen, &ChannelIndexConf ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write all necessary structures to activate the echo cancellation channel. */ ulResult = Oct6100ApiWriteChannelStructs( f_pApiInstance, f_pChannelOpen, &ChannelIndexConf ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Update the new echo cancellation channels's entry in the ECHO channel list. */ ulResult = Oct6100ApiUpdateChannelEntry( f_pApiInstance, f_pChannelOpen, &ChannelIndexConf ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiCheckChannelParams Description: Checks the user's echo cancellation channel open configuration for errors. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelOpen Pointer to echo cancellation channel open configuration structure. f_pChanIndexConf Pointer to a structure used to store the multiple resources indexes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiCheckChannelParams( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, OUT tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ) { tPOCT6100_CHANNEL_OPEN_TDM pTdmConfig; tPOCT6100_CHANNEL_OPEN_VQE pVqeConfig; tPOCT6100_CHANNEL_OPEN_CODEC pCodecConfig; UINT32 ulDecoderNumTssts; UINT32 ulResult; /* Dereference the configuration structure for clearer code and faster access.*/ pTdmConfig = &f_pChannelOpen->TdmConfig; pVqeConfig = &f_pChannelOpen->VqeConfig; pCodecConfig = &f_pChannelOpen->CodecConfig; /* Check for errors. */ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels == 0 ) return cOCT6100_ERR_CHANNEL_DISABLED; if ( f_pChannelOpen->pulChannelHndl == NULL ) return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; if ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NORMAL && f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_HT_FREEZE && f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_HT_RESET && f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_POWER_DOWN && f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_EXTERNAL && f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION && f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NO_ECHO ) return cOCT6100_ERR_CHANNEL_ECHO_OP_MODE; /* Check the 2100Hz echo disabling configuration.*/ if ( f_pChannelOpen->fEnableToneDisabler != TRUE && f_pChannelOpen->fEnableToneDisabler != FALSE ) return cOCT6100_ERR_CHANNEL_TONE_DISABLER_ENABLE; /* Check the extended Tone Detection flag value.*/ if ( f_pChannelOpen->fEnableExtToneDetection != TRUE && f_pChannelOpen->fEnableExtToneDetection != FALSE ) return cOCT6100_ERR_CHANNEL_ENABLE_EXT_TONE_DETECTION; /* Check that extented tone detection is actually enabled by the user. */ if ( ( f_pChannelOpen->fEnableExtToneDetection == TRUE ) && ( f_pApiInstance->pSharedInfo->ChipConfig.fEnableExtToneDetection == FALSE ) ) return cOCT6100_ERR_CHANNEL_EXT_TONE_DETECTION_DISABLED; /*==============================================================================*/ /* Check the TDM configuration parameters.*/ ulResult = Oct6100ApiCheckTdmConfig( f_pApiInstance, pTdmConfig ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ /*==============================================================================*/ /* Now validate the VQE parameters */ ulResult = Oct6100ApiCheckVqeConfig( f_pApiInstance, pVqeConfig, f_pChannelOpen->fEnableToneDisabler ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Verify if the echo operation mode selected can be applied. */ if ( ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) && ( pVqeConfig->fEnableNlp == FALSE ) ) return cOCT6100_ERR_CHANNEL_ECHO_OP_MODE_NLP_REQUIRED; /*==============================================================================*/ /*==============================================================================*/ /* Finally, validate the CODEC configuration.*/ if ( pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ulDecoderNumTssts = pTdmConfig->ulRinNumTssts; else /* pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ ulDecoderNumTssts = pTdmConfig->ulSinNumTssts; ulResult = Oct6100ApiCheckCodecConfig( f_pApiInstance, pCodecConfig, ulDecoderNumTssts, &f_pChanIndexConf->usPhasingTsstIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* make sure that if silence suppression is activated, the NLP is enabled.*/ if ( pCodecConfig->fEnableSilenceSuppression == TRUE && pVqeConfig->fEnableNlp == FALSE ) return cOCT6100_ERR_CHANNEL_SIL_SUP_NLP_MUST_BE_ENABLED; /* Verify if law conversion is allowed. */ if ( pCodecConfig->ulEncoderPort == cOCT6100_NO_ENCODING || pCodecConfig->ulDecoderPort == cOCT6100_NO_DECODING ) { /* No law conversion can occurs if one ADPCM memory is not reserved.*/ if ( pTdmConfig->ulRinPcmLaw != pTdmConfig->ulRoutPcmLaw ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_LAW_TRANSLATION; if ( pTdmConfig->ulSinPcmLaw != pTdmConfig->ulSoutPcmLaw ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_LAW_TRANSLATION; } /* Verify if the config supports extended tone detection.*/ if ( f_pChannelOpen->fEnableExtToneDetection == TRUE ) { if ( pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) return cOCT6100_ERR_CHANNEL_EXT_TONE_DETECTION_DECODER_PORT; } /*==============================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReserveChannelResources Description: Reserves all resources needed for the new channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelOpen Pointer to echo cancellation channel configuration structure. f_pulChannelIndex Allocated entry in ECHO channel list. f_pChanIndexConf Pointer to a structure used to store the multiple resources indexes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReserveChannelResources( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, OUT tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_CHANNEL_OPEN_TDM pTdmConfig; tPOCT6100_CHANNEL_OPEN_CODEC pCodecConfig; UINT32 ulResult; UINT32 ulTempVar; UINT32 ulFreeMixerEventCnt; BOOL fRinTsstEntry = FALSE; BOOL fSinTsstEntry = FALSE; BOOL fRoutTsstEntry = FALSE; BOOL fSoutTsstEntry = FALSE; BOOL fRinRoutTsiMemEntry = FALSE; BOOL fSinSoutTsiMemEntry = FALSE; BOOL fEchoChanEntry = FALSE; PUINT16 pusRinRoutConversionMemIndex = NULL; PUINT16 pusSinSoutConversionMemIndex = NULL; BOOL fRinRoutConversionMemEntry = FALSE; BOOL fSinSoutConversionMemEntry = FALSE; BOOL fExtToneChanEntry = FALSE; BOOL fExtToneTsiEntry = FALSE; BOOL fExtToneMixerEntry = FALSE; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Obtain a local pointer to the configuration structures.*/ pTdmConfig = &f_pChannelOpen->TdmConfig; pCodecConfig = &f_pChannelOpen->CodecConfig; /*===============================================================================*/ /* Reserve Echo and TSI entries. */ ulResult = Oct6100ApiReserveEchoEntry( f_pApiInstance, &f_pChanIndexConf->usEchoChanIndex ); if ( ulResult == cOCT6100_ERR_OK ) { fEchoChanEntry = TRUE; /* Set the echo, encoder and decoder memory indexes.*/ f_pChanIndexConf->usEchoMemIndex = f_pChanIndexConf->usEchoChanIndex; /* Reserve an entry for the RIN/ROUT tsi chariot memory. */ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, &f_pChanIndexConf->usRinRoutTsiMemIndex ); if ( ulResult == cOCT6100_ERR_OK ) { fRinRoutTsiMemEntry = TRUE; /* Reserve an entry for the SIN/SOUT tsi chariot memory. */ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, &f_pChanIndexConf->usSinSoutTsiMemIndex ); if ( ulResult == cOCT6100_ERR_OK ) { fSinSoutTsiMemEntry = TRUE; /* Reserve an ADPCM memory block for compression if required.*/ if ( pCodecConfig->ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) { pusRinRoutConversionMemIndex = &f_pChanIndexConf->usRinRoutConversionMemIndex; } else if ( pCodecConfig->ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT ) { pusSinSoutConversionMemIndex = &f_pChanIndexConf->usSinSoutConversionMemIndex; } /* Reserve an ADPCM memory block for decompression if required.*/ if ( pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) { pusRinRoutConversionMemIndex = &f_pChanIndexConf->usRinRoutConversionMemIndex; } else if ( pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN ) { pusSinSoutConversionMemIndex = &f_pChanIndexConf->usSinSoutConversionMemIndex; } /* Reserve the conversion memories. */ if ( pusRinRoutConversionMemIndex != NULL ) { /* Reserve a conversion memory for the Rin/Rout stream. */ ulResult = Oct6100ApiReserveConversionMemEntry( f_pApiInstance, pusRinRoutConversionMemIndex ); if ( ulResult == cOCT6100_ERR_OK ) { fRinRoutConversionMemEntry = TRUE; } } else { /* No conversion memory reserved.*/ f_pChanIndexConf->usRinRoutConversionMemIndex = cOCT6100_INVALID_INDEX; } if ( ( pusSinSoutConversionMemIndex != NULL ) && ( ulResult == cOCT6100_ERR_OK ) ) { /* Reserve a conversion memory for the Sin/Sout stream. */ ulResult = Oct6100ApiReserveConversionMemEntry( f_pApiInstance, pusSinSoutConversionMemIndex ); if ( ulResult == cOCT6100_ERR_OK ) { fSinSoutConversionMemEntry = TRUE; } } else { /* No conversion memory reserved.*/ f_pChanIndexConf->usSinSoutConversionMemIndex = cOCT6100_INVALID_INDEX; } /* Reserve any resources required if the extended Tone detection is enabled.*/ if ( f_pChannelOpen->fEnableExtToneDetection == TRUE ) { ulResult = Oct6100ApiReserveEchoEntry( f_pApiInstance, &f_pChanIndexConf->usExtToneChanIndex ); if ( ulResult == cOCT6100_ERR_OK ) { fExtToneChanEntry = TRUE; /* Reserve an entry for the TSI chariot memory for the additionnal channel. */ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, &f_pChanIndexConf->usExtToneTsiIndex ); if ( ulResult == cOCT6100_ERR_OK ) { fExtToneTsiEntry = TRUE; /* Reserve an entry for the TSI chariot memory for the additionnal channel. */ ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &f_pChanIndexConf->usExtToneMixerIndex ); if ( ulResult == cOCT6100_ERR_OK ) fExtToneMixerEntry = TRUE; } } } else { f_pChanIndexConf->usExtToneChanIndex = cOCT6100_INVALID_INDEX; f_pChanIndexConf->usExtToneMixerIndex = cOCT6100_INVALID_INDEX; f_pChanIndexConf->usExtToneTsiIndex = cOCT6100_INVALID_INDEX; } } else { /* Return an error other then a Fatal.*/ ulResult = cOCT6100_ERR_CHANNEL_OUT_OF_TSI_MEMORY; } } else { /* Return an error other then a Fatal.*/ ulResult = cOCT6100_ERR_CHANNEL_OUT_OF_TSI_MEMORY; } } /*===============================================================================*/ /*===============================================================================*/ /* Now reserve the TSST entries if required.*/ /* Reserve the Rin TSST entry */ if ( (ulResult == cOCT6100_ERR_OK ) && (pTdmConfig->ulRinTimeslot != cOCT6100_UNASSIGNED && pTdmConfig->ulRinStream != cOCT6100_UNASSIGNED) ) { ulResult = Oct6100ApiReserveTsst( f_pApiInstance, pTdmConfig->ulRinTimeslot, pTdmConfig->ulRinStream, pTdmConfig->ulRinNumTssts, cOCT6100_INPUT_TSST, &f_pChanIndexConf->usRinTsstIndex, NULL ); if ( ulResult == cOCT6100_ERR_OK ) fRinTsstEntry = TRUE; } else { f_pChanIndexConf->usRinTsstIndex = cOCT6100_INVALID_INDEX; } if ( (ulResult == cOCT6100_ERR_OK ) && (pTdmConfig->ulSinTimeslot != cOCT6100_UNASSIGNED && pTdmConfig->ulSinStream != cOCT6100_UNASSIGNED) ) { /* Reserve the Sin TSST entry.*/ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, pTdmConfig->ulSinTimeslot, pTdmConfig->ulSinStream, pTdmConfig->ulSinNumTssts, cOCT6100_INPUT_TSST, &f_pChanIndexConf->usSinTsstIndex, NULL ); if ( ulResult == cOCT6100_ERR_OK ) fSinTsstEntry = TRUE; } else { f_pChanIndexConf->usSinTsstIndex = cOCT6100_INVALID_INDEX; } if ( (ulResult == cOCT6100_ERR_OK ) && (pTdmConfig->ulRoutTimeslot != cOCT6100_UNASSIGNED && pTdmConfig->ulRoutStream != cOCT6100_UNASSIGNED) ) { /* Reserve the Rout TSST entry.*/ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, pTdmConfig->ulRoutTimeslot, pTdmConfig->ulRoutStream, pTdmConfig->ulRoutNumTssts, cOCT6100_OUTPUT_TSST, &f_pChanIndexConf->usRoutTsstIndex, NULL ); if ( ulResult == cOCT6100_ERR_OK ) fRoutTsstEntry = TRUE; } else { f_pChanIndexConf->usRoutTsstIndex = cOCT6100_INVALID_INDEX; } if ( (ulResult == cOCT6100_ERR_OK ) && (pTdmConfig->ulSoutTimeslot != cOCT6100_UNASSIGNED && pTdmConfig->ulSoutStream != cOCT6100_UNASSIGNED) ) { /* Reserve the Sout TSST entry.*/ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, pTdmConfig->ulSoutTimeslot, pTdmConfig->ulSoutStream, pTdmConfig->ulSoutNumTssts, cOCT6100_OUTPUT_TSST, &f_pChanIndexConf->usSoutTsstIndex, NULL ); if ( ulResult == cOCT6100_ERR_OK ) fSoutTsstEntry = TRUE; } else { f_pChanIndexConf->usSoutTsstIndex = cOCT6100_INVALID_INDEX; } /*===============================================================================*/ /*===============================================================================*/ /* Check if there are a couple of mixer events available for us. */ if ( ulResult == cOCT6100_ERR_OK ) { UINT32 ulMixerEventCntNeeded = 0; /* Calculate how many mixer events are needed. */ if ( f_pChanIndexConf->usRinTsstIndex == cOCT6100_INVALID_INDEX ) ulMixerEventCntNeeded++; if ( f_pChanIndexConf->usSinTsstIndex == cOCT6100_INVALID_INDEX ) ulMixerEventCntNeeded++; /* If at least 1 mixer event is needed, check if those are available. */ if ( ulMixerEventCntNeeded != 0 ) { ulResult = Oct6100ApiGetFreeMixerEventCnt( f_pApiInstance, &ulFreeMixerEventCnt ); if ( ulResult == cOCT6100_ERR_OK ) { /* The API might need more mixer events if the ports have to be muted. */ /* Check if these are available. */ if ( ulFreeMixerEventCnt < ulMixerEventCntNeeded ) { ulResult = cOCT6100_ERR_CHANNEL_OUT_OF_MIXER_EVENTS; } } } } /*===============================================================================*/ /*===============================================================================*/ /* Release the resources if something went wrong */ if ( ulResult != cOCT6100_ERR_OK ) { /*===============================================================================*/ /* Release the previously reserved resources .*/ if( fRinTsstEntry == TRUE ) { ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, pTdmConfig->ulRinTimeslot, pTdmConfig->ulRinStream, pTdmConfig->ulRinNumTssts, cOCT6100_INPUT_TSST, cOCT6100_INVALID_INDEX ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } if( fSinTsstEntry == TRUE ) { ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, pTdmConfig->ulSinTimeslot, pTdmConfig->ulSinStream, pTdmConfig->ulSinNumTssts, cOCT6100_INPUT_TSST, cOCT6100_INVALID_INDEX ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } if( fRoutTsstEntry == TRUE ) { ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, pTdmConfig->ulRoutTimeslot, pTdmConfig->ulRoutStream, pTdmConfig->ulRoutNumTssts, cOCT6100_OUTPUT_TSST, cOCT6100_INVALID_INDEX ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } if( fSoutTsstEntry == TRUE ) { ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, pTdmConfig->ulSoutTimeslot, pTdmConfig->ulSoutStream, pTdmConfig->ulSoutNumTssts, cOCT6100_OUTPUT_TSST, cOCT6100_INVALID_INDEX ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } if( fRinRoutTsiMemEntry == TRUE ) { ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, f_pChanIndexConf->usRinRoutTsiMemIndex ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } if( fSinSoutTsiMemEntry == TRUE ) { ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, f_pChanIndexConf->usSinSoutTsiMemIndex ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } /*===============================================================================*/ /*===============================================================================*/ /* Release the previously reserved echo resources .*/ if( fEchoChanEntry == TRUE ) { ulTempVar = Oct6100ApiReleaseEchoEntry( f_pApiInstance, f_pChanIndexConf->usEchoChanIndex ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } /*===============================================================================*/ /*===============================================================================*/ /* Release the previously reserved resources for the extended tone detection.*/ if( fExtToneChanEntry == TRUE ) { ulTempVar = Oct6100ApiReleaseEchoEntry( f_pApiInstance, f_pChanIndexConf->usExtToneChanIndex ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } if( fExtToneTsiEntry == TRUE ) { ulTempVar = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, f_pChanIndexConf->usExtToneTsiIndex ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } if( fExtToneMixerEntry == TRUE ) { ulTempVar = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_pChanIndexConf->usExtToneMixerIndex ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } /*===============================================================================*/ /*===============================================================================*/ /* Release the conversion resources. */ if( fRinRoutConversionMemEntry == TRUE ) { ulTempVar = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, f_pChanIndexConf->usRinRoutConversionMemIndex ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } if( fSinSoutConversionMemEntry == TRUE ) { ulTempVar = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, f_pChanIndexConf->usSinSoutConversionMemIndex ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } /*===============================================================================*/ return ulResult; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteChannelStructs Description: Performs all the required structure writes to configure the new echo cancellation channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelOpen Pointer to echo cancellation channel configuration structure. f_pChanIndexConf Pointer to a structure used to store the multiple resources indexes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWriteChannelStructs( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, OUT tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_CHANNEL_OPEN_TDM pTdmConfig; tOCT6100_WRITE_PARAMS WriteParams; tPOCT6100_API_CHANNEL pChanEntry; UINT32 ulResult; UINT32 ulDwordAddress; UINT32 ulDwordData; BOOL fConversionEnabled = FALSE; BOOL fProgramAdpcmMem; UINT32 ulCompType = 0; UINT32 ulPcmLaw; UINT16 usTempTsiMemIndex; UINT16 usConversionMemIndex; UINT32 ulToneEventNumber; BOOL fSSTone; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Obtain a local pointer to the TDM configuration structure.*/ pTdmConfig = &f_pChannelOpen->TdmConfig; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_pChanIndexConf->usEchoChanIndex ); /*==============================================================================*/ /* Configure the Tsst control memory.*/ /* Set the RIN Tsst control entry.*/ if ( f_pChanIndexConf->usRinTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, f_pChanIndexConf->usRinTsstIndex, f_pChanIndexConf->usRinRoutTsiMemIndex, pTdmConfig->ulRinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Set the ROUT Tsst control entry.*/ if ( f_pChanIndexConf->usRoutTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, f_pChanIndexConf->usRoutTsstIndex, f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition, pTdmConfig->ulRoutNumTssts, f_pChanIndexConf->usRinRoutTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Set the SIN Tsst control entry.*/ if ( f_pChanIndexConf->usSinTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, f_pChanIndexConf->usSinTsstIndex, f_pChanIndexConf->usSinSoutTsiMemIndex, pTdmConfig->ulSinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Set the SOUT Tsst control entry.*/ if ( f_pChanIndexConf->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, f_pChanIndexConf->usSoutTsstIndex, f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition, pTdmConfig->ulSoutNumTssts, f_pChanIndexConf->usSinSoutTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*==============================================================================*/ /*==============================================================================*/ /* Configure the ADPCM control memory for the Decoder.*/ /* Set the codec state flags.*/ f_pChanIndexConf->fRinRoutCodecActive = FALSE; f_pChanIndexConf->fSinSoutCodecActive = FALSE; if ( f_pChannelOpen->CodecConfig.ulDecoderPort != cOCT6100_NO_DECODING ) { fProgramAdpcmMem = TRUE; switch( f_pChannelOpen->CodecConfig.ulDecodingRate ) { case cOCT6100_G711_64KBPS: ulCompType = 0x8; if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) { if ( pTdmConfig->ulRinPcmLaw == pTdmConfig->ulRoutPcmLaw ) fProgramAdpcmMem = FALSE; } else /* f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ { if ( f_pChannelOpen->TdmConfig.ulSinPcmLaw == f_pChannelOpen->TdmConfig.ulSoutPcmLaw ) fProgramAdpcmMem = FALSE; } break; case cOCT6100_G726_40KBPS: ulCompType = 0x3; fConversionEnabled = TRUE; break; case cOCT6100_G726_32KBPS: ulCompType = 0x2; fConversionEnabled = TRUE; break; case cOCT6100_G726_24KBPS: ulCompType = 0x1; fConversionEnabled = TRUE; break; case cOCT6100_G726_16KBPS: ulCompType = 0x0; fConversionEnabled = TRUE; break; case cOCT6100_G727_2C_ENCODED: ulCompType = 0x4; fConversionEnabled = TRUE; break; case cOCT6100_G727_3C_ENCODED: ulCompType = 0x5; fConversionEnabled = TRUE; break; case cOCT6100_G727_4C_ENCODED: ulCompType = 0x6; fConversionEnabled = TRUE; break; case cOCT6100_G726_ENCODED: ulCompType = 0x9; fConversionEnabled = TRUE; break; case cOCT6100_G711_G726_ENCODED: ulCompType = 0xA; fConversionEnabled = TRUE; break; case cOCT6100_G711_G727_2C_ENCODED: ulCompType = 0xC; fConversionEnabled = TRUE; break; case cOCT6100_G711_G727_3C_ENCODED: ulCompType = 0xD; fConversionEnabled = TRUE; break; case cOCT6100_G711_G727_4C_ENCODED: ulCompType = 0xE; fConversionEnabled = TRUE; break; default: return cOCT6100_ERR_FATAL_D4; } if ( fProgramAdpcmMem == TRUE ) { /* Set the chariot memory based on the selected port.*/ if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) { usTempTsiMemIndex = f_pChanIndexConf->usRinRoutTsiMemIndex; ulPcmLaw = pTdmConfig->ulRoutPcmLaw; /* Set the law for later use */ /* Set the codec state flags.*/ f_pChanIndexConf->fRinRoutCodecActive = TRUE; /* Set the conversion memory index to use for decompression */ usConversionMemIndex = f_pChanIndexConf->usRinRoutConversionMemIndex; } else /* f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ { usTempTsiMemIndex = f_pChanIndexConf->usSinSoutTsiMemIndex; ulPcmLaw = pTdmConfig->ulSoutPcmLaw; /* Set the law for later use */ /* Set the codec state flags.*/ f_pChanIndexConf->fSinSoutCodecActive = TRUE; /* Set the conversion memory index to use for decompression */ usConversionMemIndex = f_pChanIndexConf->usSinSoutConversionMemIndex; } ulResult = Oct6100ApiWriteDecoderMemory( f_pApiInstance, usConversionMemIndex, ulCompType, usTempTsiMemIndex, ulPcmLaw, f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /*==============================================================================*/ /*==============================================================================*/ /* Configure the ADPCM control memory for the Encoder */ if ( f_pChannelOpen->CodecConfig.ulEncoderPort != cOCT6100_NO_ENCODING ) { fProgramAdpcmMem = TRUE; switch( f_pChannelOpen->CodecConfig.ulEncodingRate ) { case cOCT6100_G711_64KBPS: if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) { if ( pTdmConfig->ulRoutPcmLaw == cOCT6100_PCM_U_LAW ) ulCompType = 0x4; else ulCompType = 0x5; /* Check for law conversion.*/ if ( pTdmConfig->ulRinPcmLaw == pTdmConfig->ulRoutPcmLaw ) fProgramAdpcmMem = FALSE; } else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ { if ( pTdmConfig->ulSoutPcmLaw == cOCT6100_PCM_U_LAW ) ulCompType = 0x4; else ulCompType = 0x5; /* Check for law conversion.*/ if ( pTdmConfig->ulSinPcmLaw == pTdmConfig->ulSoutPcmLaw ) fProgramAdpcmMem = FALSE; } break; case cOCT6100_G726_40KBPS: ulCompType = 0x3; fConversionEnabled = TRUE; break; case cOCT6100_G726_32KBPS: ulCompType = 0x2; fConversionEnabled = TRUE; break; case cOCT6100_G726_24KBPS: ulCompType = 0x1; fConversionEnabled = TRUE; break; case cOCT6100_G726_16KBPS: ulCompType = 0x0; fConversionEnabled = TRUE; break; case cOCT6100_G727_40KBPS_4_1: ulCompType = 0xD; fConversionEnabled = TRUE; break; case cOCT6100_G727_40KBPS_3_2: ulCompType = 0xA; fConversionEnabled = TRUE; break; case cOCT6100_G727_40KBPS_2_3: ulCompType = 0x6; fConversionEnabled = TRUE; break; case cOCT6100_G727_32KBPS_4_0: ulCompType = 0xE; fConversionEnabled = TRUE; break; case cOCT6100_G727_32KBPS_3_1: ulCompType = 0xB; fConversionEnabled = TRUE; break; case cOCT6100_G727_32KBPS_2_2: ulCompType = 0x7; fConversionEnabled = TRUE; break; case cOCT6100_G727_24KBPS_3_0: ulCompType = 0xC; fConversionEnabled = TRUE; break; case cOCT6100_G727_24KBPS_2_1: ulCompType = 0x8; fConversionEnabled = TRUE; break; case cOCT6100_G727_16KBPS_2_0: ulCompType = 0x9; fConversionEnabled = TRUE; break; default: return cOCT6100_ERR_FATAL_D5; } /* Program the APDCM memory only if ADPCM is requried.*/ if ( fProgramAdpcmMem == TRUE || f_pChanIndexConf->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) { /* Set the chariot memory based on the selected port.*/ if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) { usTempTsiMemIndex = f_pChanIndexConf->usRinRoutTsiMemIndex; /* Set the codec state flags.*/ f_pChanIndexConf->fRinRoutCodecActive = TRUE; /* Set the conversion memory index to use for compression */ usConversionMemIndex = f_pChanIndexConf->usRinRoutConversionMemIndex; } else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ { usTempTsiMemIndex = f_pChanIndexConf->usSinSoutTsiMemIndex; /* Set the codec state flags.*/ f_pChanIndexConf->fSinSoutCodecActive = TRUE; /* Set the conversion memory index to use for compression */ usConversionMemIndex = f_pChanIndexConf->usSinSoutConversionMemIndex; } ulResult = Oct6100ApiWriteEncoderMemory( f_pApiInstance, usConversionMemIndex, ulCompType, usTempTsiMemIndex, f_pChannelOpen->CodecConfig.fEnableSilenceSuppression, f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition, f_pChanIndexConf->usPhasingTsstIndex, f_pChannelOpen->CodecConfig.ulPhasingType, f_pChannelOpen->CodecConfig.ulPhase ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /*==============================================================================*/ /*==============================================================================*/ /* Clearing the tone events bit vector */ ulDwordAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_pChanIndexConf->usEchoChanIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ); ulDwordAddress += cOCT6100_CH_MAIN_TONE_EVENT_OFFSET; ulDwordData = 0x00000000; ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulDwordAddress, ulDwordData ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulDwordAddress += 4; ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulDwordAddress, ulDwordData ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ /*==============================================================================*/ /* Write the VQE memory */ ulResult = Oct6100ApiWriteVqeMemory( f_pApiInstance, &f_pChannelOpen->VqeConfig, f_pChannelOpen, f_pChanIndexConf->usEchoChanIndex, f_pChanIndexConf->usEchoMemIndex, TRUE, FALSE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ /*==============================================================================*/ /* Write the echo memory */ ulResult = Oct6100ApiWriteEchoMemory( f_pApiInstance, pTdmConfig, f_pChannelOpen, f_pChanIndexConf->usEchoMemIndex, f_pChanIndexConf->usRinRoutTsiMemIndex, f_pChanIndexConf->usSinSoutTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ /*==============================================================================*/ /* Mute channel if required, this is done on a port basis */ /* Initialize the silence indexes to invalid for now. */ pChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; pChanEntry->usSinSilenceEventIndex = cOCT6100_INVALID_INDEX; /* Set the TSI memory indexes. */ pChanEntry->usRinRoutTsiMemIndex = f_pChanIndexConf->usRinRoutTsiMemIndex; pChanEntry->usSinSoutTsiMemIndex = f_pChanIndexConf->usSinSoutTsiMemIndex; ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_pChanIndexConf->usEchoChanIndex, f_pChanIndexConf->usRinTsstIndex, f_pChanIndexConf->usSinTsstIndex, FALSE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ /*==============================================================================*/ /* Set the dominant speaker to unassigned, if required. */ if ( f_pApiInstance->pSharedInfo->ImageInfo.fDominantSpeakerEnabled == TRUE ) { ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_pChanIndexConf->usEchoChanIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*==============================================================================*/ /*==============================================================================*/ /* If necessary, configure the extended tone detection channel.*/ if ( f_pChannelOpen->fEnableExtToneDetection == TRUE ) { UINT32 ulTempSinLaw; UINT32 ulTempSoutLaw; UINT32 ulTempEchoOpMode; /* save the original law.*/ ulTempSinLaw = pTdmConfig->ulSinPcmLaw; ulTempSoutLaw = pTdmConfig->ulSoutPcmLaw; ulTempEchoOpMode = f_pChannelOpen->ulEchoOperationMode; /* Now, make sure the Sin and Sout law are the same as the Rin law.*/ pTdmConfig->ulSinPcmLaw = pTdmConfig->ulRinPcmLaw; pTdmConfig->ulSoutPcmLaw = pTdmConfig->ulRinPcmLaw; f_pChannelOpen->ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_NORMAL; /* Write the Echo and VQE memory of the extended channel.*/ ulResult = Oct6100ApiWriteDebugChanMemory( f_pApiInstance, pTdmConfig, &f_pChannelOpen->VqeConfig, f_pChannelOpen, f_pChanIndexConf->usExtToneChanIndex, f_pChanIndexConf->usExtToneChanIndex, cOCT6100_API_EXT_TONE_EXTRA_TSI, f_pChanIndexConf->usExtToneTsiIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Now, write the mixer event used to copy the RIN signal of the original channel into the SIN signal of the exteded channel. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_pChanIndexConf->usExtToneMixerIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; WriteParams.usWriteData |= f_pChanIndexConf->usRinRoutTsiMemIndex; WriteParams.usWriteData |= pTdmConfig->ulRinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = f_pChanIndexConf->usExtToneTsiIndex; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* Now insert the Sin copy event into the list.*/ ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, f_pChanIndexConf->usExtToneMixerIndex, cOCT6100_EVENT_TYPE_SIN_COPY, f_pChanIndexConf->usEchoChanIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*==============================================================================*/ /* Clearing the tone events bit vector */ ulDwordAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_pChanIndexConf->usExtToneChanIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ); ulDwordAddress += cOCT6100_CH_MAIN_TONE_EVENT_OFFSET; ulDwordData = 0x00000000; ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulDwordAddress, ulDwordData ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulDwordAddress += 4; ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulDwordAddress, ulDwordData ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ /* Write back the original values in the channel open structure.*/ pTdmConfig->ulSinPcmLaw = ulTempSinLaw; pTdmConfig->ulSoutPcmLaw = ulTempSoutLaw; f_pChannelOpen->ulEchoOperationMode = ulTempEchoOpMode; } /*==============================================================================*/ /*==============================================================================*/ /* If necessary, configure the SS tone detection. */ for ( ulToneEventNumber = 0; ulToneEventNumber < cOCT6100_MAX_TONE_EVENT; ulToneEventNumber++ ) { /* Check if the current tone is a SS tone. */ ulResult = Oct6100ApiIsSSTone( f_pApiInstance, f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulToneID, &fSSTone ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( fSSTone == TRUE ) { /* Write to all resources needed to activate tone detection on this SS tone. */ ulResult = Oct6100ApiWriteToneDetectEvent( f_pApiInstance, f_pChanIndexConf->usEchoChanIndex, ulToneEventNumber, cOCT6100_INVALID_INDEX ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /*==============================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiUpdateChannelEntry Description: Updates the new channel in the ECHO channel list. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelOpen Pointer to echo cancellation channel configuration structure. f_pChanIndexConf Pointer to a structure used to store the multiple resources indexes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiUpdateChannelEntry( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, OUT tPOCT6100_API_ECHO_CHAN_INDEX f_pChanIndexConf ) { tPOCT6100_API_CHANNEL pChanEntry; tPOCT6100_CHANNEL_OPEN_TDM pTdmConfig; tPOCT6100_CHANNEL_OPEN_VQE pVqeConfig; tPOCT6100_CHANNEL_OPEN_CODEC pCodecConfig; /* Obtain a pointer to the config structures of the tPOCT6100_CHANNEL_OPEN structure. */ pTdmConfig = &f_pChannelOpen->TdmConfig; pVqeConfig = &f_pChannelOpen->VqeConfig; pCodecConfig = &f_pChannelOpen->CodecConfig; /* Obtain a pointer to the new buffer's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_pChanIndexConf->usEchoChanIndex ) /*=======================================================================*/ /* Copy the channel's configuration and allocated resources. */ pChanEntry->ulUserChanId = f_pChannelOpen->ulUserChanId; pChanEntry->byEchoOperationMode = (UINT8)( f_pChannelOpen->ulEchoOperationMode & 0xFF ); pChanEntry->fEnableToneDisabler = (UINT8)( f_pChannelOpen->fEnableToneDisabler & 0xFF ); pChanEntry->fEnableExtToneDetection = (UINT8)( f_pChannelOpen->fEnableExtToneDetection & 0xFF ); /* Save the VQE configuration.*/ pChanEntry->VqeConfig.byComfortNoiseMode = (UINT8)( pVqeConfig->ulComfortNoiseMode & 0xFF ); pChanEntry->VqeConfig.fEnableNlp = (UINT8)( pVqeConfig->fEnableNlp & 0xFF ); pChanEntry->VqeConfig.fEnableTailDisplacement = (UINT8)( pVqeConfig->fEnableTailDisplacement ); pChanEntry->VqeConfig.usTailDisplacement = (UINT16)( pVqeConfig->ulTailDisplacement & 0xFFFF ); pChanEntry->VqeConfig.usTailLength = (UINT16)( pVqeConfig->ulTailLength & 0xFFFF ); pChanEntry->VqeConfig.fSinDcOffsetRemoval = (UINT8)( pVqeConfig->fSinDcOffsetRemoval & 0xFF ); pChanEntry->VqeConfig.fRinDcOffsetRemoval = (UINT8)( pVqeConfig->fRinDcOffsetRemoval & 0xFF ); pChanEntry->VqeConfig.fRinLevelControl = (UINT8)( pVqeConfig->fRinLevelControl & 0xFF ); pChanEntry->VqeConfig.chRinLevelControlGainDb = (INT8)( pVqeConfig->lRinLevelControlGainDb & 0xFF ); pChanEntry->VqeConfig.fSoutLevelControl = (UINT8)( pVqeConfig->fSoutLevelControl & 0xFF ); pChanEntry->VqeConfig.chSoutLevelControlGainDb = (INT8)( pVqeConfig->lSoutLevelControlGainDb & 0xFF ); pChanEntry->VqeConfig.fRinAutomaticLevelControl = (UINT8)( pVqeConfig->fRinAutomaticLevelControl & 0xFF ); pChanEntry->VqeConfig.chRinAutomaticLevelControlTargetDb = (INT8)( pVqeConfig->lRinAutomaticLevelControlTargetDb & 0xFF ); pChanEntry->VqeConfig.fSoutAutomaticLevelControl = (UINT8)( pVqeConfig->fSoutAutomaticLevelControl & 0xFF ); pChanEntry->VqeConfig.chSoutAutomaticLevelControlTargetDb = (INT8)( pVqeConfig->lSoutAutomaticLevelControlTargetDb & 0xFF ); pChanEntry->VqeConfig.fRinHighLevelCompensation = (UINT8)( pVqeConfig->fRinHighLevelCompensation & 0xFF ); pChanEntry->VqeConfig.chRinHighLevelCompensationThresholdDb = (INT8)( pVqeConfig->lRinHighLevelCompensationThresholdDb & 0xFF ); pChanEntry->VqeConfig.fSoutAdaptiveNoiseReduction = (UINT8)( pVqeConfig->fSoutAdaptiveNoiseReduction & 0xFF ); pChanEntry->VqeConfig.fSoutNoiseBleaching = (UINT8)( pVqeConfig->fSoutNoiseBleaching & 0xFF ); pChanEntry->VqeConfig.fSoutConferencingNoiseReduction = (UINT8)( pVqeConfig->fSoutConferencingNoiseReduction & 0xFF ); pChanEntry->VqeConfig.fAcousticEcho = (UINT8)( pVqeConfig->fAcousticEcho & 0xFF ); pChanEntry->VqeConfig.fDtmfToneRemoval = (UINT8)( pVqeConfig->fDtmfToneRemoval & 0xFF ); pChanEntry->VqeConfig.chDefaultErlDb = (INT8)( pVqeConfig->lDefaultErlDb & 0xFF ); pChanEntry->VqeConfig.chAecDefaultErlDb = (INT8)( pVqeConfig->lAecDefaultErlDb & 0xFF ); pChanEntry->VqeConfig.usAecTailLength = (UINT16)( pVqeConfig->ulAecTailLength & 0xFFFF ); pChanEntry->VqeConfig.byNonLinearityBehaviorA = (UINT8)( pVqeConfig->ulNonLinearityBehaviorA & 0xFF ); pChanEntry->VqeConfig.byNonLinearityBehaviorB = (UINT8)( pVqeConfig->ulNonLinearityBehaviorB & 0xFF ); pChanEntry->VqeConfig.byDoubleTalkBehavior = (UINT8)( pVqeConfig->ulDoubleTalkBehavior & 0xFF ); pChanEntry->VqeConfig.chAnrSnrEnhancementDb = (INT8)( pVqeConfig->lAnrSnrEnhancementDb & 0xFF ); pChanEntry->VqeConfig.byAnrVoiceNoiseSegregation = (UINT8)( pVqeConfig->ulAnrVoiceNoiseSegregation & 0xFF ); pChanEntry->VqeConfig.usToneDisablerVqeActivationDelay = (UINT16)( pVqeConfig->ulToneDisablerVqeActivationDelay & 0xFFFF ); pChanEntry->VqeConfig.bySoutAutomaticListenerEnhancementGainDb = (UINT8)( pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb & 0xFF ); pChanEntry->VqeConfig.bySoutNaturalListenerEnhancementGainDb = (UINT8)( pVqeConfig->ulSoutNaturalListenerEnhancementGainDb & 0xFF ); pChanEntry->VqeConfig.fSoutNaturalListenerEnhancement = (UINT8)( pVqeConfig->fSoutNaturalListenerEnhancement & 0xFF ); pChanEntry->VqeConfig.fRoutNoiseReduction = (UINT8)( pVqeConfig->fRoutNoiseReduction & 0xFF ); pChanEntry->VqeConfig.fEnableMusicProtection = (UINT8)( pVqeConfig->fEnableMusicProtection & 0xFF ); pChanEntry->VqeConfig.fIdleCodeDetection = (UINT8)( pVqeConfig->fIdleCodeDetection & 0xFF ); /* Save the codec information.*/ pChanEntry->CodecConfig.byAdpcmNibblePosition = (UINT8)( pCodecConfig->ulAdpcmNibblePosition & 0xFF ); pChanEntry->CodecConfig.byDecoderPort = (UINT8)( pCodecConfig->ulDecoderPort & 0xFF ); pChanEntry->CodecConfig.byDecodingRate = (UINT8)( pCodecConfig->ulDecodingRate & 0xFF ); pChanEntry->CodecConfig.byEncoderPort = (UINT8)( pCodecConfig->ulEncoderPort & 0xFF ); pChanEntry->CodecConfig.byEncodingRate = (UINT8)( pCodecConfig->ulEncodingRate & 0xFF ); pChanEntry->CodecConfig.fEnableSilenceSuppression = (UINT8)( pCodecConfig->fEnableSilenceSuppression & 0xFF ); pChanEntry->CodecConfig.byPhase = (UINT8)( pCodecConfig->ulPhase & 0xFF ); pChanEntry->CodecConfig.byPhasingType = (UINT8)( pCodecConfig->ulPhasingType & 0xFF ); /* Save the RIN settings.*/ pChanEntry->TdmConfig.byRinPcmLaw = (UINT8)( pTdmConfig->ulRinPcmLaw & 0xFF ); pChanEntry->TdmConfig.usRinTimeslot = (UINT16)( pTdmConfig->ulRinTimeslot & 0xFFFF ); pChanEntry->TdmConfig.usRinStream = (UINT16)( pTdmConfig->ulRinStream & 0xFFFF ); /* Save the SIN settings.*/ pChanEntry->TdmConfig.bySinPcmLaw = (UINT8)( pTdmConfig->ulSinPcmLaw & 0xFF ); pChanEntry->TdmConfig.usSinTimeslot = (UINT16)( pTdmConfig->ulSinTimeslot & 0xFFFF ); pChanEntry->TdmConfig.usSinStream = (UINT16)( pTdmConfig->ulSinStream & 0xFFFF ); /* Save the ROUT settings.*/ pChanEntry->TdmConfig.byRoutPcmLaw = (UINT8)( pTdmConfig->ulRoutPcmLaw & 0xFF ); pChanEntry->TdmConfig.usRoutTimeslot = (UINT16)( pTdmConfig->ulRoutTimeslot & 0xFFFF ); pChanEntry->TdmConfig.usRoutStream = (UINT16)( pTdmConfig->ulRoutStream & 0xFFFF ); pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry = cOCT6100_INVALID_INDEX; pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry = 0; /* Save the SOUT settings.*/ pChanEntry->TdmConfig.bySoutPcmLaw = (UINT8)( pTdmConfig->ulSoutPcmLaw & 0xFF ); pChanEntry->TdmConfig.usSoutTimeslot = (UINT16)( pTdmConfig->ulSoutTimeslot & 0xFFFF ); pChanEntry->TdmConfig.usSoutStream = (UINT16)( pTdmConfig->ulSoutStream & 0xFFFF ); pChanEntry->TdmConfig.byRinNumTssts = (UINT8)( pTdmConfig->ulRinNumTssts & 0xFF ); pChanEntry->TdmConfig.bySinNumTssts = (UINT8)( pTdmConfig->ulSinNumTssts & 0xFF ); pChanEntry->TdmConfig.byRoutNumTssts = (UINT8)( pTdmConfig->ulRoutNumTssts & 0xFF ); pChanEntry->TdmConfig.bySoutNumTssts = (UINT8)( pTdmConfig->ulSoutNumTssts & 0xFF ); pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry = cOCT6100_INVALID_INDEX; pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry = 0; /* Save the extended Tone detection information.*/ pChanEntry->usExtToneChanIndex = f_pChanIndexConf->usExtToneChanIndex; pChanEntry->usExtToneMixerIndex = f_pChanIndexConf->usExtToneMixerIndex; pChanEntry->usExtToneTsiIndex = f_pChanIndexConf->usExtToneTsiIndex; if ( f_pChannelOpen->fEnableExtToneDetection == TRUE ) { tPOCT6100_API_CHANNEL pExtToneChanEntry; /* Set the mode of the original channel. He is the channel performing detection on the SIN port. The extended channel will perform detection on the RIN port.*/ pChanEntry->ulExtToneChanMode = cOCT6100_API_EXT_TONE_SIN_PORT_MODE; /* Now, program the associated channel.*/ /* Obtain a pointer to the extended tone detection channel entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pExtToneChanEntry, f_pChanIndexConf->usExtToneChanIndex ); pExtToneChanEntry->fReserved = TRUE; pExtToneChanEntry->ulExtToneChanMode = cOCT6100_API_EXT_TONE_RIN_PORT_MODE; /* Detect on RIN port.*/ pExtToneChanEntry->usExtToneChanIndex = f_pChanIndexConf->usEchoChanIndex; pExtToneChanEntry->aulToneConf[ 0 ] = 0; pExtToneChanEntry->aulToneConf[ 1 ] = 0; } else { /* No extended tone detection supported.*/ pChanEntry->ulExtToneChanMode = cOCT6100_API_EXT_TONE_DISABLED; } /*=======================================================================*/ /*=======================================================================*/ /* Store hardware related information.*/ pChanEntry->usRinRoutTsiMemIndex = f_pChanIndexConf->usRinRoutTsiMemIndex; pChanEntry->usSinSoutTsiMemIndex = f_pChanIndexConf->usSinSoutTsiMemIndex; pChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; pChanEntry->usExtraRinTsiMemIndex = cOCT6100_INVALID_INDEX; /* We are not being tapped for now. */ pChanEntry->fBeingTapped = FALSE; pChanEntry->usTapChanIndex = cOCT6100_INVALID_INDEX; pChanEntry->usTapBridgeIndex = cOCT6100_INVALID_INDEX; /* The copy event has not yet been created. */ pChanEntry->fCopyEventCreated = FALSE; pChanEntry->usRinRoutConversionMemIndex = f_pChanIndexConf->usRinRoutConversionMemIndex; pChanEntry->usSinSoutConversionMemIndex = f_pChanIndexConf->usSinSoutConversionMemIndex; pChanEntry->usPhasingTsstIndex = f_pChanIndexConf->usPhasingTsstIndex; pChanEntry->fSinSoutCodecActive = f_pChanIndexConf->fSinSoutCodecActive; pChanEntry->fRinRoutCodecActive = f_pChanIndexConf->fRinRoutCodecActive; pChanEntry->usEchoMemIndex = f_pChanIndexConf->usEchoMemIndex; pChanEntry->usRinTsstIndex = f_pChanIndexConf->usRinTsstIndex; pChanEntry->usSinTsstIndex = f_pChanIndexConf->usSinTsstIndex; pChanEntry->usRoutTsstIndex = f_pChanIndexConf->usRoutTsstIndex; pChanEntry->usSoutTsstIndex = f_pChanIndexConf->usSoutTsstIndex; pChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; pChanEntry->usSoutCopyEventIndex = cOCT6100_INVALID_INDEX; /* Nothing muted for now. */ pChanEntry->usMutedPorts = cOCT6100_CHANNEL_MUTE_PORT_NONE; /* Set all the GW feature initial value.*/ /* Bridge info */ pChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; pChanEntry->fMute = FALSE; pChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX; pChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX; /* Buffer playout info.*/ pChanEntry->fRinBufPlaying = FALSE; pChanEntry->fSoutBufPlaying = FALSE; /* Tone detection state. */ /* This array is configured as follow.*/ /* Index 0 contain event 0 to 31 (msb = event 31) and Index 1 contain index 32 - 55 */ pChanEntry->aulToneConf[ 0 ] = 0; pChanEntry->aulToneConf[ 1 ] = 0; pChanEntry->ulLastSSToneDetected = cOCT6100_INVALID_VALUE; pChanEntry->ulLastSSToneTimestamp = cOCT6100_INVALID_VALUE; /* Initialize the bidirectional flag.*/ pChanEntry->fBiDirChannel = FALSE; /*=======================================================================*/ /* Init some of the stats.*/ pChanEntry->sMaxERL = cOCT6100_INVALID_SIGNED_STAT_W; pChanEntry->sMaxERLE = cOCT6100_INVALID_SIGNED_STAT_W; pChanEntry->usMaxEchoDelay = cOCT6100_INVALID_STAT_W; pChanEntry->usNumEchoPathChangesOfst = 0; /*=======================================================================*/ /*=======================================================================*/ /* Update the dependency of the phasing TSST if one is associated to the chanel.*/ if ( f_pChanIndexConf->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) { tPOCT6100_API_PHASING_TSST pPhasingEntry; mOCT6100_GET_PHASING_TSST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPhasingEntry, f_pChanIndexConf->usPhasingTsstIndex ); pPhasingEntry->usDependencyCnt++; } /*=======================================================================*/ /*=======================================================================*/ /* Form handle returned to user. */ *f_pChannelOpen->pulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | (pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_pChanIndexConf->usEchoChanIndex; /* Finally, mark the channel as open. */ pChanEntry->fReserved = TRUE; pChanEntry->usExtraSinTsiDependencyCnt = 0; /* Increment the number of channel open.*/ f_pApiInstance->pSharedInfo->ChipStats.usNumberChannels++; /*=======================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ChannelModifySer Description: Modify an echo cancellation channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelModify Pointer to channel configuration structure. The handle identifying the buffer in all future function calls is returned in this structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ChannelModifySer( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN OUT tPOCT6100_CHANNEL_MODIFY f_pChannelModify ) { UINT16 usChanIndex; UINT32 ulResult; UINT16 usNewRinTsstIndex; UINT16 usNewSinTsstIndex; UINT16 usNewRoutTsstIndex; UINT16 usNewSoutTsstIndex; UINT8 fSinSoutCodecActive = FALSE; UINT8 fRinRoutCodecActive = FALSE; UINT16 usNewPhasingTsstIndex; tOCT6100_CHANNEL_OPEN *pTempChanOpen; /* We don't want this 290 byte structure on the stack */ pTempChanOpen = (tOCT6100_CHANNEL_OPEN *)kmalloc(sizeof(tOCT6100_CHANNEL_OPEN),GFP_ATOMIC); if(!pTempChanOpen) return cOCT6100_ERR_CHANNEL_NOT_OPEN; /* Check the user's configuration of the echo cancellation channel for errors. */ ulResult = Oct6100ApiCheckChannelModify( f_pApiInstance, f_pChannelModify, pTempChanOpen, &usNewPhasingTsstIndex, &usChanIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Reserve all resources needed by the echo cancellation channel. */ ulResult = Oct6100ApiModifyChannelResources( f_pApiInstance, f_pChannelModify, usChanIndex, &usNewRinTsstIndex, &usNewSinTsstIndex, &usNewRoutTsstIndex, &usNewSoutTsstIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write all necessary structures to activate the echo cancellation channel. */ ulResult = Oct6100ApiModifyChannelStructs( f_pApiInstance, f_pChannelModify, pTempChanOpen, usChanIndex, usNewPhasingTsstIndex, &fSinSoutCodecActive, &fRinRoutCodecActive, usNewRinTsstIndex, usNewSinTsstIndex, usNewRoutTsstIndex, usNewSoutTsstIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Update the new echo cancellation channels's entry in the ECHO channel list. */ ulResult = Oct6100ApiModifyChannelEntry( f_pApiInstance, f_pChannelModify, pTempChanOpen, usChanIndex, usNewPhasingTsstIndex, fSinSoutCodecActive, fRinRoutCodecActive, usNewRinTsstIndex, usNewSinTsstIndex, usNewRoutTsstIndex, usNewSoutTsstIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; kfree(pTempChanOpen); return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiCheckChannelModify Description: Checks the user's echo cancellation channel modify structure for errors. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelModify Pointer to echo cancellation channel modify structure. f_pTempChanOpen Pointer to a channel open structure. f_pusNewPhasingTsstIndex Pointer to a new phasing TSST index within the API instance. f_pusChanIndex Pointer to the channel index within the API instance channel list \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiCheckChannelModify( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN OUT tPOCT6100_CHANNEL_MODIFY f_pChannelModify, IN tPOCT6100_CHANNEL_OPEN f_pTempChanOpen, OUT PUINT16 f_pusNewPhasingTsstIndex, OUT PUINT16 f_pusChanIndex ) { tPOCT6100_API_CHANNEL pChanEntry; UINT32 ulResult; UINT32 ulEntryOpenCnt; UINT32 ulDecoderNumTssts; /* Check the provided handle. */ if ( (f_pChannelModify->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; *f_pusChanIndex = (UINT16)( f_pChannelModify->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); if ( *f_pusChanIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; /*=======================================================================*/ /* Get a pointer to the channel's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, *f_pusChanIndex ) /* Extract the entry open count from the provided handle. */ ulEntryOpenCnt = ( f_pChannelModify->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; /* Check for errors. */ if ( pChanEntry->fReserved != TRUE ) return cOCT6100_ERR_CHANNEL_NOT_OPEN; if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; /*=======================================================================*/ /*=======================================================================*/ /* Check the general modify parameters. */ if ( f_pChannelModify->ulEchoOperationMode != cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NORMAL && f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_HT_FREEZE && f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_HT_RESET && f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_POWER_DOWN && f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_EXTERNAL && f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION && f_pChannelModify->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NO_ECHO ) return cOCT6100_ERR_CHANNEL_ECHO_OP_MODE; /* Check the 2100Hz echo disabling configuration.*/ if ( f_pChannelModify->fEnableToneDisabler != cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->fEnableToneDisabler != TRUE && f_pChannelModify->fEnableToneDisabler != FALSE ) return cOCT6100_ERR_CHANNEL_TONE_DISABLER_ENABLE; /* Check the disable tone detection flag. */ if ( f_pChannelModify->fDisableToneDetection != TRUE && f_pChannelModify->fDisableToneDetection != FALSE ) return cOCT6100_ERR_CHANNEL_DISABLE_TONE_DETECTION; /* Check the stop buffer playout flag. */ if ( f_pChannelModify->fStopBufferPlayout != TRUE && f_pChannelModify->fStopBufferPlayout != FALSE ) return cOCT6100_ERR_CHANNEL_STOP_BUFFER_PLAYOUT; /* Check the remove conference bridge participant flag. */ if ( f_pChannelModify->fRemoveConfBridgeParticipant != TRUE && f_pChannelModify->fRemoveConfBridgeParticipant != FALSE ) return cOCT6100_ERR_CHANNEL_REMOVE_CONF_BRIDGE_PARTICIPANT; /* Check the remove broadcast timeslots flag. */ if ( f_pChannelModify->fRemoveBroadcastTssts != TRUE && f_pChannelModify->fRemoveBroadcastTssts != FALSE ) return cOCT6100_ERR_CHANNEL_REMOVE_BROADCAST_TSSTS; if ( f_pChannelModify->fCodecConfigModified != TRUE && f_pChannelModify->fCodecConfigModified != FALSE ) return cOCT6100_ERR_CHANNEL_MODIFY_CODEC_CONFIG; if ( f_pChannelModify->fVqeConfigModified != TRUE && f_pChannelModify->fVqeConfigModified != FALSE ) return cOCT6100_ERR_CHANNEL_MODIFY_VQE_CONFIG; if ( f_pChannelModify->fTdmConfigModified != TRUE && f_pChannelModify->fTdmConfigModified != FALSE ) return cOCT6100_ERR_CHANNEL_MODIFY_TDM_CONFIG; /*=======================================================================*/ /*=======================================================================*/ /* Verify if any law change was requested. If so reprogram all structures.*/ if (( f_pChannelModify->fTdmConfigModified == TRUE ) && ( f_pChannelModify->TdmConfig.ulRinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || f_pChannelModify->TdmConfig.ulSinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || f_pChannelModify->TdmConfig.ulRoutPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || f_pChannelModify->TdmConfig.ulSoutPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING )) { f_pChannelModify->fVqeConfigModified = TRUE; f_pChannelModify->fCodecConfigModified = TRUE; } /*=======================================================================*/ ulResult = Oct6100ApiUpdateOpenStruct( f_pApiInstance, f_pChannelModify, f_pTempChanOpen, pChanEntry ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* All further check will now be performed using the TempOpenChan structure in order to reuse the checks written for the open channel structure.*/ /* Check the TDM config.*/ if ( f_pChannelModify->fTdmConfigModified == TRUE ) { tPOCT6100_CHANNEL_MODIFY_TDM pModifyTdm; tPOCT6100_CHANNEL_OPEN_TDM pOpenTdm; pModifyTdm = &f_pChannelModify->TdmConfig; pOpenTdm = &f_pTempChanOpen->TdmConfig; ulResult = Oct6100ApiCheckTdmConfig( f_pApiInstance, pOpenTdm ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check if that Stream and Timeslot values are valid.*/ /* Check the RIN port.*/ if ( f_pChannelModify->TdmConfig.ulRinStream == cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) return cOCT6100_ERR_CHANNEL_RIN_TIMESLOT; if ( f_pChannelModify->TdmConfig.ulRinStream != cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->TdmConfig.ulRinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) return cOCT6100_ERR_CHANNEL_RIN_STREAM; if ( pChanEntry->fBeingTapped == TRUE ) { /* Check that the Rin stream + timeslot are not being assigned. */ if ( f_pChannelModify->TdmConfig.ulRinStream != cOCT6100_KEEP_PREVIOUS_SETTING ) { if ( f_pChannelModify->TdmConfig.ulRinStream != cOCT6100_UNASSIGNED ) return cOCT6100_ERR_CHANNEL_RIN_STREAM; if ( f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_UNASSIGNED ) return cOCT6100_ERR_CHANNEL_RIN_TIMESLOT; } } /* Check the SIN port.*/ if ( f_pChannelModify->TdmConfig.ulSinStream == cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->TdmConfig.ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) return cOCT6100_ERR_CHANNEL_SIN_TIMESLOT; if ( f_pChannelModify->TdmConfig.ulSinStream != cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->TdmConfig.ulSinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) return cOCT6100_ERR_CHANNEL_SIN_STREAM; /* Check the ROUT port.*/ if ( f_pChannelModify->TdmConfig.ulRoutStream == cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->TdmConfig.ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) return cOCT6100_ERR_CHANNEL_ROUT_TIMESLOT; if ( f_pChannelModify->TdmConfig.ulRoutStream != cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->TdmConfig.ulRoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) return cOCT6100_ERR_CHANNEL_ROUT_STREAM; /* Check the SOUT port.*/ if ( f_pChannelModify->TdmConfig.ulSoutStream == cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->TdmConfig.ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) return cOCT6100_ERR_CHANNEL_SOUT_TIMESLOT; if ( f_pChannelModify->TdmConfig.ulSoutStream != cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->TdmConfig.ulSoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) return cOCT6100_ERR_CHANNEL_SOUT_STREAM; /* Verify if the channel is currently part of a bidirectional channel, and if */ /* so perform the required checks. */ if ( pChanEntry->fBiDirChannel == TRUE ) { /* Check the ports that must remain unassigned.*/ if ( f_pTempChanOpen->TdmConfig.ulRinTimeslot != cOCT6100_UNASSIGNED ) return cOCT6100_ERR_CHANNEL_RIN_TIMESLOT; if ( f_pTempChanOpen->TdmConfig.ulSoutTimeslot != cOCT6100_UNASSIGNED ) return cOCT6100_ERR_CHANNEL_SOUT_TIMESLOT; /* Check that no PCM law change is requested.*/ if ( f_pTempChanOpen->TdmConfig.ulRinPcmLaw != f_pTempChanOpen->TdmConfig.ulRoutPcmLaw ) return cOCT6100_ERR_CHANNEL_RIN_ROUT_LAW_CONVERSION; if ( f_pTempChanOpen->TdmConfig.ulSinPcmLaw != f_pTempChanOpen->TdmConfig.ulSoutPcmLaw ) return cOCT6100_ERR_CHANNEL_SIN_SOUT_LAW_CONVERSION; } /* If this channel is on a conference bridge, a few more things must be checked. */ if ( pChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX ) { /* If conferencing, law conversion cannot be applied. */ /* This check is done only if both input and output ports are assigned. */ if ( ( f_pTempChanOpen->TdmConfig.ulRinTimeslot != cOCT6100_UNASSIGNED ) && ( f_pTempChanOpen->TdmConfig.ulRoutTimeslot != cOCT6100_UNASSIGNED ) ) { /* Laws must be the same! */ if ( f_pTempChanOpen->TdmConfig.ulRinPcmLaw != f_pTempChanOpen->TdmConfig.ulRoutPcmLaw ) return cOCT6100_ERR_CHANNEL_RIN_ROUT_LAW_CONVERSION; } /* Check for Sin. */ if ( ( f_pTempChanOpen->TdmConfig.ulSinTimeslot != cOCT6100_UNASSIGNED ) && ( f_pTempChanOpen->TdmConfig.ulSoutTimeslot != cOCT6100_UNASSIGNED ) ) { /* Laws must be the same! */ if ( f_pTempChanOpen->TdmConfig.ulSinPcmLaw != f_pTempChanOpen->TdmConfig.ulSoutPcmLaw ) return cOCT6100_ERR_CHANNEL_SIN_SOUT_LAW_CONVERSION; } /* Check if ADPCM is requested. */ if ( f_pTempChanOpen->CodecConfig.ulEncoderPort != cOCT6100_NO_ENCODING && f_pTempChanOpen->CodecConfig.ulEncodingRate != cOCT6100_G711_64KBPS ) { /* No ADPCM in a conference bridge! */ return cOCT6100_ERR_CHANNEL_ENCODING_RATE; } if ( f_pTempChanOpen->CodecConfig.ulDecoderPort != cOCT6100_NO_DECODING && f_pTempChanOpen->CodecConfig.ulDecodingRate != cOCT6100_G711_64KBPS ) { /* No ADPCM in a conference bridge! */ return cOCT6100_ERR_CHANNEL_DECODING_RATE; } } if ( f_pTempChanOpen->CodecConfig.ulEncoderPort == cOCT6100_NO_ENCODING || f_pTempChanOpen->CodecConfig.ulDecoderPort == cOCT6100_NO_DECODING ) { /* Make sure no law conversion is attempted since it is not supported by the device.*/ if ( f_pTempChanOpen->TdmConfig.ulRinPcmLaw != f_pTempChanOpen->TdmConfig.ulRoutPcmLaw ) return cOCT6100_ERR_CHANNEL_RIN_ROUT_LAW_CONVERSION; if ( f_pTempChanOpen->TdmConfig.ulSinPcmLaw != f_pTempChanOpen->TdmConfig.ulSoutPcmLaw ) return cOCT6100_ERR_CHANNEL_SIN_SOUT_LAW_CONVERSION; } if ( pChanEntry->fEnableExtToneDetection == TRUE && f_pTempChanOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) return cOCT6100_ERR_CHANNEL_EXT_TONE_DETECTION_DECODER_PORT; /* A few special checks must be done if the configuration is to be applied */ /* to all opened channels. */ if ( f_pChannelModify->fApplyToAllChannels == TRUE ) { /* When the configuration to be applied is for all channels, */ /* check that the stream and timeslot parameters are not being assigned. */ /* Check the Rout port. */ if ( f_pChannelModify->TdmConfig.ulRoutStream != cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->TdmConfig.ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) { /* Check that the Rout ports is being unassigned. */ if ( f_pTempChanOpen->TdmConfig.ulRoutStream != cOCT6100_UNASSIGNED ) return cOCT6100_ERR_CHANNEL_ROUT_STREAM_UNASSIGN; if ( f_pTempChanOpen->TdmConfig.ulRoutTimeslot != cOCT6100_UNASSIGNED ) return cOCT6100_ERR_CHANNEL_ROUT_TIMESLOT_UNASSIGN; } /* Check the Rin port. */ if ( f_pChannelModify->TdmConfig.ulRinStream != cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) { /* Check that the Rin ports is being unassigned. */ if ( f_pTempChanOpen->TdmConfig.ulRinStream != cOCT6100_UNASSIGNED ) return cOCT6100_ERR_CHANNEL_RIN_STREAM_UNASSIGN; if ( f_pTempChanOpen->TdmConfig.ulRinTimeslot != cOCT6100_UNASSIGNED ) return cOCT6100_ERR_CHANNEL_RIN_TIMESLOT_UNASSIGN; } /* Check the Sout port. */ if ( f_pChannelModify->TdmConfig.ulSoutStream != cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->TdmConfig.ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) { /* Check that the Sout ports is being unassigned. */ if ( f_pTempChanOpen->TdmConfig.ulSoutStream != cOCT6100_UNASSIGNED ) return cOCT6100_ERR_CHANNEL_SOUT_STREAM_UNASSIGN; if ( f_pTempChanOpen->TdmConfig.ulSoutTimeslot != cOCT6100_UNASSIGNED ) return cOCT6100_ERR_CHANNEL_SOUT_TIMESLOT_UNASSIGN; } /* Check the Sin port. */ if ( f_pChannelModify->TdmConfig.ulSinStream != cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->TdmConfig.ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) { /* Check that the Sin ports is being unassigned. */ if ( f_pTempChanOpen->TdmConfig.ulSinStream != cOCT6100_UNASSIGNED ) return cOCT6100_ERR_CHANNEL_SIN_STREAM_UNASSIGN; if ( f_pTempChanOpen->TdmConfig.ulSinTimeslot != cOCT6100_UNASSIGNED ) return cOCT6100_ERR_CHANNEL_SIN_TIMESLOT_UNASSIGN; } } } /* Check the VQE config.*/ if ( f_pChannelModify->fVqeConfigModified == TRUE ) { ulResult = Oct6100ApiCheckVqeConfig( f_pApiInstance, &f_pTempChanOpen->VqeConfig, f_pTempChanOpen->fEnableToneDisabler ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Verify if the echo operation mode selected can be applied. */ if ( ( f_pTempChanOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) && ( f_pTempChanOpen->VqeConfig.fEnableNlp == FALSE ) ) return cOCT6100_ERR_CHANNEL_ECHO_OP_MODE_NLP_REQUIRED; /* Check the Codec config.*/ if ( f_pChannelModify->fCodecConfigModified == TRUE ) { if ( f_pTempChanOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ulDecoderNumTssts = f_pTempChanOpen->TdmConfig.ulRinNumTssts; else /* f_pTempChanOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ ulDecoderNumTssts = f_pTempChanOpen->TdmConfig.ulSinNumTssts; ulResult = Oct6100ApiCheckCodecConfig( f_pApiInstance, &f_pTempChanOpen->CodecConfig, ulDecoderNumTssts, f_pusNewPhasingTsstIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* make sure that if silence suppression is activated, the NLP is enabled.*/ if ( f_pTempChanOpen->CodecConfig.fEnableSilenceSuppression == TRUE && f_pTempChanOpen->VqeConfig.fEnableNlp == FALSE ) return cOCT6100_ERR_CHANNEL_SIL_SUP_NLP_MUST_BE_ENABLED; /* Verify if the channel is currently part of a bidirectional channel, and if so perform the required checks.*/ if ( pChanEntry->fBiDirChannel == TRUE ) { /* Check the ports that must remain unassigned.*/ if ( f_pTempChanOpen->CodecConfig.ulEncoderPort != cOCT6100_NO_ENCODING && f_pTempChanOpen->CodecConfig.ulEncodingRate != cOCT6100_G711_64KBPS ) return cOCT6100_ERR_CHANNEL_ENCODING_RATE; if ( f_pTempChanOpen->CodecConfig.ulDecoderPort != cOCT6100_NO_DECODING && f_pTempChanOpen->CodecConfig.ulDecodingRate != cOCT6100_G711_64KBPS ) return cOCT6100_ERR_CHANNEL_DECODING_RATE; } } /*=======================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiModifyChannelResources Description: Reserves any new resources needed for the channel ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelModify Pointer to echo cancellation channel configuration structure. f_usChanIndex Allocated entry in ECHO channel list. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiModifyChannelResources( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_MODIFY f_pChannelModify, IN UINT16 f_usChanIndex, OUT PUINT16 f_pusNewRinTsstIndex, OUT PUINT16 f_pusNewSinTsstIndex, OUT PUINT16 f_pusNewRoutTsstIndex, OUT PUINT16 f_pusNewSoutTsstIndex ) { tPOCT6100_API_CHANNEL pChanEntry; tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHANNEL_TDM pApiTdmConf; tPOCT6100_CHANNEL_MODIFY_TDM pModifyTdmConf; UINT32 ulResult = cOCT6100_ERR_OK; UINT32 ulTempVar = cOCT6100_ERR_OK; UINT32 ulFreeMixerEventCnt; BOOL fRinReleased = FALSE; BOOL fSinReleased = FALSE; BOOL fRoutReleased = FALSE; BOOL fSoutReleased = FALSE; BOOL fRinReserved = FALSE; BOOL fSinReserved = FALSE; BOOL fRoutReserved = FALSE; BOOL fSoutReserved = FALSE; BOOL fReserveRin = FALSE; BOOL fReserveSin = FALSE; BOOL fReserveRout = FALSE; BOOL fReserveSout = FALSE; BOOL fRinRoutConversionMemReserved = FALSE; BOOL fSinSoutConversionMemReserved = FALSE; UINT32 ulRinNumTssts = 1; UINT32 ulSinNumTssts = 1; UINT32 ulRoutNumTssts = 1; UINT32 ulSoutNumTssts = 1; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Obtain local pointer to the TDM configuration structure of the tPOCT6100_CHANNEL_MODIFY structure. */ pModifyTdmConf = &f_pChannelModify->TdmConfig; /*=======================================================================*/ /* Get a pointer to the channel's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) /* Obtain local pointer to the TDM configuration structure of the tPOCT6100_API_CHANNEL structure. */ pApiTdmConf = &pChanEntry->TdmConfig; /*===============================================================================*/ /* Modify TSST resources if required.*/ if ( f_pChannelModify->fTdmConfigModified == TRUE ) { /* First release any entry that need to be released.*/ if ( ( pModifyTdmConf->ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) || ( pModifyTdmConf->ulRinNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) ) { if ( pChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) { /* Release the previously reserved entry.*/ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, pChanEntry->TdmConfig.usRinTimeslot, pChanEntry->TdmConfig.usRinStream, pChanEntry->TdmConfig.byRinNumTssts, cOCT6100_INPUT_TSST, cOCT6100_INVALID_INDEX ); if ( ulResult == cOCT6100_ERR_OK ) { fRinReleased = TRUE; } } fReserveRin = TRUE; } /* Release SIN port.*/ if ( ( ulResult == cOCT6100_ERR_OK ) && ( ( pModifyTdmConf->ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) || ( pModifyTdmConf->ulSinNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) ) ) { if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) { /* Release the previously reserved entry.*/ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, pChanEntry->TdmConfig.usSinTimeslot, pChanEntry->TdmConfig.usSinStream, pChanEntry->TdmConfig.bySinNumTssts, cOCT6100_INPUT_TSST, cOCT6100_INVALID_INDEX ); if ( ulResult == cOCT6100_ERR_OK ) { fSinReleased = TRUE; } } fReserveSin = TRUE; } /* Release ROUT port.*/ if ( ( ulResult == cOCT6100_ERR_OK ) && ( ( pModifyTdmConf->ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) || ( pModifyTdmConf->ulRoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) ) ) { if ( pChanEntry->usRoutTsstIndex != cOCT6100_INVALID_INDEX ) { /* Release the previously reserved entry.*/ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, pChanEntry->TdmConfig.usRoutTimeslot, pChanEntry->TdmConfig.usRoutStream, pChanEntry->TdmConfig.byRoutNumTssts, cOCT6100_OUTPUT_TSST, cOCT6100_INVALID_INDEX ); if ( ulResult == cOCT6100_ERR_OK ) { fRoutReleased = TRUE; } } fReserveRout = TRUE; } /* Release the SOUT port.*/ if ( ( ulResult == cOCT6100_ERR_OK ) && ( ( pModifyTdmConf->ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) || ( pModifyTdmConf->ulSoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) ) ) { if ( pChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) { /* Release the previously reserved entry.*/ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, pChanEntry->TdmConfig.usSoutTimeslot, pChanEntry->TdmConfig.usSoutStream, pChanEntry->TdmConfig.bySoutNumTssts, cOCT6100_OUTPUT_TSST, cOCT6100_INVALID_INDEX ); if ( ulResult == cOCT6100_ERR_OK ) { fSoutReleased = TRUE; } } fReserveSout = TRUE; } /* Now reserve any new entry required.*/ /* Modify RIN port.*/ if ( ( fReserveRin == TRUE ) && ( ulResult == cOCT6100_ERR_OK ) ) { if ( pModifyTdmConf->ulRinTimeslot != cOCT6100_UNASSIGNED ) { /* Check what number of TSSTs should be reserved this time. */ if ( pModifyTdmConf->ulRinNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) { ulRinNumTssts = pApiTdmConf->byRinNumTssts; } else /* if ( pModifyTdmConf->ulRinNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) */ { /* New number of TSSTs. */ ulRinNumTssts = pModifyTdmConf->ulRinNumTssts; } if ( pModifyTdmConf->ulRinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) { /* Reserve the new number of TSSTs. */ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, pApiTdmConf->usRinTimeslot, pApiTdmConf->usRinStream, ulRinNumTssts, cOCT6100_INPUT_TSST, f_pusNewRinTsstIndex, NULL ); } else /* if ( pModifyTdmConf->ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) */ { /* Reserve the new TSST.*/ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, pModifyTdmConf->ulRinTimeslot, pModifyTdmConf->ulRinStream, ulRinNumTssts, cOCT6100_INPUT_TSST, f_pusNewRinTsstIndex, NULL ); if ( ulResult == cOCT6100_ERR_OK ) { fRinReserved = TRUE; } } } else { *f_pusNewRinTsstIndex = cOCT6100_INVALID_INDEX; } } else { *f_pusNewRinTsstIndex = cOCT6100_INVALID_INDEX; } /* Modify SIN port.*/ if ( ( fReserveSin == TRUE ) && ( ulResult == cOCT6100_ERR_OK ) ) { if ( pModifyTdmConf->ulSinTimeslot != cOCT6100_UNASSIGNED ) { /* Check what number of TSSTs should be reserved this time. */ if ( pModifyTdmConf->ulSinNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) { ulSinNumTssts = pApiTdmConf->bySinNumTssts; } else /* if ( pModifyTdmConf->ulSinNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) */ { /* New number of TSSTs. */ ulSinNumTssts = pModifyTdmConf->ulSinNumTssts; } if ( pModifyTdmConf->ulSinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) { /* Reserve the new number of TSSTs. */ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, pApiTdmConf->usSinTimeslot, pApiTdmConf->usSinStream, ulSinNumTssts, cOCT6100_INPUT_TSST, f_pusNewSinTsstIndex, NULL ); } else /* if ( pModifyTdmConf->ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) */ { /* Reserve the new TSST.*/ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, pModifyTdmConf->ulSinTimeslot, pModifyTdmConf->ulSinStream, ulSinNumTssts, cOCT6100_INPUT_TSST, f_pusNewSinTsstIndex, NULL ); if ( ulResult == cOCT6100_ERR_OK ) { fSinReserved = TRUE; } } } else { *f_pusNewSinTsstIndex = cOCT6100_INVALID_INDEX; } } else { *f_pusNewSinTsstIndex = cOCT6100_INVALID_INDEX; } /* Modify ROUT port.*/ if ( ( fReserveRout == TRUE ) && ( ulResult == cOCT6100_ERR_OK ) ) { if ( pModifyTdmConf->ulRoutTimeslot != cOCT6100_UNASSIGNED ) { /* Check what number of TSSTs should be reserved this time. */ if ( pModifyTdmConf->ulRoutNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) { ulRoutNumTssts = pApiTdmConf->byRoutNumTssts; } else /* if ( pModifyTdmConf->ulRoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) */ { /* New number of TSSTs. */ ulRoutNumTssts = pModifyTdmConf->ulRoutNumTssts; } if ( pModifyTdmConf->ulRoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) { /* Reserve the new number of TSSTs. */ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, pApiTdmConf->usRoutTimeslot, pApiTdmConf->usRoutStream, ulRoutNumTssts, cOCT6100_OUTPUT_TSST, f_pusNewRoutTsstIndex, NULL ); } else /* if ( pModifyTdmConf->ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) */ { /* Reserve the new TSST.*/ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, pModifyTdmConf->ulRoutTimeslot, pModifyTdmConf->ulRoutStream, ulRoutNumTssts, cOCT6100_OUTPUT_TSST, f_pusNewRoutTsstIndex, NULL ); if ( ulResult == cOCT6100_ERR_OK ) { fRoutReserved = TRUE; } } } else { *f_pusNewRoutTsstIndex = cOCT6100_INVALID_INDEX; } } else { *f_pusNewRoutTsstIndex = cOCT6100_INVALID_INDEX; } /* Modify SOUT port.*/ if ( ( fReserveSout == TRUE ) && ( ulResult == cOCT6100_ERR_OK ) ) { if ( pModifyTdmConf->ulSoutTimeslot != cOCT6100_UNASSIGNED ) { /* Check what number of TSSTs should be reserved this time. */ if ( pModifyTdmConf->ulSoutNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) { ulSoutNumTssts = pApiTdmConf->bySoutNumTssts; } else /* if ( pModifyTdmConf->ulSoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) */ { /* New number of TSSTs. */ ulSoutNumTssts = pModifyTdmConf->ulSoutNumTssts; } if ( pModifyTdmConf->ulSoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) { /* Reserve the new number of TSSTs. */ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, pApiTdmConf->usSoutTimeslot, pApiTdmConf->usSoutStream, ulSoutNumTssts, cOCT6100_OUTPUT_TSST, f_pusNewSoutTsstIndex, NULL ); } else /* if ( pModifyTdmConf->ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) */ { /* Reserve the new TSST.*/ ulResult = Oct6100ApiReserveTsst( f_pApiInstance, pModifyTdmConf->ulSoutTimeslot, pModifyTdmConf->ulSoutStream, ulSoutNumTssts, cOCT6100_OUTPUT_TSST, f_pusNewSoutTsstIndex, NULL ); if ( ulResult == cOCT6100_ERR_OK ) { fSoutReserved = TRUE; } } } else { *f_pusNewSoutTsstIndex = cOCT6100_INVALID_INDEX; } } else { *f_pusNewSoutTsstIndex = cOCT6100_INVALID_INDEX; } } if ( f_pChannelModify->fCodecConfigModified == TRUE ) { if ( ulResult == cOCT6100_ERR_OK && pChanEntry->usRinRoutConversionMemIndex == cOCT6100_INVALID_INDEX && ( f_pChannelModify->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT || f_pChannelModify->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) ) { /* Reserve an ADPCM memory block.*/ ulResult = Oct6100ApiReserveConversionMemEntry( f_pApiInstance, &pChanEntry->usRinRoutConversionMemIndex ); if ( ulResult == cOCT6100_ERR_OK ) { fRinRoutConversionMemReserved = TRUE; } } if ( ulResult == cOCT6100_ERR_OK && pChanEntry->usSinSoutConversionMemIndex == cOCT6100_INVALID_INDEX && ( f_pChannelModify->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT || f_pChannelModify->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN ) ) { /* Reserve an ADPCM memory block.*/ ulResult = Oct6100ApiReserveConversionMemEntry( f_pApiInstance, &pChanEntry->usSinSoutConversionMemIndex ); if ( ulResult == cOCT6100_ERR_OK ) { fSinSoutConversionMemReserved = TRUE; } } } /*===============================================================================*/ /* Check if there are a couple of mixer events available for us. */ if ( ulResult == cOCT6100_ERR_OK ) { UINT32 ulMixerEventCntNeeded = 0; /* Calculate how many mixer events are needed. */ if ( pChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) { /* If the channel is in bidir mode, do not create the Rin silence event!!! */ if ( pChanEntry->fBiDirChannel == FALSE ) { if ( ( *f_pusNewRinTsstIndex == cOCT6100_INVALID_INDEX ) && ( pChanEntry->usRinSilenceEventIndex == cOCT6100_INVALID_INDEX ) ) ulMixerEventCntNeeded++; } } if ( ( *f_pusNewSinTsstIndex == cOCT6100_INVALID_INDEX ) && ( pChanEntry->usSinSilenceEventIndex == cOCT6100_INVALID_INDEX ) ) { ulMixerEventCntNeeded++; } /* If at least 1 mixer event is needed, check if those are available. */ if ( ulMixerEventCntNeeded != 0 ) { ulResult = Oct6100ApiGetFreeMixerEventCnt( f_pApiInstance, &ulFreeMixerEventCnt ); if ( ulResult == cOCT6100_ERR_OK ) { /* The API might need more mixer events if the ports have to be muted. */ /* Check if these are available. */ if ( ulFreeMixerEventCnt < ulMixerEventCntNeeded ) { ulResult = cOCT6100_ERR_CHANNEL_OUT_OF_MIXER_EVENTS; } } } } /*===============================================================================*/ /* Verify if an error occured. */ if ( ulResult != cOCT6100_ERR_OK ) { /* Release any resources newly reserved.*/ if ( fRinReserved == TRUE ) { ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, pModifyTdmConf->ulRinTimeslot, pModifyTdmConf->ulRinStream, ulRinNumTssts, cOCT6100_INPUT_TSST, cOCT6100_INVALID_INDEX ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } /* For the SIN port.*/ if ( fSinReserved == TRUE ) { ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, pModifyTdmConf->ulSinTimeslot, pModifyTdmConf->ulSinStream, ulSinNumTssts, cOCT6100_INPUT_TSST, cOCT6100_INVALID_INDEX ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } /* For the ROUT port.*/ if ( fRoutReserved == TRUE ) { ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, pModifyTdmConf->ulRoutTimeslot, pModifyTdmConf->ulRoutStream, ulRoutNumTssts, cOCT6100_OUTPUT_TSST, cOCT6100_INVALID_INDEX ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } /* For the SOUT port.*/ if ( fSoutReserved == TRUE ) { ulTempVar = Oct6100ApiReleaseTsst( f_pApiInstance, pModifyTdmConf->ulSoutTimeslot, pModifyTdmConf->ulSoutStream, ulSoutNumTssts, cOCT6100_OUTPUT_TSST, cOCT6100_INVALID_INDEX ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } /* Now make sure any resources released gets reserved back again.*/ /* For the RIN port.*/ if ( fRinReleased == TRUE ) { /* Reserve the new TSST.*/ ulTempVar = Oct6100ApiReserveTsst( f_pApiInstance, pChanEntry->TdmConfig.usRinTimeslot, pChanEntry->TdmConfig.usRinStream, pChanEntry->TdmConfig.byRinNumTssts, cOCT6100_INPUT_TSST, &pChanEntry->usRinTsstIndex, NULL ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } /* For the SIN port.*/ if ( fSinReleased == TRUE ) { /* Reserve the new TSST.*/ ulTempVar = Oct6100ApiReserveTsst( f_pApiInstance, pChanEntry->TdmConfig.usSinTimeslot, pChanEntry->TdmConfig.usSinStream, pChanEntry->TdmConfig.bySinNumTssts, cOCT6100_INPUT_TSST, &pChanEntry->usSinTsstIndex, NULL ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } /* For the ROUT port.*/ if ( fRoutReleased == TRUE ) { /* Reserve the new TSST.*/ ulTempVar = Oct6100ApiReserveTsst( f_pApiInstance, pChanEntry->TdmConfig.usRoutTimeslot, pChanEntry->TdmConfig.usRoutStream, pChanEntry->TdmConfig.byRoutNumTssts, cOCT6100_OUTPUT_TSST, &pChanEntry->usRoutTsstIndex, NULL ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } /* For the SOUT port.*/ if ( fSoutReleased == TRUE ) { /* Reserve the new TSST.*/ ulTempVar = Oct6100ApiReserveTsst( f_pApiInstance, pChanEntry->TdmConfig.usSoutTimeslot, pChanEntry->TdmConfig.usSoutStream, pChanEntry->TdmConfig.bySoutNumTssts, cOCT6100_OUTPUT_TSST, &pChanEntry->usSoutTsstIndex, NULL ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } /* Release the conversion memories if they were reserved.*/ if ( fRinRoutConversionMemReserved == TRUE ) { ulTempVar = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, pChanEntry->usRinRoutConversionMemIndex ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } if ( fSinSoutConversionMemReserved == TRUE ) { ulTempVar = Oct6100ApiReleaseConversionMemEntry( f_pApiInstance, pChanEntry->usSinSoutConversionMemIndex ); if ( ulTempVar != cOCT6100_ERR_OK ) return ulTempVar; } /* Now return the error.*/ return ulResult; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiModifyChannelStructs Description: Performs all the required structure writes to configure the echo cancellation channel based on the new modifications. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelModify Pointer to echo cancellation channel configuration structure. f_pChannelOpen Pointer to a structure used to store the multiple resources indexes. f_usChanIndex Index of the channel within the API's channel list. f_usNewPhasingTsstIndex Index of the new phasing TSST. f_pfSinSoutCodecActive Pointer to the state of the SIN/SOUT codec. f_pfRinRoutCodecActive Pointer to the state of the RIN/ROUT codec. f_usNewRinTsstIndex New RIN TSST memory index. f_usNewSinTsstIndex New SIN TSST memory index. f_usNewRoutTsstIndex New ROUT TSST memory index. f_usNewSoutTsstIndex New SOUT TSST memory index. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiModifyChannelStructs( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_MODIFY f_pChannelModify, IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, IN UINT16 f_usChanIndex, IN UINT16 f_usNewPhasingTsstIndex, OUT PUINT8 f_pfSinSoutCodecActive, OUT PUINT8 f_pfRinRoutCodecActive, IN UINT16 f_usNewRinTsstIndex, IN UINT16 f_usNewSinTsstIndex, IN UINT16 f_usNewRoutTsstIndex, IN UINT16 f_usNewSoutTsstIndex ) { tPOCT6100_API_CHANNEL pChanEntry; tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_READ_PARAMS ReadParams; tOCT6100_WRITE_PARAMS WriteParams; tPOCT6100_API_CHANNEL_CODEC pApiCodecConf; tPOCT6100_API_CHANNEL_TDM pApiTdmConf; tPOCT6100_API_CHANNEL_VQE pApiVqeConf; UINT32 ulResult; UINT16 usReadData; UINT16 usSinTsstIndex; UINT16 usRinTsstIndex; UINT32 ulToneConfIndex; BOOL fClearPlayoutPointers = FALSE; BOOL fConversionEnabled = FALSE; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; /*=======================================================================*/ /* Get a pointer to the channel's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) /* Obtain local pointer to the configuration structures of the tPOCT6100_API_CHANNEL structure. */ pApiCodecConf = &pChanEntry->CodecConfig; pApiTdmConf = &pChanEntry->TdmConfig; pApiVqeConf = &pChanEntry->VqeConfig; /*=======================================================================*/ /* Init the RIN and SIN TSST index */ usRinTsstIndex = pChanEntry->usRinTsstIndex; usSinTsstIndex = pChanEntry->usSinTsstIndex; /*==============================================================================*/ /* Clear the TSST that will be release.*/ if ( f_pChannelModify->fTdmConfigModified == TRUE ) { /* Modify RIN port.*/ if ( f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) { if ( pChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) { /* Clear the previous entry */ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pChanEntry->usRinTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Modify SIN port.*/ if ( f_pChannelModify->TdmConfig.ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) { if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) { /* Clear the previous entry */ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pChanEntry->usSinTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Modify ROUT port.*/ if ( f_pChannelModify->TdmConfig.ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) { if ( pChanEntry->usRoutTsstIndex != cOCT6100_INVALID_INDEX ) { /* Clear the previous entry */ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pChanEntry->usRoutTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Modify SOUT port.*/ if ( f_pChannelModify->TdmConfig.ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING) { if ( pChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) { /* Clear the previous entry */ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (pChanEntry->usSoutTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } } /*==============================================================================*/ /*==============================================================================*/ /* Now, Configure the Tsst control memory.*/ if ( f_pChannelModify->fTdmConfigModified == TRUE ) { /* Modify RIN port.*/ if ( f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) { usRinTsstIndex = f_usNewRinTsstIndex; if ( f_usNewRinTsstIndex != cOCT6100_INVALID_INDEX ) { if ( pChanEntry->usExtraRinTsiMemIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, f_usNewRinTsstIndex, pChanEntry->usExtraRinTsiMemIndex, f_pChannelOpen->TdmConfig.ulRinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } else { ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, f_usNewRinTsstIndex, pChanEntry->usRinRoutTsiMemIndex, f_pChannelOpen->TdmConfig.ulRinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } } if ( f_pChannelModify->TdmConfig.ulRinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->TdmConfig.ulRinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING ) { if ( pChanEntry->usExtraRinTsiMemIndex != cOCT6100_INVALID_INDEX ) { if ( pChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, pChanEntry->usRinTsstIndex, pChanEntry->usExtraRinTsiMemIndex, f_pChannelOpen->TdmConfig.ulRinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } else { if ( pChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, pChanEntry->usRinTsstIndex, pChanEntry->usRinRoutTsiMemIndex, f_pChannelOpen->TdmConfig.ulRinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } } /* Modify SIN port.*/ if ( f_pChannelModify->TdmConfig.ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) { usSinTsstIndex = f_usNewSinTsstIndex; if ( f_usNewSinTsstIndex != cOCT6100_INVALID_INDEX ) { if ( pChanEntry->usExtraSinTsiMemIndex != cOCT6100_INVALID_INDEX ) { /* Write the new entry now.*/ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, f_usNewSinTsstIndex, pChanEntry->usExtraSinTsiMemIndex, f_pChannelOpen->TdmConfig.ulSinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } else { /* Write the new entry now.*/ ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, f_usNewSinTsstIndex, pChanEntry->usSinSoutTsiMemIndex, f_pChannelOpen->TdmConfig.ulSinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } } if ( f_pChannelModify->TdmConfig.ulSinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING && f_pChannelModify->TdmConfig.ulSinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING ) { if ( pChanEntry->usExtraSinTsiMemIndex != cOCT6100_INVALID_INDEX ) { if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, pChanEntry->usSinTsstIndex , pChanEntry->usExtraSinTsiMemIndex, f_pChannelOpen->TdmConfig.ulSinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } else { if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, pChanEntry->usSinTsstIndex , pChanEntry->usSinSoutTsiMemIndex, f_pChannelOpen->TdmConfig.ulSinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } } /* Modify ROUT port.*/ if ( ( f_pChannelModify->TdmConfig.ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) || ( f_pChannelModify->TdmConfig.ulRoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) ) { if ( f_usNewRoutTsstIndex != cOCT6100_INVALID_INDEX ) { if ( f_pChannelModify->TdmConfig.ulRoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) { /* If this output port is not muted. */ if ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) == 0x0 ) { /* Write the new entry now.*/ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, f_usNewRoutTsstIndex, pApiCodecConf->byAdpcmNibblePosition, f_pChannelModify->TdmConfig.ulRoutNumTssts, pChanEntry->usRinRoutTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } else { /* If this output port is not muted. */ if ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) == 0x0 ) { /* Write the new entry now.*/ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, f_usNewRoutTsstIndex, pApiCodecConf->byAdpcmNibblePosition, pApiTdmConf->byRoutNumTssts, pChanEntry->usRinRoutTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } } } /* Modify SOUT port.*/ if ( ( f_pChannelModify->TdmConfig.ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) || ( f_pChannelModify->TdmConfig.ulSoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) ) { if ( f_usNewSoutTsstIndex != cOCT6100_INVALID_INDEX ) { if ( f_pChannelModify->TdmConfig.ulSoutNumTssts != cOCT6100_KEEP_PREVIOUS_SETTING ) { /* If this output port is not muted. */ if ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) == 0x0 ) { /* Write the new entry now.*/ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, f_usNewSoutTsstIndex, pApiCodecConf->byAdpcmNibblePosition, f_pChannelModify->TdmConfig.ulSoutNumTssts, pChanEntry->usSinSoutTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } else { /* If this output port is not muted. */ if ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) == 0x0 ) { /* Write the new entry now.*/ ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, f_usNewSoutTsstIndex, pApiCodecConf->byAdpcmNibblePosition, pApiTdmConf->bySoutNumTssts, pChanEntry->usSinSoutTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } } } } /*==============================================================================*/ /*==============================================================================*/ /* Modify the Encoder/Decoder memory if required.*/ if ( f_pChannelModify->fCodecConfigModified == TRUE ) { UINT32 ulCompType = 0; UINT16 usTempTsiMemIndex; UINT16 usDecoderMemIndex; UINT16 usEncoderMemIndex; UINT32 ulPcmLaw; UINT16 usPhasingIndex; BOOL fModifyAdpcmMem = TRUE; /*==============================================================================*/ /* Reprogram the Decoder memory.*/ if ( pChanEntry->CodecConfig.byDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) { usDecoderMemIndex = pChanEntry->usRinRoutConversionMemIndex; } else { usDecoderMemIndex = pChanEntry->usSinSoutConversionMemIndex; } if ( pChanEntry->CodecConfig.byEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) { usEncoderMemIndex = pChanEntry->usRinRoutConversionMemIndex; } else { usEncoderMemIndex = pChanEntry->usSinSoutConversionMemIndex; } if ( usDecoderMemIndex != cOCT6100_INVALID_INDEX ) { switch( f_pChannelOpen->CodecConfig.ulDecodingRate ) { case cOCT6100_G711_64KBPS: ulCompType = 0x8; if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) { if ( f_pChannelOpen->TdmConfig.ulRinPcmLaw == f_pChannelOpen->TdmConfig.ulRoutPcmLaw ) fModifyAdpcmMem = FALSE; /* Check if both ports are assigned. If not, no law conversion needed here.. */ if ( ( f_pChannelOpen->TdmConfig.ulRinStream == cOCT6100_UNASSIGNED ) || ( f_pChannelOpen->TdmConfig.ulRoutStream == cOCT6100_UNASSIGNED ) ) fModifyAdpcmMem = FALSE; } else /* f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ { if ( f_pChannelOpen->TdmConfig.ulSinPcmLaw == f_pChannelOpen->TdmConfig.ulSoutPcmLaw ) fModifyAdpcmMem = FALSE; /* Check if both ports are assigned. If not, no law conversion needed here.. */ if ( ( f_pChannelOpen->TdmConfig.ulSinStream == cOCT6100_UNASSIGNED ) || ( f_pChannelOpen->TdmConfig.ulSoutStream == cOCT6100_UNASSIGNED ) ) fModifyAdpcmMem = FALSE; } break; case cOCT6100_G726_40KBPS: ulCompType = 0x3; fConversionEnabled = TRUE; break; case cOCT6100_G726_32KBPS: ulCompType = 0x2; fConversionEnabled = TRUE; break; case cOCT6100_G726_24KBPS: ulCompType = 0x1; fConversionEnabled = TRUE; break; case cOCT6100_G726_16KBPS: ulCompType = 0x0; fConversionEnabled = TRUE; break; case cOCT6100_G727_2C_ENCODED: ulCompType = 0x4; fConversionEnabled = TRUE; break; case cOCT6100_G727_3C_ENCODED: ulCompType = 0x5; fConversionEnabled = TRUE; break; case cOCT6100_G727_4C_ENCODED: ulCompType = 0x6; fConversionEnabled = TRUE; break; case cOCT6100_G726_ENCODED: ulCompType = 0x9; fConversionEnabled = TRUE; break; case cOCT6100_G711_G726_ENCODED: ulCompType = 0xA; fConversionEnabled = TRUE; break; case cOCT6100_G711_G727_2C_ENCODED: ulCompType = 0xC; fConversionEnabled = TRUE; break; case cOCT6100_G711_G727_3C_ENCODED: ulCompType = 0xD; fConversionEnabled = TRUE; break; case cOCT6100_G711_G727_4C_ENCODED: ulCompType = 0xE; fConversionEnabled = TRUE; break; default: return cOCT6100_ERR_FATAL_D6; } if ( fModifyAdpcmMem == TRUE ) { /* Set the chariot memory based on the selected port.*/ if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) { usTempTsiMemIndex = pChanEntry->usRinRoutTsiMemIndex; ulPcmLaw = f_pChannelOpen->TdmConfig.ulRoutPcmLaw; /* Set the law for later use */ /* Flag the entry as active.*/ *f_pfRinRoutCodecActive = TRUE; } else /* f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ { usTempTsiMemIndex = pChanEntry->usSinSoutTsiMemIndex; ulPcmLaw = f_pChannelOpen->TdmConfig.ulSoutPcmLaw; /* Set the law for later use */ /* Flag the entry as active.*/ *f_pfSinSoutCodecActive = TRUE; } ulResult = Oct6100ApiWriteDecoderMemory( f_pApiInstance, usDecoderMemIndex, ulCompType, usTempTsiMemIndex, ulPcmLaw, pApiCodecConf->byAdpcmNibblePosition ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } else { ulResult = Oct6100ApiClearConversionMemory( f_pApiInstance, usDecoderMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Flag the entry as deactivated.*/ if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) { *f_pfRinRoutCodecActive = FALSE; } else { *f_pfSinSoutCodecActive = FALSE; } } } /*==============================================================================*/ /*==============================================================================*/ /* Reprogram the Encoder memory.*/ if ( usEncoderMemIndex != cOCT6100_INVALID_INDEX ) { fModifyAdpcmMem = TRUE; /* Set the chariot memory based on the selected port.*/ if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) { usTempTsiMemIndex = pChanEntry->usRinRoutTsiMemIndex; ulPcmLaw = f_pChannelOpen->TdmConfig.ulRoutPcmLaw; /* Set the law for later use */ } else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ { usTempTsiMemIndex = pChanEntry->usSinSoutTsiMemIndex; ulPcmLaw = f_pChannelOpen->TdmConfig.ulSoutPcmLaw; /* Set the law for later use */ } /* Set the phasing index .*/ if ( f_usNewPhasingTsstIndex != cOCT6100_INVALID_INDEX ) usPhasingIndex = f_usNewPhasingTsstIndex; else usPhasingIndex = pChanEntry->usPhasingTsstIndex; switch( f_pChannelOpen->CodecConfig.ulEncodingRate ) { case cOCT6100_G711_64KBPS: if ( ulPcmLaw == cOCT6100_PCM_U_LAW ) ulCompType = 0x4; else /* ulPcmLaw == cOCT6100_PCM_A_LAW */ ulCompType = 0x5; if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) { if ( f_pChannelOpen->TdmConfig.ulRinPcmLaw == f_pChannelOpen->TdmConfig.ulRoutPcmLaw ) fModifyAdpcmMem = FALSE; /* Check if both ports are assigned. If not, no law conversion needed here.. */ if ( ( f_pChannelOpen->TdmConfig.ulRinStream == cOCT6100_UNASSIGNED ) || ( f_pChannelOpen->TdmConfig.ulRoutStream == cOCT6100_UNASSIGNED ) ) fModifyAdpcmMem = FALSE; } else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ { if ( f_pChannelOpen->TdmConfig.ulSinPcmLaw == f_pChannelOpen->TdmConfig.ulSoutPcmLaw ) fModifyAdpcmMem = FALSE; /* Check if both ports are assigned. If not, no law conversion needed here.. */ if ( ( f_pChannelOpen->TdmConfig.ulSinStream == cOCT6100_UNASSIGNED ) || ( f_pChannelOpen->TdmConfig.ulSoutStream == cOCT6100_UNASSIGNED ) ) fModifyAdpcmMem = FALSE; } break; case cOCT6100_G726_40KBPS: ulCompType = 0x3; fConversionEnabled = TRUE; break; case cOCT6100_G726_32KBPS: ulCompType = 0x2; fConversionEnabled = TRUE; break; case cOCT6100_G726_24KBPS: ulCompType = 0x1; fConversionEnabled = TRUE; break; case cOCT6100_G726_16KBPS: ulCompType = 0x0; fConversionEnabled = TRUE; break; case cOCT6100_G727_40KBPS_4_1: ulCompType = 0xD; fConversionEnabled = TRUE; break; case cOCT6100_G727_40KBPS_3_2: ulCompType = 0xA; fConversionEnabled = TRUE; break; case cOCT6100_G727_40KBPS_2_3: ulCompType = 0x6; fConversionEnabled = TRUE; break; case cOCT6100_G727_32KBPS_4_0: ulCompType = 0xE; fConversionEnabled = TRUE; break; case cOCT6100_G727_32KBPS_3_1: ulCompType = 0xB; fConversionEnabled = TRUE; break; case cOCT6100_G727_32KBPS_2_2: ulCompType = 0x7; fConversionEnabled = TRUE; break; case cOCT6100_G727_24KBPS_3_0: ulCompType = 0xC; fConversionEnabled = TRUE; break; case cOCT6100_G727_24KBPS_2_1: ulCompType = 0x8; fConversionEnabled = TRUE; break; case cOCT6100_G727_16KBPS_2_0: ulCompType = 0x9; fConversionEnabled = TRUE; break; default: return cOCT6100_ERR_FATAL_D7; } if ( fModifyAdpcmMem == TRUE ) { if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) { *f_pfRinRoutCodecActive = TRUE; } else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ { *f_pfSinSoutCodecActive = TRUE; } ulResult = Oct6100ApiWriteEncoderMemory( f_pApiInstance, usEncoderMemIndex, ulCompType, usTempTsiMemIndex, f_pChannelOpen->CodecConfig.fEnableSilenceSuppression, pApiCodecConf->byAdpcmNibblePosition, usPhasingIndex, f_pChannelOpen->CodecConfig.ulPhasingType, f_pChannelOpen->CodecConfig.ulPhase ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } else { ulResult = Oct6100ApiClearConversionMemory( f_pApiInstance, usEncoderMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT ) { *f_pfRinRoutCodecActive = FALSE; } else /* f_pChannelOpen->CodecConfig.ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT */ { *f_pfSinSoutCodecActive = FALSE; } } } /*==============================================================================*/ } /*==============================================================================*/ /* Modify the VQE parameter if required.*/ if ( ( f_pChannelModify->fVqeConfigModified == TRUE ) || ( (UINT8)f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) || ( f_pChannelOpen->fEnableToneDisabler != pChanEntry->fEnableToneDisabler ) ) { ulResult = Oct6100ApiWriteVqeMemory( f_pApiInstance, &f_pChannelOpen->VqeConfig, f_pChannelOpen, f_usChanIndex, pChanEntry->usEchoMemIndex, FALSE, TRUE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*==============================================================================*/ /* Modify the Echo memory if required.*/ if ( f_pChannelModify->fEnableToneDisabler != cOCT6100_KEEP_PREVIOUS_SETTING || f_pChannelModify->ulEchoOperationMode != cOCT6100_KEEP_PREVIOUS_SETTING || f_pChannelModify->TdmConfig.ulRinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || f_pChannelModify->TdmConfig.ulSinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || f_pChannelModify->TdmConfig.ulRoutPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING || f_pChannelModify->TdmConfig.ulSoutPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING ) { ulResult = Oct6100ApiWriteEchoMemory( f_pApiInstance, &f_pChannelOpen->TdmConfig, f_pChannelOpen, pChanEntry->usEchoMemIndex, pChanEntry->usRinRoutTsiMemIndex, pChanEntry->usSinSoutTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Synch all the buffer playout field if needed by echo operation mode. */ /* Note that Oct6100ApiWriteVqeMemory does not clear the playout pointers */ /* since the flag is set to FALSE. */ if ( ( pSharedInfo->ImageInfo.fBufferPlayout == TRUE ) && ( ( f_pChannelModify->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_HT_FREEZE ) || ( f_pChannelModify->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_POWER_DOWN ) ) ) { /* Buffer playout must be stopped. */ fClearPlayoutPointers = TRUE; } } /*==============================================================================*/ /* Modify the Mixer events if law changes are requested. */ if ( pChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX && f_pChannelModify->TdmConfig.ulSinPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING ) { ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Modify the value according to the new law.*/ if ( f_pChannelModify->TdmConfig.ulSinPcmLaw == cOCT6100_PCM_A_LAW ) WriteParams.usWriteData = (UINT16)( usReadData | ( f_pChannelModify->TdmConfig.ulSinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET )); else WriteParams.usWriteData = (UINT16)( usReadData & (~( f_pChannelModify->TdmConfig.ulSinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET ))); /* Write back the new value.*/ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } if ( pChanEntry->usSoutCopyEventIndex != cOCT6100_INVALID_INDEX && f_pChannelModify->TdmConfig.ulSoutPcmLaw != cOCT6100_KEEP_PREVIOUS_SETTING ) { ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usSoutCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Modify the value according to the new law.*/ if ( f_pChannelModify->TdmConfig.ulSoutPcmLaw == cOCT6100_PCM_A_LAW ) WriteParams.usWriteData = (UINT16)( usReadData | ( f_pChannelModify->TdmConfig.ulSoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET )); else WriteParams.usWriteData = (UINT16)( usReadData & (~( f_pChannelModify->TdmConfig.ulSoutPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET ))); /* Write back the new value.*/ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*==============================================================================*/ /* Mute channel if required, this is done on a port basis */ ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_usChanIndex, usRinTsstIndex, usSinTsstIndex, TRUE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ /* Completely disable tone detection? */ if ( f_pChannelModify->fDisableToneDetection == TRUE ) { /* Check if tone detection has been enabled on this channel. */ for ( ulToneConfIndex = 0; ulToneConfIndex < ( sizeof( pChanEntry->aulToneConf ) / sizeof(UINT32) ); ulToneConfIndex ++ ) { /* Check if some tone has been activated on this channel. */ if ( pChanEntry->aulToneConf[ ulToneConfIndex ] != 0 ) { tOCT6100_TONE_DETECTION_DISABLE ToneDetectDisable; /* Call the default function to make sure all parameters are assigned default values. */ ulResult = Oct6100ToneDetectionDisableDef( &ToneDetectDisable ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Form channel handle. */ ToneDetectDisable.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; /* Disable all tones activated on this channel. */ ToneDetectDisable.fDisableAll = TRUE; /* Call tone detection serialized function. */ ulResult = Oct6100ToneDetectionDisableSer( f_pApiInstance, &ToneDetectDisable ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Get out of the loop, tone detection has been disabled! */ break; } } } /* Hard-stop buffer playout? */ if ( f_pChannelModify->fStopBufferPlayout == TRUE ) { /* Check if playout has been started on the Rout port. */ if ( ( pChanEntry->fRinBufPlaying == TRUE ) || ( pChanEntry->fRinBufAdded == TRUE ) ) { tOCT6100_BUFFER_PLAYOUT_STOP PlayoutStop; /* Call the default function to make sure all parameters are assigned default values. */ ulResult = Oct6100BufferPlayoutStopDef( &PlayoutStop ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Hard stop request. */ PlayoutStop.fStopCleanly = FALSE; /* Form channel handle. */ PlayoutStop.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; /* For the Rout port. */ PlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; /* Call buffer playout stop serialized function. */ ulResult = Oct6100BufferPlayoutStopSer( f_pApiInstance, &PlayoutStop ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } else { /* The chip might still be playing a last buffer. Make sure it hard-stops! */ fClearPlayoutPointers = TRUE; } /* Check if playout has been started on the Sout port. */ if ( ( pChanEntry->fSoutBufPlaying == TRUE ) || ( pChanEntry->fSoutBufAdded == TRUE ) ) { tOCT6100_BUFFER_PLAYOUT_STOP PlayoutStop; /* Call the default function to make sure all parameters are assigned default values. */ ulResult = Oct6100BufferPlayoutStopDef( &PlayoutStop ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Hard stop request. */ PlayoutStop.fStopCleanly = FALSE; /* Form channel handle. */ PlayoutStop.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; /* For the Rout port. */ PlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_SOUT; /* Call buffer playout stop serialized function. */ ulResult = Oct6100BufferPlayoutStopSer( f_pApiInstance, &PlayoutStop ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } else { /* The chip might still be playing a last buffer. Make sure it hard-stops! */ fClearPlayoutPointers = TRUE; } } /* Remove participant from bridge? */ if ( f_pChannelModify->fRemoveConfBridgeParticipant == TRUE ) { /* Check if this channel is on a bridge. */ if ( pChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX ) { /* Channel is on a bridge, remove it. */ tOCT6100_CONF_BRIDGE_CHAN_REMOVE BridgeChanRemove; /* Call the default function to make sure all parameters are assigned default values. */ ulResult = Oct6100ConfBridgeChanRemoveDef( &BridgeChanRemove ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Form channel handle. */ BridgeChanRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; /* Do not remove all channels, only the one specified. */ BridgeChanRemove.fRemoveAll = FALSE; /* No need to assign conference bridge handle, the remove function will figure it out. */ /* Call conference bridge channel remove serialized function. */ ulResult = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, &BridgeChanRemove ); if ( ulResult != cOCT6100_ERR_OK ) { if ( ulResult == cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_DEPENDENCY ) { tPOCT6100_API_CHANNEL pTapChanEntry; /* Get a pointer to the tap channel's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTapChanEntry, pChanEntry->usTapChanIndex ) /* Form tap channel handle. */ BridgeChanRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pTapChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | pChanEntry->usTapChanIndex; ulResult = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, &BridgeChanRemove ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Re-form original channel handle. */ BridgeChanRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; ulResult = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, &BridgeChanRemove ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } else { return ulResult; } } } } /* Remove all broadcast TSSTs? */ if ( f_pChannelModify->fRemoveBroadcastTssts == TRUE ) { /* Check if broadcast TSSTs were used on the Rout port. */ if ( pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry != cOCT6100_INVALID_INDEX ) { tOCT6100_CHANNEL_BROADCAST_TSST_REMOVE BroadcastTsstRemove; ulResult = Oct6100ChannelBroadcastTsstRemoveDef( &BroadcastTsstRemove ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Form channel handle. */ BroadcastTsstRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; /* Remove all broadcast TSSTs associated to the current channel. */ BroadcastTsstRemove.fRemoveAll = TRUE; /* On the Rout port. */ BroadcastTsstRemove.ulPort = cOCT6100_CHANNEL_PORT_ROUT; ulResult = Oct6100ChannelBroadcastTsstRemoveSer( f_pApiInstance, &BroadcastTsstRemove ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Check if broadcast TSSTs were used on the Sout port. */ if ( pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry != cOCT6100_INVALID_INDEX ) { tOCT6100_CHANNEL_BROADCAST_TSST_REMOVE BroadcastTsstRemove; ulResult = Oct6100ChannelBroadcastTsstRemoveDef( &BroadcastTsstRemove ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Form channel handle. */ BroadcastTsstRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | ( pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT ) | f_usChanIndex; /* Remove all broadcast TSSTs associated to the current channel. */ BroadcastTsstRemove.fRemoveAll = TRUE; /* On the Sout port. */ BroadcastTsstRemove.ulPort = cOCT6100_CHANNEL_PORT_SOUT; ulResult = Oct6100ChannelBroadcastTsstRemoveSer( f_pApiInstance, &BroadcastTsstRemove ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Check if have to make sure buffer playout is stopped. */ if ( fClearPlayoutPointers == TRUE ) { tOCT6100_BUFFER_PLAYOUT_STOP BufferPlayoutStop; Oct6100BufferPlayoutStopDef( &BufferPlayoutStop ); BufferPlayoutStop.fStopCleanly = FALSE; BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; ulResult = Oct6100ApiInvalidateChanPlayoutStructs( f_pApiInstance, &BufferPlayoutStop, f_usChanIndex, pChanEntry->usEchoMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_SOUT; ulResult = Oct6100ApiInvalidateChanPlayoutStructs( f_pApiInstance, &BufferPlayoutStop, f_usChanIndex, pChanEntry->usEchoMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiModifyChannelEntry Description: Updates the channel structure in the ECHO channel list. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelModify Pointer to echo cancellation channel modify structure. f_pChannelOpen Pointer to echo cancellation channel configuration structure. f_usChanIndex Index of the channel within the API's channel list. f_usNewPhasingTsstIndex Index of the new phasing TSST. f_fSinSoutCodecActive State of the SIN/SOUT codec. f_fRinRoutCodecActive State of the RIN/ROUT codec. f_usNewRinTsstIndex New RIN TSST memory index. f_usNewSinTsstIndex New SIN TSST memory index. f_usNewRoutTsstIndex New ROUT TSST memory index. f_usNewSoutTsstIndex New SOUT TSST memory index. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiModifyChannelEntry( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_MODIFY f_pChannelModify, IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, IN UINT16 f_usChanIndex, IN UINT16 f_usNewPhasingTsstIndex, IN UINT8 f_fSinSoutCodecActive, IN UINT8 f_fRinRoutCodecActive, IN UINT16 f_usNewRinTsstIndex, IN UINT16 f_usNewSinTsstIndex, IN UINT16 f_usNewRoutTsstIndex, IN UINT16 f_usNewSoutTsstIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHANNEL pChanEntry; tPOCT6100_API_CHANNEL_CODEC pApiCodecConf; tPOCT6100_API_CHANNEL_TDM pApiTdmConf; tPOCT6100_API_CHANNEL_VQE pApiVqeConf; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /*=======================================================================*/ /* Get a pointer to the channel's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) /* Obtain local pointer to the configuration structures of the tPOCT6100_API_CHANNEL structure. */ pApiCodecConf = &pChanEntry->CodecConfig; pApiTdmConf = &pChanEntry->TdmConfig; pApiVqeConf = &pChanEntry->VqeConfig; /*=======================================================================*/ /* Copy the channel's general configuration. */ pChanEntry->ulUserChanId = f_pChannelOpen->ulUserChanId; pChanEntry->byEchoOperationMode = (UINT8)( f_pChannelOpen->ulEchoOperationMode & 0xFF ); pChanEntry->fEnableToneDisabler = (UINT8)( f_pChannelOpen->fEnableToneDisabler & 0xFF ); /* Save the codec state.*/ pChanEntry->fSinSoutCodecActive = (UINT8)( f_fSinSoutCodecActive & 0xFF ); pChanEntry->fRinRoutCodecActive = (UINT8)( f_fRinRoutCodecActive & 0xFF ); /*=======================================================================*/ /* Copy the channel's TDM configuration of all the modified fields. */ if ( f_pChannelModify->fTdmConfigModified == TRUE ) { pApiTdmConf->byRinPcmLaw = (UINT8)( f_pChannelOpen->TdmConfig.ulRinPcmLaw & 0xFF ); pApiTdmConf->bySinPcmLaw = (UINT8)( f_pChannelOpen->TdmConfig.ulSinPcmLaw & 0xFF ); pApiTdmConf->byRoutPcmLaw = (UINT8)( f_pChannelOpen->TdmConfig.ulRoutPcmLaw & 0xFF ); pApiTdmConf->bySoutPcmLaw = (UINT8)( f_pChannelOpen->TdmConfig.ulSoutPcmLaw & 0xFF ); pApiTdmConf->byRinNumTssts = (UINT8)( f_pChannelOpen->TdmConfig.ulRinNumTssts & 0xFF ); pApiTdmConf->bySinNumTssts = (UINT8)( f_pChannelOpen->TdmConfig.ulSinNumTssts & 0xFF ); pApiTdmConf->byRoutNumTssts = (UINT8)( f_pChannelOpen->TdmConfig.ulRoutNumTssts & 0xFF ); pApiTdmConf->bySoutNumTssts = (UINT8)( f_pChannelOpen->TdmConfig.ulSoutNumTssts & 0xFF ); if ( f_pChannelModify->TdmConfig.ulRinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) { if ( f_usNewRinTsstIndex != cOCT6100_INVALID_INDEX ) { pApiTdmConf->usRinStream = (UINT16)( f_pChannelOpen->TdmConfig.ulRinStream & 0xFFFF ); pApiTdmConf->usRinTimeslot = (UINT16)( f_pChannelOpen->TdmConfig.ulRinTimeslot & 0xFFFF ); pChanEntry->usRinTsstIndex = f_usNewRinTsstIndex; } else /* f_ulNewRinTsstIndex != cOCT6100_INVALID_INDEX */ { pApiTdmConf->usRinStream = cOCT6100_UNASSIGNED; pApiTdmConf->usRinTimeslot = cOCT6100_UNASSIGNED; pChanEntry->usRinTsstIndex = cOCT6100_INVALID_INDEX; } } if ( f_pChannelModify->TdmConfig.ulSinTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) { if ( f_usNewSinTsstIndex != cOCT6100_INVALID_INDEX ) { pApiTdmConf->usSinStream = (UINT16)( f_pChannelOpen->TdmConfig.ulSinStream & 0xFFFF ); pApiTdmConf->usSinTimeslot = (UINT16)( f_pChannelOpen->TdmConfig.ulSinTimeslot & 0xFFFF ); pChanEntry->usSinTsstIndex = f_usNewSinTsstIndex; } else /* f_ulNewSinTsstIndex != cOCT6100_INVALID_INDEX */ { pApiTdmConf->usSinStream = cOCT6100_UNASSIGNED; pApiTdmConf->usSinTimeslot = cOCT6100_UNASSIGNED; pChanEntry->usSinTsstIndex = cOCT6100_INVALID_INDEX; } } if ( f_pChannelModify->TdmConfig.ulRoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) { if ( f_usNewRoutTsstIndex != cOCT6100_INVALID_INDEX ) { pApiTdmConf->usRoutStream = (UINT16)( f_pChannelOpen->TdmConfig.ulRoutStream & 0xFFFF ); pApiTdmConf->usRoutTimeslot = (UINT16)( f_pChannelOpen->TdmConfig.ulRoutTimeslot & 0xFFFF ); pChanEntry->usRoutTsstIndex = f_usNewRoutTsstIndex; } else /* f_ulNewRoutTsstIndex != cOCT6100_INVALID_INDEX */ { pApiTdmConf->usRoutStream = cOCT6100_UNASSIGNED; pApiTdmConf->usRoutTimeslot = cOCT6100_UNASSIGNED; pChanEntry->usRoutTsstIndex = cOCT6100_INVALID_INDEX; } } if ( f_pChannelModify->TdmConfig.ulSoutTimeslot != cOCT6100_KEEP_PREVIOUS_SETTING ) { if ( f_usNewSoutTsstIndex != cOCT6100_INVALID_INDEX ) { pApiTdmConf->usSoutStream = (UINT16)( f_pChannelOpen->TdmConfig.ulSoutStream & 0xFFFF ); pApiTdmConf->usSoutTimeslot = (UINT16)( f_pChannelOpen->TdmConfig.ulSoutTimeslot & 0xFFFF ); pChanEntry->usSoutTsstIndex = f_usNewSoutTsstIndex; } else /* f_ulNewSoutTsstIndex != cOCT6100_INVALID_INDEX */ { pApiTdmConf->usSoutStream = cOCT6100_UNASSIGNED; pApiTdmConf->usSoutTimeslot = cOCT6100_UNASSIGNED; pChanEntry->usSoutTsstIndex = cOCT6100_INVALID_INDEX; } } } /*=======================================================================*/ /* Copy the channel's VQE configuration of all the modified fields. */ if ( f_pChannelModify->fVqeConfigModified == TRUE ) { pApiVqeConf->fEnableNlp = (UINT8)( f_pChannelOpen->VqeConfig.fEnableNlp & 0xFF ); pApiVqeConf->byComfortNoiseMode = (UINT8)( f_pChannelOpen->VqeConfig.ulComfortNoiseMode & 0xFF ); pApiVqeConf->fSinDcOffsetRemoval = (UINT8)( f_pChannelOpen->VqeConfig.fSinDcOffsetRemoval & 0xFF ); pApiVqeConf->fRinDcOffsetRemoval = (UINT8)( f_pChannelOpen->VqeConfig.fRinDcOffsetRemoval & 0xFF ); pApiVqeConf->fRinLevelControl = (UINT8)( f_pChannelOpen->VqeConfig.fRinLevelControl & 0xFF ); pApiVqeConf->fSoutLevelControl = (UINT8)( f_pChannelOpen->VqeConfig.fSoutLevelControl & 0xFF ); pApiVqeConf->fRinAutomaticLevelControl = (UINT8)( f_pChannelOpen->VqeConfig.fRinAutomaticLevelControl & 0xFF ); pApiVqeConf->fSoutAutomaticLevelControl = (UINT8)( f_pChannelOpen->VqeConfig.fSoutAutomaticLevelControl & 0xFF ); pApiVqeConf->fRinHighLevelCompensation = (UINT8)( f_pChannelOpen->VqeConfig.fRinHighLevelCompensation & 0xFF ); pApiVqeConf->fSoutAdaptiveNoiseReduction = (UINT8)( f_pChannelOpen->VqeConfig.fSoutAdaptiveNoiseReduction & 0xFF ); pApiVqeConf->fSoutNoiseBleaching = (UINT8)( f_pChannelOpen->VqeConfig.fSoutNoiseBleaching & 0xFF ); pApiVqeConf->fSoutConferencingNoiseReduction = (UINT8)( f_pChannelOpen->VqeConfig.fSoutConferencingNoiseReduction & 0xFF ); pApiVqeConf->chRinLevelControlGainDb = (INT8)( f_pChannelOpen->VqeConfig.lRinLevelControlGainDb & 0xFF ); pApiVqeConf->chSoutLevelControlGainDb = (INT8)( f_pChannelOpen->VqeConfig.lSoutLevelControlGainDb & 0xFF ); pApiVqeConf->chRinAutomaticLevelControlTargetDb = (INT8)( f_pChannelOpen->VqeConfig.lRinAutomaticLevelControlTargetDb & 0xFF ); pApiVqeConf->chSoutAutomaticLevelControlTargetDb = (INT8)( f_pChannelOpen->VqeConfig.lSoutAutomaticLevelControlTargetDb & 0xFF ); pApiVqeConf->chRinHighLevelCompensationThresholdDb = (INT8)( f_pChannelOpen->VqeConfig.lRinHighLevelCompensationThresholdDb & 0xFF ); pApiVqeConf->fEnableTailDisplacement = (UINT8)( f_pChannelOpen->VqeConfig.fEnableTailDisplacement & 0xFF ); pApiVqeConf->usTailDisplacement = (UINT16)( f_pChannelOpen->VqeConfig.ulTailDisplacement & 0xFFFF ); pApiVqeConf->usTailLength = (UINT16)( f_pChannelOpen->VqeConfig.ulTailLength & 0xFFFF ); pApiVqeConf->fAcousticEcho = (UINT8)( f_pChannelOpen->VqeConfig.fAcousticEcho & 0xFF ); pApiVqeConf->fDtmfToneRemoval = (UINT8)( f_pChannelOpen->VqeConfig.fDtmfToneRemoval & 0xFF ); pApiVqeConf->chDefaultErlDb = (INT8)( f_pChannelOpen->VqeConfig.lDefaultErlDb & 0xFF ); pApiVqeConf->chAecDefaultErlDb = (INT8)( f_pChannelOpen->VqeConfig.lAecDefaultErlDb & 0xFF ); pApiVqeConf->usAecTailLength = (UINT16)( f_pChannelOpen->VqeConfig.ulAecTailLength & 0xFFFF ); pApiVqeConf->chAnrSnrEnhancementDb = (INT8)( f_pChannelOpen->VqeConfig.lAnrSnrEnhancementDb & 0xFF ); pApiVqeConf->byAnrVoiceNoiseSegregation = (UINT8)( f_pChannelOpen->VqeConfig.ulAnrVoiceNoiseSegregation & 0xFF ); pApiVqeConf->usToneDisablerVqeActivationDelay = (UINT16)( f_pChannelOpen->VqeConfig.ulToneDisablerVqeActivationDelay & 0xFFFF ); pApiVqeConf->byNonLinearityBehaviorA = (UINT8)( f_pChannelOpen->VqeConfig.ulNonLinearityBehaviorA & 0xFF ); pApiVqeConf->byNonLinearityBehaviorB = (UINT8)( f_pChannelOpen->VqeConfig.ulNonLinearityBehaviorB & 0xFF ); pApiVqeConf->byDoubleTalkBehavior = (UINT8)( f_pChannelOpen->VqeConfig.ulDoubleTalkBehavior & 0xFF ); pApiVqeConf->bySoutAutomaticListenerEnhancementGainDb = (UINT8)( f_pChannelOpen->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb & 0xFF ); pApiVqeConf->bySoutNaturalListenerEnhancementGainDb = (UINT8)( f_pChannelOpen->VqeConfig.ulSoutNaturalListenerEnhancementGainDb & 0xFF ); pApiVqeConf->fSoutNaturalListenerEnhancement = (UINT8)( f_pChannelOpen->VqeConfig.fSoutNaturalListenerEnhancement & 0xFF ); pApiVqeConf->fRoutNoiseReduction = (UINT8)( f_pChannelOpen->VqeConfig.fRoutNoiseReduction & 0xFF ); pApiVqeConf->fEnableMusicProtection = (UINT8)( f_pChannelOpen->VqeConfig.fEnableMusicProtection & 0xFF ); pApiVqeConf->fIdleCodeDetection = (UINT8)( f_pChannelOpen->VqeConfig.fIdleCodeDetection & 0xFF ); } /*=======================================================================*/ /* Copy the channel's CODEC configuration of all the modified fields. */ if ( f_pChannelModify->fCodecConfigModified == TRUE ) { pApiCodecConf->byAdpcmNibblePosition = (UINT8)( f_pChannelOpen->CodecConfig.ulAdpcmNibblePosition & 0xFF ); pApiCodecConf->byEncoderPort = (UINT8)( f_pChannelOpen->CodecConfig.ulEncoderPort & 0xFF ); pApiCodecConf->byEncodingRate = (UINT8)( f_pChannelOpen->CodecConfig.ulEncodingRate & 0xFF ); pApiCodecConf->byDecoderPort = (UINT8)( f_pChannelOpen->CodecConfig.ulDecoderPort & 0xFF ); pApiCodecConf->byDecodingRate = (UINT8)( f_pChannelOpen->CodecConfig.ulDecodingRate & 0xFF ); pApiCodecConf->fEnableSilenceSuppression = (UINT8)( f_pChannelOpen->CodecConfig.fEnableSilenceSuppression & 0xFF ); pApiCodecConf->byPhase = (UINT8)( f_pChannelOpen->CodecConfig.ulPhase & 0xFF ); pApiCodecConf->byPhasingType = (UINT8)( f_pChannelOpen->CodecConfig.ulPhasingType & 0xFF ); /* Update the API phasing TSST structure */ if ( f_usNewPhasingTsstIndex != cOCT6100_INVALID_INDEX ) { tPOCT6100_API_PHASING_TSST pPhasingTsst; /* Release the previous phasing TSST if the channel was already bound to one.*/ if ( pChanEntry->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) { mOCT6100_GET_PHASING_TSST_ENTRY_PNT( pSharedInfo, pPhasingTsst, pChanEntry->usPhasingTsstIndex ); pPhasingTsst->usDependencyCnt--; } mOCT6100_GET_PHASING_TSST_ENTRY_PNT( pSharedInfo, pPhasingTsst, f_usNewPhasingTsstIndex ); pPhasingTsst->usDependencyCnt++; pChanEntry->usPhasingTsstIndex = f_usNewPhasingTsstIndex; } } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ChannelBroadcastTsstRemoveSer Description: Removes a broadcast TSST from one of the output port of an echo cancellation channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelTsstRemove Pointer to TSST remove structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ChannelBroadcastTsstRemoveSer( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN OUT tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelTsstRemove) { UINT16 usChanIndex; UINT16 usTsstIndex; UINT16 usTsstEntry; UINT16 usPrevTsstEntry; UINT32 ulResult; ulResult = Oct6100ApiAssertChanTsstRemoveParams( f_pApiInstance, f_pChannelTsstRemove, &usChanIndex, &usTsstIndex, &usTsstEntry, &usPrevTsstEntry ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiInvalidateTsstRemoveStructs( f_pApiInstance, usChanIndex, usTsstIndex, f_pChannelTsstRemove->ulPort, f_pChannelTsstRemove->fRemoveAll ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiReleaseTsstRemoveResources( f_pApiInstance, f_pChannelTsstRemove, usChanIndex, usTsstIndex, usTsstEntry, usPrevTsstEntry ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiAssertChanTsstRemoveParams Description: Verify the validity of the tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE structure. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelTsstRemove Pointer to echo cancellation channel open configuration structure. f_pulChanIndex Pointer to a channel index. f_pulNewTsstIndex Pointer to a TSST index within the TSST control memory. f_pulNewTsstEntry Pointer to a TSST entry within the API TSST list. f_pulPrevTsstEntry Pointer to the previous TSST entry. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiAssertChanTsstRemoveParams( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelTsstRemove, OUT PUINT16 f_pusChanIndex, OUT PUINT16 f_pusTsstIndex, OUT PUINT16 f_pusTsstEntry, OUT PUINT16 f_pusPrevTsstEntry ) { tPOCT6100_API_CHANNEL pChanEntry; tPOCT6100_API_TSST_ENTRY pTsstEntry; UINT32 ulResult; UINT32 ulNumTssts = 1; UINT32 ulEntryOpenCnt; UINT16 usCurrentEntry; UINT16 usTsstValue; UINT16 usNumEntry; /* Check the provided handle. */ if ( (f_pChannelTsstRemove->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; *f_pusChanIndex = (UINT16)( f_pChannelTsstRemove->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); if ( *f_pusChanIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; /*=======================================================================*/ /* Get a pointer to the channel's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, *f_pusChanIndex ) /* Extract the entry open count from the provided handle. */ ulEntryOpenCnt = ( f_pChannelTsstRemove->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; /* Check for errors. */ if ( pChanEntry->fReserved != TRUE ) return cOCT6100_ERR_CHANNEL_NOT_OPEN; if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; /*=======================================================================*/ /* validate the port parameter.*/ if ( f_pChannelTsstRemove->ulPort != cOCT6100_CHANNEL_PORT_ROUT && f_pChannelTsstRemove->ulPort != cOCT6100_CHANNEL_PORT_SOUT ) return cOCT6100_ERR_CHANNEL_TSST_REMOVE_PORT; /* Verify that the requested entry is present in the channel's port broadcast TSST.*/ if ( f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_ROUT ) { usCurrentEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry; usNumEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry; } else /* f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_SOUT */ { usCurrentEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry; usNumEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry; } /* Verify if at least one TSST is present on the channel port.*/ if ( usNumEntry == 0 ) return cOCT6100_ERR_CHANNEL_TSST_REMOVE_NO_BROADCAST_TSST; /* Get the required number of TSST based on the port.*/ switch( f_pChannelTsstRemove->ulPort ) { case cOCT6100_CHANNEL_PORT_ROUT: ulNumTssts = pChanEntry->TdmConfig.byRoutNumTssts; break; case cOCT6100_CHANNEL_PORT_SOUT: ulNumTssts = pChanEntry->TdmConfig.bySoutNumTssts; break; default: return cOCT6100_ERR_FATAL_E; } /* Initialize the TSST entry to invalid.*/ *f_pusTsstEntry = cOCT6100_INVALID_INDEX; *f_pusPrevTsstEntry = cOCT6100_INVALID_INDEX; *f_pusTsstIndex = cOCT6100_INVALID_INDEX; if ( f_pChannelTsstRemove->fRemoveAll != TRUE ) { /* Check the validity of the timeslot and Stream.*/ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, ulNumTssts, f_pChannelTsstRemove->ulTimeslot, f_pChannelTsstRemove->ulStream, cOCT6100_OUTPUT_TSST ); if ( ulResult != cOCT6100_ERR_OK ) { if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) { return cOCT6100_ERR_CHANNEL_TSST_REMOVE_TIMESLOT; } else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) { return cOCT6100_ERR_CHANNEL_TSST_REMOVE_STREAM; } else { return ulResult; } } /* Set the TSST value based on the timeslot and stream value.*/ usTsstValue = (UINT16)( (f_pChannelTsstRemove->ulTimeslot << 5) | f_pChannelTsstRemove->ulStream ); while( usCurrentEntry != cOCT6100_INVALID_INDEX ) { mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, usCurrentEntry ); if ( usTsstValue == pTsstEntry->usTsstValue ) { /* A match was found.*/ *f_pusTsstEntry = usCurrentEntry; *f_pusTsstIndex = pTsstEntry->usTsstMemoryIndex; break; } /* Move on to the next entry.*/ *f_pusPrevTsstEntry = usCurrentEntry; usCurrentEntry = pTsstEntry->usNextEntry; } if ( *f_pusTsstEntry == cOCT6100_INVALID_INDEX ) return cOCT6100_ERR_CHANNEL_TSST_REMOVE_INVALID_TSST; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiInvalidateTsstRemoveStructs Description: Invalidate the entry of the broadcast TSST. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usChanIndex Channel index. f_usTsstIndex TSST index within the TSST control memory. f_ulPort Channel port where the TSST are removed from. (only used if remove all == TRUE) f_fRemoveAll Remove all flag. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiInvalidateTsstRemoveStructs( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usChanIndex, IN UINT16 f_usTsstIndex, IN UINT32 f_ulPort, IN BOOL f_fRemoveAll ) { tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; if ( f_fRemoveAll == FALSE ) { /* Deactivate the entry now.*/ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (f_usTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } else /* f_fRemoveAll == TRUE */ { tPOCT6100_API_CHANNEL pChanEntry; tPOCT6100_API_TSST_ENTRY pTsstEntry; UINT16 usTsstEntry; /*=======================================================================*/ /* Get a pointer to the channel's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_usChanIndex ); /* Clear all entry associated to the selected port.*/ if ( f_ulPort == cOCT6100_CHANNEL_PORT_ROUT ) usTsstEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry; else usTsstEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry; do { mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, usTsstEntry ); /* Deactivate the entry now.*/ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( ( pTsstEntry->usTsstMemoryIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usTsstEntry = pTsstEntry->usNextEntry; } while ( usTsstEntry != cOCT6100_INVALID_INDEX ); } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReleaseTsstRemoveResources Description: Release all API resources associated to the Removed TSST and update the channel entry accordingly. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelTsstRemove Pointer to echo cancellation channel open configuration structure. f_usChanIndex Channel index. f_usTsstIndex TSST index within the TSST control memory. f_usTsstEntry TSST entry within the API's TSST list. f_usPrevTsstEntry Previous TSST entry within the API's TSST list. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReleaseTsstRemoveResources( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_BROADCAST_TSST_REMOVE f_pChannelTsstRemove, IN UINT16 f_usChanIndex, IN UINT16 f_usTsstIndex, IN UINT16 f_usTsstEntry, IN UINT16 f_usPrevTsstEntry ) { tPOCT6100_API_CHANNEL pChanEntry; tPOCT6100_API_TSST_ENTRY pTsstEntry; tPOCT6100_API_TSST_ENTRY pPrevTsstEntry; UINT16 usCurrentEntry; UINT32 ulResult; UINT32 ulTimeslot; UINT32 ulStream; /*=======================================================================*/ /* Get a pointer to the channel's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pChanEntry, f_usChanIndex ); if ( f_pChannelTsstRemove->fRemoveAll == FALSE ) { mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, f_usTsstEntry ); /* Update the channel entry.*/ if ( f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_ROUT ) { /* Check if the entry was the first in the list.*/ if ( f_usPrevTsstEntry == cOCT6100_INVALID_INDEX ) { pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry = pTsstEntry->usNextEntry; } else /* f_ulPrevTsstEntry != cOCT6100_INVALID_INDEX */ { /* Get a pointer to the previous entry.*/ mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPrevTsstEntry, f_usPrevTsstEntry ); pPrevTsstEntry->usNextEntry = pTsstEntry->usNextEntry; } /* Decrement the number of entry.*/ pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry--; } else /* f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_SOUT */ { /* Check if the entry was the first in the list.*/ if ( f_usPrevTsstEntry == cOCT6100_INVALID_INDEX ) { pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry = pTsstEntry->usNextEntry; } else /* f_ulPrevTsstEntry != cOCT6100_INVALID_INDEX */ { /* Get a pointer to the previous entry.*/ mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPrevTsstEntry, f_usPrevTsstEntry ); pPrevTsstEntry->usNextEntry = pTsstEntry->usNextEntry; } /* Decrement the number of entry.*/ pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry--; } ulTimeslot = pTsstEntry->usTsstValue >> 5; ulStream = pTsstEntry->usTsstValue & 0x1F; /* Release the entry.*/ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ulTimeslot, ulStream, cOCT6100_NUMBER_TSSTS_1, cOCT6100_OUTPUT_TSST, f_usTsstEntry ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } else /* f_pChannelTsstRemove->fRemoveAll == TRUE */ { /* Update the channel entry.*/ if ( f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_ROUT ) usCurrentEntry = pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry; else usCurrentEntry = pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry; do { mOCT6100_GET_TSST_LIST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsstEntry, usCurrentEntry ); ulTimeslot = pTsstEntry->usTsstValue >> 5; ulStream = pTsstEntry->usTsstValue & 0x1F; /* Release the entry.*/ ulResult = Oct6100ApiReleaseTsst( f_pApiInstance, ulTimeslot, ulStream, cOCT6100_NUMBER_TSSTS_1, cOCT6100_OUTPUT_TSST, usCurrentEntry ); /* Release the entry.*/ if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usCurrentEntry = pTsstEntry->usNextEntry; /* Clear the previous node.*/ pTsstEntry->usTsstMemoryIndex = 0xFFFF; pTsstEntry->usTsstValue = 0xFFFF; pTsstEntry->usNextEntry = cOCT6100_INVALID_INDEX; } while ( usCurrentEntry != cOCT6100_INVALID_INDEX ); /* Reset the channel status.*/ if ( f_pChannelTsstRemove->ulPort == cOCT6100_CHANNEL_PORT_ROUT ) { pChanEntry->TdmConfig.usRoutBrdcastTsstFirstEntry = cOCT6100_INVALID_INDEX; pChanEntry->TdmConfig.usRoutBrdcastTsstNumEntry = 0; } else { pChanEntry->TdmConfig.usSoutBrdcastTsstFirstEntry = cOCT6100_INVALID_INDEX; pChanEntry->TdmConfig.usSoutBrdcastTsstNumEntry = 0; } } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReserveEchoEntry Description: Reserves one of the echo channel API entry. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pusEchoIndex Resulting index reserved in the echo channel list. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReserveEchoEntry( IN tPOCT6100_INSTANCE_API f_pApiInstance, OUT PUINT16 f_pusEchoIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; PVOID pEchoAlloc; UINT32 ulResult; UINT32 ulEchoIndex; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; mOCT6100_GET_CHANNEL_ALLOC_PNT( pSharedInfo, pEchoAlloc ) ulResult = OctapiLlmAllocAlloc( pEchoAlloc, &ulEchoIndex ); if ( ulResult != cOCT6100_ERR_OK ) { if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) return cOCT6100_ERR_CHANNEL_ALL_CHANNELS_ARE_OPENED; else return cOCT6100_ERR_FATAL_11; } *f_pusEchoIndex = (UINT16)( ulEchoIndex & 0xFFFF ); return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReleaseEchoEntry Description: Releases the specified ECHO channel API entry. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usEchoIndex Index reserved in the echo channel list. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReleaseEchoEntry( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usEchoIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; PVOID pEchoAlloc; UINT32 ulResult; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; mOCT6100_GET_CHANNEL_ALLOC_PNT( pSharedInfo, pEchoAlloc ) ulResult = OctapiLlmAllocDealloc( pEchoAlloc, f_usEchoIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return cOCT6100_ERR_FATAL_12; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiCheckTdmConfig Description: This function will check the validity of the TDM config parameter of an Open TDM config structure. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pTdmConfig TDM config of the channel. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiCheckTdmConfig( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_OPEN_TDM f_pTdmConfig ) { UINT32 ulResult; /*==============================================================================*/ /* Check the TDM configuration parameters.*/ /* Check the validity of the timeslot and Stream only if it is defined.*/ if ( f_pTdmConfig->ulRinTimeslot != cOCT6100_UNASSIGNED || f_pTdmConfig->ulRinStream != cOCT6100_UNASSIGNED ) { if ( f_pTdmConfig->ulRinNumTssts != 1 && f_pTdmConfig->ulRinNumTssts != 2 ) return cOCT6100_ERR_CHANNEL_RIN_NUM_TSSTS; /* Check the RIN TDM streams, timeslots component for errors.*/ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, f_pTdmConfig->ulRinNumTssts, f_pTdmConfig->ulRinTimeslot, f_pTdmConfig->ulRinStream, cOCT6100_INPUT_TSST ); if ( ulResult != cOCT6100_ERR_OK ) { if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) { return cOCT6100_ERR_CHANNEL_RIN_TIMESLOT; } else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) { return cOCT6100_ERR_CHANNEL_RIN_STREAM; } else { return ulResult; } } } /* Check the validity of the timeslot and Stream only if it is defined.*/ if ( f_pTdmConfig->ulRoutTimeslot != cOCT6100_UNASSIGNED || f_pTdmConfig->ulRoutStream != cOCT6100_UNASSIGNED ) { if ( f_pTdmConfig->ulRoutNumTssts != 1 && f_pTdmConfig->ulRoutNumTssts != 2 ) return cOCT6100_ERR_CHANNEL_ROUT_NUM_TSSTS; /* Check the ROUT TDM streams, timeslots component for errors.*/ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, f_pTdmConfig->ulRoutNumTssts, f_pTdmConfig->ulRoutTimeslot, f_pTdmConfig->ulRoutStream, cOCT6100_OUTPUT_TSST ); if ( ulResult != cOCT6100_ERR_OK ) { if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) { return cOCT6100_ERR_CHANNEL_ROUT_TIMESLOT; } else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) { return cOCT6100_ERR_CHANNEL_ROUT_STREAM; } else { return ulResult; } } } /* Check the validity of the timeslot and Stream only if it is defined.*/ if ( f_pTdmConfig->ulSinTimeslot != cOCT6100_UNASSIGNED || f_pTdmConfig->ulSinStream != cOCT6100_UNASSIGNED ) { if ( f_pTdmConfig->ulSinNumTssts != 1 && f_pTdmConfig->ulSinNumTssts != 2 ) return cOCT6100_ERR_CHANNEL_SIN_NUM_TSSTS; /* Check the SIN TDM streams, timeslots component for errors.*/ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, f_pTdmConfig->ulSinNumTssts, f_pTdmConfig->ulSinTimeslot, f_pTdmConfig->ulSinStream, cOCT6100_INPUT_TSST ); if ( ulResult != cOCT6100_ERR_OK ) { if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) { return cOCT6100_ERR_CHANNEL_SIN_TIMESLOT; } else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) { return cOCT6100_ERR_CHANNEL_SIN_STREAM; } else { return ulResult; } } } /* Check the validity of the timeslot and Stream only if it is defined.*/ if ( f_pTdmConfig->ulSoutTimeslot != cOCT6100_UNASSIGNED || f_pTdmConfig->ulSoutStream != cOCT6100_UNASSIGNED ) { if ( f_pTdmConfig->ulSoutNumTssts != 1 && f_pTdmConfig->ulSoutNumTssts != 2 ) return cOCT6100_ERR_CHANNEL_SOUT_NUM_TSSTS; /* Check the ROUT TDM streams, timeslots component for errors.*/ ulResult = Oct6100ApiValidateTsst( f_pApiInstance, f_pTdmConfig->ulSoutNumTssts, f_pTdmConfig->ulSoutTimeslot, f_pTdmConfig->ulSoutStream, cOCT6100_OUTPUT_TSST ); if ( ulResult != cOCT6100_ERR_OK ) { if ( ulResult == cOCT6100_ERR_TSST_TIMESLOT ) { return cOCT6100_ERR_CHANNEL_SOUT_TIMESLOT; } else if ( ulResult == cOCT6100_ERR_TSST_STREAM ) { return cOCT6100_ERR_CHANNEL_SOUT_STREAM; } else { return ulResult; } } } /* Check the PCM law parameters.*/ if ( f_pTdmConfig->ulRinPcmLaw != cOCT6100_PCM_U_LAW && f_pTdmConfig->ulRinPcmLaw != cOCT6100_PCM_A_LAW ) return cOCT6100_ERR_CHANNEL_RIN_PCM_LAW; if ( f_pTdmConfig->ulSinPcmLaw != cOCT6100_PCM_U_LAW && f_pTdmConfig->ulSinPcmLaw != cOCT6100_PCM_A_LAW ) return cOCT6100_ERR_CHANNEL_SIN_PCM_LAW; if ( f_pTdmConfig->ulRoutPcmLaw != cOCT6100_PCM_U_LAW && f_pTdmConfig->ulRoutPcmLaw != cOCT6100_PCM_A_LAW ) return cOCT6100_ERR_CHANNEL_ROUT_PCM_LAW; if ( f_pTdmConfig->ulSoutPcmLaw != cOCT6100_PCM_U_LAW && f_pTdmConfig->ulSoutPcmLaw != cOCT6100_PCM_A_LAW ) return cOCT6100_ERR_CHANNEL_SOUT_PCM_LAW; /*==============================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiCheckVqeConfig Description: This function will check the validity of the VQE config parameter of an Open VQE config structure. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pVqeConfig VQE config of the channel. f_fEnableToneDisabler Whether the tone disabler is active or not. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiCheckVqeConfig( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, IN BOOL f_fEnableToneDisabler ) { tPOCT6100_API_IMAGE_INFO pImageInfo; pImageInfo = &f_pApiInstance->pSharedInfo->ImageInfo; if ( f_pVqeConfig->fEnableNlp != TRUE && f_pVqeConfig->fEnableNlp != FALSE ) return cOCT6100_ERR_CHANNEL_ENABLE_NLP; if ( f_pVqeConfig->fEnableNlp == TRUE && pImageInfo->fNlpControl == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NLP_CONTROL; /* Check the comfort noise mode.*/ if ( f_pVqeConfig->ulComfortNoiseMode != cOCT6100_COMFORT_NOISE_OFF && pImageInfo->fComfortNoise == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_BKG_NOISE_FREEZE; if ( f_pVqeConfig->ulComfortNoiseMode != cOCT6100_COMFORT_NOISE_NORMAL && f_pVqeConfig->ulComfortNoiseMode != cOCT6100_COMFORT_NOISE_EXTENDED && f_pVqeConfig->ulComfortNoiseMode != cOCT6100_COMFORT_NOISE_FAST_LATCH && f_pVqeConfig->ulComfortNoiseMode != cOCT6100_COMFORT_NOISE_OFF ) return cOCT6100_ERR_CHANNEL_COMFORT_NOISE_MODE; /* Check the DC offset removal.*/ if ( f_pVqeConfig->fSinDcOffsetRemoval != TRUE && f_pVqeConfig->fSinDcOffsetRemoval != FALSE ) return cOCT6100_ERR_CHANNEL_SIN_DC_OFFSET_REM; if ( f_pVqeConfig->fSinDcOffsetRemoval == TRUE && pImageInfo->fSinDcOffsetRemoval == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SIN_DC_OFFSET_REM; if ( f_pVqeConfig->fRinDcOffsetRemoval != TRUE && f_pVqeConfig->fRinDcOffsetRemoval != FALSE ) return cOCT6100_ERR_CHANNEL_RIN_DC_OFFSET_REM; if ( f_pVqeConfig->fRinDcOffsetRemoval == TRUE && pImageInfo->fRinDcOffsetRemoval == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_RIN_DC_OFFSET_REM; /* Check the Level control.*/ if ( f_pVqeConfig->fRinLevelControl != TRUE && f_pVqeConfig->fRinLevelControl != FALSE ) return cOCT6100_ERR_CHANNEL_RIN_LEVEL_CONTROL; if ( f_pVqeConfig->fSoutLevelControl != TRUE && f_pVqeConfig->fSoutLevelControl != FALSE ) return cOCT6100_ERR_CHANNEL_SOUT_LEVEL_CONTROL; if ( ( f_pVqeConfig->lRinLevelControlGainDb < -24 ) || ( f_pVqeConfig->lRinLevelControlGainDb > 24 ) ) return cOCT6100_ERR_CHANNEL_RIN_LEVEL_CONTROL_GAIN; if ( ( f_pVqeConfig->lSoutLevelControlGainDb < -24 ) || ( f_pVqeConfig->lSoutLevelControlGainDb > 24 ) ) return cOCT6100_ERR_CHANNEL_SOUT_LEVEL_CONTROL_GAIN; if ( ( f_pVqeConfig->fRinAutomaticLevelControl != TRUE ) && ( f_pVqeConfig->fRinAutomaticLevelControl != FALSE ) ) return cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_CONTROL; if ( ( f_pVqeConfig->fRinHighLevelCompensation != TRUE ) && ( f_pVqeConfig->fRinHighLevelCompensation != FALSE ) ) return cOCT6100_ERR_CHANNEL_RIN_HIGH_LEVEL_COMP; if ( ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) && ( pImageInfo->fRinAutoLevelControl == FALSE ) ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_RIN_AUTO_LC; if ( ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) && ( pImageInfo->fRinHighLevelCompensation == FALSE ) ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_RIN_HIGH_LEVEL_COMP; if ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) { if ( f_pVqeConfig->fRinLevelControl == TRUE ) return cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_MANUAL; if ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) return cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_HIGH_LEVEL_COMP; if ( ( f_pVqeConfig->lRinAutomaticLevelControlTargetDb < -40 || f_pVqeConfig->lRinAutomaticLevelControlTargetDb > 0 ) ) return cOCT6100_ERR_CHANNEL_RIN_AUTO_LEVEL_CONTROL_TARGET; } if ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) { if ( f_pVqeConfig->fRinLevelControl == TRUE ) return cOCT6100_ERR_CHANNEL_RIN_HIGH_LEVEL_COMP_MANUAL; if ( ( f_pVqeConfig->lRinHighLevelCompensationThresholdDb < -40 || f_pVqeConfig->lRinHighLevelCompensationThresholdDb > 0 ) ) return cOCT6100_ERR_CHANNEL_RIN_HIGH_LEVEL_COMP_THRESHOLD; } if ( f_pVqeConfig->fSoutAutomaticLevelControl != TRUE && f_pVqeConfig->fSoutAutomaticLevelControl != FALSE ) return cOCT6100_ERR_CHANNEL_SOUT_AUTO_LEVEL_CONTROL; if ( ( f_pVqeConfig->fSoutAutomaticLevelControl == TRUE ) && ( pImageInfo->fSoutAutoLevelControl == FALSE ) ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SOUT_AUTO_LC; if ( f_pVqeConfig->fSoutAutomaticLevelControl == TRUE ) { if ( f_pVqeConfig->fSoutLevelControl == TRUE ) return cOCT6100_ERR_CHANNEL_SOUT_AUTO_LEVEL_MANUAL; if ( ( f_pVqeConfig->lSoutAutomaticLevelControlTargetDb < -40 || f_pVqeConfig->lSoutAutomaticLevelControlTargetDb > 0 ) ) return cOCT6100_ERR_CHANNEL_SOUT_AUTO_LEVEL_CONTROL_TARGET; } if ( f_pVqeConfig->fSoutAdaptiveNoiseReduction != TRUE && f_pVqeConfig->fSoutAdaptiveNoiseReduction != FALSE ) return cOCT6100_ERR_CHANNEL_SOUT_ADAPT_NOISE_REDUCTION; if ( f_pVqeConfig->fSoutAdaptiveNoiseReduction == TRUE && pImageInfo->fAdaptiveNoiseReduction == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ANR; if ( f_pVqeConfig->fSoutConferencingNoiseReduction != TRUE && f_pVqeConfig->fSoutConferencingNoiseReduction != FALSE ) return cOCT6100_ERR_CHANNEL_SOUT_CONFERENCE_NOISE_REDUCTION; if ( f_pVqeConfig->fSoutConferencingNoiseReduction == TRUE && pImageInfo->fConferencingNoiseReduction == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_CNR; /* Validate Sout noise bleaching parameter. */ if ( f_pVqeConfig->fSoutNoiseBleaching != TRUE && f_pVqeConfig->fSoutNoiseBleaching != FALSE ) return cOCT6100_ERR_CHANNEL_SOUT_NOISE_BLEACHING; /* Check if firmware supports Sout noise bleaching. */ if ( f_pVqeConfig->fSoutNoiseBleaching == TRUE && pImageInfo->fSoutNoiseBleaching == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NOISE_BLEACHING; /* If Sout noise bleaching is requested, no ANR or CNR shall be activated. */ if ( f_pVqeConfig->fSoutNoiseBleaching == TRUE ) { /* No xNR! */ if ( ( f_pVqeConfig->fSoutConferencingNoiseReduction == TRUE ) || ( f_pVqeConfig->fSoutAdaptiveNoiseReduction == TRUE ) ) return cOCT6100_ERR_CHANNEL_SOUT_NOISE_BLEACHING_NR; } /* Cannot activate both ANR and CNR when noise bleaching is present */ if ( pImageInfo->fSoutNoiseBleaching == TRUE ) { if ( f_pVqeConfig->fSoutAdaptiveNoiseReduction == TRUE && f_pVqeConfig->fSoutConferencingNoiseReduction == TRUE ) return cOCT6100_ERR_CHANNEL_ANR_CNR_SIMULTANEOUSLY; } /* Validate the DTMF tone removal parameter.*/ if ( f_pVqeConfig->fDtmfToneRemoval != TRUE && f_pVqeConfig->fDtmfToneRemoval != FALSE ) return cOCT6100_ERR_CHANNEL_TONE_REMOVAL; if ( f_pVqeConfig->fDtmfToneRemoval == TRUE && pImageInfo->fToneRemoval == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TONE_REMOVAL; /* Check the Tail displacement enable.*/ if ( f_pVqeConfig->fEnableTailDisplacement != TRUE && f_pVqeConfig->fEnableTailDisplacement != FALSE ) return cOCT6100_ERR_CHANNEL_ENABLE_TAIL_DISPLACEMENT; if ( f_pVqeConfig->fEnableTailDisplacement == TRUE && pImageInfo->fTailDisplacement == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TAIL_DISPLACEMENT; /* Check the Tail displacement value.*/ if ( f_pVqeConfig->fEnableTailDisplacement == TRUE ) { if ( f_pVqeConfig->ulTailDisplacement != cOCT6100_AUTO_SELECT_TAIL ) { /* Check if this feature is supported by the image. */ if ( pImageInfo->fPerChannelTailDisplacement == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_PER_CHAN_TAIL; /* Check that this value is not greater then what the image supports. */ if ( f_pVqeConfig->ulTailDisplacement > pImageInfo->usMaxTailDisplacement ) return cOCT6100_ERR_CHANNEL_TAIL_DISPLACEMENT_INVALID; } } /* Check the tail length value. */ if ( f_pVqeConfig->ulTailLength != cOCT6100_AUTO_SELECT_TAIL ) { /* Check if this feature is supported by the image. */ if ( ( pImageInfo->fPerChannelTailLength == FALSE ) && ( (UINT16)( f_pVqeConfig->ulTailLength & 0xFFFF ) != pImageInfo->usMaxTailLength ) ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TAIL_LENGTH; if ( ( f_pVqeConfig->ulTailLength < 32 ) || ( f_pVqeConfig->ulTailLength > 128 ) || ( ( f_pVqeConfig->ulTailLength % 4 ) != 0x0 ) ) return cOCT6100_ERR_CHANNEL_TAIL_LENGTH; /* Check if the requested tail length is supported by the chip. */ if ( f_pVqeConfig->ulTailLength > pImageInfo->usMaxTailLength ) return cOCT6100_ERR_CHANNEL_TAIL_LENGTH_INVALID; } /* Validate the acoustic echo cancellation parameter.*/ if ( f_pVqeConfig->fAcousticEcho != TRUE && f_pVqeConfig->fAcousticEcho != FALSE ) return cOCT6100_ERR_CHANNEL_ACOUSTIC_ECHO; if ( f_pVqeConfig->fAcousticEcho == TRUE && pImageInfo->fAcousticEcho == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ACOUSTIC_ECHO; if ( f_pVqeConfig->fAcousticEcho == TRUE ) { /* Check if acoustic echo tail length configuration is supported in the image. */ if ( ( f_pVqeConfig->ulAecTailLength != 128 ) && ( pImageInfo->fAecTailLength == FALSE ) ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ACOUSTIC_ECHO_TAIL_LENGTH; /* Check the requested acoustic echo tail length. */ if ( ( f_pVqeConfig->ulAecTailLength != 128 ) && ( f_pVqeConfig->ulAecTailLength != 256 ) && ( f_pVqeConfig->ulAecTailLength != 512 ) && ( f_pVqeConfig->ulAecTailLength != 1024 ) ) return cOCT6100_ERR_CHANNEL_ACOUSTIC_ECHO_TAIL_LENGTH; if ( f_pVqeConfig->fEnableTailDisplacement == TRUE ) { UINT32 ulTailSum; /* Start with requested tail displacement. */ if ( f_pVqeConfig->ulTailDisplacement == cOCT6100_AUTO_SELECT_TAIL ) { ulTailSum = f_pApiInstance->pSharedInfo->ChipConfig.usTailDisplacement; } else { ulTailSum = f_pVqeConfig->ulTailDisplacement; } /* Add requested tail length. */ if ( f_pVqeConfig->ulTailLength == cOCT6100_AUTO_SELECT_TAIL ) { ulTailSum += f_pApiInstance->pSharedInfo->ImageInfo.usMaxTailLength; } else { ulTailSum += f_pVqeConfig->ulTailLength; } /* The tail sum must be smaller then the requested AEC tail length. */ if ( ulTailSum > f_pVqeConfig->ulAecTailLength ) return cOCT6100_ERR_CHANNEL_ACOUSTIC_ECHO_TAIL_SUM; } } /* Validate the Default ERL parameter.*/ if ( f_pVqeConfig->lDefaultErlDb != -6 && pImageInfo->fDefaultErl == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_DEFAULT_ERL; if ( ( f_pVqeConfig->lDefaultErlDb != 0 ) && ( f_pVqeConfig->lDefaultErlDb != -3 ) && ( f_pVqeConfig->lDefaultErlDb != -6 ) && ( f_pVqeConfig->lDefaultErlDb != -9 ) && ( f_pVqeConfig->lDefaultErlDb != -12 ) ) return cOCT6100_ERR_CHANNEL_DEFAULT_ERL; /* Validate the Default AEC ERL parameter.*/ if ( f_pVqeConfig->lAecDefaultErlDb != 0 && pImageInfo->fAecDefaultErl == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_AEC_DEFAULT_ERL; if ( f_pVqeConfig->lAecDefaultErlDb != 0 && f_pVqeConfig->lAecDefaultErlDb != -3 && f_pVqeConfig->lAecDefaultErlDb != -6 ) return cOCT6100_ERR_CHANNEL_AEC_DEFAULT_ERL; /* Validate the non-linearity A parameter.*/ if ( f_pVqeConfig->ulNonLinearityBehaviorA != 1 && pImageInfo->fNonLinearityBehaviorA == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_DOUBLE_TALK; if ( f_pVqeConfig->ulNonLinearityBehaviorA >= 14 ) return cOCT6100_ERR_CHANNEL_DOUBLE_TALK; /* Validate the non-linearity B parameter.*/ if ( f_pVqeConfig->ulNonLinearityBehaviorB != 0 && pImageInfo->fNonLinearityBehaviorB == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NON_LINEARITY_B; if ( f_pVqeConfig->ulNonLinearityBehaviorB >= 9 ) return cOCT6100_ERR_CHANNEL_NON_LINEARITY_B; /* Check if configuring the double talk behavior is supported in the firmware. */ if ( f_pVqeConfig->ulDoubleTalkBehavior != cOCT6100_DOUBLE_TALK_BEH_NORMAL && pImageInfo->fDoubleTalkBehavior == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_DOUBLE_TALK_BEHAVIOR_MODE; /* Validate the double talk behavior mode parameter. */ if ( f_pVqeConfig->ulDoubleTalkBehavior != cOCT6100_DOUBLE_TALK_BEH_NORMAL && f_pVqeConfig->ulDoubleTalkBehavior != cOCT6100_DOUBLE_TALK_BEH_LESS_AGGRESSIVE ) return cOCT6100_ERR_CHANNEL_DOUBLE_TALK_MODE; /* Validate the Sout automatic listener enhancement ratio. */ if ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != 0 && pImageInfo->fListenerEnhancement == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ALE; if ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb > 30 ) return cOCT6100_ERR_CHANNEL_ALE_RATIO; /* Validate the Sout natural listener enhancement ratio. */ if ( f_pVqeConfig->fSoutNaturalListenerEnhancement != TRUE && f_pVqeConfig->fSoutNaturalListenerEnhancement != FALSE ) return cOCT6100_ERR_CHANNEL_NLE_FLAG; if ( f_pVqeConfig->fSoutNaturalListenerEnhancement == TRUE && pImageInfo->fListenerEnhancement == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_NLE; if ( f_pVqeConfig->fSoutNaturalListenerEnhancement == TRUE ) { if ( f_pVqeConfig->ulSoutNaturalListenerEnhancementGainDb > 30 ) return cOCT6100_ERR_CHANNEL_NLE_RATIO; } /* Both ALE and NLE cannot be activated simultaneously. */ if ( ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != 0 ) && ( f_pVqeConfig->fSoutNaturalListenerEnhancement == TRUE ) ) return cOCT6100_ERR_CHANNEL_ALE_NLE_SIMULTANEOUSLY; /* Validate Rout noise reduction. */ if ( f_pVqeConfig->fRoutNoiseReduction != TRUE && f_pVqeConfig->fRoutNoiseReduction != FALSE ) return cOCT6100_ERR_CHANNEL_ROUT_NOISE_REDUCTION; /* Check if Rout noise reduction is supported. */ if ( f_pVqeConfig->fRoutNoiseReduction == TRUE && pImageInfo->fRoutNoiseReduction == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ROUT_NR; /* Check if ANR SNRE is supported. */ if ( ( f_pVqeConfig->lAnrSnrEnhancementDb != -18 ) && ( pImageInfo->fAnrSnrEnhancement == FALSE ) ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ANR_SNR_ENHANCEMENT; /* Validate Sout ANR SNR enhancement. */ if ( ( f_pVqeConfig->lAnrSnrEnhancementDb != -9 ) && ( f_pVqeConfig->lAnrSnrEnhancementDb != -12 ) && ( f_pVqeConfig->lAnrSnrEnhancementDb != -15 ) && ( f_pVqeConfig->lAnrSnrEnhancementDb != -18 ) && ( f_pVqeConfig->lAnrSnrEnhancementDb != -21 ) && ( f_pVqeConfig->lAnrSnrEnhancementDb != -24 ) && ( f_pVqeConfig->lAnrSnrEnhancementDb != -27 ) && ( f_pVqeConfig->lAnrSnrEnhancementDb != -30 ) ) return cOCT6100_ERR_CHANNEL_ANR_SNR_ENHANCEMENT; /* Validate ANR voice-noise segregation. */ if ( f_pVqeConfig->ulAnrVoiceNoiseSegregation > 15 ) return cOCT6100_ERR_CHANNEL_ANR_SEGREGATION; /* Check if ANR VN segregation is supported. */ if ( ( f_pVqeConfig->ulAnrVoiceNoiseSegregation != 6 ) && ( pImageInfo->fAnrVoiceNoiseSegregation == FALSE ) ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ANR_SEGREGATION; /* Check if the loaded image supports tone disabler VQE activation delay. */ if ( ( f_pVqeConfig->ulToneDisablerVqeActivationDelay != 300 ) && ( pImageInfo->fToneDisablerVqeActivationDelay == FALSE ) ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_TONE_DISABLER_ACTIVATION_DELAY; /* Check if the specified tone disabler VQE activation delay is correct. */ if ( ( f_pVqeConfig->ulToneDisablerVqeActivationDelay < 300 ) || ( ( ( f_pVqeConfig->ulToneDisablerVqeActivationDelay - 300 ) % 512 ) != 0 ) ) return cOCT6100_ERR_CHANNEL_TONE_DISABLER_ACTIVATION_DELAY; /* Check if the tone disabler is activated when the user requests a different activation delay. */ if ( ( f_pVqeConfig->ulToneDisablerVqeActivationDelay != 300 ) && ( f_fEnableToneDisabler == FALSE ) ) return cOCT6100_ERR_CHANNEL_MUST_ENABLE_TONE_DISABLER; /* Check the enable music protection flag. */ if ( ( f_pVqeConfig->fEnableMusicProtection != TRUE ) && ( f_pVqeConfig->fEnableMusicProtection != FALSE ) ) return cOCT6100_ERR_CHANNEL_ENABLE_MUSIC_PROTECTION; /* The music protection module can only be activated if the image supports it. */ if ( ( f_pVqeConfig->fEnableMusicProtection == TRUE ) && ( pImageInfo->fMusicProtection == FALSE ) ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_MUSIC_PROTECTION; /* Check the enable idle code detection flag. */ if ( ( f_pVqeConfig->fIdleCodeDetection != TRUE ) && ( f_pVqeConfig->fIdleCodeDetection != FALSE ) ) return cOCT6100_ERR_CHANNEL_IDLE_CODE_DETECTION; /* The idle code detection module can only be activated if the image supports it. */ if ( ( f_pVqeConfig->fIdleCodeDetection == TRUE ) && ( pImageInfo->fIdleCodeDetection == FALSE ) ) return cOCT6100_ERR_NOT_SUPPORTED_IDLE_CODE_DETECTION; /* The idle code detection module can be disabled only if idle code detection configuration */ /* is supported in the image. */ if ( ( f_pVqeConfig->fIdleCodeDetection == FALSE ) && ( pImageInfo->fIdleCodeDetectionConfiguration == FALSE ) ) return cOCT6100_ERR_NOT_SUPPORTED_IDLE_CODE_DETECTION_CONFIG; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiCheckCodecConfig Description: This function will check the validity of the Codec config parameter of an Open Codec config structure. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pCodecConfig Codec config of the channel. f_ulDecoderNumTssts Number of TSST for the decoder. f_pusPhasingTsstIndex Pointer to the Phasing TSST index within the API's phasing TSST list. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiCheckCodecConfig( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_OPEN_CODEC f_pCodecConfig, IN UINT32 f_ulDecoderNumTssts, OUT PUINT16 f_pusPhasingTsstIndex ) { /* Verify the ADPCM nibble value.*/ if ( f_pCodecConfig->ulAdpcmNibblePosition != cOCT6100_ADPCM_IN_LOW_BITS && f_pCodecConfig->ulAdpcmNibblePosition != cOCT6100_ADPCM_IN_HIGH_BITS ) return cOCT6100_ERR_CHANNEL_ADPCM_NIBBLE; /* Verify the Encoder port.*/ if ( f_pCodecConfig->ulEncoderPort != cOCT6100_CHANNEL_PORT_ROUT && f_pCodecConfig->ulEncoderPort != cOCT6100_CHANNEL_PORT_SOUT && f_pCodecConfig->ulEncoderPort != cOCT6100_NO_ENCODING ) return cOCT6100_ERR_CHANNEL_ENCODER_PORT; /* Verify the Decoder port.*/ if ( f_pCodecConfig->ulDecoderPort != cOCT6100_CHANNEL_PORT_RIN && f_pCodecConfig->ulDecoderPort != cOCT6100_CHANNEL_PORT_SIN && f_pCodecConfig->ulDecoderPort != cOCT6100_NO_DECODING ) return cOCT6100_ERR_CHANNEL_DECODER_PORT; /* The codec cannot be on the same stream.*/ if ( f_pCodecConfig->ulEncoderPort == cOCT6100_CHANNEL_PORT_ROUT && f_pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) return cOCT6100_ERR_CHANNEL_INVALID_CODEC_POSITION; if ( f_pCodecConfig->ulEncoderPort == cOCT6100_CHANNEL_PORT_SOUT && f_pCodecConfig->ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN ) return cOCT6100_ERR_CHANNEL_INVALID_CODEC_POSITION; /* Verify if the requested functions are supported by the chip.*/ if ( f_pApiInstance->pSharedInfo->ImageInfo.fAdpcm == FALSE && f_pCodecConfig->ulEncoderPort != cOCT6100_NO_ENCODING ) { if ( f_pCodecConfig->ulEncodingRate != cOCT6100_G711_64KBPS ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_ENCODING; } if ( f_pApiInstance->pSharedInfo->ImageInfo.fAdpcm == FALSE && f_pCodecConfig->ulDecoderPort != cOCT6100_NO_DECODING ) { if ( f_pCodecConfig->ulDecodingRate != cOCT6100_G711_64KBPS ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_DECODING; } /* Check if encoder port has been specified when a rate has been set. */ if ( f_pCodecConfig->ulEncoderPort == cOCT6100_NO_ENCODING && f_pCodecConfig->ulEncodingRate != cOCT6100_G711_64KBPS ) return cOCT6100_ERR_CHANNEL_ENCODER_PORT; /* Check if decoder port has been specified when a rate has been set. */ if ( f_pCodecConfig->ulDecoderPort == cOCT6100_NO_DECODING && f_pCodecConfig->ulDecodingRate != cOCT6100_G711_64KBPS ) return cOCT6100_ERR_CHANNEL_DECODER_PORT; /* Check Encoder related parameter if one is used.*/ if ( f_pCodecConfig->ulEncoderPort != cOCT6100_NO_ENCODING ) { /* Check the Encoder compression rate.*/ if ( ( f_pCodecConfig->ulEncodingRate != cOCT6100_G711_64KBPS ) && ( f_pCodecConfig->ulEncodingRate != cOCT6100_G726_40KBPS ) && ( f_pCodecConfig->ulEncodingRate != cOCT6100_G726_32KBPS ) && ( f_pCodecConfig->ulEncodingRate != cOCT6100_G726_24KBPS ) && ( f_pCodecConfig->ulEncodingRate != cOCT6100_G726_16KBPS ) && ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_40KBPS_4_1 ) && ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_40KBPS_3_2 ) && ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_40KBPS_2_3 ) && ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_32KBPS_4_0 ) && ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_32KBPS_3_1 ) && ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_32KBPS_2_2 ) && ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_24KBPS_3_0 ) && ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_24KBPS_2_1 ) && ( f_pCodecConfig->ulEncodingRate != cOCT6100_G727_16KBPS_2_0 ) ) return cOCT6100_ERR_CHANNEL_ENCODING_RATE; /* Verify phasing information.*/ if ( f_pCodecConfig->ulPhasingType != cOCT6100_SINGLE_PHASING && f_pCodecConfig->ulPhasingType != cOCT6100_DUAL_PHASING && f_pCodecConfig->ulPhasingType != cOCT6100_NO_PHASING ) return cOCT6100_ERR_CHANNEL_PHASING_TYPE; /* Verify the silence suppression parameters.*/ if ( f_pCodecConfig->fEnableSilenceSuppression != TRUE && f_pCodecConfig->fEnableSilenceSuppression != FALSE ) return cOCT6100_ERR_CHANNEL_SIL_SUP_ENABLE; if ( f_pCodecConfig->fEnableSilenceSuppression == TRUE && f_pApiInstance->pSharedInfo->ImageInfo.fSilenceSuppression == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SIL_SUP; if ( f_pCodecConfig->fEnableSilenceSuppression == TRUE && f_pCodecConfig->ulPhasingType == cOCT6100_NO_PHASING ) return cOCT6100_ERR_CHANNEL_PHASE_TYPE_REQUIRED; if ( f_pCodecConfig->fEnableSilenceSuppression == TRUE && f_pCodecConfig->ulPhasingTsstHndl == cOCT6100_INVALID_HANDLE ) return cOCT6100_ERR_CHANNEL_PHASING_TSST_REQUIRED; if ( f_pCodecConfig->ulPhasingTsstHndl == cOCT6100_INVALID_HANDLE && f_pCodecConfig->ulPhasingType != cOCT6100_NO_PHASING ) return cOCT6100_ERR_CHANNEL_PHASING_TSST_REQUIRED; /* Silence suppression can only be performed if the encoder is using the SOUT port.*/ if ( f_pCodecConfig->fEnableSilenceSuppression == TRUE && f_pCodecConfig->ulEncoderPort != cOCT6100_CHANNEL_PORT_SOUT ) return cOCT6100_ERR_CHANNEL_SIL_SUP_INVALID_ENCODER_PORT; /* Check phasing TSST info if phasing is required.*/ if ( f_pCodecConfig->ulPhasingTsstHndl != cOCT6100_INVALID_HANDLE ) { tPOCT6100_API_PHASING_TSST pPhasingEntry; UINT32 ulEntryOpenCnt; /* Check the provided handle. */ if ( (f_pCodecConfig->ulPhasingTsstHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_PHASING_TSST ) return cOCT6100_ERR_CHANNEL_INVALID_PHASING_HANDLE; *f_pusPhasingTsstIndex = (UINT16)( f_pCodecConfig->ulPhasingTsstHndl & cOCT6100_HNDL_INDEX_MASK ); if ( *f_pusPhasingTsstIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxPhasingTssts ) return cOCT6100_ERR_CHANNEL_INVALID_PHASING_HANDLE; mOCT6100_GET_PHASING_TSST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPhasingEntry, *f_pusPhasingTsstIndex ); /* Extract the entry open count from the provided handle. */ ulEntryOpenCnt = (f_pCodecConfig->ulPhasingTsstHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; /* Verify if the state of the phasing TSST.*/ if ( pPhasingEntry->fReserved != TRUE ) return cOCT6100_ERR_CHANNEL_PHASING_TSST_NOT_OPEN; if ( ulEntryOpenCnt != pPhasingEntry->byEntryOpenCnt ) return cOCT6100_ERR_CHANNEL_INVALID_PHASING_HANDLE; /* Check the specified phase value against the phasing length of the phasing TSST.*/ if ( f_pCodecConfig->ulPhase >= pPhasingEntry->usPhasingLength ) return cOCT6100_ERR_CHANNEL_PHASING_INVALID_PHASE; } else { *f_pusPhasingTsstIndex = cOCT6100_INVALID_INDEX; } } else { *f_pusPhasingTsstIndex = cOCT6100_INVALID_INDEX; } /* Check Decoder related parameter if one is used.*/ if ( f_pCodecConfig->ulDecoderPort != cOCT6100_NO_DECODING ) { /* Check the Decoding rate.*/ if ( f_pCodecConfig->ulDecodingRate != cOCT6100_G711_64KBPS && f_pCodecConfig->ulDecodingRate != cOCT6100_G726_40KBPS && f_pCodecConfig->ulDecodingRate != cOCT6100_G726_32KBPS && f_pCodecConfig->ulDecodingRate != cOCT6100_G726_24KBPS && f_pCodecConfig->ulDecodingRate != cOCT6100_G726_16KBPS && f_pCodecConfig->ulDecodingRate != cOCT6100_G726_ENCODED && f_pCodecConfig->ulDecodingRate != cOCT6100_G711_G726_ENCODED && f_pCodecConfig->ulDecodingRate != cOCT6100_G727_2C_ENCODED && f_pCodecConfig->ulDecodingRate != cOCT6100_G727_3C_ENCODED && f_pCodecConfig->ulDecodingRate != cOCT6100_G727_4C_ENCODED && f_pCodecConfig->ulDecodingRate != cOCT6100_G711_G727_2C_ENCODED && f_pCodecConfig->ulDecodingRate != cOCT6100_G711_G727_3C_ENCODED && f_pCodecConfig->ulDecodingRate != cOCT6100_G711_G727_4C_ENCODED ) return cOCT6100_ERR_CHANNEL_DECODING_RATE; /* Make sure that two timeslot are allocated if PCM-ECHO encoded is selected.*/ if ( (f_pCodecConfig->ulDecodingRate == cOCT6100_G711_G726_ENCODED || f_pCodecConfig->ulDecodingRate == cOCT6100_G711_G727_2C_ENCODED || f_pCodecConfig->ulDecodingRate == cOCT6100_G711_G727_3C_ENCODED || f_pCodecConfig->ulDecodingRate == cOCT6100_G711_G727_4C_ENCODED ) && f_ulDecoderNumTssts != 2 ) return cOCT6100_ERR_CHANNEL_MISSING_TSST; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteInputTsstControlMemory Description: This function configure a TSST control memory entry in internal memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usTsstIndex TSST index within the TSST control memory. f_usTsiMemIndex TSI index within the TSI chariot memory. f_ulTsstInputLaw PCM law of the input TSST. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWriteInputTsstControlMemory( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usTsstIndex, IN UINT16 f_usTsiMemIndex, IN UINT32 f_ulTsstInputLaw ) { tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (f_usTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_TSST_CONTROL_MEM_INPUT_TSST; WriteParams.usWriteData |= f_usTsiMemIndex & cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK; /* Set the PCM law.*/ WriteParams.usWriteData |= f_ulTsstInputLaw << cOCT6100_TSST_CONTROL_MEM_PCM_LAW_OFFSET; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteOutputTsstControlMemory Description: This function configure a TSST control memory entry in internal memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWriteOutputTsstControlMemory( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usTsstIndex, IN UINT32 f_ulAdpcmNibblePosition, IN UINT32 f_ulNumTssts, IN UINT16 f_usTsiMemIndex ) { tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( (f_usTsstIndex & cOCT6100_TSST_INDEX_MASK) * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_TSST_CONTROL_MEM_OUTPUT_TSST; WriteParams.usWriteData |= f_ulAdpcmNibblePosition << cOCT6100_TSST_CONTROL_MEM_NIBBLE_POS_OFFSET; WriteParams.usWriteData |= (f_ulNumTssts - 1) << cOCT6100_TSST_CONTROL_MEM_TSST_NUM_OFFSET; WriteParams.usWriteData |= f_usTsiMemIndex & cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteEncoderMemory Description: This function configure a Encoded memory entry in internal memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulEncoderIndex Index of the encoder block within the ADPCM context memory. f_ulCompType Compression rate of the encoder. f_usTsiMemIndex TSI index within the TSI chariot memory used by the encoder. f_ulEnableSilenceSuppression Silence suppression enable flag. f_ulAdpcmNibblePosition ADPCM nibble position. f_usPhasingTsstIndex Phasing TSST index within the API's Phassing TSST list. f_ulPhasingType Type of the Phasing TSST. f_ulPhase Phase used with this encoder. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWriteEncoderMemory( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulEncoderIndex, IN UINT32 f_ulCompType, IN UINT16 f_usTsiMemIndex, IN UINT32 f_ulEnableSilenceSuppression, IN UINT32 f_ulAdpcmNibblePosition, IN UINT16 f_usPhasingTsstIndex, IN UINT32 f_ulPhasingType, IN UINT32 f_ulPhase ) { tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; /*==============================================================================*/ /* Conversion Control Base */ WriteParams.ulWriteAddress = cOCT6100_CONVERSION_CONTROL_MEM_BASE + ( f_ulEncoderIndex * cOCT6100_CONVERSION_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_ENCODER; WriteParams.usWriteData |= f_ulCompType << cOCT6100_CONVERSION_CONTROL_MEM_COMP_OFFSET; WriteParams.usWriteData |= f_usTsiMemIndex & cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ /* Conversion Control Base + 2 */ WriteParams.ulWriteAddress += 2; /* Set the phasing TSST number.*/ if ( f_usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) WriteParams.usWriteData = (UINT16)( f_usPhasingTsstIndex << cOCT6100_CONVERSION_CONTROL_MEM_PHASE_OFFSET ); else WriteParams.usWriteData = 0; /* Set the phasing type and the phase value if required.*/ switch( f_ulPhasingType ) { case cOCT6100_NO_PHASING: WriteParams.usWriteData |= 0x1 << 10; break; case cOCT6100_SINGLE_PHASING: WriteParams.usWriteData |= f_ulPhase; break; case cOCT6100_DUAL_PHASING: WriteParams.usWriteData |= 0x1 << 11; WriteParams.usWriteData |= f_ulPhase; break; default: /* No problem. */ break; } /* Set the silence suppression flag.*/ WriteParams.usWriteData |= f_ulEnableSilenceSuppression << cOCT6100_CONVERSION_CONTROL_MEM_SIL_SUP_OFFSET; /* Set the nibble position.*/ WriteParams.usWriteData |= f_ulAdpcmNibblePosition << cOCT6100_CONVERSION_CONTROL_MEM_NIBBLE_POS_OFFSET; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ /* Conversion Control Base + 4 */ WriteParams.ulWriteAddress += 2; /* Set the reset mode */ WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_RST_ON_NEXT_FR; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ /* Conversion Control Base + 6 */ WriteParams.ulWriteAddress += 2; /* Set the reset mode */ WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_ACTIVATE_ENTRY; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteDecoderMemory Description: This function configure a Decoder memory entry in internal memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usDecoderIndex Index of the decoder block within the ADPCM context memory. f_ulCompType Decompression rate of the decoder. f_usTsiMemIndex TSI index within the TSI chariot memory. f_ulPcmLaw PCM law of the decoded samples. f_ulAdpcmNibblePosition ADPCM nibble position. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWriteDecoderMemory( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usDecoderIndex, IN UINT32 f_ulCompType, IN UINT16 f_usTsiMemIndex, IN UINT32 f_ulPcmLaw, IN UINT32 f_ulAdpcmNibblePosition ) { tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; /*==============================================================================*/ /* Conversion Control Base */ WriteParams.ulWriteAddress = cOCT6100_CONVERSION_CONTROL_MEM_BASE + ( f_usDecoderIndex * cOCT6100_CONVERSION_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_DECODER; WriteParams.usWriteData |= f_ulCompType << cOCT6100_CONVERSION_CONTROL_MEM_COMP_OFFSET; WriteParams.usWriteData |= f_usTsiMemIndex & cOCT6100_TSST_CONTROL_MEM_TSI_MEM_MASK; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ /* Conversion Control Base + 2 */ WriteParams.ulWriteAddress += 2; /* Set the nibble position.*/ WriteParams.usWriteData = (UINT16)( f_ulAdpcmNibblePosition << cOCT6100_CONVERSION_CONTROL_MEM_NIBBLE_POS_OFFSET ); /* Set the law.*/ WriteParams.usWriteData |= f_ulPcmLaw << cOCT6100_CONVERSION_CONTROL_MEM_LAW_OFFSET; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ /* Conversion Control Base + 4 */ WriteParams.ulWriteAddress += 2; /* Set the reset mode */ WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_RST_ON_NEXT_FR; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ /* Conversion Control Base + 6 */ WriteParams.ulWriteAddress += 2; /* Set the reset mode */ WriteParams.usWriteData = cOCT6100_CONVERSION_CONTROL_MEM_ACTIVATE_ENTRY; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiClearConversionMemory Description: This function clears a conversion memory entry in internal memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usConversionMemIndex Index of the block within the conversion memory. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiClearConversionMemory( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usConversionMemIndex ) { tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_READ_PARAMS ReadParams; UINT32 ulResult; UINT32 ulBaseAddress; UINT16 usReadData; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; WriteParams.usWriteData = 0; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; /*==============================================================================*/ /* Clear the entry */ ulBaseAddress = cOCT6100_CONVERSION_CONTROL_MEM_BASE + ( f_usConversionMemIndex * cOCT6100_CONVERSION_CONTROL_MEM_ENTRY_SIZE ); /* The "activate" bit at offset +6 must be cleared first. */ WriteParams.ulWriteAddress = ulBaseAddress + 6; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Read at 0x200 to make sure there is no corruption on channel 0. */ ReadParams.ulReadAddress = 0x200; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Then clear the rest of the structure. */ WriteParams.ulWriteAddress = ulBaseAddress + 4; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = ulBaseAddress + 2; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = ulBaseAddress; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteVqeMemory Description: This function configure an echo memory entry in internal memory and external memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pVqeConfig Pointer to a VQE config structure. f_pChannelOpen Pointer to a channel configuration structure. f_usChanIndex Index of the echo channel in the API instance. f_usEchoMemIndex Index of the echo channel within the SSPX memory. f_fClearPlayoutPointers Flag indicating if the playout pointer should be cleared. f_fModifyOnly Flag indicating if the configuration should be modified only. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWriteVqeMemory( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, IN UINT16 f_usChanIndex, IN UINT16 f_usEchoMemIndex, IN BOOL f_fClearPlayoutPointers, IN BOOL f_fModifyOnly ) { UINT32 ulResult; /* Write the NLP software configuration structure. */ ulResult = Oct6100ApiWriteVqeNlpMemory( f_pApiInstance, f_pVqeConfig, f_pChannelOpen, f_usChanIndex, f_usEchoMemIndex, f_fClearPlayoutPointers, f_fModifyOnly ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write the AF software configuration structure. */ ulResult = Oct6100ApiWriteVqeAfMemory( f_pApiInstance, f_pVqeConfig, f_pChannelOpen, f_usChanIndex, f_usEchoMemIndex, f_fClearPlayoutPointers, f_fModifyOnly ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteVqeNlpMemory Description: This function configures the NLP related VQE features of an echo channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pVqeConfig Pointer to a VQE config structure. f_pChannelOpen Pointer to a channel configuration structure. f_usChanIndex Index of the echo channel in the API instance. f_usEchoMemIndex Index of the echo channel within the SSPX memory. f_fClearPlayoutPointers Flag indicating if the playout pointer should be cleared. f_fModifyOnly Flag indicating if the configuration should be modified only. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWriteVqeNlpMemory( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, IN UINT16 f_usChanIndex, IN UINT16 f_usEchoMemIndex, IN BOOL f_fClearPlayoutPointers, IN BOOL f_fModifyOnly ) { tPOCT6100_API_CHANNEL pChanEntry; tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_BUFFER_PLAYOUT_STOP BufferPlayoutStop; UINT32 ulResult; UINT32 ulTempData; UINT32 ulNlpConfigBaseAddress; UINT32 ulFeatureBytesOffset; UINT32 ulFeatureBitOffset; UINT32 ulFeatureFieldLength; UINT32 ulMask; UINT16 usTempData; BOOL fEchoOperationModeChanged; pSharedInfo = f_pApiInstance->pSharedInfo; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* Obtain a pointer to the new buffer's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ); /*==============================================================================*/ /* Configure the CPU NLP configuration of the channel feature by feature.*/ ulNlpConfigBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; /* Set initial value to zero.*/ ulTempData = 0; /* Configure Adaptive Noise Reduction.*/ if ( pSharedInfo->ImageInfo.fAdaptiveNoiseReduction == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( ( f_pVqeConfig->fSoutAdaptiveNoiseReduction != pChanEntry->VqeConfig.fSoutAdaptiveNoiseReduction ) || ( f_pVqeConfig->fSoutNoiseBleaching != pChanEntry->VqeConfig.fSoutNoiseBleaching ) ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.AdaptiveNoiseReductionOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.AdaptiveNoiseReductionOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.AdaptiveNoiseReductionOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* Set adaptive noise reduction on the SOUT port.*/ ulTempData |= ( ( (UINT32)f_pVqeConfig->fSoutAdaptiveNoiseReduction ) << ulFeatureBitOffset ); /* If SOUT noise bleaching is requested, ANR must be activated. */ ulTempData |= ( ( (UINT32)f_pVqeConfig->fSoutNoiseBleaching ) << ulFeatureBitOffset ); /* First read the DWORD where the field is located. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Configure Rout Noise Reduction. */ if ( pSharedInfo->ImageInfo.fRoutNoiseReduction == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pVqeConfig->fRoutNoiseReduction != pChanEntry->VqeConfig.fRoutNoiseReduction ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinAnrOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.RinAnrOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.RinAnrOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* Set noise reduction on the Rout port. */ ulTempData |= ( ( (UINT32)f_pVqeConfig->fRoutNoiseReduction ) << ulFeatureBitOffset ); /* Write the new DWORD where the field is located. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Configure Sout ANR SNR enhancement. */ if ( pSharedInfo->ImageInfo.fAnrSnrEnhancement == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pVqeConfig->lAnrSnrEnhancementDb != pChanEntry->VqeConfig.chAnrSnrEnhancementDb ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.AnrSnrEnhancementOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.AnrSnrEnhancementOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.AnrSnrEnhancementOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* Set ANR SNR enhancement on the Sout port. */ switch( f_pVqeConfig->lAnrSnrEnhancementDb ) { case -9: ulTempData |= ( 7 << ulFeatureBitOffset ); break; case -12: ulTempData |= ( 6 << ulFeatureBitOffset ); break; case -15: ulTempData |= ( 5 << ulFeatureBitOffset ); break; case -21: ulTempData |= ( 3 << ulFeatureBitOffset ); break; case -24: ulTempData |= ( 2 << ulFeatureBitOffset ); break; case -27: ulTempData |= ( 1 << ulFeatureBitOffset ); break; case -30: ulTempData |= ( 0 << ulFeatureBitOffset ); break; default: ulTempData |= ( 4 << ulFeatureBitOffset ); /* -18 */ break; } /* Write the new DWORD where the field is located. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Configure Sout ANR voice-noise segregation. */ if ( pSharedInfo->ImageInfo.fAnrVoiceNoiseSegregation == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pVqeConfig->ulAnrVoiceNoiseSegregation != pChanEntry->VqeConfig.byAnrVoiceNoiseSegregation ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.AnrVoiceNoiseSegregationOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.AnrVoiceNoiseSegregationOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.AnrVoiceNoiseSegregationOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* Set ANR voice-noise segregation on the Sout port. */ ulTempData |= ( ( (UINT32)f_pVqeConfig->ulAnrVoiceNoiseSegregation ) << ulFeatureBitOffset ); /* Write the new DWORD where the field is located. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Configure the tone disabler VQE activation delay. */ if ( pSharedInfo->ImageInfo.fToneDisablerVqeActivationDelay == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pVqeConfig->ulToneDisablerVqeActivationDelay != pChanEntry->VqeConfig.usToneDisablerVqeActivationDelay ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.ToneDisablerVqeActivationDelayOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.ToneDisablerVqeActivationDelayOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.ToneDisablerVqeActivationDelayOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* Set the tone disabler VQE activation delay. */ ulTempData |= ( ( (UINT32)( ( f_pVqeConfig->ulToneDisablerVqeActivationDelay - 300 ) / 512 ) ) << ulFeatureBitOffset ); /* Write the new DWORD where the field is located. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Configure Conferencing Noise Reduction.*/ if ( pSharedInfo->ImageInfo.fConferencingNoiseReduction == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( ( f_pVqeConfig->fSoutConferencingNoiseReduction != pChanEntry->VqeConfig.fSoutConferencingNoiseReduction ) || ( f_pVqeConfig->fSoutNoiseBleaching != pChanEntry->VqeConfig.fSoutNoiseBleaching ) ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.ConferencingNoiseReductionOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.ConferencingNoiseReductionOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.ConferencingNoiseReductionOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* Set conferencing noise reduction on the SOUT port. */ ulTempData |= (f_pVqeConfig->fSoutConferencingNoiseReduction << ulFeatureBitOffset ); /* If SOUT noise bleaching is requested, CNR must be activated. */ ulTempData |= (f_pVqeConfig->fSoutNoiseBleaching << ulFeatureBitOffset ); /* Save the DWORD where the field is located. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Set the DC removal on RIN ports.*/ if ( pSharedInfo->ImageInfo.fRinDcOffsetRemoval == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pVqeConfig->fRinDcOffsetRemoval != pChanEntry->VqeConfig.fRinDcOffsetRemoval ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinDcOffsetRemovalOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.RinDcOffsetRemovalOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.RinDcOffsetRemovalOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* Set adaptive noise reduction on the SOUT port.*/ ulTempData |= ( ( (UINT32)f_pVqeConfig->fRinDcOffsetRemoval ) << ulFeatureBitOffset ); /* The write the new DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Set the DC removal on SIN ports.*/ if ( pSharedInfo->ImageInfo.fSinDcOffsetRemoval == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pVqeConfig->fSinDcOffsetRemoval != pChanEntry->VqeConfig.fSinDcOffsetRemoval ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.SinDcOffsetRemovalOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.SinDcOffsetRemovalOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.SinDcOffsetRemovalOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* Set adaptive noise reduction on the SOUT port.*/ ulTempData |= ( ( (UINT32)f_pVqeConfig->fSinDcOffsetRemoval ) << ulFeatureBitOffset ); /* Save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Set the level control. */ if ( ( pChanEntry->byEchoOperationMode != f_pChannelOpen->ulEchoOperationMode ) && ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NORMAL ) ) fEchoOperationModeChanged = TRUE; else fEchoOperationModeChanged = FALSE; /* If opening the channel, all level control configuration must be written. */ if ( f_fModifyOnly == FALSE ) fEchoOperationModeChanged = TRUE; ulResult = Oct6100ApiSetChannelLevelControl( f_pApiInstance, f_pVqeConfig, f_usChanIndex, f_usEchoMemIndex, fEchoOperationModeChanged ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set the background noise freeze.*/ if ( pSharedInfo->ImageInfo.fComfortNoise == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pVqeConfig->ulComfortNoiseMode != pChanEntry->VqeConfig.byComfortNoiseMode ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.ComfortNoiseModeOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.ComfortNoiseModeOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.ComfortNoiseModeOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); ulTempData |= ( f_pVqeConfig->ulComfortNoiseMode << ulFeatureBitOffset ); /* Save the new DWORD where the field is located. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Set the state of the NLP */ if ( pSharedInfo->ImageInfo.fNlpControl == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pVqeConfig->fEnableNlp != pChanEntry->VqeConfig.fEnableNlp ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.NlpControlFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.NlpControlFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.NlpControlFieldOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); if ( f_pVqeConfig->fEnableNlp == FALSE ) ulTempData |= 0x1 << ulFeatureBitOffset; /* Save the new DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Set the tail configuration. */ ulResult = Oct6100ApiSetChannelTailConfiguration( f_pApiInstance, f_pVqeConfig, f_usChanIndex, f_usEchoMemIndex, f_fModifyOnly ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set the Default ERL. */ if ( ( pSharedInfo->ImageInfo.fDefaultErl == TRUE ) && ( f_pVqeConfig->fAcousticEcho == FALSE ) ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( ( f_pVqeConfig->lDefaultErlDb != pChanEntry->VqeConfig.chDefaultErlDb ) || ( f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) || ( f_pVqeConfig->fAcousticEcho != pChanEntry->VqeConfig.fAcousticEcho ) ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.DefaultErlFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.DefaultErlFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.DefaultErlFieldOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* Convert the DB value to octasic's float format. (In energy) */ if ( ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NO_ECHO ) && ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ) { usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lDefaultErlDb ); } else { /* Clear the defautl ERL when using the no echo cancellation operation mode. */ usTempData = 0x0; } if ( ulFeatureFieldLength < 16 ) usTempData = (UINT16)( usTempData >> ( 16 - ulFeatureFieldLength ) ); ulTempData |= ( usTempData << ulFeatureBitOffset ); /* Save the new DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Set the Acoustic echo control.*/ if ( pSharedInfo->ImageInfo.fAcousticEcho == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pVqeConfig->fAcousticEcho != pChanEntry->VqeConfig.fAcousticEcho ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.AecFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.AecFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.AecFieldOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field. */ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); ulTempData |= ( ( (UINT32)f_pVqeConfig->fAcousticEcho ) << ulFeatureBitOffset ); /* Then save the new DWORD where the field is located. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Set the Acoustic Echo Default ERL. */ if ( ( pSharedInfo->ImageInfo.fAecDefaultErl == TRUE ) && ( f_pVqeConfig->fAcousticEcho == TRUE ) ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( ( f_pVqeConfig->lAecDefaultErlDb != pChanEntry->VqeConfig.chAecDefaultErlDb ) || ( f_pVqeConfig->fAcousticEcho != pChanEntry->VqeConfig.fAcousticEcho ) ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.AecDefaultErlFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.AecDefaultErlFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.AecDefaultErlFieldOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field. */ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); if ( ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NO_ECHO ) && ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ) { /* Convert the DB value to octasic's float format. (In energy) */ usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lAecDefaultErlDb ); } else { /* Clear the AEC defautl ERL when using the no echo cancellation operation mode. */ usTempData = 0x0; } if ( ulFeatureFieldLength < 16 ) usTempData = (UINT16)( usTempData >> ( 16 - ulFeatureFieldLength ) ); ulTempData |= ( usTempData << ulFeatureBitOffset ); /* Then save the DWORD where the field is located. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Set the DTMF tone removal bit.*/ if ( pSharedInfo->ImageInfo.fToneRemoval == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pVqeConfig->fDtmfToneRemoval != pChanEntry->VqeConfig.fDtmfToneRemoval ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.ToneRemovalFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.ToneRemovalFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.ToneRemovalFieldOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); ulTempData |= ( ( (UINT32)f_pVqeConfig->fDtmfToneRemoval ) << ulFeatureBitOffset ); /* First read the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Set the non-linear behavior A.*/ if ( pSharedInfo->ImageInfo.fNonLinearityBehaviorA == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( ( f_pVqeConfig->ulNonLinearityBehaviorA != pChanEntry->VqeConfig.byNonLinearityBehaviorA ) || ( f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) ) ) ) { UINT16 ausLookupTable[ 14 ] = { 0x3663, 0x3906, 0x399C, 0x3A47, 0x3B06, 0x3B99, 0x3C47, 0x3D02, 0x3D99, 0x3E47, 0x3F00, 0x3F99, 0x4042, 0x4100 }; ulFeatureBytesOffset = pSharedInfo->MemoryMap.PcmLeakFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.PcmLeakFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.PcmLeakFieldOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); if ( ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) || ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ) ulTempData |= ( 0x0 << ulFeatureBitOffset ); else ulTempData |= ( ausLookupTable[ f_pVqeConfig->ulNonLinearityBehaviorA ] << ulFeatureBitOffset ); /* Then save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Synch all the buffer playout field.*/ if ( pSharedInfo->ImageInfo.fBufferPlayout == TRUE && f_fClearPlayoutPointers == TRUE ) { Oct6100BufferPlayoutStopDef( &BufferPlayoutStop ); BufferPlayoutStop.ulChannelHndl = cOCT6100_INVALID_HANDLE; BufferPlayoutStop.fStopCleanly = TRUE; BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; ulResult = Oct6100ApiInvalidateChanPlayoutStructs( f_pApiInstance, &BufferPlayoutStop, f_usChanIndex, f_usEchoMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; BufferPlayoutStop.ulPlayoutPort = cOCT6100_CHANNEL_PORT_SOUT; ulResult = Oct6100ApiInvalidateChanPlayoutStructs( f_pApiInstance, &BufferPlayoutStop, f_usChanIndex, f_usEchoMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*==============================================================================*/ /* Write the 2100 Hz Echo Disabling mode */ /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pChannelOpen->fEnableToneDisabler != pChanEntry->fEnableToneDisabler ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.ToneDisablerControlOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.ToneDisablerControlOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.ToneDisablerControlOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* This is a disable bit, so it must be set only if the enable flag is set to false. */ if ( f_pChannelOpen->fEnableToneDisabler == FALSE ) ulTempData |= 0x1 << ulFeatureBitOffset; /* Save the DWORD where the field is located. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*==============================================================================*/ /*==============================================================================*/ /* Write the Nlp Trivial enable flag. */ /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( ( f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.NlpTrivialFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.NlpTrivialFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.NlpTrivialFieldOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); if ( ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) || ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ) { ulTempData |= TRUE << ulFeatureBitOffset; } /* Then write the DWORD where the field is located. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*==============================================================================*/ /*==============================================================================*/ /* Set the double talk behavior mode. */ if ( pSharedInfo->ImageInfo.fDoubleTalkBehaviorFieldOfst == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pVqeConfig->ulDoubleTalkBehavior != pChanEntry->VqeConfig.byDoubleTalkBehavior ) ) ) { /* The field is located in the CPURO structure. */ ulFeatureBytesOffset = pSharedInfo->MemoryMap.DoubleTalkBehaviorFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.DoubleTalkBehaviorFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.DoubleTalkBehaviorFieldOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); ulTempData |= (f_pVqeConfig->ulDoubleTalkBehavior << ulFeatureBitOffset ); /* Then save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /*==============================================================================*/ /*==============================================================================*/ /* Set the music protection enable. */ if ( ( pSharedInfo->ImageInfo.fMusicProtection == TRUE ) && ( pSharedInfo->ImageInfo.fMusicProtectionConfiguration == TRUE ) ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pVqeConfig->fEnableMusicProtection != pChanEntry->VqeConfig.fEnableMusicProtection ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.MusicProtectionFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.MusicProtectionFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.MusicProtectionFieldOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); if ( f_pVqeConfig->fEnableMusicProtection == TRUE ) ulTempData |= ( 1 << ulFeatureBitOffset ); /* Then save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /*==============================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteVqeAfMemory Description: This function configures the AF related VQE features of an echo channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pVqeConfig Pointer to a VQE config structure. f_pChannelOpen Pointer to a channel configuration structure. f_usChanIndex Index of the echo channel in the API instance. f_usEchoMemIndex Index of the echo channel within the SSPX memory. f_fClearPlayoutPointers Flag indicating if the playout pointer should be cleared. f_fModifyOnly Flag indicating if the configuration should be modified only. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWriteVqeAfMemory( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, IN UINT16 f_usChanIndex, IN UINT16 f_usEchoMemIndex, IN BOOL f_fClearPlayoutPointers, IN BOOL f_fModifyOnly ) { tPOCT6100_API_CHANNEL pChanEntry; tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; UINT32 ulTempData; UINT32 ulAfConfigBaseAddress; UINT32 ulFeatureBytesOffset; UINT32 ulFeatureBitOffset; UINT32 ulFeatureFieldLength; UINT32 ulMask; UINT16 usTempData; pSharedInfo = f_pApiInstance->pSharedInfo; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* Obtain a pointer to the new buffer's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ); /*==============================================================================*/ /* Write the AF CPU configuration of the channel feature by feature.*/ /* Calculate AF CPU configuration base address. */ ulAfConfigBaseAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst; /* Set initial value to zero.*/ ulTempData = 0; /*==============================================================================*/ /* Program the Maximum echo point within the Main channel memory.*/ if ( pSharedInfo->ImageInfo.fMaxEchoPoint == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( ( f_pVqeConfig->lDefaultErlDb != pChanEntry->VqeConfig.chDefaultErlDb ) || ( f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) ) ) ) { /* Write the echo tail length */ ulFeatureBytesOffset = pSharedInfo->MemoryMap.ChanMainIoMaxEchoPointOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.ChanMainIoMaxEchoPointOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.ChanMainIoMaxEchoPointOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulAfConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* Convert the DB value to octasic's float format.*/ if ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_NO_ECHO ) { usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lDefaultErlDb ); } else { /* Clear max echo point. No echo cancellation here. */ usTempData = 0x0; } if ( ulFeatureFieldLength < 16 ) usTempData = (UINT16)( usTempData >> ( 16 - ulFeatureFieldLength ) ); ulTempData |= usTempData << ulFeatureBitOffset; /* First read the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulAfConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /*==============================================================================*/ /*==============================================================================*/ /* Set the non-linear behavior B.*/ if ( pSharedInfo->ImageInfo.fNonLinearityBehaviorB == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pVqeConfig->ulNonLinearityBehaviorB != pChanEntry->VqeConfig.byNonLinearityBehaviorB ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.NlpConvCapFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.NlpConvCapFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.NlpConvCapFieldOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulAfConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); ulTempData |= (f_pVqeConfig->ulNonLinearityBehaviorB << ulFeatureBitOffset ); /* Then save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulAfConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /*==============================================================================*/ /*==============================================================================*/ /* Set the listener enhancement feature. */ if ( pSharedInfo->ImageInfo.fListenerEnhancement == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != pChanEntry->VqeConfig.bySoutAutomaticListenerEnhancementGainDb ) || ( f_pVqeConfig->fSoutNaturalListenerEnhancement != pChanEntry->VqeConfig.fSoutNaturalListenerEnhancement ) || ( f_pVqeConfig->ulSoutNaturalListenerEnhancementGainDb != pChanEntry->VqeConfig.bySoutNaturalListenerEnhancementGainDb ) ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.AdaptiveAleOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.AdaptiveAleOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.AdaptiveAleOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulAfConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); if ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != 0 ) { UINT32 ulGainDb; ulGainDb = f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb / 3; /* Round up. */ if ( ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb % 3 ) != 0x0 ) ulGainDb ++; ulTempData |= ( ulGainDb << ulFeatureBitOffset ); } else if ( f_pVqeConfig->fSoutNaturalListenerEnhancement != 0 ) { UINT32 ulGainDb; ulGainDb = f_pVqeConfig->ulSoutNaturalListenerEnhancementGainDb / 3; /* Round up. */ if ( ( f_pVqeConfig->ulSoutNaturalListenerEnhancementGainDb % 3 ) != 0x0 ) ulGainDb ++; ulTempData |= ( ( 0x80 | ulGainDb ) << ulFeatureBitOffset ); } /* Now write the DWORD where the field is located containing the new configuration. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulAfConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /*==============================================================================*/ /*==============================================================================*/ /* Set the idle code detection enable. */ if ( ( pSharedInfo->ImageInfo.fIdleCodeDetection == TRUE ) && ( pSharedInfo->ImageInfo.fIdleCodeDetectionConfiguration == TRUE ) ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pVqeConfig->fIdleCodeDetection != pChanEntry->VqeConfig.fIdleCodeDetection ) ) ) { /* Calculate base address in the AF software configuration. */ ulFeatureBytesOffset = pSharedInfo->MemoryMap.IdleCodeDetectionFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.IdleCodeDetectionFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.IdleCodeDetectionFieldOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulAfConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); if ( f_pVqeConfig->fIdleCodeDetection == FALSE ) ulTempData |= ( 1 << ulFeatureBitOffset ); /* Then save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulAfConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /*==============================================================================*/ /*==============================================================================*/ /* Set the AFT control field. */ if ( pSharedInfo->ImageInfo.fAftControl == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pChannelOpen->ulEchoOperationMode != pChanEntry->byEchoOperationMode ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.AftControlOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.AftControlOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.AftControlOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulAfConfigBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* If the operation mode is no echo, set the field such that echo cancellation is disabled. */ if ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) { ulTempData |= ( 0x1234 << ulFeatureBitOffset ); } else if ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) { /* For clarity. */ ulTempData |= ( 0x0 << ulFeatureBitOffset ); } /* Then save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulAfConfigBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /*==============================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteEchoMemory Description: This function configure an echo memory entry in internal memory.and external memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pTdmConfig Pointer to a TDM config structure. f_pChannelOpen Pointer to a channel configuration structure. f_usEchoIndex Echo channel index within the SSPX memory. f_usRinRoutTsiIndex RIN/ROUT TSI index within the TSI chariot memory f_usSinSoutTsiIndex SIN/SOUT TSI index within the TSI chariot memory \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWriteEchoMemory( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_OPEN_TDM f_pTdmConfig, IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, IN UINT16 f_usEchoIndex, IN UINT16 f_usRinRoutTsiIndex, IN UINT16 f_usSinSoutTsiIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; UINT32 ulTempData; UINT32 ulBaseAddress; UINT32 ulRinPcmLaw; UINT32 ulRoutPcmLaw; UINT32 ulSinPcmLaw; UINT32 ulSoutPcmLaw; pSharedInfo = f_pApiInstance->pSharedInfo; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* Set immediately the PCM law to be programmed in the SSPX and NLP memory.*/ if ( f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_RIN ) { ulRinPcmLaw = f_pChannelOpen->TdmConfig.ulRoutPcmLaw; ulRoutPcmLaw = f_pChannelOpen->TdmConfig.ulRoutPcmLaw; ulSinPcmLaw = f_pChannelOpen->TdmConfig.ulSinPcmLaw; ulSoutPcmLaw = f_pChannelOpen->TdmConfig.ulSinPcmLaw; } else /* f_pChannelOpen->CodecConfig.ulDecoderPort == cOCT6100_CHANNEL_PORT_SIN */ { ulRinPcmLaw = f_pChannelOpen->TdmConfig.ulRinPcmLaw; ulRoutPcmLaw = f_pChannelOpen->TdmConfig.ulRinPcmLaw; ulSinPcmLaw = f_pChannelOpen->TdmConfig.ulSoutPcmLaw; ulSoutPcmLaw = f_pChannelOpen->TdmConfig.ulSoutPcmLaw; } /*==============================================================================*/ /* Configure the Global Static Configuration of the channel.*/ ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usEchoIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + cOCT6100_CHANNEL_ROOT_GLOBAL_CONF_OFFSET; /* Set the PGSP context base address. */ ulTempData = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + cOCT6100_CH_MAIN_PGSP_CONTEXT_OFFSET; WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_PGSP_CONTEXT_BASE_ADD_OFFSET; WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set the PGSP init context base address. */ ulTempData = ( cOCT6100_IMAGE_FILE_BASE + 0x200 ) & 0x07FFFFFF; WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_PGSP_INIT_CONTEXT_BASE_ADD_OFFSET; WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set the RIN circular buffer base address. */ ulTempData = ( pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainRinCBMemOfst) & 0x07FFFF00; ulTempData |= ( ulRoutPcmLaw << cOCT6100_GSC_BUFFER_LAW_OFFSET ); /* Set the circular buffer size.*/ if (( pSharedInfo->MemoryMap.ulChanMainRinCBMemSize & 0xFFFF00FF ) != 0 ) return cOCT6100_ERR_CHANNEL_INVALID_RIN_CB_SIZE; ulTempData |= pSharedInfo->MemoryMap.ulChanMainRinCBMemSize >> 8; WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_RIN_CIRC_BUFFER_BASE_ADD_OFFSET; WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set the SIN circular buffer base address. */ ulTempData = ( pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainSinCBMemOfst) & 0x07FFFF00; ulTempData |= ( ulSinPcmLaw << cOCT6100_GSC_BUFFER_LAW_OFFSET ); WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_SIN_CIRC_BUFFER_BASE_ADD_OFFSET; WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set the SOUT circular buffer base address. */ ulTempData = ( pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainSoutCBMemOfst ) & 0x07FFFF00; ulTempData |= ( ulSoutPcmLaw << cOCT6100_GSC_BUFFER_LAW_OFFSET ); WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_SOUT_CIRC_BUFFER_BASE_ADD_OFFSET; WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ /*==============================================================================*/ /* ECHO SSPX Memory configuration.*/ WriteParams.ulWriteAddress = cOCT6100_ECHO_CONTROL_MEM_BASE + ( f_usEchoIndex * cOCT6100_ECHO_CONTROL_MEM_ENTRY_SIZE ); /* ECHO memory BASE + 2 */ WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = 0x0000; /* Set the echo control field.*/ if ( ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_NO_ECHO ) || ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_SPEECH_RECOGNITION ) ) { WriteParams.usWriteData |= cOCT6100_ECHO_OP_MODE_NORMAL << cOCT6100_ECHO_CONTROL_MEM_AF_CONTROL; } else if ( f_pChannelOpen->ulEchoOperationMode != cOCT6100_ECHO_OP_MODE_EXTERNAL ) { WriteParams.usWriteData |= f_pChannelOpen->ulEchoOperationMode << cOCT6100_ECHO_CONTROL_MEM_AF_CONTROL; } /* Set the SIN/SOUT law.*/ WriteParams.usWriteData |= ulSinPcmLaw << cOCT6100_ECHO_CONTROL_MEM_INPUT_LAW_OFFSET; WriteParams.usWriteData |= ulSoutPcmLaw << cOCT6100_ECHO_CONTROL_MEM_OUTPUT_LAW_OFFSET; /* Set the TSI chariot memory field.*/ WriteParams.usWriteData |= f_usSinSoutTsiIndex & cOCT6100_ECHO_CONTROL_MEM_TSI_MEM_MASK; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* ECHO memory BASE */ WriteParams.ulWriteAddress -= 2; WriteParams.usWriteData = cOCT6100_ECHO_CONTROL_MEM_ACTIVATE_ENTRY; /* Set the RIN/ROUT law.*/ WriteParams.usWriteData |= ulRinPcmLaw << cOCT6100_ECHO_CONTROL_MEM_INPUT_LAW_OFFSET; WriteParams.usWriteData |= ulRoutPcmLaw << cOCT6100_ECHO_CONTROL_MEM_OUTPUT_LAW_OFFSET; /* Set the RIN external echo control bit.*/ if ( f_pChannelOpen->ulEchoOperationMode == cOCT6100_ECHO_OP_MODE_EXTERNAL ) WriteParams.usWriteData |= cOCT6100_ECHO_CONTROL_MEM_EXTERNAL_AF_CTRL; /* Set the TSI chariot memory field.*/ WriteParams.usWriteData |= f_usRinRoutTsiIndex & cOCT6100_ECHO_CONTROL_MEM_TSI_MEM_MASK; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiUpdateOpenStruct Description: This function will copy the new parameter from the modify structure into a channel open structure to be processed later by the same path as the channel open function. If a parameter is set to keep previous, it's current value will be extracted from the channel entry in the API. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- IN f_pApiInstance Pointer to an API instance structure. IN f_pChanModify Pointer to a channel modify structure. IN OUT f_pChanOpen Pointer to a channel open structure. IN f_pChanEntry Pointer to an API channel structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiUpdateOpenStruct( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_MODIFY f_pChanModify, IN OUT tPOCT6100_CHANNEL_OPEN f_pChanOpen, IN tPOCT6100_API_CHANNEL f_pChanEntry ) { /* Check the generic Echo parameters.*/ if ( f_pChanModify->ulEchoOperationMode == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->ulEchoOperationMode = f_pChanEntry->byEchoOperationMode; else f_pChanOpen->ulEchoOperationMode = f_pChanModify->ulEchoOperationMode; if ( f_pChanModify->fEnableToneDisabler == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->fEnableToneDisabler = f_pChanEntry->fEnableToneDisabler; else f_pChanOpen->fEnableToneDisabler = f_pChanModify->fEnableToneDisabler; if ( f_pChanModify->ulUserChanId == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->ulUserChanId = f_pChanEntry->ulUserChanId; else f_pChanOpen->ulUserChanId = f_pChanModify->ulUserChanId; /*======================================================================*/ /* Now update the TDM config.*/ /* Rin PCM LAW */ if ( f_pChanModify->TdmConfig.ulRinPcmLaw == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulRinPcmLaw = f_pChanEntry->TdmConfig.byRinPcmLaw; else f_pChanOpen->TdmConfig.ulRinPcmLaw = f_pChanModify->TdmConfig.ulRinPcmLaw; /* Sin PCM LAW */ if ( f_pChanModify->TdmConfig.ulSinPcmLaw == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulSinPcmLaw = f_pChanEntry->TdmConfig.bySinPcmLaw; else f_pChanOpen->TdmConfig.ulSinPcmLaw = f_pChanModify->TdmConfig.ulSinPcmLaw; /* Rout PCM LAW */ if ( f_pChanModify->TdmConfig.ulRoutPcmLaw == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulRoutPcmLaw = f_pChanEntry->TdmConfig.byRoutPcmLaw; else f_pChanOpen->TdmConfig.ulRoutPcmLaw = f_pChanModify->TdmConfig.ulRoutPcmLaw; /* Sout PCM LAW */ if ( f_pChanModify->TdmConfig.ulSoutPcmLaw == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulSoutPcmLaw = f_pChanEntry->TdmConfig.bySoutPcmLaw; else f_pChanOpen->TdmConfig.ulSoutPcmLaw = f_pChanModify->TdmConfig.ulSoutPcmLaw; /* Rin Timeslot */ if ( f_pChanModify->TdmConfig.ulRinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulRinTimeslot = f_pChanEntry->TdmConfig.usRinTimeslot; else f_pChanOpen->TdmConfig.ulRinTimeslot = f_pChanModify->TdmConfig.ulRinTimeslot; /* Rin Stream */ if ( f_pChanModify->TdmConfig.ulRinStream == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulRinStream = f_pChanEntry->TdmConfig.usRinStream; else f_pChanOpen->TdmConfig.ulRinStream = f_pChanModify->TdmConfig.ulRinStream; /* Rin Num TSSTs */ if ( f_pChanModify->TdmConfig.ulRinNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulRinNumTssts = f_pChanEntry->TdmConfig.byRinNumTssts; else f_pChanOpen->TdmConfig.ulRinNumTssts = f_pChanModify->TdmConfig.ulRinNumTssts; /* Sin Timeslot */ if ( f_pChanModify->TdmConfig.ulSinTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulSinTimeslot = f_pChanEntry->TdmConfig.usSinTimeslot; else f_pChanOpen->TdmConfig.ulSinTimeslot = f_pChanModify->TdmConfig.ulSinTimeslot; /* Sin Stream */ if ( f_pChanModify->TdmConfig.ulSinStream == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulSinStream = f_pChanEntry->TdmConfig.usSinStream; else f_pChanOpen->TdmConfig.ulSinStream = f_pChanModify->TdmConfig.ulSinStream; /* Sin Num TSSTs */ if ( f_pChanModify->TdmConfig.ulSinNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulSinNumTssts = f_pChanEntry->TdmConfig.bySinNumTssts; else f_pChanOpen->TdmConfig.ulSinNumTssts = f_pChanModify->TdmConfig.ulSinNumTssts; /* Rout Timeslot */ if ( f_pChanModify->TdmConfig.ulRoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulRoutTimeslot = f_pChanEntry->TdmConfig.usRoutTimeslot; else f_pChanOpen->TdmConfig.ulRoutTimeslot = f_pChanModify->TdmConfig.ulRoutTimeslot; /* Rout Stream */ if ( f_pChanModify->TdmConfig.ulRoutStream == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulRoutStream = f_pChanEntry->TdmConfig.usRoutStream; else f_pChanOpen->TdmConfig.ulRoutStream = f_pChanModify->TdmConfig.ulRoutStream; /* Rout Num TSSTs */ if ( f_pChanModify->TdmConfig.ulRoutNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulRoutNumTssts = f_pChanEntry->TdmConfig.byRoutNumTssts; else f_pChanOpen->TdmConfig.ulRoutNumTssts = f_pChanModify->TdmConfig.ulRoutNumTssts; /* Sout Timeslot */ if ( f_pChanModify->TdmConfig.ulSoutTimeslot == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulSoutTimeslot = f_pChanEntry->TdmConfig.usSoutTimeslot; else f_pChanOpen->TdmConfig.ulSoutTimeslot = f_pChanModify->TdmConfig.ulSoutTimeslot; /* Sout Stream */ if ( f_pChanModify->TdmConfig.ulSoutStream == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulSoutStream = f_pChanEntry->TdmConfig.usSoutStream; else f_pChanOpen->TdmConfig.ulSoutStream = f_pChanModify->TdmConfig.ulSoutStream; /* Sout Num TSSTs */ if ( f_pChanModify->TdmConfig.ulSoutNumTssts == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->TdmConfig.ulSoutNumTssts = f_pChanEntry->TdmConfig.bySoutNumTssts; else f_pChanOpen->TdmConfig.ulSoutNumTssts = f_pChanModify->TdmConfig.ulSoutNumTssts; /*======================================================================*/ /*======================================================================*/ /* Now update the VQE config.*/ if ( f_pChanModify->VqeConfig.ulComfortNoiseMode == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.ulComfortNoiseMode = f_pChanEntry->VqeConfig.byComfortNoiseMode; else f_pChanOpen->VqeConfig.ulComfortNoiseMode = f_pChanModify->VqeConfig.ulComfortNoiseMode; if ( f_pChanModify->VqeConfig.fEnableNlp == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fEnableNlp = f_pChanEntry->VqeConfig.fEnableNlp; else f_pChanOpen->VqeConfig.fEnableNlp = f_pChanModify->VqeConfig.fEnableNlp; if ( f_pChanModify->VqeConfig.fEnableTailDisplacement == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fEnableTailDisplacement = f_pChanEntry->VqeConfig.fEnableTailDisplacement; else f_pChanOpen->VqeConfig.fEnableTailDisplacement = f_pChanModify->VqeConfig.fEnableTailDisplacement; if ( f_pChanModify->VqeConfig.ulTailDisplacement == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.ulTailDisplacement = f_pChanEntry->VqeConfig.usTailDisplacement; else f_pChanOpen->VqeConfig.ulTailDisplacement = f_pChanModify->VqeConfig.ulTailDisplacement; /* Tail length cannot be modifed. */ f_pChanOpen->VqeConfig.ulTailLength = f_pChanEntry->VqeConfig.usTailLength; if ( f_pChanModify->VqeConfig.fRinDcOffsetRemoval == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fRinDcOffsetRemoval = f_pChanEntry->VqeConfig.fRinDcOffsetRemoval; else f_pChanOpen->VqeConfig.fRinDcOffsetRemoval = f_pChanModify->VqeConfig.fRinDcOffsetRemoval; if ( f_pChanModify->VqeConfig.fRinLevelControl == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fRinLevelControl = f_pChanEntry->VqeConfig.fRinLevelControl; else f_pChanOpen->VqeConfig.fRinLevelControl = f_pChanModify->VqeConfig.fRinLevelControl; if ( f_pChanModify->VqeConfig.fRinAutomaticLevelControl == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fRinAutomaticLevelControl = f_pChanEntry->VqeConfig.fRinAutomaticLevelControl; else f_pChanOpen->VqeConfig.fRinAutomaticLevelControl = f_pChanModify->VqeConfig.fRinAutomaticLevelControl; if ( f_pChanModify->VqeConfig.fRinHighLevelCompensation == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fRinHighLevelCompensation = f_pChanEntry->VqeConfig.fRinHighLevelCompensation; else f_pChanOpen->VqeConfig.fRinHighLevelCompensation = f_pChanModify->VqeConfig.fRinHighLevelCompensation; if ( f_pChanModify->VqeConfig.lRinHighLevelCompensationThresholdDb == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.lRinHighLevelCompensationThresholdDb = f_pChanEntry->VqeConfig.chRinHighLevelCompensationThresholdDb; else f_pChanOpen->VqeConfig.lRinHighLevelCompensationThresholdDb = f_pChanModify->VqeConfig.lRinHighLevelCompensationThresholdDb; if ( f_pChanModify->VqeConfig.fSinDcOffsetRemoval == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fSinDcOffsetRemoval = f_pChanEntry->VqeConfig.fSinDcOffsetRemoval; else f_pChanOpen->VqeConfig.fSinDcOffsetRemoval = f_pChanModify->VqeConfig.fSinDcOffsetRemoval; if ( f_pChanModify->VqeConfig.fSoutAdaptiveNoiseReduction == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fSoutAdaptiveNoiseReduction = f_pChanEntry->VqeConfig.fSoutAdaptiveNoiseReduction; else f_pChanOpen->VqeConfig.fSoutAdaptiveNoiseReduction = f_pChanModify->VqeConfig.fSoutAdaptiveNoiseReduction; if ( f_pChanModify->VqeConfig.fSoutConferencingNoiseReduction == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fSoutConferencingNoiseReduction = f_pChanEntry->VqeConfig.fSoutConferencingNoiseReduction; else f_pChanOpen->VqeConfig.fSoutConferencingNoiseReduction = f_pChanModify->VqeConfig.fSoutConferencingNoiseReduction; if ( f_pChanModify->VqeConfig.fSoutNoiseBleaching == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fSoutNoiseBleaching = f_pChanEntry->VqeConfig.fSoutNoiseBleaching; else f_pChanOpen->VqeConfig.fSoutNoiseBleaching = f_pChanModify->VqeConfig.fSoutNoiseBleaching; if ( f_pChanModify->VqeConfig.fSoutLevelControl == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fSoutLevelControl = f_pChanEntry->VqeConfig.fSoutLevelControl; else f_pChanOpen->VqeConfig.fSoutLevelControl = f_pChanModify->VqeConfig.fSoutLevelControl; if ( f_pChanModify->VqeConfig.fSoutAutomaticLevelControl == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fSoutAutomaticLevelControl = f_pChanEntry->VqeConfig.fSoutAutomaticLevelControl; else f_pChanOpen->VqeConfig.fSoutAutomaticLevelControl = f_pChanModify->VqeConfig.fSoutAutomaticLevelControl; if ( f_pChanModify->VqeConfig.lRinLevelControlGainDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) f_pChanOpen->VqeConfig.lRinLevelControlGainDb = f_pChanEntry->VqeConfig.chRinLevelControlGainDb; else f_pChanOpen->VqeConfig.lRinLevelControlGainDb = f_pChanModify->VqeConfig.lRinLevelControlGainDb; if ( f_pChanModify->VqeConfig.lSoutLevelControlGainDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) f_pChanOpen->VqeConfig.lSoutLevelControlGainDb = f_pChanEntry->VqeConfig.chSoutLevelControlGainDb; else f_pChanOpen->VqeConfig.lSoutLevelControlGainDb = f_pChanModify->VqeConfig.lSoutLevelControlGainDb; if ( f_pChanModify->VqeConfig.lRinAutomaticLevelControlTargetDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) f_pChanOpen->VqeConfig.lRinAutomaticLevelControlTargetDb = f_pChanEntry->VqeConfig.chRinAutomaticLevelControlTargetDb; else f_pChanOpen->VqeConfig.lRinAutomaticLevelControlTargetDb = f_pChanModify->VqeConfig.lRinAutomaticLevelControlTargetDb; if ( f_pChanModify->VqeConfig.lSoutAutomaticLevelControlTargetDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) f_pChanOpen->VqeConfig.lSoutAutomaticLevelControlTargetDb = f_pChanEntry->VqeConfig.chSoutAutomaticLevelControlTargetDb; else f_pChanOpen->VqeConfig.lSoutAutomaticLevelControlTargetDb = f_pChanModify->VqeConfig.lSoutAutomaticLevelControlTargetDb; if ( f_pChanModify->VqeConfig.lDefaultErlDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) f_pChanOpen->VqeConfig.lDefaultErlDb = f_pChanEntry->VqeConfig.chDefaultErlDb; else f_pChanOpen->VqeConfig.lDefaultErlDb = f_pChanModify->VqeConfig.lDefaultErlDb; if ( f_pChanModify->VqeConfig.lAecDefaultErlDb == ( (INT32)cOCT6100_KEEP_PREVIOUS_SETTING ) ) f_pChanOpen->VqeConfig.lAecDefaultErlDb = f_pChanEntry->VqeConfig.chAecDefaultErlDb; else f_pChanOpen->VqeConfig.lAecDefaultErlDb = f_pChanModify->VqeConfig.lAecDefaultErlDb; if ( f_pChanModify->VqeConfig.ulAecTailLength == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.ulAecTailLength = f_pChanEntry->VqeConfig.usAecTailLength; else f_pChanOpen->VqeConfig.ulAecTailLength = f_pChanModify->VqeConfig.ulAecTailLength; if ( f_pChanModify->VqeConfig.fAcousticEcho == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fAcousticEcho = f_pChanEntry->VqeConfig.fAcousticEcho; else f_pChanOpen->VqeConfig.fAcousticEcho = f_pChanModify->VqeConfig.fAcousticEcho; if ( f_pChanModify->VqeConfig.fDtmfToneRemoval == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fDtmfToneRemoval = f_pChanEntry->VqeConfig.fDtmfToneRemoval; else f_pChanOpen->VqeConfig.fDtmfToneRemoval = f_pChanModify->VqeConfig.fDtmfToneRemoval; if ( f_pChanModify->VqeConfig.ulNonLinearityBehaviorA == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.ulNonLinearityBehaviorA = f_pChanEntry->VqeConfig.byNonLinearityBehaviorA; else f_pChanOpen->VqeConfig.ulNonLinearityBehaviorA = f_pChanModify->VqeConfig.ulNonLinearityBehaviorA; if ( f_pChanModify->VqeConfig.ulNonLinearityBehaviorB == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.ulNonLinearityBehaviorB = f_pChanEntry->VqeConfig.byNonLinearityBehaviorB; else f_pChanOpen->VqeConfig.ulNonLinearityBehaviorB = f_pChanModify->VqeConfig.ulNonLinearityBehaviorB; if ( f_pChanModify->VqeConfig.ulDoubleTalkBehavior == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.ulDoubleTalkBehavior = f_pChanEntry->VqeConfig.byDoubleTalkBehavior; else f_pChanOpen->VqeConfig.ulDoubleTalkBehavior = f_pChanModify->VqeConfig.ulDoubleTalkBehavior; if ( f_pChanModify->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = f_pChanEntry->VqeConfig.bySoutAutomaticListenerEnhancementGainDb; else f_pChanOpen->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb = f_pChanModify->VqeConfig.ulSoutAutomaticListenerEnhancementGainDb; if ( f_pChanModify->VqeConfig.ulSoutNaturalListenerEnhancementGainDb == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = f_pChanEntry->VqeConfig.bySoutNaturalListenerEnhancementGainDb; else f_pChanOpen->VqeConfig.ulSoutNaturalListenerEnhancementGainDb = f_pChanModify->VqeConfig.ulSoutNaturalListenerEnhancementGainDb; if ( f_pChanModify->VqeConfig.fSoutNaturalListenerEnhancement == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fSoutNaturalListenerEnhancement = f_pChanEntry->VqeConfig.fSoutNaturalListenerEnhancement; else f_pChanOpen->VqeConfig.fSoutNaturalListenerEnhancement = f_pChanModify->VqeConfig.fSoutNaturalListenerEnhancement; if ( f_pChanModify->VqeConfig.fRoutNoiseReduction == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fRoutNoiseReduction = f_pChanEntry->VqeConfig.fRoutNoiseReduction; else f_pChanOpen->VqeConfig.fRoutNoiseReduction = f_pChanModify->VqeConfig.fRoutNoiseReduction; if ( f_pChanModify->VqeConfig.lAnrSnrEnhancementDb == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.lAnrSnrEnhancementDb = f_pChanEntry->VqeConfig.chAnrSnrEnhancementDb; else f_pChanOpen->VqeConfig.lAnrSnrEnhancementDb = f_pChanModify->VqeConfig.lAnrSnrEnhancementDb; if ( f_pChanModify->VqeConfig.ulAnrVoiceNoiseSegregation == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.ulAnrVoiceNoiseSegregation = f_pChanEntry->VqeConfig.byAnrVoiceNoiseSegregation; else f_pChanOpen->VqeConfig.ulAnrVoiceNoiseSegregation = f_pChanModify->VqeConfig.ulAnrVoiceNoiseSegregation; if ( f_pChanModify->VqeConfig.ulToneDisablerVqeActivationDelay == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.ulToneDisablerVqeActivationDelay = f_pChanEntry->VqeConfig.usToneDisablerVqeActivationDelay; else f_pChanOpen->VqeConfig.ulToneDisablerVqeActivationDelay = f_pChanModify->VqeConfig.ulToneDisablerVqeActivationDelay; if ( f_pChanModify->VqeConfig.fEnableMusicProtection == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fEnableMusicProtection = f_pChanEntry->VqeConfig.fEnableMusicProtection; else f_pChanOpen->VqeConfig.fEnableMusicProtection = f_pChanModify->VqeConfig.fEnableMusicProtection; if ( f_pChanModify->VqeConfig.fIdleCodeDetection == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->VqeConfig.fIdleCodeDetection = f_pChanEntry->VqeConfig.fIdleCodeDetection; else f_pChanOpen->VqeConfig.fIdleCodeDetection = f_pChanModify->VqeConfig.fIdleCodeDetection; /*======================================================================*/ /*======================================================================*/ /* Finaly the codec config.*/ if ( f_pChanModify->CodecConfig.ulDecoderPort == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->CodecConfig.ulDecoderPort = f_pChanEntry->CodecConfig.byDecoderPort; else f_pChanOpen->CodecConfig.ulDecoderPort = f_pChanModify->CodecConfig.ulDecoderPort; if ( f_pChanModify->CodecConfig.ulDecodingRate == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->CodecConfig.ulDecodingRate = f_pChanEntry->CodecConfig.byDecodingRate; else f_pChanOpen->CodecConfig.ulDecodingRate = f_pChanModify->CodecConfig.ulDecodingRate; if ( f_pChanModify->CodecConfig.ulEncoderPort == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->CodecConfig.ulEncoderPort = f_pChanEntry->CodecConfig.byEncoderPort; else f_pChanOpen->CodecConfig.ulEncoderPort = f_pChanModify->CodecConfig.ulEncoderPort; if ( f_pChanModify->CodecConfig.ulEncodingRate == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->CodecConfig.ulEncodingRate = f_pChanEntry->CodecConfig.byEncodingRate; else f_pChanOpen->CodecConfig.ulEncodingRate = f_pChanModify->CodecConfig.ulEncodingRate; if ( f_pChanModify->CodecConfig.fEnableSilenceSuppression == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->CodecConfig.fEnableSilenceSuppression = f_pChanEntry->CodecConfig.fEnableSilenceSuppression; else f_pChanOpen->CodecConfig.fEnableSilenceSuppression = f_pChanModify->CodecConfig.fEnableSilenceSuppression; if ( f_pChanModify->CodecConfig.ulPhasingType == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->CodecConfig.ulPhasingType = f_pChanEntry->CodecConfig.byPhasingType; else f_pChanOpen->CodecConfig.ulPhasingType = f_pChanModify->CodecConfig.ulPhasingType; if ( f_pChanModify->CodecConfig.ulPhase == cOCT6100_KEEP_PREVIOUS_SETTING ) f_pChanOpen->CodecConfig.ulPhase = f_pChanEntry->CodecConfig.byPhase; else f_pChanOpen->CodecConfig.ulPhase = f_pChanModify->CodecConfig.ulPhase; if ( f_pChanModify->CodecConfig.ulPhasingTsstHndl == cOCT6100_KEEP_PREVIOUS_SETTING ) { if ( f_pChanEntry->usPhasingTsstIndex != cOCT6100_INVALID_INDEX ) { tPOCT6100_API_PHASING_TSST pPhasingEntry; mOCT6100_GET_PHASING_TSST_ENTRY_PNT( f_pApiInstance->pSharedInfo, pPhasingEntry, f_pChanEntry->usPhasingTsstIndex ); /* Now recreate the Phasing TSST handle.*/ f_pChanOpen->CodecConfig.ulPhasingTsstHndl = cOCT6100_HNDL_TAG_PHASING_TSST | (pPhasingEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_pChanEntry->usPhasingTsstIndex; } else { f_pChanOpen->CodecConfig.ulPhasingTsstHndl = cOCT6100_INVALID_HANDLE; } } else { f_pChanOpen->CodecConfig.ulPhasingTsstHndl = f_pChanModify->CodecConfig.ulPhasingTsstHndl; } f_pChanOpen->CodecConfig.ulAdpcmNibblePosition = f_pChanEntry->CodecConfig.byAdpcmNibblePosition; /*======================================================================*/ return cOCT6100_ERR_OK; } static UINT16 Oct6100ApiDbAmpHalfToOctFloat(INT32 x) { INT32 db_div6; INT32 db_mod6; UINT16 rval; INT32 x_unsigned; if(x < 0) { x_unsigned = -x; } else { x_unsigned = x; } db_div6 = x_unsigned / 6; db_mod6 = x_unsigned % 6; if(x < 0) { if(db_mod6 == 0) { /* Change nothing! */ db_div6 = -db_div6; } else { /* When we are negative, round down, and then adjust modulo. For example, if x is -1, then db_div6 is 0 and db_mod6 is 1. We adjust so db_div6 = -1 and db_mod6 = 5, which gives the correct adjustment. */ db_div6 = -db_div6-1; db_mod6 = 6 - db_mod6; } } rval = (UINT16)(0x4100 + db_div6 * 0x100); if(db_mod6 == 0) { rval += 0x0000; } else if(db_mod6 == 1) { rval += 0x0020; } else if(db_mod6 == 2) { rval += 0x0040; } else if(db_mod6 == 3) { rval += 0x0070; } else if(db_mod6 == 4) { rval += 0x0090; } else /* if(db_mod6 == 5) */ { rval += 0x00D0; } return rval; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteDebugChanMemory Description: This function configure a debug channel echo memory entry in internal memory.and external memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pTdmConfig Pointer to a TDM configuration structure. f_pVqeConfig Pointer to a VQE configuration structure. f_pChannelOpen Pointer to a channel configuration structure. f_usChanIndex Index of the echo channel in the API instance. f_usEchoMemIndex Index of the echo channel within the SSPX memory. f_usRinRoutTsiIndex RIN/ROUT TSI index within the TSI chariot memory. f_usSinSoutTsiIndex SIN/SOUT TSI index within the TSI chariot memory. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWriteDebugChanMemory( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_OPEN_TDM f_pTdmConfig, IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, IN tPOCT6100_CHANNEL_OPEN f_pChannelOpen, IN UINT16 f_usChanIndex, IN UINT16 f_usEchoMemIndex, IN UINT16 f_usRinRoutTsiIndex, IN UINT16 f_usSinSoutTsiIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; UINT32 ulResult; /* Obtain pointer to local portion of the instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /*==============================================================================*/ /* Write the VQE configuration of the debug channel. */ ulResult = Oct6100ApiWriteVqeMemory( f_pApiInstance, f_pVqeConfig, f_pChannelOpen, f_usChanIndex, f_usEchoMemIndex, TRUE, FALSE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ /*==============================================================================*/ /* Write the echo memory configuration of the debug channel. */ ulResult = Oct6100ApiWriteEchoMemory( f_pApiInstance, f_pTdmConfig, f_pChannelOpen, f_usEchoMemIndex, f_usRinRoutTsiIndex, f_usSinSoutTsiIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiDebugChannelOpen Description: Internal function used to open a debug channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiDebugChannelOpen( IN tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_CHANNEL_OPEN TempChanOpen; UINT32 ulResult; UINT16 usChanIndex; UINT16 usDummyEchoIndex; pSharedInfo = f_pApiInstance->pSharedInfo; /* Let's program the channel memory.*/ Oct6100ChannelOpenDef( &TempChanOpen ); TempChanOpen.ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_HT_RESET; /* Activate the channel in reset.*/ TempChanOpen.VqeConfig.fEnableNlp = FALSE; TempChanOpen.VqeConfig.ulComfortNoiseMode = cOCT6100_COMFORT_NOISE_NORMAL; TempChanOpen.VqeConfig.fSinDcOffsetRemoval = FALSE; TempChanOpen.VqeConfig.fRinDcOffsetRemoval = FALSE; TempChanOpen.VqeConfig.lDefaultErlDb = 0; /* Loop to reserve the proper entry for the debug channel */ for( usChanIndex = 0; usChanIndex < ( pSharedInfo->DebugInfo.usRecordChanIndex + 1 ); usChanIndex ++ ) { ulResult = Oct6100ApiReserveEchoEntry( f_pApiInstance, &usDummyEchoIndex ); if( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Loop to free all entries except the one for the debug channel */ for( usChanIndex = pSharedInfo->DebugInfo.usRecordChanIndex; usChanIndex > 0; ) { usChanIndex--; ulResult = Oct6100ApiReleaseEchoEntry( f_pApiInstance, usChanIndex ); if( ulResult != cOCT6100_ERR_OK ) return ulResult; } ulResult = Oct6100ApiWriteDebugChanMemory( f_pApiInstance, &TempChanOpen.TdmConfig, &TempChanOpen.VqeConfig, &TempChanOpen, pSharedInfo->DebugInfo.usRecordChanIndex, pSharedInfo->DebugInfo.usRecordMemIndex, pSharedInfo->DebugInfo.usRecordRinRoutTsiMemIndex, pSharedInfo->DebugInfo.usRecordSinSoutTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiMuteChannelPort Description: This function will verify if a input TSST is bound to the RIN and SIN port. If not, the port will be muted. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiMutePorts( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usEchoIndex, IN UINT16 f_usRinTsstIndex, IN UINT16 f_usSinTsstIndex, IN BOOL f_fCheckBridgeIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHANNEL pChanEntry; tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; pSharedInfo = f_pApiInstance->pSharedInfo; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* Obtain a pointer to the new buffer's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usEchoIndex ); /* Mute the Rin port. */ if ( ( f_fCheckBridgeIndex == FALSE ) || ( ( f_fCheckBridgeIndex == TRUE ) && ( pChanEntry->usBridgeIndex == cOCT6100_INVALID_INDEX ) ) ) { /* If the channel is in bidir mode, do not create the Rin silence event!!! */ if ( pChanEntry->fBiDirChannel == FALSE ) { if ( ( ( f_usRinTsstIndex == cOCT6100_INVALID_INDEX ) || ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_RIN ) != 0x0 ) ) && ( pChanEntry->usRinSilenceEventIndex == cOCT6100_INVALID_INDEX ) ) { ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &pChanEntry->usRinSilenceEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Now, write the mixer event used to copy the RIN signal of the silence channel into the RIN signal of the current channel. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usRinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; WriteParams.usWriteData |= 1534; WriteParams.usWriteData |= cOCT6100_PCM_U_LAW << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = pChanEntry->usRinRoutTsiMemIndex; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* Now insert the Sin copy event into the list.*/ ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, pChanEntry->usRinSilenceEventIndex, cOCT6100_EVENT_TYPE_SOUT_COPY, f_usEchoIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } } /* Mute the Sin port. */ if ( ( ( f_usSinTsstIndex == cOCT6100_INVALID_INDEX ) || ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) ) && ( pChanEntry->usSinSilenceEventIndex == cOCT6100_INVALID_INDEX ) ) { ulResult = Oct6100ApiReserveMixerEventEntry( f_pApiInstance, &pChanEntry->usSinSilenceEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Now, write the mixer event used to copy the SIN signal of the silence channel into the SIN signal of the current channel. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_COPY; WriteParams.usWriteData |= 1534; WriteParams.usWriteData |= cOCT6100_PCM_U_LAW << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = pChanEntry->usSinSoutTsiMemIndex; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* Now insert the Sin copy event into the list.*/ ulResult = Oct6100ApiMixerEventAdd( f_pApiInstance, pChanEntry->usSinSilenceEventIndex, cOCT6100_EVENT_TYPE_SOUT_COPY, f_usEchoIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Unmute the Rin port if it was muted. */ if ( ( ( f_usRinTsstIndex != cOCT6100_INVALID_INDEX ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_RIN ) == 0x0 ) ) && ( pChanEntry->usRinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ) { /* Remove the event from the list.*/ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pChanEntry->usRinSilenceEventIndex, cOCT6100_EVENT_TYPE_SOUT_COPY ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pChanEntry->usRinSilenceEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_E1; pChanEntry->usRinSilenceEventIndex = cOCT6100_INVALID_INDEX; } /* Unmute the Sin port if it was muted. */ if ( ( ( f_usSinTsstIndex != cOCT6100_INVALID_INDEX ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN ) == 0x0 ) ) && ( pChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) ) { /* Remove the event from the list.*/ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pChanEntry->usSinSilenceEventIndex, cOCT6100_EVENT_TYPE_SOUT_COPY ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pChanEntry->usSinSilenceEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_E2; pChanEntry->usSinSilenceEventIndex = cOCT6100_INVALID_INDEX; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiSetChannelLevelControl Description: This function will configure the level control on a given channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pVqeConfig VQE config of the channel. f_usChanIndex Index of the channel within the API instance. f_usEchoMemIndex Index of the echo channel within the SSPX memory. f_fClearAlcHlcStatusBit If this is set, the ALC-HLC status bit must be incremented. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiSetChannelLevelControl( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, IN UINT16 f_usChanIndex, IN UINT16 f_usEchoMemIndex, IN BOOL f_fClearAlcHlcStatusBit ) { tPOCT6100_API_CHANNEL pChanEntry; tPOCT6100_SHARED_INFO pSharedInfo; UINT32 ulResult; UINT32 ulTempData; UINT32 ulBaseAddress; UINT32 ulFeatureBytesOffset; UINT32 ulFeatureBitOffset; UINT32 ulFeatureFieldLength; UINT32 ulMask; UINT32 i; UINT16 usTempData; UINT8 byLastStatus; BOOL fDisableAlcFirst; /* Get local pointer to shared portion of the API instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Obtain a pointer to the channel list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ); /* Before doing anything, check if the configuration has changed. */ if ( ( f_fClearAlcHlcStatusBit == TRUE ) || ( f_pVqeConfig->fRinLevelControl != pChanEntry->VqeConfig.fRinLevelControl ) || ( f_pVqeConfig->lRinLevelControlGainDb != pChanEntry->VqeConfig.chRinLevelControlGainDb ) || ( f_pVqeConfig->fRinAutomaticLevelControl != pChanEntry->VqeConfig.fRinAutomaticLevelControl ) || ( f_pVqeConfig->lRinAutomaticLevelControlTargetDb != pChanEntry->VqeConfig.chRinAutomaticLevelControlTargetDb ) || ( f_pVqeConfig->fRinHighLevelCompensation != pChanEntry->VqeConfig.fRinHighLevelCompensation ) || ( f_pVqeConfig->lRinHighLevelCompensationThresholdDb != pChanEntry->VqeConfig.chRinHighLevelCompensationThresholdDb ) || ( f_pVqeConfig->fSoutLevelControl != pChanEntry->VqeConfig.fSoutLevelControl ) || ( f_pVqeConfig->lSoutLevelControlGainDb != pChanEntry->VqeConfig.chSoutLevelControlGainDb ) || ( f_pVqeConfig->fSoutAutomaticLevelControl != pChanEntry->VqeConfig.fSoutAutomaticLevelControl ) || ( f_pVqeConfig->lSoutAutomaticLevelControlTargetDb != pChanEntry->VqeConfig.chSoutAutomaticLevelControlTargetDb ) || ( f_pVqeConfig->fSoutNaturalListenerEnhancement != pChanEntry->VqeConfig.fSoutNaturalListenerEnhancement ) || ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != pChanEntry->VqeConfig.bySoutAutomaticListenerEnhancementGainDb ) || ( f_pVqeConfig->ulSoutNaturalListenerEnhancementGainDb != pChanEntry->VqeConfig.bySoutNaturalListenerEnhancementGainDb ) ) { /* Calculate base address for manual level control configuration. */ ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; /* Set the Level control on RIN port.*/ ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinLevelControlOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.RinLevelControlOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.RinLevelControlOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); if ( ( f_pVqeConfig->fRinLevelControl == TRUE ) || ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) || ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) ) { /* Set the level control value.*/ if ( ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) || ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) ) ulTempData |= ( 0xFF << ulFeatureBitOffset ); else { /* Convert the dB value into OctFloat format.*/ usTempData = Oct6100ApiDbAmpHalfToOctFloat( f_pVqeConfig->lRinLevelControlGainDb ); usTempData -= 0x3800; usTempData &= 0x0FF0; usTempData >>= 4; ulTempData |= ( usTempData << ulFeatureBitOffset ); } } else /* ( ( f_pVqeConfig->fRinLevelControl == FALSE ) && ( f_pVqeConfig->fRinAutomaticLevelControl == FALSE ) && ( f_pVqeConfig->fRinHighLevelCompensation == FALSE ) ) */ { ulTempData |= ( cOCT6100_PASS_THROUGH_LEVEL_CONTROL << ulFeatureBitOffset ); } /* Save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set the Level control on SOUT port.*/ ulFeatureBytesOffset = pSharedInfo->MemoryMap.SoutLevelControlOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.SoutLevelControlOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.SoutLevelControlOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); if ( ( f_pVqeConfig->fSoutLevelControl == TRUE ) || ( f_pVqeConfig->fSoutAutomaticLevelControl == TRUE ) || ( f_pVqeConfig->fSoutNaturalListenerEnhancement == TRUE ) || ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != 0x0 ) ) { /* Set the level control value.*/ if ( ( f_pVqeConfig->fSoutAutomaticLevelControl == TRUE ) || ( f_pVqeConfig->fSoutNaturalListenerEnhancement == TRUE ) || ( f_pVqeConfig->ulSoutAutomaticListenerEnhancementGainDb != 0x0 ) ) ulTempData |= ( 0xFF << ulFeatureBitOffset ); else { /* Convert the dB value into OctFloat format.*/ usTempData = Oct6100ApiDbAmpHalfToOctFloat( f_pVqeConfig->lSoutLevelControlGainDb ); usTempData -= 0x3800; usTempData &= 0x0FF0; usTempData >>= 4; ulTempData |= ( usTempData << ulFeatureBitOffset ); } } else { ulTempData |= ( cOCT6100_PASS_THROUGH_LEVEL_CONTROL << ulFeatureBitOffset ); } /* Save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Calculate base address for auto level control + high level compensation configuration. */ ulBaseAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst; /* Check which one is to be disabled first. */ if ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) fDisableAlcFirst = FALSE; else fDisableAlcFirst = TRUE; for ( i = 0; i < 2; i ++ ) { /* Set the auto level control target Db for the Rin port. */ if ( ( ( i == 0 ) && ( fDisableAlcFirst == TRUE ) ) || ( ( i == 1 ) && ( fDisableAlcFirst == FALSE ) ) ) { if ( pSharedInfo->ImageInfo.fRinAutoLevelControl == TRUE ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinAutoLevelControlTargetOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.RinAutoLevelControlTargetOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.RinAutoLevelControlTargetOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); if ( f_pVqeConfig->fRinAutomaticLevelControl == TRUE ) { /* Convert the dB value into OctFloat format.*/ usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lRinAutomaticLevelControlTargetDb ); /* Set auto level control target on the Rin port. */ ulTempData |= ( usTempData << ulFeatureBitOffset ); } else /* if ( f_pVqeConfig->fRinAutomaticLevelControl == FALSE ) */ { /* Disable auto level control. */ ulTempData |= ( 0xFFFF << ulFeatureBitOffset ); } /* Save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } else { /* Set the high level compensation threshold Db for the Rin port. */ if ( pSharedInfo->ImageInfo.fRinHighLevelCompensation == TRUE ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.RinHighLevelCompensationThresholdOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.RinHighLevelCompensationThresholdOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.RinHighLevelCompensationThresholdOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); if ( f_pVqeConfig->fRinHighLevelCompensation == TRUE ) { /* Convert the dB value into OctFloat format.*/ usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lRinHighLevelCompensationThresholdDb ); /* Set high level compensation threshold on the Rin port. */ ulTempData |= ( usTempData << ulFeatureBitOffset ); } else /* if ( f_pVqeConfig->fRinHighLevelCompensation == FALSE ) */ { /* Disable high level compensation. */ ulTempData |= ( 0xFFFF << ulFeatureBitOffset ); } /* Save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } } /* Set the auto level control target Db for the Sout port. */ if ( pSharedInfo->ImageInfo.fRinAutoLevelControl == TRUE ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.SoutAutoLevelControlTargetOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.SoutAutoLevelControlTargetOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.SoutAutoLevelControlTargetOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); if ( f_pVqeConfig->fSoutAutomaticLevelControl == TRUE ) { /* Convert the dB value into OctFloat format.*/ usTempData = Oct6100ApiDbAmpHalfToOctFloat( 2 * f_pVqeConfig->lSoutAutomaticLevelControlTargetDb ); /* Set auto level control target on the Sout port. */ ulTempData |= ( usTempData << ulFeatureBitOffset ); } else /* if ( f_pVqeConfig->fSoutAutomaticLevelControl == FALSE ) */ { /* Disable auto level control. */ ulTempData |= ( 0xFFFF << ulFeatureBitOffset ); } /* Save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Set the high level compensation threshold Db for the Sout port. */ if ( pSharedInfo->ImageInfo.fSoutHighLevelCompensation == TRUE ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.SoutHighLevelCompensationThresholdOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.SoutHighLevelCompensationThresholdOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.SoutHighLevelCompensationThresholdOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* Disable high level compensation on Sout for now. */ ulTempData |= ( 0xFFFF << ulFeatureBitOffset ); /* Save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Check if have to clear the ALC-HLC status. */ if ( ( pSharedInfo->ImageInfo.fAlcHlcStatus == TRUE ) && ( f_fClearAlcHlcStatusBit == TRUE ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.AlcHlcStatusOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.AlcHlcStatusOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.AlcHlcStatusOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Get previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); /* Retrieve last status. */ byLastStatus = (UINT8)( ( ( ulTempData & ulMask ) >> ulFeatureBitOffset ) & 0xFF ); /* Increment to reset context. */ byLastStatus ++; /* Just in case, not to overwrite some context in external memory. */ byLastStatus &= ( 0x1 << ulFeatureFieldLength ) - 1; /* Clear last status. */ ulTempData &= (~ulMask); /* Set new status. */ ulTempData |= ( byLastStatus << ulFeatureBitOffset ); /* Save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiSetChannelTailConfiguration Description: This function will configure the tail displacement and length on a given channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pVqeConfig VQE config of the channel. f_usChanIndex Index of the channel within the API instance. f_usEchoMemIndex Index of the echo channel within the SSPX memory. f_fModifyOnly Function called from a modify or open? \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiSetChannelTailConfiguration( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_OPEN_VQE f_pVqeConfig, IN UINT16 f_usChanIndex, IN UINT16 f_usEchoMemIndex, IN BOOL f_fModifyOnly ) { tPOCT6100_API_CHANNEL pChanEntry; tPOCT6100_SHARED_INFO pSharedInfo; UINT32 ulResult; UINT32 ulTempData; UINT32 ulNlpConfBaseAddress; UINT32 ulAfConfBaseAddress; UINT32 ulFeatureBytesOffset; UINT32 ulFeatureBitOffset; UINT32 ulFeatureFieldLength; UINT32 ulMask; UINT32 ulTailSum; BOOL fTailDisplacementModified = FALSE; /* Get local pointer to shared portion of the API instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Obtain a pointer to the channel list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ); /* Calculate base addresses of NLP + AF configuration structure for the specified channel. */ ulNlpConfBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; ulAfConfBaseAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainIoMemOfst; /* Set the tail displacement.*/ if ( pSharedInfo->ImageInfo.fTailDisplacement == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( ( f_pVqeConfig->fEnableTailDisplacement != pChanEntry->VqeConfig.fEnableTailDisplacement ) || ( f_pVqeConfig->ulTailDisplacement != pChanEntry->VqeConfig.usTailDisplacement ) || ( f_pVqeConfig->fAcousticEcho != pChanEntry->VqeConfig.fAcousticEcho ) ) ) ) { /* Remember that the tail displacement parameters were changed. */ fTailDisplacementModified = TRUE; /* Check if we must set the tail displacement value. */ if ( ( f_pVqeConfig->fEnableTailDisplacement == TRUE ) && ( pSharedInfo->ImageInfo.fPerChannelTailDisplacement == TRUE ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.PerChanTailDisplacementFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.PerChanTailDisplacementFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.PerChanTailDisplacementFieldOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); if ( ( f_pVqeConfig->fEnableTailDisplacement == TRUE ) && ( f_pVqeConfig->ulTailDisplacement != 0x0 ) ) { if ( pSharedInfo->ImageInfo.fAfTailDisplacement == FALSE ) { if ( f_pVqeConfig->ulTailDisplacement == cOCT6100_AUTO_SELECT_TAIL ) { ulTempData |= ( ( ( pSharedInfo->ChipConfig.usTailDisplacement / 16 ) ) << ulFeatureBitOffset ); } else { ulTempData |= ( ( ( f_pVqeConfig->ulTailDisplacement / 16 ) ) << ulFeatureBitOffset ); } } else /* if ( pSharedInfo->ImageInfo.fAfTailDisplacement == TRUE ) */ { /* If AEC is not activated, this must be set to the requested tail displacement. */ if ( f_pVqeConfig->fAcousticEcho == FALSE ) { if ( f_pVqeConfig->ulTailDisplacement == cOCT6100_AUTO_SELECT_TAIL ) { ulTailSum = pSharedInfo->ChipConfig.usTailDisplacement; } else { ulTailSum = f_pVqeConfig->ulTailDisplacement; } if ( ulTailSum == 0 ) { ulTempData |= ( ( 0 ) << ulFeatureBitOffset ); } else if ( ulTailSum <= 128 ) { ulTempData |= ( ( 1 ) << ulFeatureBitOffset ); } else if ( ulTailSum <= 384 ) { ulTempData |= ( ( 3 ) << ulFeatureBitOffset ); } else /* if ( ulTailSum <= 896 ) */ { ulTempData |= ( ( 7 ) << ulFeatureBitOffset ); } } else /* if ( f_pVqeConfig->fAcousticEcho == FALSE ) */ { /* Otherwise, the tail displacement is configured differently. This field stays to 0. */ ulTempData |= ( 0x0 << ulFeatureBitOffset ); } } } /* Then save the new DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } if ( pSharedInfo->ImageInfo.fAfTailDisplacement == TRUE ) { /* Set the tail displacement offset in the AF. */ ulFeatureBytesOffset = pSharedInfo->MemoryMap.AfTailDisplacementFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.AfTailDisplacementFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.AfTailDisplacementFieldOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulAfConfBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); if ( f_pVqeConfig->ulTailDisplacement == cOCT6100_AUTO_SELECT_TAIL ) { ulTempData |= ( ( ( pSharedInfo->ChipConfig.usTailDisplacement / 16 ) ) << ulFeatureBitOffset ); } else { ulTempData |= ( ( ( f_pVqeConfig->ulTailDisplacement / 16 ) ) << ulFeatureBitOffset ); } /* Then save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulAfConfBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } ulFeatureBytesOffset = pSharedInfo->MemoryMap.TailDisplEnableOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.TailDisplEnableOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.TailDisplEnableOfst.byFieldSize; /* First read the DWORD where the field is located.*/ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); ulTempData |= ( ( (UINT32)f_pVqeConfig->fEnableTailDisplacement ) << ulFeatureBitOffset ); /* Then save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Set the tail length. */ if ( pSharedInfo->ImageInfo.fPerChannelTailLength == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( ( f_fModifyOnly == TRUE ) && ( f_pVqeConfig->ulTailLength != pChanEntry->VqeConfig.usTailLength ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.PerChanTailLengthFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.PerChanTailLengthFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.PerChanTailLengthFieldOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulAfConfBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* Check if must automatically select maximum or if must use user specific value. */ if ( f_pVqeConfig->ulTailLength == cOCT6100_AUTO_SELECT_TAIL ) { ulTempData |= ( ( ( pSharedInfo->ImageInfo.usMaxTailLength - 32 ) / 4 ) << ulFeatureBitOffset ); } else { ulTempData |= ( ( ( f_pVqeConfig->ulTailLength - 32 ) / 4 ) << ulFeatureBitOffset ); } /* Then save the DWORD where the field is located.*/ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulAfConfBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Configure AEC tail length. */ if ( pSharedInfo->ImageInfo.fAecTailLength == TRUE ) { /* Check if the configuration has been changed. */ if ( ( f_fModifyOnly == FALSE ) || ( fTailDisplacementModified == TRUE ) || ( ( f_fModifyOnly == TRUE ) && ( ( f_pVqeConfig->ulAecTailLength != pChanEntry->VqeConfig.usAecTailLength ) || ( f_pVqeConfig->fAcousticEcho != pChanEntry->VqeConfig.fAcousticEcho ) ) ) ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.AecTailLengthFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.AecTailLengthFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.AecTailLengthFieldOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* Set acoustic echo tail length. */ if ( f_pVqeConfig->fAcousticEcho == TRUE ) { switch( f_pVqeConfig->ulAecTailLength ) { case 1024: ulTempData |= ( ( 3 ) << ulFeatureBitOffset ); break; case 512: ulTempData |= ( ( 2 ) << ulFeatureBitOffset ); break; case 256: ulTempData |= ( ( 1 ) << ulFeatureBitOffset ); break; case 128: default: ulTempData |= ( ( 0 ) << ulFeatureBitOffset ); break; } } else if ( f_pVqeConfig->fEnableTailDisplacement == TRUE ) { /* No acoustic echo case. */ /* Start with requested tail displacement. */ if ( f_pVqeConfig->ulTailDisplacement == cOCT6100_AUTO_SELECT_TAIL ) { ulTailSum = pSharedInfo->ChipConfig.usTailDisplacement; } else { ulTailSum = f_pVqeConfig->ulTailDisplacement; } /* Add requested tail length. */ if ( f_pVqeConfig->ulTailLength == cOCT6100_AUTO_SELECT_TAIL ) { ulTailSum += pSharedInfo->ImageInfo.usMaxTailLength; } else { ulTailSum += f_pVqeConfig->ulTailLength; } /* Round this value up. */ if ( ulTailSum <= 128 ) { ulTempData |= ( ( 0 ) << ulFeatureBitOffset ); } else if ( ulTailSum <= 256 ) { ulTempData |= ( ( 1 ) << ulFeatureBitOffset ); } else if ( ulTailSum <= 512 ) { ulTempData |= ( ( 2 ) << ulFeatureBitOffset ); } else /* if ( ulTailSum <= 1024 ) */ { ulTempData |= ( ( 3 ) << ulFeatureBitOffset ); } } else { /* Keep this to zero. */ ulTempData |= ( ( 0 ) << ulFeatureBitOffset ); } /* Write the new DWORD where the field is located. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulNlpConfBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } return cOCT6100_ERR_OK; } #if 0 /* unused functions */ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ChannelMuteSer Description: This function will mute some of the ports on a given channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelMute What channel/ports to mute. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ChannelMuteSer( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_MUTE f_pChannelMute ) { UINT32 ulResult; UINT16 usChanIndex; UINT16 usPortMask; /* Verify that all the parameters given match the state of the API. */ ulResult = Oct6100ApiAssertChannelMuteParams( f_pApiInstance, f_pChannelMute, &usChanIndex, &usPortMask ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Call the actual channel mute ports function. */ ulResult = Oct6100ApiMuteChannelPorts( f_pApiInstance, usChanIndex, usPortMask, TRUE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiAssertChannelMuteParams Description: Check the user parameters passed to the channel mute function. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelMute What channel/ports to mute. f_pusChanIndex Resulting channel index where the muting should be applied. f_pusPorts Port mask on which to apply the muting. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiAssertChannelMuteParams( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_MUTE f_pChannelMute, OUT PUINT16 f_pusChanIndex, OUT PUINT16 f_pusPorts ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHANNEL pChanEntry; UINT32 ulEntryOpenCnt; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Check the provided handle. */ if ( (f_pChannelMute->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; *f_pusChanIndex = (UINT16)( f_pChannelMute->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); if ( *f_pusChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; /*=======================================================================*/ /* Get a pointer to the channel's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, *f_pusChanIndex ) /* Extract the entry open count from the provided handle. */ ulEntryOpenCnt = ( f_pChannelMute->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; /* Check for errors. */ if ( pChanEntry->fReserved != TRUE ) return cOCT6100_ERR_CHANNEL_NOT_OPEN; if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; if ( pChanEntry->fBiDirChannel == TRUE ) return cOCT6100_ERR_CHANNEL_PART_OF_BIDIR_CHANNEL; /*=======================================================================*/ /* Check the provided port mask. */ if ( ( f_pChannelMute->ulPortMask & ~( cOCT6100_CHANNEL_MUTE_PORT_NONE | cOCT6100_CHANNEL_MUTE_PORT_RIN | cOCT6100_CHANNEL_MUTE_PORT_ROUT | cOCT6100_CHANNEL_MUTE_PORT_SIN | cOCT6100_CHANNEL_MUTE_PORT_SOUT | cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) ) != 0 ) return cOCT6100_ERR_CHANNEL_MUTE_MASK; /* Sin + Sin with features cannot be muted simultaneously. */ if ( ( ( f_pChannelMute->ulPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) && ( ( f_pChannelMute->ulPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) ) return cOCT6100_ERR_CHANNEL_MUTE_MASK_SIN; /* Check if Sin mute with features is supported by the firmware. */ if ( ( ( f_pChannelMute->ulPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) && ( pSharedInfo->ImageInfo.fSinMute == FALSE ) ) return cOCT6100_ERR_NOT_SUPPORTED_CHANNEL_SIN_MUTE_FEATURES; /* Return the ports to the calling function. */ *f_pusPorts = (UINT16)( f_pChannelMute->ulPortMask & 0xFFFF ); return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ChannelUnMuteSer Description: This function will unmute some of the ports on a given channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelUnMute What channel/ports to unmute. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ChannelUnMuteSer( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute ) { UINT32 ulResult; UINT16 usChanIndex; UINT16 usPortMask; /* Verify that all the parameters given match the state of the API. */ ulResult = Oct6100ApiAssertChannelUnMuteParams( f_pApiInstance, f_pChannelUnMute, &usChanIndex, &usPortMask ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Call the actual channel mute ports function. */ ulResult = Oct6100ApiMuteChannelPorts( f_pApiInstance, usChanIndex, usPortMask, FALSE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiAssertChannelUnMuteParams Description: Check the user parameters passed to the channel unmute function. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChannelUnMute What channel/ports to Unmute. f_pusChanIndex Resulting channel index where the muting should be applied. f_pusPorts Port mask on which to apply the muting. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiAssertChannelUnMuteParams( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHANNEL_UNMUTE f_pChannelUnMute, OUT PUINT16 f_pusChanIndex, OUT PUINT16 f_pusPorts ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHANNEL pChanEntry; UINT32 ulEntryOpenCnt; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Check the provided handle. */ if ( (f_pChannelUnMute->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; *f_pusChanIndex = (UINT16)( f_pChannelUnMute->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); if ( *f_pusChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; /*=======================================================================*/ /* Get a pointer to the channel's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, *f_pusChanIndex ) /* Extract the entry open count from the provided handle. */ ulEntryOpenCnt = ( f_pChannelUnMute->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; /* Check for errors. */ if ( pChanEntry->fReserved != TRUE ) return cOCT6100_ERR_CHANNEL_NOT_OPEN; if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; if ( pChanEntry->fBiDirChannel == TRUE ) return cOCT6100_ERR_CHANNEL_PART_OF_BIDIR_CHANNEL; /*=======================================================================*/ /* Check the provided port mask. */ if ( ( f_pChannelUnMute->ulPortMask & ~( cOCT6100_CHANNEL_MUTE_PORT_NONE | cOCT6100_CHANNEL_MUTE_PORT_RIN | cOCT6100_CHANNEL_MUTE_PORT_ROUT | cOCT6100_CHANNEL_MUTE_PORT_SIN | cOCT6100_CHANNEL_MUTE_PORT_SOUT | cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) ) != 0 ) return cOCT6100_ERR_CHANNEL_MUTE_MASK; /* Return the ports to the calling function. */ *f_pusPorts = (UINT16)( f_pChannelUnMute->ulPortMask & 0xFFFF ); return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiMuteChannelPorts Description: Mute or Unmute the specified ports, according to the mask. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usChanIndex Resulting channel index where the muting should be applied. f_usPortMask Port mask on which to apply the muting/unmuting. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiMuteChannelPorts( IN tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usChanIndex, IN UINT16 f_usPortMask, IN BOOL f_fMute ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHANNEL pChanEntry; tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; UINT32 ulTempData; UINT32 ulBaseAddress; UINT32 ulFeatureBytesOffset; UINT32 ulFeatureBitOffset; UINT32 ulFeatureFieldLength; UINT32 ulMask; BOOL fDisableSinWithFeatures = FALSE; BOOL fEnableSinWithFeatures = FALSE; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* Get a pointer to the channel's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, f_usChanIndex ) /* Rin port. */ if ( ( f_fMute == TRUE ) && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_RIN ) != 0x0 ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_RIN ) == 0x0 ) ) { /* Mute this port. */ pChanEntry->usMutedPorts |= cOCT6100_CHANNEL_MUTE_PORT_RIN; ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_usChanIndex, pChanEntry->usRinTsstIndex, pChanEntry->usSinTsstIndex, TRUE ); if ( ulResult != cOCT6100_ERR_OK ) { pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_RIN; return ulResult; } } else if ( ( f_fMute == FALSE ) && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_RIN ) != 0x0 ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_RIN ) != 0x0 ) ) { /* Unmute this port. */ pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_RIN; ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_usChanIndex, pChanEntry->usRinTsstIndex, pChanEntry->usSinTsstIndex, TRUE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Rout port. */ if ( ( f_fMute == TRUE ) && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) != 0x0 ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) == 0x0 ) ) { /* Mute this port. */ if ( pChanEntry->usRoutTsstIndex != cOCT6100_INVALID_INDEX ) { /* Deactivate the TSST entry.*/ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pChanEntry->usRoutTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } pChanEntry->usMutedPorts |= cOCT6100_CHANNEL_MUTE_PORT_ROUT; } else if ( ( f_fMute == FALSE ) && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) != 0x0 ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_ROUT ) != 0x0 ) ) { /* Unmute this port. */ if ( pChanEntry->usRoutTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, pChanEntry->usRoutTsstIndex, pChanEntry->CodecConfig.byAdpcmNibblePosition, pChanEntry->TdmConfig.byRoutNumTssts, pChanEntry->usRinRoutTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_ROUT; } /* Sin port. */ if ( ( f_fMute == TRUE ) && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN ) == 0x0 ) ) { /* Mute this port. */ pChanEntry->usMutedPorts |= cOCT6100_CHANNEL_MUTE_PORT_SIN; ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_usChanIndex, pChanEntry->usRinTsstIndex, pChanEntry->usSinTsstIndex, TRUE ); if ( ulResult != cOCT6100_ERR_OK ) { pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_SIN; return ulResult; } } else if ( ( ( f_fMute == FALSE ) && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) ) || ( ( f_fMute == TRUE ) && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) ) ) { /* Unmute this port. */ pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_SIN; ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_usChanIndex, pChanEntry->usRinTsstIndex, pChanEntry->usSinTsstIndex, TRUE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Sout port. */ if ( ( f_fMute == TRUE ) && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) != 0x0 ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) == 0x0 ) ) { /* Mute this port. */ if ( pChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) { /* Deactivate the TSST entry.*/ WriteParams.ulWriteAddress = cOCT6100_TSST_CONTROL_MEM_BASE + ( pChanEntry->usSoutTsstIndex * cOCT6100_TSST_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } pChanEntry->usMutedPorts |= cOCT6100_CHANNEL_MUTE_PORT_SOUT; } else if ( ( f_fMute == FALSE ) && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) != 0x0 ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SOUT ) != 0x0 ) ) { /* Unmute this port. */ if ( pChanEntry->usSoutTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteOutputTsstControlMemory( f_pApiInstance, pChanEntry->usSoutTsstIndex, pChanEntry->CodecConfig.byAdpcmNibblePosition, pChanEntry->TdmConfig.bySoutNumTssts, pChanEntry->usSinSoutTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_SOUT; } /* Sin with features port. */ if ( ( f_fMute == TRUE ) && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) == 0x0 ) ) { /* Mute this port. */ pChanEntry->usMutedPorts |= cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES; fEnableSinWithFeatures = TRUE; } else if ( ( ( f_fMute == FALSE ) && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) ) || ( ( f_fMute == TRUE ) && ( ( f_usPortMask & cOCT6100_CHANNEL_MUTE_PORT_SIN ) != 0x0 ) && ( ( pChanEntry->usMutedPorts & cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES ) != 0x0 ) ) ) { /* Unmute this port. */ pChanEntry->usMutedPorts &= ~cOCT6100_CHANNEL_MUTE_PORT_SIN_WITH_FEATURES; fDisableSinWithFeatures = TRUE; } /* Check if must enable or disable SIN mute with features. */ if ( fDisableSinWithFeatures == TRUE || fEnableSinWithFeatures == TRUE ) { ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( pChanEntry->usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; if ( pSharedInfo->ImageInfo.fSinMute == TRUE ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.SinMuteOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.SinMuteOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.SinMuteOfst.byFieldSize; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); /* Clear the mute flag. */ ulTempData &= (~ulMask); /* Set the mute flag on the Sin port.*/ if ( fEnableSinWithFeatures == TRUE ) ulTempData |= ( 0x1 << ulFeatureBitOffset ); /* Write the new DWORD where the field is located. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pChanEntry, ulBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } return cOCT6100_ERR_OK; } #endif /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_chip_open.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains the functions used to power-up the chip according to the user's configuration. Also, the API instance is initialized to reflect the desired configuration. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 305 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "apilib/octapi_bt0.h" #include "apilib/octapi_llman.h" #include "oct6100api/oct6100_apiud.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_tsi_cnct_inst.h" #include "oct6100api/oct6100_events_inst.h" #include "oct6100api/oct6100_conf_bridge_inst.h" #include "oct6100api/oct6100_playout_buf_inst.h" #include "oct6100api/oct6100_mixer_inst.h" #include "oct6100api/oct6100_channel_inst.h" #include "oct6100api/oct6100_adpcm_chan_inst.h" #include "oct6100api/oct6100_phasing_tsst_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_chip_stats_pub.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_tsi_cnct_pub.h" #include "oct6100api/oct6100_events_pub.h" #include "oct6100api/oct6100_conf_bridge_pub.h" #include "oct6100api/oct6100_playout_buf_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_adpcm_chan_pub.h" #include "oct6100api/oct6100_phasing_tsst_pub.h" #include "oct6100api/oct6100_remote_debug_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100api/oct6100_mixer_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_debug_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_interrupts_priv.h" #include "oct6100_chip_stats_priv.h" #include "octrpc/rpc_protocol.h" #include "oct6100_remote_debug_priv.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_memory_priv.h" #include "oct6100_tsst_priv.h" #include "oct6100_tsi_cnct_priv.h" #include "oct6100_mixer_priv.h" #include "oct6100_events_priv.h" #include "oct6100_conf_bridge_priv.h" #include "oct6100_playout_buf_priv.h" #include "oct6100_channel_priv.h" #include "oct6100_adpcm_chan_priv.h" #include "oct6100_phasing_tsst_priv.h" #include "oct6100_tlv_priv.h" #include "oct6100_debug_priv.h" #include "oct6100_version.h" /**************************** PUBLIC FUNCTIONS *****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100GetInstanceSizeDef Description: Retrieves the size of the required API instance structure. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pGetSize Structure containing API instance size. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100GetInstanceSizeDef( tPOCT6100_GET_INSTANCE_SIZE f_pGetSize ) { return cOCT6100_ERR_OK; } static UINT32 Oct6100GetInstanceSize( tPOCT6100_CHIP_OPEN f_pChipOpen, tPOCT6100_GET_INSTANCE_SIZE f_pGetSize ) { tOCT6100_API_INSTANCE_SIZES InstanceSizes; UINT32 ulResult; /* Check user configuration for errors and conflicts. */ ulResult = Oct6100ApiCheckChipConfiguration( f_pChipOpen ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Calculate the instance size required for user's configuration. */ ulResult = Oct6100ApiCalculateInstanceSizes( f_pChipOpen, &InstanceSizes ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Return required size to user. */ f_pGetSize->ulApiInstanceSize = InstanceSizes.ulApiInstTotal; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ChipOpenDef Description: Inserts default chip configuration parameters into the structure pointed to by f_pChipOpen. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pChipOpen Structure containing user chip configuration. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ChipOpenDef( tPOCT6100_CHIP_OPEN f_pChipOpen ) { UINT32 i; f_pChipOpen->ulUserChipId = 0; f_pChipOpen->fMultiProcessSystem = FALSE; f_pChipOpen->pProcessContext = NULL; f_pChipOpen->ulMaxRwAccesses = 8; f_pChipOpen->pbyImageFile = NULL; f_pChipOpen->ulImageSize = 0; f_pChipOpen->ulMemClkFreq = 133000000; /* 133 Mhz */ f_pChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ; /* 33.33 Mhz */ f_pChipOpen->fEnableMemClkOut = TRUE; f_pChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR; f_pChipOpen->ulNumMemoryChips = 1; f_pChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_64MB; /* Set the tail displacement to zero. */ f_pChipOpen->ulTailDisplacement = 0; /* Disable acoustic echo by default. */ f_pChipOpen->fEnableAcousticEcho = FALSE; /* Resource allocation parameters. */ f_pChipOpen->ulMaxChannels = 672; f_pChipOpen->ulMaxTsiCncts = 0; f_pChipOpen->ulMaxBiDirChannels = 0; f_pChipOpen->ulMaxConfBridges = 0; f_pChipOpen->ulMaxFlexibleConfParticipants = 0; f_pChipOpen->ulMaxPlayoutBuffers = 0; f_pChipOpen->ulMaxPhasingTssts = 0; f_pChipOpen->ulMaxAdpcmChannels = 0; f_pChipOpen->ulMaxTdmStreams = 32; f_pChipOpen->fUseSynchTimestamp = FALSE; for ( i = 0; i < 4; i++ ) { f_pChipOpen->aulTimestampTimeslots[ i ] = cOCT6100_INVALID_TIMESLOT; f_pChipOpen->aulTimestampStreams[ i ] = cOCT6100_INVALID_STREAM; } f_pChipOpen->fEnableFastH100Mode = FALSE; /* Configure the soft tone event buffer. */ f_pChipOpen->ulSoftToneEventsBufSize = 2048; f_pChipOpen->fEnableExtToneDetection = FALSE; /* Configure the soft playout event buffer. */ f_pChipOpen->ulSoftBufferPlayoutEventsBufSize = cOCT6100_INVALID_VALUE; /* Interrupt configuration. */ f_pChipOpen->ulInterruptPolarity = cOCT6100_ACTIVE_LOW_POLARITY; f_pChipOpen->InterruptConfig.ulErrorMemoryConfig = cOCT6100_INTERRUPT_NO_TIMEOUT; f_pChipOpen->InterruptConfig.ulFatalGeneralConfig = cOCT6100_INTERRUPT_NO_TIMEOUT; f_pChipOpen->InterruptConfig.ulFatalMemoryConfig = cOCT6100_INTERRUPT_NO_TIMEOUT; f_pChipOpen->InterruptConfig.ulFatalMemoryConfig = cOCT6100_INTERRUPT_NO_TIMEOUT; f_pChipOpen->InterruptConfig.ulErrorH100Config = cOCT6100_INTERRUPT_NO_TIMEOUT; f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsConfig = cOCT6100_INTERRUPT_NO_TIMEOUT; f_pChipOpen->InterruptConfig.ulErrorMemoryTimeout = 100; f_pChipOpen->InterruptConfig.ulFatalMemoryTimeout = 100; f_pChipOpen->InterruptConfig.ulErrorH100Timeout = 100; f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsTimeout = 100; f_pChipOpen->ulMaxRemoteDebugSessions = 1; f_pChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_3_QUARTERS; for ( i = 0; i < cOCT6100_TDM_STREAM_MAX_GROUPS; i++ ) f_pChipOpen->aulTdmStreamFreqs[ i ] = cOCT6100_TDM_STREAM_FREQ_8MHZ; f_pChipOpen->fEnableChannelRecording = FALSE; f_pChipOpen->fEnableProductionBist = FALSE; f_pChipOpen->ulNumProductionBistLoops = 1; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ChipOpen Description: Configures the chip according to the user specified configuration f_pChipOpen. This function will perform all I/O accesses necessary and initialize the API instance to reflect the configuration. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChipOpen Structure containing user chip configuration. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ChipOpen( tPOCT6100_INSTANCE_API f_pApiInstance, tPOCT6100_CHIP_OPEN f_pChipOpen ) { tOCT6100_API_INSTANCE_SIZES InstanceSizes; UINT32 ulStructSize; UINT32 ulResult; UINT32 ulTempVar; /* Check user chip configuration parameters for errors. */ ulResult = Oct6100ApiCheckChipConfiguration( f_pChipOpen ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check if the host system is multi-process or not and adjust instance accordingly. */ if ( f_pChipOpen->fMultiProcessSystem != TRUE ) { /* Set pointer to tOCT6100_SHARED_INFO structure within instance. */ ulStructSize = sizeof( tOCT6100_INSTANCE_API ); mOCT6100_ROUND_MEMORY_SIZE( ulStructSize, ulTempVar ) f_pApiInstance->pSharedInfo = ( tPOCT6100_SHARED_INFO )(( PVOID )f_pApiInstance + ulStructSize); /* Save the process context specified by the user. */ f_pApiInstance->pProcessContext = f_pChipOpen->pProcessContext; /* Create serialization object handles. */ ulResult = Oct6100ApiCreateSerializeObjects( f_pApiInstance, f_pChipOpen->ulUserChipId ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Copy the configuration structure. */ ulResult = Oct6100ApiCopyChipConfiguration( f_pApiInstance, f_pChipOpen ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Perform various calculations based on user chip configuration. */ ulResult = Oct6100ApiInitializeMiscellaneousVariables( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Calculate the amount of memory needed for the API instance structure. */ ulResult = Oct6100ApiCalculateInstanceSizes( f_pChipOpen, &InstanceSizes ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Allocate the memory for the API instance structure internal pointers. */ ulResult = Oct6100ApiAllocateInstanceMemory( f_pApiInstance, &InstanceSizes ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Initialize the allocated instance structure memory. */ ulResult = Oct6100ApiInitializeInstanceMemory( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Initialize the tone information structure. */ ulResult = Oct6100ApiInitToneInfo( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Test the CPU registers. */ ulResult = Oct6100ApiCpuRegisterBist( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Boot the FC2 PLL. */ ulResult = Oct6100ApiBootFc2Pll( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Program the FC1 PLL. */ ulResult = Oct6100ApiProgramFc1Pll( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Decode the key and bist internal memories. */ ulResult = Oct6100ApiDecodeKeyAndBist( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Boot the FC1 PLL. */ ulResult = Oct6100ApiBootFc1Pll( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Boot the SDRAM. */ ulResult = Oct6100ApiBootSdram( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Bist the external memory. */ ulResult = Oct6100ApiExternalMemoryBist( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Initialize the external memory. */ ulResult = Oct6100ApiExternalMemoryInit( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Load the image into the chip. */ ulResult = Oct6100ApiLoadImage( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write the clock distribution registers. */ ulResult = Oct6100ApiEnableClocks( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Program the NLP processor. */ ulResult = Oct6100ApiProgramNLP( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) { if ( ulResult == cOCT6100_ERR_OPEN_EGO_TIMEOUT ) ulResult = Oct6100ApiProgramNLP( f_pApiInstance ); } if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( f_pChipOpen->fEnableProductionBist == FALSE ) { /* Read all TLV fields present in external memory. */ ulResult = Oct6100ApiProcessTlvRegion( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Configure the H.100 interface. */ ulResult = Oct6100ApiSetH100Register( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Write miscellaneous registers. */ ulResult = Oct6100ApiWriteMiscellaneousRegisters( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Proceed with the rest only if the production BIST has not been requested. */ if ( f_pChipOpen->fEnableProductionBist == FALSE ) { /* Configure the interrupt registers. */ ulResult = Oct6100ApiIsrHwInit( f_pApiInstance, &f_pChipOpen->InterruptConfig ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Initialize the errors counters. */ ulResult = Oct6100ApiChipStatsSwInit( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Configure all interrupts of the chip. */ ulResult = Oct6100InterruptConfigureSer( f_pApiInstance, &f_pChipOpen->InterruptConfig, FALSE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Get revision number of chip. */ ulResult = Oct6100ApiGetChipRevisionNum( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Initialize the channels. */ ulResult = Oct6100ApiInitChannels( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Initialize the mixer memory. */ ulResult = Oct6100ApiInitMixer( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Initialize the mixer memory. */ ulResult = Oct6100ApiInitRecordResources( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Initialize free external memory for buffer playout. */ ulResult = Oct6100ApiBufferPlayoutMemorySwInit( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ChipCloseDef Description: Puts the chip into soft reset. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChipClose Pointer to a tOCT6100_CHIP_CLOSE structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ChipCloseDef( tPOCT6100_CHIP_CLOSE f_pChipClose ) { f_pChipClose->ulDummyVariable = 0; return cOCT6100_ERR_OK; } static UINT32 Oct6100ChipClose( tPOCT6100_INSTANCE_API f_pApiInstance, tPOCT6100_CHIP_CLOSE f_pChipClose ) { tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; WriteParams.ulWriteAddress = 0x100; WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Destroy the allocated ressources used for serialization. */ ulResult = Oct6100ApiDestroySerializeObjects( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*************************** PRIVATE FUNCTIONS *****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiStrStr Description: OCT6100 API version of strstr() ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pszSource Source string to analyze. f_pszString String to look for. f_pszLastCharPtr Last character in the source string. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static PUINT8 Oct6100ApiStrStr( IN PUINT8 f_pszSource, IN PUINT8 f_pszString, IN PUINT8 f_pszLastCharPtr ) { UINT32 ulCurrentPos; UINT32 ulStringLength; UINT32 ulNumMatchingCharFound = 0; PUINT8 pchFirstChar = NULL; UINT32 ulSourceLength; if ( f_pszLastCharPtr < f_pszSource ) return NULL; ulSourceLength = f_pszLastCharPtr - f_pszSource; ulStringLength = Oct6100ApiStrLen( f_pszString ); for ( ulCurrentPos = 0; ulCurrentPos < ulSourceLength; ulCurrentPos++ ) { /* Check if the character matches. */ if ( f_pszSource[ ulCurrentPos ] == f_pszString[ ulNumMatchingCharFound ] ) { if ( ulNumMatchingCharFound == 0 ) pchFirstChar = ( f_pszSource + ulCurrentPos ); ulNumMatchingCharFound++; /* Check if the whole string matched. */ if ( ulNumMatchingCharFound == ulStringLength ) break; } else if ( ulNumMatchingCharFound != 0 ) { ulNumMatchingCharFound = 0; /* Reset the search, but take a look at the current character. It might */ /* be the beginning of the string we are looking for. */ if ( f_pszSource[ ulCurrentPos ] == f_pszString[ ulNumMatchingCharFound ] ) { pchFirstChar = ( f_pszSource + ulCurrentPos ); ulNumMatchingCharFound++; /* Check if the whole string matched. */ /* This check must be done in case we have the 1 character strstr */ if ( ulNumMatchingCharFound == ulStringLength ) break; } } } if ( ulCurrentPos == ulSourceLength ) return NULL; else return pchFirstChar; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiStrLen Description: OCT6100 API version of strlen() ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pszString Source string to count length of. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiStrLen( IN PUINT8 f_pszString ) { UINT32 ulCount = 0; while( f_pszString[ ulCount ] != '\0' ) ulCount++; return ulCount; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiAsciiToHex Description: Convert an ASCII character to an hexadecimal value. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_chCharacter ASCII character to convert. f_pulValue Resulting hexadecimal value. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiAsciiToHex( IN UINT8 f_chCharacter, OUT PUINT32 f_pulValue ) { switch ( f_chCharacter ) { case '0': (*f_pulValue) = 0x0; break; case '1': (*f_pulValue) = 0x1; break; case '2': (*f_pulValue) = 0x2; break; case '3': (*f_pulValue) = 0x3; break; case '4': (*f_pulValue) = 0x4; break; case '5': (*f_pulValue) = 0x5; break; case '6': (*f_pulValue) = 0x6; break; case '7': (*f_pulValue) = 0x7; break; case '8': (*f_pulValue) = 0x8; break; case '9': (*f_pulValue) = 0x9; break; case 'A': case 'a': (*f_pulValue) = 0xA; break; case 'B': case 'b': (*f_pulValue) = 0xB; break; case 'C': case 'c': (*f_pulValue) = 0xC; break; case 'D': case 'd': (*f_pulValue) = 0xD; break; case 'E': case 'e': (*f_pulValue) = 0xE; break; case 'F': case 'f': (*f_pulValue) = 0xF; break; default: (*f_pulValue) = 0x0; return cOCT6100_ERR_MISC_ASCII_CONVERSION_FAILED; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiHexToAscii Description: Convert an hexadecimal value to an ASCII character. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_ulNumber Hexadecimal value to convert. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT8 Oct6100ApiHexToAscii( IN UINT32 f_ulNumber ) { if ( f_ulNumber >= 0xA ) return (UINT8)( 55 + f_ulNumber ); /* Hex values from 0xA to 0xF */ else return (UINT8)( 48 + f_ulNumber ); /* Hex values from 0x0 to 0x9 */ } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiRand Description: Random number generator. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_ulRange Range of the random number to be generated. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiRand( IN UINT32 f_ulRange ) { static UINT32 ulRandomSeed = 0x12345678; UINT32 ulBit0; UINT32 i, j; UINT16 ulWithinRange = FALSE; UINT32 ulResult = cOCT6100_ERR_OK; UINT16 ulLoop; UINT32 ulRangeMask; UINT32 ulAddedValue; ulRangeMask = 1; ulLoop = TRUE; i = 1; while ( ulLoop ) { ulAddedValue = 2; for ( j = 1; j < i; j++ ) ulAddedValue *= 2; ulRangeMask = ulRangeMask + ulAddedValue; if ( ulRangeMask >= f_ulRange ) ulLoop = FALSE; i++; } while ( !ulWithinRange ) { ulBit0 = ((ulRandomSeed >> 19) & 0x1) ^ ((ulRandomSeed >> 16) & 0x1); ulRandomSeed = ((ulRandomSeed << 1) & 0xFFFFF) | ulBit0; ulResult = ulRandomSeed & ulRangeMask; if ( ulResult <= f_ulRange ) ulWithinRange = TRUE; } return ulResult; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiCheckChipConfiguration Description: Checks the user chip configuration structure for errors. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pChipOpen Pointer to chip configuration structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiCheckChipConfiguration( IN tPOCT6100_CHIP_OPEN f_pChipOpen ) { UINT32 ulTempVar; UINT32 i; /*-----------------------------------------------------------------------------*/ /* Check general parameters. */ if ( f_pChipOpen->fMultiProcessSystem != TRUE && f_pChipOpen->fMultiProcessSystem != FALSE ) return cOCT6100_ERR_OPEN_MULTI_PROCESS_SYSTEM; if ( f_pChipOpen->ulMaxRwAccesses < 1 || f_pChipOpen->ulMaxRwAccesses > 1024) return cOCT6100_ERR_OPEN_MAX_RW_ACCESSES; /* Check the clocks. */ if ( f_pChipOpen->ulUpclkFreq != cOCT6100_UPCLK_FREQ_33_33_MHZ && f_pChipOpen->ulUpclkFreq != cOCT6100_UPCLK_FREQ_66_67_MHZ ) return cOCT6100_ERR_OPEN_UP_CLK_FREQ; if ( f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_133_MHZ && f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_125_MHZ && f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_117_MHZ && f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_108_MHZ && f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_100_MHZ && f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_92_MHZ && f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_83_MHZ && f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_75_MHZ ) return cOCT6100_ERR_OPEN_MEM_CLK_FREQ; if ( f_pChipOpen->fEnableMemClkOut != TRUE && f_pChipOpen->fEnableMemClkOut != FALSE ) return cOCT6100_ERR_OPEN_ENABLE_MEM_CLK_OUT; /* Check the image file. */ if ( f_pChipOpen->ulImageSize < cOCT6100_MIN_IMAGE_SIZE || f_pChipOpen->ulImageSize > cOCT6100_MAX_IMAGE_SIZE ) return cOCT6100_ERR_OPEN_IMAGE_SIZE; if ( f_pChipOpen->pbyImageFile == NULL ) return cOCT6100_ERR_OPEN_IMAGE_FILE; /* Check the acoustic echo activation flag. */ if ( f_pChipOpen->fEnableAcousticEcho != TRUE && f_pChipOpen->fEnableAcousticEcho != FALSE ) return cOCT6100_ERR_OPEN_ENABLE_ACOUSTIC_ECHO; /* Check the tail displacement parameter. */ if ( f_pChipOpen->ulTailDisplacement > cOCT6100_MAX_TAIL_DISPLACEMENT ) return cOCT6100_ERR_OPEN_TAIL_DISPLACEMENT; /*-----------------------------------------------------------------------------*/ /* Check TDM bus configuration parameters. */ for ( i = 0; i < 8; i++ ) { if ( f_pChipOpen->aulTdmStreamFreqs[ i ] != cOCT6100_TDM_STREAM_FREQ_2MHZ && f_pChipOpen->aulTdmStreamFreqs[ i ] != cOCT6100_TDM_STREAM_FREQ_4MHZ && f_pChipOpen->aulTdmStreamFreqs[ i ] != cOCT6100_TDM_STREAM_FREQ_8MHZ) return cOCT6100_ERR_OPEN_TDM_STREAM_FREQS; } if ( f_pChipOpen->ulTdmSampling != cOCT6100_TDM_SAMPLE_AT_3_QUARTERS && f_pChipOpen->ulTdmSampling != cOCT6100_TDM_SAMPLE_AT_RISING_EDGE && f_pChipOpen->ulTdmSampling != cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE ) return cOCT6100_ERR_OPEN_TDM_SAMPLING; if ( f_pChipOpen->fEnableFastH100Mode != TRUE && f_pChipOpen->fEnableFastH100Mode != FALSE ) return cOCT6100_ERR_OPEN_FAST_H100_MODE; /*-----------------------------------------------------------------------------*/ /* Check external memory configuration parameters. */ if ( f_pChipOpen->ulMemoryType != cOCT6100_MEM_TYPE_SDR && f_pChipOpen->ulMemoryType != cOCT6100_MEM_TYPE_DDR && f_pChipOpen->ulMemoryType != cOCT6100_MEM_TYPE_SDR_PLL_BYPASS ) return cOCT6100_ERR_OPEN_MEMORY_TYPE; if ( f_pChipOpen->ulMemoryChipSize != cOCT6100_MEMORY_CHIP_SIZE_8MB && f_pChipOpen->ulMemoryChipSize != cOCT6100_MEMORY_CHIP_SIZE_16MB && f_pChipOpen->ulMemoryChipSize != cOCT6100_MEMORY_CHIP_SIZE_32MB && f_pChipOpen->ulMemoryChipSize != cOCT6100_MEMORY_CHIP_SIZE_64MB && f_pChipOpen->ulMemoryChipSize != cOCT6100_MEMORY_CHIP_SIZE_128MB ) return cOCT6100_ERR_OPEN_MEMORY_CHIP_SIZE; if ( f_pChipOpen->ulMemoryChipSize == cOCT6100_MEMORY_CHIP_SIZE_8MB && f_pChipOpen->ulMemoryType == cOCT6100_MEM_TYPE_DDR ) return cOCT6100_ERR_OPEN_MEMORY_CHIP_SIZE; if ( f_pChipOpen->ulNumMemoryChips < 1 || f_pChipOpen->ulNumMemoryChips > cOCT6100_MAX_NUM_MEMORY_CHIP ) return cOCT6100_ERR_OPEN_MEMORY_CHIPS_NUMBER; /* Check the total memory size. */ ulTempVar = f_pChipOpen->ulMemoryChipSize * f_pChipOpen->ulNumMemoryChips; if ( ulTempVar < cOCT6100_MEMORY_CHIP_SIZE_16MB || ulTempVar > cOCT6100_MEMORY_CHIP_SIZE_128MB ) return cOCT6100_ERR_OPEN_TOTAL_MEMORY_SIZE; if ( f_pChipOpen->ulMaxTdmStreams != 4 && f_pChipOpen->ulMaxTdmStreams != 8 && f_pChipOpen->ulMaxTdmStreams != 16 && f_pChipOpen->ulMaxTdmStreams != 32 ) return cOCT6100_ERR_OPEN_MAX_TDM_STREAM; if ( f_pChipOpen->ulMaxTdmStreams > 8 && f_pChipOpen->ulMemClkFreq == cOCT6100_MCLK_FREQ_75_MHZ ) return cOCT6100_ERR_OPEN_MAX_TDM_STREAM; if ( f_pChipOpen->fUseSynchTimestamp != TRUE && f_pChipOpen->fUseSynchTimestamp != FALSE ) return cOCT6100_ERR_OPEN_USE_SYNCH_TIMESTAMP; if ( f_pChipOpen->fUseSynchTimestamp == TRUE ) { return cOCT6100_ERR_NOT_SUPPORTED_OPEN_USE_SYNCH_TIMESTAMP; } /*-----------------------------------------------------------------------------*/ /* Check soft buffer for tone events size. */ if ( f_pChipOpen->ulSoftToneEventsBufSize < cOCT6100_NUM_PGSP_EVENT_OUT || f_pChipOpen->ulSoftToneEventsBufSize > cOCT6100_ABSOLUTE_MAX_NUM_PGSP_EVENT_OUT ) return cOCT6100_ERR_OPEN_SOFT_TONE_EVENT_SIZE; if ( f_pChipOpen->fEnableExtToneDetection != TRUE && f_pChipOpen->fEnableExtToneDetection != FALSE ) return cOCT6100_ERR_OPEN_ENABLE_EXT_TONE_DETECTION; /* Check soft buffer for playout events size. */ if ( ( f_pChipOpen->ulSoftBufferPlayoutEventsBufSize != cOCT6100_INVALID_VALUE ) && ( f_pChipOpen->ulSoftBufferPlayoutEventsBufSize < cOCT6100_MIN_BUFFER_PLAYOUT_EVENT || f_pChipOpen->ulSoftBufferPlayoutEventsBufSize > cOCT6100_MAX_BUFFER_PLAYOUT_EVENT ) ) return cOCT6100_ERR_OPEN_SOFT_PLAYOUT_STOP_EVENT_SIZE; /*-----------------------------------------------------------------------------*/ /* Check interrupt configuration parameters. */ if ( f_pChipOpen->ulInterruptPolarity != cOCT6100_ACTIVE_LOW_POLARITY && f_pChipOpen->ulInterruptPolarity != cOCT6100_ACTIVE_HIGH_POLARITY ) return cOCT6100_ERR_OPEN_INTERRUPT_POLARITY; if ( f_pChipOpen->InterruptConfig.ulFatalGeneralConfig != cOCT6100_INTERRUPT_NO_TIMEOUT && f_pChipOpen->InterruptConfig.ulFatalGeneralConfig != cOCT6100_INTERRUPT_DISABLE ) return cOCT6100_ERR_OPEN_FATAL_GENERAL_CONFIG; if ( f_pChipOpen->InterruptConfig.ulFatalMemoryConfig != cOCT6100_INTERRUPT_NO_TIMEOUT && f_pChipOpen->InterruptConfig.ulFatalMemoryConfig != cOCT6100_INTERRUPT_TIMEOUT && f_pChipOpen->InterruptConfig.ulFatalMemoryConfig != cOCT6100_INTERRUPT_DISABLE ) return cOCT6100_ERR_OPEN_FATAL_MEMORY_CONFIG; if ( f_pChipOpen->InterruptConfig.ulErrorMemoryConfig != cOCT6100_INTERRUPT_NO_TIMEOUT && f_pChipOpen->InterruptConfig.ulErrorMemoryConfig != cOCT6100_INTERRUPT_TIMEOUT && f_pChipOpen->InterruptConfig.ulErrorMemoryConfig != cOCT6100_INTERRUPT_DISABLE ) return cOCT6100_ERR_OPEN_ERROR_MEMORY_CONFIG; if ( f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_NO_TIMEOUT && f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_TIMEOUT && f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_DISABLE ) return cOCT6100_ERR_OPEN_ERROR_OVERFLOW_TONE_EVENTS_CONFIG; if ( f_pChipOpen->InterruptConfig.ulErrorH100Config != cOCT6100_INTERRUPT_NO_TIMEOUT && f_pChipOpen->InterruptConfig.ulErrorH100Config != cOCT6100_INTERRUPT_TIMEOUT && f_pChipOpen->InterruptConfig.ulErrorH100Config != cOCT6100_INTERRUPT_DISABLE ) return cOCT6100_ERR_OPEN_ERROR_H100_CONFIG; /* Check the timeout value. */ if ( f_pChipOpen->InterruptConfig.ulFatalMemoryTimeout < 10 || f_pChipOpen->InterruptConfig.ulFatalMemoryTimeout > 10000 ) return cOCT6100_ERR_OPEN_FATAL_MEMORY_TIMEOUT; if ( f_pChipOpen->InterruptConfig.ulErrorMemoryTimeout < 10 || f_pChipOpen->InterruptConfig.ulErrorMemoryTimeout > 10000 ) return cOCT6100_ERR_OPEN_ERROR_MEMORY_TIMEOUT; if ( f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsTimeout < 10 || f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsTimeout > 10000 ) return cOCT6100_ERR_OPEN_ERROR_OVERFLOW_TONE_EVENTS_TIMEOUT; if ( f_pChipOpen->InterruptConfig.ulErrorH100Timeout < 10 || f_pChipOpen->InterruptConfig.ulErrorH100Timeout > 10000 ) return cOCT6100_ERR_OPEN_ERROR_H100_TIMEOUT; /*-----------------------------------------------------------------------------*/ /* Check maximum resources. */ switch ( f_pChipOpen->ulMemClkFreq ) { case 133000000: ulTempVar = 672; break; case 125000000: ulTempVar = 624; break; case 117000000: ulTempVar = 576; break; case 108000000: ulTempVar = 528; break; case 100000000: ulTempVar = 480; break; case 92000000: ulTempVar = 432; break; case 83000000: ulTempVar = 384; break; case 75000000: ulTempVar = 336; break; default: return cOCT6100_ERR_FATAL_DA; } if ( f_pChipOpen->ulMaxChannels > ulTempVar ) return cOCT6100_ERR_OPEN_MAX_ECHO_CHANNELS; if ( f_pChipOpen->ulMaxTsiCncts > cOCT6100_MAX_TSI_CNCTS ) return cOCT6100_ERR_OPEN_MAX_TSI_CNCTS; if ( f_pChipOpen->ulMaxBiDirChannels > (f_pChipOpen->ulMaxChannels / 2) ) return cOCT6100_ERR_OPEN_MAX_BIDIR_CHANNELS; if ( f_pChipOpen->ulMaxConfBridges > cOCT6100_MAX_CONF_BRIDGE ) return cOCT6100_ERR_OPEN_MAX_CONF_BRIDGES; if ( f_pChipOpen->ulMaxFlexibleConfParticipants > cOCT6100_MAX_FLEX_CONF_PARTICIPANTS ) return cOCT6100_ERR_OPEN_MAX_FLEXIBLE_CONF_PARTICIPANTS; if ( f_pChipOpen->ulMaxPlayoutBuffers > cOCT6100_MAX_PLAYOUT_BUFFERS ) return cOCT6100_ERR_OPEN_MAX_PLAYOUT_BUFFERS; if ( f_pChipOpen->ulMaxPhasingTssts > cOCT6100_MAX_PHASING_TSST ) return cOCT6100_ERR_OPEN_MAX_PHASING_TSSTS; if ( f_pChipOpen->ulMaxAdpcmChannels > cOCT6100_MAX_ADPCM_CHANNELS ) return cOCT6100_ERR_OPEN_MAX_ADPCM_CHANNELS; if ( f_pChipOpen->ulMaxRemoteDebugSessions > 256 ) return cOCT6100_ERR_OPEN_MAX_REMOTE_DEBUG_SESSIONS; /* Check the channel recording flag. */ if ( f_pChipOpen->fEnableChannelRecording != TRUE && f_pChipOpen->fEnableChannelRecording != FALSE ) return cOCT6100_ERR_OPEN_DEBUG_CHANNEL_RECORDING; /* Check the enable production BIST flag. */ if ( ( f_pChipOpen->fEnableProductionBist != TRUE ) && ( f_pChipOpen->fEnableProductionBist != FALSE ) ) return cOCT6100_ERR_OPEN_ENABLE_PRODUCTION_BIST; /* Check number of loops for the production BIST. */ if ( f_pChipOpen->fEnableProductionBist == TRUE ) { if ( f_pChipOpen->ulNumProductionBistLoops == 0 ) return cOCT6100_ERR_OPEN_NUM_PRODUCTION_BIST_LOOPS; } /* If the production BIST has been requested, make sure all */ /* other resources are disabled. */ if ( f_pChipOpen->fEnableProductionBist == TRUE ) { /* All must be disabled. */ f_pChipOpen->ulMaxChannels = 0; f_pChipOpen->ulMaxTsiCncts = 0; f_pChipOpen->fEnableChannelRecording = FALSE; f_pChipOpen->ulMaxBiDirChannels = 0; f_pChipOpen->ulMaxConfBridges = 0; f_pChipOpen->ulMaxPlayoutBuffers = 0; f_pChipOpen->ulSoftBufferPlayoutEventsBufSize = cOCT6100_INVALID_VALUE; f_pChipOpen->ulMaxPhasingTssts = 0; f_pChipOpen->ulMaxAdpcmChannels = 0; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiCopyChipConfiguration Description: Copies the chip configuration from the user supplied config structure to the instance structure. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pChipOpen Pointer to chip configuration structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiCopyChipConfiguration( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CHIP_OPEN f_pChipOpen ) { tPOCT6100_SHARED_INFO pSharedInfo; UINT32 i; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; pSharedInfo->ChipConfig.ulUserChipId = f_pChipOpen->ulUserChipId; pSharedInfo->ChipConfig.fMultiProcessSystem = (UINT8)( f_pChipOpen->fMultiProcessSystem & 0xFF ); pSharedInfo->ChipConfig.usMaxRwAccesses = (UINT16)( f_pChipOpen->ulMaxRwAccesses & 0xFFFF ); pSharedInfo->ChipConfig.pbyImageFile = f_pChipOpen->pbyImageFile; pSharedInfo->ChipConfig.ulImageSize = f_pChipOpen->ulImageSize; pSharedInfo->ChipConfig.ulMemClkFreq = f_pChipOpen->ulMemClkFreq; pSharedInfo->ChipConfig.ulUpclkFreq = f_pChipOpen->ulUpclkFreq; pSharedInfo->ChipConfig.byMemoryType = (UINT8)( f_pChipOpen->ulMemoryType & 0xFF ); pSharedInfo->ChipConfig.byNumMemoryChips = (UINT8)( f_pChipOpen->ulNumMemoryChips & 0xFF ); pSharedInfo->ChipConfig.ulMemoryChipSize = f_pChipOpen->ulMemoryChipSize; pSharedInfo->ChipConfig.usTailDisplacement = (UINT16)( f_pChipOpen->ulTailDisplacement & 0xFFFF ); pSharedInfo->ChipConfig.fEnableAcousticEcho = (UINT8)( f_pChipOpen->fEnableAcousticEcho & 0xFF ); /* Resource allocation parameters. */ if ( f_pChipOpen->fEnableChannelRecording == TRUE && f_pChipOpen->ulMaxChannels == 672 ) pSharedInfo->ChipConfig.usMaxChannels = (UINT16)( ( f_pChipOpen->ulMaxChannels - 1 ) & 0xFFFF ); else pSharedInfo->ChipConfig.usMaxChannels = (UINT16)( f_pChipOpen->ulMaxChannels & 0xFFFF ); pSharedInfo->ChipConfig.usMaxTsiCncts = (UINT16)( f_pChipOpen->ulMaxTsiCncts & 0xFFFF ); pSharedInfo->ChipConfig.usMaxBiDirChannels = (UINT16)( f_pChipOpen->ulMaxBiDirChannels & 0xFFFF ); pSharedInfo->ChipConfig.usMaxConfBridges = (UINT16)( f_pChipOpen->ulMaxConfBridges & 0xFFFF ); pSharedInfo->ChipConfig.usMaxFlexibleConfParticipants = (UINT16)( f_pChipOpen->ulMaxFlexibleConfParticipants & 0xFFFF ); pSharedInfo->ChipConfig.usMaxPlayoutBuffers = (UINT16)( f_pChipOpen->ulMaxPlayoutBuffers & 0xFFFF ); pSharedInfo->ChipConfig.usMaxPhasingTssts = (UINT16)( f_pChipOpen->ulMaxPhasingTssts & 0xFFFF ); pSharedInfo->ChipConfig.usMaxAdpcmChannels = (UINT16)( f_pChipOpen->ulMaxAdpcmChannels & 0xFFFF ); pSharedInfo->ChipConfig.byMaxTdmStreams = (UINT8)( f_pChipOpen->ulMaxTdmStreams & 0xFF ); pSharedInfo->ChipConfig.fUseSynchTimestamp = (UINT8)( f_pChipOpen->fUseSynchTimestamp & 0xFF ); for ( i = 0; i < 4; i++ ) { pSharedInfo->ChipConfig.ausTimestampTimeslots[ i ] = (UINT16)( f_pChipOpen->aulTimestampTimeslots[ i ] & 0xFFFF ); pSharedInfo->ChipConfig.ausTimestampStreams[ i ] = (UINT16)( f_pChipOpen->aulTimestampStreams[ i ] & 0xFFFF ); } pSharedInfo->ChipConfig.byInterruptPolarity = (UINT8)( f_pChipOpen->ulInterruptPolarity & 0xFF ); pSharedInfo->ChipConfig.byTdmSampling = (UINT8)( f_pChipOpen->ulTdmSampling & 0xFF ); pSharedInfo->ChipConfig.fEnableFastH100Mode = (UINT8)( f_pChipOpen->fEnableFastH100Mode & 0xFF ); for ( i = 0; i < cOCT6100_TDM_STREAM_MAX_GROUPS; i++ ) { if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) pSharedInfo->ChipConfig.aulTdmStreamFreqs[ i ] = cOCT6100_TDM_STREAM_FREQ_16MHZ; else pSharedInfo->ChipConfig.aulTdmStreamFreqs[ i ] = f_pChipOpen->aulTdmStreamFreqs[ i ]; } pSharedInfo->ChipConfig.fEnableFastH100Mode = (UINT8)( f_pChipOpen->fEnableFastH100Mode & 0xFF ); pSharedInfo->ChipConfig.fEnableMemClkOut = (UINT8)( f_pChipOpen->fEnableMemClkOut & 0xFF ); /* Add 1 to the circular buffer such that all user requested events can fit in the circular queue. */ pSharedInfo->ChipConfig.ulSoftToneEventsBufSize = f_pChipOpen->ulSoftToneEventsBufSize + 1; pSharedInfo->ChipConfig.fEnableExtToneDetection = (UINT8)( f_pChipOpen->fEnableExtToneDetection & 0xFF ); if ( f_pChipOpen->ulSoftBufferPlayoutEventsBufSize != cOCT6100_INVALID_VALUE ) pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize = f_pChipOpen->ulSoftBufferPlayoutEventsBufSize + 1; else pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize = 0; pSharedInfo->ChipConfig.usMaxRemoteDebugSessions = (UINT16)( f_pChipOpen->ulMaxRemoteDebugSessions & 0xFFFF ); pSharedInfo->ChipConfig.fEnableChannelRecording = (UINT8)( f_pChipOpen->fEnableChannelRecording & 0xFF ); pSharedInfo->ChipConfig.fEnableProductionBist = (UINT8)( f_pChipOpen->fEnableProductionBist & 0xFF ); pSharedInfo->ChipConfig.ulNumProductionBistLoops = f_pChipOpen->ulNumProductionBistLoops; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiInitializeMiscellaneousVariables Description: Function where all the various parameters from the API instance are set to their defaults value. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiInitializeMiscellaneousVariables( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; UINT32 i; /* Obtain pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Calculate the total memory available. */ pSharedInfo->MiscVars.ulTotalMemSize = pSharedInfo->ChipConfig.ulMemoryChipSize * pSharedInfo->ChipConfig.byNumMemoryChips; /* Software buffers initialization. */ /* Tones */ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr = 0; pSharedInfo->SoftBufs.ulToneEventBufferReadPtr = 0; pSharedInfo->SoftBufs.ulToneEventBufferSize = pSharedInfo->ChipConfig.ulSoftToneEventsBufSize; pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt = 0; /* Playout */ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr = 0; pSharedInfo->SoftBufs.ulBufPlayoutEventBufferReadPtr = 0; pSharedInfo->SoftBufs.ulBufPlayoutEventBufferSize = pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize; pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt = 0; /* Set the number of conference bridges opened to zero. */ pSharedInfo->MiscVars.usNumBridgesOpened = 0; pSharedInfo->MiscVars.usFirstBridge = cOCT6100_INVALID_INDEX; /* Set the H.100 slave mode. */ pSharedInfo->MiscVars.ulH100SlaveMode = cOCT6100_H100_TRACKA; /* Save the Mclk value.*/ pSharedInfo->MiscVars.ulMclkFreq = pSharedInfo->ChipConfig.ulMemClkFreq; /* Init the NLP params. */ pSharedInfo->MiscVars.usCodepoint = 0; pSharedInfo->MiscVars.usCpuLsuWritePtr = 0; /* Pouch counter not present until TLVs are read. */ pSharedInfo->DebugInfo.fPouchCounter = FALSE; pSharedInfo->DebugInfo.fIsIsrCalledField = FALSE; /* Initialize the image info parameters */ pSharedInfo->ImageInfo.fAdaptiveNoiseReduction = FALSE; pSharedInfo->ImageInfo.fSoutNoiseBleaching = FALSE; pSharedInfo->ImageInfo.fComfortNoise = FALSE; pSharedInfo->ImageInfo.fBufferPlayout = TRUE; pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip = FALSE; pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip = FALSE; pSharedInfo->ImageInfo.fNlpControl = FALSE; pSharedInfo->ImageInfo.fRinAutoLevelControl = FALSE; pSharedInfo->ImageInfo.fSoutAutoLevelControl = FALSE; pSharedInfo->ImageInfo.fRinHighLevelCompensation = FALSE; pSharedInfo->ImageInfo.fSoutHighLevelCompensation = FALSE; pSharedInfo->ImageInfo.fAlcHlcStatus = FALSE; pSharedInfo->ImageInfo.fRinDcOffsetRemoval = FALSE; pSharedInfo->ImageInfo.fSilenceSuppression = FALSE; pSharedInfo->ImageInfo.fSinDcOffsetRemoval = FALSE; pSharedInfo->ImageInfo.fToneDisabler = FALSE; pSharedInfo->ImageInfo.fAdpcm = FALSE; pSharedInfo->ImageInfo.fTailDisplacement = FALSE; pSharedInfo->ImageInfo.fConferencing = FALSE; pSharedInfo->ImageInfo.fConferencingNoiseReduction = FALSE; pSharedInfo->ImageInfo.fDominantSpeakerEnabled = FALSE; pSharedInfo->ImageInfo.fAecEnabled = FALSE; pSharedInfo->ImageInfo.fAcousticEcho = FALSE; pSharedInfo->ImageInfo.fToneRemoval = FALSE; pSharedInfo->ImageInfo.fDefaultErl = FALSE; pSharedInfo->ImageInfo.fMaxEchoPoint = FALSE; pSharedInfo->ImageInfo.fNonLinearityBehaviorA = FALSE; pSharedInfo->ImageInfo.fNonLinearityBehaviorB = FALSE; pSharedInfo->ImageInfo.fPerChannelTailDisplacement = FALSE; pSharedInfo->ImageInfo.fPerChannelTailLength = FALSE; pSharedInfo->ImageInfo.fAfTailDisplacement = FALSE; pSharedInfo->ImageInfo.fMusicProtection = FALSE; pSharedInfo->ImageInfo.fAftControl = FALSE; pSharedInfo->ImageInfo.fSinVoiceDetectedStat = FALSE; pSharedInfo->ImageInfo.fRinAppliedGainStat = FALSE; pSharedInfo->ImageInfo.fSoutAppliedGainStat = FALSE; pSharedInfo->ImageInfo.fListenerEnhancement = FALSE; pSharedInfo->ImageInfo.fRoutNoiseReduction = FALSE; pSharedInfo->ImageInfo.fAnrSnrEnhancement = FALSE; pSharedInfo->ImageInfo.fAnrVoiceNoiseSegregation = FALSE; pSharedInfo->ImageInfo.fRinMute = FALSE; pSharedInfo->ImageInfo.fSinMute = FALSE; pSharedInfo->ImageInfo.fToneDisablerVqeActivationDelay = FALSE; pSharedInfo->ImageInfo.fAecTailLength = FALSE; pSharedInfo->ImageInfo.fMusicProtectionConfiguration= FALSE; pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents = FALSE; pSharedInfo->ImageInfo.fRinEnergyStat = FALSE; pSharedInfo->ImageInfo.fSoutEnergyStat = FALSE; pSharedInfo->ImageInfo.fDoubleTalkBehavior = FALSE; pSharedInfo->ImageInfo.fDoubleTalkBehaviorFieldOfst = FALSE; pSharedInfo->ImageInfo.fIdleCodeDetection = TRUE; pSharedInfo->ImageInfo.fIdleCodeDetectionConfiguration = FALSE; pSharedInfo->ImageInfo.fSinLevel = TRUE; pSharedInfo->ImageInfo.usMaxNumberOfChannels = 0; pSharedInfo->ImageInfo.ulToneProfileNumber = cOCT6100_INVALID_VALUE; pSharedInfo->ImageInfo.ulBuildId = cOCT6100_INVALID_VALUE; pSharedInfo->ImageInfo.byImageType = cOCT6100_IMAGE_TYPE_WIRELINE; pSharedInfo->ImageInfo.usMaxTailDisplacement = 0; pSharedInfo->ImageInfo.usMaxTailLength = cOCT6100_TAIL_LENGTH_128MS; pSharedInfo->DebugInfo.ulDebugEventSize = 0x100; pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents = 32; pSharedInfo->DebugInfo.ulMatrixBaseAddress = cOCT6100_MATRIX_DWORD_BASE; pSharedInfo->DebugInfo.ulDebugChanStatsByteSize = cOCT6100_DEBUG_CHAN_STATS_EVENT_BYTE_SIZE; pSharedInfo->DebugInfo.ulDebugChanLiteStatsByteSize = cOCT6100_DEBUG_CHAN_STATS_LITE_EVENT_BYTE_SIZE; pSharedInfo->DebugInfo.ulHotChannelSelectBaseAddress= cOCT6100_MATRIX_CHAN_SELECT_DWORD_ADD; pSharedInfo->DebugInfo.ulMatrixTimestampBaseAddress = cOCT6100_MATRIX_TIMESTAMP_DWORD_ADD; pSharedInfo->DebugInfo.ulMatrixWpBaseAddress = cOCT6100_MATRIX_WRITE_PTR_DWORD_ADD; pSharedInfo->DebugInfo.ulAfWritePtrByteOffset = 206; pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize = 4096; pSharedInfo->DebugInfo.ulAfEventCbByteSize = 0x100000; /* Set all tones to invalid. */ pSharedInfo->ImageInfo.byNumToneDetectors = 0; for ( i = 0; i < cOCT6100_MAX_TONE_EVENT; i++ ) { pSharedInfo->ImageInfo.aToneInfo[ i ].ulToneID = cOCT6100_INVALID_VALUE; pSharedInfo->ImageInfo.aToneInfo[ i ].ulDetectionPort = cOCT6100_INVALID_PORT; Oct6100UserMemSet( pSharedInfo->ImageInfo.aToneInfo[ i ].aszToneName, 0x00, cOCT6100_TLV_MAX_TONE_NAME_SIZE ); } /* Initialize the channel recording info. */ pSharedInfo->DebugInfo.usRecordChanIndex = pSharedInfo->ChipConfig.usMaxChannels; pSharedInfo->DebugInfo.usRecordMemIndex = cOCT6100_INVALID_INDEX; pSharedInfo->DebugInfo.usCurrentDebugChanIndex = cOCT6100_INVALID_INDEX; /* Initialize the mixer information. */ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = cOCT6100_INVALID_INDEX; pSharedInfo->MixerInfo.usFirstSinCopyEventPtr = cOCT6100_INVALID_INDEX; pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr = cOCT6100_INVALID_INDEX; pSharedInfo->MixerInfo.usLastBridgeEventPtr = cOCT6100_INVALID_INDEX; pSharedInfo->MixerInfo.usLastSinCopyEventPtr = cOCT6100_INVALID_INDEX; pSharedInfo->MixerInfo.usLastSoutCopyEventPtr = cOCT6100_INVALID_INDEX; pSharedInfo->MixerInfo.usRecordCopyEventIndex = cOCT6100_INVALID_INDEX; pSharedInfo->MixerInfo.usRecordSinEventIndex = cOCT6100_INVALID_INDEX; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiCalculateInstanceSizes Description: Calculates the amount of memory needed for the instance structure memory block based on the user's configuration. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pChipOpen Pointer to user chip configuration structure. f_pInstSizes Pointer to structure containing the size of memory needed by all pointers internal to the API instance. The memory is needed to keep track of the present state of all the chip's resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiCalculateInstanceSizes( IN OUT tPOCT6100_CHIP_OPEN f_pChipOpen, OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) { UINT32 ulApiInstProcessSpecific; UINT32 ulTempVar; UINT32 ulResult; /* Start with all instance sizes set to 0. */ Oct6100UserMemSet( f_pInstSizes, 0x00, sizeof( tOCT6100_API_INSTANCE_SIZES ) ); /* All memory sizes are rounded up to the next multiple of 64 bytes. */ /*-----------------------------------------------------------------------------*/ /* Obtain size of static members of API instance. */ f_pInstSizes->ulApiInstStatic = sizeof( tOCT6100_SHARED_INFO ); mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulApiInstStatic, ulTempVar ) /* Calculate memory needed by pointers internal to the API instance. */ /*-----------------------------------------------------------------------------*/ /* Calculate memory needed for the EC channels. */ ulResult = Oct6100ApiGetChannelsEchoSwSizes( f_pChipOpen, f_pInstSizes ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Memory needed by the TSI structures. */ ulResult = Oct6100ApiGetTsiCnctSwSizes( f_pChipOpen, f_pInstSizes ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Calculate memory needed for the conference bridges. */ ulResult = Oct6100ApiGetConfBridgeSwSizes( f_pChipOpen, f_pInstSizes ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Memory needed by the buffer playout structures. */ ulResult = Oct6100ApiGetPlayoutBufferSwSizes( f_pChipOpen, f_pInstSizes ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Memory needed by soft Rx Event buffers. */ ulResult = Oct6100ApiGetEventsSwSizes( f_pChipOpen, f_pInstSizes ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Calculate memory needed for phasing tssts. */ ulResult = Oct6100ApiGetPhasingTsstSwSizes( f_pChipOpen, f_pInstSizes ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Calculate memory needed for the ADPCM channels. */ ulResult = Oct6100ApiGetAdpcmChanSwSizes( f_pChipOpen, f_pInstSizes ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Calculate memory needed for the management of TSSTs. */ ulResult = Oct6100ApiGetTsstSwSizes( f_pInstSizes ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Calculate memory needed for the management of the mixer. */ ulResult = Oct6100ApiGetMixerSwSizes( f_pChipOpen, f_pInstSizes ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Determine amount of memory needed for memory allocation softwares. These pieces of software will be responsible for the allocation of the chip's external memory and API memory. */ ulResult = Oct6100ApiGetMemorySwSizes( f_pChipOpen, f_pInstSizes ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Memory needed for remote debugging sessions. */ ulResult = Oct6100ApiGetRemoteDebugSwSizes( f_pChipOpen, f_pInstSizes ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Calculate total memory needed by pointers internal to API instance. The total contains both the process specific portion of the instance (tOCT6100_INSTANCE_API) and the shared portion (tOCT6100_SHARED_INFO). The process specific portion will be used only in the case where the host system is a single-process one. */ ulApiInstProcessSpecific = sizeof( tOCT6100_INSTANCE_API ); mOCT6100_ROUND_MEMORY_SIZE( ulApiInstProcessSpecific, ulTempVar ) f_pInstSizes->ulApiInstTotal = f_pInstSizes->ulChannelList + f_pInstSizes->ulChannelAlloc + f_pInstSizes->ulTsiCnctList + f_pInstSizes->ulTsiCnctAlloc + f_pInstSizes->ulSoftToneEventsBuffer + f_pInstSizes->ulSoftBufPlayoutEventsBuffer + f_pInstSizes->ulBiDirChannelList + f_pInstSizes->ulBiDirChannelAlloc + f_pInstSizes->ulConfBridgeList + f_pInstSizes->ulConfBridgeAlloc + f_pInstSizes->ulFlexConfParticipantsList + f_pInstSizes->ulFlexConfParticipantsAlloc + f_pInstSizes->ulPlayoutBufList + f_pInstSizes->ulPlayoutBufAlloc + f_pInstSizes->ulPlayoutBufMemoryNodeList + f_pInstSizes->ulCopyEventList + f_pInstSizes->ulCopyEventAlloc + f_pInstSizes->ulMixerEventList + f_pInstSizes->ulMixerEventAlloc + f_pInstSizes->ulPhasingTsstList + f_pInstSizes->ulPhasingTsstAlloc + f_pInstSizes->ulAdpcmChannelList + f_pInstSizes->ulAdpcmChannelAlloc + f_pInstSizes->ulConversionMemoryAlloc + f_pInstSizes->ulTsiMemoryAlloc + f_pInstSizes->ulRemoteDebugList + f_pInstSizes->ulRemoteDebugTree + f_pInstSizes->ulRemoteDebugPktCache + f_pInstSizes->ulRemoteDebugDataBuf + f_pInstSizes->ulTsstEntryList + f_pInstSizes->ulTsstEntryAlloc + f_pInstSizes->ulTsstAlloc + f_pInstSizes->ulApiInstStatic + ulApiInstProcessSpecific; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiAllocateInstanceMemory Description: Allocates the API instance memory to the various members of the structure f_pApiInstance according to the sizes contained in f_pInstSizes. No initialization of this memory is performed. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pInstSizes Pointer to structure containing the size of memory needed by all pointers internal to the API instance. The memory is needed to keep track of the present state of all the chip's resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiAllocateInstanceMemory( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) { tPOCT6100_SHARED_INFO pSharedInfo; UINT32 ulOffset; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Get address of first UINT32 of memory in API instance structure following */ /* the static members of the API instance structure. */ ulOffset = f_pInstSizes->ulApiInstStatic; /*===================================================================*/ /* Allocate memory for the echo channels.*/ pSharedInfo->ulChannelListOfst = ulOffset; ulOffset += f_pInstSizes->ulChannelList; pSharedInfo->ulChannelAllocOfst = ulOffset; ulOffset += f_pInstSizes->ulChannelAlloc; /*===================================================================*/ /* Allocate memory for the TSI connections */ pSharedInfo->ulTsiCnctListOfst = ulOffset; ulOffset += f_pInstSizes->ulTsiCnctList; pSharedInfo->ulTsiCnctAllocOfst = ulOffset; ulOffset += f_pInstSizes->ulTsiCnctAlloc; pSharedInfo->ulMixerEventListOfst = ulOffset; ulOffset += f_pInstSizes->ulMixerEventList; pSharedInfo->ulMixerEventAllocOfst = ulOffset; ulOffset += f_pInstSizes->ulMixerEventAlloc; pSharedInfo->ulBiDirChannelListOfst = ulOffset; ulOffset += f_pInstSizes->ulBiDirChannelList; pSharedInfo->ulBiDirChannelAllocOfst = ulOffset; ulOffset += f_pInstSizes->ulBiDirChannelAlloc; pSharedInfo->ulCopyEventListOfst = ulOffset; ulOffset += f_pInstSizes->ulCopyEventList; pSharedInfo->ulCopyEventAllocOfst = ulOffset; ulOffset += f_pInstSizes->ulCopyEventAlloc; /*===================================================================*/ /* Allocate memory for the conference bridges */ pSharedInfo->ulConfBridgeListOfst = ulOffset; ulOffset += f_pInstSizes->ulConfBridgeList; pSharedInfo->ulConfBridgeAllocOfst = ulOffset; ulOffset += f_pInstSizes->ulConfBridgeAlloc; /*===================================================================*/ /* Allocate memory for the flexible conferencing participants. */ pSharedInfo->ulFlexConfParticipantListOfst = ulOffset; ulOffset += f_pInstSizes->ulFlexConfParticipantsList; pSharedInfo->ulFlexConfParticipantAllocOfst = ulOffset; ulOffset += f_pInstSizes->ulFlexConfParticipantsAlloc; /*===================================================================*/ /* Allocate memory for the play-out buffers */ pSharedInfo->ulPlayoutBufListOfst = ulOffset; ulOffset += f_pInstSizes->ulPlayoutBufList; pSharedInfo->ulPlayoutBufAllocOfst = ulOffset; ulOffset += f_pInstSizes->ulPlayoutBufAlloc; pSharedInfo->ulPlayoutBufMemoryNodeListOfst = ulOffset; ulOffset += f_pInstSizes->ulPlayoutBufMemoryNodeList; /*===================================================================*/ /* Allocate memory for the phasing TSSTs */ pSharedInfo->ulPhasingTsstListOfst = ulOffset; ulOffset += f_pInstSizes->ulPhasingTsstList; pSharedInfo->ulPhasingTsstAllocOfst = ulOffset; ulOffset += f_pInstSizes->ulPhasingTsstAlloc; /*===================================================================*/ /* Allocate memory for the ADPCM channel */ pSharedInfo->ulAdpcmChanAllocOfst = ulOffset; ulOffset += f_pInstSizes->ulAdpcmChannelAlloc; pSharedInfo->ulAdpcmChanListOfst = ulOffset; ulOffset += f_pInstSizes->ulAdpcmChannelList; /*===================================================================*/ /* Allocate memory for the conversion memory */ pSharedInfo->ulConversionMemoryAllocOfst = ulOffset; ulOffset += f_pInstSizes->ulConversionMemoryAlloc; /*===================================================================*/ /* Allocate memory for the TSI chariot memory */ pSharedInfo->ulTsiMemoryAllocOfst = ulOffset; ulOffset += f_pInstSizes->ulTsiMemoryAlloc; /*===================================================================*/ /* Allocate memory for the TSST management */ pSharedInfo->ulTsstAllocOfst = ulOffset; ulOffset += f_pInstSizes->ulTsstAlloc; pSharedInfo->ulTsstListOfst = ulOffset; ulOffset += f_pInstSizes->ulTsstEntryList; pSharedInfo->ulTsstListAllocOfst = ulOffset; ulOffset += f_pInstSizes->ulTsstEntryAlloc; /*===================================================================*/ pSharedInfo->SoftBufs.ulToneEventBufferMemOfst = ulOffset; ulOffset += f_pInstSizes->ulSoftToneEventsBuffer; pSharedInfo->SoftBufs.ulBufPlayoutEventBufferMemOfst = ulOffset; ulOffset += f_pInstSizes->ulSoftBufPlayoutEventsBuffer; /*===================================================================*/ pSharedInfo->RemoteDebugInfo.ulSessionListOfst = ulOffset; ulOffset += f_pInstSizes->ulRemoteDebugList; pSharedInfo->RemoteDebugInfo.ulSessionTreeOfst = ulOffset; ulOffset += f_pInstSizes->ulRemoteDebugTree; pSharedInfo->RemoteDebugInfo.ulDataBufOfst = ulOffset; ulOffset += f_pInstSizes->ulRemoteDebugDataBuf; pSharedInfo->RemoteDebugInfo.ulPktCacheOfst = ulOffset; ulOffset += f_pInstSizes->ulRemoteDebugPktCache; /*===================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiInitializeInstanceMemory Description: Initializes the various members of the structure f_pApiInstance to reflect the current state of the chip and its resources. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiInitializeInstanceMemory( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { UINT32 ulResult; /*-----------------------------------------------------------------------------*/ /* Initialize API EC channels. */ ulResult = Oct6100ApiChannelsEchoSwInit( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Initialize the API TSI connection structures. */ ulResult = Oct6100ApiTsiCnctSwInit( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Initialize the API conference bridges. */ ulResult = Oct6100ApiConfBridgeSwInit( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Initialize the API buffer playout structures. */ ulResult = Oct6100ApiPlayoutBufferSwInit( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Initialize the API phasing tssts. */ ulResult = Oct6100ApiPhasingTsstSwInit( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Initialize the API ADPCM channels. */ ulResult = Oct6100ApiAdpcmChanSwInit( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Initialize the external memory management structures. */ ulResult = Oct6100ApiMemorySwInit( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Initialize TSST management stuctures. */ ulResult = Oct6100ApiTsstSwInit( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Initialize the mixer management stuctures. */ ulResult = Oct6100ApiMixerSwInit( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Initialize the remote debugging session management variables. */ ulResult = Oct6100ApiRemoteDebuggingSwInit( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*-----------------------------------------------------------------------------*/ /* Configure the interrupt registers. */ ulResult = Oct6100ApiIsrSwInit( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetChipRevisionNum Description: Reads the chip's revision number register. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiGetChipRevisionNum( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_READ_PARAMS ReadParams; UINT32 ulResult; UINT16 usReadData; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Get the chip revision number. */ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ReadParams.ulReadAddress = cOCT6100_CHIP_ID_REVISION_REG; ReadParams.pusReadData = &usReadData; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save the info in the API miscellaneous structure. */ pSharedInfo->MiscVars.usChipId = (UINT16)( usReadData & 0xFF ); pSharedInfo->MiscVars.usChipRevision = (UINT16)( usReadData >> 8 ); return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiDecodeKeyAndBist Description: This function decodes the key and runs the automatic BIST. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiDecodeKeyAndBist( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHIP_CONFIG pChipConfig; tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_READ_PARAMS ReadParams; UINT16 ausBistData[ 3 ]; UINT16 usReadData; UINT32 ulResult; BOOL fBitEqual; UINT32 i; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Obtain a local pointer to the chip config structure */ /* contained in the instance structure. */ pChipConfig = &pSharedInfo->ChipConfig; /* Set the process context and user chip ID parameters once and for all. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pChipConfig->ulUserChipId; /* Set the process context and user chip ID parameters once and for all. */ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pChipConfig->ulUserChipId; /* Write key in CPU internal memory. */ for(i=0; i<8; i++) { WriteParams.ulWriteAddress = 0x150; WriteParams.usWriteData = 0x0000; if (( i % 2 ) == 0) { WriteParams.usWriteData |= ((UINT16)pChipConfig->pbyImageFile[0x100 + ((i/2)*4) + 2]) << 8; WriteParams.usWriteData |= ((UINT16)pChipConfig->pbyImageFile[0x100 + ((i/2)*4) + 3]) << 0; } else { WriteParams.usWriteData |= ((UINT16)pChipConfig->pbyImageFile[0x100 + ((i/2)*4) + 0]) << 8; WriteParams.usWriteData |= ((UINT16)pChipConfig->pbyImageFile[0x100 + ((i/2)*4) + 1]) << 0; } mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x152; WriteParams.usWriteData = (UINT16)( 0x8000 | i ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Write one in CPU internal memory. */ for(i=0; i<8; i++) { WriteParams.ulWriteAddress = 0x150; if (i == 0) { WriteParams.usWriteData = 0x0001; } else { WriteParams.usWriteData = 0x0000; } mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x152; WriteParams.usWriteData = (UINT16)( 0x8000 | ( i + 8 )); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Clear memory access registers: */ WriteParams.ulWriteAddress = 0x150; WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x152; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Run BISTs and key decode. */ WriteParams.ulWriteAddress = 0x160; WriteParams.usWriteData = 0x0081; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Wait for the key decode PC to clear. */ ulResult = Oct6100ApiWaitForPcRegisterBit( f_pApiInstance, 0x160, 0, 0, 100000, &fBitEqual ); if ( TRUE != fBitEqual ) return cOCT6100_ERR_FATAL_13; /* Read the key valid bit to make sure everything is ok. */ ReadParams.ulReadAddress = 0x160; ReadParams.pusReadData = &usReadData; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Either the firmware image was not loaded correctly (from pointer given by user) */ /* or the channel capacity pins of the chip do not match what the firmware is expecting. */ if ( ( usReadData & 0x4 ) == 0 ) return cOCT6100_ERR_OPEN_INVALID_FIRMWARE_OR_CAPACITY_PINS; /* Read the result of the internal memory bist. */ ReadParams.ulReadAddress = 0x110; ReadParams.pusReadData = &ausBistData[ 0 ]; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ReadParams.ulReadAddress = 0x114; ReadParams.pusReadData = &ausBistData[ 1 ]; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ReadParams.ulReadAddress = 0x118; ReadParams.pusReadData = &ausBistData[ 2 ]; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check if an error was reported. */ if (ausBistData[0] != 0x0000 || ausBistData[1] != 0x0000 || ausBistData[2] != 0x0000) return cOCT6100_ERR_OPEN_INTERNAL_MEMORY_BIST; /* Put key decoder in powerdown. */ WriteParams.ulWriteAddress = 0x160; WriteParams.usWriteData = 0x008A; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiBootFc2Pll Description: Configures the chip's FC2 PLL. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiBootFc2Pll( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHIP_CONFIG pChipConfig; tOCT6100_WRITE_PARAMS WriteParams; UINT32 aulWaitTime[ 2 ]; UINT32 ulResult; UINT32 ulFc2PllDivisor = 0; UINT32 ulMtDivisor = 0; UINT32 ulFcDivisor = 0; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Obtain local pointer to chip configuration structure. */ pChipConfig = &pSharedInfo->ChipConfig; /* Set the process context and user chip ID parameters once and for all. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pChipConfig->ulUserChipId; /* First put the chip and main registers in soft-reset. */ WriteParams.ulWriteAddress = 0x100; WriteParams.usWriteData = 0x0; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Select register configuration based on the memory frequency. */ switch ( f_pApiInstance->pSharedInfo->ChipConfig.ulMemClkFreq ) { case 133000000: ulFc2PllDivisor = 0x1050; ulMtDivisor = 0x4300; ulFcDivisor = 0x4043; pSharedInfo->MiscVars.usMaxNumberOfChannels = 672; pSharedInfo->MiscVars.usMaxH100Speed = 124; if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) pSharedInfo->MiscVars.usTdmClkBoundary = 0x050B; else pSharedInfo->MiscVars.usTdmClkBoundary = 0x0516; break; case 125000000: ulFc2PllDivisor = 0x0F50; ulMtDivisor = 0x4300; ulFcDivisor = 0x4043; pSharedInfo->MiscVars.usMaxNumberOfChannels = 624; pSharedInfo->MiscVars.usMaxH100Speed = 116; if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) pSharedInfo->MiscVars.usTdmClkBoundary = 0x04CA; else pSharedInfo->MiscVars.usTdmClkBoundary = 0x04D4; break; case 117000000: ulFc2PllDivisor = 0x0E50; ulMtDivisor = 0x4300; ulFcDivisor = 0x4043; pSharedInfo->MiscVars.usMaxNumberOfChannels = 576; pSharedInfo->MiscVars.usMaxH100Speed = 108; if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) pSharedInfo->MiscVars.usTdmClkBoundary = 0x0489; else pSharedInfo->MiscVars.usTdmClkBoundary = 0x0492; break; case 108000000: ulFc2PllDivisor = 0x0D50; ulMtDivisor = 0x4300; ulFcDivisor = 0x4043; pSharedInfo->MiscVars.usMaxNumberOfChannels = 528; pSharedInfo->MiscVars.usMaxH100Speed = 99; if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) pSharedInfo->MiscVars.usTdmClkBoundary = 0x0408; else pSharedInfo->MiscVars.usTdmClkBoundary = 0x0410; break; case 100000000: ulFc2PllDivisor = 0x0C50; ulMtDivisor = 0x4300; ulFcDivisor = 0x4043; pSharedInfo->MiscVars.usMaxNumberOfChannels = 480; pSharedInfo->MiscVars.usMaxH100Speed = 91; if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) pSharedInfo->MiscVars.usTdmClkBoundary = 0x03C8; else pSharedInfo->MiscVars.usTdmClkBoundary = 0x03D0; break; case 92000000: ulFc2PllDivisor = 0x0B50; ulMtDivisor = 0x4300; ulFcDivisor = 0x4043; pSharedInfo->MiscVars.usMaxNumberOfChannels = 432; pSharedInfo->MiscVars.usMaxH100Speed = 83; if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) pSharedInfo->MiscVars.usTdmClkBoundary = 0x0387; else pSharedInfo->MiscVars.usTdmClkBoundary = 0x038E; break; case 83000000: ulFc2PllDivisor = 0x0A50; ulMtDivisor = 0x4300; ulFcDivisor = 0x4043; pSharedInfo->MiscVars.usMaxNumberOfChannels = 384; pSharedInfo->MiscVars.usMaxH100Speed = 74; if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) pSharedInfo->MiscVars.usTdmClkBoundary = 0x0346; else pSharedInfo->MiscVars.usTdmClkBoundary = 0x034C; break; case 75000000: ulFc2PllDivisor = 0x0950; ulMtDivisor = 0x4200; ulFcDivisor = 0x4043; pSharedInfo->MiscVars.usMaxNumberOfChannels = 336; pSharedInfo->MiscVars.usMaxH100Speed = 64; if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) pSharedInfo->MiscVars.usTdmClkBoundary = 0x0306; else pSharedInfo->MiscVars.usTdmClkBoundary = 0x030C; break; default: return cOCT6100_ERR_FATAL_DB; } /* Verify that the max channel is not too big based on the chip frequency. */ if ( pSharedInfo->ChipConfig.usMaxChannels > pSharedInfo->MiscVars.usMaxNumberOfChannels ) return cOCT6100_ERR_OPEN_MAX_ECHO_CHANNELS; /* Setup delay chains. */ if ( (pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_SDR) || (pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS) ) { /* SDRAM */ WriteParams.ulWriteAddress = 0x1B0; WriteParams.usWriteData = 0x1003; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x1B2; WriteParams.usWriteData = 0x0021; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x1B4; WriteParams.usWriteData = 0x4030; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x1B6; WriteParams.usWriteData = 0x0021; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } else /* if ( cOCT6100_MEM_TYPE_DDR == pChipConfig->byMemoryType ) */ { /* DDR */ WriteParams.ulWriteAddress = 0x1B0; WriteParams.usWriteData = 0x201F; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x1B2; WriteParams.usWriteData = 0x0021; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x1B4; WriteParams.usWriteData = 0x1000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x1B6; WriteParams.usWriteData = 0x0021; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* udqs */ WriteParams.ulWriteAddress = 0x1B8; WriteParams.usWriteData = 0x1003; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x1BA; WriteParams.usWriteData = 0x0021; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* ldqs */ WriteParams.ulWriteAddress = 0x1BC; WriteParams.usWriteData = 0x1000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x1BE; WriteParams.usWriteData = 0x0021; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x12C; WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x12E; WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Select fc2pll for fast_clk and mtsclk sources. Select mem_clk_i for afclk. */ WriteParams.ulWriteAddress = 0x140; WriteParams.usWriteData = (UINT16)ulMtDivisor; if ( f_pApiInstance->pSharedInfo->ChipConfig.byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS ) WriteParams.usWriteData |= 0x0001; else WriteParams.usWriteData |= 0x0004; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x144; WriteParams.usWriteData = (UINT16)ulFcDivisor; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x13E; WriteParams.usWriteData = 0x0001; /* Remove reset from above divisors */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Select upclk directly as ref source for fc2pll. */ WriteParams.ulWriteAddress = 0x134; if ( pChipConfig->ulUpclkFreq == cOCT6100_UPCLK_FREQ_66_67_MHZ ) { WriteParams.usWriteData = 0x0002; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Remove the reset */ WriteParams.usWriteData = 0x0102; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } else /* pChipConfig->ulUpclkFreq == cOCT6100_UPCLK_FREQ_33_33_MHZ */ { WriteParams.usWriteData = 0x0001; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Setup fc2pll. */ WriteParams.ulWriteAddress = 0x132; WriteParams.usWriteData = (UINT16)ulFc2PllDivisor; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.usWriteData |= 0x02; /* Raise fb divisor reset. */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.usWriteData |= 0x80; /* Raise IDDTN signal.*/ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Wait for fc2pll to stabilize. */ aulWaitTime[ 0 ] = 2000; aulWaitTime[ 1 ] = 0; ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Drive mem_clk_o out on proper interface. */ if ( TRUE == pChipConfig->fEnableMemClkOut ) { if ( (pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_SDR) || (pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS) ) { WriteParams.ulWriteAddress = 0x128; WriteParams.usWriteData = 0x0301; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } if ( pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_DDR || pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS ) { WriteParams.ulWriteAddress = 0x12A; WriteParams.usWriteData = 0x000F; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiProgramFc1Pll Description: Configures the chip's FC1 PLL. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiProgramFc1Pll( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHIP_CONFIG pChipConfig; tOCT6100_WRITE_PARAMS WriteParams; UINT32 aulWaitTime[ 2 ]; UINT32 ulResult; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Obtain local pointer to chip configuration structure. */ pChipConfig = &pSharedInfo->ChipConfig; /* Set the process context and user chip ID parameters once and for all. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pChipConfig->ulUserChipId; /* Programm P/Z bits. */ WriteParams.ulWriteAddress = 0x130; if ( f_pApiInstance->pSharedInfo->ChipConfig.byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS ) WriteParams.usWriteData = 0x0041; else WriteParams.usWriteData = 0x0040; WriteParams.usWriteData |= ( pChipConfig->byMemoryType << 8 ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Raise FB divisor. */ WriteParams.usWriteData |= 0x0002; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Raise IDDTN. */ WriteParams.usWriteData |= 0x0080; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Wait for fc1pll to stabilize. */ aulWaitTime[ 0 ] = 2000; aulWaitTime[ 1 ] = 0; ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Enable all the clock domains to do reset procedure. */ WriteParams.ulWriteAddress = 0x186; WriteParams.usWriteData = 0x015F; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; aulWaitTime[ 0 ] = 15000; aulWaitTime[ 1 ] = 0; ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiBootFc1Pll Description: Boot the chip's FC1 PLL. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiBootFc1Pll( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHIP_CONFIG pChipConfig; tOCT6100_WRITE_PARAMS WriteParams; UINT32 aulWaitTime[ 2 ]; UINT32 ulResult; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Obtain local pointer to chip configuration structure. */ pChipConfig = &pSharedInfo->ChipConfig; /* Set the process context and user chip ID parameters once and for all. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pChipConfig->ulUserChipId; /* Force bist_clk also (it too is used on resetable flops). */ WriteParams.ulWriteAddress = 0x160; WriteParams.usWriteData = 0x0188; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Force all cpu clocks on chariot controllers. */ WriteParams.ulWriteAddress = 0x182; WriteParams.usWriteData = 0x0002; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x184; WriteParams.usWriteData = 0x0202; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; aulWaitTime[ 0 ] = 1000; aulWaitTime[ 1 ] = 0; ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Remove the reset on the entire chip and disable CPU access caching. */ WriteParams.ulWriteAddress = 0x100; WriteParams.usWriteData = 0x2003; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Remove the bist_clk. It is no longer needed.*/ WriteParams.ulWriteAddress = 0x160; WriteParams.usWriteData = 0x0088; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Disable all clks to prepare for bist clock switchover. */ WriteParams.ulWriteAddress = 0x182; WriteParams.usWriteData = 0x0001; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x186; WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x184; WriteParams.usWriteData = 0x0101; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Deassert bist_active */ WriteParams.ulWriteAddress = 0x160; WriteParams.usWriteData = 0x0008; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Change CPU interface to normal mode (from boot mode). */ WriteParams.ulWriteAddress = 0x154; WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Give a couple of BIST clock cycles to turn off the BIST permanently. */ WriteParams.ulWriteAddress = 0x160; WriteParams.usWriteData = 0x0108; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Turn BIST clock off for the last time. */ WriteParams.ulWriteAddress = 0x160; WriteParams.usWriteData = 0x0008; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Reset procedure done! */ /* Enable mclk for cpu interface and external memory controller. */ WriteParams.ulWriteAddress = 0x186; WriteParams.usWriteData = 0x0100; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiLoadImage Description: This function writes the firmware image in the external memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiLoadImage( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_WRITE_BURST_PARAMS BurstParams; tOCT6100_READ_PARAMS ReadParams; UINT32 ulResult; UINT32 ulTempPtr; UINT32 ulNumWrites; PUINT16 pusSuperArray; PUINT8 pbyImageFile; UINT32 ulByteCount = 0; UINT16 usReadData; UINT32 ulAddressOfst; UINT32 i; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Set the process context and user chip ID parameters once and for all. */ BurstParams.pProcessContext = f_pApiInstance->pProcessContext; BurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; /* Breakdown image into subcomponents. */ ulTempPtr = cOCT6100_IMAGE_FILE_BASE + cOCT6100_IMAGE_AF_CST_OFFSET; for(i=0;iImageRegion[ i ].ulPart1Size = pSharedInfo->ChipConfig.pbyImageFile[ 0x110 + ( i * 4 ) + 0 ]; pSharedInfo->ImageRegion[ i ].ulPart2Size = pSharedInfo->ChipConfig.pbyImageFile[ 0x110 + ( i * 4 ) + 1 ]; pSharedInfo->ImageRegion[ i ].ulClockInfo = pSharedInfo->ChipConfig.pbyImageFile[ 0x110 + ( i * 4 ) + 2 ]; pSharedInfo->ImageRegion[ i ].ulReserved = pSharedInfo->ChipConfig.pbyImageFile[ 0x110 + ( i * 4 ) + 3 ]; if (i == 0) /* AF constant. */ { pSharedInfo->ImageRegion[ i ].ulPart1BaseAddress = ulTempPtr & 0x07FFFFFF; pSharedInfo->ImageRegion[ i ].ulPart2BaseAddress = 0; ulTempPtr += ( pSharedInfo->ImageRegion[ i ].ulPart1Size * 612 ); } else if (i == 1) /* NLP image */ { pSharedInfo->ImageRegion[ i ].ulPart1BaseAddress = ulTempPtr & 0x07FFFFFF; pSharedInfo->ImageRegion[ i ].ulPart2BaseAddress = 0; ulTempPtr += ( pSharedInfo->ImageRegion[ i ].ulPart1Size * 2056 ); } else /* Others */ { pSharedInfo->ImageRegion[ i ].ulPart1BaseAddress = ulTempPtr & 0x07FFFFFF; ulTempPtr += ( pSharedInfo->ImageRegion[ i ].ulPart1Size * 2064 ); pSharedInfo->ImageRegion[ i ].ulPart2BaseAddress = ulTempPtr & 0x07FFFFFF; ulTempPtr += ( pSharedInfo->ImageRegion[ i ].ulPart2Size * 2448 ); } } /* Write the image in external memory. */ ulNumWrites = pSharedInfo->ChipConfig.ulImageSize / 2; BurstParams.ulWriteAddress = cOCT6100_IMAGE_FILE_BASE; BurstParams.pusWriteData = pSharedInfo->MiscVars.ausSuperArray; pusSuperArray = pSharedInfo->MiscVars.ausSuperArray; pbyImageFile = pSharedInfo->ChipConfig.pbyImageFile; while ( ulNumWrites != 0 ) { if ( ulNumWrites >= pSharedInfo->ChipConfig.usMaxRwAccesses ) BurstParams.ulWriteLength = pSharedInfo->ChipConfig.usMaxRwAccesses; else BurstParams.ulWriteLength = ulNumWrites; for ( i = 0; i < BurstParams.ulWriteLength; i++ ) { pusSuperArray[ i ] = ( UINT16 )(( pbyImageFile [ ulByteCount++ ]) << 8); pusSuperArray[ i ] |= ( UINT16 )pbyImageFile [ ulByteCount++ ]; } mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; BurstParams.ulWriteAddress += 2 * BurstParams.ulWriteLength; ulNumWrites -= BurstParams.ulWriteLength; } /* Perform a serie of reads to make sure the image was correclty written into memory. */ ulAddressOfst = ( pSharedInfo->ChipConfig.ulImageSize / 2 ) & 0xFFFFFFFE; while ( ulAddressOfst != 0 ) { ReadParams.ulReadAddress = cOCT6100_IMAGE_FILE_BASE + ulAddressOfst; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( (usReadData >> 8) != pbyImageFile[ ulAddressOfst ] ) return cOCT6100_ERR_OPEN_IMAGE_WRITE_FAILED; ulAddressOfst = (ulAddressOfst / 2) & 0xFFFFFFFE; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiCpuRegisterBist Description: Tests the operation of the CPU registers. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiCpuRegisterBist( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_READ_PARAMS ReadParams; UINT32 ulResult; UINT16 i; UINT16 usReadData; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Set the process context and user chip ID parameters once and for all. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* Assign read data pointer that will be used throughout the function. */ ReadParams.pusReadData = &usReadData; /* Start with a walking bit test. */ for ( i = 0; i < 16; i ++ ) { /* Write at address 0x150.*/ WriteParams.ulWriteAddress = 0x150; WriteParams.usWriteData = (UINT16)( 0x1 << i ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write at address 0x180.*/ WriteParams.ulWriteAddress = 0x180; WriteParams.usWriteData = (UINT16)( 0x1 << ( 15 - i ) ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Now read back the two registers to make sure the acceses were successfull. */ ReadParams.ulReadAddress = 0x150; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( usReadData != ( 0x1 << i ) ) return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR; ReadParams.ulReadAddress = 0x180; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( usReadData != ( 0x1 << ( 15 - i ) ) ) return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR; } /* Write at address 0x150. */ WriteParams.ulWriteAddress = 0x150; WriteParams.usWriteData = 0xCAFE; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write at address 0x180. */ WriteParams.ulWriteAddress = 0x180; WriteParams.usWriteData = 0xDECA; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Now read back the two registers to make sure the acceses were successfull. */ ReadParams.ulReadAddress = 0x150; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( usReadData != 0xCAFE ) return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR; ReadParams.ulReadAddress = 0x180; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( usReadData != 0xDECA ) return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiBootSdram Description: Configure and test the SDRAM. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiBootSdram( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHIP_CONFIG pChipConfig; tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_READ_PARAMS ReadParams; UINT32 ulResult; UINT16 usReadData; UINT16 usWriteData23E; UINT16 usWriteData230; UINT32 i; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Get local pointer to the chip configuration structure.*/ pChipConfig = &f_pApiInstance->pSharedInfo->ChipConfig; /* Set the process context and user chip ID parameters once and for all. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; usWriteData23E = 0x0000; usWriteData230 = 0x0000; if ( (pSharedInfo->ChipConfig.byMemoryType == cOCT6100_MEM_TYPE_SDR) || (pSharedInfo->ChipConfig.byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS) ) { /* SDRAM: */ switch( pChipConfig->ulMemoryChipSize ) { case cOCT6100_MEMORY_CHIP_SIZE_8MB: usWriteData230 |= ( cOCT6100_16MB_MEMORY_BANKS << 2 ); break; case cOCT6100_MEMORY_CHIP_SIZE_16MB: usWriteData230 |= ( cOCT6100_32MB_MEMORY_BANKS << 2 ); break; case cOCT6100_MEMORY_CHIP_SIZE_32MB: usWriteData230 |= ( cOCT6100_64MB_MEMORY_BANKS << 2 ); break; case cOCT6100_MEMORY_CHIP_SIZE_64MB: usWriteData230 |= ( cOCT6100_128MB_MEMORY_BANKS << 2 ); break; default: return cOCT6100_ERR_FATAL_16; } WriteParams.ulWriteAddress = 0x230; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Precharge all banks. */ usWriteData230 &= 0x000C; usWriteData230 |= 0x0010; WriteParams.ulWriteAddress = 0x230; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usWriteData230 |= 0x0002; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x23E; WriteParams.usWriteData = usWriteData23E; for ( i = 0; i < 5; i++ ) { /* Wait cycle. */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Program the mode register. */ usWriteData23E = 0x0030; WriteParams.usWriteData = usWriteData23E; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usWriteData230 &= 0x000C; usWriteData230 |= 0x0000; WriteParams.ulWriteAddress = 0x230; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usWriteData230 |= 0x0002; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x23E; WriteParams.usWriteData = usWriteData23E; for ( i = 0; i < 5; i++ ) { /* Wait cycle. */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Do CBR refresh (twice) */ usWriteData230 &= 0x000C; usWriteData230 |= 0x0040; WriteParams.ulWriteAddress = 0x230; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usWriteData230 |= 0x0002; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x23E; WriteParams.usWriteData = usWriteData23E; for ( i = 0; i < 5; i++ ) { /* Wait cycle. */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } WriteParams.ulWriteAddress = 0x230; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x23E; WriteParams.usWriteData = usWriteData23E; for ( i = 0; i < 5; i++ ) { /* Wait cycle. */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } else { /* DDR: */ switch( pChipConfig->ulMemoryChipSize ) { case cOCT6100_MEMORY_CHIP_SIZE_16MB: usWriteData230 |= ( cOCT6100_16MB_MEMORY_BANKS << 2 ); break; case cOCT6100_MEMORY_CHIP_SIZE_32MB: usWriteData230 |= ( cOCT6100_32MB_MEMORY_BANKS << 2 ); break; case cOCT6100_MEMORY_CHIP_SIZE_64MB: usWriteData230 |= ( cOCT6100_64MB_MEMORY_BANKS << 2 ); break; case cOCT6100_MEMORY_CHIP_SIZE_128MB: usWriteData230 |= ( cOCT6100_128MB_MEMORY_BANKS << 2 ); break; default: return cOCT6100_ERR_FATAL_17; } WriteParams.ulWriteAddress = 0x230; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Precharge all banks. */ usWriteData230 &= 0x000C; usWriteData230 |= 0x0010; WriteParams.ulWriteAddress = 0x230; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usWriteData230 |= 0x0002; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x23E; WriteParams.usWriteData = usWriteData23E; for ( i = 0; i < 5; i++ ) { /* Wait cycle. */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Program DDR mode register. */ usWriteData23E = 0x4000; WriteParams.ulWriteAddress = 0x23E; WriteParams.usWriteData = usWriteData23E; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usWriteData230 &= 0x000C; usWriteData230 |= 0x0000; WriteParams.ulWriteAddress = 0x230; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usWriteData230 |= 0x0002; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x23E; WriteParams.usWriteData = usWriteData23E; for ( i = 0; i < 5; i++ ) { /* Wait cycle. */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Program SDR mode register. */ usWriteData23E = 0x0161; WriteParams.ulWriteAddress = 0x23E; WriteParams.usWriteData = usWriteData23E; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usWriteData230 &= 0x000C; usWriteData230 |= 0x0000; WriteParams.ulWriteAddress = 0x230; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usWriteData230 |= 0x0002; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x23E; WriteParams.usWriteData = usWriteData23E; for ( i = 0; i < 5; i++ ) { /* Wait cycle. */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Precharge all banks. */ usWriteData23E = 0xFFFF; WriteParams.ulWriteAddress = 0x23E; WriteParams.usWriteData = usWriteData23E; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usWriteData230 &= 0x000C; usWriteData230 |= 0x0010; WriteParams.ulWriteAddress = 0x230; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usWriteData230 |= 0x0002; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x23E; WriteParams.usWriteData = usWriteData23E; for ( i = 0; i < 5; i++ ) { /* Wait cycle. */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Do CBR refresh (twice) */ usWriteData230 &= 0x000C; usWriteData230 |= 0x0040; WriteParams.ulWriteAddress = 0x230; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usWriteData230 |= 0x0002; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x23E; WriteParams.usWriteData = usWriteData23E; for ( i = 0; i < 5; i++ ) { /* Wait cycle. */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } WriteParams.ulWriteAddress = 0x230; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x23E; WriteParams.usWriteData = usWriteData23E; for ( i = 0; i < 5; i++ ) { /* Wait cycle.*/ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Program SDR mode register. */ usWriteData23E = 0x0061; WriteParams.ulWriteAddress = 0x23E; WriteParams.usWriteData = usWriteData23E; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usWriteData230 &= 0x000C; usWriteData230 |= 0x0000; WriteParams.ulWriteAddress = 0x230; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; usWriteData230 |= 0x0002; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x23E; WriteParams.usWriteData = usWriteData23E; for ( i = 0; i < 5; i++ ) { /* Wait cycle. */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Set the refresh frequency. */ WriteParams.ulWriteAddress = 0x242; WriteParams.usWriteData = 0x0400; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x244; WriteParams.usWriteData = 0x0200; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x248; WriteParams.usWriteData = 0x800; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x246; WriteParams.usWriteData = 0x0012; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Enable the SDRAM and refreshes. */ usWriteData230 &= 0x000C; usWriteData230 |= 0x0001; WriteParams.ulWriteAddress = 0x230; WriteParams.usWriteData = usWriteData230; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x246; WriteParams.usWriteData = 0x0013; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiEnableClocks Description: This function will disable clock masking for all the modules of the chip. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiEnableClocks( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; /* Initialize the process context and user chip ID once and for all. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; /* Enable tdmie / adpcm mclk clocks. */ WriteParams.ulWriteAddress = 0x186; WriteParams.usWriteData = 0x015F; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Configure the DQS register for the DDR memory */ WriteParams.ulWriteAddress = 0x180; WriteParams.usWriteData = 0xFF00; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Enable pgsp chariot clocks */ WriteParams.ulWriteAddress = 0x182; WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Enable af/mt chariot clocks */ WriteParams.ulWriteAddress = 0x184; WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiProgramNLP Description: This function will write image values to configure the NLP. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiProgramNLP( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_READ_PARAMS ReadParams; tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHIP_CONFIG pChipConfig; UINT32 ulResult; UINT16 usReadData; UINT16 usReadHighData; BOOL fBitEqual; UINT32 ulEgoEntry[4]; UINT32 ulTempAddress; UINT32 ulAfCpuUp = FALSE; UINT32 i; UINT32 ulLoopCounter = 0; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Get local pointer to the chip configuration structure.*/ pChipConfig = &f_pApiInstance->pSharedInfo->ChipConfig; /* Initialize the process context and user chip ID once and for all. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; /* Initialize the process context and user chip ID once and for all. */ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; if ( pSharedInfo->ChipConfig.fEnableProductionBist == TRUE ) { UINT32 ulReadData; UINT32 ulBitPattern; UINT32 j, k; /* Since the pouch section (256 bytes) will not be tested by the firmware, */ /* the API has to make sure this section is working correctly. */ for ( k = 0; k < 2; k ++ ) { if ( k == 0 ) ulBitPattern = 0x1; else ulBitPattern = 0xFFFFFFFE; for ( j = 0; j < 32; j ++ ) { /* Write the DWORDs. */ for ( i = 0; i < 64; i ++ ) { ulResult = Oct6100ApiWriteDword( f_pApiInstance, cOCT6100_POUCH_BASE + i * 4, ulBitPattern << j ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Read the DWORDs. */ for ( i = 0; i < 64; i ++ ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, cOCT6100_POUCH_BASE + i * 4, &ulReadData ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check if the value matches. */ if ( ( ulBitPattern << j ) != ulReadData ) return cOCT6100_ERR_OPEN_PRODUCTION_BIST_POUCH_ERROR; } } } } /* Write the image info in the chip. */ WriteParams.ulWriteAddress = cOCT6100_PART1_END_STATICS_BASE; WriteParams.usWriteData = (UINT16)( ( pSharedInfo->ImageRegion[ 0 ].ulPart1BaseAddress >> 16 ) & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( pSharedInfo->ImageRegion[ 0 ].ulPart1BaseAddress & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; for( i = 0; i < 8; i++ ) { if ( pSharedInfo->ImageRegion[ i + 2 ].ulPart1Size != 0 ) { WriteParams.ulWriteAddress = cOCT6100_PART1_END_STATICS_BASE + 0x4 + ( i * 0xC ); WriteParams.usWriteData = (UINT16)(( pSharedInfo->ImageRegion[ i + 2 ].ulPart1BaseAddress >> 16 ) & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( pSharedInfo->ImageRegion[ i + 2 ].ulPart1BaseAddress & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } if ( pSharedInfo->ImageRegion[ i + 2 ].ulPart2Size != 0 ) { WriteParams.ulWriteAddress = cOCT6100_PART1_END_STATICS_BASE + 0x4 + ( i * 0xC ) + 4; WriteParams.usWriteData = (UINT16)(( pSharedInfo->ImageRegion[ i + 2 ].ulPart2BaseAddress >> 16 ) & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( pSharedInfo->ImageRegion[ i + 2 ].ulPart2BaseAddress & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } WriteParams.ulWriteAddress = cOCT6100_PART1_END_STATICS_BASE + 0x4 + ( i * 0xC ) + 8; WriteParams.usWriteData = 0x0000; WriteParams.usWriteData |= ( pSharedInfo->ImageRegion[ i + 2 ].ulPart1Size << 8 ); WriteParams.usWriteData |= pSharedInfo->ImageRegion[ i + 2 ].ulPart2Size; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = 0x0000; WriteParams.usWriteData |= ( pSharedInfo->ImageRegion[ i + 2 ].ulClockInfo << 8 ); WriteParams.usWriteData |= pSharedInfo->ImageRegion[ i + 2 ].ulReserved; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Put NLP in config mode. */ WriteParams.ulWriteAddress = 0x2C2; WriteParams.usWriteData = 0x160E; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x692; WriteParams.usWriteData = 0x010A; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Upload the up to 8 NLP pages + 1 AF page (for timing reasons). */ for ( i = 0; i < pSharedInfo->ImageRegion[ 1 ].ulPart1Size; i++ ) { ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 1 ].ulPart1BaseAddress + 1028 * ( i * 2 ), 0x1280, 1024, &(ulEgoEntry[0])); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 1 ].ulPart1BaseAddress + 1028 * (( i * 2 ) + 1 ), 0x1680, 1024, &(ulEgoEntry[2])); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiRunEgo( f_pApiInstance, FALSE, 2, ulEgoEntry ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Shift mt chariot memories. This process will complete by the time */ /* the next LSU transfer is done. */ WriteParams.ulWriteAddress = 0x692; WriteParams.usWriteData = 0x010B; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiWaitForPcRegisterBit( f_pApiInstance, 0x692, 0, 0, 100000, &fBitEqual ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( TRUE != fBitEqual ) return cOCT6100_ERR_FATAL_1A; } /* 1 AF page (for timing reasons). */ ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 2 ].ulPart1BaseAddress + (516 * 0), 0x1280, 512, &(ulEgoEntry[0])); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 2 ].ulPart1BaseAddress + (516 * 1), 0x1480, 512, &(ulEgoEntry[2])); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiRunEgo( f_pApiInstance, FALSE, 2, ulEgoEntry ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 2 ].ulPart1BaseAddress + (516 * 2), 0x1680, 512, &(ulEgoEntry[0])); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 2 ].ulPart1BaseAddress + (516 * 3), 0x1880, 512, &(ulEgoEntry[2])); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiRunEgo( f_pApiInstance, FALSE, 2, ulEgoEntry ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write constant memory init context position in channel "672" for pgsp. */ WriteParams.ulWriteAddress = 0x71A; WriteParams.usWriteData = 0x8000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set fixed PGSP event_in base address to 800 on a 2k boundary */ WriteParams.ulWriteAddress = 0x716; WriteParams.usWriteData = 0x800 >> 11; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set fixed PGSP event_out to 0x2C0000h on a 16k boundary */ WriteParams.ulWriteAddress = 0x71C; WriteParams.usWriteData = 0x2C0000 >> 14; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Give chariot control of the chip. */ WriteParams.ulWriteAddress = 0x712; WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + 0x2C0000 + 0xC; ulTempAddress = 0x300000 + 0x0800; WriteParams.usWriteData = (UINT16)( ( ulTempAddress >> 16 ) & 0x07FF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + 0x2C0000 + 0xE; WriteParams.usWriteData = (UINT16)( ( ulTempAddress >> 0 ) & 0xFF00 ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write the init PGSP event in place. */ WriteParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + 0x800; WriteParams.usWriteData = 0x0200; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + 0x802; WriteParams.usWriteData = 0x02A0; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Also write the register 710, which tells PGSP how many tones are supported. */ WriteParams.ulWriteAddress = 0x710; WriteParams.usWriteData = 0x0000; WriteParams.usWriteData |= pChipConfig->pbyImageFile[ 0x7FA ] << 8; WriteParams.usWriteData |= pChipConfig->pbyImageFile[ 0x7FB ] << 0; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Start both processors in the NLP. */ WriteParams.ulWriteAddress = 0x373FE; WriteParams.usWriteData = 0x00FF; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x37BFE; WriteParams.usWriteData = 0x00FE; /* Tell processor 1 to just go to sleep. */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x37FC6; WriteParams.usWriteData = 0x8004; /* First PC.*/ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x37FD0; WriteParams.usWriteData = 0x0002; /* Take out of reset. */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x37FD2; WriteParams.usWriteData = 0x0002; /* Take out of reset. */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Start processor in the AF. */ for ( i = 0; i < 16; i ++ ) { WriteParams.ulWriteAddress = cOCT6100_POUCH_BASE + ( i * 2 ); if ( i == 9 ) { if ( pSharedInfo->ChipConfig.fEnableProductionBist == TRUE ) { WriteParams.usWriteData = cOCT6100_PRODUCTION_BOOT_TYPE; } else { WriteParams.usWriteData = cOCT6100_AF_BOOT_TYPE; } } else WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Check if the production BIST mode was requested. */ if ( pSharedInfo->ChipConfig.fEnableProductionBist == TRUE ) { UINT32 ulTotalElements = 3; UINT32 ulCrcKey; UINT32 aulMessage[ 4 ]; UINT32 ulWriteAddress = 0x20 + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS; /* Magic key. */ aulMessage[ 0 ] = 0xCAFECAFE; /* Memory size. */ aulMessage[ 1 ] = pSharedInfo->MiscVars.ulTotalMemSize; /* Loop count. */ aulMessage[ 2 ] = pSharedInfo->ChipConfig.ulNumProductionBistLoops; /* CRC initialized. */ aulMessage[ 3 ] = 0; ulResult = Oct6100ApiProductionCrc( f_pApiInstance, aulMessage, ulTotalElements, &ulCrcKey ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; aulMessage[ 3 ] = ulCrcKey; /* Write the message to the external memory. */ for ( i = 0; i < ulTotalElements + 1; i ++ ) { ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulWriteAddress + i * 4, aulMessage[ i ] ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } WriteParams.ulWriteAddress = 0xFFFC6; WriteParams.usWriteData = 0x1284; /* First PC.*/ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0xFFFD0; WriteParams.usWriteData = 0x0002; /* Take out of reset. */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; while ( ulAfCpuUp == FALSE ) { if ( ulAfCpuUp == FALSE ) { ReadParams.ulReadAddress = cOCT6100_POUCH_BASE; ReadParams.pusReadData = &usReadHighData; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ReadParams.ulReadAddress += 2; ReadParams.pusReadData = &usReadData; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( pSharedInfo->ChipConfig.fEnableProductionBist == TRUE ) { /* Should read 0x0007 when bisting. */ if ( ( usReadHighData & 0xFFFF ) == cOCT6100_PRODUCTION_BOOT_TYPE ) { /* Verify if the bist has started successfully. */ if ( ( usReadData & 0xFFFF ) == 0x0002 ) return cOCT6100_ERR_OPEN_PRODUCTION_BIST_CONF_FAILED; else if ( ( usReadData & 0xFFFF ) != 0xEEEE ) return cOCT6100_ERR_OPEN_PRODUCTION_BOOT_FAILED; ulAfCpuUp = TRUE; } } else /* if ( pSharedInfo->ChipConfig.fEnableProductionBist == FALSE ) */ { if ( ( usReadHighData & 0xFFFF ) == cOCT6100_AF_BOOT_TYPE ) { /* Verify if the bist succeeded. */ if ( ( usReadData & 0xFFFF ) != 0x0000 ) return cOCT6100_ERR_OPEN_FUNCTIONAL_BIST_FAILED; /* Bad chip. */ ulAfCpuUp = TRUE; } } } ulLoopCounter++; if ( ulLoopCounter == cOCT6100_MAX_LOOP_CPU_TIMEOUT ) return cOCT6100_ERR_OPEN_AF_CPU_TIMEOUT; } /* Return NLP in operationnal mode. */ WriteParams.ulWriteAddress = 0x2C2; WriteParams.usWriteData = 0x060E; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x692; WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiSetH100Register Description: This function will configure the H.100 registers. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiSetH100Register( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHIP_CONFIG pChipConfig; UINT32 i; UINT32 ulOffset; BOOL fAllStreamAt2Mhz = TRUE; const UINT16 ausAdpcmResetContext[32] = { 0x1100, 0x0220, 0x0000, 0x0000, 0x0000, 0x0020, 0x0000, 0x0000, 0x0008, 0x0000, 0x0000, 0x0100, 0x0000, 0x0020, 0x0000, 0x0000, 0x0000, 0x0002, 0x0000, 0x0000, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x0000, 0x0010, 0x0000, 0x0000, 0x0000}; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Get local pointer to the chip configuration structure. */ pChipConfig = &f_pApiInstance->pSharedInfo->ChipConfig; /* Initialize the process context and user chip ID once and for all. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; /* Set the Global OE bit. */ WriteParams.ulWriteAddress = 0x300; WriteParams.usWriteData = 0x0004; /* Set the number of streams. */ switch( pChipConfig->byMaxTdmStreams ) { case 32: WriteParams.usWriteData |= ( 0 << 3 ); break; case 16: WriteParams.usWriteData |= ( 1 << 3 ); break; case 8: WriteParams.usWriteData |= ( 2 << 3 ); break; case 4: WriteParams.usWriteData |= ( 3 << 3 ); break; default: break; } mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Configure the stream frequency. */ WriteParams.ulWriteAddress = 0x330; WriteParams.usWriteData = 0x0000; for ( i = 0; i < (UINT32)(pChipConfig->byMaxTdmStreams / 4); i++) { ulOffset = i*2; switch( pChipConfig->aulTdmStreamFreqs[ i ] ) { case cOCT6100_TDM_STREAM_FREQ_2MHZ: WriteParams.usWriteData |= ( 0x0 << ulOffset ); break; case cOCT6100_TDM_STREAM_FREQ_4MHZ: WriteParams.usWriteData |= ( 0x1 << ulOffset ); fAllStreamAt2Mhz = FALSE; break; case cOCT6100_TDM_STREAM_FREQ_8MHZ: WriteParams.usWriteData |= ( 0x2 << ulOffset ); fAllStreamAt2Mhz = FALSE; break; default: break; } } /* Set the stream to 16 MHz if the fast H.100 mode is selected. */ if ( pChipConfig->fEnableFastH100Mode == TRUE ) { fAllStreamAt2Mhz = FALSE; WriteParams.usWriteData = 0xFFFF; } mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) { /* Make the chip track both clock A and B to perform fast H.100 mode. */ WriteParams.ulWriteAddress = 0x322; WriteParams.usWriteData = 0x0004; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Enable the fast H.100 mode. */ WriteParams.ulWriteAddress = 0x332; WriteParams.usWriteData = 0x0003; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } WriteParams.ulWriteAddress = 0x376; WriteParams.usWriteData = (UINT16)( pSharedInfo->MiscVars.usTdmClkBoundary ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Select delay for early clock (90 and 110). */ WriteParams.ulWriteAddress = 0x378; if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) WriteParams.usWriteData = 0x000A; else { /* Set the TDM sampling. */ if ( pSharedInfo->ChipConfig.byTdmSampling == cOCT6100_TDM_SAMPLE_AT_RISING_EDGE ) { WriteParams.usWriteData = 0x0AF0; } else if ( pSharedInfo->ChipConfig.byTdmSampling == cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE ) { WriteParams.usWriteData = 0x0A0F; } else /* pSharedInfo->ChipConfig.ulTdmSampling == cOCT6100_TDM_SAMPLE_AT_3_QUARTERS */ { WriteParams.usWriteData = 0x0A08; } } mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Protect chip by preventing too rapid timeslot arrival (mclk == 133 MHz). */ WriteParams.ulWriteAddress = 0x37A; WriteParams.usWriteData = (UINT16)pSharedInfo->MiscVars.usMaxH100Speed; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Allow H.100 TS to progress. */ WriteParams.ulWriteAddress = 0x382; WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set by-pass mode. */ WriteParams.ulWriteAddress = 0x50E; WriteParams.usWriteData = 0x0001; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* TDMIE bits. */ WriteParams.ulWriteAddress = 0x500; WriteParams.usWriteData = 0x0003; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write normal ADPCM reset values in ADPCM context 1344. */ for(i=0;i<32;i++) { WriteParams.ulWriteAddress = 0x140000 + ( 0x40 * 1344 ) + ( i * 2 ); WriteParams.usWriteData = ausAdpcmResetContext[i]; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Make sure delay flops are configured correctly if all streams are at 2 MHz. */ if ( fAllStreamAt2Mhz == TRUE ) { /* Setup H.100 sampling to lowest value. */ WriteParams.ulWriteAddress = 0x144; WriteParams.usWriteData = 0x4041; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x378; WriteParams.usWriteData = 0x0A00; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteMiscellaneousRegisters Description: This function will write to various registers to activate the chip. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWriteMiscellaneousRegisters( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; /* Initialize the process context and user chip ID once and for all. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; /* Free the interrupt pin of the chip (i.e. remove minimum time requirement between interrupts). */ WriteParams.ulWriteAddress = 0x214; WriteParams.usWriteData = 0x0000; if ( f_pApiInstance->pSharedInfo->ChipConfig.byInterruptPolarity == cOCT6100_ACTIVE_HIGH_POLARITY ) WriteParams.usWriteData |= 0x4000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write MT chariot interval */ WriteParams.ulWriteAddress = 0x2C2; if ( f_pApiInstance->pSharedInfo->ImageInfo.usMaxNumberOfChannels > 640 ) WriteParams.usWriteData = 0x05EA; else if ( f_pApiInstance->pSharedInfo->ImageInfo.usMaxNumberOfChannels > 513 ) WriteParams.usWriteData = 0x0672; else /* if ( f_pApiInstance->pSharedInfo->ImageInfo.usMaxNumberOfChannels <= 513 ) */ WriteParams.usWriteData = 0x0750; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write set second part5 time. */ WriteParams.ulWriteAddress = 0x2C4; WriteParams.usWriteData = 0x04A0; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write CPU bucket timer to guarantee 200 cycles between each CPU access. */ WriteParams.ulWriteAddress = 0x234; WriteParams.usWriteData = 0x0804; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x236; WriteParams.usWriteData = 0x0100; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiCreateSerializeObjects Description: Creates a handle to each serialization object used by the API. Note that in a multi-process system the user's process context structure pointer is needed by this function. Thus, the pointer must be valid. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulUserChipId User chip ID for this serialization object. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiCreateSerializeObjects( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulUserChipId ) { tOCT6100_CREATE_SERIALIZE_OBJECT CreateSerObj = { 0, }; UINT32 ulResult; CHAR szSerObjName[ 64 ] = "Oct6100ApiXXXXXXXXApiSerObj"; /* Set some parameters of the create structure once and for all. */ CreateSerObj.pProcessContext = f_pApiInstance->pProcessContext; CreateSerObj.pszSerialObjName = szSerObjName; /*----------------------------------------------------------------------*/ /* Set the chip ID in the semaphore name. */ szSerObjName[ 10 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 28 ) & 0xFF ); szSerObjName[ 11 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 24 ) & 0xFF ); szSerObjName[ 12 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 20 ) & 0xFF ); szSerObjName[ 13 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 16 ) & 0xFF ); szSerObjName[ 14 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 12 ) & 0xFF ); szSerObjName[ 15 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 8 ) & 0xFF ); szSerObjName[ 16 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 4 ) & 0xFF ); szSerObjName[ 17 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 0 ) & 0xFF ); ulResult = Oct6100UserCreateSerializeObject( &CreateSerObj ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; f_pApiInstance->ulApiSerObj = CreateSerObj.ulSerialObjHndl; /*----------------------------------------------------------------------*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiDestroySerializeObjects Description: Destroy handles to each serialization object used by the API. Note that in a multi-process system the user's process context structure pointer is needed by this function. Thus, the pointer must be valid. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiDestroySerializeObjects( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tOCT6100_DESTROY_SERIALIZE_OBJECT DestroySerObj; UINT32 ulResult; /* Set some parameters of the create structure once and for all. */ DestroySerObj.pProcessContext = f_pApiInstance->pProcessContext; DestroySerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ulResult = Oct6100UserDestroySerializeObject( &DestroySerObj ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiRunEgo Description: Private function used to communicate with the internal processors. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_fStoreFlag Type of access performed. (Load or Store) f_ulNumEntry Number of access. f_aulEntry Array of access to perform. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiRunEgo( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN BOOL f_fStoreFlag, IN UINT32 f_ulNumEntry, OUT PUINT32 f_aulEntry ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHIP_CONFIG pChipConfig; tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_READ_PARAMS ReadParams; UINT32 ulResult; UINT32 aulCpuLsuCmd[ 2 ]; UINT16 usReadData; UINT32 i; BOOL fConditionFlag = TRUE; UINT32 ulLoopCounter = 0; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Get local pointer to the chip configuration structure. */ pChipConfig = &f_pApiInstance->pSharedInfo->ChipConfig; /* Set the process context and user chip ID parameters once and for all. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; /* No more than 2 entries may be requested. */ if ( f_ulNumEntry > 2 ) return cOCT6100_ERR_FATAL_1B; /* Write the requested entries at address reserved for CPU. */ for( i = 0; i < f_ulNumEntry; i++ ) { WriteParams.ulWriteAddress = cOCT6100_PART1_API_SCRATCH_PAD + ( 0x8 * i ); WriteParams.usWriteData = (UINT16)(( f_aulEntry[ i * 2 ] >> 16 ) & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( f_aulEntry[ i * 2 ] & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)(( f_aulEntry[ (i * 2) + 1] >> 16 ) & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( f_aulEntry[ (i * 2) + 1] & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Preincrement code point. */ pSharedInfo->MiscVars.usCodepoint++; /* Create DWORD 0 of command. */ aulCpuLsuCmd[0] = 0x00000000; if ( f_fStoreFlag == FALSE ) aulCpuLsuCmd[0] |= 0xC0000000; /* EGO load. */ else aulCpuLsuCmd[0] |= 0xE0000000; /* EGO store. */ aulCpuLsuCmd[0] |= (f_ulNumEntry - 1) << 19; aulCpuLsuCmd[0] |= cOCT6100_PART1_API_SCRATCH_PAD; /* Create DWORD 1 of command. */ aulCpuLsuCmd[1] = 0x00000000; aulCpuLsuCmd[1] |= ( ( cOCT6100_PART1_API_SCRATCH_PAD + 0x10 ) & 0xFFFF ) << 16; aulCpuLsuCmd[1] |= pSharedInfo->MiscVars.usCodepoint; /* Write the EGO command in the LSU CB. */ WriteParams.ulWriteAddress = cOCT6100_PART1_CPU_LSU_CB_BASE + ((pSharedInfo->MiscVars.usCpuLsuWritePtr & 0x7) * 0x8 ); WriteParams.usWriteData = (UINT16)(( aulCpuLsuCmd[ 0 ] >> 16 ) & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( aulCpuLsuCmd[ 0 ] & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)(( aulCpuLsuCmd[ 1 ] >> 16 ) & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( aulCpuLsuCmd[ 1 ] & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Post increment the write pointer. */ pSharedInfo->MiscVars.usCpuLsuWritePtr++; /* Indicate new write pointer position to HW. */ WriteParams.ulWriteAddress = cOCT6100_PART1_EGO_REG + 0x5A; WriteParams.usWriteData = (UINT16)( pSharedInfo->MiscVars.usCpuLsuWritePtr & 0x7 ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Wait for codepoint to be updated before returning. */ while( fConditionFlag ) { ReadParams.ulReadAddress = cOCT6100_PART1_API_SCRATCH_PAD + 0x12; usReadData = (UINT16)( pSharedInfo->MiscVars.usCodepoint ); mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( usReadData == pSharedInfo->MiscVars.usCodepoint ) fConditionFlag = FALSE; ulLoopCounter++; if ( ulLoopCounter == cOCT6100_MAX_LOOP ) return cOCT6100_ERR_OPEN_EGO_TIMEOUT; } /* CRC error bit must be zero. */ ReadParams.ulReadAddress = 0x202; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( ( usReadData & 0x0400 ) != 0 ) return cOCT6100_ERR_OPEN_CORRUPTED_IMAGE; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiCreateEgoEntry Description: Private function used to create an access structure to be sent to the internal processors. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_ulExternalAddress External memory address for the access. f_ulInternalAddress Which process should receive the command. f_ulNumBytes Number of bytes associated to the access. f_aulEntry Array of access to perform. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiCreateEgoEntry( IN UINT32 f_ulExternalAddress, IN UINT32 f_ulInternalAddress, IN UINT32 f_ulNumBytes, OUT UINT32 f_aulEntry[ 2 ] ) { f_aulEntry[0] = 0x80000000; f_aulEntry[0] |= f_ulExternalAddress & 0x07FFFFFC; f_aulEntry[1] = 0x0011C000; f_aulEntry[1] |= (f_ulNumBytes / 8) << 23; f_aulEntry[1] |= (f_ulInternalAddress >> 2) & 0x3FFF; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiInitChannels Description: This function will initialize all the channels to power down. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiInitChannels( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; UINT32 i; UINT32 ulResult; tOCT6100_WRITE_BURST_PARAMS BurstParams; tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_READ_PARAMS ReadParams; UINT16 usReadData; UINT32 ulTempData; UINT32 ulBaseAddress; UINT32 ulFeatureBytesOffset; UINT32 ulFeatureBitOffset; UINT32 ulFeatureFieldLength; UINT32 ulMask; UINT16 ausWriteData[ 4 ]; UINT16 usLoopCount = 0; UINT16 usWriteData = 0; UINT16 usMclkRead; UINT16 usLastMclkRead; UINT16 usMclkDiff; UINT32 ulNumberOfCycleToWait; pSharedInfo = f_pApiInstance->pSharedInfo; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; BurstParams.pProcessContext = f_pApiInstance->pProcessContext; BurstParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; BurstParams.pusWriteData = ausWriteData; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; /* Verify that the image has enough memory to work correctly. */ if ( ( pSharedInfo->MiscVars.ulTotalMemSize + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ) < pSharedInfo->MemoryMap.ulFreeMemBaseAddress ) return cOCT6100_ERR_OPEN_INSUFFICIENT_EXTERNAL_MEMORY; /* Verify that the tail length is supported by the device.*/ if ( pSharedInfo->ChipConfig.usTailDisplacement > pSharedInfo->ImageInfo.usMaxTailDisplacement ) return cOCT6100_ERR_NOT_SUPPORTED_OPEN_TAIL_DISPLACEMENT_VALUE; /* Verify that acoustic echo is supported by the device. */ if ( pSharedInfo->ChipConfig.fEnableAcousticEcho == TRUE && pSharedInfo->ImageInfo.fAcousticEcho == FALSE ) return cOCT6100_ERR_NOT_SUPPORTED_OPEN_ACOUSTIC_ECHO; /* Verify that the image supports all the requested channels. */ if ( pSharedInfo->ChipConfig.usMaxChannels > pSharedInfo->ImageInfo.usMaxNumberOfChannels ) return cOCT6100_ERR_NOT_SUPPORTED_OPEN_MAX_ECHO_CHANNELS_VALUE; /* Max number of channels the image supports + 1 for channel recording, if requested */ if ( ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) && ( pSharedInfo->ImageInfo.usMaxNumberOfChannels < cOCT6100_MAX_ECHO_CHANNELS ) && ( pSharedInfo->ChipConfig.usMaxChannels == pSharedInfo->ImageInfo.usMaxNumberOfChannels ) ) return cOCT6100_ERR_NOT_SUPPORTED_OPEN_MAX_ECHO_CHANNELS_VALUE; /* Initialize the memory for all required channels. */ for( i = 0; i < f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels; i++ ) { /*==============================================================================*/ /* Configure the Global Static Configuration memory of the channel. */ ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( i * cOCT6100_CHANNEL_ROOT_SIZE ) + cOCT6100_CHANNEL_ROOT_GLOBAL_CONF_OFFSET; /* Set the PGSP context base address. */ ulTempData = pSharedInfo->MemoryMap.ulChanMainMemBase + ( i * pSharedInfo->MemoryMap.ulChanMainMemSize ) + cOCT6100_CH_MAIN_PGSP_CONTEXT_OFFSET; WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_PGSP_CONTEXT_BASE_ADD_OFFSET; WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set the PGSP init context base address. */ ulTempData = ( cOCT6100_IMAGE_FILE_BASE + 0x200 ) & 0x07FFFFFF; WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_PGSP_INIT_CONTEXT_BASE_ADD_OFFSET; WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set the RIN circular buffer base address. */ ulTempData = pSharedInfo->MemoryMap.ulChanMainMemBase + ( i * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainRinCBMemOfst; /* Set the circular buffer size. */ ulTempData &= 0xFFFFFF00; if (( pSharedInfo->MemoryMap.ulChanMainRinCBMemSize & 0xFFFF00FF ) != 0 ) return cOCT6100_ERR_CHANNEL_INVALID_RIN_CB_SIZE; ulTempData |= pSharedInfo->MemoryMap.ulChanMainRinCBMemSize >> 8; WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_RIN_CIRC_BUFFER_BASE_ADD_OFFSET; WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set the SIN circular buffer base address. */ ulTempData = pSharedInfo->MemoryMap.ulChanMainMemBase + ( i * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainSinCBMemOfst; WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_SIN_CIRC_BUFFER_BASE_ADD_OFFSET; WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set the SOUT circular buffer base address. */ ulTempData = pSharedInfo->MemoryMap.ulChanMainMemBase + ( i * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainSoutCBMemOfst;; WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_SOUT_CIRC_BUFFER_BASE_ADD_OFFSET; WriteParams.usWriteData = (UINT16)( ulTempData >> 16 ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==============================================================================*/ } /* Put all channel in powerdown mode "3". */ for( i = 0; i < f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels; i++ ) { WriteParams.ulWriteAddress = 0x014000 + (i*4) + 0; WriteParams.usWriteData = 0x85FF; /* TSI index 1535 reserved for power-down mode */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x014000 + (i*4) + 2; WriteParams.usWriteData = 0xC5FF; /* TSI index 1535 reserved for power-down mode */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Set the maximum number of channels. */ WriteParams.ulWriteAddress = 0x690; if ( pSharedInfo->ImageInfo.usMaxNumberOfChannels < 384 ) WriteParams.usWriteData = 384; else WriteParams.usWriteData = (UINT16)pSharedInfo->ImageInfo.usMaxNumberOfChannels; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set power-dowm TSI chariot memory to silence. */ for( i = 0; i < 6; i++ ) { WriteParams.ulWriteAddress = 0x20000 + ( i * 0x1000 ) + ( 1534 * 2 ); WriteParams.usWriteData = 0xFF; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x20000 + ( i * 0x1000 ) + ( 1535 * 2 ); WriteParams.usWriteData = 0xFF; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Remove chariot hold. */ WriteParams.ulWriteAddress = 0x500; WriteParams.usWriteData = 0x0001; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; for( usLoopCount = 0; usLoopCount < 4096; usLoopCount++ ) { if ( (usLoopCount % 16) < 8 ) { usWriteData = (UINT16)((usLoopCount / 16) << 7); usWriteData |= (UINT16)((usLoopCount % 8)); } else { usWriteData = (UINT16)((usLoopCount / 16) << 7); usWriteData |= (UINT16)((usLoopCount % 8)); usWriteData |= 0x78; } /* Set timeslot pointer. */ WriteParams.ulWriteAddress = 0x50E; WriteParams.usWriteData = 0x0003; WriteParams.usWriteData |= usWriteData << 2; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Now read the mclk counter. */ ReadParams.ulReadAddress = 0x30A; ReadParams.pusReadData = &usLastMclkRead; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; do { ReadParams.pusReadData = &usMclkRead; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( ( usLoopCount % 16 ) != 15 ) { ulNumberOfCycleToWait = 133; } else { ulNumberOfCycleToWait = 20000; } /* Evaluate the difference. */ usMclkDiff = (UINT16)(( usMclkRead - usLastMclkRead ) & 0xFFFF); } while( usMclkDiff <= ulNumberOfCycleToWait ); } /* Back to normal mode. */ WriteParams.ulWriteAddress = 0x50E; WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check for CRC errors. */ ReadParams.pusReadData = &usReadData; ReadParams.ulReadAddress = 0x202; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( (usReadData & 0x400) != 0x0000 ) return cOCT6100_ERR_OPEN_CRC_ERROR; /* Clear the error rol raised by manually moving the clocks. */ WriteParams.ulWriteAddress = 0x502; WriteParams.usWriteData = 0x0002; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*======================================================================*/ /* Write the tail displacement value in external memory. */ ulFeatureBytesOffset = pSharedInfo->MemoryMap.PouchTailDisplOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.PouchTailDisplOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.PouchTailDisplOfst.byFieldSize; ulResult = Oct6100ApiReadDword( f_pApiInstance, cOCT6100_POUCH_BASE + ulFeatureBytesOffset, &ulTempData ); /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); /* Set the tail displacement. */ ulTempData |= (pSharedInfo->ChipConfig.usTailDisplacement << ulFeatureBitOffset ); /* Write the DWORD where the field is located. */ ulResult = Oct6100ApiWriteDword( f_pApiInstance, cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ulTempData ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*======================================================================*/ /*======================================================================*/ /* Clear the pouch counter, if present. */ if ( pSharedInfo->DebugInfo.fPouchCounter == TRUE ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.PouchCounterFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.PouchCounterFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.PouchCounterFieldOfst.byFieldSize; ulResult = Oct6100ApiReadDword( f_pApiInstance, cOCT6100_POUCH_BASE + ulFeatureBytesOffset, &ulTempData ); /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); /* Clear counter! */ ulTempData &= (~ulMask); /* Write the DWORD where the field is located.*/ ulResult = Oct6100ApiWriteDword( f_pApiInstance, cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ulTempData ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* The ISR has not yet been called. Set the appropriate bit in external memory. */ if ( pSharedInfo->DebugInfo.fIsIsrCalledField == TRUE ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.IsIsrCalledFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.IsIsrCalledFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.IsIsrCalledFieldOfst.byFieldSize; ulResult = Oct6100ApiReadDword( f_pApiInstance, cOCT6100_POUCH_BASE + ulFeatureBytesOffset, &ulTempData ); /* Read previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); /* Toggle the bit to '1'. */ ulTempData |= 1 << ulFeatureBitOffset; /* Write the DWORD where the field is located.*/ ulResult = Oct6100ApiWriteDword( f_pApiInstance, cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ulTempData ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*======================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiInitToneInfo Description: This function will parse the software image and retrieve the information about the tones that it supports. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiInitToneInfo( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { UINT32 ulResult; PUINT8 pszToneInfoStart = NULL; PUINT8 pszToneInfoEnd = NULL; PUINT8 pszCurrentInfo; PUINT8 pszNextInfo; UINT32 ulToneEventNumber; UINT32 ulTempValue; UINT32 ulNumCharForValue; UINT32 ulUniqueToneId; UINT32 ulToneNameSize; UINT32 ulOffset = 0; UINT32 i; /* Init the tone detector parameter. */ f_pApiInstance->pSharedInfo->ImageInfo.byNumToneDetectors = 0; /* Find the start and the end of the tone info section. */ if ( f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize > 4096 ) { /* For performance reasons, and since the tone detector information */ /* is always located at the end of the image file, try to start from the end */ /* of the buffer. */ ulOffset = f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize - 2048; pszToneInfoStart = Oct6100ApiStrStr( f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + ulOffset, (PUINT8)cOCT6100_TONE_INFO_START_STRING, f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize ); /* Check if the information was found. */ if ( pszToneInfoStart == NULL ) { /* Try again, but giving a larger string to search. */ ulOffset = f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize - 4096; pszToneInfoStart = Oct6100ApiStrStr( f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + ulOffset, (PUINT8)cOCT6100_TONE_INFO_START_STRING, f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize ); } } if ( pszToneInfoStart == NULL ) { /* Travel through the whole file buffer. */ pszToneInfoStart = Oct6100ApiStrStr( f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile, (PUINT8)cOCT6100_TONE_INFO_START_STRING, f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize ); } /* We have to return immediatly if no tones are found. */ if ( pszToneInfoStart == NULL ) return cOCT6100_ERR_OK; /* The end of the tone detector information is after the beginning of the tone information. */ pszToneInfoEnd = Oct6100ApiStrStr( pszToneInfoStart, (PUINT8)cOCT6100_TONE_INFO_STOP_STRING, f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize ); if ( pszToneInfoEnd == NULL ) return cOCT6100_ERR_OPEN_TONE_INFO_STOP_TAG_NOT_FOUND; /* Find and process all tone events within the region. */ pszCurrentInfo = Oct6100ApiStrStr( pszToneInfoStart, (PUINT8)cOCT6100_TONE_INFO_EVENT_STRING, pszToneInfoEnd ); while ( pszCurrentInfo != NULL ) { /* Skip the string. */ pszCurrentInfo += ( Oct6100ApiStrLen( (PUINT8)cOCT6100_TONE_INFO_EVENT_STRING ) ); /* Extract the number of char used to represent the tone event number ( 1 or 2 ). */ pszNextInfo = Oct6100ApiStrStr( pszCurrentInfo, (PUINT8)",", pszToneInfoEnd ); ulNumCharForValue = pszNextInfo - pszCurrentInfo; /* Retreive the event number */ ulToneEventNumber = 0; for ( i = ulNumCharForValue; i > 0; i-- ) { ulResult = Oct6100ApiAsciiToHex( *pszCurrentInfo, &ulTempValue ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulToneEventNumber |= ( ulTempValue << (( i - 1) * 4 ) ); pszCurrentInfo++; } if ( ulToneEventNumber >= cOCT6100_MAX_TONE_EVENT ) return cOCT6100_ERR_OPEN_INVALID_TONE_EVENT; /* Skip the comma and the 0x. */ pszCurrentInfo += 3; /*======================================================================*/ /* Retreive the unique tone id. */ ulUniqueToneId = 0; for ( i = 0; i < 8; i++ ) { ulResult = Oct6100ApiAsciiToHex( *pszCurrentInfo, &ulTempValue ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulOffset = 28 - ( i * 4 ); ulUniqueToneId |= ( ulTempValue << ulOffset ); pszCurrentInfo++; } /*======================================================================*/ /* Skip the comma. */ pszCurrentInfo++; /* Find out where the next event info starts */ pszNextInfo = Oct6100ApiStrStr( pszCurrentInfo,(PUINT8) cOCT6100_TONE_INFO_EVENT_STRING, pszToneInfoEnd ); if ( pszNextInfo == NULL ) pszNextInfo = pszToneInfoEnd; /* Extract the name size. */ ulToneNameSize = pszNextInfo - pszCurrentInfo - 2; /* - 2 for 0x0D and 0x0A.*/ if ( ulToneNameSize > cOCT6100_TLV_MAX_TONE_NAME_SIZE ) return cOCT6100_ERR_OPEN_INVALID_TONE_NAME; /* Copy the tone name into the image info structure. */ ulResult = Oct6100UserMemCopy( f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].aszToneName, pszCurrentInfo, ulToneNameSize ); /* Update the tone info into the image info structure. */ f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulToneID = ulUniqueToneId; /* Find out the port on which this tone detector is associated. */ switch( (ulUniqueToneId >> 28) & 0xF ) { case 1: f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulDetectionPort = cOCT6100_CHANNEL_PORT_ROUT; break; case 2: f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulDetectionPort = cOCT6100_CHANNEL_PORT_SIN; break; case 4: f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulDetectionPort = cOCT6100_CHANNEL_PORT_SOUT; break; case 5: f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulDetectionPort = cOCT6100_CHANNEL_PORT_ROUT_SOUT; break; default: f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulDetectionPort = cOCT6100_INVALID_PORT; break; } /* Find out where the next event info starts */ pszNextInfo = Oct6100ApiStrStr( pszCurrentInfo,(PUINT8) cOCT6100_TONE_INFO_EVENT_STRING, pszToneInfoEnd ); /* Update the current info pointer. */ pszCurrentInfo = pszNextInfo; f_pApiInstance->pSharedInfo->ImageInfo.byNumToneDetectors++; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiExternalMemoryBist Description: Tests the functionality of the external memories. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiExternalMemoryBist( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; UINT32 ulMemSize = 0; UINT32 ulResult; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Test the external memory. */ switch ( pSharedInfo->ChipConfig.ulMemoryChipSize ) { case cOCT6100_MEMORY_CHIP_SIZE_8MB: ulMemSize = cOCT6100_SIZE_8M; break; case cOCT6100_MEMORY_CHIP_SIZE_16MB: ulMemSize = cOCT6100_SIZE_16M; break; case cOCT6100_MEMORY_CHIP_SIZE_32MB: ulMemSize = cOCT6100_SIZE_32M; break; case cOCT6100_MEMORY_CHIP_SIZE_64MB: ulMemSize = cOCT6100_SIZE_64M; break; case cOCT6100_MEMORY_CHIP_SIZE_128MB: ulMemSize = cOCT6100_SIZE_128M; break; default: return cOCT6100_ERR_FATAL_D9; } ulMemSize *= pSharedInfo->ChipConfig.byNumMemoryChips; ulResult = Oct6100ApiRandomMemoryWrite( f_pApiInstance, cOCT6100_EXTERNAL_MEM_BASE_ADDRESS, ulMemSize, 16, 1000, cOCT6100_ERR_OPEN_EXTERNAL_MEM_BIST_FAILED ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Make sure the user I/O functions are working as required. */ ulResult = Oct6100ApiUserIoTest( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGenerateNumber Description: Generate a number using an index. Passing the same index generates the same number. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulIndex Index used to generate the random number. f_ulDataMask Data mask to apply to generated number. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT16 Oct6100ApiGenerateNumber( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulIndex, IN UINT32 f_ulDataMask ) { UINT16 usGeneratedNumber; usGeneratedNumber = (UINT16)( ( ( ~( f_ulIndex - 1 ) ) & 0xFF00 ) | ( ( f_ulIndex + 1 ) & 0xFF ) ); return (UINT16)( usGeneratedNumber & f_ulDataMask ); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiRandomMemoryWrite Description: Writes to f_ulNumAccesses random locations in the indicated memory and read back to test the operation of that memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulMemBase Base address of the memory access. f_ulMemSize Size of the memory to be tested. f_ulNumDataBits Number of data bits. f_ulNumAccesses Number of random access to be perform. f_ulErrorCode Error code to be returned if the bist fails. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiRandomMemoryWrite( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulMemBase, IN UINT32 f_ulMemSize, IN UINT32 f_ulNumDataBits, IN UINT32 f_ulNumAccesses, IN UINT32 f_ulErrorCode ) { tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_READ_PARAMS ReadParams; UINT32 ulDataMask; UINT32 ulResult, i, j; UINT32 ulBistAddress; UINT16 usReadData; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Set the process context and user chip ID parameters once and for all. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* Make sure we don't perform more access then the size of our BIST resources. */ if ( f_ulNumAccesses > 1024 ) return cOCT6100_ERR_FATAL_C0; /* Determine mask for number of data bits. */ ulDataMask = (1 << f_ulNumDataBits) - 1; /* Bist all data pin. */ for ( i = 0; i < 32; i += 2 ) { WriteParams.ulWriteAddress = f_ulMemBase + i * 2; WriteParams.usWriteData = (UINT16)(0x1 << (i / 2)); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = f_ulMemBase + i * 2 + 2; WriteParams.usWriteData = (UINT16)(0x1 << (i / 2)); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Read back the data written. */ for ( i = 0; i < 32; i += 2 ) { ReadParams.ulReadAddress = f_ulMemBase + i * 2; ReadParams.pusReadData = &usReadData; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( usReadData != (UINT16)(0x1 << (i / 2)) ) return f_ulErrorCode; ReadParams.ulReadAddress = f_ulMemBase + i * 2 + 2; ReadParams.pusReadData = &usReadData; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( usReadData != (UINT16)(0x1 << (i / 2)) ) return f_ulErrorCode; } /* Perform the first write at address 0 + mem base */ j = 0; WriteParams.ulWriteAddress = f_ulMemBase; WriteParams.usWriteData = Oct6100ApiGenerateNumber( f_pApiInstance, j, ulDataMask ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Try each address line of the memory. */ for ( i = 2, j = 1; i < f_ulMemSize; i <<= 1, j++ ) { WriteParams.ulWriteAddress = ( f_ulMemBase + i ); WriteParams.usWriteData = Oct6100ApiGenerateNumber( f_pApiInstance, j, ulDataMask ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } for ( i = 0; i < j; i++ ) { if ( i > 0 ) ReadParams.ulReadAddress = ( f_ulMemBase + ( 0x1 << i ) ); else ReadParams.ulReadAddress = f_ulMemBase; ReadParams.pusReadData = &usReadData; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( usReadData != Oct6100ApiGenerateNumber( f_pApiInstance, i, ulDataMask ) ) return f_ulErrorCode; } /* Write to random addresses of the memory. */ for ( i = 0; i < f_ulNumAccesses; i++ ) { ulBistAddress = (UINT16)Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ) << 16; ulBistAddress |= (UINT16)Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ); ulBistAddress &= f_ulMemSize - 2; ulBistAddress |= f_ulMemBase; WriteParams.ulWriteAddress = ulBistAddress; WriteParams.usWriteData = Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } for ( i = 0; i < f_ulNumAccesses; i++ ) { ulBistAddress = (UINT16)Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ) << 16; ulBistAddress |= (UINT16)Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ); ulBistAddress &= f_ulMemSize - 2; ulBistAddress |= f_ulMemBase; ReadParams.ulReadAddress = ulBistAddress; ReadParams.pusReadData = &usReadData; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( ( usReadData & ulDataMask ) != ( Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ) & ulDataMask ) ) return f_ulErrorCode; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiUserIoTest Description: This function will verify the correct functionality of the following user functions: - Oct6100UserDriverWriteBurstApi - Oct6100UserDriverWriteSmearApi - Oct6100UserDriverReadBurstApi The Oct6100UserDriverWriteApi and Oct6100UserDriverReadApi functions do not need to be tested here as this has be done in the external memory bisting function above. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiUserIoTest( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_WRITE_BURST_PARAMS WriteBurstParams; tOCT6100_WRITE_SMEAR_PARAMS WriteSmearParams; tOCT6100_READ_PARAMS ReadParams; tOCT6100_READ_BURST_PARAMS ReadBurstParams; UINT32 ulResult, i; UINT16 usReadData; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Set the process context and user chip ID parameters once and for all. */ WriteBurstParams.pProcessContext = f_pApiInstance->pProcessContext; WriteBurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* Test what the user has specified is the maximum that can be used for a burst. */ WriteBurstParams.ulWriteLength = pSharedInfo->ChipConfig.usMaxRwAccesses; WriteBurstParams.pusWriteData = pSharedInfo->MiscVars.ausSuperArray; WriteSmearParams.pProcessContext = f_pApiInstance->pProcessContext; WriteSmearParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* Test what the user has specified is the maximum that can be used for a smear. */ WriteSmearParams.ulWriteLength = pSharedInfo->ChipConfig.usMaxRwAccesses; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; ReadBurstParams.pProcessContext = f_pApiInstance->pProcessContext; ReadBurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* Test what the user has specified is the maximum that can be used for a burst. */ ReadBurstParams.ulReadLength = pSharedInfo->ChipConfig.usMaxRwAccesses; ReadBurstParams.pusReadData = pSharedInfo->MiscVars.ausSuperArray; /*======================================================================*/ /* Write burst check. */ WriteBurstParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS; /* Set the random data to be written. */ for ( i = 0; i < WriteBurstParams.ulWriteLength; i++ ) { WriteBurstParams.pusWriteData[ i ] = Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ); } mOCT6100_DRIVER_WRITE_BURST_API( WriteBurstParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Read back pattern using simple read function and make sure we are reading what's expected. */ ReadParams.ulReadAddress = WriteBurstParams.ulWriteAddress; for ( i = 0; i < WriteBurstParams.ulWriteLength; i++ ) { mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check if the data matches. */ if ( usReadData != WriteBurstParams.pusWriteData[ i ] ) { /* The values do not match. Something seems to be wrong with the WriteBurst user function. */ return cOCT6100_ERR_OPEN_USER_WRITE_BURST_FAILED; } /* Next address to check. */ ReadParams.ulReadAddress += 2; } /*======================================================================*/ /*======================================================================*/ /* Write smear check. */ WriteSmearParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + ( WriteBurstParams.ulWriteLength * 2 ); /* Set the random data to be written. */ WriteSmearParams.usWriteData = Oct6100ApiGenerateNumber( f_pApiInstance, Oct6100ApiRand( 0xFFFF ), 0xFFFF ); mOCT6100_DRIVER_WRITE_SMEAR_API( WriteSmearParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Read back pattern using simple read function and make sure we are reading what's expected. */ ReadParams.ulReadAddress = WriteSmearParams.ulWriteAddress; for ( i = 0; i < WriteSmearParams.ulWriteLength; i++ ) { mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check if the data matches. */ if ( usReadData != WriteSmearParams.usWriteData ) { /* The values do not match. Something seems to be wrong with the WriteSmear user function. */ return cOCT6100_ERR_OPEN_USER_WRITE_SMEAR_FAILED; } /* Next address to check. */ ReadParams.ulReadAddress += 2; } /*======================================================================*/ /*======================================================================*/ /* Read burst check. */ /* First check with what the WriteBurst function wrote. */ ReadBurstParams.ulReadAddress = WriteBurstParams.ulWriteAddress; mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; for ( i = 0; i < ReadBurstParams.ulReadLength; i++ ) { /* Check if the data matches. */ if ( ReadBurstParams.pusReadData[ i ] != Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ) ) { /* The values do not match. Something seems to be wrong with the ReadBurst user function. */ return cOCT6100_ERR_OPEN_USER_READ_BURST_FAILED; } } /* Then check with what the WriteSmear function wrote. */ ReadBurstParams.ulReadAddress = WriteSmearParams.ulWriteAddress; mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; for ( i = 0; i < ReadBurstParams.ulReadLength; i++ ) { /* Check if the data matches. */ if ( ReadBurstParams.pusReadData[ i ] != WriteSmearParams.usWriteData ) { /* The values do not match. Something seems to be wrong with the ReadBurst user function. */ return cOCT6100_ERR_OPEN_USER_READ_BURST_FAILED; } } /*======================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiExternalMemoryInit Description: Initialize the external memory before uploading the image. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiExternalMemoryInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_WRITE_SMEAR_PARAMS SmearParams; UINT32 ulTotalWordToWrite; UINT32 ulResult; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; SmearParams.pProcessContext = f_pApiInstance->pProcessContext; SmearParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* Clear the first part of the memory. */ ulTotalWordToWrite = 0x400; SmearParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS; while ( ulTotalWordToWrite != 0 ) { if ( ulTotalWordToWrite >= pSharedInfo->ChipConfig.usMaxRwAccesses ) SmearParams.ulWriteLength = pSharedInfo->ChipConfig.usMaxRwAccesses; else SmearParams.ulWriteLength = ulTotalWordToWrite; SmearParams.usWriteData = 0x0; mOCT6100_DRIVER_WRITE_SMEAR_API( SmearParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Update the number of words to write. */ ulTotalWordToWrite -= SmearParams.ulWriteLength; /* Update the address. */ SmearParams.ulWriteAddress += ( SmearParams.ulWriteLength * 2 ); } /* Clear the TLV flag.*/ ulResult = Oct6100ApiWriteDword( f_pApiInstance, cOCT6100_TLV_BASE, 0x0 ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiInitMixer Description: This function will initialize the mixer memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiInitMixer( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_WRITE_BURST_PARAMS BurstParams; UINT16 ausWriteData[ 4 ]; UINT32 ulResult; pSharedInfo = f_pApiInstance->pSharedInfo; BurstParams.pProcessContext = f_pApiInstance->pProcessContext; BurstParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; BurstParams.pusWriteData = ausWriteData; /*======================================================================*/ /* Initialize the mixer memory if required. */ if ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) { /* Modify the mixer pointer by adding the record event into the link list. */ pSharedInfo->MixerInfo.usFirstSinCopyEventPtr = pSharedInfo->MixerInfo.usRecordSinEventIndex; pSharedInfo->MixerInfo.usLastSinCopyEventPtr = pSharedInfo->MixerInfo.usRecordSinEventIndex; pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr = pSharedInfo->MixerInfo.usRecordCopyEventIndex; pSharedInfo->MixerInfo.usLastSoutCopyEventPtr = pSharedInfo->MixerInfo.usRecordCopyEventIndex; /* Program the Sin copy event. */ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSharedInfo->MixerInfo.usRecordSinEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); BurstParams.ulWriteLength = 4; ausWriteData[ 0 ] = 0x0000; ausWriteData[ 1 ] = 0x0000; ausWriteData[ 2 ] = (UINT16)(cOCT6100_MIXER_TAIL_NODE & 0x7FF); /* Head node.*/ ausWriteData[ 3 ] = 0x0000; mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Program the Sout copy event. */ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSharedInfo->MixerInfo.usRecordCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); BurstParams.ulWriteLength = 4; ausWriteData[ 0 ] = 0x0000; ausWriteData[ 1 ] = 0x0000; ausWriteData[ 2 ] = (UINT16)(pSharedInfo->MixerInfo.usRecordSinEventIndex & 0x7FF); ausWriteData[ 3 ] = 0x0000; mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Configure the head node. */ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE; BurstParams.ulWriteLength = 4; ausWriteData[ 0 ] = 0x0000; ausWriteData[ 1 ] = 0x0000; ausWriteData[ 2 ] = (UINT16)(pSharedInfo->MixerInfo.usRecordCopyEventIndex & 0x7FF); ausWriteData[ 3 ] = 0x0000; mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Init the mixer pointer */ pSharedInfo->MixerInfo.usFirstSinCopyEventPtr = pSharedInfo->MixerInfo.usRecordSinEventIndex; } else { /* Configure the head node. */ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE; BurstParams.ulWriteLength = 4; ausWriteData[ 0 ] = 0x0000; ausWriteData[ 1 ] = 0x0000; ausWriteData[ 2 ] = (UINT16)(cOCT6100_MIXER_TAIL_NODE & 0x7FF); /* Head node. */ ausWriteData[ 3 ] = 0x0000; mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Configure the tail node. */ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + 0x10; BurstParams.ulWriteLength = 4; ausWriteData[ 0 ] = 0x0000; ausWriteData[ 1 ] = 0x0000; ausWriteData[ 2 ] = (UINT16)(cOCT6100_MIXER_HEAD_NODE & 0x7FF); /* Head node. */ ausWriteData[ 3 ] = 0x0000; mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiInitRecordResources Description: This function will initialize the resources required to perform recording on a debug channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiInitRecordResources( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; UINT32 ulResult; pSharedInfo = f_pApiInstance->pSharedInfo; /* Check if recording is enabled. */ if ( pSharedInfo->ChipConfig.fEnableChannelRecording == FALSE ) return cOCT6100_ERR_OK; if ( pSharedInfo->DebugInfo.usRecordMemIndex == cOCT6100_INVALID_INDEX ) return cOCT6100_ERR_NOT_SUPPORTED_OPEN_DEBUG_RECORD; /* Check the provided recording memory index within the SSPX. */ if ( pSharedInfo->DebugInfo.usRecordMemIndex != ( pSharedInfo->ImageInfo.usMaxNumberOfChannels - 1 ) ) return cOCT6100_ERR_OPEN_DEBUG_MEM_INDEX; /* Reserve the TSI entries for the channel. */ ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, &pSharedInfo->DebugInfo.usRecordRinRoutTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, &pSharedInfo->DebugInfo.usRecordSinSoutTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Open the debug channel. */ ulResult = Oct6100ApiDebugChannelOpen( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiProductionCrc Description: This function calculates the crc for a production BIST message. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pulMessage Message to be exchanged with the firmware. The CRC will be calculated on this. f_ulMessageLength Length of the message to be exchanged. This value does not include the CRC value at the end f_pulCrcResult Resulting calculated CRC value. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiProductionCrc( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN PUINT32 f_pulMessage, IN UINT32 f_ulMessageLength, OUT PUINT32 f_pulCrcResult ) { UINT32 ulWidth = 32; UINT32 ulKey, i, j; UINT32 ulRemainder = 0; /* CRC the message. */ ulRemainder = f_pulMessage[ f_ulMessageLength - 1 ]; for ( j = f_ulMessageLength - 1; j != 0xFFFFFFFF ; j-- ) { for ( i = 0; i < ulWidth; i++ ) { if ( ( ( ulRemainder >> 0x1F ) & 0x1 ) == 0x1 ) { /* Division is by something meaningful */ ulKey = 0x8765DCBA; } else { /* Remainder is less than our divisor */ ulKey = 0; } ulRemainder = ulRemainder ^ ulKey; ulRemainder = ulRemainder << 1; if ( j != 0 ) { ulRemainder = ulRemainder | ( ( f_pulMessage[ j - 1 ] ) >> ( 0x1F - i ) ); } } } *f_pulCrcResult = ulRemainder; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_mixer.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains the functions used to manage the allocation of mixer blocks in memories. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 42 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "apilib/octapi_llman.h" #include "oct6100api/oct6100_apiud.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_channel_inst.h" #include "oct6100api/oct6100_mixer_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_mixer_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_channel_priv.h" #include "oct6100_mixer_priv.h" /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetMixerSwSizes Description: Gets the sizes of all portions of the API instance pertinent to the management of mixer events. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pOpenChip User chip configuration. f_pInstSizes Pointer to struct containing instance sizes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiGetMixerSwSizes( IN tPOCT6100_CHIP_OPEN f_pOpenChip, OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) { UINT32 ulTempVar; UINT32 ulResult; /* Calculate the API memory required for the resource entry lists. */ f_pInstSizes->ulMixerEventList = cOCT6100_MAX_MIXER_EVENTS * sizeof( tOCT6100_API_MIXER_EVENT ); /* Calculate memory needed for mixers entry allocation. */ ulResult = OctapiLlmAllocGetSize( cOCT6100_MAX_MIXER_EVENTS, &f_pInstSizes->ulMixerEventAlloc ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_1D; mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulMixerEventList, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulMixerEventAlloc, ulTempVar ) f_pInstSizes->ulCopyEventList = cOCT6100_MAX_MIXER_EVENTS * sizeof( tOCT6100_API_COPY_EVENT ); ulResult = OctapiLlmAllocGetSize( cOCT6100_MAX_MIXER_EVENTS, &f_pInstSizes->ulCopyEventAlloc ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_1D; mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulCopyEventList, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulCopyEventAlloc, ulTempVar ) return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReserveMixerEventEntry Description: Reserves a free entry in the mixer event list. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pusEventIndex List entry reserved. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReserveMixerEventEntry( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, OUT PUINT16 f_pusEventIndex ) { PVOID pMixerEventAlloc; UINT32 ulResult; UINT32 ulEventIndex; mOCT6100_GET_MIXER_EVENT_ALLOC_PNT( f_pApiInstance->pSharedInfo, pMixerEventAlloc ) ulResult = OctapiLlmAllocAlloc( pMixerEventAlloc, &ulEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) { if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) return cOCT6100_ERR_MIXER_ALL_MIXER_EVENT_ENTRY_OPENED; else return cOCT6100_ERR_FATAL_2B; } *f_pusEventIndex = (UINT16)( ulEventIndex & 0xFFFF ); return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiMixerSwInit Description: Initializes all elements of the instance structure associated to the mixer events. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This mixer is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiMixerSwInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_MIXER_EVENT pMixerEventList; PVOID pMixerEventAlloc; PVOID pCopyEventAlloc; UINT32 ulTempVar; UINT32 ulResult; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; /*===================================================================*/ /* Initialize the mixer event list. */ mOCT6100_GET_MIXER_EVENT_LIST_PNT( pSharedInfo, pMixerEventList ); /* Initialize the mixer event allocation software to "all free". */ Oct6100UserMemSet( pMixerEventList, 0x00, cOCT6100_MAX_MIXER_EVENTS * sizeof( tOCT6100_API_MIXER_EVENT )); mOCT6100_GET_MIXER_EVENT_ALLOC_PNT( pSharedInfo, pMixerEventAlloc ) ulResult = OctapiLlmAllocInit( &pMixerEventAlloc, cOCT6100_MAX_MIXER_EVENTS ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_1F; /* Now reserve the first entry as the first node. */ ulResult = OctapiLlmAllocAlloc( pMixerEventAlloc, &ulTempVar ); if ( ulResult != cOCT6100_ERR_OK ) { return cOCT6100_ERR_FATAL_20; } /* Check that we obtain the first event. */ if ( ulTempVar != 0 ) return cOCT6100_ERR_FATAL_21; /* Now reserve the tail entry. */ ulResult = OctapiLlmAllocAlloc( pMixerEventAlloc, &ulTempVar ); if ( ulResult != cOCT6100_ERR_OK ) { return cOCT6100_ERR_FATAL_AA; } /* Check that we obtain the first event. */ if ( ulTempVar != 1 ) return cOCT6100_ERR_FATAL_AB; /* Program the head node. */ pMixerEventList[ cOCT6100_MIXER_HEAD_NODE ].fReserved = TRUE; pMixerEventList[ cOCT6100_MIXER_HEAD_NODE ].usNextEventPtr = cOCT6100_MIXER_TAIL_NODE; pMixerEventList[ cOCT6100_MIXER_HEAD_NODE ].usEventType = cOCT6100_MIXER_CONTROL_MEM_NO_OP; /* Program the tail node. */ pMixerEventList[ cOCT6100_MIXER_TAIL_NODE ].fReserved = TRUE; pMixerEventList[ cOCT6100_MIXER_TAIL_NODE ].usNextEventPtr = cOCT6100_INVALID_INDEX; pMixerEventList[ cOCT6100_MIXER_TAIL_NODE ].usEventType = cOCT6100_MIXER_CONTROL_MEM_NO_OP; /* Now reserve the entry used for channel recording if the feature is enabled. */ if ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) { UINT32 ulAllocIndex; /* Reserve an entry to copy the desire SOUT signal to the SIN signal of the recording channel. */ ulResult = OctapiLlmAllocAlloc( pMixerEventAlloc, &ulAllocIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return cOCT6100_ERR_FATAL_90; } pSharedInfo->MixerInfo.usRecordCopyEventIndex = (UINT16)( ulAllocIndex & 0xFFFF ); /* Reserve an entry to copy the saved SIN signal of the debugged channel into it's original location. */ ulResult = OctapiLlmAllocAlloc( pMixerEventAlloc, &ulAllocIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return cOCT6100_ERR_FATAL_90; } pSharedInfo->MixerInfo.usRecordSinEventIndex = (UINT16)( ulAllocIndex & 0xFFFF ); /* Configure the SIN event. */ pMixerEventList[ pSharedInfo->MixerInfo.usRecordSinEventIndex ].fReserved = TRUE; pMixerEventList[ pSharedInfo->MixerInfo.usRecordSinEventIndex ].usNextEventPtr = cOCT6100_MIXER_TAIL_NODE; pMixerEventList[ pSharedInfo->MixerInfo.usRecordSinEventIndex ].usEventType = cOCT6100_MIXER_CONTROL_MEM_NO_OP; /* Configure the SOUT copy event. */ pMixerEventList[ pSharedInfo->MixerInfo.usRecordCopyEventIndex ].fReserved = TRUE; pMixerEventList[ pSharedInfo->MixerInfo.usRecordCopyEventIndex ].usNextEventPtr = pSharedInfo->MixerInfo.usRecordSinEventIndex; pMixerEventList[ pSharedInfo->MixerInfo.usRecordCopyEventIndex ].usEventType = cOCT6100_MIXER_CONTROL_MEM_NO_OP; /* Program the head node. */ pMixerEventList[ cOCT6100_MIXER_HEAD_NODE ].usNextEventPtr = pSharedInfo->MixerInfo.usRecordCopyEventIndex; } /* Initialize the copy event list. */ mOCT6100_GET_COPY_EVENT_ALLOC_PNT( pSharedInfo, pCopyEventAlloc ) ulResult = OctapiLlmAllocInit( &pCopyEventAlloc, cOCT6100_MAX_MIXER_EVENTS ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_B4; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiMixerEventAdd Description: This function adds a mixer event event to the list of events based on the event type passed to the function. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usEventIndex Index of the event within the API's mixer event list. f_usEventType Type of mixer event. f_usDestinationChanIndex Index of the destination channel within the API's channel list. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiMixerEventAdd( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usEventIndex, IN UINT16 f_usEventType, IN UINT16 f_usDestinationChanIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_MIXER_EVENT pCurrentEventEntry; tPOCT6100_API_MIXER_EVENT pTempEventEntry; tPOCT6100_API_CHANNEL pDestinationEntry; tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; UINT16 usTempEventIndex; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* Get a pointer to the event entry. */ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCurrentEventEntry, f_usEventIndex ); /* Get a pointer to the destination channel entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pDestinationEntry, f_usDestinationChanIndex ); /* Now proceed according to the event type. */ switch ( f_usEventType ) { case cOCT6100_EVENT_TYPE_SOUT_COPY: /* Now insert the Sin copy event */ if ( pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) { /* The only node in the list before the point where the node needs to */ /* be inserted is the head node. */ usTempEventIndex = cOCT6100_MIXER_HEAD_NODE; /* This node will be the first one in the Sout copy section. */ pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr = f_usEventIndex; pSharedInfo->MixerInfo.usLastSoutCopyEventPtr = f_usEventIndex; } else /* pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr != cOCT6100_INVALID_INDEX */ { usTempEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; pSharedInfo->MixerInfo.usLastSoutCopyEventPtr = f_usEventIndex; } break; case cOCT6100_EVENT_TYPE_SIN_COPY: /* Now insert the Sin copy event. */ if ( pSharedInfo->MixerInfo.usFirstSinCopyEventPtr == cOCT6100_INVALID_INDEX ) { /* This is the first Sin copy event. We must find the event that comes before */ /* the event we want to add. First let's check for a bridge event. */ if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == cOCT6100_INVALID_INDEX ) { /* No event in the bridge section, now let's check in the Sout copy section. */ if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) { /* The only node in the list then is the head node. */ usTempEventIndex = cOCT6100_MIXER_HEAD_NODE; } else { usTempEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; } } else { usTempEventIndex = pSharedInfo->MixerInfo.usLastBridgeEventPtr; } /* This node will be the first one in the Sin copy section. */ pSharedInfo->MixerInfo.usFirstSinCopyEventPtr = f_usEventIndex; pSharedInfo->MixerInfo.usLastSinCopyEventPtr = f_usEventIndex; } else /* pSharedInfo->MixerInfo.usFirstSinCopyEventPtr != cOCT6100_INVALID_INDEX */ { usTempEventIndex = pSharedInfo->MixerInfo.usLastSinCopyEventPtr; pSharedInfo->MixerInfo.usLastSinCopyEventPtr = f_usEventIndex; } break; default: return cOCT6100_ERR_FATAL_AF; } mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, usTempEventIndex ); /*=======================================================================*/ /* Program the Copy event. */ /* Set the Copy event first. */ pCurrentEventEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_COPY; pCurrentEventEntry->usNextEventPtr = pTempEventEntry->usNextEventPtr; WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.ulWriteAddress += 4; WriteParams.usWriteData = pCurrentEventEntry->usNextEventPtr; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* Modify the previous node. */ /* Set the last Sub-store entry. */ pTempEventEntry->usNextEventPtr = f_usEventIndex; WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usTempEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.ulWriteAddress += 4; WriteParams.usWriteData = f_usEventIndex; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /* Save the destination channel index, needed when removing the event from the mixer. */ pCurrentEventEntry->usDestinationChanIndex = f_usDestinationChanIndex; /* Mark the entry as reserved. */ pCurrentEventEntry->fReserved = TRUE; /* Increment the event count on that particular destination channel */ pDestinationEntry->usMixerEventCnt++; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiMixerEventRemove Description: This function removes a mixer event event from the list of events based on the event type passed to the function. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usEventIndex Index of event within the API's mixer event list. f_usEventType Type of mixer event. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiMixerEventRemove( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usEventIndex, IN UINT16 f_usEventType ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_MIXER_EVENT pCurrentEventEntry; tPOCT6100_API_MIXER_EVENT pTempEventEntry; tPOCT6100_API_CHANNEL pDestinationEntry; tOCT6100_WRITE_BURST_PARAMS BurstWriteParams; tOCT6100_WRITE_PARAMS WriteParams; BOOL fFirstSinCopyEvent = FALSE; UINT32 ulResult; UINT16 usTempEventIndex; UINT32 ulLoopCount = 0; UINT16 ausWriteData[ 4 ] = { 0 }; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; BurstWriteParams.pProcessContext = f_pApiInstance->pProcessContext; BurstWriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; BurstWriteParams.pusWriteData = ausWriteData; BurstWriteParams.ulWriteLength = 4; /* Get a pointer to the event entry. */ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCurrentEventEntry, f_usEventIndex ); /* Get the pointer to the channel entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pDestinationEntry, pCurrentEventEntry->usDestinationChanIndex ); /* Now proceed according to the event type. */ switch ( f_usEventType ) { case cOCT6100_EVENT_TYPE_SOUT_COPY: if ( f_usEventIndex == pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr ) { usTempEventIndex = cOCT6100_MIXER_HEAD_NODE; } else { /* Now insert the Sin copy event. */ usTempEventIndex = pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr; } /* Find the copy entry before the entry to remove. */ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, usTempEventIndex ); while( pTempEventEntry->usNextEventPtr != f_usEventIndex ) { usTempEventIndex = pTempEventEntry->usNextEventPtr; mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, usTempEventIndex ); ulLoopCount++; if ( ulLoopCount == cOCT6100_MAX_LOOP ) return cOCT6100_ERR_FATAL_B2; } /*=======================================================================*/ /* Update the global mixer pointers. */ if ( f_usEventIndex == pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr ) { if ( f_usEventIndex == pSharedInfo->MixerInfo.usLastSoutCopyEventPtr ) { /* This event was the only of the list.*/ pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr = cOCT6100_INVALID_INDEX; pSharedInfo->MixerInfo.usLastSoutCopyEventPtr = cOCT6100_INVALID_INDEX; } else { pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr = pCurrentEventEntry->usNextEventPtr; } } else if ( f_usEventIndex == pSharedInfo->MixerInfo.usLastSoutCopyEventPtr ) { pSharedInfo->MixerInfo.usLastSoutCopyEventPtr = usTempEventIndex; } /*=======================================================================*/ break; case cOCT6100_EVENT_TYPE_SIN_COPY: if ( f_usEventIndex == pSharedInfo->MixerInfo.usFirstSinCopyEventPtr ) { fFirstSinCopyEvent = TRUE; if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr != cOCT6100_INVALID_INDEX ) { usTempEventIndex = pSharedInfo->MixerInfo.usLastBridgeEventPtr; } else if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr != cOCT6100_INVALID_INDEX ) { usTempEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; } else { usTempEventIndex = cOCT6100_MIXER_HEAD_NODE; } } else { /* Now insert the Sin copy event. */ usTempEventIndex = pSharedInfo->MixerInfo.usFirstSinCopyEventPtr; } /* Find the copy entry before the entry to remove. */ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, usTempEventIndex ); /* If we are not the first event of the Sin copy list. */ if ( fFirstSinCopyEvent == FALSE ) { while( pTempEventEntry->usNextEventPtr != f_usEventIndex ) { usTempEventIndex = pTempEventEntry->usNextEventPtr; mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEventEntry, usTempEventIndex ); ulLoopCount++; if ( ulLoopCount == cOCT6100_MAX_LOOP ) return cOCT6100_ERR_FATAL_B1; } } /*=======================================================================*/ /* Update the global mixer pointers. */ if ( f_usEventIndex == pSharedInfo->MixerInfo.usFirstSinCopyEventPtr ) { if ( f_usEventIndex == pSharedInfo->MixerInfo.usLastSinCopyEventPtr ) { /* This event was the only of the list. */ pSharedInfo->MixerInfo.usFirstSinCopyEventPtr = cOCT6100_INVALID_INDEX; pSharedInfo->MixerInfo.usLastSinCopyEventPtr = cOCT6100_INVALID_INDEX; } else { pSharedInfo->MixerInfo.usFirstSinCopyEventPtr = pCurrentEventEntry->usNextEventPtr; } } else if ( f_usEventIndex == pSharedInfo->MixerInfo.usLastSinCopyEventPtr ) { pSharedInfo->MixerInfo.usLastSinCopyEventPtr = usTempEventIndex; } /*=======================================================================*/ break; default: return cOCT6100_ERR_FATAL_B0; } /*=======================================================================*/ /* Modify the previous event. */ pTempEventEntry->usNextEventPtr = pCurrentEventEntry->usNextEventPtr; WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usTempEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.ulWriteAddress += 4; WriteParams.usWriteData = pTempEventEntry->usNextEventPtr; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* Clear the current event. */ BurstWriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); mOCT6100_DRIVER_WRITE_BURST_API( BurstWriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* Decrement the mixer event count active on that channel. */ pDestinationEntry->usMixerEventCnt--; /*=======================================================================*/ /*=======================================================================*/ /* This index of this channel is not valid anymore! */ pCurrentEventEntry->usDestinationChanIndex = cOCT6100_INVALID_INDEX; /* Mark this entry as free. */ pCurrentEventEntry->fReserved = FALSE; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetFreeMixerEventCnt Description: Retrieve the number of events left in the list. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pulFreeEventCnt How many events left. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiGetFreeMixerEventCnt( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, OUT PUINT32 f_pulFreeEventCnt ) { PVOID pMixerEventAlloc; UINT32 ulResult; UINT32 ulAllocatedEvents; UINT32 ulAvailableEvents; mOCT6100_GET_MIXER_EVENT_ALLOC_PNT( f_pApiInstance->pSharedInfo, pMixerEventAlloc ) ulResult = OctapiLlmAllocInfo( pMixerEventAlloc, &ulAllocatedEvents, &ulAvailableEvents ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_E8; /* Return number of free events. */ *f_pulFreeEventCnt = ulAvailableEvents; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteDword Description: Write a DWORD at specified address in external memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulAddress DWORD address where to write. f_ulWriteData DWORD data to write. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWriteDword( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulAddress, IN UINT32 f_ulWriteData ) { tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; /* Write the first 16 bits. */ WriteParams.ulWriteAddress = f_ulAddress; WriteParams.usWriteData = (UINT16)((f_ulWriteData >> 16) & 0xFFFF); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write the last word. */ WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)(f_ulWriteData & 0xFFFF); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReleaseTsiMemEntry Description: Releases a TSI chariot memory entry specified. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usTsiMemIndex Index reserved in the TSI chariot memory. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReleaseTsiMemEntry( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usTsiMemIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; PVOID pTsiMemAlloc; UINT32 ulResult; UINT32 ulIndex; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Check if the entry programmed is greater then the timestamp entries. */ if ( f_usTsiMemIndex > cOCT6100_TSST_CONTROL_TIMESTAMP_BASE_ENTRY ) ulIndex = f_usTsiMemIndex - cOCT6100_TSI_MEM_FOR_TIMESTAMP; else ulIndex = f_usTsiMemIndex; /* Check if the entry programmed is greater then the phasing TSST entries. */ if ( ulIndex > cOCT6100_TSST_CONTROL_PHASING_TSST_BASE_ENTRY ) ulIndex -= pSharedInfo->ChipConfig.usMaxPhasingTssts; mOCT6100_GET_TSI_MEMORY_ALLOC_PNT( pSharedInfo, pTsiMemAlloc ) ulResult = OctapiLlmAllocDealloc( pTsiMemAlloc, ulIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return cOCT6100_ERR_FATAL_93; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReleaseMixerEventEntry Description: Release an entry from the mixer event list. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usEventIndex List entry reserved. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReleaseMixerEventEntry( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usEventIndex ) { PVOID pMixerEventAlloc; UINT32 ulResult; mOCT6100_GET_MIXER_EVENT_ALLOC_PNT( f_pApiInstance->pSharedInfo, pMixerEventAlloc ) ulResult = OctapiLlmAllocDealloc( pMixerEventAlloc, f_usEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_2C; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWaitForPcRegisterBit Description: Polls the specified PC register bit. The function exits once the bit is cleared by hardware, or when the specified timeout period has been expired. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulPcRegAdd Address of the register containing the PC bit. f_ulPcBitNum Number of the PC bit within the register. f_ulValue Expected value of the bit. f_ulTimeoutUs The timeout period, in usec. f_pfBitEqual Pointer to the result of the bit comparison. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWaitForPcRegisterBit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulPcRegAdd, IN UINT32 f_ulPcBitNum, IN UINT32 f_ulValue, IN UINT32 f_ulTimeoutUs, OUT PBOOL f_pfBitEqual ) { tOCT6100_READ_PARAMS ReadParams; tOCT6100_GET_TIME StartTime; tOCT6100_GET_TIME TimeoutTime; tOCT6100_GET_TIME CurrentTime; UINT32 ulResult; UINT16 usReadData; BOOL fConditionFlag = TRUE; /* Copy the process context. */ StartTime.pProcessContext = f_pApiInstance->pProcessContext; CurrentTime.pProcessContext = f_pApiInstance->pProcessContext; /* Get the current system time. */ ulResult = Oct6100UserGetTime( &StartTime ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Mark the bit as not being equal, for now. */ *f_pfBitEqual = FALSE; /* Determine the time at which the timeout has expired. */ ulResult = octapi_lm_add( StartTime.aulWallTimeUs, 1, &f_ulTimeoutUs, 0, TimeoutTime.aulWallTimeUs, 1 ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Prepare read structure. */ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ReadParams.ulReadAddress = f_ulPcRegAdd; ReadParams.pusReadData = &usReadData; /* Read the PC bit while the timeout period hasn't expired. */ while ( fConditionFlag ) { /* Read the current time again to check for timeout. */ ulResult = Oct6100UserGetTime( &CurrentTime ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100UserDriverReadApi( &ReadParams ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( ( UINT16 )((usReadData >> f_ulPcBitNum) & 0x1) == ( UINT16 )f_ulValue ) { /* Mark the bit as being equal. */ *f_pfBitEqual = TRUE; fConditionFlag = FALSE; } if ( CurrentTime.aulWallTimeUs[ 1 ] > TimeoutTime.aulWallTimeUs[ 1 ] || (CurrentTime.aulWallTimeUs[ 1 ] == TimeoutTime.aulWallTimeUs[ 1 ] && CurrentTime.aulWallTimeUs[ 0 ] >= TimeoutTime.aulWallTimeUs[ 0 ]) ) fConditionFlag = FALSE; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReleaseConversionMemEntry Description: Releases the conversion chariot memory entry specified. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usConversionMemIndex Index reserved in the conversion chariot memory. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReleaseConversionMemEntry( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usConversionMemIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; PVOID pConversionMemAlloc; UINT32 ulResult; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; mOCT6100_GET_CONVERSION_MEMORY_ALLOC_PNT( pSharedInfo, pConversionMemAlloc ) ulResult = OctapiLlmAllocDealloc( pConversionMemAlloc, f_usConversionMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return cOCT6100_ERR_FATAL_B7; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReadDword Description: Read a DWORD at specified address in external memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulAddress DWORD address where to read. f_pulReadData Resulting data. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReadDword( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulAddress, OUT PUINT32 f_pulReadData ) { tOCT6100_READ_PARAMS ReadParams; UINT16 usReadData; UINT32 ulResult; UINT32 ulTempData; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; /*==================================================================================*/ /* Read the first 16 bits. */ ReadParams.ulReadAddress = f_ulAddress; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulTempData = usReadData << 16; /* Read the last 16 bits. */ ReadParams.ulReadAddress += 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulTempData |= usReadData; /*==================================================================================*/ /* Return the read value.*/ *f_pulReadData = ulTempData; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100BufferPlayoutStop Description: This function disables playout of a buffer on the specified channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pBufferPlayoutStop Pointer to buffer playout stop structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100BufferPlayoutStopDef( tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop ) { f_pBufferPlayoutStop->ulChannelHndl = cOCT6100_INVALID_HANDLE; f_pBufferPlayoutStop->ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; f_pBufferPlayoutStop->fStopCleanly = TRUE; f_pBufferPlayoutStop->pfAlreadyStopped = NULL; f_pBufferPlayoutStop->pfNotifyOnPlayoutStop = NULL; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWaitForTime Description: Waits for the specified amount of time. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_aulWaitTime[ 2 ] The amout of time to be waited. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWaitForTime( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_aulWaitTime[ 2 ] ) { tOCT6100_GET_TIME StartTime; tOCT6100_GET_TIME CurrentTime; UINT32 aulTimeDelta[ 2 ]; UINT32 ulResult; UINT16 usTempVar; BOOL fConditionFlag = TRUE; /* Copy the process context. */ StartTime.pProcessContext = f_pApiInstance->pProcessContext; CurrentTime.pProcessContext = f_pApiInstance->pProcessContext; ulResult = Oct6100UserGetTime( &StartTime ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; while ( fConditionFlag ) { ulResult = Oct6100UserGetTime( &CurrentTime ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = octapi_lm_subtract( CurrentTime.aulWallTimeUs, 1, StartTime.aulWallTimeUs, 1, aulTimeDelta, 1, &usTempVar ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_37; if ( aulTimeDelta[ 1 ] >= f_aulWaitTime[ 1 ] && aulTimeDelta[ 0 ] >= f_aulWaitTime[ 0 ] ) fConditionFlag = FALSE; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReserveTsiMemEntry Description: Reserves a TSI chariot memory entry. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pusTsiMemIndex Resulting index reserved in the TSI chariot memory. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReserveTsiMemEntry( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, OUT PUINT16 f_pusTsiMemIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; PVOID pTsiMemAlloc; UINT32 ulResult; UINT32 ulIndex; UINT32 ulNumTsiB4Timestamp; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; mOCT6100_GET_TSI_MEMORY_ALLOC_PNT( pSharedInfo, pTsiMemAlloc ) ulResult = OctapiLlmAllocAlloc( pTsiMemAlloc, &ulIndex ); if ( ulResult != cOCT6100_ERR_OK ) { if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) return cOCT6100_ERR_MEMORY_ALL_TSI_MEM_ENTRY_RESERVED; else return cOCT6100_ERR_FATAL_92; } if ( ulIndex >= cOCT6100_NUM_TSI_B4_PHASING ) { /* Evaluate the number of TSI memory before the timestamp TSI. */ ulNumTsiB4Timestamp = cOCT6100_NUM_TSI_B4_PHASING + cOCT6100_MAX_TSI_B4_TIMESTAMP - pSharedInfo->ChipConfig.usMaxPhasingTssts; if ( ulIndex >= ulNumTsiB4Timestamp ) { /* + 4 for the timestamp TSI entries.*/ *f_pusTsiMemIndex = (UINT16)( pSharedInfo->ChipConfig.usMaxPhasingTssts + ulIndex + cOCT6100_TSI_MEM_FOR_TIMESTAMP ); } else /* ulIndex < ulNumTsiB4Timestamp */ { *f_pusTsiMemIndex = (UINT16)( pSharedInfo->ChipConfig.usMaxPhasingTssts + ulIndex ); } } else /* ulIndex < ulNumTsiB4Timestamp */ { *f_pusTsiMemIndex = (UINT16)( ulIndex ); } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReserveConversionMemEntry Description: Reserves one of the conversion memory entry ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pusConversionMemIndex Resulting index reserved in the conversion memory. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReserveConversionMemEntry( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, OUT PUINT16 f_pusConversionMemIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; PVOID pConversionMemAlloc; UINT32 ulConversionMemIndex; UINT32 ulResult; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; mOCT6100_GET_CONVERSION_MEMORY_ALLOC_PNT( pSharedInfo, pConversionMemAlloc ) ulResult = OctapiLlmAllocAlloc( pConversionMemAlloc, &ulConversionMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) { if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) return cOCT6100_ERR_MEMORY_ALL_CONVERSION_MEM_ENTRY_RESERVED; else return cOCT6100_ERR_FATAL_B8; } *f_pusConversionMemIndex = (UINT16)( ulConversionMemIndex & 0xFFFF ); return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ConfBridgeClose Description: This function closes a conference bridge. A conference bridge can only be closed if no participants are present on the bridge. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pConfBridgeClose Pointer to conference bridge close structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ConfBridgeCloseDef( tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose ) { f_pConfBridgeClose->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE; return cOCT6100_ERR_OK; } #include "apilib/octapi_largmath.h" /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ | API UTILITIES | | Function: OctApiLmSubtract. | | Description: This function subtracts 2 numbers, a and b. Number a is | (alen + 1) * 32 bits long; b is (blen + 1) * 32 bits long. The result | is (zlen + 1) * 32 bits long. It the function succeeds it returns | GENERIC_OK, else GENERIC_ERROR. | | ----------------------------------------------------------------------- | | Variable | Type | Description | ----------------------------------------------------------------------- | *a UINT32 The array containing the first number. | alen USHORT The length of array a, minus 1 (0 - 99). | *bneg UINT32 The array containing the second number. | blen USHORT The length of array b, minus 1 (0 - 99). | *z UINT32 The array containing the resulting number. | zlen USHORT The length of array z, minus 1 (0 - 99). | *neg USHORT Indicates if the result is negative | (TRUE/FALSE). | \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 OctApiLmSubtract(UINT32 * a,USHORT alen,UINT32 * bneg,USHORT blen,UINT32 * z,USHORT zlen,USHORT * neg) { USHORT i; UINT32 temp; UINT32 carry=1; UINT32 aprim; UINT32 bprim; /* Check for array lengths.*/ if (alen > zlen || blen > zlen) return(OCTAPI_LM_ARRAY_SIZE_MISMATCH); for(i=0;i<=zlen;i++) { if (i <= alen) aprim = *(a+i); else aprim = 0; if (i <= blen) bprim = ~(*(bneg+i)); else bprim = 0xFFFFFFFF; temp = aprim + bprim + carry; /* Calculate carry for next time.*/ if (carry == 0) if (temp < aprim) carry = 1; else carry = 0; else if (temp <= aprim) carry = 1; else carry = 0; /* Write new value.*/ *(z+i) = temp; } /* Check for overflow, which means negative number!*/ if (carry == 0) { /* Number is not of right neg. Invert and add one to correct neg.*/ for(i=0;i<=zlen;i++) *(z+i) = ~(*(z+i)); temp = 1; OctApiLmAdd(&temp,0,z,zlen,z,zlen); *neg = TRUE; return(GENERIC_OK); } /* Result is positive.*/ *neg = FALSE; return(GENERIC_OK); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ | API UTILITIES | | Function: OctApiLmAdd. | | Description: This function adds 2 numbers, a and b. Number a is | (alen + 1) * 32 bits long; b is (blen + 1) * 32 bits long. The | result is (zlen + 1) * 32 bits long. It the function succeeds it returns | GENERIC_OK, else GENERIC_ERROR. | | ----------------------------------------------------------------------- | | Variable | Type | Description | ----------------------------------------------------------------------- | *a UINT32 The array containing the first number. | alen USHORT The length of array a, minus 1 (0 - 99). | *b UINT32 The array containing the second number. | blen USHORT The length of array b, minus 1 (0 - 99). | *z UINT32 The array containing the resulting number. | zlen USHORT The length of array z, minus 1 (0 - 99). | \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 OctApiLmAdd(UINT32 * a,USHORT alen,UINT32 * b,USHORT blen,UINT32 * z, USHORT zlen) { USHORT i; UINT32 temp; UINT32 carry=0; UINT32 aprim; UINT32 bprim; /* Check for array lengths.*/ if (alen > zlen || blen > zlen) return(OCTAPI_LM_ARRAY_SIZE_MISMATCH); for(i=0;i<=zlen;i++) { if (i <= alen) aprim = *(a+i); else aprim = 0; if (i <= blen) bprim = *(b+i); else bprim = 0; temp = aprim + bprim + carry; /* Calculate carry for next time.*/ if (carry == 0) if (temp < aprim) carry = 1; else carry = 0; else if (temp <= aprim) carry = 1; else carry = 0; /* Write new value.*/ *(z+i) = temp; } /* Check for overflow.*/ if (carry == 1) return(OCTAPI_LM_OVERFLOW); /* All is well.*/ return(GENERIC_OK); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_chip_stats.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains functions used to retreive the OCT6100 chip stats. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 85 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "oct6100api/oct6100_apiud.h" #include "apilib/octapi_llman.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_chip_stats_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_chip_stats_priv.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_chip_stats_priv.h" /**************************** PUBLIC FUNCTIONS *****************************/ /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiChipStatsSwInit Description: Initializes portions of API instance associated to chip stats. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiChipStatsSwInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; /* Get local pointer to shared portion of API instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Initialize chip stats. */ pSharedInfo->ErrorStats.fFatalChipError = FALSE; pSharedInfo->ErrorStats.ulH100ClkABadCnt = 0; pSharedInfo->ErrorStats.ulH100ClkBBadCnt = 0; pSharedInfo->ErrorStats.ulH100FrameABadCnt = 0; pSharedInfo->ErrorStats.ulH100OutOfSyncCnt = 0; pSharedInfo->ErrorStats.ulInternalReadTimeoutCnt = 0; pSharedInfo->ErrorStats.ulSdramRefreshTooLateCnt = 0; pSharedInfo->ErrorStats.ulPllJitterErrorCnt = 0; pSharedInfo->ErrorStats.ulOverflowToneEventsCnt = 0; pSharedInfo->ErrorStats.ulToneDetectorErrorCnt = 0; /* Init the chip stats. */ pSharedInfo->ChipStats.usNumberChannels = 0; pSharedInfo->ChipStats.usNumberBiDirChannels = 0; pSharedInfo->ChipStats.usNumberTsiCncts = 0; pSharedInfo->ChipStats.usNumberConfBridges = 0; pSharedInfo->ChipStats.usNumberPlayoutBuffers = 0; pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts = 0; pSharedInfo->ChipStats.ulPlayoutMemUsed = 0; pSharedInfo->ChipStats.usNumEcChanUsingMixer = 0; pSharedInfo->ChipStats.usNumberPhasingTssts = 0; pSharedInfo->ChipStats.usNumberAdpcmChans = 0; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_conf_bridge.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains all functions related to a conference bridge. Procedures needed to open/close a bridge, add/remove a participant to a conference bridge, mute/unmute a participant, etc.. are all present in this source file. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 145 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "oct6100api/oct6100_apiud.h" #include "apilib/octapi_llman.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_channel_inst.h" #include "oct6100api/oct6100_mixer_inst.h" #include "oct6100api/oct6100_conf_bridge_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_mixer_pub.h" #include "oct6100api/oct6100_conf_bridge_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_memory_priv.h" #include "oct6100_tsst_priv.h" #include "oct6100_channel_priv.h" #include "oct6100_mixer_priv.h" #include "oct6100_conf_bridge_priv.h" /**************************** PUBLIC FUNCTIONS *****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ConfBridgeChanRemove Description: This function removes an echo channel (participant) from a conference bridge. All participants can be removed from the bridge if a special flag (fRemoveAll) is set to TRUE. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pConfBridgeRemove Pointer to conference bridge channel removal structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ConfBridgeChanRemoveDef( tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove ) { f_pConfBridgeRemove->ulChannelHndl = cOCT6100_INVALID_HANDLE; f_pConfBridgeRemove->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE; f_pConfBridgeRemove->fRemoveAll = FALSE; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetConfBridgeSwSizes Description: Gets the sizes of all portions of the API instance pertinent to the management of conference bridges. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pOpenChip Pointer to chip configuration struct. f_pInstSizes Pointer to struct containing instance sizes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiGetConfBridgeSwSizes( IN tPOCT6100_CHIP_OPEN f_pOpenChip, OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) { UINT32 ulTempVar; UINT32 ulResult; /* Calculate memory needed for conference bridge list. */ if ( f_pOpenChip->ulMaxConfBridges == 0 && f_pOpenChip->fEnableChannelRecording == TRUE ) f_pOpenChip->ulMaxConfBridges = 1; f_pInstSizes->ulConfBridgeList = f_pOpenChip->ulMaxConfBridges * sizeof( tOCT6100_API_CONF_BRIDGE ); /* Calculate memory needed for conference bridge allocation software. */ if ( f_pOpenChip->ulMaxConfBridges > 0 ) { /* Get size of bridge allocation memory */ ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxConfBridges, &f_pInstSizes->ulConfBridgeAlloc ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_1C; /* Check if the user wants to build flexible conference bridges. */ if ( f_pOpenChip->ulMaxFlexibleConfParticipants > 0 ) { /* Allocate the lowest quantity according to what the user requested. */ if ( f_pOpenChip->ulMaxFlexibleConfParticipants < ( f_pOpenChip->ulMaxConfBridges * cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ) ) f_pInstSizes->ulFlexConfParticipantsList = f_pOpenChip->ulMaxFlexibleConfParticipants * sizeof( tOCT6100_API_FLEX_CONF_PARTICIPANT ); else { f_pOpenChip->ulMaxFlexibleConfParticipants = f_pOpenChip->ulMaxConfBridges * cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; f_pInstSizes->ulFlexConfParticipantsList = f_pOpenChip->ulMaxConfBridges * cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE * sizeof( tOCT6100_API_FLEX_CONF_PARTICIPANT ); } /* Get size of flexible conferencing participants allocation memory */ ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxFlexibleConfParticipants, &f_pInstSizes->ulFlexConfParticipantsAlloc ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_1C; } else { f_pInstSizes->ulFlexConfParticipantsList = 0; f_pInstSizes->ulFlexConfParticipantsAlloc = 0; } } else { f_pInstSizes->ulMixerEventList = 0; f_pInstSizes->ulMixerEventAlloc = 0; f_pInstSizes->ulConfBridgeAlloc = 0; /* Make sure flexible conferencing is not used. */ f_pInstSizes->ulFlexConfParticipantsList = 0; f_pInstSizes->ulFlexConfParticipantsAlloc = 0; } /* Calculate memory needed for list and allocation software serialization. */ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulConfBridgeList, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulConfBridgeAlloc, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulFlexConfParticipantsList, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulFlexConfParticipantsAlloc, ulTempVar ) return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiConfBridgeSwInit Description: Initializes all elements of the instance structure associated to conference bridges. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiConfBridgeSwInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CONF_BRIDGE pConfBridgeList; tPOCT6100_API_FLEX_CONF_PARTICIPANT pFlexConfParticipantList; PVOID pFlexConfPartipantsAlloc; UINT32 ulMaxFlexConfParicipants; PVOID pConfBridgeAlloc; UINT32 ulMaxConfBridges; UINT32 ulResult; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Get the maximum number of conference bridges. */ ulMaxConfBridges = pSharedInfo->ChipConfig.usMaxConfBridges; /*===================================================================*/ /* Set all entries in the conference bridge list to unused. */ mOCT6100_GET_CONF_BRIDGE_LIST_PNT( pSharedInfo, pConfBridgeList ); /* Initialize the conference bridge allocation software to "all free". */ if ( ulMaxConfBridges > 0 ) { /* Clear the bridge memory */ Oct6100UserMemSet( pConfBridgeList, 0x00, ulMaxConfBridges * sizeof( tOCT6100_API_CONF_BRIDGE )); mOCT6100_GET_CONF_BRIDGE_ALLOC_PNT( pSharedInfo, pConfBridgeAlloc ) ulResult = OctapiLlmAllocInit( &pConfBridgeAlloc, ulMaxConfBridges ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_1E; } /*===================================================================*/ /*===================================================================*/ /* Set all entries in the flexible conferencing participant list to unused. */ /* Get the maximum number of flexible conferencing participants. */ ulMaxFlexConfParicipants = pSharedInfo->ChipConfig.usMaxFlexibleConfParticipants; mOCT6100_GET_FLEX_CONF_PARTICIPANT_LIST_PNT( pSharedInfo, pFlexConfParticipantList ); /* Initialize the flexible conferencing allocation software. */ if ( ulMaxFlexConfParicipants > 0 ) { UINT32 i, ulEventIndex; /* Clear the participants memory */ Oct6100UserMemSet( pFlexConfParticipantList, 0x00, ulMaxFlexConfParicipants * sizeof( tOCT6100_API_FLEX_CONF_PARTICIPANT )); mOCT6100_GET_FLEX_CONF_PARTICIPANT_ALLOC_PNT( pSharedInfo, pFlexConfPartipantsAlloc ) ulResult = OctapiLlmAllocInit( &pFlexConfPartipantsAlloc, ulMaxFlexConfParicipants ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_1E; /* Initialize the conferencing indexes. */ for ( i = 0; i < ulMaxFlexConfParicipants; i ++ ) { for ( ulEventIndex = 0; ulEventIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulEventIndex ++ ) pFlexConfParticipantList[ i ].ausLoadOrAccumulateEventIndex[ ulEventIndex ] = cOCT6100_INVALID_INDEX; } } /*===================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ConfBridgeCloseSer Description: Closes a conference bridge. Note that no client must be present on the bridge for the bridge to be closed. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pConfBridgeClose Pointer to conference bridge close structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ConfBridgeCloseSer( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose ) { UINT16 usBridgeIndex; UINT32 ulResult; /* Verify that all the parameters given match the state of the API. */ ulResult = Oct6100ApiAssertBridgeParams( f_pApiInstance, f_pConfBridgeClose, &usBridgeIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Release all resources associated to the conference bridge. */ ulResult = Oct6100ApiReleaseBridgeResources( f_pApiInstance, usBridgeIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Invalidate the handle. */ f_pConfBridgeClose->ulConfBridgeHndl = cOCT6100_INVALID_HANDLE; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiAssertBridgeParams Description: Checks the user's conference bridge close configuration for errors. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pConfBridgeClose Pointer to conference bridge close structure. f_pusBridgeIndex Pointer to API instance conference bridge index. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiAssertBridgeParams( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CONF_BRIDGE_CLOSE f_pConfBridgeClose, OUT PUINT16 f_pusBridgeIndex ) { tPOCT6100_API_CONF_BRIDGE pBridgeEntry; UINT32 ulEntryOpenCnt; /* Check the provided handle. */ if ( (f_pConfBridgeClose->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE ) return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; *f_pusBridgeIndex = (UINT16)( f_pConfBridgeClose->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK ); if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex ) /* Extract the entry open count from the provided handle. */ ulEntryOpenCnt = (f_pConfBridgeClose->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; /* Check for errors. */ if ( pBridgeEntry->fReserved != TRUE ) return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; if ( pBridgeEntry->usNumClients != 0 ) return cOCT6100_ERR_CONF_BRIDGE_ACTIVE_DEPENDENCIES; if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt ) return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReleaseBridgeResources Description: Release all resources reserved for the conference bridge. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usBridgeIndex Allocated external memory block for the conference bridge. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReleaseBridgeResources( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usBridgeIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CONF_BRIDGE pBridgeEntry; tPOCT6100_API_CONF_BRIDGE pTempBridgeEntry; UINT32 ulResult; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Release the entry from the conference bridge list. */ ulResult = Oct6100ApiReleaseBridgeEntry( f_pApiInstance, f_usBridgeIndex ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_24; mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex ); /* Remove the bridge entry from the bridge list. */ if ( pSharedInfo->MiscVars.usNumBridgesOpened == 1 ) { /* This bridge was the only one opened. */ pSharedInfo->MiscVars.usFirstBridge = cOCT6100_INVALID_INDEX; } else if ( pSharedInfo->MiscVars.usNumBridgesOpened > 1 ) { /* There are more then one bridge open, must update the list. */ if ( pBridgeEntry->usPrevBridgePtr != cOCT6100_INVALID_INDEX ) { /* There is a valid entry before this bridge, let's update this entry. */ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempBridgeEntry, pBridgeEntry->usPrevBridgePtr ); pTempBridgeEntry->usNextBridgePtr = pBridgeEntry->usNextBridgePtr; } if ( pBridgeEntry->usNextBridgePtr != cOCT6100_INVALID_INDEX ) { /* There is a valid entry after this bridge, let's update this entry. */ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempBridgeEntry, pBridgeEntry->usNextBridgePtr ); pTempBridgeEntry->usPrevBridgePtr = pBridgeEntry->usPrevBridgePtr; } if ( pSharedInfo->MiscVars.usFirstBridge == f_usBridgeIndex ) { /* This entry was the first of the list, make the next one be the first now. */ pSharedInfo->MiscVars.usFirstBridge = pBridgeEntry->usNextBridgePtr; } } else { /* Variable has become out of sync. */ return cOCT6100_ERR_FATAL_25; } /*=============================================================*/ /* Update the conference bridge's list entry. */ /* Mark the bridge as closed. */ pBridgeEntry->fFlexibleConferencing = FALSE; pBridgeEntry->fReserved = FALSE; pBridgeEntry->byEntryOpenCnt++; /* Decrement the number of conference bridges opened. */ pSharedInfo->MiscVars.usNumBridgesOpened--; pSharedInfo->ChipStats.usNumberConfBridges--; /*=============================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ConfBridgeChanRemoveSer Description: Removes an echo channel from a conference bridge. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pConfBridgeRemove Pointer to conference bridge channel remove structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ConfBridgeChanRemoveSer( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove ) { UINT16 usBridgeIndex; UINT16 usChanIndex=0; UINT16 usLoadEventIndex; UINT16 usSubStoreEventIndex; UINT16 usCopyEventIndex; UINT32 ulResult; UINT8 fFlexibleConfBridge; UINT8 fTap; /* Check the validity of the channel and conference bridge given. */ ulResult = Oct6100ApiCheckChanRemoveParams( f_pApiInstance, f_pConfBridgeRemove, &usBridgeIndex, &usChanIndex, &fFlexibleConfBridge, &fTap, &usLoadEventIndex, &usSubStoreEventIndex, &usCopyEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Release all resources reserved for the conference bridge. */ ulResult = Oct6100ApiReleaseChanEventResources( f_pApiInstance, f_pConfBridgeRemove, usBridgeIndex, usChanIndex, fFlexibleConfBridge, usLoadEventIndex, usSubStoreEventIndex, usCopyEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear the memory entry for this channel within the bridge. */ ulResult = Oct6100ApiBridgeEventRemove( f_pApiInstance, f_pConfBridgeRemove, usBridgeIndex, usChanIndex, fFlexibleConfBridge, usLoadEventIndex, usSubStoreEventIndex, usCopyEventIndex, fTap ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiCheckChanRemoveParams Description: Check the validity of the channel and conference bridge given. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pConfBridgeRemove Pointer to conference bridge channenl add structure. f_pusBridgeIndex Pointer to the bridge index. f_pfFlexibleConfBridge If this is a flexible conference bridge f_pusChannelIndex Pointer to the channel index to be added to the bridge. f_pusLoadEventIndex Pointer to the load mixer event. f_pusSubStoreEventIndex Pointer to the sub-store mixer event. f_pusCopyEventIndex Pointer to the copy mixer event. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiCheckChanRemoveParams( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove, OUT PUINT16 f_pusBridgeIndex, OUT PUINT16 f_pusChannelIndex, OUT PUINT8 f_pfFlexibleConfBridge, OUT PUINT8 f_pfTap, OUT PUINT16 f_pusLoadEventIndex, OUT PUINT16 f_pusSubStoreEventIndex, OUT PUINT16 f_pusCopyEventIndex ) { UINT32 ulEntryOpenCnt; tPOCT6100_API_CHANNEL pEchoChanEntry; tPOCT6100_API_CONF_BRIDGE pBridgeEntry; /* Verify if the remove all flag is valid. */ if ( f_pConfBridgeRemove->fRemoveAll != TRUE && f_pConfBridgeRemove->fRemoveAll != FALSE ) return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_REMOVE_ALL; /* Check the channel handle only if the remove all flag is set to FALSE. */ if ( f_pConfBridgeRemove->fRemoveAll == FALSE ) { /*=====================================================================*/ /* Check the channel handle. */ if ( (f_pConfBridgeRemove->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; *f_pusChannelIndex = (UINT16)( f_pConfBridgeRemove->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); if ( *f_pusChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, *f_pusChannelIndex ) /* Extract the entry open count from the provided handle. */ ulEntryOpenCnt = (f_pConfBridgeRemove->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; /* Check for errors. */ if ( pEchoChanEntry->fReserved != TRUE ) return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; if ( ulEntryOpenCnt != pEchoChanEntry->byEntryOpenCnt ) return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; if ( pEchoChanEntry->fBeingTapped == TRUE ) return cOCT6100_ERR_CONF_BRIDGE_CHANNEL_TAP_DEPENDENCY; /*=====================================================================*/ *f_pusBridgeIndex = pEchoChanEntry->usBridgeIndex; *f_pusLoadEventIndex = pEchoChanEntry->usLoadEventIndex; *f_pusSubStoreEventIndex = pEchoChanEntry->usSubStoreEventIndex; *f_pusCopyEventIndex = pEchoChanEntry->usSinCopyEventIndex; /* Check if the channel is really part of the bridge. */ if ( *f_pusBridgeIndex == cOCT6100_INVALID_INDEX ) return cOCT6100_ERR_CONF_BRIDGE_CHAN_NOT_ON_BRIDGE; mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex ) /* Return whether this is a flexible bridge or not. */ *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing; /* Return whether this is a tap or not. */ *f_pfTap = pEchoChanEntry->fTap; } else /* f_pConfBridgeRemove->fRemoveAll == TRUE */ { /* Check the provided handle. */ if ( (f_pConfBridgeRemove->ulConfBridgeHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CONF_BRIDGE ) return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; *f_pusBridgeIndex = (UINT16)( f_pConfBridgeRemove->ulConfBridgeHndl & cOCT6100_HNDL_INDEX_MASK ); if ( *f_pusBridgeIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxConfBridges ) return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, *f_pusBridgeIndex ) /* Extract the entry open count from the provided handle. */ ulEntryOpenCnt = (f_pConfBridgeRemove->ulConfBridgeHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; /* Check for errors. */ if ( pBridgeEntry->fReserved != TRUE ) return cOCT6100_ERR_CONF_BRIDGE_NOT_OPEN; if ( ulEntryOpenCnt != pBridgeEntry->byEntryOpenCnt ) return cOCT6100_ERR_CONF_BRIDGE_INVALID_HANDLE; /* This information is not currently available. */ *f_pusLoadEventIndex = cOCT6100_INVALID_INDEX; *f_pusSubStoreEventIndex = cOCT6100_INVALID_INDEX; *f_pusCopyEventIndex = cOCT6100_INVALID_INDEX; /* Return whether this is a flexible bridge or not. */ *f_pfFlexibleConfBridge = pBridgeEntry->fFlexibleConferencing; *f_pfTap = FALSE; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReleaseChanEventResources Description: Release all resources reserved to the channel part of the conference bridge. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pConfBridgeRemove Pointer to conference bridge channel add structure. f_usBridgeIndex Index of the bridge structure within the API's bridge list. f_usChanIndex Index of the channel structure within the API's channel list f_fFlexibleConfBridge If this is a flexible conference bridge. f_usLoadEventIndex Index of the load mixer event. f_usSubStoreEventIndex Index of the sub-store mixer event. f_usCopyEventIndex Index of the copy mixer event. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReleaseChanEventResources( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove, IN UINT16 f_usBridgeIndex, IN UINT16 f_usChanIndex, IN UINT8 f_fFlexibleConfBridge, IN UINT16 f_usLoadEventIndex, IN UINT16 f_usSubStoreEventIndex, IN UINT16 f_usCopyEventIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHANNEL pEchoChanEntry; UINT32 ulResult; UINT32 i; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; if ( f_fFlexibleConfBridge == TRUE ) { tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant; tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; if ( f_pConfBridgeRemove->fRemoveAll == FALSE ) { tPOCT6100_API_CHANNEL pTempEchoChanEntry; mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); /* Release an entry for the store event in the mixer memory. */ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usSubStoreEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } /* Release an entry for the Sin copy event in the mixer memory. */ /* This value can be invalid if the Rin port was used - no need to release. */ if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usCopyEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } } /* This value can be 0 if the Rin port was used - no need to release. */ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) { /* Release the extra TSI entry.*/ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } } /* This value can be 0 if the Sout port was used - no need to release. */ if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 ) { /* Release the extra TSI entry.*/ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraRinTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } } /* Must travel all clients of this conference and release the load or accumulate events for */ /* all participants which can hear us and vice versa. */ /* Search through the list of API channel entry for the ones on to this bridge. */ for ( i = 0; ( i < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ); i++ ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, i ); /* Channel reserved? */ if ( ( i != f_usChanIndex ) && pTempEchoChanEntry->fReserved == TRUE ) { /* On current bridge? */ if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) { mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); /* Check if we can hear this participant. */ if ( ( pParticipant->ulListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) { /* Must release the allocated mixer event. */ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } pParticipant->ausLoadOrAccumulateEventIndex[ pTempParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; } /* Check if this participant can hear us. */ if ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 ) { /* Must release the allocated mixer event. */ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pTempParticipant->ausLoadOrAccumulateEventIndex[ pParticipant->ulListenerMaskIndex ] ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } pTempParticipant->ausLoadOrAccumulateEventIndex[ pParticipant->ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; } } } } } else /* f_pConfBridgeRemove->fRemoveAll == TRUE */ { UINT32 ulListenerMaskIndex; ulResult = cOCT6100_ERR_OK; /* Search through the list of API channel entry for the ones on to this bridge.*/ for ( i = 0; ( i < pSharedInfo->ChipConfig.usMaxChannels ) && ( ulResult == cOCT6100_ERR_OK ); i++ ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i ); /* Channel reserved? */ if ( pEchoChanEntry->fReserved == TRUE ) { /* On current bridge? */ if ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) { mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); /* Release an entry for the Store event in the Mixer memory. */ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usSubStoreEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } /* Release an entry for the Sin copy event in the Mixer memory. */ /* This value can be invalid if the Rin port was used - no need to release. */ if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } } /* This value can be 0 if the Rin port was used - no need to release. */ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) { /* Release the extra TSI entry.*/ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } } /* This value can be 0 if the Sout port was used - no need to release. */ if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 ) { /* Release the extra TSI entry.*/ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraRinTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } } /* Check if something can be freed. */ for ( ulListenerMaskIndex = 0; ulListenerMaskIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulListenerMaskIndex ++ ) { if ( pParticipant->ausLoadOrAccumulateEventIndex[ ulListenerMaskIndex ] != cOCT6100_INVALID_INDEX ) { /* Must release the allocated mixer event. */ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pParticipant->ausLoadOrAccumulateEventIndex[ ulListenerMaskIndex ] ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } pParticipant->ausLoadOrAccumulateEventIndex[ ulListenerMaskIndex ] = cOCT6100_INVALID_INDEX; } } } } } if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } else /* if ( f_fFlexibleConfBridge == FALSE ) */ { if ( f_pConfBridgeRemove->fRemoveAll == FALSE ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); /* Release the entry for the load event in the mixer memory. */ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usLoadEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } /* Release an entry for the substract and store event in the mixer memory. */ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usSubStoreEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } /* Release an entry for the Sin copy event in the Mixer memory. */ /* This value can be invalid if the Rin port was used - no need to release. */ if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, f_usCopyEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } } /* This value can be 0 if the Rin port was used - no need to release. */ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) { /* Release the extra TSI entry. */ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } } } else /* f_pConfBridgeRemove->fRemoveAll == TRUE */ { /* Search through the list of API channel entry for the ones on to the specified bridge.*/ for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i++ ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i ); if ( pEchoChanEntry->fReserved == TRUE ) { if ( ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) && ( pEchoChanEntry->fTap == FALSE ) ) { /* Release the entry for the load event in the mixer memory. */ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usLoadEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } /* Release an entry for the substract and store event in the Mixer memory. */ ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usSubStoreEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } /* Release an entry for the Sin copy event in the Mixer memory. */ /* This value can be invalid if the Rin port was used - no need to release. */ if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiReleaseMixerEventEntry( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } } /* This value can be 0 if the Rin port was used - no need to release. */ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) { /* Release the extra TSI entry.*/ ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pEchoChanEntry->usExtraSinTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } } } } } } } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiBridgeEventRemove Description: Remove the event from the global event list of the chip and update the bridge and channel structures. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pConfBridgeRemove Pointer to a conference bridge channel remove structure. f_usBridgeIndex Index of the current bridge in the API list. f_usChanIndex Index of the current channel in the API list. f_fFlexibleConfBridge If this is a flexible conference bridge. f_usLoadEventIndex Allocated entry for the Load event of the channel. f_usSubStoreEventIndex Allocated entry for the substract and store event of the channel. f_usCopyEventIndex Allocated entry for the copy event of the channel. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiBridgeEventRemove ( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_CONF_BRIDGE_CHAN_REMOVE f_pConfBridgeRemove, IN UINT16 f_usBridgeIndex, IN UINT16 f_usChanIndex, IN UINT8 f_fFlexibleConfBridge, IN UINT16 f_usLoadEventIndex, IN UINT16 f_usSubStoreEventIndex, IN UINT16 f_usCopyEventIndex, IN UINT8 f_fTap ) { tPOCT6100_API_CONF_BRIDGE pBridgeEntry; tPOCT6100_API_MIXER_EVENT pLoadEventEntry; tPOCT6100_API_MIXER_EVENT pSubStoreEventEntry; tPOCT6100_API_MIXER_EVENT pCopyEventEntry = NULL; tPOCT6100_API_MIXER_EVENT pTempEntry; tPOCT6100_API_CHANNEL pEchoChanEntry; tPOCT6100_API_CHANNEL pTempEchoChanEntry; tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_READ_PARAMS ReadParams; UINT32 ulResult; UINT16 usPreviousEventIndex; UINT16 usTempEventIndex; UINT32 ulLoopCount = 0; UINT16 usReadData; UINT16 usChannelIndex; UINT32 i; BOOL fRemoveSinCopy = FALSE; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, f_usBridgeIndex ); /* If no client on the bridge, and the remove all option is specified, return here. */ if ( ( pBridgeEntry->usNumClients == 0 ) && ( f_pConfBridgeRemove->fRemoveAll == TRUE ) ) return cOCT6100_ERR_OK; /* Make sure the dominant speaker feature is disabled first. */ if ( pBridgeEntry->fDominantSpeakerSet == TRUE ) { /* If all channels are to be removed or if the dominant speaker is the current channel to be removed. */ if ( ( f_pConfBridgeRemove->fRemoveAll == TRUE ) || ( ( f_pConfBridgeRemove->fRemoveAll == FALSE ) && ( pBridgeEntry->usDominantSpeakerChanIndex == f_usChanIndex ) ) ) { /* Disable on all channels part of this conference. */ /* Search through the list of API channel entry for the ones on to this bridge. */ for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); if ( pTempEchoChanEntry->fReserved == TRUE ) { if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) { ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, usChannelIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } } /* Save this in the conference bridge structure. */ pBridgeEntry->fDominantSpeakerSet = FALSE; pBridgeEntry->usDominantSpeakerChanIndex = cOCT6100_INVALID_INDEX; } else { /* Only disable this current channel. */ ulResult = Oct6100ApiBridgeSetDominantSpeaker( f_pApiInstance, f_usChanIndex, cOCT6100_CONF_DOMINANT_SPEAKER_UNASSIGNED ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } if ( f_fFlexibleConfBridge == TRUE ) { tPOCT6100_API_FLEX_CONF_PARTICIPANT pParticipant; tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; UINT16 ausMutePortChannelIndexes[ cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE ]; UINT32 ulMutePortChannelIndex; for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = cOCT6100_INVALID_INDEX; if ( f_pConfBridgeRemove->fRemoveAll == FALSE ) { /* The channel index is valid. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); /* Search through the list of API channel entry for the ones on to this bridge. */ for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); if ( ( usChannelIndex != f_usChanIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) { if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) { mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); /* Check if we can hear this participant. */ if ( ( ( pParticipant->ulListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) && ( pParticipant->fFlexibleMixerCreated == TRUE ) && ( pTempEchoChanEntry->fMute == FALSE ) ) { /* First update the current channel's mixer. */ ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( f_pApiInstance, f_usBridgeIndex, usChannelIndex, f_usChanIndex, TRUE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Check if this participant can hear us. */ if ( ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 ) && ( pTempParticipant->fFlexibleMixerCreated == TRUE ) && ( pEchoChanEntry->fMute == FALSE ) ) { /* Then update this channel's mixer. */ ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( f_pApiInstance, f_usBridgeIndex, f_usChanIndex, usChannelIndex, TRUE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Remember to mute the port on this channel. */ for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) { if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == usChannelIndex ) { break; } else if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) { ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = usChannelIndex; break; } } } } } } /* Check if must manually clear the Sin copy event. */ if ( ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) && ( pEchoChanEntry->fCopyEventCreated == TRUE ) ) { /* Transform event into no-operation. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Now remove the copy event from the event list. */ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; pEchoChanEntry->fCopyEventCreated = FALSE; } /* Release an entry for the participant. */ ulResult = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pEchoChanEntry->usFlexConfParticipantIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } /*=======================================================================*/ /* Update the event and channel API structure */ pEchoChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX; pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX; pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX; pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; /* Indicate that the extra SIN TSI is not needed anymore by the mixer. */ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) { pEchoChanEntry->usExtraSinTsiDependencyCnt--; pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; } /* Indicate that the extra RIN TSI is not needed anymore by the mixer. */ if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 ) { pEchoChanEntry->usExtraRinTsiDependencyCnt--; pEchoChanEntry->usExtraRinTsiMemIndex = cOCT6100_INVALID_INDEX; } /* Update the chip stats structure. */ pSharedInfo->ChipStats.usNumEcChanUsingMixer--; pBridgeEntry->usNumClients--; /* For sure we have to mute the ports of this channel to be removed. */ ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_usChanIndex, pEchoChanEntry->usRinTsstIndex, pEchoChanEntry->usSinTsstIndex, FALSE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Travel through the channels that were heard by the participant removed and check if their Rin port must be muted. */ for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) { if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] != cOCT6100_INVALID_INDEX ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, ausMutePortChannelIndexes[ ulMutePortChannelIndex ] ); mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); if ( pTempParticipant->fFlexibleMixerCreated == FALSE ) { /* Check if the Rin port must be muted on this channel. */ ulResult = Oct6100ApiMutePorts( f_pApiInstance, ausMutePortChannelIndexes[ ulMutePortChannelIndex ], pTempEchoChanEntry->usRinTsstIndex, pTempEchoChanEntry->usSinTsstIndex, FALSE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } else /* if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) */ { /* No more channels to check for muting. */ break; } } } else /* if ( f_pConfBridgeRemove->fRemoveAll == TRUE ) */ { UINT16 usMainChannelIndex; for ( usMainChannelIndex = 0 ; usMainChannelIndex < pSharedInfo->ChipConfig.usMaxChannels ; usMainChannelIndex++ ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, usMainChannelIndex ); /* If this channel is on the bridge we are closing all the channels. */ if ( ( pEchoChanEntry->fReserved == TRUE ) && ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) ) { /* Remember to mute the port on this channel. */ for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) { if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == usMainChannelIndex ) { break; } else if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) { ausMutePortChannelIndexes[ ulMutePortChannelIndex ] = usMainChannelIndex; break; } } mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pParticipant, pEchoChanEntry->usFlexConfParticipantIndex ); /* Search through the list of API channel entry for the ones on to this bridge. */ for ( usChannelIndex = (UINT16)( usMainChannelIndex + 1 ); usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); if ( pTempEchoChanEntry->fReserved == TRUE ) { if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) { mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); /* Everyone that we can hear must be removed. */ if ( ( ( pParticipant->ulListenerMask & ( 0x1 << pTempParticipant->ulListenerMaskIndex ) ) == 0x0 ) && ( pParticipant->fFlexibleMixerCreated == TRUE ) && ( pTempEchoChanEntry->fMute == FALSE ) ) { /* First update the current channel's mixer. */ ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( f_pApiInstance, f_usBridgeIndex, usChannelIndex, usMainChannelIndex, TRUE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Check if this participant can hear us. */ if ( ( ( pTempParticipant->ulListenerMask & ( 0x1 << pParticipant->ulListenerMaskIndex ) ) == 0x0 ) && ( pTempParticipant->fFlexibleMixerCreated == TRUE ) && ( pEchoChanEntry->fMute == FALSE ) ) { /* Then update this channel's mixer. */ ulResult = Oct6100ApiBridgeRemoveParticipantFromChannel( f_pApiInstance, f_usBridgeIndex, usMainChannelIndex, usChannelIndex, TRUE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } } } /* Check if must manually clear the Sin copy event. */ if ( ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) && ( pEchoChanEntry->fCopyEventCreated == TRUE ) ) { /* Transform event into no-operation. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Now remove the copy event from the event list. */ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; pEchoChanEntry->fCopyEventCreated = FALSE; } /* Release an entry for the participant. */ ulResult = Oct6100ApiReleaseFlexConfParticipantEntry( f_pApiInstance, pEchoChanEntry->usFlexConfParticipantIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return ulResult; } /*=======================================================================*/ /* Update the event and channel API structure */ pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX; pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX; pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; /* Indicate that the Extra SIN TSI is not needed anymore by the mixer. */ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) { pEchoChanEntry->usExtraSinTsiDependencyCnt--; pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; } /* Indicate that the Extra RIN TSI is not needed anymore by the mixer. */ if ( pEchoChanEntry->usExtraRinTsiDependencyCnt == 1 ) { pEchoChanEntry->usExtraRinTsiDependencyCnt--; pEchoChanEntry->usExtraRinTsiMemIndex = cOCT6100_INVALID_INDEX; } /* Update the chip stats structure. */ pSharedInfo->ChipStats.usNumEcChanUsingMixer--; } } /* Travel through the channels that were heard by the participant removed and check if their Rin port must be muted. */ for( ulMutePortChannelIndex = 0; ulMutePortChannelIndex < cOCT6100_MAX_FLEX_CONF_PARTICIPANTS_PER_BRIDGE; ulMutePortChannelIndex ++ ) { if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] != cOCT6100_INVALID_INDEX ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, ausMutePortChannelIndexes[ ulMutePortChannelIndex ] ); mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); if ( pTempParticipant->fFlexibleMixerCreated == FALSE ) { /* Check if the Rin port must be muted on this channel. */ ulResult = Oct6100ApiMutePorts( f_pApiInstance, ausMutePortChannelIndexes[ ulMutePortChannelIndex ], pTempEchoChanEntry->usRinTsstIndex, pTempEchoChanEntry->usSinTsstIndex, FALSE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } else /* if ( ausMutePortChannelIndexes[ ulMutePortChannelIndex ] == cOCT6100_INVALID_INDEX ) */ { /* No more channels to check for muting. */ break; } /* Clear the flexible conf bridge participant index. */ pTempEchoChanEntry->usFlexConfParticipantIndex = cOCT6100_INVALID_INDEX; } /* No more clients on bridge. */ pBridgeEntry->usNumClients = 0; } } else /* if ( f_fFlexibleConfBridge == FALSE ) */ { if ( f_pConfBridgeRemove->fRemoveAll == FALSE ) { /* The channel index is valid. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); if ( f_fTap == TRUE ) { mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pBridgeEntry, pEchoChanEntry->usTapBridgeIndex ); } /* Get a pointer to the event entry. */ if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX ) mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCopyEventEntry, f_usCopyEventIndex ); mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex ); mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, f_usLoadEventIndex ); /*=======================================================================*/ /* Check if have to modify the silence load event. */ if ( pBridgeEntry->usNumClients != 1 ) { if ( pBridgeEntry->usSilenceLoadEventPtr != cOCT6100_INVALID_INDEX ) { if ( pBridgeEntry->usSilenceLoadEventPtr == f_usLoadEventIndex ) { /* Make sure the next event becomes the silence event. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pLoadEventEntry->usNextEventPtr * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_LOAD; WriteParams.usWriteData |= 1534; /* TSI index 1534 reserved for silence */ mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Update the software model to remember the silence load. */ pBridgeEntry->usSilenceLoadEventPtr = pLoadEventEntry->usNextEventPtr; } else { /* Somebody else is the silence event, no need to worry. */ } } } /*=======================================================================*/ /*=======================================================================*/ /* Clear the Load event. */ /* First verify if the event to be removed was a load event. */ if ( f_usLoadEventIndex == pBridgeEntry->usLoadIndex ) { /* Change the next entry if one is present to a load event to keep the bridge alive. */ if ( pBridgeEntry->usNumClients == 1 ) { /* There is no other entry on the bridge, no need to search for an Accumulate event. */ pBridgeEntry->usLoadIndex = cOCT6100_INVALID_INDEX; /* Clear the silence event, for sure it's invalid. */ pBridgeEntry->usSilenceLoadEventPtr = cOCT6100_INVALID_INDEX; } else { /* Search for an accumulate event to tranform into a Load event. */ usTempEventIndex = pLoadEventEntry->usNextEventPtr; ulLoopCount = 0; /* Find the copy entry before the entry to remove. */ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); while( pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_SUB_STORE && pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_STORE ) { if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE ) { /* Change this entry into a load event. */ ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usTempEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = ReadParams.ulReadAddress; WriteParams.usWriteData = (UINT16)(( usReadData & 0x1FFF ) | cOCT6100_MIXER_CONTROL_MEM_LOAD); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set this entry as the load index. */ pBridgeEntry->usLoadIndex = usTempEventIndex; /* Update the software model. */ pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; /* Stop searching. */ break; } /* Go to the next entry into the list. */ usTempEventIndex = pTempEntry->usNextEventPtr; mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); ulLoopCount++; if ( ulLoopCount == cOCT6100_MAX_LOOP ) return cOCT6100_ERR_FATAL_9B; } } } WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* Clear the substract and store event. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* Clear the Copy event - if needed. */ if ( f_usCopyEventIndex != cOCT6100_INVALID_INDEX ) { /* Transform event into no-operation. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( f_usCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( f_fTap == FALSE ) { /* Set remove Sin copy event flag to remove the event from the mixer's list. */ fRemoveSinCopy = TRUE; /* Clear the copy event created flag. */ pEchoChanEntry->fCopyEventCreated = FALSE; } } /*=======================================================================*/ /*=======================================================================*/ /* Now remove the event from the event list. */ /* Look for the entry that is pointing at the first entry of our bridge. */ if ( f_fTap == FALSE ) { ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, f_usBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usPreviousEventIndex ); } else { ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, pEchoChanEntry->usTapBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usPreviousEventIndex ); } if ( ulResult != cOCT6100_ERR_OK ) { /* If the entry was not found, we now check for the Sout copy event section/list. */ if ( ulResult == cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND ) { if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) { /* No Sout copy, it has to be the head node. */ usPreviousEventIndex = cOCT6100_MIXER_HEAD_NODE; } else { /* Use the last Sout copy event. */ usPreviousEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; } } else { return cOCT6100_ERR_FATAL_27; } } if ( pBridgeEntry->usNumClients == 1 ) { /* An entry was found, now, modify it's value. */ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex ); /* Now modify the previous last Sub Store event from another bridge. */ pTempEntry->usNextEventPtr = pSubStoreEventEntry->usNextEventPtr; /*=======================================================================*/ /* Modify the last node of the previous bridge to point to the next bridge. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.ulWriteAddress += 4; WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /* Set the event pointer info in the bridge stucture. */ pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX; pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX; pBridgeEntry->usLastSubStoreEventPtr = cOCT6100_INVALID_INDEX; /*=======================================================================*/ /* Update the global mixer pointers. */ if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == f_usLoadEventIndex && pSharedInfo->MixerInfo.usLastBridgeEventPtr == f_usSubStoreEventIndex ) { /* There is no more bridge entry in the mixer link list. */ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = cOCT6100_INVALID_INDEX; pSharedInfo->MixerInfo.usLastBridgeEventPtr = cOCT6100_INVALID_INDEX; } else if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == f_usLoadEventIndex ) { pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pSubStoreEventEntry->usNextEventPtr; } else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == f_usSubStoreEventIndex ) { pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex; } /*=======================================================================*/ if ( f_fTap == TRUE ) { /* The channel being tapped is not tapped anymore. */ /* There is no direct way of finding the tap, so loop through all channels and find the */ /* tapped channel index. */ for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); if ( pTempEchoChanEntry->usTapChanIndex == f_usChanIndex ) { tPOCT6100_API_CONF_BRIDGE pTempBridgeEntry; pTempEchoChanEntry->fBeingTapped = FALSE; pTempEchoChanEntry->usTapChanIndex = cOCT6100_INVALID_INDEX; mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( pSharedInfo, pTempBridgeEntry, f_usBridgeIndex ); pTempBridgeEntry->usNumTappedClients--; /* Re-assign Rin TSST for tapped channel. */ if ( pTempEchoChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, pTempEchoChanEntry->usRinTsstIndex, pTempEchoChanEntry->usRinRoutTsiMemIndex, pTempEchoChanEntry->TdmConfig.byRinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } break; } } /* Check if our model is broken. */ if ( usChannelIndex == pSharedInfo->ChipConfig.usMaxChannels ) return cOCT6100_ERR_FATAL_D3; } } else /* pBridgeEntry->usNumClients > 1 */ { if ( pBridgeEntry->usFirstLoadEventPtr != f_usLoadEventIndex ) { /* Now find the load entry of this bridge pointing at this load event */ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstLoadEventPtr, f_usLoadEventIndex, 0, &usPreviousEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Remove the load event to the list. */ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex ); /* Now modify the previous last Sub Store event from another bridge. */ pTempEntry->usNextEventPtr = pLoadEventEntry->usNextEventPtr; /*=======================================================================*/ /* Modify the previous node. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.ulWriteAddress += 4; WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /* Now find the last load entry of this bridge ( the one pointing at the first sub-store event ). */ if ( pBridgeEntry->usFirstSubStoreEventPtr == f_usSubStoreEventIndex ) { /* Must start with the first load to get the entry before the first sub store. */ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstLoadEventPtr, f_usSubStoreEventIndex, 0, &usPreviousEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } else { /* Must start with the first load to get the entry before the first sub store. */ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pBridgeEntry->usFirstSubStoreEventPtr, f_usSubStoreEventIndex, 0, &usPreviousEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex ); mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, f_usSubStoreEventIndex ); /* Now modify the last load event of the bridge. */ pTempEntry->usNextEventPtr = pSubStoreEventEntry->usNextEventPtr; /*=======================================================================*/ /* Modify the last node of the other bridge. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.ulWriteAddress += 4; WriteParams.usWriteData = (UINT16)( pTempEntry->usNextEventPtr ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* Update the bridge pointers. */ if ( pBridgeEntry->usFirstLoadEventPtr == f_usLoadEventIndex ) pBridgeEntry->usFirstLoadEventPtr = pLoadEventEntry->usNextEventPtr; if ( pBridgeEntry->usFirstSubStoreEventPtr == f_usSubStoreEventIndex ) pBridgeEntry->usFirstSubStoreEventPtr = pSubStoreEventEntry->usNextEventPtr; if ( pBridgeEntry->usLastSubStoreEventPtr == f_usSubStoreEventIndex ) pBridgeEntry->usLastSubStoreEventPtr = usPreviousEventIndex; /*=======================================================================*/ /*=======================================================================*/ /* Update the global mixer pointers. */ if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == f_usLoadEventIndex ) { pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pLoadEventEntry->usNextEventPtr; } if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == f_usSubStoreEventIndex ) { pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex; } /*=======================================================================*/ } /* Check if must remove the Sin copy event from the event list. */ if ( fRemoveSinCopy == TRUE ) { /* Now remove the copy event from the event list. */ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, f_usCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* Get the channel. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_usChanIndex ); /* Reprogram the TSST entry correctly if the Extra SIN TSI entry was released. */ if ( ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) && ( f_fTap == FALSE ) ) { if ( pEchoChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, pEchoChanEntry->usSinTsstIndex, pEchoChanEntry->usSinSoutTsiMemIndex, pEchoChanEntry->TdmConfig.bySinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* If the silence TSI is loaded on this port, update with the original sin TSI. */ if ( pEchoChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) { WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = pEchoChanEntry->usSinSoutTsiMemIndex; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Set the event entries as free. */ pLoadEventEntry->fReserved = FALSE; pLoadEventEntry->usEventType = cOCT6100_INVALID_INDEX; pLoadEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; pSubStoreEventEntry->fReserved = FALSE; pSubStoreEventEntry->usEventType = cOCT6100_INVALID_INDEX; pSubStoreEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; if ( pCopyEventEntry != NULL ) { pCopyEventEntry->fReserved = FALSE; pCopyEventEntry->usEventType = cOCT6100_INVALID_INDEX; pCopyEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; } pBridgeEntry->usNumClients--; /*=======================================================================*/ /* Update the event and channel API structure */ pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX; pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX; pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; /* Indicate that the Extra SIN TSI is not needed anymore by the mixer. */ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) { pEchoChanEntry->usExtraSinTsiDependencyCnt--; pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; } /* Update the chip stats structure. */ pSharedInfo->ChipStats.usNumEcChanUsingMixer--; if ( f_fTap == TRUE ) { /* Can now close the bridge. */ tOCT6100_CONF_BRIDGE_CLOSE BridgeClose; Oct6100ConfBridgeCloseDef( &BridgeClose ); BridgeClose.ulConfBridgeHndl = cOCT6100_HNDL_TAG_CONF_BRIDGE | (pBridgeEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | pEchoChanEntry->usTapBridgeIndex; ulResult = Oct6100ConfBridgeCloseSer( f_pApiInstance, &BridgeClose ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; pEchoChanEntry->usTapBridgeIndex = cOCT6100_INVALID_INDEX; pEchoChanEntry->fTap = FALSE; } /* Check if the Rin port must be muted. */ ulResult = Oct6100ApiMutePorts( f_pApiInstance, f_usChanIndex, pEchoChanEntry->usRinTsstIndex, pEchoChanEntry->usSinTsstIndex, FALSE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ } else /* f_ulBridgeChanRemove->fRemoveAll == TRUE ) */ { UINT16 usNextEventPtr; /* Save the next event pointer before invalidating everything. */ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, pBridgeEntry->usLastSubStoreEventPtr ); usNextEventPtr = pSubStoreEventEntry->usNextEventPtr; /* Search through the list of API channel entry for the ones on to the specified bridge. */ for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i++ ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i ); if ( pEchoChanEntry->fReserved == TRUE ) { if ( ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) && ( pEchoChanEntry->fTap == FALSE ) ) { /* Check if we are being tapped. If so, remove the channel that taps us from the conference. */ /* The removal of the channel will make sure the Rin TSST is re-assigned. */ if ( pEchoChanEntry->fBeingTapped == TRUE ) { tOCT6100_CONF_BRIDGE_CHAN_REMOVE ChanRemove; mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, pEchoChanEntry->usTapChanIndex ); ulResult = Oct6100ConfBridgeChanRemoveDef( &ChanRemove ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ChanRemove.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | (pTempEchoChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | pEchoChanEntry->usTapChanIndex; ulResult = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, &ChanRemove ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*=======================================================================*/ /* Clear the Load event. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usLoadEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* Clear the Substract and store event. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* Clear the SIN copy event.*/ if ( pEchoChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) { /* Transform event into no-operation. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Get a pointer to the event entry. */ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCopyEventEntry, pEchoChanEntry->usSinCopyEventIndex ); /* Update the next event pointer if required. */ if ( usNextEventPtr == pEchoChanEntry->usSinCopyEventIndex ) usNextEventPtr = pCopyEventEntry->usNextEventPtr; /* Now remove the copy event from the event list. */ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pEchoChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear the copy event created flag. */ pEchoChanEntry->fCopyEventCreated = FALSE; } /*=======================================================================*/ /*=======================================================================*/ /* Update the event and channel API structure */ /* Reprogram the TSST entry correctly if the Extra SIN TSI entry was released.*/ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) { if ( pEchoChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, pEchoChanEntry->usSinTsstIndex, pEchoChanEntry->usSinSoutTsiMemIndex, pEchoChanEntry->TdmConfig.bySinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* If the silence TSI is loaded on this port, update with the original Sin TSI. */ if ( pEchoChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) { WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pEchoChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = pEchoChanEntry->usSinSoutTsiMemIndex; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, pEchoChanEntry->usLoadEventIndex ); mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pSubStoreEventEntry, pEchoChanEntry->usSubStoreEventIndex ); /* Set the event entries as free. */ pLoadEventEntry->fReserved = FALSE; pLoadEventEntry->usEventType = cOCT6100_INVALID_EVENT; pLoadEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; pSubStoreEventEntry->fReserved = FALSE; pSubStoreEventEntry->usEventType = cOCT6100_INVALID_EVENT; pSubStoreEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; if ( pCopyEventEntry != NULL ) { pCopyEventEntry->fReserved = FALSE; pCopyEventEntry->usEventType = cOCT6100_INVALID_EVENT; pCopyEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; } /* Indicate that the Extra SIN TSI is not needed anymore by the mixer. */ if ( pEchoChanEntry->usExtraSinTsiDependencyCnt == 1 ) { pEchoChanEntry->usExtraSinTsiDependencyCnt--; pEchoChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; } /* Invalidate the channel entry. */ pEchoChanEntry->usLoadEventIndex = cOCT6100_INVALID_INDEX; pEchoChanEntry->usSubStoreEventIndex = cOCT6100_INVALID_INDEX; pEchoChanEntry->usSinCopyEventIndex = cOCT6100_INVALID_INDEX; /* Update the chip stats structure. */ pSharedInfo->ChipStats.usNumEcChanUsingMixer--; /*=======================================================================*/ } } } ulResult = Oct6100ApiGetPrevLastSubStoreEvent( f_pApiInstance, f_usBridgeIndex, pBridgeEntry->usFirstLoadEventPtr, &usPreviousEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) { if ( cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND == ulResult ) { if ( pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) { usPreviousEventIndex = cOCT6100_MIXER_HEAD_NODE; } else { usPreviousEventIndex = pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; } } else { return cOCT6100_ERR_FATAL_28; } } /* An Entry was found, now, modify it's value. */ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex ); /* Now modify the previous last Sub Store event from another bridge.*/ /* It will now point at the next bridge, or copy events. */ pTempEntry->usNextEventPtr = usNextEventPtr; /*=======================================================================*/ /* Modify the last node of the other bridge. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.ulWriteAddress += 4; WriteParams.usWriteData = pTempEntry->usNextEventPtr; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* Update the global mixer pointers. */ if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == pBridgeEntry->usFirstLoadEventPtr && pSharedInfo->MixerInfo.usLastBridgeEventPtr == pBridgeEntry->usLastSubStoreEventPtr ) { /* This bridge was the only one with event in the list. */ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = cOCT6100_INVALID_INDEX; pSharedInfo->MixerInfo.usLastBridgeEventPtr = cOCT6100_INVALID_INDEX; } else if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == pBridgeEntry->usFirstLoadEventPtr ) { /* This bridge was the first bridge. */ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = usNextEventPtr; } else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == pBridgeEntry->usLastSubStoreEventPtr ) { /* This bridge was the last bridge.*/ pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex; } /*=======================================================================*/ /* Set the event pointer info in the bridge stucture. */ pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX; pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX; pBridgeEntry->usLastSubStoreEventPtr = cOCT6100_INVALID_INDEX; pBridgeEntry->usLoadIndex = cOCT6100_INVALID_INDEX; pBridgeEntry->usSilenceLoadEventPtr = cOCT6100_INVALID_INDEX; /* Set the number of clients to 0. */ pBridgeEntry->usNumClients = 0; /* Search through the list of API channel entry for the ones on to the specified bridge. */ for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i++ ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, i ); if ( pEchoChanEntry->fReserved == TRUE ) { if ( ( pEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) && ( pEchoChanEntry->fTap == FALSE ) ) { pEchoChanEntry->usBridgeIndex = cOCT6100_INVALID_INDEX; /* Check if the Rin port must be muted. */ ulResult = Oct6100ApiMutePorts( f_pApiInstance, (UINT16)( i & 0xFFFF ), pEchoChanEntry->usRinTsstIndex, pEchoChanEntry->usSinTsstIndex, FALSE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } } } } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiBridgeRemoveParticipantFromChannel Description: This will remove a flexible conference participant from a channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usBridgeIndex Bridge index where this channel is located. f_usSourceChannelIndex Source channel to copy voice from. f_usDestinationChannelIndex Destination channel to store resulting voice to. f_fRemovePermanently Whether to remove permanently this participant. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiBridgeRemoveParticipantFromChannel( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usBridgeIndex, IN UINT16 f_usSourceChannelIndex, IN UINT16 f_usDestinationChannelIndex, IN UINT8 f_fRemovePermanently ) { tPOCT6100_API_CONF_BRIDGE pBridgeEntry; tPOCT6100_API_MIXER_EVENT pLoadEventEntry; tPOCT6100_API_MIXER_EVENT pStoreEventEntry; tPOCT6100_API_MIXER_EVENT pCopyEventEntry; tPOCT6100_API_MIXER_EVENT pTempEntry; tPOCT6100_API_MIXER_EVENT pLoadTempEntry; tPOCT6100_API_MIXER_EVENT pLastEventEntry; tPOCT6100_API_MIXER_EVENT pLastLoadOrAccumulateEventEntry; tPOCT6100_API_CHANNEL pSourceChanEntry; tPOCT6100_API_CHANNEL pDestinationChanEntry; tPOCT6100_API_FLEX_CONF_PARTICIPANT pSourceParticipant; tPOCT6100_API_FLEX_CONF_PARTICIPANT pDestinationParticipant; tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_READ_PARAMS ReadParams; UINT32 ulResult; UINT32 ulLoopCount; UINT16 usLastLoadEventIndex; UINT16 usLoadOrAccumulateEventIndex; UINT16 usTempEventIndex; UINT16 usPreviousEventIndex; UINT16 usLastEventIndex; UINT16 usReadData; BOOL fLastEvent = FALSE; BOOL fSoutCopyEvent = FALSE; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex ); mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pSourceChanEntry, f_usSourceChannelIndex ); mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pSourceParticipant, pSourceChanEntry->usFlexConfParticipantIndex ); mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pDestinationChanEntry, f_usDestinationChannelIndex ); mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pDestinationParticipant, pDestinationChanEntry->usFlexConfParticipantIndex ); /* Check if the mixer has been created on this channel. */ if ( pDestinationParticipant->fFlexibleMixerCreated == TRUE ) { /*=======================================================================*/ /* Clear the Load or Accumulate event.*/ usTempEventIndex = pDestinationChanEntry->usLoadEventIndex; ulLoopCount = 0; /* Find the Load or Accumulate event entry. */ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, usTempEventIndex ); mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pStoreEventEntry, pDestinationChanEntry->usSubStoreEventIndex ); mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); pLastEventEntry = pLoadEventEntry; pLastLoadOrAccumulateEventEntry = pLoadEventEntry; usLastLoadEventIndex = usTempEventIndex; usLastEventIndex = usTempEventIndex; while( pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_SUB_STORE && pTempEntry->usEventType != cOCT6100_MIXER_CONTROL_MEM_STORE ) { /* If this is the entry we are looking for. */ if ( pTempEntry->usSourceChanIndex == f_usSourceChannelIndex ) { /* Check if this is a Load or Accumulate event. */ if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_LOAD ) { /* This is the first entry. Check if next entry is an accumulate. */ pLoadTempEntry = pTempEntry; mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, pTempEntry->usNextEventPtr ); if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE ) { /* Change this entry into a Load event. */ ReadParams.ulReadAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pLoadTempEntry->usNextEventPtr * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = ReadParams.ulReadAddress; WriteParams.usWriteData = (UINT16)(( usReadData & 0x1FFF ) | cOCT6100_MIXER_CONTROL_MEM_LOAD); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Update the channel information with this new load event. */ pDestinationChanEntry->usLoadEventIndex = pLoadTempEntry->usNextEventPtr; /* Update the software model. */ pTempEntry->usEventType = cOCT6100_MIXER_CONTROL_MEM_LOAD; /* Get the previous event. */ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usTempEventIndex, 0, &usPreviousEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLastEventEntry, usPreviousEventIndex ); usLastEventIndex = usPreviousEventIndex; /* Stop searching. */ break; } else if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_STORE ) { /* Get back the event to remove. */ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); /* This is the only event on this channel so we can clear everything up. */ fLastEvent = TRUE; /* Get the previous event. */ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usTempEventIndex, 0, &usPreviousEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLastEventEntry, usPreviousEventIndex ); usLastEventIndex = usPreviousEventIndex; /* Stop searching. */ break; } else { /* Software model is broken. */ return cOCT6100_ERR_FATAL_C5; } } else if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_ACCUMULATE ) { /* Simply remove the entry. */ /* Get the previous event. */ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usTempEventIndex, 0, &usPreviousEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLastEventEntry, usPreviousEventIndex ); usLastEventIndex = usPreviousEventIndex; /* Stop searching. */ break; } else { /* Software model is broken. */ return cOCT6100_ERR_FATAL_C6; } } pLastLoadOrAccumulateEventEntry = pTempEntry; usLastLoadEventIndex = usTempEventIndex; /* Go to the next entry into the list. */ usTempEventIndex = pTempEntry->usNextEventPtr; mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usTempEventIndex ); ulLoopCount++; if ( ulLoopCount == cOCT6100_MAX_LOOP ) return cOCT6100_ERR_FATAL_C8; } /* Check if we found what we were looking for. */ if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_STORE || pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_SUB_STORE ) { /* Software model is broken. */ return cOCT6100_ERR_FATAL_C7; } /*=======================================================================*/ /*=======================================================================*/ /* Clear the Store event - if needed. */ if ( fLastEvent == TRUE ) { WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pDestinationChanEntry->usSubStoreEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*=======================================================================*/ /*=======================================================================*/ /* Clear the Load or Accumulate event. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usTempEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save this event index. It's the Load or Accumulate we want to remove from the list later. */ usLoadOrAccumulateEventIndex = usTempEventIndex; /*=======================================================================*/ /*=======================================================================*/ /* Clear the Copy event - if needed. */ if ( ( fLastEvent == TRUE ) && ( pDestinationChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) && ( f_fRemovePermanently == TRUE ) ) { /* Transform event into no-operation. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pDestinationChanEntry->usSinCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.usWriteData = cOCT6100_MIXER_CONTROL_MEM_NO_OP; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* The event remove from the list will be done below. */ /* Clear the copy event created flag. */ pDestinationChanEntry->fCopyEventCreated = FALSE; } /*=======================================================================*/ /*=======================================================================*/ /*=======================================================================*/ /* Remove the events from the mixer event list.*/ /*=======================================================================*/ /*=======================================================================*/ /*=======================================================================*/ /* Remove the Load or Accumulate event from the event list. */ if ( fLastEvent == FALSE ) { /*=======================================================================*/ /* Remove the Accumulate event from the event list. */ /* We saved the Load or Accumulate event above. We also saved the previous event. Use those. */ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pLoadEventEntry, usLoadOrAccumulateEventIndex ); /* Now modify the previous last event. */ pLastEventEntry->usNextEventPtr = pLoadEventEntry->usNextEventPtr; /* Modify the previous node. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usLastEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.ulWriteAddress += 4; WriteParams.usWriteData = pLastEventEntry->usNextEventPtr; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check if this is the first load event on the bridge. */ if ( pBridgeEntry->usFirstLoadEventPtr == usLoadOrAccumulateEventIndex ) { pBridgeEntry->usFirstLoadEventPtr = pLoadEventEntry->usNextEventPtr; } /* Check if this was the first load of all bridges. */ if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == usLoadOrAccumulateEventIndex ) { pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pLoadEventEntry->usNextEventPtr; } /*=======================================================================*/ } else /* if ( fLastEvent == TRUE ) */ { /*=======================================================================*/ /* Remove the Load event from the event list. */ /* Look for the entry that is pointing at the first entry of our mixer. */ ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, cOCT6100_MIXER_HEAD_NODE, usLoadOrAccumulateEventIndex, 0, &usPreviousEventIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* An Entry was found, now, modify it's value. */ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pTempEntry, usPreviousEventIndex ); /* Check if this is a Sout copy event. */ if ( pTempEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_COPY ) { /* No more previous bridges. */ fSoutCopyEvent = TRUE; } /* Now modify the previous last Store or Sub-Store or Head-Node event from another bridge/channel. */ pTempEntry->usNextEventPtr = pStoreEventEntry->usNextEventPtr; /*=======================================================================*/ /*=======================================================================*/ /* Modify the last node of the previous bridge/channel to point to the next bridge. */ WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( usPreviousEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.ulWriteAddress += 4; WriteParams.usWriteData = pTempEntry->usNextEventPtr; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* Set the event pointer info in the bridge stucture. */ if ( pBridgeEntry->usFirstLoadEventPtr == pDestinationChanEntry->usLoadEventIndex ) { UINT16 usChannelIndex; tPOCT6100_API_CHANNEL pTempEchoChanEntry; pBridgeEntry->usFirstSubStoreEventPtr = cOCT6100_INVALID_INDEX; pBridgeEntry->usFirstLoadEventPtr = cOCT6100_INVALID_INDEX; /* Find the next channel in this conference that could give us valid values. */ for ( usChannelIndex = 0; usChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; usChannelIndex++ ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempEchoChanEntry, usChannelIndex ); if ( ( usChannelIndex != f_usDestinationChannelIndex ) && ( pTempEchoChanEntry->fReserved == TRUE ) ) { if ( pTempEchoChanEntry->usBridgeIndex == f_usBridgeIndex ) { tPOCT6100_API_FLEX_CONF_PARTICIPANT pTempParticipant; mOCT6100_GET_FLEX_CONF_PARTICIPANT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempParticipant, pTempEchoChanEntry->usFlexConfParticipantIndex ); if ( pTempParticipant->fFlexibleMixerCreated == TRUE ) { pBridgeEntry->usFirstSubStoreEventPtr = pTempEchoChanEntry->usSubStoreEventIndex; pBridgeEntry->usFirstLoadEventPtr = pTempEchoChanEntry->usLoadEventIndex; break; } } } } } /* Reprogram the TSST entry correctly if the extra SIN TSI entry was released. */ if ( ( pDestinationChanEntry->usExtraSinTsiDependencyCnt == 1 ) && ( f_fRemovePermanently == TRUE ) ) { if ( pDestinationChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, pDestinationChanEntry->usSinTsstIndex, pDestinationChanEntry->usSinSoutTsiMemIndex, pDestinationChanEntry->TdmConfig.bySinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* If the silence TSI is loaded on this port, update with the original sin TSI. */ if ( pDestinationChanEntry->usSinSilenceEventIndex != cOCT6100_INVALID_INDEX ) { WriteParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pDestinationChanEntry->usSinSilenceEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = pDestinationChanEntry->usSinSoutTsiMemIndex; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Reprogram the TSST entry correctly if the extra RIN TSI entry was released. */ if ( ( pDestinationChanEntry->usExtraRinTsiDependencyCnt == 1 ) && ( f_fRemovePermanently == TRUE ) ) { if ( pDestinationChanEntry->usRinTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, pDestinationChanEntry->usRinTsstIndex, pDestinationChanEntry->usRinRoutTsiMemIndex, pDestinationChanEntry->TdmConfig.byRinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /*=======================================================================*/ /* Update the global mixer pointers. */ if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == usLoadOrAccumulateEventIndex && pSharedInfo->MixerInfo.usLastBridgeEventPtr == pDestinationChanEntry->usSubStoreEventIndex ) { /* There is no more bridge entry in the mixer link list. */ pSharedInfo->MixerInfo.usFirstBridgeEventPtr = cOCT6100_INVALID_INDEX; pSharedInfo->MixerInfo.usLastBridgeEventPtr = cOCT6100_INVALID_INDEX; } else if ( pSharedInfo->MixerInfo.usFirstBridgeEventPtr == usLoadOrAccumulateEventIndex ) { pSharedInfo->MixerInfo.usFirstBridgeEventPtr = pStoreEventEntry->usNextEventPtr; } else if ( pSharedInfo->MixerInfo.usLastBridgeEventPtr == pDestinationChanEntry->usSubStoreEventIndex ) { pSharedInfo->MixerInfo.usLastBridgeEventPtr = usPreviousEventIndex; } /*=======================================================================*/ /*=======================================================================*/ /* Check if must remove the Sin copy event from the list. */ if ( ( pDestinationChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) && ( f_fRemovePermanently == TRUE ) ) { /* Now remove the copy event from the event list. */ ulResult = Oct6100ApiMixerEventRemove( f_pApiInstance, pDestinationChanEntry->usSinCopyEventIndex, cOCT6100_EVENT_TYPE_SIN_COPY ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*=======================================================================*/ /*=======================================================================*/ if ( f_fRemovePermanently == TRUE ) { /* Set the event entries as free. */ pLoadEventEntry->fReserved = FALSE; pLoadEventEntry->usEventType = cOCT6100_INVALID_EVENT; pLoadEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; pStoreEventEntry->fReserved = FALSE; pStoreEventEntry->usEventType = cOCT6100_INVALID_EVENT; pStoreEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; if ( pDestinationChanEntry->usSinCopyEventIndex != cOCT6100_INVALID_INDEX ) { mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( pSharedInfo, pCopyEventEntry, pDestinationChanEntry->usSinCopyEventIndex ); pCopyEventEntry->fReserved = FALSE; pCopyEventEntry->usEventType = cOCT6100_INVALID_EVENT; pCopyEventEntry->usNextEventPtr = cOCT6100_INVALID_INDEX; } } /* Flexible mixer for this channel not created anymore. */ pDestinationParticipant->fFlexibleMixerCreated = FALSE; /*=======================================================================*/ } /*=======================================================================*/ } else /* if ( pDestinationChanEntry->fFlexibleMixerCreated == FALSE ) */ { /* This point should never be reached. */ return cOCT6100_ERR_FATAL_C9; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReleaseBridgeEntry Description: Release an entry from the bridge list. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usBridgeIndex List entry reserved. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReleaseBridgeEntry( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usBridgeIndex ) { PVOID pBridgeAlloc; UINT32 ulResult; mOCT6100_GET_CONF_BRIDGE_ALLOC_PNT( f_pApiInstance->pSharedInfo, pBridgeAlloc ) ulResult = OctapiLlmAllocDealloc( pBridgeAlloc, f_usBridgeIndex ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_2A; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetPrevLastSubStoreEvent Description: This function will search for the first valid LastSubStoreEvent in a bridge located before the current bridge in the bridge link list. If the function does not find an event before reaching the end of the mixers list, then the event head node will be used as the last Store or SubStore event. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pusBridgeEntry Bridge entry. f_usBridgeFirstLoadEventPtr Load index to check against. First valid sub store index. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiGetPrevLastSubStoreEvent( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usBridgeIndex, IN UINT16 f_usBridgeFirstLoadEventPtr, OUT PUINT16 f_pusLastSubStoreEventIndex ) { tPOCT6100_API_CONF_BRIDGE pBridgeEntry; tPOCT6100_API_MIXER_EVENT pTempMixerEntry; UINT16 usNextEventPtr; UINT16 usHeadEventPtr; UINT16 usLastSubStoreEventPtr; UINT32 ulLoopCount = 0; UINT16 usCurrentPtr; UINT32 ulResult = cOCT6100_ERR_OK; /* Get current entry to obtain the link to the previous entry.*/ mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, f_usBridgeIndex ); /* Since we have flexible bridges, we have to */ /* run down the list and check for the appropriate event. */ /* Travel down the list for the last Store or Sub/Store event before the bridge. */ if ( f_pApiInstance->pSharedInfo->MixerInfo.usLastSoutCopyEventPtr == cOCT6100_INVALID_INDEX ) { /* The only node in the list then is the head node.*/ usHeadEventPtr = cOCT6100_MIXER_HEAD_NODE; } else { usHeadEventPtr = f_pApiInstance->pSharedInfo->MixerInfo.usLastSoutCopyEventPtr; } mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempMixerEntry, usHeadEventPtr ); usLastSubStoreEventPtr = usHeadEventPtr; usNextEventPtr = pTempMixerEntry->usNextEventPtr; usCurrentPtr = usHeadEventPtr; while( usCurrentPtr != f_usBridgeFirstLoadEventPtr ) { if ( ( pTempMixerEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_STORE ) || ( pTempMixerEntry->usEventType == cOCT6100_MIXER_CONTROL_MEM_SUB_STORE ) ) { usLastSubStoreEventPtr = usNextEventPtr; } /* Next pointer. */ usCurrentPtr = usNextEventPtr; usNextEventPtr = pTempMixerEntry->usNextEventPtr; /* Check if next event pointer is valid. */ if ( ( ( f_usBridgeFirstLoadEventPtr != usCurrentPtr ) && ( pTempMixerEntry->usNextEventPtr == cOCT6100_INVALID_INDEX ) ) || ( pTempMixerEntry->usNextEventPtr == cOCT6100_MIXER_HEAD_NODE ) ) return cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND; if ( usNextEventPtr != cOCT6100_INVALID_INDEX ) mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTempMixerEntry, usNextEventPtr ); ulLoopCount++; if ( ulLoopCount == cOCT6100_MAX_LOOP ) return cOCT6100_ERR_FATAL_CA; } /* Return the result to the user. */ *f_pusLastSubStoreEventIndex = usLastSubStoreEventPtr; return ulResult; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetPreviousEvent Description: This is a recursive function, it requires an entry event index and will run down the list until it finds the node just before the one required. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usEntryIndex Event entry index. f_pusBridgeEntry Bridge entry. f_pusPreviousIndex Previous index. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiGetPreviousEvent( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usEntryIndex, IN UINT16 f_usSearchedIndex, IN UINT16 f_usLoopCnt, OUT PUINT16 f_pusPreviousIndex ) { tPOCT6100_API_MIXER_EVENT pCurrentEntry; UINT32 ulResult; /* Get current entry to obtain the link to the previous entry. */ mOCT6100_GET_MIXER_EVENT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pCurrentEntry, f_usEntryIndex ); /* Avoid stack overflows. */ if ( f_usLoopCnt == cOCT6100_MAX_MIXER_EVENTS ) return cOCT6100_ERR_FATAL_E3; if ( pCurrentEntry->usNextEventPtr == cOCT6100_INVALID_INDEX ) { /* Event not found. */ ulResult = cOCT6100_ERR_CONF_MIXER_EVENT_NOT_FOUND; } else if ( pCurrentEntry->usNextEventPtr == f_usSearchedIndex ) { /* We found our node. */ *f_pusPreviousIndex = f_usEntryIndex; ulResult = cOCT6100_ERR_OK; } else { /* Keep searching.*/ f_usLoopCnt++; ulResult = Oct6100ApiGetPreviousEvent( f_pApiInstance, pCurrentEntry->usNextEventPtr, f_usSearchedIndex, f_usLoopCnt, f_pusPreviousIndex ); } return ulResult; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiBridgeSetDominantSpeaker Description: This function will set the index of the dominant speaker for the channel index specified. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usChannelIndex Index of the channel where the API must set the current dominant speaker for the conference. f_usDominantSpeakerIndex Index of the channel which is the dominant speaker in the conference. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiBridgeSetDominantSpeaker( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usChannelIndex, IN UINT16 f_usDominantSpeakerIndex ) { UINT32 ulBaseAddress; UINT32 ulFeatureBytesOffset; UINT32 ulFeatureBitOffset; UINT32 ulFeatureFieldLength; UINT32 ulResult; UINT32 ulTempData; UINT32 ulMask; tPOCT6100_API_CHANNEL pEchoChanEntry; mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChanEntry, f_usChannelIndex ); ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usChannelIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + f_pApiInstance->pSharedInfo->MemoryMap.ulChanRootConfOfst; ulFeatureBytesOffset = f_pApiInstance->pSharedInfo->MemoryMap.DominantSpeakerFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = f_pApiInstance->pSharedInfo->MemoryMap.DominantSpeakerFieldOfst.byBitOffset; ulFeatureFieldLength = f_pApiInstance->pSharedInfo->MemoryMap.DominantSpeakerFieldOfst.byFieldSize; /* Retrieve the current configuration. */ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChanEntry, ulBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear previous value set in the feature field.*/ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); ulTempData &= (~ulMask); ulTempData |= ( ( f_usDominantSpeakerIndex ) << ulFeatureBitOffset ); /* Save the new dominant speaker. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChanEntry, ulBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReleaseFlexConfParticipantEntry Description: Release an entry from the flexible conferencing participant list. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usParticipantIndex List entry reserved. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReleaseFlexConfParticipantEntry( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usParticipantIndex ) { PVOID pParticipantAlloc; UINT32 ulResult; mOCT6100_GET_FLEX_CONF_PARTICIPANT_ALLOC_PNT( f_pApiInstance->pSharedInfo, pParticipantAlloc ) ulResult = OctapiLlmAllocDealloc( pParticipantAlloc, f_usParticipantIndex ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_2A; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_debug.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains functions used to debug the OCT6100. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 58 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "oct6100api/oct6100_apiud.h" #include "oct6100api/oct6100_apiud.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_channel_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_debug_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_channel_priv.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_memory_priv.h" #include "oct6100_debug_priv.h" #include "oct6100_version.h" /**************************** PRIVATE FUNCTIONS ****************************/ #ifndef cOCT6100_REMOVE_EVENTS /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_events.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains functions used to retrieve tone and playout events. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 79 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "oct6100api/oct6100_apiud.h" #include "apilib/octapi_llman.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_channel_inst.h" #include "oct6100api/oct6100_events_inst.h" #include "oct6100api/oct6100_tone_detection_inst.h" #include "oct6100api/oct6100_playout_buf_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_events_pub.h" #include "oct6100api/oct6100_tone_detection_pub.h" #include "oct6100api/oct6100_playout_buf_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_channel_priv.h" #include "oct6100_events_priv.h" #include "oct6100_tone_detection_priv.h" #include "oct6100_playout_buf_priv.h" /**************************** PUBLIC FUNCTIONS *****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100EventGetTone Description: Retreives an array of tone events. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pEventGetTone Pointer to structure used to store the Tone events. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100EventGetToneDef( tPOCT6100_EVENT_GET_TONE f_pEventGetTone ) { f_pEventGetTone->pToneEvent = NULL; f_pEventGetTone->ulMaxToneEvent = 1; f_pEventGetTone->ulNumValidToneEvent = cOCT6100_INVALID_VALUE; f_pEventGetTone->fMoreEvents = FALSE; f_pEventGetTone->fResetBufs = FALSE; return cOCT6100_ERR_OK; } static UINT32 Oct6100EventGetTone( tPOCT6100_INSTANCE_API f_pApiInstance, tPOCT6100_EVENT_GET_TONE f_pEventGetTone ) { tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; UINT32 ulSerRes = cOCT6100_ERR_OK; UINT32 ulFncRes = cOCT6100_ERR_OK; /* Set the process context of the serialize structure. */ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; /* Seize all list semaphores needed by this function. */ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); if ( ulSerRes == cOCT6100_ERR_OK ) { /* Call the serialized function. */ ulFncRes = Oct6100EventGetToneSer( f_pApiInstance, f_pEventGetTone ); } else { return ulSerRes; } /* Release the seized semaphores. */ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); /* If an error occured then return the error code. */ if ( ulSerRes != cOCT6100_ERR_OK ) return ulSerRes; if ( ulFncRes != cOCT6100_ERR_OK ) return ulFncRes; return cOCT6100_ERR_OK; } /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetEventsSwSizes Description: Gets the sizes of all portions of the API instance pertinent to the management of the tone events and playout events software buffers. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pOpenChip Pointer to chip configuration struct. f_pInstSizes Pointer to struct containing instance sizes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiGetEventsSwSizes( IN tPOCT6100_CHIP_OPEN f_pOpenChip, OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) { { UINT32 ulTempVar; /* Memory needed by soft tone event buffers. */ /* Add 1 to the circular buffer such that all user requested events can fit in the circular queue. */ f_pInstSizes->ulSoftToneEventsBuffer = ( f_pOpenChip->ulSoftToneEventsBufSize + 1 ) * sizeof( tOCT6100_API_TONE_EVENT ); /* Round off the sizes of the soft buffers above. */ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulSoftToneEventsBuffer, ulTempVar ) } { UINT32 ulTempVar; /* Memory needed by soft playout stop event buffers. */ if ( f_pOpenChip->ulSoftBufferPlayoutEventsBufSize != cOCT6100_INVALID_VALUE ) { f_pInstSizes->ulSoftBufPlayoutEventsBuffer = ( f_pOpenChip->ulSoftBufferPlayoutEventsBufSize + 1 ) * sizeof( tOCT6100_API_BUFFER_PLAYOUT_EVENT ); /* Round off the sizes of the soft buffers above. */ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulSoftBufPlayoutEventsBuffer, ulTempVar ) } else /* if ( f_pInstSizes->ulSoftBufferPlayoutEventsBufSize == cOCT6100_INVALID_VALUE ) */ { f_pInstSizes->ulSoftBufPlayoutEventsBuffer = 0; } } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100EventGetToneSer Description: Retreives an array of tone event from the software event buffer. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pEventGetTone Pointer to structure which will contain the retreived events. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100EventGetToneSer( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN OUT tPOCT6100_EVENT_GET_TONE f_pEventGetTone ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_TONE_EVENT pSoftEvent; UINT32 ulSoftReadPnt; UINT32 ulSoftWritePnt; UINT32 ulSoftBufSize; UINT32 ulNumEventsReturned; UINT32 ulResult; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Check the parameters given by the user. */ if ( f_pEventGetTone->fResetBufs != TRUE && f_pEventGetTone->fResetBufs != FALSE ) return cOCT6100_ERR_EVENTS_GET_TONE_RESET_BUFS; /* Check max tones. */ if ( f_pEventGetTone->ulMaxToneEvent > pSharedInfo->ChipConfig.ulSoftToneEventsBufSize ) return cOCT6100_ERR_EVENTS_MAX_TONES; if ( f_pEventGetTone->fResetBufs == FALSE ) { /* Check if the events need to be fetched from the chip buffer. */ ulSoftReadPnt = pSharedInfo->SoftBufs.ulToneEventBufferReadPtr; ulSoftWritePnt = pSharedInfo->SoftBufs.ulToneEventBufferWritePtr; if ( ulSoftReadPnt == ulSoftWritePnt ) { ulResult = Oct6100ApiTransferToneEvents( f_pApiInstance, f_pEventGetTone->fResetBufs ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* If there are no events in the soft buffer then there are none in the chip */ /* either, so return the empty case. Else, return the events in the buffer. */ ulSoftReadPnt = pSharedInfo->SoftBufs.ulToneEventBufferReadPtr; ulSoftWritePnt = pSharedInfo->SoftBufs.ulToneEventBufferWritePtr; ulSoftBufSize = pSharedInfo->SoftBufs.ulToneEventBufferSize; if ( ulSoftReadPnt != ulSoftWritePnt ) { ulNumEventsReturned = 0; while( (ulSoftReadPnt != ulSoftWritePnt) && ( ulNumEventsReturned != f_pEventGetTone->ulMaxToneEvent) ) { /* Get a pointer to the first event in the buffer. */ mOCT6100_GET_TONE_EVENT_BUF_PNT( pSharedInfo, pSoftEvent ) pSoftEvent += ulSoftReadPnt; f_pEventGetTone->pToneEvent[ ulNumEventsReturned ].ulChannelHndl = pSoftEvent->ulChannelHandle; f_pEventGetTone->pToneEvent[ ulNumEventsReturned ].ulUserChanId = pSoftEvent->ulUserChanId; f_pEventGetTone->pToneEvent[ ulNumEventsReturned ].ulTimestamp = pSoftEvent->ulTimestamp; f_pEventGetTone->pToneEvent[ ulNumEventsReturned ].ulEventType = pSoftEvent->ulEventType; f_pEventGetTone->pToneEvent[ ulNumEventsReturned ].ulToneDetected = pSoftEvent->ulToneDetected; f_pEventGetTone->pToneEvent[ ulNumEventsReturned ].ulExtToneDetectionPort = pSoftEvent->ulExtToneDetectionPort; /* Update the pointers of the soft buffer. */ ulSoftReadPnt++; if ( ulSoftReadPnt == ulSoftBufSize ) ulSoftReadPnt = 0; ulNumEventsReturned++; } pSharedInfo->SoftBufs.ulToneEventBufferReadPtr = ulSoftReadPnt; /* Detemine if there are more events pending in the soft buffer. */ if ( ulSoftReadPnt != ulSoftWritePnt ) f_pEventGetTone->fMoreEvents = TRUE; else /* ( ulSoftReadPnt == ulSoftWritePnt ) */ { f_pEventGetTone->fMoreEvents = FALSE; /* Remember this state in the interrupt manager. */ pSharedInfo->IntrptManage.fToneEventsPending = FALSE; } f_pEventGetTone->ulNumValidToneEvent = ulNumEventsReturned; } else { /* No valid tone.*/ f_pEventGetTone->ulNumValidToneEvent = 0; f_pEventGetTone->fMoreEvents = FALSE; /* Remember this state in the interrupt manager. */ pSharedInfo->IntrptManage.fToneEventsPending = FALSE; return cOCT6100_ERR_EVENTS_TONE_BUF_EMPTY; } } else /* ( f_pEventGetTone->fResetBufs == TRUE ) */ { /* Empty the hardware buffer. */ ulResult = Oct6100ApiTransferToneEvents( f_pApiInstance, f_pEventGetTone->fResetBufs ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* If the buffers are to be reset then update the pointers and full flag. */ pSharedInfo->SoftBufs.ulToneEventBufferReadPtr = 0; pSharedInfo->SoftBufs.ulToneEventBufferWritePtr = 0; f_pEventGetTone->fMoreEvents = FALSE; f_pEventGetTone->ulNumValidToneEvent = 0; /* Remember this state in the interrupt manager. */ pSharedInfo->IntrptManage.fToneEventsPending = FALSE; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiTransferToneEvents Description: Transfers all tone events from the PGSP event out chip buffer to the soft buffer. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulResetBuf Reset flag. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiTransferToneEvents( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulResetBuf ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_TONE_EVENT pSoftEvent; tPOCT6100_API_CHANNEL pEchoChannel; tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_READ_PARAMS ReadParams; tOCT6100_READ_BURST_PARAMS BurstParams; UINT32 ulChipBufFill; UINT32 ulChipWritePtr = 0; UINT32 ulChipReadPtr = 0; UINT32 usChannelIndex; UINT32 ulBaseTimestamp; UINT32 ulToneCnt; UINT32 ulNumWordsToRead; UINT32 ulResult; UINT32 i, j; UINT16 usReadData; UINT16 ausReadData[ cOCT6100_NUM_WORDS_PER_TONE_EVENT ]; UINT32 ulExtToneDetectionPort; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; /* If the buffer is to be reset then clear the overflow flag. */ if ( f_ulResetBuf == TRUE ) { pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt = 0; } /* Set some parameters of read struct. */ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; /* Get the current read pointer of the chip buffer. */ ReadParams.ulReadAddress = cOCT6100_TONE_EVENT_READ_PTR_REG; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulChipReadPtr = usReadData; /* Now get the current write pointer. */ ReadParams.ulReadAddress = cOCT6100_TONE_EVENT_WRITE_PTR_REG; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulChipWritePtr = usReadData; ulChipBufFill = (( ulChipWritePtr - ulChipReadPtr ) & ( cOCT6100_NUM_PGSP_EVENT_OUT - 1 )); /* Set some parameters of write structs. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; BurstParams.pProcessContext = f_pApiInstance->pProcessContext; BurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* Read in the tone event one at a time. */ for ( i = 0; i < ulChipBufFill; i++ ) { /* Skip the event processing if the buffer is to be reset. */ if ( f_ulResetBuf == TRUE ) { /* Update the control variables of the buffer. */ ulChipReadPtr++; if ( cOCT6100_NUM_PGSP_EVENT_OUT == ulChipReadPtr ) ulChipReadPtr = 0; } else { /* Read in the event only if there's enough room in the soft buffer, and */ /* the chip buffer is NOT to be reset. */ if ( ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferReadPtr) && ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferSize || pSharedInfo->SoftBufs.ulToneEventBufferReadPtr != 0) ) { BurstParams.ulReadAddress = cOCT6100_PGSP_EVENT_OUT_BASE + ( ulChipReadPtr * cOCT6100_PGSP_TONE_EVENT_SIZE ); BurstParams.pusReadData = ausReadData; ulNumWordsToRead = cOCT6100_PGSP_TONE_EVENT_SIZE / 2; while ( ulNumWordsToRead > 0 ) { if ( ulNumWordsToRead > pSharedInfo->ChipConfig.usMaxRwAccesses ) { BurstParams.ulReadLength = pSharedInfo->ChipConfig.usMaxRwAccesses; } else { BurstParams.ulReadLength = ulNumWordsToRead; } mOCT6100_DRIVER_READ_BURST_API( BurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; BurstParams.pusReadData += BurstParams.ulReadLength; BurstParams.ulReadAddress += BurstParams.ulReadLength * 2; ulNumWordsToRead -= BurstParams.ulReadLength; } /* Verify if the event is valid. */ if ( ( ausReadData[ 0 ] & cOCT6100_VALID_TONE_EVENT ) == 0x0 ) return cOCT6100_ERR_FATAL_2D; /* First extract the channel number of the tone event. */ usChannelIndex = ausReadData[ 1 ] & 0x3FF; /* Now the timestamp. */ ulBaseTimestamp = ausReadData[ 2 ] << 16; ulBaseTimestamp |= ausReadData[ 3 ]; /* This timestamp is 256 in adwance, must remove 256 frames. */ ulBaseTimestamp -= 256; /* Fetch the channel stucture to validate which event can be reported. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChannel, usChannelIndex ); if ( pEchoChannel->fReserved != TRUE ) { /* Update the control variables of the buffer. */ ulChipReadPtr++; if ( ulChipReadPtr == cOCT6100_NUM_PGSP_EVENT_OUT ) ulChipReadPtr = 0; /* This channel has been closed since the generation of the event. */ continue; } /* Extract the extended tone detection port if available. */ if ( pEchoChannel->ulExtToneChanMode == cOCT6100_API_EXT_TONE_SIN_PORT_MODE ) { ulExtToneDetectionPort = cOCT6100_CHANNEL_PORT_SIN; } else if ( pEchoChannel->ulExtToneChanMode == cOCT6100_API_EXT_TONE_RIN_PORT_MODE ) { ulExtToneDetectionPort = cOCT6100_CHANNEL_PORT_RIN; /* Modify the channel index. */ usChannelIndex = pEchoChannel->usExtToneChanIndex; /* Change the channel entry to the original one for statistical purposes. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChannel, usChannelIndex ); } else /* pEchoChannel->ulExtToneChanMode == cOCT6100_API_EXT_TONE_DISABLED */ { ulExtToneDetectionPort = cOCT6100_INVALID_VALUE; } ulToneCnt = 0; /* Verify all the possible events that might have been detected. */ for ( j = 4; j < cOCT6100_NUM_WORDS_PER_TONE_EVENT; j++ ) { if ( (( ausReadData[ j ] >> 8 ) & 0x7 ) != 0x0 ) { /* This tone generated an event, now check if event is masked for the channel. */ if ((( pEchoChannel->aulToneConf[ ulToneCnt / 32 ] >> ( 31 - ( ulToneCnt % 32 ))) & 0x1) == 1 ) { /* If enough space. */ if ( ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferReadPtr) && ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferSize || pSharedInfo->SoftBufs.ulToneEventBufferReadPtr != 0) ) { /* The tone event is not masked, The API can create a soft tone event. */ mOCT6100_GET_TONE_EVENT_BUF_PNT( pSharedInfo, pSoftEvent ) pSoftEvent += pSharedInfo->SoftBufs.ulToneEventBufferWritePtr; /* Decode the event type. */ switch(( ausReadData[ j ] >> 8 ) & 0x7 ) { case 1: pSoftEvent->ulEventType = cOCT6100_TONE_PRESENT; break; case 2: pSoftEvent->ulEventType = cOCT6100_TONE_STOP; break; case 3: /* This one is a little tricky. We first */ /* generate the "PRESENT" event and then generate the "STOP" event. */ pSoftEvent->ulEventType = cOCT6100_TONE_PRESENT; pSoftEvent->ulChannelHandle = cOCT6100_HNDL_TAG_CHANNEL | (pEchoChannel->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | usChannelIndex; pSoftEvent->ulUserChanId = pEchoChannel->ulUserChanId; pSoftEvent->ulToneDetected = pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID; /* We want the timestamp not to be equal to the "STOP" event, so we subtract one to the detector's value. */ pSoftEvent->ulTimestamp = ( ulBaseTimestamp + ((( ausReadData[ j ] >> 13 ) & 0x7) * cOCT6100_LOCAL_TIMESTAMP_INCREMENT ) ) - 1; pSoftEvent->ulExtToneDetectionPort = ulExtToneDetectionPort; /* Update the control variables of the buffer. */ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr++; if ( pSharedInfo->SoftBufs.ulToneEventBufferWritePtr == pSharedInfo->SoftBufs.ulToneEventBufferSize ) pSharedInfo->SoftBufs.ulToneEventBufferWritePtr = 0; /* If enough space for the "STOP" event. */ if ( ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferReadPtr) && ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferSize || pSharedInfo->SoftBufs.ulToneEventBufferReadPtr != 0) ) { mOCT6100_GET_TONE_EVENT_BUF_PNT( pSharedInfo, pSoftEvent ) pSoftEvent += pSharedInfo->SoftBufs.ulToneEventBufferWritePtr; pSoftEvent->ulEventType = cOCT6100_TONE_STOP; } else { /* Set the overflow flag of the buffer. */ pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt++; /* We continue in the loop in order to empty the hardware buffer. */ continue; } break; case 4: pSoftEvent->ulEventType = cOCT6100_TONE_PRESENT; break; default: pSharedInfo->ErrorStats.ulToneDetectorErrorCnt++; /* do not process this packet*/ continue; } pSoftEvent->ulChannelHandle = cOCT6100_HNDL_TAG_CHANNEL | (pEchoChannel->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | usChannelIndex; pSoftEvent->ulUserChanId = pEchoChannel->ulUserChanId; pSoftEvent->ulToneDetected = pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID; pSoftEvent->ulTimestamp = ulBaseTimestamp + ((( ausReadData[ j ] >> 13 ) & 0x7) * cOCT6100_LOCAL_TIMESTAMP_INCREMENT ); pSoftEvent->ulExtToneDetectionPort = ulExtToneDetectionPort; /* Update the control variables of the buffer. */ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr++; if ( pSharedInfo->SoftBufs.ulToneEventBufferWritePtr == pSharedInfo->SoftBufs.ulToneEventBufferSize ) pSharedInfo->SoftBufs.ulToneEventBufferWritePtr = 0; /* Set the interrupt manager such that the user knows that some tone events */ /* are pending in the software Q. */ pSharedInfo->IntrptManage.fToneEventsPending = TRUE; } else { /* Set the overflow flag of the buffer. */ pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt++; /* We continue in the loop in order to empty the hardware buffer. */ } } else { BOOL fSSTone; ulResult = Oct6100ApiIsSSTone( f_pApiInstance, pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID, &fSSTone ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( fSSTone == TRUE ) { /* Check if this is a "PRESENT" or "STOP" event */ switch( ( ( ausReadData[ j ] >> 8 ) & 0x7 ) ) { case 1: /* This is a signaling system present event. Keep this in the instance memory. */ pEchoChannel->ulLastSSToneDetected = pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID; pEchoChannel->ulLastSSToneTimestamp = ulBaseTimestamp + ((( ausReadData[ j ] >> 13 ) & 0x7) * cOCT6100_LOCAL_TIMESTAMP_INCREMENT ); break; case 2: /* This is the "STOP" event, invalidate the last value. The user does not want to know about this. */ pEchoChannel->ulLastSSToneDetected = cOCT6100_INVALID_VALUE; pEchoChannel->ulLastSSToneTimestamp = cOCT6100_INVALID_VALUE; break; default: break; } } } } ulToneCnt++; /* Check the other tone of this word. */ if ( ( ausReadData[ j ] & 0x7 ) != 0x0 ) { if ((( pEchoChannel->aulToneConf[ ulToneCnt / 32 ] >> ( 31 - ( ulToneCnt % 32 ))) & 0x1) == 1 ) { /* If enough space. */ if ( ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferReadPtr) && ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferSize || pSharedInfo->SoftBufs.ulToneEventBufferReadPtr != 0) ) { /* The tone event is not masked, The API can create a soft tone event. */ mOCT6100_GET_TONE_EVENT_BUF_PNT( pSharedInfo, pSoftEvent ) pSoftEvent += pSharedInfo->SoftBufs.ulToneEventBufferWritePtr; /* Decode the event type. */ switch(( ausReadData[ j ] ) & 0x7 ) { case 1: pSoftEvent->ulEventType = cOCT6100_TONE_PRESENT; break; case 2: pSoftEvent->ulEventType = cOCT6100_TONE_STOP; break; case 3: /* This one is a little tricky. We first */ /* generate the "PRESENT" event and then generate the "STOP" event. */ pSoftEvent->ulEventType = cOCT6100_TONE_PRESENT; pSoftEvent->ulChannelHandle = cOCT6100_HNDL_TAG_CHANNEL | (pEchoChannel->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | usChannelIndex; pSoftEvent->ulUserChanId = pEchoChannel->ulUserChanId; pSoftEvent->ulToneDetected = pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID; /* We want the timestamp not to be equal to the "STOP" event, so we subtract one to the detector's value. */ pSoftEvent->ulTimestamp = ( ulBaseTimestamp + ((( ausReadData[ j ] >> 5 ) & 0x7) * cOCT6100_LOCAL_TIMESTAMP_INCREMENT ) ) - 1; pSoftEvent->ulExtToneDetectionPort = ulExtToneDetectionPort; /* Update the control variables of the buffer. */ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr++; if ( pSharedInfo->SoftBufs.ulToneEventBufferWritePtr == pSharedInfo->SoftBufs.ulToneEventBufferSize ) pSharedInfo->SoftBufs.ulToneEventBufferWritePtr = 0; /* If enough space for the "STOP" event. */ if ( ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferReadPtr) && ((pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1) != pSharedInfo->SoftBufs.ulToneEventBufferSize || pSharedInfo->SoftBufs.ulToneEventBufferReadPtr != 0) ) { mOCT6100_GET_TONE_EVENT_BUF_PNT( pSharedInfo, pSoftEvent ) pSoftEvent += pSharedInfo->SoftBufs.ulToneEventBufferWritePtr; pSoftEvent->ulEventType = cOCT6100_TONE_STOP; } else { /* Set the overflow flag of the buffer. */ pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt++; /* We continue in the loop in order to empty the hardware buffer. */ continue; } break; case 4: pSoftEvent->ulEventType = cOCT6100_TONE_PRESENT; break; default: pSharedInfo->ErrorStats.ulToneDetectorErrorCnt++; /* Do not process this packet. */ continue; } pSoftEvent->ulChannelHandle = cOCT6100_HNDL_TAG_CHANNEL | (pEchoChannel->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | usChannelIndex; pSoftEvent->ulUserChanId = pEchoChannel->ulUserChanId; pSoftEvent->ulToneDetected = pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID; pSoftEvent->ulTimestamp = ulBaseTimestamp + ((( ausReadData[ j ] >> 5 ) & 0x7) * cOCT6100_LOCAL_TIMESTAMP_INCREMENT ); pSoftEvent->ulExtToneDetectionPort = ulExtToneDetectionPort; /* Update the control variables of the buffer. */ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr++; if ( pSharedInfo->SoftBufs.ulToneEventBufferWritePtr == pSharedInfo->SoftBufs.ulToneEventBufferSize ) pSharedInfo->SoftBufs.ulToneEventBufferWritePtr = 0; /* Set the interrupt manager such that the user knows that some tone events */ /* are pending in the software Q. */ pSharedInfo->IntrptManage.fToneEventsPending = TRUE; } else { /* Set the overflow flag of the buffer. */ pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt++; /* We continue in the loop in order to empty the hardware buffer. */ } } else { BOOL fSSTone; ulResult = Oct6100ApiIsSSTone( f_pApiInstance, pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID, &fSSTone ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( fSSTone == TRUE ) { /* Check if this is a "PRESENT" event. */ switch ( ( ausReadData[ j ] ) & 0x7 ) { case 1: /* This is a signaling system present event. Keep this in the instance memory. */ pEchoChannel->ulLastSSToneDetected = pSharedInfo->ImageInfo.aToneInfo[ ulToneCnt ].ulToneID; pEchoChannel->ulLastSSToneTimestamp = ulBaseTimestamp + ((( ausReadData[ j ] >> 5 ) & 0x7) * cOCT6100_LOCAL_TIMESTAMP_INCREMENT ); break; case 2: /* This is the "STOP" event, invalidate the last value. The user does not want to know about this. */ pEchoChannel->ulLastSSToneDetected = cOCT6100_INVALID_VALUE; pEchoChannel->ulLastSSToneTimestamp = cOCT6100_INVALID_VALUE; break; default: break; } } } } ulToneCnt++; } } else { /* Set the overflow flag of the buffer. */ pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt++; /* We continue in the loop in order to empty the hardware buffer. */ } /* Update the control variables of the buffer. */ ulChipReadPtr++; if ( ulChipReadPtr == cOCT6100_NUM_PGSP_EVENT_OUT ) ulChipReadPtr = 0; } } /* Write the value of the new Read pointer.*/ WriteParams.ulWriteAddress = cOCT6100_TONE_EVENT_READ_PTR_REG; WriteParams.usWriteData = (UINT16)( ulChipReadPtr ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100BufferPlayoutTransferEvents Description: Check all channels that are currently playing a buffer and generate an event if a buffer has stopped playing. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulResetBuf Reset flag. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100BufferPlayoutTransferEvents( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulResetBuf ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHANNEL pEchoChannel; UINT32 ulChannelIndex; UINT32 ulResult; UINT32 ulLastBufPlayoutEventBufferOverflowCnt; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; /* If the buffer is to be reset then clear the overflow flag. */ if ( f_ulResetBuf == TRUE ) { pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt = 0; /* We are done for now. */ /* No need to check for new events since the user requested to empty the soft buffer. */ return cOCT6100_ERR_OK; } /* Check if buffer playout has been activated on some ports. */ if ( pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts == 0 ) { /* Buffer playout has not been activated on any channel, */ /* let's not waste time here. */ return cOCT6100_ERR_OK; } /* Save the current overflow count. We want to know if an overflow occured to get out of the loop. */ ulLastBufPlayoutEventBufferOverflowCnt = pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt; /* Search through the list of API channel entry for the ones that need playout event checking. */ for ( ulChannelIndex = 0; ulChannelIndex < pSharedInfo->ChipConfig.usMaxChannels; ulChannelIndex++ ) { mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChannel, ulChannelIndex ); /* Check if buffer playout is active on this channel, using the optimization flag. */ /* This flag is redundant of other flags used for playout, but will make the above loop */ /* much faster. This is needed since this function is called very frequently on systems */ /* which use buffer playout stop events. */ if ( pEchoChannel->fBufPlayoutActive == TRUE ) { /* Read in the event only if there's enough room in the soft buffer. */ if ( ulLastBufPlayoutEventBufferOverflowCnt == pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt ) { /* Check Rout buffer playout first. */ if ( ( pEchoChannel->fRinBufPlayoutNotifyOnStop == TRUE ) && ( pEchoChannel->fRinBufPlaying == TRUE ) ) { ulResult = Oct6100BufferPlayoutCheckForSpecificEvent( f_pApiInstance, ulChannelIndex, cOCT6100_CHANNEL_PORT_ROUT, TRUE, NULL ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } else /* if ( ulLastBufPlayoutEventBufferOverflowCnt != pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt ) */ { /* Get out of the loop, no more events can be inserted in the soft buffer. */ break; } /* An overflow might have been detected in the lower level function. */ /* Check the overflow count once again to make sure there might be room for a next event. */ if ( ulLastBufPlayoutEventBufferOverflowCnt == pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt ) { /* Check Sout buffer playout. */ if ( ( pEchoChannel->fSoutBufPlayoutNotifyOnStop == TRUE ) && ( pEchoChannel->fSoutBufPlaying == TRUE ) ) { ulResult = Oct6100BufferPlayoutCheckForSpecificEvent( f_pApiInstance, ulChannelIndex, cOCT6100_CHANNEL_PORT_SOUT, TRUE, NULL ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } else /* if ( ulLastBufPlayoutEventBufferOverflowCnt != pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt ) */ { /* Get out of the loop, no more events can be inserted in the soft buffer. */ break; } } } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100BufferPlayoutCheckForSpecificEvent Description: Check a specific channel/port for playout buffer events. If asked to, save this event to the software event buffer. Return a flag specifying whether the event was detected or not. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulChannelIndex Index of the channel to be checked. f_ulChannelPort Port of the channel to be checked. f_fSaveToSoftBuffer Save event to software buffer. f_pfEventDetected Whether or not an event was detected. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100BufferPlayoutCheckForSpecificEvent( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulChannelIndex, IN UINT32 f_ulChannelPort, IN BOOL f_fSaveToSoftBuffer, OUT PBOOL f_pfEventDetected ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_BUFFER_PLAYOUT_EVENT pSoftEvent; tPOCT6100_API_CHANNEL pEchoChannel; tOCT6100_READ_PARAMS ReadParams; tOCT6100_GET_TIME GetTimeParms; UINT32 ulResult; UINT16 usReadData; UINT32 ulReadPtrBytesOfst; UINT32 ulReadPtrBitOfst; UINT32 ulReadPtrFieldSize; UINT32 ulWritePtrBytesOfst; UINT32 ulWritePtrBitOfst; UINT32 ulWritePtrFieldSize; UINT32 ulPlayoutBaseAddress; UINT32 ulTempData; UINT32 ulReadPtr; UINT32 ulMask; UINT32 ulWritePtr; UINT32 ulUserEventId; UINT32 ulEventType; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Compare the read and write pointers for matching. If they matched, playout stopped. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChannel, f_ulChannelIndex ); /* Set the playout feature base address. */ ulPlayoutBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_ulChannelIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; if ( f_ulChannelPort == cOCT6100_CHANNEL_PORT_ROUT ) { /* Check on the Rout port. */ ulUserEventId = pEchoChannel->ulRinUserBufPlayoutEventId; ulEventType = pEchoChannel->byRinPlayoutStopEventType; ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.usDwordOffset * 4; ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byBitOffset; ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byFieldSize; ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.usDwordOffset * 4; ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byBitOffset; ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byFieldSize; } else /* if ( f_ulChannelPort == cOCT6100_CHANNEL_PORT_SOUT ) */ { /* Check on the Sout port. */ ulUserEventId = pEchoChannel->ulSoutUserBufPlayoutEventId; ulEventType = pEchoChannel->bySoutPlayoutStopEventType; ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.usDwordOffset * 4; ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byBitOffset; ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byFieldSize; ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.usDwordOffset * 4; ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byBitOffset; ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byFieldSize; } /* Retrieve the current write pointer. */ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulPlayoutBaseAddress + ulWritePtrBytesOfst, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; mOCT6100_CREATE_FEATURE_MASK( ulWritePtrFieldSize, ulWritePtrBitOfst, &ulMask ); /* Store the write pointer.*/ ulWritePtr = ( ulTempData & ulMask ) >> ulWritePtrBitOfst; /* Read the read pointer.*/ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; ReadParams.ulReadAddress = ulPlayoutBaseAddress + ulReadPtrBytesOfst; /* Optimize this access by only reading the word we are interested in. */ if ( ulReadPtrBitOfst < 16 ) ReadParams.ulReadAddress += 2; /* Must read in memory directly since this value is changed by hardware */ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Move data at correct position according to what was read. */ if ( ulReadPtrBitOfst < 16 ) ulTempData = usReadData; else ulTempData = usReadData << 16; mOCT6100_CREATE_FEATURE_MASK( ulReadPtrFieldSize, ulReadPtrBitOfst, &ulMask ); /* Store the read pointer. */ ulReadPtr = ( ulTempData & ulMask ) >> ulReadPtrBitOfst; /* Playout has finished when the read pointer reaches the write pointer. */ if ( ulReadPtr != ulWritePtr ) { /* Still playing -- do not generate an event. */ if ( f_pfEventDetected != NULL ) *f_pfEventDetected = FALSE; } else { /* Buffer stopped playing, generate an event here, if asked. */ if ( ( f_fSaveToSoftBuffer == TRUE ) && ( ( pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr + 1 ) != pSharedInfo->SoftBufs.ulBufPlayoutEventBufferReadPtr ) && ( ( pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr + 1 ) != pSharedInfo->SoftBufs.ulBufPlayoutEventBufferSize || pSharedInfo->SoftBufs.ulBufPlayoutEventBufferReadPtr != 0 ) ) { /* The API can create a soft buffer playout event. */ mOCT6100_GET_BUFFER_PLAYOUT_EVENT_BUF_PNT( pSharedInfo, pSoftEvent ) pSoftEvent += pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr; pSoftEvent->ulChannelHandle = cOCT6100_HNDL_TAG_CHANNEL | (pEchoChannel->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_ulChannelIndex; pSoftEvent->ulUserChanId = pEchoChannel->ulUserChanId; pSoftEvent->ulUserEventId = ulUserEventId; pSoftEvent->ulChannelPort = f_ulChannelPort; /* For now, only this type of event is available. */ pSoftEvent->ulEventType = ulEventType; /* Generate millisecond timestamp. */ GetTimeParms.pProcessContext = f_pApiInstance->pProcessContext; ulResult = Oct6100UserGetTime( &GetTimeParms ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; pSoftEvent->ulTimestamp = ( GetTimeParms.aulWallTimeUs[ 0 ] / 1000 ); pSoftEvent->ulTimestamp += ( GetTimeParms.aulWallTimeUs[ 1 ] ) * ( 0xFFFFFFFF / 1000 ); /* Update the control variables of the buffer. */ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr++; if ( pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr == pSharedInfo->SoftBufs.ulBufPlayoutEventBufferSize ) pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr = 0; /* Set the interrupt manager such that the user knows that some playout events */ /* are pending in the software Q. */ pSharedInfo->IntrptManage.fBufferPlayoutEventsPending = TRUE; } else if ( f_fSaveToSoftBuffer == TRUE ) { /* Set the overflow flag of the buffer. */ pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt++; } /* Update the channel entry to set the playing flag to FALSE. */ /* Select the port of interest. */ if ( f_ulChannelPort == cOCT6100_CHANNEL_PORT_ROUT ) { /* Decrement the number of active buffer playout ports. */ /* No need to check anything here, it's been done in the calling function. */ pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts--; pEchoChannel->fRinBufPlaying = FALSE; pEchoChannel->fRinBufPlayoutNotifyOnStop = FALSE; /* Clear optimization flag if possible. */ if ( ( pEchoChannel->fSoutBufPlaying == FALSE ) && ( pEchoChannel->fSoutBufPlayoutNotifyOnStop == FALSE ) ) { /* Buffer playout is no more active on this channel. */ pEchoChannel->fBufPlayoutActive = FALSE; } } else /* f_ulChannelPort == cOCT6100_CHANNEL_PORT_SOUT */ { /* Decrement the number of active buffer playout ports. */ /* No need to check anything here, it's been done in the calling function. */ pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts--; pEchoChannel->fSoutBufPlaying = FALSE; pEchoChannel->fSoutBufPlayoutNotifyOnStop = FALSE; /* Clear optimization flag if possible. */ if ( ( pEchoChannel->fRinBufPlaying == FALSE ) && ( pEchoChannel->fRinBufPlayoutNotifyOnStop == FALSE ) ) { /* Buffer playout is no more active on this channel. */ pEchoChannel->fBufPlayoutActive = FALSE; } } /* Return that an event was detected. */ if ( f_pfEventDetected != NULL ) *f_pfEventDetected = TRUE; } return cOCT6100_ERR_OK; } #endif /* cOCT6100_REMOVE_EVENTS */ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_interrupts.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains the API's interrupt service routine and all of its sub-functions. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 71 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "oct6100api/oct6100_apiud.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100api/oct6100_events_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_events_priv.h" #include "oct6100_interrupts_priv.h" /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100InterruptServiceRoutine Description: The API's interrupt service routine. This function clears all register ROLs which have generated an interrupt and report the events in the user supplied structure. Also, the tone event and/or playout event buffer will be emptied if valid events are present. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pIntFlags Pointer to structure containing event flags returned to user. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100InterruptServiceRoutineDef( tPOCT6100_INTERRUPT_FLAGS f_pIntFlags ) { f_pIntFlags->fFatalGeneral = FALSE; f_pIntFlags->ulFatalGeneralFlags = 0x0; f_pIntFlags->fFatalReadTimeout = FALSE; f_pIntFlags->fErrorRefreshTooLate = FALSE; f_pIntFlags->fErrorPllJitter = FALSE; f_pIntFlags->fErrorOverflowToneEvents = FALSE; f_pIntFlags->fErrorH100OutOfSync = FALSE; f_pIntFlags->fErrorH100ClkA = FALSE; f_pIntFlags->fErrorH100ClkB = FALSE; f_pIntFlags->fErrorH100FrameA = FALSE; f_pIntFlags->fToneEventsPending = FALSE; f_pIntFlags->fBufferPlayoutEventsPending = FALSE; f_pIntFlags->fApiSynch = FALSE; return cOCT6100_ERR_OK; } static UINT32 Oct6100InterruptServiceRoutine( tPOCT6100_INSTANCE_API f_pApiInstance, tPOCT6100_INTERRUPT_FLAGS f_pIntFlags ) { tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; UINT32 ulResult; UINT32 ulFncRes; /* Set the process context of the serialize structure. */ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; /* Seize the serialization object for the ISR. */ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ulResult = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); if ( ulResult == cOCT6100_ERR_OK ) { /* Call the serialized sub-function. */ ulFncRes = Oct6100InterruptServiceRoutineSer( f_pApiInstance, f_pIntFlags ); } else { return ulResult; } /* Release the serialization object. */ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ulResult = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check for an error in the sub-function. */ if ( ulFncRes != cOCT6100_ERR_OK ) return ulFncRes; return cOCT6100_ERR_OK; } /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiIsrSwInit Description: Initializes portions of API instance associated to the API's interrupt service routine. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiIsrSwInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Set the state of each interrupt group to disabled. The state will */ /* be updated to the true configuration once the configure interrupts function is called. */ pSharedInfo->IntrptManage.byFatalGeneralState = cOCT6100_INTRPT_DISABLED; pSharedInfo->IntrptManage.byFatalMemoryState = cOCT6100_INTRPT_DISABLED; pSharedInfo->IntrptManage.byErrorMemoryState = cOCT6100_INTRPT_DISABLED; pSharedInfo->IntrptManage.byErrorH100State = cOCT6100_INTRPT_DISABLED; pSharedInfo->IntrptManage.byErrorOverflowToneEventsState = cOCT6100_INTRPT_DISABLED; /* Indicate that the mclk interrupt is not active at the moment. */ pSharedInfo->IntrptManage.fMclkIntrptActive = FALSE; /* Indicate that no buffer playout events are pending for the moment. */ pSharedInfo->IntrptManage.fBufferPlayoutEventsPending = FALSE; /* Indicate that no tone events are pending for the moment. */ pSharedInfo->IntrptManage.fToneEventsPending = FALSE; /* The ISR has never been called. */ pSharedInfo->IntrptManage.fIsrCalled = FALSE; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiIsrHwInit Description: Initializes the chip's interrupt registers. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pIntrptConfig Pointer to structure defining how the interrupts should be configured. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiIsrHwInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_INTERRUPT_CONFIGURE f_pIntrptConfig ) { tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; /* Set some parameters of write struct. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; /*==================================================================================*/ /* Enable all the interrupts */ WriteParams.ulWriteAddress = 0x104; WriteParams.usWriteData = 0x0001; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x204; WriteParams.usWriteData = 0x1C05; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x304; WriteParams.usWriteData = 0xFFFF; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x504; WriteParams.usWriteData = 0x0001; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x704; WriteParams.usWriteData = 0x0007; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==================================================================================*/ /* Calculate the number of mclk cycles in 1 ms. */ f_pApiInstance->pSharedInfo->IntrptManage.ulNumMclkCyclesIn1Ms = f_pApiInstance->pSharedInfo->MiscVars.ulMclkFreq / 1000; /* Configure the interrupt registers as requested by the user. */ ulResult = Oct6100InterruptConfigureSer( f_pApiInstance, f_pIntrptConfig, TRUE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100InterruptConfigureSer Description: Configure the operation of interrupt groups. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pIntrptConfig Pointer to interrupt configuration structure. f_fCheckParams Check parameter enable flag. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100InterruptConfigureSer( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_INTERRUPT_CONFIGURE f_pIntrptConfig, IN BOOL f_fCheckParams ) { tPOCT6100_API_INTRPT_CONFIG pIntrptConfig; tPOCT6100_API_INTRPT_MANAGE pIntrptManage; UINT32 ulResult; /* Check for errors. */ if ( f_fCheckParams == TRUE ) { if ( f_pIntrptConfig->ulFatalGeneralConfig != cOCT6100_INTERRUPT_DISABLE && f_pIntrptConfig->ulFatalGeneralConfig != cOCT6100_INTERRUPT_NO_TIMEOUT ) return cOCT6100_ERR_INTRPTS_FATAL_GENERAL_CONFIG; if ( f_pIntrptConfig->ulFatalMemoryConfig != cOCT6100_INTERRUPT_DISABLE && f_pIntrptConfig->ulFatalMemoryConfig != cOCT6100_INTERRUPT_TIMEOUT && f_pIntrptConfig->ulFatalMemoryConfig != cOCT6100_INTERRUPT_NO_TIMEOUT ) return cOCT6100_ERR_INTRPTS_FATAL_MEMORY_CONFIG; if ( f_pIntrptConfig->ulErrorMemoryConfig != cOCT6100_INTERRUPT_DISABLE && f_pIntrptConfig->ulErrorMemoryConfig != cOCT6100_INTERRUPT_TIMEOUT && f_pIntrptConfig->ulErrorMemoryConfig != cOCT6100_INTERRUPT_NO_TIMEOUT ) return cOCT6100_ERR_INTRPTS_DATA_ERR_MEMORY_CONFIG; if ( f_pIntrptConfig->ulErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_DISABLE && f_pIntrptConfig->ulErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_TIMEOUT && f_pIntrptConfig->ulErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_NO_TIMEOUT ) return cOCT6100_ERR_INTRPTS_OVERFLOW_TONE_EVENTS_CONFIG; if ( f_pIntrptConfig->ulErrorH100Config != cOCT6100_INTERRUPT_DISABLE && f_pIntrptConfig->ulErrorH100Config != cOCT6100_INTERRUPT_TIMEOUT && f_pIntrptConfig->ulErrorH100Config != cOCT6100_INTERRUPT_NO_TIMEOUT ) return cOCT6100_ERR_INTRPTS_H100_ERROR_CONFIG; if ( f_pIntrptConfig->ulFatalMemoryTimeout < 10 || f_pIntrptConfig->ulFatalMemoryTimeout > 10000 ) return cOCT6100_ERR_INTRPTS_FATAL_MEMORY_TIMEOUT; if ( f_pIntrptConfig->ulErrorMemoryTimeout < 10 || f_pIntrptConfig->ulErrorMemoryTimeout > 10000 ) return cOCT6100_ERR_INTRPTS_DATA_ERR_MEMORY_TIMEOUT; if ( f_pIntrptConfig->ulErrorOverflowToneEventsTimeout < 10 || f_pIntrptConfig->ulErrorOverflowToneEventsTimeout > 10000 ) return cOCT6100_ERR_INTRPTS_OVERFLOW_TONE_EVENTS_TIMEOUT; if ( f_pIntrptConfig->ulErrorH100Timeout < 10 || f_pIntrptConfig->ulErrorH100Timeout > 10000 ) return cOCT6100_ERR_INTRPTS_H100_ERROR_TIMEOUT; } /* Copy the configuration to the API instance. */ pIntrptConfig = &f_pApiInstance->pSharedInfo->IntrptConfig; pIntrptManage = &f_pApiInstance->pSharedInfo->IntrptManage; pIntrptConfig->byFatalGeneralConfig = (UINT8)( f_pIntrptConfig->ulFatalGeneralConfig & 0xFF ); pIntrptConfig->byFatalMemoryConfig = (UINT8)( f_pIntrptConfig->ulFatalMemoryConfig & 0xFF ); pIntrptConfig->byErrorMemoryConfig = (UINT8)( f_pIntrptConfig->ulErrorMemoryConfig & 0xFF ); pIntrptConfig->byErrorOverflowToneEventsConfig = (UINT8)( f_pIntrptConfig->ulErrorOverflowToneEventsConfig & 0xFF ); pIntrptConfig->byErrorH100Config = (UINT8)( f_pIntrptConfig->ulErrorH100Config & 0xFF ); f_pIntrptConfig->ulFatalMemoryTimeout = ((f_pIntrptConfig->ulFatalMemoryTimeout + 9) / 10) * 10; pIntrptConfig->ulFatalMemoryTimeoutMclk = f_pIntrptConfig->ulFatalMemoryTimeout * pIntrptManage->ulNumMclkCyclesIn1Ms; f_pIntrptConfig->ulErrorMemoryTimeout = ((f_pIntrptConfig->ulErrorMemoryTimeout + 9) / 10) * 10; pIntrptConfig->ulErrorMemoryTimeoutMclk = f_pIntrptConfig->ulErrorMemoryTimeout * pIntrptManage->ulNumMclkCyclesIn1Ms; f_pIntrptConfig->ulErrorOverflowToneEventsTimeout = ((f_pIntrptConfig->ulErrorOverflowToneEventsTimeout + 9) / 10) * 10; pIntrptConfig->ulErrorOverflowToneEventsTimeoutMclk = f_pIntrptConfig->ulErrorOverflowToneEventsTimeout * pIntrptManage->ulNumMclkCyclesIn1Ms; f_pIntrptConfig->ulErrorH100Timeout = ((f_pIntrptConfig->ulErrorH100Timeout + 9) / 10) * 10; pIntrptConfig->ulErrorH100TimeoutMclk = f_pIntrptConfig->ulErrorH100Timeout * pIntrptManage->ulNumMclkCyclesIn1Ms; /* Before writing the new configuration to the chip's registers, make sure that any */ /* interrupts which are either disabled or have no timeout period are not on the */ /* disabled interrupt list. */ /*==================================================================================*/ if ( pIntrptConfig->byFatalGeneralConfig == cOCT6100_INTERRUPT_DISABLE ) pIntrptManage->byFatalGeneralState = cOCT6100_INTRPT_DISABLED; else /* pIntrptConfig->byFatalGeneralConfig == cOCT6100_INTERRUPT_NO_TIMEOUT */ pIntrptManage->byFatalGeneralState = cOCT6100_INTRPT_ACTIVE; /*==================================================================================*/ if ( pIntrptConfig->byFatalMemoryConfig == cOCT6100_INTERRUPT_DISABLE ) pIntrptManage->byFatalMemoryState = cOCT6100_INTRPT_DISABLED; else if ( pIntrptConfig->byFatalMemoryConfig == cOCT6100_INTERRUPT_NO_TIMEOUT ) pIntrptManage->byFatalMemoryState = cOCT6100_INTRPT_ACTIVE; else /* ( pIntrptConfig->byFatalMemoryConfig == cOCT6100_INTERRUPT_TIMEOUT ) */ { if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_DISABLED ) pIntrptManage->byFatalMemoryState = cOCT6100_INTRPT_ACTIVE; } /*==================================================================================*/ if ( pIntrptConfig->byErrorMemoryConfig == cOCT6100_INTERRUPT_DISABLE ) pIntrptManage->byErrorMemoryState = cOCT6100_INTRPT_DISABLED; else if ( pIntrptConfig->byErrorMemoryConfig == cOCT6100_INTERRUPT_NO_TIMEOUT ) pIntrptManage->byErrorMemoryState = cOCT6100_INTRPT_ACTIVE; else /* (pIntrptConfig->byErrorMemoryConfig == cOCT6100_INTERRUPT_TIMEOUT ) */ { if ( pIntrptManage->byErrorMemoryState == cOCT6100_INTRPT_DISABLED ) pIntrptManage->byErrorMemoryState = cOCT6100_INTRPT_ACTIVE; } /*==================================================================================*/ if ( pIntrptConfig->byErrorOverflowToneEventsConfig == cOCT6100_INTERRUPT_DISABLE ) pIntrptManage->byErrorOverflowToneEventsState = cOCT6100_INTRPT_DISABLED; else if ( pIntrptConfig->byErrorOverflowToneEventsConfig == cOCT6100_INTERRUPT_NO_TIMEOUT ) pIntrptManage->byErrorOverflowToneEventsState = cOCT6100_INTRPT_ACTIVE; else /* (pIntrptConfig->byErrorOverflowToneEventsConfig == cOCT6100_INTERRUPT_TIMEOUT ) */ { if ( pIntrptManage->byErrorOverflowToneEventsState == cOCT6100_INTRPT_DISABLED ) pIntrptManage->byErrorOverflowToneEventsState = cOCT6100_INTRPT_ACTIVE; } /*==================================================================================*/ if ( pIntrptConfig->byErrorH100Config == cOCT6100_INTERRUPT_DISABLE ) pIntrptManage->byErrorH100State = cOCT6100_INTRPT_DISABLED; else if ( pIntrptConfig->byErrorH100Config == cOCT6100_INTERRUPT_NO_TIMEOUT ) pIntrptManage->byErrorH100State = cOCT6100_INTRPT_ACTIVE; else /* (pIntrptConfig->byErrorH100Config == cOCT6100_INTERRUPT_TIMEOUT ) */ { if ( pIntrptManage->byErrorH100State == cOCT6100_INTRPT_DISABLED ) pIntrptManage->byErrorH100State = cOCT6100_INTRPT_ACTIVE; } /* Write to the interrupt registers to update the state of each interrupt group. */ ulResult = Oct6100ApiWriteIeRegs( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100InterruptServiceRoutineSer Description: Serialized sub-function of API's interrupt service routine. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pIntFlags Pointer to structure containing event flags returned to user. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100InterruptServiceRoutineSer( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_INTERRUPT_FLAGS f_pIntFlags ) { tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_READ_PARAMS ReadParams; tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulRegister210h; UINT32 ulResult; UINT16 usReadData; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Must update the statistics. Set parameters in read and write structs. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; /* Start by reading registers 210h to determine if any modules have flagged an interrupt. */ ReadParams.ulReadAddress = 0x210; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulRegister210h = usReadData; /* Update the extended mclk counter. */ ulResult = Oct6100ApiReadChipMclkTime( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* If the mclk interrupt is active then check which interrupt timeout periods have expired. */ ReadParams.ulReadAddress = 0x302; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( (usReadData & 0x1) != 0 && pSharedInfo->IntrptManage.fMclkIntrptActive == TRUE ) { /* Update timeout periods. */ ulResult = Oct6100ApiUpdateIntrptTimeouts( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; f_pIntFlags->fApiSynch = TRUE; /* Read registers 210h and 212h again to determine if any modules have flagged an interrupt. */ ReadParams.ulReadAddress = 0x210; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulRegister210h = usReadData; } /* Read the interrupt registers to determine what interrupt conditions have occured. */ ulResult = Oct6100ApiReadIntrptRegs( f_pApiInstance, f_pIntFlags, ulRegister210h ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Empty the tone buffer if any events are pending. */ ulResult = Oct6100ApiTransferToneEvents( f_pApiInstance, FALSE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set the tone events pending flag. */ f_pIntFlags->fToneEventsPending = pSharedInfo->IntrptManage.fToneEventsPending; /* Check for buffer playout events and insert in the software queue -- if activated. */ if ( pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize != 0 ) { ulResult = Oct6100BufferPlayoutTransferEvents( f_pApiInstance, FALSE ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set the buffer playout events pending flag. */ f_pIntFlags->fBufferPlayoutEventsPending = pSharedInfo->IntrptManage.fBufferPlayoutEventsPending; } /* Update the states of each interrupt group. */ ulResult = Oct6100ApiUpdateIntrptStates( f_pApiInstance, f_pIntFlags ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check the state of the NLP timestamp if required.*/ ulResult = Oct6100ApiCheckProcessorState( f_pApiInstance, f_pIntFlags ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write to the necessary IE registers. */ ulResult = Oct6100ApiWriteIntrptRegs( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Schedule the next mclk interrupt, if one is needed. */ ulResult = Oct6100ApiScheduleNextMclkIntrptSer( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Free the interrupt pin of the chip (i.e. remove minimum time requirement between interrupts). */ WriteParams.ulWriteAddress = 0x214; WriteParams.usWriteData = 0x0000; if ( pSharedInfo->ChipConfig.byInterruptPolarity == cOCT6100_ACTIVE_HIGH_POLARITY ) WriteParams.usWriteData |= 0x4000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Indicate that the interrupt ROLs have been treated. */ WriteParams.ulWriteAddress = 0x212; WriteParams.usWriteData = 0x8000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReadIntrptRegs Description: Reads the interrupt registers of all modules currently indicating an interrupt condition. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pIntFlags Pointer to an interrupt flag structure. f_ulRegister210h Value of register 0x210. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReadIntrptRegs( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, OUT tPOCT6100_INTERRUPT_FLAGS f_pIntFlags, IN UINT32 f_ulRegister210h ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHIP_ERROR_STATS pErrorStats; tPOCT6100_API_INTRPT_MANAGE pIntrptManage; tOCT6100_READ_PARAMS ReadParams; tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; UINT16 usReadData; UINT32 ulFeatureBytesOffset; UINT32 ulFeatureBitOffset; UINT32 ulFeatureFieldLength; UINT32 ulTempData = 0; UINT32 ulCounterValue; UINT32 ulMask; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; pErrorStats = &pSharedInfo->ErrorStats; pIntrptManage = &pSharedInfo->IntrptManage; /* Set some parameters of read struct. */ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; /* Set some parameters of write struct. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* CPU registers. */ if ( (f_ulRegister210h & 0x00001) != 0 ) { /*=======================================================================*/ /* Read registers of this module. */ ReadParams.ulReadAddress = 0x102; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check which interrupt(s) were set. */ if ( (usReadData & 0x0001) != 0 ) { f_pIntFlags->fFatalReadTimeout = TRUE; pErrorStats->ulInternalReadTimeoutCnt++; } pIntrptManage->usRegister102h = usReadData; /*=======================================================================*/ } else { pIntrptManage->usRegister102h = 0x0; } /* MAIN registers. */ if ( (f_ulRegister210h & 0x00002) != 0 ) { /*=======================================================================*/ /* Read registers of this module. */ ReadParams.ulReadAddress = 0x202; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save current value in instance. */ pIntrptManage->usRegister202h = usReadData; /* Check which interrupts were set. */ if ( (usReadData & 0x0001) != 0 ) { f_pIntFlags->fErrorRefreshTooLate = TRUE; pErrorStats->ulSdramRefreshTooLateCnt++; } if ( (usReadData & 0x0800) != 0 ) { f_pIntFlags->ulFatalGeneralFlags |= cOCT6100_FATAL_GENERAL_ERROR_TYPE_1; f_pIntFlags->fFatalGeneral = TRUE; pErrorStats->fFatalChipError = TRUE; } if ( (usReadData & 0x1000) != 0 ) { f_pIntFlags->ulFatalGeneralFlags |= cOCT6100_FATAL_GENERAL_ERROR_TYPE_2; f_pIntFlags->fFatalGeneral = TRUE; pErrorStats->fFatalChipError = TRUE; } if ( (usReadData & 0x0400) != 0 ) { f_pIntFlags->fErrorPllJitter = TRUE; pErrorStats->ulPllJitterErrorCnt++; /* Update the PLL jitter error count here. */ if ( pSharedInfo->DebugInfo.fPouchCounter == TRUE ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.PouchCounterFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.PouchCounterFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.PouchCounterFieldOfst.byFieldSize; ulResult = Oct6100ApiReadDword( f_pApiInstance, cOCT6100_POUCH_BASE + ulFeatureBytesOffset, &ulTempData ); /* Read previous value set in the feature field. */ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); /* Update counter. */ ulCounterValue = ulTempData & ulMask; ulCounterValue = ulCounterValue >> ulFeatureBitOffset; ulCounterValue ++; /* Handle wrap around case. */ ulCounterValue &= ( 1 << ulFeatureFieldLength ) - 1; /* Clear old counter value. */ ulTempData &= (~ulMask); ulTempData |= ulCounterValue << ulFeatureBitOffset; /* Write the DWORD where the field is located.*/ ulResult = Oct6100ApiWriteDword( f_pApiInstance, cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ulTempData ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /*=======================================================================*/ } else { pIntrptManage->usRegister202h = 0x0; } /* H.100 registers. */ if ( (f_ulRegister210h & 0x00004) != 0 ) { /*=======================================================================*/ /* Read registers of this module. */ ReadParams.ulReadAddress = 0x302; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check which interrupts were set. */ if ( (usReadData & 0x0100) != 0 ) { f_pIntFlags->fErrorH100OutOfSync = TRUE; pErrorStats->ulH100OutOfSyncCnt++; } if ( (usReadData & 0x1000) != 0 ) { f_pIntFlags->fErrorH100FrameA = TRUE; pErrorStats->ulH100FrameABadCnt++; } if ( (usReadData & 0x4000) != 0 ) { f_pIntFlags->fErrorH100ClkA = TRUE; pErrorStats->ulH100ClkABadCnt++; } if ( (usReadData & 0x8000) != 0 ) { if ( f_pApiInstance->pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) { f_pIntFlags->fErrorH100ClkB = TRUE; pErrorStats->ulH100ClkBBadCnt++; } } pIntrptManage->usRegister302h = usReadData; /*=======================================================================*/ } else { pIntrptManage->usRegister302h = 0x0; } /* TDMIE registers. */ if ( (f_ulRegister210h & 0x00010) != 0 ) { /*=======================================================================*/ /* Read register. */ ReadParams.ulReadAddress = 0x502; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check which interrupts were set. */ if ( (usReadData & 0x0002) != 0 ) { f_pIntFlags->ulFatalGeneralFlags |= cOCT6100_FATAL_GENERAL_ERROR_TYPE_3; f_pIntFlags->fFatalGeneral = TRUE; pErrorStats->fFatalChipError = TRUE; } pIntrptManage->usRegister502h = usReadData; /*=======================================================================*/ } else { pIntrptManage->usRegister502h = 0x0; } /* PGSP registers. */ if ( (f_ulRegister210h & 0x00080) != 0 ) { /*=======================================================================*/ /* Read register. */ ReadParams.ulReadAddress = 0x702; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check which interrupts were set. */ if ( (usReadData & 0x0002) != 0 ) { f_pIntFlags->fErrorOverflowToneEvents = TRUE; pErrorStats->ulOverflowToneEventsCnt++; } pIntrptManage->usRegister702h = usReadData; /*=======================================================================*/ } else { pIntrptManage->usRegister702h = 0x0; } /* If this is the first time the ISR is called, clear the ISR is not called bit */ /* in external memory to signal the remote client that we are called. */ if ( pSharedInfo->IntrptManage.fIsrCalled == FALSE ) { /* Remember that we are being called. */ pSharedInfo->IntrptManage.fIsrCalled = TRUE; if ( pSharedInfo->DebugInfo.fIsIsrCalledField == TRUE ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.IsIsrCalledFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.IsIsrCalledFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.IsIsrCalledFieldOfst.byFieldSize; ulResult = Oct6100ApiReadDword( f_pApiInstance, cOCT6100_POUCH_BASE + ulFeatureBytesOffset, &ulTempData ); /* Read previous value set in the feature field. */ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); /* Clear the field. */ ulTempData &= (~ulMask); /* Write the DWORD where the field is located.*/ ulResult = Oct6100ApiWriteDword( f_pApiInstance, cOCT6100_POUCH_BASE + ulFeatureBytesOffset, ulTempData ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiUpdateIntrptStates Description: Updates the state of all interrupt register groups. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pIntFlags Interrupt flags. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiUpdateIntrptStates( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_INTERRUPT_FLAGS f_pIntFlags ) { tPOCT6100_API_INTRPT_CONFIG pIntrptConfig; tPOCT6100_API_INTRPT_MANAGE pIntrptManage; pIntrptConfig = &f_pApiInstance->pSharedInfo->IntrptConfig; pIntrptManage = &f_pApiInstance->pSharedInfo->IntrptManage; /*-----------------------------------------------------------------------*/ if ( ( f_pIntFlags->fFatalReadTimeout == TRUE) && pIntrptConfig->byFatalMemoryConfig == cOCT6100_INTERRUPT_TIMEOUT && pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_ACTIVE ) { pIntrptManage->byFatalMemoryState = cOCT6100_INTRPT_WILL_TIMEOUT; pIntrptManage->ulFatalMemoryDisableMclkHigh = pIntrptManage->ulRegMclkTimeHigh; pIntrptManage->ulFatalMemoryDisableMclkLow = pIntrptManage->ulRegMclkTimeLow; } /*-----------------------------------------------------------------------*/ if ( (f_pIntFlags->fErrorRefreshTooLate == TRUE || f_pIntFlags->fErrorPllJitter == TRUE ) && pIntrptConfig->byErrorMemoryConfig == cOCT6100_INTERRUPT_TIMEOUT && pIntrptManage->byErrorMemoryState == cOCT6100_INTRPT_ACTIVE ) { pIntrptManage->byErrorMemoryState = cOCT6100_INTRPT_WILL_TIMEOUT; pIntrptManage->ulErrorMemoryDisableMclkHigh = pIntrptManage->ulRegMclkTimeHigh; pIntrptManage->ulErrorMemoryDisableMclkLow = pIntrptManage->ulRegMclkTimeLow; } /*-----------------------------------------------------------------------*/ if ( (f_pIntFlags->fErrorOverflowToneEvents == TRUE) && pIntrptConfig->byErrorOverflowToneEventsConfig == cOCT6100_INTERRUPT_TIMEOUT && pIntrptManage->byErrorOverflowToneEventsState == cOCT6100_INTRPT_ACTIVE ) { pIntrptManage->byErrorOverflowToneEventsState = cOCT6100_INTRPT_WILL_TIMEOUT; pIntrptManage->ulErrorOverflowToneEventsDisableMclkHigh = pIntrptManage->ulRegMclkTimeHigh; pIntrptManage->ulErrorOverflowToneEventsDisableMclkLow = pIntrptManage->ulRegMclkTimeLow; } /*-----------------------------------------------------------------------*/ if ( (f_pIntFlags->fErrorH100OutOfSync == TRUE || f_pIntFlags->fErrorH100ClkA == TRUE || f_pIntFlags->fErrorH100ClkB == TRUE || f_pIntFlags->fErrorH100FrameA == TRUE ) && pIntrptConfig->byErrorH100Config == cOCT6100_INTERRUPT_TIMEOUT && pIntrptManage->byErrorH100State == cOCT6100_INTRPT_ACTIVE ) { pIntrptManage->byErrorH100State = cOCT6100_INTRPT_WILL_TIMEOUT; pIntrptManage->ulErrorH100DisableMclkHigh = pIntrptManage->ulRegMclkTimeHigh; pIntrptManage->ulErrorH100DisableMclkLow = pIntrptManage->ulRegMclkTimeLow; } /*-----------------------------------------------------------------------*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteIntrptRegs Description: Writes to interrupt registers to clear interrupt condition, and writes to an interrupt's IE register if interrupt is to time out. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWriteIntrptRegs( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_API_INTRPT_MANAGE pIntrptManage; tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; /* Get some local pointers. */ pIntrptManage = &f_pApiInstance->pSharedInfo->IntrptManage; /* Set some parameters of write struct. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; /*===========================================================================*/ if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_WILL_TIMEOUT ) { WriteParams.ulWriteAddress = 0x104; WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } if ( (pIntrptManage->usRegister102h & cOCT6100_INTRPT_MASK_REG_102H) != 0 ) { WriteParams.ulWriteAddress = 0x102; WriteParams.usWriteData = pIntrptManage->usRegister102h; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*===========================================================================*/ /*===========================================================================*/ if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_WILL_TIMEOUT || pIntrptManage->byErrorMemoryState == cOCT6100_INTRPT_WILL_TIMEOUT ) { WriteParams.ulWriteAddress = 0x204; WriteParams.usWriteData = 0x0000; if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_ACTIVE ) WriteParams.usWriteData |= 0x1800; if ( pIntrptManage->byErrorMemoryState == cOCT6100_INTRPT_ACTIVE ) WriteParams.usWriteData |= 0x0401; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } if ( (pIntrptManage->usRegister202h & cOCT6100_INTRPT_MASK_REG_202H) != 0 ) { WriteParams.ulWriteAddress = 0x202; WriteParams.usWriteData = pIntrptManage->usRegister202h; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*===========================================================================*/ /*===========================================================================*/ if ( pIntrptManage->byErrorH100State == cOCT6100_INTRPT_WILL_TIMEOUT ) { WriteParams.ulWriteAddress = 0x304; WriteParams.usWriteData = 0x0000; if ( pIntrptManage->fMclkIntrptActive == TRUE ) WriteParams.usWriteData |= 0x0001; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } if ( (pIntrptManage->usRegister302h & cOCT6100_INTRPT_MASK_REG_302H) != 0 ) { WriteParams.ulWriteAddress = 0x302; WriteParams.usWriteData = pIntrptManage->usRegister302h; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*===========================================================================*/ /*===========================================================================*/ if ( (pIntrptManage->usRegister502h & cOCT6100_INTRPT_MASK_REG_502H) != 0 ) { WriteParams.ulWriteAddress = 0x502; WriteParams.usWriteData = pIntrptManage->usRegister502h; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*===========================================================================*/ /*===========================================================================*/ if ( pIntrptManage->byErrorOverflowToneEventsState == cOCT6100_INTRPT_WILL_TIMEOUT ) { WriteParams.ulWriteAddress = 0x704; WriteParams.usWriteData = 0x0000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } if ( (pIntrptManage->usRegister702h & cOCT6100_INTRPT_MASK_REG_702H) != 0 ) { WriteParams.ulWriteAddress = 0x702; WriteParams.usWriteData = pIntrptManage->usRegister702h; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*===========================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteIeRegs Description: Writes the IE field of each interrupt register. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWriteIeRegs( tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_API_INTRPT_MANAGE pIntrptManage; tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_READ_PARAMS ReadParams; UINT32 ulResult; /* Get some local pointers. */ pIntrptManage = &f_pApiInstance->pSharedInfo->IntrptManage; /* Set some parameters of write struct. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; /* Set some parameters of read struct. */ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; /*==================================================================================*/ WriteParams.ulWriteAddress = 0x104; WriteParams.usWriteData = 0x0000; if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_ACTIVE ) WriteParams.usWriteData |= 0x0001; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==================================================================================*/ /*==================================================================================*/ WriteParams.ulWriteAddress = 0x204; WriteParams.usWriteData = 0x0000; if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_ACTIVE ) WriteParams.usWriteData |= 0x1800; if ( pIntrptManage->byErrorMemoryState == cOCT6100_INTRPT_ACTIVE ) WriteParams.usWriteData |= 0x0401; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==================================================================================*/ /*==================================================================================*/ WriteParams.ulWriteAddress = 0x304; WriteParams.usWriteData = 0x0000; if ( pIntrptManage->fMclkIntrptActive == TRUE ) WriteParams.usWriteData |= 0x0001; if ( pIntrptManage->byErrorH100State == cOCT6100_INTRPT_ACTIVE ) { if ( f_pApiInstance->pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) WriteParams.usWriteData |= 0xD100; else WriteParams.usWriteData |= 0x5100; } mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==================================================================================*/ /*==================================================================================*/ WriteParams.ulWriteAddress = 0x504; WriteParams.usWriteData = 0x0000; if ( pIntrptManage->byFatalGeneralState == cOCT6100_INTRPT_ACTIVE ) WriteParams.usWriteData |= 0x0002; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==================================================================================*/ /*==================================================================================*/ WriteParams.ulWriteAddress = 0x704; WriteParams.usWriteData = 0x0000; if ( pIntrptManage->byErrorOverflowToneEventsState == cOCT6100_INTRPT_ACTIVE ) WriteParams.usWriteData |= 0x0002; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==================================================================================*/ /*==================================================================================*/ /* Enable the GLOBAL IEs for the interrupt pin. */ WriteParams.ulWriteAddress = 0x218; WriteParams.usWriteData = 0x00D7; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*==================================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReadChipMclkTime Description: Reads the chip's mclk cycle count to construct a chip time. The time is used to manage interrupts. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReadChipMclkTime( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_API_INTRPT_MANAGE pIntrptManage; tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_READ_PARAMS ReadParams; UINT32 ulCheckData; UINT32 ulResult; UINT32 i; UINT16 usReadData; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; pIntrptManage = &pSharedInfo->IntrptManage; /* Assign memory for read data. */ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; /* Perform reads. */ for ( i = 0; i < 100; i++ ) { ReadParams.ulReadAddress = 0x306; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; pIntrptManage->ulRegMclkTimeHigh = usReadData & 0xFF; ulCheckData = usReadData; ReadParams.ulReadAddress = 0x308; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; pIntrptManage->ulRegMclkTimeLow = (usReadData & 0xFFFF) << 16; ReadParams.ulReadAddress = 0x306; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( ulCheckData == usReadData ) break; } if ( i == 100 ) return cOCT6100_ERR_FATAL_2F; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiUpdateIntrptTimeouts Description: Checks which interrupt groups have finished their timeout period. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiUpdateIntrptTimeouts( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_API_INTRPT_MANAGE pIntrptManage; tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulRegMclkTimePlus5MsHigh; UINT32 ulRegMclkTimePlus5MsLow; UINT32 ulResult; BOOL fFatalMemoryChange = FALSE; BOOL fDataErrMemoryChange = FALSE; BOOL fErrorOverflowToneEventsChange = FALSE; BOOL fH100ErrorChange = FALSE; /* Get local pointer to interrupt management structure. */ pIntrptManage = &f_pApiInstance->pSharedInfo->IntrptManage; /* Calculate mclk time + 5 ms. */ ulRegMclkTimePlus5MsLow = pIntrptManage->ulRegMclkTimeLow + (5 * pIntrptManage->ulNumMclkCyclesIn1Ms); if ( ulRegMclkTimePlus5MsLow < pIntrptManage->ulRegMclkTimeLow ) ulRegMclkTimePlus5MsHigh = pIntrptManage->ulRegMclkTimeHigh + 1; else /* ( ulRegMclkTimePlus5MsLow >= pIntrptManage->ulRegMclkTimeLow ) */ ulRegMclkTimePlus5MsHigh = pIntrptManage->ulRegMclkTimeHigh; /* Check which interrupts are timed out and need to be reenabled now. */ if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_IN_TIMEOUT ) { mOCT6100_CHECK_INTRPT_TIMEOUT( ulRegMclkTimePlus5MsHigh, ulRegMclkTimePlus5MsLow, pIntrptManage->ulFatalMemoryDisableMclkHigh, pIntrptManage->ulFatalMemoryDisableMclkLow, pIntrptManage->ulFatalMemoryEnableMclkHigh, pIntrptManage->ulFatalMemoryEnableMclkLow, pIntrptManage->byFatalMemoryState, fFatalMemoryChange ) } if ( pIntrptManage->byErrorMemoryState == cOCT6100_INTRPT_IN_TIMEOUT ) { mOCT6100_CHECK_INTRPT_TIMEOUT( ulRegMclkTimePlus5MsHigh, ulRegMclkTimePlus5MsLow, pIntrptManage->ulErrorMemoryDisableMclkHigh, pIntrptManage->ulErrorMemoryDisableMclkLow, pIntrptManage->ulErrorMemoryEnableMclkHigh, pIntrptManage->ulErrorMemoryEnableMclkLow, pIntrptManage->byErrorMemoryState, fDataErrMemoryChange ) } if ( pIntrptManage->byErrorOverflowToneEventsState == cOCT6100_INTRPT_IN_TIMEOUT ) { mOCT6100_CHECK_INTRPT_TIMEOUT( ulRegMclkTimePlus5MsHigh, ulRegMclkTimePlus5MsLow, pIntrptManage->ulErrorOverflowToneEventsDisableMclkHigh, pIntrptManage->ulErrorOverflowToneEventsDisableMclkLow, pIntrptManage->ulErrorOverflowToneEventsEnableMclkHigh, pIntrptManage->ulErrorOverflowToneEventsEnableMclkLow, pIntrptManage->byErrorOverflowToneEventsState, fErrorOverflowToneEventsChange ) } if ( pIntrptManage->byErrorH100State == cOCT6100_INTRPT_IN_TIMEOUT ) { mOCT6100_CHECK_INTRPT_TIMEOUT( ulRegMclkTimePlus5MsHigh, ulRegMclkTimePlus5MsLow, pIntrptManage->ulErrorH100DisableMclkHigh, pIntrptManage->ulErrorH100DisableMclkLow, pIntrptManage->ulErrorH100EnableMclkHigh, pIntrptManage->ulErrorH100EnableMclkLow, pIntrptManage->byErrorH100State, fH100ErrorChange ) } /* Set some parameters of write struct. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; /* Write to the IE registers which have changed. */ /*==================================================================================*/ if ( fFatalMemoryChange == TRUE ) { WriteParams.ulWriteAddress = 0x104; WriteParams.usWriteData = 0x0000; if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_ACTIVE ) WriteParams.usWriteData |= 0x0001; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*==================================================================================*/ /*==================================================================================*/ if ( fFatalMemoryChange == TRUE || fDataErrMemoryChange == TRUE ) { WriteParams.ulWriteAddress = 0x204; WriteParams.usWriteData = 0x0000; if ( pIntrptManage->byFatalMemoryState == cOCT6100_INTRPT_ACTIVE ) WriteParams.usWriteData |= 0x1800; if ( pIntrptManage->byErrorMemoryState == cOCT6100_INTRPT_ACTIVE ) WriteParams.usWriteData |= 0x0401; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*==================================================================================*/ /*==================================================================================*/ if ( pIntrptManage->fMclkIntrptActive == TRUE || fH100ErrorChange == TRUE ) { WriteParams.ulWriteAddress = 0x304; WriteParams.usWriteData = 0x0000; if ( pIntrptManage->fMclkIntrptActive == TRUE ) WriteParams.usWriteData |= 0x0001; if ( pIntrptManage->byErrorH100State == cOCT6100_INTRPT_ACTIVE ) { if ( f_pApiInstance->pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) WriteParams.usWriteData |= 0xD100; else WriteParams.usWriteData |= 0x5100; } mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*==================================================================================*/ /*==================================================================================*/ if ( fErrorOverflowToneEventsChange == TRUE ) { WriteParams.ulWriteAddress = 0x704; WriteParams.usWriteData = 0x0000; if ( pIntrptManage->byErrorOverflowToneEventsState == cOCT6100_INTRPT_ACTIVE ) WriteParams.usWriteData |= 0x0002; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*==================================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiScheduleNextMclkIntrptSer Description: Serialized sub-function of Oct6100ApiScheduleNextMclkIntrpt. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiScheduleNextMclkIntrptSer( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_INTRPT_CONFIG pIntrptConfig; tPOCT6100_API_INTRPT_MANAGE pIntrptManage; tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulTimeDiff; UINT32 ulRegMclkTimeHigh; UINT32 ulRegMclkTimeLow; UINT32 ulResult; BOOL fConditionFlag = TRUE; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Obtain temporary pointers to reduce indirection, thus speeding up processing. */ pIntrptConfig = &pSharedInfo->IntrptConfig; pIntrptManage = &pSharedInfo->IntrptManage; ulRegMclkTimeHigh = pIntrptManage->ulRegMclkTimeHigh; ulRegMclkTimeLow = pIntrptManage->ulRegMclkTimeLow; /* First, check if any interrupts have just been disabled. If there are any, */ /* determine the time at which they should be reenabled. */ pIntrptManage->ulNextMclkIntrptTimeHigh = cOCT6100_INVALID_VALUE; pIntrptManage->ulNextMclkIntrptTimeLow = cOCT6100_INVALID_VALUE; while ( fConditionFlag ) { /* Indicate that no mclk interrupt is needed, yet. */ ulTimeDiff = cOCT6100_INVALID_VALUE; /* Check each interrupt category to see if an mclk interrupt is needed to */ /* reenable an interrupt at a later time. */ if ( pIntrptManage->byFatalMemoryState != cOCT6100_INTRPT_ACTIVE && pIntrptManage->byFatalMemoryState != cOCT6100_INTRPT_DISABLED ) { mOCT6100_GET_INTRPT_ENABLE_TIME( ulRegMclkTimeHigh, ulRegMclkTimeLow, pIntrptManage->byFatalMemoryState, pIntrptManage->ulFatalMemoryEnableMclkHigh, pIntrptManage->ulFatalMemoryEnableMclkLow, pIntrptConfig->ulFatalMemoryTimeoutMclk, ulTimeDiff ) } if ( pIntrptManage->byErrorMemoryState != cOCT6100_INTRPT_ACTIVE && pIntrptManage->byErrorMemoryState != cOCT6100_INTRPT_DISABLED ) { mOCT6100_GET_INTRPT_ENABLE_TIME( ulRegMclkTimeHigh, ulRegMclkTimeLow, pIntrptManage->byErrorMemoryState, pIntrptManage->ulErrorMemoryEnableMclkHigh, pIntrptManage->ulErrorMemoryEnableMclkLow, pIntrptConfig->ulErrorMemoryTimeoutMclk, ulTimeDiff ) } if ( pIntrptManage->byErrorOverflowToneEventsState != cOCT6100_INTRPT_ACTIVE && pIntrptManage->byErrorOverflowToneEventsState != cOCT6100_INTRPT_DISABLED ) { mOCT6100_GET_INTRPT_ENABLE_TIME( ulRegMclkTimeHigh, ulRegMclkTimeLow, pIntrptManage->byErrorOverflowToneEventsState, pIntrptManage->ulErrorOverflowToneEventsEnableMclkHigh, pIntrptManage->ulErrorOverflowToneEventsEnableMclkLow, pIntrptConfig->ulErrorOverflowToneEventsTimeoutMclk, ulTimeDiff ) } if ( pIntrptManage->byErrorH100State != cOCT6100_INTRPT_ACTIVE && pIntrptManage->byErrorH100State != cOCT6100_INTRPT_DISABLED ) { mOCT6100_GET_INTRPT_ENABLE_TIME( ulRegMclkTimeHigh, ulRegMclkTimeLow, pIntrptManage->byErrorH100State, pIntrptManage->ulErrorH100EnableMclkHigh, pIntrptManage->ulErrorH100EnableMclkLow, pIntrptConfig->ulErrorH100TimeoutMclk, ulTimeDiff ) } /* Set some parameters of write struct. */ WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; /* Schedule next mclk interrupt, if any is needed. */ if ( ulTimeDiff != cOCT6100_INVALID_VALUE ) { UINT32 ulMclkTimeTest; UINT32 ulAlarmTimeTest; UINT32 ulTimeDiffTest; BOOL fAlarmTimePassed; /* Indicate that an mclk interrupt is scheduled.*/ pIntrptManage->fMclkIntrptActive = TRUE; pIntrptManage->ulNextMclkIntrptTimeLow = ulRegMclkTimeLow + ulTimeDiff; if ( pIntrptManage->ulNextMclkIntrptTimeLow < ulRegMclkTimeLow ) pIntrptManage->ulNextMclkIntrptTimeHigh = ulRegMclkTimeHigh + 1; else /* ( pIntrptManage->ulNextMclkIntrptTimeLow >= ulRegMclkTimeLow ) */ pIntrptManage->ulNextMclkIntrptTimeHigh = ulRegMclkTimeHigh; WriteParams.ulWriteAddress = 0x30C; WriteParams.usWriteData = (UINT16)( (pIntrptManage->ulNextMclkIntrptTimeLow >> 24) & 0xFF ); WriteParams.usWriteData |= (UINT16)( (pIntrptManage->ulNextMclkIntrptTimeHigh & 0xFF) << 8 ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x30E; WriteParams.usWriteData = (UINT16)( (pIntrptManage->ulNextMclkIntrptTimeLow >> 8) & 0xFFFF ); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteParams.ulWriteAddress = 0x304; WriteParams.usWriteData = 0; if ( pIntrptManage->fMclkIntrptActive == TRUE ) WriteParams.usWriteData = 0x0001; if ( pIntrptManage->byErrorH100State == cOCT6100_INTRPT_ACTIVE ) { if ( f_pApiInstance->pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) WriteParams.usWriteData |= 0xD100; else WriteParams.usWriteData |= 0x5100; } mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Disable the ROL if previously set. */ WriteParams.ulWriteAddress = 0x302; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check if already passed the next interrupt time. */ ulResult = Oct6100ApiReadChipMclkTime( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulMclkTimeTest = (pIntrptManage->ulRegMclkTimeLow >> 16) & 0xFFFF; ulAlarmTimeTest = (pIntrptManage->ulNextMclkIntrptTimeLow >> 16) & 0xFFFF; /* Update the local Mlck timer values.*/ ulRegMclkTimeHigh = pIntrptManage->ulRegMclkTimeHigh; ulRegMclkTimeLow = pIntrptManage->ulRegMclkTimeLow; fAlarmTimePassed = FALSE; if ( ulMclkTimeTest > ulAlarmTimeTest ) { ulTimeDiffTest = ulMclkTimeTest - ulAlarmTimeTest; if ( ulTimeDiffTest <= 0x8000 ) fAlarmTimePassed = TRUE; } else /* ( ulMclkTimeTest <= ulAlarmTimeTest ) */ { ulTimeDiffTest = ulAlarmTimeTest - ulMclkTimeTest; if ( ulTimeDiffTest > 0x8000 ) fAlarmTimePassed = TRUE; } if ( fAlarmTimePassed == TRUE ) { /* Passed the interrupt time. Schedule next interrupt (if needed). */ ulResult = Oct6100ApiUpdateIntrptTimeouts( f_pApiInstance ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; continue; } else { fConditionFlag = FALSE; } } else { /* Indicate that no mclk interrupt is scheduled. */ pIntrptManage->fMclkIntrptActive = FALSE; /* Insure that the mclk interrupt is not enabled. */ WriteParams.ulWriteAddress = 0x304; WriteParams.usWriteData = 0x0000; if ( pIntrptManage->byErrorH100State == cOCT6100_INTRPT_ACTIVE ) { if ( f_pApiInstance->pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE ) WriteParams.usWriteData |= 0xD100; else WriteParams.usWriteData |= 0x5100; } mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; fConditionFlag = FALSE; } } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiCheckProcessorState Description: This function verifies if the NLP and AF processors are operating correctly. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pIntFlags Pointer to a tOCT6100_INTERRUPT_FLAGS structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiCheckProcessorState( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN OUT tPOCT6100_INTERRUPT_FLAGS f_pIntFlags ) { tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_READ_PARAMS ReadParams; tOCT6100_READ_BURST_PARAMS ReadBurstParams; UINT32 ulNlpTimestamp; UINT32 ulAfTimestamp; UINT32 ulTimestampDiff; UINT32 ulResult; UINT32 i; UINT16 usReadData; UINT16 ausReadData[ 2 ]; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Set some parameters of write struct. */ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; /* Set some parameters of write struct. */ ReadBurstParams.pProcessContext = f_pApiInstance->pProcessContext; ReadBurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadBurstParams.pusReadData = ausReadData; /*-----------------------------------------------------------------------*/ /* Check if chip is in reset. */ /* Read the main control register. */ ReadParams.ulReadAddress = 0x100; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( usReadData == 0x0000 ) { /* Chip was resetted. */ f_pIntFlags->ulFatalGeneralFlags |= cOCT6100_FATAL_GENERAL_ERROR_TYPE_4; f_pIntFlags->fFatalGeneral = TRUE; pSharedInfo->ErrorStats.fFatalChipError = TRUE; } /*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/ /* Reading the AF timestamp.*/ for ( i = 0; i < cOCT6100_MAX_LOOP; i++ ) { /* Read the timestamp.*/ ReadBurstParams.ulReadAddress = 0x082E0008; ReadBurstParams.ulReadLength = 2; mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Read the high part again to make sure it didn't wrap. */ ReadParams.ulReadAddress = 0x082E0008; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check if the low part wrapped. */ if ( ausReadData[ 0 ] == usReadData ) break; } if ( i == cOCT6100_MAX_LOOP ) return cOCT6100_ERR_INTRPTS_AF_TIMESTAMP_READ_TIMEOUT; /* Save the AF timestamp. */ ulAfTimestamp = (ausReadData[ 0 ] << 16) | ausReadData[ 1 ]; /*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/ /* Reading the NLP timestamp. */ for ( i = 0; i < cOCT6100_MAX_LOOP; i++ ) { /* Read the timestamp. */ ReadBurstParams.ulReadAddress = 0x08000008; ReadBurstParams.ulReadLength = 2; mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Read the high part again to make sure it didn't wrap. */ ReadParams.ulReadAddress = 0x08000008; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check if the low part wrapped. */ if ( ausReadData[ 0 ] == usReadData ) break; } if ( i == cOCT6100_MAX_LOOP ) return cOCT6100_ERR_INTRPTS_NLP_TIMESTAMP_READ_TIMEOUT; /* Save the NLP timestamp. */ ulNlpTimestamp = (ausReadData[ 0 ] << 16) | ausReadData[ 1 ]; /*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/ /* Check the validity of the timestamp. */ if ( ulAfTimestamp > ulNlpTimestamp ) { /* The NLP timestamp wrapped. */ ulTimestampDiff = 0xFFFFFFFF - ulAfTimestamp + 1; ulTimestampDiff += ulNlpTimestamp; } else ulTimestampDiff = ulNlpTimestamp - ulAfTimestamp; if ( ulTimestampDiff > 0x1000 ) { f_pIntFlags->ulFatalGeneralFlags |= cOCT6100_FATAL_GENERAL_ERROR_TYPE_5; f_pIntFlags->fFatalGeneral = TRUE; pSharedInfo->ErrorStats.fFatalChipError = TRUE; } /*-----------------------------------------------------------------------*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_memory.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains the functions used to manage the allocation of memory blocks in external memory. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 42 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "apilib/octapi_llman.h" #include "oct6100api/oct6100_apiud.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_playout_buf_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_memory_priv.h" /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetMemorySwSizes Description: Gets the sizes of all portions of the API instance pertinent to the management of the memories. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pOpenChip Pointer to chip configuration struct. f_pInstSizes Pointer to struct containing instance sizes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiGetMemorySwSizes( IN tPOCT6100_CHIP_OPEN f_pOpenChip, OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) { UINT32 ulTempVar; UINT32 ulResult; UINT32 ulNumTsiChariots; /*=========================================================================*/ /* Internal memory */ /* Evaluate the number of available TSI memory after reserving the ones used by channels. */ ulNumTsiChariots = cOCT6100_TOTAL_TSI_CONTROL_MEM_ENTRY - f_pOpenChip->ulMaxPhasingTssts - cOCT6100_TSI_MEM_FOR_TIMESTAMP; if ( f_pOpenChip->fEnableExtToneDetection == TRUE ) ulNumTsiChariots--; /* Calculate memory needed for TSI memory allocation. */ ulResult = OctapiLlmAllocGetSize( ulNumTsiChariots, &f_pInstSizes->ulTsiMemoryAlloc ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_94; /* Calculate memory needed for conversion memory allocation. */ ulResult = OctapiLlmAllocGetSize( cOCT6100_MAX_CONVERSION_MEMORY_BLOCKS, &f_pInstSizes->ulConversionMemoryAlloc ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_B5; mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulTsiMemoryAlloc, ulTempVar ); mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulConversionMemoryAlloc, ulTempVar ); return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiMemorySwInit Description: Initializes all elements of the instance structure associated to memories. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiMemorySwInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; PVOID pTsiMemAlloc; PVOID pAllocPnt; UINT32 ulResult; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; /*=========================================================================*/ /* Internal memory */ /* Initialize the TSI memory allocation structure. */ pSharedInfo->MemoryMap.ulNumTsiEntries = cOCT6100_TOTAL_TSI_CONTROL_MEM_ENTRY - pSharedInfo->ChipConfig.usMaxPhasingTssts - cOCT6100_TSI_MEM_FOR_TIMESTAMP; if ( pSharedInfo->ChipConfig.fEnableExtToneDetection == TRUE ) pSharedInfo->MemoryMap.ulNumTsiEntries--; mOCT6100_GET_TSI_MEMORY_ALLOC_PNT( pSharedInfo, pTsiMemAlloc ); ulResult = OctapiLlmAllocInit( &pTsiMemAlloc, pSharedInfo->MemoryMap.ulNumTsiEntries ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_95; /* Initialize the conversion memory allocation structure. */ mOCT6100_GET_CONVERSION_MEMORY_ALLOC_PNT( pSharedInfo, pAllocPnt ); ulResult = OctapiLlmAllocInit( &pAllocPnt, cOCT6100_MAX_CONVERSION_MEMORY_BLOCKS ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_B6; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiBufferPlayoutMemorySwInit Description: Initialize the buffer playout memory allocation working structures. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiBufferPlayoutMemorySwInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pNode; UINT32 i; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Only if buffer playout will be used. */ if ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers > 0 ) { mOCT6100_GET_BUFFER_MEMORY_NODE_LIST_PNT( pSharedInfo, pNode ); /* First node contains all free memory at beginning. This node is not used, but represents the memory. */ pNode->ulSize = ( pSharedInfo->MiscVars.ulTotalMemSize + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ) - pSharedInfo->MemoryMap.ulFreeMemBaseAddress; pNode->ulNext = 0; pNode->ulPrevious = 0; pNode->fAllocated = FALSE; pNode->ulStartAddress = pSharedInfo->MemoryMap.ulFreeMemBaseAddress; pNode++; /* Now create the first node of the free list, i.e. nodes that can be used later for modeling the memory. */ pNode->ulSize = 0; /* Next free. */ pNode->ulNext = 2; /* Last. */ pNode->ulPrevious = ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers * 2 ) - 1; pNode->fAllocated = FALSE; pNode->ulStartAddress = 0; pNode++; /* Link all the unused nodes. */ for( i = 2; i < (UINT32)( ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers * 2 ) - 1 ); i ++ ) { pNode->ulNext = i + 1; pNode->ulPrevious = i - 1; pNode->ulStartAddress = 0; pNode->ulSize = 0; pNode->fAllocated = FALSE; pNode++; } /* Last node of the unused list. */ pNode->fAllocated = FALSE; pNode->ulPrevious = ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers * 2 ) - 2; /* Free list head. */ pNode->ulNext = 1; pNode->ulSize = 0; pNode->ulStartAddress = 0; /* Set roving pointer to first node ( which can be used! ) */ pSharedInfo->PlayoutInfo.ulRovingNode = 0; /* First unused node. */ pSharedInfo->PlayoutInfo.ulFirstUnusedNode = 1; /* Last unused node. */ pSharedInfo->PlayoutInfo.ulLastUnusedNode = ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers * 2 ) - 1; /* Number of unused nodes. */ pSharedInfo->PlayoutInfo.ulUnusedNodeCnt = ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers * 2 ) - 1; } else { pSharedInfo->PlayoutInfo.ulUnusedNodeCnt = 0; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_phasing_tsst.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains functions used to open and close phasing TSSTs. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 42 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "oct6100api/oct6100_apiud.h" #include "apilib/octapi_llman.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_phasing_tsst_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_phasing_tsst_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_memory_priv.h" #include "oct6100_tsst_priv.h" #include "oct6100_phasing_tsst_priv.h" /**************************** PUBLIC FUNCTIONS ****************************/ /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetPhasingTsstSwSizes Description: Gets the sizes of all portions of the API instance pertinent to the management of Phasing TSSTs. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pOpenChip Pointer to chip configuration struct. f_pInstSizes Pointer to struct containing instance sizes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiGetPhasingTsstSwSizes( IN tPOCT6100_CHIP_OPEN f_pOpenChip, OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) { UINT32 ulTempVar; UINT32 ulResult; /* Determine the amount of memory required for the API phasing TSST list. */ f_pInstSizes->ulPhasingTsstList = f_pOpenChip->ulMaxPhasingTssts * sizeof( tOCT6100_API_PHASING_TSST ); if ( f_pOpenChip->ulMaxPhasingTssts > 0 ) { /* Calculate memory needed for Phasing TSST API memory allocation */ ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxPhasingTssts, &f_pInstSizes->ulPhasingTsstAlloc ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_38; } else { f_pInstSizes->ulPhasingTsstAlloc = 0; } mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulPhasingTsstList, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulPhasingTsstAlloc, ulTempVar ) return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiPhasingTsstSwInit Description: Initializes all elements of the instance structure associated to phasing TSST. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiPhasingTsstSwInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_API_PHASING_TSST pPhasingTsstList; tPOCT6100_SHARED_INFO pSharedInfo; UINT32 ulMaxPhasingTssts; PVOID pPhasingTsstAlloc; UINT32 ulResult; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Initialize the phasing TSST API list. */ ulMaxPhasingTssts = pSharedInfo->ChipConfig.usMaxPhasingTssts; /* Set all entries in the phasing TSST list to unused. */ mOCT6100_GET_PHASING_TSST_LIST_PNT( pSharedInfo, pPhasingTsstList ) /* Clear the memory */ Oct6100UserMemSet( pPhasingTsstList, 0x00, sizeof(tOCT6100_API_PHASING_TSST) * ulMaxPhasingTssts ); /* Initialize the phasing TSST allocation software to "all free". */ if ( ulMaxPhasingTssts > 0 ) { mOCT6100_GET_PHASING_TSST_ALLOC_PNT( pSharedInfo, pPhasingTsstAlloc ) ulResult = OctapiLlmAllocInit( &pPhasingTsstAlloc, ulMaxPhasingTssts ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_39; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_playout_buf.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains functions used to manage buffer playout. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 109 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "oct6100api/oct6100_apiud.h" #include "apilib/octapi_llman.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_channel_inst.h" #include "oct6100api/oct6100_playout_buf_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_events_pub.h" #include "oct6100api/oct6100_playout_buf_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_memory_priv.h" #include "oct6100_channel_priv.h" #include "oct6100_events_priv.h" #include "oct6100_playout_buf_priv.h" /**************************** PUBLIC FUNCTIONS *****************************/ /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetPlayoutBufferSwSizes Description: Gets the sizes of all portions of the API instance pertinent to the management of playout buffers. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pOpenChip Pointer to chip configuration struct. f_pInstSizes Pointer to struct containing instance sizes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiGetPlayoutBufferSwSizes( IN tPOCT6100_CHIP_OPEN f_pOpenChip, OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) { UINT32 ulTempVar; UINT32 ulResult; /* Calculate memory needed for playout buffer list. */ f_pInstSizes->ulPlayoutBufList = f_pOpenChip->ulMaxPlayoutBuffers * sizeof( tOCT6100_API_BUFFER ); f_pInstSizes->ulPlayoutBufMemoryNodeList = 0; /* Calculate memory needed for playout buffer allocation software. */ if ( f_pOpenChip->ulMaxPlayoutBuffers > 0 ) { ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxPlayoutBuffers, &f_pInstSizes->ulPlayoutBufAlloc ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_3C; f_pInstSizes->ulPlayoutBufMemoryNodeList = 2 * f_pOpenChip->ulMaxPlayoutBuffers * sizeof( tOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE ); } else { f_pInstSizes->ulPlayoutBufAlloc = 0; } /* Calculate memory needed for list and allocation software serialization. */ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulPlayoutBufList, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulPlayoutBufAlloc, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulPlayoutBufMemoryNodeList, ulTempVar ) return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiPlayoutBufferSwInit Description: Initializes all elements of the instance structure associated to playout buffers. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiPlayoutBufferSwInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_BUFFER pBufferList; PVOID pBufferPlayoutAlloc; UINT32 ulMaxBufferPlayout; UINT32 ulResult, i; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Get the maximum number of buffer playout. */ ulMaxBufferPlayout = pSharedInfo->ChipConfig.usMaxPlayoutBuffers; /* Set all entries in the buffer playout list to unused. */ mOCT6100_GET_BUFFER_LIST_PNT( pSharedInfo, pBufferList ) for ( i = 0; i < ulMaxBufferPlayout; i++ ) { pBufferList[ i ].fReserved = FALSE; pBufferList[ i ].ulBufferSize = 0; pBufferList[ i ].ulBufferBase = cOCT6100_INVALID_VALUE; pBufferList[ i ].usDependencyCnt = 0; pBufferList[ i ].byBufferPcmLaw = cOCT6100_PCM_U_LAW; } /* Initialize the buffer playout allocation software to "all free". */ if ( ulMaxBufferPlayout > 0 ) { mOCT6100_GET_BUFFER_ALLOC_PNT( pSharedInfo, pBufferPlayoutAlloc ) ulResult = OctapiLlmAllocInit( &pBufferPlayoutAlloc, ulMaxBufferPlayout ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_3D; } /* Initialize the amount of free memory used by playout. */ f_pApiInstance->pSharedInfo->ChipStats.ulPlayoutMemUsed = 0; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100BufferPlayoutStopSer Description: Stops buffer playout on a channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pBufferPlayoutStop Pointer to buffer playout stop structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100BufferPlayoutStopSer( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN OUT tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop ) { UINT32 ulChannelIndex; UINT16 usEchoMemIndex; UINT32 ulResult; /* Check the user's configuration of the buffer for errors. */ ulResult = Oct6100ApiAssertPlayoutStopParams( f_pApiInstance, f_pBufferPlayoutStop, &ulChannelIndex, &usEchoMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write to all resources needed to deactivate buffer playout. */ ulResult = Oct6100ApiInvalidateChanPlayoutStructs( f_pApiInstance, f_pBufferPlayoutStop, ulChannelIndex, usEchoMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiAssertPlayoutStopParams Description: Check the validity of the channel and buffer requested. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pBufferPlayoutStop Pointer to buffer playout stop structure. f_pulChannelIndex Pointer to the channel index on which playout is to be stopped. f_pusEchoMemIndex Pointer to the echo mem index on which playout is to be stopped. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiAssertPlayoutStopParams( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop, OUT PUINT32 f_pulChannelIndex, OUT PUINT16 f_pusEchoMemIndex ) { tPOCT6100_API_CHANNEL pEchoChannel; UINT32 ulEntryOpenCnt; /* Check for errors. */ if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers == 0 ) return cOCT6100_ERR_BUFFER_PLAYOUT_DISABLED; if ( f_pBufferPlayoutStop->ulChannelHndl == cOCT6100_INVALID_HANDLE ) return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; if ( f_pBufferPlayoutStop->ulPlayoutPort != cOCT6100_CHANNEL_PORT_ROUT && f_pBufferPlayoutStop->ulPlayoutPort != cOCT6100_CHANNEL_PORT_SOUT ) return cOCT6100_ERR_BUFFER_PLAYOUT_PLAYOUT_PORT; if ( f_pBufferPlayoutStop->fStopCleanly != TRUE && f_pBufferPlayoutStop->fStopCleanly != FALSE ) return cOCT6100_ERR_BUFFER_PLAYOUT_STOP_CLEANLY; /*=====================================================================*/ /* Check the channel handle. */ if ( (f_pBufferPlayoutStop->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; *f_pulChannelIndex = f_pBufferPlayoutStop->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK; if ( *f_pulChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChannel, *f_pulChannelIndex ) /* Extract the entry open count from the provided handle. */ ulEntryOpenCnt = (f_pBufferPlayoutStop->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; /* Check for errors. */ if ( pEchoChannel->fReserved != TRUE ) return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_NOT_OPEN; if ( ulEntryOpenCnt != pEchoChannel->byEntryOpenCnt ) return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; /* Return echo memory index. */ *f_pusEchoMemIndex = pEchoChannel->usEchoMemIndex; /* Check if buffer playout is active for the selected port. */ if ( ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) && ( pEchoChannel->fRinBufPlaying == FALSE ) && ( pEchoChannel->fRinBufAdded == FALSE ) ) return cOCT6100_ERR_BUFFER_PLAYOUT_NOT_STARTED; if ( ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pEchoChannel->fSoutBufPlaying == FALSE ) && ( pEchoChannel->fSoutBufAdded == FALSE ) ) return cOCT6100_ERR_BUFFER_PLAYOUT_NOT_STARTED; /*=====================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiInvalidateChanPlayoutStructs Description: Write the buffer playout event in the channel main structure. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pBufferPlayoutStop Pointer to buffer playout stop structure. f_ulChannelIndex Index of the channel within the API's channel list. f_usEchoMemIndex Index of the echo channel in hardware memory. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiInvalidateChanPlayoutStructs( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop, IN UINT32 f_ulChannelIndex, IN UINT16 f_usEchoMemIndex ) { tPOCT6100_API_CHANNEL pEchoChannel; tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_READ_PARAMS ReadParams; tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; UINT32 ulWritePtrBytesOfst; UINT32 ulWritePtrBitOfst; UINT32 ulWritePtrFieldSize; UINT32 ulSkipPtrBytesOfst; UINT32 ulSkipPtrBitOfst; UINT32 ulSkipPtrFieldSize; UINT32 ulIgnoreBytesOfst; UINT32 ulIgnoreBitOfst; UINT32 ulIgnoreFieldSize; UINT32 ulHardSkipBytesOfst; UINT32 ulHardSkipBitOfst; UINT32 ulHardSkipFieldSize; UINT32 ulReadPtrBytesOfst; UINT32 ulReadPtrBitOfst; UINT32 ulReadPtrFieldSize; UINT32 ulSkipPtr; UINT32 ulWritePtr; UINT32 ulReadPtr = 0; UINT32 ulCurrentPtr; UINT32 ulPlayoutBaseAddress; UINT32 ulAddress; UINT32 ulTempData; UINT32 ulMask; UINT32 ulReadData; UINT16 usReadData; BOOL fCheckStop = FALSE; UINT32 ulEventBuffer; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChannel, f_ulChannelIndex ); /* Select the port of interest. */ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) { ulWritePtr = pEchoChannel->ulRinBufWritePtr; ulSkipPtr = ulWritePtr; ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.usDwordOffset * 4; ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byBitOffset; ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byFieldSize; ulSkipPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.usDwordOffset * 4; ulSkipPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.byBitOffset; ulSkipPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.byFieldSize; ulIgnoreBytesOfst = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.usDwordOffset * 4; ulIgnoreBitOfst = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.byBitOffset; ulIgnoreFieldSize = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.byFieldSize; ulHardSkipBytesOfst = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.usDwordOffset * 4; ulHardSkipBitOfst = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.byBitOffset; ulHardSkipFieldSize = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.byFieldSize; ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.usDwordOffset * 4; ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byBitOffset; ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byFieldSize; } else /* f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ { ulWritePtr = pEchoChannel->ulSoutBufWritePtr; ulSkipPtr = ulWritePtr; ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.usDwordOffset * 4; ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byBitOffset; ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byFieldSize; ulSkipPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.usDwordOffset * 4; ulSkipPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.byBitOffset; ulSkipPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.byFieldSize; ulIgnoreBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.usDwordOffset * 4; ulIgnoreBitOfst = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.byBitOffset; ulIgnoreFieldSize = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.byFieldSize; ulHardSkipBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.usDwordOffset * 4; ulHardSkipBitOfst = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.byBitOffset; ulHardSkipFieldSize = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.byFieldSize; ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.usDwordOffset * 4; ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byBitOffset; ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byFieldSize; } /* Set the playout feature base address. */ ulPlayoutBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_usEchoMemIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; /* Check if something is currently playing. */ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) { if ( pEchoChannel->fRinBufPlaying == TRUE ) { /* Check if we are stopping it or if it stopped by itself. */ fCheckStop = TRUE; } else { /* Not playing! */ if ( f_pBufferPlayoutStop->pfAlreadyStopped != NULL ) *f_pBufferPlayoutStop->pfAlreadyStopped = TRUE; } } else /* if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) */ { if ( pEchoChannel->fSoutBufPlaying == TRUE ) { /* Check if we are stopping it or if it stopped by itself. */ fCheckStop = TRUE; } else { /* Not playing! */ if ( f_pBufferPlayoutStop->pfAlreadyStopped != NULL ) *f_pBufferPlayoutStop->pfAlreadyStopped = TRUE; } } if ( ( fCheckStop == TRUE ) || ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE ) ) { /* Read the read pointer. */ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; ReadParams.ulReadAddress = ulPlayoutBaseAddress + ulReadPtrBytesOfst; /* Optimize this access by only reading the word we are interested in. */ if ( ulReadPtrBitOfst < 16 ) ReadParams.ulReadAddress += 2; /* Must read in memory directly since this value is changed by hardware */ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ) if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Move data at correct position according to what was read. */ if ( ulReadPtrBitOfst < 16 ) ulTempData = usReadData; else ulTempData = usReadData << 16; mOCT6100_CREATE_FEATURE_MASK( ulReadPtrFieldSize, ulReadPtrBitOfst, &ulMask ); /* Store the read pointer. */ ulReadPtr = ( ulTempData & ulMask ) >> ulReadPtrBitOfst; /* Playout has finished when the read pointer reaches the write pointer. */ if ( f_pBufferPlayoutStop->pfAlreadyStopped != NULL ) { if ( ulReadPtr != ulWritePtr ) *f_pBufferPlayoutStop->pfAlreadyStopped = FALSE; else /* if ( ulReadPtr == ulWritePtr ) */ *f_pBufferPlayoutStop->pfAlreadyStopped = TRUE; } } /* If the skip bits are located in the event itself, the playout is stopped by setting the */ /* skip pointer to the hardware chip write pointer. Read it directly from the NLP configuration. */ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE ) { if ( ulReadPtr != ulWritePtr ) { /* Get the write pointer in the chip. */ ulAddress = ulPlayoutBaseAddress + ulWritePtrBytesOfst; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, &ulReadData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; mOCT6100_CREATE_FEATURE_MASK( ulWritePtrFieldSize, ulWritePtrBitOfst, &ulMask ); /* Store the write pointer. */ ulWritePtr = ( ulReadData & ulMask ) >> ulWritePtrBitOfst; ulSkipPtr = ulWritePtr; } } /* Check if must clear repeat bit. */ if ( ( ( pEchoChannel->fRinBufPlayoutRepeatUsed == TRUE ) && ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ) || ( ( pEchoChannel->fSoutBufPlayoutRepeatUsed == TRUE ) && ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) ) ) { if ( ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE ) || ( ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE ) && ( ulWritePtr != ulReadPtr ) ) ) { if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) { ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainRinPlayoutMemOfst; } else /* f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ { ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainSoutPlayoutMemOfst; } /* Set the playout event base address. */ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == TRUE ) && ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == TRUE ) ) { /* 127 or 31 events image. */ ulAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + ulEventBuffer + (cOCT6100_PLAYOUT_EVENT_MEM_SIZE * ( ( ulWritePtr - 1 ) & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ))); } else { /* Old 31 events image. */ ulAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + ulEventBuffer + (cOCT6100_PLAYOUT_EVENT_MEM_SIZE * ( ( ulWritePtr - 1 ) & 0x1F)); } /* EVENT BASE + 4 */ /* Playout configuration. */ ulAddress += 4; ReadParams.ulReadAddress = ulAddress; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Read-clear-write the new repeat bit. */ usReadData &= 0x7FFF; WriteParams.ulWriteAddress = ulAddress; WriteParams.usWriteData = usReadData; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* Write the skip to the value of the write pointer to stop buffer playout. */ /*=======================================================================*/ /* First set the ignore skip clean bit if required. */ if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == FALSE ) || ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == FALSE ) ) { ulAddress = ulPlayoutBaseAddress + ulIgnoreBytesOfst; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; mOCT6100_CREATE_FEATURE_MASK( ulIgnoreFieldSize, ulIgnoreBitOfst, &ulMask ); ulTempData &= ( ~ulMask ); /* Check if the skip need to be clean or not. */ if ( f_pBufferPlayoutStop->fStopCleanly == FALSE ) ulTempData |= 0x1 << ulIgnoreBitOfst; mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*=======================================================================*/ /*=======================================================================*/ /* Fetch and modify the write pointer. */ ulAddress = ulPlayoutBaseAddress + ulWritePtrBytesOfst; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; mOCT6100_CREATE_FEATURE_MASK( ulWritePtrFieldSize, ulWritePtrBitOfst, &ulMask ); ulTempData &= ( ~ulMask ); ulTempData |= ulWritePtr << ulWritePtrBitOfst; mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* Fetch and modify the skip pointer. */ ulAddress = ulPlayoutBaseAddress + ulSkipPtrBytesOfst; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; mOCT6100_CREATE_FEATURE_MASK( ulSkipPtrFieldSize, ulSkipPtrBitOfst, &ulMask ); ulTempData &= ( ~ulMask ); ulTempData |= ulSkipPtr << ulSkipPtrBitOfst; mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* If in the new buffer playout case, things are in a different order. */ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE ) { if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == TRUE ) && ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == TRUE ) ) { ulAddress = ulPlayoutBaseAddress + ulHardSkipBytesOfst; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; mOCT6100_CREATE_FEATURE_MASK( ulHardSkipFieldSize, ulHardSkipBitOfst, &ulMask ); ulTempData &= ( ~ulMask ); /* Check if the skip need to be clean or not. */ if ( f_pBufferPlayoutStop->fStopCleanly == FALSE ) ulTempData |= 0x1 << ulHardSkipBitOfst; mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Now is the appropriate time to skip! */ ulAddress = ulPlayoutBaseAddress + ulIgnoreBytesOfst; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, &ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; mOCT6100_CREATE_FEATURE_MASK( ulIgnoreFieldSize, ulIgnoreBitOfst, &ulMask ); ulTempData &= ( ~ulMask ); /* Set the skip bit. */ ulTempData |= 0x1 << ulIgnoreBitOfst; mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /*=======================================================================*/ /*=======================================================================*/ /* The API must set the skip bit in all the events that are queued. */ if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE ) { if ( fCheckStop == TRUE ) { if ( ulReadPtr != ulWritePtr ) { if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) { ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainRinPlayoutMemOfst; } else /* f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ { ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainSoutPlayoutMemOfst; } for ( ulCurrentPtr = ulReadPtr; ulCurrentPtr != ulWritePtr; ) { /* Set the playout event base address. */ /* 127 or 31 events image. */ ulAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_usEchoMemIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + ulEventBuffer + ( cOCT6100_PLAYOUT_EVENT_MEM_SIZE * ulCurrentPtr ); ulCurrentPtr++; ulCurrentPtr &= ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ); /* EVENT BASE + 0 playout configuration. */ WriteParams.ulWriteAddress = ulAddress; /* Set skip bit + hard-skip bit. */ WriteParams.usWriteData = 0x8000; if ( f_pBufferPlayoutStop->fStopCleanly == FALSE ) WriteParams.usWriteData |= 0x4000; mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } } } /*=======================================================================*/ /* If stop immediatly, wait the stop before leaving the function. */ if ( f_pBufferPlayoutStop->fStopCleanly == FALSE ) { /* Remember that an "hard stop" was used for the next start. */ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) pEchoChannel->fRinHardStop = TRUE; else /* if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) */ pEchoChannel->fSoutHardStop = TRUE; } /*=======================================================================*/ /* Update the channel entry to set the playing flag to FALSE. */ /* Select the port of interest. */ if ( f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) { /* Check if the global ports active stat must be decremented. */ if ( pEchoChannel->fRinBufPlaying == TRUE ) { /* Decrement the number of active buffer playout ports. */ pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts--; } pEchoChannel->fRinBufPlaying = FALSE; /* Return user information. */ if ( f_pBufferPlayoutStop->pfNotifyOnPlayoutStop != NULL ) *f_pBufferPlayoutStop->pfNotifyOnPlayoutStop = pEchoChannel->fRinBufPlayoutNotifyOnStop; /* Make sure no new event is recorded for this channel/port. */ pEchoChannel->fRinBufPlayoutNotifyOnStop = FALSE; if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE ) { pEchoChannel->ulRinBufSkipPtr = ulSkipPtr; pEchoChannel->ulRinBufWritePtr = ulWritePtr; } else /* if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE ) */ pEchoChannel->ulRinBufSkipPtr = pEchoChannel->ulRinBufWritePtr; /* The repeat flag can now be used. */ pEchoChannel->fRinBufPlayoutRepeatUsed = FALSE; /* For sure, all buffers have now been cleared on the Rin port. */ pEchoChannel->fRinBufAdded = FALSE; /* Clear optimization flag if possible. */ if ( ( pEchoChannel->fSoutBufPlaying == FALSE ) && ( pEchoChannel->fSoutBufPlayoutNotifyOnStop == FALSE ) ) { /* Buffer playout is no more active on this channel. */ pEchoChannel->fBufPlayoutActive = FALSE; } } else /* f_pBufferPlayoutStop->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ { /* Check if the global ports active stat must be decremented. */ if ( pEchoChannel->fSoutBufPlaying == TRUE ) { /* Decrement the number of active buffer playout ports. */ pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts--; } pEchoChannel->fSoutBufPlaying = FALSE; /* Return user information. */ if ( f_pBufferPlayoutStop->pfNotifyOnPlayoutStop != NULL ) *f_pBufferPlayoutStop->pfNotifyOnPlayoutStop = pEchoChannel->fSoutBufPlayoutNotifyOnStop; /* Make sure no new event is recorded for this channel/port. */ pEchoChannel->fSoutBufPlayoutNotifyOnStop = FALSE; if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == TRUE ) { pEchoChannel->ulSoutBufSkipPtr = ulSkipPtr; pEchoChannel->ulSoutBufWritePtr = ulWritePtr; } else /* if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE ) */ pEchoChannel->ulSoutBufSkipPtr = pEchoChannel->ulSoutBufWritePtr; /* The repeat flag can now be used. */ pEchoChannel->fSoutBufPlayoutRepeatUsed = FALSE; /* For sure, all buffers have now been cleared on the Sout port. */ pEchoChannel->fSoutBufAdded = FALSE; /* Clear optimization flag if possible. */ if ( ( pEchoChannel->fRinBufPlaying == FALSE ) && ( pEchoChannel->fRinBufPlayoutNotifyOnStop == FALSE ) ) { /* Buffer playout is no more active on this channel. */ pEchoChannel->fBufPlayoutActive = FALSE; } } /*=======================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_remote_debug.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains the routines used for remote debugging. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 35 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "apilib/octapi_bt0.h" #include "apilib/octapi_largmath.h" #include "oct6100api/oct6100_apiud.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_channel_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100api/oct6100_debug_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_remote_debug_pub.h" #include "octrpc/rpc_protocol.h" #include "octrpc/oct6100_rpc_protocol.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_chip_open_priv.h" #include "oct6100_channel_priv.h" #include "oct6100_debug_priv.h" #include "oct6100_remote_debug_priv.h" /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetRemoteDebugSwSizes Description: Gets the sizes of all portions of the API instance pertinent to the management of remote debugging. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pChipOpen Pointer to chip configuration struct. f_pInstSizes Pointer to struct containing instance sizes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiGetRemoteDebugSwSizes( IN tPOCT6100_CHIP_OPEN f_pChipOpen, OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) { UINT32 ulTempVar; UINT32 ulResult; /* Memory needed for remote debugging sessions. */ if ( f_pChipOpen->ulMaxRemoteDebugSessions > 0 ) { f_pInstSizes->ulRemoteDebugList = f_pChipOpen->ulMaxRemoteDebugSessions * sizeof( tOCT6100_API_REMOTE_DEBUG_SESSION ); ulResult = octapi_bt0_get_size( f_pChipOpen->ulMaxRemoteDebugSessions, 4, 4, &f_pInstSizes->ulRemoteDebugTree ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_41; f_pInstSizes->ulRemoteDebugPktCache = cOCTRPC_MAX_PACKET_BYTE_LENGTH * f_pChipOpen->ulMaxRemoteDebugSessions; f_pInstSizes->ulRemoteDebugDataBuf = cOCTRPC_MAX_PACKET_BYTE_LENGTH * 4; } else { f_pInstSizes->ulRemoteDebugList = 0; f_pInstSizes->ulRemoteDebugTree = 0; f_pInstSizes->ulRemoteDebugPktCache = 0; f_pInstSizes->ulRemoteDebugDataBuf = 0; } /* Round off the size. */ mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulRemoteDebugList, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulRemoteDebugTree, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulRemoteDebugPktCache, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulRemoteDebugDataBuf, ulTempVar ) return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiRemoteDebuggingSwInit Description: Initializes all portions of the API instance associated to remote debugging. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiRemoteDebuggingSwInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; PVOID pSessionTree; UINT32 ulResult; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; pSharedInfo->RemoteDebugInfo.ulNumSessionsOpen = 0; pSharedInfo->RemoteDebugInfo.ulMaxSessionsOpen = pSharedInfo->ChipConfig.usMaxRemoteDebugSessions; pSharedInfo->RemoteDebugInfo.ulSessionListHead = cOCT6100_INVALID_VALUE; pSharedInfo->RemoteDebugInfo.ulSessionListTail = cOCT6100_INVALID_VALUE; if ( pSharedInfo->ChipConfig.usMaxRemoteDebugSessions > 0 ) { mOCT6100_GET_REMOTE_DEBUG_TREE_PNT( pSharedInfo, pSessionTree ) ulResult = octapi_bt0_init( ( ( PVOID* )&pSessionTree ), pSharedInfo->ChipConfig.usMaxRemoteDebugSessions, 4, 4 ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_42; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_tlv.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains the functions used to read information allowing the API to know where all the features supported by this API version are located in the chip's external memory. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 109 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "oct6100api/oct6100_apiud.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_tlv_priv.h" /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiProcessTlvRegion Description: This function will read and interpret the TLV memory of the chip to obtain memory offsets and features available of the image loaded into the chip. The API will read this region until it finds a TLV type of 0 with a length of 0. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiProcessTlvRegion( tPOCT6100_INSTANCE_API f_pApiInstance ) { tOCT6100_READ_PARAMS ReadParams; UINT16 usReadData; UINT32 ulResult; UINT32 ulTlvTypeField; UINT32 ulTlvLengthField; UINT32 ulTlvWritingTimeoutCount = 0; UINT32 ulConditionFlag = TRUE; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; /* Set the address of the first TLV type. */ ReadParams.ulReadAddress = cOCT6100_TLV_BASE; ReadParams.ulReadAddress += 2; /* Wait for the TLV configuration to be configured in memory. */ while ( ulConditionFlag ) { /* Read the TLV write done flag. */ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( usReadData & 0x1 ) break; ulTlvWritingTimeoutCount++; if ( ulTlvWritingTimeoutCount == 0x100000 ) return cOCT6100_ERR_TLV_TIMEOUT; } /*======================================================================*/ /* Read the first 16 bits of the TLV type. */ ReadParams.ulReadAddress += 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulTlvTypeField = usReadData << 16; /* Read the last word of the TLV type. */ ReadParams.ulReadAddress += 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulTlvTypeField |= usReadData; /*======================================================================*/ /*======================================================================*/ /* Now, read the TLV field length. */ ReadParams.ulReadAddress += 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulTlvLengthField = usReadData << 16; /* Read the last word of the TLV length. */ ReadParams.ulReadAddress += 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulTlvLengthField |= usReadData; /* Modify the address to point at the TLV value field. */ ReadParams.ulReadAddress += 2; /*======================================================================*/ /* Read the TLV value until the end of TLV region is reached. */ while( !((ulTlvTypeField == 0) && (ulTlvLengthField == 0)) ) { ulResult = Oct6100ApiInterpretTlvEntry( f_pApiInstance, ulTlvTypeField, ulTlvLengthField, ReadParams.ulReadAddress ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Set the address to after the TLV value. */ ReadParams.ulReadAddress += ulTlvLengthField; /*======================================================================*/ /* Read the first 16 bits of the TLV type. */ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulTlvTypeField = usReadData << 16; /* Read the last word of the TLV type. */ ReadParams.ulReadAddress += 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulTlvTypeField |= usReadData; /*======================================================================*/ /*======================================================================*/ /* Now, read the TLV field length. */ ReadParams.ulReadAddress += 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulTlvLengthField = usReadData << 16; /* Read the last word of the TLV length. */ ReadParams.ulReadAddress += 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulTlvLengthField |= usReadData; ReadParams.ulReadAddress += 2; /*======================================================================*/ } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiInterpretTlvEntry Description: This function will interpret a TLV entry from the chip. All known TLV types by the API are exhaustively listed here. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulTlvFieldType Type of the TLV field to interpret. f_ulTlvFieldLength Byte length of the TLV field. f_ulTlvValueAddress Address where the data of the TLV block starts. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiInterpretTlvEntry( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulTlvFieldType, IN UINT32 f_ulTlvFieldLength, IN UINT32 f_ulTlvValueAddress ) { tOCT6100_READ_PARAMS ReadParams; UINT32 ulResult = cOCT6100_ERR_OK; UINT16 usReadData; UINT32 i; UINT32 ulTempValue = 0; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; /* Find out how to interpret the TLV value according to the TLV type. */ switch( f_ulTlvFieldType ) { case cOCT6100_TLV_TYPE_VERSION_NUMBER: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_VERSION_NUMBER, cOCT6100_TLV_MAX_LENGTH_VERSION_NUMBER ); if ( ulResult == cOCT6100_ERR_OK ) { ReadParams.ulReadAddress = f_ulTlvValueAddress; for( i = 0; i < (f_ulTlvFieldLength/2); i++ ) { /* Perform the actual read. */ mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; f_pApiInstance->pSharedInfo->ImageInfo.szVersionNumber[ (i * 2) ] = (UINT8)((usReadData >> 8) & 0xFF); f_pApiInstance->pSharedInfo->ImageInfo.szVersionNumber[ (i * 2) + 1 ] = (UINT8)((usReadData >> 0) & 0xFF); /* Modify the address. */ ReadParams.ulReadAddress += 2; } } break; case cOCT6100_TLV_TYPE_CUSTOMER_PROJECT_ID: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CUSTOMER_PROJECT_ID, cOCT6100_TLV_MAX_LENGTH_CUSTOMER_PROJECT_ID ); if ( ulResult == cOCT6100_ERR_OK ) { /* Perform the actual read. */ ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->ImageInfo.ulBuildId ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } break; case cOCT6100_TLV_TYPE_CH0_MAIN_BASE_ADDRESS: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CH0_MAIN_BASE_ADDRESS, cOCT6100_TLV_MAX_LENGTH_CH0_MAIN_BASE_ADDRESS ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase &= 0x0FFFFFFF; /* Modify the base address to incorporate the external memory offset. */ f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemBase += cOCT6100_EXTERNAL_MEM_BASE_ADDRESS; } break; case cOCT6100_TLV_TYPE_CH_MAIN_SIZE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CH_MAIN_SIZE, cOCT6100_TLV_MAX_LENGTH_CH_MAIN_SIZE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainMemSize ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } break; case cOCT6100_TLV_TYPE_CH_MAIN_IO_OFFSET: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CH_MAIN_IO_OFFSET, cOCT6100_TLV_MAX_LENGTH_CH_MAIN_IO_OFFSET ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoMemOfst ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } break; case cOCT6100_TLV_TYPE_CH_MAIN_ZCB_OFFSET: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CH_MAIN_ZCB_OFFSET, cOCT6100_TLV_MAX_LENGTH_CH_MAIN_ZCB_OFFSET ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainRinCBMemOfst ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } break; case cOCT6100_TLV_TYPE_CH_MAIN_ZCB_SIZE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CH_MAIN_ZCB_SIZE, cOCT6100_TLV_MAX_LENGTH_CH_MAIN_ZCB_SIZE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainRinCBMemSize ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } break; case cOCT6100_TLV_TYPE_CH_MAIN_XCB_OFFSET: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CH_MAIN_XCB_OFFSET, cOCT6100_TLV_MAX_LENGTH_CH_MAIN_XCB_OFFSET ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainSinCBMemOfst ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } break; case cOCT6100_TLV_TYPE_CH_MAIN_XCB_SIZE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CH_MAIN_XCB_SIZE, cOCT6100_TLV_MAX_LENGTH_CH_MAIN_XCB_SIZE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainSinCBMemSize ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } break; case cOCT6100_TLV_TYPE_CH_MAIN_YCB_OFFSET: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CH_MAIN_YCB_OFFSET, cOCT6100_TLV_MAX_LENGTH_CH_MAIN_YCB_OFFSET ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainSoutCBMemOfst ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } break; case cOCT6100_TLV_TYPE_CH_MAIN_YCB_SIZE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CH_MAIN_YCB_SIZE, cOCT6100_TLV_MAX_LENGTH_CH_MAIN_YCB_SIZE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainSoutCBMemSize ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } break; case cOCT6100_TLV_TYPE_FREE_MEM_BASE_ADDRESS: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_FREE_MEM_BASE_ADDRESS, cOCT6100_TLV_MAX_LENGTH_FREE_MEM_BASE_ADDRESS ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulFreeMemBaseAddress ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; f_pApiInstance->pSharedInfo->MemoryMap.ulFreeMemBaseAddress &= 0x0FFFFFFF; } break; case cOCT6100_TLV_TYPE_CHAN_MAIN_IO_STATS_OFFSET: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CHAN_MAIN_IO_STATS_OFFSET, cOCT6100_TLV_MAX_LENGTH_CHAN_MAIN_IO_STATS_OFFSET ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoStatsOfst ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } break; case cOCT6100_TLV_TYPE_CHAN_MAIN_IO_STATS_SIZE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CHAN_MAIN_IO_STATS_OFFSET, cOCT6100_TLV_MAX_LENGTH_CHAN_MAIN_IO_STATS_OFFSET ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainIoStatsSize ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } break; case cOCT6100_TLV_TYPE_CH_ROOT_CONF_OFFSET: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CH_ROOT_CONF_OFFSET, cOCT6100_TLV_MAX_LENGTH_CH_ROOT_CONF_OFFSET ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanRootConfOfst ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } break; case cOCT6100_TLV_TYPE_POA_CH_MAIN_ZPO_OFFSET: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_POA_CH_MAIN_ZPO_OFFSET, cOCT6100_TLV_MAX_LENGTH_POA_CH_MAIN_ZPO_OFFSET ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainRinPlayoutMemOfst ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } break; case cOCT6100_TLV_TYPE_POA_CH_MAIN_ZPO_SIZE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_POA_CH_MAIN_ZPO_SIZE, cOCT6100_TLV_MAX_LENGTH_POA_CH_MAIN_ZPO_SIZE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainRinPlayoutMemSize ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } break; case cOCT6100_TLV_TYPE_POA_CH_MAIN_YPO_OFFSET: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_POA_CH_MAIN_YPO_OFFSET, cOCT6100_TLV_MAX_LENGTH_POA_CH_MAIN_YPO_OFFSET ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainSoutPlayoutMemOfst ); } break; case cOCT6100_TLV_TYPE_POA_CH_MAIN_YPO_SIZE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_POA_CH_MAIN_YPO_SIZE, cOCT6100_TLV_MAX_LENGTH_POA_CH_MAIN_YPO_SIZE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ulChanMainSoutPlayoutMemSize ); } break; case cOCT6100_TLV_TYPE_POA_BOFF_RW_ZWP: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_ZWP, cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_ZWP ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst ); } break; case cOCT6100_TLV_TYPE_POA_BOFF_RW_ZIS: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_ZIS, cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_ZIS ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst ); } break; case cOCT6100_TLV_TYPE_POA_BOFF_RW_ZSP: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_ZSP, cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_ZSP ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst ); } break; case cOCT6100_TLV_TYPE_POA_BOFF_RW_YWP: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_YWP, cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_YWP ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst ); } break; case cOCT6100_TLV_TYPE_POA_BOFF_RW_YIS: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_YIS, cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_YIS ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst ); } break; case cOCT6100_TLV_TYPE_POA_BOFF_RW_YSP: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RW_YSP, cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RW_YSP ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst ); } break; case cOCT6100_TLV_TYPE_POA_BOFF_RO_ZRP: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RO_ZRP, cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RO_ZRP ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst ); } break; case cOCT6100_TLV_TYPE_POA_BOFF_RO_YRP: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_POA_BOFF_RO_YRP, cOCT6100_TLV_MAX_LENGTH_POA_BOFF_RO_YRP ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst ); } break; case cOCT6100_TLV_TYPE_CNR_CONF_BOFF_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CNR_CONF_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_CNR_CONF_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ConferencingNoiseReductionOfst ); } break; case cOCT6100_TLV_TYPE_ANR_CONF_BOFF_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_ANR_CONF_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_ANR_CONF_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.AdaptiveNoiseReductionOfst ); } break; case cOCT6100_TLV_TYPE_HZ_CONF_BOFF_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_HZ_CONF_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_HZ_CONF_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.RinDcOffsetRemovalOfst ); } /* Set flag indicating that the feature is present.*/ f_pApiInstance->pSharedInfo->ImageInfo.fRinDcOffsetRemoval = TRUE; break; case cOCT6100_TLV_TYPE_HX_CONF_BOFF_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_HX_CONF_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_HX_CONF_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.SinDcOffsetRemovalOfst ); } /* Set flag indicating that the feature is present.*/ f_pApiInstance->pSharedInfo->ImageInfo.fSinDcOffsetRemoval = TRUE; break; case cOCT6100_TLV_TYPE_LCA_Z_CONF_BOFF_RW_GAIN: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_LCA_Z_CONF_BOFF_RW_GAIN, cOCT6100_TLV_MAX_LENGTH_LCA_Z_CONF_BOFF_RW_GAIN ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.RinLevelControlOfst ); } break; case cOCT6100_TLV_TYPE_LCA_Y_CONF_BOFF_RW_GAIN: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_LCA_Y_CONF_BOFF_RW_GAIN, cOCT6100_TLV_MAX_LENGTH_LCA_Y_CONF_BOFF_RW_GAIN ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.SoutLevelControlOfst ); } break; case cOCT6100_TLV_TYPE_CNA_CONF_BOFF_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CNA_CONF_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_CNA_CONF_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ComfortNoiseModeOfst ); } /* Set flag indicating that the feature is present.*/ f_pApiInstance->pSharedInfo->ImageInfo.fComfortNoise = TRUE; break; case cOCT6100_TLV_TYPE_NOA_CONF_BOFF_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_NOA_CONF_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_NOA_CONF_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.NlpControlFieldOfst ); } /* Set flag indicating that the feature is present.*/ f_pApiInstance->pSharedInfo->ImageInfo.fNlpControl = TRUE; break; case cOCT6100_TLV_TYPE_VFA_CONF_BOFF_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_VFA_CONF_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_VFA_CONF_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.VadControlFieldOfst ); } /* Set flag indicating that the feature is present.*/ f_pApiInstance->pSharedInfo->ImageInfo.fSilenceSuppression = TRUE; break; case cOCT6100_TLV_TYPE_TLA_MAIN_IO_BOFF_RW_TAIL_DISP: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_TLA_MAIN_IO_BOFF_RW_TAIL_DISP, cOCT6100_TLV_MAX_LENGTH_TLA_MAIN_IO_BOFF_RW_TAIL_DISP ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PouchTailDisplOfst ); } break; case cOCT6100_TLV_TYPE_BOOTA_POUCH_BOFF_RW_BOOT_INST: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_BOOTA_POUCH_BOFF_RW_BOOT_INST, cOCT6100_TLV_MAX_LENGTH_BOOTA_POUCH_BOFF_RW_BOOT_INST ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PouchBootInstructionOfst ); } break; case cOCT6100_TLV_TYPE_BOOTA_POUCH_BOFF_RW_BOOT_RESULT: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_BOOTA_POUCH_BOFF_RW_BOOT_RESULT, cOCT6100_TLV_MAX_LENGTH_BOOTA_POUCH_BOFF_RW_BOOT_RESULT ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PouchBootResultOfst ); } break; case cOCT6100_TLV_TYPE_TDM_CONF_BOFF_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_TDM_CONF_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_TDM_CONF_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ToneDisablerControlOfst ); } f_pApiInstance->pSharedInfo->ImageInfo.fToneDisabler = TRUE; break; case cOCT6100_TLV_TYPE_DIS_CONF_BOFF_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_DIS_CONF_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_DIS_CONF_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.TailDisplEnableOfst ); } f_pApiInstance->pSharedInfo->ImageInfo.fTailDisplacement = TRUE; break; case cOCT6100_TLV_TYPE_NT_CONF_BOFF_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_NT_CONF_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_NT_CONF_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.NlpTrivialFieldOfst ); } break; case cOCT6100_TLV_TYPE_DEBUG_CHAN_INDEX_VALUE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_DEBUG_CHAN_INDEX_VALUE, cOCT6100_TLV_MAX_LENGTH_DEBUG_CHAN_INDEX_VALUE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); } f_pApiInstance->pSharedInfo->DebugInfo.usRecordMemIndex = (UINT16)( ulTempValue & 0xFFFF ); break; case cOCT6100_TLV_TYPE_ADPCM_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_ADPCM_ENABLE, cOCT6100_TLV_MAX_LENGTH_ADPCM_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); } if ( ulTempValue == 0 ) f_pApiInstance->pSharedInfo->ImageInfo.fAdpcm = FALSE; else f_pApiInstance->pSharedInfo->ImageInfo.fAdpcm = TRUE; break; case cOCT6100_TLV_TYPE_CONFERENCING_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CONFERENCING_ENABLE, cOCT6100_TLV_MAX_LENGTH_CONFERENCING_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); } if ( ulTempValue == 0 ) f_pApiInstance->pSharedInfo->ImageInfo.fConferencing = FALSE; else f_pApiInstance->pSharedInfo->ImageInfo.fConferencing = TRUE; break; case cOCT6100_TLV_TYPE_TONE_DETECTOR_PROFILE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_TONE_DETECTOR_PROFILE, cOCT6100_TLV_MIN_LENGTH_TONE_DETECTOR_PROFILE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->ImageInfo.ulToneProfileNumber ); } break; case cOCT6100_TLV_TYPE_MAX_TAIL_DISPLACEMENT: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_MAX_TAIL_DISPLACEMENT, cOCT6100_TLV_MAX_LENGTH_MAX_TAIL_DISPLACEMENT ); if ( ulResult == cOCT6100_ERR_OK ) { UINT32 ulTailDispTempValue = 0; ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTailDispTempValue ); ulTailDispTempValue += 1; /* Convert the value into milliseconds.*/ ulTailDispTempValue *= 16; /* value was given in multiple of 16 ms. */ if ( ulTailDispTempValue >= 128 ) f_pApiInstance->pSharedInfo->ImageInfo.usMaxTailDisplacement = (UINT16)( ulTailDispTempValue - 128 ); else f_pApiInstance->pSharedInfo->ImageInfo.usMaxTailDisplacement = 0; } break; case cOCT6100_TLV_TYPE_AEC_CONF_BOFF_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_AEC_CONF_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_AEC_CONF_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.AecFieldOfst ); } /* Set the flag. */ f_pApiInstance->pSharedInfo->ImageInfo.fAecEnabled = TRUE; /* Acoustic echo cancellation available! */ f_pApiInstance->pSharedInfo->ImageInfo.fAcousticEcho = TRUE; break; case cOCT6100_TLV_TYPE_PCM_LEAK_CONF_BOFF_RW: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_PCM_LEAK_CONF_BOFF_RW, cOCT6100_TLV_MAX_LENGTH_PCM_LEAK_CONF_BOFF_RW ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PcmLeakFieldOfst ); } f_pApiInstance->pSharedInfo->ImageInfo.fNonLinearityBehaviorA = TRUE; break; case cOCT6100_TLV_TYPE_DEFAULT_ERL_CONF_BOFF_RW: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_DEFAULT_ERL_CONF_BOFF_RW, cOCT6100_TLV_MAX_LENGTH_DEFAULT_ERL_CONF_BOFF_RW ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.DefaultErlFieldOfst ); } /* Set the flag. */ f_pApiInstance->pSharedInfo->ImageInfo.fDefaultErl = TRUE; break; case cOCT6100_TLV_TYPE_TONE_REM_CONF_BOFF_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_TONE_REM_CONF_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_TONE_REM_CONF_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ToneRemovalFieldOfst ); } /* Set the flag. */ f_pApiInstance->pSharedInfo->ImageInfo.fToneRemoval = TRUE; break; case cOCT6100_TLV_TYPE_TLA_MAIN_IO_BOFF_RW_MAX_ECHO_POINT: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_TLA_MAIN_IO_BOFF_RW_MAX_ECHO_POINT, cOCT6100_TLV_MAX_LENGTH_TLA_MAIN_IO_BOFF_RW_MAX_ECHO_POINT ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ChanMainIoMaxEchoPointOfst ); } /* Set the flag. */ f_pApiInstance->pSharedInfo->ImageInfo.fMaxEchoPoint = TRUE; break; case cOCT6100_TLV_TYPE_NLP_CONV_CAP_CONF_BOFF_RW: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_NLP_CONV_CAP_CONF_BOFF_RW, cOCT6100_TLV_MAX_LENGTH_NLP_CONV_CAP_CONF_BOFF_RW ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.NlpConvCapFieldOfst ); } /* Set the flag. */ f_pApiInstance->pSharedInfo->ImageInfo.fNonLinearityBehaviorB = TRUE; break; case cOCT6100_TLV_TYPE_MATRIX_EVENT_SIZE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_MATRIX_EVENT_SIZE, cOCT6100_TLV_MAX_LENGTH_MATRIX_EVENT_SIZE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->DebugInfo.ulDebugEventSize ); } break; case cOCT6100_TLV_TYPE_CNR_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CNR_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_CNR_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); f_pApiInstance->pSharedInfo->ImageInfo.fConferencingNoiseReduction = (UINT8)( ulTempValue & 0xFF ); if ( f_pApiInstance->pSharedInfo->ImageInfo.fConferencingNoiseReduction == TRUE ) { /* Set flag indicating that the dominant speaker feature is present. */ f_pApiInstance->pSharedInfo->ImageInfo.fDominantSpeakerEnabled = TRUE; } } break; case cOCT6100_TLV_TYPE_MAX_TAIL_LENGTH_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_MAX_TAIL_LENGTH_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_MAX_TAIL_LENGTH_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); f_pApiInstance->pSharedInfo->ImageInfo.usMaxTailLength = (UINT16)( ulTempValue & 0xFFFF ); } break; case cOCT6100_TLV_TYPE_MAX_NUMBER_OF_CHANNELS: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_MAX_NUMBER_OF_CHANNELS, cOCT6100_TLV_MAX_LENGTH_MAX_NUMBER_OF_CHANNELS ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); f_pApiInstance->pSharedInfo->ImageInfo.usMaxNumberOfChannels = (UINT16)( ulTempValue & 0xFFFF ); } break; case cOCT6100_TLV_TYPE_PLAYOUT_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_PLAYOUT_ENABLE, cOCT6100_TLV_MAX_LENGTH_PLAYOUT_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { /* Set flag indicating that the feature is present. */ ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); f_pApiInstance->pSharedInfo->ImageInfo.fBufferPlayout = (UINT8)( ulTempValue & 0xFF ); } break; case cOCT6100_TLV_TYPE_DOMINANT_SPEAKER_BOFF_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_DOMINANT_SPEAKER_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_DOMINANT_SPEAKER_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.DominantSpeakerFieldOfst ); } break; case cOCT6100_TLV_TYPE_TAIL_DISP_CONF_BOFF_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_TAIL_DISP_CONF_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_TAIL_DISP_CONF_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PerChanTailDisplacementFieldOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fPerChannelTailDisplacement = TRUE; } break; case cOCT6100_TLV_TYPE_ANR_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_ANR_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_ANR_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); f_pApiInstance->pSharedInfo->ImageInfo.fAdaptiveNoiseReduction = (UINT8)( ulTempValue & 0xFF ); } break; case cOCT6100_TLV_TYPE_MUSIC_PROTECTION_RW_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_MUSIC_PROTECTION_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_MUSIC_PROTECTION_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); f_pApiInstance->pSharedInfo->ImageInfo.fMusicProtection = (UINT8)( ulTempValue & 0xFF ); } break; case cOCT6100_TLV_TYPE_AEC_DEFAULT_ERL_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_AEC_DEFAULT_ERL_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_AEC_DEFAULT_ERL_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.AecDefaultErlFieldOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fAecDefaultErl = TRUE; } break; case cOCT6100_TLV_TYPE_Z_ALC_TARGET_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_Z_ALC_TARGET_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_Z_ALC_TARGET_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.RinAutoLevelControlTargetOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fRinAutoLevelControl = TRUE; } break; case cOCT6100_TLV_TYPE_Y_ALC_TARGET_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_Y_ALC_TARGET_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_Y_ALC_TARGET_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.SoutAutoLevelControlTargetOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fSoutAutoLevelControl = TRUE; } break; case cOCT6100_TLV_TYPE_Z_HLC_TARGET_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_Z_HLC_TARGET_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_Z_HLC_TARGET_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.RinHighLevelCompensationThresholdOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fRinHighLevelCompensation = TRUE; } break; case cOCT6100_TLV_TYPE_Y_HLC_TARGET_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_Y_HLC_TARGET_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_Y_HLC_TARGET_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.SoutHighLevelCompensationThresholdOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fSoutHighLevelCompensation = TRUE; } break; case cOCT6100_TLV_TYPE_ALC_HLC_STATUS_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_ALC_HLC_STATUS_BOFF_RW_ENABLE, cOCT6100_TLV_MAX_LENGTH_ALC_HLC_STATUS_BOFF_RW_ENABLE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.AlcHlcStatusOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fAlcHlcStatus = TRUE; } break; case cOCT6100_TLV_TYPE_Z_PLAYOUT_HARD_SKIP_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_Z_PLAYOUT_HARD_SKIP_BOFF_RW, cOCT6100_TLV_MAX_LENGTH_Z_PLAYOUT_HARD_SKIP_BOFF_RW ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip = TRUE; } break; case cOCT6100_TLV_TYPE_Y_PLAYOUT_HARD_SKIP_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_Y_PLAYOUT_HARD_SKIP_BOFF_RW, cOCT6100_TLV_MAX_LENGTH_Y_PLAYOUT_HARD_SKIP_BOFF_RW ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip = TRUE; } break; case cOCT6100_TLV_TYPE_AFT_FIELD_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_AFT_FIELD_BOFF_RW, cOCT6100_TLV_MAX_LENGTH_AFT_FIELD_BOFF_RW ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.AftControlOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fAftControl = TRUE; } break; case cOCT6100_TLV_TYPE_VOICE_DETECTED_STAT_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_VOICE_DETECTED_STAT_BOFF_RW, cOCT6100_TLV_MAX_LENGTH_VOICE_DETECTED_STAT_BOFF_RW ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.SinVoiceDetectedStatOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fSinVoiceDetectedStat = TRUE; } break; case cOCT6100_TLV_TYPE_GAIN_APPLIED_RIN_STAT_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_GAIN_APPLIED_RIN_STAT_BOFF_RW, cOCT6100_TLV_MAX_LENGTH_GAIN_APPLIED_RIN_STAT_BOFF_RW ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.RinAppliedGainStatOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fRinAppliedGainStat = TRUE; } break; case cOCT6100_TLV_TYPE_GAIN_APPLIED_SOUT_STAT_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_GAIN_APPLIED_SOUT_STAT_BOFF_RW, cOCT6100_TLV_MAX_LENGTH_GAIN_APPLIED_SOUT_STAT_BOFF_RW ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.SoutAppliedGainStatOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fSoutAppliedGainStat = TRUE; } break; case cOCT6100_TLV_TYPE_MAX_ADAPT_ALE_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_MAX_ADAPT_ALE_BOFF_RW, cOCT6100_TLV_MAX_LENGTH_MAX_ADAPT_ALE_BOFF_RW ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.AdaptiveAleOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fListenerEnhancement = TRUE; } break; case cOCT6100_TLV_TYPE_RIN_ANR_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_RIN_ANR_BOFF_RW, cOCT6100_TLV_MAX_LENGTH_RIN_ANR_BOFF_RW ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.RinAnrOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fRoutNoiseReduction = TRUE; } break; case cOCT6100_TLV_TYPE_RIN_MUTE_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_RIN_MUTE_BOFF_RW, cOCT6100_TLV_MAX_LENGTH_RIN_MUTE_BOFF_RW ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.RinMuteOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fRinMute = TRUE; } break; case cOCT6100_TLV_TYPE_SIN_MUTE_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_SIN_MUTE_BOFF_RW, cOCT6100_TLV_MAX_LENGTH_SIN_MUTE_BOFF_RW ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.SinMuteOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fSinMute = TRUE; } break; case cOCT6100_TLV_TYPE_NUMBER_PLAYOUT_EVENTS: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_NUMBER_PLAYOUT_EVENTS, cOCT6100_TLV_MAX_LENGTH_NUMBER_PLAYOUT_EVENTS ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); f_pApiInstance->pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents = (UINT8)( ulTempValue & 0xFF ); } break; case cOCT6100_TLV_TYPE_ANR_SNR_IMPROVEMENT_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_ANR_SNR_IMPROVEMENT_BOFF_RW, cOCT6100_TLV_MAX_LENGTH_ANR_SNR_IMPROVEMENT_BOFF_RW ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.AnrSnrEnhancementOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fAnrSnrEnhancement = TRUE; } break; case cOCT6100_TLV_TYPE_ANR_AGRESSIVITY_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_ANR_AGRESSIVITY_BOFF_RW, cOCT6100_TLV_MAX_LENGTH_ANR_AGRESSIVITY_BOFF_RW ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.AnrVoiceNoiseSegregationOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fAnrVoiceNoiseSegregation = TRUE; } break; case cOCT6100_TLV_TYPE_CHAN_TAIL_LENGTH_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CHAN_TAIL_LENGTH_BOFF, cOCT6100_TLV_MAX_LENGTH_CHAN_TAIL_LENGTH_BOFF ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PerChanTailLengthFieldOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fPerChannelTailLength = TRUE; } break; case cOCT6100_TLV_TYPE_CHAN_VQE_TONE_DISABLING_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_CHAN_VQE_TONE_DIS_BOFF, cOCT6100_TLV_MAX_LENGTH_CHAN_VQE_TONE_DIS_BOFF ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.ToneDisablerVqeActivationDelayOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fToneDisablerVqeActivationDelay = TRUE; } break; case cOCT6100_TLV_TYPE_AF_TAIL_DISP_VALUE_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_AF_TAIL_DISP_VALUE_BOFF, cOCT6100_TLV_MAX_LENGTH_AF_TAIL_DISP_VALUE_BOFF ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.AfTailDisplacementFieldOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fAfTailDisplacement = TRUE; } break; case cOCT6100_TLV_TYPE_POUCH_COUNTER_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_POUCH_COUNTER_BOFF, cOCT6100_TLV_MAX_LENGTH_POUCH_COUNTER_BOFF ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.PouchCounterFieldOfst ); f_pApiInstance->pSharedInfo->DebugInfo.fPouchCounter = TRUE; } break; case cOCT6100_TLV_TYPE_AEC_TAIL_LENGTH_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_AEC_TAIL_BOFF, cOCT6100_TLV_MAX_LENGTH_AEC_TAIL_BOFF ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.AecTailLengthFieldOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fAecTailLength = TRUE; } break; case cOCT6100_TLV_TYPE_MATRIX_DWORD_BASE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_MATRIX_DWORD_BASE, cOCT6100_TLV_MAX_LENGTH_MATRIX_DWORD_BASE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->DebugInfo.ulMatrixBaseAddress ); /* Mask the upper bits set by the firmware. */ f_pApiInstance->pSharedInfo->DebugInfo.ulMatrixBaseAddress &= 0x0FFFFFFF; /* Modify the base address to incorporate the external memory offset. */ f_pApiInstance->pSharedInfo->DebugInfo.ulMatrixBaseAddress += cOCT6100_EXTERNAL_MEM_BASE_ADDRESS; } break; case cOCT6100_TLV_TYPE_DEBUG_CHAN_STATS_BYTE_SIZE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_DEBUG_CHAN_STATS_BYTE_SIZE, cOCT6100_TLV_MAX_LENGTH_DEBUG_CHAN_STATS_BYTE_SIZE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ); } break; case cOCT6100_TLV_TYPE_DEBUG_CHAN_LITE_STATS_BYTE_SIZE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_DEBUG_CHAN_LITE_STATS_BYTE_SIZE, cOCT6100_TLV_MAX_LENGTH_DEBUG_CHAN_LITE_STATS_BYTE_SIZE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->DebugInfo.ulDebugChanLiteStatsByteSize ); } break; case cOCT6100_TLV_TYPE_HOT_CHANNEL_SELECT_DWORD_BASE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_HOT_CHANNEL_SELECT_DWORD_BASE, cOCT6100_TLV_MAX_LENGTH_HOT_CHANNEL_SELECT_DWORD_BASE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->DebugInfo.ulHotChannelSelectBaseAddress ); } break; case cOCT6100_TLV_TYPE_MATRIX_TIMESTAMP_DWORD_BASE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_TIMESTAMP_DWORD_BASE, cOCT6100_TLV_MAX_LENGTH_TIMESTAMP_DWORD_BASE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->DebugInfo.ulMatrixTimestampBaseAddress ); } break; case cOCT6100_TLV_TYPE_MATRIX_WP_DWORD_BASE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_MATRIX_WP_DWORD_BASE, cOCT6100_TLV_MAX_LENGTH_MATRIX_WP_DWORD_BASE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->DebugInfo.ulMatrixWpBaseAddress ); } break; case cOCT6100_TLV_TYPE_AF_WRITE_PTR_BYTE_OFFSET: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_AF_WRITE_PTR_BYTE_OFFSET, cOCT6100_TLV_MAX_LENGTH_AF_WRITE_PTR_BYTE_OFFSET ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->DebugInfo.ulAfWritePtrByteOffset ); } break; case cOCT6100_TLV_TYPE_RECORDED_PCM_EVENT_BYTE_SIZE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_RECORDED_PCM_EVENT_BYTE_SIZE, cOCT6100_TLV_MAX_LENGTH_RECORDED_PCM_EVENT_BYTE_SIZE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize ); } break; case cOCT6100_TLV_TYPE_IS_ISR_CALLED_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_IS_ISR_CALLED_BOFF, cOCT6100_TLV_MAX_LENGTH_IS_ISR_CALLED_BOFF ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.IsIsrCalledFieldOfst ); f_pApiInstance->pSharedInfo->DebugInfo.fIsIsrCalledField = TRUE; } break; case cOCT6100_TLV_TYPE_MUSIC_PROTECTION_ENABLE_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_MUSIC_PROTECTION_ENABLE_BOFF, cOCT6100_TLV_MAX_LENGTH_MUSIC_PROTECTION_ENABLE_BOFF ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.MusicProtectionFieldOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fMusicProtectionConfiguration = TRUE; } break; case cOCT6100_TLV_TYPE_IDLE_CODE_DETECTION_ENABLE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_IDLE_CODE_DETECTION, cOCT6100_TLV_MAX_LENGTH_IDLE_CODE_DETECTION ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); f_pApiInstance->pSharedInfo->ImageInfo.fIdleCodeDetection = (UINT8)( ulTempValue & 0xFF ); } break; case cOCT6100_TLV_TYPE_IDLE_CODE_DETECTION_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_IDLE_CODE_DETECTION_BOFF, cOCT6100_TLV_MAX_LENGTH_IDLE_CODE_DETECTION_BOFF ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.IdleCodeDetectionFieldOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fIdleCodeDetectionConfiguration = TRUE; } break; case cOCT6100_TLV_TYPE_IMAGE_TYPE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_IMAGE_TYPE, cOCT6100_TLV_MAX_LENGTH_IMAGE_TYPE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); /* Check if read image type value is what's expected. */ if ( ( ulTempValue != cOCT6100_IMAGE_TYPE_WIRELINE ) && ( ulTempValue != cOCT6100_IMAGE_TYPE_COMBINED ) ) return cOCT6100_ERR_FATAL_E9; f_pApiInstance->pSharedInfo->ImageInfo.byImageType = (UINT8)( ulTempValue & 0xFF ); } break; case cOCT6100_TLV_TYPE_MAX_WIRELINE_CHANNELS: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_MAX_WIRELINE_CHANNELS, cOCT6100_TLV_MAX_LENGTH_MAX_WIRELINE_CHANNELS ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); } break; case cOCT6100_TLV_TYPE_AF_EVENT_CB_SIZE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_AF_EVENT_CB_BYTE_SIZE, cOCT6100_TLV_MAX_LENGTH_AF_EVENT_CB_BYTE_SIZE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->DebugInfo.ulAfEventCbByteSize ); } break; case cOCT6100_TLV_TYPE_BUFFER_PLAYOUT_SKIP_IN_EVENTS: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_BUFFER_PLAYOUT_SKIP_IN_EVENTS, cOCT6100_TLV_MAX_LENGTH_BUFFER_PLAYOUT_SKIP_IN_EVENTS ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); f_pApiInstance->pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents = TRUE; } break; case cOCT6100_TLV_TYPE_ZZ_ENERGY_CHAN_STATS_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_ZZ_ENERGY_CHAN_STATS_BOFF, cOCT6100_TLV_MAX_LENGTH_ZZ_ENERGY_CHAN_STATS_BOFF ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.RinEnergyStatFieldOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fRinEnergyStat = TRUE; } break; case cOCT6100_TLV_TYPE_YY_ENERGY_CHAN_STATS_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_YY_ENERGY_CHAN_STATS_BOFF, cOCT6100_TLV_MAX_LENGTH_YY_ENERGY_CHAN_STATS_BOFF ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.SoutEnergyStatFieldOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fSoutEnergyStat = TRUE; } break; case cOCT6100_TLV_TYPE_DOUBLE_TALK_BEH_MODE: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_DOUBLE_TALK_BEH_MODE, cOCT6100_TLV_MAX_LENGTH_DOUBLE_TALK_BEH_MODE ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); if ( ulTempValue != 0 ) f_pApiInstance->pSharedInfo->ImageInfo.fDoubleTalkBehavior = TRUE; else f_pApiInstance->pSharedInfo->ImageInfo.fDoubleTalkBehavior = FALSE; } break; case cOCT6100_TLV_TYPE_DOUBLE_TALK_BEH_MODE_BOFF: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_DOUBLE_TALK_BEH_MODE_BOFF, cOCT6100_TLV_MAX_LENGTH_DOUBLE_TALK_BEH_MODE_BOFF ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiTlvReadBitOffsetStruct( f_pApiInstance, f_ulTlvValueAddress, &f_pApiInstance->pSharedInfo->MemoryMap.DoubleTalkBehaviorFieldOfst ); f_pApiInstance->pSharedInfo->ImageInfo.fDoubleTalkBehaviorFieldOfst = TRUE; } break; case cOCT6100_TLV_TYPE_SOUT_NOISE_BLEACHING: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_SOUT_NOISE_BLEACHING, cOCT6100_TLV_MAX_LENGTH_SOUT_NOISE_BLEACHING ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); if ( ulTempValue != 0 ) f_pApiInstance->pSharedInfo->ImageInfo.fSoutNoiseBleaching = TRUE; else f_pApiInstance->pSharedInfo->ImageInfo.fSoutNoiseBleaching = FALSE; } break; case cOCT6100_TLV_TYPE_NLP_STATISTICS: ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_NLP_STATISTICS, cOCT6100_TLV_MAX_LENGTH_NLP_STATISTICS ); if ( ulResult == cOCT6100_ERR_OK ) { ulResult = Oct6100ApiReadDword( f_pApiInstance, f_ulTlvValueAddress, &ulTempValue ); if ( ulTempValue != 0 ) f_pApiInstance->pSharedInfo->ImageInfo.fSinLevel = TRUE; else f_pApiInstance->pSharedInfo->ImageInfo.fSinLevel = FALSE; } break; default: /* Unknown TLV type field... check default length and nothing else. */ ulResult = Oct6100ApiTlvCheckLengthField( f_ulTlvFieldLength, cOCT6100_TLV_MIN_LENGTH_DEFAULT, cOCT6100_TLV_MAX_LENGTH_DEFAULT ); break; } return ulResult; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiTlvCheckLengthField Description: This function validates the TLV length field. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_ulTlvFieldLength Length field read from the TLV. f_ulMinLengthValue Minimum value supported for the TLV. f_ulMaxLengthValue Maximum value supported for the TLV. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiTlvCheckLengthField( IN UINT32 f_ulTlvFieldLength, IN UINT32 f_ulMinLengthValue, IN UINT32 f_ulMaxLengthValue ) { /* Check if the value is too small. */ if ( f_ulTlvFieldLength < f_ulMinLengthValue ) return ( cOCT6100_ERR_FATAL_59 ); /* Check if the value is too big. */ if ( f_ulTlvFieldLength > f_ulMaxLengthValue ) return ( cOCT6100_ERR_FATAL_5A ); /* Check if the value is dword aligned. */ if ( ( f_ulTlvFieldLength % 4 ) != 0 ) return ( cOCT6100_ERR_OPEN_INVALID_TLV_LENGTH ); return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiTlvReadBitOffsetStruct Description: This function extracts a bit offset structure from the TLV. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulAddress Address where the read the TLV information. f_pBitOffsetStruct Pointer to a bit offset stucture. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiTlvReadBitOffsetStruct( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulAddress, OUT tPOCT6100_TLV_OFFSET f_pBitOffsetStruct ) { tOCT6100_READ_PARAMS ReadParams; UINT16 usReadData; UINT32 ulResult; UINT32 ulOffsetValue; UINT32 ulSizeValue; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; /*======================================================================*/ /* Read the first 16 bits of the TLV field. */ ReadParams.ulReadAddress = f_ulAddress; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulOffsetValue = usReadData << 16; /* Read the last word of the TLV type. */ ReadParams.ulReadAddress += 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulOffsetValue |= usReadData; /*======================================================================*/ /*======================================================================*/ /* Read the first 16 bits of the TLV field. */ ReadParams.ulReadAddress += 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulSizeValue = usReadData << 16; /* Read the last word of the TLV type. */ ReadParams.ulReadAddress += 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulSizeValue |= usReadData; /*======================================================================*/ /* Set the structure fields. */ f_pBitOffsetStruct->usDwordOffset = (UINT16)(ulOffsetValue / 32); f_pBitOffsetStruct->byBitOffset = (UINT8) (32 - (ulOffsetValue % 32) - ulSizeValue); f_pBitOffsetStruct->byFieldSize = (UINT8) (ulSizeValue); return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_tone_detection.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains functions used to enable and disable tone detection on an echo channel. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 49 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "oct6100api/oct6100_apiud.h" #include "apilib/octapi_llman.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_channel_inst.h" #include "oct6100api/oct6100_tone_detection_inst.h" #include "oct6100api/oct6100_events_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_tone_detection_pub.h" #include "oct6100api/oct6100_events_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_memory_priv.h" #include "oct6100_channel_priv.h" #include "oct6100_tone_detection_priv.h" #include "oct6100_events_priv.h" /**************************** PUBLIC FUNCTIONS *****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ToneDetectionEnable Description: This function enables the generation of event for a selected tone on the specified channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pToneDetectEnable Pointer to tone detection enable structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ToneDetectionEnableDef( tPOCT6100_TONE_DETECTION_ENABLE f_pToneDetectEnable ) { f_pToneDetectEnable->ulChannelHndl = cOCT6100_INVALID_HANDLE; f_pToneDetectEnable->ulToneNumber = cOCT6100_INVALID_TONE; return cOCT6100_ERR_OK; } static UINT32 Oct6100ToneDetectionEnable( tPOCT6100_INSTANCE_API f_pApiInstance, tPOCT6100_TONE_DETECTION_ENABLE f_pToneDetectEnable ) { tOCT6100_SEIZE_SERIALIZE_OBJECT SeizeSerObj; tOCT6100_RELEASE_SERIALIZE_OBJECT ReleaseSerObj; UINT32 ulSerRes = cOCT6100_ERR_OK; UINT32 ulFncRes = cOCT6100_ERR_OK; /* Set the process context of the serialize structure. */ SeizeSerObj.pProcessContext = f_pApiInstance->pProcessContext; ReleaseSerObj.pProcessContext = f_pApiInstance->pProcessContext; /* Seize all list semaphores needed by this function. */ SeizeSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; SeizeSerObj.ulTryTimeMs = cOCT6100_WAIT_INFINITELY; ulSerRes = Oct6100UserSeizeSerializeObject( &SeizeSerObj ); if ( ulSerRes == cOCT6100_ERR_OK ) { /* Call the serialized function. */ ulFncRes = Oct6100ToneDetectionEnableSer( f_pApiInstance, f_pToneDetectEnable ); } else { return ulSerRes; } /* Release the seized semaphores. */ ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj; ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj ); /* If an error occured then return the error code. */ if ( ulSerRes != cOCT6100_ERR_OK ) return ulSerRes; if ( ulFncRes != cOCT6100_ERR_OK ) return ulFncRes; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ToneDetectionDisable Description: This function disables the detection of a tone for a specific channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pToneDetectDisable Pointer to tone detection disable structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ToneDetectionDisableDef( tPOCT6100_TONE_DETECTION_DISABLE f_pToneDetectDisable ) { f_pToneDetectDisable->ulChannelHndl = cOCT6100_INVALID_HANDLE; f_pToneDetectDisable->ulToneNumber = cOCT6100_INVALID_VALUE; f_pToneDetectDisable->fDisableAll = FALSE; return cOCT6100_ERR_OK; } /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ToneDetectionEnableSer Description: Activate the detection of a tone on the specified channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pToneDetectEnable Pointer to tone detect enable structure. This structure contains, among other things, the tone ID to enable and the channel handle where detection should be enabled. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ToneDetectionEnableSer( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_TONE_DETECTION_ENABLE f_pToneDetectEnable ) { UINT32 ulChanIndex; UINT32 ulExtToneChanIndex; UINT32 ulToneEventNumber=0; UINT32 ulResult; /* Check the user's configuration of the tone detection for errors. */ ulResult = Oct6100ApiCheckToneEnableParams( f_pApiInstance, f_pToneDetectEnable, &ulChanIndex, &ulToneEventNumber, &ulExtToneChanIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write to all resources needed to enable tone detection. */ ulResult = Oct6100ApiWriteToneDetectEvent( f_pApiInstance, ulChanIndex, ulToneEventNumber, ulExtToneChanIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Update the channel entry to indicate that a new tone has been activated. */ ulResult = Oct6100ApiUpdateChanToneDetectEntry( f_pApiInstance, ulChanIndex, ulToneEventNumber, ulExtToneChanIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiCheckToneEnableParams Description: Check the validity of the channel and tone requested. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pToneDetectEnable Pointer to tone detection enable structure. f_pulChannelIndex Pointer to the channel index. f_pulToneEventNumber Pointer to the Index of the tone associated to the requested tone. f_pulExtToneChanIndex Pointer to the index of the extended channel index. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiCheckToneEnableParams( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_TONE_DETECTION_ENABLE f_pToneDetectEnable, OUT PUINT32 f_pulChannelIndex, OUT PUINT32 f_pulToneEventNumber, OUT PUINT32 f_pulExtToneChanIndex ) { tPOCT6100_API_CHANNEL pEchoChannel; UINT32 ulEntryOpenCnt; UINT32 i; /*=====================================================================*/ /* Check the channel handle. */ if ( (f_pToneDetectEnable->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) return cOCT6100_ERR_TONE_DETECTION_CHANNEL_HANDLE_INVALID; *f_pulChannelIndex = f_pToneDetectEnable->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK; if ( *f_pulChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) return cOCT6100_ERR_TONE_DETECTION_CHANNEL_HANDLE_INVALID; mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChannel, *f_pulChannelIndex ) /* Extract the entry open count from the provided handle. */ ulEntryOpenCnt = (f_pToneDetectEnable->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; /* Check for errors. */ if ( pEchoChannel->fReserved != TRUE ) return cOCT6100_ERR_TONE_DETECTION_CHANNEL_NOT_OPEN; if ( ulEntryOpenCnt != pEchoChannel->byEntryOpenCnt ) return cOCT6100_ERR_TONE_DETECTION_CHANNEL_HANDLE_INVALID; /* Set the extended tone detection info if it is activated on the channel. */ *f_pulExtToneChanIndex = pEchoChannel->usExtToneChanIndex; /*=====================================================================*/ /* Check the tone information. */ /* Find out if the tone is present in the build. */ for ( i = 0; i < cOCT6100_MAX_TONE_EVENT; i++ ) { if ( f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ i ].ulToneID == f_pToneDetectEnable->ulToneNumber ) { *f_pulToneEventNumber = i; break; } } /* Check if tone is present. */ if ( i == cOCT6100_MAX_TONE_EVENT ) return cOCT6100_ERR_NOT_SUPPORTED_TONE_NOT_PRESENT_IN_FIRMWARE; /* Check if the requested tone is actually detected. */ if ((( pEchoChannel->aulToneConf[ *f_pulToneEventNumber / 32 ] >> ( 31 - ( *f_pulToneEventNumber % 32 ))) & 0x1) == 1 ) return cOCT6100_ERR_TONE_DETECTION_TONE_ACTIVATED; /*=====================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteToneDetectEvent Description: Write the tone detection event in the channel main structure. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulChannelIndex Index of the channel within the API's channel list. f_ulToneEventNumber Event number of the tone to be activated. f_ulExtToneChanIndex Index of the extended tone detection channel. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiWriteToneDetectEvent( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulChannelIndex, IN UINT32 f_ulToneEventNumber, IN UINT32 f_ulExtToneChanIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_READ_PARAMS ReadParams; UINT32 ulResult; UINT16 usReadData; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /*=======================================================================*/ /* Read the current event config about to be modified. */ ReadParams.ulReadAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_ulChannelIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ); ReadParams.ulReadAddress += cOCT6100_CH_MAIN_TONE_EVENT_OFFSET; ReadParams.ulReadAddress += (f_ulToneEventNumber / 16) * 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /* Set the tone event in the channel main memory for the requested direction. */ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; WriteParams.usWriteData = usReadData; WriteParams.usWriteData |= ( 0x1 << ( 15 - ( f_ulToneEventNumber % 16 ))); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /* Also program the extended channel if one is present. */ if ( f_ulExtToneChanIndex != cOCT6100_INVALID_INDEX ) { /* Read the current event config about to be modified. */ ReadParams.ulReadAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_ulExtToneChanIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ); ReadParams.ulReadAddress += cOCT6100_CH_MAIN_TONE_EVENT_OFFSET; ReadParams.ulReadAddress += (f_ulToneEventNumber / 16) * 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write the tone event in the channel main memory for the requested direction. */ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; WriteParams.usWriteData = usReadData; WriteParams.usWriteData |= ( 0x1 << ( 15 - ( f_ulToneEventNumber % 16 ))); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*=======================================================================*/ return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiUpdateChanToneDetectEntry Description: Update the echo channel entry to store the info about the tone being configured to generate detection events. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulChannelIndex Index of the channel within the API's channel list. f_ulToneEventNumber Enabled tone event number. f_ulExtToneChanIndex Index of the extended tone detection channel. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiUpdateChanToneDetectEntry ( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulChannelIndex, IN UINT32 f_ulToneEventNumber, IN UINT32 f_ulExtToneChanIndex ) { tPOCT6100_API_CHANNEL pEchoChanEntry; tPOCT6100_SHARED_INFO pSharedInfo; UINT32 ulToneEntry; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Update the channel entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_ulChannelIndex ); /* Set the corresponding bit in the channel array. */ ulToneEntry = pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ]; /* Modify the entry. */ ulToneEntry |= ( 0x1 << ( 31 - ( f_ulToneEventNumber % 32 ))); /* Copy back the new value. */ pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ] = ulToneEntry; /* Configure also the extended channel if necessary. */ if ( f_ulExtToneChanIndex != cOCT6100_INVALID_INDEX ) { /* Update the channel entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_ulExtToneChanIndex ); /* Set the corresponding bit in the channel array. */ ulToneEntry = pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ]; /* Modify the entry. */ ulToneEntry |= ( 0x1 << ( 31 - ( f_ulToneEventNumber % 32 ))); /* Copy back the new value. */ pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ] = ulToneEntry; } /* Check for the SS tone events that could have been generated before. */ if ( f_ulExtToneChanIndex == cOCT6100_INVALID_INDEX ) { BOOL fSSTone; UINT32 ulResult; ulResult = Oct6100ApiIsSSTone( f_pApiInstance, pSharedInfo->ImageInfo.aToneInfo[ f_ulToneEventNumber ].ulToneID, &fSSTone ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Is this a signaling system tone? */ if ( fSSTone == TRUE ) { /* Check if must generate an event for the last detected SS tone. */ if ( ( pEchoChanEntry->ulLastSSToneDetected != cOCT6100_INVALID_INDEX ) && ( pEchoChanEntry->ulLastSSToneDetected == pSharedInfo->ImageInfo.aToneInfo[ f_ulToneEventNumber ].ulToneID ) ) { /* Must write an event for this. */ tPOCT6100_API_TONE_EVENT pSoftEvent; /* If enough space. */ if ( ( ( pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1 ) != pSharedInfo->SoftBufs.ulToneEventBufferReadPtr ) && ( ( pSharedInfo->SoftBufs.ulToneEventBufferWritePtr + 1 ) != pSharedInfo->SoftBufs.ulToneEventBufferSize || pSharedInfo->SoftBufs.ulToneEventBufferReadPtr != 0 ) ) { /* Form the event for this captured tone. */ mOCT6100_GET_TONE_EVENT_BUF_PNT( pSharedInfo, pSoftEvent ) pSoftEvent += pSharedInfo->SoftBufs.ulToneEventBufferWritePtr; pSoftEvent->ulChannelHandle = cOCT6100_HNDL_TAG_CHANNEL | (pEchoChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | f_ulChannelIndex; pSoftEvent->ulUserChanId = pEchoChanEntry->ulUserChanId; pSoftEvent->ulToneDetected = pSharedInfo->ImageInfo.aToneInfo[ f_ulToneEventNumber ].ulToneID; pSoftEvent->ulTimestamp = pEchoChanEntry->ulLastSSToneTimestamp; pSoftEvent->ulExtToneDetectionPort = cOCT6100_INVALID_VALUE; pSoftEvent->ulEventType = cOCT6100_TONE_PRESENT; /* Update the control variables of the buffer. */ pSharedInfo->SoftBufs.ulToneEventBufferWritePtr++; if ( pSharedInfo->SoftBufs.ulToneEventBufferWritePtr == pSharedInfo->SoftBufs.ulToneEventBufferSize ) pSharedInfo->SoftBufs.ulToneEventBufferWritePtr = 0; /* Set the interrupt manager such that the user knows that some tone events */ /* are pending in the software Q. */ pSharedInfo->IntrptManage.fToneEventsPending = TRUE; } else { /* Set the overflow flag of the buffer. */ pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt++; } } } } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ToneDetectionDisableSer Description: Disable the generation of events for a selected tone on the specified channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pToneDetectDisable Pointer to tOCT6100_TONE_DETECTION_DISABLE structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ToneDetectionDisableSer( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_TONE_DETECTION_DISABLE f_pToneDetectDisable ) { UINT32 ulChanIndex; UINT32 ulExtToneChanIndex; UINT32 ulToneEventNumber; UINT32 ulResult; BOOL fDisableAll; /* Check the user's configuration of the tone detection disable structure for errors. */ ulResult = Oct6100ApiAssertToneDetectionParams( f_pApiInstance, f_pToneDetectDisable, &ulChanIndex, &ulToneEventNumber, &ulExtToneChanIndex, &fDisableAll ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear the event to detect the specified tone. */ ulResult = Oct6100ApiClearToneDetectionEvent( f_pApiInstance, ulChanIndex, ulToneEventNumber, ulExtToneChanIndex, fDisableAll ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Update the channel structure to indicate that the tone is no longer detected. */ ulResult = Oct6100ApiReleaseToneDetectionEvent( f_pApiInstance, ulChanIndex, ulToneEventNumber, ulExtToneChanIndex, fDisableAll ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiAssertToneDetectionParams Description: Check the validity of the tone detection disable command. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pToneDetectDisable Pointer to tone detection disable structure. f_pulChannelIndex Pointer to the channel index f_pulToneEventNumber Pointer to the tone event number. f_pulExtToneChanIndex Pointer to the extended channel index. f_pfDisableAll Pointer to the flag specifying whether all tones should be disabled. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiAssertToneDetectionParams( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_TONE_DETECTION_DISABLE f_pToneDetectDisable, OUT PUINT32 f_pulChannelIndex, OUT PUINT32 f_pulToneEventNumber, OUT PUINT32 f_pulExtToneChanIndex, OUT PBOOL f_pfDisableAll ) { tPOCT6100_API_CHANNEL pEchoChannel; UINT32 ulEntryOpenCnt; UINT32 i; /*=====================================================================*/ /* Check the echo channel handle. */ if ( (f_pToneDetectDisable->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) return cOCT6100_ERR_TONE_DETECTION_CHANNEL_HANDLE_INVALID; *f_pulChannelIndex = f_pToneDetectDisable->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK; if ( *f_pulChannelIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels ) return cOCT6100_ERR_TONE_DETECTION_CHANNEL_HANDLE_INVALID; mOCT6100_GET_CHANNEL_ENTRY_PNT( f_pApiInstance->pSharedInfo, pEchoChannel, *f_pulChannelIndex ) /* Extract the entry open count from the provided handle. */ ulEntryOpenCnt = (f_pToneDetectDisable->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; /* Check for errors. */ if ( pEchoChannel->fReserved != TRUE ) return cOCT6100_ERR_TONE_DETECTION_CHANNEL_NOT_OPEN; if ( ulEntryOpenCnt != pEchoChannel->byEntryOpenCnt ) return cOCT6100_ERR_TONE_DETECTION_CHANNEL_HANDLE_INVALID; /* Return the extended channel index. */ *f_pulExtToneChanIndex = pEchoChannel->usExtToneChanIndex; /* Check the disable all flag. */ if ( f_pToneDetectDisable->fDisableAll != TRUE && f_pToneDetectDisable->fDisableAll != FALSE ) return cOCT6100_ERR_TONE_DETECTION_DISABLE_ALL; /*=====================================================================*/ /* Check the tone information. */ /* Find out if the tone is present in the build. */ if ( f_pToneDetectDisable->fDisableAll == FALSE ) { for ( i = 0; i < cOCT6100_MAX_TONE_EVENT; i++ ) { if ( f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ i ].ulToneID == f_pToneDetectDisable->ulToneNumber ) { *f_pulToneEventNumber = i; break; } } /* Check if tone is present. */ if ( i == cOCT6100_MAX_TONE_EVENT ) return cOCT6100_ERR_NOT_SUPPORTED_TONE_NOT_PRESENT_IN_FIRMWARE; /* Check if the requested tone is actually detected. */ if ((( pEchoChannel->aulToneConf[ *f_pulToneEventNumber / 32 ] >> ( 31 - ( *f_pulToneEventNumber % 32 ))) & 0x1) == 0 ) return cOCT6100_ERR_TONE_DETECTION_TONE_NOT_ACTIVATED; } /*=====================================================================*/ /* Return the disable all flag as requested. */ *f_pfDisableAll = f_pToneDetectDisable->fDisableAll; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiClearToneDetectionEvent Description: Clear the buffer playout event in the channel main structure. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulChannelIndex Index of the channel within the API's channel list. f_ulToneEventNumber Tone event number to be deactivated. f_ulExtToneChanIndex Index of the extended tone detection channel. f_fDisableAll Clear all activated tones. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiClearToneDetectionEvent( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulChannelIndex, IN UINT32 f_ulToneEventNumber, IN UINT32 f_ulExtToneChanIndex, IN BOOL f_fDisableAll ) { tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_READ_PARAMS ReadParams; tOCT6100_WRITE_SMEAR_PARAMS SmearParams; UINT32 ulResult; UINT32 ulToneEventBaseAddress; UINT16 usReadData; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; SmearParams.pProcessContext = f_pApiInstance->pProcessContext; SmearParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /*=======================================================================*/ /* Read the current event config about to be modified. */ ulToneEventBaseAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_ulChannelIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ); ulToneEventBaseAddress += cOCT6100_CH_MAIN_TONE_EVENT_OFFSET; /* Check if must disable all tone events or not. */ if ( f_fDisableAll == FALSE ) { ReadParams.ulReadAddress = ulToneEventBaseAddress; ReadParams.ulReadAddress += (f_ulToneEventNumber / 16) * 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear the event in the channel main memory.*/ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; WriteParams.usWriteData = usReadData; WriteParams.usWriteData &= (~( 0x1 << ( 15 - ( f_ulToneEventNumber % 16 )))); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } else /* if ( f_fDisableAll == TRUE ) */ { /* Clear all events in the channel main memory. */ SmearParams.ulWriteLength = 4; SmearParams.usWriteData = 0x0000; SmearParams.ulWriteAddress = ulToneEventBaseAddress; mOCT6100_DRIVER_WRITE_SMEAR_API( SmearParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /*=======================================================================*/ /* Also program the extended channel if one is present. */ if ( f_ulExtToneChanIndex != cOCT6100_INVALID_INDEX ) { ulToneEventBaseAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + ( f_ulExtToneChanIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ); ulToneEventBaseAddress += cOCT6100_CH_MAIN_TONE_EVENT_OFFSET; /* Check if must disable all tone events or not. */ if ( f_fDisableAll == FALSE ) { /* Read the current event config about to be modified. */ ReadParams.ulReadAddress = ulToneEventBaseAddress; ReadParams.ulReadAddress += (f_ulToneEventNumber / 16) * 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Clear the event in the channel main memory.*/ WriteParams.ulWriteAddress = ReadParams.ulReadAddress; WriteParams.usWriteData = usReadData; WriteParams.usWriteData &= (~( 0x1 << ( 15 - ( f_ulToneEventNumber % 16 )))); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } else /* if ( f_fDisableAll == TRUE ) */ { /* Clear all events in the channel main memory.*/ SmearParams.ulWriteLength = 4; SmearParams.usWriteData = 0x0000; SmearParams.ulWriteAddress = ulToneEventBaseAddress; mOCT6100_DRIVER_WRITE_SMEAR_API( SmearParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReleaseToneDetectionEvent Description: Clear the entry made for this tone in the channel tone enable array. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulChannelIndex Index of the channel within the API's channel list. f_ulToneEventNumber Tone event number to be deactivated. f_ulExtToneChanIndex Index of the extended tone detection channel. f_fDisableAll Release all activated tones. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReleaseToneDetectionEvent ( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulChannelIndex, IN UINT32 f_ulToneEventNumber, IN UINT32 f_ulExtToneChanIndex, IN BOOL f_fDisableAll ) { tPOCT6100_API_CHANNEL pEchoChanEntry; tPOCT6100_SHARED_INFO pSharedInfo; UINT32 ulToneEntry; UINT32 ulResult; UINT32 ulToneEventNumber; BOOL fSSTone; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Update the channel entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_ulChannelIndex ); /* Check if must release all tone events. */ if ( f_fDisableAll == FALSE ) { /* Set the corresponding bit in the channel array. */ ulToneEntry = pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ]; /* Modify the entry. */ ulToneEntry &= (~( 0x1 << ( 31 - ( f_ulToneEventNumber % 32 )))); /* Copy back the new value. */ pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ] = ulToneEntry; } else /* if ( f_fDisableAll == TRUE ) */ { /* Clear all events. */ Oct6100UserMemSet( pEchoChanEntry->aulToneConf, 0x00, sizeof( pEchoChanEntry->aulToneConf ) ); } /* Configure also the extended channel if necessary. */ if ( f_ulExtToneChanIndex != cOCT6100_INVALID_INDEX ) { /* Update the channel entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChanEntry, f_ulExtToneChanIndex ); /* Check if must release all tone events. */ if ( f_fDisableAll == FALSE ) { /* Set the corresponding bit in the channel array. */ ulToneEntry = pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ]; /* Modify the entry. */ ulToneEntry &= (~( 0x1 << ( 31 - ( f_ulToneEventNumber % 32 )))); /* Copy back the new value. */ pEchoChanEntry->aulToneConf[ f_ulToneEventNumber / 32 ] = ulToneEntry; } else /* if ( f_fDisableAll == TRUE ) */ { /* Clear all events. */ Oct6100UserMemSet( pEchoChanEntry->aulToneConf, 0x00, sizeof( pEchoChanEntry->aulToneConf ) ); } } /* Re-enable the SS7 tones */ for ( ulToneEventNumber = 0; ulToneEventNumber < cOCT6100_MAX_TONE_EVENT; ulToneEventNumber++ ) { /* Check if the current tone is a SS tone. */ ulResult = Oct6100ApiIsSSTone( f_pApiInstance, f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulToneID, &fSSTone ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( fSSTone == TRUE ) { /* Write to all resources needed to activate tone detection on this SS tone. */ ulResult = Oct6100ApiWriteToneDetectEvent( f_pApiInstance, f_ulChannelIndex, ulToneEventNumber, cOCT6100_INVALID_INDEX ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiIsSSTone Description: Check if specified tone number is a special signaling system tone. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulToneEventNumber Tone event number to be checked against. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiIsSSTone( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulToneEventNumber, OUT PBOOL f_fSSTone ) { *f_fSSTone = FALSE; switch( f_ulToneEventNumber ) { case cOCT6100_TONE_SIN_SYSTEM7_2000: case cOCT6100_TONE_SIN_SYSTEM7_1780: *f_fSSTone = TRUE; break; default: break; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_tsi_cnct.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains functions used to open and close TSI connections This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 37 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "oct6100api/oct6100_apiud.h" #include "apilib/octapi_llman.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_channel_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_tsi_cnct_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_tsi_cnct_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_memory_priv.h" #include "oct6100_tsst_priv.h" #include "oct6100_channel_priv.h" #include "oct6100_tsi_cnct_priv.h" /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetTsiCnctSwSizes Description: Gets the sizes of all portions of the API instance pertinent to the management the TSI memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pOpenChip Pointer to chip configuration struct. f_pInstSizes Pointer to struct containing instance sizes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiGetTsiCnctSwSizes( IN tPOCT6100_CHIP_OPEN f_pOpenChip, OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) { UINT32 ulTempVar; UINT32 ulResult; /* Determine the amount of memory required for the API TSI connection list. */ f_pInstSizes->ulTsiCnctList = f_pOpenChip->ulMaxTsiCncts * sizeof( tOCT6100_API_TSI_CNCT ); if ( f_pOpenChip->ulMaxTsiCncts > 0 ) { /* Calculate memory needed for TSI memory allocation. */ ulResult = OctapiLlmAllocGetSize( f_pOpenChip->ulMaxTsiCncts, &f_pInstSizes->ulTsiCnctAlloc ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_48; } else { f_pInstSizes->ulTsiCnctAlloc = 0; } mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulTsiCnctList, ulTempVar ) mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulTsiCnctAlloc, ulTempVar ) return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiTsiCnctSwInit Description: Initializes all elements of the instance structure associated to the TSI memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiTsiCnctSwInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_API_TSI_CNCT pChannelsTsiList; tPOCT6100_SHARED_INFO pSharedInfo; UINT32 ulMaxTsiChannels; PVOID pTsiChannelsAlloc; UINT32 ulResult; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Initialize the TSI connections API list. */ ulMaxTsiChannels = pSharedInfo->ChipConfig.usMaxTsiCncts; mOCT6100_GET_TSI_CNCT_LIST_PNT( pSharedInfo, pChannelsTsiList ) /* Clear the memory. */ Oct6100UserMemSet( pChannelsTsiList, 0x00, sizeof(tOCT6100_API_TSI_CNCT) * ulMaxTsiChannels ); /* Set all entries in the TSI connections list to unused. */ if ( ulMaxTsiChannels > 0 ) { mOCT6100_GET_TSI_CNCT_ALLOC_PNT( pSharedInfo, pTsiChannelsAlloc ) ulResult = OctapiLlmAllocInit( &pTsiChannelsAlloc, ulMaxTsiChannels ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_49; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_tsst.c Copyright (c) 2001-2005 Octasic Inc. Description: This file contains the functions used to manage the allocation of TSST control structures in internal memory. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 39 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "apilib/octapi_llman.h" #include "oct6100api/oct6100_apiud.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_tsst_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_tsst_priv.h" /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetTsstSwSizes Description: Gets the sizes of all portions of the API instance pertinent to the management of TSSTs. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pInstSizes Pointer to struct containing instance sizes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiGetTsstSwSizes( OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) { UINT32 ulTempVar; UINT32 ulResult; /* Determine amount of TSST needed for TSST allocation table. */ f_pInstSizes->ulTsstAlloc = 4096 / 8; /* Calculate the API memory required for the TSST entry list. */ f_pInstSizes->ulTsstEntryList = cOCT6100_MAX_TSSTS * sizeof( tOCT6100_API_TSST_ENTRY ); /* Calculate memory needed for TSST entry allocation. */ ulResult = OctapiLlmAllocGetSize( cOCT6100_MAX_TSSTS, &f_pInstSizes->ulTsstEntryAlloc ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_4D; mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulTsstAlloc, ulTempVar ); mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulTsstEntryList, ulTempVar ); mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulTsstEntryAlloc, ulTempVar ); return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiTsstSwInit Description: Initializes all elements of the instance structure associated to the TSST control entries. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This tsst is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiTsstSwInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_TSST_ENTRY pTsstList; PUINT32 pulTsstAlloc; PVOID pTsstListAlloc; UINT32 ulResult; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Initialize the TSST allocation table to "all free". */ mOCT6100_GET_TSST_ALLOC_PNT( pSharedInfo, pulTsstAlloc ); Oct6100UserMemSet( pulTsstAlloc, 0x00, 512 ); /* Initialize all the TSST list entries. */ mOCT6100_GET_TSST_LIST_PNT( pSharedInfo, pTsstList ); Oct6100UserMemSet( pTsstList, 0xFF, cOCT6100_MAX_TSSTS * sizeof(tOCT6100_API_TSST_ENTRY) ); /* Initialize the allocation list to manage the TSST entries.*/ mOCT6100_GET_TSST_LIST_ALLOC_PNT( pSharedInfo, pTsstListAlloc ) ulResult = OctapiLlmAllocInit( &pTsstListAlloc, cOCT6100_MAX_TSSTS ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_4E; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiValidateTsst Description: Validates a timeslot, stream combination. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This tsst is used to keep the present state of the chip and all its resources. f_ulTimeslot Timeslot component of the TDM TSST. f_ulStream Stream component of the TDM TSST. f_ulNumTssts Number of TSST required. f_ulDirection Direction of the TSST (Input or Output). \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiValidateTsst( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulNumTssts, IN UINT32 f_ulTimeslot, IN UINT32 f_ulStream, IN UINT32 f_ulDirection ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHIP_CONFIG pChipConfig; PUINT32 pulTsstAlloc; /* Obtain local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; mOCT6100_GET_TSST_ALLOC_PNT( f_pApiInstance->pSharedInfo, pulTsstAlloc ); /* Obtain local pointer to chip configuration. */ pChipConfig = &pSharedInfo->ChipConfig; /* Check the TDM streams, timeslots component for errors. */ if ( f_ulTimeslot == cOCT6100_UNASSIGNED && f_ulStream != cOCT6100_UNASSIGNED ) return cOCT6100_ERR_TSST_TIMESLOT; if ( f_ulTimeslot != cOCT6100_UNASSIGNED && f_ulStream == cOCT6100_UNASSIGNED ) return cOCT6100_ERR_TSST_STREAM; if ( f_ulStream >= pChipConfig->byMaxTdmStreams ) return cOCT6100_ERR_TSST_STREAM; /* Check timeslot value based on the frequenccy of the selected stream. */ switch ( pChipConfig->aulTdmStreamFreqs[ f_ulStream / 4 ] ) { case cOCT6100_TDM_STREAM_FREQ_2MHZ: if ( f_ulTimeslot >= 32 ) return cOCT6100_ERR_TSST_TIMESLOT; break; case cOCT6100_TDM_STREAM_FREQ_4MHZ: if ( f_ulTimeslot >= 64 ) return cOCT6100_ERR_TSST_TIMESLOT; break; case cOCT6100_TDM_STREAM_FREQ_8MHZ: if ( f_ulTimeslot >= 128 ) return cOCT6100_ERR_TSST_TIMESLOT; break; case cOCT6100_TDM_STREAM_FREQ_16MHZ: if ( f_ulTimeslot >= 256 ) return cOCT6100_ERR_TSST_TIMESLOT; /* Check the stream value based on the direction. */ if ( f_ulDirection == cOCT6100_INPUT_TSST && f_ulStream >= 16 ) { return cOCT6100_ERR_TSST_STREAM; } else if( f_ulDirection == cOCT6100_OUTPUT_TSST && f_ulStream < 16 ) { return cOCT6100_ERR_TSST_STREAM; } break; default: return cOCT6100_ERR_FATAL_DC; } /* Stream must be odd if two TSSTs are required. */ if ( f_ulNumTssts == 2 && ( ( f_ulStream & 0x1) != 0x1 ) ) return cOCT6100_ERR_TSST_STREAM; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReserveTsst Description: Reserves a TSST, only one TSI entry can access a TSST at any one time. If the pointer f_pulTsstListIndex is set to NULL, no TSST list entry will be reserved. The index in TSST control memory returned is based on the frequency of the streams where the TSST is located and on the direction of the TSST ( input or output ). ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This tsst is used to keep the present state of the chip and all its resources. f_ulTimeslot Timeslot component of the TDM TSST. f_ulNumTssts Number of TSSTs required. f_ulStream Stream component of the TDM TSST. f_ulDirection Whether the TSST in and input TSST or output TSST. f_pusTsstMemIndex Index of the resulting TSST in the TSST control memory. f_pusTsstListIndex Index in the TSST list of the current entry. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReserveTsst( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulTimeslot, IN UINT32 f_ulStream, IN UINT32 f_ulNumTsst, IN UINT32 f_ulDirection, OUT PUINT16 f_pusTsstMemIndex, OUT PUINT16 f_pusTsstListIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; PVOID pTsstListAlloc; PUINT32 pulTsstAlloc; UINT32 ulResult = cOCT6100_ERR_OK; UINT32 ulStream; UINT32 ulTimeslot; /* Get local pointer to shared portion of API instance structure. */ pSharedInfo = f_pApiInstance->pSharedInfo; mOCT6100_GET_TSST_ALLOC_PNT( f_pApiInstance->pSharedInfo, pulTsstAlloc ); /*==================================================================================*/ /* Now make the proper conversion to obtain the TSST value. */ /* Save the timeslot and stream value received. */ ulStream = f_ulStream; ulTimeslot = f_ulTimeslot; /* Set the TSST index associated to this stream, timeslot combination. */ switch ( f_pApiInstance->pSharedInfo->ChipConfig.aulTdmStreamFreqs[ f_ulStream / 4 ] ) { case cOCT6100_TDM_STREAM_FREQ_16MHZ: if ( f_ulDirection == cOCT6100_INPUT_TSST ) { ulStream = f_ulStream + ( f_ulTimeslot % 2 ) * 16; ulTimeslot = f_ulTimeslot / 2; } else /* f_ulDirection == cOCT6100_OUTPUT_TSST */ { ulStream = ( f_ulStream - 16 ) + ( f_ulTimeslot % 2 ) * 16; if ( f_ulStream < 28 && ((f_ulTimeslot % 2) == 1) ) { ulTimeslot = ((f_ulTimeslot / 2) + 4) % 128; } else { ulTimeslot = f_ulTimeslot / 2 ; } } *f_pusTsstMemIndex = (UINT16)( ulTimeslot * 32 + ulStream ); break; case cOCT6100_TDM_STREAM_FREQ_8MHZ: *f_pusTsstMemIndex = (UINT16)( ulTimeslot * 32 + ulStream ); break; case cOCT6100_TDM_STREAM_FREQ_4MHZ: *f_pusTsstMemIndex = (UINT16)( ulTimeslot * 32 * 2 ); if ( f_ulDirection == cOCT6100_OUTPUT_TSST ) { *f_pusTsstMemIndex = (UINT16)( *f_pusTsstMemIndex + ulStream ); } else /* if ( f_ulDirection == cOCT6100_INPUT_TSST ) */ { *f_pusTsstMemIndex = (UINT16)( ( 1 * 32 + ulStream ) + *f_pusTsstMemIndex ); } break; case cOCT6100_TDM_STREAM_FREQ_2MHZ: *f_pusTsstMemIndex = (UINT16)( ulTimeslot * 32 * 4 ); if ( f_ulDirection == cOCT6100_OUTPUT_TSST ) { *f_pusTsstMemIndex = (UINT16)( ulStream + *f_pusTsstMemIndex ); } else /* if ( f_ulDirection == cOCT6100_INPUT_TSST ) */ { *f_pusTsstMemIndex = (UINT16)( ( 3 * 32 + ulStream ) + *f_pusTsstMemIndex ); } break; default: ulResult = cOCT6100_ERR_FATAL_8B; } /*======================================================================*/ /*======================================================================*/ /* First reserve the TSST. */ /* Get local pointer to TSST's entry in allocation table. */ switch ( pSharedInfo->ChipConfig.aulTdmStreamFreqs[ ulStream / 4 ] ) { case cOCT6100_TDM_STREAM_FREQ_2MHZ: ulTimeslot *= 4; break; case cOCT6100_TDM_STREAM_FREQ_4MHZ: ulTimeslot *= 2; break; case cOCT6100_TDM_STREAM_FREQ_8MHZ: ulTimeslot *= 1; break; case cOCT6100_TDM_STREAM_FREQ_16MHZ: ulTimeslot *= 1; break; default: return cOCT6100_ERR_FATAL_DD; } /* Check if entry is already reserved. */ if ( ((pulTsstAlloc[ ulTimeslot ] >> ulStream) & 0x1) == 0x1 ) return cOCT6100_ERR_TSST_TSST_RESERVED; /* Check and reserve the associated TSST if required. */ if ( f_ulNumTsst == 2 ) { /* Check if entry is already reserved. */ if ( ((pulTsstAlloc[ ulTimeslot ] >> (ulStream - 1) ) & 0x1) == 0x1 ) return cOCT6100_ERR_TSST_ASSOCIATED_TSST_RESERVED; /* The entry is free, it won't anymore. */ pulTsstAlloc[ ulTimeslot ] |= (0x1 << (ulStream - 1)); } /* The entry is free, it won't anymore.*/ pulTsstAlloc[ ulTimeslot ] |= (0x1 << ulStream); /*======================================================================*/ /*======================================================================*/ /* Now reserve a TSST entry if requested. */ if ( f_pusTsstListIndex != NULL && ulResult == cOCT6100_ERR_OK ) { UINT32 ulTsstListIndex; /* Reserve a TSST entry in the API TSST list. */ mOCT6100_GET_TSST_LIST_ALLOC_PNT( f_pApiInstance->pSharedInfo, pTsstListAlloc ); ulResult = OctapiLlmAllocAlloc( pTsstListAlloc, &ulTsstListIndex ); if ( ulResult != cOCT6100_ERR_OK ) { if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) ulResult = cOCT6100_ERR_TSST_ALL_TSSTS_ARE_OPENED; else ulResult = cOCT6100_ERR_FATAL_52; } *f_pusTsstListIndex = (UINT16)( ulTsstListIndex & 0xFFFF ); } /*======================================================================*/ /*======================================================================*/ /* Check the result of the TSST list reservation. */ if ( ulResult != cOCT6100_ERR_OK ) { /* Release the previously reserved TSST. */ if ( f_ulNumTsst == 2 ) { /* Clear the entry. */ pulTsstAlloc[ ulTimeslot ] &= ~(0x1 << (ulStream - 1) ); } /* Clear the entry. */ pulTsstAlloc[ ulTimeslot ] &= ~(0x1 << ulStream); } /*======================================================================*/ return ulResult; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReleaseTsst Description: Releases a TSST. If f_usTsstListIndex is set to cOCT6100_INVALID_INDEX, the API will assume that no TSST list entry was reserved for this TSST. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This tsst is used to keep the present state of the chip and all its resources. f_ulNumTssts Number of TSSTs to be released. f_ulStream Stream component of the TDM TSST. f_ulTimeslot Timeslot component of the TDM TSST. f_ulDirection Whether the TSST is an input TSST or output TSST. f_usTsstListIndex Index in the TSST list of the current entry. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 Oct6100ApiReleaseTsst( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulTimeslot, IN UINT32 f_ulStream, IN UINT32 f_ulNumTsst, IN UINT32 f_ulDirection, IN UINT16 f_usTsstListIndex) { tPOCT6100_SHARED_INFO pSharedInfo; PUINT32 pulTsstAlloc; PVOID pTsstListAlloc; UINT32 ulResult; UINT32 ulStream; UINT32 ulTimeslot; /* Get local pointer to shared portion of API instance structure. */ pSharedInfo = f_pApiInstance->pSharedInfo; if ( f_usTsstListIndex != cOCT6100_INVALID_INDEX ) { mOCT6100_GET_TSST_LIST_ALLOC_PNT( pSharedInfo, pTsstListAlloc ) ulResult = OctapiLlmAllocDealloc( pTsstListAlloc, f_usTsstListIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return cOCT6100_ERR_FATAL_53; } } mOCT6100_GET_TSST_ALLOC_PNT( f_pApiInstance->pSharedInfo, pulTsstAlloc ); /*==================================================================================*/ /* Now make the proper conversion to obtain the TSST value. */ /* Save the timeslot and stream value received. */ ulStream = f_ulStream; ulTimeslot = f_ulTimeslot; /* Set the TSST index associated to this stream, timeslot combination. */ if ( pSharedInfo->ChipConfig.aulTdmStreamFreqs[ f_ulStream / 4 ] == cOCT6100_TDM_STREAM_FREQ_16MHZ ) { if ( f_ulDirection == cOCT6100_INPUT_TSST ) { ulStream = f_ulStream + ( f_ulTimeslot % 2 ) * 16; ulTimeslot = f_ulTimeslot / 2; } else /* f_ulDirection == cOCT6100_OUTPUT_TSST */ { ulStream = ( f_ulStream - 16 ) + ( f_ulTimeslot % 2 ) * 16; if ( f_ulStream < 28 && ((f_ulTimeslot % 2) == 1) ) { ulTimeslot = ((f_ulTimeslot / 2) + 4) % 128; } else { ulTimeslot = f_ulTimeslot / 2 ; } } } /* Get local pointer to TSST's entry in allocation table. */ switch ( pSharedInfo->ChipConfig.aulTdmStreamFreqs[ ulStream / 4 ] ) { case cOCT6100_TDM_STREAM_FREQ_2MHZ: ulTimeslot *= 4; break; case cOCT6100_TDM_STREAM_FREQ_4MHZ: ulTimeslot *= 2; break; case cOCT6100_TDM_STREAM_FREQ_8MHZ: ulTimeslot *= 1; break; case cOCT6100_TDM_STREAM_FREQ_16MHZ: ulTimeslot *= 1; break; default: return cOCT6100_ERR_FATAL_DE; } /* Check if entry is actualy reserved. */ if ( ((pulTsstAlloc[ ulTimeslot ] >> ulStream) & 0x1) != 0x1 ) return cOCT6100_ERR_FATAL_55; /*==================================================================================*/ /* Clear the entry. */ pulTsstAlloc[ ulTimeslot ] &= ~(0x1 << ulStream); /* Check and release the associated TSST if required. */ if ( f_ulNumTsst == 2 ) { /* Check if entry is actualy reserved. */ if ( ((pulTsstAlloc[ ulTimeslot ] >> ( ulStream - 1)) & 0x1) != 0x1 ) return cOCT6100_ERR_FATAL_54; /* Clear the entry. */ pulTsstAlloc[ ulTimeslot ] &= ~(0x1 << (ulStream - 1)); } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: octapi_llman.c Copyright (c) 2001-2005 Octasic Inc. Description: Library used to manage allocation tables and linked lists. The library is made such that only a block of contiguous memory is needed for the management of the linked list/allocation table. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 21 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #include "octapi_llman_private.h" #include "apilib/octapi_llman.h" #include "apilib/octapi_largmath.h" /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ | API UTILITIES | | Function: OctapiLlmAllocGetSize. | | Description: This function determines the amount of memory needed to | manage the allocation of a fixed amount of resources. | The memory is measured in bytes. | | ----------------------------------------------------------------------- | | Variable | Type | Description | ----------------------------------------------------------------------- | number_of_items UINT32 The number of resources to be allocated. | *l_size UINT32 UINT32 The amount of memory needed, returned. | \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 OctapiLlmAllocGetSize(UINT32 number_of_items,UINT32 * l_size) { if (number_of_items == 0) return(GENERIC_BAD_PARAM); *l_size = (sizeof(LLM_ALLOC)) + (number_of_items * sizeof(UINT32)); return(GENERIC_OK); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ | API UTILITIES | | Function: OctapiLlmAllocInit. | | Description: This function intializes the LLM_ALLOC structure. | | ----------------------------------------------------------------------- | | Variable | Type | Description | ----------------------------------------------------------------------- | **l void The memory used by the LLM_ALLOC structure. | number_of_items UINT32 The number of resources to be allocated. | \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 OctapiLlmAllocInit(void ** l,UINT32 number_of_items) { LLM_ALLOC* ls; UINT32 i; /* Check the number of items required.*/ if (number_of_items == 0) return(GENERIC_BAD_PARAM); /* If no memory has been allocated yet:*/ if (*l == NULL) return(OCTAPI_LLM_MEMORY_NOT_ALLOCATED); /* Build the structure before starting.*/ ls = (LLM_ALLOC *)(*l); ls->linked_list = (UINT32 *)((BYTE *)ls + sizeof(LLM_ALLOC)); ls->number_of_items = number_of_items; /* Linked list links all structures in ascending order.*/ for(i=0;ilinked_list[i] = i+1; } ls->linked_list[number_of_items - 1] = 0xFFFFFFFF; /* Invalid link.*/ /* Next avail is 0.*/ ls->next_avail_num = 0; /* Number of allocated items is null.*/ ls->allocated_items = 0; return(GENERIC_OK); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ | API UTILITIES | | Function: OctapiLlmAllocInfo. | | Description: This function returns the number of free and allocated | block in the LLMAN list. | | ----------------------------------------------------------------------- | | Variable | Type | Description | ----------------------------------------------------------------------- | *l void The memory used by the LLM_ALLOC structure. | *allocated_items UINT32 Number of allocated items. | *available_items UINT32 Number of available items. | \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 OctapiLlmAllocInfo(void * l,UINT32 * allocated_items,UINT32 * available_items) { LLM_ALLOC* ls; /* Build the structure before starting.*/ ls = (LLM_ALLOC *)l; ls->linked_list = (UINT32 *)((BYTE *)ls + sizeof(LLM_ALLOC)); *allocated_items = ls->allocated_items; *available_items = ls->number_of_items - ls->allocated_items; return(GENERIC_OK); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ | API UTILITIES | | Function: OctapiLlmAllocInfo. | | Description: This function allocates the resource indicated by blocknum. | If the resource can be allocated then GENERIC_OK is returned. | Else an error. | | ----------------------------------------------------------------------- | | Variable | Type | Description | ----------------------------------------------------------------------- | *l void The memory used by the LLM_ALLOC structure. | *block_num UINT32 The resource to be allocated. | \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 OctapiLlmAllocAlloc(void * l,UINT32 * blocknum) { LLM_ALLOC* ls; UINT32 allocated_block; UINT32* node; /* Build the structure before starting.*/ ls = (LLM_ALLOC *)l; ls->linked_list = (UINT32 *)((BYTE *)ls + sizeof(LLM_ALLOC)); /* Get next available block number.*/ allocated_block = ls->next_avail_num; /* Check if block is invalid.*/ if (allocated_block == 0xFFFFFFFF) { /* Make blocknum NULL.*/ *blocknum = 0xFFFFFFFF; return(OCTAPI_LLM_NO_STRUCTURES_LEFT); } node = &ls->linked_list[allocated_block]; /* Copy next block number.*/ ls->next_avail_num = *node; /* Tag as used the current block number.*/ *node = 0xFFFFFFFE; /* Return proper block number.*/ *blocknum = allocated_block; /* Update block usage number.*/ ls->allocated_items++; return(GENERIC_OK); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ | API UTILITIES | | Function: OctapiLlmAllocDealloc. | | Description: This function deallocates the resource indicated by blocknum. | If the resource is not already allocated an error is returned. | Else GENERIC_OK is returned. | | ----------------------------------------------------------------------- | | Variable | Type | Description | ----------------------------------------------------------------------- | *l void The memory used by the LLM_ALLOC structure. | block_num UINT32 The resource to be deallocated. | \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static UINT32 OctapiLlmAllocDealloc(void * l,UINT32 blocknum) { LLM_ALLOC* ls; UINT32* node; /* Build the structure before starting.*/ ls = (LLM_ALLOC *)l; ls->linked_list = (UINT32 *)((BYTE *)ls + sizeof(LLM_ALLOC)); /* Check for null item pointer.*/ if (blocknum == 0xFFFFFFFF) return(GENERIC_OK); /* Check if blocknum is within specified item range.*/ if (blocknum >= ls->number_of_items) return(OCTAPI_LLM_BLOCKNUM_OUT_OF_RANGE); node = &ls->linked_list[blocknum]; /* Check if block is really used as of now.*/ if (*node != 0xFFFFFFFE) return(OCTAPI_LLM_MEMORY_NOT_ALLOCATED); /* Add link to list.*/ *node = ls->next_avail_num; /* Point to returned block.*/ ls->next_avail_num = blocknum; /* Update block usage number.*/ ls->allocated_items--; return(GENERIC_OK); } /**************************************** llm_list section **********************************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: octapi_bt0.c Copyright (c) 2001-2005 Octasic Inc. Description: Library used to manage a binary tree of variable max size. Library is made to use one block of contiguous memory to manage the tree. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 18 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #include "apilib/octapi_bt0.h" #include "octapi_bt0_private.h" static UINT32 OctApiBt0GetSize(UINT32 number_of_items,UINT32 key_size, UINT32 data_size, UINT32 * b_size) { if ((key_size % 4) != 0) return(OCTAPI_BT0_KEY_SIZE_NOT_MUTLIPLE_OF_UINT32); if ((data_size % 4) != 0) return(OCTAPI_BT0_DATA_SIZE_NOT_MUTLIPLE_OF_UINT32); *b_size = 0; *b_size += sizeof(OCTAPI_BT0); *b_size += sizeof(OCTAPI_BT0_NODE) * number_of_items; *b_size += key_size * number_of_items; *b_size += data_size * number_of_items; return(GENERIC_OK); } static UINT32 OctApiBt0Init(void ** b,UINT32 number_of_items,UINT32 key_size, UINT32 data_size) { UINT32 i; OCTAPI_BT0 * bb; /* Check input parameters.*/ if ((key_size % 4) != 0) return(OCTAPI_BT0_KEY_SIZE_NOT_MUTLIPLE_OF_UINT32); if ((data_size % 4) != 0) return(OCTAPI_BT0_DATA_SIZE_NOT_MUTLIPLE_OF_UINT32); /* If b is not already allocated.*/ if (*b == NULL) return(OCTAPI_BT0_MALLOC_FAILED); bb = (OCTAPI_BT0 *)(*b); /* Initialize the tree to an empty one!*/ bb->root_link.node_number = 0xFFFFFFFF; bb->root_link.depth = 0; /* Initialize tree parameters.*/ bb->number_of_items = number_of_items; bb->key_size = key_size / 4; bb->data_size = data_size / 4; /* Initialize the next free node pointer.*/ if (number_of_items != 0) bb->next_free_node = 0; else bb->next_free_node = 0xFFFFFFFF; /* Setup the arrays.*/ OctApiBt0CorrectPointers(bb); /* Initialize the Nodes to unused!*/ for(i=0;inode[i].next_free_node = i + 1; } /* Last empty node points to invalid node.*/ bb->node[number_of_items-1].next_free_node = 0xFFFFFFFF; bb->invalid_value = 0xFFFFFFFF; bb->no_smaller_key = OCTAPI_BT0_NO_SMALLER_KEY; return(GENERIC_OK); } void OctApiBt0CorrectPointers(OCTAPI_BT0 * bb) { bb->node = (OCTAPI_BT0_NODE *)(((BYTE *)bb) + sizeof(OCTAPI_BT0)); bb->key = (UINT32 *)(((BYTE *)bb->node) + (sizeof(OCTAPI_BT0_NODE) * bb->number_of_items)); bb->data = (UINT32 *)(((BYTE *)bb->key) + (sizeof(UINT32) * bb->number_of_items * bb->key_size)); } static UINT32 OctApiBt0AddNode2(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link,UINT32 * lkey,UINT32 new_node_number) { UINT32 result; if (link->node_number == 0xFFFFFFFF) /* We have an empty node. Here, we shall place the new node.*/ { bb->node[new_node_number].l[0].node_number = 0xFFFFFFFF; bb->node[new_node_number].l[0].depth = 0; bb->node[new_node_number].l[1].node_number = 0xFFFFFFFF; bb->node[new_node_number].l[1].depth = 0; /* OCTAPI_BT0_LINK to parent!*/ link->node_number = new_node_number; link->depth = 1; /* We are a leaf, last OCTAPI_BT0_LINK depth is 1.*/ return(GENERIC_OK); } else /* Current node is used, check for a match and a direction.*/ { OCTAPI_BT0_NODE * this_node; UINT32 compare; /* Get a pointer to this node.*/ this_node = &(bb->node[link->node_number]); /* Compare this node to the lkey.*/ compare = OctApiBt0KeyCompare(bb,link,lkey); if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/ { result = OctApiBt0AddNode2(bb,&(this_node->l[0]), lkey, new_node_number); if (result != GENERIC_OK) return(result); } else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/ { result = OctApiBt0AddNode2(bb,&(this_node->l[1]), lkey, new_node_number); if (result != GENERIC_OK) return(result); } else { return(OCTAPI_BT0_KEY_ALREADY_IN_TREE); } /* Check if this node is unbalanced by 2. If so, rebalance it:*/ if (this_node->l[0].depth > (this_node->l[1].depth + 1) || this_node->l[1].depth > (this_node->l[0].depth + 1)) { OctApiBt0Rebalance(bb,link); } /* Always update the OCTAPI_BT0_LINK depth before exiting.*/ OctApiBt0UpdateLinkDepth(bb,link); return(GENERIC_OK); } } static UINT32 OctApiBt0AddNode3(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link,UINT32 * lkey,UINT32 *p_new_node_number) { UINT32 result; if (link->node_number == 0xFFFFFFFF) /* We have an empty node. Here, we shall place the new node.*/ { if ( *p_new_node_number == 0xFFFFFFFF ) return(OCTAPI_BT0_NO_NODES_AVAILABLE); bb->node[*p_new_node_number].l[0].node_number = 0xFFFFFFFF; bb->node[*p_new_node_number].l[0].depth = 0; bb->node[*p_new_node_number].l[1].node_number = 0xFFFFFFFF; bb->node[*p_new_node_number].l[1].depth = 0; /* OCTAPI_BT0_LINK to parent!*/ link->node_number = *p_new_node_number; link->depth = 1; /* We are a leaf, last OCTAPI_BT0_LINK depth is 1.*/ return(GENERIC_OK); } else /* Current node is used, check for a match and a direction.*/ { OCTAPI_BT0_NODE * this_node; UINT32 compare; /* Get a pointer to this node.*/ this_node = &(bb->node[link->node_number]); /* Compare this node to the lkey.*/ compare = OctApiBt0KeyCompare(bb,link,lkey); if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/ { result = OctApiBt0AddNode3(bb,&(this_node->l[0]), lkey, p_new_node_number); if (result != GENERIC_OK) return(result); } else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/ { result = OctApiBt0AddNode3(bb,&(this_node->l[1]), lkey, p_new_node_number); if (result != GENERIC_OK) return(result); } else { *p_new_node_number = link->node_number; return(OCTAPI_BT0_KEY_ALREADY_IN_TREE); } /* Check if this node is unbalanced by 2. If so, rebalance it:*/ if (this_node->l[0].depth > (this_node->l[1].depth + 1) || this_node->l[1].depth > (this_node->l[0].depth + 1)) { OctApiBt0Rebalance(bb,link); } /* Always update the OCTAPI_BT0_LINK depth before exiting.*/ OctApiBt0UpdateLinkDepth(bb,link); return(GENERIC_OK); } } /* state 0 -> first call to the function. 1 -> recursive call.*/ static UINT32 OctApiBt0AddNode4(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link,UINT32 * lkey,UINT32 *p_new_node_number, UINT32 *p_prev_node_number, UINT32 state ) { UINT32 result; UINT32 *nkey; UINT32 *okey; if (link->node_number == 0xFFFFFFFF) /* We have an empty node. Here, we shall place the new node.*/ { bb->node[*p_new_node_number].l[0].node_number = 0xFFFFFFFF; bb->node[*p_new_node_number].l[0].depth = 0; bb->node[*p_new_node_number].l[1].node_number = 0xFFFFFFFF; bb->node[*p_new_node_number].l[1].depth = 0; /* OCTAPI_BT0_LINK to parent!*/ link->node_number = *p_new_node_number; link->depth = 1; /* We are a leaf, last OCTAPI_BT0_LINK depth is 1.*/ if ( state == 0 ) *p_prev_node_number = 0xFFFFFFFF; return(GENERIC_OK); } else /* Current node is used, check for a match and a direction.*/ { OCTAPI_BT0_NODE * this_node; UINT32 compare; /* Get a pointer to this node.*/ this_node = &(bb->node[link->node_number]); /* Compare this node to the lkey.*/ compare = OctApiBt0KeyCompare(bb,link,lkey); if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/ { if ( state == 0 ) *p_prev_node_number = OCTAPI_BT0_NO_SMALLER_KEY; if ( *p_prev_node_number != OCTAPI_BT0_NO_SMALLER_KEY ) { /* Check if the key is the smallest one encountered yet.*/ okey = &(bb->key[bb->key_size * (*p_prev_node_number)]); nkey = &(bb->key[bb->key_size * link->node_number]); /* If the node is key smaller then the old small one, change the value.*/ if ( *nkey > *okey ) { if ( *nkey < *lkey ) *p_prev_node_number = link->node_number; } } result = OctApiBt0AddNode4(bb,&(this_node->l[0]), lkey, p_new_node_number, p_prev_node_number, 1); if (result != GENERIC_OK) return(result); } else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/ { if ( state == 0 ) *p_prev_node_number = link->node_number; else { if ( *p_prev_node_number == OCTAPI_BT0_NO_SMALLER_KEY ) *p_prev_node_number = link->node_number; else { /* Check if the key is the smallest one encountered yet.*/ okey = &(bb->key[bb->key_size * (*p_prev_node_number)]); nkey = &(bb->key[bb->key_size * link->node_number]); /* If the node is key smaller then the old small one, change the value.*/ if ( *nkey > *okey ) { if ( *nkey < *lkey ) *p_prev_node_number = link->node_number; } } } result = OctApiBt0AddNode4(bb,&(this_node->l[1]), lkey, p_new_node_number, p_prev_node_number, 1); if (result != GENERIC_OK) return(result); } else { *p_new_node_number = link->node_number; return(OCTAPI_BT0_KEY_ALREADY_IN_TREE); } /* Check if this node is unbalanced by 2. If so, rebalance it:*/ if (this_node->l[0].depth > (this_node->l[1].depth + 1) || this_node->l[1].depth > (this_node->l[0].depth + 1)) { OctApiBt0Rebalance(bb,link); } /* Always update the OCTAPI_BT0_LINK depth before exiting.*/ OctApiBt0UpdateLinkDepth(bb,link); return(GENERIC_OK); } } static UINT32 OctApiBt0KeyCompare(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link, UINT32 * lkey) { UINT32 * nkey; UINT32 i; /* Find the first UINT32 of the key.*/ nkey = &(bb->key[bb->key_size * link->node_number]); for(i=0;ikey_size;i++) { if (lkey[i] < nkey[i]) return(OCTAPI_BT0_LKEY_SMALLER); else if (lkey[i] > nkey[i]) return(OCTAPI_BT0_LKEY_LARGER); } return(OCTAPI_BT0_LKEY_EQUAL); } void OctApiBt0UpdateLinkDepth(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link) { OCTAPI_BT0_NODE * this_node; /* Get a pointer to this node.*/ this_node = &(bb->node[link->node_number]); if (this_node->l[0].depth > this_node->l[1].depth) link->depth = this_node->l[0].depth + 1; else link->depth = this_node->l[1].depth + 1; } void OctApiBt0Rebalance(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * root_link) { if (bb->node[root_link->node_number].l[0].depth > (bb->node[root_link->node_number].l[1].depth + 1)) /* Heavy to the left.*/ { /* Check if the right child of the heavy child node is causing a problem.*/ /* If so, do a left rotate in order to make the left most child the longer one.*/ { OCTAPI_BT0_LINK * heavy_link; heavy_link = &(bb->node[root_link->node_number].l[0]); if (bb->node[heavy_link->node_number].l[1].depth > bb->node[heavy_link->node_number].l[0].depth) { OctApiBt0ExternalHeavy(bb,heavy_link); } } /* Ready to do super rotation!*/ { OCTAPI_BT0_LINK init_root_link; OCTAPI_BT0_LINK init_heavy_link; OCTAPI_BT0_LINK init_leaf_tree[3]; /* Save pertinent initial OCTAPI_BT0_LINK information.*/ init_root_link = *root_link; init_heavy_link = bb->node[root_link->node_number].l[0]; init_leaf_tree[2] = bb->node[root_link->node_number].l[1]; init_leaf_tree[0] = bb->node[bb->node[root_link->node_number].l[0].node_number].l[0]; init_leaf_tree[1] = bb->node[bb->node[root_link->node_number].l[0].node_number].l[1]; /* Restructure the tree.*/ *root_link = init_heavy_link; bb->node[init_heavy_link.node_number].l[1] = init_root_link; bb->node[init_root_link.node_number].l[0] = init_leaf_tree[1]; /* Reconstruct the depth of the branches.*/ OctApiBt0UpdateLinkDepth(bb,&(bb->node[root_link->node_number].l[1])); OctApiBt0UpdateLinkDepth(bb,root_link); } } else if (bb->node[root_link->node_number].l[1].depth > (bb->node[root_link->node_number].l[0].depth + 1)) /* Heavy to the right.*/ { /* Check if the right child of the heavy child node is causing a problem.*/ /* If so, do a left rotate in order to make the left most child the longer one.*/ { OCTAPI_BT0_LINK * heavy_link; heavy_link = &(bb->node[root_link->node_number].l[1]); if (bb->node[heavy_link->node_number].l[0].depth > bb->node[heavy_link->node_number].l[1].depth) { OctApiBt0ExternalHeavy(bb,heavy_link); } } /* Ready to do super rotation!*/ { OCTAPI_BT0_LINK init_root_link; OCTAPI_BT0_LINK init_heavy_link; OCTAPI_BT0_LINK init_leaf_tree[3]; /* Save pertinent initial OCTAPI_BT0_LINK information.*/ init_root_link = *root_link; init_heavy_link = bb->node[root_link->node_number].l[1]; init_leaf_tree[2] = bb->node[root_link->node_number].l[0]; init_leaf_tree[0] = bb->node[bb->node[root_link->node_number].l[1].node_number].l[1]; init_leaf_tree[1] = bb->node[bb->node[root_link->node_number].l[1].node_number].l[0]; /* Restructure the tree.*/ *root_link = init_heavy_link; bb->node[init_heavy_link.node_number].l[0] = init_root_link; bb->node[init_root_link.node_number].l[1] = init_leaf_tree[1]; /* Reconstruct the depth of the branches.*/ OctApiBt0UpdateLinkDepth(bb,&(bb->node[root_link->node_number].l[0])); OctApiBt0UpdateLinkDepth(bb,root_link); } } } /* This function does a rotation towards the outside of the tree*/ /* in order to keep the heavy branches towards the outside.*/ void OctApiBt0ExternalHeavy(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * root_link) { if (bb->node[root_link->node_number].l[1].depth > bb->node[root_link->node_number].l[0].depth) /* Exterior of tree is towards the left.*/ { OCTAPI_BT0_LINK init_root_link; OCTAPI_BT0_LINK init_heavy_link; OCTAPI_BT0_LINK init_leaf_tree[3]; /* Save pertinent initial OCTAPI_BT0_LINK information.*/ init_root_link = *root_link; init_leaf_tree[0] = bb->node[root_link->node_number].l[0]; init_heavy_link = bb->node[root_link->node_number].l[1]; init_leaf_tree[1] = bb->node[bb->node[root_link->node_number].l[1].node_number].l[0]; init_leaf_tree[2] = bb->node[bb->node[root_link->node_number].l[1].node_number].l[1]; /* Restructure the tree.*/ *root_link = init_heavy_link; bb->node[init_heavy_link.node_number].l[0] = init_root_link; bb->node[init_root_link.node_number].l[1] = init_leaf_tree[1]; /* Reconstruct the depth of the branches.*/ OctApiBt0UpdateLinkDepth(bb,&(bb->node[root_link->node_number].l[0])); OctApiBt0UpdateLinkDepth(bb,root_link); } else if (bb->node[root_link->node_number].l[0].depth > bb->node[root_link->node_number].l[1].depth) /* Exterior of tree is towards the right.*/ { OCTAPI_BT0_LINK init_root_link; OCTAPI_BT0_LINK init_heavy_link; OCTAPI_BT0_LINK init_leaf_tree[3]; /* Save pertinent initial OCTAPI_BT0_LINK information.*/ init_root_link = *root_link; init_leaf_tree[0] = bb->node[root_link->node_number].l[1]; init_heavy_link = bb->node[root_link->node_number].l[0]; init_leaf_tree[1] = bb->node[bb->node[root_link->node_number].l[0].node_number].l[1]; init_leaf_tree[2] = bb->node[bb->node[root_link->node_number].l[0].node_number].l[0]; /* Restructure the tree.*/ *root_link = init_heavy_link; bb->node[init_heavy_link.node_number].l[1] = init_root_link; bb->node[init_root_link.node_number].l[0] = init_leaf_tree[1]; /* Reconstruct the depth of the branches.*/ OctApiBt0UpdateLinkDepth(bb,&(bb->node[root_link->node_number].l[1])); OctApiBt0UpdateLinkDepth(bb,root_link); } } /* State:*/ /* 0 = seeking node to be removed.*/ /* 1 = node found, left branch taken.*/ /* 2 = node found, right branch taken.*/ static UINT32 OctApiBt0RemoveNode2(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link, UINT32 * lkey, OCTAPI_BT0_LINK * link_to_removed_node, UINT32 state, OCTAPI_BT0_LINK * volatile_grandparent_link) { UINT32 result; OCTAPI_BT0_NODE * this_node; /* Get a pointer to this node.*/ this_node = &(bb->node[link->node_number]); if (state == 0) { if (link->node_number == 0xFFFFFFFF) /* We have an empty node. The node we were looking for does not exist.*/ { return(OCTAPI_BT0_KEY_NOT_IN_TREE); } else /* Current node is used, check for a match and a direction.*/ { UINT32 compare; /* Compare this node to the lkey.*/ compare = OctApiBt0KeyCompare(bb,link,lkey); if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/ { result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[0]), lkey, link_to_removed_node, 0, NULL); if (result != GENERIC_OK) return(result); } else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/ { result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[1]), lkey, link_to_removed_node, 0, NULL); if (result != GENERIC_OK) return(result); } else { link_to_removed_node = link; /* Keep on going down to find a replacement node.*/ if (bb->node[link->node_number].l[0].node_number == 0xFFFFFFFF && bb->node[link->node_number].l[1].node_number == 0xFFFFFFFF) { /* Doe! No tree left! WHAT TO DO? */ /* Just delete the current node. That's it.*/ /* Release the current node (restore free node link-list)*/ bb->node[link->node_number].next_free_node = bb->next_free_node; bb->next_free_node = link->node_number; link->node_number = 0xFFFFFFFF; link->depth = 0; return(GENERIC_OK); } else if (bb->node[link->node_number].l[0].node_number != 0xFFFFFFFF) /* Left node is present. Go left, then permanently right.*/ { OCTAPI_BT0_NODE * removed_node_pnt; removed_node_pnt = &(bb->node[link->node_number]); result = OctApiBt0RemoveNode2(bb,&(removed_node_pnt->l[0]), lkey, link_to_removed_node, 1, link); if (result != GENERIC_OK) return(result); /* Caution! Once we are here, the link->node_pnt->l[0] has been modified,*/ /* but is about to be discarded! Save it quickly!*/ /* bb->node[link->node_number].l[0] = removed_node_pnt->l[0];*/ } else /* Right node is present. Go right, then permanently left.*/ { OCTAPI_BT0_NODE * removed_node_pnt; removed_node_pnt = &(bb->node[link->node_number]); result = OctApiBt0RemoveNode2(bb,&(removed_node_pnt->l[1]), lkey, link_to_removed_node, 2, link); if (result != GENERIC_OK) return(result); /* Caution! Once we are here, the link->node_pnt->l[0] has been modified,*/ /* but is about to be discarded! Save it quickly!*/ /* bb->node[link->node_number].l[1] = removed_node_pnt->l[1];*/ } } } } else { /* Left side, Right-most node found! OR*/ /* Right side, Left-most node found!*/ if ((state == 1 && bb->node[link->node_number].l[1].node_number == 0xFFFFFFFF) || (state == 2 && bb->node[link->node_number].l[0].node_number == 0xFFFFFFFF)) { OCTAPI_BT0_LINK init_chosen_link; /* Release the current node (restore free node link-list)*/ bb->node[link_to_removed_node->node_number].next_free_node = bb->next_free_node; bb->next_free_node = link_to_removed_node->node_number; /* Save the link to the chosen node, because it is about to be deleted.*/ init_chosen_link = *link; /* Remove this node, and allow the tree to go on:*/ { OCTAPI_BT0_LINK init_child_link[2]; init_child_link[0] = bb->node[link->node_number].l[0]; init_child_link[1] = bb->node[link->node_number].l[1]; if (state == 1) *link = init_child_link[0]; else *link = init_child_link[1]; } /* Replace the removed node by this node.*/ { OCTAPI_BT0_LINK init_removed_child_link[2]; init_removed_child_link[0] = bb->node[link_to_removed_node->node_number].l[0]; init_removed_child_link[1] = bb->node[link_to_removed_node->node_number].l[1]; *link_to_removed_node = init_chosen_link; bb->node[init_chosen_link.node_number].l[0] = init_removed_child_link[0]; bb->node[init_chosen_link.node_number].l[1] = init_removed_child_link[1]; } return(GENERIC_OK); } else { /* Keep on going, we have not found the center most node yet!*/ if (state == 1) { result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[1]), lkey, link_to_removed_node, state, NULL); if (result != GENERIC_OK) return(result); /* Refresh the link if our link is volatile.*/ if (volatile_grandparent_link != NULL) { link = &(bb->node[volatile_grandparent_link->node_number].l[0]); } } else { result = OctApiBt0RemoveNode2(bb,&(bb->node[link->node_number].l[0]), lkey, link_to_removed_node, state, NULL); if (result != GENERIC_OK) return(result); /* Refresh the link if our link is volatile.*/ if (volatile_grandparent_link != NULL) { link = &(bb->node[volatile_grandparent_link->node_number].l[1]); } } } } /* We may have messed up the tree. So patch it!*/ /* Check if this node is unbalanced by 2. If so, rebalance it:*/ if (this_node->l[0].depth > (this_node->l[1].depth + 1) || this_node->l[1].depth > (this_node->l[0].depth + 1)) { OctApiBt0Rebalance(bb,link); } /* Always update the OCTAPI_BT0_LINK depth before exiting.*/ OctApiBt0UpdateLinkDepth(bb,link); return(GENERIC_OK); } static UINT32 OctApiBt0QueryNode2(OCTAPI_BT0 * bb,OCTAPI_BT0_LINK * link,UINT32 * lkey,UINT32 * node_number) { UINT32 result; if (link->node_number == 0xFFFFFFFF) /* We have an empty node. The node we were looking for does not exist.*/ { return(OCTAPI_BT0_KEY_NOT_IN_TREE); } else /* Current node is used, check for a match and a direction.*/ { UINT32 compare; /* Compare this node to the lkey.*/ compare = OctApiBt0KeyCompare(bb,link,lkey); if (compare == OCTAPI_BT0_LKEY_SMALLER) /* Go left.*/ { result = OctApiBt0QueryNode2(bb,&(bb->node[link->node_number].l[0]), lkey, node_number); if (result != GENERIC_OK) return(result); } else if (compare == OCTAPI_BT0_LKEY_LARGER) /* Go right.*/ { result = OctApiBt0QueryNode2(bb,&(bb->node[link->node_number].l[1]), lkey, node_number); if (result != GENERIC_OK) return(result); } else { /* A match!*/ *node_number = link->node_number; } } return(GENERIC_OK); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: octapi_largmath.h Copyright (c) 2001-2005 Octasic Inc. Description: Library used to perform arithmetic on integer values of an integer multiple of 32-bits. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR38 $ $Octasic_Revision: 10 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #include "apilib/octapi_largmath.h" /* * Copyright (C) 2005-2006 Digium, Inc. * * Mark Spencer * * All Rights Reserved */ #include "oct6100_api.h" #include #include //#include //#include #include "vpm450m.h" /* API for Octasic access */ static UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime) { /* Why couldn't they just take a timeval like everyone else? */ struct timeval tv; unsigned long long total_usecs; unsigned int mask = ~0; do_gettimeofday(&tv); total_usecs = (((unsigned long long)(tv.tv_sec)) * 1000000) + (((unsigned long long)(tv.tv_usec))); f_pTime->aulWallTimeUs[0] = (total_usecs & mask); f_pTime->aulWallTimeUs[1] = (total_usecs >> 32); return cOCT6100_ERR_OK; } static UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern, UINT32 f_ulLength) { memset(f_pAddress, f_ulPattern, f_ulLength); return cOCT6100_ERR_OK; } static UINT32 Oct6100UserMemCopy(PVOID f_pDestination, PVOID f_pSource, UINT32 f_ulLength) { memcpy(f_pDestination, f_pSource, f_ulLength); return cOCT6100_ERR_OK; } static UINT32 Oct6100UserCreateSerializeObject(tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate) { return cOCT6100_ERR_OK; } static UINT32 Oct6100UserDestroySerializeObject(tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy) { #ifdef OCTASIC_DEBUG printk("I should never be called! (destroy serialize object)\n"); #endif return cOCT6100_ERR_OK; } static UINT32 Oct6100UserSeizeSerializeObject(tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize) { /* Not needed */ return cOCT6100_ERR_OK; } static UINT32 Oct6100UserReleaseSerializeObject(tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease) { /* Not needed */ return cOCT6100_ERR_OK; } static UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams) { oct_set_reg(f_pWriteParams->pProcessContext, f_pWriteParams->ulWriteAddress, f_pWriteParams->usWriteData); return cOCT6100_ERR_OK; } static UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams) { unsigned int x; for (x=0;xulWriteLength;x++) { oct_set_reg(f_pSmearParams->pProcessContext, f_pSmearParams->ulWriteAddress + (x << 1), f_pSmearParams->usWriteData); } return cOCT6100_ERR_OK; } static UINT32 Oct6100UserDriverWriteBurstApi(tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams) { unsigned int x; for (x=0;xulWriteLength;x++) { oct_set_reg(f_pBurstParams->pProcessContext, f_pBurstParams->ulWriteAddress + (x << 1), f_pBurstParams->pusWriteData[x]); } return cOCT6100_ERR_OK; } static UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams) { *(f_pReadParams->pusReadData) = oct_get_reg(f_pReadParams->pProcessContext, f_pReadParams->ulReadAddress); return cOCT6100_ERR_OK; } static UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams) { unsigned int x; for (x=0;xulReadLength;x++) { f_pBurstParams->pusReadData[x] = oct_get_reg(f_pBurstParams->pProcessContext, f_pBurstParams->ulReadAddress + (x << 1)); } return cOCT6100_ERR_OK; } #include "vpm450m_fw.h" #define SOUT_G168_1100GB_ON 0x40000004 #define SOUT_DTMF_1 0x40000011 #define SOUT_DTMF_2 0x40000012 #define SOUT_DTMF_3 0x40000013 #define SOUT_DTMF_A 0x4000001A #define SOUT_DTMF_4 0x40000014 #define SOUT_DTMF_5 0x40000015 #define SOUT_DTMF_6 0x40000016 #define SOUT_DTMF_B 0x4000001B #define SOUT_DTMF_7 0x40000017 #define SOUT_DTMF_8 0x40000018 #define SOUT_DTMF_9 0x40000019 #define SOUT_DTMF_C 0x4000001C #define SOUT_DTMF_STAR 0x4000001E #define SOUT_DTMF_0 0x40000010 #define SOUT_DTMF_POUND 0x4000001F #define SOUT_DTMF_D 0x4000001D #define ROUT_G168_2100GB_ON 0x10000000 #define ROUT_G168_2100GB_WSPR 0x10000002 #define ROUT_SOUT_G168_2100HB_END 0x50000003 #define ROUT_G168_1100GB_ON 0x10000004 #define ROUT_DTMF_1 0x10000011 #define ROUT_DTMF_2 0x10000012 #define ROUT_DTMF_3 0x10000013 #define ROUT_DTMF_A 0x1000001A #define ROUT_DTMF_4 0x10000014 #define ROUT_DTMF_5 0x10000015 #define ROUT_DTMF_6 0x10000016 #define ROUT_DTMF_B 0x1000001B #define ROUT_DTMF_7 0x10000017 #define ROUT_DTMF_8 0x10000018 #define ROUT_DTMF_9 0x10000019 #define ROUT_DTMF_C 0x1000001C #define ROUT_DTMF_STAR 0x1000001E #define ROUT_DTMF_0 0x10000010 #define ROUT_DTMF_POUND 0x1000001F #define ROUT_DTMF_D 0x1000001D #if 0 #define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_HT_FREEZE #else #define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_POWER_DOWN #endif struct vpm450m { tPOCT6100_INSTANCE_API pApiInstance; UINT32 aulEchoChanHndl[ 128 ]; int chanflags[128]; int ecmode[128]; }; #define FLAG_DTMF (1 << 0) #define FLAG_MUTE (1 << 1) #define FLAG_ECHO (1 << 2) static unsigned int tones[] = { SOUT_DTMF_1, SOUT_DTMF_2, SOUT_DTMF_3, SOUT_DTMF_A, SOUT_DTMF_4, SOUT_DTMF_5, SOUT_DTMF_6, SOUT_DTMF_B, SOUT_DTMF_7, SOUT_DTMF_8, SOUT_DTMF_9, SOUT_DTMF_C, SOUT_DTMF_STAR, SOUT_DTMF_0, SOUT_DTMF_POUND, SOUT_DTMF_D, SOUT_G168_1100GB_ON, ROUT_DTMF_1, ROUT_DTMF_2, ROUT_DTMF_3, ROUT_DTMF_A, ROUT_DTMF_4, ROUT_DTMF_5, ROUT_DTMF_6, ROUT_DTMF_B, ROUT_DTMF_7, ROUT_DTMF_8, ROUT_DTMF_9, ROUT_DTMF_C, ROUT_DTMF_STAR, ROUT_DTMF_0, ROUT_DTMF_POUND, ROUT_DTMF_D, ROUT_G168_1100GB_ON, }; static void vpm450m_setecmode(struct vpm450m *vpm450m, int channel, int mode) { tOCT6100_CHANNEL_MODIFY modify; UINT32 ulResult; if (vpm450m->ecmode[channel] == mode) return; Oct6100ChannelModifyDef(&modify); modify.ulEchoOperationMode = mode; modify.ulChannelHndl = vpm450m->aulEchoChanHndl[channel]; ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, &modify); if (ulResult != GENERIC_OK) { printk("Failed to apply echo can changes on channel %d!\n", channel); } else { #ifdef OCTASIC_DEBUG printk("Echo can on channel %d set to %d\n", channel, mode); #endif vpm450m->ecmode[channel] = mode; } } void vpm450m_setdtmf(struct vpm450m *vpm450m, int channel, int detect, int mute) { tOCT6100_CHANNEL_MODIFY modify; UINT32 ulResult; Oct6100ChannelModifyDef(&modify); modify.ulChannelHndl = vpm450m->aulEchoChanHndl[channel]; if (mute) { vpm450m->chanflags[channel] |= FLAG_MUTE; modify.VqeConfig.fDtmfToneRemoval = TRUE; } else { vpm450m->chanflags[channel] &= ~FLAG_MUTE; modify.VqeConfig.fDtmfToneRemoval = FALSE; } if (detect) vpm450m->chanflags[channel] |= FLAG_DTMF; else vpm450m->chanflags[channel] &= ~FLAG_DTMF; if (vpm450m->chanflags[channel] & (FLAG_DTMF|FLAG_MUTE)) { if (!(vpm450m->chanflags[channel] & FLAG_ECHO)) { vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET); vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_FREEZE); } } else { if (!(vpm450m->chanflags[channel] & FLAG_ECHO)) vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_DIGITAL); } ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, &modify); if (ulResult != GENERIC_OK) { printk("Failed to apply dtmf mute changes on channel %d!\n", channel); } /* printk("VPM450m: Setting DTMF on channel %d: %s / %s\n", channel, (detect ? "DETECT" : "NO DETECT"), (mute ? "MUTE" : "NO MUTE")); */ } void vpm450m_setec(struct vpm450m *vpm450m, int channel, int eclen) { if (eclen) { vpm450m->chanflags[channel] |= FLAG_ECHO; vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET); vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_NORMAL); } else { vpm450m->chanflags[channel] &= ~FLAG_ECHO; if (vpm450m->chanflags[channel] & (FLAG_DTMF | FLAG_MUTE)) { vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET); vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_FREEZE); } else vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_DIGITAL); } /* printk("VPM450m: Setting EC on channel %d to %d\n", channel, eclen); */ } int vpm450m_checkirq(struct vpm450m *vpm450m) { tOCT6100_INTERRUPT_FLAGS InterruptFlags; Oct6100InterruptServiceRoutineDef(&InterruptFlags); Oct6100InterruptServiceRoutine(vpm450m->pApiInstance, &InterruptFlags); if (InterruptFlags.fToneEventsPending) { printk("VPM450M: Tone events pending!\n"); return 1; } return 0; } int vpm450m_getdtmf(struct vpm450m *vpm450m, int *channel, int *tone, int *start) { tOCT6100_TONE_EVENT tonefound; tOCT6100_EVENT_GET_TONE tonesearch; UINT32 ulResult; Oct6100EventGetToneDef(&tonesearch); tonesearch.pToneEvent = &tonefound; tonesearch.ulMaxToneEvent = 1; ulResult = Oct6100EventGetTone(vpm450m->pApiInstance, &tonesearch); if (tonesearch.ulNumValidToneEvent) { if (channel) *channel = tonefound.ulUserChanId; if (tone) { switch(tonefound.ulToneDetected) { case SOUT_DTMF_1: *tone = '1'; break; case SOUT_DTMF_2: *tone = '2'; break; case SOUT_DTMF_3: *tone = '3'; break; case SOUT_DTMF_A: *tone = 'A'; break; case SOUT_DTMF_4: *tone = '4'; break; case SOUT_DTMF_5: *tone = '5'; break; case SOUT_DTMF_6: *tone = '6'; break; case SOUT_DTMF_B: *tone = 'B'; break; case SOUT_DTMF_7: *tone = '7'; break; case SOUT_DTMF_8: *tone = '8'; break; case SOUT_DTMF_9: *tone = '9'; break; case SOUT_DTMF_C: *tone = 'C'; break; case SOUT_DTMF_STAR: *tone = '*'; break; case SOUT_DTMF_0: *tone = '0'; break; case SOUT_DTMF_POUND: *tone = '#'; break; case SOUT_DTMF_D: *tone = 'D'; break; case SOUT_G168_1100GB_ON: *tone = 'f'; break; default: printk("Unknown tone value %08x\n", tonefound.ulToneDetected); *tone = 'u'; break; } } if (start) *start = (tonefound.ulEventType == cOCT6100_TONE_PRESENT); return 1; } return 0; } struct vpm450m *init_vpm450m(void *wc, int *isalaw) { tOCT6100_CHIP_OPEN ChipOpen; tOCT6100_GET_INSTANCE_SIZE InstanceSize; tOCT6100_CHANNEL_OPEN ChannelOpen; UINT32 ulResult; struct vpm450m *vpm450m; int x,y,law; vpm450m = kmalloc(sizeof(struct vpm450m), GFP_KERNEL); if (!vpm450m) return NULL; memset(vpm450m, 0, sizeof(struct vpm450m)); for (x=0;x<128;x++) vpm450m->ecmode[x] = -1; Oct6100ChipOpenDef(&ChipOpen); /* Setup Chip Open Parameters */ ChipOpen.ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ; Oct6100GetInstanceSizeDef(&InstanceSize); ChipOpen.pbyImageFile = vpm450m_fw; ChipOpen.pProcessContext = wc; ChipOpen.ulImageSize = sizeof(vpm450m_fw); ChipOpen.fEnableMemClkOut = TRUE; ChipOpen.ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ; ChipOpen.ulMaxChannels = 128; ChipOpen.ulMemoryType = cOCT6100_MEM_TYPE_DDR; ChipOpen.ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_32MB; ChipOpen.ulNumMemoryChips = 1; ChipOpen.ulMaxTdmStreams = 4; ChipOpen.aulTdmStreamFreqs[0] = cOCT6100_TDM_STREAM_FREQ_8MHZ; ChipOpen.ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE; #if 0 ChipOpen.fEnableAcousticEcho = TRUE; #endif ulResult = Oct6100GetInstanceSize(&ChipOpen, &InstanceSize); if (ulResult != cOCT6100_ERR_OK) { printk("Failed to get instance size, code %08x!\n", ulResult); kfree(vpm450m); return NULL; } vpm450m->pApiInstance = vmalloc(InstanceSize.ulApiInstanceSize); if (!vpm450m->pApiInstance) { printk("Out of memory (can't allocate %d bytes)!\n", InstanceSize.ulApiInstanceSize); kfree(vpm450m); return NULL; } printk("Before chip open!\n"); ulResult = Oct6100ChipOpen(vpm450m->pApiInstance, &ChipOpen); printk("After chip open!\n"); if (ulResult != cOCT6100_ERR_OK) { printk("Failed to open chip, code %08x!\n", ulResult); kfree(vpm450m); return NULL; } for (x=0;x<128;x++) { if (isalaw[x >> 5]) law = cOCT6100_PCM_A_LAW; else law = cOCT6100_PCM_U_LAW; Oct6100ChannelOpenDef(&ChannelOpen); ChannelOpen.pulChannelHndl = &vpm450m->aulEchoChanHndl[x]; ChannelOpen.ulUserChanId = x; ChannelOpen.TdmConfig.ulRinPcmLaw = law; ChannelOpen.TdmConfig.ulRinStream = 0; ChannelOpen.TdmConfig.ulRinTimeslot = x; ChannelOpen.TdmConfig.ulSinPcmLaw = law; ChannelOpen.TdmConfig.ulSinStream = 1; ChannelOpen.TdmConfig.ulSinTimeslot = x; ChannelOpen.TdmConfig.ulSoutPcmLaw = law; ChannelOpen.TdmConfig.ulSoutStream = 2; ChannelOpen.TdmConfig.ulSoutTimeslot = x; ChannelOpen.TdmConfig.ulRoutPcmLaw = law; ChannelOpen.TdmConfig.ulRoutStream = 3; ChannelOpen.TdmConfig.ulRoutTimeslot = x; ChannelOpen.VqeConfig.fEnableNlp = TRUE; ChannelOpen.VqeConfig.fRinDcOffsetRemoval = TRUE; ChannelOpen.VqeConfig.fSinDcOffsetRemoval = TRUE; ChannelOpen.fEnableToneDisabler = TRUE; ChannelOpen.ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_DIGITAL; ulResult = Oct6100ChannelOpen(vpm450m->pApiInstance, &ChannelOpen); if (ulResult != GENERIC_OK) { printk("Failed to open channel %d!\n", x); } for (y=0;yaulEchoChanHndl[x]; enable.ulToneNumber = tones[y]; if (Oct6100ToneDetectionEnable(vpm450m->pApiInstance, &enable) != GENERIC_OK) printk("Failed to enable tone detection on channel %d for tone %d!\n", x, y); } } return vpm450m; } void release_vpm450m(struct vpm450m *vpm450m) { UINT32 ulResult; tOCT6100_CHIP_CLOSE ChipClose; Oct6100ChipCloseDef(&ChipClose); ulResult = Oct6100ChipClose(vpm450m->pApiInstance, &ChipClose); if (ulResult != cOCT6100_ERR_OK) { printk("Failed to close chip, code %08x!\n", ulResult); } vfree(vpm450m->pApiInstance); kfree(vpm450m); }