/* $Revision: 2 $ */
/* $Date: 10/29/07 8:15a $ */
/*
*	Implement various Transmitter related services.
*/
/* $Log: /NEW SOURCESAFE DATABASE/SDK/PLX/gsc/hpdi32/sbtest/tx.c $
 * 
 * 2     10/29/07 8:15a Dnewbold
 * Updated for Linux port.
 * 
 * 1     8/22/05 4:14p Dnewbold
 * 
 * 5     12/27/04 4:29p Dnewbold
 * Moved some items to the utils directory.
 * 
 * 4     7/08/04 8:34a Dnewbold
 * Cross platform porting.
 * 
 * 3     10/22/03 4:40p Dnewbold
 * Account for the absence of Tx or Rx FIFOs.
 * 
 * 2     8/25/03 2:17p Dnewbold
 * Updated test procedures.
 * 
 * 1     6/18/03 9:29a Dnewbold
*/

#include <stdio.h>
#include <string.h>

#include "hpdi32_api.h"
#include "main.h"
#include "util_label.h"
#include "util_sleep.h"



/* typedefs	*****************************************************************/

typedef struct
{
	unsigned long	set;
	unsigned long	get;
} set_get_t;

typedef struct
{
	const char*			name;
	U32					parm;
	const set_get_t*	list;
	size_t				size;
} set_get_list_t;



/*****************************************************************************
*
*	Function:	_parm_list_test
*
*	Purpose:
*
*		Perform a series of tests per the given data and list.
*
*	Arguments:
*
*		handle	The handle used to access the device under test.
*
*		set		The data set to act on.
*
*	Returned:
*
*		0		All went well.
*		> 0		The number of errors seen.
*
*****************************************************************************/

static int _parm_list_test(void* handle, const set_get_list_t* set)
{
	int				errs	= 0;
	int				form;
	unsigned long	get;
	int				i;
	U32				status	= GSC_SUCCESS;

	if (set->name)
		label_text(set->name);

	for (form = 0; form <= 2; form++)
	{
		printf(".");

		for (i = 0; i < (int) set->size; i++)
		{
			status	= hpdi32_config(handle,
									set->parm,
									0,
									set->list[i].set,
									&get);

			if ((status == GSC_SUCCESS) && (get != set->list[i].get))
			{
				printf(	"(%d. %ld->%ld) ",
						i,
						(long) set->list[i].get,
						(long) get);
				status	= GSC_FAILED;
			}

			if (status != GSC_SUCCESS)
				break;
		}

		if (status != GSC_SUCCESS)
			break;
	}

	if (set->name)
		hpdi32_reset(handle);

	errs	= (status == GSC_SUCCESS) ? 0 : 1;

	if (set->name)
	{
		if (errs)
			printf("FAIL <---\n");
		else
			printf("PASS\n");
	}

	return(errs);
}



/*****************************************************************************
*
*	Function:	_tx_auto_start_tests
*
*	Purpose:
*
*		Perform Transmitter Auto Start tests.
*
*	Arguments:
*
*		handle	The handle used to access the device under test.
*
*	Returned:
*
*		0		All went well.
*		> 0		The number of errors seen.
*
*****************************************************************************/

static int _tx_auto_start_tests(void* handle)
{
	static const set_get_t	list[]	=
	{
		/* set							get								*/
		{ HPDI32_TX_AUTO_START_NO,		HPDI32_TX_AUTO_START_NO			},
		{ GSC_NO_CHANGE,				HPDI32_TX_AUTO_START_NO			},
		{ GSC_DEFAULT,					HPDI32_TX_AUTO_START_DEFAULT	},
		{ HPDI32_TX_AUTO_START_YES,		HPDI32_TX_AUTO_START_YES		},
		{ GSC_NO_CHANGE,				HPDI32_TX_AUTO_START_YES		},
		{ GSC_DEFAULT,					HPDI32_TX_AUTO_START_DEFAULT	},
		{ HPDI32_TX_AUTO_START_DEFAULT,	HPDI32_TX_AUTO_START_DEFAULT	},
		{ GSC_NO_CHANGE,				HPDI32_TX_AUTO_START_DEFAULT	},
		{ GSC_DEFAULT,					HPDI32_TX_AUTO_START_DEFAULT	}
	};

	static const set_get_list_t	set	=
	{
		/* name	*/	"Tx Auto Start",
		/* parm	*/	HPDI32_TX_AUTO_START,
		/* list	*/	list,
		/* size	*/	ARRAY_ELEMENTS(list)
	};

	int	errs;

	errs	= _parm_list_test(handle, &set);
	return(errs);
}



/*****************************************************************************
*
*	Function:	_tx_clock_divider_tests
*
*	Purpose:
*
*		Perform Transmitter Clock Divider tests.
*
*	Arguments:
*
*		handle	The handle used to access the device under test.
*
*	Returned:
*
*		0		All went well.
*		> 0		The number of errors seen.
*
*****************************************************************************/

static int _tx_clock_divider_tests(void* handle)
{
	static const set_get_t	list[]	=
	{
		/* set								get								*/
		{ HPDI32_TX_CLOCK_DIVIDER_DEFAULT,	HPDI32_TX_CLOCK_DIVIDER_DEFAULT	},
		{ GSC_NO_CHANGE,					HPDI32_TX_CLOCK_DIVIDER_DEFAULT	},
		{ GSC_DEFAULT,						HPDI32_TX_CLOCK_DIVIDER_DEFAULT	},
		{ HPDI32_TX_CLOCK_DIVIDER_MAX,		HPDI32_TX_CLOCK_DIVIDER_MAX		},
		{ GSC_NO_CHANGE,					HPDI32_TX_CLOCK_DIVIDER_MAX		},
		{ GSC_DEFAULT,						HPDI32_TX_CLOCK_DIVIDER_DEFAULT	}
	};

	static const set_get_list_t	set	=
	{
		/* name	*/	NULL,
		/* parm	*/	HPDI32_TX_CLOCK_DIVIDER,
		/* list	*/	list,
		/* size	*/	ARRAY_ELEMENTS(list)
	};

	int				errs;
	unsigned long	get;
	U32				status;
	U32				tcdr	= 0;

	label_text("Tx Clock Divider");
	hpdi32_reset(handle);

	// Process the automated list above.
	errs	= _parm_list_test(handle, &set);

	if (errs == 0)
	{
		// Perform manual validation.
		printf(".");

		// Manually set the divider and verify the results via the service call.

		status	= hpdi32_reg_write(handle, HPDI32_TCDR, 99);

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_CLOCK_DIVIDER,
									0,
									GSC_NO_CHANGE,
									&get);
		}

		if ((status == GSC_SUCCESS) && (get != 99))
			status	= GSC_FAILED;

		// Set the divider via the service call and manually verify the results.

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_CLOCK_DIVIDER,
									0,
									1024,
									&get);
		}

		if ((status == GSC_SUCCESS) && (get != 1024))
			status	= GSC_FAILED;

		if (status == GSC_SUCCESS)
			status	= hpdi32_reg_read(handle, HPDI32_TCDR, &tcdr);

		if ((status == GSC_SUCCESS) && (tcdr != 1024))
			status	= GSC_FAILED;

		errs	= (status == GSC_SUCCESS) ? 0 : 1;
	}

	hpdi32_reset(handle);

	if (errs)
		printf("FAIL <---\n");
	else
		printf("PASS\n");

	return(errs);
}



/*****************************************************************************
*
*	Function:	_tx_enable_tests
*
*	Purpose:
*
*		Perform Transmitter Enable tests.
*
*	Arguments:
*
*		handle	The handle used to access the device under test.
*
*	Returned:
*
*		0		All went well.
*		> 0		The number of errors seen.
*
*****************************************************************************/

static int _tx_enable_tests(void* handle)
{
	static const set_get_t	list[]	=
	{
		/* set						get							*/
		{ HPDI32_TX_ENABLE_YES,		HPDI32_TX_ENABLE_YES		},
		{ GSC_NO_CHANGE,			HPDI32_TX_ENABLE_YES		},
		{ GSC_DEFAULT,				HPDI32_TX_ENABLE_DEFAULT	},
		{ HPDI32_TX_ENABLE_NO,		HPDI32_TX_ENABLE_NO			},
		{ GSC_NO_CHANGE,			HPDI32_TX_ENABLE_NO			},
		{ GSC_DEFAULT,				HPDI32_TX_ENABLE_DEFAULT	},
		{ HPDI32_TX_ENABLE_DEFAULT,	HPDI32_TX_ENABLE_DEFAULT	},
		{ GSC_NO_CHANGE,			HPDI32_TX_ENABLE_DEFAULT	},
		{ GSC_DEFAULT,				HPDI32_TX_ENABLE_DEFAULT	}
	};

	static const set_get_list_t	set	=
	{
		/* name	*/	NULL,
		/* parm	*/	HPDI32_TX_ENABLE,
		/* list	*/	list,
		/* size	*/	ARRAY_ELEMENTS(list)
	};

	U32				bcr		= 0;
	int				errs;
	unsigned long	get;
	U32				status;

	label_text("Tx Enable");

	// Process the automated list above.
	errs	= _parm_list_test(handle, &set);

	if (errs == 0)
	{
		// Enable the transmitter and verify the results via BCR

		status	= hpdi32_config(handle,
								HPDI32_TX_ENABLE,
								0,
								HPDI32_TX_ENABLE_YES,
								&get);

		if ((status == GSC_SUCCESS) && (get != HPDI32_TX_ENABLE_YES))
			status	= GSC_FAILED;

		if (status == GSC_SUCCESS)
			status	= hpdi32_reg_read(handle, HPDI32_BCR, &bcr);

		if ((status == GSC_SUCCESS) && ((bcr & HPDI32_BCR_TX_ENABLED) == 0))
			status	= GSC_FAILED;

		// Disable the transmitter and verify the results via BCR

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_ENABLE,
									0,
									HPDI32_TX_ENABLE_NO,
									&get);
		}

		if ((status == GSC_SUCCESS) && (get != HPDI32_TX_ENABLE_NO))
			status	= GSC_FAILED;

		if (status == GSC_SUCCESS)
			status	= hpdi32_reg_read(handle, HPDI32_BCR, &bcr);

		if ((status == GSC_SUCCESS) && ((bcr & HPDI32_BCR_TX_ENABLED) != 0))
			status	= GSC_FAILED;

		errs	= (status == GSC_SUCCESS) ? 0 : 1;
	}

	if (errs)
		printf("FAIL <---\n");
	else
		printf("PASS\n");

	return(errs);
}



/*****************************************************************************
*
*	Function:	_tx_flow_control_tests
*
*	Purpose:
*
*		Perform Transmitter Flow Control tests.
*
*	Arguments:
*
*		handle	The handle used to access the device under test.
*
*	Returned:
*
*		0		All went well.
*		> 0		The number of errors seen.
*
*****************************************************************************/

static int _tx_flow_control_tests(void* handle)
{
	static const set_get_t	list[]	=
	{
		/* set								get								*/
		{ HPDI32_TX_FLOW_CONTROL_DISABLE,	HPDI32_TX_FLOW_CONTROL_DISABLE	},
		{ GSC_NO_CHANGE,					HPDI32_TX_FLOW_CONTROL_DISABLE	}
	};

	static const set_get_list_t	set	=
	{
		/* name	*/	"Tx Flow Control",
		/* parm	*/	HPDI32_TX_FLOW_CONTROL,
		/* list	*/	list,
		/* size	*/	ARRAY_ELEMENTS(list)
	};

	int	errs;

	// Limited testing as this is a stand alone test.
	errs	= _parm_list_test(handle, &set);
	return(errs);
}



/*****************************************************************************
*
*	Function:	_tx_line_valid_off_count_tests
*
*	Purpose:
*
*		Perform Transmitter Line Valid Off tests.
*
*	Arguments:
*
*		handle	The handle used to access the device under test.
*
*	Returned:
*
*		0		All went well.
*		> 0		The number of errors seen.
*
*****************************************************************************/

static int _tx_line_valid_off_count_tests(void* handle)
{
	static const set_get_t	list[]	=
	{
		/* set										get										*/
		{ HPDI32_TX_LINE_VALID_OFF_COUNT_DISABLE,	HPDI32_TX_LINE_VALID_OFF_COUNT_DISABLE	},
		{ GSC_NO_CHANGE,							HPDI32_TX_LINE_VALID_OFF_COUNT_DISABLE	},
		{ GSC_DEFAULT,								HPDI32_TX_LINE_VALID_OFF_COUNT_DEFAULT	},
		{ HPDI32_TX_LINE_VALID_OFF_COUNT_MAX,		HPDI32_TX_LINE_VALID_OFF_COUNT_MAX		},
		{ GSC_NO_CHANGE,							HPDI32_TX_LINE_VALID_OFF_COUNT_MAX		},
		{ GSC_DEFAULT,								HPDI32_TX_LINE_VALID_OFF_COUNT_DEFAULT	},
		{ HPDI32_TX_LINE_VALID_OFF_COUNT_DEFAULT,	HPDI32_TX_LINE_VALID_OFF_COUNT_DEFAULT	},
		{ GSC_NO_CHANGE,							HPDI32_TX_LINE_VALID_OFF_COUNT_DEFAULT	},
		{ GSC_DEFAULT,								HPDI32_TX_LINE_VALID_OFF_COUNT_DEFAULT	}
	};

	static const set_get_list_t	set	=
	{
		/* name	*/	NULL,
		/* parm	*/	HPDI32_TX_CLOCK_DIVIDER,
		/* list	*/	list,
		/* size	*/	ARRAY_ELEMENTS(list)
	};

	int				errs;
	unsigned long	get;
	U32				status;
	U32				tlilcr	= 0;

	label_text("Tx Line Valid Off Count");
	hpdi32_reset(handle);

	// Process the automated list above.
	errs	= _parm_list_test(handle, &set);

	if (errs == 0)
	{
		// Perform manual validation.
		printf(".");

		// Manually set the value and verify the results via the service call.

		status	= hpdi32_reg_write(handle, HPDI32_TLILCR, 99);

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_LINE_VALID_OFF_COUNT,
									0,
									GSC_NO_CHANGE,
									&get);
		}

		if ((status == GSC_SUCCESS) && (get != 99))
			status	= GSC_FAILED;

		// Set the value via the service call and manually verify the results.

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_LINE_VALID_OFF_COUNT,
									0,
									1024,
									&get);
		}

		if ((status == GSC_SUCCESS) && (get != 1024))
			status	= GSC_FAILED;

		if (status == GSC_SUCCESS)
			status	= hpdi32_reg_read(handle, HPDI32_TLILCR, &tlilcr);

		if ((status == GSC_SUCCESS) && (tlilcr != 1024))
			status	= GSC_FAILED;

		errs	= (status == GSC_SUCCESS) ? 0 : 1;
	}

	hpdi32_reset(handle);

	if (errs)
		printf("FAIL <---\n");
	else
		printf("PASS\n");

	return(errs);
}



/*****************************************************************************
*
*	Function:	_tx_line_valid_on_count_tests
*
*	Purpose:
*
*		Perform Transmitter Line Valid On tests.
*
*	Arguments:
*
*		handle	The handle used to access the device under test.
*
*	Returned:
*
*		0		All went well.
*		> 0		The number of errors seen.
*
*****************************************************************************/

static int _tx_line_valid_on_count_tests(void* handle)
{
	static const set_get_t	list[]	=
	{
		/* set										get										*/
		{ HPDI32_TX_LINE_VALID_ON_COUNT_DISABLE,	HPDI32_TX_LINE_VALID_ON_COUNT_DISABLE	},
		{ GSC_NO_CHANGE,							HPDI32_TX_LINE_VALID_ON_COUNT_DISABLE	},
		{ GSC_DEFAULT,								HPDI32_TX_LINE_VALID_ON_COUNT_DEFAULT	},
		{ HPDI32_TX_LINE_VALID_ON_COUNT_MAX - 5,	HPDI32_TX_LINE_VALID_ON_COUNT_MAX - 5	},
		{ GSC_NO_CHANGE,							HPDI32_TX_LINE_VALID_ON_COUNT_MAX - 5	},
		{ GSC_DEFAULT,								HPDI32_TX_LINE_VALID_ON_COUNT_DEFAULT	},
		{ HPDI32_TX_LINE_VALID_ON_COUNT_DEFAULT,	HPDI32_TX_LINE_VALID_ON_COUNT_DEFAULT	},
		{ GSC_NO_CHANGE,							HPDI32_TX_LINE_VALID_ON_COUNT_DEFAULT	},
		{ GSC_DEFAULT,								HPDI32_TX_LINE_VALID_ON_COUNT_DEFAULT	}
	};

	static const set_get_list_t	set	=
	{
		/* name	*/	NULL,
		/* parm	*/	HPDI32_TX_LINE_VALID_ON_COUNT,
		/* list	*/	list,
		/* size	*/	ARRAY_ELEMENTS(list)
	};

	int				errs;
	unsigned long	get;
	U32				status;
	U32				tlvlcr	= 0;

	label_text("Tx Line Valid On Count");
	hpdi32_reset(handle);

	// Process the automated list above.
	errs	= _parm_list_test(handle, &set);

	if (errs == 0)
	{
		// Perform manual validation.
		printf(".");

		// Manually set the value and verify the results via the service call.

		status	= hpdi32_reg_write(handle, HPDI32_TLVLCR, 99);

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_LINE_VALID_ON_COUNT,
									0,
									GSC_NO_CHANGE,
									&get);
		}

		if ((status == GSC_SUCCESS) && (get != 99))
			status	= GSC_FAILED;

		// Set the value via the service call and manually verify the results.

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_LINE_VALID_ON_COUNT,
									0,
									1024,
									&get);
		}

		if ((status == GSC_SUCCESS) && (get != 1024))
			status	= GSC_FAILED;

		if (status == GSC_SUCCESS)
			status	= hpdi32_reg_read(handle, HPDI32_TLVLCR, &tlvlcr);

		if ((status == GSC_SUCCESS) && (tlvlcr != 1024))
			status	= GSC_FAILED;

		errs	= (status == GSC_SUCCESS) ? 0 : 1;
	}

	hpdi32_reset(handle);

	if (errs)
		printf("FAIL <---\n");
	else
		printf("PASS\n");

	return(errs);
}



/*****************************************************************************
*
*	Function:	_tx_overrun_tests
*
*	Purpose:
*
*		Perform Receiver Overrun tests.
*
*	Arguments:
*
*		handle	The handle used to access the device under test.
*
*	Returned:
*
*		0		All went well.
*		> 0		The number of errors seen.
*
*****************************************************************************/

static int _tx_overrun_tests(void* handle)
{
	static set_get_t	list[]	=
	{
		/* set	get	*/
		{ 0,	0	}
	};

	static const set_get_list_t	set	=
	{
		/* name	*/	NULL,
		/* parm	*/	HPDI32_TX_OVERRUN,
		/* list	*/	list,
		/* size	*/	ARRAY_ELEMENTS(list)
	};

	U32			bsr		= 0;
	int			errs	= 0;
	fifo_info_t	info;
	U32			size;
	U32			status	= GSC_SUCCESS;

	label_text("Tx Overrun");
	hpdi32_reset(handle);
	fifo_info_tx(&info, &size);

	// Force an Tx Overrun and verify that it is so.
	status	= tx_write(handle, 129L * 1024);

	if (status == GSC_SUCCESS)
	{
		sleep_ms(100);
		status	= hpdi32_reg_read(handle, HPDI32_BSR, &bsr);
	}

	if ((status == GSC_SUCCESS) && ((bsr & HPDI32_BSR_TX_OVERRUN) == 0))
		status	= GSC_FAILED;

	if (status == GSC_SUCCESS)
	{
		list[0].set	= HPDI32_TX_OVERRUN_IGNORE;
		list[0].get	= HPDI32_TX_OVERRUN_YES;
		errs		= _parm_list_test(handle, &set);
	}
	else
	{
		errs	= 1;
	}

	status	= errs ? GSC_FAILED : status;

	if (status == GSC_SUCCESS)
	{
		sleep_ms(100);
		status	= hpdi32_reg_read(handle, HPDI32_BSR, &bsr);
	}

	if ((status == GSC_SUCCESS) && ((bsr & HPDI32_BSR_TX_OVERRUN) == 0))
		status	= GSC_FAILED;

	// Clear the Tx Overrun and verify that it is so.

	if (status == GSC_SUCCESS)
	{
		list[0].set	= HPDI32_TX_OVERRUN_CLEAR;
		list[0].get	= HPDI32_TX_OVERRUN_NO;
		errs		= _parm_list_test(handle, &set);
	}
	else
	{
		errs	= 1;
	}

	status	= errs ? GSC_FAILED : status;

	if (status == GSC_SUCCESS)
	{
		sleep_ms(100);
		status	= hpdi32_reg_read(handle, HPDI32_BSR, &bsr);
	}

	if ((status == GSC_SUCCESS) && (bsr & HPDI32_BSR_TX_OVERRUN))
		status	= GSC_FAILED;

	errs	= (status == GSC_SUCCESS) ? errs : 1;
	hpdi32_reset(handle);

	if (info == FIFO_NONE)
	{
		errs	= 0;
		printf("SKIPPED (no Tx FIFOs)\n");
	}
	else if (errs)
	{
		printf("FAIL <---\n");
	}
	else
	{
		printf("PASS\n");
	}

	return(errs);
}



/*****************************************************************************
*
*	Function:	_tx_remote_throttle_tests
*
*	Purpose:
*
*		Perform Transmitter Remote Throttle tests.
*
*	Arguments:
*
*		handle	The handle used to access the device under test.
*
*	Returned:
*
*		0		All went well.
*		> 0		The number of errors seen.
*
*****************************************************************************/

static int _tx_remote_throttle_tests(void* handle)
{
	static const set_get_t	list[]	=
	{
		/* set									get									*/
		{ HPDI32_TX_REMOTE_THROTTLE_DISABLE,	HPDI32_TX_REMOTE_THROTTLE_DISABLE	},
		{ GSC_NO_CHANGE,						HPDI32_TX_REMOTE_THROTTLE_DISABLE	},
		{ GSC_DEFAULT,							HPDI32_TX_REMOTE_THROTTLE_DEFAULT	},
		{ HPDI32_TX_REMOTE_THROTTLE_ENABLE,		HPDI32_TX_REMOTE_THROTTLE_ENABLE	},
		{ GSC_NO_CHANGE,						HPDI32_TX_REMOTE_THROTTLE_ENABLE	},
		{ GSC_DEFAULT,							HPDI32_TX_REMOTE_THROTTLE_DEFAULT	},
		{ HPDI32_TX_REMOTE_THROTTLE_DEFAULT,	HPDI32_TX_REMOTE_THROTTLE_DEFAULT	},
		{ GSC_NO_CHANGE,						HPDI32_TX_REMOTE_THROTTLE_DEFAULT	},
		{ GSC_DEFAULT,							HPDI32_TX_REMOTE_THROTTLE_DEFAULT	}
	};

	static const set_get_list_t	set	=
	{
		/* name	*/	NULL,
		/* parm	*/	HPDI32_TX_REMOTE_THROTTLE,
		/* list	*/	list,
		/* size	*/	ARRAY_ELEMENTS(list)
	};

	U32				bcr		= 0;
	int				errs;
	unsigned long	get;
	U32				status;

	label_text("Tx Remote Throttle");
	hpdi32_reset(handle);

	// Process the automated list above.
	errs	= _parm_list_test(handle, &set);

	if (errs == 0)
	{
		// Perform manual validation.
		printf(".");

		// Manually set the value and verify the results via the service call.

		status	= hpdi32_reg_write(handle, HPDI32_BCR, 0);

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_REMOTE_THROTTLE,
									0,
									GSC_NO_CHANGE,
									&get);
		}

		if ((status == GSC_SUCCESS) &&
			(get != HPDI32_TX_REMOTE_THROTTLE_ENABLE))
		{
			status	= GSC_FAILED;
		}

		// Manually set the value and verify the results via the service call.

		status	= hpdi32_reg_write(handle, HPDI32_BCR, HPDI32_BCR_TX_THROTTLE);

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_REMOTE_THROTTLE,
									0,
									GSC_NO_CHANGE,
									&get);
		}

		if ((status == GSC_SUCCESS) &&
			(get != HPDI32_TX_REMOTE_THROTTLE_ENABLE))
		{
			status	= GSC_FAILED;
		}

		// Set the value via the service call and manually verify the results.

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_REMOTE_THROTTLE,
									0,
									HPDI32_TX_REMOTE_THROTTLE_ENABLE,
									&get);
		}

		if ((status == GSC_SUCCESS) &&
			(get != HPDI32_TX_REMOTE_THROTTLE_ENABLE))
		{
			status	= GSC_FAILED;
		}

		if (status == GSC_SUCCESS)
			status	= hpdi32_reg_read(handle, HPDI32_BCR, &bcr);

		if ((status == GSC_SUCCESS) && ((bcr & HPDI32_BCR_TX_THROTTLE) == 0))
			status	= GSC_FAILED;

		// Set the value via the service call and manually verify the results.

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_REMOTE_THROTTLE,
									0,
									HPDI32_TX_REMOTE_THROTTLE_DISABLE,
									&get);
		}

		if ((status == GSC_SUCCESS) &&
			(get != HPDI32_TX_REMOTE_THROTTLE_DISABLE))
		{
			status	= GSC_FAILED;
		}

		if (status == GSC_SUCCESS)
			status	= hpdi32_reg_read(handle, HPDI32_BCR, &bcr);

		if ((status == GSC_SUCCESS) && (bcr & HPDI32_BCR_TX_THROTTLE))
			status	= GSC_FAILED;

		errs	= (status == GSC_SUCCESS) ? 0 : 1;
	}

	hpdi32_reset(handle);

	if (errs)
		printf("FAIL <---\n");
	else
		printf("PASS\n");

	return(errs);
}



/*****************************************************************************
*
*	Function:	_tx_remote_throttle_state_tests
*
*	Purpose:
*
*		Perform Transmitter Remote Throttle tests.
*
*	Arguments:
*
*		handle	The handle used to access the device under test.
*
*	Returned:
*
*		0		All went well.
*		> 0		The number of errors seen.
*
*****************************************************************************/

static int _tx_remote_throttle_state_tests(void* handle)
{
	static const set_get_t	list[]	=
	{
		/* set	get											*/
		{ 0,	HPDI32_TX_REMOTE_THROTTLE_STATE_INACTIVE	}
	};

	static const set_get_list_t	set	=
	{
		/* name	*/	"Tx Remote Throttle State",
		/* parm	*/	HPDI32_TX_REMOTE_THROTTLE_STATE,
		/* list	*/	list,
		/* size	*/	ARRAY_ELEMENTS(list)
	};

	int	errs;

	// Limited testing as this is a stand alone test.
	errs	= _parm_list_test(handle, &set);
	return(errs);
}



/*****************************************************************************
*
*	Function:	_tx_state_tests
*
*	Purpose:
*
*		Perform Transmitter State tests.
*
*	Arguments:
*
*		handle	The handle used to access the device under test.
*
*	Returned:
*
*		0		All went well.
*		> 0		The number of errors seen.
*
*****************************************************************************/

static int _tx_state_tests(void* handle)
{
	static const set_get_t	list[]	=
	{
		/* set	get							*/
		{ 0,	HPDI32_TX_STATE_INACTIVE	}
	};

	static const set_get_list_t	set	=
	{
		/* name	*/	"Tx State",
		/* parm	*/	HPDI32_TX_STATE,
		/* list	*/	list,
		/* size	*/	ARRAY_ELEMENTS(list)
	};

	int	errs;

	// Limited testing as this is a stand alone test.
	errs	= _parm_list_test(handle, &set);
	return(errs);
}



/*****************************************************************************
*
*	Function:	_tx_status_valid_count_tests
*
*	Purpose:
*
*		Perform Transmitter Status Valid tests.
*
*	Arguments:
*
*		handle	The handle used to access the device under test.
*
*	Returned:
*
*		0		All went well.
*		> 0		The number of errors seen.
*
*****************************************************************************/

static int _tx_status_valid_count_tests(void* handle)
{
	static const set_get_t	list[]	=
	{
		/* set									get										*/
		{ HPDI32_TX_STATUS_VALID_COUNT_DISABLE,	HPDI32_TX_STATUS_VALID_COUNT_DISABLE	},
		{ GSC_NO_CHANGE,						HPDI32_TX_STATUS_VALID_COUNT_DISABLE	},
		{ GSC_DEFAULT,							HPDI32_TX_STATUS_VALID_COUNT_DEFAULT	},
		{ HPDI32_TX_STATUS_VALID_COUNT_MAX - 5,	HPDI32_TX_STATUS_VALID_COUNT_MAX - 5	},
		{ GSC_NO_CHANGE,						HPDI32_TX_STATUS_VALID_COUNT_MAX - 5	},
		{ GSC_DEFAULT,							HPDI32_TX_STATUS_VALID_COUNT_DEFAULT	},
		{ HPDI32_TX_STATUS_VALID_COUNT_DEFAULT,	HPDI32_TX_STATUS_VALID_COUNT_DEFAULT	},
		{ GSC_NO_CHANGE,						HPDI32_TX_STATUS_VALID_COUNT_DEFAULT	},
		{ GSC_DEFAULT,							HPDI32_TX_STATUS_VALID_COUNT_DEFAULT	}
	};

	static const set_get_list_t	set	=
	{
		/* name	*/	NULL,
		/* parm	*/	HPDI32_TX_STATUS_VALID_COUNT,
		/* list	*/	list,
		/* size	*/	ARRAY_ELEMENTS(list)
	};

	int				errs;
	unsigned long	get;
	U32				status;
	U32				tsvlcr	= 0;

	label_text("Tx Status Valid Count");
	hpdi32_reset(handle);

	// Process the automated list above.
	errs	= _parm_list_test(handle, &set);

	if (errs == 0)
	{
		// Perform manual validation.
		printf(".");

		// Manually set the value and verify the results via the service call.

		status	= hpdi32_reg_write(handle, HPDI32_TSVLCR, 99);

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_STATUS_VALID_COUNT,
									0,
									GSC_NO_CHANGE,
									&get);
		}

		if ((status == GSC_SUCCESS) && (get != 99))
			status	= GSC_FAILED;

		// Set the value via the service call and manually verify the results.

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_STATUS_VALID_COUNT,
									0,
									1024,
									&get);
		}

		if ((status == GSC_SUCCESS) && (get != 1024))
			status	= GSC_FAILED;

		if (status == GSC_SUCCESS)
			status	= hpdi32_reg_read(handle, HPDI32_TSVLCR, &tsvlcr);

		if ((status == GSC_SUCCESS) && (tsvlcr != 1024))
			status	= GSC_FAILED;

		errs	= (status == GSC_SUCCESS) ? 0 : 1;
	}

	hpdi32_reset(handle);

	if (errs)
		printf("FAIL <---\n");
	else
		printf("PASS\n");

	return(errs);
}



/*****************************************************************************
*
*	Function:	_tx_status_valid_mirror_tests
*
*	Purpose:
*
*		Perform Transmitter Status Valid Mirror tests.
*
*	Arguments:
*
*		handle	The handle used to access the device under test.
*
*	Returned:
*
*		0		All went well.
*		> 0		The number of errors seen.
*
*****************************************************************************/

static int _tx_status_valid_mirror_tests(void* handle)
{
	static const set_get_t	list[]	=
	{
		/* set										get										*/
		{ HPDI32_TX_STATUS_VALID_MIRROR_DISABLE,	HPDI32_TX_STATUS_VALID_MIRROR_DISABLE	},
		{ GSC_NO_CHANGE,							HPDI32_TX_STATUS_VALID_MIRROR_DISABLE	},
		{ GSC_DEFAULT,								HPDI32_TX_STATUS_VALID_MIRROR_DEFAULT	},
		{ HPDI32_TX_STATUS_VALID_MIRROR_ENABLE,		HPDI32_TX_STATUS_VALID_MIRROR_ENABLE	},
		{ GSC_NO_CHANGE,							HPDI32_TX_STATUS_VALID_MIRROR_ENABLE	},
		{ GSC_DEFAULT,								HPDI32_TX_STATUS_VALID_MIRROR_DEFAULT	},
		{ HPDI32_TX_STATUS_VALID_MIRROR_DEFAULT,	HPDI32_TX_STATUS_VALID_MIRROR_DEFAULT	},
		{ GSC_NO_CHANGE,							HPDI32_TX_STATUS_VALID_MIRROR_DEFAULT	},
		{ GSC_DEFAULT,								HPDI32_TX_STATUS_VALID_MIRROR_DEFAULT	}
	};

	static const set_get_list_t	set	=
	{
		/* name	*/	NULL,
		/* parm	*/	HPDI32_TX_STATUS_VALID_MIRROR,
		/* list	*/	list,
		/* size	*/	ARRAY_ELEMENTS(list)
	};

	U32				bcr		= 0;
	int				errs;
	unsigned long	get;
	U32				status;

	label_text("Tx Status Valid Mirror");

	// Process the automated list above.
	errs	= _parm_list_test(handle, &set);

	if (errs == 0)
	{
		// Perform manual validation.
		printf(".");

		// Set the value manually and verify the results.
		status	= hpdi32_reg_write(handle, HPDI32_BCR, HPDI32_BCR_STATUS_VALID);

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_STATUS_VALID_MIRROR,
									0,
									GSC_NO_CHANGE,
									&get);
		}

		if ((status == GSC_SUCCESS) &&
			(get != HPDI32_TX_STATUS_VALID_MIRROR_DISABLE))
		{
			status	= GSC_FAILED;
		}

		// Set the value manually and verify the results.

		if (status == GSC_SUCCESS)
			status	= hpdi32_reg_write(handle, HPDI32_BCR, 0);

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_STATUS_VALID_MIRROR,
									0,
									GSC_NO_CHANGE,
									&get);
		}

		if ((status == GSC_SUCCESS) &&
			(get != HPDI32_TX_STATUS_VALID_MIRROR_ENABLE))
		{
			status	= GSC_FAILED;
		}

		// Set the value with the service and verify the results manually.

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_STATUS_VALID_MIRROR,
									0,
									HPDI32_TX_STATUS_VALID_MIRROR_ENABLE,
									&get);
		}

		if (status == GSC_SUCCESS)
			status	= hpdi32_reg_read(handle, HPDI32_BCR, &bcr);

		if ((status == GSC_SUCCESS) && (bcr & HPDI32_BCR_STATUS_VALID))
			status	= GSC_FAILED;

		// Set the value with the service and verify the results manually.

		if (status == GSC_SUCCESS)
		{
			status	= hpdi32_config(handle,
									HPDI32_TX_STATUS_VALID_MIRROR,
									0,
									HPDI32_TX_STATUS_VALID_MIRROR_DISABLE,
									&get);
		}

		if (status == GSC_SUCCESS)
			status	= hpdi32_reg_read(handle, HPDI32_BCR, &bcr);

		if ((status == GSC_SUCCESS) && ((bcr & HPDI32_BCR_STATUS_VALID) == 0))
			status	= GSC_FAILED;

		errs	= (status == GSC_SUCCESS) ? 0 : 1;
	}

	if (errs)
		printf("FAIL <---\n");
	else
		printf("PASS\n");

	return(errs);
}



/*****************************************************************************
*
*	Function:	tx_config_tests
*
*	Purpose:
*
*		Perform Transmitter configuration tests.
*
*	Arguments:
*
*		handle	The handle used to access the device under test.
*
*	Returned:
*
*		0		All went well.
*		> 0		The number of errors seen.
*
*****************************************************************************/

int tx_config_tests(void* handle)
{
	int	errs	= 0;

	label_text("Transmitter Configuration");
	printf("\n");
	label_level_inc();

	errs	+= _tx_auto_start_tests(handle);
	errs	+= _tx_clock_divider_tests(handle);
	errs	+= _tx_enable_tests(handle);
	errs	+= _tx_flow_control_tests(handle);
	errs	+= _tx_line_valid_off_count_tests(handle);
	errs	+= _tx_line_valid_on_count_tests(handle);
	errs	+= _tx_overrun_tests(handle);
	errs	+= _tx_remote_throttle_tests(handle);
	errs	+= _tx_remote_throttle_state_tests(handle);
	errs	+= _tx_state_tests(handle);
	errs	+= _tx_status_valid_count_tests(handle);
	errs	+= _tx_status_valid_mirror_tests(handle);

	label_level_dec();
	return(errs);
}



/*****************************************************************************
*
*	Function:	tx_write
*
*	Purpose:
*
*		Write data to the Tx FIFO.
*
*	Arguments:
*
*		handle		The handle used to access the device under test.
*
*		samples		The number of samples to write.
*
*	Returned:
*
*		GSC_SUCCESS	All went well.
*		else		An appropriate error status.
*
*****************************************************************************/

U32 tx_write(void* handle, U32 samples)
{
	U32	status	= GSC_SUCCESS;

	for (;samples; samples--)
	{
		status	= hpdi32_reg_write(handle, HPDI32_FDR, 0);

		if (status != GSC_SUCCESS)
			break;
	}

	return(status);
}


