00001 #include <stdio.h>
00002 #include <string.h>
00003 #include <arpa/inet.h>
00004
00005 #include <rtsLog.h>
00006 #include <rtsSystems.h>
00007 #include <daqFormats.h>
00008 #include <rts.h>
00009
00010
00011 #include "daq_pmd.h"
00012
00013 static pmd_t *pmd_p ;
00014 static int adcReader(int sec, struct PMDADCD *adcd) ;
00015 static int pedReader(int sec, int type, struct PMDPEDR *pedr) ;
00016
00017
00018 int pmd_reader(char *m, struct pmd_t *pmd, u_int driver)
00019 {
00020 struct DATAP *datap = (struct DATAP *)m ;
00021 struct DATAPX *datapx ;
00022 struct PMDP *pmdp = 0;
00023 struct PMDSECP *secp = 0;
00024 struct PMDADCD *adcd ;
00025 struct PMDPEDR *pedr ;
00026 struct PMDRMSR *rmsr ;
00027 struct PMDTHRR *thrr ;
00028
00029 int off ;
00030 int len = 0 ;
00031
00032 int start_sec, stop_sec ;
00033 int sec, type ;
00034 int ret ;
00035 int swapdatap = 0;
00036 int swapdatapx = 0;
00037
00038 pmd_p = pmd ;
00039
00040 if(pmd_p->max_channels) ;
00041 else {
00042 pmd_p->channels = 0 ;
00043 pmd_p->max_channels = 2*PMD_CRAMS_MAX*2*PMD_CRAMS_CH_MAX ;
00044 pmd_p->mode = 0 ;
00045 pmd_p->status[0] = pmd_p->status[1] = 0 ;
00046 }
00047
00048 LOG(DBG,"PMD reader: %p: sector %d",datap,driver) ;
00049
00050 if(datap == NULL) return 0 ;
00051
00052 if(driver != 0) {
00053 secp = (struct PMDSECP *) m ;
00054 start_sec = stop_sec = driver - 1 ;
00055 goto do_sectors ;
00056 }
00057 else {
00058 start_sec = 0 ;
00059 stop_sec = 1 ;
00060 }
00061
00062
00063
00064 if(datap->bh.byte_order != DAQ_RAW_FORMAT_ORDER) swapdatap = 1;
00065
00066 off = qswap32(swapdatap, datap->det[EXT_ID].len) ;
00067 if(off == 0) return 0 ;
00068
00069 off = qswap32(swapdatap, datap->det[EXT_ID].off) ;
00070
00071
00072 datapx = (struct DATAPX *)(m + off*4) ;
00073
00074
00075 if(checkBank(datapx->bh.bank_type, CHAR_DATAPX) < 0) {
00076 return 0 ;
00077 }
00078
00079
00080 if(datapx->bh.byte_order != DAQ_RAW_FORMAT_ORDER) swapdatapx = 1;
00081
00082 len = qswap32(swapdatapx, datapx->det[PMD_ID-10].len) * 4 ;
00083
00084 if(len == 0) return 0 ;
00085
00086
00087 off = qswap32(swapdatapx, datapx->det[PMD_ID-10].off)*4 ;
00088
00089 pmdp = (struct PMDP *)((char *)datapx + off) ;
00090
00091
00092 if(checkBank(pmdp->bh.bank_type, CHAR_PMDP) < 0) {
00093 return -1 ;
00094 }
00095
00096
00097
00098
00099
00100 do_sectors:;
00101 for(sec=start_sec;sec<=stop_sec;sec++) {
00102
00103 if(driver == 0) {
00104 LOG(DBG,"PMD %d, len %d, offset %u",sec,b2h32(pmdp->sec[sec].len),b2h32(pmdp->sec[sec].off),0,0) ;
00105
00106 if(pmdp->sec[sec].len == 0) continue ;
00107
00108
00109 secp = (struct PMDSECP *)((char *)pmdp + b2h32(pmdp->sec[sec].off)*4) ;
00110 }
00111
00112 if(checkBank((char *)secp,CHAR_PMDSECP) < 0) return -1 ;
00113
00114 pmd_p->status[sec] = b2h32(secp->bh.format_number) ;
00115
00116 for(type=0;type<4;type++) {
00117
00118 if(secp->type[type].len == 0) continue ;
00119
00120 switch(type) {
00121 case PMD_ADCD_N :
00122 adcd = (struct PMDADCD *)((char *)secp + b2h32(secp->type[type].off)*4) ;
00123 if(checkBank(adcd->bh.bank_type, CHAR_PMDADCD) < 0) return -1 ;
00124
00125 ret = adcReader(sec, adcd) ;
00126 if(ret < 0) return -1 ;
00127
00128 pmd_p->channels += ret ;
00129
00130 break ;
00131 case PMD_PEDR_N :
00132 pedr = (struct PMDPEDR *)((char *)secp + b2h32(secp->type[type].off)*4) ;
00133 if(checkBank(pedr->bh.bank_type, CHAR_PMDPEDR) < 0) return -1 ;
00134
00135 ret = pedReader(sec, type, pedr) ;
00136 if(ret < 0) return -1 ;
00137
00138 pmd_p->mode = 1 ;
00139
00140 pmd_p->channels += ret ;
00141
00142
00143 break ;
00144 case PMD_RMSR_N :
00145 rmsr = (struct PMDRMSR *)((char *)secp + b2h32(secp->type[type].off)*4) ;
00146 if(checkBank(rmsr->bh.bank_type, CHAR_PMDRMSR) < 0) return -1 ;
00147
00148 ret = pedReader(sec, type, (struct PMDPEDR *)rmsr) ;
00149 if(ret < 0) return -1 ;
00150
00151 pmd_p->mode = 1 ;
00152
00153
00154 break ;
00155 case PMD_THRR_N :
00156 thrr = (struct PMDTHRR *)((char *)secp + b2h32(secp->type[type].off)*4) ;
00157 if(checkBank(thrr->bh.bank_type, CHAR_PMDTHRR) < 0) return -1 ;
00158
00159 ret = pedReader(sec, type, (struct PMDPEDR *)thrr) ;
00160 if(ret < 0) return -1 ;
00161
00162 pmd_p->mode = 1 ;
00163
00164 break ;
00165
00166 }
00167 }
00168
00169 }
00170
00171 return len ;
00172
00173 }
00174
00175 static int adcReader(int sec, struct PMDADCD *adcd)
00176 {
00177 int items = b2h32(adcd->bh.length) - sizeof(adcd->bh)/4 ;
00178 u_int *datum ;
00179 u_int j ;
00180 u_int rb, mz ;
00181 u_int ch_num ;
00182 u_int ch ;
00183
00184 if(items <= 0) return 0 ;
00185
00186
00187 datum = adcd->data ;
00188
00189 ch_num = 0 ;
00190
00191 LOG(DBG,"ADC: PMD sec %d: items %d",sec,items,0,0,0) ;
00192
00193 u_int *end_datum = datum + items ;
00194
00195 for(end_datum=datum+items;datum<end_datum;) {
00196 u_int tmp = b2h32(*datum) ;
00197 datum++ ;
00198
00199
00200 rb = (tmp & 0xFF000000) >> 24 ;
00201 mz = (tmp & 0x00FF0000) >> 16 ;
00202 ch = (tmp & 0x0000FFFF) ;
00203
00204
00205
00206
00207 if(rb >= PMD_CRAMS_MAX) {
00208 LOG(ERR,"PMD: Bad RB number %d",rb,0,0,0,0) ;
00209 return -1 ;
00210 }
00211
00212 if((mz != 0) && (mz != 1)) {
00213 LOG(ERR,"PMD: Bad mezzanine %d in RB %d",mz,rb,0,0,0) ;
00214 return -1 ;
00215 }
00216
00217 if(ch > PMD_CRAMS_CH_MAX) {
00218 LOG(ERR,"PMD: too many channels in RB %d, MZ %d: %d",rb,mz,ch,0,0) ;
00219 return -1 ;
00220 }
00221
00222 LOG(DBG,"PMD ADCD: sec %d, rb %d, mz %d, channels %d",sec,rb,mz,ch,0) ;
00223
00224 for(j=0;j<ch;j++) {
00225 u_int val ;
00226
00227 val = b2h32(*datum) ;
00228 datum++ ;
00229
00230
00231 if(val & 0x40000000) {
00232 u_int channel = (val & 0x007ff000) >> 12 ;
00233 val &= 0xFFF ;
00234
00235
00236
00237 if(channel >= PMD_CRAMS_CH_MAX) {
00238 LOG(ERR,"PMD: channel too big %d in RB %d, MZ %d: %d",rb,mz,channel,0,0) ;
00239 return -1 ;
00240 }
00241
00242 pmd_p->adc[sec][rb][mz][channel] = val ;
00243 ch_num++ ;
00244 }
00245 else {
00246 LOG(ERR,"PMD %d: RB %d, MZ %d: illegal value in channel %d: 0x%08X",sec,rb,mz,j,val) ;
00247 }
00248 }
00249 }
00250
00251 return ch_num ;
00252 }
00253
00254 static int pedReader(int sec, int type, struct PMDPEDR *pedr)
00255 {
00256 int items ;
00257 u_short *datum ;
00258 int rb, mz, ch ;
00259 int ch_num ;
00260 int valid ;
00261
00262
00263 items = (b2h32(pedr->bh.length) - sizeof(pedr->bh)/4)*2 ;
00264
00265 if(items <= 0) return 0 ;
00266
00267
00268 datum = pedr->data ;
00269
00270 ch_num = 0 ;
00271
00272
00273
00274 u_short *end_datum = datum + items ;
00275
00276 for(end_datum=datum+items;datum<end_datum;) {
00277 int channel ;
00278 u_int tmp = b2h16(*datum) ;
00279 datum++ ;
00280
00281 rb = (tmp & 0x7F00) >> 8 ;
00282 mz = (tmp & 0x00FF) ;
00283
00284 valid = tmp & 0x8000 ;
00285
00286
00287 ch = PMD_CRAMS_CH_MAX ;
00288
00289 if(!valid) {
00290 LOG(WARN,"Type %d: datum not valid at %u == 0x%04X",type,datum-pedr->data, (u_int)tmp,0,0) ;
00291
00292 datum += ch ;
00293 continue ;
00294 }
00295
00296
00297 if(rb >= PMD_CRAMS_MAX) {
00298 LOG(ERR,"PMD: Bad RB number %d",rb,0,0,0,0) ;
00299 return -1 ;
00300 }
00301
00302 if((mz != 0) && (mz != 1)) {
00303 LOG(ERR,"PMD: Bad mezzanine %d in RB %d",mz,rb,0,0,0) ;
00304 return -1 ;
00305 }
00306
00307 LOG(DBG," %d: SEC %d, RB %d, MZ %d: channel count %d...",type,sec,rb,mz,ch) ;
00308
00309
00310
00311
00312 for(channel=0;channel<ch;channel++) {
00313 u_int val ;
00314 u_short blah ;
00315
00316 blah = *datum ;
00317 val = b2h16(blah) ;
00318 datum++ ;
00319
00320
00321
00322
00323
00324 switch(type) {
00325 case PMD_PEDR_N :
00326 pmd_p->ped[sec][rb][mz][channel] = val ;
00327 break ;
00328 case PMD_RMSR_N :
00329 pmd_p->rms[sec][rb][mz][channel] = val ;
00330 break ;
00331 case PMD_THRR_N :
00332 pmd_p->thr[sec][rb][mz][channel] = val ;
00333 break ;
00334 }
00335 ch_num++ ;
00336
00337 }
00338 }
00339
00340 return ch_num ;
00341 }