/**************************************************************
$Workfile:   systemState.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 $
***************************************************************/
#include <stdio.h>

//#define	DEBUG	


#include "ipos.h"

#include "appconfig.h"
#include "apperrCode.h"
#include "oamp.h"
#include "pprofile.h"
#include "portmap.h"

eoamp_port_state    tstPState=uENABLE;      /* test state	*/

extern oamp_bme oampBme [IPOS_MAX_BME+1];

void
oampBmeMarkNotCrashed( int bmeNum )
{
    oamp_bme *pOampBme;

    pOampBme = getBmeOampHandle(bmeNum);
    if (pOampBme == NULL)
    {
        printf( "\ncannot get handle for BME %d in oampBmeMarkNotCrashed\n", bmeNum );
        return;
    }

    pOampBme->bmeHasCrashed = 0;
    pOampBme->bmeErrorCode = 0;
}

void
oampBmeMarkHasCrashed( int bmeNum, int bmeErrorCode )
{
    oamp_bme *pOampBme;

    pOampBme = getBmeOampHandle(bmeNum);
    if (pOampBme == NULL)
    {
        printf( "\ncannot get handle for BME %d in oampBmeMarkHasCrashed\n", bmeNum );
        return;
    }

    pOampBme->bmeHasCrashed = 1;
    pOampBme->bmeErrorCode = bmeErrorCode;
}

int
oampBmeHasItCrashed( int bmeNum )
{
    oamp_bme *pOampBme;

    pOampBme = getBmeOampHandle(bmeNum);
    if (pOampBme == NULL)
    {
        printf( "\ncannot get handle for BME %d in oampBmeMarkHasCrashed\n", bmeNum );
        return( 0 );
    }

    return( pOampBme->bmeHasCrashed );
}

int
oampGetBmeErrorCode( int bmeNum )
{
    oamp_bme *pOampBme;

    pOampBme = getBmeOampHandle(bmeNum);
    if (pOampBme == NULL)
    {
        printf( "\ncannot get handle for BME %d in oampGetBmeErrorCode\n", bmeNum );
        return( 0 );
    }

    return( pOampBme->bmeErrorCode );
}

/* initial state: BME: Down, Port Disables; command state idle	*/
/*  ... and NOT crashed */

void    oampStateResetAll(void)
{

    int i;

    for (i=1;i<=MAX_NUM_OF_BMES;i++)
    {
        oampBmeStateReset(i);
        oampBmeMarkNotCrashed(i);
    }
}

void    oampPortStateReset(ipos_port_id pid)
{


}

void    oampBmeStateReset(int bmeNum)
{
    int j;
    ipos_port_id pid;
    int lineNum;
    oamp_bme *pOampBme;

    pid.bmeNum = bmeNum;


    pOampBme = getBmeOampHandle(bmeNum);
    pOampBme->bmeState=uDOWN;
    pOampBme->cmdState=uCMD_IDLE;
   	
    for (j=1;j<=MAX_PORTS_PER_BME;j++)
    {
        pOampBme->oampPort[j].portState=uDISABLE;
        pid.portNum = j;
	getLineNum(pid, &lineNum);
    	pOampBme->oampPort[j].pPortProfile=&sPortProfiles[ProfileMapping[lineNum]];
    }

    return;
}


/********************************************************
 
 update the port state	
 
 Input:	 event, portid 
 
 
 Output:	the new state for the port 
 
*********************************************************/

eoamp_port_state    oampStateUpdate(ipos_port_id pid,eoamp_event    event)
{

    int bmeNum,portNum;
    int portState = uENABLE;
    oamp_bme    *pOampBme;

    bmeNum=pid.bmeNum;
    portNum=pid.portNum;

    pOampBme=getBmeOampHandle(bmeNum);

    /* cmd event: update the cmd status	*/
    if (event==CMD_IN_PROGRESS)
    {
        pOampBme->cmdState=uCMD_IN_PROGRESS;

    } else
    {
        pOampBme->cmdState=uIDLE;
    }

    if (portNum > 0)
    {
        portState=pOampBme->oampPort[portNum].portState;

#ifdef	DEBUG
        printf("b%dp%d	event %d, portstate before event %d\n", bmeNum, portNum,event, portState);
#endif


        switch (portState)
        {
            
            case    uENABLE:
                {
                    switch (event)
                    {
						case ePORT_START:       
						case ePORT_INSTANTIATE:
                            portState=uACTIVATING;
                            break;

                        case ePORT_DESTROY:
                            portState=uDISABLE;
                            break;

                        default:
                            break;
                    }

                }
                break;

            case uACTIVATING:

                {
                    switch (event)
                    {
                        case ePORT_START_COMPLETE:
						case ePORT_INSTANTIATE:
                            portState=uSHOWTIME;
                            break;

                        case   ePORT_STOP:
                            portState=uENABLE;
                            break;

                        case ePORT_DESTROY:
                            portState=uDISABLE;
                            break;
                        case ePORT_LB_START_COMPLETE:
                            portState = uLOOPBACK;
           break;
                        case CMD_FAILED:
                            portState=uENABLE;
                            break;

                        default:
                            break;
                    }
                }

                break;

            case uSTOP:
            case uSHOWTIME:
                {
                    switch (event)
                    {
                        case ePORT_RESET:
                            portState=uSHOWTIME;
                            break;

                        case ePORT_STOP:
                            portState=uENABLE;
                            break;

                        case ePORT_DESTROY:
                            portState=uDISABLE;
                            break;

                        case eSTOP_PORT:
                            portState = uSTOP;
                            break;
                        default:
                            break;
                    }

                }

                break;

            case    uDISABLE:

                {
                    switch (event)
                    {
                        case ePORT_PROVISION:
                            portState=uENABLE;
                            break;

                        default:
                            break;
                    }

                }

                break;

	case uLOOPBACK:
		{
         switch(event)
         {
         	case ePORT_RESET:
          		portState=uLOOPBACK;
          		break;

         	case ePORT_STOP:
            	portState=uENABLE;
          		break;

         	case ePORT_DESTROY:
         		 portState=uDISABLE;
           		break;

           	case eSTOP_PORT:
            	 portState = uSTOP;
             	break;
         	default:
           		break;
         }

      	}
		break;
            default:
                printf("b%dp%d Fatal error: unknown port state \n", bmeNum, portNum);
                return	OAMP_ERROR_UNKNOWN_PORTSTATE;

        }

        pOampBme->oampPort[portNum].portState=portState;
    }

#ifdef DEBUG
    printf("portstate after event %d \n", portState);
#endif	
    return portState;
}



/********************************************************
 
 update the bme state	
 
 Input:	 event, portid 
 
 
 Output:	the new state for the port 
 
*********************************************************/


eoamp_bme_state oampBmeStateUpdate(int bmeNum,eoamp_event   event)
{


    int bmeState;
    oamp_bme    *pOampBme;


    pOampBme=getBmeOampHandle(bmeNum);

    /* cmd event: update the cmd status	*/
    if (event == eBME_RESTART_INPROGRESS)
    {
        pOampBme->cmdState=uCMD_IN_PROGRESS;
        bmeState=uDOWN;
    } else
    {
        if (event==CMD_IN_PROGRESS)
            pOampBme->cmdState=uCMD_IN_PROGRESS;
        else
            pOampBme->cmdState=uCMD_IDLE;

        bmeState=pOampBme->bmeState;

#ifdef	DEBUG
        printf("b%dp0	event %d, bmestate before event %d\n", bmeNum,event, bmeState);
#endif


        /* RUN state	*/
        switch (bmeState)
        {
            case  uIDLE:                      /* IDLE state	*/
                if (event == eSYSTEM_PROVISION)
                    bmeState=uRUN;
                break;

            case uREADY:
                if (event == ePORT_PPREPORT_ENABLE)
                    bmeState = uIDLE;
                break;

            case  uDOWN:                  /* DOWN state	*/
                switch (event)
                {
                    case  eBME_START:
                    case  eBME_RESTART_COMPLETE:
                        bmeState=uREADY;
                        break;

                    default:
                        break;
                }
                break;

            case  uRUN:
                break;

            default:
                printf("b%dp0 Fatal error: unknown BME state \n", bmeNum);
                return	OAMP_ERROR_UNKNOWN_BMESTATE;
        }
    }

    pOampBme->bmeState=bmeState;

#ifdef	DEBUG	
    printf("bme state after event %d \n", bmeState);
#endif	
    return	bmeState;
}



eoamp_bme_state oampGetBmeState(int bmeNum)
{

    oamp_bme    *pOampBme;

    pOampBme=getBmeOampHandle(bmeNum);

    return pOampBme->bmeState;
}


eoamp_port_state oampGetPortState(ipos_port_id pid)
{
    int bmeNum,portNum;
    int portState;
    oamp_bme    *pOampBme;

    bmeNum=pid.bmeNum;
    portNum=pid.portNum;
    if ((bmeNum > IPOS_MAX_BME) || (portNum > IPOS_MAX_PORT_PER_BME))
    {
      printf ("\n Error: Illegal BME/Port Number!!");
      return uDOWN;
    }

    pOampBme=getBmeOampHandle(bmeNum);

    portState=pOampBme->oampPort[portNum].portState;

    return	portState;

}

eoamp_cmd_state oampGetCmdState(int bmeNum)

{

    oamp_bme    *pOampBme;

    pOampBme=getBmeOampHandle(bmeNum);

    return pOampBme->cmdState;
}

void dumpAllBmeStatus(void)
{
    int i;
    oamp_bme *pOampBme;

    for (i = 1; i <= MAX_NUM_OF_BMES; i++)
    {
        pOampBme = getBmeOampHandle(i);
        printf("\nBME #%d States: 0x%x, CMD_STATE: 0x%x", i, pOampBme->bmeState,
               pOampBme->cmdState);
    }
}

void dumpAllPortStatus(void)
{

    int i, j, portNum = 1;
    oamp_bme *pOampBme;

    for (i = 1; i <= MAX_NUM_OF_BMES; i++)
    {
        pOampBme = getBmeOampHandle(i);
        for (j=1;j<=MAX_PORTS_PER_BME;j++)
        {
            printf("\nPort #%d States: 0x%x, Profile #%d", portNum++,
                   pOampBme->oampPort[j].portState,
                   pOampBme->oampPort[j].pPortProfile->PortProfileNum);
        }
    }
    return;
}

/******************************************************************************
*                                                                             *
* Function.. : oampPortStateStop                            	                *
*                                                   	                        *
* Purpose... : Reads the part number and version number from the INI FPGA     *
*              and copy it to the array as a string.                          *
*									                                                            *
* Parameters : Array Pointer                                                  *
*                                                                             *
* Returns... : None                                                           *
*                                                                             *
******************************************************************************/
void oampPortStateStop ( int bmeNum, int portNum)
{
  oampBme[bmeNum].oampPort[portNum].portState = uSTOP;
}

void oampHost_HotReset_StateUpdate(ipos_port_id pid, oamp_cb_msg *pMsg)
{
  int count;
  int i;
  int bme_provisioned;
  int ports, port;
  oamp_bme    *pOampBme;
  int showtime_port [MAX_NUM_OF_PORTS], showtime_count = 0;

  count = 0;
  bme_provisioned = pMsg->par[count++];
  ports = pMsg->par[count++];
    
  pOampBme=getBmeOampHandle (pid.bmeNum);
  //printf("Number of Ports is %x\n", ports);
  //printf("Current BME State is %x\n", pOampBme->bmeState);

  if (bme_provisioned)
    pOampBme->bmeState = uRUN;

  //printf("New BME State is %x\n",pOampBme->bmeState);

  for (i = 0; i <ports; i++) {
    port = pMsg->par[count++];


    if (pMsg->par[count] & 0x4) {
      pOampBme->oampPort[port].portState = uSHOWTIME;
      showtime_port [showtime_count++] = port;
    }
    else if (pMsg->par[count] & 0x2)
      pOampBme->oampPort[port].portState = uACTIVATING;
    else if (pMsg->par[count] & 0x1)
      pOampBme->oampPort[port].portState = uENABLE;

    count++;

  }

  printf ("\n");
  if (showtime_count == 0)
    printf ("No ports are in Showtime\n");
  else if (showtime_count == 1) {
    printf ("Port %d is in showtime\n", showtime_port[0]);
  } else {
    printf ("Ports "); 
    for (i=0; i<showtime_count; i++) {
      printf ("%d", showtime_port[i]);
      if (i+1 < showtime_count)
        printf (", ");
    }
    printf(" are in Showtime\n");
  }
		
}
