From 3d61697e688c99ff9265238b2eab474f7f1bcfc8 Mon Sep 17 00:00:00 2001 From: Octasic Inc Date: Wed, 23 Nov 2005 15:07:18 +0200 Subject: importing OCT612x-01.00-PR38 --- .../oct6100api/oct6100_api/oct6100_playout_buf.c | 3275 ++++++++++++++++++++ 1 file changed, 3275 insertions(+) create mode 100644 software/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c (limited to 'software/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c') diff --git a/software/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c b/software/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c new file mode 100644 index 0000000..c815095 --- /dev/null +++ b/software/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c @@ -0,0 +1,3275 @@ +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +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 *****************************/ + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100BufferPlayoutLoad + +Description: This function loads a playout buffer into 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_pBufferLoad Pointer to buffer playout load structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100BufferPlayoutLoadDef( + tPOCT6100_BUFFER_LOAD f_pBufferLoad ) +{ + f_pBufferLoad->pbyBufferPattern = NULL; + f_pBufferLoad->ulBufferSize = 128; + f_pBufferLoad->ulBufferPcmLaw = cOCT6100_PCM_U_LAW; + + f_pBufferLoad->pulBufferIndex = NULL; + f_pBufferLoad->pulPlayoutFreeMemSize = NULL; + + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100BufferPlayoutLoad( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_BUFFER_LOAD f_pBufferLoad ) +{ + 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 = Oct6100BufferLoadSer( f_pApiInstance, f_pBufferLoad, TRUE, cOCT6100_INVALID_INDEX ); + } + 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: Oct6100BufferPlayoutLoadBlockInit + +Description: This function allows the user to initialize loading a buffer + into external memory using blocks. + +------------------------------------------------------------------------------- +| 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_pBufferLoadBlockInit Pointer to buffer playout load block init structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100BufferPlayoutLoadBlockInitDef( + tPOCT6100_BUFFER_LOAD_BLOCK_INIT f_pBufferLoadBlockInit ) +{ + f_pBufferLoadBlockInit->ulBufferSize = 128; + f_pBufferLoadBlockInit->ulBufferPcmLaw = cOCT6100_PCM_U_LAW; + + f_pBufferLoadBlockInit->pulBufferIndex = NULL; + f_pBufferLoadBlockInit->pulPlayoutFreeMemSize = NULL; + + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100BufferPlayoutLoadBlockInit( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_BUFFER_LOAD_BLOCK_INIT f_pBufferLoadBlockInit ) +{ + 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 = Oct6100BufferLoadBlockInitSer( f_pApiInstance, f_pBufferLoadBlockInit ); + } + 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: Oct6100BufferPlayoutLoadBlock + +Description: This function allows the user to load a buffer block into + 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_pBufferLoadBlock Pointer to buffer playout load block structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100BufferPlayoutLoadBlockDef( + tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock ) +{ + f_pBufferLoadBlock->ulBufferIndex = cOCT6100_INVALID_VALUE; + f_pBufferLoadBlock->ulBlockLength = cOCT6100_INVALID_VALUE; + f_pBufferLoadBlock->ulBlockOffset = cOCT6100_INVALID_VALUE; + + f_pBufferLoadBlock->pbyBufferPattern = NULL; + + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100BufferPlayoutLoadBlock( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock ) +{ + 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 = Oct6100BufferLoadBlockSer( f_pApiInstance, f_pBufferLoadBlock ); + } + 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: Oct6100BufferPlayoutUnload + +Description: This function unloads a playout buffer from 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_pBufferUnload Pointer to buffer playout unload structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100BufferPlayoutUnloadDef( + tPOCT6100_BUFFER_UNLOAD f_pBufferUnload ) +{ + f_pBufferUnload->ulBufferIndex = cOCT6100_INVALID_VALUE; + + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100BufferPlayoutUnload( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_BUFFER_UNLOAD f_pBufferUnload ) +{ + 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 = Oct6100BufferUnloadSer( f_pApiInstance, f_pBufferUnload, TRUE ); + } + 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: Oct6100BufferPlayoutAdd + +Description: This function adds a buffer to a port's playout list on the + selected 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_pBufferPlayoutAdd Pointer to buffer playout add structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100BufferPlayoutAddDef( + tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd ) +{ + f_pBufferPlayoutAdd->ulChannelHndl = cOCT6100_INVALID_HANDLE; + f_pBufferPlayoutAdd->ulBufferIndex = cOCT6100_INVALID_VALUE; + + f_pBufferPlayoutAdd->ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; + f_pBufferPlayoutAdd->ulMixingMode = cOCT6100_MIXING_MINUS_6_DB; + f_pBufferPlayoutAdd->lGainDb = 0; + + f_pBufferPlayoutAdd->fRepeat = FALSE; + f_pBufferPlayoutAdd->ulRepeatCount = cOCT6100_REPEAT_INFINITELY; + + f_pBufferPlayoutAdd->ulDuration = cOCT6100_INVALID_VALUE; + + f_pBufferPlayoutAdd->ulBufferLength = cOCT6100_AUTO_SELECT; + + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100BufferPlayoutAdd( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd ) +{ + 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 = Oct6100BufferPlayoutAddSer( f_pApiInstance, f_pBufferPlayoutAdd ); + } + 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: Oct6100BufferPlayoutStart + +Description: This function enables playout of the specified buffer on the + requested 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_pBufferPlayoutStart Pointer to buffer playout start structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100BufferPlayoutStartDef( + tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart ) +{ + f_pBufferPlayoutStart->ulChannelHndl = cOCT6100_INVALID_HANDLE; + f_pBufferPlayoutStart->ulPlayoutPort = cOCT6100_CHANNEL_PORT_ROUT; + f_pBufferPlayoutStart->fNotifyOnPlayoutStop = FALSE; + f_pBufferPlayoutStart->ulUserEventId = cOCT6100_INVALID_VALUE; + f_pBufferPlayoutStart->fAllowStartWhileActive = FALSE; + + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100BufferPlayoutStart( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart ) +{ + 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 = Oct6100BufferPlayoutStartSer( f_pApiInstance, f_pBufferPlayoutStart, cOCT6100_BUFFER_PLAYOUT_EVENT_STOP ); + } + 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: 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. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +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; +} + +UINT32 Oct6100BufferPlayoutStop( + tPOCT6100_INSTANCE_API f_pApiInstance, + tPOCT6100_BUFFER_PLAYOUT_STOP f_pBufferPlayoutStop ) +{ + 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 = Oct6100BufferPlayoutStopSer( f_pApiInstance, f_pBufferPlayoutStop ); + } + 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: 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. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +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. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +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: Oct6100BufferLoadSer + +Description: Loads a buffer 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_pBufferLoad Pointer to buffer configuration structure. The handle + identifying the buffer in all future function calls is + returned in this structure. + +f_fReserveListStruct Flag indicating if a list structure should be reserved + or if the structure has been reserved before. If this + is set, the f_ulBufIndex variable must also be set. + +f_ulBufIndex If the f_fReserveListStruct flag is set, this index + will identify the buffer playout list structure + that must be used to load the specified buffer. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100BufferLoadSer( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_BUFFER_LOAD f_pBufferLoad, + IN BOOL f_fReserveListStruct, + IN UINT32 f_ulBufIndex ) +{ + UINT32 ulBufferIndex; + UINT32 ulBufferBase; + UINT32 ulResult; + + /* Check the user's configuration of the buffer for errors. */ + ulResult = Oct6100ApiCheckBufferParams( f_pApiInstance, f_pBufferLoad, TRUE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Reserve all resources needed by the buffer. */ + ulResult = Oct6100ApiReserveBufferResources( f_pApiInstance, f_pBufferLoad, f_fReserveListStruct, f_ulBufIndex, &ulBufferIndex, &ulBufferBase ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Write the buffer in external memory. */ + ulResult = Oct6100ApiWriteBufferInMemory( f_pApiInstance, ulBufferBase, f_pBufferLoad->ulBufferSize, f_pBufferLoad->pbyBufferPattern ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Update the new buffer's entry in the buffer list. */ + ulResult = Oct6100ApiUpdateBufferEntry( f_pApiInstance, f_pBufferLoad, ulBufferIndex, ulBufferBase ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100BufferLoadBlockInitSer + +Description: Reserve resources for loading a buffer into 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_pBufferLoadBlockInit Pointer to buffer configuration structure. The + handle identifying the buffer in all future + function calls is returned in this structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100BufferLoadBlockInitSer( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_BUFFER_LOAD_BLOCK_INIT f_pBufferLoadBlockInit ) +{ + UINT32 ulBufferIndex; + UINT32 ulBufferBase; + UINT32 ulResult; + tOCT6100_BUFFER_LOAD BufferLoad; + + Oct6100BufferPlayoutLoadDef( &BufferLoad ); + + /* Not to replicate the code, we use the BufferLoad functions directly. */ + BufferLoad.pulBufferIndex = f_pBufferLoadBlockInit->pulBufferIndex; + BufferLoad.pulPlayoutFreeMemSize = f_pBufferLoadBlockInit->pulPlayoutFreeMemSize; + BufferLoad.ulBufferPcmLaw = f_pBufferLoadBlockInit->ulBufferPcmLaw; + BufferLoad.ulBufferSize = f_pBufferLoadBlockInit->ulBufferSize; + BufferLoad.pbyBufferPattern = NULL; /* Must not check this for now */ + + /* Check the user's configuration of the buffer for errors, but do */ + /* not check if the buffer pointer is NULL. It is NULL for sure! */ + ulResult = Oct6100ApiCheckBufferParams( f_pApiInstance, &BufferLoad, FALSE ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Reserve all resources needed by the buffer. */ + ulResult = Oct6100ApiReserveBufferResources( f_pApiInstance, &BufferLoad, TRUE, cOCT6100_INVALID_INDEX, &ulBufferIndex, &ulBufferBase ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Update the new buffer's entry in the buffer list. */ + ulResult = Oct6100ApiUpdateBufferEntry( f_pApiInstance, &BufferLoad, ulBufferIndex, ulBufferBase ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100BufferLoadBlockSer + +Description: Loads a buffer in external memory using blocks. + +------------------------------------------------------------------------------- +| 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_pBufferLoadBlock Pointer to buffer block to be loaded into external + memory descriptor. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100BufferLoadBlockSer( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock ) +{ + UINT32 ulBufferBase; + UINT32 ulResult; + + /* Check the user's configuration for errors. */ + ulResult = Oct6100ApiCheckBufferLoadBlockParams( f_pApiInstance, f_pBufferLoadBlock, &ulBufferBase ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Write the buffer in external memory at the appropriate offset - must do some pointer arithmetic. */ + ulResult = Oct6100ApiWriteBufferInMemory( f_pApiInstance, ulBufferBase + f_pBufferLoadBlock->ulBlockOffset, + f_pBufferLoadBlock->ulBlockLength, f_pBufferLoadBlock->pbyBufferPattern + f_pBufferLoadBlock->ulBlockOffset ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckBufferParams + +Description: Checks the user's buffer playout load 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_pBufferLoad Pointer to buffer configuration structure. +f_fCheckBufferPtr Check if the buffer pointer is NULL or not. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiCheckBufferParams( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_BUFFER_LOAD f_pBufferLoad, + IN BOOL f_fCheckBufferPtr ) +{ + /* Check for errors. */ + if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers == 0 ) + return cOCT6100_ERR_BUFFER_PLAYOUT_DISABLED; + + if ( f_pApiInstance->pSharedInfo->ImageInfo.fBufferPlayout == FALSE ) + return cOCT6100_ERR_NOT_SUPPORTED_BUFFER_PLAYOUT; + + if ( f_pBufferLoad->pulBufferIndex == NULL ) + return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_INDEX; + + if( f_fCheckBufferPtr ) + { + if ( f_pBufferLoad->pbyBufferPattern == NULL ) + return cOCT6100_ERR_BUFFER_PLAYOUT_PATTERN; + } + + if ( f_pBufferLoad->ulBufferSize < cOCT6100_MINIMUM_BUFFER_SIZE ) + return cOCT6100_ERR_BUFFER_PLAYOUT_TOO_SMALL; + + if ( ( f_pBufferLoad->ulBufferSize % cOCT6100_BUFFER_SIZE_GRANULARITY ) != 0 ) + return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_SIZE; + + if ( f_pBufferLoad->ulBufferPcmLaw != cOCT6100_PCM_U_LAW && + f_pBufferLoad->ulBufferPcmLaw != cOCT6100_PCM_A_LAW ) + return cOCT6100_ERR_BUFFER_PLAYOUT_PCM_LAW; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckBufferLoadBlockParams + +Description: Checks the user's buffer playout load block 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_pBufferLoadBlock Pointer to buffer block descriptor. +f_pulBufferBase Pointer to the base address of the buffer in external + memory. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiCheckBufferLoadBlockParams( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_BUFFER_LOAD_BLOCK f_pBufferLoadBlock, + OUT PUINT32 f_pulBufferBase ) +{ + /* Check for errors. */ + tPOCT6100_API_BUFFER pBufEntry; + + if ( f_pBufferLoadBlock->ulBufferIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers ) + return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_INDEX; + + mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufEntry, f_pBufferLoadBlock->ulBufferIndex ) + + if ( pBufEntry->fReserved != TRUE ) + return cOCT6100_ERR_BUFFER_PLAYOUT_NOT_OPEN; + + if ( ( f_pBufferLoadBlock->ulBlockLength % 2 ) != 0 ) + return cOCT6100_ERR_BUFFER_PLAYOUT_BLOCK_LENGTH_INVALID; + + if ( ( f_pBufferLoadBlock->ulBlockOffset % 2 ) != 0 ) + return cOCT6100_ERR_BUFFER_PLAYOUT_BLOCK_OFFSET_INVALID; + + if ( f_pBufferLoadBlock->pbyBufferPattern == NULL ) + return cOCT6100_ERR_BUFFER_PLAYOUT_PATTERN; + + /* Check boundaries */ + if ( ( f_pBufferLoadBlock->ulBlockLength + f_pBufferLoadBlock->ulBlockOffset ) > pBufEntry->ulBufferSize ) + return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_SIZE; + + *f_pulBufferBase = pBufEntry->ulBufferBase; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReserveBufferResources + +Description: Reserves all resources needed for the new 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_pBufferLoad Pointer to buffer configuration structure. + +f_fReserveListStruct Flag indicating if a list structure should be reserved + or if the structure has been reserved before. + +f_ulBufIndex If the f_fReserveListStruct flag is set, this index + will identifying the buffer playout list structure + that must be used to load the specified buffer. + +f_pulBufferIndex Allocated entry in buffer playout list. + +f_pulBufferBase Allocated external memory block for the buffer. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiReserveBufferResources( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_BUFFER_LOAD f_pBufferLoad, + IN BOOL f_fReserveListStruct, + IN UINT32 f_ulBufIndex, + OUT PUINT32 f_pulBufferIndex, + OUT PUINT32 f_pulBufferBase ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + UINT32 ulResult = cOCT6100_ERR_OK; + UINT32 ulTempVar; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Reserve an entry in the buffer list. */ + if ( f_fReserveListStruct == TRUE ) + { + ulResult = Oct6100ApiReserveBufPlayoutListEntry( f_pApiInstance, f_pulBufferIndex ); + } + else + { + *f_pulBufferIndex = f_ulBufIndex; + } + if ( ulResult == cOCT6100_ERR_OK ) + { + /* Find a free block to store the buffer. */ + ulResult = Oct6100ApiReserveBufferPlayoutMemory( f_pApiInstance, f_pBufferLoad->ulBufferSize, f_pulBufferBase ); + if ( ulResult != cOCT6100_ERR_OK ) + { + /* Release the list entry. */ + if ( f_fReserveListStruct == TRUE ) + { + ulTempVar = Oct6100ApiReleaseBufPlayoutListEntry( f_pApiInstance, *f_pulBufferIndex ); + if ( ulTempVar != cOCT6100_ERR_OK ) + return ulTempVar; + } + } + } + + return ulResult; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiWriteBufferInMemory + +Description: Writes the buffer 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_ulBufferBase Allocated external memory address for the buffer. + +f_ulBufferLength Length in bytes of the buffer to be copied in memory. + +f_pbyBuffer Address where the buffer should be copied from. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiWriteBufferInMemory( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT32 f_ulBufferBase, + IN UINT32 f_ulBufferLength, + IN PUINT8 f_pbyBuffer ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tOCT6100_WRITE_BURST_PARAMS BurstParams; + tOCT6100_WRITE_PARAMS WriteParams; + UINT32 ulResult; + UINT32 ulNumWrites; + PUINT16 pusSuperArray; + PUINT8 pbyPlayoutBuffer; + UINT32 ulByteCount = 0; + 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; + + WriteParams.pProcessContext = f_pApiInstance->pProcessContext; + + WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + + /* Write the buffer in external memory. */ + ulNumWrites = f_ulBufferLength / 2; + + BurstParams.ulWriteAddress = f_ulBufferBase; + BurstParams.pusWriteData = pSharedInfo->MiscVars.ausSuperArray; + + pusSuperArray = pSharedInfo->MiscVars.ausSuperArray; + pbyPlayoutBuffer = f_pbyBuffer; + + /* Check if we can maximize the bandwidth through the CPU port. */ + if ( f_pApiInstance->pSharedInfo->ChipStats.usNumberChannels == 0 ) + { + WriteParams.ulWriteAddress = 0x234; + WriteParams.usWriteData = 0x08ff; + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + 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 )(( pbyPlayoutBuffer [ ulByteCount++ ]) << 8); + pusSuperArray[ i ] |= ( UINT16 )pbyPlayoutBuffer [ ulByteCount++ ]; + } + + mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ) + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + BurstParams.ulWriteAddress += 2 * BurstParams.ulWriteLength; + ulNumWrites -= BurstParams.ulWriteLength; + + } + + /* Make sure we revert back the changes made to the CPU bandwidth register. */ + if ( f_pApiInstance->pSharedInfo->ChipStats.usNumberChannels == 0 ) + { + WriteParams.ulWriteAddress = 0x234; + WriteParams.usWriteData = 0x0804; + mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiUpdateBufferEntry + +Description: Updates the new buffer's entry in the buffer playout 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_pBufferLoad Pointer to buffer configuration structure. +f_ulBufferIndex Allocated entry in buffer playout list. +f_ulBufferBase Allocated external memory block for the buffer. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiUpdateBufferEntry( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_BUFFER_LOAD f_pBufferLoad, + IN UINT32 f_ulBufferIndex, + IN UINT32 f_ulBufferBase ) +{ + tPOCT6100_API_BUFFER pBufEntry; + UINT32 ulBufferSize = f_pBufferLoad->ulBufferSize; + + /* Obtain a pointer to the new buffer's list entry. */ + mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufEntry, f_ulBufferIndex ) + + /* Copy the buffer's configuration and allocated resources. */ + pBufEntry->ulBufferSize = f_pBufferLoad->ulBufferSize; + pBufEntry->byBufferPcmLaw = (UINT8)( f_pBufferLoad->ulBufferPcmLaw & 0xFF ); + pBufEntry->ulBufferBase = f_ulBufferBase; + + /* Update the entries flags. */ + pBufEntry->usDependencyCnt = 0; + + /* Mark the buffer as opened. */ + pBufEntry->fReserved = TRUE; + + /* Increment the number of buffer loaded into the chip.*/ + f_pApiInstance->pSharedInfo->ChipStats.usNumberPlayoutBuffers++; + + /* Refresh the amount of memory used by buffer playout. */ + + /* Reserved size is divisible by 64. */ + if ( ulBufferSize % 64 ) + ulBufferSize = ulBufferSize + ( 64 - ( ulBufferSize % 64 ) ); + f_pApiInstance->pSharedInfo->ChipStats.ulPlayoutMemUsed += ulBufferSize; + + /* Return the buffer index to the user. */ + *f_pBufferLoad->pulBufferIndex = f_ulBufferIndex; + + /* Return the amount of free memory left in the chip. */ + /* Note that this value does not give the "fragmentation" state of the available memory. */ + /* This value only gives the amount of free memory */ + if( f_pBufferLoad->pulPlayoutFreeMemSize ) + *f_pBufferLoad->pulPlayoutFreeMemSize = ( f_pApiInstance->pSharedInfo->MiscVars.ulTotalMemSize - ( f_pApiInstance->pSharedInfo->MemoryMap.ulFreeMemBaseAddress - cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ) ) - ( f_pApiInstance->pSharedInfo->ChipStats.ulPlayoutMemUsed ); + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100BufferUnloadSer + +Description: Unloads a buffer from 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_pBufferUnload Pointer to buffer unload structure. +f_fReleaseListStruct Whether to release the buffer playout list structure + or not. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100BufferUnloadSer( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_BUFFER_UNLOAD f_pBufferUnload, + IN BOOL f_fReleaseListStruct ) +{ + UINT32 ulBufferIndex; + UINT32 ulBufferBase; + UINT32 ulResult; + + /* Verify that all the parameters given match the state of the API. */ + ulResult = Oct6100ApiAssertBufferParams( f_pApiInstance, f_pBufferUnload, &ulBufferIndex, &ulBufferBase ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Release all resources associated to the unloaded buffer. */ + ulResult = Oct6100ApiReleaseBufferResources( f_pApiInstance, ulBufferIndex, ulBufferBase, f_fReleaseListStruct ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiAssertBufferParams + +Description: Checks the buffer playout unload 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_pBufferUnload Pointer to buffer unload structure. +f_pulBufferIndex Pointer to the index of the buffer in the API's buffers list. +f_pulBufferBase Pointer to the base address of the buffer in external memory. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiAssertBufferParams( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_BUFFER_UNLOAD f_pBufferUnload, + OUT PUINT32 f_pulBufferIndex, + OUT PUINT32 f_pulBufferBase ) +{ + tPOCT6100_API_BUFFER pBufEntry; + + *f_pulBufferIndex = f_pBufferUnload->ulBufferIndex; + + if ( *f_pulBufferIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers ) + return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_INDEX; + + mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufEntry, *f_pulBufferIndex ) + + /* Check for errors. */ + if ( pBufEntry->fReserved != TRUE ) + return cOCT6100_ERR_BUFFER_PLAYOUT_NOT_OPEN; + if ( pBufEntry->usDependencyCnt != 0 ) + return cOCT6100_ERR_BUFFER_PLAYOUT_ACTIVE_DEPENDENCIES; + + /* Return all info needed to invalidate buffer. */ + *f_pulBufferBase = pBufEntry->ulBufferBase; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReleaseBufferResources + +Description: Release resources needed by the 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_ulBufferIndex Allocated entry in buffer playout list. +f_ulBufferBase Allocated external memory block for the buffer. +f_fReleaseListStruct Free the list structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiReleaseBufferResources( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT32 f_ulBufferIndex, + IN UINT32 f_ulBufferBase, + IN BOOL f_fReleaseListStruct ) +{ + tPOCT6100_SHARED_INFO pSharedInfo; + tPOCT6100_API_BUFFER pBufEntry; + UINT32 ulResult; + UINT32 ulBufferSize; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + /* Free the external memory reserved for the buffer. */ + ulResult = Oct6100ApiReleaseBufferPlayoutMemory( f_pApiInstance, f_ulBufferBase ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_3E; + + /* Release the entry from the buffer list. */ + if ( f_fReleaseListStruct == TRUE ) + ulResult = Oct6100ApiReleaseBufPlayoutListEntry( f_pApiInstance, f_ulBufferIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufEntry, f_ulBufferIndex ); + + /* Save buffer size before releasing that entry, will be needed to calculate the amount of */ + /* free memory left for the user. */ + ulBufferSize = pBufEntry->ulBufferSize; + + /* Flag the buffer entry as free. */ + pBufEntry->fReserved = FALSE; + + /* Decrement the number of buffer loaded into the chip. */ + f_pApiInstance->pSharedInfo->ChipStats.usNumberPlayoutBuffers--; + + /* Refresh the amount of memory used by buffer playout. */ + /* Reserved size is divisible by 64. */ + if ( ulBufferSize % 64 ) + ulBufferSize = ulBufferSize + ( 64 - ( ulBufferSize % 64 ) ); + f_pApiInstance->pSharedInfo->ChipStats.ulPlayoutMemUsed -= ulBufferSize; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100BufferPlayoutAddSer + +Description: This function adds a buffer to a channel buffer 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_pBufferPlayoutAdd Pointer to buffer playout add structure. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100BufferPlayoutAddSer( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd ) +{ + UINT32 ulBufferIndex; + UINT32 ulChannelIndex; + UINT32 ulResult; + + /* Check the user's configuration of the buffer for errors. */ + ulResult = Oct6100ApiCheckPlayoutAddParams( f_pApiInstance, f_pBufferPlayoutAdd, &ulChannelIndex, &ulBufferIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Write to all resources needed to activate buffer playout. */ + ulResult = Oct6100ApiWriteBufferAddStructs( f_pApiInstance, f_pBufferPlayoutAdd, ulChannelIndex, ulBufferIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckPlayoutAddParams + +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_pBufferPlayoutAdd Pointer to buffer playout add structure. +f_pulChannelIndex Pointer to the channel index of the selected channel. +f_pulBufferIndex Pointer to the buffer index within the API's buffer list. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiCheckPlayoutAddParams( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd, + OUT PUINT32 f_pulChannelIndex, + OUT PUINT32 f_pulBufferIndex ) +{ + tPOCT6100_API_BUFFER pBufferEntry; + tPOCT6100_API_CHANNEL pEchoChannel; + UINT32 ulEntryOpenCnt; + + /* Check for errors. */ + if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers == 0 ) + return cOCT6100_ERR_BUFFER_PLAYOUT_DISABLED; + + if ( f_pBufferPlayoutAdd->ulChannelHndl == cOCT6100_INVALID_HANDLE ) + return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; + + if ( f_pBufferPlayoutAdd->ulPlayoutPort != cOCT6100_CHANNEL_PORT_ROUT && + f_pBufferPlayoutAdd->ulPlayoutPort != cOCT6100_CHANNEL_PORT_SOUT ) + return cOCT6100_ERR_BUFFER_PLAYOUT_PLAYOUT_PORT; + + if ( f_pBufferPlayoutAdd->fRepeat != TRUE && f_pBufferPlayoutAdd->fRepeat != FALSE ) + return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_REPEAT; + + if ( f_pBufferPlayoutAdd->fRepeat == TRUE ) + { + if ( f_pBufferPlayoutAdd->ulRepeatCount != cOCT6100_REPEAT_INFINITELY ) + { + if ( f_pBufferPlayoutAdd->ulRepeatCount == 0x0 + || f_pBufferPlayoutAdd->ulRepeatCount > cOCT6100_REPEAT_MAX) + { + return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_REPEAT_COUNT; + } + } + } + + if ( f_pBufferPlayoutAdd->ulMixingMode != cOCT6100_MIXING_0_DB && + f_pBufferPlayoutAdd->ulMixingMode != cOCT6100_MIXING_MINUS_6_DB && + f_pBufferPlayoutAdd->ulMixingMode != cOCT6100_MIXING_MINUS_12_DB && + f_pBufferPlayoutAdd->ulMixingMode != cOCT6100_MIXING_MUTE ) + return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_MIXING; + + if ( ( f_pBufferPlayoutAdd->lGainDb < -24 ) + || ( f_pBufferPlayoutAdd->lGainDb > 24 ) ) + return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_GAIN_DB; + + /*=====================================================================*/ + /* Check the channel handle. */ + + if ( (f_pBufferPlayoutAdd->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; + + *f_pulChannelIndex = f_pBufferPlayoutAdd->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_pBufferPlayoutAdd->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; + + /* Check if repeat flag has been used for this port. */ + if ( ( ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) && ( pEchoChannel->fRinBufPlayoutRepeatUsed == TRUE ) ) + || ( ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pEchoChannel->fSoutBufPlayoutRepeatUsed == TRUE ) ) ) + return cOCT6100_ERR_BUFFER_PLAYOUT_REPEAT_USED; + + /*=====================================================================*/ + + /*=====================================================================*/ + /* Check the buffer information. */ + + *f_pulBufferIndex = f_pBufferPlayoutAdd->ulBufferIndex; + if ( *f_pulBufferIndex >= f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers ) + return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_INDEX; + + mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufferEntry, *f_pulBufferIndex ) + + if ( pBufferEntry->fReserved != TRUE ) + return cOCT6100_ERR_BUFFER_PLAYOUT_NOT_OPEN; + + /* Check if the play length is not larger then the currently uploaded buffer. */ + if ( ( f_pBufferPlayoutAdd->ulBufferLength > pBufferEntry->ulBufferSize ) && + ( f_pBufferPlayoutAdd->ulBufferLength != cOCT6100_AUTO_SELECT ) ) + return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_SIZE; + + if( f_pBufferPlayoutAdd->ulBufferLength != cOCT6100_AUTO_SELECT ) + { + if ( f_pBufferPlayoutAdd->ulBufferLength < cOCT6100_MINIMUM_BUFFER_SIZE ) + return cOCT6100_ERR_BUFFER_PLAYOUT_TOO_SMALL; + + if ( ( f_pBufferPlayoutAdd->ulBufferLength % cOCT6100_BUFFER_SIZE_GRANULARITY ) != 0 ) + return cOCT6100_ERR_BUFFER_PLAYOUT_BUF_SIZE; + } + + /*=====================================================================*/ + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiWriteBufferAddStructs + +Description: Write the buffer playout event in the channel's port playout + circular 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_pBufferPlayoutAdd Pointer to buffer playout add structure. +f_ulChannelIndex Index of the channel on which the buffer is to be added. +f_ulBufferIndex Index of the buffer structure within the API's buffer list. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiWriteBufferAddStructs( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_BUFFER_PLAYOUT_ADD f_pBufferPlayoutAdd, + IN UINT32 f_ulChannelIndex, + IN UINT32 f_ulBufferIndex ) +{ + tPOCT6100_API_BUFFER pBufferEntry; + tPOCT6100_API_CHANNEL pEchoChannel; + tPOCT6100_SHARED_INFO pSharedInfo; + tOCT6100_READ_PARAMS ReadParams; + UINT32 ulResult; + UINT32 ulTempData; + UINT32 ulEventBuffer; + + UINT32 ulReadPtrBytesOfst; + UINT32 ulReadPtrBitOfst; + UINT32 ulReadPtrFieldSize; + + UINT32 ulWritePtrBytesOfst; + UINT32 ulWritePtrBitOfst; + UINT32 ulWritePtrFieldSize; + + UINT32 ulWritePtr; + UINT32 ulReadPtr; + + UINT32 ulPlayoutBaseAddress; + UINT32 ulAddress; + UINT32 ulEventIndex; + UINT32 ulMask; + + UINT32 ulRepeatCount = 0; + BOOL fRepeatCountSet = FALSE; + UINT32 ulDurationModulo = 0; + UINT32 ulEventsToCreate = 1; + UINT32 ulBufferDurationMs; + + UINT32 ulBufferLength; + UINT16 usTempData = 0; + + UINT16 usReadData; + UINT32 ulChipWritePtr; + UINT32 ulReadData; + UINT32 ulLoopCnt = 0; + BOOL fStillPlaying = TRUE; + BOOL fCheckHardStop = FALSE; + BOOL fOldBufferPlayoutVersion = FALSE; + + UINT32 aulWaitTime[ 2 ]; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChannel, f_ulChannelIndex ); + mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufferEntry, f_ulBufferIndex ); + + /* Select the buffer of interest. */ + if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainRinPlayoutMemOfst; + ulWritePtr = pEchoChannel->ulRinBufWritePtr; + + 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 /* f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ + { + ulEventBuffer = pSharedInfo->MemoryMap.ulChanMainSoutPlayoutMemOfst; + ulWritePtr = pEchoChannel->ulSoutBufWritePtr; + + 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; + } + + /*=======================================================================*/ + /* Calculate the repeat count. */ + + /* The buffer length is either the total buffer size or the value specified by the user */ + if ( f_pBufferPlayoutAdd->ulBufferLength == cOCT6100_AUTO_SELECT ) + { + ulBufferLength = pBufferEntry->ulBufferSize; + } + else + { + ulBufferLength = f_pBufferPlayoutAdd->ulBufferLength; + } + + if ( f_pBufferPlayoutAdd->ulDuration != cOCT6100_INVALID_VALUE ) + { + /* With duration and buffer length, we can find the number of times we must repeat playing this buffer. */ + ulBufferDurationMs = ulBufferLength / cOCT6100_SAMPLES_PER_MS; + ulRepeatCount = f_pBufferPlayoutAdd->ulDuration / ulBufferDurationMs; + fRepeatCountSet = TRUE; + + /* Check if buffer is larger then asked duration. */ + if ( ulRepeatCount != 0x0 ) + { + /* We might have to create more then 1 event to accomodate for the repeat-max limit. */ + ulEventsToCreate = ( ulRepeatCount / cOCT6100_REPEAT_MAX ) + 1; + } + else + { + /* No repeat event. Maybe only the duration modulo! */ + ulEventsToCreate = 0x0; + } + + /* Check if must create a second event for a buffer that cannot be played completely. */ + ulDurationModulo = f_pBufferPlayoutAdd->ulDuration % ulBufferDurationMs; + if ( ulDurationModulo != 0x0 ) + { + ulDurationModulo *= cOCT6100_SAMPLES_PER_MS; + if ( ulDurationModulo / cOCT6100_BUFFER_SIZE_GRANULARITY ) + { + /* Round the modulo to be on a buffer size granularity. */ + /* This will round down. */ + ulDurationModulo = ( ulDurationModulo / cOCT6100_BUFFER_SIZE_GRANULARITY ) * cOCT6100_BUFFER_SIZE_GRANULARITY; + + /* If the event about to be created is smaller then the minimum buffer size, */ + /* round up to the minimum required by the hardware. */ + if ( ulDurationModulo < cOCT6100_MINIMUM_BUFFER_SIZE ) + ulDurationModulo = cOCT6100_MINIMUM_BUFFER_SIZE; + ulEventsToCreate++; + } + else + { + /* The modulo is too small to be played. Skip. */ + ulDurationModulo = 0; + } + } + } + else if ( f_pBufferPlayoutAdd->fRepeat == TRUE + && f_pBufferPlayoutAdd->ulRepeatCount != cOCT6100_REPEAT_INFINITELY ) + { + /* The repeat count is set directly from the user. */ + ulRepeatCount = f_pBufferPlayoutAdd->ulRepeatCount; + fRepeatCountSet = TRUE; + } + + /*=======================================================================*/ + + /* Set the playout feature base address. */ + ulPlayoutBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_ulChannelIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; + + /* Read the read pointer. */ + ulAddress = ulPlayoutBaseAddress + ulReadPtrBytesOfst; + + /* Must read in memory directly since this value is changed by hardware. */ + ulResult = Oct6100ApiReadDword( f_pApiInstance, ulAddress, &ulTempData ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + mOCT6100_CREATE_FEATURE_MASK( ulReadPtrFieldSize, ulReadPtrBitOfst, &ulMask ); + + /* Store the read pointer. */ + ulReadPtr = ( ulTempData & ulMask ) >> ulReadPtrBitOfst; + + /* Compare the pointers... Are they different? If so, there is something already in the list. */ + if ( ulReadPtr != ulWritePtr ) + { + /* Check if there is enough room for the playout events. */ + if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == TRUE ) + && ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == TRUE ) ) + { + /* 127 or 31 events image. */ + if ( (UINT8)( ( ulWritePtr - ulReadPtr ) & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ) ) >= ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - (UINT8)ulEventsToCreate ) ) + fCheckHardStop = TRUE; + } + else + { + /* Old 31 events image. */ + if ( ( ( ulWritePtr - ulReadPtr ) & 0x1F ) >= ( 0x20 - ulEventsToCreate ) ) + fCheckHardStop = TRUE; + + fOldBufferPlayoutVersion = TRUE; + } + + if ( fCheckHardStop == TRUE ) + { + /* Ok. From what was read, the list is full. But we might still have a chance if the hard-stop */ + /* version was used. In this case, some of the buffers in the list might */ + /* become free in a couple of milliseconds, so try to wait for this. */ + + if ( ( ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) && ( pEchoChannel->fRinHardStop == TRUE ) ) + || ( ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pEchoChannel->fSoutHardStop == TRUE ) ) ) + { + /* Read the 'chip' write pointer in the hardware. */ + ReadParams.pProcessContext = f_pApiInstance->pProcessContext; + + ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + ReadParams.pusReadData = &usReadData; + ReadParams.ulReadAddress = ulPlayoutBaseAddress + ulReadPtrBytesOfst; + + /* 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. */ + ulChipWritePtr = ( ulReadData & ulMask ) >> ulWritePtrBitOfst; + + /* Optimize this access by only reading the word we are interested in. */ + if ( ulReadPtrBitOfst < 16 ) + ReadParams.ulReadAddress += 2; + + while( fStillPlaying == TRUE ) + { + /* Read the read pointer until equals to the write pointer. */ + 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 == ulChipWritePtr ) + break; + + ulLoopCnt++; + if ( ulLoopCnt > cOCT6100_MAX_LOOP ) + { + return cOCT6100_ERR_FATAL_E7; + } + + aulWaitTime[ 0 ] = 100; + aulWaitTime[ 1 ] = 0; + ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + + /* Clear hard-stop flag. */ + if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + /* No hard stop for now. */ + pEchoChannel->fRinHardStop = FALSE; + } + else /* if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) */ + { + /* No hard stop for now. */ + pEchoChannel->fSoutHardStop = FALSE; + } + + /* Now check again if the event can be added... */ + if ( fOldBufferPlayoutVersion == FALSE ) + { + if ( (UINT8)( ( ulWritePtr - ulReadPtr ) & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ) ) >= ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - (UINT8)ulEventsToCreate ) ) + return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_EVENT_BUF_FULL; + } + else /* if ( fOldBufferPlayoutVersion == TRUE ) */ + { + /* Old 31 events image. */ + if ( ( ( ulWritePtr - ulReadPtr ) & 0x1F ) >= ( 0x20 - ulEventsToCreate ) ) + return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_EVENT_BUF_FULL; + } + + /* Good, at least another buffer can be added! Add the buffer to the list. */ + } + else + { + /* Well the list is full! */ + return cOCT6100_ERR_BUFFER_PLAYOUT_ADD_EVENT_BUF_FULL; + } + } + } + + /*=======================================================================*/ + /* Write the events. */ + + for ( ulEventIndex = 0; ulEventIndex < ulEventsToCreate; ulEventIndex ++ ) + { + /* 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_ulChannelIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + ulEventBuffer + (cOCT6100_PLAYOUT_EVENT_MEM_SIZE * (ulWritePtr & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ))); + } + else + { + /* Old 31 events image. */ + ulAddress = pSharedInfo->MemoryMap.ulChanMainMemBase + (f_ulChannelIndex * pSharedInfo->MemoryMap.ulChanMainMemSize ) + ulEventBuffer + (cOCT6100_PLAYOUT_EVENT_MEM_SIZE * (ulWritePtr & 0x1F)); + } + + /* EVENT BASE + 0 */ + /* Make sure the xIS and xHS bits are cleared. */ + ulTempData = 0; + + /* Set the repeat count. */ + if ( fRepeatCountSet == TRUE ) + { + if ( ( ulRepeatCount != 0x0 ) && ( ulRepeatCount <= cOCT6100_REPEAT_MAX ) ) + { + /* Use repeat count directly. */ + ulTempData |= ulRepeatCount; + + /* Will be used later when creating the duration modulo event. */ + ulRepeatCount = 0; + } + else if ( ulRepeatCount != 0x0 ) + { + /* Get ready for next event. */ + ulRepeatCount -= cOCT6100_REPEAT_MAX; + + /* Set maximum for this event. */ + ulTempData |= cOCT6100_REPEAT_MAX; + } + else + { + /* Duration modulo case. Nothing to set here. */ + } + } + else /* if ( fRepeatCountSet != TRUE ) */ + { + /* Repeat only once. */ + ulTempData |= 0x1; + } + + ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulAddress, ulTempData ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* EVENT BASE + 4 */ + /* Set the buffer base address and playout configuration. */ + ulAddress += 4; + ulTempData = pBufferEntry->ulBufferBase & 0x07FFFFFF; + + /* Set play indefinitely or loop N times. */ + if ( ( fRepeatCountSet == FALSE ) && ( f_pBufferPlayoutAdd->fRepeat == TRUE ) ) + { + /* Repeat indefinitely. */ + ulTempData |= 0x1 << cOCT6100_PLAYOUT_EVENT_REPEAT_OFFSET; + + if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) + pEchoChannel->fRinBufPlayoutRepeatUsed = TRUE; + else /* if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) */ + pEchoChannel->fSoutBufPlayoutRepeatUsed = TRUE; + } + + /* Use loop N times feature. */ + ulTempData |= 0x1 << cOCT6100_PLAYOUT_EVENT_LOOP_TIMES_OFFSET; + + /* Set the law.*/ + ulTempData |= ( pBufferEntry->byBufferPcmLaw << cOCT6100_PLAYOUT_EVENT_LAW_OFFSET ); + + /* Set the mixing configuration.*/ + ulTempData |= f_pBufferPlayoutAdd->ulMixingMode << cOCT6100_PLAYOUT_EVENT_MIX_OFFSET; + + ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulAddress, ulTempData ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + + /* EVENT BASE + 8 */ + /* Set the buffer size and playout gain. */ + ulAddress += 4; + + /* Check if we are setting the duration modulo. This would be the last event and this */ + /* event is of a very specific size. */ + if ( ( fRepeatCountSet == TRUE ) + && ( ulEventIndex == ( ulEventsToCreate - 1 ) ) + && ( ulDurationModulo != 0x0 ) ) + { + /* The duration modulo variable contains all that is needed here. */ + ulBufferLength = ulDurationModulo; + } + ulTempData = ulBufferLength; + + /* Adjust playout gain. */ + if ( f_pBufferPlayoutAdd->lGainDb != 0 ) + { + /* Convert the dB value into OctFloat format. */ + usTempData = Oct6100ApiDbAmpHalfToOctFloat( f_pBufferPlayoutAdd->lGainDb ); + ulTempData |= ( usTempData & 0xFF00 ) << 16; + } + else + { + ulTempData |= cOCT6100_PLAYOUT_GAIN; + } + + ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulAddress, ulTempData ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* EVENT BASE + 0xC */ + ulAddress += 4; + ulTempData = ( ulBufferLength - 1 ) & 0xFFFFFFC0; /* Must be multiple of 64 bytes */ + + /* Adjust playout gain. */ + if ( f_pBufferPlayoutAdd->lGainDb != 0 ) + { + ulTempData |= ( usTempData & 0xFF ) << 24; + } + + ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulAddress, ulTempData ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Next event. */ + ulWritePtr++; + } + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Increment the write pointer to make it point to the next empty entry. */ + + if ( f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + pEchoChannel->ulRinBufWritePtr = ( pEchoChannel->ulRinBufWritePtr + ulEventsToCreate ) & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ); + /* Remember that a buffer was added on the rin port. */ + pEchoChannel->fRinBufAdded = TRUE; + } + else /* f_pBufferPlayoutAdd->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ + { + pEchoChannel->ulSoutBufWritePtr = ( pEchoChannel->ulSoutBufWritePtr + ulEventsToCreate ) & ( pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents - 1 ); + /* Remember that a buffer was added on the sout port. */ + pEchoChannel->fSoutBufAdded = TRUE; + } + + /*=======================================================================*/ + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100BufferPlayoutStartSer + +Description: Starts 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_pBufferPlayoutStart Pointer to buffer playout start structure. + +f_ulPlayoutStopEventType Playout stop event type to be generated if required. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100BufferPlayoutStartSer( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart, + IN UINT32 f_ulPlayoutStopEventType ) +{ + UINT32 ulBufferIndex; + UINT32 ulChannelIndex; + BOOL fNotifyOnPlayoutStop; + UINT32 ulUserEventId; + BOOL fAddToCurrentlyPlayingList; + UINT32 ulResult; + + /* Check the user's configuration of the buffer for errors. */ + ulResult = Oct6100ApiCheckPlayoutStartParams( f_pApiInstance, f_pBufferPlayoutStart, &ulChannelIndex, &ulBufferIndex, &fNotifyOnPlayoutStop, &ulUserEventId, &fAddToCurrentlyPlayingList ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Write to all resources needed to activate buffer playout. */ + ulResult = Oct6100ApiWriteChanPlayoutStructs( f_pApiInstance, f_pBufferPlayoutStart, ulChannelIndex, ulBufferIndex, fNotifyOnPlayoutStop, ulUserEventId, fAddToCurrentlyPlayingList, f_ulPlayoutStopEventType ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiCheckPlayoutStartParams + +Description: Check the validity of the channel and buffer requested. + Check the validity of the flags 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_pBufferPlayoutStart Pointer to buffer playout start structure. +f_pulChannelIndex Pointer to the channel index of the selected channel. +f_pulBufferIndex Pointer to the buffer index within the API's buffer list. +f_pfNotifyOnPlayoutStop Pointer to the notify on playout stop flag. +f_pulUserEventId Pointer to the user event id specified. +f_pfAllowStartIfActive Pointer to the add to currently playing list flag. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiCheckPlayoutStartParams( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN OUT tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart, + OUT PUINT32 f_pulChannelIndex, + OUT PUINT32 f_pulBufferIndex, + OUT PBOOL f_pfNotifyOnPlayoutStop, + OUT PUINT32 f_pulUserEventId, + OUT PBOOL f_pfAllowStartIfActive ) +{ + tPOCT6100_API_CHANNEL pEchoChannel; + UINT32 ulEntryOpenCnt; + + /* Check for errors. */ + if ( f_pApiInstance->pSharedInfo->ChipConfig.usMaxPlayoutBuffers == 0 ) + return cOCT6100_ERR_BUFFER_PLAYOUT_DISABLED; + + if ( f_pBufferPlayoutStart->ulChannelHndl == cOCT6100_INVALID_HANDLE ) + return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; + + if ( f_pBufferPlayoutStart->ulPlayoutPort != cOCT6100_CHANNEL_PORT_ROUT && + f_pBufferPlayoutStart->ulPlayoutPort != cOCT6100_CHANNEL_PORT_SOUT ) + return cOCT6100_ERR_BUFFER_PLAYOUT_PLAYOUT_PORT; + + if ( f_pBufferPlayoutStart->fNotifyOnPlayoutStop != FALSE + && f_pBufferPlayoutStart->fNotifyOnPlayoutStop != TRUE ) + return cOCT6100_ERR_BUFFER_PLAYOUT_NOTIFY_ON_STOP; + + if ( f_pBufferPlayoutStart->fAllowStartWhileActive != FALSE + && f_pBufferPlayoutStart->fAllowStartWhileActive != TRUE ) + return cOCT6100_ERR_BUFFER_PLAYOUT_ALLOW_ACTIVE; + + /*=====================================================================*/ + /* Check the channel handle. */ + + if ( (f_pBufferPlayoutStart->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) + return cOCT6100_ERR_BUFFER_PLAYOUT_CHANNEL_HANDLE_INVALID; + + *f_pulChannelIndex = f_pBufferPlayoutStart->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_pBufferPlayoutStart->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; + + /* The channel cannot be in POWER_DOWN or HT_FREEZE to start the playout. */ + if ( ( pEchoChannel->byEchoOperationMode == cOCT6100_ECHO_OP_MODE_POWER_DOWN ) + || ( pEchoChannel->byEchoOperationMode == cOCT6100_ECHO_OP_MODE_HT_FREEZE ) ) + return cOCT6100_ERR_BUFFER_PLAYOUT_ECHO_OP_MODE; + + /* The channel's NLP must be enabled for playout to occur. */ + if ( pEchoChannel->VqeConfig.fEnableNlp == FALSE ) + return cOCT6100_ERR_BUFFER_PLAYOUT_NLP_DISABLED; + + /*=====================================================================*/ + + /*=====================================================================*/ + /* Check if the user activated the buffer playout events. */ + + if ( f_pBufferPlayoutStart->fNotifyOnPlayoutStop == TRUE + && f_pApiInstance->pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize == 0 ) + return cOCT6100_ERR_BUFFER_PLAYOUT_EVENT_DISABLED; + + /*=====================================================================*/ + + /*=====================================================================*/ + /* Check if there is actually a buffer added in the list. */ + + if ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + if ( pEchoChannel->fRinBufAdded == FALSE ) + return cOCT6100_ERR_BUFFER_PLAYOUT_LIST_EMPTY; + } + else /* if ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) */ + { + if ( pEchoChannel->fSoutBufAdded == FALSE ) + return cOCT6100_ERR_BUFFER_PLAYOUT_LIST_EMPTY; + } + + /*=====================================================================*/ + + /* Return the requested information. */ + *f_pfNotifyOnPlayoutStop = f_pBufferPlayoutStart->fNotifyOnPlayoutStop; + *f_pulUserEventId = f_pBufferPlayoutStart->ulUserEventId; + *f_pfAllowStartIfActive = f_pBufferPlayoutStart->fAllowStartWhileActive; + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiWriteChanPlayoutStructs + +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_pBufferPlayoutStart Pointer to buffer playout start structure. +f_ulChannelIndex Index of the channel within the API's channel list. +f_ulBufferIndex Index of the buffer within the API's buffer list. +f_fNotifyOnPlayoutStop Flag for the notify on playout stop. +f_ulUserEventId User event id passed to the user when a playout event is generated. +f_fAllowStartIfActive Add to currently playing list flag. +f_ulPlayoutStopEventType Playout stop event type to be generated if required. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiWriteChanPlayoutStructs( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN tPOCT6100_BUFFER_PLAYOUT_START f_pBufferPlayoutStart, + IN UINT32 f_ulChannelIndex, + IN UINT32 f_ulBufferIndex, + IN BOOL f_fNotifyOnPlayoutStop, + IN UINT32 f_ulUserEventId, + IN BOOL f_fAllowStartIfActive, + IN UINT32 f_ulPlayoutStopEventType ) +{ + tPOCT6100_API_BUFFER pBufferEntry; + tPOCT6100_API_CHANNEL pEchoChannel; + tPOCT6100_SHARED_INFO pSharedInfo; + tOCT6100_READ_PARAMS ReadParams; + + UINT32 ulResult; + + UINT32 ulWritePtr; + UINT32 ulChipWritePtr; + PUINT32 pulSkipPtr; + UINT32 ulWritePtrBytesOfst; + UINT32 ulSkipPtrBytesOfst; + UINT32 ulWritePtrBitOfst; + UINT32 ulSkipPtrBitOfst; + UINT32 ulWritePtrFieldSize; + UINT32 ulSkipPtrFieldSize; + + UINT32 ulIgnoreBytesOfst; + UINT32 ulIgnoreBitOfst; + UINT32 ulIgnoreFieldSize; + + UINT32 ulHardSkipBytesOfst; + UINT32 ulHardSkipBitOfst; + UINT32 ulHardSkipFieldSize; + + UINT32 ulReadPtrBytesOfst; + UINT32 ulReadPtrBitOfst; + UINT32 ulReadPtrFieldSize; + + UINT32 ulPlayoutBaseAddress; + UINT32 ulAddress; + UINT32 ulTempData; + UINT32 ulMask; + UINT32 ulReadData; + UINT32 ulReadPtr; + UINT32 ulLoopCnt = 0; + + UINT16 usReadData; + + BOOL fBufferPlayoutStopDetected; + BOOL fWriteSkipPtr = FALSE; + BOOL fStillPlaying = TRUE; + + UINT32 aulWaitTime[ 2 ]; + + /* Obtain local pointer to shared portion of instance. */ + pSharedInfo = f_pApiInstance->pSharedInfo; + + mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pEchoChannel, f_ulChannelIndex ); + mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBufferEntry, f_ulBufferIndex ); + + /* First off, check for buffer playout events, if requested for this channel/port. */ + /* At the same time, if requested, check that the playout has stopped for this channel/port. */ + if ( ( ( pEchoChannel->fRinBufPlaying == TRUE ) + && ( ( pEchoChannel->fRinBufPlayoutNotifyOnStop == TRUE ) || ( f_fAllowStartIfActive == FALSE ) ) + && ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) ) + || ( ( ( pEchoChannel->fSoutBufPlaying == TRUE ) || ( f_fAllowStartIfActive == FALSE ) ) + && ( pEchoChannel->fSoutBufPlayoutNotifyOnStop == TRUE ) + && ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) ) ) + { + /* Buffer playout might still be going on for this channel/port. */ + ulResult = Oct6100BufferPlayoutCheckForSpecificEvent( f_pApiInstance, + f_ulChannelIndex, + f_pBufferPlayoutStart->ulPlayoutPort, + pEchoChannel->fRinBufPlayoutNotifyOnStop, + &fBufferPlayoutStopDetected ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Check if the user requested to only start if playout is over. Return an error if */ + /* buffer playout is still going on on this channel/port. */ + if ( ( f_fAllowStartIfActive == FALSE ) && ( fBufferPlayoutStopDetected == FALSE ) ) + { + /* No go! User should wait for the current list to stop, or call the */ + /* Oct6100BufferPlayoutStop function. */ + return cOCT6100_ERR_BUFFER_PLAYOUT_STILL_ACTIVE; + } + } + + /* Select the buffer of interest. */ + if ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + ulWritePtr = pEchoChannel->ulRinBufWritePtr; + pulSkipPtr = &pEchoChannel->ulRinBufSkipPtr; + + ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.usDwordOffset * 4; + ulSkipPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.usDwordOffset * 4; + ulIgnoreBytesOfst = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.usDwordOffset * 4; + ulHardSkipBytesOfst = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.usDwordOffset * 4; + ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.usDwordOffset * 4; + + ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byBitOffset; + ulSkipPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.byBitOffset; + ulIgnoreBitOfst = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.byBitOffset; + ulHardSkipBitOfst = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.byBitOffset; + ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byBitOffset; + + ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinWritePtrOfst.byFieldSize; + ulSkipPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinSkipPtrOfst.byFieldSize; + ulIgnoreFieldSize = pSharedInfo->MemoryMap.PlayoutRinIgnoreSkipCleanOfst.byFieldSize; + ulHardSkipFieldSize = pSharedInfo->MemoryMap.PlayoutRinHardSkipOfst.byFieldSize; + ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutRinReadPtrOfst.byFieldSize; + } + else /* f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ + { + ulWritePtr = pEchoChannel->ulSoutBufWritePtr; + pulSkipPtr = &pEchoChannel->ulSoutBufSkipPtr; + + ulWritePtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.usDwordOffset * 4; + ulSkipPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.usDwordOffset * 4; + ulIgnoreBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.usDwordOffset * 4; + ulHardSkipBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.usDwordOffset * 4; + ulReadPtrBytesOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.usDwordOffset * 4; + + ulWritePtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byBitOffset; + ulSkipPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.byBitOffset; + ulIgnoreBitOfst = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.byBitOffset; + ulHardSkipBitOfst = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.byBitOffset; + ulReadPtrBitOfst = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byBitOffset; + + ulWritePtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutWritePtrOfst.byFieldSize; + ulSkipPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutSkipPtrOfst.byFieldSize; + ulIgnoreFieldSize = pSharedInfo->MemoryMap.PlayoutSoutIgnoreSkipCleanOfst.byFieldSize; + ulHardSkipFieldSize = pSharedInfo->MemoryMap.PlayoutSoutHardSkipOfst.byFieldSize; + ulReadPtrFieldSize = pSharedInfo->MemoryMap.PlayoutSoutReadPtrOfst.byFieldSize; + } + + + + /* Set the playout feature base address. */ + ulPlayoutBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( f_ulChannelIndex * cOCT6100_CHANNEL_ROOT_SIZE ) + pSharedInfo->MemoryMap.ulChanRootConfOfst; + + /* Check if we must wait for stop to complete before starting a new list. */ + if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE ) + { + if ( ( ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) && ( pEchoChannel->fRinHardStop == TRUE ) ) + || ( ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT ) && ( pEchoChannel->fSoutHardStop == TRUE ) ) ) + { + /* Read the read pointer. */ + ReadParams.pProcessContext = f_pApiInstance->pProcessContext; + + ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; + ReadParams.pusReadData = &usReadData; + ReadParams.ulReadAddress = ulPlayoutBaseAddress + ulReadPtrBytesOfst; + + /* 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. */ + ulChipWritePtr = ( ulReadData & ulMask ) >> ulWritePtrBitOfst; + + /* Optimize this access by only reading the word we are interested in. */ + if ( ulReadPtrBitOfst < 16 ) + ReadParams.ulReadAddress += 2; + + while( fStillPlaying == TRUE ) + { + /* Read the read pointer until equals to the write pointer. */ + 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 == ulChipWritePtr ) + break; + + ulLoopCnt++; + if( ulLoopCnt > cOCT6100_MAX_LOOP ) + { + return cOCT6100_ERR_FATAL_E6; + } + + aulWaitTime[ 0 ] = 100; + aulWaitTime[ 1 ] = 0; + ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + } + + /* Check if must clear the skip bit. */ + if ( pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents == FALSE ) + { + if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == TRUE ) + && ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == TRUE ) ) + { + /* Make sure the skip bit is cleared to start playout! */ + 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 ); + + /* Cleared! */ + ulTempData &= ( ~ulMask ); + + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pEchoChannel, + ulAddress, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + + /* Make sure the hard skip bit is cleared to start playout! */ + 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( ulIgnoreFieldSize, ulHardSkipBitOfst, &ulMask ); + + /* Cleared! */ + ulTempData &= ( ~ulMask ); + + mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, + pEchoChannel, + ulAddress, + ulTempData, + ulResult ); + if ( ulResult != cOCT6100_ERR_OK ) + return ulResult; + } + } + + /* Write the skip and write pointer to activate buffer playout. */ + + /* Update the skip pointer. */ + if ( ( pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip == FALSE ) + || ( pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip == FALSE ) ) + { + /* Old 31 events image. */ + if ( ( ( ulWritePtr - *pulSkipPtr ) & 0x7F ) > 63 ) + { + *pulSkipPtr = ( ulWritePtr - 63 ) & 0x7F; + fWriteSkipPtr = TRUE; + } + } + else + { + /* No need to update the skip pointer, a bit needs to be set when skipping. */ + /* fWriteSkipPtr set to FALSE from variable declaration. */ + } + + if ( fWriteSkipPtr == TRUE ) + { + /*=======================================================================*/ + /* 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 |= *pulSkipPtr << ulSkipPtrBitOfst; + + 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; + + /*=======================================================================*/ + + + /*=======================================================================*/ + /* Now update the state of the channel stating that the buffer playout is activated. */ + + /* Select the buffer of interest.*/ + if ( f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_ROUT ) + { + /* Check if the global ports active stat must be incremented. */ + if ( pEchoChannel->fRinBufPlaying == FALSE ) + { + /* Increment the number of active buffer playout ports. */ + pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts++; + } + + pEchoChannel->fRinBufPlaying = TRUE; + /* Keep the new notify on event flag. */ + pEchoChannel->fRinBufPlayoutNotifyOnStop = (UINT8)( f_fNotifyOnPlayoutStop & 0xFF ); + /* Keep the specified user event id. */ + pEchoChannel->ulRinUserBufPlayoutEventId = f_ulUserEventId; + /* Keep type of event to be generated. */ + pEchoChannel->byRinPlayoutStopEventType = (UINT8)( f_ulPlayoutStopEventType & 0xFF ); + /* No hard stop for now. */ + pEchoChannel->fRinHardStop = FALSE; + /* No buffer added in the rin list for now. */ + pEchoChannel->fRinBufAdded = FALSE; + /* Buffer playout is active on this channel. */ + pEchoChannel->fBufPlayoutActive = TRUE; + } + else /* f_pBufferPlayoutStart->ulPlayoutPort == cOCT6100_CHANNEL_PORT_SOUT */ + { + /* Check if the global ports active stat must be incremented. */ + if ( pEchoChannel->fSoutBufPlaying == FALSE ) + { + /* Increment the number of active buffer playout ports. */ + pSharedInfo->ChipStats.usNumberActiveBufPlayoutPorts++; + } + + pEchoChannel->fSoutBufPlaying = TRUE; + /* Keep the new notify on event flag. */ + pEchoChannel->fSoutBufPlayoutNotifyOnStop = (UINT8)( f_fNotifyOnPlayoutStop & 0xFF ); + /* Keep the specified user event id. */ + pEchoChannel->ulSoutUserBufPlayoutEventId = f_ulUserEventId; + /* Keep type of event to be generated. */ + pEchoChannel->bySoutPlayoutStopEventType = (UINT8)( f_ulPlayoutStopEventType & 0xFF ); + /* No hard stop for now. */ + pEchoChannel->fSoutHardStop = FALSE; + /* No buffer added in the sout list for now. */ + pEchoChannel->fSoutBufAdded = FALSE; + /* Buffer playout is active on this channel. */ + pEchoChannel->fBufPlayoutActive = TRUE; + } + + 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. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +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. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +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. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +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; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReserveBufPlayoutListEntry + +Description: Reserves a free entry in the Buffer playout 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_pulBufferIndex List entry reserved. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiReserveBufPlayoutListEntry( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + OUT PUINT32 f_pulBufferIndex ) +{ + PVOID pBufPlayoutAlloc; + UINT32 ulResult; + + mOCT6100_GET_BUFFER_ALLOC_PNT( f_pApiInstance->pSharedInfo, pBufPlayoutAlloc ) + + ulResult = OctapiLlmAllocAlloc( pBufPlayoutAlloc, f_pulBufferIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + { + if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) + return cOCT6100_ERR_BUFFER_PLAYOUT_ALL_BUFFERS_OPEN; + else + return cOCT6100_ERR_FATAL_40; + } + + return cOCT6100_ERR_OK; +} + + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ + +Function: Oct6100ApiReleaseBufPlayoutListEntry + +Description: Release an entry from the Buffer playout 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_ulBufferIndex List entry to be freed. + +\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +UINT32 Oct6100ApiReleaseBufPlayoutListEntry( + IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, + IN UINT32 f_ulBufferIndex ) +{ + PVOID pBufPlayoutAlloc; + UINT32 ulResult; + + mOCT6100_GET_BUFFER_ALLOC_PNT( f_pApiInstance->pSharedInfo, pBufPlayoutAlloc ) + + ulResult = OctapiLlmAllocDealloc( pBufPlayoutAlloc, f_ulBufferIndex ); + if ( ulResult != cOCT6100_ERR_OK ) + return cOCT6100_ERR_FATAL_41; + + return cOCT6100_ERR_OK; +} + -- cgit v1.2.3