Line data Source code
1 : #include "l1id_decoder.h"
2 : #include "felix/felix_fid.h"
3 : #include "log.h"
4 :
5 : static int (*check_sequence)(uint64_t fid, struct l1id_data* xl1id, const uint8_t* data, size_t size);
6 : static int check_sequence_latome( uint64_t fid, struct l1id_data* xl1id, const uint8_t* data, size_t size);
7 : static int check_sequence_fmemu( uint64_t fid, struct l1id_data* xl1id, const uint8_t* data, size_t size);
8 : static int check_sequence_felig( uint64_t fid, struct l1id_data* xl1id, const uint8_t* data, size_t size);
9 : static int check_sequence_nsw_vmm(uint64_t fid, struct l1id_data* xl1id, const uint8_t* data, size_t size);
10 : static int check_sequence_nsw_tp( uint64_t fid, struct l1id_data* xl1id, const uint8_t* data, size_t size);
11 :
12 :
13 8 : static inline int compare(uint64_t fid, xl1id_t current, xl1id_t expected)
14 : {
15 8 : if(current.fields.ec != expected.fields.ec){
16 0 : LOG_INFO("fid 0x%lx (0x%x) has L1ID 0x%06x, expected 0x%06x", fid, get_elink(fid), current.fields.ec, expected.fields.ec);
17 0 : return 1;
18 : }
19 : return 0;
20 : }
21 :
22 600 : int is_ttc2h_elink(uint64_t fid)
23 : {
24 600 : uint32_t elink = get_elink(fid);
25 600 : if (elink == 315 || elink == 827 || elink == 1537 || elink == 0x600){
26 : return 1;
27 : } else {
28 0 : return 0;
29 : }
30 : }
31 :
32 8 : int check_sequence_ttc2h(uint64_t fid, struct l1id_data* last, const uint8_t* data, size_t size)
33 : {
34 8 : if(size < 8){
35 0 : LOG_INFO("TTC2H message from fid 0x%lx (0x%x) too small to retrieve XL1ID, size %lu.", fid, get_elink(fid), size);
36 0 : return 1;
37 : }
38 8 : xl1id_t current, expected;
39 8 : bcid_t current_bc;
40 8 : current_bc.bc_data = ((uint32_t*)data)[0];
41 8 : current.xl1id = ((uint32_t*)data)[1];
42 8 : LOG_DBG("Current L1ID 0x%06x BCID 0x%04x", current.fields.ec, current_bc.fields.bcid);
43 8 : if(current.fields.ecrc == (last->l1id.fields.ecrc+1)){
44 0 : LOG_INFO("ECR on TTC2H fid 0x%lx (0x%x)", fid, get_elink(fid));
45 0 : expected.fields.ec = 0x0;
46 : } else {
47 8 : expected.fields.ec = (last->l1id.fields.ec+1) & 0x00ffffff;
48 : }
49 8 : int ret = compare(fid, current, expected);
50 8 : if (ret) {
51 0 : LOG_INFO("fid 0x%lx last data block address = %p, current data block address = %p",
52 : fid, last->ptr, data);
53 : }
54 8 : last->mask = 0xffffffff;
55 8 : last->l1id.xl1id = current.xl1id;
56 8 : last->ptr = data;
57 8 : return ret;
58 : }
59 :
60 :
61 8 : int check_sequence_daq(uint64_t fid, struct l1id_data* xl1id, const uint8_t* data, size_t size)
62 : {
63 8 : int ret = 0;
64 8 : if(check_sequence){
65 0 : ret = check_sequence(fid, xl1id, data, size);
66 : }
67 8 : return ret;
68 : }
69 :
70 :
71 48 : void init_l1id_decoder(int format)
72 : {
73 48 : switch(format){
74 44 : case 0:
75 44 : check_sequence = NULL;
76 44 : break;
77 2 : case 1:
78 2 : LOG_INFO("L1ID sequentiality check enabled: TTC2H only");
79 2 : check_sequence = NULL;
80 2 : break;
81 0 : case 2:
82 0 : LOG_INFO("L1ID sequentiality check enabled: TTC2H, LATOME data");
83 0 : check_sequence = &check_sequence_latome;
84 0 : break;
85 0 : case 3:
86 0 : LOG_INFO("L1ID sequentiality check enabled: TTC2H, FMEMU data");
87 0 : check_sequence = &check_sequence_fmemu;
88 0 : break;
89 2 : case 4:
90 2 : LOG_INFO("L1ID sequentiality check enabled: TTC2H, FELIG data");
91 2 : check_sequence = &check_sequence_felig;
92 2 : break;
93 0 : case 5:
94 0 : LOG_INFO("L1ID sequentiality check enabled: TTC2H, NSW VMM data");
95 0 : check_sequence = &check_sequence_nsw_vmm;
96 0 : break;
97 0 : case 6:
98 0 : LOG_INFO("L1ID sequentiality check enabled: TTC2H, NSW TP data");
99 0 : check_sequence = &check_sequence_nsw_tp;
100 0 : break;
101 0 : default:
102 0 : LOG_INFO("Invalid choice for L1ID sequentiality check. Check disabled");
103 0 : check_sequence = NULL;
104 : }
105 48 : }
106 :
107 :
108 0 : static int check_sequence_latome(uint64_t fid, struct l1id_data* last, const uint8_t* data, size_t size){
109 0 : if(size < 48){
110 0 : LOG_INFO("LATOME message from fid 0x%lx (0x%x) too small to retrieve XL1ID, size %lu.",fid, get_elink(fid), size);
111 0 : return 1;
112 : }
113 0 : xl1id_t current, expected;
114 0 : current.xl1id = ((uint32_t*)data)[5];
115 0 : if(current.fields.ecrc == (last->l1id.fields.ecrc+1)){
116 0 : LOG_DBG("ECR on fid 0x%lx (0x%x)", fid, get_elink(fid));
117 0 : expected.fields.ec = 0x0;
118 : } else{
119 0 : expected.fields.ec = (last->l1id.fields.ec+1) & 0x00ffffff;
120 : }
121 0 : last->mask = 0xffffffff;
122 0 : last->l1id.xl1id = current.xl1id;
123 0 : int ret = compare(fid, current, expected);
124 0 : return ret;
125 : }
126 :
127 :
128 0 : static int check_sequence_fmemu(uint64_t fid, struct l1id_data* last, const uint8_t* data, size_t size)
129 : {
130 0 : if(size < 4){
131 0 : LOG_INFO("FMEMU message from fid 0x%lx (0x%x) too small to retrieve XL1ID, size %lu.", fid, get_elink(fid), size);
132 0 : return 1;
133 : }
134 0 : xl1id_t current, expected;
135 0 : current.xl1id = ((uint32_t*)data)[0];
136 0 : if(current.fields.ecrc == (last->l1id.fields.ecrc+1)){
137 0 : LOG_DBG("ECR on fid 0x%lx (0x%x)", fid, get_elink(fid));
138 0 : expected.fields.ec = 0x0;
139 : } else{
140 0 : expected.fields.ec = (last->l1id.fields.ec+1) & 0x00ffffff;
141 : }
142 0 : last->mask = 0xffffffff;
143 0 : last->l1id.xl1id = current.xl1id;
144 0 : int ret = compare(fid, current, expected);
145 0 : return ret;
146 : }
147 :
148 :
149 0 : static int check_sequence_felig(uint64_t fid, struct l1id_data* last, const uint8_t* data, size_t size){
150 0 : if(size < 8){
151 0 : LOG_INFO("FELIX message from fid 0x%lx (0x%x) smaller than FELIG header, size %lu.", fid, get_elink(fid), size);
152 0 : return 1;
153 : }
154 0 : xl1id_t current, expected;
155 0 : current.fields.ec = (data[4] | (data[3]<<8));
156 0 : expected.fields.ec = (last->l1id.fields.ec+1) & 0x0000ffff;
157 0 : last->mask = 0x0000ffff;
158 0 : last->l1id.xl1id = current.xl1id;
159 0 : int ret = compare(fid, current, expected);
160 0 : return ret;
161 : }
162 :
163 :
164 0 : static int check_sequence_nsw_vmm(uint64_t fid, struct l1id_data* last, const uint8_t* data, size_t size)
165 : {
166 0 : if(size < 2){
167 0 : LOG_INFO("NSW VMM message from fid 0x%lx (0x%x) too small to retrieve XL1ID, size %lu.", fid, get_elink(fid), size);
168 0 : return 1;
169 : }
170 0 : if (size > 4*(512+4)) {
171 0 : LOG_INFO("NSW VMM message from fid 0x%lx (0x%x) too long, size %lu.", fid, get_elink(fid), size);
172 : }
173 0 : xl1id_t current, expected;
174 : //enum packetType { FULL_MM=0, NULL_EVENT=1, FULL_STGC=2 , ILLEGAL=3};
175 0 : unsigned char headerType = data[0] >> 6;
176 0 : switch (headerType){
177 0 : case 0: // MM full header
178 : case 2: // sTGC full header
179 0 : current.fields.ec = (data[3] | (data[2]<<8)) & 0xff;
180 0 : expected.fields.ec = (last->l1id.fields.ec+1) & 0xff;
181 0 : last->mask = 0xffff;
182 0 : last->l1id.fields.ec = (data[3] | (data[2]<<8)) & last->mask;
183 0 : break;
184 0 : case 1: // null header
185 0 : current.fields.ec = data[1];
186 0 : expected.fields.ec = (last->l1id.fields.ec+1) & 0xff;
187 0 : last->mask = 0xff;
188 0 : last->l1id.fields.ec = data[1];
189 0 : break;
190 0 : case 3: // illegal header type
191 : {
192 0 : unsigned int vmmHeader = (data[0]<<24)|(data[1]<<16)|(data[2]<<8)|data[3];
193 0 : LOG_INFO("Illegal VMM message from fid 0x%lx (0x%x), headerType = 3, headerword = 0x%x, size %d.", fid, get_elink(fid), vmmHeader, size+8);
194 0 : break;
195 : }
196 : default:
197 : LOG_INFO("Invalid header from fid 0x%lx (0x%x), type 0x%x", fid, get_elink(fid), headerType);
198 : }
199 0 : int ret = compare(fid, current, expected);
200 0 : return ret;
201 : }
202 :
203 :
204 0 : static int check_sequence_nsw_tp(uint64_t fid, struct l1id_data* last, const uint8_t* data, size_t size)
205 : {
206 0 : if(size < 8){
207 0 : LOG_INFO("NSW TP message from fid 0x%lx (0x%x) too small to retrieve XL1ID, size %lu.", fid, get_elink(fid), size);
208 0 : return 1;
209 : }
210 0 : xl1id_t current, expected;
211 0 : current.fields.ec = ( data[5]<<16 | data[6]<<8 | data[7] ) & 0x00ffffff;
212 0 : current.fields.ecrc = (data[4]<<24) & 0xff;
213 0 : if(current.fields.ecrc == (last->l1id.fields.ecrc+1) ){
214 : LOG_DBG("ECR on fid 0x%lx (0x%x)", fid, get_elink(fid));
215 : expected.fields.ec = 0x0;
216 : } else{
217 0 : expected.fields.ec = (last->l1id.fields.ec+1) & 0x00ffffff;
218 : }
219 0 : last->mask = 0xffffffff;
220 0 : last->l1id.xl1id = current.xl1id;
221 0 : int ret = compare(fid, current, expected);
222 0 : return ret;
223 : }
|