/***************************************************************************/
/* example_exception.c
 * 
 * Simple example of how exception/signal handling works.
 * 
 * Build:  
 *  $COMMONCC -o example_exception example_exception.c $VMELIBS
 *
 * One of the #define lines below to choose the exception policy 
 * or none of them for the default.
 *
 *#define EXAMPLE_DEFAULT 
 *        By default the bus error signal is capture mainly to do
 *        a defined cleanup before the exit is executed. 
 *
 *#define EXAMPLE_PRINT
 *        The bus error signal will be captured and a message will
 *        be printed to standard output but no exit() is executed.
 * 
 *#define EXAMPLE_NONE 
 *        does not capture any bus error signal which will actually
 *        by system default means a quick exit. But you can capture
 *        the signal in your own program.
 *
 *#define EXAMPLE_CHECK
 *        captures the bus error signal and sets a variable which
 *        should be tested with the call VmeCheckException(). 
 */
/***************************************************************************/
#define EXAMPLE_PRINT

#include <stdio.h>
#include <sys/types.h>
#include <time.h>

#include "Vme.h"

#define VME_MAP_ADDRESS 0x10000000
#define VME_MAP_SIZE    1024*1024  /* 1 MB */ 
#define VME_MAP_AM      0x09       /* Extended VME address */

/***************************************************************************/
main (int argc, char *argv[])
/*---------------------------
*/
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
{
  u_long vme_address = VME_MAP_ADDRESS;
  int    cid, signal_nr;
  volatile int data;
  int    *vme_base;
/*.........................................................................*/

  /* Use a different VME base address if specified.
   */
  if ((argc==2)&&(sscanf(argv[1],"%x",&vme_address)!=1))
    {
      printf("Usage: %s <vme-base-address>\n",argv[0]);
      exit(1);
    }
  
  /* Define the exception handling policy.
   */  
#ifdef EXAMPLE_PRINT
  VmeSetExceptionHandling(Vme_EXCEPTION_PRINT);
#endif
#ifdef EXAMPLE_NONE
  VmeSetExceptionHandling(Vme_EXCEPTION_NONE);
#endif
#ifdef EXAMPLE_CHECK
  VmeSetExceptionHandling(Vme_EXCEPTION_CHECK);
#endif

  /* Open a VME channel for Programmed I/O.
   */
  cid = VmeOpenChannel("Example1","pio");
  if (cid < 0 ) 
    exit(1);
  
  /* Map VME address space.
   */
  vme_base = (int *)VmeMapAddress(cid,vme_address,VME_MAP_SIZE,VME_MAP_AM);
  if (vme_base == NULL)
    exit(1);
  
  /* We try to access two times a maybe wrong address 
   * to see the result of a bus error.
   */
  printf("Reading from VME address 0x%x \n",vme_address);
  Vme_D32READ(vme_base, &vme_base[0], data);
#ifdef EXAMPLE_CHECK
  if (signal_nr=VmeCheckException())
    {
      printf("... read failed, signal number = %d\n",signal_nr);
      if (signal_nr = SIGBUS)
	{
	  int bus_error_type = VmeGetBusErrorType();
	  switch (bus_error_type)
	    {
	    case Vme_BUS_ERROR_TYPE_TIMEOUT:
	      printf("... this was a timeout bus error\n");
	      break;
	    case Vme_BUS_ERROR_TYPE_TIMEOUT:
	      printf("... this was a bus error from the slave\n");
	      break;
	    default:
	      printf("... unknown bus error type (timeout or from slave)\n");
	      break;
	    }
	}
    }
  else
    printf("... 0x%x read\n",data);
#endif

  printf("Reading from VME address 0x%x again ...\n",vme_address);
  Vme_D32READ(vme_base, &vme_base[0], data);
#ifdef EXAMPLE_CHECK
  if (signal_nr=VmeCheckException())
    printf("... read failed, signal number = %d\n",signal_nr);
  else
    printf("... 0x%x read\n",data);
#endif

  /* Close Vme channel. Do not forget to call this function
   * before you exit otherwise you might get some trouble later.
   */
  (void)VmeCloseChannel(cid);
}