/**************************************************************
$Workfile:   msgbuf.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:51 $
***************************************************************/

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

#include "ipos.h"
#include "time.h"

ipos_msg_buf	iposMsg[IPOS_MAX_MSG+1];               /* index 0 is not used	*/
ipos_msg_buf	*iposMsgRdyLst;

/* oamp_cb_msg defined in ipos.h */

U8		iposDataBuf[IPOS_MAX_MSG][ sizeof( oamp_cb_msg ) ];

void iposMsgFreeTimeout();

int	iposMsgBufInit(int	numMsgBuf)
{

	int	i;
	
	iposMsgRdyLst=&(iposMsg[1]);		/* initial state: all buffer are ready	*/

	for(i=1;i<IPOS_MAX_MSG;i++)
	{

		iposMsg[i].index=i;
		iposMsg[i].pNextMsg=(ipos_msg_buf *) &iposMsg[i+1];
		iposMsg[i].len=0;
		iposMsg[i].flag=IPOS_MSG_NOTUSED;
		iposMsg[i].pDataBuf=(void *) &(iposDataBuf[i-1][0]);
		iposMsg[i].start_timestamp=0;

	}

/* the last one		*/
	iposMsg[i].pNextMsg=NULL;
	iposMsg[i].len=0;
	iposMsg[i].pDataBuf=(void *) &(iposDataBuf[i-1][0]);

	return(IPOS_SUCCESS);

}


ipos_msg_buf	*iposMsgGet()
{
	int	intLevel;
	ipos_msg_buf	*pNewMsg;
	struct tm  	timeStamp;

	intLevel=iposIntLock();			/* protection	*/


/*	if(iposMsgRdyLst==NULL)
	{
		iposMsgFreeTimeout();
	}
*/


	if(iposMsgRdyLst!=NULL)
	{
		pNewMsg=iposMsgRdyLst;

        pNewMsg->flag=IPOS_MSG_USED;
		
		pNewMsg->len=0;

		iposMsgRdyLst=pNewMsg->pNextMsg;
	
		time(&pNewMsg->start_timestamp);

		localtime_r(&pNewMsg->start_timestamp,&timeStamp);
		
/*		printf ("\niposMsgGet idx: %i %.2i:%.2i:%.2i "
				,pNewMsg->index,(int)timeStamp.tm_hour
				,(int)timeStamp.tm_min
				,(int)timeStamp.tm_sec);
*/		
		iposIntUnlock(intLevel);
		
		return	(pNewMsg);
	}

	
	iposIntUnlock(intLevel);
	return(NULL);
}


int iposMsgFree(ipos_msg_buf *msgBuf)
{
	int	intLevel;
//	struct tm  	timeStamp;
//	time_t present_time;

	intLevel=iposIntLock();						/* protection	*/
	
	msgBuf->pNextMsg=iposMsgRdyLst;

	msgBuf->start_timestamp=0;
	
/*	time (&present_time);

	localtime_r(&present_time,&timeStamp);
		
	printf ("\niposMsgFree idx %i %.2i:%.2i:%.2i"
				,msgBuf->index,(int)timeStamp.tm_hour
				,(int)timeStamp.tm_min
				,(int)timeStamp.tm_sec);
*/
	
/*	printf ("\nipos idx: %is present %is start %is diff %is",msgBuf->index,(UINT32)present_time,(UINT32) msgBuf->start_timestamp,
			(UINT32)(present_time-msgBuf->start_timestamp));
*/

		//difftime(time(&present_time),msgBuf->start_timestamp)

	msgBuf->flag=IPOS_MSG_NOTUSED;				/* msg not used	*/
	msgBuf->cbSet=IPOS_MSG_CALLBACK_NOTSET;		/* callback not set	*/
	msgBuf->tick=0;								/* callback tick=0 */

	iposMsgRdyLst=msgBuf;
	


	iposIntUnlock(intLevel);
	return(IPOS_SUCCESS);
}


void iposMsgFreeTimeout()
{
	int	i, intLevel;
	ipos_msg_buf	*pMsg;
	time_t present_time;

	intLevel=iposIntLock(); /* any procedure access msgbuf must be atomic	*/

	for(i=0;i<IPOS_MAX_MSG;i++)
	{		
		pMsg=iposMsgFindMsg(i);

		if(pMsg==NULL) 
		{
			iposIntUnlock(intLevel);
			printf("Can't find valid iposMsgBuf. Fatal\n");	/*should always have msg buf available */

		}

		if(pMsg->cbSet==IPOS_MSG_CALLBACK_SET) 	/* check msg_buf with callback pending */
		{
		
			if( difftime( time(&present_time), pMsg->start_timestamp) >= 3000 )
			{					
#ifdef VTU_O		
			//iposMsgFree (pMsg); 
#endif

			}
		}

	}

	iposIntUnlock(intLevel);

}


int iposMsgGetLen(ipos_msg_buf	*msgBuf)
{
	
	return(msgBuf->len);

}


int	iposMsgPutData(ipos_msg_buf *msgBuf, int len,  void	*pSource)
{

	if(len>IPOS_MSG_LEN) return(IPOS_ERROR);

	msgBuf->len=len;
	
	memcpy(msgBuf->pDataBuf,pSource,len);

	return(IPOS_SUCCESS);

}


int	iposMsgGetData(ipos_msg_buf *msgBuf, int *plen, void *pDest)
{

	*plen=msgBuf->len;
    
	memcpy(pDest, msgBuf->pDataBuf, *plen);
	
	return(IPOS_SUCCESS);

}



int	iposMsgGetIndex(ipos_msg_buf *pBuf)
{
	return pBuf->index;

}


ipos_msg_buf *iposMsgFindMsg(int index)
{


	if(index>IPOS_MAX_MSG||index<1)
	{
		return NULL;
	}

	return &iposMsg[index];

}


void	iposMsgShow(int option)		/* option 0:brief report, 1: detailed report */
{

	int	i, cnt_used, cnt_unused;

	cnt_used=0;
	cnt_unused=0;

	for(i=1;i<IPOS_MAX_MSG;i++)
	{

		if(iposMsg[i].flag==IPOS_MSG_USED)
		{
			if(option==1)
			{

				printf("\nIPOS used msg info: \n");

				printf("	index=%d, pNextMsg=0x%x, len=%d, pDataBuf=0x%x\n",
						i, (unsigned int)iposMsg[i].pNextMsg, iposMsg[i].len,
							(unsigned int)iposMsg[i].pDataBuf);

				
				printf("	cbSet=%d, pCb=%lx, UID=%ld, uPar=%ld\n",
						iposMsg[i].cbSet, iposMsg[i].usrData[0], iposMsg[i].usrData[1],iposMsg[i].usrData[4]);
				
						
				printf("	bmeNum=%ld,portNum=%ld\n",	 	
				
							iposMsg[i].usrData[2],iposMsg[i].usrData[3]);

			}
			cnt_used++;
		}

		else
		{
			cnt_unused++;
		}

	}
	
	printf("\nIPOS msg info: number of buffers in use: %d, number of freed buffers: %d\n", cnt_used, cnt_unused);
}
