#include "archinc.h"
#include "cli.h"
#include "clichar.h"
#include "zarlink.h"
#include "zl_event.h"
#include "zl_bus.h"
#include "zlregs.h"

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

#ifdef CONFIG_INCLUDE_ZARLINK

extern char cpuMacAddr[];

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);

#if 0
  // issue software reset to all the PHYs
  for(i=8;i<14;i++) {
    zarlinkMiiWrite(i, 0, 0x8000);
    }
#endif

  // 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;

  // enable all ports
  for(i=0;i<6;i++) {
    zarlinkIndexedWrite(ECR4P_ADDR(i), 0x18);
    }

  // enable receive of runt packets (<64b)
  for(i=0;i<6;i++) {
    zarlinkIndexedWrite(ECR3P_ADDR(i), 0x01);
    }

  // force all fiber ports to 100BaseT, FDX
  for(i=0;i<4;i++) {
    zarlinkIndexedWrite(ECR1P_ADDR(i), 0xd9);
    }

  // enable statistics engine
  zarlinkIndexedWrite(FEN, STATISTIC_COUNTER_ENABLE);

  // support multicast
  zarlinkIndexedWrite(PVMODE, IP_MULTICAST_ENABLE);

  // Initialize Link heartbeat timer
  zarlinkIndexedWrite(LHBTIMER, 0x80); // 0x80 * 512 bit time = x10000 bit time
  zarlinkIndexedWrite(LHBREG0,  0x5a); // MAC control frame opcode = "ZL"
  zarlinkIndexedWrite(LHBREG1,  0x4c);

  //
  // CPU port configuration
  //
  zarlinkCpuMacAddrSet(cpuMacAddr);

  // 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);

  // tell the switch to start
  zarlinkIndexedWrite(GCR, INIT_DONE);

  return 0;
}

#endif /* CONFIG_INCLUDE_ZARLINK */

