/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_memory.c Copyright (c) 2001-2011 Octasic Inc. Description: This file contains the functions used to manage the allocation of memory blocks in external memory. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.04.06 $ $Octasic_Revision: 42 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "apilib/octapi_llman.h" #include "oct6100api/oct6100_apiud.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_playout_buf_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_memory_priv.h" /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiGetMemorySwSizes Description: Gets the sizes of all portions of the API instance pertinent to the management of the memories. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pOpenChip Pointer to chip configuration struct. f_pInstSizes Pointer to struct containing instance sizes. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiGetMemorySwSizes( IN tPOCT6100_CHIP_OPEN f_pOpenChip, OUT tPOCT6100_API_INSTANCE_SIZES f_pInstSizes ) { UINT32 ulTempVar; UINT32 ulResult; UINT32 ulNumTsiChariots; /*=========================================================================*/ /* Internal memory */ /* Evaluate the number of available TSI memory after reserving the ones used by channels. */ ulNumTsiChariots = cOCT6100_TOTAL_TSI_CONTROL_MEM_ENTRY - f_pOpenChip->ulMaxPhasingTssts - cOCT6100_TSI_MEM_FOR_TIMESTAMP; if ( f_pOpenChip->fEnableExtToneDetection == TRUE ) ulNumTsiChariots--; /* Calculate memory needed for TSI memory allocation. */ ulResult = OctapiLlmAllocGetSize( ulNumTsiChariots, &f_pInstSizes->ulTsiMemoryAlloc ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_94; /* Calculate memory needed for conversion memory allocation. */ ulResult = OctapiLlmAllocGetSize( cOCT6100_MAX_CONVERSION_MEMORY_BLOCKS, &f_pInstSizes->ulConversionMemoryAlloc ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_B5; mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulTsiMemoryAlloc, ulTempVar ); mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulConversionMemoryAlloc, ulTempVar ); return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiMemorySwInit Description: Initializes all elements of the instance structure associated to memories. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiMemorySwInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; PVOID pTsiMemAlloc; PVOID pAllocPnt; UINT32 ulResult; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; /*=========================================================================*/ /* Internal memory */ /* Initialize the TSI memory allocation structure. */ pSharedInfo->MemoryMap.ulNumTsiEntries = cOCT6100_TOTAL_TSI_CONTROL_MEM_ENTRY - pSharedInfo->ChipConfig.usMaxPhasingTssts - cOCT6100_TSI_MEM_FOR_TIMESTAMP; if ( pSharedInfo->ChipConfig.fEnableExtToneDetection == TRUE ) pSharedInfo->MemoryMap.ulNumTsiEntries--; mOCT6100_GET_TSI_MEMORY_ALLOC_PNT( pSharedInfo, pTsiMemAlloc ); ulResult = OctapiLlmAllocInit( &pTsiMemAlloc, pSharedInfo->MemoryMap.ulNumTsiEntries ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_95; /* Initialize the conversion memory allocation structure. */ mOCT6100_GET_CONVERSION_MEMORY_ALLOC_PNT( pSharedInfo, pAllocPnt ); ulResult = OctapiLlmAllocInit( &pAllocPnt, cOCT6100_MAX_CONVERSION_MEMORY_BLOCKS ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_B6; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiBufferPlayoutMemorySwInit Description: Initialize the buffer playout memory allocation working structures. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiBufferPlayoutMemorySwInit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pNode; UINT32 i; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Only if buffer playout will be used. */ if ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers > 0 ) { mOCT6100_GET_BUFFER_MEMORY_NODE_LIST_PNT( pSharedInfo, pNode ); /* First node contains all free memory at beginning. This node is not used, but represents the memory. */ pNode->ulSize = ( pSharedInfo->MiscVars.ulTotalMemSize + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ) - pSharedInfo->MemoryMap.ulFreeMemBaseAddress; pNode->ulNext = 0; pNode->ulPrevious = 0; pNode->fAllocated = FALSE; pNode->ulStartAddress = pSharedInfo->MemoryMap.ulFreeMemBaseAddress; pNode++; /* Now create the first node of the free list, i.e. nodes that can be used later for modeling the memory. */ pNode->ulSize = 0; /* Next free. */ pNode->ulNext = 2; /* Last. */ pNode->ulPrevious = ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers * 2 ) - 1; pNode->fAllocated = FALSE; pNode->ulStartAddress = 0; pNode++; /* Link all the unused nodes. */ for( i = 2; i < (UINT32)( ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers * 2 ) - 1 ); i ++ ) { pNode->ulNext = i + 1; pNode->ulPrevious = i - 1; pNode->ulStartAddress = 0; pNode->ulSize = 0; pNode->fAllocated = FALSE; pNode++; } /* Last node of the unused list. */ pNode->fAllocated = FALSE; pNode->ulPrevious = ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers * 2 ) - 2; /* Free list head. */ pNode->ulNext = 1; pNode->ulSize = 0; pNode->ulStartAddress = 0; /* Set roving pointer to first node ( which can be used! ) */ pSharedInfo->PlayoutInfo.ulRovingNode = 0; /* First unused node. */ pSharedInfo->PlayoutInfo.ulFirstUnusedNode = 1; /* Last unused node. */ pSharedInfo->PlayoutInfo.ulLastUnusedNode = ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers * 2 ) - 1; /* Number of unused nodes. */ pSharedInfo->PlayoutInfo.ulUnusedNodeCnt = ( pSharedInfo->ChipConfig.usMaxPlayoutBuffers * 2 ) - 1; } else { pSharedInfo->PlayoutInfo.ulUnusedNodeCnt = 0; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReserveBufferPlayoutMemoryNode Description: Get a free node from the unused buffer playout node 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_pulNewNode The index of the node. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiReserveBufferPlayoutMemoryNode( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, OUT PUINT32 f_pulNewNode ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pNode; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Check if a free block is left. */ if ( pSharedInfo->PlayoutInfo.ulUnusedNodeCnt == 0 ) { /* This should not happen according to the allocated list from the beginning. */ return cOCT6100_ERR_FATAL_CC; } /* The new node is the first in the unused list. */ *f_pulNewNode = pSharedInfo->PlayoutInfo.ulFirstUnusedNode; /* Unlink this new node from the unused list. */ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pNode, *f_pulNewNode ); pSharedInfo->PlayoutInfo.ulFirstUnusedNode = pNode->ulNext; pNode->ulPrevious = pSharedInfo->PlayoutInfo.ulLastUnusedNode; mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pNode, pSharedInfo->PlayoutInfo.ulLastUnusedNode ); pNode->ulNext = pSharedInfo->PlayoutInfo.ulFirstUnusedNode; /* Update unused node count. */ pSharedInfo->PlayoutInfo.ulUnusedNodeCnt--; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReleaseBufferPlayoutMemoryNode Description: Release a node that is not used anymore. Insert this node into the unused 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_ulOldNode The index of the node. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiReleaseBufferPlayoutMemoryNode( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulOldNode ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pNode; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Get the last unused node. Insert this old node at the end of the unused list. */ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pNode, pSharedInfo->PlayoutInfo.ulLastUnusedNode ); /* Last node points to old node. */ pNode->ulNext = f_ulOldNode; /* Update old node. */ mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pNode, f_ulOldNode ); pNode->ulPrevious = pSharedInfo->PlayoutInfo.ulLastUnusedNode; pNode->ulNext = pSharedInfo->PlayoutInfo.ulFirstUnusedNode; pSharedInfo->PlayoutInfo.ulLastUnusedNode = f_ulOldNode; /* Keep unused node count. */ pSharedInfo->PlayoutInfo.ulUnusedNodeCnt++; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReserveBufferPlayoutMemory Description: Try to allocate requested size. Returns an error if malloc point could not be found. ------------------------------------------------------------------------------- | 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_ulSize Needed size. f_pulMallocAddress Alloc point. This memory can now be used. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiReserveBufferPlayoutMemory( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulSize, OUT PUINT32 f_pulMallocAddress ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pCurrentNode; tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pTempNode; tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pNewNode; UINT32 ulCurrentBufferPlayoutMallocNode; UINT32 ulNewNode; BOOL fFoundMemory = FALSE; UINT32 ulResult; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Requested size must be divisible by 64. */ if ( f_ulSize % 64 ) { f_ulSize = f_ulSize + ( 64 - ( f_ulSize % 64 ) ); } /* Start with roving pointer. */ ulCurrentBufferPlayoutMallocNode = pSharedInfo->PlayoutInfo.ulRovingNode; *f_pulMallocAddress = 0; /* Return an error if size requested is zero. */ if ( f_ulSize == 0 ) { return cOCT6100_ERR_BUFFER_PLAYOUT_MALLOC_ZERO; } do { mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pCurrentNode, ulCurrentBufferPlayoutMallocNode ); /* Look for a free node big enough to fulfill user requested size. */ if ( ( pCurrentNode->fAllocated == FALSE ) && ( pCurrentNode->ulSize >= f_ulSize ) ) { /* Use this node! */ pCurrentNode->fAllocated = TRUE; if ( pCurrentNode->ulNext != 0 ) { mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pTempNode, pCurrentNode->ulNext ); if( ( pTempNode->fAllocated == TRUE ) && ( pCurrentNode->ulSize > f_ulSize ) ) { /* Fragmentation NOW! */ /* Allocate new node that will contain free size. */ ulResult = Oct6100ApiReserveBufferPlayoutMemoryNode( f_pApiInstance, &ulNewNode ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pNewNode, ulNewNode ); /* Can use this free node. */ pNewNode->ulSize = pCurrentNode->ulSize - f_ulSize; pNewNode->ulStartAddress = pCurrentNode->ulStartAddress + f_ulSize; /* Link new node into the list. */ pNewNode->ulNext = pCurrentNode->ulNext; pNewNode->ulPrevious = ulCurrentBufferPlayoutMallocNode; pNewNode->fAllocated = FALSE; pTempNode->ulPrevious = ulNewNode; pCurrentNode->ulNext = ulNewNode; } } else if ( pCurrentNode->ulSize > f_ulSize ) { /* Must allocate a new free node for the rest of the space. */ ulResult = Oct6100ApiReserveBufferPlayoutMemoryNode( f_pApiInstance, &ulNewNode ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pNewNode, ulNewNode ); pNewNode->ulNext = pCurrentNode->ulNext; pCurrentNode->ulNext = ulNewNode; pNewNode->ulPrevious = ulCurrentBufferPlayoutMallocNode; pNewNode->fAllocated = FALSE; pNewNode->ulSize = pCurrentNode->ulSize - f_ulSize; pNewNode->ulStartAddress = pCurrentNode->ulStartAddress + f_ulSize; mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pTempNode, 0 ); /* Check for the head node that would have to be updated. */ if ( ( ulCurrentBufferPlayoutMallocNode == 0 ) && ( pTempNode->ulPrevious == 0 ) ) pTempNode->ulPrevious = ulNewNode; } else { /* Perfect fit. */ } pCurrentNode->ulSize = f_ulSize; /* Update roving pointer. */ pSharedInfo->PlayoutInfo.ulRovingNode = ulCurrentBufferPlayoutMallocNode; *f_pulMallocAddress = pCurrentNode->ulStartAddress; fFoundMemory = TRUE; break; } /* Next block! */ ulCurrentBufferPlayoutMallocNode = pCurrentNode->ulNext; } while ( pSharedInfo->PlayoutInfo.ulRovingNode != ulCurrentBufferPlayoutMallocNode ); if ( fFoundMemory == FALSE ) { return cOCT6100_ERR_BUFFER_PLAYOUT_NO_MEMORY; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReleaseBufferPlayoutMemory Description: Free what was allocated at address. Free is somewhat slower then Malloc. O(n), must travel through the list looking for the malloc point. Return an error if alloc point was not found. ------------------------------------------------------------------------------- | 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_ulMallocAddress Alloc point. The memory at address will be freed. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiReleaseBufferPlayoutMemory( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulMallocAddress ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pCurrentNode; tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pTempNode; tPOCT6100_API_BUFFER_PLAYOUT_MALLOC_NODE pOldNode; UINT32 ulResult = cOCT6100_ERR_BUFFER_PLAYOUT_MALLOC_POINT_NOT_FOUND; UINT32 ulNodeToMerge; UINT32 ulNodeToRemove; UINT32 ulCurrentBufferPlayoutMallocNode; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Start from the beginning and find the alloc node. */ ulCurrentBufferPlayoutMallocNode = 0; do { mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pCurrentNode, ulCurrentBufferPlayoutMallocNode ); if ( ( pCurrentNode->ulStartAddress == f_ulMallocAddress ) && ( pCurrentNode->fAllocated == TRUE ) ) { /* We found the block! */ pCurrentNode->fAllocated = FALSE; /* Check if the next node can be merged. */ if ( pCurrentNode->ulNext != 0 ) { mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pTempNode, pCurrentNode->ulNext ); if ( pTempNode->fAllocated == FALSE ) { /* Can merge this block to us. */ pCurrentNode->ulSize += pTempNode->ulSize; pTempNode->ulSize = 0; /* Unlink unused node. */ ulNodeToRemove = pCurrentNode->ulNext; pCurrentNode->ulNext = pTempNode->ulNext; mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pTempNode, pCurrentNode->ulNext ); pTempNode->ulPrevious = ulCurrentBufferPlayoutMallocNode; ulResult = Oct6100ApiReleaseBufferPlayoutMemoryNode( f_pApiInstance, ulNodeToRemove ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Move roving pointer if have to. */ if ( pSharedInfo->PlayoutInfo.ulRovingNode == ulNodeToRemove ) pSharedInfo->PlayoutInfo.ulRovingNode = ulCurrentBufferPlayoutMallocNode; } } /* Check if previous node can merge. */ if ( ulCurrentBufferPlayoutMallocNode != 0 ) { mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pTempNode, pCurrentNode->ulPrevious ); if ( pTempNode->fAllocated == FALSE ) { ulNodeToMerge = pCurrentNode->ulPrevious; /* Can merge us to this node. */ pTempNode->ulSize += pCurrentNode->ulSize; pCurrentNode->ulSize = 0; /* Unlink unused node. */ ulNodeToRemove = ulCurrentBufferPlayoutMallocNode; mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pOldNode, ulNodeToRemove ); pTempNode->ulNext = pOldNode->ulNext; mOCT6100_GET_BUFFER_MEMORY_NODE_ENTRY_PNT( pSharedInfo, pTempNode, pTempNode->ulNext ); pTempNode->ulPrevious = ulNodeToMerge; pOldNode->fAllocated = FALSE; pOldNode->ulSize = 0; pOldNode->ulStartAddress = 0; /* Move roving pointer if have to. */ if ( pSharedInfo->PlayoutInfo.ulRovingNode == ulNodeToRemove ) pSharedInfo->PlayoutInfo.ulRovingNode = ulNodeToMerge; /* Release this unused node. */ ulResult = Oct6100ApiReleaseBufferPlayoutMemoryNode( f_pApiInstance, ulNodeToRemove ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /* All's good! */ ulResult = 0; break; } /* Next node. */ ulCurrentBufferPlayoutMallocNode = pCurrentNode->ulNext; } while( ulCurrentBufferPlayoutMallocNode != 0 ); return ulResult; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReserveTsiMemEntry Description: Reserves a TSI chariot memory entry. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pusTsiMemIndex Resulting index reserved in the TSI chariot memory. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiReserveTsiMemEntry( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, OUT PUINT16 f_pusTsiMemIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; PVOID pTsiMemAlloc; UINT32 ulResult; UINT32 ulIndex; UINT32 ulNumTsiB4Timestamp; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; mOCT6100_GET_TSI_MEMORY_ALLOC_PNT( pSharedInfo, pTsiMemAlloc ) ulResult = OctapiLlmAllocAlloc( pTsiMemAlloc, &ulIndex ); if ( ulResult != cOCT6100_ERR_OK ) { if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) return cOCT6100_ERR_MEMORY_ALL_TSI_MEM_ENTRY_RESERVED; else return cOCT6100_ERR_FATAL_92; } if ( ulIndex >= cOCT6100_NUM_TSI_B4_PHASING ) { /* Evaluate the number of TSI memory before the timestamp TSI. */ ulNumTsiB4Timestamp = cOCT6100_NUM_TSI_B4_PHASING + cOCT6100_MAX_TSI_B4_TIMESTAMP - pSharedInfo->ChipConfig.usMaxPhasingTssts; if ( ulIndex >= ulNumTsiB4Timestamp ) { /* + 4 for the timestamp TSI entries.*/ *f_pusTsiMemIndex = (UINT16)( pSharedInfo->ChipConfig.usMaxPhasingTssts + ulIndex + cOCT6100_TSI_MEM_FOR_TIMESTAMP ); } else /* ulIndex < ulNumTsiB4Timestamp */ { *f_pusTsiMemIndex = (UINT16)( pSharedInfo->ChipConfig.usMaxPhasingTssts + ulIndex ); } } else /* ulIndex < ulNumTsiB4Timestamp */ { *f_pusTsiMemIndex = (UINT16)( ulIndex ); } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReleaseTsiMemEntry Description: Releases a TSI chariot memory entry specified. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usTsiMemIndex Index reserved in the TSI chariot memory. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiReleaseTsiMemEntry( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usTsiMemIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; PVOID pTsiMemAlloc; UINT32 ulResult; UINT32 ulIndex; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; /* Check if the entry programmed is greater then the timestamp entries. */ if ( f_usTsiMemIndex > cOCT6100_TSST_CONTROL_TIMESTAMP_BASE_ENTRY ) ulIndex = f_usTsiMemIndex - cOCT6100_TSI_MEM_FOR_TIMESTAMP; else ulIndex = f_usTsiMemIndex; /* Check if the entry programmed is greater then the phasing TSST entries. */ if ( ulIndex > cOCT6100_TSST_CONTROL_PHASING_TSST_BASE_ENTRY ) ulIndex -= pSharedInfo->ChipConfig.usMaxPhasingTssts; mOCT6100_GET_TSI_MEMORY_ALLOC_PNT( pSharedInfo, pTsiMemAlloc ) ulResult = OctapiLlmAllocDealloc( pTsiMemAlloc, ulIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return cOCT6100_ERR_FATAL_93; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReserveConversionMemEntry Description: Reserves one of the conversion memory entry ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pusConversionMemIndex Resulting index reserved in the conversion memory. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiReserveConversionMemEntry( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, OUT PUINT16 f_pusConversionMemIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; PVOID pConversionMemAlloc; UINT32 ulConversionMemIndex; UINT32 ulResult; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; mOCT6100_GET_CONVERSION_MEMORY_ALLOC_PNT( pSharedInfo, pConversionMemAlloc ) ulResult = OctapiLlmAllocAlloc( pConversionMemAlloc, &ulConversionMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) { if ( ulResult == OCTAPI_LLM_NO_STRUCTURES_LEFT ) return cOCT6100_ERR_MEMORY_ALL_CONVERSION_MEM_ENTRY_RESERVED; else return cOCT6100_ERR_FATAL_B8; } *f_pusConversionMemIndex = (UINT16)( ulConversionMemIndex & 0xFFFF ); return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReleaseConversionMemEntry Description: Releases the conversion chariot memory entry specified. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_usConversionMemIndex Index reserved in the conversion chariot memory. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiReleaseConversionMemEntry( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT16 f_usConversionMemIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; PVOID pConversionMemAlloc; UINT32 ulResult; /* Get local pointer to shared portion of instance. */ pSharedInfo = f_pApiInstance->pSharedInfo; mOCT6100_GET_CONVERSION_MEMORY_ALLOC_PNT( pSharedInfo, pConversionMemAlloc ) ulResult = OctapiLlmAllocDealloc( pConversionMemAlloc, f_usConversionMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) { return cOCT6100_ERR_FATAL_B7; } return cOCT6100_ERR_OK; }