/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

File: oct6100_chip_open.c

    Copyright (c) 2001-2006 Octasic Inc.
    
Description: 

	This file contains the functions used to power-up the chip according to the
	user's configuration.  Also, the API instance is initialized to reflect the
	desired configuration.

This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API  is 
free software; you can redistribute it and/or modify it under the terms of 
the GNU General Public License as published by the Free Software Foundation; 
either version 2 of the License, or (at your option) any later version.

The OCT6100 GPL API is distributed in the hope that it will be useful, but 
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
for more details. 

You should have received a copy of the GNU General Public License 
along with the OCT6100 GPL API; if not, write to the Free Software 
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.

$Octasic_Release: OCT612xAPI-01.00-PR43 $

$Octasic_Revision: 312 $

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/


/*****************************  INCLUDE FILES  *******************************/

#include "octdef.h"

#include "oct6100api/oct6100_defines.h"
#include "oct6100api/oct6100_errors.h"

#include "apilib/octapi_bt0.h"
#include "apilib/octapi_llman.h"

#include "oct6100api/oct6100_apiud.h"
#include "oct6100api/oct6100_chip_stats_inst.h"
#include "oct6100api/oct6100_tsi_cnct_inst.h"
#include "oct6100api/oct6100_events_inst.h"
#include "oct6100api/oct6100_conf_bridge_inst.h"
#include "oct6100api/oct6100_playout_buf_inst.h"

#include "oct6100api/oct6100_mixer_inst.h"
#include "oct6100api/oct6100_channel_inst.h"
#include "oct6100api/oct6100_adpcm_chan_inst.h"
#include "oct6100api/oct6100_phasing_tsst_inst.h"
#include "oct6100api/oct6100_interrupts_inst.h"
#include "oct6100api/oct6100_remote_debug_inst.h"
#include "oct6100api/oct6100_debug_inst.h"
#include "oct6100api/oct6100_tlv_inst.h"
#include "oct6100api/oct6100_chip_open_inst.h"
#include "oct6100api/oct6100_api_inst.h"

#include "oct6100api/oct6100_chip_stats_pub.h"
#include "oct6100api/oct6100_interrupts_pub.h"
#include "oct6100api/oct6100_tsi_cnct_pub.h"
#include "oct6100api/oct6100_events_pub.h"
#include "oct6100api/oct6100_conf_bridge_pub.h"
#include "oct6100api/oct6100_playout_buf_pub.h"

#include "oct6100api/oct6100_channel_pub.h"
#include "oct6100api/oct6100_adpcm_chan_pub.h"
#include "oct6100api/oct6100_phasing_tsst_pub.h"
#include "oct6100api/oct6100_remote_debug_pub.h"
#include "oct6100api/oct6100_chip_open_pub.h"
#include "oct6100api/oct6100_mixer_pub.h"
#include "oct6100api/oct6100_channel_pub.h"
#include "oct6100api/oct6100_debug_pub.h"

#include "oct6100_chip_open_priv.h"
#include "oct6100_interrupts_priv.h"
#include "oct6100_chip_stats_priv.h"
#include "octrpc/rpc_protocol.h"
#include "oct6100_remote_debug_priv.h"
#include "oct6100_miscellaneous_priv.h"
#include "oct6100_memory_priv.h"
#include "oct6100_tsst_priv.h"
#include "oct6100_tsi_cnct_priv.h"
#include "oct6100_mixer_priv.h"
#include "oct6100_events_priv.h"
#include "oct6100_conf_bridge_priv.h"
#include "oct6100_playout_buf_priv.h"

#include "oct6100_channel_priv.h"
#include "oct6100_adpcm_chan_priv.h"
#include "oct6100_phasing_tsst_priv.h"
#include "oct6100_tlv_priv.h"
#include "oct6100_debug_priv.h"
#include "oct6100_version.h"


/****************************  PUBLIC FUNCTIONS  *****************************/


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100GetInstanceSizeDef

Description:    Retrieves the size of the required API instance structure.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

f_pGetSize			Structure containing API instance size. 
 
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100GetInstanceSizeDef
UINT32 Oct6100GetInstanceSizeDef(
				tPOCT6100_GET_INSTANCE_SIZE		f_pGetSize )
{
	return cOCT6100_ERR_OK;
}
#endif

#if !SKIP_Oct6100GetInstanceSize
UINT32 Oct6100GetInstanceSize(
				tPOCT6100_CHIP_OPEN				f_pChipOpen,
				tPOCT6100_GET_INSTANCE_SIZE		f_pGetSize )
{
	tOCT6100_API_INSTANCE_SIZES	InstanceSizes;
	UINT32						ulResult;

	/* Check user configuration for errors and conflicts. */
	ulResult = Oct6100ApiCheckChipConfiguration( f_pChipOpen );
	if ( ulResult != cOCT6100_ERR_OK  )
		return ulResult;

	/* Calculate the instance size required for user's configuration. */
	ulResult = Oct6100ApiCalculateInstanceSizes( f_pChipOpen, &InstanceSizes );
	if ( ulResult != cOCT6100_ERR_OK  )
		return ulResult;

	/* Return required size to user. */
	f_pGetSize->ulApiInstanceSize = InstanceSizes.ulApiInstTotal;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ChipOpenDef

Description:    Inserts default chip configuration parameters into the
				structure pointed to by f_pChipOpen.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------

f_pChipOpen			Structure containing user chip configuration. 
 
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ChipOpenDef
UINT32 Oct6100ChipOpenDef(
				tPOCT6100_CHIP_OPEN	f_pChipOpen )
{
	UINT32	i;

	f_pChipOpen->ulUserChipId = 0;
	f_pChipOpen->fMultiProcessSystem = FALSE;
	f_pChipOpen->pProcessContext = NULL;

	f_pChipOpen->ulMaxRwAccesses = 8;

	f_pChipOpen->pbyImageFile = NULL;
	f_pChipOpen->ulImageSize = 0;
	
	f_pChipOpen->ulMemClkFreq = 133000000;							/* 133 Mhz */
	f_pChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ;		/* 33.33  Mhz */
	f_pChipOpen->fEnableMemClkOut = TRUE;

	f_pChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR;
	f_pChipOpen->ulNumMemoryChips = 1;
	f_pChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_64MB;

	/* Set the tail displacement to zero. */
	f_pChipOpen->ulTailDisplacement = 0;
	
	/* Disable acoustic echo by default. */
	f_pChipOpen->fEnableAcousticEcho = FALSE;

	/* Resource allocation parameters. */
	f_pChipOpen->ulMaxChannels = 672;
	f_pChipOpen->ulMaxTsiCncts = 0;
	f_pChipOpen->ulMaxBiDirChannels = 0;
	f_pChipOpen->ulMaxConfBridges = 0;
	f_pChipOpen->ulMaxFlexibleConfParticipants = 0;
	f_pChipOpen->ulMaxPlayoutBuffers = 0;

	f_pChipOpen->ulMaxPhasingTssts	= 0;
	f_pChipOpen->ulMaxAdpcmChannels = 0;
	f_pChipOpen->ulMaxTdmStreams = 32;
	f_pChipOpen->fUseSynchTimestamp = FALSE;
	for ( i = 0; i < 4; i++ )
	{
		f_pChipOpen->aulTimestampTimeslots[ i ] = cOCT6100_INVALID_TIMESLOT;
		f_pChipOpen->aulTimestampStreams[ i ] = cOCT6100_INVALID_STREAM;
	}
	f_pChipOpen->fEnableFastH100Mode = FALSE;

	/* Configure the soft tone event buffer. */
	f_pChipOpen->ulSoftToneEventsBufSize = 2048;
	f_pChipOpen->fEnableExtToneDetection = FALSE;

	/* Configure the soft playout event buffer. */
	f_pChipOpen->ulSoftBufferPlayoutEventsBufSize = cOCT6100_INVALID_VALUE;

	/* Interrupt configuration. */
	f_pChipOpen->ulInterruptPolarity = cOCT6100_ACTIVE_LOW_POLARITY;

	f_pChipOpen->InterruptConfig.ulErrorMemoryConfig = cOCT6100_INTERRUPT_NO_TIMEOUT;
	f_pChipOpen->InterruptConfig.ulFatalGeneralConfig = cOCT6100_INTERRUPT_NO_TIMEOUT;
	f_pChipOpen->InterruptConfig.ulFatalMemoryConfig = cOCT6100_INTERRUPT_NO_TIMEOUT;
	f_pChipOpen->InterruptConfig.ulFatalMemoryConfig = cOCT6100_INTERRUPT_NO_TIMEOUT;
	f_pChipOpen->InterruptConfig.ulErrorH100Config = cOCT6100_INTERRUPT_NO_TIMEOUT;
	f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsConfig = cOCT6100_INTERRUPT_NO_TIMEOUT;

	f_pChipOpen->InterruptConfig.ulErrorMemoryTimeout = 100;
	f_pChipOpen->InterruptConfig.ulFatalMemoryTimeout = 100;
	f_pChipOpen->InterruptConfig.ulErrorH100Timeout = 100;
	f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsTimeout = 100;
	f_pChipOpen->ulMaxRemoteDebugSessions = 1;
	f_pChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_3_QUARTERS;
	for ( i = 0; i < cOCT6100_TDM_STREAM_MAX_GROUPS; i++ )
		f_pChipOpen->aulTdmStreamFreqs[ i ] = cOCT6100_TDM_STREAM_FREQ_8MHZ;



	f_pChipOpen->fEnableChannelRecording = FALSE;
	f_pChipOpen->fEnableProductionBist = FALSE;
	f_pChipOpen->ulNumProductionBistLoops = 1;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ChipOpen

Description:    Configures the chip according to the user specified
				configuration f_pChipOpen. This function will perform all I/O
				accesses necessary and initialize the API instance to reflect
				the configuration.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance			Pointer to API instance. This memory is used to keep the
						present state of the chip and all its resources.

f_pChipOpen				Structure containing user chip configuration. 
 
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ChipOpen
UINT32 Oct6100ChipOpen(
				tPOCT6100_INSTANCE_API	f_pApiInstance,
				tPOCT6100_CHIP_OPEN		f_pChipOpen )
{
	tOCT6100_API_INSTANCE_SIZES	InstanceSizes;
	UINT32						ulStructSize;
	UINT32						ulResult;
	UINT32						ulTempVar;

	/* Check user chip configuration parameters for errors. */
	ulResult = Oct6100ApiCheckChipConfiguration( f_pChipOpen );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Check if the host system is multi-process or not and adjust instance accordingly. */
	if ( f_pChipOpen->fMultiProcessSystem != TRUE )
	{
		/* Set pointer to tOCT6100_SHARED_INFO structure within instance. */
		ulStructSize = sizeof( tOCT6100_INSTANCE_API );
		mOCT6100_ROUND_MEMORY_SIZE( ulStructSize, ulTempVar )

		f_pApiInstance->pSharedInfo = ( tPOCT6100_SHARED_INFO )(( PUINT8 )f_pApiInstance + ulStructSize);

		/* Save the process context specified by the user. */
		f_pApiInstance->pProcessContext = f_pChipOpen->pProcessContext;


		/* Create serialization object handles. */
		ulResult = Oct6100ApiCreateSerializeObjects( f_pApiInstance, f_pChipOpen->ulUserChipId );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}

	/* Copy the configuration structure. */
	ulResult = Oct6100ApiCopyChipConfiguration( f_pApiInstance, f_pChipOpen );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Perform various calculations based on user chip configuration. */
	ulResult = Oct6100ApiInitializeMiscellaneousVariables( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Calculate the amount of memory needed for the API instance structure. */
	ulResult = Oct6100ApiCalculateInstanceSizes( f_pChipOpen, &InstanceSizes );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Allocate the memory for the API instance structure internal pointers. */
	ulResult = Oct6100ApiAllocateInstanceMemory( f_pApiInstance, &InstanceSizes );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Initialize the allocated instance structure memory. */
	ulResult = Oct6100ApiInitializeInstanceMemory( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Initialize the tone information structure. */
	ulResult = Oct6100ApiInitToneInfo( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Test the CPU registers. */
	ulResult = Oct6100ApiCpuRegisterBist( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Boot the FC2 PLL. */
	ulResult = Oct6100ApiBootFc2Pll( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;
	
	/* Program the FC1 PLL. */
	ulResult = Oct6100ApiProgramFc1Pll( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Decode the key and bist internal memories. */
	ulResult = Oct6100ApiDecodeKeyAndBist( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;
	
	/* Boot the FC1 PLL. */
	ulResult = Oct6100ApiBootFc1Pll( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;
	
	/* Boot the SDRAM. */
	ulResult = Oct6100ApiBootSdram( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Bist the external memory. */
	ulResult = Oct6100ApiExternalMemoryBist( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Initialize the external memory. */
	ulResult = Oct6100ApiExternalMemoryInit( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Load the image into the chip. */
	ulResult = Oct6100ApiLoadImage( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Write the clock distribution registers. */
	ulResult = Oct6100ApiEnableClocks( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Program the NLP processor. */
	ulResult = Oct6100ApiProgramNLP( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
	{		
		if ( ulResult == cOCT6100_ERR_OPEN_EGO_TIMEOUT )
			ulResult = Oct6100ApiProgramNLP( f_pApiInstance );
	}
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;	

	if ( f_pChipOpen->fEnableProductionBist == FALSE )
	{
		/* Read all TLV fields present in external memory. */
		ulResult = Oct6100ApiProcessTlvRegion( f_pApiInstance );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;	
		
		/* Configure the H.100 interface. */
		ulResult = Oct6100ApiSetH100Register( f_pApiInstance );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}

	/* Write miscellaneous registers. */
	ulResult = Oct6100ApiWriteMiscellaneousRegisters( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;
	
	/* Proceed with the rest only if the production BIST has not been requested. */
	if ( f_pChipOpen->fEnableProductionBist == FALSE )
	{
		/* Configure the interrupt registers. */
		ulResult = Oct6100ApiIsrHwInit( f_pApiInstance, &f_pChipOpen->InterruptConfig );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Initialize the errors counters. */
		ulResult = Oct6100ApiChipStatsSwInit( f_pApiInstance );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Configure all interrupts of the chip. */
		ulResult = Oct6100InterruptConfigureSer( f_pApiInstance, &f_pChipOpen->InterruptConfig, FALSE );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Get revision number of chip. */
		ulResult = Oct6100ApiGetChipRevisionNum( f_pApiInstance );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;


		


		/* Initialize the channels. */
		ulResult = Oct6100ApiInitChannels( f_pApiInstance );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Initialize the mixer memory. */
		ulResult = Oct6100ApiInitMixer( f_pApiInstance );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Initialize the mixer memory. */
		ulResult = Oct6100ApiInitRecordResources( f_pApiInstance );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Initialize free external memory for buffer playout. */
		ulResult = Oct6100ApiBufferPlayoutMemorySwInit( f_pApiInstance );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;



	}

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ChipCloseDef

Description:    Puts the chip into soft reset.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance			Pointer to API instance. This memory is used to keep the
						present state of the chip and all its resources.

f_pChipClose			Pointer to a tOCT6100_CHIP_CLOSE structure.
 
\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ChipCloseDef
UINT32 Oct6100ChipCloseDef(
				tPOCT6100_CHIP_CLOSE	f_pChipClose )
{
	f_pChipClose->ulDummyVariable = 0;

	return cOCT6100_ERR_OK;
}
#endif

#if !SKIP_Oct6100ChipClose
UINT32 Oct6100ChipClose(
				tPOCT6100_INSTANCE_API	f_pApiInstance,
				tPOCT6100_CHIP_CLOSE	f_pChipClose )
{
	tOCT6100_WRITE_PARAMS	WriteParams;
	UINT32	ulResult;

	WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId;
	WriteParams.ulWriteAddress = 0x100;
	WriteParams.usWriteData = 0x0000;
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult )
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Destroy the allocated ressources used for serialization. */
	ulResult = Oct6100ApiDestroySerializeObjects( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100CreateLocalInstance

Description:    Creates a local instance for a process in a multi-process
				host system.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pCreateLocal			Structure used to create process' local instance.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100CreateLocalInstanceDef
UINT32 Oct6100CreateLocalInstanceDef(
				tPOCT6100_CREATE_LOCAL_INSTANCE		f_pCreateLocal )
{
	f_pCreateLocal->pApiInstShared = NULL;
	f_pCreateLocal->pApiInstLocal = NULL;
	f_pCreateLocal->pProcessContext = NULL;
	f_pCreateLocal->ulUserChipId = 0;

	return cOCT6100_ERR_OK;
}
#endif


#if !SKIP_Oct6100CreateLocalInstance
UINT32 Oct6100CreateLocalInstance(
				tPOCT6100_CREATE_LOCAL_INSTANCE		f_pCreateLocal )
{
	tPOCT6100_INSTANCE_API	pApiInstLocal;
	UINT32					ulApiInstSize;
	UINT32					ulTempVar;
	UINT32					ulResult;

	/* Check user's structure for errors. */
	if ( f_pCreateLocal->pApiInstShared == NULL )
		return cOCT6100_ERR_MULTIPROC_API_INST_SHARED;

	if ( f_pCreateLocal->pApiInstLocal == NULL )
		return cOCT6100_ERR_MULTIPROC_API_INST_LOCAL;

	/* Get local pointer to local instance. */
	pApiInstLocal = f_pCreateLocal->pApiInstLocal;

	/* Assign pointers to local structure. */
	ulApiInstSize = sizeof( tOCT6100_INSTANCE_API );
	mOCT6100_ROUND_MEMORY_SIZE( ulApiInstSize, ulTempVar )

	pApiInstLocal->pSharedInfo = ( tPOCT6100_SHARED_INFO )(( PUINT8 )f_pCreateLocal->pApiInstShared + ulApiInstSize);
	pApiInstLocal->pProcessContext = f_pCreateLocal->pProcessContext;

	/* Create serialization object handles needed. */
	ulResult = Oct6100ApiCreateSerializeObjects( pApiInstLocal, f_pCreateLocal->ulUserChipId );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100DestroyLocalInstance

Description:    Release local instance for a process in a multi-process
				host system.

-------------------------------------------------------------------------------
|	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_pDestroyLocal			Structure used to destroy the process' local instance.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100DestroyLocalInstanceDef
UINT32 Oct6100DestroyLocalInstanceDef(
				tPOCT6100_DESTROY_LOCAL_INSTANCE		f_pDestroyLocal )
{
	f_pDestroyLocal->ulDummy = 0;

	return cOCT6100_ERR_OK;
}
#endif

#if !SKIP_Oct6100DestroyLocalInstance
UINT32 Oct6100DestroyLocalInstance(
				tPOCT6100_INSTANCE_API					f_pApiInstance,
				tPOCT6100_DESTROY_LOCAL_INSTANCE		f_pDestroyLocal )
{
	UINT32					ulResult;

	/* Destroy the allocated ressources used for serialization. */
	ulResult = Oct6100ApiDestroySerializeObjects( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100GetHwRevision

Description:    Gets the hardware revision number of the chip.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pGetHwRev				Pointer to user structure in which to return revision
						number.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100GetHwRevisionDef
UINT32 Oct6100GetHwRevisionDef(
				tPOCT6100_GET_HW_REVISION		f_pGetHwRev )
{
	f_pGetHwRev->ulUserChipId = cOCT6100_INVALID_CHIP_ID;
	f_pGetHwRev->pProcessContext = NULL;
	f_pGetHwRev->ulRevisionNum = cOCT6100_INVALID_VALUE;

	return cOCT6100_ERR_OK;
}
#endif


#if !SKIP_Oct6100GetHwRevision
UINT32 Oct6100GetHwRevision(
				tPOCT6100_GET_HW_REVISION		f_pGetHwRev )
{
	tOCT6100_READ_PARAMS	ReadParams;
	UINT32	ulResult;
	UINT16	usReadData;

	/* Read the hardware revision register. */
	ReadParams.pProcessContext = f_pGetHwRev->pProcessContext;

	ReadParams.ulUserChipId = f_pGetHwRev->ulUserChipId;
	ReadParams.pusReadData = &usReadData;
	ReadParams.ulReadAddress = 0x17E;
	mOCT6100_DRIVER_READ_API( ReadParams, ulResult )
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	f_pGetHwRev->ulRevisionNum = ( usReadData >> 8 ) & 0xFF;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100FreeResources

Description:    This function closes all opened channels and frees all 
				specified global resources used by the chip.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance			Pointer to API instance. This memory is used to keep
						the present state of the chip and all its resources.

f_pFreeResources		Pointer to user structure in which to choose what 
						to free.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100FreeResourcesDef
UINT32 Oct6100FreeResourcesDef(
				tPOCT6100_FREE_RESOURCES			f_pFreeResources )
{
	f_pFreeResources->fFreeTsiConnections = FALSE;
	f_pFreeResources->fFreeConferenceBridges = FALSE;
	f_pFreeResources->fFreePlayoutBuffers = FALSE;
	f_pFreeResources->fFreePhasingTssts = FALSE;
	f_pFreeResources->fFreeAdpcmChannels = FALSE;
	
	return cOCT6100_ERR_OK;
}
#endif


#if !SKIP_Oct6100FreeResources
UINT32 Oct6100FreeResources(
				tPOCT6100_INSTANCE_API				f_pApiInstance,
				tPOCT6100_FREE_RESOURCES			f_pFreeResources )
{
	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 = Oct6100FreeResourcesSer( f_pApiInstance, f_pFreeResources );
	}
	else
	{
		return ulSerRes;
	}

	/* Release the seized semaphores. */
	ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
	ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );

	/* If an error occured then return the error code. */
	if ( ulSerRes != cOCT6100_ERR_OK )
		return ulSerRes;
	if ( ulFncRes != cOCT6100_ERR_OK )
		return ulFncRes;
	
	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ProductionBist

Description:    This function retrieves the current BIST status of the
				firmware.

-------------------------------------------------------------------------------
|	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_pProductionBist		Pointer to user structure where the bist information
						will be returned.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ProductionBistDef
UINT32 Oct6100ProductionBistDef(
				tPOCT6100_PRODUCTION_BIST		f_pProductionBist )
{
	f_pProductionBist->ulCurrentAddress = cOCT6100_INVALID_VALUE;
	f_pProductionBist->ulCurrentLoop = cOCT6100_INVALID_VALUE;
	f_pProductionBist->ulFailedAddress = cOCT6100_INVALID_VALUE;
	f_pProductionBist->ulReadValue = cOCT6100_INVALID_VALUE;
	f_pProductionBist->ulExpectedValue = cOCT6100_INVALID_VALUE;
	f_pProductionBist->ulBistStatus = cOCT6100_BIST_IN_PROGRESS;
	f_pProductionBist->ulCurrentTest = cOCT6100_INVALID_VALUE;

	return cOCT6100_ERR_OK;
}
#endif


#if !SKIP_Oct6100ProductionBist
UINT32 Oct6100ProductionBist(
				tPOCT6100_INSTANCE_API				f_pApiInstance,
				tPOCT6100_PRODUCTION_BIST			f_pProductionBist )
{
	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 = Oct6100ProductionBistSer( f_pApiInstance, f_pProductionBist );
	}
	else
	{
		return ulSerRes;
	}

	/* Release the seized semaphores. */
	ReleaseSerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;
	ulSerRes = Oct6100UserReleaseSerializeObject( &ReleaseSerObj );

	/* If an error occured then return the error code. */
	if ( ulSerRes != cOCT6100_ERR_OK )
		return ulSerRes;
	if ( ulFncRes != cOCT6100_ERR_OK )
		return ulFncRes;
	
	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiGetVersion

Description:    Retrieves the API version.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------

f_pApiGetVersion	 Pointer to structure that will receive version information.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiGetVersionDef
UINT32 Oct6100ApiGetVersionDef(
				tPOCT6100_API_GET_VERSION			f_pApiGetVersion )
{
	UINT32	i;

	/* Initialize the string. */
	for ( i = 0; i < cOCT6100_API_VERSION_STRING_LENGTH; i++ )
		f_pApiGetVersion->achApiVersion[ i ] = 0;

	return cOCT6100_ERR_OK;
}
#endif

#if !SKIP_Oct6100ApiGetVersion
UINT32 Oct6100ApiGetVersion(
				tPOCT6100_API_GET_VERSION		f_pApiGetVersion )
{
	/* Copy API version information to user. */
	Oct6100UserMemCopy( f_pApiGetVersion->achApiVersion, cOCT6100_API_VERSION, sizeof(cOCT6100_API_VERSION) );

	return cOCT6100_ERR_OK;
}
#endif


/***************************  PRIVATE FUNCTIONS  *****************************/


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiCheckChipConfiguration

Description:    Checks the user chip configuration structure for errors.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------

f_pChipOpen			Pointer to chip configuration structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiCheckChipConfiguration
UINT32 Oct6100ApiCheckChipConfiguration(
				IN		tPOCT6100_CHIP_OPEN		f_pChipOpen )
{
	UINT32	ulTempVar;
	UINT32	i;
	
	/*-----------------------------------------------------------------------------*/
	/* Check general parameters. */
	if ( f_pChipOpen->fMultiProcessSystem != TRUE &&
		 f_pChipOpen->fMultiProcessSystem != FALSE )
		return cOCT6100_ERR_OPEN_MULTI_PROCESS_SYSTEM;

	if ( f_pChipOpen->ulMaxRwAccesses < 1 ||
		 f_pChipOpen->ulMaxRwAccesses > 1024)
		return cOCT6100_ERR_OPEN_MAX_RW_ACCESSES;

	/* Check the clocks. */
	if ( f_pChipOpen->ulUpclkFreq != cOCT6100_UPCLK_FREQ_33_33_MHZ )
		return cOCT6100_ERR_OPEN_UP_CLK_FREQ;

	if ( f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_133_MHZ &&
		 f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_125_MHZ &&
		 f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_117_MHZ &&
		 f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_108_MHZ &&
		 f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_100_MHZ &&
		 f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_92_MHZ &&
		 f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_83_MHZ &&
		 f_pChipOpen->ulMemClkFreq != cOCT6100_MCLK_FREQ_75_MHZ )
		return cOCT6100_ERR_OPEN_MEM_CLK_FREQ;

	if ( f_pChipOpen->fEnableMemClkOut != TRUE &&
		 f_pChipOpen->fEnableMemClkOut != FALSE )
		return cOCT6100_ERR_OPEN_ENABLE_MEM_CLK_OUT;

	/* Check the image file. */
	if ( f_pChipOpen->ulImageSize < cOCT6100_MIN_IMAGE_SIZE ||
		 f_pChipOpen->ulImageSize > cOCT6100_MAX_IMAGE_SIZE )
		return cOCT6100_ERR_OPEN_IMAGE_SIZE;

	if ( f_pChipOpen->pbyImageFile == NULL )
		return cOCT6100_ERR_OPEN_IMAGE_FILE;

	/* Check the acoustic echo activation flag. */
	if ( f_pChipOpen->fEnableAcousticEcho != TRUE && 
		f_pChipOpen->fEnableAcousticEcho != FALSE )
		return cOCT6100_ERR_OPEN_ENABLE_ACOUSTIC_ECHO;

	/* Check the tail displacement parameter. */
	if ( f_pChipOpen->ulTailDisplacement > cOCT6100_MAX_TAIL_DISPLACEMENT )
		return cOCT6100_ERR_OPEN_TAIL_DISPLACEMENT;

	/*-----------------------------------------------------------------------------*/
	/* Check TDM bus configuration parameters. */
	for ( i = 0; i < 8; i++ )
	{
		if ( f_pChipOpen->aulTdmStreamFreqs[ i ] != cOCT6100_TDM_STREAM_FREQ_2MHZ &&
			 f_pChipOpen->aulTdmStreamFreqs[ i ] != cOCT6100_TDM_STREAM_FREQ_4MHZ &&
			 f_pChipOpen->aulTdmStreamFreqs[ i ] != cOCT6100_TDM_STREAM_FREQ_8MHZ)
			return cOCT6100_ERR_OPEN_TDM_STREAM_FREQS;
	}

	if ( f_pChipOpen->ulTdmSampling != cOCT6100_TDM_SAMPLE_AT_3_QUARTERS &&
		 f_pChipOpen->ulTdmSampling != cOCT6100_TDM_SAMPLE_AT_RISING_EDGE &&
		 f_pChipOpen->ulTdmSampling != cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE )
		return cOCT6100_ERR_OPEN_TDM_SAMPLING;

	if ( f_pChipOpen->fEnableFastH100Mode != TRUE && 
		 f_pChipOpen->fEnableFastH100Mode != FALSE )
		return cOCT6100_ERR_OPEN_FAST_H100_MODE;

	/*-----------------------------------------------------------------------------*/
	/* Check external memory configuration parameters. */
	if ( f_pChipOpen->ulMemoryType != cOCT6100_MEM_TYPE_SDR &&
		 f_pChipOpen->ulMemoryType != cOCT6100_MEM_TYPE_DDR &&
		 f_pChipOpen->ulMemoryType != cOCT6100_MEM_TYPE_SDR_PLL_BYPASS )
		return cOCT6100_ERR_OPEN_MEMORY_TYPE;
	
	if ( f_pChipOpen->ulMemoryChipSize != cOCT6100_MEMORY_CHIP_SIZE_8MB &&
		 f_pChipOpen->ulMemoryChipSize != cOCT6100_MEMORY_CHIP_SIZE_16MB &&
		 f_pChipOpen->ulMemoryChipSize != cOCT6100_MEMORY_CHIP_SIZE_32MB &&
		 f_pChipOpen->ulMemoryChipSize != cOCT6100_MEMORY_CHIP_SIZE_64MB &&
		 f_pChipOpen->ulMemoryChipSize != cOCT6100_MEMORY_CHIP_SIZE_128MB )
		return cOCT6100_ERR_OPEN_MEMORY_CHIP_SIZE;
	
	if ( f_pChipOpen->ulMemoryChipSize == cOCT6100_MEMORY_CHIP_SIZE_8MB &&
		 f_pChipOpen->ulMemoryType == cOCT6100_MEM_TYPE_DDR )
		return cOCT6100_ERR_OPEN_MEMORY_CHIP_SIZE;

	if ( f_pChipOpen->ulNumMemoryChips < 1 ||
		 f_pChipOpen->ulNumMemoryChips > cOCT6100_MAX_NUM_MEMORY_CHIP )
		return cOCT6100_ERR_OPEN_MEMORY_CHIPS_NUMBER;

	/* Check the total memory size. */
	ulTempVar = f_pChipOpen->ulMemoryChipSize * f_pChipOpen->ulNumMemoryChips;
	if ( ulTempVar < cOCT6100_MEMORY_CHIP_SIZE_16MB ||
		 ulTempVar > cOCT6100_MEMORY_CHIP_SIZE_128MB )
		return cOCT6100_ERR_OPEN_TOTAL_MEMORY_SIZE;

	if ( f_pChipOpen->ulMaxTdmStreams != 4 &&
		 f_pChipOpen->ulMaxTdmStreams != 8 &&
		 f_pChipOpen->ulMaxTdmStreams != 16 &&
		 f_pChipOpen->ulMaxTdmStreams != 32 )
		return cOCT6100_ERR_OPEN_MAX_TDM_STREAM;

	if ( f_pChipOpen->ulMaxTdmStreams > 8 && 
		 f_pChipOpen->ulMemClkFreq == cOCT6100_MCLK_FREQ_75_MHZ )
		return cOCT6100_ERR_OPEN_MAX_TDM_STREAM;

	if ( f_pChipOpen->fUseSynchTimestamp != TRUE &&
		 f_pChipOpen->fUseSynchTimestamp != FALSE )
		return cOCT6100_ERR_OPEN_USE_SYNCH_TIMESTAMP;

	if ( f_pChipOpen->fUseSynchTimestamp == TRUE )
	{
		return cOCT6100_ERR_NOT_SUPPORTED_OPEN_USE_SYNCH_TIMESTAMP;
	}

	/*-----------------------------------------------------------------------------*/
	/* Check soft buffer for tone events size. */
	if ( f_pChipOpen->ulSoftToneEventsBufSize < cOCT6100_NUM_PGSP_EVENT_OUT ||
		 f_pChipOpen->ulSoftToneEventsBufSize > cOCT6100_ABSOLUTE_MAX_NUM_PGSP_EVENT_OUT )
		return cOCT6100_ERR_OPEN_SOFT_TONE_EVENT_SIZE;

	if ( f_pChipOpen->fEnableExtToneDetection != TRUE && 
		 f_pChipOpen->fEnableExtToneDetection != FALSE )
		return cOCT6100_ERR_OPEN_ENABLE_EXT_TONE_DETECTION;

	/* Check soft buffer for playout events size. */
	if ( ( f_pChipOpen->ulSoftBufferPlayoutEventsBufSize != cOCT6100_INVALID_VALUE )
		&& ( f_pChipOpen->ulSoftBufferPlayoutEventsBufSize < cOCT6100_MIN_BUFFER_PLAYOUT_EVENT ||
		 f_pChipOpen->ulSoftBufferPlayoutEventsBufSize > cOCT6100_MAX_BUFFER_PLAYOUT_EVENT ) )
		return cOCT6100_ERR_OPEN_SOFT_PLAYOUT_STOP_EVENT_SIZE;

	/*-----------------------------------------------------------------------------*/
	/* Check interrupt configuration parameters. */
	if ( f_pChipOpen->ulInterruptPolarity != cOCT6100_ACTIVE_LOW_POLARITY &&
		 f_pChipOpen->ulInterruptPolarity != cOCT6100_ACTIVE_HIGH_POLARITY )
		return cOCT6100_ERR_OPEN_INTERRUPT_POLARITY;

	if ( f_pChipOpen->InterruptConfig.ulFatalGeneralConfig != cOCT6100_INTERRUPT_NO_TIMEOUT &&
		 f_pChipOpen->InterruptConfig.ulFatalGeneralConfig != cOCT6100_INTERRUPT_DISABLE )
		return cOCT6100_ERR_OPEN_FATAL_GENERAL_CONFIG;

	if ( f_pChipOpen->InterruptConfig.ulFatalMemoryConfig != cOCT6100_INTERRUPT_NO_TIMEOUT &&
		 f_pChipOpen->InterruptConfig.ulFatalMemoryConfig != cOCT6100_INTERRUPT_TIMEOUT &&
		 f_pChipOpen->InterruptConfig.ulFatalMemoryConfig != cOCT6100_INTERRUPT_DISABLE )
		return cOCT6100_ERR_OPEN_FATAL_MEMORY_CONFIG;

	if ( f_pChipOpen->InterruptConfig.ulErrorMemoryConfig != cOCT6100_INTERRUPT_NO_TIMEOUT &&
		 f_pChipOpen->InterruptConfig.ulErrorMemoryConfig != cOCT6100_INTERRUPT_TIMEOUT &&
		 f_pChipOpen->InterruptConfig.ulErrorMemoryConfig != cOCT6100_INTERRUPT_DISABLE )
		return cOCT6100_ERR_OPEN_ERROR_MEMORY_CONFIG;

	if ( f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_NO_TIMEOUT &&
		 f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_TIMEOUT &&
		 f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsConfig != cOCT6100_INTERRUPT_DISABLE )
		return cOCT6100_ERR_OPEN_ERROR_OVERFLOW_TONE_EVENTS_CONFIG;

	if ( f_pChipOpen->InterruptConfig.ulErrorH100Config != cOCT6100_INTERRUPT_NO_TIMEOUT &&
		 f_pChipOpen->InterruptConfig.ulErrorH100Config != cOCT6100_INTERRUPT_TIMEOUT &&
		 f_pChipOpen->InterruptConfig.ulErrorH100Config != cOCT6100_INTERRUPT_DISABLE )
		return cOCT6100_ERR_OPEN_ERROR_H100_CONFIG;

	/* Check the timeout value. */
	if ( f_pChipOpen->InterruptConfig.ulFatalMemoryTimeout < 10 ||
		 f_pChipOpen->InterruptConfig.ulFatalMemoryTimeout > 10000 )
		return cOCT6100_ERR_OPEN_FATAL_MEMORY_TIMEOUT;

	if ( f_pChipOpen->InterruptConfig.ulErrorMemoryTimeout < 10 ||
		 f_pChipOpen->InterruptConfig.ulErrorMemoryTimeout > 10000 )
		return cOCT6100_ERR_OPEN_ERROR_MEMORY_TIMEOUT;

	if ( f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsTimeout < 10 ||
		 f_pChipOpen->InterruptConfig.ulErrorOverflowToneEventsTimeout > 10000 )
		return cOCT6100_ERR_OPEN_ERROR_OVERFLOW_TONE_EVENTS_TIMEOUT;

	if ( f_pChipOpen->InterruptConfig.ulErrorH100Timeout < 10 ||
		 f_pChipOpen->InterruptConfig.ulErrorH100Timeout > 10000 )
		return cOCT6100_ERR_OPEN_ERROR_H100_TIMEOUT;

	/*-----------------------------------------------------------------------------*/
	/* Check maximum resources. */

	switch ( f_pChipOpen->ulMemClkFreq )
	{
	case 133000000:
		ulTempVar = 672;
		break;
	case 125000000:
		ulTempVar = 624;
		break;
	case 117000000:
		ulTempVar = 576;
		break;
	case 108000000:
		ulTempVar = 528;
		break;
	case 100000000:
		ulTempVar = 480;
		break;
	case 92000000:
		ulTempVar = 432;
		break;
	case 83000000:
		ulTempVar = 384;
		break;
	case 75000000:
		ulTempVar = 336;
		break;
	default:
		return cOCT6100_ERR_FATAL_DA;
	}

	if ( f_pChipOpen->ulMaxChannels > ulTempVar )
		return cOCT6100_ERR_OPEN_MAX_ECHO_CHANNELS;

	if ( f_pChipOpen->ulMaxTsiCncts > cOCT6100_MAX_TSI_CNCTS )
		return cOCT6100_ERR_OPEN_MAX_TSI_CNCTS;


	if ( f_pChipOpen->ulMaxBiDirChannels > 255 )
		return cOCT6100_ERR_OPEN_MAX_BIDIR_CHANNELS;
	
	if ( f_pChipOpen->ulMaxBiDirChannels > (f_pChipOpen->ulMaxChannels / 2) )
		return cOCT6100_ERR_OPEN_MAX_BIDIR_CHANNELS;

	if ( f_pChipOpen->ulMaxConfBridges > cOCT6100_MAX_CONF_BRIDGE )
		return cOCT6100_ERR_OPEN_MAX_CONF_BRIDGES;

	if ( f_pChipOpen->ulMaxFlexibleConfParticipants > cOCT6100_MAX_FLEX_CONF_PARTICIPANTS )
		return cOCT6100_ERR_OPEN_MAX_FLEXIBLE_CONF_PARTICIPANTS;

	if ( f_pChipOpen->ulMaxPlayoutBuffers > cOCT6100_MAX_PLAYOUT_BUFFERS )
		return cOCT6100_ERR_OPEN_MAX_PLAYOUT_BUFFERS;



	if ( f_pChipOpen->ulMaxPhasingTssts > cOCT6100_MAX_PHASING_TSST )
		return cOCT6100_ERR_OPEN_MAX_PHASING_TSSTS;

	if ( f_pChipOpen->ulMaxAdpcmChannels > cOCT6100_MAX_ADPCM_CHANNELS )
		return cOCT6100_ERR_OPEN_MAX_ADPCM_CHANNELS;

	if ( f_pChipOpen->ulMaxRemoteDebugSessions > 256 )
		return cOCT6100_ERR_OPEN_MAX_REMOTE_DEBUG_SESSIONS;





	/* Check the channel recording flag. */
	if ( f_pChipOpen->fEnableChannelRecording != TRUE &&
		 f_pChipOpen->fEnableChannelRecording != FALSE )
		return cOCT6100_ERR_OPEN_DEBUG_CHANNEL_RECORDING;

	/* Check the enable production BIST flag. */
	if ( ( f_pChipOpen->fEnableProductionBist != TRUE )
		&& ( f_pChipOpen->fEnableProductionBist != FALSE ) )
		return cOCT6100_ERR_OPEN_ENABLE_PRODUCTION_BIST;

	/* Check number of loops for the production BIST. */
	if ( f_pChipOpen->fEnableProductionBist == TRUE )
	{
		if ( f_pChipOpen->ulNumProductionBistLoops == 0 )
			return cOCT6100_ERR_OPEN_NUM_PRODUCTION_BIST_LOOPS;
	}

	/* If the production BIST has been requested, make sure all */
	/* other resources are disabled. */
	if ( f_pChipOpen->fEnableProductionBist == TRUE )
	{
		/* All must be disabled. */
		f_pChipOpen->ulMaxChannels = 0;
		f_pChipOpen->ulMaxTsiCncts = 0;
		f_pChipOpen->fEnableChannelRecording = FALSE;
		f_pChipOpen->ulMaxBiDirChannels = 0;
		f_pChipOpen->ulMaxConfBridges = 0;
		f_pChipOpen->ulMaxPlayoutBuffers = 0;
		f_pChipOpen->ulSoftBufferPlayoutEventsBufSize = cOCT6100_INVALID_VALUE;
		f_pChipOpen->ulMaxPhasingTssts = 0;
		f_pChipOpen->ulMaxAdpcmChannels = 0;


	}

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiCopyChipConfiguration

Description:    Copies the chip configuration from the user supplied config
				structure to the instance structure.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance			Pointer to API instance. This memory is used to keep the
						present state of the chip and all its resources.

f_pChipOpen				Pointer to chip configuration structure.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiCopyChipConfiguration
UINT32 Oct6100ApiCopyChipConfiguration(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance,
				IN		tPOCT6100_CHIP_OPEN		f_pChipOpen )
{
	tPOCT6100_SHARED_INFO	pSharedInfo;
	UINT32	i;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	pSharedInfo->ChipConfig.ulUserChipId = f_pChipOpen->ulUserChipId;
	pSharedInfo->ChipConfig.fMultiProcessSystem = (UINT8)( f_pChipOpen->fMultiProcessSystem & 0xFF );

	pSharedInfo->ChipConfig.usMaxRwAccesses = (UINT16)( f_pChipOpen->ulMaxRwAccesses & 0xFFFF );

	pSharedInfo->ChipConfig.pbyImageFile = f_pChipOpen->pbyImageFile;
	pSharedInfo->ChipConfig.ulImageSize = f_pChipOpen->ulImageSize;	
	
	pSharedInfo->ChipConfig.ulMemClkFreq = f_pChipOpen->ulMemClkFreq;
	pSharedInfo->ChipConfig.ulUpclkFreq = f_pChipOpen->ulUpclkFreq;

	pSharedInfo->ChipConfig.byMemoryType = (UINT8)( f_pChipOpen->ulMemoryType & 0xFF );
	pSharedInfo->ChipConfig.byNumMemoryChips = (UINT8)( f_pChipOpen->ulNumMemoryChips & 0xFF );
	pSharedInfo->ChipConfig.ulMemoryChipSize = f_pChipOpen->ulMemoryChipSize;

	pSharedInfo->ChipConfig.usTailDisplacement = (UINT16)( f_pChipOpen->ulTailDisplacement & 0xFFFF );
	pSharedInfo->ChipConfig.fEnableAcousticEcho = (UINT8)( f_pChipOpen->fEnableAcousticEcho & 0xFF );
	/* Resource allocation parameters. */
	if ( f_pChipOpen->fEnableChannelRecording == TRUE && f_pChipOpen->ulMaxChannels == 672 )
		pSharedInfo->ChipConfig.usMaxChannels = (UINT16)( ( f_pChipOpen->ulMaxChannels - 1 ) & 0xFFFF );
	else
		pSharedInfo->ChipConfig.usMaxChannels = (UINT16)( f_pChipOpen->ulMaxChannels & 0xFFFF );
	pSharedInfo->ChipConfig.usMaxTsiCncts = (UINT16)( f_pChipOpen->ulMaxTsiCncts & 0xFFFF );
	pSharedInfo->ChipConfig.usMaxBiDirChannels = (UINT16)( f_pChipOpen->ulMaxBiDirChannels & 0xFFFF );
	pSharedInfo->ChipConfig.usMaxConfBridges = (UINT16)( f_pChipOpen->ulMaxConfBridges & 0xFFFF );
	pSharedInfo->ChipConfig.usMaxFlexibleConfParticipants = (UINT16)( f_pChipOpen->ulMaxFlexibleConfParticipants & 0xFFFF );
	pSharedInfo->ChipConfig.usMaxPlayoutBuffers = (UINT16)( f_pChipOpen->ulMaxPlayoutBuffers & 0xFFFF );

	pSharedInfo->ChipConfig.usMaxPhasingTssts = (UINT16)( f_pChipOpen->ulMaxPhasingTssts & 0xFFFF );
	pSharedInfo->ChipConfig.usMaxAdpcmChannels = (UINT16)( f_pChipOpen->ulMaxAdpcmChannels & 0xFFFF );
	pSharedInfo->ChipConfig.byMaxTdmStreams = (UINT8)( f_pChipOpen->ulMaxTdmStreams & 0xFF );
	pSharedInfo->ChipConfig.fUseSynchTimestamp = (UINT8)( f_pChipOpen->fUseSynchTimestamp & 0xFF );
	for ( i = 0; i < 4; i++ )
	{
		pSharedInfo->ChipConfig.ausTimestampTimeslots[ i ] = (UINT16)( f_pChipOpen->aulTimestampTimeslots[ i ] & 0xFFFF );
		pSharedInfo->ChipConfig.ausTimestampStreams[ i ]  = (UINT16)( f_pChipOpen->aulTimestampStreams[ i ] & 0xFFFF );
	}
	pSharedInfo->ChipConfig.byInterruptPolarity = (UINT8)( f_pChipOpen->ulInterruptPolarity & 0xFF );

	pSharedInfo->ChipConfig.byTdmSampling = (UINT8)( f_pChipOpen->ulTdmSampling & 0xFF );
	pSharedInfo->ChipConfig.fEnableFastH100Mode = (UINT8)( f_pChipOpen->fEnableFastH100Mode & 0xFF );

	for ( i = 0; i < cOCT6100_TDM_STREAM_MAX_GROUPS; i++ )
	{
		if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE )
			pSharedInfo->ChipConfig.aulTdmStreamFreqs[ i ] = cOCT6100_TDM_STREAM_FREQ_16MHZ;
		else
			pSharedInfo->ChipConfig.aulTdmStreamFreqs[ i ] = f_pChipOpen->aulTdmStreamFreqs[ i ];
	}
	
	pSharedInfo->ChipConfig.fEnableFastH100Mode = (UINT8)( f_pChipOpen->fEnableFastH100Mode & 0xFF );
	pSharedInfo->ChipConfig.fEnableMemClkOut = (UINT8)( f_pChipOpen->fEnableMemClkOut & 0xFF );

	/* Add 1 to the circular buffer such that all user requested events can fit in the circular queue. */
	pSharedInfo->ChipConfig.ulSoftToneEventsBufSize = f_pChipOpen->ulSoftToneEventsBufSize + 1;
	pSharedInfo->ChipConfig.fEnableExtToneDetection = (UINT8)( f_pChipOpen->fEnableExtToneDetection & 0xFF );

	if ( f_pChipOpen->ulSoftBufferPlayoutEventsBufSize != cOCT6100_INVALID_VALUE )
		pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize = f_pChipOpen->ulSoftBufferPlayoutEventsBufSize + 1;
	else
		pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize = 0;
	pSharedInfo->ChipConfig.usMaxRemoteDebugSessions = (UINT16)( f_pChipOpen->ulMaxRemoteDebugSessions & 0xFFFF );

	pSharedInfo->ChipConfig.fEnableChannelRecording = (UINT8)( f_pChipOpen->fEnableChannelRecording & 0xFF );



	pSharedInfo->ChipConfig.fEnableProductionBist = (UINT8)( f_pChipOpen->fEnableProductionBist & 0xFF );
	pSharedInfo->ChipConfig.ulNumProductionBistLoops  = f_pChipOpen->ulNumProductionBistLoops;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiInitializeMiscellaneousVariables

Description:    Function where all the various parameters from the API instance 
				are set to their defaults value.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance			Pointer to API instance. This memory is used to keep the
						present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiInitializeMiscellaneousVariables
UINT32 Oct6100ApiInitializeMiscellaneousVariables(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tPOCT6100_SHARED_INFO		pSharedInfo;
	UINT32	i;

	/* Obtain pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Calculate the total memory available. */
	pSharedInfo->MiscVars.ulTotalMemSize = pSharedInfo->ChipConfig.ulMemoryChipSize * pSharedInfo->ChipConfig.byNumMemoryChips;

	/* Software buffers initialization. */

	/* Tones */
	pSharedInfo->SoftBufs.ulToneEventBufferWritePtr = 0;
	pSharedInfo->SoftBufs.ulToneEventBufferReadPtr = 0;
	pSharedInfo->SoftBufs.ulToneEventBufferSize = pSharedInfo->ChipConfig.ulSoftToneEventsBufSize;
	pSharedInfo->SoftBufs.ulToneEventBufferOverflowCnt = 0;

	/* Playout */
	pSharedInfo->SoftBufs.ulBufPlayoutEventBufferWritePtr = 0;
	pSharedInfo->SoftBufs.ulBufPlayoutEventBufferReadPtr = 0;
	pSharedInfo->SoftBufs.ulBufPlayoutEventBufferSize = pSharedInfo->ChipConfig.ulSoftBufPlayoutEventsBufSize;
	pSharedInfo->SoftBufs.ulBufPlayoutEventBufferOverflowCnt = 0;

	/* Set the number of conference bridges opened to zero. */
	pSharedInfo->MiscVars.usNumBridgesOpened = 0;
	pSharedInfo->MiscVars.usFirstBridge = cOCT6100_INVALID_INDEX;
	
	/* Set the H.100 slave mode. */
	pSharedInfo->MiscVars.ulH100SlaveMode = cOCT6100_H100_TRACKA;

	/* Save the Mclk value.*/
	pSharedInfo->MiscVars.ulMclkFreq = pSharedInfo->ChipConfig.ulMemClkFreq;

	/* Init the NLP params. */
	pSharedInfo->MiscVars.usCodepoint = 0;
	pSharedInfo->MiscVars.usCpuLsuWritePtr = 0;

	/* Pouch counter not present until TLVs are read. */
	pSharedInfo->DebugInfo.fPouchCounter = FALSE;
	pSharedInfo->DebugInfo.fIsIsrCalledField = FALSE;

	/* Initialize the image info parameters */
	pSharedInfo->ImageInfo.fAdaptiveNoiseReduction		= FALSE;
	pSharedInfo->ImageInfo.fSoutNoiseBleaching			= FALSE;
	pSharedInfo->ImageInfo.fComfortNoise				= FALSE;
	pSharedInfo->ImageInfo.fBufferPlayout				= TRUE;
	pSharedInfo->ImageInfo.fSoutBufferPlayoutHardSkip	= FALSE; 
	pSharedInfo->ImageInfo.fRinBufferPlayoutHardSkip	= FALSE;
	pSharedInfo->ImageInfo.fNlpControl					= FALSE;
	pSharedInfo->ImageInfo.fRinAutoLevelControl			= FALSE;
	pSharedInfo->ImageInfo.fSoutAutoLevelControl		= FALSE;
	pSharedInfo->ImageInfo.fAlcNoiseBleedOutTime		= FALSE;
	pSharedInfo->ImageInfo.fRinHighLevelCompensation	= FALSE;
	pSharedInfo->ImageInfo.fSoutHighLevelCompensation	= FALSE;
	pSharedInfo->ImageInfo.fAlcHlcStatus				= FALSE;
	pSharedInfo->ImageInfo.fRinDcOffsetRemoval			= FALSE;
	pSharedInfo->ImageInfo.fSilenceSuppression			= FALSE;
	pSharedInfo->ImageInfo.fSinDcOffsetRemoval			= FALSE;
	pSharedInfo->ImageInfo.fToneDisabler				= FALSE;
	pSharedInfo->ImageInfo.fAdpcm						= FALSE;
	pSharedInfo->ImageInfo.fTailDisplacement			= FALSE;
	pSharedInfo->ImageInfo.fConferencing				= FALSE;
	pSharedInfo->ImageInfo.fConferencingNoiseReduction	= FALSE;
	pSharedInfo->ImageInfo.fDominantSpeakerEnabled		= FALSE;
	pSharedInfo->ImageInfo.fAecEnabled					= FALSE;
	pSharedInfo->ImageInfo.fAcousticEcho				= FALSE;
	pSharedInfo->ImageInfo.fToneRemoval					= FALSE;

	pSharedInfo->ImageInfo.fDefaultErl					= FALSE;
	pSharedInfo->ImageInfo.fMaxEchoPoint				= FALSE;
	pSharedInfo->ImageInfo.fNonLinearityBehaviorA		= FALSE;
	pSharedInfo->ImageInfo.fNonLinearityBehaviorB		= FALSE;
	pSharedInfo->ImageInfo.fPerChannelTailDisplacement	= FALSE;
	pSharedInfo->ImageInfo.fPerChannelTailLength		= FALSE;
	pSharedInfo->ImageInfo.fAfTailDisplacement			= FALSE;
	pSharedInfo->ImageInfo.fMusicProtection				= FALSE;
	pSharedInfo->ImageInfo.fAftControl					= FALSE;
	pSharedInfo->ImageInfo.fSinVoiceDetectedStat		= FALSE;
	pSharedInfo->ImageInfo.fRinAppliedGainStat			= FALSE;
	pSharedInfo->ImageInfo.fSoutAppliedGainStat			= FALSE;
	pSharedInfo->ImageInfo.fListenerEnhancement			= FALSE;
	pSharedInfo->ImageInfo.fRoutNoiseReduction			= FALSE;
	pSharedInfo->ImageInfo.fAnrSnrEnhancement			= FALSE;
	pSharedInfo->ImageInfo.fAnrVoiceNoiseSegregation	= FALSE;
	pSharedInfo->ImageInfo.fRinMute						= FALSE;
	pSharedInfo->ImageInfo.fSinMute						= FALSE;
	pSharedInfo->ImageInfo.fToneDisablerVqeActivationDelay = FALSE;
	pSharedInfo->ImageInfo.fAecTailLength				= FALSE;
	pSharedInfo->ImageInfo.fMusicProtectionConfiguration= FALSE;
	pSharedInfo->ImageInfo.fBufferPlayoutSkipInEvents	= FALSE;
	pSharedInfo->ImageInfo.fRinEnergyStat				= FALSE;
	pSharedInfo->ImageInfo.fSoutEnergyStat				= FALSE;
	pSharedInfo->ImageInfo.fDoubleTalkBehavior			= FALSE;
	pSharedInfo->ImageInfo.fDoubleTalkBehaviorFieldOfst	= FALSE;
	pSharedInfo->ImageInfo.fIdleCodeDetection			= TRUE;
	pSharedInfo->ImageInfo.fIdleCodeDetectionConfiguration = FALSE;
	pSharedInfo->ImageInfo.fSinLevel					= TRUE;
	pSharedInfo->ImageInfo.fResetRinAlcOnTones			= FALSE;
	pSharedInfo->ImageInfo.fResetSoutAlcOnTones			= FALSE;

	pSharedInfo->ImageInfo.usMaxNumberOfChannels		= 0;
	pSharedInfo->ImageInfo.ulToneProfileNumber			= cOCT6100_INVALID_VALUE;
	pSharedInfo->ImageInfo.ulBuildId					= cOCT6100_INVALID_VALUE;
	pSharedInfo->ImageInfo.byImageType					= cOCT6100_IMAGE_TYPE_WIRELINE;
	pSharedInfo->ImageInfo.usMaxTailDisplacement		= 0;
	pSharedInfo->ImageInfo.usMaxTailLength				= cOCT6100_TAIL_LENGTH_128MS;
	pSharedInfo->DebugInfo.ulDebugEventSize				= 0x100;
	pSharedInfo->ImageInfo.byMaxNumberPlayoutEvents		= 32;
	pSharedInfo->DebugInfo.ulMatrixBaseAddress			= cOCT6100_MATRIX_DWORD_BASE;
	pSharedInfo->DebugInfo.ulDebugChanStatsByteSize		= cOCT6100_DEBUG_CHAN_STATS_EVENT_BYTE_SIZE;
	pSharedInfo->DebugInfo.ulDebugChanLiteStatsByteSize	= cOCT6100_DEBUG_CHAN_STATS_LITE_EVENT_BYTE_SIZE;
	pSharedInfo->DebugInfo.ulHotChannelSelectBaseAddress= cOCT6100_MATRIX_CHAN_SELECT_DWORD_ADD;
	pSharedInfo->DebugInfo.ulMatrixTimestampBaseAddress = cOCT6100_MATRIX_TIMESTAMP_DWORD_ADD;
	pSharedInfo->DebugInfo.ulMatrixWpBaseAddress		= cOCT6100_MATRIX_WRITE_PTR_DWORD_ADD;
	pSharedInfo->DebugInfo.ulAfWritePtrByteOffset		= 206;
	pSharedInfo->DebugInfo.ulRecordedPcmEventByteSize	= 4096;
	pSharedInfo->DebugInfo.ulAfEventCbByteSize			= 0x100000;

	/* Set all tones to invalid. */
	pSharedInfo->ImageInfo.byNumToneDetectors = 0;
	for ( i = 0; i < cOCT6100_MAX_TONE_EVENT; i++ )
	{
		pSharedInfo->ImageInfo.aToneInfo[ i ].ulToneID = cOCT6100_INVALID_VALUE;
		pSharedInfo->ImageInfo.aToneInfo[ i ].ulDetectionPort = cOCT6100_INVALID_PORT;
		Oct6100UserMemSet( pSharedInfo->ImageInfo.aToneInfo[ i ].aszToneName, 0x00, cOCT6100_TLV_MAX_TONE_NAME_SIZE );
	}
	/* Initialize the channel recording info. */
	pSharedInfo->DebugInfo.usRecordChanIndex = pSharedInfo->ChipConfig.usMaxChannels;
	pSharedInfo->DebugInfo.usRecordMemIndex = cOCT6100_INVALID_INDEX;
	
	pSharedInfo->DebugInfo.usCurrentDebugChanIndex = cOCT6100_INVALID_INDEX;
	/* Initialize the mixer information. */
	pSharedInfo->MixerInfo.usFirstBridgeEventPtr	= cOCT6100_INVALID_INDEX;
	pSharedInfo->MixerInfo.usFirstSinCopyEventPtr	= cOCT6100_INVALID_INDEX;
	pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr  = cOCT6100_INVALID_INDEX;
	pSharedInfo->MixerInfo.usLastBridgeEventPtr		= cOCT6100_INVALID_INDEX;
	pSharedInfo->MixerInfo.usLastSinCopyEventPtr	= cOCT6100_INVALID_INDEX;
	pSharedInfo->MixerInfo.usLastSoutCopyEventPtr	= cOCT6100_INVALID_INDEX;
	
	pSharedInfo->MixerInfo.usRecordCopyEventIndex	= cOCT6100_INVALID_INDEX;
	pSharedInfo->MixerInfo.usRecordSinEventIndex	= cOCT6100_INVALID_INDEX;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiCalculateInstanceSizes

Description:    Calculates the amount of memory needed for the instance
				structure memory block based on the user's configuration.  

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pChipOpen			Pointer to user chip configuration structure.

f_pInstSizes		Pointer to structure containing the size of memory needed
					by all pointers internal to the API instance.  The memory
					is needed to keep track of the present state of all the
					chip's resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiCalculateInstanceSizes
UINT32 Oct6100ApiCalculateInstanceSizes(
				IN OUT	tPOCT6100_CHIP_OPEN				f_pChipOpen,
				OUT		tPOCT6100_API_INSTANCE_SIZES	f_pInstSizes )
{
	UINT32	ulApiInstProcessSpecific;
	UINT32	ulTempVar;
	UINT32	ulResult;

	/* Start with all instance sizes set to 0. */
	Oct6100UserMemSet( f_pInstSizes, 0x00, sizeof( tOCT6100_API_INSTANCE_SIZES ) );

	/* All memory sizes are rounded up to the next multiple of 64 bytes. */

	/*-----------------------------------------------------------------------------*/
	/* Obtain size of static members of API instance. */
	f_pInstSizes->ulApiInstStatic = sizeof( tOCT6100_SHARED_INFO );
	mOCT6100_ROUND_MEMORY_SIZE( f_pInstSizes->ulApiInstStatic, ulTempVar )

	/* Calculate memory needed by pointers internal to the API instance. */

	/*-----------------------------------------------------------------------------*/
	/* Calculate memory needed for the EC channels. */
	ulResult = Oct6100ApiGetChannelsEchoSwSizes( f_pChipOpen, f_pInstSizes );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Memory needed by the TSI structures. */
	ulResult = Oct6100ApiGetTsiCnctSwSizes( f_pChipOpen, f_pInstSizes );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Calculate memory needed for the conference bridges. */
	ulResult = Oct6100ApiGetConfBridgeSwSizes( f_pChipOpen, f_pInstSizes );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Memory needed by the buffer playout structures. */
	ulResult = Oct6100ApiGetPlayoutBufferSwSizes( f_pChipOpen, f_pInstSizes );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;



	/*-----------------------------------------------------------------------------*/
	/* Memory needed by soft Rx Event buffers. */
	ulResult = Oct6100ApiGetEventsSwSizes( f_pChipOpen, f_pInstSizes );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Calculate memory needed for phasing tssts. */
	ulResult = Oct6100ApiGetPhasingTsstSwSizes( f_pChipOpen, f_pInstSizes );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Calculate memory needed for the ADPCM channels. */
	ulResult = Oct6100ApiGetAdpcmChanSwSizes( f_pChipOpen, f_pInstSizes );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Calculate memory needed for the management of TSSTs. */
	ulResult = Oct6100ApiGetTsstSwSizes( f_pInstSizes );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Calculate memory needed for the management of the mixer. */
	ulResult = Oct6100ApiGetMixerSwSizes( f_pChipOpen, f_pInstSizes );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Determine amount of memory needed for memory allocation softwares.  These
		pieces of software will be responsible for the allocation of the chip's
		external memory and API memory. */
	ulResult = Oct6100ApiGetMemorySwSizes( f_pChipOpen, f_pInstSizes );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;
	
	/*-----------------------------------------------------------------------------*/
	/* Memory needed for remote debugging sessions. */
	ulResult = Oct6100ApiGetRemoteDebugSwSizes( f_pChipOpen, f_pInstSizes );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;
	
	/*-----------------------------------------------------------------------------*/
	/* Calculate total memory needed by pointers internal to API instance.  The
		total contains both the process specific portion of the instance
		(tOCT6100_INSTANCE_API) and the shared portion (tOCT6100_SHARED_INFO).  The
		process specific portion will be used only in the case where the host system
		is a single-process one. */

	ulApiInstProcessSpecific = sizeof( tOCT6100_INSTANCE_API );
	mOCT6100_ROUND_MEMORY_SIZE( ulApiInstProcessSpecific, ulTempVar )

	f_pInstSizes->ulApiInstTotal = 
									f_pInstSizes->ulChannelList +
									f_pInstSizes->ulChannelAlloc +
									f_pInstSizes->ulTsiCnctList +
									f_pInstSizes->ulTsiCnctAlloc +
									f_pInstSizes->ulSoftToneEventsBuffer + 
									f_pInstSizes->ulSoftBufPlayoutEventsBuffer +
									f_pInstSizes->ulBiDirChannelList +
									f_pInstSizes->ulBiDirChannelAlloc +
									f_pInstSizes->ulConfBridgeList +
									f_pInstSizes->ulConfBridgeAlloc +
									f_pInstSizes->ulFlexConfParticipantsList +
									f_pInstSizes->ulFlexConfParticipantsAlloc +
									f_pInstSizes->ulPlayoutBufList +
									f_pInstSizes->ulPlayoutBufAlloc +
									f_pInstSizes->ulPlayoutBufMemoryNodeList +

									f_pInstSizes->ulCopyEventList +
									f_pInstSizes->ulCopyEventAlloc +
									f_pInstSizes->ulMixerEventList +
									f_pInstSizes->ulMixerEventAlloc +
									f_pInstSizes->ulPhasingTsstList +
									f_pInstSizes->ulPhasingTsstAlloc +
									f_pInstSizes->ulAdpcmChannelList + 
									f_pInstSizes->ulAdpcmChannelAlloc + 
									f_pInstSizes->ulConversionMemoryAlloc +
									f_pInstSizes->ulTsiMemoryAlloc +
									f_pInstSizes->ulRemoteDebugList +
									f_pInstSizes->ulRemoteDebugTree +
									f_pInstSizes->ulRemoteDebugPktCache +
									f_pInstSizes->ulRemoteDebugDataBuf +
									f_pInstSizes->ulTsstEntryList +
									f_pInstSizes->ulTsstEntryAlloc +									
									f_pInstSizes->ulTsstAlloc + 
									f_pInstSizes->ulApiInstStatic + 
									ulApiInstProcessSpecific;
	
	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiAllocateInstanceMemory

Description:    Allocates the API instance memory to the various members of
				the structure f_pApiInstance according to the sizes contained
				in f_pInstSizes.  No initialization of this memory is
				performed.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

f_pInstSizes		Pointer to structure containing the size of memory needed
					by all pointers internal to the API instance.  The memory
					is needed to keep track of the present state of all the
					chip's resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiAllocateInstanceMemory
UINT32 Oct6100ApiAllocateInstanceMemory(
				IN OUT	tPOCT6100_INSTANCE_API			f_pApiInstance,
				IN		tPOCT6100_API_INSTANCE_SIZES	f_pInstSizes )
{
	tPOCT6100_SHARED_INFO	pSharedInfo;
	UINT32	ulOffset;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Get address of first UINT32 of memory in API instance structure following */
	/* the static members of the API instance structure. */
	ulOffset = f_pInstSizes->ulApiInstStatic;

	/*===================================================================*/
	/* Allocate memory for the echo channels.*/
	pSharedInfo->ulChannelListOfst = ulOffset;
	ulOffset += f_pInstSizes->ulChannelList;
	pSharedInfo->ulChannelAllocOfst = ulOffset;
	ulOffset += f_pInstSizes->ulChannelAlloc;

	/*===================================================================*/
	/* Allocate memory for the TSI connections */
	pSharedInfo->ulTsiCnctListOfst = ulOffset;
	ulOffset += f_pInstSizes->ulTsiCnctList;
	pSharedInfo->ulTsiCnctAllocOfst = ulOffset;
	ulOffset += f_pInstSizes->ulTsiCnctAlloc;
	pSharedInfo->ulMixerEventListOfst = ulOffset;
	ulOffset += f_pInstSizes->ulMixerEventList;
	pSharedInfo->ulMixerEventAllocOfst = ulOffset;
	ulOffset += f_pInstSizes->ulMixerEventAlloc;

	pSharedInfo->ulBiDirChannelListOfst = ulOffset;
	ulOffset += f_pInstSizes->ulBiDirChannelList;
	pSharedInfo->ulBiDirChannelAllocOfst = ulOffset;
	ulOffset += f_pInstSizes->ulBiDirChannelAlloc;
	pSharedInfo->ulCopyEventListOfst = ulOffset;
	ulOffset += f_pInstSizes->ulCopyEventList;
	pSharedInfo->ulCopyEventAllocOfst = ulOffset;
	ulOffset += f_pInstSizes->ulCopyEventAlloc;

	/*===================================================================*/
	/* Allocate memory for the conference bridges */
	pSharedInfo->ulConfBridgeListOfst = ulOffset;
	ulOffset += f_pInstSizes->ulConfBridgeList;
	pSharedInfo->ulConfBridgeAllocOfst = ulOffset;
	ulOffset += f_pInstSizes->ulConfBridgeAlloc;

	/*===================================================================*/
	/* Allocate memory for the flexible conferencing participants. */
	pSharedInfo->ulFlexConfParticipantListOfst = ulOffset;
	ulOffset += f_pInstSizes->ulFlexConfParticipantsList;
	pSharedInfo->ulFlexConfParticipantAllocOfst = ulOffset;
	ulOffset += f_pInstSizes->ulFlexConfParticipantsAlloc;

	/*===================================================================*/
	/* Allocate memory for the play-out buffers */
	pSharedInfo->ulPlayoutBufListOfst = ulOffset;
	ulOffset += f_pInstSizes->ulPlayoutBufList;
	pSharedInfo->ulPlayoutBufAllocOfst = ulOffset;
	ulOffset += f_pInstSizes->ulPlayoutBufAlloc;
	pSharedInfo->ulPlayoutBufMemoryNodeListOfst = ulOffset;
	ulOffset += f_pInstSizes->ulPlayoutBufMemoryNodeList;


	
	/*===================================================================*/
	/* Allocate memory for the phasing TSSTs */
	pSharedInfo->ulPhasingTsstListOfst = ulOffset;
	ulOffset += f_pInstSizes->ulPhasingTsstList;
	pSharedInfo->ulPhasingTsstAllocOfst = ulOffset;
	ulOffset += f_pInstSizes->ulPhasingTsstAlloc;

	/*===================================================================*/
	/* Allocate memory for the ADPCM channel */
	pSharedInfo->ulAdpcmChanAllocOfst = ulOffset;
	ulOffset += f_pInstSizes->ulAdpcmChannelAlloc;
	pSharedInfo->ulAdpcmChanListOfst = ulOffset;
	ulOffset += f_pInstSizes->ulAdpcmChannelList;
	
	/*===================================================================*/
	/* Allocate memory for the conversion memory */
	pSharedInfo->ulConversionMemoryAllocOfst = ulOffset;
	ulOffset += f_pInstSizes->ulConversionMemoryAlloc;

	/*===================================================================*/
	/* Allocate memory for the TSI chariot memory */
	pSharedInfo->ulTsiMemoryAllocOfst = ulOffset;
	ulOffset += f_pInstSizes->ulTsiMemoryAlloc;
	
	/*===================================================================*/
	/* Allocate memory for the TSST management */
	pSharedInfo->ulTsstAllocOfst = ulOffset;
	ulOffset += f_pInstSizes->ulTsstAlloc;
	pSharedInfo->ulTsstListOfst = ulOffset;
	ulOffset += f_pInstSizes->ulTsstEntryList;
	pSharedInfo->ulTsstListAllocOfst = ulOffset;
	ulOffset += f_pInstSizes->ulTsstEntryAlloc;

	/*===================================================================*/
	pSharedInfo->SoftBufs.ulToneEventBufferMemOfst = ulOffset;
	ulOffset += f_pInstSizes->ulSoftToneEventsBuffer;

	pSharedInfo->SoftBufs.ulBufPlayoutEventBufferMemOfst = ulOffset;
	ulOffset += f_pInstSizes->ulSoftBufPlayoutEventsBuffer;
	/*===================================================================*/
	pSharedInfo->RemoteDebugInfo.ulSessionListOfst = ulOffset;
	ulOffset += f_pInstSizes->ulRemoteDebugList;

	pSharedInfo->RemoteDebugInfo.ulSessionTreeOfst = ulOffset;
	ulOffset += f_pInstSizes->ulRemoteDebugTree;

	pSharedInfo->RemoteDebugInfo.ulDataBufOfst = ulOffset;
	ulOffset += f_pInstSizes->ulRemoteDebugDataBuf;

	pSharedInfo->RemoteDebugInfo.ulPktCacheOfst = ulOffset;
	ulOffset += f_pInstSizes->ulRemoteDebugPktCache;
	/*===================================================================*/

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiInitializeInstanceMemory

Description:    Initializes the various members of the structure f_pApiInstance
				to reflect the current state of the chip and its resources.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiInitializeInstanceMemory
UINT32 Oct6100ApiInitializeInstanceMemory(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	UINT32	ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Initialize API EC channels. */
	ulResult = Oct6100ApiChannelsEchoSwInit( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Initialize the API TSI connection structures. */
	ulResult = Oct6100ApiTsiCnctSwInit( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Initialize the API conference bridges. */
	ulResult = Oct6100ApiConfBridgeSwInit( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Initialize the API buffer playout structures. */
	ulResult = Oct6100ApiPlayoutBufferSwInit( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Initialize the API phasing tssts. */
	ulResult = Oct6100ApiPhasingTsstSwInit( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Initialize the API ADPCM channels. */
	ulResult = Oct6100ApiAdpcmChanSwInit( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Initialize the external memory management structures. */
	ulResult = Oct6100ApiMemorySwInit( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Initialize TSST management stuctures. */
	ulResult = Oct6100ApiTsstSwInit( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Initialize the mixer management stuctures. */
	ulResult = Oct6100ApiMixerSwInit( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Initialize the remote debugging session management variables. */
	ulResult = Oct6100ApiRemoteDebuggingSwInit( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*-----------------------------------------------------------------------------*/
	/* Configure the interrupt registers. */
	ulResult = Oct6100ApiIsrSwInit( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiGetChipRevisionNum

Description:    Reads the chip's revision number register.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance			Pointer to API instance. This memory is used to keep
						the present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiGetChipRevisionNum
UINT32 Oct6100ApiGetChipRevisionNum(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tPOCT6100_SHARED_INFO	pSharedInfo;
	tOCT6100_READ_PARAMS	ReadParams;
	UINT32					ulResult;
	UINT16					usReadData;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Get the chip revision number. */
	ReadParams.pProcessContext = f_pApiInstance->pProcessContext;

	ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId;
	ReadParams.ulReadAddress = cOCT6100_CHIP_ID_REVISION_REG;
	ReadParams.pusReadData = &usReadData;

	mOCT6100_DRIVER_READ_API( ReadParams, ulResult )
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Save the info in the API miscellaneous structure. */
	pSharedInfo->MiscVars.usChipId = (UINT16)( usReadData & 0xFF );
	pSharedInfo->MiscVars.usChipRevision = (UINT16)( usReadData >> 8 );

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiDecodeKeyAndBist

Description:    This function decodes the key and runs the automatic BIST.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiDecodeKeyAndBist
UINT32 Oct6100ApiDecodeKeyAndBist(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tPOCT6100_SHARED_INFO		pSharedInfo;
	tPOCT6100_API_CHIP_CONFIG	pChipConfig;
	tOCT6100_WRITE_PARAMS		WriteParams;
	tOCT6100_READ_PARAMS		ReadParams;
	UINT16						ausBistData[ 3 ];
	UINT16						usReadData;
	UINT32						ulResult;
	BOOL						fBitEqual;
	UINT32						i;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Obtain a local pointer to the chip config structure */
	/* contained in the instance structure. */
	pChipConfig = &pSharedInfo->ChipConfig;

	/* Set the process context and user chip ID parameters once and for all. */
	WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteParams.ulUserChipId = pChipConfig->ulUserChipId;

	/* Set the process context and user chip ID parameters once and for all. */
	ReadParams.pProcessContext = f_pApiInstance->pProcessContext;

	ReadParams.ulUserChipId = pChipConfig->ulUserChipId;

	/* Write key in CPU internal memory. */
	for(i=0; i<8; i++)
	{
		WriteParams.ulWriteAddress = 0x150;
		WriteParams.usWriteData = 0x0000;
		if (( i % 2 ) == 0)
		{
			WriteParams.usWriteData  |= ((UINT16)pChipConfig->pbyImageFile[0x100 + ((i/2)*4) + 2]) << 8;
			WriteParams.usWriteData  |= ((UINT16)pChipConfig->pbyImageFile[0x100 + ((i/2)*4) + 3]) << 0;
		}
		else
		{
			WriteParams.usWriteData  |= ((UINT16)pChipConfig->pbyImageFile[0x100 + ((i/2)*4) + 0]) << 8;
			WriteParams.usWriteData  |= ((UINT16)pChipConfig->pbyImageFile[0x100 + ((i/2)*4) + 1]) << 0;
		}

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
		
		WriteParams.ulWriteAddress = 0x152;
		WriteParams.usWriteData = (UINT16)( 0x8000 | i );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}

	/* Write one in CPU internal memory. */
	for(i=0; i<8; i++)
	{
		WriteParams.ulWriteAddress = 0x150;
		if (i == 0) 
		{
			WriteParams.usWriteData = 0x0001;
		}
		else
		{
			WriteParams.usWriteData = 0x0000;
		}

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x152;
		WriteParams.usWriteData = (UINT16)( 0x8000 | ( i + 8 ));

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}

	/* Clear memory access registers: */
	WriteParams.ulWriteAddress = 0x150;
	WriteParams.usWriteData = 0x0000;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult )
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x152;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult )
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Run BISTs and key decode. */
	WriteParams.ulWriteAddress = 0x160;
	WriteParams.usWriteData = 0x0081;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Wait for the key decode PC to clear. */
	ulResult = Oct6100ApiWaitForPcRegisterBit( f_pApiInstance, 0x160, 0, 0, 100000, &fBitEqual );
	if ( TRUE != fBitEqual )
		return cOCT6100_ERR_FATAL_13;

	/* Read the key valid bit to make sure everything is ok. */
	ReadParams.ulReadAddress = 0x160;
	ReadParams.pusReadData = &usReadData;

	mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Either the firmware image was not loaded correctly (from pointer given by user) */
	/* or the channel capacity pins of the chip do not match what the firmware is expecting. */
	if ( ( usReadData & 0x4 ) == 0 )
		return cOCT6100_ERR_OPEN_INVALID_FIRMWARE_OR_CAPACITY_PINS;

	/* Read the result of the internal memory bist. */
	ReadParams.ulReadAddress = 0x110;
	ReadParams.pusReadData = &ausBistData[ 0 ];

	mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	ReadParams.ulReadAddress = 0x114;
	ReadParams.pusReadData = &ausBistData[ 1 ];

	mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;
	
	ReadParams.ulReadAddress = 0x118;
	ReadParams.pusReadData = &ausBistData[ 2 ];

	mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Check if an error was reported. */
	if (ausBistData[0] != 0x0000 || ausBistData[1] != 0x0000 || ausBistData[2] != 0x0000)
		return cOCT6100_ERR_OPEN_INTERNAL_MEMORY_BIST;

	/* Put key decoder in powerdown. */
	WriteParams.ulWriteAddress = 0x160;
	WriteParams.usWriteData = 0x008A;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiBootFc2Pll

Description:    Configures the chip's FC2 PLL.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiBootFc2Pll
UINT32 Oct6100ApiBootFc2Pll(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tPOCT6100_SHARED_INFO		pSharedInfo;
	tPOCT6100_API_CHIP_CONFIG	pChipConfig;
	tOCT6100_WRITE_PARAMS		WriteParams;
	UINT32						aulWaitTime[ 2 ];
	UINT32						ulResult;
	UINT32						ulFc2PllDivisor = 0;
	UINT32						ulMtDivisor = 0;
	UINT32						ulFcDivisor = 0;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Obtain local pointer to chip configuration structure. */
	pChipConfig = &pSharedInfo->ChipConfig;

	/* Set the process context and user chip ID parameters once and for all. */
	WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteParams.ulUserChipId = pChipConfig->ulUserChipId;

	/* First put the chip and main registers in soft-reset. */
	WriteParams.ulWriteAddress = 0x100;
	WriteParams.usWriteData = 0x0;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult )
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Select register configuration based on the memory frequency. */
	switch ( f_pApiInstance->pSharedInfo->ChipConfig.ulMemClkFreq )
	{
	case 133000000:
		ulFc2PllDivisor = 0x1050;
		ulMtDivisor = 0x4300;
		ulFcDivisor = 0x4043;
		pSharedInfo->MiscVars.usMaxNumberOfChannels = 672;
		pSharedInfo->MiscVars.usMaxH100Speed = 124;

		if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE )
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x050B;
		else
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x0516;

		break;
	case 125000000:
		ulFc2PllDivisor = 0x0F50;
		ulMtDivisor = 0x4300;
		ulFcDivisor = 0x4043;
		pSharedInfo->MiscVars.usMaxNumberOfChannels = 624;
		pSharedInfo->MiscVars.usMaxH100Speed = 116;

		if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE )
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x04CA;
		else
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x04D4;

		break;
	case 117000000:
		ulFc2PllDivisor = 0x0E50;
		ulMtDivisor = 0x4300;
		ulFcDivisor = 0x4043;
		pSharedInfo->MiscVars.usMaxNumberOfChannels = 576;
		pSharedInfo->MiscVars.usMaxH100Speed = 108;

		if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE )
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x0489;
		else
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x0492;

		break;
	case 108000000:
		ulFc2PllDivisor = 0x0D50;
		ulMtDivisor = 0x4300;
		ulFcDivisor = 0x4043;
		pSharedInfo->MiscVars.usMaxNumberOfChannels = 528;
		pSharedInfo->MiscVars.usMaxH100Speed = 99;

		if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE )
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x0408;
		else
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x0410;

		break;
	case 100000000:
		ulFc2PllDivisor = 0x0C50;
		ulMtDivisor = 0x4300;
		ulFcDivisor = 0x4043;
		pSharedInfo->MiscVars.usMaxNumberOfChannels = 480;
		pSharedInfo->MiscVars.usMaxH100Speed = 91;

		if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE )
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x03C8;
		else
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x03D0;

		break;
	case 92000000:
		ulFc2PllDivisor = 0x0B50;
		ulMtDivisor = 0x4300;
		ulFcDivisor = 0x4043;
		pSharedInfo->MiscVars.usMaxNumberOfChannels = 432;
		pSharedInfo->MiscVars.usMaxH100Speed = 83;

		if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE )
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x0387;
		else
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x038E;

		break;
	case 83000000:
		ulFc2PllDivisor = 0x0A50;
		ulMtDivisor = 0x4300;
		ulFcDivisor = 0x4043;
		pSharedInfo->MiscVars.usMaxNumberOfChannels = 384;
		pSharedInfo->MiscVars.usMaxH100Speed = 74;

		if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE )
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x0346;
		else
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x034C;

		break;
	case 75000000:
		ulFc2PllDivisor = 0x0950;
		ulMtDivisor = 0x4200;
		ulFcDivisor = 0x4043;
		pSharedInfo->MiscVars.usMaxNumberOfChannels = 336;
		pSharedInfo->MiscVars.usMaxH100Speed = 64;

		if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE )
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x0306;
		else
			pSharedInfo->MiscVars.usTdmClkBoundary = 0x030C;

		break;
	default:
		return cOCT6100_ERR_FATAL_DB;
	}

	/* Verify that the max channel is not too big based on the chip frequency. */
	if ( pSharedInfo->ChipConfig.usMaxChannels > pSharedInfo->MiscVars.usMaxNumberOfChannels )
		return cOCT6100_ERR_OPEN_MAX_ECHO_CHANNELS;
	
	/* Setup delay chains. */
	if ( (pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_SDR) ||  (pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS) )
	{
		/* SDRAM */
		WriteParams.ulWriteAddress = 0x1B0;
		WriteParams.usWriteData = 0x1003;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x1B2;
		WriteParams.usWriteData = 0x0021;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x1B4;
		WriteParams.usWriteData = 0x4030;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x1B6;
		WriteParams.usWriteData = 0x0021;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}
	else /* if ( cOCT6100_MEM_TYPE_DDR == pChipConfig->byMemoryType ) */
	{
		/* DDR */
		WriteParams.ulWriteAddress = 0x1B0;
		WriteParams.usWriteData = 0x201F;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x1B2;
		WriteParams.usWriteData = 0x0021;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x1B4;
		WriteParams.usWriteData = 0x1000;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x1B6;
		WriteParams.usWriteData = 0x0021;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}

	/* udqs */
	WriteParams.ulWriteAddress = 0x1B8;
	WriteParams.usWriteData = 0x1003;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x1BA;
	WriteParams.usWriteData = 0x0021;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* ldqs */
	WriteParams.ulWriteAddress = 0x1BC;
	WriteParams.usWriteData = 0x1000;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x1BE;
	WriteParams.usWriteData = 0x0021;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x12C;
	WriteParams.usWriteData = 0x0000;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x12E;
	WriteParams.usWriteData = 0x0000;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Select fc2pll for fast_clk and mtsclk sources. Select mem_clk_i for afclk. */
	WriteParams.ulWriteAddress = 0x140;
	WriteParams.usWriteData = (UINT16)ulMtDivisor;

	if ( f_pApiInstance->pSharedInfo->ChipConfig.byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS )
		WriteParams.usWriteData |= 0x0001;
	else
		WriteParams.usWriteData |= 0x0004;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x144;
	WriteParams.usWriteData = (UINT16)ulFcDivisor;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x13E;
	WriteParams.usWriteData = 0x0001;	/*  Remove reset from above divisors */

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Select upclk directly as ref source for fc2pll. */
	WriteParams.ulWriteAddress = 0x134;
	WriteParams.usWriteData = 0x0001;
		
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Setup fc2pll. */
	WriteParams.ulWriteAddress = 0x132;
	WriteParams.usWriteData = (UINT16)ulFc2PllDivisor;
		
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.usWriteData |= 0x02;	/* Raise fb divisor reset. */
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.usWriteData |= 0x80;	/* Raise IDDTN signal.*/
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Wait for fc2pll to stabilize. */
	aulWaitTime[ 0 ] = 2000;
	aulWaitTime[ 1 ] = 0;
	ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Drive mem_clk_o out on proper interface. */
	if ( TRUE == pChipConfig->fEnableMemClkOut )
	{
		if ( (pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_SDR) || (pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS)  )
		{
			WriteParams.ulWriteAddress = 0x128;
			WriteParams.usWriteData = 0x0301;

			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}
	
		if ( pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_DDR || pChipConfig->byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS )
		{
			WriteParams.ulWriteAddress = 0x12A;
			WriteParams.usWriteData = 0x000F;
			
			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}
	}

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiProgramFc1Pll

Description:    Configures the chip's FC1 PLL.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiProgramFc1Pll
UINT32 Oct6100ApiProgramFc1Pll(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tPOCT6100_SHARED_INFO		pSharedInfo;
	tPOCT6100_API_CHIP_CONFIG	pChipConfig;
	tOCT6100_WRITE_PARAMS		WriteParams;
	UINT32						aulWaitTime[ 2 ];
	UINT32						ulResult;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Obtain local pointer to chip configuration structure. */
	pChipConfig = &pSharedInfo->ChipConfig;

	/* Set the process context and user chip ID parameters once and for all. */
	WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteParams.ulUserChipId = pChipConfig->ulUserChipId;

	/* Programm P/Z bits. */
	WriteParams.ulWriteAddress = 0x130;
	
	if ( f_pApiInstance->pSharedInfo->ChipConfig.byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS )
		WriteParams.usWriteData  = 0x0041;
	else
		WriteParams.usWriteData  = 0x0040;

	WriteParams.usWriteData |= ( pChipConfig->byMemoryType << 8 );
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;
	
	/* Raise FB divisor. */
	WriteParams.usWriteData |= 0x0002;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;
	
	/* Raise IDDTN. */
	WriteParams.usWriteData |= 0x0080;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Wait for fc1pll to stabilize. */ 
	aulWaitTime[ 0 ] = 2000;
	aulWaitTime[ 1 ] = 0;
	ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Enable all the clock domains to do reset procedure. */
	WriteParams.ulWriteAddress = 0x186;
	WriteParams.usWriteData  = 0x015F;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	aulWaitTime[ 0 ] = 15000;
	aulWaitTime[ 1 ] = 0;
	ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiBootFc1Pll

Description:    Boot the chip's FC1 PLL.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiBootFc1Pll
UINT32 Oct6100ApiBootFc1Pll(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tPOCT6100_SHARED_INFO		pSharedInfo;
	tPOCT6100_API_CHIP_CONFIG	pChipConfig;
	tOCT6100_WRITE_PARAMS		WriteParams;
	UINT32						aulWaitTime[ 2 ];
	UINT32						ulResult;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Obtain local pointer to chip configuration structure. */
	pChipConfig = &pSharedInfo->ChipConfig;

	/* Set the process context and user chip ID parameters once and for all. */
	WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteParams.ulUserChipId = pChipConfig->ulUserChipId;

	/* Force bist_clk also (it too is used on resetable flops). */
	WriteParams.ulWriteAddress = 0x160;
	WriteParams.usWriteData  = 0x0188;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Force all cpu clocks on chariot controllers. */
	WriteParams.ulWriteAddress = 0x182;
	WriteParams.usWriteData  = 0x0002;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x184;
	WriteParams.usWriteData  = 0x0202;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	aulWaitTime[ 0 ] = 1000;
	aulWaitTime[ 1 ] = 0;
	ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Remove the reset on the entire chip and disable CPU access caching. */
	WriteParams.ulWriteAddress = 0x100;
	WriteParams.usWriteData  = 0x2003;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Remove the bist_clk. It is no longer needed.*/
	WriteParams.ulWriteAddress = 0x160;
	WriteParams.usWriteData  = 0x0088;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Disable all clks to prepare for bist clock switchover. */
	WriteParams.ulWriteAddress = 0x182;
	WriteParams.usWriteData  = 0x0001;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x186;
	WriteParams.usWriteData  = 0x0000;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x184;
	WriteParams.usWriteData  = 0x0101;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Deassert bist_active */
	WriteParams.ulWriteAddress = 0x160;
	WriteParams.usWriteData  = 0x0008;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Change CPU interface to normal mode (from boot mode). */
	WriteParams.ulWriteAddress = 0x154;
	WriteParams.usWriteData  = 0x0000;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Give a couple of BIST clock cycles to turn off the BIST permanently. */
	WriteParams.ulWriteAddress = 0x160;
	WriteParams.usWriteData  = 0x0108;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	ulResult = Oct6100ApiWaitForTime( f_pApiInstance, aulWaitTime );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Turn BIST clock off for the last time. */
	WriteParams.ulWriteAddress = 0x160;
	WriteParams.usWriteData  = 0x0008;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Reset procedure done! */

	/* Enable mclk for cpu interface and external memory controller. */
	WriteParams.ulWriteAddress = 0x186;
	WriteParams.usWriteData  = 0x0100;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiLoadImage

Description:    This function writes the firmware image in the external memory.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiLoadImage
UINT32 Oct6100ApiLoadImage(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tPOCT6100_SHARED_INFO		pSharedInfo;
	tOCT6100_WRITE_BURST_PARAMS	BurstParams;
	tOCT6100_READ_PARAMS		ReadParams;
	UINT32						ulResult;
	UINT32						ulTempPtr;
	UINT32						ulNumWrites;
	PUINT16						pusSuperArray;
	PUINT8						pbyImageFile;
	UINT32						ulByteCount = 0;
	UINT16						usReadData;
	UINT32						ulAddressOfst;
	UINT32						i;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Set the process context and user chip ID parameters once and for all. */
	BurstParams.pProcessContext = f_pApiInstance->pProcessContext;

	BurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;

	ReadParams.pProcessContext = f_pApiInstance->pProcessContext;

	ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
	ReadParams.pusReadData = &usReadData;

	/* Breakdown image into subcomponents. */
	ulTempPtr = cOCT6100_IMAGE_FILE_BASE + cOCT6100_IMAGE_AF_CST_OFFSET;

	for(i=0;i<cOCT6100_MAX_IMAGE_REGION;i++)
	{
		pSharedInfo->ImageRegion[ i ].ulPart1Size = pSharedInfo->ChipConfig.pbyImageFile[ 0x110 + ( i * 4 ) + 0 ];
		pSharedInfo->ImageRegion[ i ].ulPart2Size = pSharedInfo->ChipConfig.pbyImageFile[ 0x110 + ( i * 4 ) + 1 ];
		pSharedInfo->ImageRegion[ i ].ulClockInfo = pSharedInfo->ChipConfig.pbyImageFile[ 0x110 + ( i * 4 ) + 2 ];
		pSharedInfo->ImageRegion[ i ].ulReserved  = pSharedInfo->ChipConfig.pbyImageFile[ 0x110 + ( i * 4 ) + 3 ];

		if (i == 0)		/* AF constant. */
		{
			pSharedInfo->ImageRegion[ i ].ulPart1BaseAddress = ulTempPtr & 0x07FFFFFF;
			pSharedInfo->ImageRegion[ i ].ulPart2BaseAddress = 0;

			ulTempPtr += ( pSharedInfo->ImageRegion[ i ].ulPart1Size * 612 );
		}
		else if (i == 1)	/* NLP image */
		{
			pSharedInfo->ImageRegion[ i ].ulPart1BaseAddress = ulTempPtr & 0x07FFFFFF;
			pSharedInfo->ImageRegion[ i ].ulPart2BaseAddress = 0;

			ulTempPtr += ( pSharedInfo->ImageRegion[ i ].ulPart1Size * 2056 );
		}
		else	/* Others */
		{
			pSharedInfo->ImageRegion[ i ].ulPart1BaseAddress = ulTempPtr & 0x07FFFFFF;
			ulTempPtr += ( pSharedInfo->ImageRegion[ i ].ulPart1Size * 2064 );

			pSharedInfo->ImageRegion[ i ].ulPart2BaseAddress = ulTempPtr & 0x07FFFFFF;
			ulTempPtr += ( pSharedInfo->ImageRegion[ i ].ulPart2Size * 2448 );
		}
	}

	/* Write the image in external memory. */
	ulNumWrites = pSharedInfo->ChipConfig.ulImageSize / 2;

	BurstParams.ulWriteAddress = cOCT6100_IMAGE_FILE_BASE;
	BurstParams.pusWriteData = pSharedInfo->MiscVars.ausSuperArray;
	
	pusSuperArray = pSharedInfo->MiscVars.ausSuperArray;
	pbyImageFile = pSharedInfo->ChipConfig.pbyImageFile;

	while ( ulNumWrites != 0 )
	{
		if ( ulNumWrites >= pSharedInfo->ChipConfig.usMaxRwAccesses )
			BurstParams.ulWriteLength = pSharedInfo->ChipConfig.usMaxRwAccesses;
		else
			BurstParams.ulWriteLength = ulNumWrites;

		for ( i = 0; i < BurstParams.ulWriteLength; i++ )
		{
			pusSuperArray[ i ]  = ( UINT16 )(( pbyImageFile [ ulByteCount++ ]) << 8);
			pusSuperArray[ i ] |= ( UINT16 )pbyImageFile [ ulByteCount++ ];
		}

		mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		BurstParams.ulWriteAddress += 2 * BurstParams.ulWriteLength;
		ulNumWrites -= BurstParams.ulWriteLength;
	}

	/* Perform a serie of reads to make sure the image was correclty written into memory. */
	ulAddressOfst = ( pSharedInfo->ChipConfig.ulImageSize / 2 ) & 0xFFFFFFFE;
	while ( ulAddressOfst != 0 )
	{
		ReadParams.ulReadAddress = cOCT6100_IMAGE_FILE_BASE + ulAddressOfst;

		mOCT6100_DRIVER_READ_API( ReadParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		if ( (usReadData >> 8) != pbyImageFile[ ulAddressOfst ] )
			return cOCT6100_ERR_OPEN_IMAGE_WRITE_FAILED;

		ulAddressOfst = (ulAddressOfst / 2) & 0xFFFFFFFE;
	}

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiCpuRegisterBist

Description:    Tests the operation of the CPU registers.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiCpuRegisterBist
UINT32 Oct6100ApiCpuRegisterBist(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tPOCT6100_SHARED_INFO	pSharedInfo;
	tOCT6100_WRITE_PARAMS	WriteParams;
	tOCT6100_READ_PARAMS	ReadParams;
	UINT32	ulResult;
	UINT16	i;
	UINT16	usReadData;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Set the process context and user chip ID parameters once and for all. */
	WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;

	ReadParams.pProcessContext = f_pApiInstance->pProcessContext;

	ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;

	/* Assign read data pointer that will be used throughout the function. */
	ReadParams.pusReadData = &usReadData;

	/* Start with a walking bit test. */
	for ( i = 0; i < 16; i ++ )
	{
		/* Write at address 0x150.*/
		WriteParams.ulWriteAddress = 0x150;
		WriteParams.usWriteData = (UINT16)( 0x1 << i );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Write at address 0x180.*/
		WriteParams.ulWriteAddress = 0x180;
		WriteParams.usWriteData = (UINT16)( 0x1 << ( 15 - i ) );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Now read back the two registers to make sure the acceses were successfull. */
		ReadParams.ulReadAddress = 0x150;

		mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		if ( usReadData != ( 0x1 << i ) )
			return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR;

		ReadParams.ulReadAddress = 0x180;

		mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		if ( usReadData != ( 0x1 << ( 15 - i ) ) )
			return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR;
	}

	/* Write at address 0x150. */
	WriteParams.ulWriteAddress = 0x150;
	WriteParams.usWriteData = 0xCAFE;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Write at address 0x180. */
	WriteParams.ulWriteAddress = 0x180;
	WriteParams.usWriteData = 0xDECA;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Now read back the two registers to make sure the acceses were successfull. */
	ReadParams.ulReadAddress = 0x150;

	mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	if ( usReadData != 0xCAFE )
		return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR;

	ReadParams.ulReadAddress = 0x180;

	mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	if ( usReadData != 0xDECA )
		return cOCT6100_ERR_OPEN_CPU_REG_BIST_ERROR;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiBootSdram

Description:    Configure and test the SDRAM.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiBootSdram
UINT32 Oct6100ApiBootSdram(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tPOCT6100_SHARED_INFO		pSharedInfo;
	tPOCT6100_API_CHIP_CONFIG	pChipConfig;
	tOCT6100_WRITE_PARAMS		WriteParams;
	tOCT6100_READ_PARAMS		ReadParams;
	UINT32	ulResult;
	UINT16	usReadData;
	UINT16	usWriteData23E;
	UINT16	usWriteData230;
	UINT32	i;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Get local pointer to the chip configuration structure.*/
	pChipConfig = &f_pApiInstance->pSharedInfo->ChipConfig;

	/* Set the process context and user chip ID parameters once and for all. */
	WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;

	ReadParams.pProcessContext = f_pApiInstance->pProcessContext;

	ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
	ReadParams.pusReadData = &usReadData;

	usWriteData23E = 0x0000;
	usWriteData230 = 0x0000;

	if ( (pSharedInfo->ChipConfig.byMemoryType == cOCT6100_MEM_TYPE_SDR) || (pSharedInfo->ChipConfig.byMemoryType == cOCT6100_MEM_TYPE_SDR_PLL_BYPASS)  )
	{
		/* SDRAM: */
		switch( pChipConfig->ulMemoryChipSize )
		{
		case cOCT6100_MEMORY_CHIP_SIZE_8MB:
			usWriteData230 |= ( cOCT6100_16MB_MEMORY_BANKS << 2 );
			break;
		case cOCT6100_MEMORY_CHIP_SIZE_16MB:
			usWriteData230 |= ( cOCT6100_32MB_MEMORY_BANKS << 2 );
			break;
		case cOCT6100_MEMORY_CHIP_SIZE_32MB:
			usWriteData230 |= ( cOCT6100_64MB_MEMORY_BANKS << 2 );
			break;
		case cOCT6100_MEMORY_CHIP_SIZE_64MB:
			usWriteData230 |= ( cOCT6100_128MB_MEMORY_BANKS << 2 );
			break;
		default:
			return cOCT6100_ERR_FATAL_16;
		}

		usWriteData230 |= 0x0002;

		WriteParams.ulWriteAddress = 0x230;
		WriteParams.usWriteData = usWriteData230;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
		
		/* Precharge all banks. */
		usWriteData230 &= 0x000C;
		usWriteData230 |= 0x0010;

		WriteParams.ulWriteAddress = 0x230;
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		usWriteData230 |= 0x0002;

		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x23E;
		WriteParams.usWriteData = usWriteData23E;
		for ( i = 0; i < 5; i++ )
		{
			/* Wait cycle. */
			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}

		/* Program the mode register. */
		usWriteData23E = 0x0030;
		WriteParams.usWriteData = usWriteData23E;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		usWriteData230 &= 0x000C;
		usWriteData230 |= 0x0000;

		WriteParams.ulWriteAddress = 0x230;
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		usWriteData230 |= 0x0002;

		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x23E;
		WriteParams.usWriteData = usWriteData23E;
		for ( i = 0; i < 5; i++ )
		{
			/* Wait cycle. */
			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}
		
		/* Do CBR refresh (twice) */
		usWriteData230 &= 0x000C;
		usWriteData230 |= 0x0040;

		WriteParams.ulWriteAddress = 0x230;
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		usWriteData230 |= 0x0002;

		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x23E;
		WriteParams.usWriteData = usWriteData23E;
		for ( i = 0; i < 5; i++ )
		{
			/* Wait cycle. */
			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}

		WriteParams.ulWriteAddress = 0x230;
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x23E;
		WriteParams.usWriteData = usWriteData23E;
		for ( i = 0; i < 5; i++ )
		{
			/* Wait cycle. */
			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}
	}
	else
	{
		/* DDR: */
		switch( pChipConfig->ulMemoryChipSize )
		{
		case cOCT6100_MEMORY_CHIP_SIZE_16MB:
			usWriteData230 |= ( cOCT6100_16MB_MEMORY_BANKS << 2 );
			break;
		case cOCT6100_MEMORY_CHIP_SIZE_32MB:
			usWriteData230 |= ( cOCT6100_32MB_MEMORY_BANKS << 2 );
			break;
		case cOCT6100_MEMORY_CHIP_SIZE_64MB:
			usWriteData230 |= ( cOCT6100_64MB_MEMORY_BANKS << 2 );
			break;
		case cOCT6100_MEMORY_CHIP_SIZE_128MB:
			usWriteData230 |= ( cOCT6100_128MB_MEMORY_BANKS << 2 );
			break;
		default:
			return cOCT6100_ERR_FATAL_17;
		}
		WriteParams.ulWriteAddress = 0x230;
		WriteParams.usWriteData = usWriteData230;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Precharge all banks. */
		usWriteData230 &= 0x000C;
		usWriteData230 |= 0x0010;

		WriteParams.ulWriteAddress = 0x230;
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		usWriteData230 |= 0x0002;
	
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x23E;
		WriteParams.usWriteData = usWriteData23E;
		for ( i = 0; i < 5; i++ )
		{
			/* Wait cycle. */
			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}

		/* Program DDR mode register. */
		usWriteData23E = 0x4000;
		
		WriteParams.ulWriteAddress = 0x23E;
		WriteParams.usWriteData = usWriteData23E;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		usWriteData230 &= 0x000C;
		usWriteData230 |= 0x0000;

		WriteParams.ulWriteAddress = 0x230;
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		usWriteData230 |= 0x0002;
	
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x23E;
		WriteParams.usWriteData = usWriteData23E;
		for ( i = 0; i < 5; i++ )
		{
			/* Wait cycle. */
			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}
		
		/* Program SDR mode register. */
		usWriteData23E = 0x0161;

		WriteParams.ulWriteAddress = 0x23E;
		WriteParams.usWriteData = usWriteData23E;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		usWriteData230 &= 0x000C;
		usWriteData230 |= 0x0000;

		WriteParams.ulWriteAddress = 0x230;
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		usWriteData230 |= 0x0002;
	
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x23E;
		WriteParams.usWriteData = usWriteData23E;
		for ( i = 0; i < 5; i++ )
		{
			/* Wait cycle. */
			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}
		
		/* Precharge all banks. */
		usWriteData23E = 0xFFFF;

		WriteParams.ulWriteAddress = 0x23E;
		WriteParams.usWriteData = usWriteData23E;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		usWriteData230 &= 0x000C;
		usWriteData230 |= 0x0010;

		WriteParams.ulWriteAddress = 0x230;
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		usWriteData230 |= 0x0002;
	
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x23E;
		WriteParams.usWriteData = usWriteData23E;
		for ( i = 0; i < 5; i++ )
		{
			/* Wait cycle. */
			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}

		/* Do CBR refresh (twice) */
		usWriteData230 &= 0x000C;
		usWriteData230 |= 0x0040;

		WriteParams.ulWriteAddress = 0x230;
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		usWriteData230 |= 0x0002;
	
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x23E;
		WriteParams.usWriteData = usWriteData23E;
		for ( i = 0; i < 5; i++ )
		{
			/* Wait cycle. */
			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}

		WriteParams.ulWriteAddress = 0x230;
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x23E;
		WriteParams.usWriteData = usWriteData23E;
		for ( i = 0; i < 5; i++ )
		{
			/* Wait cycle.*/
			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}

		/* Program SDR mode register. */
		usWriteData23E = 0x0061;

		WriteParams.ulWriteAddress = 0x23E;
		WriteParams.usWriteData = usWriteData23E;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		usWriteData230 &= 0x000C;
		usWriteData230 |= 0x0000;

		WriteParams.ulWriteAddress = 0x230;
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		usWriteData230 |= 0x0002;
	
		WriteParams.usWriteData = usWriteData230;
		
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x23E;
		WriteParams.usWriteData = usWriteData23E;
		for ( i = 0; i < 5; i++ )
		{
			/* Wait cycle. */
			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}
	}

	/* Set the refresh frequency. */
	WriteParams.ulWriteAddress = 0x242;
	WriteParams.usWriteData = 0x0400;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x244;
	WriteParams.usWriteData = 0x0200;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x248;
	WriteParams.usWriteData = 0x800;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x246;
	WriteParams.usWriteData = 0x0012;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Enable the SDRAM and refreshes. */
	usWriteData230 &= 0x000C;
	usWriteData230 |= 0x0001;

	WriteParams.ulWriteAddress = 0x230;
	WriteParams.usWriteData = usWriteData230;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x246;
	WriteParams.usWriteData = 0x0013;
	
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiEnableClocks

Description:    This function will disable clock masking for all the modules
				of the chip. 

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiEnableClocks
UINT32 Oct6100ApiEnableClocks(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tOCT6100_WRITE_PARAMS	WriteParams;
	UINT32	ulResult;

	/* Initialize the process context and user chip ID once and for all. */
	WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId;

	/* Enable tdmie / adpcm mclk clocks. */
	WriteParams.ulWriteAddress = 0x186;
	WriteParams.usWriteData = 0x015F;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Configure the DQS register for the DDR memory */
	WriteParams.ulWriteAddress = 0x180;
	WriteParams.usWriteData = 0xFF00;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Enable pgsp chariot clocks */
	WriteParams.ulWriteAddress = 0x182;
	WriteParams.usWriteData = 0x0000;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;
	
	/* Enable af/mt chariot clocks */
	WriteParams.ulWriteAddress = 0x184;
	WriteParams.usWriteData = 0x0000;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiProgramNLP

Description:    This function will write image values to configure the NLP.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiProgramNLP
UINT32 Oct6100ApiProgramNLP(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tOCT6100_WRITE_PARAMS		WriteParams;
	tOCT6100_READ_PARAMS		ReadParams;
	tPOCT6100_SHARED_INFO		pSharedInfo;
	tPOCT6100_API_CHIP_CONFIG	pChipConfig;
	UINT32	ulResult;
	UINT16	usReadData;
	UINT16	usReadHighData;
	BOOL	fBitEqual;
	UINT32	ulEgoEntry[4];
	UINT32	ulTempAddress;
	UINT32  ulAfCpuUp = FALSE;
	UINT32	i;
	UINT32	ulLoopCounter = 0;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Get local pointer to the chip configuration structure.*/
	pChipConfig = &f_pApiInstance->pSharedInfo->ChipConfig;

	/* Initialize the process context and user chip ID once and for all. */
	WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId;

	/* Initialize the process context and user chip ID once and for all. */
	ReadParams.pProcessContext = f_pApiInstance->pProcessContext;

	ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId;
	ReadParams.pusReadData = &usReadData;

	if ( pSharedInfo->ChipConfig.fEnableProductionBist == TRUE )
	{
		UINT32	ulReadData;
		UINT32	ulBitPattern;
		UINT32	j, k;

		/* Since the pouch section (256 bytes) will not be tested by the firmware, */
		/* the API has to make sure this section is working correctly. */
		for ( k = 0; k < 2; k ++ )
		{
			if ( k == 0 )
				ulBitPattern = 0x1;
			else
				ulBitPattern = 0xFFFFFFFE;

			for ( j = 0; j < 32; j ++ )
			{
				/* Write the DWORDs. */
				for ( i = 0; i < 64; i ++ )
				{
					ulResult = Oct6100ApiWriteDword( f_pApiInstance, cOCT6100_POUCH_BASE + i * 4, ulBitPattern << j );
					if ( ulResult != cOCT6100_ERR_OK )
						return ulResult;
				}

				/* Read the DWORDs. */
				for ( i = 0; i < 64; i ++ )
				{
					ulResult = Oct6100ApiReadDword( f_pApiInstance, cOCT6100_POUCH_BASE + i * 4, &ulReadData );
					if ( ulResult != cOCT6100_ERR_OK )
						return ulResult;

					/* Check if the value matches. */
					if ( ( ulBitPattern << j ) != ulReadData )
						return cOCT6100_ERR_OPEN_PRODUCTION_BIST_POUCH_ERROR;
				}
			}
		}
	}

	/* Write the image info in the chip. */
	WriteParams.ulWriteAddress = cOCT6100_PART1_END_STATICS_BASE;
	WriteParams.usWriteData = (UINT16)( ( pSharedInfo->ImageRegion[ 0 ].ulPart1BaseAddress >> 16 ) & 0xFFFF );

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress += 2;
	WriteParams.usWriteData = (UINT16)( pSharedInfo->ImageRegion[ 0 ].ulPart1BaseAddress & 0xFFFF );

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	for( i = 0; i < 8; i++ )
	{
		if ( pSharedInfo->ImageRegion[ i + 2 ].ulPart1Size != 0 )
		{
			WriteParams.ulWriteAddress = cOCT6100_PART1_END_STATICS_BASE + 0x4 + ( i * 0xC );
			WriteParams.usWriteData = (UINT16)(( pSharedInfo->ImageRegion[ i + 2 ].ulPart1BaseAddress >> 16 ) & 0xFFFF );

			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;

			WriteParams.ulWriteAddress += 2;
			WriteParams.usWriteData = (UINT16)( pSharedInfo->ImageRegion[ i + 2 ].ulPart1BaseAddress & 0xFFFF );

			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}

		if ( pSharedInfo->ImageRegion[ i + 2 ].ulPart2Size != 0 )
		{
			WriteParams.ulWriteAddress = cOCT6100_PART1_END_STATICS_BASE + 0x4 + ( i * 0xC ) + 4;
			WriteParams.usWriteData = (UINT16)(( pSharedInfo->ImageRegion[ i + 2 ].ulPart2BaseAddress >> 16 ) & 0xFFFF );

			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;

			WriteParams.ulWriteAddress += 2;
			WriteParams.usWriteData = (UINT16)( pSharedInfo->ImageRegion[ i + 2 ].ulPart2BaseAddress & 0xFFFF );

			mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}

		WriteParams.ulWriteAddress = cOCT6100_PART1_END_STATICS_BASE + 0x4 + ( i * 0xC ) + 8;
		WriteParams.usWriteData  = 0x0000;
		WriteParams.usWriteData |= ( pSharedInfo->ImageRegion[ i + 2 ].ulPart1Size << 8 );
		WriteParams.usWriteData |= pSharedInfo->ImageRegion[ i + 2 ].ulPart2Size;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress += 2;
		WriteParams.usWriteData  = 0x0000;
		WriteParams.usWriteData |= ( pSharedInfo->ImageRegion[ i + 2 ].ulClockInfo << 8 );
		WriteParams.usWriteData |= pSharedInfo->ImageRegion[ i + 2 ].ulReserved;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}

	/* Put NLP in config mode. */
	WriteParams.ulWriteAddress = 0x2C2;
	WriteParams.usWriteData = 0x160E;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x692;
	WriteParams.usWriteData = 0x010A;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Upload the up to 8 NLP pages + 1 AF page (for timing reasons). */
	for ( i = 0; i < pSharedInfo->ImageRegion[ 1 ].ulPart1Size; i++ )
	{
		ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 1 ].ulPart1BaseAddress + 1028 * ( i * 2 ), 0x1280, 1024, &(ulEgoEntry[0]));
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 1 ].ulPart1BaseAddress + 1028 * (( i * 2 ) + 1 ), 0x1680, 1024, &(ulEgoEntry[2]));
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		ulResult = Oct6100ApiRunEgo( f_pApiInstance, FALSE, 2, ulEgoEntry );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
		
		/* Shift mt chariot memories. This process will complete by the time */
		/* the next LSU transfer is done. */
		WriteParams.ulWriteAddress = 0x692;
		WriteParams.usWriteData = 0x010B;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		ulResult = Oct6100ApiWaitForPcRegisterBit( f_pApiInstance, 0x692, 0, 0, 100000, &fBitEqual );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
		if ( TRUE != fBitEqual )
			return cOCT6100_ERR_FATAL_1A;
	}

	/* 1 AF page (for timing reasons). */
	ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 2 ].ulPart1BaseAddress + (516 * 0), 0x1280, 512, &(ulEgoEntry[0]));
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 2 ].ulPart1BaseAddress + (516 * 1), 0x1480, 512, &(ulEgoEntry[2]));
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	ulResult = Oct6100ApiRunEgo( f_pApiInstance, FALSE, 2, ulEgoEntry );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 2 ].ulPart1BaseAddress + (516 * 2), 0x1680, 512, &(ulEgoEntry[0]));
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	ulResult = Oct6100ApiCreateEgoEntry( cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + pSharedInfo->ImageRegion[ 2 ].ulPart1BaseAddress + (516 * 3), 0x1880, 512, &(ulEgoEntry[2]));
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	ulResult = Oct6100ApiRunEgo( f_pApiInstance, FALSE, 2, ulEgoEntry );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Write constant memory init context position in channel "672" for pgsp. */
	WriteParams.ulWriteAddress = 0x71A;
	WriteParams.usWriteData = 0x8000;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Set fixed PGSP event_in base address to 800 on a 2k boundary */
	WriteParams.ulWriteAddress = 0x716;
	WriteParams.usWriteData = 0x800 >> 11;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Set fixed PGSP event_out to 0x2C0000h on a 16k boundary */
	WriteParams.ulWriteAddress = 0x71C;
	WriteParams.usWriteData = 0x2C0000 >> 14;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Give chariot control of the chip. */
	WriteParams.ulWriteAddress = 0x712;
	WriteParams.usWriteData = 0x0000;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + 0x2C0000 + 0xC;
	ulTempAddress = 0x300000 + 0x0800;
	WriteParams.usWriteData = (UINT16)( ( ulTempAddress >> 16 ) & 0x07FF );

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + 0x2C0000 + 0xE;
	WriteParams.usWriteData = (UINT16)( ( ulTempAddress >> 0 ) & 0xFF00 );

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Write the init PGSP event in place. */
	WriteParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + 0x800;
	WriteParams.usWriteData = 0x0200;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + 0x802;
	WriteParams.usWriteData = 0x02A0;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Also write the register 710, which tells PGSP how many tones are supported. */
	WriteParams.ulWriteAddress = 0x710;
	WriteParams.usWriteData = 0x0000;
	WriteParams.usWriteData |= pChipConfig->pbyImageFile[ 0x7FA ] << 8;
	WriteParams.usWriteData |= pChipConfig->pbyImageFile[ 0x7FB ] << 0;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Start both processors in the NLP. */
	WriteParams.ulWriteAddress = 0x373FE;
	WriteParams.usWriteData = 0x00FF;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x37BFE;
	WriteParams.usWriteData = 0x00FE;	/* Tell processor 1 to just go to sleep. */

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x37FC6;
	WriteParams.usWriteData = 0x8004;	/* First PC.*/

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x37FD0;
	WriteParams.usWriteData = 0x0002;	/* Take out of reset. */

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x37FD2;
	WriteParams.usWriteData = 0x0002;	/* Take out of reset. */

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Start processor in the AF. */
	for ( i = 0; i < 16; i ++ )
	{
		WriteParams.ulWriteAddress = cOCT6100_POUCH_BASE + ( i * 2 );
		if ( i == 9 )
		{
			if ( pSharedInfo->ChipConfig.fEnableProductionBist == TRUE )
			{
				WriteParams.usWriteData = cOCT6100_PRODUCTION_BOOT_TYPE;
			}
			else
			{
				WriteParams.usWriteData = cOCT6100_AF_BOOT_TYPE;
			}
		}
		else
			WriteParams.usWriteData = 0x0000;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}

	/* Check if the production BIST mode was requested. */
	if ( pSharedInfo->ChipConfig.fEnableProductionBist == TRUE )
	{
		UINT32	ulTotalElements = 3;
		UINT32	ulCrcKey;
		UINT32	aulMessage[ 4 ];
		UINT32	ulWriteAddress = 0x20 + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS;

		/* Magic key. */
		aulMessage[ 0 ] = 0xCAFECAFE; 
		/* Memory size. */
		aulMessage[ 1 ] = pSharedInfo->MiscVars.ulTotalMemSize;
		/* Loop count. */
		aulMessage[ 2 ] = pSharedInfo->ChipConfig.ulNumProductionBistLoops;
		/* CRC initialized. */
		aulMessage[ 3 ] = 0;

		ulResult = Oct6100ApiProductionCrc( f_pApiInstance, aulMessage, ulTotalElements, &ulCrcKey );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		aulMessage[ 3 ] = ulCrcKey;

		/* Write the message to the external memory. */
		for ( i = 0; i < ulTotalElements + 1; i ++ )
		{
			ulResult = Oct6100ApiWriteDword( f_pApiInstance, ulWriteAddress + i * 4, aulMessage[ i ] );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}
	}

	WriteParams.ulWriteAddress = 0xFFFC6;
	WriteParams.usWriteData = 0x1284;	/* First PC.*/

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;
	
	WriteParams.ulWriteAddress = 0xFFFD0;
	WriteParams.usWriteData = 0x0002;	/* Take out of reset. */

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	while ( ulAfCpuUp == FALSE )
	{
		if ( ulAfCpuUp == FALSE )
		{
			ReadParams.ulReadAddress = cOCT6100_POUCH_BASE;
			ReadParams.pusReadData = &usReadHighData;

			mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;

			ReadParams.ulReadAddress += 2;
			ReadParams.pusReadData = &usReadData;

			mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;

			if ( pSharedInfo->ChipConfig.fEnableProductionBist == TRUE )
			{
				/* Should read 0x0007 when bisting. */
				if ( ( usReadHighData & 0xFFFF ) == cOCT6100_PRODUCTION_BOOT_TYPE )
				{
					/* Verify if the bist has started successfully. */
					if ( ( usReadData & 0xFFFF ) == 0x0002 )
						return cOCT6100_ERR_OPEN_PRODUCTION_BIST_CONF_FAILED;
					else if ( ( usReadData & 0xFFFF ) != 0xEEEE )
						return cOCT6100_ERR_OPEN_PRODUCTION_BOOT_FAILED;

					ulAfCpuUp = TRUE;
				}
			}
			else /* if ( pSharedInfo->ChipConfig.fEnableProductionBist == FALSE ) */
			{
				if ( ( usReadHighData & 0xFFFF ) == cOCT6100_AF_BOOT_TYPE )
				{
					/* Verify if the bist succeeded. */
					if ( ( usReadData & 0xFFFF ) != 0x0000 )
						return cOCT6100_ERR_OPEN_FUNCTIONAL_BIST_FAILED;	/* Bad chip. */

					ulAfCpuUp = TRUE;
				}
			}
		}

		ulLoopCounter++;

		if ( ulLoopCounter == cOCT6100_MAX_LOOP_CPU_TIMEOUT )
			return cOCT6100_ERR_OPEN_AF_CPU_TIMEOUT;
	}

	/* Return NLP in operationnal mode. */
	WriteParams.ulWriteAddress = 0x2C2;
	WriteParams.usWriteData = 0x060E;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x692;
	WriteParams.usWriteData = 0x0000;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiSetH100Register

Description:    This function will configure the H.100 registers.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiSetH100Register
UINT32 Oct6100ApiSetH100Register(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tOCT6100_WRITE_PARAMS		WriteParams;
	UINT32						ulResult;
	tPOCT6100_SHARED_INFO		pSharedInfo;
	tPOCT6100_API_CHIP_CONFIG	pChipConfig;
	UINT32						i;
	UINT32						ulOffset;
	BOOL						fAllStreamAt2Mhz = TRUE;
	const UINT16	ausAdpcmResetContext[32] = { 0x1100, 0x0220, 0x0000, 0x0000, 0x0000, 0x0020, 0x0000, 0x0000, 0x0008, 0x0000, 0x0000, 0x0100, 0x0000, 0x0020, 0x0000, 0x0000, 0x0000, 0x0002, 0x0000, 0x0000, 0x0040, 
												 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x0000, 0x0010, 0x0000, 0x0000, 0x0000};

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Get local pointer to the chip configuration structure. */
	pChipConfig = &f_pApiInstance->pSharedInfo->ChipConfig;

	/* Initialize the process context and user chip ID once and for all. */
	WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId;

	/* Set the Global OE bit. */
	WriteParams.ulWriteAddress = 0x300;
	WriteParams.usWriteData = 0x0004;

	/* Set the number of streams. */
	switch( pChipConfig->byMaxTdmStreams )
	{
	case 32:
		WriteParams.usWriteData |= ( 0 << 3 );
		break;
	case 16:
		WriteParams.usWriteData |= ( 1 << 3 );
		break;
	case 8:
		WriteParams.usWriteData |= ( 2 << 3 );
		break;
	case 4:
		WriteParams.usWriteData |= ( 3 << 3 );
		break;
	default:
		break;
	}

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Configure the stream frequency. */
	WriteParams.ulWriteAddress = 0x330;
	WriteParams.usWriteData = 0x0000;
	for ( i = 0; i < (UINT32)(pChipConfig->byMaxTdmStreams / 4); i++)
	{
		ulOffset = i*2;
		switch( pChipConfig->aulTdmStreamFreqs[ i ] )
		{
		case cOCT6100_TDM_STREAM_FREQ_2MHZ:
			WriteParams.usWriteData |= ( 0x0 << ulOffset );
			break;
		case cOCT6100_TDM_STREAM_FREQ_4MHZ:
			WriteParams.usWriteData |= ( 0x1 << ulOffset );
			fAllStreamAt2Mhz = FALSE;
			break;
		case cOCT6100_TDM_STREAM_FREQ_8MHZ:
			WriteParams.usWriteData |= ( 0x2 << ulOffset );
			fAllStreamAt2Mhz = FALSE;
			break;
		default:
			break;
		}
	}

	/* Set the stream to 16 MHz if the fast H.100 mode is selected. */
	if ( pChipConfig->fEnableFastH100Mode == TRUE )
	{
		fAllStreamAt2Mhz = FALSE;
		WriteParams.usWriteData = 0xFFFF;
	}

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE )
	{
		/* Make the chip track both clock A and B to perform fast H.100 mode. */
		WriteParams.ulWriteAddress = 0x322;
		WriteParams.usWriteData = 0x0004;
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Enable the fast H.100 mode. */
		WriteParams.ulWriteAddress = 0x332;
		WriteParams.usWriteData = 0x0003;
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}

	WriteParams.ulWriteAddress = 0x376;
	WriteParams.usWriteData = (UINT16)( pSharedInfo->MiscVars.usTdmClkBoundary );
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Select delay for early clock (90 and 110). */
	WriteParams.ulWriteAddress = 0x378;
	if ( pSharedInfo->ChipConfig.fEnableFastH100Mode == TRUE )
		WriteParams.usWriteData = 0x000A;
	else
	{
		/* Set the TDM sampling. */
		if ( pSharedInfo->ChipConfig.byTdmSampling == cOCT6100_TDM_SAMPLE_AT_RISING_EDGE )
		{
			WriteParams.usWriteData = 0x0AF0;
		}
		else if ( pSharedInfo->ChipConfig.byTdmSampling == cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE )
		{
			WriteParams.usWriteData = 0x0A0F;
		}
		else /* pSharedInfo->ChipConfig.ulTdmSampling == cOCT6100_TDM_SAMPLE_AT_3_QUARTERS */
		{
			WriteParams.usWriteData = 0x0A08;
		}
	}

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Protect chip by preventing too rapid timeslot arrival (mclk == 133 MHz). */
	WriteParams.ulWriteAddress = 0x37A;
	WriteParams.usWriteData = (UINT16)pSharedInfo->MiscVars.usMaxH100Speed;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Allow H.100 TS to progress. */
	WriteParams.ulWriteAddress = 0x382;
	WriteParams.usWriteData = 0x0000;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Set by-pass mode. */
	WriteParams.ulWriteAddress = 0x50E;
	WriteParams.usWriteData = 0x0001;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* TDMIE bits. */
	WriteParams.ulWriteAddress = 0x500;
	WriteParams.usWriteData = 0x0003;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Write normal ADPCM reset values in ADPCM context 1344. */
	for(i=0;i<32;i++)
	{
		WriteParams.ulWriteAddress = 0x140000 + ( 0x40 * 1344 ) + ( i * 2 );
		WriteParams.usWriteData = ausAdpcmResetContext[i];

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}

	/* Make sure delay flops are configured correctly if all streams are at 2 MHz. */
	if ( fAllStreamAt2Mhz == TRUE )
	{
		/* Setup H.100 sampling to lowest value. */
		WriteParams.ulWriteAddress = 0x144;
		WriteParams.usWriteData = 0x4041;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK  )
			return ulResult;

		WriteParams.ulWriteAddress = 0x378;
		WriteParams.usWriteData = 0x0A00;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK  )
			return ulResult;
	}
	
	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiWriteMiscellaneousRegisters

Description:    This function will write to various registers to activate the chip.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiWriteMiscellaneousRegisters
UINT32 Oct6100ApiWriteMiscellaneousRegisters(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tOCT6100_WRITE_PARAMS	WriteParams;
	UINT32	ulResult;

	/* Initialize the process context and user chip ID once and for all. */
	WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId;

	/* Free the interrupt pin of the chip (i.e. remove minimum time requirement between interrupts). */
	WriteParams.ulWriteAddress = 0x214;
	WriteParams.usWriteData = 0x0000;
	if ( f_pApiInstance->pSharedInfo->ChipConfig.byInterruptPolarity == cOCT6100_ACTIVE_HIGH_POLARITY )
		WriteParams.usWriteData |= 0x4000;
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult )
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Write MT chariot interval */
	WriteParams.ulWriteAddress = 0x2C2;
	if ( f_pApiInstance->pSharedInfo->ImageInfo.usMaxNumberOfChannels > 640 )
		WriteParams.usWriteData = 0x05EA;
	else if ( f_pApiInstance->pSharedInfo->ImageInfo.usMaxNumberOfChannels > 513 )
		WriteParams.usWriteData = 0x0672;
	else /* if ( f_pApiInstance->pSharedInfo->ImageInfo.usMaxNumberOfChannels <= 513 ) */
		WriteParams.usWriteData = 0x0750;
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Write set second part5 time. */
	WriteParams.ulWriteAddress = 0x2C4;
	WriteParams.usWriteData = 0x04A0;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Write CPU bucket timer to guarantee 200 cycles between each CPU access. */
	WriteParams.ulWriteAddress = 0x234;
	WriteParams.usWriteData = 0x0804;	

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress = 0x236;
	WriteParams.usWriteData = 0x0100;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiCreateSerializeObjects

Description:    Creates a handle to each serialization object used by the API.

				Note that in a multi-process system the user's process context
				structure pointer is needed by this function.  Thus, the
				pointer must be valid.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

f_ulUserChipId		User chip ID for this serialization object.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiCreateSerializeObjects
UINT32 Oct6100ApiCreateSerializeObjects(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance,
				IN		UINT32					f_ulUserChipId )
{
	tOCT6100_CREATE_SERIALIZE_OBJECT	CreateSerObj;
	UINT32	ulResult;
	CHAR	szSerObjName[ 64 ] = "Oct6100ApiXXXXXXXXApiSerObj";


	/* Set some parameters of the create structure once and for all. */
	CreateSerObj.pProcessContext = f_pApiInstance->pProcessContext;
	CreateSerObj.pszSerialObjName = szSerObjName;

	/*----------------------------------------------------------------------*/
	/* Set the chip ID in the semaphore name. */
	szSerObjName[ 10 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 28 ) & 0xFF );
	szSerObjName[ 11 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 24 ) & 0xFF );
	szSerObjName[ 12 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 20 ) & 0xFF );
	szSerObjName[ 13 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 16 ) & 0xFF );
	szSerObjName[ 14 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >> 12 ) & 0xFF );
	szSerObjName[ 15 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >>  8 ) & 0xFF );
	szSerObjName[ 16 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >>  4 ) & 0xFF );
	szSerObjName[ 17 ] = (CHAR) Oct6100ApiHexToAscii( (f_ulUserChipId >>  0 ) & 0xFF );

	ulResult = Oct6100UserCreateSerializeObject( &CreateSerObj );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;
	f_pApiInstance->ulApiSerObj = CreateSerObj.ulSerialObjHndl;
	/*----------------------------------------------------------------------*/



	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiDestroySerializeObjects

Description:    Destroy handles to each serialization object used by the API.

				Note that in a multi-process system the user's process context
				structure pointer is needed by this function.  Thus, the
				pointer must be valid.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiDestroySerializeObjects
UINT32 Oct6100ApiDestroySerializeObjects(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tOCT6100_DESTROY_SERIALIZE_OBJECT	DestroySerObj;
	UINT32	ulResult;

	/* Set some parameters of the create structure once and for all. */
	DestroySerObj.pProcessContext = f_pApiInstance->pProcessContext;
	DestroySerObj.ulSerialObjHndl = f_pApiInstance->ulApiSerObj;	

	ulResult = Oct6100UserDestroySerializeObject( &DestroySerObj );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiRunEgo

Description:    Private function used to communicate with the internal processors.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

f_fStoreFlag		Type of access performed. (Load or Store)
f_ulNumEntry		Number of access.
f_aulEntry			Array of access to perform.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiRunEgo
UINT32 Oct6100ApiRunEgo( 
				IN OUT	tPOCT6100_INSTANCE_API			f_pApiInstance, 
				IN		BOOL							f_fStoreFlag, 
				IN		UINT32							f_ulNumEntry, 
				OUT		PUINT32							f_aulEntry )
{
	tPOCT6100_SHARED_INFO		pSharedInfo;
	tPOCT6100_API_CHIP_CONFIG	pChipConfig;
	tOCT6100_WRITE_PARAMS		WriteParams;
	tOCT6100_READ_PARAMS		ReadParams;
	UINT32	ulResult;
	UINT32	aulCpuLsuCmd[ 2 ];
	UINT16	usReadData;
	UINT32	i;
	BOOL	fConditionFlag = TRUE;
	UINT32	ulLoopCounter = 0;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Get local pointer to the chip configuration structure. */
	pChipConfig = &f_pApiInstance->pSharedInfo->ChipConfig;

	/* Set the process context and user chip ID parameters once and for all. */
	WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;

	ReadParams.pProcessContext = f_pApiInstance->pProcessContext;

	ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
	ReadParams.pusReadData = &usReadData;

	/* No more than 2 entries may be requested. */
	if ( f_ulNumEntry > 2 )
		return cOCT6100_ERR_FATAL_1B;

	/* Write the requested entries at address reserved for CPU. */
	for( i = 0; i < f_ulNumEntry; i++ )
	{
		WriteParams.ulWriteAddress = cOCT6100_PART1_API_SCRATCH_PAD + ( 0x8 * i );
		WriteParams.usWriteData = (UINT16)(( f_aulEntry[ i * 2 ] >> 16 ) & 0xFFFF );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress += 2;
		WriteParams.usWriteData = (UINT16)( f_aulEntry[ i * 2 ] & 0xFFFF );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress += 2;
		WriteParams.usWriteData = (UINT16)(( f_aulEntry[ (i * 2) + 1] >> 16 ) & 0xFFFF );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress += 2;
		WriteParams.usWriteData = (UINT16)( f_aulEntry[ (i * 2) + 1] & 0xFFFF );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}

	/* Preincrement code point. */
	pSharedInfo->MiscVars.usCodepoint++;

	/* Create DWORD 0 of command. */
	aulCpuLsuCmd[0] = 0x00000000;
	if ( f_fStoreFlag == FALSE )
		aulCpuLsuCmd[0] |= 0xC0000000;	/* EGO load. */
	else
		aulCpuLsuCmd[0] |= 0xE0000000;	/* EGO store. */

	aulCpuLsuCmd[0] |= (f_ulNumEntry - 1) << 19;
	aulCpuLsuCmd[0] |= cOCT6100_PART1_API_SCRATCH_PAD;

	/* Create DWORD 1 of command. */
	aulCpuLsuCmd[1] = 0x00000000;
	aulCpuLsuCmd[1] |= ( ( cOCT6100_PART1_API_SCRATCH_PAD + 0x10 ) & 0xFFFF ) << 16;
	aulCpuLsuCmd[1] |= pSharedInfo->MiscVars.usCodepoint;

	/* Write the EGO command in the LSU CB. */
	WriteParams.ulWriteAddress = cOCT6100_PART1_CPU_LSU_CB_BASE + ((pSharedInfo->MiscVars.usCpuLsuWritePtr & 0x7) * 0x8 );
	WriteParams.usWriteData = (UINT16)(( aulCpuLsuCmd[ 0 ] >> 16 ) & 0xFFFF );

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;
	
	WriteParams.ulWriteAddress += 2;
	WriteParams.usWriteData = (UINT16)( aulCpuLsuCmd[ 0 ] & 0xFFFF );

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress += 2;
	WriteParams.usWriteData = (UINT16)(( aulCpuLsuCmd[ 1 ] >> 16 ) & 0xFFFF );

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	WriteParams.ulWriteAddress += 2;
	WriteParams.usWriteData = (UINT16)( aulCpuLsuCmd[ 1 ] & 0xFFFF );

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Post increment the write pointer. */
	pSharedInfo->MiscVars.usCpuLsuWritePtr++;

	/* Indicate new write pointer position to HW. */
	WriteParams.ulWriteAddress = cOCT6100_PART1_EGO_REG + 0x5A;
	WriteParams.usWriteData = (UINT16)( pSharedInfo->MiscVars.usCpuLsuWritePtr & 0x7 );

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Wait for codepoint to be updated before returning. */
	while( fConditionFlag )
	{
		ReadParams.ulReadAddress = cOCT6100_PART1_API_SCRATCH_PAD + 0x12;
		usReadData = (UINT16)( pSharedInfo->MiscVars.usCodepoint );

		mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	
		if ( usReadData == pSharedInfo->MiscVars.usCodepoint )
			fConditionFlag = FALSE;

		ulLoopCounter++;

		if ( ulLoopCounter == cOCT6100_MAX_LOOP )
			return cOCT6100_ERR_OPEN_EGO_TIMEOUT;
	}

	/* CRC error bit must be zero. */
	ReadParams.ulReadAddress = 0x202;

	mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	if ( ( usReadData & 0x0400 ) != 0 )
		return cOCT6100_ERR_OPEN_CORRUPTED_IMAGE;
	
	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiCreateEgoEntry

Description:    Private function used to create an access structure to be sent
				to the internal processors.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_ulExternalAddress		External memory address for the access.
f_ulInternalAddress		Which process should receive the command.
f_ulNumBytes			Number of bytes associated to the access.
f_aulEntry			Array of access to perform.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiCreateEgoEntry
UINT32 Oct6100ApiCreateEgoEntry( 
				IN		UINT32						f_ulExternalAddress, 
				IN		UINT32						f_ulInternalAddress, 
				IN		UINT32						f_ulNumBytes, 
				OUT		UINT32						f_aulEntry[ 2 ] )
{
	f_aulEntry[0] = 0x80000000;
	f_aulEntry[0] |= f_ulExternalAddress & 0x07FFFFFC;
	
	f_aulEntry[1] = 0x0011C000;
	f_aulEntry[1] |= (f_ulNumBytes / 8) << 23;
	f_aulEntry[1] |= (f_ulInternalAddress >> 2) & 0x3FFF;

	return cOCT6100_ERR_OK;
}
#endif








/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiInitChannels

Description:    This function will initialize all the channels to power down.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiInitChannels
UINT32 Oct6100ApiInitChannels(
				IN OUT	tPOCT6100_INSTANCE_API f_pApiInstance )
{
	tPOCT6100_SHARED_INFO		pSharedInfo;
	UINT32 i;
	UINT32 ulResult;
	tOCT6100_WRITE_BURST_PARAMS	BurstParams;
	tOCT6100_WRITE_PARAMS		WriteParams;
	tOCT6100_READ_PARAMS		ReadParams;
	UINT16						usReadData;
	UINT32						ulTempData;
	UINT32						ulBaseAddress;
	UINT32						ulFeatureBytesOffset;
	UINT32						ulFeatureBitOffset;
	UINT32						ulFeatureFieldLength;
	UINT32						ulMask;
	UINT16						ausWriteData[ 4 ];
	UINT16						usLoopCount = 0;
	UINT16						usWriteData = 0;
	UINT16						usMclkRead;
	UINT16						usLastMclkRead;
	UINT16						usMclkDiff;
	UINT32						ulNumberOfCycleToWait;
	UINT32						ulTimeoutCounter;

	pSharedInfo = f_pApiInstance->pSharedInfo;

	WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId;

	BurstParams.pProcessContext = f_pApiInstance->pProcessContext;

	BurstParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId;
	BurstParams.pusWriteData = ausWriteData;

	ReadParams.pProcessContext = f_pApiInstance->pProcessContext;

	ReadParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId;
	ReadParams.pusReadData = &usReadData;
	
	/* Verify that the image has enough memory to work correctly. */
	if ( ( pSharedInfo->MiscVars.ulTotalMemSize + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS ) < pSharedInfo->MemoryMap.ulFreeMemBaseAddress )
		return cOCT6100_ERR_OPEN_INSUFFICIENT_EXTERNAL_MEMORY;

	/* Verify that the tail length is supported by the device.*/
	if ( pSharedInfo->ChipConfig.usTailDisplacement > pSharedInfo->ImageInfo.usMaxTailDisplacement )
		return cOCT6100_ERR_NOT_SUPPORTED_OPEN_TAIL_DISPLACEMENT_VALUE;

	/* Verify that acoustic echo is supported by the device. */
	if ( pSharedInfo->ChipConfig.fEnableAcousticEcho == TRUE && pSharedInfo->ImageInfo.fAcousticEcho == FALSE )
		return cOCT6100_ERR_NOT_SUPPORTED_OPEN_ACOUSTIC_ECHO;
	
	/* Verify that the image supports all the requested channels. */
	if ( pSharedInfo->ChipConfig.usMaxChannels > pSharedInfo->ImageInfo.usMaxNumberOfChannels )
		return cOCT6100_ERR_NOT_SUPPORTED_OPEN_MAX_ECHO_CHANNELS_VALUE;

	/* Max number of channels the image supports + 1 for channel recording, if requested */
	if ( ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE )
	  && ( pSharedInfo->ImageInfo.usMaxNumberOfChannels < cOCT6100_MAX_ECHO_CHANNELS )
	  && ( pSharedInfo->ChipConfig.usMaxChannels == pSharedInfo->ImageInfo.usMaxNumberOfChannels ) )
		return cOCT6100_ERR_NOT_SUPPORTED_OPEN_MAX_ECHO_CHANNELS_VALUE; 
	
	/* Initialize the memory for all required channels. */
	for( i = 0; i < f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels; i++ )
	{
		/*==============================================================================*/
		/*	Configure the Global Static Configuration memory of the channel. */

		ulBaseAddress = cOCT6100_CHANNEL_ROOT_BASE + ( i * cOCT6100_CHANNEL_ROOT_SIZE ) + cOCT6100_CHANNEL_ROOT_GLOBAL_CONF_OFFSET;

		/* Set the PGSP context base address. */
		ulTempData = pSharedInfo->MemoryMap.ulChanMainMemBase + ( i * pSharedInfo->MemoryMap.ulChanMainMemSize ) + cOCT6100_CH_MAIN_PGSP_CONTEXT_OFFSET;
		
		WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_PGSP_CONTEXT_BASE_ADD_OFFSET;
		WriteParams.usWriteData = (UINT16)( ulTempData >> 16 );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress += 2;
		WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Set the PGSP init context base address. */
		ulTempData = ( cOCT6100_IMAGE_FILE_BASE + 0x200 ) & 0x07FFFFFF;
		
		WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_PGSP_INIT_CONTEXT_BASE_ADD_OFFSET;
		WriteParams.usWriteData = (UINT16)( ulTempData >> 16 );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress += 2;
		WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
		
		/* Set the RIN circular buffer base address. */
		ulTempData = pSharedInfo->MemoryMap.ulChanMainMemBase + ( i * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainRinCBMemOfst;

		/* Set the circular buffer size. */
		ulTempData &= 0xFFFFFF00;
		if (( pSharedInfo->MemoryMap.ulChanMainRinCBMemSize & 0xFFFF00FF ) != 0 )
			return cOCT6100_ERR_CHANNEL_INVALID_RIN_CB_SIZE;
		ulTempData |= pSharedInfo->MemoryMap.ulChanMainRinCBMemSize >> 8;
			
		WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_RIN_CIRC_BUFFER_BASE_ADD_OFFSET;
		WriteParams.usWriteData = (UINT16)( ulTempData >> 16 );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress += 2;
		WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Set the SIN circular buffer base address. */
		ulTempData = pSharedInfo->MemoryMap.ulChanMainMemBase + ( i * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainSinCBMemOfst;

		WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_SIN_CIRC_BUFFER_BASE_ADD_OFFSET;
		WriteParams.usWriteData = (UINT16)( ulTempData >> 16 );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress += 2;
		WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Set the SOUT circular buffer base address. */
		ulTempData = pSharedInfo->MemoryMap.ulChanMainMemBase + ( i * pSharedInfo->MemoryMap.ulChanMainMemSize ) + pSharedInfo->MemoryMap.ulChanMainSoutCBMemOfst;;

		WriteParams.ulWriteAddress = ulBaseAddress + cOCT6100_GSC_SOUT_CIRC_BUFFER_BASE_ADD_OFFSET;
		WriteParams.usWriteData = (UINT16)( ulTempData >> 16 );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress += 2;
		WriteParams.usWriteData = (UINT16)( ulTempData & 0xFFFF );

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK  )
			return ulResult;

		/*==============================================================================*/
	}

	/* Put all channel in powerdown mode "3". */
	for( i = 0; i < f_pApiInstance->pSharedInfo->ChipConfig.usMaxChannels; i++ )
	{
		WriteParams.ulWriteAddress = 0x014000 + (i*4) + 0;
		WriteParams.usWriteData = 0x85FF;		/* TSI index 1535 reserved for power-down mode */

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x014000 + (i*4) + 2;
		WriteParams.usWriteData = 0xC5FF;		/* TSI index 1535 reserved for power-down mode */

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}

	/* Set the maximum number of channels. */
	WriteParams.ulWriteAddress = 0x690;
	if ( pSharedInfo->ImageInfo.usMaxNumberOfChannels < 384 )
		WriteParams.usWriteData = 384;
	else
		WriteParams.usWriteData = (UINT16)pSharedInfo->ImageInfo.usMaxNumberOfChannels;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;
	
	/* Set power-dowm TSI chariot memory to silence. */
	for( i = 0; i < 6; i++ )
	{
		WriteParams.ulWriteAddress = 0x20000 + ( i * 0x1000 ) + ( 1534 * 2 );
		WriteParams.usWriteData = 0xFF;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = 0x20000 + ( i * 0x1000 ) + ( 1535 * 2 );
		WriteParams.usWriteData = 0xFF;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;	
	}

	/* Remove chariot hold. */
	WriteParams.ulWriteAddress = 0x500;
	WriteParams.usWriteData = 0x0001;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	for( usLoopCount = 0; usLoopCount < 4096; usLoopCount++ )
	{
		if ( (usLoopCount % 16) < 8 )
		{
			usWriteData  = (UINT16)((usLoopCount / 16) << 7);
			usWriteData |= (UINT16)((usLoopCount % 8));
		}
		else
		{
			usWriteData  = (UINT16)((usLoopCount / 16) << 7);
			usWriteData |= (UINT16)((usLoopCount % 8));
			usWriteData |= 0x78;
		}

		/* Set timeslot pointer. */
		WriteParams.ulWriteAddress = 0x50E;
		WriteParams.usWriteData  = 0x0003;
		WriteParams.usWriteData |= usWriteData << 2;

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Now read the mclk counter. */
		ReadParams.ulReadAddress = 0x30A;
		ReadParams.pusReadData = &usLastMclkRead;

		mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Reset loop timeout counter. */
		ulTimeoutCounter = 0x0;

		do {
			ReadParams.pusReadData = &usMclkRead;

			mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;

			if ( ( usLoopCount % 16 ) != 15 )
			{
				ulNumberOfCycleToWait = 133;
			}
			else
			{
				ulNumberOfCycleToWait = 20000;
			}

			/* Evaluate the difference. */
			usMclkDiff = (UINT16)(( usMclkRead - usLastMclkRead ) & 0xFFFF);

			/* Check for loop timeout. Bad mclk? */
			ulTimeoutCounter++;
			if ( ulTimeoutCounter == cOCT6100_MAX_LOOP_CPU_TIMEOUT )
				return cOCT6100_ERR_FATAL_EA;
			
		} while( usMclkDiff <= ulNumberOfCycleToWait );
	}
	
	/* Back to normal mode. */
	WriteParams.ulWriteAddress = 0x50E;
	WriteParams.usWriteData  = 0x0000;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Check for CRC errors. */
	ReadParams.pusReadData = &usReadData;
	ReadParams.ulReadAddress = 0x202;

	mOCT6100_DRIVER_READ_API( ReadParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	if ( (usReadData & 0x400) != 0x0000 )
		return cOCT6100_ERR_OPEN_CRC_ERROR;

	/* Clear the error rol raised by manually moving the clocks. */
	WriteParams.ulWriteAddress = 0x502;
	WriteParams.usWriteData  = 0x0002;

	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/*======================================================================*/
	/* Write the tail displacement value in external memory. */

	ulFeatureBytesOffset = pSharedInfo->MemoryMap.PouchTailDisplOfst.usDwordOffset * 4;
	ulFeatureBitOffset	 = pSharedInfo->MemoryMap.PouchTailDisplOfst.byBitOffset;
	ulFeatureFieldLength = pSharedInfo->MemoryMap.PouchTailDisplOfst.byFieldSize;

	ulResult = Oct6100ApiReadDword(	f_pApiInstance,
									cOCT6100_POUCH_BASE + ulFeatureBytesOffset,
									&ulTempData );
	
	/* Clear previous value set in the feature field.*/
	mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask );

	ulTempData &= (~ulMask);

	/* Set the tail displacement. */
	ulTempData |= (pSharedInfo->ChipConfig.usTailDisplacement << ulFeatureBitOffset );

	/* Write the DWORD where the field is located. */
	ulResult = Oct6100ApiWriteDword( f_pApiInstance,
									 cOCT6100_POUCH_BASE + ulFeatureBytesOffset,
									 ulTempData );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;	

	/*======================================================================*/


	/*======================================================================*/
	/* Clear the pouch counter, if present. */
	
	if ( pSharedInfo->DebugInfo.fPouchCounter == TRUE )
	{
		ulFeatureBytesOffset = pSharedInfo->MemoryMap.PouchCounterFieldOfst.usDwordOffset * 4;
		ulFeatureBitOffset	 = pSharedInfo->MemoryMap.PouchCounterFieldOfst.byBitOffset;
		ulFeatureFieldLength = pSharedInfo->MemoryMap.PouchCounterFieldOfst.byFieldSize;

		ulResult = Oct6100ApiReadDword(	f_pApiInstance,
										cOCT6100_POUCH_BASE + ulFeatureBytesOffset,
										&ulTempData );
		
		/* Clear previous value set in the feature field.*/
		mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask );

		/* Clear counter! */
		ulTempData &= (~ulMask);

		/* Write the DWORD where the field is located.*/
		ulResult = Oct6100ApiWriteDword( f_pApiInstance,
										 cOCT6100_POUCH_BASE + ulFeatureBytesOffset,
										 ulTempData );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;	
	}

	/* The ISR has not yet been called.  Set the appropriate bit in external memory. */
	if ( pSharedInfo->DebugInfo.fIsIsrCalledField == TRUE )
	{
		ulFeatureBytesOffset = pSharedInfo->MemoryMap.IsIsrCalledFieldOfst.usDwordOffset * 4;
		ulFeatureBitOffset	 = pSharedInfo->MemoryMap.IsIsrCalledFieldOfst.byBitOffset;
		ulFeatureFieldLength = pSharedInfo->MemoryMap.IsIsrCalledFieldOfst.byFieldSize;

		ulResult = Oct6100ApiReadDword(	f_pApiInstance,
										cOCT6100_POUCH_BASE + ulFeatureBytesOffset,
										&ulTempData );
		
		/* Read previous value set in the feature field.*/
		mOCT6100_CREATE_FEATURE_MASK( ulFeatureFieldLength, ulFeatureBitOffset, &ulMask );

		/* Toggle the bit to '1'. */
		ulTempData |= 1 << ulFeatureBitOffset;

		/* Write the DWORD where the field is located.*/
		ulResult = Oct6100ApiWriteDword( f_pApiInstance,
										 cOCT6100_POUCH_BASE + ulFeatureBytesOffset,
										 ulTempData );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;	
	}

	/*======================================================================*/

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiInitToneInfo

Description:    This function will parse the software image and retrieve 
				the information about the tones that it supports.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiInitToneInfo
UINT32 Oct6100ApiInitToneInfo(
				IN OUT	tPOCT6100_INSTANCE_API f_pApiInstance )
{
	UINT32	ulResult;
	
	PUINT8	pszToneInfoStart = NULL;
	PUINT8	pszToneInfoEnd = NULL;
	
	PUINT8	pszCurrentInfo;
	PUINT8	pszNextInfo;
	
	UINT32	ulToneEventNumber;
	UINT32	ulTempValue;
	UINT32	ulNumCharForValue;
	UINT32	ulUniqueToneId;
	UINT32	ulToneNameSize;
	UINT32	ulOffset = 0;

	UINT32	i;

	/* Init the tone detector parameter. */
	f_pApiInstance->pSharedInfo->ImageInfo.byNumToneDetectors = 0;

	/* Find the start and the end of the tone info section. */
	if ( f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize > 4096 )
	{
		/* For performance reasons, and since the tone detector information */
		/* is always located at the end of the image file, try to start from the end */
		/* of the buffer. */

		ulOffset = f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize - 2048;
		pszToneInfoStart = Oct6100ApiStrStr( f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + ulOffset,
										 (PUINT8)cOCT6100_TONE_INFO_START_STRING,
										 f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize );

		/* Check if the information was found. */
		if ( pszToneInfoStart == NULL )
		{
			/* Try again, but giving a larger string to search. */
			ulOffset = f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize - 4096;
			pszToneInfoStart = Oct6100ApiStrStr( f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + ulOffset,
											 (PUINT8)cOCT6100_TONE_INFO_START_STRING,
											 f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize );

		}
	}

	if ( pszToneInfoStart == NULL )
	{
		/* Travel through the whole file buffer. */
		pszToneInfoStart = Oct6100ApiStrStr( f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile,
										 (PUINT8)cOCT6100_TONE_INFO_START_STRING,
										 f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize );
	}
	/* We have to return immediatly if no tones are found. */
	if ( pszToneInfoStart == NULL )
		return cOCT6100_ERR_OK;

	/* The end of the tone detector information is after the beginning of the tone information. */
	pszToneInfoEnd = Oct6100ApiStrStr(	 pszToneInfoStart,
										 (PUINT8)cOCT6100_TONE_INFO_STOP_STRING,
										 f_pApiInstance->pSharedInfo->ChipConfig.pbyImageFile + f_pApiInstance->pSharedInfo->ChipConfig.ulImageSize );
	if ( pszToneInfoEnd == NULL )
		return cOCT6100_ERR_OPEN_TONE_INFO_STOP_TAG_NOT_FOUND;

	/* Find and process all tone events within the region. */
	pszCurrentInfo = Oct6100ApiStrStr( pszToneInfoStart, (PUINT8)cOCT6100_TONE_INFO_EVENT_STRING, pszToneInfoEnd );

	while ( pszCurrentInfo != NULL )
	{
		/* Skip the string. */
		pszCurrentInfo += ( Oct6100ApiStrLen( (PUINT8)cOCT6100_TONE_INFO_EVENT_STRING ) );

		/* Extract the number of char used to represent the tone event number ( 1 or 2 ). */
		pszNextInfo = Oct6100ApiStrStr( pszCurrentInfo, (PUINT8)",", pszToneInfoEnd );
		ulNumCharForValue = (UINT32)( pszNextInfo - pszCurrentInfo );
		
		/* Retreive the event number */
		ulToneEventNumber = 0;
		for ( i = ulNumCharForValue; i > 0; i-- )
		{
			ulResult = Oct6100ApiAsciiToHex( *pszCurrentInfo, &ulTempValue );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;

			ulToneEventNumber |= ( ulTempValue << (( i - 1) * 4 ) );
			pszCurrentInfo++;
		}

		if ( ulToneEventNumber >= cOCT6100_MAX_TONE_EVENT )
			return cOCT6100_ERR_OPEN_INVALID_TONE_EVENT;
		
		/* Skip the comma and the 0x. */
		pszCurrentInfo += 3;

		/*======================================================================*/
		/* Retreive the unique tone id. */
		ulUniqueToneId = 0;
		for ( i = 0; i < 8; i++ )
		{
			ulResult = Oct6100ApiAsciiToHex( *pszCurrentInfo, &ulTempValue );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;

			ulOffset = 28 - ( i * 4 );
			ulUniqueToneId |= ( ulTempValue << ulOffset );
			pszCurrentInfo++;
		}
		
		/*======================================================================*/

		/* Skip the comma. */
		pszCurrentInfo++;
		
		/* Find out where the next event info starts */
		pszNextInfo = Oct6100ApiStrStr( pszCurrentInfo,(PUINT8) cOCT6100_TONE_INFO_EVENT_STRING, pszToneInfoEnd );
		if ( pszNextInfo == NULL )
			pszNextInfo = pszToneInfoEnd;

		/* Extract the name size. */
		ulToneNameSize = (UINT32)( pszNextInfo - pszCurrentInfo - 2 );	/* - 2 for 0x0D and 0x0A.*/

		if ( ulToneNameSize > cOCT6100_TLV_MAX_TONE_NAME_SIZE )
			return cOCT6100_ERR_OPEN_INVALID_TONE_NAME;

		/* Copy the tone name into the image info structure. */
		ulResult = Oct6100UserMemCopy( f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].aszToneName,
									   pszCurrentInfo,
									   ulToneNameSize );



		/* Update the tone info into the image info structure. */
		f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulToneID = ulUniqueToneId;
		/* Find out the port on which this tone detector is associated. */
		switch( (ulUniqueToneId >> 28) & 0xF )
		{
		case 1:
			f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulDetectionPort = cOCT6100_CHANNEL_PORT_ROUT;
			break;

		case 2:
			f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulDetectionPort = cOCT6100_CHANNEL_PORT_SIN;
			break;

		case 4:
			f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulDetectionPort = cOCT6100_CHANNEL_PORT_SOUT;
			break;

		case 5:
			f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulDetectionPort = cOCT6100_CHANNEL_PORT_ROUT_SOUT;
			break;
		
		default:
			f_pApiInstance->pSharedInfo->ImageInfo.aToneInfo[ ulToneEventNumber ].ulDetectionPort = cOCT6100_INVALID_PORT;
			break;
		}
		
		/* Find out where the next event info starts */
		pszNextInfo = Oct6100ApiStrStr( pszCurrentInfo,(PUINT8) cOCT6100_TONE_INFO_EVENT_STRING, pszToneInfoEnd );
		/* Update the current info pointer. */
		pszCurrentInfo = pszNextInfo;

		f_pApiInstance->pSharedInfo->ImageInfo.byNumToneDetectors++;
	}

	return	cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiExternalMemoryBist

Description:    Tests the functionality of the external memories.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiExternalMemoryBist
UINT32 Oct6100ApiExternalMemoryBist(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tPOCT6100_SHARED_INFO	pSharedInfo;
	UINT32	ulMemSize = 0;
	UINT32	ulResult;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Test the external memory. */
	switch ( pSharedInfo->ChipConfig.ulMemoryChipSize )
	{
	case cOCT6100_MEMORY_CHIP_SIZE_8MB:			
		ulMemSize = cOCT6100_SIZE_8M;		
		break;
	case cOCT6100_MEMORY_CHIP_SIZE_16MB:		
		ulMemSize = cOCT6100_SIZE_16M;		
		break;
	case cOCT6100_MEMORY_CHIP_SIZE_32MB:		
		ulMemSize = cOCT6100_SIZE_32M;		
		break;
	case cOCT6100_MEMORY_CHIP_SIZE_64MB:		
		ulMemSize = cOCT6100_SIZE_64M;		
		break;
	case cOCT6100_MEMORY_CHIP_SIZE_128MB:		
		ulMemSize = cOCT6100_SIZE_128M;		
		break;
	default:									
		return cOCT6100_ERR_FATAL_D9;
	}

	ulMemSize *= pSharedInfo->ChipConfig.byNumMemoryChips;

	ulResult = Oct6100ApiRandomMemoryWrite( f_pApiInstance, cOCT6100_EXTERNAL_MEM_BASE_ADDRESS, ulMemSize, 16, 1000, cOCT6100_ERR_OPEN_EXTERNAL_MEM_BIST_FAILED );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;
	
	/* Make sure the user I/O functions are working as required. */
	ulResult = Oct6100ApiUserIoTest( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiGenerateNumber

Description:    Generate a number using an index.  Passing the same
				index generates the same number.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.
f_ulIndex			Index used to generate the random number.
f_ulDataMask		Data mask to apply to generated number.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiGenerateNumber
UINT16 Oct6100ApiGenerateNumber( 
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance,
				IN		UINT32					f_ulIndex,
				IN		UINT32					f_ulDataMask )
{
	UINT16 usGeneratedNumber;

	usGeneratedNumber = (UINT16)( ( ( ~( f_ulIndex - 1 ) ) & 0xFF00 ) | ( ( f_ulIndex + 1 ) & 0xFF ) );

	return (UINT16)( usGeneratedNumber & f_ulDataMask );
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiRandomMemoryWrite

Description:    Writes to f_ulNumAccesses random locations in the indicated 
				memory and read back to test the operation of that memory.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.
f_ulMemBase			Base address of the memory access.
f_ulMemSize			Size of the memory to be tested.
f_ulNumDataBits		Number of data bits.
f_ulNumAccesses		Number of random access to be perform.
f_ulErrorCode		Error code to be returned if the bist fails.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiRandomMemoryWrite
UINT32 Oct6100ApiRandomMemoryWrite(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance,
				IN		UINT32					f_ulMemBase,
				IN		UINT32					f_ulMemSize,
				IN		UINT32					f_ulNumDataBits,
				IN		UINT32					f_ulNumAccesses,
				IN		UINT32					f_ulErrorCode )
{
	tPOCT6100_SHARED_INFO	pSharedInfo;
	tOCT6100_WRITE_PARAMS	WriteParams;
	tOCT6100_READ_PARAMS	ReadParams;
	UINT32	ulDataMask;
	UINT32	ulResult, i, j;
	UINT32	ulBistAddress;
	UINT16	usReadData;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Set the process context and user chip ID parameters once and for all. */
	WriteParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;

	ReadParams.pProcessContext = f_pApiInstance->pProcessContext;

	ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;

	/* Make sure we don't perform more access then the size of our BIST resources. */
	if ( f_ulNumAccesses > 1024 )
		return cOCT6100_ERR_FATAL_C0;

	/* Determine mask for number of data bits. */
	ulDataMask = (1 << f_ulNumDataBits) - 1;
	
	/* Bist all data pin. */
	for ( i = 0; i < 32; i += 2 )
	{
		WriteParams.ulWriteAddress = f_ulMemBase + i * 2;
		WriteParams.usWriteData = (UINT16)(0x1 << (i / 2));

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		WriteParams.ulWriteAddress = f_ulMemBase + i * 2 + 2;
		WriteParams.usWriteData = (UINT16)(0x1 << (i / 2));

		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}

	/* Read back the data written. */
	for ( i = 0; i < 32; i += 2 )
	{
		ReadParams.ulReadAddress = f_ulMemBase + i * 2;
		ReadParams.pusReadData = &usReadData;
		mOCT6100_DRIVER_READ_API( ReadParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		if ( usReadData != (UINT16)(0x1 << (i / 2)) )
			return f_ulErrorCode;

		ReadParams.ulReadAddress = f_ulMemBase + i * 2 + 2;
		ReadParams.pusReadData = &usReadData;
		mOCT6100_DRIVER_READ_API( ReadParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		if ( usReadData != (UINT16)(0x1 << (i / 2)) )
			return f_ulErrorCode;
	}

	/* Perform the first write at address 0 + mem base */
	j = 0;
	WriteParams.ulWriteAddress = f_ulMemBase;
	WriteParams.usWriteData = Oct6100ApiGenerateNumber( f_pApiInstance, j, ulDataMask );
	mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult )
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Try each address line of the memory. */
	for ( i = 2, j = 1; i < f_ulMemSize; i <<= 1, j++ )
	{
		WriteParams.ulWriteAddress = ( f_ulMemBase + i );
		WriteParams.usWriteData = Oct6100ApiGenerateNumber( f_pApiInstance, j, ulDataMask );
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}

	for ( i = 0; i < j; i++ )
	{
		if ( i > 0 )
			ReadParams.ulReadAddress = ( f_ulMemBase + ( 0x1 << i ) );
		else
			ReadParams.ulReadAddress = f_ulMemBase;
		ReadParams.pusReadData = &usReadData;
		mOCT6100_DRIVER_READ_API( ReadParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		if ( usReadData != Oct6100ApiGenerateNumber( f_pApiInstance, i, ulDataMask ) )
			return f_ulErrorCode;
	}

	/* Write to random addresses of the memory. */
	for ( i = 0; i < f_ulNumAccesses; i++ )
	{
		ulBistAddress  = (UINT16)Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ) << 16;
		ulBistAddress |= (UINT16)Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF );
		ulBistAddress &= f_ulMemSize - 2;
		ulBistAddress |= f_ulMemBase;

		WriteParams.ulWriteAddress = ulBistAddress;
		WriteParams.usWriteData = Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF );
		mOCT6100_DRIVER_WRITE_API( WriteParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}

	for ( i = 0; i < f_ulNumAccesses; i++ )
	{
		ulBistAddress  = (UINT16)Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ) << 16;
		ulBistAddress |= (UINT16)Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF );
		ulBistAddress &= f_ulMemSize - 2;
		ulBistAddress |= f_ulMemBase;

		ReadParams.ulReadAddress = ulBistAddress;
		ReadParams.pusReadData = &usReadData;
		mOCT6100_DRIVER_READ_API( ReadParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		if ( ( usReadData & ulDataMask ) != ( Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ) & ulDataMask ) )
			return f_ulErrorCode;
	}
	
	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiUserIoTest

Description:    This function will verify the correct functionality of 
				the following user functions:

				- Oct6100UserDriverWriteBurstApi
				- Oct6100UserDriverWriteSmearApi
				- Oct6100UserDriverReadBurstApi

				The Oct6100UserDriverWriteApi and Oct6100UserDriverReadApi
				functions do not need to be tested here as this has be done in 
				the external memory bisting function above.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiUserIoTest
UINT32 Oct6100ApiUserIoTest( 
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tPOCT6100_SHARED_INFO		pSharedInfo;
	tOCT6100_WRITE_BURST_PARAMS	WriteBurstParams;
	tOCT6100_WRITE_SMEAR_PARAMS	WriteSmearParams;
	tOCT6100_READ_PARAMS		ReadParams;
	tOCT6100_READ_BURST_PARAMS	ReadBurstParams;
	UINT32	ulResult, i;
	UINT16	usReadData;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Set the process context and user chip ID parameters once and for all. */
	WriteBurstParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteBurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
	/* Test what the user has specified is the maximum that can be used for a burst. */
	WriteBurstParams.ulWriteLength = pSharedInfo->ChipConfig.usMaxRwAccesses;
	WriteBurstParams.pusWriteData = pSharedInfo->MiscVars.ausSuperArray;

	WriteSmearParams.pProcessContext = f_pApiInstance->pProcessContext;

	WriteSmearParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
	/* Test what the user has specified is the maximum that can be used for a smear. */
	WriteSmearParams.ulWriteLength = pSharedInfo->ChipConfig.usMaxRwAccesses;

	ReadParams.pProcessContext = f_pApiInstance->pProcessContext;

	ReadParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
	ReadParams.pusReadData = &usReadData;

	ReadBurstParams.pProcessContext = f_pApiInstance->pProcessContext;

	ReadBurstParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;
	/* Test what the user has specified is the maximum that can be used for a burst. */
	ReadBurstParams.ulReadLength = pSharedInfo->ChipConfig.usMaxRwAccesses;
	ReadBurstParams.pusReadData = pSharedInfo->MiscVars.ausSuperArray;


	/*======================================================================*/
	/* Write burst check. */

	WriteBurstParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS;
	/* Set the random data to be written. */
	for ( i = 0; i < WriteBurstParams.ulWriteLength; i++ )
	{
		WriteBurstParams.pusWriteData[ i ] = Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF );
	}
	mOCT6100_DRIVER_WRITE_BURST_API( WriteBurstParams, ulResult )
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Read back pattern using simple read function and make sure we are reading what's expected. */
	ReadParams.ulReadAddress = WriteBurstParams.ulWriteAddress;
	for ( i = 0; i < WriteBurstParams.ulWriteLength; i++ )
	{
		mOCT6100_DRIVER_READ_API( ReadParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Check if the data matches. */
		if ( usReadData != WriteBurstParams.pusWriteData[ i ] )
		{
			/* The values do not match.  Something seems to be wrong with the WriteBurst user function. */
			return cOCT6100_ERR_OPEN_USER_WRITE_BURST_FAILED;
		}

		/* Next address to check. */
		ReadParams.ulReadAddress += 2;
	}

	/*======================================================================*/


	/*======================================================================*/
	/* Write smear check. */

	WriteSmearParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS + ( WriteBurstParams.ulWriteLength * 2 );
	/* Set the random data to be written. */
	WriteSmearParams.usWriteData = Oct6100ApiGenerateNumber( f_pApiInstance, Oct6100ApiRand( 0xFFFF ), 0xFFFF );
	mOCT6100_DRIVER_WRITE_SMEAR_API( WriteSmearParams, ulResult )
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Read back pattern using simple read function and make sure we are reading what's expected. */
	ReadParams.ulReadAddress = WriteSmearParams.ulWriteAddress;
	for ( i = 0; i < WriteSmearParams.ulWriteLength; i++ )
	{
		mOCT6100_DRIVER_READ_API( ReadParams, ulResult )
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Check if the data matches. */
		if ( usReadData != WriteSmearParams.usWriteData )
		{
			/* The values do not match.  Something seems to be wrong with the WriteSmear user function. */
			return cOCT6100_ERR_OPEN_USER_WRITE_SMEAR_FAILED;
		}

		/* Next address to check. */
		ReadParams.ulReadAddress += 2;
	}

	/*======================================================================*/


	/*======================================================================*/
	/* Read burst check. */

	/* First check with what the WriteBurst function wrote. */
	ReadBurstParams.ulReadAddress = WriteBurstParams.ulWriteAddress;
	mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult )
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	for ( i = 0; i < ReadBurstParams.ulReadLength; i++ )
	{
		/* Check if the data matches. */
		if ( ReadBurstParams.pusReadData[ i ] != Oct6100ApiGenerateNumber( f_pApiInstance, i, 0xFFFF ) )
		{
			/* The values do not match.  Something seems to be wrong with the ReadBurst user function. */
			return cOCT6100_ERR_OPEN_USER_READ_BURST_FAILED;
		}
	}

	/* Then check with what the WriteSmear function wrote. */
	ReadBurstParams.ulReadAddress = WriteSmearParams.ulWriteAddress;
	mOCT6100_DRIVER_READ_BURST_API( ReadBurstParams, ulResult )
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	for ( i = 0; i < ReadBurstParams.ulReadLength; i++ )
	{
		/* Check if the data matches. */
		if ( ReadBurstParams.pusReadData[ i ] != WriteSmearParams.usWriteData )
		{
			/* The values do not match.  Something seems to be wrong with the ReadBurst user function. */
			return cOCT6100_ERR_OPEN_USER_READ_BURST_FAILED;
		}
	}

	/*======================================================================*/
	
	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiExternalMemoryInit

Description:    Initialize the external memory before uploading the image.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiExternalMemoryInit
UINT32 Oct6100ApiExternalMemoryInit(
				IN OUT	tPOCT6100_INSTANCE_API	f_pApiInstance )
{
	tPOCT6100_SHARED_INFO			pSharedInfo;
	tOCT6100_WRITE_SMEAR_PARAMS		SmearParams;
	UINT32	ulTotalWordToWrite;
	UINT32	ulResult;

	/* Get local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	SmearParams.pProcessContext = f_pApiInstance->pProcessContext;

	SmearParams.ulUserChipId = pSharedInfo->ChipConfig.ulUserChipId;

	/* Clear the first part of the memory. */
	ulTotalWordToWrite = 0x400;
	SmearParams.ulWriteAddress = cOCT6100_EXTERNAL_MEM_BASE_ADDRESS;

	while ( ulTotalWordToWrite != 0 )
	{
		if ( ulTotalWordToWrite >= pSharedInfo->ChipConfig.usMaxRwAccesses )
			SmearParams.ulWriteLength = pSharedInfo->ChipConfig.usMaxRwAccesses;
		else
			SmearParams.ulWriteLength = ulTotalWordToWrite;

		SmearParams.usWriteData = 0x0;

		mOCT6100_DRIVER_WRITE_SMEAR_API( SmearParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Update the number of words to write. */
		ulTotalWordToWrite -= SmearParams.ulWriteLength;
		/* Update the address. */
		SmearParams.ulWriteAddress += ( SmearParams.ulWriteLength * 2 );
	}

	/* Clear the TLV flag.*/
	ulResult = Oct6100ApiWriteDword( f_pApiInstance, cOCT6100_TLV_BASE, 0x0 );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiInitMixer

Description:    This function will initialize the mixer memory.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiInitMixer
UINT32 Oct6100ApiInitMixer(
				IN OUT	tPOCT6100_INSTANCE_API f_pApiInstance )
{
	tPOCT6100_SHARED_INFO		pSharedInfo;
	tOCT6100_WRITE_BURST_PARAMS	BurstParams;
	UINT16						ausWriteData[ 4 ];
	UINT32						ulResult;

	pSharedInfo = f_pApiInstance->pSharedInfo;

	BurstParams.pProcessContext = f_pApiInstance->pProcessContext;

	BurstParams.ulUserChipId = f_pApiInstance->pSharedInfo->ChipConfig.ulUserChipId;
	BurstParams.pusWriteData = ausWriteData;
	/*======================================================================*/
	/* Initialize the mixer memory if required. */
	if ( pSharedInfo->ChipConfig.fEnableChannelRecording == TRUE )
	{
		/* Modify the mixer pointer by adding the record event into the link list. */
		pSharedInfo->MixerInfo.usFirstSinCopyEventPtr	= pSharedInfo->MixerInfo.usRecordSinEventIndex;
		pSharedInfo->MixerInfo.usLastSinCopyEventPtr	= pSharedInfo->MixerInfo.usRecordSinEventIndex;
		pSharedInfo->MixerInfo.usFirstSoutCopyEventPtr	= pSharedInfo->MixerInfo.usRecordCopyEventIndex; 
		pSharedInfo->MixerInfo.usLastSoutCopyEventPtr	= pSharedInfo->MixerInfo.usRecordCopyEventIndex;

		/* Program the Sin copy event. */
		BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSharedInfo->MixerInfo.usRecordSinEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
		BurstParams.ulWriteLength = 4;

		ausWriteData[ 0 ] = 0x0000;
		ausWriteData[ 1 ] = 0x0000;
		ausWriteData[ 2 ] = (UINT16)(cOCT6100_MIXER_TAIL_NODE & 0x7FF);	/* Head node.*/
		ausWriteData[ 3 ] = 0x0000;

		mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Program the Sout copy event. */
		BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + ( pSharedInfo->MixerInfo.usRecordCopyEventIndex * cOCT6100_MIXER_CONTROL_MEM_ENTRY_SIZE );
		BurstParams.ulWriteLength = 4;

		ausWriteData[ 0 ] = 0x0000;
		ausWriteData[ 1 ] = 0x0000;
		ausWriteData[ 2 ] = (UINT16)(pSharedInfo->MixerInfo.usRecordSinEventIndex & 0x7FF);
		ausWriteData[ 3 ] = 0x0000;

		mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
		
		/* Configure the head node. */
		BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE;
		BurstParams.ulWriteLength = 4;

		ausWriteData[ 0 ] = 0x0000;
		ausWriteData[ 1 ] = 0x0000;
		ausWriteData[ 2 ] = (UINT16)(pSharedInfo->MixerInfo.usRecordCopyEventIndex & 0x7FF);
		ausWriteData[ 3 ] = 0x0000;

		mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Init the mixer pointer */
		pSharedInfo->MixerInfo.usFirstSinCopyEventPtr = pSharedInfo->MixerInfo.usRecordSinEventIndex;
	}
	else
	{
		/* Configure the head node. */
		BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE;
		BurstParams.ulWriteLength = 4;

		ausWriteData[ 0 ] = 0x0000;
		ausWriteData[ 1 ] = 0x0000;
		ausWriteData[ 2 ] = (UINT16)(cOCT6100_MIXER_TAIL_NODE & 0x7FF);	/* Head node. */
		ausWriteData[ 3 ] = 0x0000;

		mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* Configure the tail node. */
		BurstParams.ulWriteAddress = cOCT6100_MIXER_CONTROL_MEM_BASE + 0x10;
		BurstParams.ulWriteLength = 4;

		ausWriteData[ 0 ] = 0x0000;
		ausWriteData[ 1 ] = 0x0000;
		ausWriteData[ 2 ] = (UINT16)(cOCT6100_MIXER_HEAD_NODE & 0x7FF);	/* Head node. */
		ausWriteData[ 3 ] = 0x0000;

		mOCT6100_DRIVER_WRITE_BURST_API( BurstParams, ulResult );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;
	}

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiInitRecordResources

Description:    This function will initialize the resources required to 
				perform recording on a debug channel.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance		Pointer to API instance. This memory is used to keep the
					present state of the chip and all its resources.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiInitRecordResources
UINT32 Oct6100ApiInitRecordResources(
				IN OUT	tPOCT6100_INSTANCE_API f_pApiInstance )
{
	tPOCT6100_SHARED_INFO	pSharedInfo;
	UINT32					ulResult;

	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Check if recording is enabled. */
	if ( pSharedInfo->ChipConfig.fEnableChannelRecording == FALSE )
		return cOCT6100_ERR_OK;

	if ( pSharedInfo->DebugInfo.usRecordMemIndex == cOCT6100_INVALID_INDEX )
		return cOCT6100_ERR_NOT_SUPPORTED_OPEN_DEBUG_RECORD;
	
	/* Check the provided recording memory index within the SSPX. */
	if ( pSharedInfo->DebugInfo.usRecordMemIndex != ( pSharedInfo->ImageInfo.usMaxNumberOfChannels - 1 ) )
		return cOCT6100_ERR_OPEN_DEBUG_MEM_INDEX;

	/* Reserve the TSI entries for the channel. */
	ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, &pSharedInfo->DebugInfo.usRecordRinRoutTsiMemIndex );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	ulResult = Oct6100ApiReserveTsiMemEntry( f_pApiInstance, &pSharedInfo->DebugInfo.usRecordSinSoutTsiMemIndex );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	/* Open the debug channel. */
	ulResult = Oct6100ApiDebugChannelOpen( f_pApiInstance );
	if ( ulResult != cOCT6100_ERR_OK )
		return ulResult;

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100FreeResourcesSer

Description:    This function closes all opened channels and frees all 
				specified global resources used by the chip.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance			Pointer to API instance. This memory is used to keep
						the present state of the chip and all its resources.

f_pFreeResources		Pointer to user structure in which to choose what 
						to free.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100FreeResourcesSer
UINT32 Oct6100FreeResourcesSer(
				IN OUT	tPOCT6100_INSTANCE_API				f_pApiInstance,
				IN		tPOCT6100_FREE_RESOURCES			f_pFreeResources )
{
	tPOCT6100_SHARED_INFO		pSharedInfo;
	tPOCT6100_API_CHANNEL		pChanEntry;
	
	UINT32	ulResult;
	UINT32	i;

	/* Obtain local pointer to shared portion of instance. */
	pSharedInfo = f_pApiInstance->pSharedInfo;

	/* Close all bidirectional channels. */
	for ( i = 0; i < pSharedInfo->ChipConfig.usMaxBiDirChannels; i ++ )
	{
		tPOCT6100_API_BIDIR_CHANNEL		pBiDirChanEntry;

		mOCT6100_GET_BIDIR_CHANNEL_ENTRY_PNT( pSharedInfo, pBiDirChanEntry, i );

		if ( pBiDirChanEntry->fReserved == TRUE )
		{
			tOCT6100_CHANNEL_DESTROY_BIDIR DestroyBidir;

			Oct6100ChannelDestroyBiDirDef( &DestroyBidir );

			DestroyBidir.ulBiDirChannelHndl = cOCT6100_HNDL_TAG_BIDIR_CHANNEL | (pBiDirChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | i;

			ulResult = Oct6100ChannelDestroyBiDirSer( f_pApiInstance, &DestroyBidir );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}
	}

	/* Close all bridge participants. */
	for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i ++ )
	{
		mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, i  );
		if ( pChanEntry->fReserved == TRUE && pChanEntry->usBridgeIndex != cOCT6100_INVALID_INDEX )
		{
			/* This channel is on a bridge. */
			tOCT6100_CONF_BRIDGE_CHAN_REMOVE	BridgeChanRemove;
			tPOCT6100_API_CONF_BRIDGE			pBridgeEntry;

			Oct6100ConfBridgeChanRemoveDef( &BridgeChanRemove );

			/* Obtain a pointer to the conference bridge's list entry. */
			mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBridgeEntry, pChanEntry->usBridgeIndex );

			BridgeChanRemove.fRemoveAll = TRUE;
			BridgeChanRemove.ulConfBridgeHndl = cOCT6100_HNDL_TAG_CONF_BRIDGE | (pBridgeEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | pChanEntry->usBridgeIndex;

			ulResult = Oct6100ConfBridgeChanRemoveSer( f_pApiInstance, &BridgeChanRemove );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}
	}

	/* Close all opened channels.  This will bring the broadcast TSSTs with it. */
	for ( i = 0; i < pSharedInfo->ChipConfig.usMaxChannels; i ++ )
	{
		mOCT6100_GET_CHANNEL_ENTRY_PNT( pSharedInfo, pChanEntry, i  );

		if ( pChanEntry->fReserved == TRUE )
		{
			tOCT6100_CHANNEL_CLOSE	ChannelClose;

			/* Generate handle. */
			ChannelClose.ulChannelHndl = cOCT6100_HNDL_TAG_CHANNEL | (pChanEntry->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | i;

			/* Call serialized close channel function. */
			ulResult = Oct6100ChannelCloseSer( f_pApiInstance, &ChannelClose );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}
	}

	/* Close all TSI connections. */
	if ( f_pFreeResources->fFreeTsiConnections == TRUE )
	{
		tPOCT6100_API_TSI_CNCT		pTsiCnct;
		tOCT6100_TSI_CNCT_CLOSE		TsiCnctClose;

		Oct6100TsiCnctCloseDef( &TsiCnctClose );

		for ( i = 0; i < pSharedInfo->ChipConfig.usMaxTsiCncts; i ++ )
		{
			/* Obtain a pointer to the TSI connection list entry. */
			mOCT6100_GET_TSI_CNCT_ENTRY_PNT( f_pApiInstance->pSharedInfo, pTsiCnct, i );

			if ( pTsiCnct->fReserved == TRUE )
			{
				TsiCnctClose.ulTsiCnctHndl = cOCT6100_HNDL_TAG_TSI_CNCT | (pTsiCnct->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | i;

				ulResult = Oct6100TsiCnctCloseSer( f_pApiInstance, &TsiCnctClose );
				if ( ulResult != cOCT6100_ERR_OK )
					return ulResult;
			}
		}
	}

	/* Close all conference bridges. */
	if ( f_pFreeResources->fFreeConferenceBridges == TRUE )
	{
		tPOCT6100_API_CONF_BRIDGE	pConfBridge;
		tOCT6100_CONF_BRIDGE_CLOSE	ConfBridgeClose;

		Oct6100ConfBridgeCloseDef( &ConfBridgeClose );

		for ( i = 0; i < pSharedInfo->ChipConfig.usMaxConfBridges; i ++ )
		{
			/* Obtain a pointer to the conference bridge's list entry. */
			mOCT6100_GET_CONF_BRIDGE_ENTRY_PNT( f_pApiInstance->pSharedInfo, pConfBridge, i );

			if ( pConfBridge->fReserved == TRUE )
			{
				ConfBridgeClose.ulConfBridgeHndl = cOCT6100_HNDL_TAG_CONF_BRIDGE | (pConfBridge->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | i;

				ulResult = Oct6100ConfBridgeCloseSer( f_pApiInstance, &ConfBridgeClose );
				if ( ulResult != cOCT6100_ERR_OK )
					return ulResult;
			}
		}
	}

	/* Free all playout buffers loaded in external memory. */
	if ( f_pFreeResources->fFreePlayoutBuffers == TRUE )
	{
		tPOCT6100_API_BUFFER pBuffer;
		tOCT6100_BUFFER_UNLOAD BufferUnload;

		Oct6100BufferPlayoutUnloadDef( &BufferUnload );

		for ( i = 0; i < pSharedInfo->ChipConfig.usMaxPlayoutBuffers; i ++ )
		{


			/* Obtain a pointer to the buffer list entry. */
			mOCT6100_GET_BUFFER_ENTRY_PNT( f_pApiInstance->pSharedInfo, pBuffer, i );

			if ( pBuffer->fReserved == TRUE )
			{
				BufferUnload.ulBufferIndex = i;
				ulResult = Oct6100BufferUnloadSer( f_pApiInstance, &BufferUnload, TRUE );
				if ( ulResult != cOCT6100_ERR_OK )
					return ulResult;
			}
		}
	}


	/* Close all phasing TSSTs. */
	if ( f_pFreeResources->fFreePhasingTssts == TRUE )
	{
		tPOCT6100_API_PHASING_TSST	pPhasingTsst;
		tOCT6100_PHASING_TSST_CLOSE	PhasingTsstClose;

		Oct6100PhasingTsstCloseDef( &PhasingTsstClose );

		for ( i = 0; i < pSharedInfo->ChipConfig.usMaxPhasingTssts; i ++ )
		{
			mOCT6100_GET_PHASING_TSST_ENTRY_PNT( pSharedInfo, pPhasingTsst, i );

			if ( pPhasingTsst->fReserved == TRUE )
			{
				PhasingTsstClose.ulPhasingTsstHndl = cOCT6100_HNDL_TAG_PHASING_TSST | (pPhasingTsst->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | i;

				ulResult = Oct6100PhasingTsstCloseSer( f_pApiInstance, &PhasingTsstClose );
				if ( ulResult != cOCT6100_ERR_OK )
					return ulResult;
			}
		}
	}
	
	/* Close all ADPCM channels. */
	if ( f_pFreeResources->fFreeAdpcmChannels == TRUE )
	{
		tPOCT6100_API_ADPCM_CHAN	pAdpcmChannel;
		tOCT6100_ADPCM_CHAN_CLOSE	AdpcmChanClose;

		Oct6100AdpcmChanCloseDef( &AdpcmChanClose );

		for ( i = 0; i < pSharedInfo->ChipConfig.usMaxAdpcmChannels; i ++ )
		{
			mOCT6100_GET_ADPCM_CHAN_ENTRY_PNT( pSharedInfo, pAdpcmChannel, i );
			if ( pAdpcmChannel->fReserved == TRUE )
			{
				AdpcmChanClose.ulChanHndl = cOCT6100_HNDL_TAG_ADPCM_CHANNEL | (pAdpcmChannel->byEntryOpenCnt << cOCT6100_ENTRY_OPEN_CNT_SHIFT) | i;

				ulResult = Oct6100AdpcmChanCloseSer( f_pApiInstance, &AdpcmChanClose );
				if ( ulResult != cOCT6100_ERR_OK )
					return ulResult;
			}
		}
	}


	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ProductionBistSer

Description:    This function returns the instantaneous production BIST status.

-------------------------------------------------------------------------------
|	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_pProductionBist		Pointer to user structure in which BIST status will
						be returned.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ProductionBistSer
UINT32 Oct6100ProductionBistSer(
				IN OUT	tPOCT6100_INSTANCE_API				f_pApiInstance,
				IN OUT	tPOCT6100_PRODUCTION_BIST			f_pProductionBist )
{
	UINT32 ulCalculatedCrc = cOCT6100_INVALID_VALUE;
	UINT32 ulResult;
	UINT32 ulLoopCnt = 0x0;
	UINT32 i = 1;
	UINT32 ulTotalElements = 4;
	UINT32 ulReadAddress = cOCT6100_POUCH_BASE;
	UINT32 aulMessage[ 5 ];

	/* Check if the production bist has been activated. */
	if ( f_pApiInstance->pSharedInfo->ChipConfig.fEnableProductionBist == FALSE )
		return cOCT6100_ERR_PRODUCTION_BIST_DISABLED;

	f_pProductionBist->ulCurrentAddress = cOCT6100_INVALID_VALUE;
	f_pProductionBist->ulCurrentLoop = cOCT6100_INVALID_VALUE;
	f_pProductionBist->ulCurrentTest = cOCT6100_INVALID_VALUE;
	f_pProductionBist->ulFailedAddress = cOCT6100_INVALID_VALUE;
	f_pProductionBist->ulReadValue = cOCT6100_INVALID_VALUE;
	f_pProductionBist->ulExpectedValue = cOCT6100_INVALID_VALUE;
	f_pProductionBist->ulBistStatus = cOCT6100_BIST_IN_PROGRESS;

	/* The API knows that the firmware might be writing a status event. */
	/* The firmware does write a status event every 200ms (approximately). */
	/* So the status is read a couple of times to make sure an event was not read while */
	/* it was written. */
	while ( ulLoopCnt != 2 )
	{
		/* Read the BIST status in the external memory. */
		for ( i = 0; i < ulTotalElements + 1; i ++ )
		{
			ulResult = Oct6100ApiReadDword( f_pApiInstance, ulReadAddress + i * 4, &aulMessage[ i ] );
			if ( ulResult != cOCT6100_ERR_OK )
				return ulResult;
		}

		/* Calculate the CRC of this message. */
		ulResult = Oct6100ApiProductionCrc( f_pApiInstance, aulMessage, ulTotalElements, &ulCalculatedCrc );
		if ( ulResult != cOCT6100_ERR_OK )
			return ulResult;

		/* If the CRCs do match, break off the while.  We have a valid status event. */
		if ( aulMessage[ i - 1 ] == ulCalculatedCrc )
			break;

		ulLoopCnt++;
	}

	/* Check if the CRC matches */
	if ( aulMessage[ i - 1 ] != ulCalculatedCrc )
	{
		/* Well, the exchange memory at the base of the external memory is corrupted.  */
		/* Something very basic is not working correctly with this chip! */
		f_pProductionBist->ulBistStatus = cOCT6100_BIST_STATUS_CRC_FAILED;
	}
	else
	{
		/* Check for problems. */
		switch ( aulMessage[ 0 ] & 0xFFFF )
		{
		case ( 0x2 ):

			/* The initial configuration failed. */
			f_pProductionBist->ulBistStatus = cOCT6100_BIST_CONFIGURATION_FAILED;
			break;
			
		case ( 0x1 ):

			/* A memory location failed.  Return useful information to the user. */
			f_pProductionBist->ulBistStatus = cOCT6100_BIST_MEMORY_FAILED;

			f_pProductionBist->ulFailedAddress = ( aulMessage[ 1 ] & ( ~0x80000000 ) ) + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS;
			f_pProductionBist->ulReadValue = aulMessage[ 2 ];
			f_pProductionBist->ulExpectedValue = aulMessage[ 3 ];
			break;

		case ( 0xFFFF ):

			/* Bist is completed! */
			f_pProductionBist->ulBistStatus = cOCT6100_BIST_SUCCESS;
			break;

		default:
			/* Bist is in progress. All seems to be working fine up to now. */

			/* Return progress status. */
			f_pProductionBist->ulCurrentAddress = ( aulMessage[ 1 ] & ( ~0x80000000 ) ) + cOCT6100_EXTERNAL_MEM_BASE_ADDRESS;
			f_pProductionBist->ulCurrentTest = aulMessage[ 2 ];
			f_pProductionBist->ulCurrentLoop = aulMessage[ 3 ];
			break;
		}
	}

	return cOCT6100_ERR_OK;
}
#endif


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\

Function:		Oct6100ApiProductionCrc

Description:    This function calculates the crc for a production BIST
				message.

-------------------------------------------------------------------------------
|	Argument		|	Description
-------------------------------------------------------------------------------
f_pApiInstance			Pointer to API instance. This memory is used to keep
						the present state of the chip and all its resources.

f_pulMessage			Message to be exchanged with the firmware.  The CRC
						will be calculated on this.
f_ulMessageLength		Length of the message to be exchanged.  This value
						does not include the CRC value at the end
f_pulCrcResult			Resulting calculated CRC value.

\*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if !SKIP_Oct6100ApiProductionCrc
UINT32 Oct6100ApiProductionCrc(
				IN OUT	tPOCT6100_INSTANCE_API		f_pApiInstance,
				IN		PUINT32						f_pulMessage,
				IN		UINT32						f_ulMessageLength,
				OUT		PUINT32						f_pulCrcResult )
{
	UINT32	ulWidth = 32;
	UINT32	ulKey, i, j;
	UINT32	ulRemainder = 0;
	
	/* CRC the message. */
	ulRemainder = f_pulMessage[ f_ulMessageLength - 1 ]; 
	for ( j = f_ulMessageLength - 1; j != 0xFFFFFFFF ; j-- ) 
	{
		for ( i = 0; i < ulWidth; i++ )
		{			
			if ( ( ( ulRemainder >> 0x1F ) & 0x1 ) == 0x1 ) 
			{
				/* Division is by something meaningful */
				ulKey = 0x8765DCBA;
			}
			else	
			{
				/* Remainder is less than our divisor */
				ulKey = 0;
			}
			ulRemainder = ulRemainder ^ ulKey;
			
			ulRemainder = ulRemainder << 1;
			if ( j != 0 )
			{
				ulRemainder = ulRemainder | ( ( f_pulMessage[ j - 1 ] ) >> ( 0x1F - i ) );
			}
		}
	}

	*f_pulCrcResult = ulRemainder;

	return cOCT6100_ERR_OK;
}
#endif
