/**************************************************************
***************************************************************
**
** Host Application, Copyright (C) 2000-2002
** Ikanos Communication, 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:49 $
**************************************************************/

/*******  Include Files         ***************************************/
#include <stdio.h>
#include <string.h>
#include "appconfig.h"
#include "ipos.h"
#include "dapi.h"
#include "apidef.h"
#include "apilocal.h"
#include "oampdef.h"
#include "oampstruct.h"
#include "oampproto.h"
#include "bmeconfig.h"
#include "pprofile.h"
#include "oampdb.h"
#include "portmap.h"
#include "autoStart.h"
#include "apposmacro.h"
#include "bmetl.h"
#include "uiUtil.h"
#include "notchBnd.h"
#include "elmdef.h"

extern void dump (int iNum);
extern int getdump (int bmeNum);
//extern int sysClkRateGet (void); /*IXDP425 */
extern void bmeRelCpu (tBmeStruct *pBme,unsigned char enable);
extern void bmeHwResetApi (int BmeNum);
extern void setclk (tBmeStruct *pBme, int num);
extern	void InitDmaChannel15 (tBmeStruct *bmeStruct);
extern	HWAPI_RET_VAL InitEMIConfig (tBmeStruct *bmeStruct);

extern int okToDumpLog;
extern ipos_port_profile sPortProfiles[];
extern tBmeStruct BmeStruct[];
extern	int	doConsoleTimeOut;

int okToDumpLog = 0;
int autoStart = 0;
int	notResetBme = 0;				/* initial state: reset BME	*/

#ifdef VTU_O
static int profilenum = 1;
#else		
static int profilenum = 2;
#endif
static unsigned char bmeHBCnt[IPOS_MAX_BME];

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

          F U N C T I O N     I N T E R F A C E S 

************************************************************************
***********************************************************************/
void heartBeat (ipos_port_id pid, U8 uid, U32 upar, int status,
                ipos_system_status *pREPORT)
{ 
  bmeHBCnt[pid.bmeNum - 1] = 0;
}

void autoStartBME (int BandPlan)
{

#define MAX_WAIT_IN_SECOND 6

  static char pTlStr[256];
  int i, j[IPOS_MAX_BME + 1], nextState[IPOS_MAX_BME + 1];
  int portNum[IPOS_MAX_BME + 1];
  int bmeBandPlan;
  ipos_port_id pid;
  U8 pktMode, done, waitASecond;
  int lineNum;


  for (i = 1; i <= IPOS_MAX_BME; i++)
  {
    j[i] = -1;
    nextState[i] = uREADY;
    portNum[i] = 1;
  }
  do
  {
    done = 1;
    waitASecond = 0;
    for (i = 1; i <= IPOS_MAX_BME; i++)
    {
      switch (oampGetBmeState(i))
      {
        case uREADY:
          if (nextState[i] == uREADY)
          {
            sprintf(pTlStr,"perrep:99:%i:0:7:20:30;", i);	
            if (ReceiveTLCommand ((U8*)pTlStr) == 0)
            {
              nextState[i] = uIDLE;
              j[i] = 0;
              done = 0;
            }
          }
          break;
        case uIDLE:
          if ((nextState[i] == uIDLE) || (nextState[i] == uREADY))
          {
            printf ("\nProvisioning BME %d...", i);
            bmeBandPlan = getBmeBandPlan (BandPlan);


            if (oampGetUtopiaMode == 0x80 || oampGetUtopiaMode == 0x81)
              pktMode = 128;      // PTM mode
            else if(oampGetUtopiaMode == 0xc0 || oampGetUtopiaMode == 0xc1)
              pktMode = 0xc0;      // EFM mode
            else
              pktMode = 0;        // ATM mode

            //printf ("\nChanging port profile #%d BAND_PLAN=0x%x PTM MODE=0x%x", profilenum, bmeBandPlan, pktMode);
            sprintf(pTlStr,"sysprov:0:%i:33:55:17185:1:%i:53:0:%d:%d;",
                    i, pktMode, bmeBandPlan, IPOS_MAX_PORTS / IPOS_MAX_BME);

            if (ReceiveTLCommand ((U8*)pTlStr) == 0)
            {
              nextState[i] = uRUN;
              j[i] = 0;
              done = 0;
              setPortMap(i, bmeBandPlan);	   		/* set the port mapping	*/
            }
          }
          break;
        case uRUN:
          pid.bmeNum = i;
          pid.portNum = portNum[i];
          switch (oampGetPortState(pid))
          {
            case uDISABLE:
              if (nextState[i] == uRUN)
              {
                if ((getLineNum(pid, &lineNum)) == IPOS_SUCCESS)
                {
		  profilenum=ProfileMapping[lineNum];
                  printf ("\nUsing port profile #%d", profilenum);
                  sprintf (pTlStr,"pprov:0:%i:%i:%i;", pid.bmeNum, pid.portNum,
                          profilenum);
                  ReceiveTLCommand ((U8*)pTlStr);
                }
                j[i] = -1;
                if (++(portNum[i]) > IPOS_MAX_PORT_PER_BME)
                {
                  portNum[i] = (IPOS_MAX_PORT_PER_BME > 1)? 5 : 1;
                  j[i] = 0;
                  nextState[i] = uREADY;
                }
                done = 0;
              }
#if (IPOS_MAX_PORT_PER_BME > 1)
              else
              {
                if (j[i] == MAX_WAIT_IN_SECOND)
                {
                  if (++(portNum[i]) > IPOS_MAX_PORT_PER_BME)
                    portNum[i] = 1;
                  if (portNum[i] == 5)
                    j[i] = -1;
                  else
                    done = 0;
                }
              }
#endif
              break;
            case uENABLE:
              if (j[i] != -1)
              {
		getLineNum(pid, &lineNum);
		profilenum=ProfileMapping[lineNum];

                if (sPortProfiles[profilenum].OptionParms.PortOption & 0x1)
                  sprintf(pTlStr,"pinst:0:%i:%i;",pid.bmeNum,pid.portNum);
                else
                  sprintf(pTlStr,"pstart:0:%i:%i;", pid.bmeNum, pid.portNum);
                ReceiveTLCommand ((U8*)pTlStr);
#if (IPOS_MAX_PORT_PER_BME > 1)
                done = 0;
                j[i] = MAX_WAIT_IN_SECOND;
                if (++(portNum[i]) > IPOS_MAX_PORT_PER_BME)
                  portNum[i] = 1;
                if (portNum[i] == 5)
#endif
                  j[i] = -1;
              }
              break;
            default:
              break;
          }
          break;
        default:
          break;
      }
      if ((j[i] >= 0) && (j[i] < MAX_WAIT_IN_SECOND))
      {
        j[i]++;
        done = 0;
        waitASecond = 1;
      }
    }
    if (waitASecond)
      iposTaskDelay (CLOCKS_PER_SEC); // Gives up processor.
  } while (!done);
}

void autoRestart (void)
{
	static char pTlStr[256];
  static unsigned char startCnt[IPOS_MAX_PORTS + 1];
  int bmeNum;
  int portNum;
  unsigned char loopCount = 0;
  unsigned int waitedTime;
  int bmeBandPlan;
  int i, startPort, len;
  ipos_port_id Pid[IPOS_MAX_BME + 1];
  ipos_api_bme	*pApiBme;
  
  U8 pktMode;

  // printf("Fusiv autoRestart() : is called \n");
  for (i = 0; i < IPOS_MAX_BME; i++)
  {
    bmeHBCnt[i] = 0;
    Pid[i + 1].bmeNum = i + 1;
    Pid[i + 1].portNum = 0;
    iposSetCbStatusReport(Pid[i + 1], 0x88, heartBeat);
    Pid[i + 1].portNum = 1;
  }
  for (i = 1; i <= IPOS_MAX_PORTS; i++)
		startCnt[i] = 0;
  while (1)
  {
    iposTaskDelay (oampGetAutoStartScanTime * CLOCKS_PER_SEC); // Wait in seconds.
    for (bmeNum = 1; bmeNum <= IPOS_MAX_BME; bmeNum++)
    {
      switch (oampGetBmeState(bmeNum))
      {
        case uREADY:
          sprintf(pTlStr,"perrep:99:%i:0:7:20:30;", bmeNum);	
          ReceiveTLCommand ((U8*)pTlStr);
          break;

        case uIDLE:
        case uRUN:
          if (++bmeHBCnt[bmeNum - 1] >= 45)
          {
            U8 *eventLogShadow;
            U32 eventLogSize;

            pApiBme=(ipos_api_bme *) iposGetBmeHandle(bmeNum);
            i = 0;
            if(iposSemTake(pApiBme->semBme, IPOS_WAIT_FOREVER) == OS_SUCCESS)
            {

              if (notResetBme==0)	/* not reset BME, PIO read directly */
              {
                bmeRelCpu (&BmeStruct[bmeNum],FALSE); /* hold BME cpu */

                /* Add BME speed change HERE */

                bmeHwResetApi(bmeNum);
                iposTaskDelay(10);


#ifdef P2CO
                setclk(&BmeStruct[bmeNum],157);
#else
                setclk(&BmeStruct[bmeNum],148);
#endif

                InitDmaChannel15 (&BmeStruct[bmeNum]);

                /* 3. Initialize & program the EMI interface */
                InitEMIConfig (&BmeStruct[bmeNum]);	

              }
              else
              {
                doConsoleTimeOut=0;		/* not doing console time out */
                autoStart=0;			/* if not reset BME: disable auto start */
              }

              bmePioRead (&BmeStruct[bmeNum], 0x40008300, (BYTE *)&i);
              printf("BME 0x40008300: %d\n", i);

              iposSemGive(pApiBme->semBme);
            }

            // reset MSGbuf
            oampBmeStateReset(bmeNum);
            oampBmeMarkHasCrashed( bmeNum, i );
            bmeHBCnt[bmeNum - 1] = 0;

            // Dump BME EventLog on terminal
            if (okToDumpLog)
            {
              printf("#########################################################\n");
              printf("###########       B M E   D U M P      ##################\n");
              printf("#########################################################\n");
              if (!getdump(bmeNum))
                dump( 200);
              printf("#########################################################\n");
              printf("#########################################################\n");
            }

            /*  call to sysGetEventLogAddr here must match the call to the same
              routine in updateFlashProf / writeEventLogsToFlash (oampdb.c)	*/

            eventLogShadow = sysGetEventLogAddr( 0 );		/* 0 -> local log */
            iposGetBmeEventLog (bmeNum, eventLogShadow, DEFAULT_EVENT_LOG_SIZE,
                                eELM_BME_IS_HUNG, 0, 0, NULL);
            eventLogSize = iposSizeofEventLog (eventLogShadow,
                                               DEFAULT_EVENT_LOG_SIZE );
            printf( "Event log extracted after crash found to be %ld bytes\n",
                    eventLogSize );

            /* write the event log to flash memory here ... */

            updateFlashProf();
          }	/* if (bmeHBCnt) */
        default:
          break;
      }

      if (autoStart)
      {
        switch (oampGetBmeState(bmeNum))
        {
          case uDOWN:
            if (oampGetCmdState(bmeNum) != uCMD_IN_PROGRESS)
            {

              iposMsgBufInit(IPOS_MAX_MSG);				/* Release all msg pool */
              oampBmeStateReset(bmeNum);
              sprintf(pTlStr,"breset:0:%i;",bmeNum);
              ReceiveTLCommand ((U8*)pTlStr);
            }
            break;
          case uIDLE:
            if (oampGetCmdState(bmeNum) != uCMD_IN_PROGRESS)
            {
              bmeBandPlan = getBmeBandPlan (oampGetBandPlan);


              if (oampGetUtopiaMode == 0x80 || oampGetUtopiaMode == 0x81)
                pktMode = 128;      // PTM mode
              else if(oampGetUtopiaMode == 0xc0 || oampGetUtopiaMode == 0xc1)
                pktMode = 0xc0;      // EFM mode
              else
                pktMode = 0;        // ATM mode

              printf ("\nChanging port profile #%d BAND_PLAN=0x%x PTM MODE=0x%x", profilenum, bmeBandPlan, pktMode);
              sprintf(pTlStr,"sysprov:0:%i:33:55:17185:1:%i:53:0:%d:%d;",
                      bmeNum, pktMode, bmeBandPlan, IPOS_MAX_PORTS / IPOS_MAX_BME);

              ReceiveTLCommand ((U8*)pTlStr);
              setPortMap(bmeNum, bmeBandPlan);	   		/* set the port mapping	*/
            }
            break;
          case uRUN:
            startPort = Pid[bmeNum].portNum;
            pTlStr[0] = '\0';
            do
            {
              if (getLineNum(Pid[bmeNum], &portNum) == IPOS_SUCCESS)
              {
                switch (oampGetPortState(Pid[bmeNum]))
                {
                  case uDISABLE:

		    profilenum=ProfileMapping[portNum];

                    sprintf (pTlStr,"pprov:0:%i:%i:%d;", bmeNum, Pid[bmeNum].portNum,
                             profilenum);
                    break;

                  case uENABLE:
                    if (startCnt[portNum] == 0)
                    {
                      if ((startCnt[portNum] = loopCount) == 0)
                        startCnt[portNum] = 1;
                    }
                    else
                    {
                      waitedTime = loopCount;
                      if (startCnt[portNum] > loopCount)
                        waitedTime += 0x100;
                      waitedTime -= startCnt[portNum];
                      waitedTime *= oampGetAutoStartScanTime;
#ifdef VTU_O
#define STOP_START_WAIT 0
#else
#define STOP_START_WAIT 0
#endif
#if (STOP_START_WAIT > 0)
                      if (waitedTime >= STOP_START_WAIT)
#endif
                      {
			profilenum=ProfileMapping[portNum];
                        if (sPortProfiles[profilenum].OptionParms.PortOption & 0x1)
                        {
                          sprintf(pTlStr,"pinst:0:%i:%i;",bmeNum,Pid[bmeNum].portNum);
                        }
                        else
                        {
                          sprintf(pTlStr,"pstart:0:%i:%i;", bmeNum, Pid[bmeNum].portNum);
                        }
                      }
                    }
                    break;

                  case uSTOP:
                    sprintf (pTlStr,"pstop:0:%i:%i;",bmeNum, Pid[bmeNum].portNum);
                    break;

                  default:
                    break;
                }
              }
              if ((len = strlen(pTlStr)) <= 0)
              {
                if (++(Pid[bmeNum].portNum) > IPOS_MAX_PORT_PER_BME)
                  Pid[bmeNum].portNum = 1;
              }
            } while ((len <= 0) && (Pid[bmeNum].portNum != startPort));

            if ((len > 0) && (ReceiveTLCommand ((U8*)pTlStr) == 0))
            {
              startCnt[portNum] = 0;
              if (++(Pid[bmeNum].portNum) > IPOS_MAX_PORT_PER_BME)
                Pid[bmeNum].portNum = 1;
            }
            break;
          default:
            break;
        }
      }
    }
    loopCount++;
  }
}
