/************************************************************/
/*                                                          */
/* File        : rockfifo.c                                 */
/* Description : ROCK FIFO specific library                 */
/*                                                          */
/* Author: Sfiligoi Igor                                    */
/*                                                          */
/* Comment: If this module is used to manipulate a FIFO,    */
/*          nobody else should access that FIFO             */
/*                                                          */
/* Created      : 16.06.1997                                */
/* Last modified: 04.07.1997                                */
/*                                                          */
/************************************************************/

#include <stdlib.h>
#include <Error.h>
#include <bits.h>
#include "RockM_field_access.h"

#include "rockmfifo_private.h"

/**********************************************************************/
/*                                                                    */
/*                       Initialisation routines                      */
/*                                                                    */
/**********************************************************************/

int rockm_fifo_open(ROCKM_id       rockm_id,    /* IN : standard rockm id */
		    unsigned char  cancache,    /* IN : see ROCKM_FIFO_CACHE_... constants */
                    ROCKM_FIFO_id *fifo_id)     /* OUT: fifo id related to the rock */
{
 (*fifo_id) = (ROCKM_FIFO_id_base *) malloc(sizeof(ROCKM_FIFO_id_base));
 if ((*fifo_id)==NULL)
   { /* malloc error */
     ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_open","Malloc returned NULL.");
     return ROCKM_ERROR_UNKNOWN;
   }

 (*fifo_id)->rockm_id = rockm_id;
 (*fifo_id)->head = 0;
 (*fifo_id)->tail = 0;

 (*fifo_id)->cancache = ROCKM_FIFO_CACHE_OFF;
 return rockm_fifo_set_cancache((*fifo_id),cancache);
}


int rockm_fifo_close(ROCKM_FIFO_id   fifo_id,    /* IN : fifo id */
                     ROCKM_FIFO_RAW *cache)      /* OUT: the unused cache */
					         /*      should be disposed by caller */ 
{
 cache->nrels=rockm_fifo_cache_get_nrels(fifo_id);

 if (cache->nrels!=0)
   {
     cache->els = (unsigned int *) malloc(cache->nrels*sizeof(unsigned int));
     if (cache->els==NULL)
       { /* malloc error */
	 ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_close","Malloc returned NULL.");
	 return ROCKM_ERROR_UNKNOWN;
       }

     rockm_fifo_cache_read(fifo_id,cache->nrels,cache->els);
   }
 else
   cache->els = NULL;

 free(fifo_id);

 return ROCKM_ERROR_OK;
}		    

/**********************************************************************/
/*                                                                    */
/*                          Settings routines                         */
/*                                                                    */
/**********************************************************************/

int rockm_fifo_set_cancache(ROCKM_FIFO_id  fifo_id,	/* IN : fifo id */
			    unsigned char  cancache)	/* IN : new cancache value */
{
 fifo_id->cancache = cancache;

 return ROCKM_ERROR_OK;
}

/**********************************************************************/
/*                                                                    */
/*                          Cache routines                            */
/*                                                                    */
/**********************************************************************/

int rockm_fifo_cache_flush(ROCKM_FIFO_id   fifo_id,	/* IN : fifo id */
			   ROCKM_FIFO_RAW *cache)   	/* OUT: the unused cache */
							/*      should be disposed by caller */ 
{
 cache->nrels=rockm_fifo_cache_get_nrels(fifo_id);
 if (cache->nrels!=0)
   {
     cache->els = (unsigned int *) malloc(cache->nrels*sizeof(unsigned int));
     if (cache->els==NULL)
       { /* malloc error */
	 ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_cache_flush","Malloc returned NULL.");
	 return ROCKM_ERROR_UNKNOWN;
       }
     
     rockm_fifo_cache_read(fifo_id,cache->nrels,cache->els);
   }
 else
   cache->els = NULL;

 return ROCKM_ERROR_OK;
}		    

    /* Very dangerous!!!! */
int rockm_fifo_cache_refill(ROCKM_FIFO_id  fifo_id,   /* IN : fifo_id */
                            ROCKM_FIFO_RAW data)      /* IN : data to be filled to the cache */
{
 return rockm_fifo_cache_return(fifo_id,data.els,data.nrels);
}

/**********************************************************************/
/*                                                                    */
/*                          Raw read routines                         */
/*                                                                    */
/**********************************************************************/

int rockm_fifo_raw_read(ROCKM_FIFO_id  fifo_id,		/* IN : fifo id */
		        unsigned int  *data)		/* OUT: one FIFO value */
{
 int err;

 err = rockm_fifo_cache_read(fifo_id,1,data);
 if (err==ROCKM_ERROR_OK)
   return ROCKM_ERROR_OK;   /* was in cache, ok */

 err = rockm_fifo_fillcache(fifo_id,1);

 if (err==ROCKM_ERROR_OK)
   { /* data is in cache => read from cache */
     rockm_fifo_cache_read(fifo_id,1,data);
     return ROCKM_ERROR_OK;
   }
 else if (err==ROCKM_ERROR_FIFO_EMPTY)
   return err;
 else
   { /* serious error */
     ErrorSetF(err,"rockm_fifo_raw_read","rockm_fifo_fillcache error: %s",ErrorGetMessage());
     return err;
   }

}

int rockm_fifo_raw_blockread(ROCKM_FIFO_id   fifo_id,	/* IN : fifo id */
			     unsigned int    nrels,	/* IN : max number of elements */
			     ROCKM_FIFO_RAW *data)	/* OUT: FIFO data */
					    		/*      should be disposed by caller */ 
{
 int csize;
 unsigned int *actel;         /* point to the first unused space in data->els */
 int err;

 data->els = (unsigned int *) malloc(nrels*sizeof(unsigned int));
 if (data->els==NULL)
   { /* malloc error */
     ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_raw_blockread","Malloc returned NULL.");
     return ROCKM_ERROR_UNKNOWN;
   }

 actel = data->els;
 data->nrels=0;

 while (1)
   {
     csize = rockm_fifo_cache_get_nrels(fifo_id);
     if (csize>=nrels)
       { /* all needed elements are in cache */
	 data->nrels+=nrels;
	 rockm_fifo_cache_read(fifo_id,nrels,actel);
	 return ROCKM_ERROR_OK;
       }
     
     /* cache has not enough elements */
     data->nrels+=csize;
     rockm_fifo_cache_read(fifo_id,csize,actel);
     
     /* loop */
     nrels-=csize;
     
     err = rockm_fifo_fillcache(fifo_id,nrels);

     if (err!=ROCKM_ERROR_OK)
       {
	 if (err!=ROCKM_ERROR_FIFO_EMPTY)
	   { /* serious error, exit */
	     ErrorSetF(err,"rockm_fifo_raw_blockread","rockm_fifo_fillcache error: %s",ErrorGetMessage());
	     return err;
	   }
	 else
	   { /* save the elements found and exit*/
	     csize = rockm_fifo_cache_get_nrels(fifo_id);
	     data->nrels+=csize;
	     rockm_fifo_cache_read(fifo_id,csize,actel);
	     return ROCKM_ERROR_FIFO_EMPTY;
	   }
       }
   }
}

/**********************************************************************/
/*                                                                    */
/*                          Frame read routines                       */
/*                                                                    */
/**********************************************************************/

int rockm_fifo_frame_read(ROCKM_FIFO_id     fifo_id,	/* IN : fifo id */
		   	  ROCKM_FIFO_FRAME *data) 	/* OUT: one FIFO value */
{
 RockM_reg_declaration;
 int nrels;
 unsigned int rawels[ROCKM_FIFO_FRAME_SIZE];
 unsigned int softparity;
 unsigned int softparity_fail;
 unsigned int trigger_err;
 unsigned int last_bits;        /* count nr. of bits set on */
 unsigned char prec_addr;       /* needed to test that addresses go from highest to lower */
 unsigned int nrslaves[16];     /* nr of slaves with a address are in the subframe */

 int err,whatis;

 /* read super header */
 err = rockm_fifo_raw_read(fifo_id,&(rawels[0]));

   /* exit immediatly if cannot read the super header */
 if (err!=ROCKM_ERROR_OK)
   if (err==ROCKM_ERROR_FIFO_EMPTY)
     return err;
   else
     {
       ErrorSetF(err,"rockm_fifo_frame_read","rockm_fifo_raw_read_bits error: %s",ErrorGetMessage());
       return err;
     }

 whatis= rockm_fifo_whatis(rawels[0]);

 if (whatis!=ROCKM_FIFO_IS_SUPER_HEADER)
   { /* error, return element to cache and report error */
    rockm_fifo_cache_return(fifo_id,rawels,1);
    ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUPER_HEADER,"rockm_fifo_frame_read","Super header expected.");
    return ROCKM_ERROR_FIFO_FRAME_SUPER_HEADER;
   }

 SUPER_HEADER = rawels[0];

 data->header.ring = RING;
 data->header.chadd = CHAIN;
 data->header.trigger = T_WORD_H;

 if (RING==0)
   { /* ring test */
     { /* initialize */
       int i;
       
       nrels = 2;
       
       softparity_fail = 0xff;  /* for test only */
       trigger_err = 0;         /* for test only */
       last_bits = 0;
       
       for (i=0; i<8; i++)
	 {
	   data->subfr[i].ispresent = 0;
	 }
     }
     
     err = rockm_fifo_raw_read(fifo_id,&(rawels[1]));
     
     /* exit if cannot read the FIFO */
     if (err!=ROCKM_ERROR_OK)
       { /* error, return elements to cache and report error */
	 rockm_fifo_cache_return(fifo_id,rawels,2);
	 if (err!=ROCKM_ERROR_FIFO_EMPTY)
	   ErrorSetF(err,"rockm_fifo_frame_read","rockm_fifo_raw_read error: %s",ErrorGetMessage());
	 return err;
       }
     
     whatis= rockm_fifo_whatis(rawels[1]);
     
     
     while (whatis!=ROCKM_FIFO_IS_SUPER_FOOTER)
       { /* loop until end of super-frame */
	 if (whatis!=ROCKM_FIFO_IS_SLAVE)
	   { /* error, return element to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_read","Ringtest word expected.");
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 
	 SUB_HEADER = rawels[nrels-1];
	 
	 if (CRT_ADD_h!=CRATE)
	   {/* error, return element to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_read","Crt_add different from crate! (%i,%i).",CRT_ADD_h,CRATE);
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 
	 /* test if duplicated and set */
	 if (data->subfr[CRATE].ispresent!=0)
	   {/* error, return element to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_read","Duplicated crate %i.",CRATE);
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 data->subfr[CRATE].ispresent = 1;
	 
	 if (LAST==0)
	   {
	     last_bits++; 
	   }
	 
	 data->subfr[CRATE].header.last = LAST;
	 data->subfr[CRATE].header.trigger = T_WORD_h;

	 {
	   int i;
	   for (i=0; i<16; i++)
	     {
	       data->subfr[CRATE].slv[i].nrels = 0;
	       data->subfr[CRATE].slv[i].els = NULL;
	     }
	 }

	 data->subfr[CRATE].footer.softparity = PARITY_h;
	 data->subfr[CRATE].footer.hardparity = PARITY_h;
	 
	 /*************************/
	 /* Prepare for next loop */
	 /*************************/
	 
	 err = rockm_fifo_raw_read(fifo_id,&(rawels[nrels]));
	 nrels++;
	 
	 /* exit if cannot read the FIFO */
	 if (err!=ROCKM_ERROR_OK)
	   { /* error, return elements to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     if (err!=ROCKM_ERROR_FIFO_EMPTY)
	       ErrorSetF(err,"rockm_fifo_frame_read","rockm_fifo_raw_read error: %s",ErrorGetMessage());
	     return err;
	   }
	 
	 whatis= rockm_fifo_whatis(rawels[nrels-1]);
       }
     
     SUPER_FOOTER = rawels[nrels-1];
     
     data->footer.softparity_fail = softparity_fail;
     data->footer.hardparity_fail = ((PARITY_CRATE_7*0x80) +
				     (PARITY_CRATE_6*0x40) +
				     (PARITY_CRATE_5*0x20) +
				     (PARITY_CRATE_4*0x10) +
				     (PARITY_CRATE_3*0x8) +
				     (PARITY_CRATE_2*0x4) +
				     (PARITY_CRATE_1*0x2) +
				     PARITY_CRATE_0);
     data->footer.overflow = OVERFLOW;
     data->footer.softcounter = nrels-2;
     data->footer.hardcounter = COUNTER;
   }
 else
   { /* no ring test, standard superframe */
     { /* initialize */
       int i;
       
       nrels = 2;
       
       softparity_fail = 0xff;  /* no error yet */
       trigger_err = 0;         /* no error yet */
       last_bits = 0;
       
       for (i=0; i<8; i++)
	 {
	   data->subfr[i].ispresent = 0;
	 }
     }
     
     err = rockm_fifo_raw_read(fifo_id,&(rawels[1]));
     
     /* exit if cannot read the FIFO */
     if (err!=ROCKM_ERROR_OK)
       { /* error, return elements to cache and report error */
	 rockm_fifo_cache_return(fifo_id,rawels,2);
	 if (err!=ROCKM_ERROR_FIFO_EMPTY)
	   ErrorSetF(err,"rockm_fifo_frame_read","rockm_fifo_raw_read error: %s",ErrorGetMessage());
	 return err;
       }
     
     whatis= rockm_fifo_whatis(rawels[1]);
     
     
     while (whatis!=ROCKM_FIFO_IS_SUPER_FOOTER)
       { /* loop until end of super-frame */
	 int start_nrels;
	 
	 start_nrels = nrels;
	 
	 if (whatis!=ROCKM_FIFO_IS_SUB_HEADER)
	   { /* error, return element to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_read","Sub header expected.");
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 
	 SUB_HEADER = rawels[start_nrels-1];
	 
	 if (CRT_ADD_h!=CRATE)
	   {/* error, return element to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_read","Crt_add different from crate! (%i,%i).",CRT_ADD_h,CRATE);
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 
	 /* test if duplicated and set */
	 if (data->subfr[CRATE].ispresent!=0)
	   {/* error, return element to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_read","Duplicated crate %i.",CRATE);
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 data->subfr[CRATE].ispresent = 1;
	 
	 if (T_WORD_H!=T_WORD_h)
	   {
	     trigger_err = 1;
	   }
	 if (LAST==0)
	   {
	     last_bits++; 
	   }
	 
	 /* header data will be saved after the full frame read */
	 
	 /* Now I have the header, start reading slaves */
	 prec_addr = 255;
	 {
	   int i;
	   for (i=0; i<16; i++)
	     nrslaves[i]=0;
	 }
	 
	 for (; nrels<ROCKM_FIFO_FRAME_SIZE; nrels++)
	   {
	     err = rockm_fifo_raw_read(fifo_id,&(rawels[nrels]));
	     
	     /* exit if cannot read the FIFO */
	     if (err!=ROCKM_ERROR_OK)
	       { /* error, return elements to cache and report error */
		 rockm_fifo_cache_return(fifo_id,rawels,nrels);
		 if (err!=ROCKM_ERROR_FIFO_EMPTY)
		   ErrorSetF(err,"rockm_fifo_frame_read","rockm_fifo_raw_read error: %s",ErrorGetMessage());
		 return err;
	       }
	     
	     whatis= rockm_fifo_whatis(rawels[nrels]);
	     
	     if (whatis==ROCKM_FIFO_IS_SUB_FOOTER)
	       break;    /* exit from loop and elaborate footer */
	     else if (whatis==ROCKM_FIFO_IS_SUPER_FOOTER)
	       { /* error, return elements to cache and report error */
		 rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
		 ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUPER_FOOTER,"rockm_fifo_frame_read","A super footer before a sub footer found.");
		 return ROCKM_ERROR_FIFO_FRAME_SUPER_FOOTER;
	       }
	     else if (whatis!=ROCKM_FIFO_IS_SLAVE)
	       { /* error, return elements to cache and report error */
		 rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
		 ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_frame_read","Invalid type found: %i (slave expected).",whatis);
		 return ROCKM_ERROR_FIFO_FRAME_SLAVE;
	       }
	     
	     /* interpret the slave */
	     
	     DATA_HEADER = rawels[nrels];
	     
	     if (CRT_ADD_D!=CRT_ADD_h)
	       { /* error, return elements to cache and report error */
		 rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
		 ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_frame_read","Crate address different from subheader.");
		 return ROCKM_ERROR_FIFO_FRAME_SLAVE;
	       }
	     
	     if (SLV_ADD>prec_addr)
	       { /* error, return elements to cache and report error */
		 rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
		 ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_frame_read","Slave addresses not in decreasing order.");
		 return ROCKM_ERROR_FIFO_FRAME_SLAVE;
	       }
	     
	     prec_addr = SLV_ADD;
	     nrslaves[SLV_ADD]++;
	     /* data will be saved after the full frame read */
	   }
	 
	 if (nrels>=ROCKM_FIFO_FRAME_SIZE)
	   { /* error, return elements to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,ROCKM_FIFO_FRAME_SIZE);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_OVERFLOW,"rockm_fifo_frame_read","Frame too large.");
	     return ROCKM_ERROR_FIFO_FRAME_OVERFLOW;
	   }
	 
	 SUB_FOOTER = rawels[nrels];
	 
	 if (CRT_ADD_f!=CRT_ADD_h)
	   { /* error, return elements to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER,"rockm_fifo_frame_read","Subframe address different from subheader.");
	     return ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER;
	   }
	 
	 nrels++;
	 
	 if ((nrels-start_nrels)==1)
	   { /* a sub header followed by a sub footer not allowed */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER,"rockm_fifo_frame_read","Subfooter immediatly after subheader.");
	     return ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER;
	   }
	 
	 /* set the header */
	 {
	   data->subfr[CRATE].header.last = LAST;
	   data->subfr[CRATE].header.trigger = T_WORD_h;
	   
	   softparity = PARITY_h;
	 }
	 
	 /* set the slaves */
	 {
	   int i;
	   
	   /* allocate space */
	   for (i=0; i<16; i++)
	     {
	       data->subfr[CRATE].slv[i].nrels = 0;
	       if (nrslaves[i]!=0)
		 {
		   data->subfr[CRATE].slv[i].els = (ROCKM_FIFO_SLV_data *) malloc(nrslaves[i]*sizeof(ROCKM_FIFO_SLV_data));
		   if (data->subfr[CRATE].slv[i].els==NULL)
		     { /* malloc error */
		       ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_frame_read","Malloc returned NULL.");
		       return ROCKM_ERROR_UNKNOWN;
		     }
		 }
	       else
		 data->subfr[CRATE].slv[i].els = NULL;
	       
	     }
	   
	   /* save data */
	   for (i=start_nrels; i<(nrels-1); i++)
	     {
	       int a_nrels;
	       ROCKM_FIFO_SLV_data *a_el;  /* element to write in */
	       
	       DATA_HEADER = rawels[i];
	       
	       a_nrels = data->subfr[CRATE].slv[SLV_ADD].nrels++;
	       a_el = &(data->subfr[CRATE].slv[SLV_ADD].els[a_nrels]);
	       
	       a_el->channel = CHAIN_DATA;
	       a_el->reserved = RSV;
	       a_el->data = SLAVE_DATA;
	       
	       softparity ^= PARITY_D;
	     }
	 }
	 
	 /*Set footer */
	 {
	   SUB_FOOTER = rawels[nrels-1];
	   
	   data->subfr[CRATE].footer.hardparity = PARITY_f;
	   data->subfr[CRATE].footer.softparity = softparity;
	   if (PARITY_f!=softparity)
	     softparity_fail = bits_set_bit(softparity_fail,CRATE,0);
	 }
	 
	 
	 /*************************/
	 /* Prepare for next loop */
	 /*************************/
	 
	 err = rockm_fifo_raw_read(fifo_id,&(rawels[nrels]));
	 nrels++;
	 
	 /* exit if cannot read the FIFO */
	 if (err!=ROCKM_ERROR_OK)
	   { /* error, return elements to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     if (err!=ROCKM_ERROR_FIFO_EMPTY)
	       ErrorSetF(err,"rockm_fifo_frame_read","rockm_fifo_raw_read error: %s",ErrorGetMessage());
	     return err;
	   }
	 
	 whatis= rockm_fifo_whatis(rawels[nrels-1]);
       }
     
     SUPER_FOOTER = rawels[nrels-1];
     
     data->footer.softparity_fail = softparity_fail;
     data->footer.hardparity_fail = ((PARITY_CRATE_7*0x80) +
				     (PARITY_CRATE_6*0x40) +
				     (PARITY_CRATE_5*0x20) +
				     (PARITY_CRATE_4*0x10) +
				     (PARITY_CRATE_3*0x8) +
				     (PARITY_CRATE_2*0x4) +
				     (PARITY_CRATE_1*0x2) +
				     PARITY_CRATE_0);
     data->footer.overflow = OVERFLOW;
     data->footer.softcounter = nrels-2;
     data->footer.hardcounter = COUNTER;
   } /* end if RING */

 if (data->footer.hardparity_fail!=data->footer.softparity_fail)
   { /* report error, but do return the frame */
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_PARITY,"rockm_fifo_frame_read","Parity fail error: hard %i soft %i.",
	       data->footer.hardparity_fail,data->footer.softparity_fail);
     return ROCKM_ERROR_FIFO_FRAME_PARITY;
   }

 if (data->footer.hardparity_fail!=0xff)
   { /* report error, but do return the frame */
     char tmp[128];
     int i;

     strcpy(tmp,"");
     if (data->subfr[7].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 7: %i",PARITY_CRATE_7);
	 strcat(tmp,tmp1);
       }
     if (data->subfr[6].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 6: %i",PARITY_CRATE_6);
	 strcat(tmp,tmp1);
       }
     if (data->subfr[5].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 5: %i",PARITY_CRATE_5);
	 strcat(tmp,tmp1);
       }
     if (data->subfr[4].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 4: %i",PARITY_CRATE_4);
	 strcat(tmp,tmp1);
       }
     if (data->subfr[3].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 3: %i",PARITY_CRATE_3);
	 strcat(tmp,tmp1);
       }
     if (data->subfr[2].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 2: %i",PARITY_CRATE_2);
	 strcat(tmp,tmp1);
       }
     if (data->subfr[1].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 1: %i",PARITY_CRATE_1);
	 strcat(tmp,tmp1);
       }
     if (data->subfr[0].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 0: %i",PARITY_CRATE_0);
	 strcat(tmp,tmp1);
       }
       

     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_PARITY,"rockm_fifo_frame_read",
	       "Hard parity error: (%s).",tmp);
     return ROCKM_ERROR_FIFO_FRAME_PARITY;
   }

 if (data->footer.overflow==0)
   { /* report error, but do return the frame */
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_COUNTER,"rockm_fifo_frame_read","Counter overflow!.");
     return ROCKM_ERROR_FIFO_FRAME_COUNTER;
   }

 if (data->footer.hardcounter!=data->footer.softcounter)
   { /* report error, but do return the frame */
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_COUNTER,"rockm_fifo_frame_read","Counter error: hard %i soft %i.",
	       data->footer.hardcounter,data->footer.softcounter);
     return ROCKM_ERROR_FIFO_FRAME_COUNTER;
   }

 if (trigger_err)
   {/* report error, but do return the frame */
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_TRIGGER,"rockm_fifo_frame_read","Trigger word error.");
     return ROCKM_ERROR_FIFO_FRAME_TRIGGER;
   }

 if (last_bits>1)
   {/* report error, but do return the frame */
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_LAST,"rockm_fifo_frame_read","Last bit error.");
     return ROCKM_ERROR_FIFO_FRAME_LAST;
   }

 return ROCKM_ERROR_OK;
}

	/* non fatal errors are not considered */
int rockm_fifo_frame_blockread(ROCKM_FIFO_id      fifo_id,      /* IN : fifo id */
			       unsigned int      nrels, 	/* IN : max number of raw elements */
			       ROCKM_FIFO_FRAMEs *data) 	/* OUT: FIFO data */
					    	        	/*      should be disposed by caller */ 
{
  int i;
  int err;

  if (nrels==0)
    { /* nothing to do */
      data->nrframes = 0;
      data->frames = NULL;
      return ROCKM_ERROR_OK;
    }

  /* alloc space for the worst case */
  data->frames = (ROCKM_FIFO_FRAME *) malloc(nrels*sizeof(ROCKM_FIFO_FRAME));
  if (data->frames==NULL)
    { /* malloc error */
      ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_frame_blockread","Malloc returned NULL.");
      return ROCKM_ERROR_UNKNOWN;
    }


  for (i=0; i<nrels; i++)
    {
      err = rockm_fifo_frame_read(fifo_id,&(data->frames[i]));

      if ((err!=ROCKM_ERROR_OK)&&
	  (err!=ROCKM_ERROR_FIFO_FRAME_PARITY)&&
	  (err!=ROCKM_ERROR_FIFO_FRAME_TRIGGER)&&
	  (err!=ROCKM_ERROR_FIFO_FRAME_LAST)&&
	  (err!=ROCKM_ERROR_FIFO_FRAME_COUNTER))
	{
	  if (err==ROCKM_ERROR_FIFO_EMPTY)
	    break;
	  else
	    { /* a serious error occured, exit */
	      ErrorSetF(err,"rockm_fifo_frame_blockread","rockm_fifo_frame_read error: %s",ErrorGetMessage());
	      data->nrframes=i;
	      return err;
	    }
	}
	 
      ErrorClear(); /* clean any old error */   
    }

 data->nrframes=i;
 if (data->nrframes<nrels)
   return ROCKM_ERROR_FIFO_EMPTY;
 else
   return ROCKM_ERROR_OK;
}


int rockm_fifo_frame_rawread(ROCKM_FIFO_id     fifo_id,	/* IN : fifo id */
			     ROCKM_FIFO_RAW *data) 	/* OUT: one FIFO value */
				       			/*      should be disposed by caller */ 
{
 RockM_reg_declaration;
 int nrels;
 unsigned char subfr[8];
 unsigned int rawels[ROCKM_FIFO_FRAME_SIZE];
 unsigned int softparity;
 unsigned int softparity_fail;
 unsigned int hardparity_fail;
 unsigned int trigger_err;
 unsigned int last_bits;        /* count nr. of bits set on */
 unsigned char prec_addr;       /* needed to test that addresses go from highest to lower */
 unsigned int nrslaves[16];     /* nr of slaves with a address are in the subframe */

 int err,whatis;

 /* read super header */
 err = rockm_fifo_raw_read(fifo_id,&(rawels[0]));

   /* exit immediatly if cannot read the super header */
 if (err!=ROCKM_ERROR_OK)
   if (err==ROCKM_ERROR_FIFO_EMPTY)
     return err;
   else
     {
       ErrorSetF(err,"rockm_fifo_frame_rawread","rockm_fifo_raw_read error: %s",ErrorGetMessage());
       return err;
     }

 whatis= rockm_fifo_whatis(rawels[0]);

 if (whatis!=ROCKM_FIFO_IS_SUPER_HEADER)
   { /* error, return element to cache and report error */
    rockm_fifo_cache_return(fifo_id,rawels,1);
    ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUPER_HEADER,"rockm_fifo_frame_rawread","Super header expected.");
    return ROCKM_ERROR_FIFO_FRAME_SUPER_HEADER;
   }

 SUPER_HEADER = rawels[0];

 if (RING==0)
   { /* ring test */
     { /* initialize */
       int i;

       nrels = 2;
       
       softparity_fail = 0xff;  /* no error yet */
       trigger_err = 0;         /* for test only */
       last_bits = 0;
       
       for (i=0; i<8; i++)
	 subfr[i]=0;
     }
     
     err = rockm_fifo_raw_read(fifo_id,&(rawels[1]));
     
     /* exit if cannot read the FIFO */
     if (err!=ROCKM_ERROR_OK)
       { /* error, return elements to cache and report error */
	 rockm_fifo_cache_return(fifo_id,rawels,2);
	 if (err!=ROCKM_ERROR_FIFO_EMPTY)
	   ErrorSetF(err,"rockm_fifo_frame_rawread","rockm_fifo_raw_read error: %s",ErrorGetMessage());
	 return err;
       }
     
     whatis= rockm_fifo_whatis(rawels[1]);
     
     
     while (whatis!=ROCKM_FIFO_IS_SUPER_FOOTER)
       { /* loop until end of super-frame */
	 
	 if (whatis!=ROCKM_FIFO_IS_SLAVE)
	   { /* error, return element to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_rawread","Ringtest word expected.");
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 
	 SUB_HEADER = rawels[nrels-1];
	 
	 if (CRT_ADD_h!=CRATE)
	   {/* error, return element to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_rawread","Crt_add different from crate! (%i,%i).",CRT_ADD_h,CRATE);
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 
	 /* test if duplicated and set */
	 if (subfr[CRATE]!=0)
	   {/* error, return element to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_rawread","Duplicated crate %i.",CRATE);
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 subfr[CRATE] = 1;
	 
	 if (LAST==0)
	   {
	     last_bits++; 
	   }
	 
	 /*************************/
	 /* Prepare for next loop */
	 /*************************/
	 
	 err = rockm_fifo_raw_read(fifo_id,&(rawels[nrels]));
	 nrels++;
	 
	 /* exit if cannot read the FIFO */
	 if (err!=ROCKM_ERROR_OK)
	   { /* error, return elements to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     if (err!=ROCKM_ERROR_FIFO_EMPTY)
	       ErrorSetF(err,"rockm_fifo_frame_rawread","rockm_fifo_raw_read error: %s",ErrorGetMessage());
	     return err;
	   }
	 
	 whatis= rockm_fifo_whatis(rawels[nrels-1]);
       }
     
     SUPER_FOOTER = rawels[nrels-1];
     
     hardparity_fail = ((PARITY_CRATE_7*0x80) +
			(PARITY_CRATE_6*0x40) +
			(PARITY_CRATE_5*0x20) +
			(PARITY_CRATE_4*0x10) +
			(PARITY_CRATE_3*0x8) +
			(PARITY_CRATE_2*0x4) +
			(PARITY_CRATE_1*0x2) +
			PARITY_CRATE_0);
   }
 else
   { /* no ring test, standard superframe */

     { /* initialize */
       int i;

       nrels = 2;
       
       softparity_fail = 0xff;  /* no error yet */
       trigger_err = 0;         /* no error yet */
       last_bits = 0;
       
       for (i=0; i<8; i++)
	 subfr[i]=0;
     }
     
     err = rockm_fifo_raw_read(fifo_id,&(rawels[1]));
     
     /* exit if cannot read the FIFO */
     if (err!=ROCKM_ERROR_OK)
       { /* error, return elements to cache and report error */
	 rockm_fifo_cache_return(fifo_id,rawels,2);
	 if (err!=ROCKM_ERROR_FIFO_EMPTY)
	   ErrorSetF(err,"rockm_fifo_frame_rawread","rockm_fifo_raw_read error: %s",ErrorGetMessage());
	 return err;
       }
     
     whatis= rockm_fifo_whatis(rawels[1]);
     
     
     while (whatis!=ROCKM_FIFO_IS_SUPER_FOOTER)
       { /* loop until end of super-frame */
	 int start_nrels;
	 
	 start_nrels = nrels;
	 
	 if (whatis!=ROCKM_FIFO_IS_SUB_HEADER)
	   { /* error, return element to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_rawread","Sub header expected.");
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 
	 SUB_HEADER = rawels[start_nrels-1];
	 
	 if (CRT_ADD_h!=CRATE)
	   {/* error, return element to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_rawread","Crt_add different from crate! (%i,%i).",CRT_ADD_h,CRATE);
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 
	 /* test if duplicated and set */
	 if (subfr[CRATE]!=0)
	   {/* error, return element to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_rawread","Duplicated crate %i.",CRATE);
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 subfr[CRATE] = 1;
	 
	 if (T_WORD_H!=T_WORD_h)
	   {
	     trigger_err = 1;
	   }
	 if (LAST==0)
	   {
	     last_bits++; 
	   }
	 
	 /* header data will be saved after the full frame read */
	 
	 /* Now I have the header, start reading slaves */
	 prec_addr = 255;
	 {
	   int i;
	   for (i=0; i<16; i++)
	     nrslaves[i]=0;
	 }
	 
	 for (; nrels<ROCKM_FIFO_FRAME_SIZE; nrels++)
	   {
	     err = rockm_fifo_raw_read(fifo_id,&(rawels[nrels]));
	     
	     /* exit if cannot read the FIFO */
	     if (err!=ROCKM_ERROR_OK)
	       { /* error, return elements to cache and report error */
		 rockm_fifo_cache_return(fifo_id,rawels,nrels);
		 if (err!=ROCKM_ERROR_FIFO_EMPTY)
		   ErrorSetF(err,"rockm_fifo_frame_rawread","rockm_fifo_raw_read error: %s",ErrorGetMessage());
		 return err;
	       }
	     
	     whatis= rockm_fifo_whatis(rawels[nrels]);
	     
	     if (whatis==ROCKM_FIFO_IS_SUB_FOOTER)
	       break;    /* exit from loop and elaborate footer */
	     else if (whatis==ROCKM_FIFO_IS_SUPER_FOOTER)
	       { /* error, return elements to cache and report error */
		 rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
		 ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUPER_FOOTER,"rockm_fifo_frame_rawread","A super footer before a sub footer found.");
		 return ROCKM_ERROR_FIFO_FRAME_SUPER_FOOTER;
	       }
	     else if (whatis!=ROCKM_FIFO_IS_SLAVE)
	       { /* error, return elements to cache and report error */
		 rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
		 ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_frame_rawread","Invalid type found: %i (slave expected).",whatis);
		 return ROCKM_ERROR_FIFO_FRAME_SLAVE;
	       }
	     
	     /* interpret the slave */
	     
	     DATA_HEADER = rawels[nrels];
	     
	     if (CRT_ADD_D!=CRT_ADD_h)
	       { /* error, return elements to cache and report error */
		 rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
		 ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_frame_rawread","Crate address different from subheader.");
		 return ROCKM_ERROR_FIFO_FRAME_SLAVE;
	       }
	     
	     if (SLV_ADD>prec_addr)
	       { /* error, return elements to cache and report error */
		 rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
		 ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_frame_rawread","Slave addresses not in decreasing order.");
		 return ROCKM_ERROR_FIFO_FRAME_SLAVE;
	       }
	     
	     prec_addr = SLV_ADD;
	     nrslaves[SLV_ADD]++;
	   }
	 
	 if (nrels>=ROCKM_FIFO_FRAME_SIZE)
	   { /* error, return elements to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,ROCKM_FIFO_FRAME_SIZE);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_OVERFLOW,"rockm_fifo_frame_rawread","Frame too large.");
	     return ROCKM_ERROR_FIFO_FRAME_OVERFLOW;
	   }
	 
	 SUB_FOOTER = rawels[nrels];
	 
	 if (CRT_ADD_f!=CRT_ADD_h)
	   { /* error, return elements to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER,"rockm_fifo_frame_rawread","Subframe address different from subheader.");
	     return ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER;
	   }
	 
	 nrels++;
	 
	 if ((nrels-start_nrels)==1)
	   { /* a sub header followed by a sub footer not allowed */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER,"rockm_fifo_frame_rawread","Subfooter immediatly after subheader.");
	     return ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER;
	   }
	 
	 /* set the header */
	 {
	   softparity = PARITY_h;
	 }
	 
	 /* set the slaves */
	 {
	   int i;
	   
	   /* save data */
	   for (i=start_nrels; i<(nrels-1); i++)
	     {
	       DATA_HEADER = rawels[i];
	       
	       softparity ^= PARITY_D;
	     }
	 }
	 
	 /*Set footer */
	 {
	   SUB_FOOTER = rawels[nrels-1];
	   
	   if (PARITY_f!=softparity)
	     softparity_fail = bits_set_bit(softparity_fail,CRATE,0);
	 }
	 
	 
	 /*************************/
	 /* Prepare for next loop */
	 /*************************/
	 
	 err = rockm_fifo_raw_read(fifo_id,&(rawels[nrels]));
	 nrels++;
	 
	 /* exit if cannot read the FIFO */
	 if (err!=ROCKM_ERROR_OK)
	   { /* error, return elements to cache and report error */
	     rockm_fifo_cache_return(fifo_id,rawels,nrels);
	     if (err!=ROCKM_ERROR_FIFO_EMPTY)
	       ErrorSetF(err,"rockm_fifo_frame_rawread","rockm_fifo_raw_read error: %s",ErrorGetMessage());
	     return err;
	   }
	 
	 whatis= rockm_fifo_whatis(rawels[nrels-1]);
       }
     
     SUPER_FOOTER = rawels[nrels-1];
     
     hardparity_fail = ((PARITY_CRATE_7*0x80) +
			(PARITY_CRATE_6*0x40) +
			(PARITY_CRATE_5*0x20) +
			(PARITY_CRATE_4*0x10) +
			(PARITY_CRATE_3*0x8) +
			(PARITY_CRATE_2*0x4) +
			(PARITY_CRATE_1*0x2) +
			PARITY_CRATE_0);
   }

 /* copy the buffer */
 data->nrels = nrels;
 data->els = (unsigned int *) malloc(nrels*sizeof(unsigned int));
 
 if (data->els==NULL)
   { /* malloc error */
     ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_frame_rawread","Malloc returned NULL.");
     return ROCKM_ERROR_UNKNOWN;
   }
 
 memcpy(data->els,rawels,nrels*sizeof(unsigned int));
     
 /* check errors */
     
 if (hardparity_fail!=softparity_fail)
   { /* report error, but do return the frame */
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_PARITY,"rockm_fifo_frame_rawread","Parity fail error: hard %i soft %i.",
	       hardparity_fail,softparity_fail);
     return ROCKM_ERROR_FIFO_FRAME_PARITY;
   }

 if (hardparity_fail!=0xff)
   { /* report error, but do return the frame */
     char tmp[128];
     int i;

     strcpy(tmp,"");
     if (subfr[7])
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 7: %i",PARITY_CRATE_7);
	 strcat(tmp,tmp1);
       }
     if (subfr[6])
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 6: %i",PARITY_CRATE_6);
	 strcat(tmp,tmp1);
       }
     if (subfr[5])
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 5: %i",PARITY_CRATE_5);
	 strcat(tmp,tmp1);
       }
     if (subfr[4])
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 4: %i",PARITY_CRATE_4);
	 strcat(tmp,tmp1);
       }
     if (subfr[3])
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 3: %i",PARITY_CRATE_3);
	 strcat(tmp,tmp1);
       }
     if (subfr[2])
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 2: %i",PARITY_CRATE_2);
	 strcat(tmp,tmp1);
       }
     if (subfr[1])
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 1: %i",PARITY_CRATE_1);
	 strcat(tmp,tmp1);
       }
     if (subfr[0])
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 0: %i",PARITY_CRATE_0);
	 strcat(tmp,tmp1);
       }
       

     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_PARITY,"rockm_fifo_frame_rawread",
	       "Hard parity error: (%s).",tmp);
     return ROCKM_ERROR_FIFO_FRAME_PARITY;
   }

 if (OVERFLOW==0)
   { /* report error, but do return the frame */
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_COUNTER,"rockm_fifo_frame_rawread","Counter overflow!.");
     return ROCKM_ERROR_FIFO_FRAME_COUNTER;
   }

 if (COUNTER!=(nrels-2))
   { /* report error, but do return the frame */
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_COUNTER,"rockm_fifo_frame_rawread","Counter error: hard %i soft %i.",
	       COUNTER,(nrels-2));
     return ROCKM_ERROR_FIFO_FRAME_COUNTER;
   }

 if (trigger_err)
   {/* report error, but do return the frame */
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_TRIGGER,"rockm_fifo_frame_rawread","Trigger word error.");
     return ROCKM_ERROR_FIFO_FRAME_TRIGGER;
   }

 if (last_bits>1)
   {/* report error, but do return the frame */
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_LAST,"rockm_fifo_frame_rawread","Last bit error.");
     return ROCKM_ERROR_FIFO_FRAME_LAST;
   }

 return ROCKM_ERROR_OK;
}

	/* block of data allocated each time */
#define ROCKM_FIFO_FS_BLOCK		1024

	/* Synch the FIFO to the start of the frame */
int rockm_fifo_frame_synch(ROCKM_FIFO_id   fifo_id,	/* IN : fifo id */
			   ROCKM_FIFO_RAW *data)       	/* OUT: FIFO data */
					    		/*      should be disposed by caller */ 
{
  int err;
  int actblock;		/* actual size of the buffer */

  data->nrels = 0;
  actblock = ROCKM_FIFO_FS_BLOCK;
  data->els = (unsigned int *) malloc(actblock*sizeof(unsigned int));
  if (data->els==NULL)
    { /* malloc error */
      ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_frame_synch","Malloc returned NULL.");
      return ROCKM_ERROR_UNKNOWN;
    }

  /* read the first element without checking the type */
  err = rockm_fifo_raw_read(fifo_id,&(data->els[data->nrels]));
  if (err!=ROCKM_ERROR_OK)
    {
      if (err!=ROCKM_ERROR_FIFO_EMPTY)
	{ /* serious error */
	  ErrorSetF(err,"rockm_fifo_frame_synch","rockm_fifo_raw_read error: %s",ErrorGetMessage());
	  return err;
	}
      else
	return ROCKM_ERROR_FIFO_EMPTY;
    }
  data->nrels++;

  while (1)
    {
      int whatis;

      err = rockm_fifo_raw_read(fifo_id,&(data->els[data->nrels]));
      if (err!=ROCKM_ERROR_OK)
	{
	  if (err!=ROCKM_ERROR_FIFO_EMPTY)
	    { /* serious error */
	      ErrorSetF(err,"rockm_fifo_frame_synch","rockm_fifo_raw_read error: %s",ErrorGetMessage());
	      return err;
	    }
	  else
	    return ROCKM_ERROR_FIFO_EMPTY;
	}

      whatis = rockm_fifo_whatis(data->els[data->nrels]);
      if (whatis==ROCKM_FIFO_IS_SUPER_HEADER)
	{ /* found, return to cache and exit */
	  rockm_fifo_cache_return(fifo_id,&(data->els[data->nrels]),1);
	  return ROCKM_ERROR_OK;
	}

      /* not yet syncronised */
      data->nrels++;
      if (data->nrels>=actblock)
	{ /* must resize the buffer */
	  actblock += ROCKM_FIFO_FS_BLOCK;
	  data->els = (unsigned int *) realloc(data->els,actblock*sizeof(unsigned int));
	  if (data->els==NULL)
	    { /* realloc error */
	      ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_frame_synch","Realloc returned NULL.");
	      return ROCKM_ERROR_UNKNOWN;
	    }
	}
    }
}


/**********************************************************************/
/*                                                                    */
/*                          FIFO test routines                        */
/*                                                                    */
/**********************************************************************/

int rockm_fifo_isnotempty(ROCKM_FIFO_id fifo_id)	/* IN : fifo id */
{
 RockM_reg_declaration;

 if (rockm_fifo_cache_get_nrels(fifo_id)!=0)
   { /* if data is in cache, not empty */
     return ROCKM_ERROR_OK;
   }

 if (RockM_read_d_e(fifo_id->rockm_id)==0)
   return ROCKM_ERROR_FIFO_EMPTY;
 else
   return ROCKM_ERROR_OK;
}

/**********************************************************************/
/*                                                                    */
/*                       Frame conversion routines                    */
/*                                                                    */
/**********************************************************************/

int rockm_fifo_conv_frame2raw(ROCKM_FIFO_FRAME indata,	/* IN : formatted data */
			      ROCKM_FIFO_RAW  *outdata)	/* OUT: raw data */
{
 RockM_reg_declaration;
 int actel;

 /* not empty */
 outdata->nrels = indata.footer.hardcounter+2;
 outdata->els = (unsigned int *) malloc(outdata->nrels*sizeof(unsigned int));
 if (outdata->els==NULL)
   { /* malloc error */
     ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_conv_frame2raw","Malloc returned NULL.");
     return ROCKM_ERROR_UNKNOWN;
   }

 { /* convert superheader */
   SUPER_HEADER = 0xE00000;
   TYPE_H = 1;
   RING = indata.header.ring;
   CHAIN = indata.header.chadd;
   T_WORD_H = indata.header.trigger;
   outdata->els[0] = SUPER_HEADER;
 }

 actel=1;
 
 if (indata.header.ring==0)
   { /* convert ring test */
     int subfrnr;
     
     for (subfrnr=7; subfrnr>=0; subfrnr--)
       if (indata.subfr[subfrnr].ispresent)
	 {
	   SUB_HEADER = 0x40000;
	   TYPE_h = 7;
	   CRT_ADD_h = subfrnr;
	   CRATE = subfrnr;
	   LAST = indata.subfr[subfrnr].header.last;
	   T_WORD_h = indata.subfr[subfrnr].header.trigger;
	   outdata->els[actel] = SUB_HEADER;
	   actel++;
	 }
   }
 else
   { /* convert subframes */
     int subfrnr;
     
     for (subfrnr=7; subfrnr>=0; subfrnr--)
       if (indata.subfr[subfrnr].ispresent)
	 {
	   { /* convert subheader */
	     SUB_HEADER = 0x40000;
	     TYPE_h = 5;
	     CRT_ADD_h = subfrnr;
	     CRATE = subfrnr;
	     LAST = indata.subfr[subfrnr].header.last;
	     T_WORD_h = indata.subfr[subfrnr].header.trigger;
	     outdata->els[actel] = SUB_HEADER;
	     actel++;
	   }
	   
	   { /* convert slaves */
	     int slvnr;
	     
	     for (slvnr=15; slvnr>=0; slvnr--)
	       {
		 int i;
		 
		 for (i=0; i<indata.subfr[subfrnr].slv[slvnr].nrels; i++)
		   {
		     DATA_HEADER = 0;
		     TYPE_D = 7;
		     SLV_ADD = slvnr;
		     CRT_ADD_D = subfrnr;
		     CHAIN_DATA = indata.subfr[subfrnr].slv[slvnr].els[i].channel;
		     RSV = indata.subfr[subfrnr].slv[slvnr].els[i].reserved;
		     SLAVE_DATA = indata.subfr[subfrnr].slv[slvnr].els[i].data;
		     outdata->els[actel] = DATA_HEADER;
		     actel++;
		   }
	       }
	   }
	   
	   { /* convert subfooter */
	     SUB_FOOTER = 0;
	     TYPE_f = 6;
	     CRT_ADD_f = subfrnr;
	     PARITY_f = indata.subfr[subfrnr].footer.hardparity;
	     outdata->els[actel] = SUB_FOOTER;
	     actel++;
	   }
	 }
   } /* end if RING */
 
 { /* convert super footer */
   SUPER_FOOTER = 0;
   TYPE_F = 2;
   OVERFLOW = indata.footer.overflow;
   COUNTER = indata.footer.hardcounter;
   PARITY_CRATE_0 = bits_get_bit(indata.footer.hardparity_fail,0);
   PARITY_CRATE_1 = bits_get_bit(indata.footer.hardparity_fail,1);
   PARITY_CRATE_2 = bits_get_bit(indata.footer.hardparity_fail,2);
   PARITY_CRATE_3 = bits_get_bit(indata.footer.hardparity_fail,3);
   PARITY_CRATE_4 = bits_get_bit(indata.footer.hardparity_fail,4);
   PARITY_CRATE_5 = bits_get_bit(indata.footer.hardparity_fail,5);
   PARITY_CRATE_6 = bits_get_bit(indata.footer.hardparity_fail,6);
   PARITY_CRATE_7 = bits_get_bit(indata.footer.hardparity_fail,7);
   outdata->els[actel] = SUPER_FOOTER;
   actel++;
 }

 return ROCKM_ERROR_OK;
}

int rockm_fifo_conv_raw2frame(ROCKM_FIFO_RAW    indata, 	/* IN : raw data */
			      ROCKM_FIFO_FRAME *outdata)	/* OUT: formated data */
{
 RockM_reg_declaration;
 int nrels;
 unsigned int *rawels = indata.els;
 unsigned int softparity;
 unsigned int softparity_fail;
 unsigned int trigger_err;
 unsigned int last_bits;        /* count nr. of bits set on */
 unsigned char prec_addr;       /* needed to test that addresses go from highest to lower */
 unsigned int nrslaves[16];     /* nr of slaves with a address are in the subframe */

 int err,whatis;

 if (indata.nrels<1)
   {
     ErrorClear();
     return ROCKM_ERROR_FIFO_EMPTY; 
   }

 whatis= rockm_fifo_whatis(rawels[0]);

 if (whatis!=ROCKM_FIFO_IS_SUPER_HEADER)
   { /* error, return element to cache and report error */
    ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUPER_HEADER,"rockm_fifo_conv_raw2frame","Super header expected.");
    return ROCKM_ERROR_FIFO_FRAME_SUPER_HEADER;
   }

 if (indata.nrels<2)
   { /* not enough data to contain a valid frame */
     ErrorClear();
     return ROCKM_ERROR_FIFO_EMPTY; 
   }

 SUPER_HEADER = rawels[0];

 outdata->header.ring = RING;
 outdata->header.chadd = CHAIN;
 outdata->header.trigger = T_WORD_H;

 if (RING==0)
   { /* ring test */
     { /* initialize */
       int i;
       
       nrels = 2;
       last_bits = 0;
       trigger_err = 0;  /* needed for the error checking */
       
       for (i=0; i<8; i++)
	 {
	   outdata->subfr[i].ispresent = 0;
	 }
     }
     
     whatis= rockm_fifo_whatis(rawels[1]);
     
     while (whatis!=ROCKM_FIFO_IS_SUPER_FOOTER)
       { /* loop until end of super-frame */

	 if (whatis!=ROCKM_FIFO_IS_SLAVE)
	   { /* error, return element to cache and report error */
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_conv_raw2frame","Ringtest word expected.");
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 
	 SUB_HEADER = rawels[nrels-1];
	 
	 if (CRT_ADD_h!=CRATE)
	   {/* error, return element to cache and report error */
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_conv_raw2frame","Crt_add different from crate! (%i,%i).",CRT_ADD_h,CRATE);
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 
	 /* test if duplicated and set */
	 if (outdata->subfr[CRATE].ispresent!=0)
	   {/* error, return element to cache and report error */
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_conv_raw2frame","Duplicated crate %i.",CRATE);
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 outdata->subfr[CRATE].ispresent = 1;
	 
	 if (LAST==0)
	   {
	     last_bits++; 
	   }

	 outdata->subfr[CRATE].header.last = LAST;
	 outdata->subfr[CRATE].header.trigger = T_WORD_h;

	 {
	   int i;
	   for (i=0; i<16; i++)
	     {
	       outdata->subfr[CRATE].slv[i].nrels = 0;
	       outdata->subfr[CRATE].slv[i].els = NULL;
	     }
	 }

	 outdata->subfr[CRATE].footer.softparity = PARITY_h;
	 outdata->subfr[CRATE].footer.hardparity = PARITY_h;
	 
	 /*************************/
	 /* Prepare for next loop */
	 /*************************/
	 
	 nrels++;
	 
	 if (nrels>indata.nrels)
	   { /* end of data before the superfooter */
	     ErrorClear();
	     return ROCKM_ERROR_FIFO_EMPTY; 
	   }

	 whatis= rockm_fifo_whatis(rawels[nrels-1]);
       }

     SUPER_FOOTER = rawels[nrels-1];
     
     outdata->footer.softparity_fail = 0xff;
     outdata->footer.hardparity_fail = ((PARITY_CRATE_7*0x80) +
					(PARITY_CRATE_6*0x40) +
					(PARITY_CRATE_5*0x20) +
					(PARITY_CRATE_4*0x10) +
					(PARITY_CRATE_3*0x8) +
					(PARITY_CRATE_2*0x4) +
					(PARITY_CRATE_1*0x2) +
					PARITY_CRATE_0);
     outdata->footer.overflow = OVERFLOW;
     outdata->footer.softcounter = nrels-2;
     outdata->footer.hardcounter = COUNTER;
     
   }
 else /* RING!=0 */
   { /* no ring test, standard superframe */
     
     { /* initialize */
       int i;
       
       nrels = 2;
       
       softparity_fail = 0xff;  /* no error yet */
       trigger_err = 0;         /* no error yet */
       last_bits = 0;
       
       for (i=0; i<8; i++)
	 {
	   outdata->subfr[i].ispresent = 0;
	 }
     }
     
     whatis= rockm_fifo_whatis(rawels[1]);
     
     
     while (whatis!=ROCKM_FIFO_IS_SUPER_FOOTER)
       { /* loop until end of super-frame */
	 int start_nrels;
	 
	 start_nrels = nrels;
	 
	 if (whatis!=ROCKM_FIFO_IS_SUB_HEADER)
	   { /* error, return element to cache and report error */
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_conv_raw2frame","Sub header expected.");
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 
	 SUB_HEADER = rawels[start_nrels-1];
	 
	 if (CRT_ADD_h!=CRATE)
	   {/* error, return element to cache and report error */
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_conv_raw2frame","Crt_add different from crate! (%i,%i).",CRT_ADD_h,CRATE);
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 
	 /* test if duplicated and set */
	 if (outdata->subfr[CRATE].ispresent!=0)
	   {/* error, return element to cache and report error */
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_conv_raw2frame","Duplicated crate %i.",CRATE);
	     return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
	   }
	 outdata->subfr[CRATE].ispresent = 1;
	 
	 if (T_WORD_H!=T_WORD_h)
	   {
	     trigger_err = 1;
	   }
	 if (LAST==0)
	   {
	     last_bits++; 
	   }
	 
	 /* header data will be saved after the full frame read */
	 
	 /* Now I have the header, start reading slaves */
	 prec_addr = 255;
	 {
	   int i;
	   for (i=0; i<16; i++)
	     nrslaves[i]=0;
	 }
	 
	 for (; nrels<indata.nrels; nrels++)
	   {
	     whatis= rockm_fifo_whatis(rawels[nrels]);
	     
	     if (whatis==ROCKM_FIFO_IS_SUB_FOOTER)
	       break;    /* exit from loop and elaborate footer */
	     else if (whatis==ROCKM_FIFO_IS_SUPER_FOOTER)
	       { /* error, return elements to cache and report error */
		 ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUPER_FOOTER,"rockm_fifo_conv_raw2frame","A super footer before a sub footer found.");
		 return ROCKM_ERROR_FIFO_FRAME_SUPER_FOOTER;
	       }
	     else if (whatis!=ROCKM_FIFO_IS_SLAVE)
	       { /* error, return elements to cache and report error */
		 ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_conv_raw2frame","Invalid type found: %i (slave expected).",whatis);
		 return ROCKM_ERROR_FIFO_FRAME_SLAVE;
	       }
	     
	     /* interpret the slave */
	     
	     DATA_HEADER = rawels[nrels];
	     
	     if (CRT_ADD_D!=CRT_ADD_h)
	       { /* error, return elements to cache and report error */
		 ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_conv_raw2frame","Crate address different from subheader.");
		 return ROCKM_ERROR_FIFO_FRAME_SLAVE;
	       }
	     
	     if (SLV_ADD>prec_addr)
	       { /* error, return elements to cache and report error */
		 ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_conv_raw2frame","Slave addresses not in decreasing order.");
		 return ROCKM_ERROR_FIFO_FRAME_SLAVE;
	       }
	     
	     prec_addr = SLV_ADD;
	     nrslaves[SLV_ADD]++;
	     /* data will be saved after the full frame read */
	   }
	 
	 if (nrels>=indata.nrels)
	   {
	     ErrorClear();
	     return ROCKM_ERROR_FIFO_EMPTY;
	   }
	 
	 SUB_FOOTER = rawels[nrels];
	 
	 if (CRT_ADD_f!=CRT_ADD_h)
	   { /* error, return elements to cache and report error */
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER,"rockm_fifo_conv_raw2frame","Subframe address different from subheader.");
	     return ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER;
	   }
	 
	 nrels++;
	 
	 if ((nrels-start_nrels)==1)
	   { /* a sub header followed by a sub footer not allowed */
	     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER,"rockm_fifo_conv_raw2frame","Subfooter immediatly after subheader.");
	     return ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER;
	   }
	 
	 /* set the header */
	 {
	   outdata->subfr[CRATE].header.last = LAST;
	   outdata->subfr[CRATE].header.trigger = T_WORD_h;
	   
	   softparity = PARITY_h;
	 }
	 
	 /* set the slaves */
	 {
	   int i;
	   
	   /* allocate space */
	   for (i=0; i<16; i++)
	     {
	       outdata->subfr[CRATE].slv[i].nrels = 0;
	       if (nrslaves[i]!=0)
		 {
		   outdata->subfr[CRATE].slv[i].els = (ROCKM_FIFO_SLV_data *) malloc(nrslaves[i]*sizeof(ROCKM_FIFO_SLV_data));
		   if (outdata->subfr[CRATE].slv[i].els==NULL)
		     { /* malloc error */
		       ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_conv_raw2frame","Malloc returned NULL.");
		       return ROCKM_ERROR_UNKNOWN;
		     }
		 }
	       else
		 outdata->subfr[CRATE].slv[i].els = NULL;
	       
	     }
	   
	   /* save data */
	   for (i=start_nrels; i<(nrels-1); i++)
	     {
	       int a_nrels;
	       ROCKM_FIFO_SLV_data *a_el;  /* element to write in */
	       
	       DATA_HEADER = rawels[i];
	       
	       a_nrels = outdata->subfr[CRATE].slv[SLV_ADD].nrels++;
	       a_el = &(outdata->subfr[CRATE].slv[SLV_ADD].els[a_nrels]);
	       
	       a_el->channel = CHAIN_DATA;
	       a_el->reserved = RSV;
	       a_el->data = SLAVE_DATA;
	       
	       softparity ^= PARITY_D;
	     }
	 }
	 
	 /*Set footer */
	 {
	   SUB_FOOTER = rawels[nrels-1];
	   
	   outdata->subfr[CRATE].footer.hardparity = PARITY_f;
	   outdata->subfr[CRATE].footer.softparity = softparity;
	   if (PARITY_f!=softparity)
	     softparity_fail = bits_set_bit(softparity_fail,CRATE,0);
	 }
	 
	 
	 /*************************/
	 /* Prepare for next loop */
	 /*************************/
	 
	 nrels++;
	 
	 if (nrels>indata.nrels)
	   { /* end of data before the superfooter */
	     ErrorClear();
	     return ROCKM_ERROR_FIFO_EMPTY; 
	   }

	 whatis= rockm_fifo_whatis(rawels[nrels-1]);
       }
     
     SUPER_FOOTER = rawels[nrels-1];
     
     outdata->footer.softparity_fail = softparity_fail;
     outdata->footer.hardparity_fail = ((PARITY_CRATE_7*0x80) +
					(PARITY_CRATE_6*0x40) +
					(PARITY_CRATE_5*0x20) +
					(PARITY_CRATE_4*0x10) +
					(PARITY_CRATE_3*0x8) +
					(PARITY_CRATE_2*0x4) +
					(PARITY_CRATE_1*0x2) +
					PARITY_CRATE_0);
     outdata->footer.overflow = OVERFLOW;
     outdata->footer.softcounter = nrels-2;
     outdata->footer.hardcounter = COUNTER;
   } /* end if RING */
     
 if (outdata->footer.hardparity_fail!=outdata->footer.softparity_fail)
   { /* report error, but do return the frame */
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_PARITY,"rockm_fifo_conv_raw2frame","Parity fail error: hard %i soft %i.",
	       outdata->footer.hardparity_fail,outdata->footer.softparity_fail);
     return ROCKM_ERROR_FIFO_FRAME_PARITY;
   }
 
 if (outdata->footer.hardparity_fail!=0xff)
   { /* report error, but do return the frame */
     char tmp[128];
     int i;
     
     strcpy(tmp,"");
     if (outdata->subfr[7].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 7: %i",PARITY_CRATE_7);
	 strcat(tmp,tmp1);
       }
     if (outdata->subfr[6].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 6: %i",PARITY_CRATE_6);
	 strcat(tmp,tmp1);
       }
     if (outdata->subfr[5].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 5: %i",PARITY_CRATE_5);
	 strcat(tmp,tmp1);
       }
     if (outdata->subfr[4].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 4: %i",PARITY_CRATE_4);
	 strcat(tmp,tmp1);
       }
     if (outdata->subfr[3].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 3: %i",PARITY_CRATE_3);
	 strcat(tmp,tmp1);
       }
     if (outdata->subfr[2].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 2: %i",PARITY_CRATE_2);
	 strcat(tmp,tmp1);
       }
     if (outdata->subfr[1].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 1: %i",PARITY_CRATE_1);
	 strcat(tmp,tmp1);
       }
     if (outdata->subfr[0].ispresent)
       {
	 char tmp1[32];
	 
	 sprintf(tmp1," 0: %i",PARITY_CRATE_0);
	 strcat(tmp,tmp1);
       }
     
     
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_PARITY,"rockm_fifo_conv_raw2frame",
	       "Hard parity error: (%s).",tmp);
     return ROCKM_ERROR_FIFO_FRAME_PARITY;
   }
 
 if (outdata->footer.overflow==0)
   { /* report error, but do return the frame */
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_COUNTER,"rockm_fifo_conv_raw2frame","Counter overflow!.");
     return ROCKM_ERROR_FIFO_FRAME_COUNTER;
   }
 
 if (outdata->footer.hardcounter!=outdata->footer.softcounter)
   { /* report error, but do return the frame */
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_COUNTER,"rockm_fifo_conv_raw2frame","Counter error: hard %i soft %i.",
	       outdata->footer.hardcounter,outdata->footer.softcounter);
     return ROCKM_ERROR_FIFO_FRAME_COUNTER;
   }
 
 if (trigger_err)
   {/* report error, but do return the frame */
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_TRIGGER,"rockm_fifo_conv_raw2frame","Trigger word error.");
     return ROCKM_ERROR_FIFO_FRAME_TRIGGER;
   }
 
 if (last_bits>1)
   {/* report error, but do return the frame */
     ErrorSetF(ROCKM_ERROR_FIFO_FRAME_LAST,"rockm_fifo_conv_raw2frame","Last bit error.");
     return ROCKM_ERROR_FIFO_FRAME_LAST;
   }
 
 return ROCKM_ERROR_OK;
}


 /* return one of the ROCKM_FIFO_IS_... consts */
int rockm_fifo_whatis(unsigned int el)
{
 unsigned int el_type;

 el_type = bits_get_bits(el,24,3);

 switch (el_type)
   {
   case 1:
     return ROCKM_FIFO_IS_SUPER_HEADER;
     break;
   case 5:
     return ROCKM_FIFO_IS_SUB_HEADER;
     break;
   case 7:
     return ROCKM_FIFO_IS_SLAVE;
     break;
   case 6:
     return ROCKM_FIFO_IS_SUB_FOOTER;
     break;
   case 2:
     return ROCKM_FIFO_IS_SUPER_FOOTER;
     break;
   default:
     return ROCKM_FIFO_IS_ERROR;
     break;
   }

 return -99; /* dummy, never reach this point */
}