/******************************************************************************
 *
 *	spi3br_linux_app.c
 *	--------------------
 *	Example using SPI-3 bridge VxWorks configuration and status device
 *	driver. This code is specific to the mthood hardware.
 *
 ******************************************************************************
 *
 *	COPYRIGHT 2003 BY RADISYS CORPORATION.  ALL RIGHTS RESERVED.
 *
 ******************************************************************************/
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include "spi3br_linux.h"
#include "spi3br_defs.h"

/*
 *	BUILD OPTIONS
 */
#define ENABLE_INTERRUPTS					TRUE

/*
 * 	Global storage for device handle
 */
static SPI3BR_HANDLE	spi3br;

/*
 * 	Global storage for user context parameter
 */
static UINT32	usrCtxt0 = 0;

/*
 * 	Forward declarations
 */
void spi3brCallback( void *usrCtxt, UINT16 intEvents );

static int openSpi3br()
{
	/* open device */
	spi3br = open("/dev/spi3br", O_RDWR, 0);
	if( spi3br == -1 ) {
		spi3br = 0;
		return SPI3BR_DEVICE_NOT_FOUND;
	}
	return SPI3BR_SUCCESS;
}

static void closeSpi3Br()
{
	if (spi3br) close(spi3br);
	spi3br = 0;
}

/*
 *	StartSpi3br()
 *	-------------
 *	Init spi3br driver & device, open device, install isr callback.  Device is
 *	ready for rx and tx.
 */
void StartSpi3br( void )
{
	SPI3BR_STATUS		status;
	UINT16				intMask;

	status = openSpi3br();
	if( status != SPI3BR_SUCCESS )
	{
		printf("StartSpi3br: device open failed. Device not found\n");
		exit(-1);
	}

	/* enable interrupts */
#if( ENABLE_INTERRUPTS )
	intMask = SPI3BR_IRQ_ALL;
	ioctl( spi3br, SPI3BR_IOCTL_SET_INT_EN, &intMask );
#endif

	closeSpi3Br();

	printf("SPI3 bridge started\n");
	return;
}


/*
 *	ShowSpi3br()
 *	------------
 *	Show all settings for spi3br device
 */
void ShowSpi3br( void )
{
	SPI3BR_STATUS			status;
	UINT16					p0;
	UINT8					p1;
	int						i;
	SPI3BR_CHAN_CFG			chCfg;

	status = openSpi3br();
	if( status != SPI3BR_SUCCESS )
	{
		printf("ShowSpi3br: device open failed, Status = 0x%x\n", status);
		exit(-1);
	}

	/* device id */
	status = ioctl( spi3br, SPI3BR_IOCTL_GET_CHIP_ID, &p0 );
	if( status != SPI3BR_SUCCESS )
	{
		printf("SPI3BR_IOCTL_GET_CHIP_ID failed, status = 0x%x\n", status);
		exit(-1);
	}
	printf("Chip ID                   0x%04x\n", p0);

	/* device rev */
	status = ioctl( spi3br, SPI3BR_IOCTL_GET_CHIP_REV, &p1 );
	if( status != SPI3BR_SUCCESS )
	{
		printf("SPI3BR_IOCTL_GET_CHIP_REV failed, status = 0x%x\n", status);
		exit(-1);
	}
	printf("Chip Rev                  0x  %02x\n", p1);

	/* device int enable */
	status = ioctl( spi3br, SPI3BR_IOCTL_GET_INT_EN, &p0 );
	if( status != SPI3BR_SUCCESS )
	{
		printf("SPI3BR_IOCTL_GET_INT_EN failed, status = 0x%x\n", status);
		exit(-1);
	}
	printf("Interrupt Enable          0x%04x\n", p0);

	/* device int status */
	status = ioctl( spi3br, SPI3BR_IOCTL_GET_INT_STTS, &p0 );
	if( status != SPI3BR_SUCCESS )
	{
		printf("SPI3BR_IOCTL_GET_INT_STTS failed, status = 0x%x\n", status);
		exit(-1);
	}
	printf("Interrupt Status          0x%04x\n", p0);

	/* port enables */
	for(i=0; i<4; i++ )
	{
		chCfg.port = i;
		status = ioctl( spi3br, SPI3BR_IOCTL_GET_PORT_EN, &chCfg );
		if( status != SPI3BR_SUCCESS )
		{
			printf("SPI3BR_IOCTL_GET_PORT_EN failed on port %d, status = 0x%x\n", i, status);
			exit(-1);
		}
		printf("Port %d enable             0x%04x\n", i, chCfg.val);
	}

	/* burst size */
	status = ioctl( spi3br, SPI3BR_IOCTL_GET_BURST_SIZE, &p1 );
	if( status != SPI3BR_SUCCESS )
	{
		printf("SPI3BR_IOCTL_GET_BURST_SIZE failed, status = 0x%x\n", status);
		exit(-1);
	}
	printf("Burst Size                0x  %02x\n", p1);

	/* port paus */
	for(i=0; i<4; i++ )
	{
		chCfg.port = i;
		status = ioctl( spi3br, SPI3BR_IOCTL_GET_PORT_PAUS, &chCfg );
		if( status != SPI3BR_SUCCESS )
		{
			printf("SPI3BR_IOCTL_GET_PORT_PAUS failed on port %d, status = 0x%x\n", i, status);
			exit(-1);
		}
		printf("Port %d pause              0x%04x\n", i, chCfg.val);
	}

	/* port pausd */
	for(i=0; i<4; i++ )
	{
		chCfg.port = i;
		status = ioctl( spi3br, SPI3BR_IOCTL_GET_PORT_PAUSD, &chCfg );
		if( status != SPI3BR_SUCCESS )
		{
			printf("SPI3BR_IOCTL_GET_PORT_PAUSD failed on port %d, status = 0x%x\n", i, status);
			exit(-1);
		}
		printf("Port %d paused             0x%04x\n", i, chCfg.val);
	}

	/* rx fifo control */
	for(i=0; i<4; i++ )
	{
		chCfg.port = i;
		status = ioctl( spi3br, SPI3BR_IOCTL_GET_RX_FIFO_CTL, &chCfg );
		if( status != SPI3BR_SUCCESS )
		{
			printf("SPI3BR_IOCTL_GET_RX_FIFO_CTL failed on port %d, status = 0x%x\n", i, status);
			exit(-1);
		}
		printf("Port %d rx fifo ctrl       0x%04x\n", i, chCfg.val);
	}

	/* tx fifo control */
	for(i=0; i<4; i++ )
	{
		chCfg.port = i;
		status = ioctl( spi3br, SPI3BR_IOCTL_GET_TX_FIFO_CTL, &chCfg );
		if( status != SPI3BR_SUCCESS )
		{
			printf("SPI3BR_IOCTL_GET_TX_FIFO_CTL failed on port %d, status = 0x%x\n", i, status);
			exit(-1);
		}
		printf("Port %d tx fifo ctrl       0x%04x\n", i, chCfg.val);
	}

	closeSpi3Br();
}


/*
 *	StopSpi3br()
 *	------------
 *	remove callbacks, close macs, and stop spi3br driver
 */
void StopSpi3br( void )
{
	SPI3BR_STATUS		status;
	UINT16				intMask;

	status = openSpi3br();
	if( status != SPI3BR_SUCCESS )
	{
		printf("ShowSpi3br: device open failed, Status = 0x%x\n", status);
		exit(-1);
	}

	/* disable interrupts */
#if( ENABLE_INTERRUPTS )
	intMask = SPI3BR_IRQ_ALL;
	ioctl( spi3br, SPI3BR_IOCTL_CLR_INT_EN, &intMask );
#endif

	closeSpi3Br();

	printf("SPI3 bridge stopped\n");
}



/*
 *	spi3brCallback()
 *	----------------
 *	Callback function for spi3br device interrupts.
 */
void spi3brCallback( void *usrCtxt,  UINT16 intEvents )
{
	printf("Spi3br interrupt callback: usrCtxt = 0x%x\n", *((UINT32 *)usrCtxt));

	if(intEvents & SPI3BR_IRQ_PHY0_CH0_RX_OVERFW)
	{
		printf("-> PHY0_CH0_RX_OVERFW\n");
	}

	if(intEvents & SPI3BR_IRQ_PHY0_CH1_RX_OVERFW)
	{
		printf("-> PHY0_CH1_RX_OVERFW\n");
	}

	if(intEvents & SPI3BR_IRQ_PHY1_CH0_RX_OVRFLW)
	{
		printf("-> PHY1_CH0_RX_OVRFLW\n");
	}

	if(intEvents & SPI3BR_IRQ_PHY1_CH1_RX_OVRFLW)
	{
		printf("-> PHY1_CH1_RX_OVRFLW\n");
	}

	if(intEvents & SPI3BR_IRQ_PHY0_CH0_TX_OVERFW)
	{
		printf("-> PHY0_CH0_TX_OVERFW\n");
	}

	if(intEvents & SPI3BR_IRQ_PHY0_CH1_TX_OVERFW)
	{
		printf("-> PHY0_CH1_TX_OVERFW\n");
	}

	if(intEvents & SPI3BR_IRQ_PHY1_CH0_TX_OVRFLW)
	{
		printf("-> PHY1_CH0_TX_OVRFLW\n");
	}

	if(intEvents & SPI3BR_IRQ_PHY1_CH1_TX_OVRFLW)
	{
		printf("-> PHY1_CH1_TX_OVRFLW\n");
	}

	if(intEvents & SPI3BR_IRQ_IXP_TX_PARITY)
	{
		printf("-> IXP_TX_PARITY\n");
	}

	if(intEvents & SPI3BR_IRQ_PHY0_RX_PARITY)
	{
		printf("-> PHY0_RX_PARITY\n");
	}

	if(intEvents & SPI3BR_IRQ_PHY1_RX_PARITY)
	{
		printf("-> PHY1_RX_PARITY\n");
	}

}

void TestSPI3Interrupts(void)
{
	SPI3BR_STATUS		status;
	SPI3BR_CHAN_CFG	chCfg;
	int i;

	printf("Testing SPI3 Interrupts\n");

	status = openSpi3br();
	if( status != SPI3BR_SUCCESS )
	{
		printf("ShowSpi3br: device open failed, Status = 0x%x\n", status);
		exit(-1);
	}

	for (i=0; i<8; i++) {
		chCfg.port = SPI3BR_REG_DEBUG0;
		chCfg.val = (1<<i) & 0xff;
		ioctl(spi3br, SPI3BR_IOCTL_DBG_SET_REG, &chCfg );
	}

	for (i=0; i<3; i++) {
		chCfg.port = SPI3BR_REG_DEBUG1;
		chCfg.val = (1<<i) & 0xff;
		ioctl(spi3br, SPI3BR_IOCTL_DBG_SET_REG, &chCfg );
	}

	chCfg.port = SPI3BR_REG_DEBUG0;
	chCfg.val = 0xff;
	ioctl(spi3br, SPI3BR_IOCTL_DBG_SET_REG, &chCfg );

	chCfg.port = SPI3BR_REG_DEBUG1;
	chCfg.val = 0x7;
	ioctl(spi3br, SPI3BR_IOCTL_DBG_SET_REG, &chCfg );

	closeSpi3Br();
}
