/* devVmebcmS.c */
/* devVmebcmS.c - Device Support Routines for  VME bunch current board */
/*
 *      Original Author: Makoto Tobiyama
 *      Current Author:
 *      Date:            20/Jul/98
 *      Modified         30/Sep/98
 *
 *      Experimental Physics and Industrial Control System (EPICS)
 *
 *      Copyright 1997, KEKB.
 *
 *
 * Modification Log:
 *
 * 07/Jan/1999  Bug fix MT
 * -----------------
 */


#include	<vxWorks.h>
#include	<types.h>
#include	<stdioLib.h>
#include	<string.h>

#include	<vme.h>
#include	<dbDefs.h>
#include	<dbAccess.h>
#include	<recSup.h>
#include	<devSup.h>
#include	<devCamac.h>
#include	<link.h>
#include        <iv.h>
#include	<module_types.h>
#include	<longinRecord.h>
#include	<longoutRecord.h>
#include	<boRecord.h>
#include	<biRecord.h>
#include	<mbbiDirectRecord.h>
#include	<mbboDirectRecord.h>
#include	<waveformRecord.h>

#include	<dbScan.h>

#include        <time.h>
#include        <semLib.h>
#include        <assert.h>


typedef unsigned short Bit16;
typedef unsigned long  Bit32;

/* #define	Base_IO		0x20000 */ /* Std. I/O Address */
#define NUM_INT_CHAN	8
#define MAX_RATE 5000
#define STD_RATE sysClkRateGet()
#define MEM_OFFSET 0x0
static long counter = 0;
SEM_ID semid=NULL;

/*
struct Dvmebcm {
  unsigned long	  board0[10240];
  unsigned long   dum0[6144];
  unsigned long	  board1[10240];
  unsigned long   dum1[6144];
  unsigned long   board2[10240];
  unsigned long   dum2[6144];
  unsigned long	  board3[10240];
  unsigned long   dum3[6144];
  unsigned long	  board4[10240];
  unsigned long   dum4[6144];
  unsigned long	  board5[10240];
  unsigned long   dum5[6144];
  unsigned long	  board6[10240];
  unsigned long   dum6[6144];
  unsigned long	  board7[10240];
  unsigned long   dum7[6144];
  unsigned long	  board8[10240];
  unsigned long   dum8[6144];
  unsigned long	  board9[10240];
  unsigned long   dum9[6144];
  unsigned long	  board10[10240];
  unsigned long   dumA[6144];
  unsigned long	  board11[10240];
  unsigned long   dumB[6144];
  unsigned long	  board12[10240];
  unsigned long   dumC[6144];
  unsigned long	  board13[10240];
  unsigned long   dumD[6144];
  unsigned long	  board14[10240];
  unsigned long   dumE[6144];
  unsigned long	  board15[10240];
  unsigned long   dumF[6144];
  unsigned long	  board16[10240];
  unsigned long   dum10[6144];
  unsigned long	  board17[10240];
  unsigned long   dum11[6144];
  unsigned long	  board18[10240];
  unsigned long   dum12[6144];
  unsigned long	  board19[10240];
  unsigned long   dum13[6144];
  unsigned long	  board20[10240];
  unsigned long   dum14[6144];
  unsigned long	  board21[10240];
  unsigned long   dum15[6144];
  unsigned long	  board22[10240];
  unsigned long   dum16[6144];
  unsigned long	  board23[10240];
  unsigned long   dum17[6144];
  unsigned long	  board24[10240];
  unsigned long   dum18[6144];
  unsigned long	  board25[10240];
  unsigned long   dum19[6144];
  unsigned long	  board26[10240];
  unsigned long   dum1A[6144];
  unsigned long	  board27[10240];
  unsigned long   dum1B[6144];
  unsigned long	  board28[10240];
  unsigned long   dum1C[6144];
  unsigned long	  board29[10240];
  unsigned long   dum1D[6144];
  unsigned long	  board30[10240];
  unsigned long   dum1E[6144];
  unsigned long	  board31[10240];
  unsigned long   dum1F[6144];
  unsigned short  cntl1;
  unsigned short  dum20;
  unsigned short  cntl2;
  unsigned short  dum21;
  unsigned short  stop1;
  unsigned short  dum22;
  unsigned short  stop2;
  unsigned short  dum23;
  unsigned long   dummy[524284];
};
*/
/* struct Dvmebcm {
  unsigned long	  board[32][16384];
  unsigned short  cntl1;
  unsigned short  dum20;
  unsigned short  cntl2;
  unsigned short  dum21;
  unsigned short  stop1;
  unsigned short  dum22;
  unsigned short  stop2;
  unsigned short  dum23;
  unsigned long   dummy[524284];
  };*/
struct Dvmebcm {
  unsigned long   board[8][16384];
  unsigned long   board2[24][16384];
  unsigned long   cntl1;
  unsigned long   cntl2;
  unsigned short  stop1;
  unsigned short  dum22;
  unsigned short  stop2;
  unsigned short  dum23;
  unsigned long   dummy_mem[524284];
};

#define	Status	Enable



static long init_all();
static long init_mi_record();
static long init_bo_record();
static long write_bo();
static long read_mbbiDirect();
void bcm_isr();
static long init_wf_record();
static long get_wf_int_info();
static long read_wf_record();

static int  checkLink();

static int sendek();

static void write_smemek(Bit32*, Bit32*, short, short);
static unsigned long read_smem(Bit32* p);

static void network_error();
static void auxSleep(double howlong);


/* Create the dset for devBovmebcm */
struct {
        long            number;
        DEVSUPFUN       report;         
        DEVSUPFUN       init;   
        DEVSUPFUN       init_record;
        DEVSUPFUN       get_ioint_info;
        DEVSUPFUN       write_bo;       
}devBoVmebcmS={
        5,
        NULL,
        NULL,
        init_bo_record,
        NULL,
        write_bo
};
/* For devMbbiVmebcm  */
struct{
        long            number;
        DEVSUPFUN       report;
        DEVSUPFUN       init;
        DEVSUPFUN       init_mi_record;
        DEVSUPFUN       get_ioint_info;
        DEVSUPFUN       read_mbbiDirect;
}devMbbiVmebcmS={
        5,
        NULL,
        NULL,
        init_mi_record,
        NULL,
        read_mbbiDirect
};

struct {
    long        number;
    DEVSUPFUN   report;
    DEVSUPFUN   init;
    DEVSUPFUN   init_record;
    DEVSUPFUN   get_ioint_info;
    DEVSUPFUN   read_write;
    DEVSUPFUN   conv;
}devWfVmebcmS ={
  6,
  NULL,
  NULL,
  init_wf_record,
  get_wf_int_info,
  read_wf_record,
  NULL
};

struct ioCard {
  volatile struct Dvmebcm     *card; /* address of this card */
  FAST_LOCK                    lock; /* semaphore */
  IOSCANPVT                    ioscanpvt; /* list or records processed upon interrupt */
      };

#define CONST_NUM_LINKS 2
/* #define STATIC  */
#define DEBUG_ON



#define R_MID   (CARD1522 + 0x03)  /* Node ID */
#define R_MINF1 (CARD1522 + 0x07)  /* Memory Information 1 */
#define R_MINF2 (CARD1522 + 0x0B)  /* Memory Information 2 */
#define R_SR    (CARD1522 + 0x0F)  /* Status */
#define R_CMD   (CARD1522 + 0x13)  /* Command */
#define R_HCNT  (CARD1522 + 0x17)  /* Hop Count Register */
#define R_IIVEC (CARD1522 + 0x1B)  /* Internal Interrupt Vector */
#define R_IILEV (CARD1522 + 0x1F)  /* Internal Interrupt Level  */
#define R_EIVEC (CARD1522 + 0x23)  /* External Interrupt Vector */
#define R_EILEV (CARD1522 + 0x27)  /* External Interrupt Level  */
#define R_TITID (CARD1522 + 0x2B)  /* Transfer Interrupt Command ID  */
#define R_TIINF (CARD1522 + 0x2F)  /* Transfer Interrupt Information */
#define R_RIDTD (CARD1522 + 0x33)  /* Receive  Interrupt Command ID  */
#define R_RIINF (CARD1522 + 0x37)  /* Receive  Interrupt Infromation */
#define R_MEM1  ((void*)(CARD1522 + 0x200))
              /* Start addr. of network shared memory */
#define R_MEM2  ((void*)(CARD1522 + 0x2200))

static int            debug_flag = 2;
static unsigned long  Base_IO;
static int            vmebcm_num_links;
static unsigned char  INT_LEVEL = 0x03;
static unsigned short INT_VEC_BASE;

static struct ioCard  cards[CONST_NUM_LINKS];
static int            init_flag = 0;
unsigned long         BASE1522;
char                  *CARD1522;
/* double                cal_fac_bcm_H = 7.8125e-3; */
/* double                cal_fac_bcm_L = 7.8125e-3; */
double               cal_fac_bcm_H = 8.373642e-3;
double               cal_fac_bcm_L = 7.102273e-3;
unsigned char bc_o[5120];
unsigned long ref_dat[2560];

/* static unsigned long (*data)[32]; */

int devVmebcmConfigS(ncards,a32base,intlevel,intvecbase)
int ncards;
long a32base;
int intlevel;
int intvecbase;
{
  vmebcm_num_links = ncards;
  Base_IO = a32base;
  INT_LEVEL = intlevel;
  INT_VEC_BASE = intvecbase;
  logMsg("devVmebcm NumLink= %d BaseIO= %x IntLevel = %d IntVecBase =0x%x\n",vmebcm_num_links,Base_IO,INT_LEVEL,INT_VEC_BASE);

  init_all(0);
}


static long init_all(after)
int after;
{
  int                          cardNum, chanNum;
  unsigned char                probeVal[2];
  volatile  struct Dvmebcm     *p;

  if (init_flag != 0 ) 
   return(OK);


  init_flag = 1;

  /*  data = (unsigned long (*)[32])calloc(10240*32,sizeof(long));
  if (data == NULL)
	{
       logMsg("Cannot allocate buffer\n");
       return(ERROR);
	}
  */
  if (sysBusToLocalAdrs(VME_AM_EXT_SUP_DATA,(char *)Base_IO,(char **)&p) == ERROR)
	{
		logMsg("VmebcmL: cannot find extended address space\n");
		return(ERROR);
	}

  for (cardNum=0; cardNum< vmebcm_num_links; cardNum++)
   {
     if (vxMemProbe((char*) &(p->cntl1), READ, 2, &probeVal[0])< OK)
       {
	 if (debug_flag >0 ) 
         logMsg("No vmebcm with cardNum= %d\n probe= %x\n",cardNum,p);
	 cards[cardNum].card = NULL;
       }
     else
       {
	 if (debug_flag >0)
         logMsg("Found vmebcm with cardNum= %d\n address= %x\n",cardNum,p);
	 cards[cardNum].card = p;  /* Remember address of the board */

	 cards[cardNum].card->cntl2 = 0x40;
	 cards[cardNum].card->cntl1 = 0x01;
	 scanIoInit(&(cards[cardNum].ioscanpvt));
	 FASTLOCKINIT(&(cards[cardNum].lock));
	 FASTUNLOCK(&(cards[cardNum].lock)); /* Init the board lock */
       }
     p++;
   }

  BASE1522=0x30000000;
  if (sysBusToLocalAdrs(VME_AM_EXT_SUP_DATA, (char *)(int)BASE1522,
                        (char **)&CARD1522) == ERROR)
    {
      logMsg("devDvmesw: cannot find extended address space\n");
    }
  
  logMsg("R_MID=0x%x R_MEM1= 0x%x R_MEM2= 0x%x\n",R_MID,R_MEM1,R_MEM2);
  *R_TITID=0xFF; /* reciever ID  3= Linac */
  *R_MINF1=0x80; /* transfer enable */


  return(OK);
}


/**************************************************************************
 *
 * BO Initialization (Called one time for each BO PowerUT card record)
 *
 **************************************************************************/
static long init_bo_record(pbo)
struct boRecord *pbo;
{

        pbo->mask = 1;
		return(0);
}


/**************************************************************************
 *
 * Perform a write operation from a BO record
 *
 **************************************************************************/
static long write_bo(pbo)
struct boRecord *pbo;
{

  short cardN;

  cardN = pbo->out.value.vmeio.card;
  if (checkLink(cardN) == ERROR)
    {
      logMsg("Error--- No vmebcm for card %d\n",cardN);
      return(ERROR);
    }

  FASTLOCK(&(cards[cardN].lock));
  switch(pbo->out.value.vmeio.signal){
  case 0 : 
    cards[cardN].card->cntl1 = 0x01;
    cards[cardN].card->cntl1 = 0x09;
    cards[cardN].card->cntl1 = 0xff0c;
    break;
  case 1 :
    cards[cardN].card->cntl1 = 0x01;
    break;
  }
  FASTUNLOCK(&(cards[cardN].lock));
  return(0);
}

static long init_mi_record(pmbbi)
struct MbbiDirectRecord	*pmbbi;
{
  return(0);
}

static long read_mbbiDirect(pmbbi)
struct mbbiDirectRecord *pmbbi;
{
  short cardN;
  
  cardN = pmbbi->inp.value.vmeio.card;
  if (debug_flag >5) 
   logMsg("read_mbbiDirect called with card %d\n",cardN);

  if (checkLink(cardN) == ERROR)
    return(ERROR);
   
  pmbbi->rval = cards[cardN].card->cntl2;

  if (debug_flag >5)
   logMsg("read complete \n");

        return(CONVERT);
}


void bcm_isr(pwf)
struct waveformRecord	*pwf;
{
  unsigned char mode;
  short cardN;

  cardN = pwf->inp.value.vmeio.card;
  /* cards[cardN].card->cntl1 = 0x01; */
  /*  cards[cardN].card->cntl2 = 0x40; */
  scanIoRequest(cards[cardN].ioscanpvt);
  return;
}

static long init_wf_record(pwf)
struct waveformRecord	*pwf;
{
  short cardNum;
  
  cardNum = pwf->inp.value.vmeio.card;

  if (intConnect(INUM_TO_IVEC(INT_VEC_BASE + cardNum),
		 (VOIDFUNCPTR)bcm_isr, 
		 (int)pwf) != OK)
    logMsg("devbcm: Interrupt connect failed for card %d\n",pwf->inp.value.vmeio.card);
  logMsg("intConnect 0x%X\n",pwf);
  cards[cardNum].card->cntl1 = 0x01;
  sysIntEnable(INT_LEVEL+cardNum);
  logMsg("bcm int set for int 0x%x\n",INT_LEVEL+cardNum);
  cards[cardNum].card->cntl1 = 0x01;
  cards[cardNum].card->cntl1 = 0x09;
  cards[cardNum].card->cntl1 = 0xff0c;
  return(0);
}



/* static long read_wf_record(pwf)
struct waveformRecord	*pwf;
{
  short cardN;
  int i,j,k;
  unsigned long int a1;
 
  unsigned short* us_thing = (unsigned short*)pwf->bptr;
	
  if (debug_flag >5)
    logMsg("read_wf_record called...\n");

  cardN = pwf->inp.value.vmeio.card;
  if (debug_flag >5)
    logMsg("read_wf_record called with card number of %d\n",cardN);

  if (checkLink(cardN) == ERROR)
    return(ERROR);
    cards[cardN].card->cntl1 = 0x01 ;  

  switch(pwf->ftvl)
    {
    case DBF_USHORT: 
	  {
	    switch (pwf->inp.value.vmeio.signal)
	      {
	      case 0: 
		for (j=0; j<32; j++)
		  for (i=0;i<80; i++)
		    {
		      (unsigned long)a1 = (unsigned long)(cards[cardN].card->board[j][i]);
		      us_thing[j*2+i*64] = (short)(a1 & 0xff);
		      us_thing[j*2+1+i*64] = (short)(a1 & 0xff0000)>>16;
		    };  
		break;

	      case 1: 
		for (j=0; j<32; j++)
		  for (i=0;i<80; i++)
		    {
		      a1 = cards[cardN].card->board[j][i];
		      us_thing[i*32+j] = (a1 & 0xff);
		      us_thing[i*32+j+1] = (a1 & 0xff0000)>>16;
		    };
		for (k=1; k<4; k++)
		  for (j=0; j<32; j++)
		    for (i=0;i<80; i++)
		      {
			a1 = cards[cardN].card->board[j][i+80*k];
			us_thing[i*32+j] += (a1 & 0xff);
			us_thing[i*32+1+j] += (a1 & 0xff0000)>>16;
		      };
		break;
	      case 2: 
		for (j=0; j<32; j++)
		  for (i=0;i<80; i++)
		    {
		      a1 = cards[cardN].card->board[j][i];
		      us_thing[i*32+j] = (a1 & 0xff);
		      us_thing[i*32+1+j] = (a1 & 0xff0000)>>16;
		    };
		for (k=1; k<64; k++)
		  for (j=0; j<32; j++)
		    for (i=0;i<80; i++)
		      {
			a1 = cards[cardN].card->board[j][i+80*k];
			us_thing[i*32+j] += (a1 & 0xff);
			us_thing[i*32+1+j] += (a1 & 0xff0000)>>16;
		      };
		break;
	      }
	  }
	pwf->nord=5120;

	break;
    case DBF_SHORT:
    default:
      logMsg("devVmebcm: Invalid data type\n");
    }
  cards[cardN].card->cntl1 = 0x01;
  cards[cardN].card->cntl1 = 0x09;
  cards[cardN].card->cntl1 = 0x0c;
  cards[cardN].card->cntl1 = 0x01;
  cards[cardN].card->cntl1 = 0x09;
  cards[cardN].card->cntl1 = 0x0c;
  if (debug_flag > 5)
    logMsg("devVmebcm:end\n");
  return(0);
}
*/

static unsigned long bc_comb(unsigned char bc_o[], int i)
{
  unsigned long a = 0;
  a = ((unsigned long)(bc_o[i*4])<<24) | ((unsigned long)(bc_o[i*4+1])<<16) | ((unsigned long)(bc_o[i*4+2])<<8) | (unsigned long)(bc_o[i*4+3]);
  return a;
}

static long read_wf_record(pwf)
struct waveformRecord	*pwf;
{
  short cardN;
  int i,j,k;
  unsigned long int a1;
  unsigned long *SMemL, *SMemH;
  short iad,nwd = 4;
  
  unsigned short* us_thing = (unsigned short*)pwf->bptr;
  float* f_thing = (float*)pwf->bptr;
	
  SMemL = (unsigned long*)R_MEM1;
  SMemH = (unsigned long*)R_MEM2;

  if (debug_flag >4)
    logMsg("read_wf_record called...\n");

  cardN = pwf->inp.value.vmeio.card;
  if (debug_flag >5)
    logMsg("read_wf_record called with card number of %d\n",cardN);

  if (checkLink(cardN) == ERROR)
    return(ERROR);
  /* cards[cardN].card->cntl1 = 0x01 ; */
  cards[cardN].card->cntl2 = 0x40;
  cards[cardN].card->cntl1 = 0x01;
  cards[cardN].card->cntl1 = 0x09;

  switch(pwf->ftvl)
    {
    case DBF_USHORT: 
	  {
	    switch (pwf->inp.value.vmeio.signal)
	      {
	      case 0: /*   no average */
		for (j=0; j<8; j++)
		  for (i=0;i<160; i++)
		    {
		      a1=cards[cardN].card->board[j][i+MEM_OFFSET];
		      bc_o[j*4+i*32]= (a1 & 0xff);
		      bc_o[j*4+i*32+1] = (a1 & 0xff0000)>>16;
		      bc_o[j*4+i*32+2] = (a1 & 0xff00)>>8;
		      bc_o[j*4+i*32+3] = (a1 >>24);
		    };
                for (i=0; i<1280; i++)
		  {
		    for (j=0; j<4; j++)
		      {
			us_thing[i*4+j]=bc_o[i*4+j];
		      }
		    ref_dat[i]=bc_comb(bc_o,i);
		  }
		if (cardN==0)  /* for LER */
		  {
		      for (iad=0; iad<1280;iad++){
		     write_smemek(SMemL,ref_dat,iad,nwd);
		    }
		    *R_TIINF = 0xf0;
		    *R_CMD=1; /* inform interrupt */
		  }
		else 
		  {
		     for (iad=0;iad<1280;iad++){
		    write_smemek(SMemH,ref_dat,iad,nwd);
		    }
		    *R_TIINF = 0x00;
		    *R_CMD=1; /* inform interrupt */
		  }
		if (debug_flag >4) logMsg("end of read\n"); 
		break;

	      case 1: /* average 4 */ 
		for (j=0; j<8; j++)
		  for (i=0;i<160; i++)
		    {
		      a1=cards[cardN].card->board[j][i+MEM_OFFSET];
		      us_thing[j*4+i*32]= (a1 & 0xff);
		      us_thing[j*4+i*32+1] = (a1 & 0xff0000)>>16;
		      us_thing[j*4+i*32+2] = (a1 & 0xff00)>>8;
		      us_thing[j*4+i*32+3] = (a1 >>24);
		    };
		for (k=1; k<4; k++)
		  for (j=0; j<8; j++)
		    for (i=0;i<160; i++)
		      {
		      a1=cards[cardN].card->board[j][i+160*k+MEM_OFFSET];
		      us_thing[j*4+i*32] += (a1 & 0xff);
		      us_thing[j*4+i*32+1] += (a1 & 0xff0000)>>16;
		      us_thing[j*4+i*32+2] += (a1 & 0xff00)>>8;
		      us_thing[j*4+i*32+3] += (a1 >>24);
		      };
		break;
	      case 2: /* average 64 */
		for (j=0; j<8; j++)
		  for (i=0;i<160; i++)
		    {
		      a1=cards[cardN].card->board[j][i+MEM_OFFSET];
		      us_thing[j*4+i*32] = (a1 & 0xff);
		      us_thing[j*4+i*32+1] = (a1 & 0xff0000)>>16;
		      us_thing[j*4+i*32+2] = (a1 & 0xff00)>>8;
		      us_thing[j*4+i*32+3] = (a1 >>24);
		    };
		for (k=1; k<64; k++)
		  for (j=0; j<32; j++)
		    for (i=0;i<160; i++)
		      {
			a1=cards[cardN].card->board[j][i+160*k+MEM_OFFSET];
			us_thing[j*4+i*32] += (a1 & 0xff);
			us_thing[j*4+i*32+1] += (a1 & 0xff0000)>>16;
			us_thing[j*4+i*32+2] += (a1 & 0xff00)>>8;
			us_thing[j*4+i*32+3] += (a1 >>24);
		      };
		break;
	      }
	  }
	pwf->nord=5120;

	break;

    case DBF_FLOAT:
	  {
	    switch (pwf->inp.value.vmeio.signal)
	      {
	      case 0: /*   no average */
		for (j=0; j<8; j++)
		  {
		    /*		     cards[cardN].card->cntl2 = 0x40;*/

		  for (i=0;i<160; i++)
		    {
		      a1=cards[cardN].card->board[j][i+MEM_OFFSET];
		      bc_o[j*4+i*32]=    (unsigned char)(a1 & 0x000000ff);
		      bc_o[j*4+i*32+1] = (unsigned char)((a1 & 0x00ff0000)>>16);
		      bc_o[j*4+i*32+2] = (unsigned char)((a1 & 0x0000ff00)>>8);
		      bc_o[j*4+i*32+3] = (unsigned char)((a1 >>24));

		    } 
		  }
		if (cardN==0) /* for LER */
		  {
		    for (i=0; i<1280; i++)
		      {
			for (j=0; j<4; j++)
			  {
			    f_thing[i*4+j]=cal_fac_bcm_L*bc_o[i*4+j];
			  }
			ref_dat[i]=bc_comb(bc_o,i);
		      }			 
		    for (iad=0;iad<320;iad++){
		      write_smemek(SMemL,ref_dat,iad*4,nwd);
		    }
		    *R_TIINF = 0xf0;
		    *R_CMD=1; /* inform interrupt */
		  }
		else  /* HER */
		  {
		    for (i=0; i<1280; i++)
		      {
			for (j=0; j<4; j++)
			  {
			    f_thing[i*4+j]=cal_fac_bcm_H*bc_o[i*4+j];
			  }
			ref_dat[i]=bc_comb(bc_o,i);
		      }			 
		    for (iad=0;iad<320;iad++){
		    write_smemek(SMemH,ref_dat,iad*4,nwd);
		    }
		    *R_TIINF = 0x00;
		    *R_CMD=1;
		  }


		if (debug_flag >4) logMsg("end of read\n"); 
		break;

	      case 1: /* average 4 */ 
		for (j=0; j<8; j++)
		  for (i=0;i<160; i++)
		    {
		      a1=cards[cardN].card->board[j][i+MEM_OFFSET];
		      f_thing[j*4+i*32]= 1.0*(a1 & 0xff);
		      f_thing[j*4+i*32+1] = 1.0*((a1 & 0xff0000)>>16);
		      f_thing[j*4+i*32+2] = 1.0*((a1 & 0xff00)>>8);
		      f_thing[j*4+i*32+3] = 1.0*((a1 >>24));
		    };
		for (k=1; k<4; k++)
		  for (j=0; j<8; j++)
		    for (i=0;i<160; i++)
		      {
			a1=cards[cardN].card->board[j][i+160*k+MEM_OFFSET];
			f_thing[j*4+i*32] += 1.0*(a1 & 0xff);
			f_thing[j*4+i*32+1] += 1.0*((a1 & 0xff0000)>>16);
			f_thing[j*4+i*32+2] += 1.0*((a1 & 0xff00)>>8);
			f_thing[j*4+i*32+3] += 1.0*(a1 >>24);
		      };
		break;
	      case 2: /* average 64 */
		for (j=0; j<8; j++)
		  for (i=0;i<160; i++)
		    {
		      a1=cards[cardN].card->board[j][i+MEM_OFFSET];
		      f_thing[j*4+i*32] = 1.0*(a1 & 0xff);
		      f_thing[j*4+i*32+1] = 1.0*((a1 & 0xff0000)>>16);
		      f_thing[j*4+i*32+2] = 1.0*((a1 & 0xff00)>>8);
		      f_thing[j*4+i*32+3] = 1.0*(a1 >>24);
		    };
		for (k=1; k<64; k++)
		  for (j=0; j<32; j++)
		    for (i=0;i<160; i++)
		      {
			a1=cards[cardN].card->board[j][i+160*k+MEM_OFFSET];
			f_thing[j*4+i*32] += 1.0*(a1 & 0xff);
			f_thing[j*4+i*32+1] += 1.0*((a1 & 0xff0000)>>16);
			f_thing[j*4+i*32+2] += 1.0*((a1 & 0xff00)>>8);
			f_thing[j*4+i*32+3] += 1.0*(a1 >>24);
		      };
		break;
	      }
	  }
	pwf->nord=5120;

	break;
    default:
      logMsg("devVmebcm: Invalid data type\n");
    }
  cards[cardN].card->cntl1 = 0x01;
  cards[cardN].card->cntl1 = 0x09;
  cards[cardN].card->cntl1 = 0xff0c;
  if (debug_flag > 4)
    logMsg("devVmebcm:end\n");
  return(0);
}



#define	ADDING  	0
#define DELETING	1

static long get_wf_int_info(cmd,pwf,ppvt)
int                    cmd;
struct waveformRecord  *pwf;
IOSCANPVT              *ppvt;
{
  short                cardN;
  unsigned char        stat; 

  cardN = pwf->inp.value.vmeio.card;
  *ppvt = cards[cardN].ioscanpvt;
  cards[cardN].card->cntl1 = 0x09;
  /*  cards[cardN].card->cntl1 = 0x09;
      cards[cardN].card->cntl1 = 0x0c; */
  if (debug_flag >1) logMsg("wf_INT CALLED\n");
  return(0);
}





/**************************************************************************
 *
 * Make sure card number is valid
 *
 **************************************************************************/



static int checkLink(cardN)
short   cardN;
{
  if (cardN >= vmebcm_num_links)
    return(ERROR);
  if (cards[cardN].card == NULL)
    {
      logMsg("No VMEBCM with this number = %d\n",cardN);
      return(ERROR);
    }

  if (debug_flag >10)
    logMsg("Yes you have vmeBCM with card No= %d\n",cardN);
  return(OK);
}

/*===============================================*/
static void auxSleepCB()
{
    if (--counter <= 0){
        semGive(semid);     /* timer expired !*/
        sysAuxClkDisable();/* start it */
     }
}
/*=================================================*/
static void auxSleep(double howlong)
{
    assert(howlong > 0.0);
    sysAuxClkConnect ((FUNCPTR) auxSleepCB, 0); /* connect clock ISR */
    sysAuxClkRateSet (MAX_RATE);  /* set auxiliary clock rate 5000=max value*/

    counter = (howlong * MAX_RATE + 0.5);
    assert(counter > 0);
    sysAuxClkEnable ();           /* start it */

    semTake(semid, WAIT_FOREVER); /* wait for the timer to expire */
    sysAuxClkRateSet(STD_RATE);
}
/*============================================*/
static void write_smemek(Bit32* p, Bit32* data, short iad
                  ,short nwd)
{
    unsigned char r_sr;
    short i;
    r_sr = *R_SR;

    /* Check Network */
    if ((r_sr & 0x0C) != 0x0C) network_error();

    if (r_sr & 0x40) /* Check R-FIFO */
        auxSleep(0.000500); /* Wait 500 micro sec */
    else if (r_sr & 0x80) /* Check T-FIFO */
        auxSleep(0.000100); /* Wait 100 micro sec */
    for (i=0;i<nwd;i++)
      *(p+i+iad)=data[iad+i];
}
/*==============================================================*/
static void network_error()
{
  fprintf(stdout,"Advme1522:Optical Network Error.\n");
  fflush(stdout);
  /*  while ((*R_SR && 0x0c)!=0x0c) */
    {
      taskDelay(60);
      *R_TITID=0x03; /* reciever ID  3= Linac */
      *R_MINF1=0x80; /* transfer enable */

    }
}