#include "archinc.h"
#include "cli.h"
#include "clichar.h"
#include "zarlink.h"
#include "zl_event.h"
#include "zl_util.h"
#include "zl_bus.h"
#include "zlregs.h"

#include <stdio.h>
#include <stdlib.h>

#ifdef CONFIG_INCLUDE_ZARLINK

int zarlinkInit(void)
{
  volatile unsigned long dummy;
  int i;
  int bufLen;
  char * pOutBuf;
  volatile unsigned char probeVal;

  pOutBuf = clicharGetOutputBuffer(&bufLen);

  // probe the 'dead or alive' register to see if bus interface is functional
  for(i=0; i<10; i++ ) {
    probeVal = zarlinkIndexedRead(DA);
    if (probeVal == 0xda) {
      break;
      }
    }

  if (probeVal != 0xda) {
    sprintf(pOutBuf, "\r\nzarlinkInit: ZL50409 not found, dareg[%02x]\r\n",probeVal);
    clicharSendOutputBuffer(pOutBuf, bufLen);
    return -1;
    }

  // magic write to keep switch from resetting if TSTOUT12 is high
  zarlinkIndexedWrite(MASK0, 0x07);
  
  // disable interrupts for the CPU until we're ready
  zarlinkIndexedWrite(INT_MASK0, INT_ALL);

  // start off with port-specific interrupts masked off
  zarlinkEventMaskPorts(0x77);

  // set one microsecond divider to 50 for 50MHz clock
  zarlinkIndexedWrite(USD, 0x50);

  // reset all ports
  for(i=0;i<6;i++) {
    zarlinkIndexedWrite(ECR4P_ADDR(i), 0x98);
    }

  // read an RTC register for some delay
  for(i=0;i<100;i++)
    dummy = CTIME0;

  // negate reset
  for(i=0;i<6;i++) {
    zarlinkIndexedWrite(ECR4P_ADDR(i), 0x18);
    }

#if 0
  // force all fiber ports to 100BaseT, FDX -- no autoneg
  for(i=0;i<4;i++) {
    zarlinkIndexedWrite(ECR1P_ADDR(i), 0xd9);
    }
#endif

  // enable statistics engine
  zarlinkIndexedWrite(FEN, STATISTIC_COUNTER_ENABLE);

  // support multicast
  zarlinkIndexedWrite(PVMODE, IP_MULTICAST_ENABLE);

  // enable CPU port to receive on uni- and multicast queues
  zarlinkIndexedWrite(RQS, 0xff);

  // disable MAC learning on CPU port 
  zarlinkIndexedWrite(ECR2P_ADDR(CPU_PORT), 0x04);

  return 0;
}

void zarlinkInitDone(void)
{
  // tell the switch to start
  zarlinkIndexedWrite(GCR, INIT_DONE);
}
#endif /* CONFIG_INCLUDE_ZARLINK */

