#include "archinc.h"
#include "cli.h"
#include "eventq.h"
#include "timer0.h"
#include "zarlink.h"
#include "zl_bus.h"
#include "zl_event.h"
#include "zlregs.h"
#include "zl_trunk.h"
#include "portmgr.h"

#include <stdio.h>
#include <stdlib.h>

#ifdef CONFIG_INCLUDE_ZARLINK

static int lhbHandler(int myArgc, char * myArgv[], int flags);

int zarlinkLhbRxTimeout(int port)
{
  unsigned char u8temp;

  // reset timeout bit
  u8temp = zarlinkIndexedRead(ECR4P_ADDR(port));
  zarlinkIndexedWrite(ECR4P_ADDR(port), (u8temp & ~0x40));
  timer0Delay(1);
  zarlinkIndexedWrite(ECR4P_ADDR(port), u8temp);

  // notify port manager
  portmgrPortEventNotify(port, PORT_EVENT_LHB_TMOUT);

  return 0;
}


int zarlinkLhbRxDetect(int port)
{
  // notify port manager
  portmgrPortEventNotify(port, PORT_EVENT_LHB_DETECT);

  return 0;
}


int zarlinkLhbSetup(int port, boolean enable)
{
  unsigned char ecr3, ecr4;

  ecr3 = zarlinkIndexedRead(ECR3P_ADDR(port));
  ecr4 = zarlinkIndexedRead(ECR4P_ADDR(port));

  if (enable == true) {
    // enable receive
    zarlinkIndexedWrite(ECR3P_ADDR(port), (ecr3 | 0x80)); // receive

    // reset the timeout bit
    zarlinkIndexedWrite(ECR4P_ADDR(port), (ecr4 & ~0x40));
    timer0Delay(1);

    // enable transmit
    zarlinkIndexedWrite(ECR4P_ADDR(port), (ecr4 | 0x40)); // xmit
    }
  else {
    zarlinkIndexedWrite(ECR3P_ADDR(port), (ecr3 & ~0x80)); // receive
    zarlinkIndexedWrite(ECR4P_ADDR(port), (ecr4 & ~0x40)); // xmit
    }

  return 0;
}

int zarlinkLhbInit(void)
{
  int i;

  // Initialize link heartbeat timer
#if 0
  zarlinkIndexedWrite(LHBTIMER, 0x80); // 0x80 * 512 bit time = x10000 bit time
#else
  zarlinkIndexedWrite(LHBTIMER, 0xff); // 0xff * 512 bit time 
#endif

  // data sheet says that LHBREG1 goes on the link 'first'
  zarlinkIndexedWrite(LHBREG0,  0x12); // data sheet: "we recommend h00-12"
  zarlinkIndexedWrite(LHBREG1,  0x00); // data sheet: "we recommend h00-12"


  // disable on all ports
  for(i=0;i<NUM_ALL_PORTS;i++) {
    zarlinkLhbSetup(i, false);
    }

  cliRegisterCommand("lhb", lhbHandler, "lhb [(e)nable | (d)isable)] [portNum] - change LHB status");

  return 0;
} 

static int lhbHandler(int myArgc, char * myArgv[], int flags)
{
  int retVal = -1;
  int bufLen;
  int lhbPort;
  char * pOutBuf;
  boolean doDisable;
  char * pCh;

  pOutBuf = clicharGetOutputBuffer(&bufLen);

  if (myArgc < 3)
    return -1;

  lhbPort = atoi(myArgv[2]);

  if ((lhbPort < 0) || (lhbPort >= NUM_ALL_PORTS))
    return -1;

  pCh = myArgv[1];

  switch(*pCh) {
    case 'e':
    case 'E':
      retVal = portmgrLhbStatusRequest(lhbPort, LHB_STATUS_ENABLED);
      sprintf(pOutBuf, "%s: port [%d] LHB enabled\r\n", myArgv[0], lhbPort);
      clicharSendOutputBuffer(pOutBuf, bufLen);
      break;
    case 'd':
    case 'D':
      retVal = portmgrLhbStatusRequest(lhbPort, LHB_STATUS_DISABLED);
      sprintf(pOutBuf, "%s: port [%d] LHB disabled\r\n", myArgv[0], lhbPort);
      clicharSendOutputBuffer(pOutBuf, bufLen);
      break;
    }

  return retVal;
}




#endif /* CONFIG_INCLUDE_ZARLINK */

