/**************************************************************
$Workfile:   elmcpepe.c  $
***************************************************************
**
** FIRMWARE, Copyright (C) 2000-2002
** Ikanos Communications, Fremont, CA
** All rights reserved. 
**
** The information and contents of this file are the
** proprietary information of Ikanos Communication and may not
** be disclosed or used without the formal written approval of
** Ikanos Communication
**
$Revision: 1.1 $
$Date: 2006/10/16 04:34:50 $
***************************************************************/


/**************************************************************

	This file contains functions for 
	ELM related Protocol Entitry specific to the CPE:

**************************************************************/

#ifdef	VTU_R

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

#include "ipos.h"
#include "appconfig.h"
#include "apperrCode.h"
#include "apposmacro.h"
#include "portmap.h"
#include "oampdb.h"

#include "elmlocal.h"
#include "elmdeferred.h"
#include "elmapp.h"

extern readEventLogFromFlash( U32 nvramEventLogSize );

/*  forward declarations  */

static void 	cpeSendAckHandler(ipos_port_id portId, U8 UID, U32 uPar, int status, void *par);
static int	iposELMCPEiFftpComplete( ipos_port_id pid, U8 uid,
				iposelm_transfer_info  *pInfo, iposELMCmdCb pComplete);


ipos_elm_cpe		iposELMCpe[MAX_NUM_OF_PORTS];

int			iposelm_file_expiration_tick = IPOSELM_FILE_EXPIRATION_TICK;

ipos_elm_cpe	*
iposELMIndxGetCpe( int index )
{
	if(index>MAX_NUM_OF_PORTS-1||index<0)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf("Failed to get the ELM object: index=%d \n", index);
#endif
		return	NULL;
	}

	return(&iposELMCpe[index]);
}



ipos_elm_cpe *
iposELMGetCpePe(ipos_port_id	pid)
{

	int	lineNum;
	if(getLineNum(pid, &lineNum)!=IPOS_SUCCESS)
	{
//		printf("Failed to get the ELM object \n");
//		return	NULL;
	}

	if(lineNum>MAX_NUM_OF_PORTS)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf("port index of %d out of range in iposELMGetCpePe\n", lineNum);
#endif
		return	NULL;
	}

	lineNum=lineNum-1;
	return(&iposELMCpe[lineNum]);
}

/* timeout mechanism for CPE */

/* File expiration handler	*/

static void
cpeTmrExpired(U32 arg1, U32 arg2)
{
	ipos_elm_cpe	*pCpePe;

	pCpePe=(ipos_elm_cpe *) arg1;
	
	printf( "CPE EFM: File transfer connection error detected\n"); 

    /* file transfer state = IDLE Ready for restart */

	pCpePe->stateiFftp = IPOSELM_IFFTP_CPE_IDLE;
	pCpePe->stateXfer = IPOSELM_CPE_XFER_IDLE;

    /* error callback function TBD	*/

}


static	int
cpePetTimer( ipos_elm_cpe *pCpePe)
{
	int	errCode=IPOS_SUCCESS;   

    /* start the expiration timer*/

	errCode=iposSetTmr( pCpePe->ptmrExp, iposelm_file_expiration_tick, cpeTmrExpired,
			(U32) pCpePe, (U32) 0);
	return	errCode;
}


/* initialize the ELM CPE iFftp */

/* because of the reversal of file transfer roles vis-a-vis RFM,
   this method is mostly borrowed from iposRFMCOiFftpInit	*/

static int
iposELMCPEiFftpInit( ipos_elm_cpe *pCpePe )
{
	int	iter, errCode;

	pCpePe->sid = 0;
	pCpePe->currBlkIdx=0;
	pCpePe->lastBlkIdx=0;

	/* state=IDLE	*/
	pCpePe->stateiFftp = IPOSELM_IFFTP_CO_IDLE;

	/* initilize flgAck	*/
	for (iter = 0; iter < MAX_NUM_DATA_BLOCKS; iter++)
	{
		pCpePe->flgAck[ iter ]=0;
	}

	pCpePe->cntAck=0;
	pCpePe->cntDataBlk=0;
	pCpePe->displayLevel=4;		/* modulo for report, 1: report every block */

	/* Get the expiration timer	*/
	errCode=iposCreateTmr(&(pCpePe->ptmrExp));

	return	IPOS_SUCCESS;
}

int	iposELMCPEInit( void )
{
	int	i, errCode, lineNum;
	ipos_elm_cpe	*pCpePe;

	for(i=0;i<MAX_NUM_OF_PORTS;i++)
	{
		pCpePe=iposELMIndxGetCpe(i);

		/* PID init	*/
		lineNum=i+1;
		errCode=getBmePortId(lineNum, &(pCpePe->pid));
		// ignore the errCode

		/* initialize the cmd obj */
		errCode=iposELMCmdInit(&(pCpePe->cmdHandler), pCpePe->pid );
		if(errCode!=IPOS_SUCCESS)
		{
#ifdef ELM_DIAGNOSTIC_DEBUG
			printf("FATAL ERROR: Command object Initialization Failed! %d \n", errCode);
#endif
			return	errCode;
		}

		pCpePe->addrEventLog = sysGetEventLogAddr( lineNum );

		/* initialize the iFFTP obj	*/

		errCode=iposELMCPEiFftpInit(pCpePe);

		pCpePe->stateXfer = IPOSELM_CPE_XFER_IDLE;
	}

	return	IPOS_SUCCESS;
}

/* on error, reset states to IDLE */

int
cpeErrorHandler(ipos_elm_cpe *pCpePe, int status)
{
	ipos_elm_cmd_handler	*pCmd;

	pCpePe->stateiFftp = IPOSELM_IFFTP_CPE_IDLE;
	pCmd = &(pCpePe->cmdHandler);
	pCmd->stateCmd = IPOSELM_STATE_CMD_IDLE;

	if (pCmd->pCbCmd!=NULL) 
	{
		pCmd->pCbCmd(pCmd->pid, pCmd->uidResp, IPOS_ERROR, (void *)pCmd->respStruct);
	}

	return( IPOS_SUCCESS );
}

int
cpeGetDataBlk(ipos_elm_cpe *pCpePe)
{
	pCpePe->currBlk.genericHdr.pt=IPOSELM_PT;
	pCpePe->currBlk.genericHdr.msgType=IPOSELM_MSG_DATA_BLOCK;
	pCpePe->currBlk.genericHdr.length= IPOS_DATA_MSG_LEN;
	pCpePe->currBlk.sid=pCpePe->sid;
	pCpePe->currBlk.seq=pCpePe->currBlkIdx;
	pCpePe->currBlk.pData = (U8*) ((pCpePe->addrEventLog) + (U32) (pCpePe->currBlkIdx)*IPOS_DATA_BLK_SIZE);
	return	IPOS_SUCCESS;															

}

/* send	a packet	*/

int
cpeSendDataPkt(ipos_elm_cpe *pCpePe, iposelm_data_block *pData, U16 BlkIndex)
{
	U8	eocMsg[MAX_MSG_SIZE];

	int	intLevel;
	int	errCode=IPOS_SUCCESS;
	
	/* check the ackflag	*/

	if(pCpePe->flgAck[ BlkIndex ] >= 0)
	{
		/* construct a msg buffer	*/
		eocMsg[IPOSELM_MSGHDR_PT]=IPOSELM_PT;
		eocMsg[IPOSELM_MSGHDR_MSGTYPE]=pData->genericHdr.msgType;
		eocMsg[IPOSELM_MSGHDR_MSGLEN]=IPOS_DATA_MSG_LEN;
		eocMsg[IPOSELM_FILE_SID]=pCpePe->sid;
		eocMsg[IPOSELM_FILE_SEQ]=(pData->seq&0xff00)>>8;
		eocMsg[IPOSELM_FILE_SEQ+1]=(pData->seq&0xff);

		memcpy(&(eocMsg[IPOSELM_FILE_DATA]),pData->pData,IPOS_DATA_BLK_SIZE);

		errCode= iposEocSendDataStream(pCpePe->pid, IPOS_DATA_MSG_LEN, eocMsg, 
							  0, (U32) pCpePe, cpeSendAckHandler); 
		if(pCpePe->displayLevel>0)
		{
			if((pCpePe->cntDataBlk % pCpePe->displayLevel) == 0)
			{
				/*printf(" %d", BlkIndex );*/
				printf("." );
			}
		}

		/* increment the counter	*/
		intLevel=iposIntLock();
		pCpePe->flgAck[ BlkIndex ]++;
		pCpePe->cntDataBlk++;
		iposIntUnlock(intLevel);
	}

	return	errCode;
}

static	void
cpeCompletionDone(ipos_port_id pid, U8 uid, int status, void *uPar)
{
	int	errCode;

	/* iposelm_xfer_complete_resp *uPar; */

	ipos_elm_cpe	*pCpePe;

	pCpePe=iposELMGetCpePe(pid);
	if(pCpePe==NULL)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf("Cannot locate CPE PE object for b%dp%d in cpeCompletionDone\n",
			pid.bmeNum, pid.portNum );
#endif
		return;

	}

	errCode=iposResetTmr(pCpePe->ptmrExp);
	if(errCode!=IPOS_SUCCESS)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf("CPE ELM: Failed to reset the timer \n");
#endif
	}

	pCpePe->stateiFftp = IPOSELM_IFFTP_CPE_IDLE;
}

static	int
cpeCompleteHandler(ipos_elm_cpe *pCpePe,int status)
{
	int errCode;
	iposelm_transfer_info	info;

	/* stop the error detection timer	*/

        errCode=iposResetTmr(pCpePe->ptmrExp);
	if(errCode!=IPOS_SUCCESS)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf("CPE ELM: Failed to reset the timer \n");
#endif
	}

	/* send the completion to CO */

	info.dataBlockSent=pCpePe->lastBlkIdx+1;
	info.byteSent=(pCpePe->lastBlkIdx+1) * IPOS_DATA_BLK_SIZE;
	errCode=iposELMCPEiFftpComplete(pCpePe->pid, 1, &info, cpeCompletionDone); 
	pCpePe->stateXfer = IPOSELM_CPE_XFER_IDLE;
	return	errCode;
}

static void
cpeSendAckHandler(ipos_port_id portId,  U8 UID, U32 uPar, int status, void *par)
{
	ipos_elm_cpe	*pCpePe;

	/*printf( "cpeSendAckHandler called for port b%dp%d with status %d\n",
		 portId.bmeNum, portId.portNum, status );*/

	pCpePe=iposELMGetCpePe(portId);

	if(pCpePe==NULL)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf("Cannot locate CPE PE object for b%dp%d in cpeSendAckHandler\n",
			portId.bmeNum, portId.portNum );
#endif
		return;

	}

	/* check the CpePe state		*/

	if(pCpePe->stateiFftp==IPOSELM_IFFTP_CPE_ACTIVE)
	{
		submitJobCpeAckHandler( portId, status );
	}
	else
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf( "\nin cpeSendAckHandler, but the iFftp state is not active\n" );
#endif
	}

	return;
}

int
cpeStart( ipos_elm_cpe *pCpePe )
{
	int	iter, errCode;

    /*printf( "cpeStart starts\n" );*/
	for(iter=0; iter < pCpePe->lastBlkIdx+1; iter++)
	{
		if (pCpePe->flgAck[ iter ] >= 0)	/* check the first block not acked */
		{
			if(pCpePe->flgAck[ iter ] > IPOSELM_DATABLK_RESEND)
			{
#ifdef ELM_DIAGNOSTIC_DEBUG
				printf("\ncpeStart: Indx=%d, cnt=%d\n",
					iter, pCpePe->flgAck[ iter ]); 
#endif
				cpeErrorHandler(pCpePe, 0);
				return	IPOS_ERROR;
			}
			
			pCpePe->currBlkIdx = iter;
			cpeGetDataBlk(pCpePe);
			errCode=cpeSendDataPkt(pCpePe, &(pCpePe->currBlk), pCpePe->currBlkIdx);
		    /*printf( "cpeStart sent block %d at %ld\n", pCpePe->currBlkIdx, iposTickGet() );*/
			return	errCode;				/* exit	*/
		}
	}

   /* come here if all packets sent and acknowledged */

	errCode = cpeCompleteHandler(pCpePe, IPOS_SUCCESS);
	return( IPOS_SUCCESS );
}

static int
iposELMCPEiFftpComplete(
	ipos_port_id pid,
	U8 uid, iposelm_transfer_info  *pInfo,
	iposELMCmdCb pComplete
)
{
	int errCode;
	ipos_elm_cpe	*pCpePe;
	ipos_elm_cmd_handler		*pCmd;
	iposelm_xfer_complete_req	msgStruct;


	pCpePe=iposELMGetCpePe( pid );
    
	/* setup the structure	*/

	iposELMCmdSetCtrlHdr(&(msgStruct.ctrlHdr),IPOSELM_MSG_FILE_TR_COMPLETE,IPOSELM_ACK_CMD, uid); /* setup the control header	*/
	memcpy( &(msgStruct.transferInfo), pInfo, sizeof(iposelm_transfer_info) );

	/* call Cmd Core functions			*/
	pCmd=&(pCpePe->cmdHandler);
	errCode=iposELMCmdCoreReq(pCmd,IPOSELM_MSG_FILE_TR_COMPLETE, (void *)&msgStruct, 3,
							  uid, pComplete);
	
	return	errCode;
}

int
iposELMCPEiFftpStart( ipos_port_id pid, U8 sid )
{
	int		 iter, errCode;
	U32		 fileLen;
	ipos_elm_cpe	*pCpePe;

	pCpePe=iposELMGetCpePe(pid);
	if (pCpePe == NULL)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf(
	   "fatal error in iposELMCPEiFftpStart, cannot locate CPE object for port b%dp%d\n", 
	    pid.bmeNum, pid.portNum
		);
#endif
		return( IPOS_ERROR );
	}

	fileLen = pCpePe->fileInfo.size;
	if (fileLen > (U32)MAX_NUM_DATA_BLOCKS * (U32)IPOS_DATA_BLK_SIZE)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf( "file size of %ld exceeds maximum size\n", fileLen );
#endif
		return( IPOS_ERROR );
	}

	pCpePe->sid = sid;
	pCpePe->currBlkIdx = 0;
	pCpePe->lastBlkIdx = (fileLen / IPOS_DATA_BLK_SIZE);

	/* state=IDLE	*/
	pCpePe->stateiFftp=IPOSELM_IFFTP_CPE_IDLE;

	for (iter = 0; iter < MAX_NUM_DATA_BLOCKS; iter++)
	{
		pCpePe->flgAck[ iter ] = 0;
	}

	pCpePe->cntAck = 0;
	pCpePe->cntDataBlk = 0;

	pCpePe->stateiFftp=IPOSELM_IFFTP_CPE_ACTIVE;
	errCode = cpeStart( pCpePe );

	return( IPOS_SUCCESS );
}

int
iposELMCPEiFftpHandler(ipos_elm_cpe *pCpePe, U8 *pEocData)
{
	U16	i;
	U16	ack1, ack2;
	int	intLevel;
	/* msgType=Msg Ack?	*/


	if(pCpePe->stateiFftp!=IPOSELM_IFFTP_CO_ACTIVE)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf( "iFftp state is idle in iposELMCPEiFftpHandler\n" );
#endif
		return	IPOS_SUCCESS;			/* wrong state: ignored	*/

	}

	if(pEocData[ IPOSELM_MSGHDR_MSGTYPE ] != IPOSELM_MSG_ACK)
	{
		return	IPOS_SUCCESS;			/* other packets received: ignored	*/
	}

	/* sid match?	*/

	if (pEocData[ IPOSELM_FILE_SID ] != pCpePe->sid)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
	    printf( "remote session ID of %d does not match local session ID of %d\n",
		     pEocData[ IPOSELM_FILE_SID ],  pCpePe->sid );
#endif
		return IPOS_SUCCESS;		/* session ID does not match: ignored	*/
	}
    
	/* ack1, ack2 in range?	*/
	ack1=((U16)pEocData[IPOSELM_FILE_ACK1]<<8) | ( ((U16) pEocData[IPOSELM_FILE_ACK1+1]) & 0x0ff); 

	ack2=( (U16)pEocData[IPOSELM_FILE_ACK2]<<8) |( ((U16) pEocData[IPOSELM_FILE_ACK2+1]) & 0x0ff); 

	if((ack1<=ack2)&&(ack2<MAX_NUM_DATA_BLOCKS))
	{						/* valid packet	*/
		intLevel=iposIntLock();
		
		for(i=ack1;i<=ack2;i++)
		{
			pCpePe->flgAck[i]=-1;		/* -1: the packet acked	*/
		}
		pCpePe->cntAck++;			/* ack counter ++	*/

		iposIntUnlock(intLevel);

		/* pet the error detection timer	*/

		cpePetTimer(pCpePe);
	}

	return	IPOS_SUCCESS;				/* other packet ignored	*/
}

/* Respond to a command packet from the CO modem */

int	iposELMCPEEvntHandler(ipos_elm_cpe *pCpePe, U8 *pEocMsg)
{
	int	errCode;
	U8	msgType;
	U8	uid;	
	U8	msgStruct[ MAX_STRUCT_SIZE ];

	/* decode the Eoc Msg	*/

	errCode=iposELMMsg2Struct(pEocMsg, msgStruct, &msgType);

	if( errCode!=IPOS_SUCCESS)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf("Not a Valid EOC msg: %d \n", errCode);
#endif
		return	errCode;
	}

    /*printf( "Got message of type %d in iposELMCPEEvntHandler\n", msgType );*/
	switch (msgType)
	{
	  case IPOSELM_MSG_GET_EVENT_LOG:
	  {
		iposelm_select_event_log_req	*pSelectEventLogReq =
		  (iposelm_select_event_log_req *) &msgStruct[ 0 ];

	   	uid=pSelectEventLogReq->ctrlHdr.uid;
	    /*printf( "get event log of type %d\n",
		     pSelectEventLogReq->eventLogChoice.eventLogOption
	    );*/

	    /* only respond to the GET EVENT LOG request if the current transfer state is idle */

		if(pCpePe->pEvntGetEventLogReq!=NULL && pCpePe->stateXfer == IPOSELM_CPE_XFER_IDLE)
		{
			pCpePe->pEvntGetEventLogReq(pCpePe->pid, uid, &(pSelectEventLogReq->eventLogChoice));
		}
	  }
	  break;

	  case IPOSELM_MSG_FILE_TRANSFER:
	  {
		iposelm_xfer_event_log_req	*pXferEventLogReq =
			(iposelm_xfer_event_log_req *) &msgStruct[ 0 ];

		/*printf(
	   "iposELMCPEEvntHandler has a IPOSELM_MSG_FILE_TRANSFER message with session ID %d\n",
	    pXferEventLogReq->sid );*/

		if (pCpePe->stateiFftp == IPOSELM_IFFTP_CPE_IDLE)
		{

	   /* CO sets the session ID for the transfer */

		    iposELMCPEiFftpStart( pCpePe->pid, pXferEventLogReq->sid );	
		}
	  }
	  break;

	  default:
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf( "\nUnexpected message %d for ELM CPE\n", msgType );
#endif
	  break;
	}

	return	IPOS_SUCCESS;
}

/* top level CPE callback, called by appEocMsgParser */

void
iposELMCPEEntry(ipos_port_id pid, U8 *pEocMsg)
{
	int		 errCode;
	int		 msgClass;
	ipos_elm_cpe	*pCpePe;

	/*printf( "from port b%dp%d at %ld, received message with header %d %d %d %d\n",
		 pid.bmeNum, pid.portNum, iposTickGet(),
		*pEocMsg, *(pEocMsg + 1), *(pEocMsg + 2), *(pEocMsg + 3)
	);*/

    /* check the PT: if not ELM, exit	*/

	if	(pEocMsg[ IPOSELM_MSGHDR_PT ]!= EOC_ELM_PROTOCOL)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf("fatal error: NonELM msg passed to the CPE_PE\n"); 
#endif
        	return;
	}

	pCpePe=iposELMGetCpePe(pid);
	msgClass=msgCheckElmClass(pEocMsg);	

	if(pCpePe==NULL)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf("Fatal ELM error: Invalid PID b%dp%d for the CPE\n",
			pid.bmeNum, pid.portNum);
#endif
		return;

	}

	switch(msgClass)
	{
	  case IPOSELM_MSG_COMMAND:
		errCode=iposELMCPEEvntHandler(pCpePe, pEocMsg);
		break;

	  case IPOSELM_MSG_FILE:
		errCode=iposELMCPEiFftpHandler(pCpePe,pEocMsg);
		break;

	  case IPOSELM_MSG_RESPONSE:
		errCode=iposELMCmdCoreResp(&(pCpePe->cmdHandler),pEocMsg);
		break;

	  default:
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf( "Unknown message class %d in iposELMCPEEntry\n", msgClass );
#endif
		break;
	}
}

int
iposELMCPEGetEventLogResp(
	ipos_port_id pid,
	U8 uid,
	U8 status,
	U32 theEventLogSize,
	U32 theEventLogCheckSum
)
{
	ipos_elm_cpe			*pCpePe;
	int				 errCode;
	U8				 msgLen = 0;
	U8		 		 msgBuf[ MAX_MSG_SIZE ];
	iposelm_select_event_log_resp	 msgStruct;

	pCpePe = iposELMGetCpePe( pid );
	if (pCpePe == NULL)
	{
		return( IPOS_ERROR );
	}

	iposELMCmdSetCtrlHdr(
			&(msgStruct.ctrlHdr),
			 IPOSELM_MSG_GET_EVENT_LOG,
			 (status == IPOS_SUCCESS) ? IPOSELM_ACK_ACK : IPOSELM_ACK_NACK,
			 uid
	);

	msgStruct.eventLogInfo.checkSum = 0;
	if (status == IPOS_SUCCESS)
	{
		msgStruct.eventLogInfo.size = theEventLogSize;
		msgStruct.eventLogInfo.checkSum = theEventLogCheckSum;
	}
	else
	{
		msgStruct.eventLogInfo.size = 0;
		msgStruct.eventLogInfo.checkSum = 0;
	}

	pCpePe->fileInfo = msgStruct.eventLogInfo;

	msgLen = iposELMStruct2Msg( &msgStruct, IPOSELM_MSG_GET_EVENT_LOG, &msgBuf[ 0 ] );

	errCode = iposELMSendMsg( pid, &msgBuf[ 0 ], msgLen );

/* If the event log is empty, the CO modem is not going to proceed.  Set transfer state to idle */

	if (msgStruct.eventLogInfo.size < 1)			/* TT 938 */
	  pCpePe->stateXfer = IPOSELM_CPE_XFER_IDLE;		/* TT 938 */

	return( IPOS_SUCCESS );
}

app_cpe_elm		cpeAppElm[MAX_NUM_OF_PORTS];	/* the cpe application object	*/

app_cpe_elm *
getELMCpeApp( ipos_port_id pid )
{
	int	lineNum;
	if(getLineNum(pid, &lineNum)!=IPOS_SUCCESS)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf("Failed to get the ELM object \n");
#endif
		return	NULL;
	}

	if(lineNum>MAX_NUM_OF_PORTS)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf("port index of %d out of range in getELMCpeApp\n", lineNum);
#endif
		return	NULL;
	}

	lineNum=lineNum-1;
	return(&cpeAppElm[lineNum]);
}

static	void
cpeELMGetEventLogEvnt(ipos_port_id pid, U8 uid, iposelm_event_log_choice *pEventLogChoice )
{
	app_cpe_elm		*pApp;
	eELMTypeEventLog	 eThisEventLogType =
					(eELMTypeEventLog) (pEventLogChoice->eventLogOption);
	U32			 thisEventLogSize = 0, thisEventLogCheckSum = 0;

   /*printf( "cpeELMGetEventLogEvnt called for port b%dp%d, UID: %d, event log: %d\n",
	      pid.bmeNum, pid.portNum, uid, pEventLogChoice->eventLogOption );*/
	pApp=getELMCpeApp(pid);
	if (pApp == NULL)
	  return;

	switch (eThisEventLogType)
	{
	  case eELM_CURRENT_BME_LOG:
	  case eELM_SAVED_BME_LOG:
		/*printf( "Requesting the current BME event log\n" );
		printf( "Would look at 0x%lx, for %d bytes\n",
			 pApp->pCpePe->addrEventLog, DEFAULT_EVENT_LOG_SIZE );*/
		/*printf( "this event log size: %ld\n", thisEventLogSize );*/
		if (eThisEventLogType == eELM_SAVED_BME_LOG)
		  readEventLogFromFlash( DEFAULT_EVENT_LOG_SIZE );

		if (pApp->pCpePe != NULL)
		{
			if (pApp->pCpePe->addrEventLog != NULL)
			{
				thisEventLogSize = iposSizeofEventLog(
					pApp->pCpePe->addrEventLog, DEFAULT_EVENT_LOG_SIZE
				);
				thisEventLogCheckSum = iposRFMGetCheckSum(
					pApp->pCpePe->addrEventLog, thisEventLogSize
				);
			}
			else				/* something's wrong */
			{
				thisEventLogSize = 0;
				thisEventLogCheckSum = 0;
			}

			pApp->pCpePe->fileInfo.size = thisEventLogSize;
			pApp->pCpePe->fileInfo.checkSum = thisEventLogCheckSum;
		   /*printf( "get current BME event log, size: %ld, check sum: %ld\n",
		     pApp->pCpePe->fileInfo.size, pApp->pCpePe->fileInfo.checkSum
		   );*/
			pApp->pCpePe->stateXfer = IPOSELM_CPE_GET_EVENT_LOG;
		}
		else
		{
#ifdef ELM_DIAGNOSTIC_DEBUG
			printf(
		    "Cannot get CPE PE object in cpeELMGetEventLogEvnt for port b%dp%d\n",
		     pid.bmeNum, pid.portNum
			);
#endif
		}
		iposELMCPEGetEventLogResp(
			pid, uid, IPOS_SUCCESS, thisEventLogSize, thisEventLogCheckSum
		);
		break;

	  case eELM_NEW_BME_LOG:
	  {
		int	errCode = IPOS_SUCCESS;

	/* a new BME log should not be done in the context of a callback
	   tests show it takes from 500 ms to 1 s for iposGetBmeEventLog to complete
	   here an OAMP job is submitted, to the blocking OAMP task for the bme   */

		errCode = submitJobNewBmeEventLog( pid.bmeNum, uid );
		if (errCode != IPOS_SUCCESS )
		{
			iposELMCPEGetEventLogResp( pid, uid, errCode, 0, 0 );
		}
		else
		{
			if (pApp->pCpePe != NULL)
		  	  pApp->pCpePe->stateXfer = IPOSELM_CPE_GET_EVENT_LOG;
		}
		/*printf( "completed initial response to get new BME event log\n" );*/
	  }
	  break;

	  case eELM_HOST_CPU_LOG:
	  default:
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf( "Requesting an unsupported event log\n" );
#endif
		iposELMCPEGetEventLogResp( pid, uid, IPOS_ERROR, 0, 0 );
		break;
	}
}

static int
iposELMCPERegGetEventLogReq( ipos_port_id pid, iposELMGetEventLogReq pHandler )
{
	ipos_elm_cpe	*pCpePe;

	pCpePe=iposELMGetCpePe(pid);
	if(pCpePe==NULL)
	{
		return IPOS_ERROR;
	}

	pCpePe->pEvntGetEventLogReq=pHandler;
	return	IPOS_SUCCESS;
}

int	cpeELMAppInit( void )
{

	int i;
	int	errCode;
	ipos_port_id pid;
	app_cpe_elm	*pAppCpe;
	ipos_elm_cpe	*pCpePe;

	/* inititialize the timers	*/
	errCode=iposTmrInit();
	if(errCode!=IPOS_SUCCESS)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf("cpeELMAppInit: Timer Initialization Failed \n");
#endif
		return	errCode;

	}

	/* initialize the ELM CPE	*/
	
	errCode=iposELMCPEInit();
	if(errCode!=IPOS_SUCCESS)
	{
#ifdef ELM_DIAGNOSTIC_DEBUG
		printf("cpeELMAppInit: CPE ELM iPOS Initialization Failed \n");
#endif
		return	errCode;

	}
	/* initialize the app object	*/
	for(i=0;i<MAX_NUM_OF_PORTS;i++)
	{

		pAppCpe=&cpeAppElm[i];
		/* get the app object	*/
		errCode=getBmePortId(i+1, &pid);	/* even if portID is not valid, continue on init */
		pAppCpe->pid=pid;
		
		/* get ELM CPE object	*/
		pCpePe=iposELMGetCpePe(pid);
		pAppCpe->pCpePe=pCpePe;

		/* current Connection State is idle	*/
		pAppCpe->currConnectionState=0;
		pAppCpe->cntConnectionAttempt=0;

		/* current displayLevel is 1	*/
		pAppCpe->displayLevel=1;
		
		/* register event handlers */
		iposELMCPERegGetEventLogReq( pid, cpeELMGetEventLogEvnt );
	}

	return	IPOS_SUCCESS;
}

#endif  /* VTU_R */
