/******************************************************************************/
/*                       Copyright 2001 Broadcom Corporation                  */
/*                                                                            */
/* This material is the confidential trade secret and proprietary information */
/* of Broadcom Corp.  It may not be reproduced, used, sold or transferred to  */
/* any third party without the prior written consent of Broadcom Corp.        */
/* All rights reserved.                                                       */
/******************************************************************************/
/*   FileName        : bcm_utils.c                                            */
/*   Purpose         : Usefull routines for toplevel applications             */
/*   Limitations     : None                                                   */
/*   Author          : Emmanuel Hanssens                                      */
/*   Creation Date   : 27-Nov-2001                                            */
/*   History         : Compiled by CVS                                        */
/******************************************************************************/
/*   $Id: bcm_utils.c,v 1.42 2004/09/27 15:33:11 hanssens Exp $  */
/******************************************************************************/

#include <stdio.h>
#include <string.h>
#include "bcm_utils.h"
#include "bcm_globalObject.h"
#include "bcm_loadImages.h"
#include "bcm_boot.h"
#include "bcm_hmiCoreServices.h"
#include "bcm_errorHandler.h"
#ifndef NO_HOST_ACCESS
# include "bcm_hostFunctions.h"
# include "bcm_interrupt.h"
#endif

/************************************************ */
/* {{{ showSelfTestOutput: print out failing test */
/************************************************ */
void showSelfTestOutput(SelfTest *selfTest)
{
  int i;
  uint32 mask;

  for (i=0, mask=1; i<32; i++, mask<<=1)
  {
    if (selfTest->progress & mask)
      printf("POST output: test %i did not complete or has not been started\n", 
             i);
    else if (selfTest->results & mask)
      printf("POST output: test %i failed\n", i);
  }
}
/* }}} */
/************************************************ */
  
/*********************************************************** */
/* {{{ initBcmDev: load images and boot BCM6410 if requested */
/*********************************************************** */
void initBcmDev(DevObject *devPtr)
{
#ifndef UDP_PHY
  static int imagesLoaded = 0;
  extern int skipBoot;
  SelfTest selfTest;
#else
  BCM_UNUSED_PARAMETER(devPtr);
#endif
  
#ifndef NO_HOST_ACCESS
  hostDriverInit();
#endif

#ifndef UDP_PHY
/* booting is done via bootp protocol for ipdslam */
  if (! skipBoot)
  {
    static TargetImage bootImage, fwImage;
    
    if (! imagesLoaded)
    {
      loadImages(&bootImage, &fwImage);
      imagesLoaded = 1;
    }
    
    switch (boot(&bootImage, &fwImage, devPtr->devId, &selfTest))
    /* {{{ process boot service result */
    {
        case BCM_SUCCESS:       /* nothing to do */
			printf("Device %d: Initialize Success.\n", devPtr->devId);
          break;

        case BCM_BOOTER_NO_START:
          if ((selfTest.progress | selfTest.results) != 0)
          {
            showSelfTestOutput(&selfTest);
            FATAL_ERROR("Device %d: booter did not start, and POST failed",
                        devPtr->devId);
          }
          else
            FATAL_ERROR("Device %d: booter did not start, while POST passed",
                        devPtr->devId);
          break;

        case BCM_BOOTER_POST_FAILED:
          showSelfTestOutput(&selfTest);
          FATAL_ERROR("Device %d: booter did start, while POST failed",
                      devPtr->devId);
          break;

        case BCM_DOWNLOAD_PROBLEM:
          FATAL_ERROR("Device %d: downloading firmware image failed",
                     devPtr->devId);
          break;

        case BCM_FIRMWARE_NO_START:
          if ((selfTest.progress | selfTest.results) != 0)
          {
            showSelfTestOutput(&selfTest);
            FATAL_ERROR("Device %d: firmware did not start, and POST failed",
                        devPtr->devId);
          }
          else
            FATAL_ERROR("Device %d: firmware did not start, while POST passed",
                        devPtr->devId);
          break;

        case BCM_FIRMWARE_POST_FAILED:
          showSelfTestOutput(&selfTest);
          FATAL_ERROR("Device %d: firmware did start, while POST failed",
                      devPtr->devId);
          break;

    } 
    /* }}} */
  }
  else
#endif
  {                             /* need to wait for target ready */
#ifndef NO_HOST_ACCESS
    int res = BCM_SUCCESS;
    extern int doReset;
    
    HostDev *hostDev = hostOpen(devPtr->devId);
    hostInit(hostDev);

    if (doReset)
    {
      /* reset the BCM6410 */
      hostResetBCM6410(hostDev);
      res = waitForTargetReady(hostDev);
    }
    
# ifndef BCM_NO_SELFTEST_CHECK
    hostGetSelfTest(hostDev, &selfTest);
    hostClose(hostDev);
    if (res != BCM_SUCCESS)
    {
      if ((selfTest.progress | selfTest.results) != 0)
      {
        showSelfTestOutput(&selfTest);
        FATAL_ERROR("Device %d: firmware did not start, and POST failed",
                    devPtr->devId);
      }
      else
        /* this may not be fatal, if the fw ready interrupt was already read */
        /* by other means, so we just give a warning */
        SOFT_ERROR(0,
        "Device %d: firmware did not start, while POST passed (probably OK)",
                   devPtr->devId);
    }
    else if ((selfTest.progress | selfTest.results) != 0)
    {
      showSelfTestOutput(&selfTest);
      FATAL_ERROR("Device %d: firmware did start, while POST failed",
                  devPtr->devId);
    }
# endif
#endif
  }
}
/* }}} */
/************************************************************ */

/***************************** */
/* {{{ Get firmware image info */
/***************************** */
int GetFirmwareInfo(DevObject *devPtr)
{
  CALL_HMIQA_REQ(GetFirmwareVersionInfo, devPtr, CORE_MANAGER_ID,
                 &devPtr->fwVersion);
  
  printf("Chip Id: %lx\n", devPtr->fwVersion.hwChipId);
  printf("ADSL firmware release: %02d.%02d.%02d\n",
         devPtr->fwVersion.fwMajorVersion, devPtr->fwVersion.fwMinorVersion,
         devPtr->fwVersion.fwFixVersion);
  printf("HMI protocol: %d.%d\n",
         devPtr->fwVersion.hmiMajorVersion, devPtr->fwVersion.hmiMinorVersion);
  printf("Firmware info: %s\n", devPtr->fwVersion.info);

  /* check hmi version matches */
  if (devPtr->fwVersion.hmiMajorVersion != HMI_MAJOR_VERSION ||
      devPtr->fwVersion.hmiMinorVersion != HMI_MINOR_VERSION)
    SOFT_ERROR(0, "HMI version mismatch (fw %d_%d, ref code %d_%d)",
               devPtr->fwVersion.hmiMajorVersion,
               devPtr->fwVersion.hmiMinorVersion,
               HMI_MAJOR_VERSION, HMI_MINOR_VERSION);
    
  /* check to see whether correct number of lines per device */
  if (devPtr->fwVersion.nrOfLinesSupportedInFirmwareVersion != BCM_DEV_NB_LINES)
    SOFT_ERROR(0, "Firmware supports %d lines, ref code expects %d lines",
               devPtr->fwVersion.nrOfLinesSupportedInFirmwareVersion,
               BCM_DEV_NB_LINES);

  if (strstr(devPtr->fwVersion.info, "Annex C") != NULL) 
    return ANNEX_C;
  else if (strstr(devPtr->fwVersion.info, "Annex I") != NULL) 
    return ANNEX_I;
  else if (strstr(devPtr->fwVersion.info, "Annex A") != NULL) 
    return ANNEX_A;
  else 
    return ANNEX_B;
}
/* }}} */
/***************************** */

/****************************************** */
/* {{{ reference code global initialisation */
/****************************************** */
void GlobalInit()
{
  uint8 devId, lineId;

  /* first initialise the drivers and the BCM6410 (boot) */
//  hmiDriverInit();
//  initGlobalObject();
//  for (devId=3; devId<NB_BCM_DEV; devId++)
  for (devId=3; devId<5; devId++)
  {
    DevObject *devPtr = getDevPtr(devId);

    /* init dev & line objects */
    initDevObject(devId);
    for (lineId = devId*BCM_DEV_NB_LINES;
         lineId < min((devId+1)*BCM_DEV_NB_LINES, NB_LINES);
         lineId++)
      initLineObject(lineId, devPtr);
    
    /* boot the device */
    initBcmDev(devPtr);

    /* open the hmi driver */
    devPtr->hmiDev = hmiOpen(devId);
    hmiInit(devPtr->hmiDev);
    devPtr->devState = DEVICE_HMI_READY;

    /* get image info (same for all dev -> only get for devId 0) */
    if (devId == 0)
      GetFirmwareInfo(devPtr);
    else
      devPtr->fwVersion = getDevPtr(0)->fwVersion;
    
    /* Configure the Core Manager application */
    if (ConfigureDevice(devPtr) != BCM_SUCCESS)
      FATAL_ERROR("Can't configure the device %d", devId);
  }
}
/* }}} */
/****************************************** */

