/************************************************************/ /* */ /* 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 */ }