#include <csl_intc.h>
#include <cslr_srio.h>
#include <csl_srio.h>
#include <csl_srioAux.h>
#include <stdio.h>
#include "environment.h"
#include "com.h"
#include "hardware.h"
#include "system_control.h"
#include "timer.h"
#include "srio.h"
#include "srio_master.h"
#include "Spb_system.h"
#include "DMAScheduler.h"
#include "data_indicator.h"
#include "system_setup.h"
#include "processing.h"
#pragma DATA_SECTION(srio_master_packet, ".srio_data_buffer");
//#pragma DATA_ALIGN(srio_master_packet, 8);

TSRIOPacket srio_master_packet;

CSL_SrioObj			srioObj;       ///< Srio Object
CSL_SrioHandle		hSrio;         ///< Srio Handle to the object
CSL_InstNum			srioNum = 0;   ///< Instance number of the SRIO 
CSL_SrioContext		SrioContext;   ///< Srio Context
CSL_Status			srio_status;        ///< CSL status variable
CSL_SrioParam		srioParam;     ///< Srio parameter structure
CSL_SrioPortData	response;      ///< Port data variable
static CSL_SrioHwSetup		sriosetup = CSL_SRIO_HWSETUP_DEFAULTS; ///< Srio configuration structure, set to defaults
extern TTabletCharacter TabletCharacter_SPB;
int rx_count = 0;
int errorOccured = 0;
extern volatile Uint32 srio_complet_isr[4];
TSrioControl srio_process_control;
TSRIOTransferStatus SRIOTransferStatus;
int master_checksum;
int srio_error_count=0;
int chip_index = 0;
volatile int srio_lock =0;
int tempDelay = 1;
int srio_test_count[20];

unsigned int testCheckSum(unsigned int* src, unsigned int len);
void Srio_Master_Init(void)
{
	//setup interrupt 
	Srio_SetupInterrupt();

	//init srio
	srio_status = CSL_srioInit (&SrioContext);
	hSrio = CSL_srioOpen (&srioObj, srioNum, &srioParam, &srio_status);

    if (srio_status != CSL_SOK) 
    {
       return ;
    }
	
	Srio_Module_Init();
	memset(srio_master_packet, 0x00, sizeof(TSRIOPacket));
	memset(srio_test_count,0x00,sizeof(srio_test_count));
}


void Srio_Module_Init(void)
{
	Int32 data;
	int srio_timeout;
	int portIndex = 0;
	int cpbIndex = 0;
	int core_count = 8;
	int i;
	int iTimeout,port_ok_no;
	int srio_timeout_count = 20000;
	int CBBSetMask=0;
	data = 0xFFFFFFFF;
	

	CSL_SrioLsuIntrClear (hSrio, data);
	hSrio->regs->GBL_EN = 0;
	hSrio->regs->BLK_ENABLE[0].BLK_EN = 0x0;
	hSrio->regs->BLK_ENABLE[1].BLK_EN = 0x0;
	hSrio->regs->BLK_ENABLE[2].BLK_EN = 0x0;
	hSrio->regs->BLK_ENABLE[3].BLK_EN = 0x0;
	hSrio->regs->BLK_ENABLE[4].BLK_EN = 0x0;
	hSrio->regs->BLK_ENABLE[5].BLK_EN = 0x0;
	hSrio->regs->BLK_ENABLE[6].BLK_EN = 0x0;
	hSrio->regs->BLK_ENABLE[7].BLK_EN = 0x0;
	hSrio->regs->BLK_ENABLE[8].BLK_EN = 0x0;

	// disable PLL enable to disable the SerDes registers
	hSrio->regs->SERDES_CFG_CNTL[0] = 0x0; 
	hSrio->regs->SERDES_CFG_CNTL[1] = 0x0; 
	hSrio->regs->SERDES_CFG_CNTL[2] = 0x0; 
	hSrio->regs->SERDES_CFG_CNTL[3] = 0x0; 

	srio_process_control.srio_process_status = SRIO_TX_PROCESS_STATUS_IDLE;
	srio_process_control.blken = 1;		// // Peripheral enable 
	srio_process_control.port = 0;// init port		
	srio_process_control.srcID = SRIO_MASTER_ID;
	srio_process_control.dstID = SRIO_SLAVE_ID;
	srio_process_control.portmode = PMODE1X;
	srio_process_control.portspeed = SPEED3_125G; // SPEED3_125G  SPEED2_50G   SPEED1_25G  
	srio_process_control.loopback = 0;	//internal looback mode disable	
	srio_process_control.portEnbit = 0;

	Srio_Init(&sriosetup, 1, srio_process_control.port, srio_process_control.srcID, srio_process_control.portmode, srio_process_control.portspeed, srio_process_control.loopback);
	srio_status = CSL_srioHwSetup (hSrio, &sriosetup); // Write config in registers

	if (srio_status != CSL_SOK) 
	{
		printf("SRIO CSL_srioHwSetup Fail\n");
		return ;
	}

	Srio_LSUSetup();                    // Setup LSU

	data =  hSrio->regs->PER_SET_CNTL;
	data = data | 0x01000000;           // writing into the bootcomplete
	hSrio->regs->PER_SET_CNTL = data; 
	if(SystemSetupData.CPBEnabled[1])
	{
		CBBSetMask |= SRIO_PORT0_ENABLE_BIT;
	}
	if(SystemSetupData.CPBEnabled[9])
	{
		CBBSetMask |= SRIO_PORT1_ENABLE_BIT;
	}
	if(SystemSetupData.CPBEnabled[17])
	{
		CBBSetMask |= SRIO_PORT2_ENABLE_BIT;
	}
	if(SystemSetupData.CPBEnabled[25])
	{
		CBBSetMask |= SRIO_PORT3_ENABLE_BIT;
	}
	srio_timeout = Board1MSTmr;

	while(1)
	{
		response.index = i;
		if(!(srio_process_control.portEnbit&(0x1<<response.index))){
			CSL_srioGetHwStatus (hSrio, CSL_SRIO_QUERY_SP_ERR_STAT, &response);
			
			if((response.data&0x2)==0x2)
			{
				srio_process_control.portEnbit |= 0x1<< i;
//				printf("Port %d success\n",response.index);
			}
		}
		if(srio_process_control.portEnbit==CBBSetMask)//0x0F)
		{
			break;
		}
		if(srio_timeout+srio_timeout_count < Board1MSTmr) // 30sec timeout
		{
			ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, 0x25252525, __LINE__, 0, portIndex); 
			break;
		}
		i++;
		if(i > 3) i = 0; 	
	}
		

	if(!(srio_process_control.portEnbit&SRIO_PORT0_ENABLE_BIT))
	{
		portIndex = 0;
		ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, portIndex, 0); 
		
		if(SystemSetupData.CamBootEnabled == 1)		
		{
			NFA_CAMERA_RESET = 0x1;
			Sleep(5000);
			NFA_CAMERA_RESET = 0x0;
			FPGARELOAD = 0x00FA;		
		}
		
		for (cpbIndex = portIndex*core_count ; cpbIndex < (portIndex*core_count)+core_count;cpbIndex++)
		{
			if(SystemSetupData.CPBEnabled[cpbIndex]==1)
			{
				SystemSetupData.CPBEnabled[cpbIndex] = 0;
			}
		}
	}
	else if(!(srio_process_control.portEnbit&SRIO_PORT1_ENABLE_BIT))
	{
		portIndex = 1;
		
		if(SystemSetupData.CamBootEnabled == 1)		
		{
			NFA_CAMERA_RESET = 0x1;
			Sleep(5000);
			NFA_CAMERA_RESET = 0x0;
			FPGARELOAD = 0x00FA;		
		}
		
		ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, portIndex, 0); 
		for (cpbIndex = portIndex*core_count ; cpbIndex < (portIndex*core_count)+core_count;cpbIndex++)
		{
			if(SystemSetupData.CPBEnabled[cpbIndex]==1)
			{
				SystemSetupData.CPBEnabled[cpbIndex] = 0;
			}
		}	
	}
	else if(!(srio_process_control.portEnbit&SRIO_PORT2_ENABLE_BIT))
	{
		portIndex = 2;
		
		if(SystemSetupData.CamBootEnabled == 1)		
		{
			NFA_CAMERA_RESET = 0x1;
			Sleep(5000);
			NFA_CAMERA_RESET = 0x0;
			FPGARELOAD = 0x00FA;		
		}
		
		ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, portIndex, 0); 
		for (cpbIndex = portIndex*core_count ; cpbIndex < (portIndex*core_count)+core_count;cpbIndex++)
		{
			if(SystemSetupData.CPBEnabled[cpbIndex]==1)
			{
				SystemSetupData.CPBEnabled[cpbIndex] = 0;
			}
		}	
	}

	else if(!(srio_process_control.portEnbit&SRIO_PORT3_ENABLE_BIT))
	{
		portIndex = 3;
		
		if(SystemSetupData.CamBootEnabled == 1)		
		{
			NFA_CAMERA_RESET = 0x1;
			Sleep(5000);
			NFA_CAMERA_RESET = 0x0;
			FPGARELOAD = 0x00FA;		
		}
		
		ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, portIndex, 0); 
		for (cpbIndex = portIndex*core_count ; cpbIndex < (portIndex*core_count)+core_count;cpbIndex++)
		{
			if(SystemSetupData.CPBEnabled[cpbIndex]==1)
			{
				SystemSetupData.CPBEnabled[cpbIndex] = 0;
			}
		}	
	}
	ApplySystemSetup();
	Sleep(15000);							//wait 30sec
}

void Request_SRIO_WriteData(unsigned char targetCPB, unsigned int bufferAddress, unsigned int cpbAddress, unsigned int countWord, TSRIOTransferStatus *transferStatus)
{
	CSL_IntcGlobalEnableState 	state;
	int retcode;
//	CSL_intcGlobalDisable(&state);
	srio_lock = 1;
	srio_process_control.TransferStatus = transferStatus;

	srio_process_control.TransferStatus->Status = SRIO_TRANSFER_STATUS_PENDING;
	
	retcode = Srio_ReadWrite((Uint32)bufferAddress, (Uint32)cpbAddress, countWord*4, REQ_NWRITE,((int)targetCPB)/8, srio_process_control.dstID);

	if(retcode)
	{
//       	printf("ERROR: Cannot write srio packet correctly CPB : %d!\r\n",targetCPB); // report error
//       	ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, targetCPB, srio_error_count++); 
		ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, 0, targetCPB);
		SystemSetupData.CPBEnabled[targetCPB] = 0;
		CPBStatus[targetCPB].IsDown = TRUE;
		CPBStatus[targetCPB].Enabled= FALSE;
	}

//	if(srio_complet_isr[srio_process_control.port] == 1)
//	{
		srio_complet_isr[srio_process_control.port] == 0;
		srio_process_control.TransferStatus->Status = SRIO_TRANSFER_STATUS_COMPLETE;
		
//	}
	srio_lock = 0;
//	CSL_intcGlobalEnable(&state);
}

void Request_SRIO_ReadData(unsigned char targetCPB, unsigned int bufferAddress, unsigned int cpbAddress, unsigned int countWord, TSRIOTransferStatus *transferStatus)
{

	CSL_IntcGlobalEnableState 	state;
	int retcode;
//	CSL_intcGlobalDisable(&state);
	srio_lock = 1;
	srio_process_control.TransferStatus = transferStatus;

	srio_process_control.TransferStatus->Status = SRIO_TRANSFER_STATUS_PENDING;
	
	retcode = Srio_ReadWrite((Uint32)bufferAddress, (Uint32)cpbAddress, countWord*4, REQ_NREAD, ((int)targetCPB)/8, srio_process_control.dstID);

	if(retcode)
	{
 //      	printf("ERROR: Cannot write srio packet correctly CPB : %d!\r\n",targetCPB); // report error
//		ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, targetCPB, srio_error_count++); 
		ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_CPB_BOARD_DOWN, __LINE__, 0, targetCPB);
      		SystemSetupData.CPBEnabled[targetCPB] = 0;
		CPBStatus[targetCPB].IsDown = TRUE;
		CPBStatus[targetCPB].Enabled= FALSE;
	}

//	if(srio_complet_isr[srio_process_control.port] == 1)
//	{
		srio_complet_isr[srio_process_control.port] == 0;
		srio_process_control.TransferStatus->Status = SRIO_TRANSFER_STATUS_COMPLETE;	
//	}		
	srio_lock = 0;
//	CSL_intcGlobalEnable(&state);
}

int SRIO_SendData(unsigned short pri_indicator, unsigned int sec_indicator, void *data_address, int elementLength_word, int cpbIndex, int transferKind, int frameCount, int frameIndex, int dstStartPosition)
{
	TQDMARequestUnit qdmaRequestUnit;
	TSRIOHeaderPacket srio_master_header_packet;
	int remain_element_length_word;
	int transfer_length_word;
	int remain_frame_count;
	int transfer_frame_count;
	int max_image_line_word;
	unsigned int current_data_position;
	unsigned int current_src_address;
	unsigned int startTime;
	unsigned int PacketSentTime;
	int bWhile;
	int ImageWidth;
	int framePos;
	int reTryCount;
	int pollingTime;
	unsigned int DMA_Job_End_SW;
	CSL_IntcGlobalEnableState 	state;
	
	srio_master_packet.PRI_Indicator = pri_indicator;
	srio_master_packet.SEC_Indicator = sec_indicator;
	srio_master_header_packet.PRI_Indicator= pri_indicator;
	srio_master_header_packet.SEC_Indicator= sec_indicator;
	remain_frame_count = frameCount;
	current_data_position = dstStartPosition;
	current_src_address = (unsigned int)data_address;
	SRIOTransferStatus.Status = 0;
	remain_element_length_word = elementLength_word;
	srio_process_control.srio_process_status = SRIO_TX_PROCESS_STATUS_READY;
		
	if(sec_indicator == IND_IMAGE_BUFFER_1)
	{
		if(TabletCharacter_SPB.HighResolutionImage)
		{
			max_image_line_word = SYSTEM_CAMERA_HD_WIDTH >> 2;
			ImageWidth = SYSTEM_CAMERA_HD_WIDTH;	
		}
		else
		{
			max_image_line_word = SYSTEM_CAMERA_WIDTH >> 2;
			ImageWidth = SYSTEM_CAMERA_WIDTH;
		}	

	}
	else
	{
		max_image_line_word = SYSTEM_CAMERA_WIDTH_3D >> 2;
		ImageWidth = SYSTEM_CAMERA_WIDTH_3D;
	}
	
	startTime = Board50usTimer;
	errorOccured = 0;
	bWhile = 1;
	reTryCount = 0;
	pollingTime =0;
	while(srio_process_control.srio_process_status!= SRIO_TX_PROCESS_STATUS_SEND_COMPLETE)	
	{	
/*
		if(startTime+2000 < Board50usTimer)//5ms timeout
		{
			errorOccured = ERROR_CODE_SRIO_TX_TIMEOUT;
			bWhile = 0;
			return FALSE;
		}
*/
		switch(srio_process_control.srio_process_status)
		{
			case SRIO_TX_PROCESS_STATUS_READY:
				if(transferKind==SRIO_TRANSFER_KIND_IMAGE)
				{
					srio_process_control.srio_process_status = SRIO_TX_PROCESS_STATUS_MAKE_IMAGE_PACKET;
				}
				else
				{
					srio_process_control.srio_process_status = SRIO_TX_PROCESS_STATUS_MAKE_DATA_PACKET;
				}
				break;
			case SRIO_TX_PROCESS_STATUS_MAKE_IMAGE_PACKET:
				if(remain_frame_count ==0)
				{
					srio_process_control.srio_process_status = SRIO_TX_PROCESS_STATUS_SEND_COMPLETE;
				}
				else
				{
					// calc size
					transfer_length_word = 0;
			 		transfer_frame_count = 0;
			 		while(1)
					{
						if(transfer_length_word + elementLength_word <  SRIO_PACKET_DATA_SIZE_WORD)
						{
							transfer_length_word += elementLength_word;
							transfer_frame_count++;

							remain_frame_count--;

							if(remain_frame_count == 0)
								break;
						}
						else
						{
							break;
						}
					}

					// set packet data					
					srio_master_packet.SRIO_State = SRIO_STATE_SEND_REQUEST;
//					srio_master_header_packet.SRIO_State = SRIO_STATE_SEND_REQUEST;
					srio_master_packet.DataLength_Word = transfer_length_word;
					srio_master_packet.Address = current_data_position;
					srio_master_packet.FrameCount = transfer_frame_count;
					srio_master_packet.CompleteSW = 0;
		
					// copy data to packet				
					qdmaRequestUnit.Opt = MakeDMAOpt(DMA_ESIZE_32BIT, EDMA_CFG_NO_INC_NO_INC);
					qdmaRequestUnit.Cnt = elementLength_word;
					qdmaRequestUnit.Idx = 0;
					qdmaRequestUnit.Fin = &DMA_Job_End_SW;

					DMA_Job_End_SW = 1; // 첫번째 데이터는 무조건 END 상태로 시작
					for(framePos = 0; framePos < transfer_frame_count; framePos++)
					{
						DMA_Job_End_SW = 0;
												
						qdmaRequestUnit.Src = (Uint32) current_src_address;
						qdmaRequestUnit.Dst = (Uint32) srio_master_packet.Data + ((elementLength_word << 2) * framePos);						
						QDMA_Request(&qdmaRequestUnit);
						PacketSentTime = Board50usTimer;
						while (!DMA_Job_End_SW)
						{
							if(Board50usTimer - PacketSentTime > 50)
							{
								ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_OVERFLOW, __LINE__, 0, 0);
								break;
							}
						}
						current_src_address += (max_image_line_word << 2);
						current_data_position += (max_image_line_word << 2);
					}

					PacketSentTime = Board50usTimer;
					srio_process_control.srio_process_status = SRIO_TX_PROCESS_STATUS_MAKE_CHECKSUM;			 	
				}			
				break;
			case SRIO_TX_PROCESS_STATUS_MAKE_DATA_PACKET:
				
				if(remain_frame_count ==0)
				{
					srio_process_control.srio_process_status = SRIO_TX_PROCESS_STATUS_MAKE_LAST_PACKET;
				}
				else
				{
					if (remain_element_length_word < SRIO_PACKET_DATA_SIZE_WORD)
			 		{
			 			transfer_length_word = remain_element_length_word;
			 		}
			 		else
			 		{
			 			transfer_length_word = SRIO_PACKET_DATA_SIZE_WORD;
			 		}
					// set packet data
					srio_master_packet.SRIO_State = SRIO_STATE_SEND_REQUEST;
//					srio_master_header_packet.SRIO_State = SRIO_STATE_SEND_REQUEST;					
					srio_master_packet.DataLength_Word = transfer_length_word;
					srio_master_packet.Address = current_data_position;
					srio_master_packet.FrameCount = frameCount;
					srio_master_packet.CompleteSW = 0;
					// copy data to packet				
					DMA_Job_End_SW= 0;

					qdmaRequestUnit.Opt = MakeDMAOpt(DMA_ESIZE_32BIT, EDMA_CFG_NO_INC_NO_INC);
					qdmaRequestUnit.Src = (Uint32) current_src_address;
					qdmaRequestUnit.Cnt = transfer_length_word;
					qdmaRequestUnit.Dst = (Uint32) srio_master_packet.Data;
					qdmaRequestUnit.Idx = 0;
					qdmaRequestUnit.Fin = &DMA_Job_End_SW;
					QDMA_Request(&qdmaRequestUnit);


					// proceed pointer
			 		current_data_position += transfer_length_word * 4;
			 		current_src_address += transfer_length_word * 4;
			 		remain_element_length_word -= transfer_length_word;
					
					if (remain_element_length_word == 0)
					{
				 		current_data_position += frameIndex;
				 		current_src_address += frameIndex;						
						remain_element_length_word = elementLength_word;
						remain_frame_count--;
					}
					PacketSentTime = Board50usTimer;
					srio_process_control.srio_process_status = SRIO_TX_PROCESS_STATUS_MAKE_CHECKSUM;			 	
				}			
				break;				
			case SRIO_TX_PROCESS_STATUS_MAKE_CHECKSUM:
				if(DMA_Job_End_SW ==1)
				{
					srio_master_packet.SPB_CheckSum = CheckSum((unsigned int *)&srio_master_packet.PRI_Indicator, srio_master_packet.DataLength_Word + SRIO_PACKET_HEADER_SIZE_WORD - 3);// testCheckSum((unsigned int *)&srio_master_packet.PRI_Indicator, srio_master_packet.DataLength_Word + SRIO_PACKET_HEADER_SIZE_WORD - 3);
					srio_process_control.srio_process_status = SRIO_TX_PROCESS_STATUS_WRITE_PACKET;	
				}
				else
				{
					if( PacketSentTime+200 < Board50usTimer)
					{	
						ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_CHECKSUM, __LINE__, srio_master_header_packet.SRIO_State, srio_error_count++); 
						errorOccured = ERROR_CODE_SRIO_TX_MAKE_PACKET_TIMEOUT;
						return FALSE;
					}					
				}
				srio_test_count[0]++;
				break;				
			case SRIO_TX_PROCESS_STATUS_WRITE_PACKET:
				{
					srio_master_packet.CompleteSW = 0;
					Request_SRIO_WriteData(cpbIndex, (Uint32)&srio_master_packet, CPBHWInfo[cpbIndex].CPBBuffer1Addr, transfer_length_word+SRIO_PACKET_HEADER_SIZE_WORD,&SRIOTransferStatus);
					while(SRIOTransferStatus.Status != SRIO_TRANSFER_STATUS_COMPLETE );

					srio_master_packet.CompleteSW= SRIO_TRANSFER_COMPLETE_CODE;
					Request_SRIO_WriteData(cpbIndex, (Uint32)&srio_master_packet.CompleteSW, CPBHWInfo[cpbIndex].CPBBuffer1Addr+4, 1, &SRIOTransferStatus);
					while(SRIOTransferStatus.Status != SRIO_TRANSFER_STATUS_COMPLETE );

					srio_process_control.srio_process_status = SRIO_TX_PROCESS_STATUS_READ_PACKET;	
//				
				}
				break;
			case SRIO_TX_PROCESS_STATUS_READ_PACKET:
				if(SRIOTransferStatus.Status == SRIO_TRANSFER_STATUS_COMPLETE)// && pollingTime+1 < Board50usTimer)
				{
					Request_SRIO_ReadData(cpbIndex, (Uint32)&srio_master_header_packet, CPBHWInfo[cpbIndex].CPBBuffer1Addr, SRIO_PACKET_HEADER_SIZE_WORD, &SRIOTransferStatus);
					srio_test_count[3]++;
					if(srio_master_header_packet.SRIO_State == SRIO_STATE_READ_COMPLETE)
					{
						srio_process_control.srio_process_status = SRIO_TX_PROCESS_STATUS_READY;	
						break;
					}
					else if(srio_master_header_packet.SRIO_State == SRIO_STATE_READ_ERR_CHECKSUM)
					{
						ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_CHECKSUM, __LINE__, reTryCount, transferKind); 
						ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_CHECKSUM, __LINE__, srio_master_packet.SPB_CheckSum, srio_master_header_packet.SPB_CheckSum); 
						ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_CHECKSUM, __LINE__, remain_frame_count, transfer_length_word); 
						errorOccured = srio_master_header_packet.SRIO_State;
						return FALSE;			
					}
					if(Board50usTimer - PacketSentTime > 20000)
					{	
//						ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_CHECKSUM, __LINE__, srio_master_header_packet.SRIO_State, srio_master_packet.SEC_Indicator); 
						errorOccured = srio_master_header_packet.SRIO_State;
						return FALSE;
					}
				}
				else 
					{
					srio_test_count[1]++;
						if(Board50usTimer - PacketSentTime > 10000)
						{	
//							if(reTryCount < SRIO_TRANSFER_RETRY_COUNT){
//								srio_process_control.srio_process_status = SRIO_TX_PROCESS_STATUS_MAKE_CHECKSUM;
//								reTryCount++;
//								break;
//							}
//							else
//							{
								ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_CHECKSUM, __LINE__, srio_master_header_packet.SRIO_State,  srio_master_header_packet.SEC_Indicator); 
								errorOccured = srio_master_header_packet.SRIO_State;
								return FALSE;
//							}
						}					
					}
				break;
			case SRIO_TX_PROCESS_STATUS_MAKE_LAST_PACKET:
				{
					srio_master_header_packet.CompleteSW= SRIO_TRANSFER_COMPLETE_CODE;
					srio_master_header_packet.SRIO_State= SRIO_STATE_SEND_LAST;
					srio_master_header_packet.Address= 0;
					srio_master_header_packet.DataLength_Word= 0;
					srio_master_header_packet.FrameCount= 0;	
					reTryCount = 0;
					srio_process_control.srio_process_status = SRIO_TX_PROCESS_STATUS_SEND_LAST_PACKET;
				}
			case SRIO_TX_PROCESS_STATUS_SEND_LAST_PACKET:
				{
					srio_master_header_packet.SPB_CheckSum = CheckSum((unsigned int *) &srio_master_header_packet.PRI_Indicator, SRIO_PACKET_HEADER_SIZE_WORD - 3);
					Request_SRIO_WriteData(cpbIndex, (Uint32)&srio_master_header_packet, CPBHWInfo[cpbIndex].CPBBuffer1Addr, SRIO_PACKET_HEADER_SIZE_WORD, &SRIOTransferStatus);
					PacketSentTime = Board50usTimer;
					srio_process_control.srio_process_status = SRIO_TX_PROCESS_STATUS_READ_LAST_PACKET;
				}
				break;
			case SRIO_TX_PROCESS_STATUS_READ_LAST_PACKET:
				if(SRIOTransferStatus.Status ==SRIO_TRANSFER_STATUS_COMPLETE)
				{
					Request_SRIO_ReadData(cpbIndex, (Uint32)&srio_master_header_packet, CPBHWInfo[cpbIndex].CPBBuffer1Addr, SRIO_PACKET_HEADER_SIZE_WORD, &SRIOTransferStatus);
					if(srio_master_header_packet.SRIO_State == SRIO_STATE_COMPLETE_LAST)
					{
						srio_process_control.srio_process_status = SRIO_TX_PROCESS_STATUS_SEND_COMPLETE;	
						break;
					}
					else if(Board50usTimer - PacketSentTime > 1000)
					{	
						ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_CHECKSUM, __LINE__, srio_master_header_packet.SRIO_State, srio_error_count++); 
						errorOccured = srio_master_header_packet.SRIO_State;
						return FALSE;
					}					
				}
				else
				{
					if(Board50usTimer - PacketSentTime > 2000)
					{	
						ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_CHECKSUM, __LINE__, srio_master_header_packet.SRIO_State, srio_error_count++); 
						errorOccured = ERROR_CODE_SRIO_TX_WRITE_TIMEOUT;
						return FALSE;
					}
				}
				break;
		}
	}
	return TRUE;
}

int SRIO_ReceiveData(unsigned short pri_indicator, unsigned int sec_indicator, void *data_address, unsigned int data_size, int cpbIndex)
{
	TSRIOHeaderPacket srio_master_header_packet;
	int remain_data_size, transfer_size_int;
	unsigned int current_data_position;

	int PacketRetryCount;
	unsigned int PacketSentTime;

	int SRIOBufferState;	// buffer state
	int currentBuffer;
	TQDMARequestUnit qdmaRequestUnit;
	unsigned int DMA_Job_End_SW;	// dma complete switch

	int reTryCount;
	int DataReceiveTryTime;
	
	if (data_size == 0) return TRUE;

	SRIOTransferStatus.Status = 0;
	srio_process_control.srio_process_status = SRIO_RX_PROCESS_STATUS_MAKE_HEADER_PACKET;
	current_data_position = 0;
	remain_data_size = (data_size + 3) / 4 * 4;

	// set packet's indicator here
	srio_master_header_packet.PRI_Indicator = pri_indicator; 
	srio_master_header_packet.SEC_Indicator= sec_indicator; 
	errorOccured = 0;
	reTryCount = 0;
	DataReceiveTryTime = Board50usTimer;
	
	while(srio_process_control.srio_process_status!= SRIO_RX_PROCESS_STATUS_RECEIVE_COMPLETE)	
	{			
/*
		if(DataReceiveTryTime+2000 < Board50usTimer)//5ms timeout
		{
			errorOccured = ERROR_CODE_SRIO_RX_TIMEOUT;
			return FALSE;
		}
*/
		switch(srio_process_control.srio_process_status)
		{
			case SRIO_RX_PROCESS_STATUS_MAKE_HEADER_PACKET:
				if (remain_data_size == 0)
				{
					srio_process_control.srio_process_status= SRIO_RX_PROCESS_STATUS_RECEIVE_COMPLETE;
				}
				else
				{
					if (remain_data_size < SRIO_PACKET_DATA_SIZE_WORD * 4)
			 		{
			 			transfer_size_int = remain_data_size / 4;
			 		}
			 		else
			 		{
			 			transfer_size_int = SRIO_PACKET_DATA_SIZE_WORD;
			 		}

					srio_master_header_packet.DataLength_Word = transfer_size_int;
					srio_master_header_packet.Address = current_data_position;
					srio_master_header_packet.SRIO_State = SRIO_STATE_RECEIVE_REQUEST;
					srio_master_header_packet.FrameCount = 0;
					srio_master_header_packet.SPB_CheckSum = 0;//CheckSum((unsigned int *) &srio_master_header_packet.PRI_Indicator, srio_master_header_packet.DataLength_Word+SRIO_PACKET_HEADER_SIZE_WORD - 3);	
					srio_master_header_packet.CompleteSW= SRIO_TRANSFER_COMPLETE_CODE;
					srio_process_control.srio_process_status= SRIO_RX_PROCESS_STATUS_WRITE_HEADER;
					current_data_position+= transfer_size_int*4;
					remain_data_size-=transfer_size_int*4;
				}
				break;
			case SRIO_RX_PROCESS_STATUS_WRITE_HEADER:
				{
					Request_SRIO_WriteData(cpbIndex, (Uint32)&srio_master_header_packet, CPBHWInfo[cpbIndex].CPBBuffer1Addr, SRIO_PACKET_HEADER_SIZE_WORD, &SRIOTransferStatus);
					srio_process_control.srio_process_status = SRIO_RX_PROCESS_STATUS_READ_HEADER;	
					PacketSentTime = Board50usTimer;	
				}
				break;
			case SRIO_RX_PROCESS_STATUS_READ_HEADER:
				if(SRIOTransferStatus.Status ==SRIO_TRANSFER_STATUS_COMPLETE)
				{
					Request_SRIO_ReadData(cpbIndex, (Uint32)&srio_master_header_packet, CPBHWInfo[cpbIndex].CPBBuffer1Addr, SRIO_PACKET_HEADER_SIZE_WORD, &SRIOTransferStatus);
					if(srio_master_header_packet.SRIO_State == SRIO_STATE_WRITE_COMPLETE)
					{
						srio_process_control.srio_process_status = SRIO_RX_PROCESS_STATUS_READ_DATA;	
					}
					else
					{	
						if(Board50usTimer - PacketSentTime > 1000)
						{	
							errorOccured = srio_master_header_packet.SRIO_State;
							ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_CHECKSUM, __LINE__, srio_master_header_packet.SRIO_State, srio_error_count++); 

							return FALSE;
						}						
					}			
				}
				else
				{
					if(Board50usTimer - PacketSentTime > 2000)
					{	
						errorOccured = ERROR_CODE_SRIO_TX_READ_TIMEOUT;
						return FALSE;
					}
				}
				break;
			case SRIO_RX_PROCESS_STATUS_READ_DATA:
				if(SRIOTransferStatus.Status ==SRIO_TRANSFER_STATUS_COMPLETE)
				{
					Request_SRIO_ReadData(cpbIndex, (Uint32)&srio_master_packet, CPBHWInfo[cpbIndex].CPBBuffer1Addr, srio_master_header_packet.DataLength_Word + SRIO_PACKET_HEADER_SIZE_WORD, &SRIOTransferStatus);
					if(srio_master_header_packet.SRIO_State == SRIO_STATE_WRITE_COMPLETE)
					{
						srio_process_control.srio_process_status = SRIO_RX_PROCESS_STATUS_CHECKSUM;	
					}
					else 
					{
						if(Board50usTimer - PacketSentTime > 100)
						{	
							ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_CHECKSUM, __LINE__, srio_master_header_packet.SRIO_State, srio_error_count++); 
							errorOccured = srio_master_header_packet.SRIO_State;
							return FALSE;
						}

						if(reTryCount < SRIO_TRANSFER_RETRY_COUNT){
							srio_process_control.srio_process_status = SRIO_RX_PROCESS_STATUS_WRITE_HEADER;
							reTryCount++;
							ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL,	ERROR_CODE_HPI_RECEIVE,	__LINE__, srio_master_header_packet.SRIO_State, cpbIndex);
							return FALSE;
						}	
					}					
				}					
				break;
			case SRIO_RX_PROCESS_STATUS_CHECKSUM:
				if(SRIOTransferStatus.Status ==SRIO_TRANSFER_STATUS_COMPLETE)
				{
					srio_process_control.srio_process_status = SRIO_RX_PROCESS_STATUS_COPY_DATA;	
				}
				break;
			case SRIO_RX_PROCESS_STATUS_COPY_DATA:
				{
					DMA_Job_End_SW = 0;
					qdmaRequestUnit.Opt = MakeDMAOpt(DMA_ESIZE_32BIT, EDMA_CFG_NO_INC_NO_INC);
					qdmaRequestUnit.Src = (Uint32) srio_master_packet.Data;
					qdmaRequestUnit.Cnt = srio_master_packet.DataLength_Word;
					qdmaRequestUnit.Dst = (Uint32) ((unsigned char *)data_address + srio_master_packet.Address);
					qdmaRequestUnit.Idx = 0;
					qdmaRequestUnit.Fin = &DMA_Job_End_SW;
					QDMA_Request(&qdmaRequestUnit);
					PacketSentTime = Board50usTimer;
					srio_process_control.srio_process_status = SRIO_RX_PROCESS_STATUS_COPY_COMPLET;	
				}
				break;
			case SRIO_RX_PROCESS_STATUS_COPY_COMPLET:
				if (DMA_Job_End_SW == 1)
				{
					srio_process_control.srio_process_status = SRIO_RX_PROCESS_STATUS_MAKE_HEADER_PACKET;	
				}
				else
				{
					if(Board50usTimer - PacketSentTime > 500)
					{	
						errorOccured = srio_master_header_packet.SRIO_State;
						ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL,	ERROR_CODE_HPI_RECEIVE,	__LINE__, srio_master_header_packet.SRIO_State, cpbIndex);
						return FALSE;
					}

				}
				break;				
		}
	}
	return TRUE;
}


unsigned int testCheckSum(unsigned int* src, unsigned int len)
{
	register unsigned int sum = 0;
	while (len--)
	{
		sum += *src++;
	}
	return sum;
}
//---------------------------------------------------------------------------

