#include "archinc.h"
#include "cli.h"
#include "strutil.h"
#include "eventq.h"
#include "zlregs.h"
#include "zl_event.h"
#include "zarlink.h"

#ifdef CONFIG_INCLUDE_ZARLINK

#include <stdio.h>
#include <stdlib.h>

static void handleCtrl1RxEvent(void);
static void handleCtrl2RxEvent(void);

static int ctl1showHandler(int argc, char * argv[], int flags);
static int ctl2showHandler(int argc, char * argv[], int flags);

static unsigned short ctrl1Data16[20];
static unsigned short ctrl2Data16[20];

int decodeIntFrame(unsigned char *pFrameData)
{
  unsigned char intPort;
  unsigned long rmonOverflowBits;
  int bufLen;
  char * pOutBuf;

  int lsChange = 0;
  int modDetectChange = 0;
  int lhbChange = 0;
  int qosChange = 0;

  union {
    unsigned char u8[4];
    unsigned long u32;
  } u;

  // TODO: loop until all ctrl1 buffers retrieved and
  // processed before re-enabling interrupts

  pOutBuf = clicharGetOutputBuffer(&bufLen);

  if (pFrameData == NULL)
    return -1;

  // ensure it's an interrupt frame
  if ((pFrameData[0] != 0x70) || (pFrameData[1] != 0x00)) 
    return -1;

  intPort = pFrameData[6];

  u.u8[0] = pFrameData[8];
  u.u8[1] = pFrameData[9];
  u.u8[2] = pFrameData[10];
  u.u8[3] = pFrameData[11];
  rmonOverflowBits = u.u32;

  if (rmonOverflowBits != 0) {
    zarlinkRmonCounterOverflow(intPort, rmonOverflowBits);
    }

  if ((pFrameData[11] & 0x40) != 0) {
    lsChange = 1;
    // Link status change
    }

  if ((pFrameData[12] & 0x01) != 0) {
    modDetectChange = 1;
    // module detect status change
    }

  if ((pFrameData[12] & 0x04) != 0) {
    lhbChange = 1;
    // LHB status change
    }

  if ((pFrameData[12] & 0x20) != 0) {
    qosChange = 1;
    // QoS status change
    }

  sprintf(pOutBuf, "port[%02x] LnkStat[%d] MOD[%d] LHB[%d] Qos[%d]\r\n",
    intPort, lsChange, modDetectChange, lhbChange, qosChange);

  clicharSendOutputBuffer(pOutBuf, bufLen);    
  
  return 0;
}


int zarlinkCtrlRetrieveCtrl1(unsigned short *pCtrl1Buffer)
{
  int i;

  for(i=0;i<40/2;i++) {
    pCtrl1Buffer[i] = zarlinkCtrlBuffer1Read();
    }
  zarlinkCommandWrite(0x02);

  return 0;
}

int zarlinkCtrlRetrieveCtrl2(unsigned short *pCtrl2Buffer)
{
  int i;
  for(i=0;i<40/2;i++) {
    ctrl2Data16[i] = zarlinkCtrlBuffer2Read();
    }
  zarlinkCommandWrite(0x04);

  return 0;
}

static void handleCtrl1RxEvent(void)
{
  // TODO: loop until all ctrl1 buffers retrieved and
  // processed before re-enabling interrupts
  zarlinkCtrlRetrieveCtrl1(ctrl1Data16);
  decodeIntFrame((unsigned char *)ctrl1Data16);
}

static void handleCtrl2RxEvent(void)
{
  zarlinkCtrlRetrieveCtrl2(ctrl2Data16);
}

static int ctl1showHandler(int argc, char * argv[], int flags)
{
  // strutilHexdump((char *)(ctrl1Data16), 40);
  // zarlinkEventUnmaskIrq(INT_CONTROL_FRAME1);
  return 0;
}

static int ctl2showHandler(int argc, char * argv[], int flags)
{
  // strutilHexdump((char *)(ctrl2Data16), 40);
  // zarlinkEventUnmaskIrq(INT_CONTROL_FRAME2);
  return 0;
}

static int ctl1getHandler(int argc, char * argv[], int flags)
{
  zarlinkCtrlRetrieveCtrl1(ctrl1Data16);
  return 0;
}

static int ctl2getHandler(int argc, char * argv[], int flags)
{
  zarlinkCtrlRetrieveCtrl2(ctrl2Data16);
  return 0;
}

int zarlinkControlInit(void)
{
  // register event handlers for CTRL1 and CTRL2 events
  eventqRegisterHandler(SWITCH_CTRL1_RX, handleCtrl1RxEvent);
//  eventqRegisterHandler(SWITCH_CTRL2_RX, handleCtrl2RxEvent);
  
  cliRegisterCommand("ctl1show", ctl1showHandler, "ctl1show - show CTRL1 buffer");
//  cliRegisterCommand("ctl2show", ctl2showHandler, "ctl2show - show CTRL2 buffer");
  cliRegisterCommand("ctl1get", ctl1getHandler, "ctl1get - read CTRL1 buffer");
//  cliRegisterCommand("ctl2get", ctl2getHandler, "ctl2get - read CTRL2 buffer");

  return 0;
}

#endif

