/******************************************************************************/
/*                       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_interrupt.c                                        */
/*   Purpose         : Various interrupt related functions                    */
/*   Limitations     : None                                                   */
/*   Author          : Emmanuel Hanssens                                      */
/*   Creation Date   : 20-Sep-2001                                            */
/*   History         : Compiled by CVS                                        */
/******************************************************************************/
/*   $Id: bcm_interrupt.c,v 1.16 2004/10/20 10:12:08 hanssens Exp $  */
/******************************************************************************/

#include <stdio.h>
#include "bcm_interrupt.h"
#include "bcm_errorHandler.h"
#include "bcm_timer.h"

/* {{{ waitForInterrupt: */

/* Poll (with time out) the BCM6410 interrupt reg until the */
/* expectedInterrupt is seen. */

int waitForInterrupt(HostDev *dev, uint8 expectedInterrupt, MyTime timeOut)
{
#ifdef NO_INTERRUPT_POLLING

  BCM_UNUSED_PARAMETER(dev);
  BCM_UNUSED_PARAMETER(expectedInterrupt);
  
  goSleep(timeOut);             /* sleep a minimum */
  
#else
  
  int    stop = 0;
  uint8  data;
  MyTime myTime;
# ifndef NO_STDOUT_PRINT
  extern int device_offset;
# endif
  
  /* install timer */
  startTimer();

  data = 0;
  while (!data && !stop) 
  {
    /* wait until timeout or until interrupt is seen */
    data = hostReadInterruptStatus(dev);

    if (data & ~expectedInterrupt)
    {
      /* we have seen an interrupt but it is not the expected one => report */
# ifndef NO_STDOUT_PRINT
      printf("Unexpected interrupt %#x seen for device %d\n",
             data & ~expectedInterrupt, dev->devId + device_offset);
# endif
      data &= expectedInterrupt; /* mask them */
    }
    
    if (!data)
    {
      /* check for time out */
      stop = compareTimer(timeOut);
      goSleep(sleepTime);       /* sleep to avoid constant polling */
    }
  }
  
  /* disable timer */
  getTimer(&myTime);
  stopTimer();
  
  if (stop)
# ifndef NO_FULL_ERROR_HANDLING
    /* timeout on interrupt */
    return SOFT_ERROR(EHOSTINTO, hostErr[EHOSTINTO]);
# else
    return BCM_FAILURE;
# endif 
# ifndef NO_STDOUT_PRINT
  else
    printf("Interrupt %#x detected for device %d after %ld sec %ld usec\n",
           expectedInterrupt, dev->devId + device_offset,
           myTime.sec, myTime.usec);
# endif
#endif

  return BCM_SUCCESS;
}

/* }}} */

/* {{{ polling functions on device readyness */
int waitForBooterReady(HostDev *dev)
{
  return waitForInterrupt(dev, INTERRUPT_BOOTER_READY, booterReadyTimeOut);
}

int waitForTargetReady(HostDev *dev)
{
  return waitForInterrupt(dev, INTERRUPT_DEVICE_READY, fwReadyTimeOut);
}
/* }}} */

/* {{{ printInterrupt: */

void printInterrupt(HostDev *dev)
{
#ifndef NO_STDOUT_PRINT
  uint8  data;
  extern int device_offset;
  
# define CHECK_AND_PRINT_INT(INT)\
  if (data & INT)                                                       \
    do {                                                                \
      printf("Device %d, %s received (%#x)\n",                          \
             dev->devId + device_offset, #INT, data);                   \
      data &= ~INT;                                                     \
    } while (0)
  
  data = hostReadInterruptStatus(dev);

  CHECK_AND_PRINT_INT(INTERRUPT_WATCHDOG_TIMER);
  CHECK_AND_PRINT_INT(INTERRUPT_DEVICE_READY);
  CHECK_AND_PRINT_INT(INTERRUPT_DEVICE_MAJOR_EXCEPTION);
  CHECK_AND_PRINT_INT(INTERRUPT_DEVICE_MINOR_EXCEPTION);
  CHECK_AND_PRINT_INT(INTERRUPT_BOOTER_READY);
  CHECK_AND_PRINT_INT(INTERRUPT_REPLY_AVAILABLE);
  
  if (data)
    printf("Device %d, unknown interrupt received (%#x)\n",
           dev->devId + device_offset, data);
#else
  BCM_UNUSED_PARAMETER(dev);
#endif
}

/* }}} */


