/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_debug.c Copyright (c) 2001-2011 Octasic Inc. Description: This file contains functions used to debug the OCT6100. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.04.05 $ $Octasic_Revision: 83 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.h" #include "oct6100api/oct6100_apiud.h" #include "apilib/octapi_largmath.h" #include "oct6100api/oct6100_apiud.h" #include "oct6100api/oct6100_tlv_inst.h" #include "oct6100api/oct6100_chip_open_inst.h" #include "oct6100api/oct6100_chip_stats_inst.h" #include "oct6100api/oct6100_interrupts_inst.h" #include "oct6100api/oct6100_remote_debug_inst.h" #include "oct6100api/oct6100_debug_inst.h" #include "oct6100api/oct6100_api_inst.h" #include "oct6100api/oct6100_channel_inst.h" #include "oct6100api/oct6100_interrupts_pub.h" #include "oct6100api/oct6100_chip_open_pub.h" #include "oct6100api/oct6100_chip_stats_pub.h" #include "oct6100api/oct6100_channel_pub.h" #include "oct6100api/oct6100_debug_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_chip_stats_priv.h" #include "oct6100_channel_priv.h" #include "oct6100_miscellaneous_priv.h" #include "oct6100_memory_priv.h" #include "oct6100_debug_priv.h" #include "oct6100_version.h" /**************************** PUBLIC FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100DebugSelectChannel Description: This function sets the current debug channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pSelectDebugChan Pointer to select debug channel structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100DebugSelectChannelDef( tPOCT6100_DEBUG_SELECT_CHANNEL f_pSelectDebugChan ) { f_pSelectDebugChan->ulChannelHndl = cOCT6100_INVALID_VALUE; return cOCT6100_ERR_OK; } UINT32 Oct6100DebugSelectChannel( tPOCT6100_INSTANCE_API f_pApiInstance, tPOCT6100_DEBUG_SELECT_CHANNEL f_pSelectDebugChan ) { 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 = Oct6100DebugSelectChannelSer( f_pApiInstance, f_pSelectDebugChan, 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: Oct6100DebugGetData Description: This function retrieves the last recorded debug data. ------------------------------------------------------------------------------- | 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_pGetData Pointer to debug get data structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100DebugGetDataDef( tPOCT6100_DEBUG_GET_DATA f_pGetData ) { f_pGetData->ulGetDataMode = cOCT6100_DEBUG_GET_DATA_MODE_120S_LITE; f_pGetData->ulGetDataContent = cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE; f_pGetData->ulRemainingNumBytes = cOCT6100_INVALID_VALUE; f_pGetData->ulTotalNumBytes = cOCT6100_INVALID_VALUE; f_pGetData->ulMaxBytes = cOCT6100_INVALID_VALUE; f_pGetData->ulValidNumBytes = cOCT6100_INVALID_VALUE; f_pGetData->pbyData = NULL; return cOCT6100_ERR_OK; } UINT32 Oct6100DebugGetData( tPOCT6100_INSTANCE_API f_pApiInstance, tPOCT6100_DEBUG_GET_DATA f_pGetData ) { 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 = Oct6100DebugGetDataSer( f_pApiInstance, f_pGetData ); } 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: Oct6100DebugSelectChannelSer Description: This function sets the debug channel. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_pSelectDebugChan Pointer to a tOCT6100_DEBUG_SELECT_CHANNEL structure. f_fCheckChannelRecording Check if channel recording is enabled or not. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100DebugSelectChannelSer( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN tPOCT6100_DEBUG_SELECT_CHANNEL f_pSelectDebugChan, IN BOOL f_fCheckChannelRecording ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHANNEL pChanEntry = NULL; tPOCT6100_API_CHANNEL pTempChanEntry; tOCT6100_CHANNEL_OPEN TempChanOpen; tOCT6100_WRITE_BURST_PARAMS BurstParams; UINT16 usChanIndex = 0; UINT32 ulEntryOpenCnt; UINT16 ausWriteData[ 2 ]; UINT32 ulResult; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; BurstParams.pProcessContext = f_pApiInstance->pProcessContext; BurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; BurstParams.pusWriteData = ausWriteData; /* First release the resources reserved for the channel that was previously debugged. */ if ( ( pSharedInfo->DebugInfo.usCurrentDebugChanIndex != cOCT6100_INVALID_INDEX ) && ( ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) || ( pSharedInfo->ChipConfig.fAllowDynamicRecording == TRUE ) ) ) { /*=======================================================================*/ /* Get a pointer to the channel's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pTempChanEntry, pSharedInfo->DebugInfo.usCurrentDebugChanIndex ) /* Release the extra TSI memory entry and reprogram the TSST control memory if required. */ if ( pTempChanEntry->usExtraSinTsiDependencyCnt >= 1 ) { /*=======================================================================*/ /* Clear memcpy operations. */ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSharedInfo->MixerInfo.usRecordCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); BurstParams.ulWriteLength = 2; ausWriteData[ 0 ] = cOCT6100_MIXER_CONTROL_MEM_NO_OP; ausWriteData[ 1 ] = 0x0; mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSharedInfo->MixerInfo.usRecordSinEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /* If we are the last dependency using the extra Sin TSI, release it */ if ( pTempChanEntry->usExtraSinTsiDependencyCnt == 1 ) { ulResult = Oct6100ApiReleaseTsiMemEntry( f_pApiInstance, pTempChanEntry->usExtraSinTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Do not forget to reprogram the TSST control memory. */ if ( pTempChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, pTempChanEntry->usSinTsstIndex, pTempChanEntry->usSinSoutTsiMemIndex, pTempChanEntry->TdmConfig.bySinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } pTempChanEntry->usExtraSinTsiMemIndex = cOCT6100_INVALID_INDEX; } pTempChanEntry->usExtraSinTsiDependencyCnt--; } } /* Set the new parameters. */ if ( f_pSelectDebugChan->ulChannelHndl != cOCT6100_INVALID_HANDLE ) { /* Check the provided handle. */ if ( (f_pSelectDebugChan->ulChannelHndl & cOCT6100_HNDL_TAG_MASK) != cOCT6100_HNDL_TAG_CHANNEL ) return cOCT6100_ERR_DEBUG_CHANNEL_INVALID_HANDLE; usChanIndex = (UINT16)( f_pSelectDebugChan->ulChannelHndl & cOCT6100_HNDL_INDEX_MASK ); if ( usChanIndex >= pSharedInfo->ChipConfig.usMaxChannels ) return cOCT6100_ERR_DEBUG_CHANNEL_INVALID_HANDLE; if ( f_fCheckChannelRecording == TRUE ) { if ( ( ( pSharedInfo->ChipConfig.fEnableChannelRecording == FALSE ) && ( pSharedInfo->ChipConfig.fAllowDynamicRecording == FALSE ) ) || ( ( pSharedInfo->ChipConfig.fAllowDynamicRecording == TRUE ) && ( pSharedInfo->DebugInfo.fRecordChanUp == FALSE ) ) ) return cOCT6100_ERR_DEBUG_CHANNEL_RECORDING_DISABLED; } /*=======================================================================*/ /* Get a pointer to the channel's list entry. */ mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, usChanIndex ); /* Extract the entry open count from the provided handle. */ ulEntryOpenCnt = ( f_pSelectDebugChan->ulChannelHndl >> cOCT6100_ENTRY_OPEN_CNT_SHIFT) & cOCT6100_ENTRY_OPEN_CNT_MASK; /* Check for errors. */ if ( pChanEntry->fReserved != TRUE ) return cOCT6100_ERR_CHANNEL_NOT_OPEN; if ( ulEntryOpenCnt != pChanEntry->byEntryOpenCnt ) return cOCT6100_ERR_CHANNEL_INVALID_HANDLE; /*=======================================================================*/ /* First program the mixer entry if the user wants to record. */ /* Check if the API needs to reserve an extra TSI memory to load the SIN signal. */ if ( ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) || ( pSharedInfo->ChipConfig.fAllowDynamicRecording == TRUE ) ) { /* Reserve the extra Sin TSI memory if it was not already reserved. */ if ( pChanEntry->usExtraSinTsiMemIndex == cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, &pChanEntry->usExtraSinTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Reprogram the TSST control memory accordingly. */ if ( pChanEntry->usSinTsstIndex != cOCT6100_INVALID_INDEX ) { ulResult = Oct6100ApiWriteInputTsstControlMemory( f_pApiInstance, pChanEntry->usSinTsstIndex, pChanEntry->usExtraSinTsiMemIndex, pChanEntry->TdmConfig.bySinPcmLaw ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } /*=======================================================================*/ /* Program the Sout Copy event. */ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSharedInfo->MixerInfo.usRecordCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); BurstParams.ulWriteLength = 2; ausWriteData[ 0 ] = cOCT6100_MIXER_CONTROL_MEM_COPY; ausWriteData[ 0 ] |= pChanEntry->usSinSoutTsiMemIndex; ausWriteData[ 0 ] |= pChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ausWriteData[ 1 ] = (UINT16)( pSharedInfo->DebugInfo.usRecordRinRoutTsiMemIndex ); mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* Program the Sin copy event. */ BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSharedInfo->MixerInfo.usRecordSinEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE ); BurstParams.ulWriteLength = 2; ausWriteData[ 0 ] = cOCT6100_MIXER_CONTROL_MEM_COPY; ausWriteData[ 0 ] |= pChanEntry->usExtraSinTsiMemIndex; ausWriteData[ 0 ] |= pChanEntry->TdmConfig.bySinPcmLaw << cOCT6100_MIXER_CONTROL_MEM_LAW_OFFSET; ausWriteData[ 1 ] = pChanEntry->usSinSoutTsiMemIndex; mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ pChanEntry->usExtraSinTsiDependencyCnt++; } } else { /* Set the index to invalid to deactivate the recording. */ usChanIndex = cOCT6100_INVALID_INDEX; } /* Set law of newly selected hot channel. */ if ( ( ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE ) || ( pSharedInfo->ChipConfig.fAllowDynamicRecording == TRUE ) ) && ( f_pSelectDebugChan->ulChannelHndl != cOCT6100_INVALID_HANDLE ) && ( pChanEntry != NULL ) ) { /* Set the PCM law of the debug channel. */ /* Let's program the channel memory. */ Oct6100ChannelOpenDef( &TempChanOpen ); TempChanOpen.ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_HT_RESET; /* Activate the channel. */ TempChanOpen.VqeConfig.fEnableNlp = FALSE; TempChanOpen.VqeConfig.ulComfortNoiseMode = cOCT6100_COMFORT_NOISE_NORMAL; TempChanOpen.VqeConfig.fSinDcOffsetRemoval = FALSE; TempChanOpen.VqeConfig.fRinDcOffsetRemoval = FALSE; TempChanOpen.VqeConfig.lDefaultErlDb = 0; /* Use the law of the channel being recorded. */ TempChanOpen.TdmConfig.ulRinPcmLaw = pChanEntry->TdmConfig.byRinPcmLaw; TempChanOpen.TdmConfig.ulSinPcmLaw = pChanEntry->TdmConfig.bySinPcmLaw; TempChanOpen.TdmConfig.ulRoutPcmLaw = pChanEntry->TdmConfig.byRoutPcmLaw; TempChanOpen.TdmConfig.ulSoutPcmLaw = pChanEntry->TdmConfig.bySoutPcmLaw; ulResult = Oct6100ApiWriteDebugChanMemory( f_pApiInstance, &TempChanOpen.TdmConfig, &TempChanOpen.VqeConfig, &TempChanOpen, pSharedInfo->DebugInfo.usRecordChanIndex, pSharedInfo->DebugInfo.usRecordMemIndex, pSharedInfo->DebugInfo.usRecordRinRoutTsiMemIndex, pSharedInfo->DebugInfo.usRecordSinSoutTsiMemIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } if ( usChanIndex == cOCT6100_INVALID_INDEX ) ausWriteData[ 0 ] = 0xFFFF; else ausWriteData[ 0 ] = 0x0; ausWriteData[ 1 ] = (UINT16)(( usChanIndex >> 0) & 0xFFFF); /* Write the channel number into the Matrix hot channel field.*/ BurstParams.ulWriteAddress = pSharedInfo->DebugInfo.ulHotChannelSelectBaseAddress; BurstParams.pusWriteData = ausWriteData; BurstParams.ulWriteLength = 2; mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; pSharedInfo->DebugInfo.usCurrentDebugChanIndex = usChanIndex; /* Cancel data dump request, if there was one. */ pSharedInfo->DebugInfo.fDebugDataBeingDumped = FALSE; pSharedInfo->DebugInfo.ulDebugDataTotalNumBytes = cOCT6100_INVALID_VALUE; /* Call from remote client. */ if ( f_fCheckChannelRecording == FALSE ) { /* If the user has not activated recording, let the remote client know. */ if ( ( ( pSharedInfo->ChipConfig.fEnableChannelRecording == FALSE ) && ( pSharedInfo->ChipConfig.fAllowDynamicRecording == FALSE ) ) || ( ( pSharedInfo->ChipConfig.fAllowDynamicRecording == TRUE ) && ( pSharedInfo->DebugInfo.fRecordChanUp == FALSE ) ) ) return cOCT6100_ERR_DEBUG_RC_CHANNEL_RECORDING_DISABLED; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100DebugGetDataSer Description: This function retrieves the latest recorded debug data. ------------------------------------------------------------------------------- | 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_pGetData Pointer to a tOCT6100_DEBUG_GET_DATA structure. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100DebugGetDataSer( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN OUT tPOCT6100_DEBUG_GET_DATA f_pGetData ) { tPOCT6100_SHARED_INFO pSharedInfo; tPOCT6100_API_CHANNEL pChanEntry = NULL; tOCT6100_READ_PARAMS ReadParams; tOCT6100_WRITE_PARAMS WriteParams; tOCT6100_READ_BURST_PARAMS ReadBurstParams; tOCT6100_WRITE_BURST_PARAMS WriteBurstParams; UINT16 ausWriteData[ 2 ]; UINT16 usReadData; UINT16 usDebugEventReadPtr; UINT16 usTempNumEvents; UINT32 ulResult; UINT32 ulToneEventIndex; UINT32 ulReadPointer; UINT32 ulUserBufWriteIndex = 0; UINT32 ulTimestamp; UINT32 ulDebugEventIndex = 0; UINT32 ulStreamIndex; UINT32 ulPcmSampleIndex; UINT32 ulNumAfEvents; UINT32 ulNumReads = 0; UINT32 ulTempIndex; UINT32 ulCopyIndex; UINT32 ulFeatureBytesOffset; UINT32 ulFeatureBitOffset; UINT32 ulFeatureFieldLength; UINT32 ulStreamIndexMin; UINT32 ulStreamIndexMax; UINT32 ulTempData; UINT32 ulMask; UINT32 ulDiff; UINT32 ulLastTimestamp = 0; BOOL fResetRemainingDataFlag = FALSE; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; ReadBurstParams.pProcessContext = f_pApiInstance->pProcessContext; ReadBurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; WriteBurstParams.pProcessContext = f_pApiInstance->pProcessContext; WriteBurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* Check all user parameters. */ /* Check if channel recording is enabled. */ if ( ( ( pSharedInfo->ChipConfig.fEnableChannelRecording == FALSE ) && ( pSharedInfo->ChipConfig.fAllowDynamicRecording == FALSE ) ) || ( ( pSharedInfo->ChipConfig.fAllowDynamicRecording == TRUE ) && ( pSharedInfo->DebugInfo.fRecordChanUp == FALSE ) ) ) return cOCT6100_ERR_DEBUG_CHANNEL_RECORDING_DISABLED; /* Check if a current debugging channel has been selected. */ /* If not, the user has not yet called Oct6100DebugSelectChannel. */ if ( pSharedInfo->DebugInfo.usCurrentDebugChanIndex == cOCT6100_INVALID_INDEX ) return cOCT6100_ERR_DEBUG_RECORD_NO_CHAN_SELECTED; /* Check that the user supplied a valid max bytes value. */ if ( f_pGetData->ulMaxBytes == cOCT6100_INVALID_VALUE ) return cOCT6100_ERR_DEBUG_GET_DATA_MAX_BYTES; /* Data buffer must be aligned on 1024 bytes. */ if ( ( f_pGetData->ulMaxBytes % 1024 ) != 0 ) return cOCT6100_ERR_DEBUG_GET_DATA_MAX_BYTES; /* Check that the user provided the required memory to transfer the information. */ if ( f_pGetData->pbyData == NULL ) return cOCT6100_ERR_DEBUG_GET_DATA_PTR_INVALID; /* Check dump type. */ if ( ( f_pGetData->ulGetDataMode != cOCT6100_DEBUG_GET_DATA_MODE_16S_LITE ) && ( f_pGetData->ulGetDataMode != cOCT6100_DEBUG_GET_DATA_MODE_120S_LITE ) && ( f_pGetData->ulGetDataMode != cOCT6100_DEBUG_GET_DATA_MODE_16S ) && ( f_pGetData->ulGetDataMode != cOCT6100_DEBUG_GET_DATA_MODE_120S ) && ( f_pGetData->ulGetDataMode != cOCT6100_DEBUG_GET_DATA_MODE_CORE_DUMP ) ) return cOCT6100_ERR_DEBUG_GET_DATA_MODE; /* Check dump content. */ if ( ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) && ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_RIN_PCM ) && ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_SIN_PCM ) && ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_SOUT_PCM ) ) return cOCT6100_ERR_DEBUG_GET_DATA_CONTENT; /* The core dump mode does not support the xxx_PCM data contents. */ if ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_CORE_DUMP ) && ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) ) return cOCT6100_ERR_DEBUG_GET_DATA_CONTENT; /* Check if can accomodate the 120 seconds dump. */ if ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S_LITE ) || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S ) ) { if ( pSharedInfo->DebugInfo.ulDebugEventSize != 0x100 ) return cOCT6100_ERR_NOT_SUPPORTED_DEBUG_DATA_MODE_120S; } mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, pSharedInfo->DebugInfo.usCurrentDebugChanIndex ) /* Lets go dump the requested data. */ usDebugEventReadPtr = 0; /* Check if this is the first time this function is called since the hot channel was set. */ if ( pSharedInfo->DebugInfo.fDebugDataBeingDumped == FALSE ) { /* Check that the channel is not in POWER_DOWN. When the channel is in POWER_DOWN, */ /* the debug events are not recorded correctly in external memory. */ if ( pChanEntry->byEchoOperationMode == cOCT6100_ECHO_OP_MODE_POWER_DOWN ) return cOCT6100_ERR_DEBUG_CHANNEL_IN_POWER_DOWN; /* Flag the hot channel that it must stop recording. The data is being transfered. */ /* This also tells the remote client not to do anything right now. */ ReadBurstParams.ulReadAddress = pSharedInfo->DebugInfo.ulHotChannelSelectBaseAddress; ReadBurstParams.ulReadLength = 2; ReadBurstParams.pusReadData = pSharedInfo->DebugInfo.ausHotChannelData; mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; WriteBurstParams.pusWriteData = ausWriteData; WriteBurstParams.ulWriteAddress = pSharedInfo->DebugInfo.ulHotChannelSelectBaseAddress; WriteBurstParams.ulWriteLength = 2; WriteBurstParams.pusWriteData[ 0 ] = 0xFFFF; WriteBurstParams.pusWriteData[ 1 ] = 0xFFFF; mOCT6100_DRIVER_WRITE_BURST_API( WriteBurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Get the maximum number of events this firmware supports from the TLVs. */ pSharedInfo->DebugInfo.usMatrixCBMask = (UINT16)( pSharedInfo->DebugInfo.ulDebugEventSize & 0xFFFF ); pSharedInfo->DebugInfo.usMatrixCBMask -= 1; /* Find out the chip log write pointer. */ /* Now get the current write pointer for matrix events. */ ReadParams.pusReadData = &pSharedInfo->DebugInfo.usChipDebugEventWritePtr; ReadParams.ulReadAddress = pSharedInfo->DebugInfo.ulMatrixWpBaseAddress + 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ReadParams.pusReadData = &usReadData; /* This write pointer might have wrapped, but we don't know for sure. */ /* To be confident, the chip frame timestamp is read. */ ReadParams.ulReadAddress = pSharedInfo->DebugInfo.ulMatrixTimestampBaseAddress; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulTimestamp = usReadData << 16; ReadParams.ulReadAddress += 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulTimestamp |= usReadData; ulTimestamp >>= 12; /* TDM time for 1 event (512 ms) */ /* There is a probability here (once very 6.2 days) that the timestamp is close */ /* to 0, because it has wrapped. But still, we need a way to workaround the highly */ /* occuring case of the chip just being opened. This will fix this problem. */ if ( ulTimestamp < (UINT32)( pSharedInfo->DebugInfo.usMatrixCBMask + 1 ) ) { if ( pSharedInfo->DebugInfo.usChipDebugEventWritePtr >= 2 ) { /* Must trash the first 2 events. The chip is not yet ready. */ pSharedInfo->DebugInfo.usNumEvents = (UINT16)( pSharedInfo->DebugInfo.usChipDebugEventWritePtr - 2 ); } else { pSharedInfo->DebugInfo.usNumEvents = 0x0; } } else { pSharedInfo->DebugInfo.usNumEvents = (UINT16)( pSharedInfo->DebugInfo.usMatrixCBMask + 1 ); /* Account for event being created right now while the chip is running. */ /* The event at the write pointer will be discarded. */ if ( pSharedInfo->DebugInfo.usNumEvents > 0 ) pSharedInfo->DebugInfo.usNumEvents--; } /* If the user only requested the last 16 seconds, cap the number of events. */ if ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S || f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S_LITE || ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_CORE_DUMP ) && ( pSharedInfo->DebugInfo.ulDebugEventSize != 0x100 ) ) ) { /* x events to get the last 16 seconds. */ if ( pSharedInfo->DebugInfo.usNumEvents > ( 16000 / ( pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize / 8 ) ) ) pSharedInfo->DebugInfo.usNumEvents = (UINT16)( ( 16000 / ( pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize / 8 ) ) & 0xFFFF ); } /* Make sure that all the events are pertaining to the current hot channel. */ /* Calculate the event read pointer. */ ulReadPointer = ( ( pSharedInfo->DebugInfo.usChipDebugEventWritePtr - pSharedInfo->DebugInfo.usNumEvents ) & pSharedInfo->DebugInfo.usMatrixCBMask ) * pSharedInfo->DebugInfo.ulDebugChanStatsByteSize; ulReadPointer %= ( ( pSharedInfo->DebugInfo.usMatrixCBMask + 1 ) * pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ); /* Travel through the events and throw away the bad events. */ usTempNumEvents = pSharedInfo->DebugInfo.usNumEvents; pSharedInfo->DebugInfo.usNumEvents = 0; for ( ulDebugEventIndex = 0; ulDebugEventIndex < usTempNumEvents; ulDebugEventIndex ++ ) { /* The HOT channel index for the event is stored at offset 0xF2 (word offset) */ ReadParams.ulReadAddress = pSharedInfo->DebugInfo.ulMatrixBaseAddress + ulReadPointer; ReadParams.ulReadAddress += 0xF2 * sizeof(UINT16); ReadParams.pusReadData = &usReadData; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Check if the current debug index is the same as the one found in the event. */ if ( usReadData != pSharedInfo->DebugInfo.usCurrentDebugChanIndex ) pSharedInfo->DebugInfo.usNumEvents = 0; /* As soon as we hit another channel, we reset the number of valid events. */ else pSharedInfo->DebugInfo.usNumEvents++; /* If this event was valid.. */ if ( pSharedInfo->DebugInfo.usNumEvents != 0 ) { /* The HOT channel timestamp for the event is stored at offset 0x0 (word offset) */ ReadBurstParams.ulReadAddress = pSharedInfo->DebugInfo.ulMatrixBaseAddress + ulReadPointer; ReadBurstParams.ulReadLength = 2; ReadBurstParams.pusReadData = ausWriteData; mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Recreate timestamp at the time of the event. */ ulTimestamp = ( ausWriteData[ 0 ] << 16 ); ulTimestamp |= ausWriteData[ 1 ]; /* TDM time for 1 event (512 ms) */ ulTimestamp = ( ulTimestamp >> 12 ); ulDiff = ulTimestamp - ulLastTimestamp; /* Check if difference makes some sense. */ if ( pSharedInfo->DebugInfo.usNumEvents > 1 ) { /* Check if the current timestamp is one less then the previous one. */ if ( ulDiff != 1 ) { pSharedInfo->DebugInfo.usNumEvents = 0; /* If it is not a difference of 1, throw this event. */ } ulLastTimestamp = ulTimestamp; } else { ulLastTimestamp = ulTimestamp; } } /* Increment read pointer to get next event. */ ulReadPointer = ( ulReadPointer + pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ) % ( ( pSharedInfo->DebugInfo.usMatrixCBMask + 1 ) * pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ); } /* In heavy mode, the AF log pointer is retrieved. */ if ( ( pSharedInfo->DebugInfo.usNumEvents >= 2 ) && ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S ) || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S ) || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_CORE_DUMP ) ) ) { /* The latest AF log write pointer is at the latest matrix event. */ ReadParams.ulReadAddress = pSharedInfo->DebugInfo.ulMatrixBaseAddress + ( ( pSharedInfo->DebugInfo.usChipDebugEventWritePtr & pSharedInfo->DebugInfo.usMatrixCBMask ) * 1024 ); /* To get the AF log write pointer, which is at offset pSharedInfo->ImageInfo.ulAfWritePtrByteOffset. */ ReadParams.ulReadAddress += pSharedInfo->DebugInfo.ulAfWritePtrByteOffset; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; pSharedInfo->DebugInfo.usAfLogWritePtr = usReadData; /* The AF event read pointer is the AF write pointer +4096 */ /* This will make sure we do not get mixed up and fetch events that have */ /* just been written, but we think are old. */ /* To get the exact AF log pointer, the API would have to wait 512 milliseconds to make */ /* sure logging had stopped. This is not required since missing a few last events is not */ /* important at this point (the user knows that valid data has already been recorded). */ pSharedInfo->DebugInfo.usLastAfLogReadPtr = (UINT16)( ( pSharedInfo->DebugInfo.usAfLogWritePtr + 4096 ) & 0xFFFF ); /* Note that if the chip has just been booted, some of the AF events might not be initialized. */ } else { pSharedInfo->DebugInfo.usLastAfLogReadPtr = 0; pSharedInfo->DebugInfo.usAfLogWritePtr = 0; } /* To be aligned correctly for the bursts. */ while ( ( pSharedInfo->DebugInfo.usLastAfLogReadPtr % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE / 8 ) ) != 0 ) pSharedInfo->DebugInfo.usLastAfLogReadPtr++; /* Remember the data mode for later checks. Also, the user cannot change this "mode". */ pSharedInfo->DebugInfo.ulCurrentGetDataMode = f_pGetData->ulGetDataMode; /* Remember that we are currently dumping. */ pSharedInfo->DebugInfo.fDebugDataBeingDumped = TRUE; } else { /* Check that the user did not change the current data mode. */ if ( pSharedInfo->DebugInfo.ulCurrentGetDataMode != f_pGetData->ulGetDataMode ) return cOCT6100_ERR_DEBUG_GET_DATA_MODE_CANNOT_CHANGE; } /* Check if this is the first pass here. */ if ( pSharedInfo->DebugInfo.ulDebugDataTotalNumBytes == cOCT6100_INVALID_VALUE ) { /* Calculate how many bytes of data will be returned with respect to the selected data content. */ /* Check what content type the user requested. */ if ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) { /* Remember first AF Event Read Pointer. */ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->DebugInfo.usLastAfLogReadPtr ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->DebugInfo.usLastAfLogReadPtr >> 8 ) & 0xFF ); /* Remember the AF Event Write Pointer. */ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->DebugInfo.usAfLogWritePtr ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->DebugInfo.usAfLogWritePtr >> 8 ) & 0xFF ); /* Remember law and hot channel */ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( pChanEntry->TdmConfig.bySinPcmLaw | ( ( pSharedInfo->DebugInfo.usCurrentDebugChanIndex >> 2 ) & 0xFE ) ); f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( pChanEntry->TdmConfig.bySoutPcmLaw ); /* Insert light or heavy mode in array. */ if ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S_LITE ) || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S_LITE ) ) { f_pGetData->pbyData[ ulUserBufWriteIndex - 1 ] |= 0x80; } f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( pChanEntry->TdmConfig.byRinPcmLaw | ( ( pSharedInfo->DebugInfo.usCurrentDebugChanIndex & 0x1F ) << 3 ) ); /* Remember usNumEvents */ f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->DebugInfo.usNumEvents ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->DebugInfo.usNumEvents >> 8 ) & 0xFF ); } /* Last indexes set to '0'! */ pSharedInfo->DebugInfo.usLastDebugEventIndex = 0; pSharedInfo->DebugInfo.ulLastPcmSampleIndex = 0; /* No tone event has been retrieved. */ pSharedInfo->DebugInfo.usLastToneEventIndex = 0; /* The version strings have not yet been copied. */ pSharedInfo->DebugInfo.fImageVersionCopied = FALSE; pSharedInfo->DebugInfo.fApiVersionCopied = FALSE; /* The core dump flag has not been set yet. */ pSharedInfo->DebugInfo.fCoreDumped = FALSE; pSharedInfo->DebugInfo.ulLastMemoryOffset = 0; /* Estimate the total size of the buffer that will be returned. */ f_pGetData->ulTotalNumBytes = ulUserBufWriteIndex; /* If the full content is requested, add all the debug data. */ if ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) { /* Add the matrix events. */ if ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S ) || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S ) || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_CORE_DUMP ) ) { /* Heavy mode! Grab everything! */ f_pGetData->ulTotalNumBytes += pSharedInfo->DebugInfo.usNumEvents * pSharedInfo->DebugInfo.ulDebugChanStatsByteSize; } else { /* Lite mode! Only the most important stuff. */ f_pGetData->ulTotalNumBytes += pSharedInfo->DebugInfo.usNumEvents * pSharedInfo->DebugInfo.ulDebugChanLiteStatsByteSize; } /* Add the PCM samples. */ f_pGetData->ulTotalNumBytes += pSharedInfo->DebugInfo.usNumEvents * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize * 3; /* If requested, add the AF log events. */ if ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S ) || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S ) || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_CORE_DUMP ) ) { f_pGetData->ulTotalNumBytes += (UINT32)( ( pSharedInfo->DebugInfo.usAfLogWritePtr - pSharedInfo->DebugInfo.usLastAfLogReadPtr ) & 0xFFFF ) * 16; } /* Add the tone events strings. */ f_pGetData->ulTotalNumBytes += cOCT6100_TLV_MAX_TONE_NAME_SIZE * pSharedInfo->ImageInfo.byNumToneDetectors; /* Add the image version string. */ f_pGetData->ulTotalNumBytes += 512; /* Add the API version string. */ f_pGetData->ulTotalNumBytes += sizeof( cOCT6100_API_VERSION ); /* If core dumping, must add the size of the memory regions that will be returned to the user. */ if ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_CORE_DUMP ) { /* Internal memories. */ f_pGetData->ulTotalNumBytes += 0x300000; /* External memory. */ f_pGetData->ulTotalNumBytes += ( pSharedInfo->MemoryMap.ulFreeMemBaseAddress - cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ); } } else /* if ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) */ { /* Add one PCM stream. */ f_pGetData->ulTotalNumBytes += pSharedInfo->DebugInfo.usNumEvents * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize; } /* Save this in the instance for further calls. */ pSharedInfo->DebugInfo.ulDebugDataTotalNumBytes = f_pGetData->ulTotalNumBytes; /* Calculate remaining bytes. All the bytes for now! */ f_pGetData->ulRemainingNumBytes = f_pGetData->ulTotalNumBytes; /* Save this in the instance for the next calls. */ pSharedInfo->DebugInfo.ulDebugDataRemainingNumBytes = f_pGetData->ulRemainingNumBytes; } else { f_pGetData->ulTotalNumBytes = pSharedInfo->DebugInfo.ulDebugDataTotalNumBytes; } /* Calculate the event read pointer. */ ulReadPointer = ( ( pSharedInfo->DebugInfo.usChipDebugEventWritePtr - pSharedInfo->DebugInfo.usNumEvents ) & pSharedInfo->DebugInfo.usMatrixCBMask ) * pSharedInfo->DebugInfo.ulDebugChanStatsByteSize; ulReadPointer += pSharedInfo->DebugInfo.ulDebugChanStatsByteSize * pSharedInfo->DebugInfo.usLastDebugEventIndex; ulReadPointer %= ( ( pSharedInfo->DebugInfo.usMatrixCBMask + 1 ) * pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ); if ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) { /* Copy the debug events in the user buffer. */ for( ulDebugEventIndex = pSharedInfo->DebugInfo.usLastDebugEventIndex; ulDebugEventIndex < pSharedInfo->DebugInfo.usNumEvents; ulDebugEventIndex ++ ) { ReadBurstParams.ulReadAddress = pSharedInfo->DebugInfo.ulMatrixBaseAddress + ulReadPointer; /* Check if we are in light or heavy mode. The burst size is not the same. */ if ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S ) || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S ) || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_CORE_DUMP ) ) { if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) >= pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ) ulNumReads = pSharedInfo->DebugInfo.ulDebugChanStatsByteSize / 2; else break; } else { if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) >= pSharedInfo->DebugInfo.ulDebugChanLiteStatsByteSize ) ulNumReads = pSharedInfo->DebugInfo.ulDebugChanLiteStatsByteSize / 2; else break; } ulTempIndex = 0; while ( ulNumReads != 0 ) { if ( ulNumReads >= pSharedInfo->ChipConfig.usMaxRwAccesses ) ReadBurstParams.ulReadLength = pSharedInfo->ChipConfig.usMaxRwAccesses; else ReadBurstParams.ulReadLength = ulNumReads; /* Set pointer where to write data. */ ReadBurstParams.pusReadData = pSharedInfo->MiscVars.ausSuperArray; mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Copy data byte per byte to avoid endianess problems. */ for ( ulCopyIndex = 0; ulCopyIndex < ReadBurstParams.ulReadLength; ulCopyIndex ++ ) { f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex + ( 2 * ulCopyIndex ) ] = (UINT8)( ReadBurstParams.pusReadData[ ulCopyIndex ] & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex + ( 2 * ulCopyIndex ) + 1 ] = (UINT8)( ( ReadBurstParams.pusReadData[ ulCopyIndex ] >> 8 ) & 0xFF ); } /* Update indexes, temp variables, addresses. */ ulNumReads -= ReadBurstParams.ulReadLength; ulTempIndex += ReadBurstParams.ulReadLength * 2; ReadBurstParams.ulReadAddress += ReadBurstParams.ulReadLength * 2; } /* Store register 0x202 in the event structure. */ f_pGetData->pbyData[ ulUserBufWriteIndex + 255 ] = (UINT8)( pSharedInfo->IntrptManage.usRegister202h & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + 256 ] = (UINT8)( ( pSharedInfo->IntrptManage.usRegister202h >> 8 ) & 0xFF ); /* Increment index. */ if ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S ) || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S ) || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_CORE_DUMP ) ) { ulUserBufWriteIndex += pSharedInfo->DebugInfo.ulDebugChanStatsByteSize; } else { ulUserBufWriteIndex += pSharedInfo->DebugInfo.ulDebugChanLiteStatsByteSize; } /* Increment read pointer to get next event. */ ulReadPointer = ( ulReadPointer + pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ) % ( ( pSharedInfo->DebugInfo.usMatrixCBMask + 1 ) * pSharedInfo->DebugInfo.ulDebugChanStatsByteSize ); /* Save in the instance that one of the events was dumped. */ pSharedInfo->DebugInfo.usLastDebugEventIndex ++; } } /* Check if all debug events have been transfered. */ if ( ( ulDebugEventIndex == pSharedInfo->DebugInfo.usNumEvents ) || ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) ) { /* Fetch all streams per event. */ for ( ulPcmSampleIndex = pSharedInfo->DebugInfo.ulLastPcmSampleIndex; ulPcmSampleIndex < ( (UINT32)pSharedInfo->DebugInfo.usNumEvents * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize ); ulPcmSampleIndex ++ ) { /* Check if enough room for this sample. */ if ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) { if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) < 1 ) break; } else /* if ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) */ { if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) < 3 ) break; } /* Check if must retrieve data from external memory. */ if ( ( ulPcmSampleIndex % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE * 2 ) ) == 0x0 ) { ulReadPointer = ( ( ( pSharedInfo->DebugInfo.usChipDebugEventWritePtr - pSharedInfo->DebugInfo.usNumEvents ) * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize ) & ( pSharedInfo->DebugInfo.usMatrixCBMask * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize ) ); ulReadPointer += ( ulPcmSampleIndex / pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize ) * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize; ulReadPointer &= ( pSharedInfo->DebugInfo.usMatrixCBMask * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize ); ulReadPointer += ulPcmSampleIndex % pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize; /* Retrieve more data from external memory. */ switch ( f_pGetData->ulGetDataContent ) { case cOCT6100_DEBUG_GET_DATA_CONTENT_RIN_PCM: ulStreamIndexMin = 0; ulStreamIndexMax = 1; break; case cOCT6100_DEBUG_GET_DATA_CONTENT_SIN_PCM: ulStreamIndexMin = 1; ulStreamIndexMax = 2; break; case cOCT6100_DEBUG_GET_DATA_CONTENT_SOUT_PCM: ulStreamIndexMin = 2; ulStreamIndexMax = 3; break; case cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE: default: ulStreamIndexMin = 0; ulStreamIndexMax = 3; break; } for ( ulStreamIndex = ulStreamIndexMin; ulStreamIndex < ulStreamIndexMax; ulStreamIndex ++ ) { ReadBurstParams.ulReadAddress = pSharedInfo->MemoryMap.ulChanMainMemBase; /* To get right channel information. */ ReadBurstParams.ulReadAddress += ( ( pSharedInfo->DebugInfo.usRecordMemIndex + 2 ) * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->DebugInfo.ulAfEventCbByteSize; /* To get correct stream. */ ReadBurstParams.ulReadAddress += ( ( pSharedInfo->DebugInfo.usMatrixCBMask + 1 ) * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize * ulStreamIndex ); /* PCM sample pointer in that stream. */ ReadBurstParams.ulReadAddress += ulReadPointer; /* As much as we can for the burst. */ ulTempIndex = 0; ulNumReads = cOCT6100_INTERNAL_SUPER_ARRAY_SIZE; while ( ulNumReads != 0 ) { if ( ulNumReads >= pSharedInfo->ChipConfig.usMaxRwAccesses ) ReadBurstParams.ulReadLength = pSharedInfo->ChipConfig.usMaxRwAccesses; else ReadBurstParams.ulReadLength = ulNumReads; /* Set pointer where to write data. */ if ( ulStreamIndex == 0 ) ReadBurstParams.pusReadData = &pSharedInfo->MiscVars.ausSuperArray[ ulTempIndex ]; else if ( ulStreamIndex == 1 ) ReadBurstParams.pusReadData = &pSharedInfo->MiscVars.ausSuperArray1[ ulTempIndex ]; else /* if ( ulStreamIndex == 2 ) */ ReadBurstParams.pusReadData = &pSharedInfo->MiscVars.ausSuperArray2[ ulTempIndex ]; mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Update indexes, temp variables, addresses. */ ulNumReads -= ReadBurstParams.ulReadLength; ulTempIndex += ReadBurstParams.ulReadLength; ReadBurstParams.ulReadAddress += ReadBurstParams.ulReadLength * 2; } } } /* We now have the stream data for all streams for 1 event. */ /* Return what we can to the user. */ if ( ( ulPcmSampleIndex % 2 ) == 0 ) { if ( ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) || ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_RIN_PCM ) ) f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray[ ( ulPcmSampleIndex / 2 ) % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ) ] >> 8 ) & 0xFF ); if ( ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) || ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_SIN_PCM ) ) f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray1[ ( ulPcmSampleIndex / 2 ) % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ) ] >> 8 ) & 0xFF ); if ( ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) || ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_SOUT_PCM ) ) f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray2[ ( ulPcmSampleIndex / 2 ) % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ) ] >> 8 ) & 0xFF ); } else /* if ( ulPcmSampleIndex % 2 == 1 ) */ { if ( ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) || ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_RIN_PCM ) ) f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray[ ( ulPcmSampleIndex / 2 ) % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ) ] >> 0 ) & 0xFF ); if ( ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) || ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_SIN_PCM ) ) f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray1[ ( ulPcmSampleIndex / 2 ) % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ) ] >> 0 ) & 0xFF ); if ( ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) || ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_SOUT_PCM ) ) f_pGetData->pbyData[ ulUserBufWriteIndex++ ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray2[ ( ulPcmSampleIndex / 2 ) % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ) ] >> 0 ) & 0xFF ); } pSharedInfo->DebugInfo.ulLastPcmSampleIndex++; } /* Check if we are done dumping the PCM samples! */ if ( pSharedInfo->DebugInfo.ulLastPcmSampleIndex == ( (UINT32)pSharedInfo->DebugInfo.usNumEvents * pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize ) ) { if ( f_pGetData->ulGetDataContent == cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) { /* Go for the AF events. The AF events are only copied in heavy mode. */ if ( ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_16S ) || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_120S ) || ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_CORE_DUMP ) ) { while ( pSharedInfo->DebugInfo.usLastAfLogReadPtr != pSharedInfo->DebugInfo.usAfLogWritePtr ) { /* Check if enough room for an event. */ if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) < 16 ) break; /* Check if must fill our buffer. */ if ( ( pSharedInfo->DebugInfo.usLastAfLogReadPtr % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE / 8 ) ) == 0x0 ) { ulNumAfEvents = ( pSharedInfo->DebugInfo.usAfLogWritePtr - pSharedInfo->DebugInfo.usLastAfLogReadPtr ) & 0xFFFF; /* Check for the size of the available buffer. */ if ( ulNumAfEvents > ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE / 8 ) ) ulNumAfEvents = ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE / 8 ); /* Start at channel main base address. */ ReadBurstParams.ulReadAddress = pSharedInfo->MemoryMap.ulChanMainMemBase; /* To get right channel information. */ ReadBurstParams.ulReadAddress += ( ( pSharedInfo->DebugInfo.usRecordMemIndex + 2 ) * pSharedInfo->MemoryMap.ulChanMainMemSize ); /* To get the right AF log. */ ReadBurstParams.ulReadAddress += ( pSharedInfo->DebugInfo.usLastAfLogReadPtr * 16 ); ulTempIndex = 0; ulNumReads = ulNumAfEvents * 8; while ( ulNumReads != 0 ) { if ( ulNumReads >= pSharedInfo->ChipConfig.usMaxRwAccesses ) ReadBurstParams.ulReadLength = pSharedInfo->ChipConfig.usMaxRwAccesses; else ReadBurstParams.ulReadLength = ulNumReads; /* Set pointer where to write data. */ ReadBurstParams.pusReadData = &pSharedInfo->MiscVars.ausSuperArray[ ulTempIndex ]; mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Update indexes, temp variables, addresses. */ ulNumReads -= ReadBurstParams.ulReadLength; ulTempIndex += ReadBurstParams.ulReadLength; ReadBurstParams.ulReadAddress += ReadBurstParams.ulReadLength * 2; } } /* Copy data byte per byte to avoid endianess problems. */ for ( ulCopyIndex = 0; ulCopyIndex < 8; ulCopyIndex ++ ) { f_pGetData->pbyData[ ulUserBufWriteIndex + ( 2 * ulCopyIndex ) ] = (UINT8)( pSharedInfo->MiscVars.ausSuperArray[ ( ( pSharedInfo->DebugInfo.usLastAfLogReadPtr % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE / 8 ) ) * 8 ) + ulCopyIndex ] & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ( 2 * ulCopyIndex ) + 1 ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray[ ( ( pSharedInfo->DebugInfo.usLastAfLogReadPtr % ( cOCT6100_INTERNAL_SUPER_ARRAY_SIZE / 8 ) ) * 8 ) + ulCopyIndex ] >> 8 ) & 0xFF ); } ulUserBufWriteIndex += 16; /* Increment AF log read ptr. */ pSharedInfo->DebugInfo.usLastAfLogReadPtr = (UINT16)(( pSharedInfo->DebugInfo.usLastAfLogReadPtr + 1 ) & 0xFFFF ); } } /* Check if we are done with the AF events. */ if ( pSharedInfo->DebugInfo.usLastAfLogReadPtr == pSharedInfo->DebugInfo.usAfLogWritePtr ) { /* Insert the tone event information. */ for ( ulToneEventIndex = pSharedInfo->DebugInfo.usLastToneEventIndex; ulToneEventIndex < pSharedInfo->ImageInfo.byNumToneDetectors; ulToneEventIndex++ ) { if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) < cOCT6100_TLV_MAX_TONE_NAME_SIZE ) break; Oct6100UserMemCopy( &f_pGetData->pbyData[ ulUserBufWriteIndex ], pSharedInfo->ImageInfo.aToneInfo[ ulToneEventIndex ].aszToneName, cOCT6100_TLV_MAX_TONE_NAME_SIZE ); ulUserBufWriteIndex += cOCT6100_TLV_MAX_TONE_NAME_SIZE; pSharedInfo->DebugInfo.usLastToneEventIndex++; } /* If all the tone information has been copied. */ if ( ulToneEventIndex == pSharedInfo->ImageInfo.byNumToneDetectors ) { /* Copy the image version. */ if ( pSharedInfo->DebugInfo.fImageVersionCopied == FALSE ) { if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) >= 512 ) { tOCT6100_CHIP_STATS ChipStats; UINT32 ulTempIndex; Oct6100UserMemCopy( &f_pGetData->pbyData[ ulUserBufWriteIndex ], pSharedInfo->ImageInfo.szVersionNumber, 512 ); /* Get PLL jitter count from external memory. */ if ( pSharedInfo->DebugInfo.fPouchCounter == TRUE ) { ulFeatureBytesOffset = pSharedInfo->MemoryMap.PouchCounterFieldOfst.usDwordOffset * 4; ulFeatureBitOffset = pSharedInfo->MemoryMap.PouchCounterFieldOfst.byBitOffset; ulFeatureFieldLength = pSharedInfo->MemoryMap.PouchCounterFieldOfst.byFieldSize; ulResult = Oct6100ApiReadDword( f_pApiInstance, cOCT6100_POUCH_BASE + ulFeatureBytesOffset, &ulTempData ); /* Create the mask to retrieve the appropriate value. */ mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask ); /* Mask data. */ ulTempData &= ulMask; /* Move to right position. */ ulTempData = ulTempData >> ulFeatureBitOffset; f_pGetData->pbyData[ ulUserBufWriteIndex + 510 ] = (UINT8)( ( ulTempData >> 8 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + 511 ] = (UINT8)( ( ulTempData >> 0 ) & 0xFF ); } /* Add "ISR is not called" bit. */ if ( pSharedInfo->IntrptManage.fIsrCalled == FALSE ) { f_pGetData->pbyData[ ulUserBufWriteIndex + 510 ] |= 0x80; } /* Set the hardware revision number. */ ulTempIndex = 509; f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( pSharedInfo->MiscVars.usChipRevision ) & 0xFF ); Oct6100ChipGetStatsDef( &ChipStats ); ulResult = Oct6100ChipGetStatsSer( f_pApiInstance, &ChipStats ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ChipStats.ulNumberChannels & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulNumberChannels >> 8 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( f_pApiInstance->pSharedInfo->MiscVars.ulNumActiveChannels & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( f_pApiInstance->pSharedInfo->MiscVars.ulNumActiveChannels >> 8 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ChipStats.ulNumberTsiCncts & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulNumberTsiCncts >> 8 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ChipStats.ulNumberConfBridges & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulNumberConfBridges >> 8 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ChipStats.ulNumberPlayoutBuffers & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulNumberPlayoutBuffers >> 8 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ChipStats.ulPlayoutFreeMemSize & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulPlayoutFreeMemSize >> 8 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulPlayoutFreeMemSize >> 16 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulPlayoutFreeMemSize >> 24 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ChipStats.ulNumberPhasingTssts & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulNumberPhasingTssts >> 8 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ChipStats.ulNumberAdpcmChannels & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulNumberAdpcmChannels >> 8 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ChipStats.ulInternalReadTimeoutCount & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulInternalReadTimeoutCount >> 8 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulInternalReadTimeoutCount >> 16 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulInternalReadTimeoutCount >> 24 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ChipStats.ulSdramRefreshTooLateCount & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulSdramRefreshTooLateCount >> 8 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulSdramRefreshTooLateCount >> 16 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulSdramRefreshTooLateCount >> 24 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ChipStats.ulPllJitterErrorCount & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulPllJitterErrorCount >> 8 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulPllJitterErrorCount >> 16 ) & 0xFF ); f_pGetData->pbyData[ ulUserBufWriteIndex + ulTempIndex-- ] = (UINT8)( ( ChipStats.ulPllJitterErrorCount >> 24 ) & 0xFF ); ulTempIndex -= 5; /* Update write pointer. */ ulUserBufWriteIndex += 512; /* The version has been copied. */ pSharedInfo->DebugInfo.fImageVersionCopied = TRUE; } } /* If the image version has been copied, proceed with the API version. */ if ( pSharedInfo->DebugInfo.fImageVersionCopied == TRUE ) { if ( pSharedInfo->DebugInfo.fApiVersionCopied == FALSE ) { if ( ( f_pGetData->ulMaxBytes - ulUserBufWriteIndex ) >= sizeof(cOCT6100_API_VERSION) ) { Oct6100UserMemCopy( &f_pGetData->pbyData[ ulUserBufWriteIndex ], cOCT6100_API_VERSION, sizeof(cOCT6100_API_VERSION) ); ulUserBufWriteIndex += sizeof(cOCT6100_API_VERSION); /* The API version has been copied. */ pSharedInfo->DebugInfo.fApiVersionCopied = TRUE; } } } /* Check for the core dump content. */ if ( pSharedInfo->DebugInfo.fApiVersionCopied == TRUE ) { if ( f_pGetData->ulGetDataMode == cOCT6100_DEBUG_GET_DATA_MODE_CORE_DUMP ) { if ( pSharedInfo->DebugInfo.fCoreDumped == FALSE ) { ulResult = Oct6100DebugCoreDump( f_pApiInstance, f_pGetData, &ulUserBufWriteIndex ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } } else { /* Even though it was not requested, set the flag to pass through the next gate. */ pSharedInfo->DebugInfo.fCoreDumped = TRUE; } } } /* Check if we are done! */ if ( ( pSharedInfo->DebugInfo.fApiVersionCopied == TRUE ) && ( pSharedInfo->DebugInfo.fCoreDumped == TRUE ) ) { /* Done dumping. */ /* Reset data being dumped flag. */ pSharedInfo->DebugInfo.fDebugDataBeingDumped = FALSE; /* Reset data recording in the chip. */ WriteBurstParams.ulWriteAddress = pSharedInfo->DebugInfo.ulHotChannelSelectBaseAddress; WriteBurstParams.ulWriteLength = 2; WriteBurstParams.pusWriteData = pSharedInfo->DebugInfo.ausHotChannelData; mOCT6100_DRIVER_WRITE_BURST_API( WriteBurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; fResetRemainingDataFlag = TRUE; } } } else /* if ( f_pGetData->ulGetDataContent != cOCT6100_DEBUG_GET_DATA_CONTENT_COMPLETE ) */ { fResetRemainingDataFlag = TRUE; pSharedInfo->DebugInfo.fDebugDataBeingDumped = FALSE; } } } /* Return number of valid bytes in buffer to user. */ f_pGetData->ulValidNumBytes = ulUserBufWriteIndex; /* Update remaining bytes. */ pSharedInfo->DebugInfo.ulDebugDataRemainingNumBytes -= ulUserBufWriteIndex; /* Return remaining bytes. */ f_pGetData->ulRemainingNumBytes = pSharedInfo->DebugInfo.ulDebugDataRemainingNumBytes; /* Return total number of bytes. */ f_pGetData->ulTotalNumBytes = pSharedInfo->DebugInfo.ulDebugDataTotalNumBytes; /* Check if we are done dumping the requested content. */ if ( fResetRemainingDataFlag == TRUE ) pSharedInfo->DebugInfo.ulDebugDataTotalNumBytes = cOCT6100_INVALID_VALUE; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100DebugCoreDump Description: Called to generate debug core dump information. ------------------------------------------------------------------------------- | 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_pGetData Pointer to a tOCT6100_DEBUG_GET_DATA structure. f_pulUserBufWriteIndex User buffer write index. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100DebugCoreDump( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN OUT tPOCT6100_DEBUG_GET_DATA f_pGetData, IN OUT PUINT32 f_pulUserBufWriteIndex ) { tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_READ_BURST_PARAMS ReadBurstParams; tOCT6100_READ_PARAMS ReadParams; UINT32 ulResult; UINT32 ulNumReads; UINT32 ulTempIndex; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; ReadBurstParams.pProcessContext = f_pApiInstance->pProcessContext; ReadBurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* All registers. */ if ( pSharedInfo->DebugInfo.ulLastMemoryOffset < 0x800 ) { /* Here we assume cOCT6100_INTERNAL_SUPER_ARRAY_SIZE can contain all the registers. */ /* Check if must retrieve data from the hardware. */ if ( pSharedInfo->DebugInfo.ulLastMemoryOffset == 0 ) { /* Clear whole array */ Oct6100UserMemSet( pSharedInfo->MiscVars.ausSuperArray, 0, sizeof( pSharedInfo->MiscVars.ausSuperArray ) ); /* Retrieve all registers data from the hardware. */ /* Start at the CPU registers (0x100). */ ReadParams.ulReadAddress = 0x100; /* As much as we can for the burst. */ ulTempIndex = 0x100 / 2; /* Start indexing at the CPU registers (0x100) */ ulNumReads = 0x380; /* Up to 0x800 */ while ( ulNumReads != 0 ) { /* Set pointer where to write data. */ ReadParams.pusReadData = &pSharedInfo->MiscVars.ausSuperArray[ ulTempIndex ]; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Update indexes, temp variables, addresses. */ ulNumReads--; ulTempIndex++; ReadParams.ulReadAddress += 2; /* Skip range 0x400 to 0x500 -- Cannot read between 0x400 & 0x500. */ if ( ReadParams.ulReadAddress == 0x400 ) { ReadParams.ulReadAddress += 0x100; ulTempIndex += 0x80; ulNumReads -= 0x80; } } } for ( ; pSharedInfo->DebugInfo.ulLastMemoryOffset < 0x800; pSharedInfo->DebugInfo.ulLastMemoryOffset +=2 ) { /* Check if enough room for this word. */ if ( ( f_pGetData->ulMaxBytes - *f_pulUserBufWriteIndex ) < 2 ) break; /* Copy data byte per byte to avoid endianess problems. */ f_pGetData->pbyData[ *f_pulUserBufWriteIndex ] = (UINT8)( pSharedInfo->MiscVars.ausSuperArray[ ( pSharedInfo->DebugInfo.ulLastMemoryOffset / 2 ) % cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ] & 0xFF ); f_pGetData->pbyData[ *f_pulUserBufWriteIndex + 1 ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray[ ( pSharedInfo->DebugInfo.ulLastMemoryOffset / 2 ) % cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ] >> 8 ) & 0xFF ); /* Update indexes. */ *f_pulUserBufWriteIndex += 2; } } /* All internal memories */ if ( pSharedInfo->DebugInfo.ulLastMemoryOffset < 0x300000 ) { ulResult = Oct6100DebugCoreDumpMemory( f_pApiInstance, f_pGetData, f_pulUserBufWriteIndex, 0x800, 0x300000 ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } /* All external memory, up until the beginning of the free memory pool. */ if ( pSharedInfo->DebugInfo.ulLastMemoryOffset < pSharedInfo->MemoryMap.ulFreeMemBaseAddress ) { /* External memory. */ ulResult = Oct6100DebugCoreDumpMemory( f_pApiInstance, f_pGetData, f_pulUserBufWriteIndex, cOCT6100_EXTERNAL_MEM_BASE_ADDRESS, pSharedInfo->MemoryMap.ulFreeMemBaseAddress ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; } if ( pSharedInfo->DebugInfo.ulLastMemoryOffset >= pSharedInfo->MemoryMap.ulFreeMemBaseAddress ) { /* Done here. */ pSharedInfo->DebugInfo.fCoreDumped = TRUE; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100DebugCoreDumpMemory Description: Called to read a memory region. ------------------------------------------------------------------------------- | 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_pGetData Pointer to a tOCT6100_DEBUG_GET_DATA structure. f_pulUserBufWriteIndex User buffer write index. f_ulMemOffsetBottom Memory address, bottom. f_ulMemOffsetTop Memory address, top. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100DebugCoreDumpMemory( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN OUT tPOCT6100_DEBUG_GET_DATA f_pGetData, IN OUT PUINT32 f_pulUserBufWriteIndex, IN UINT32 f_ulMemOffsetBottom, IN UINT32 f_ulMemOffsetTop ) { tPOCT6100_SHARED_INFO pSharedInfo; tOCT6100_READ_BURST_PARAMS ReadBurstParams; UINT32 ulResult; UINT32 ulNumReads; UINT32 ulTempIndex; /* Get local pointer(s). */ pSharedInfo = f_pApiInstance->pSharedInfo; ReadBurstParams.pProcessContext = f_pApiInstance->pProcessContext; ReadBurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId; /* Check if enough room for at least 1 word. */ if ( ( f_pGetData->ulMaxBytes - *f_pulUserBufWriteIndex ) < 2 ) return cOCT6100_ERR_OK; /* Make sure we are starting at the right offset.. Sometimes memory regions are not continuous. */ if ( pSharedInfo->DebugInfo.ulLastMemoryOffset < f_ulMemOffsetBottom ) pSharedInfo->DebugInfo.ulLastMemoryOffset = f_ulMemOffsetBottom; for ( ; pSharedInfo->DebugInfo.ulLastMemoryOffset < f_ulMemOffsetTop; pSharedInfo->DebugInfo.ulLastMemoryOffset +=2 ) { /* Check if enough room for this word. */ if ( ( f_pGetData->ulMaxBytes - *f_pulUserBufWriteIndex ) < 2 ) break; /* Check if must retrieve data from the hardware. */ if ( ( pSharedInfo->DebugInfo.ulLastMemoryOffset / 2 ) % cOCT6100_INTERNAL_SUPER_ARRAY_SIZE == 0 ) { ReadBurstParams.ulReadAddress = pSharedInfo->DebugInfo.ulLastMemoryOffset; /* Some internal memory regions cannot be read. Check for these here. */ if ( (( ReadBurstParams.ulReadAddress >= 0x14a80 ) && ( ReadBurstParams.ulReadAddress < 0x26000 )) || (( ReadBurstParams.ulReadAddress >= 0x26640 ) && ( ReadBurstParams.ulReadAddress < 0x28000 )) || (( ReadBurstParams.ulReadAddress >= 0x2AA00 ) && ( ReadBurstParams.ulReadAddress < 0x220000 )) || (( ReadBurstParams.ulReadAddress >= 0x235000 ) && ( ReadBurstParams.ulReadAddress < 0x240000 )) || (( ReadBurstParams.ulReadAddress >= 0x255000 ) && ( ReadBurstParams.ulReadAddress < 0x260000 )) || (( ReadBurstParams.ulReadAddress >= 0x26a800 ) && ( ReadBurstParams.ulReadAddress < 0x280000 )) || (( ReadBurstParams.ulReadAddress >= 0x285400 ) && ( ReadBurstParams.ulReadAddress < 0x8000000 ))) { /* Region cannot be read. */ Oct6100UserMemSet( pSharedInfo->MiscVars.ausSuperArray, 0, cOCT6100_INTERNAL_SUPER_ARRAY_SIZE * sizeof( UINT16 ) ); } else { /* As much as we can for the burst. */ ulTempIndex = 0x0; ulNumReads = cOCT6100_INTERNAL_SUPER_ARRAY_SIZE; while ( ulNumReads != 0 ) { /* Set read burst size. */ if ( ulNumReads >= pSharedInfo->ChipConfig.usMaxRwAccesses ) ReadBurstParams.ulReadLength = pSharedInfo->ChipConfig.usMaxRwAccesses; else ReadBurstParams.ulReadLength = ulNumReads; /* Set pointer where to write data. */ ReadBurstParams.pusReadData = &pSharedInfo->MiscVars.ausSuperArray[ ulTempIndex ]; mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Update indexes, temp variables, addresses. */ ulNumReads -= ReadBurstParams.ulReadLength; ulTempIndex += ReadBurstParams.ulReadLength; ReadBurstParams.ulReadAddress += ReadBurstParams.ulReadLength * 2; } } } /* Copy data byte per byte to avoid endianness problems. */ f_pGetData->pbyData[ *f_pulUserBufWriteIndex ] = (UINT8)( pSharedInfo->MiscVars.ausSuperArray[ ( pSharedInfo->DebugInfo.ulLastMemoryOffset / 2 ) % cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ] & 0xFF ); f_pGetData->pbyData[ *f_pulUserBufWriteIndex + 1 ] = (UINT8)( ( pSharedInfo->MiscVars.ausSuperArray[ ( pSharedInfo->DebugInfo.ulLastMemoryOffset / 2 ) % cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ] >> 8 ) & 0xFF ); /* Update indexes. */ *f_pulUserBufWriteIndex += 2; } return cOCT6100_ERR_OK; }