#include <stdio.h>

#include "bme.h"
#include "bme_app.h"
#include "mem.h"
#include "drvUtils.h"
#include "hostType.h"

 
extern char capTest;

int read_afifo_status(int line_num, int *fifo_start_addr, int *size)	
{
	int a_fifo_start_addr;
	int	fifo_size, tmp0, tmp1, tmp2, tmp3;
	u32	afifo_cntxt_a, afifo_cntxt_c, afifo_cntxt_d;
	
	afifo_cntxt_a = readPIO_SingleRegChannel((int *)CAFT_A, line_num);
	afifo_cntxt_c = readPIO_SingleRegChannel((int *)CAFT_C, line_num);
	afifo_cntxt_d = readPIO_SingleRegChannel((int *)CAFT_D, line_num);
	
	a_fifo_start_addr = (ADDRESS_AFIFO + (((afifo_cntxt_a>>7)&0x3ff)<<7));
	tmp0 = (int) afifo_cntxt_a;
	tmp1 = tmp0>>3;
	tmp2 = tmp1&0xf;
	tmp3 = 1<<tmp2;
	fifo_size = tmp3*128;
    if (!capTest) {
        logMsg("line # %d\n", line_num);
        logMsg("\tbuf_start = 0x%8x, buf_size = %d\n", 	(int)a_fifo_start_addr, fifo_size);
        logMsg("\tbuf_rd_ptr = 0x%8x, buf_wr_ptr = 0x%8x\n",   afifo_cntxt_c&0x1ffff, afifo_cntxt_d&0x1ffff);
        logMsg("\tRD_WRAP_STATUS = %d, WR_WRAP_STATUS = %d", (afifo_cntxt_c>>17)&0x1, (afifo_cntxt_d>>17)&0x1);
    }

	*fifo_start_addr = ADDRESS_AFIFO;
	*size = fifo_size;
	return(a_fifo_start_addr);
}


int afifo_data_avail(int line_num, int fifo_size)
{
	u32 	afifo_cntxt_c, afifo_cntxt_d;
	int		rd_ptr, wr_ptr, data_avail;
		
	afifo_cntxt_c = readPIO_SingleRegChannel((int *)CAFT_C, line_num);
	afifo_cntxt_d = readPIO_SingleRegChannel((int *)CAFT_D, line_num);

	if((afifo_cntxt_c>>17)&0x1)
		logMsg("\n afifo read ptr wrap around happened");
	if((afifo_cntxt_d>>17)&0x1)
		logMsg("\n afifo write ptr wrap around happened");	
	rd_ptr = afifo_cntxt_c&0x1ffff;
	wr_ptr = afifo_cntxt_d&0x1ffff;
	
    if (!capTest) {
        logMsg("\n afifo data avail: rd_ptr=%d,wr_ptr=%d", rd_ptr,wr_ptr);
    }
	
    if(wr_ptr>=rd_ptr)
		data_avail = wr_ptr-rd_ptr;
	else
		data_avail = fifo_size - (rd_ptr-wr_ptr);
	
    if (!capTest) {
        logMsg("\n afifo data avail = %d", data_avail);
    }
		
	return(data_avail);		
}

void read_ibfifo_status(int line_num, int *fifo_start_addr, int *size)
{
	u8	*b_fifo_start_addr;
	int	fifo_size, tmp0, tmp1, tmp2, tmp3;
	u32	bfifo_cntxt_a, bfifo_cntxt_b, bfifo_cntxt_c;
	
	bfifo_cntxt_a = readPIO_SingleRegChannel((int *)CBIT_A, line_num);
	bfifo_cntxt_b = readPIO_SingleRegChannel((int *)CBIT_B, line_num);
	bfifo_cntxt_c = readPIO_SingleRegChannel((int *)CBIT_C, line_num);
	
	b_fifo_start_addr = (u8 *)(ADDRESS_BFIFOINTERLEAVE + (((bfifo_cntxt_a>>7)&0x3ff)<<7));
	tmp0 = (int) bfifo_cntxt_a;
	tmp1 = tmp0>>3;
	tmp2 = tmp1&0xf;
	tmp3 = 1<<tmp2;
	fifo_size = tmp3*128;
	*fifo_start_addr = ADDRESS_BFIFOINTERLEAVE;
	*size = fifo_size;

}	
	
int ibfifo_data_avail(int line_num, int fifo_size)
{
	u32 	bfifo_cntxt_b, bfifo_cntxt_c;
	int		rd_ptr, wr_ptr, data_avail;
		
	bfifo_cntxt_b = readPIO_SingleRegChannel((int *)CBIT_B, line_num);
	bfifo_cntxt_c = readPIO_SingleRegChannel((int *)CBIT_C, line_num);

	rd_ptr = bfifo_cntxt_b&0xffff;
	wr_ptr = (bfifo_cntxt_b>>16)&0xffff;
	
	if(wr_ptr>=rd_ptr)
		data_avail = wr_ptr-rd_ptr;
	else
		data_avail = fifo_size - (rd_ptr-wr_ptr);
	
    return(data_avail);	
}

void clear_bfifo(int line_num)
{
	int		fifo_start_addr;
	int		size;
	
	read_ibfifo_status(line_num, &fifo_start_addr, &size);
	ibfifo_data_avail(line_num, size);
	writePIO_SingleRegChannel((int *)CBIT_B, line_num, 0x0);
	writePIO_SingleRegChannel((int *)CBIT_C, line_num, 0x0);
}

int read_zfifo_status(int line_num, int *fifo_start_addr, int *size)	
{
	int z_fifo_start_addr;
	int	fifo_size, tmp0, tmp1, tmp2, tmp3;
	u32	zfifo_cntxt_a, zfifo_cntxt_c, zfifo_cntxt_d;
	
	zfifo_cntxt_a = readPIO_SingleRegChannel((int *)ZFIFO_CZFT_A, line_num);
	zfifo_cntxt_c = readPIO_SingleRegChannel((int *)ZFIFO_CZFT_C, line_num);
	zfifo_cntxt_d = readPIO_SingleRegChannel((int *)ZFIFO_CZFT_D, line_num);
	
	z_fifo_start_addr = (ADDRESS_ZFIFO + (((zfifo_cntxt_a>>7)&0x3ff)<<7));
	tmp0 = (int) zfifo_cntxt_a;
	tmp1 = tmp0>>3;
	tmp2 = tmp1&0xf;
	tmp3 = 1<<tmp2;
	fifo_size = tmp3*128;

	logMsg("ZFifo status for line # %d\n", line_num);
	logMsg("\tbuf_start = 0x%8x, buf_size = %d\n", 	(int)z_fifo_start_addr, fifo_size);
	logMsg("\tbuf_rd_ptr = 0x%8x, buf_wr_ptr = 0x%8x\n",   zfifo_cntxt_c&0x1ffff, zfifo_cntxt_d&0x1ffff);
	logMsg("\tRD_WRAP_STATUS = %d, WR_WRAP_STATUS = %d", (zfifo_cntxt_c>>17)&0x1, (zfifo_cntxt_d>>17)&0x1);

	*fifo_start_addr = ADDRESS_ZFIFO;
	*size = fifo_size;
	return(z_fifo_start_addr);
}

int zfifo_data_avail(int line_num, int fifo_size)
{
	u32 	zfifo_cntxt_c, zfifo_cntxt_d;
	int		rd_ptr, wr_ptr, data_avail;
		
	zfifo_cntxt_c = readPIO_SingleRegChannel((int *)ZFIFO_CZFT_C, line_num);
	zfifo_cntxt_d = readPIO_SingleRegChannel((int *)ZFIFO_CZFT_D, line_num);

	if((zfifo_cntxt_c>>17)&0x1)
		logMsg("\n afifo read ptr wrap around happened");
	if((zfifo_cntxt_d>>17)&0x1)
		logMsg("\n afifo write ptr wrap around happened");	
	rd_ptr = zfifo_cntxt_c&0x1ffff;
	wr_ptr = zfifo_cntxt_d&0x1ffff;
	
	if(wr_ptr>=rd_ptr)
		data_avail = wr_ptr-rd_ptr;
	else
		data_avail = fifo_size - (rd_ptr-wr_ptr);
	
	logMsg("\n zfifo data avail = %d", data_avail);
		
	return(data_avail);		
}
