/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: oct6100_miscellaneous.c Copyright (c) 2001-2011 Octasic Inc. Description: This file contains miscellaneous functions used in various files. 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: 36 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /***************************** INCLUDE FILES *******************************/ #include "octdef.h" #include "oct6100api/oct6100_defines.h" #include "oct6100api/oct6100_errors.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_channel_pub.h" #include "oct6100_chip_open_priv.h" #include "oct6100_channel_priv.h" #include "oct6100_miscellaneous_priv.h" /**************************** PRIVATE FUNCTIONS ****************************/ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWaitForTime Description: Waits for the specified amount of time. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_aulWaitTime[ 2 ] The amout of time to be waited, in microseconds. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiWaitForTime( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_aulWaitTime[ 2 ] ) { tOCT6100_GET_TIME StartTime; tOCT6100_GET_TIME CurrentTime; UINT32 aulTimeDelta[ 2 ]; UINT32 ulResult; UINT16 usTempVar; BOOL fConditionFlag = TRUE; /* Copy the process context. */ StartTime.pProcessContext = f_pApiInstance->pProcessContext; CurrentTime.pProcessContext = f_pApiInstance->pProcessContext; ulResult = Oct6100UserGetTime( &StartTime ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; while ( fConditionFlag ) { ulResult = Oct6100UserGetTime( &CurrentTime ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = octapi_lm_subtract( CurrentTime.aulWallTimeUs, 1, StartTime.aulWallTimeUs, 1, aulTimeDelta, 1, &usTempVar ); if ( ulResult != cOCT6100_ERR_OK ) return cOCT6100_ERR_FATAL_37; if ( aulTimeDelta[ 1 ] >= f_aulWaitTime[ 1 ] && aulTimeDelta[ 0 ] >= f_aulWaitTime[ 0 ] ) fConditionFlag = FALSE; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWaitForPcRegisterBit Description: Polls the specified PC register bit. The function exits once the bit is cleared by hardware, or when the specified timeout period has been expired. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulPcRegAdd Address of the register containing the PC bit. f_ulPcBitNum Number of the PC bit within the register. f_ulValue Expected value of the bit. f_ulTimeoutUs The timeout period, in usec. f_pfBitEqual Pointer to the result of the bit comparison. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiWaitForPcRegisterBit( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulPcRegAdd, IN UINT32 f_ulPcBitNum, IN UINT32 f_ulValue, IN UINT32 f_ulTimeoutUs, OUT PBOOL f_pfBitEqual ) { tOCT6100_READ_PARAMS ReadParams; tOCT6100_GET_TIME StartTime; tOCT6100_GET_TIME TimeoutTime; tOCT6100_GET_TIME CurrentTime; UINT32 ulResult; UINT16 usReadData; BOOL fConditionFlag = TRUE; /* Copy the process context. */ StartTime.pProcessContext = f_pApiInstance->pProcessContext; CurrentTime.pProcessContext = f_pApiInstance->pProcessContext; /* Get the current system time. */ ulResult = Oct6100UserGetTime( &StartTime ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Mark the bit as not being equal, for now. */ *f_pfBitEqual = FALSE; /* Determine the time at which the timeout has expired. */ ulResult = octapi_lm_add( StartTime.aulWallTimeUs, 1, &f_ulTimeoutUs, 0, TimeoutTime.aulWallTimeUs, 1 ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Prepare read structure. */ ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ReadParams.ulReadAddress = f_ulPcRegAdd; ReadParams.pusReadData = &usReadData; /* Read the PC bit while the timeout period hasn't expired. */ while ( fConditionFlag ) { /* Read the current time again to check for timeout. */ ulResult = Oct6100UserGetTime( &CurrentTime ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; ulResult = Oct6100UserDriverReadApi( &ReadParams ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; if ( ( UINT16 )((usReadData >> f_ulPcBitNum) & 0x1) == ( UINT16 )f_ulValue ) { /* Mark the bit as being equal. */ *f_pfBitEqual = TRUE; fConditionFlag = FALSE; } if ( CurrentTime.aulWallTimeUs[ 1 ] > TimeoutTime.aulWallTimeUs[ 1 ] || (CurrentTime.aulWallTimeUs[ 1 ] == TimeoutTime.aulWallTimeUs[ 1 ] && CurrentTime.aulWallTimeUs[ 0 ] >= TimeoutTime.aulWallTimeUs[ 0 ]) ) fConditionFlag = FALSE; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiReadDword Description: Read a DWORD at specified address in external memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulAddress DWORD address where to read. f_pulReadData Resulting data. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiReadDword( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulAddress, OUT PUINT32 f_pulReadData ) { tOCT6100_READ_PARAMS ReadParams; UINT16 usReadData; UINT32 ulResult; UINT32 ulTempData; ReadParams.pProcessContext = f_pApiInstance->pProcessContext; ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; ReadParams.pusReadData = &usReadData; /*==================================================================================*/ /* Read the first 16 bits. */ ReadParams.ulReadAddress = f_ulAddress; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulTempData = usReadData << 16; /* Read the last 16 bits. */ ReadParams.ulReadAddress += 2; mOCT6100_DRIVER_READ_API( ReadParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Save data. */ ulTempData |= usReadData; /*==================================================================================*/ /* Return the read value.*/ *f_pulReadData = ulTempData; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiWriteDword Description: Write a DWORD at specified address in external memory. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pApiInstance Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. f_ulAddress DWORD address where to write. f_ulWriteData DWORD data to write. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiWriteDword( IN OUT tPOCT6100_INSTANCE_API f_pApiInstance, IN UINT32 f_ulAddress, IN UINT32 f_ulWriteData ) { tOCT6100_WRITE_PARAMS WriteParams; UINT32 ulResult; WriteParams.pProcessContext = f_pApiInstance->pProcessContext; WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId; /* Write the first 16 bits. */ WriteParams.ulWriteAddress = f_ulAddress; WriteParams.usWriteData = (UINT16)((f_ulWriteData >> 16) & 0xFFFF); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Write the last word. */ WriteParams.ulWriteAddress += 2; WriteParams.usWriteData = (UINT16)(f_ulWriteData & 0xFFFF); mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiCreateFeatureMask Description: ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_ulFieldSize Size of the field, in bits. f_ulFieldBitOffset Bit offset, from the least significant bit. f_pulFieldMask Resulting mask. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ VOID Oct6100ApiCreateFeatureMask( IN UINT32 f_ulFieldSize, IN UINT32 f_ulFieldBitOffset, OUT PUINT32 f_pulFieldMask ) { UINT32 ulMask; UINT32 i; ulMask = 0; /* Create the mask based on the field size. */ for ( i = 0; i < f_ulFieldSize; i++ ) { ulMask <<= 1; ulMask |= 1; } /* Once the mask is of the desired size, offset it to fit the field */ /* within the DWORD read. */ ulMask <<= f_ulFieldBitOffset; /* Return the mask. */ *f_pulFieldMask = ulMask; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiStrStr Description: OCT6100 API version of strstr() ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pszSource Source string to analyze. f_pszString String to look for. f_pszLastCharPtr Last character in the source string. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ PUINT8 Oct6100ApiStrStr( IN PUINT8 f_pszSource, IN PUINT8 f_pszString, IN PUINT8 f_pszLastCharPtr ) { UINT32 ulCurrentPos; UINT32 ulStringLength; UINT32 ulNumMatchingCharFound = 0; PUINT8 pchFirstChar = NULL; UINT32 ulSourceLength; if ( f_pszLastCharPtr < f_pszSource ) return NULL; ulSourceLength = (UINT32)( f_pszLastCharPtr - f_pszSource ); ulStringLength = Oct6100ApiStrLen( f_pszString ); for ( ulCurrentPos = 0; ulCurrentPos < ulSourceLength; ulCurrentPos++ ) { /* Check if the character matches. */ if ( f_pszSource[ ulCurrentPos ] == f_pszString[ ulNumMatchingCharFound ] ) { if ( ulNumMatchingCharFound == 0 ) pchFirstChar = ( f_pszSource + ulCurrentPos ); ulNumMatchingCharFound++; /* Check if the whole string matched. */ if ( ulNumMatchingCharFound == ulStringLength ) break; } else if ( ulNumMatchingCharFound != 0 ) { ulNumMatchingCharFound = 0; /* Reset the search, but take a look at the current character. It might */ /* be the beginning of the string we are looking for. */ if ( f_pszSource[ ulCurrentPos ] == f_pszString[ ulNumMatchingCharFound ] ) { pchFirstChar = ( f_pszSource + ulCurrentPos ); ulNumMatchingCharFound++; /* Check if the whole string matched. */ /* This check must be done in case we have the 1 character strstr */ if ( ulNumMatchingCharFound == ulStringLength ) break; } } } if ( ulCurrentPos == ulSourceLength ) return NULL; else return pchFirstChar; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiStrLen Description: OCT6100 API version of strlen() ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_pszString Source string to count length of. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiStrLen( IN PUINT8 f_pszString ) { UINT32 ulCount = 0; while( f_pszString[ ulCount ] != '\0' ) ulCount++; return ulCount; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiAsciiToHex Description: Convert an ASCII character to an hexadecimal value. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_chCharacter ASCII character to convert. f_pulValue Resulting hexadecimal value. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiAsciiToHex( IN UINT8 f_chCharacter, OUT PUINT32 f_pulValue ) { switch ( f_chCharacter ) { case '0': (*f_pulValue) = 0x0; break; case '1': (*f_pulValue) = 0x1; break; case '2': (*f_pulValue) = 0x2; break; case '3': (*f_pulValue) = 0x3; break; case '4': (*f_pulValue) = 0x4; break; case '5': (*f_pulValue) = 0x5; break; case '6': (*f_pulValue) = 0x6; break; case '7': (*f_pulValue) = 0x7; break; case '8': (*f_pulValue) = 0x8; break; case '9': (*f_pulValue) = 0x9; break; case 'A': case 'a': (*f_pulValue) = 0xA; break; case 'B': case 'b': (*f_pulValue) = 0xB; break; case 'C': case 'c': (*f_pulValue) = 0xC; break; case 'D': case 'd': (*f_pulValue) = 0xD; break; case 'E': case 'e': (*f_pulValue) = 0xE; break; case 'F': case 'f': (*f_pulValue) = 0xF; break; default: (*f_pulValue) = 0x0; return cOCT6100_ERR_MISC_ASCII_CONVERSION_FAILED; } return cOCT6100_ERR_OK; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiHexToAscii Description: Convert an hexadecimal value to an ASCII character. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_ulNumber Hexadecimal value to convert. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT8 Oct6100ApiHexToAscii( IN UINT32 f_ulNumber ) { if ( f_ulNumber >= 0xA ) return (UINT8)( 55 + f_ulNumber ); /* Hex values from 0xA to 0xF */ else return (UINT8)( 48 + f_ulNumber ); /* Hex values from 0x0 to 0x9 */ } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: Oct6100ApiRand Description: Random number generator. ------------------------------------------------------------------------------- | Argument | Description ------------------------------------------------------------------------------- f_ulRange Range of the random number to be generated. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ UINT32 Oct6100ApiRand( IN UINT32 f_ulRange ) { static UINT32 ulRandomSeed = 0x12345678; UINT32 ulBit0; UINT32 i, j; UINT16 ulWithinRange = FALSE; UINT32 ulResult = cOCT6100_ERR_OK; UINT16 ulLoop; UINT32 ulRangeMask; UINT32 ulAddedValue; ulRangeMask = 1; ulLoop = TRUE; i = 1; while ( ulLoop ) { ulAddedValue = 2; for ( j = 1; j < i; j++ ) ulAddedValue *= 2; ulRangeMask = ulRangeMask + ulAddedValue; if ( ulRangeMask >= f_ulRange ) ulLoop = FALSE; i++; } while ( !ulWithinRange ) { ulBit0 = ((ulRandomSeed >> 19) & 0x1) ^ ((ulRandomSeed >> 16) & 0x1); ulRandomSeed = ((ulRandomSeed << 1) & 0xFFFFF) | ulBit0; ulResult = ulRandomSeed & ulRangeMask; if ( ulResult <= f_ulRange ) ulWithinRange = TRUE; } return ulResult; }