#include "data_transfer.h"
#include "DMAScheduler.h"
#include "image_control.h"
#include "data_indicator.h"
#include "com.h"
#include "timer.h"
#include "HPI_Controller.h"
#include "Srio_master.h"
#include <csl_intc.h>
#include <csl_intcAux.h>
#include <csl_edma2.h>
#define SDRAM1_ADDR							(unsigned char *)0x80000000
#define CPB_IMAGE_BUFFER_ADDRESS			0xE00E8080



// for dma copy
#define COPY_BLOCK_SIZE								1024
#pragma DATA_ALIGN(copy_temp_buffer1, 8);
#pragma DATA_ALIGN(copy_temp_buffer2, 8);
unsigned char copy_temp_buffer1[COPY_BLOCK_SIZE];
unsigned char copy_temp_buffer2[COPY_BLOCK_SIZE];


//#define HPI_PACKET_RETRY_COUNT			3
#define HPI_PACKET_RETRY_COUNT				5
#define HPI_PACKET_READ_COUNT				3
extern CSL_Edma3Handle 				hNFAEdma;
#define HPI_BUFFER_STATE_LOAD				0

#pragma DATA_ALIGN(HPIImagePacket, 8);
#pragma DATA_ALIGN(ReadImagePacket, 8);
#pragma DATA_ALIGN(HPIPacket, 8);
#pragma DATA_ALIGN(HPIHeaderPacket, 8);
#pragma DATA_ALIGN(DSPInt_Status, 8);
THPIImagePacket HPIImagePacket[4];		// double buffer
THPIImagePacket ReadImagePacket;
THPIPacket HPIPacket[2];				// double buffer
THPIHeaderPacket HPIHeaderPacket[2];		// double buffer
unsigned int DSPInt_Status[8];

THPITransferStatus HPITransferStatus[4];		// double buffer
THPIControlStatus HPIControlStatus[2];		// double buffer

#pragma DATA_ALIGN(clear_value, 8);
unsigned int clear_value[MAX_SDRAM_COPY_SIZE / 4];

extern unsigned char HPIStatus;
int hpi_current_time;

unsigned char HPI_Transfer_Complete_SW = 0;
int ImageSendErrorCount = 0;

#define TRANSFER_STEP_REQUEST_ADDRESS		1
#define TRANSFER_STEP_OBTAIN_ADDRESS		2
#define TRANSFER_STEP_SEND_CHECKSUM			3
#define TRANSFER_STEP_SEND_DATA_RECEIVED	4
#define TRANSFER_STEP_COMPLETE				5
#define TRANSFER_STEP_RETRY					6
#define TRANSFER_STEP_ERROR					0xFFFF

#pragma DATA_ALIGN(HPIStat, 8)
THPIStat HPIStat;

#define MAX_DMA_JOB_COUNT		16
#define DMA_TABLE_SIZE			16

#define IMG_CHECK_COUNT	8
#define SMALL_SIZE_HPI_COM_TIMEOUT	200		//200ms
#define LARGE_SIZE_HPI_COM_TIMEOUT	3000	//3000ms
#define DMA_ACTIVE_TIME_OUT	5

#define min(x, y) ((x) < (y) ? (x) : (y))

volatile unsigned int DMA_Copy_Complete_SW = 0;

unsigned int PartialCheckSum(unsigned char* src, unsigned int len, unsigned int size);
int HPI_SendData_Image_Streaming(unsigned short pri_indicator, unsigned int sec_indicator, void *data_address, int elementLength_word, int cpbIndex, int transferKind, int frameCount, int frameIndex, int dstStartPosition, void *zero_Address, int left, int top, int width, int height);
void DataTransferInit()
{
	HPIStat.TotalSendWord = 0;
	HPIStat.TotalErrorWord = 0;
	HPIStat.ActualTransferDataWord = 0;
	HPIStat.TotalSendCount = 0;
	HPIStat.AckPacketCount = 0;
	HPIStat.ErrPacketCount = 0;
	HPIStat.RetryCount = 0;
	HPIStat.ReadErrorCount = 0;
	HPIStat.LazeInterruptCount = 0;
	HPIStat.CritErrorCount = 0;
	HPIStat.RetryExceededCount = 0;
	HPIStat.SendTime = 0;
	HPIStat.IntStateRetryCount = 0;
	HPIStat.CPBErrorPacketCount = 0;
	HPIStat.CPBTOPacketCount = 0;
	HPIStat.ChecksumErrorPacketCount = 0;
	
	HPI_Controller_Init();
}

void Request_DMA_Linear_Copy_Direct(void *dst_address, void *src_address, int size, unsigned int esize)
{
	unsigned char *src_addr, *dst_addr;
	int remain_word_cnt = (size >> DMA_SHIFT(esize));
	int max_transfer_word_cnt = (MAX_SDRAM_COPY_SIZE >> DMA_SHIFT(esize));
	int copy_cnt;
	TQDMARequestUnit qdmaRequestUnit;
	volatile unsigned int qdmaFin;
	volatile unsigned int checkStartTime;

	src_addr = (unsigned char *) src_address;
	dst_addr = (unsigned char *) dst_address;
	while(remain_word_cnt)
	{
		if (remain_word_cnt < max_transfer_word_cnt)
		{
			copy_cnt = remain_word_cnt;
		}
		else
		{
			copy_cnt = max_transfer_word_cnt;
		}
		qdmaFin = 0;
		qdmaRequestUnit.Opt = MakeDMAOpt(esize, EDMA_CFG_NO_INC_NO_INC);
		qdmaRequestUnit.Src = (Uint32)src_addr;
		qdmaRequestUnit.Cnt = copy_cnt;
		qdmaRequestUnit.Dst = (Uint32)dst_addr;
		qdmaRequestUnit.Idx = 0;
		qdmaRequestUnit.Fin = &qdmaFin;
		QDMA_Request(&qdmaRequestUnit);
		//checkStartTime = 100;
		checkStartTime = Board50usTimer;
		while (!qdmaFin)
		{
			if(Board50usTimer - checkStartTime > 10)
			{
				ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_OVERFLOW, __LINE__, copy_cnt, 0);
				break;
			}
		}
		src_addr += (copy_cnt << DMA_SHIFT(esize));
		dst_addr += (copy_cnt << DMA_SHIFT(esize));
		remain_word_cnt -= copy_cnt;
	}	
}

void Request_DMA_Linear_Copy_Indirect(void *dst_address, void *src_address, int size, unsigned int esize)
{
	unsigned char *src_addr, *dst_addr;
	int remain_word_cnt = (size >> DMA_SHIFT(esize));
	int max_transfer_word_cnt = (COPY_BLOCK_SIZE >> DMA_SHIFT(esize));
	int copy_cnt;
	TQDMARequestUnit qdmaRequestUnit;
	volatile unsigned int qdmaFin;
	volatile unsigned int checkStartTime;

	src_addr = (unsigned char *) src_address;
	dst_addr = (unsigned char *) dst_address;

 	while (remain_word_cnt)
 	{
		if (remain_word_cnt < max_transfer_word_cnt)
		{
			copy_cnt = remain_word_cnt;
		}
		else
		{
			copy_cnt = max_transfer_word_cnt;
		}

		qdmaFin = 0;
		qdmaRequestUnit.Opt = MakeDMAOpt(esize, EDMA_CFG_NO_INC_NO_INC);
		qdmaRequestUnit.Src = (Uint32)src_addr;
		qdmaRequestUnit.Cnt = copy_cnt;
		qdmaRequestUnit.Dst = (Uint32)copy_temp_buffer1;
		qdmaRequestUnit.Idx = 0;
		qdmaRequestUnit.Fin = &qdmaFin;
		QDMA_Request(&qdmaRequestUnit);
		checkStartTime = Board50usTimer;
		while (!qdmaFin)
		{
			if(Board50usTimer - checkStartTime > 10)
			{
				ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_OVERFLOW, __LINE__, copy_cnt, 0);
				break;
			}
		}
		qdmaFin = 0;
		qdmaRequestUnit.Opt = MakeDMAOpt(esize, EDMA_CFG_NO_INC_NO_INC);
		qdmaRequestUnit.Src = (Uint32)copy_temp_buffer1;
		qdmaRequestUnit.Cnt = copy_cnt;
		qdmaRequestUnit.Dst = (Uint32)dst_addr;
		qdmaRequestUnit.Idx = 0;
		qdmaRequestUnit.Fin = &qdmaFin;
		QDMA_Request(&qdmaRequestUnit);
		checkStartTime = Board50usTimer;
		while (!qdmaFin)
		{
			if(Board50usTimer - checkStartTime > 10)
			{
				ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_OVERFLOW, __LINE__, copy_cnt, 0);
				break;
			}
		}
		src_addr += (copy_cnt << DMA_SHIFT(esize));
		dst_addr += (copy_cnt << DMA_SHIFT(esize));
		remain_word_cnt -= copy_cnt;
 	} 	
}

void Request_CopyData(void *dst_address, void *src_address, int size)
{
	unsigned int srcESize;
	unsigned int dstESize;
	unsigned int countESize;
	unsigned int transferESize;
	unsigned int CopySDR2SDR = FALSE;
	// data_address ０伊０見 AＤ∮c
	if ((unsigned int)src_address >= (unsigned int)SDRAM1_ADDR)	// SDRAM ０伊０見AI╱e
	{
		if ((unsigned int)dst_address >= (unsigned int)SDRAM1_ADDR)  // SDR -> SDR
		{
			CopySDR2SDR = TRUE;
		}
	}

	// analyze element size(alignment of address and size)
	if (((unsigned int)src_address & 0x03) == 0) // src is 4-byte aligned
	{
		srcESize = DMA_ESIZE_32BIT;
	}
	else if (((unsigned int)src_address & 0x01) == 0) // src is 2-byte aligned
	{
		srcESize = DMA_ESIZE_16BIT;
	}
	else
	{
		srcESize = DMA_ESIZE_8BIT;
	}

	if (((unsigned int)dst_address & 0x03) == 0) // dst is 4-byte aligned
	{
		dstESize = DMA_ESIZE_32BIT;
	}
	else if (((unsigned int)dst_address & 0x01) == 0) // dst is 2-byte aligned
	{
		dstESize = DMA_ESIZE_16BIT;
	}
	else
	{
		dstESize = DMA_ESIZE_8BIT;
	}

	if (((unsigned int)size & 0x03) == 0) // size is 4-byte aligned
	{
		countESize = DMA_ESIZE_32BIT;
	}
	else if (((unsigned int)size & 0x01) == 0) // size is 2-byte aligned
	{
		countESize = DMA_ESIZE_16BIT;
	}
	else
	{
		countESize = DMA_ESIZE_8BIT;
	}

	transferESize = min(min(srcESize, dstESize), countESize);

	if (CopySDR2SDR)
	{
		Request_DMA_Linear_Copy_Indirect(dst_address, src_address, size, transferESize);
	}
	else
	{
		Request_DMA_Linear_Copy_Direct(dst_address, src_address, size, transferESize);
	}
}

void Request_ClearData_Aligned(void *dst_address, unsigned int fill_value, int size)
{
	int clear_size_int;
	int m;
	unsigned int *dst_addr;
	volatile unsigned int qdmaFin;
	unsigned int checkStartTime;

	int remain_size_int = size / 4;	
	TQDMARequestUnit qdmaRequestUnit;

	dst_addr = (unsigned int *) dst_address;
	
	for(m = 0; m < MAX_SDRAM_COPY_SIZE / 4; m++)
	{
		clear_value[m] = fill_value;
	}

	while(remain_size_int)
	{
		if (remain_size_int < MAX_SDRAM_COPY_SIZE / 4)
		{
			clear_size_int = remain_size_int;
		}
		else
		{
			clear_size_int = MAX_SDRAM_COPY_SIZE / 4;
		}

		qdmaFin = 0;
		qdmaRequestUnit.Opt = MakeDMAOpt(DMA_ESIZE_32BIT, EDMA_CFG_NO_NONE_NO_INC);
		qdmaRequestUnit.Src = (Uint32)clear_value;
		qdmaRequestUnit.Cnt = clear_size_int;
		qdmaRequestUnit.Dst = (Uint32)dst_addr;
		qdmaRequestUnit.Idx = 0;
		qdmaRequestUnit.Fin = &qdmaFin;
		QDMA_Request(&qdmaRequestUnit);		
		
		checkStartTime = Board50usTimer;
		while (!qdmaFin)
		{
			if(Board50usTimer - checkStartTime > 10)
			{
				ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_OVERFLOW, __LINE__, clear_size_int, 0);
				break;
			}
		}

		dst_addr += clear_size_int;
		remain_size_int -= clear_size_int;
	}
}

void Request_ImageScaleConversion(void *src_address, void *dst_address, int width, int height)
{
	int m;
	unsigned char *dst_addr;
	unsigned char *src_addr;
	volatile unsigned int qdmaFin;
	unsigned int checkStartTime;
	int current_size;
	int bindSize;
	int yPositionCount;

	TQDMARequestUnit qdmaRequestUnit;
	int remain_size_int = width * height;	

	dst_addr = (unsigned char *) dst_address;
	src_addr = (unsigned char *) src_address;

	if(width == SYSTEM_CAMERA_WIDTH)
	{
		bindSize = 4; // 640 Scale
	}
	else
	{
		bindSize = 8; // 1280 Scale
	}
	
	yPositionCount = 0;

	while(remain_size_int)
	{
		if (remain_size_int < width)
		{
			current_size = remain_size_int;
		}
		else
		{
			current_size = width;
		}

		if(yPositionCount % bindSize == 0)
		{
			qdmaFin = 0;
			qdmaRequestUnit.Opt = MakeDMAOpt(DMA_ESIZE_8BIT, EDMA_CFG_NO_NONE_NO_INC);
			qdmaRequestUnit.Src = (Uint32)src_addr;
			qdmaRequestUnit.Cnt = current_size;
			qdmaRequestUnit.Dst = (Uint32)dst_addr;
			qdmaRequestUnit.Idx = 0;
			qdmaRequestUnit.Fin = &qdmaFin;
			QDMA_Request_ScaleConversion(&qdmaRequestUnit, bindSize);		
			
			checkStartTime = Board50usTimer;
			while (!qdmaFin)
			{
				if(Board50usTimer - checkStartTime > 10)
				{
					ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_OVERFLOW, __LINE__, current_size, 0);
					break;
				}
			}

			dst_addr += current_size / bindSize;
		}

		src_addr += current_size;
		remain_size_int -= current_size;
		yPositionCount++;
	}
}

//---------------------------------------------------------------------------

//-------------------------------------------
// receive data
//-------------------------------------------
int HPI_ReceiveData(unsigned short pri_indicator, unsigned int sec_indicator, void *data_address, unsigned int data_size, int cpbIndex)
{
	int remain_data_size, transfer_size_int;
	unsigned int current_data_position;

	int PacketRetryCount[2];
	unsigned int PacketSentTime[2];

	int HPIBufferState[2];	// buffer state
	int currentBuffer;

	unsigned int CPBBufferAddress[2];		// buffer address in cpb
	TQDMARequestUnit qdmaRequestUnit[2];
	unsigned int DMA_Job_End_SW[2];	// dma complete switch

	int errorOccured;

	int Int_Lock = 0;
	int Int_Buffer = 0;

	int totalPacketCount = 0;
	int totalPacketCount_Buffer1 = 0;
	int totalPacketCount_Buffer2 = 0;
	int successPacketCount = 0;
	int errorPacketCount = 0;
	int lazeInterruptCount = 0;
	int timeOutCount = 0;
	int bWhile;
	unsigned int DataReceiveTryTime;
	unsigned int maxDataRec_timeout;

	if (data_size == 0) return 1;

	CPBBufferAddress[0] = CPBHWInfo[cpbIndex].CPBBuffer1Addr;
	CPBBufferAddress[1] = CPBHWInfo[cpbIndex].CPBBuffer2Addr;

	HPIBufferState[0] = 0;
	HPIBufferState[1] = 0;
	HPITransferStatus[0].Status = 0;
	HPITransferStatus[1].Status = 0;
	PacketRetryCount[0] = 0;
	PacketRetryCount[1] = 0;

	currentBuffer = 0;

	current_data_position = 0;
	remain_data_size = (data_size + 3) / 4 * 4;

	// set packet's indicator here
	HPIHeaderPacket[0].PRI_Indicator = pri_indicator; 
	HPIHeaderPacket[0].SEC_Indicator = sec_indicator;
	HPIHeaderPacket[1].PRI_Indicator = pri_indicator; 
	HPIHeaderPacket[1].SEC_Indicator = sec_indicator;
	errorOccured = 0;

	if(data_size < 1024) // 1k
		maxDataRec_timeout = SMALL_SIZE_HPI_COM_TIMEOUT; // 20ms
	else
		maxDataRec_timeout = LARGE_SIZE_HPI_COM_TIMEOUT; // 2000ms
	
	DataReceiveTryTime = Board1MSTmr;

	while (1)
	{		
		if(Board1MSTmr - DataReceiveTryTime > maxDataRec_timeout)
		{
			errorOccured = 1;
			break;	
		}		

		if (HPIBufferState[currentBuffer] == 20)	// check cpb state
		{
			if(HPIStatus == 0)
			{
				Request_HPI_PollingInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
				HPIBufferState[currentBuffer] = 21;
			}
		}
		else if (HPIBufferState[currentBuffer] == 21)
		{
			if (HPIControlStatus[currentBuffer].Status == HPI_CONTROL_STATUS_COMPLETE)
			{
				if ((HPIControlStatus[currentBuffer].ControlResult & 0x00000002) == 0)
				{
					HPIBufferState[currentBuffer] = 0;
				}
				else if (PacketRetryCount[currentBuffer] == HPI_PACKET_RETRY_COUNT)
				{
					HPIStat.IntStateRetryCount++;
					ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_CPB_INT_STATE,0, 0, 0);

					errorOccured = 1;
					break;
				}
				else
				{					
					PacketRetryCount[currentBuffer]++;
					if(HPIStatus == 0)
					{
						Request_HPI_PollingInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
						
						HPIBufferState[currentBuffer] = 21;
						HPIStat.IntStateRetryCount++;
					}
				}
			}
		}
		else if (HPIBufferState[currentBuffer] == 0)	// setup
		{
			if (remain_data_size == 0)
			{
				HPIBufferState[currentBuffer] = 12;
			}
			else
			{
				// calc size
		 		if (remain_data_size < MAX_HPI_READ_SIZE_WORD * 4)
		 		{
		 			transfer_size_int = remain_data_size / 4;
		 		}
		 		else
		 		{
		 			transfer_size_int = MAX_HPI_READ_SIZE_WORD;
		 		}
				// set packet data
				HPIHeaderPacket[currentBuffer].DataLength_Word = transfer_size_int;
				HPIHeaderPacket[currentBuffer].Address = current_data_position;

				HPIHeaderPacket[currentBuffer].HPI_State = HPI_STATE_RECEIVE_REQUEST;
				HPIHeaderPacket[currentBuffer].SPB_CheckSum = CheckSum((unsigned int *) &HPIHeaderPacket[currentBuffer] + 1, HPI_PACKET_HEADER_SIZE_WORD - 1);
				PacketRetryCount[currentBuffer] = 0;				

				// proceed pointer
		 		current_data_position += transfer_size_int * 4;
		 		remain_data_size -= transfer_size_int * 4;
				totalPacketCount++;
				if (currentBuffer == 0)
				{
					totalPacketCount_Buffer1++;
				}
				else
				{
					totalPacketCount_Buffer2++;
				}

				HPIBufferState[currentBuffer] = 1;
			}
		}
		else if (HPIBufferState[currentBuffer] == 1)		// request
		{
			// send a packet to cpb
			if (HPIStatus == 0)
			{
				Request_HPI_WriteData(cpbIndex, (Uint32) &HPIHeaderPacket[currentBuffer], CPBBufferAddress[currentBuffer], HPI_PACKET_HEADER_SIZE_WORD + 7, &HPITransferStatus[currentBuffer]);
				HPIBufferState[currentBuffer] = 2;
			}
		}
		else if (HPIBufferState[currentBuffer] == 2)		// write dspint reason
		{
			if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE)
			{
				if (Int_Lock == 0)
				{
					Int_Lock = 1;
					DSPInt_Status[0] = (currentBuffer << 16) | (HPIHeaderPacket[currentBuffer].HPI_State & 0xFFFF);
					
					HPIBufferState[currentBuffer] = 3;
				}
			}
		}
		else if (HPIBufferState[currentBuffer] == 3)		// raise interrupt
		{
			if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE&& HPIStatus == 0)
			{ 	
				Int_Buffer = currentBuffer;
				// raise CPB's DSP interrupt
				Request_HPI_RaiseInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
				PacketSentTime[currentBuffer] = Board1MSTmr;
				HPIBufferState[currentBuffer] = 4;
			}
		}
		else if (HPIBufferState[currentBuffer] == 4)
		{
			if (HPIControlStatus[currentBuffer].Status == HPI_CONTROL_STATUS_COMPLETE&& HPIStatus == 0)
			{
				PacketSentTime[currentBuffer] = Board1MSTmr;
				Request_HPI_PollingInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
				HPIBufferState[currentBuffer] = 5;
			}
		}
		else if (HPIBufferState[currentBuffer] == 5)		// polling processing
		{
			if (HPIControlStatus[currentBuffer].Status == HPI_CONTROL_STATUS_COMPLETE)
			{
				if ((HPIControlStatus[currentBuffer].ControlResult & 0x00000002) == 0)
				{
					HPIBufferState[currentBuffer] = 6;
					Int_Lock = 0;
				}
				else	// cpb's interrupt routine is not entered
				{
					if (Board1MSTmr - PacketSentTime[currentBuffer] > CPB_COM_TIMEOUT)
					{						
						ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_READ_TIMEOUT,
										HPIPacket[currentBuffer].HPI_State, HPIHeaderPacket[currentBuffer].Address, data_size);
						
						errorOccured = 1;
						Int_Lock = 0;
						break;
					}	
					else
					{	
						if(HPIStatus == 0)
						{
							Request_HPI_PollingInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
							HPIBufferState[currentBuffer] = 5;		// polling again
						}
					}	
				}
			}
		}
		else if (HPIBufferState[currentBuffer] == 6)		// polling status
		{
			if (HPIStatus ==0)
			{
				Request_HPI_ReadData(cpbIndex, (Uint32) &HPIPacket[currentBuffer], CPBBufferAddress[currentBuffer], HPI_PACKET_HEADER_SIZE_WORD, &HPITransferStatus[currentBuffer]);
				HPIBufferState[currentBuffer] = 7;
			}
		}
		else if (HPIBufferState[currentBuffer] == 7)	// interrupt routine is finished or laze interrupt 
		{
			if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE)
			{
				if (HPIPacket[currentBuffer].HPI_State > HPI_STATE_RECEIVE_REQUEST && HPIPacket[currentBuffer].HPI_State <= HPI_STATE_WRITE_COMPLETE) //cpb has done something
				{
					if (HPIPacket[currentBuffer].HPI_State == HPI_STATE_WRITE_COMPLETE) // success
					{
						HPIBufferState[currentBuffer] = 8;
					}
					else	// error
					{
						errorPacketCount++;
						HPIStat.CPBErrorPacketCount++;
						if (PacketRetryCount[currentBuffer] == HPI_PACKET_RETRY_COUNT)
						{
							ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RETRY_EXCEEDED,
											HPIPacket[currentBuffer].HPI_State,	HPIHeaderPacket[currentBuffer].Address, data_size);
							
							errorOccured = 1;
							
							break;
						}
						else
						{
							PacketRetryCount[currentBuffer]++;
							//Int_Lock = 0;
							HPIBufferState[currentBuffer] = 1;							
						}
					}				
				}
				else	// cpb did nothing (laze interrupt)
				{
					// check time out
					if (Board1MSTmr - PacketSentTime[currentBuffer] > CPB_COM_TIMEOUT)
					{
						timeOutCount++;
						HPIStat.CPBTOPacketCount++;
						if (PacketRetryCount[currentBuffer] == HPI_PACKET_RETRY_COUNT)
						{
							ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RETRY_EXCEEDED,
											HPIPacket[currentBuffer].HPI_State, HPIHeaderPacket[currentBuffer].Address, data_size);
							
							errorOccured = 1;

							break;
						}
						else
						{														
							PacketRetryCount[currentBuffer]++;
							//Int_Lock = 0;
							HPIBufferState[currentBuffer] = 1;
						}
					}	
					else
					{				
						HPIBufferState[currentBuffer] = 1;
					}
				}
			}
		}
		else if (HPIBufferState[currentBuffer] == 8)	// receive cpb data
		{
			if (HPIStatus ==0)
			{
				Request_HPI_ReadData(cpbIndex, (Uint32) &HPIPacket[currentBuffer], CPBBufferAddress[currentBuffer], HPIHeaderPacket[currentBuffer].DataLength_Word + HPI_PACKET_HEADER_SIZE_WORD, &HPITransferStatus[currentBuffer]);
				HPIBufferState[currentBuffer] = 9;
			}
			
		}
		else if (HPIBufferState[currentBuffer] == 9)	// polling complete
		{
			if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE)
			{
				if (CheckSum((unsigned int *) &HPIPacket[currentBuffer] + 1, HPIHeaderPacket[currentBuffer].DataLength_Word + (HPI_PACKET_HEADER_SIZE_WORD - 1)) == HPIPacket[currentBuffer].SPB_CheckSum)
				{
					successPacketCount++;
					HPIBufferState[currentBuffer] = 10;
				}
				else		// check sum error
				{
					errorPacketCount++;
					HPIStat.ChecksumErrorPacketCount++;
					if (PacketRetryCount[currentBuffer] == HPI_PACKET_RETRY_COUNT)
					{
						ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_CHECKSUM,
										CheckSum((unsigned int *) &HPIPacket[currentBuffer] + 1, HPIHeaderPacket[currentBuffer].DataLength_Word + (HPI_PACKET_HEADER_SIZE_WORD - 1)),	HPIHeaderPacket[currentBuffer].DataLength_Word, __LINE__);
						ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RETRY_EXCEEDED,
										HPIPacket[currentBuffer].HPI_State,	HPIHeaderPacket[currentBuffer].Address, data_size);
						
						errorOccured = 1;
						break;
					}
					else
					{
						PacketRetryCount[currentBuffer]++;
						//Int_Lock = 0;
						HPIBufferState[currentBuffer] = 8;
					}
				}
			}
		}
		else if (HPIBufferState[currentBuffer] == 10 && HPIStatus == 0)
		{	// copy size and address depend on spb's data
			DMA_Job_End_SW[currentBuffer] = 0;
			qdmaRequestUnit[currentBuffer].Opt = MakeDMAOpt(DMA_ESIZE_32BIT, EDMA_CFG_NO_INC_NO_INC);
			qdmaRequestUnit[currentBuffer].Src = (Uint32) HPIPacket[currentBuffer].Data;
			qdmaRequestUnit[currentBuffer].Cnt = HPIHeaderPacket[currentBuffer].DataLength_Word;
			qdmaRequestUnit[currentBuffer].Dst = (Uint32) ((unsigned char *)data_address + HPIHeaderPacket[currentBuffer].Address);
			qdmaRequestUnit[currentBuffer].Idx = 0;
			qdmaRequestUnit[currentBuffer].Fin = &DMA_Job_End_SW[currentBuffer];
			QDMA_Request(&qdmaRequestUnit[currentBuffer]);
			PacketSentTime[currentBuffer] = Board1MSTmr;
			HPIBufferState[currentBuffer] = 11;
		}
		else if (HPIBufferState[currentBuffer] == 11) // DMA end polling
		{
			if (DMA_Job_End_SW[currentBuffer] == 1)
			{
				HPIBufferState[currentBuffer] = 0;
			}
			else
			{
				if (Board1MSTmr - PacketSentTime[currentBuffer] > 100)
				{
					ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_OVERFLOW, __LINE__, HPIHeaderPacket[currentBuffer].DataLength_Word, 0);
					errorOccured = 1;
					break;
				}
			}
		}
		else if (HPIBufferState[currentBuffer] == 12)
		{
			if (HPIBufferState[0] == 12 && HPIBufferState[1] == 12)
			{
				break;
			}
		}
		currentBuffer ^= 1;
	}

	// send transfer complete
	if (!errorOccured)
	{
		currentBuffer = 0;
		PacketRetryCount[currentBuffer] = 0;
		HPIPacket[currentBuffer].DataLength_Word = (data_size + 3) / 4;
		HPIPacket[currentBuffer].HPI_State = HPI_STATE_RECEIVE_COMPLETE;		// transfer end signal
		HPIPacket[currentBuffer].Address = 0;
		HPIPacket[currentBuffer].SPB_CheckSum = CheckSum((unsigned int *) &HPIPacket[currentBuffer] + 1, HPI_PACKET_HEADER_SIZE_WORD - 1);

		// send packet to cpb
		HPIBufferState[currentBuffer] = 0;
		bWhile = 1;
		
		DataReceiveTryTime = Board1MSTmr;

		while(bWhile)
		{
			if(Board1MSTmr - DataReceiveTryTime > maxDataRec_timeout)
			{
				errorOccured = 1;
				bWhile = 0;
				break;	
			}		

			switch(HPIBufferState[currentBuffer])
			{
				case 0:
					if (HPIStatus ==0)
					{
						Request_HPI_WriteData(cpbIndex, (Uint32) &HPIPacket[currentBuffer], CPBBufferAddress[currentBuffer], HPI_PACKET_HEADER_SIZE_WORD + 7, &HPITransferStatus[currentBuffer]);
						HPIBufferState[currentBuffer] = 1;
					}
					break;

				case 1:		// write dspint reason
					if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE)
					{
						DSPInt_Status[0] = (currentBuffer << 16) | (HPIPacket[currentBuffer].HPI_State & 0xFFFF);
						HPIBufferState[currentBuffer] = 2;
					}
					break;

				case 2:
					// DMA end polling
					if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE && HPIStatus == 0)
					{ 	
						// raise CPB's DSP interrupt
						Request_HPI_RaiseInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);

						PacketSentTime[currentBuffer] = Board1MSTmr;
						HPIBufferState[currentBuffer] = 3;
					}
					break;

				case 3:	
					if (HPIControlStatus[currentBuffer].Status == HPI_CONTROL_STATUS_COMPLETE && HPIStatus == 0)
					{
						Request_HPI_PollingInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
						PacketSentTime[currentBuffer] = Board1MSTmr;
						HPIBufferState[currentBuffer] = 4;
					}
					break;

				case 4:
					// polling complete
					if (HPIControlStatus[currentBuffer].Status == HPI_CONTROL_STATUS_COMPLETE)
					{
						if ((HPIControlStatus[currentBuffer].ControlResult & 0x00000002) == 0)
						{
							if (HPIStatus ==0)
							{
								Request_HPI_ReadData(cpbIndex, (Uint32) &HPIHeaderPacket[currentBuffer], CPBBufferAddress[currentBuffer], HPI_PACKET_HEADER_SIZE_WORD, &HPITransferStatus[currentBuffer]);
								HPIBufferState[currentBuffer] = 5;
							}
						}
						else
						{
							if (Board1MSTmr - PacketSentTime[currentBuffer] > CPB_COM_TIMEOUT)
							{
								ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RLI_TIMEOUT, 
									HPIHeaderPacket[currentBuffer].HPI_State, HPIPacket[currentBuffer].Address, data_size);
								
								errorOccured = 1;
								bWhile = 0;
							}	
							else
							{
								if(HPIStatus == 0)
								{
									Request_HPI_PollingInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
									HPIBufferState[currentBuffer] = 4;
								}
							}
						}
					}
					break;

				case 5:
					// polling complete
					if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE)
					{
						if (HPIHeaderPacket[currentBuffer].HPI_State == HPI_STATE_COMPLETE_LAST)
						{
							if (HPIHeaderPacket[currentBuffer].DataLength_Word == HPIPacket[currentBuffer].DataLength_Word) //cpb receive successfully
							{
								bWhile = 0;
							}
							else	// packet error
							{
								errorPacketCount++;
								HPIStat.CPBErrorPacketCount++;
								if (PacketRetryCount[currentBuffer] == HPI_PACKET_RETRY_COUNT)
								{
									ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RETRY_EXCEEDED,
													HPIHeaderPacket[currentBuffer].HPI_State, HPIPacket[currentBuffer].Address, data_size);
									
									errorOccured = 1;
									bWhile = 0;
								}
								else
								{
									PacketRetryCount[currentBuffer]++;
									HPIBufferState[currentBuffer] = 4;
								}
							}
						}
						else
						{
							if (Board1MSTmr - PacketSentTime[currentBuffer] > CPB_COM_TIMEOUT)
							{
								HPIStat.CPBTOPacketCount++;
								if (PacketRetryCount[currentBuffer] == HPI_PACKET_RETRY_COUNT)
								{
									ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RETRY_EXCEEDED,
													HPIHeaderPacket[currentBuffer].HPI_State, HPIPacket[currentBuffer].Address, data_size);

									errorOccured = 1;
									bWhile = 0;
								}
								else
								{
									PacketRetryCount[currentBuffer]++;
									HPIBufferState[currentBuffer] = 1;
								}
							}	
							else
							{
								HPIStat.CPBErrorPacketCount++;
								lazeInterruptCount++;
								HPIBufferState[currentBuffer] = 4;
							}
						}
					}
					break;
			}
		}
	}

	if (errorOccured)
	{
		//CPBStatus[cpbIndex].IsDown = TRUE;

		return FALSE;
	}
	else
	{
		return TRUE;
	}
}

//---------------------------------------------------------------------------
int HPI_SendData_2D(unsigned short pri_indicator, unsigned int sec_indicator, void *data_address, int elementLength_word, int cpbIndex, int transferKind, int frameCount, int frameIndex, int dstStartPosition)
{
	int remain_element_length_word, transfer_length_word;
	int remain_frame_count;
	unsigned int current_data_position;
	unsigned int current_src_address;

	int PacketRetryCount[2];
	unsigned int PacketSentTime[2];

	TQDMARequestUnit qdmaRequestUnit[2];
	unsigned int DMA_Job_End_SW[2];	// dma complete switch

	int HPIBufferState[2];
	int currentBuffer;

	unsigned int CPBBufferAddress[2];
	unsigned int DataSendTryTime;
	unsigned int maxDataSend_timeout;
	int errorOccured;

	int Int_Lock = 0;

	unsigned int startTime;
	int bWhile;
	volatile unsigned int delay;
	volatile unsigned int hpicVal;
	startTime = Board50usTimer;

	CPBBufferAddress[0] = CPBHWInfo[cpbIndex].CPBBuffer1Addr;
	CPBBufferAddress[1] = CPBHWInfo[cpbIndex].CPBBuffer2Addr;
	HPITransferStatus[0].Status = 0;
	HPITransferStatus[1].Status = 0;
	HPIBufferState[0] = 0;
	HPIBufferState[1] = 0;

	currentBuffer = 0;

	current_data_position = dstStartPosition;
	current_src_address = (unsigned int) data_address;
	remain_frame_count = frameCount;
	remain_element_length_word = elementLength_word;

	// set packet's indicator here
	HPIPacket[0].PRI_Indicator = pri_indicator; 
	HPIPacket[0].SEC_Indicator = sec_indicator;
	HPIPacket[1].PRI_Indicator = pri_indicator; 
	HPIPacket[1].SEC_Indicator = sec_indicator;

	errorOccured = 0;

	if(elementLength_word * 4 < 1024) // 1k
		maxDataSend_timeout = SMALL_SIZE_HPI_COM_TIMEOUT;
	else
		maxDataSend_timeout = LARGE_SIZE_HPI_COM_TIMEOUT;

	DataSendTryTime = Board1MSTmr;

	bWhile = 1;
	while (bWhile)
	{		
		if(Board1MSTmr - DataSendTryTime > maxDataSend_timeout)
		{
			errorOccured = 1;
			bWhile = 0;
			break;	
		}		

		switch(HPIBufferState[currentBuffer])
		{
			case 0:		// load
				if (remain_frame_count == 0)
				{
					HPIBufferState[currentBuffer] = 8;
				}
				else
				{
					if (transferKind == 0 || transferKind == 1&& HPIStatus == 0)
					{
						// calc size
				 		if (remain_element_length_word < MAX_HPI_PACKET_DATA_LENGTH_WORD)
				 		{
				 			transfer_length_word = remain_element_length_word;
				 		}
				 		else
				 		{
				 			transfer_length_word = MAX_HPI_PACKET_DATA_LENGTH_WORD;
				 		}
						// set packet data
						HPIPacket[currentBuffer].DataLength_Word = transfer_length_word;
						HPIPacket[currentBuffer].Address = current_data_position;
						// copy data to packet				
						DMA_Job_End_SW[currentBuffer] = 0;
						qdmaRequestUnit[currentBuffer].Opt = MakeDMAOpt(DMA_ESIZE_32BIT, EDMA_CFG_NO_INC_NO_INC);
						qdmaRequestUnit[currentBuffer].Src = (Uint32) current_src_address;
						qdmaRequestUnit[currentBuffer].Cnt = transfer_length_word;
						qdmaRequestUnit[currentBuffer].Dst = (Uint32) HPIPacket[currentBuffer].Data;
						qdmaRequestUnit[currentBuffer].Idx = 0;
						qdmaRequestUnit[currentBuffer].Fin = &DMA_Job_End_SW[currentBuffer];
						QDMA_Request(&qdmaRequestUnit[currentBuffer]);

						HPIBufferState[currentBuffer] = 1;

						// 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--;
						}
					}
					else if (transferKind == 2 && HPIStatus == 0)
					{
						// calc size
				 		if (remain_element_length_word < MAX_HPI_PACKET_DATA_LENGTH_WORD)
				 		{
				 			transfer_length_word = remain_element_length_word;
				 		}
				 		else
				 		{
				 			transfer_length_word = MAX_HPI_PACKET_DATA_LENGTH_WORD;
				 		}
				 							
						// set packet data
						HPIPacket[currentBuffer].DataLength_Word = transfer_length_word;
						HPIPacket[currentBuffer].Address = current_data_position;
						// copy data to packet
						DMA_Job_End_SW[currentBuffer] = 0;
						qdmaRequestUnit[currentBuffer].Opt = MakeDMAOpt(DMA_ESIZE_32BIT, EDMA_CFG_NO_IDX_NO_INC);
						qdmaRequestUnit[currentBuffer].Src = (Uint32) current_src_address;
						qdmaRequestUnit[currentBuffer].Cnt = transfer_length_word * 4;
						qdmaRequestUnit[currentBuffer].Dst = (Uint32) HPIPacket[currentBuffer].Data;
						qdmaRequestUnit[currentBuffer].Idx = SYSTEM_CAMERA_WIDTH_3D;
						qdmaRequestUnit[currentBuffer].Fin = &DMA_Job_End_SW[currentBuffer];
						QDMA_Request(&qdmaRequestUnit[currentBuffer]);

						HPIBufferState[currentBuffer] = 1;

						// proceed pointer
				 		current_data_position += frameIndex;
						current_src_address += 1;
				 		remain_frame_count--;
					}

					PacketSentTime[currentBuffer] = Board1MSTmr;
				}			
				break;

			case 1:		// checksum
				if (DMA_Job_End_SW[currentBuffer] == 1)
				{
					if (HPIBufferState[currentBuffer ^ 1] == 1 || HPIBufferState[currentBuffer ^ 1] == 6 ||
						HPIBufferState[currentBuffer ^ 1] == 8)
					{		
						HPIPacket[currentBuffer].HPI_State = HPI_STATE_SEND_REQUEST;
						HPIPacket[currentBuffer].SPB_CheckSum = CheckSum((unsigned int *) &HPIPacket[currentBuffer] + 1, HPIPacket[currentBuffer].DataLength_Word + (HPI_PACKET_HEADER_SIZE_WORD - 1));
						PacketRetryCount[currentBuffer] = 0;
						HPIBufferState[currentBuffer] = 2;
					}
				}
				else
				{
					if (Board1MSTmr - PacketSentTime[currentBuffer] > 100)
					{
						ErrorUnit_Put(BoardID, ERROR_TYPE_CRITICAL, ERROR_CODE_OVERFLOW, __LINE__, qdmaRequestUnit[currentBuffer].Cnt, DMA_Job_End_SW[currentBuffer]);
						errorOccured = 1;
						bWhile = 0;
					}
				}
				break;

			case 2:		// send
				if (!(CSL_FEXT(hNFAEdma->regs->IPR,EDMA3CC_IPR_REG)&&0xFFFF))
				{
					Request_HPI_WriteData(cpbIndex, (Uint32) &HPIPacket[currentBuffer], CPBBufferAddress[currentBuffer], HPIPacket[currentBuffer].DataLength_Word + HPI_PACKET_HEADER_SIZE_WORD + 7, &HPITransferStatus[currentBuffer]);
					HPIBufferState[currentBuffer] = 3;
				}
				break;

			case 3:		// write dspint reason
				if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE)
				{
					if (Int_Lock == 0)
					{
						Int_Lock = 1;
						DSPInt_Status[0] = (currentBuffer << 16) | (HPIPacket[currentBuffer].HPI_State & 0xFFFF);

						HPIBufferState[currentBuffer] = 4;
					}
				}
				break;

			case 4:		// raise interrupt
				if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE && HPIStatus == 0)
				{ 	
					// raise CPB's DSP interrupt
					Request_HPI_RaiseInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
					HPIBufferState[currentBuffer] = 5;
					HPIStat.TotalSendWord += (HPIPacket[currentBuffer].DataLength_Word + HPI_PACKET_HEADER_SIZE_WORD);
					HPIStat.TotalSendCount++;
				}
				break;

			case 5:		// DMA end polling
				if (HPIControlStatus[currentBuffer].Status == HPI_CONTROL_STATUS_COMPLETE && HPIStatus == 0)
				{
					Request_HPI_PollingInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
					PacketSentTime[currentBuffer] = Board1MSTmr;
					HPIBufferState[currentBuffer] = 6;
				}
				break;

			case 6:		// polling processing
				if (HPIControlStatus[currentBuffer].Status == HPI_CONTROL_STATUS_COMPLETE)
				{
					if ((HPIControlStatus[currentBuffer].ControlResult & 0x00000002) == 0)
					{
						if (HPIStatus ==0){
							Int_Lock = 0;
							Request_HPI_ReadData(cpbIndex, (Uint32) &HPIHeaderPacket[currentBuffer], CPBBufferAddress[currentBuffer], HPI_PACKET_HEADER_SIZE_WORD, &HPITransferStatus[currentBuffer]);
							HPIBufferState[currentBuffer] = 7;
						}
					}
					else
					{
						if (Board1MSTmr - PacketSentTime[currentBuffer] > CPB_COM_TIMEOUT)
						{
							HPIStat.CritErrorCount++;
							ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_SI_TIMEOUT, 
								0, HPIPacket[currentBuffer].Address, __LINE__);
							
							errorOccured = 1;
							Int_Lock = 0;
							bWhile = 0;
						}	
						else
						{
							if(HPIStatus == 0){
							Request_HPI_PollingInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
							HPIBufferState[currentBuffer] = 6;
							}
						}
					}
				}
				break;

			case 7:		// polling complete			
				if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE)
				{
					if (HPIHeaderPacket[currentBuffer].HPI_State == HPI_STATE_READ_COMPLETE) // success
					{
						HPIStat.AckPacketCount++;
						HPIBufferState[currentBuffer] = 0;						
					}
					else	// error
					{
						HPIStat.ErrPacketCount++;
						HPIStat.TotalErrorWord += (HPIPacket[currentBuffer].DataLength_Word + HPI_PACKET_HEADER_SIZE_WORD); 
						if (PacketRetryCount[currentBuffer] == HPI_PACKET_RETRY_COUNT)
						{
							HPIStat.RetryExceededCount++;
							ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RETRY_EXCEEDED,
								HPIHeaderPacket[currentBuffer].HPI_State, HPIPacket[currentBuffer].Address, __LINE__);
							
							
							errorOccured = 1;
							bWhile = 0;
						}
						else
						{
							HPIStat.RetryCount++;
							PacketRetryCount[currentBuffer]++;
							HPIBufferState[currentBuffer] = 2;
						}
					}				
				}
				break;

			case 8:
				//check add finished
				if (HPIBufferState[0] == 8 && HPIBufferState[1] == 8)
				{
					bWhile = 0;
				}
				break;
		}
		currentBuffer ^= 1;
	}

	// send transfer complete
	if (!errorOccured)
	{
		currentBuffer = 0;
		PacketRetryCount[currentBuffer] = 0;
		
		HPIPacket[currentBuffer].DataLength_Word = elementLength_word * frameCount;
		HPIPacket[currentBuffer].HPI_State = HPI_STATE_SEND_LAST;		// transfer end signal
		HPIPacket[currentBuffer].Address = 0;
		HPIPacket[currentBuffer].SPB_CheckSum = CheckSum((unsigned int *) &HPIPacket[currentBuffer] + 1, HPI_PACKET_HEADER_SIZE_WORD - 1);

		// send packet to cpb
		HPIBufferState[currentBuffer] = 0;
		bWhile = 1;

		DataSendTryTime = Board1MSTmr;

		while(bWhile)
		{
			if(Board1MSTmr - DataSendTryTime > maxDataSend_timeout)
			{	
				errorOccured = 1;
				bWhile = 0;
				break;	
			}		

			switch(HPIBufferState[currentBuffer])
			{
				case 0:
					if (HPIStatus ==0)
					{
						Request_HPI_WriteData(cpbIndex, (Uint32) &HPIPacket[currentBuffer], CPBBufferAddress[currentBuffer], HPI_PACKET_HEADER_SIZE_WORD + 7, &HPITransferStatus[currentBuffer]);
						HPIBufferState[currentBuffer] = 1;
					}
					break;

				case 1:		// write dspint reason
					if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE)
					{
						DSPInt_Status[0] = (currentBuffer << 16) | (HPIPacket[currentBuffer].HPI_State & 0xFFFF);
						
						HPIBufferState[currentBuffer] = 2;
					}
					break;

				case 2:		// DMA end polling
					if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE && HPIStatus == 0)
					{ 	
						// raise CPB's DSP interrupt
						Request_HPI_RaiseInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
						PacketSentTime[currentBuffer] = Board1MSTmr;
						HPIBufferState[currentBuffer] = 3;
						HPIStat.TotalSendWord += (HPI_PACKET_HEADER_SIZE_WORD);
						HPIStat.TotalSendCount++;
					}
					break;

				case 3:
					if (HPIControlStatus[currentBuffer].Status == HPI_CONTROL_STATUS_COMPLETE && HPIStatus == 0)
					{
						Request_HPI_PollingInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
						PacketSentTime[currentBuffer] = Board1MSTmr;
						HPIBufferState[currentBuffer] = 4;
					}
					break;

				case 4:
					if (HPIControlStatus[currentBuffer].Status == HPI_CONTROL_STATUS_COMPLETE)
					{
						// polling cpb's processing complete
						if ((HPIControlStatus[currentBuffer].ControlResult & 2) == 0)
						{
							if (HPIStatus ==0)
							{
								Request_HPI_ReadData(cpbIndex, (Uint32) &HPIHeaderPacket[currentBuffer], CPBBufferAddress[currentBuffer], HPI_PACKET_HEADER_SIZE_WORD, &HPITransferStatus[currentBuffer]);
								HPIBufferState[currentBuffer] = 5;
							}
						}
						else
						{
							if (Board1MSTmr - PacketSentTime[currentBuffer] > CPB_COM_TIMEOUT)
							{
								HPIStat.CritErrorCount++;
								ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_SLI_TIMEOUT, 
												HPIHeaderPacket[currentBuffer].HPI_State, HPIPacket[currentBuffer].Address, __LINE__);
								
								errorOccured = 1;
								bWhile = 0;
							}	
							else
							{
								if(HPIStatus == 0)
								{
									Request_HPI_PollingInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
									HPIBufferState[currentBuffer] = 4;
								}
							}
						}
					}
					break;

				case 5:
					// polling complete
					if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE)
					{
						if (HPIHeaderPacket[currentBuffer].HPI_State == HPI_STATE_COMPLETE_LAST)
						{
							if (HPIHeaderPacket[currentBuffer].DataLength_Word == HPIPacket[currentBuffer].DataLength_Word) //cpb receive successfully
							{
								HPIStat.AckPacketCount++;
								bWhile = 0;
							}
							else	// packet error
							{
								HPIStat.ErrPacketCount++;
								HPIStat.TotalErrorWord += (HPI_PACKET_HEADER_SIZE_WORD); 
								if (PacketRetryCount[currentBuffer] == HPI_PACKET_RETRY_COUNT)
								{
									ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RETRY_EXCEEDED, 
													HPIHeaderPacket[currentBuffer].HPI_State, HPIPacket[currentBuffer].Address, __LINE__);
									
									errorOccured = 1;
									bWhile = 0;
								}
								else
								{
									HPIStat.RetryCount++;
									PacketRetryCount[currentBuffer]++;
									HPIBufferState[currentBuffer] = 4;
								}
							}
						}
						else if (HPIHeaderPacket[currentBuffer].HPI_State == HPI_STATE_PROCESSING_LAST)
						{
							if (PacketRetryCount[currentBuffer] == HPI_PACKET_RETRY_COUNT)
							{
								ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RETRY_EXCEEDED, 
												HPIHeaderPacket[currentBuffer].HPI_State, HPIPacket[currentBuffer].Address, __LINE__);
								
								
								errorOccured = 1;
								bWhile = 0;
							}
							else
							{
								HPIStat.RetryCount++;
								PacketRetryCount[currentBuffer]++;
								HPIBufferState[currentBuffer] = 4;
							}
						}
						else if (HPIHeaderPacket[currentBuffer].HPI_State == HPI_STATE_SEND_LAST)
						{
							if (Board1MSTmr - PacketSentTime[currentBuffer] > CPB_COM_TIMEOUT)
							{
								if (PacketRetryCount[currentBuffer] == HPI_PACKET_RETRY_COUNT)
								{
									HPIStat.RetryExceededCount++;
									ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RETRY_EXCEEDED, 
													HPIHeaderPacket[currentBuffer].HPI_State, HPIPacket[currentBuffer].Address, __LINE__);
																		
									errorOccured = 1;
									bWhile = 0;
								}
								else
								{
									HPIStat.RetryCount++;
									PacketRetryCount[currentBuffer]++;
									HPIBufferState[currentBuffer] = 1;
								}
							}	
							else
							{
								HPIStat.ChecksumErrorPacketCount++;
								HPIBufferState[currentBuffer] = 4;
							}
						}
						else	// read error
						{
							if (PacketRetryCount[currentBuffer] == HPI_PACKET_RETRY_COUNT)
							{
								ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RETRY_EXCEEDED, 
												HPIHeaderPacket[currentBuffer].HPI_State, HPIPacket[currentBuffer].Address, __LINE__);
								
								errorOccured = 1;
								bWhile = 0;
							}
							else
							{
								HPIStat.ReadErrorCount++;
								PacketRetryCount[currentBuffer]++;
								HPIBufferState[currentBuffer] = 4;
							}
						}
					}
					break;
			}
		}
	}
	if (errorOccured)
	{
		//CPBStatus[cpbIndex].IsDown = TRUE;

		return FALSE;
	}
	else
	{
		HPIStat.ActualTransferDataWord += (elementLength_word * frameCount);
		HPIStat.SendTime = (Board50usTimer - startTime);
		return TRUE;
	}
}

//---------------------------------------------------------------------------
int HPI_SendData(unsigned short pri_indicator, unsigned int sec_indicator, void *data_address, int data_size, int cpbIndex)
{
	if (data_size == 0) return TRUE;
	return SRIO_SendData(pri_indicator, sec_indicator, data_address, (data_size + 3) / 4, cpbIndex, SRIO_TRANSFER_KIND_DATA, 1, 0, 0);
}
//---------------------------------------------------------------------------
int HPI_SendStream(void *data_address, int data_size, int cpbIndex, unsigned int cpbDataAddress)
{
}

//---------------------------------------------------------------------------
int HPI_SendData_2DImageTo2D_NoECC(unsigned short pri_indicator, unsigned int sec_indicator, 
	void *data_address, int left, int top, int width, int height, int arrayWidth, int cpbIndex)
{
}
//---------------------------------------------------------------------------

int HPI_SendData_2DImageTo2D(unsigned short pri_indicator, unsigned int sec_indicator, 
	void *data_address, int left, int top, int width, int height, int arrayWidth, int cpbIndex)
{
	return 0;
}

//---------------------------------------------------------------------------
int HPI_SendData_2DImageTo2D_Rotate(unsigned short pri_indicator, unsigned int sec_indicator, 
	void *data_address, int srcLeft, int srcTop, int srcWidth, int srcHeight, int srcArrayWidth, int cpbIndex)
{
	return 0;
}

//---------------------------------------------------------------------------
int Request_SendImage_Buffer(int captureIndex, int width, int height, int cpbIndex, int bufferIndex, int imageMode)
{

	int arrangedTopPos = 0;
	int arrangedLeftPos = 0;
	int lineWidth_Word = (width + 3) / 4;
	if (bufferIndex == 0)
	{		
		return SRIO_SendData(PRI_IND_PROCESSING, IND_IMAGE_BUFFER_1, (unsigned char *)ImageInfo[captureIndex].ImageBuffer[bufferIndex], 
							lineWidth_Word, cpbIndex, SRIO_TRANSFER_KIND_IMAGE, height, SYSTEM_CAMERA_WIDTH - lineWidth_Word * 4,0);	
	}
	else
	{
		return 0;
	}

}
//-- -------------------------------------------------------------------------

int HPI_SendData_Image_Streaming(unsigned short pri_indicator, unsigned int sec_indicator, void *data_address, int elementLength_word, int cpbIndex, int transferKind, int frameCount, int frameIndex, int dstStartPosition, void *zero_Address, int left, int top, int width, int height)
{	
	int remain_element_length_word, transfer_length_word;
	int remain_frame_count;
	unsigned int current_data_position;
	unsigned int current_src_address;

	int PacketRetryCount[4];
	unsigned int PacketSentTime[4];
	unsigned int DMAActiveTime[4];

	TQDMARequestUnit qdmaRequestUnit[4];
	unsigned int DMA_Job_End_SW[4];	

	int HPIBufferState[4];
	int currentBuffer;

	unsigned int CPBBufferAddress[4];
	int errorOccured;

	int Int_Lock = 0;

	unsigned int startTime;
	int bWhile;
	volatile unsigned int delay;
	volatile unsigned int hpicVal;
	unsigned int currentTime;
	int lastDataLength;
	unsigned int SPBImageCheckSumResult;
	int CheckSumSize;
	int transfer_frame_count;
	int qdmaCount;
	int framePos;
	int max_image_line_word;
	unsigned char *tempaddr;
	int test;
	int ImageWidth;
	int CPBProcessSW;
	int kk;
	int i;
	int retryCount;
	int errorSW;
	int addStep;
	const int DEST_IMG_ADDRESS_PTR = 3;
	unsigned int BuffAddress;
	int readCount;
	int checkCount;
	int writeValue, readValue;
	unsigned int ImageSendTryTime;
	
	if(sec_indicator == IND_IMAGE_BUFFER_1)
	{
		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;

	CPBBufferAddress[0] = CPBHWInfo[cpbIndex].CPBBuffer1Addr;
	CPBBufferAddress[1] = CPBHWInfo[cpbIndex].CPBBuffer2Addr;
	CPBBufferAddress[2] = CPBHWInfo[cpbIndex].CPBBuffer3Addr;
	CPBBufferAddress[3] = CPBHWInfo[cpbIndex].CPBBuffer4Addr;

	HPITransferStatus[0].Status = 0;
	HPITransferStatus[1].Status = 0;
	HPITransferStatus[2].Status = 0;
	HPITransferStatus[3].Status = 0;
	
	HPIBufferState[0] = 0;
	HPIBufferState[1] = 0;
	HPIBufferState[2] = 0;
	HPIBufferState[3] = 0;

	currentBuffer = 0;

	current_data_position = dstStartPosition;
	current_src_address = (unsigned int) data_address;
	remain_frame_count = frameCount;
	remain_element_length_word = elementLength_word;

	// set packet's indicator here
	HPIPacket[0].PRI_Indicator = pri_indicator; 
	HPIPacket[0].SEC_Indicator = sec_indicator;
	HPIPacket[1].PRI_Indicator = pri_indicator; 
	HPIPacket[1].SEC_Indicator = sec_indicator;

	HPIImagePacket[0].PRI_Indicator = pri_indicator; 	
	HPIImagePacket[0].SEC_Indicator = sec_indicator;
	HPIImagePacket[1].PRI_Indicator = pri_indicator; 	
	HPIImagePacket[1].SEC_Indicator = sec_indicator;
	HPIImagePacket[2].PRI_Indicator = pri_indicator; 	
	HPIImagePacket[2].SEC_Indicator = sec_indicator;
	HPIImagePacket[3].PRI_Indicator = pri_indicator; 	
	HPIImagePacket[3].SEC_Indicator = sec_indicator;

	errorOccured = 0;

	bWhile = 1;

	ImageSendTryTime = Board1MSTmr;

	while (bWhile)
	{	
		if(Board1MSTmr - ImageSendTryTime > SMALL_SIZE_HPI_COM_TIMEOUT)
		{
			errorOccured = 1;
			bWhile = 0;

			//CPBStatus[cpbIndex].IsDown = TRUE;
			break;	
		}		
			
		if(HPIStatus) continue;

		switch(HPIBufferState[currentBuffer])
		{
			case 0:		
				if (remain_frame_count == 0)
				{
					HPIBufferState[currentBuffer] = 8;
				}
				else
				{
					// calc size
					transfer_length_word = 0;
			 		transfer_frame_count = 0;
			 		while(1)
					{
						if(transfer_length_word + elementLength_word <  MAX_HPI_IMAGE_PACKET_DATA_LENGTH_WORD)
						{
							transfer_length_word += elementLength_word;
							transfer_frame_count++;

							remain_frame_count--;

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

					// set packet data					
					HPIImagePacket[currentBuffer].HPI_State = HPI_STATE_SEND_REQUEST;
					HPIImagePacket[currentBuffer].DataLength_Word = transfer_length_word;
					HPIImagePacket[currentBuffer].Address = current_data_position;
					HPIImagePacket[currentBuffer].FrameCount = transfer_frame_count;
		
					// copy data to packet				
					qdmaRequestUnit[currentBuffer].Opt = MakeDMAOpt(DMA_ESIZE_32BIT, EDMA_CFG_NO_INC_NO_INC);
					qdmaRequestUnit[currentBuffer].Cnt = elementLength_word;
					qdmaRequestUnit[currentBuffer].Idx = 0;
					qdmaRequestUnit[currentBuffer].Fin = &DMA_Job_End_SW[currentBuffer];

					for(framePos = 0; framePos < transfer_frame_count; framePos++)
					{
						DMA_Job_End_SW[currentBuffer] = 0;
						qdmaRequestUnit[currentBuffer].Src = (Uint32) current_src_address;
						qdmaRequestUnit[currentBuffer].Dst = (Uint32) HPIImagePacket[currentBuffer].Data + ((elementLength_word << 2) * framePos);						
						
						DMAActiveTime[currentBuffer] = Board1MSTmr; 
						QDMA_Request(&qdmaRequestUnit[currentBuffer]);
						
						while(1)
						{
							if(DMA_Job_End_SW[currentBuffer] == 1) // DMA end check
							{
								break;
							}
							else if(Board1MSTmr - DMAActiveTime[currentBuffer] > DMA_ACTIVE_TIME_OUT)
							{
								errorOccured = 1;
								bWhile = 0;

								//CPBStatus[cpbIndex].IsDown = TRUE;
								break;								
							}
						}

						current_src_address += (max_image_line_word << 2);
						current_data_position += (max_image_line_word << 2);
					}

					HPIBufferState[currentBuffer] = 2;	

					PacketSentTime[currentBuffer] = Board1MSTmr;		 	
				}			
				break;

			case 2: 
				// send
				if (!(CSL_FEXT(hNFAEdma->regs->IPR,EDMA3CC_IPR_REG)&&0xFFFF))
				{
					Request_HPI_WriteData(cpbIndex, (Uint32) HPIImagePacket[currentBuffer].Data, CPBBufferAddress[currentBuffer] + HPI_PACKET_HEADER_SIZE_WORD * 4, transfer_length_word, &HPITransferStatus[currentBuffer]);
					while(HPITransferStatus[currentBuffer].Status != HPI_TRANSEFR_STATUS_COMPLETE)
					{
						if(Board1MSTmr - PacketSentTime[currentBuffer] > CPB_COM_TIMEOUT)
						{
							errorOccured = 1;
							bWhile = 0;

							//CPBStatus[cpbIndex].IsDown = TRUE;
							break;
						}
					}

					// 嬪 輿戮 囀萄蒂 嬴楚煎 渠羹 (Address 薑爾虜 僥薯陛 腎嘎煎 и廓 渦 write п遽棻)
					Request_HPI_WriteData(cpbIndex, (Uint32) &HPIImagePacket[currentBuffer], CPBBufferAddress[currentBuffer], HPI_PACKET_HEADER_SIZE_WORD, &HPITransferStatus[currentBuffer]);
					while(HPITransferStatus[currentBuffer].Status != HPI_TRANSEFR_STATUS_COMPLETE)
					{
						if(Board1MSTmr - PacketSentTime[currentBuffer] > CPB_COM_TIMEOUT)
						{
							errorOccured = 1;
							bWhile = 0;

							//CPBStatus[cpbIndex].IsDown = TRUE;
							break;
						}
					}					

					Request_HPI_WriteData(cpbIndex, (Uint32) &HPIImagePacket[currentBuffer].Address, CPBBufferAddress[currentBuffer] + (DEST_IMG_ADDRESS_PTR) * 4, 1, &HPITransferStatus[currentBuffer]);
					while(HPITransferStatus[currentBuffer].Status != HPI_TRANSEFR_STATUS_COMPLETE)
					{
						if(Board1MSTmr - PacketSentTime[currentBuffer] > CPB_COM_TIMEOUT)
						{
							errorOccured = 1;
							bWhile = 0;

							//CPBStatus[cpbIndex].IsDown = TRUE;
							break;
						}
					}

					HPIImagePacket[currentBuffer].CompleteSW = 0xFFFF;
					Request_HPI_WriteData(cpbIndex, (Uint32) &HPIImagePacket[currentBuffer].CompleteSW, CPBBufferAddress[currentBuffer] + (HPI_PACKET_HEADER_SIZE_WORD + MAX_HPI_IMAGE_TRANSFER_SIZE_WORD) * 4, 1, &HPITransferStatus[currentBuffer]);
					while(HPITransferStatus[currentBuffer].Status != HPI_TRANSEFR_STATUS_COMPLETE)
					{
						if(Board1MSTmr - PacketSentTime[currentBuffer] > CPB_COM_TIMEOUT)
						{
							errorOccured = 1;
							bWhile = 0;

							//CPBStatus[cpbIndex].IsDown = TRUE;
							break;
						}
					}

					HPIBufferState[currentBuffer] = 0;
				}
				break;

			case 8:
				//check add finished
				if (HPIBufferState[0] == 8 && HPIBufferState[1] == 8 && HPIBufferState[2] == 8 && HPIBufferState[3] == 8)
				{
					bWhile = 0;
				}
				break;
		}	
		
		currentBuffer++;

		if(currentBuffer >= 4) currentBuffer = 0;
	}

	// send transfer complete
	if (!errorOccured)
	{
		currentBuffer = 0;
		PacketRetryCount[currentBuffer] = 0;
		
		lastDataLength = 4;

		CheckSumSize = width / IMG_CHECK_COUNT;

		SPBImageCheckSumResult = ImageCheckSum((unsigned char*)zero_Address, left, top, width, height, ImageWidth, CheckSumSize);

		HPIPacket[currentBuffer].Data[0] = left;
		HPIPacket[currentBuffer].Data[1] = top;
		HPIPacket[currentBuffer].Data[2] = width;
		HPIPacket[currentBuffer].Data[3] = height;

		HPIPacket[currentBuffer].DataLength_Word = lastDataLength;
		HPIPacket[currentBuffer].HPI_State = HPI_STATE_SEND_LAST_IMAGE;		// transfer end signal
		HPIPacket[currentBuffer].Address = 0;

		// send packet to cpb
		HPIBufferState[currentBuffer] = 0;
		bWhile = 1;
		
		ImageSendTryTime = Board1MSTmr;

		while(bWhile)
		{
			if(Board1MSTmr - ImageSendTryTime > SMALL_SIZE_HPI_COM_TIMEOUT)
			{
				errorOccured = 1;
				bWhile = 0;

				//CPBStatus[cpbIndex].IsDown = TRUE;
				break;	
			}		

			switch(HPIBufferState[currentBuffer])
			{
				case 0:
					if (HPIStatus ==0)
					{
						Request_HPI_WriteData(cpbIndex, (Uint32) &HPIPacket[currentBuffer], CPBBufferAddress[currentBuffer], lastDataLength + HPI_PACKET_HEADER_SIZE_WORD + 7, &HPITransferStatus[currentBuffer]);
						HPIBufferState[currentBuffer] = 1;
					}
					break;

				case 1:		
					// write dspint reason
					if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE)
					{
						DSPInt_Status[0] = (currentBuffer << 16) | (HPIPacket[currentBuffer].HPI_State & 0xFFFF);
						HPIBufferState[currentBuffer] = 2;
					}
					break;

				case 2:
					// DMA end polling
					if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE && HPIStatus == 0)
					{ 	
						// raise CPB's DSP interrupt
						Request_HPI_RaiseInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
						PacketSentTime[currentBuffer] = Board1MSTmr;
						HPIBufferState[currentBuffer] = 3;
						HPIStat.TotalSendWord += (HPI_PACKET_HEADER_SIZE_WORD);
						HPIStat.TotalSendCount++;
					}
					break;

				case 3:
					if (HPIControlStatus[currentBuffer].Status == HPI_CONTROL_STATUS_COMPLETE && HPIStatus == 0)
					{
						Request_HPI_PollingInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
						PacketSentTime[currentBuffer] = Board1MSTmr;
						HPIBufferState[currentBuffer] = 4;
					}
					break;

				case 4:
					if (HPIControlStatus[currentBuffer].Status == HPI_CONTROL_STATUS_COMPLETE)
					{
						// polling cpb's processing complete
						if ((HPIControlStatus[currentBuffer].ControlResult & 2) == 0)
						{
							if (HPIStatus ==0)
							{
								Request_HPI_ReadData(cpbIndex, (Uint32) &HPIHeaderPacket[currentBuffer], CPBBufferAddress[currentBuffer], HPI_PACKET_HEADER_SIZE_WORD, &HPITransferStatus[currentBuffer]);
								HPIBufferState[currentBuffer] = 5;
							}
						}
						else
						{
							if (Board1MSTmr - PacketSentTime[currentBuffer] > CPB_COM_TIMEOUT)
							{
								HPIStat.CritErrorCount++;
								ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_SLI_TIMEOUT, 
												HPIHeaderPacket[currentBuffer].HPI_State, HPIPacket[currentBuffer].Address, __LINE__);
								
								errorOccured = 1;
								bWhile = 0;

								//CPBStatus[cpbIndex].IsDown = TRUE;
							}	
							else
							{
								if(HPIStatus == 0)
								{
									Request_HPI_PollingInterrupt(cpbIndex, &HPIControlStatus[currentBuffer]);
									HPIBufferState[currentBuffer] = 4;
								}
							}
						}
					}
					break;

				case 5:
					// polling complete
					if (HPITransferStatus[currentBuffer].Status == HPI_TRANSEFR_STATUS_COMPLETE)
					{
						if (HPIHeaderPacket[currentBuffer].HPI_State == HPI_STATE_COMPLETE_LAST)
						{
							if (HPIHeaderPacket[currentBuffer].DataLength_Word == HPIPacket[currentBuffer].DataLength_Word) //cpb receive successfully
							{
								if(SPBImageCheckSumResult == HPIHeaderPacket[currentBuffer].SPB_CheckSum)
								{
									HPIStat.AckPacketCount++;
									bWhile = 0;
								}
								else
								{
									ImageSendErrorCount++;
									bWhile = 0;

									ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_CHECKSUM, SPBImageCheckSumResult, HPIHeaderPacket[currentBuffer].SPB_CheckSum, ImageSendErrorCount); 
									

									// 檜嘐雖 艙羲縑 評塭 縑楝陛 嫦儅й 陽氈堅 嫦儅ж雖 彊擊 陽陛 氈擠
									// 縑楝馨檜蝶縑憮 薯諼 衛麵獄棻
									/*
									errorOccured = 1;
									bWhile = 0;	
									
									CPBStatus[cpbIndex].IsDown = TRUE;							
									*/
								}
							}
							else	// packet error
							{
								HPIStat.ErrPacketCount++;
								HPIStat.TotalErrorWord += (HPI_PACKET_HEADER_SIZE_WORD); 
								if (PacketRetryCount[currentBuffer] == HPI_PACKET_RETRY_COUNT)
								{
									ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RETRY_EXCEEDED, 
													HPIHeaderPacket[currentBuffer].HPI_State, HPIPacket[currentBuffer].Address, __LINE__);
									
									errorOccured = 1;
									bWhile = 0;

									//CPBStatus[cpbIndex].IsDown = TRUE;
								}
								else
								{
									HPIStat.RetryCount++;
									PacketRetryCount[currentBuffer]++;
									HPIBufferState[currentBuffer] = 0;
								}
							}
						}
						else	// read error
						{
							if (PacketRetryCount[currentBuffer] == HPI_PACKET_RETRY_COUNT)
							{
								ErrorUnit_Put(BoardID + cpbIndex + 1, ERROR_TYPE_CRITICAL, ERROR_CODE_HPI_RETRY_EXCEEDED, 
												HPIHeaderPacket[currentBuffer].HPI_State, HPIPacket[currentBuffer].Address, __LINE__);
								
								errorOccured = 1;
								bWhile = 0;

								//CPBStatus[cpbIndex].IsDown = TRUE;
							}
							else
							{
								HPIStat.ReadErrorCount++;
								PacketRetryCount[currentBuffer]++;
								HPIBufferState[currentBuffer] = 0;
							}
						}
					}
					break;
			}
		}
	}

	if (errorOccured)
	{
		return FALSE;
	}
	else
	{
		HPIStat.ActualTransferDataWord += (elementLength_word * frameCount);
		HPIStat.SendTime = (Board50usTimer - startTime);
		return TRUE;
	}
}
//---------------------------------------------------------------------------

unsigned int PartialCheckSum(unsigned char* src, unsigned int len, unsigned int size)
{
	unsigned int sum = 0;
	int i;

	for(i = len - 1; i >= 0; i -= size)
	{
		sum += *(src + i);
	}

	return sum;
}
