AlcapDAQ  1
new_fadc_2007_07_17.cpp
Go to the documentation of this file.
1 #include <map>
2 using namespace std;
3 
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <stdarg.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <time.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <sys/types.h>
13 #include <sys/mman.h>
14 #include <sys/stat.h>
15 #include <sys/ioctl.h>
16 #include <sys/time.h>
17 #include <sys/socket.h>
18 #include <net/if.h>
19 #include <net/ethernet.h>
20 #include <netinet/in.h>
21 #include <linux/if_packet.h>
22 
23 #include "midas.h"
24 
25 #include "crate.h"
26 #include "vme.h"
27 #include "odb_wrapper.h"
28 #include "diag.h"
29 
30 INT new_fadc_bor();
31 INT new_fadc_eor();
32 INT new_fadc_read(char *pevent);
33 
34 const int TP_BLOCK_SIZE = 8192;
35 const int TP_NUM_BLOCKS = 512;
36 const int FRAME_SIZE = 2048;
37 const int NUM_FRAMES = 2048;
38 
39 unsigned char *packet_space = 0;
41 
43  NULL, // init
44  NULL, // exit
45  NULL, // pre_bor
46  new_fadc_bor, // bor
47  new_fadc_eor, // eor
48  NULL, // poll_live
49  NULL, // poll_dead
50  NULL, // start_cycle
51  NULL, // stop_cycle
52  new_fadc_read, // read
53 };
54 
55 bool allPacketsReceived(bool diag = false);
56 
58 
59 // packet format, including Ethernet-level headers
60 struct fadc_packet
61 {
62  unsigned char dest_addr[6];
63  unsigned char src_addr[6];
64  unsigned short protocol;
65  unsigned short content_length;
66  unsigned char buffer_number;
67  unsigned char admin_message;
68  unsigned short packet_serial;
69 };
70 
71 // state associated with each board
72 const int max_boards = 256;
73 struct fadc_board
74 {
75  bool enabled;
76  map<int, fadc_packet *> packets;
77  int start_packet;
78  int stop_packet;
79  int first_packet;
80  double first_packet_time;
81  int last_packet;
82  double last_packet_time;
83  bool start_packet_seen;
84  bool stop_packet_seen;
85 };
87 
89 {
90  for(int i = 0; i < NUM_FRAMES; i++) {
91  if(frame_examined[i]) continue;
92 
93  unsigned char *frame = packet_space + i*FRAME_SIZE;
94  struct tpacket_hdr *tph = (struct tpacket_hdr *) frame;
95  if(!(tph->tp_status & TP_STATUS_USER)) continue;
96 
97  struct fadc_packet *pkt = (struct fadc_packet *) (frame + tph->tp_mac);
98  int board_number = pkt->src_addr[5];
99  if(!board[board_number].enabled) continue;
100 
101  int content_length = ntohs(pkt->content_length);
102  int buffer_number = pkt->buffer_number;
103  int admin_message = pkt->admin_message;
104  int packet_serial = ntohs(pkt->packet_serial);
105 
106 
107 #if 0
108  printf("board %d length %d buffer %d admin %d serial %d\n",
109  board_number, content_length, buffer_number,
110  admin_message, packet_serial);
111 #endif
112 
113  board[board_number].packets[packet_serial] = pkt;
114  if(admin_message & 0x1) {
115  board[board_number].start_packet = packet_serial;
116  board[board_number].start_packet_seen = true;
117  }
118  if(admin_message & 0x2) {
119  board[board_number].stop_packet = packet_serial;
120  board[board_number].stop_packet_seen = true;
121  }
122 
123  double packet_time = tph->tp_sec*1e6 + tph->tp_usec;
124  double fpt = board[board_number].first_packet_time;
125  if(packet_time < fpt || fpt < 0) {
126  board[board_number].first_packet = packet_serial;
127  board[board_number].first_packet_time = packet_time;
128  }
129  double lpt = board[board_number].last_packet_time;
130  if(packet_time > lpt || lpt < 0) {
131  board[board_number].last_packet = packet_serial;
132  board[board_number].last_packet_time = packet_time;
133  }
134 
135  frame_examined[i] = true;
136  }
137 }
138 
140 {
141  for(int i = 0; i < max_boards; i++) {
142  if(board[i].enabled) {
143  board[i].packets.clear();
144  board[i].start_packet_seen = false;
145  board[i].stop_packet_seen = false;
146  board[i].first_packet_time = -1;
147  }
148  }
149 
150  // release all frame buffers back to the kernel
151  for(int i = 0; i < NUM_FRAMES; i++) {
152  unsigned char *frame = packet_space + i*FRAME_SIZE;
153  struct tpacket_hdr *tph = (struct tpacket_hdr *) frame;
154  tph->tp_status = TP_STATUS_KERNEL;
155  frame_examined[i] = false;
156  }
157 }
158 
159 bool allPacketsReceived(bool diag)
160 {
161  // check whether we have a start packet, a stop packet, and a stream of
162  // continuous serial numbers in between.
163 
164  bool missing = false;
165 
166  for(int i = 0; i < max_boards; i++) {
167  if(!board[i].enabled) continue;
168  if(!board[i].start_packet_seen) {
170 #if 0
171  if(diag) {
172  printf("-- board 0x%02x waiting on start packet\n", i);
173  missing = true;
174  } else {
175  return false;
176  }
177 #endif
178  if(diag) {
179  printf("-- board 0x%02x workaround for missing start packet\n", i);
180  }
181  }
182  if(!board[i].stop_packet_seen) {
184  if(diag) {
185  printf("-- board 0x%02x waiting on stop packet\n", i);
186  missing = true;
187  } else {
188  return false;
189  }
190  }
191  }
192  for(int i = 0; i < max_boards; i++) {
193  if(!board[i].enabled) continue;
194  int num_packets = board[i].stop_packet - board[i].start_packet;
195  if(num_packets < 0) {
196  num_packets += 0x10000;
197  }
198 
199  int num_missing = 0;
200 #if 0
201  if(diag) {
202  printf("Start=%d Stop=%d\n", board[i].start_packet, board[i].stop_packet);
203  }
204 #endif
205  for(int j = num_packets; j >= 0; j--) {
206  int pn = (board[i].start_packet + j) & 0xffff;
207  if(board[i].packets[pn] == NULL) {
208  if(diag) {
209 // printf("Waiting on packet %d\n", pn);
210  num_missing++;
211  missing = true;
212  } else {
213  return false;
214  }
215  }
216  }
217  if(diag) {
218  printf("-- board 0x%02x waiting on %d/%d packets\n", i,
219  num_missing, num_packets);
220  }
221  }
222  return !missing;
223 }
224 
225 
226 void setReg(char *if_name, int board, int fadc, int reg,
227  unsigned long long value)
228 {
229  // look up the index of the interface
230  int if_index = if_nametoindex(if_name);
231  if(if_index < 0) {
232  printf("Unknown interface %s\n", if_name);
233  return;
234  }
235 
236  struct ifreq req;
237  strcpy(req.ifr_name, if_name);
238  if(ioctl(packet_socket, SIOCGIFHWADDR, &req) < 0) {
239  perror("SIOCGIFHWADDR");
240  return;
241  }
242  unsigned char src[ETH_ALEN];
243  memcpy(src, req.ifr_hwaddr.sa_data, ETH_ALEN);
244 
245  unsigned char dst[ETH_ALEN] = { 0x00, 0x12, 0x6d, 0x12, 0x34, 0xff};
246  dst[5] = board;
247  struct sockaddr_ll dstaddr;
248  dstaddr.sll_family = AF_PACKET;
249  dstaddr.sll_protocol = htons(ETH_P_ALL);
250  dstaddr.sll_ifindex = if_index;
251  dstaddr.sll_hatype = 0;
252  dstaddr.sll_pkttype = 0;
253  dstaddr.sll_halen = ETH_ALEN;
254  memcpy(dstaddr.sll_addr, dst, ETH_ALEN);
255 
256  // format a packet
257  unsigned char packet[512];
258  memcpy(&packet[0], dst, ETH_ALEN);
259  memcpy(&packet[6], src, ETH_ALEN);
260 
261  // protocol
262  packet[12] = 0x0b;
263  packet[13] = 0x04;
264 
265  // the content
266  packet[14] = (fadc << 5) | reg;
267  packet[15] = (value >> 56) & 0xff;
268  packet[16] = (value >> 48) & 0xff;
269  packet[17] = (value >> 40) & 0xff;
270  packet[18] = (value >> 32) & 0xff;
271  packet[19] = (value >> 24) & 0xff;
272  packet[20] = (value >> 16) & 0xff;
273  packet[21] = (value >> 8) & 0xff;
274  packet[22] = (value ) & 0xff;
275 
276  int packet_length = 512;
277 
278  if(sendto(packet_socket, packet, packet_length, 0, (const sockaddr *) &dstaddr, sizeof(dstaddr)) < 0) {
279  perror("sendto");
280  }
281 }
282 
283 void setupRegs()
284 {
285  for(int i = 0; i < max_boards; i++) {
286 
287  // If no settings exist for the board, disable it.
288  if(!odb_find_key("/Equipment/Crate %d/Settings/NFADC %02x",
289  crate_number, i)) {
290  board[i].enabled = false;
291  continue;
292  }
293  printf("Found board %02x\n", i);
294 
295  bool enabled =
296  odb_get_bool("/Equipment/Crate %d/Settings/NFADC %02x/Enabled",
297  crate_number, i);
298  board[i].enabled = enabled;
299 
300 
301  for(int chan = 0; chan < 8; chan++) {
302  int led_mode =
303  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/LED Mode",
304  crate_number, i, chan);
305 
306  int lower_threshold =
307  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Lower threshold",
308  crate_number, i, chan);
309  int upper_threshold =
310  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Upper threshold",
311  crate_number, i, chan);
312  int pulser_period =
313  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Pulser period",
314  crate_number, i, chan);
315  int trigger_mask =
316  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Trigger mask",
317  crate_number, i, chan);
318  int presamples =
319  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Presamples",
320  crate_number, i, chan);
321  int stretch_samples =
322  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/Stretch samples",
323  crate_number, i, chan);
324  int dcm_phase =
325  odb_get_int("/Equipment/Crate %d/Settings/NFADC %02x/Channel %d/DCM phase",
326  crate_number, i, chan);
327 
328  if(enabled) {
329  unsigned long long r0;
330  if(i == 0xff) {
331  r0 = (lower_threshold & 0xfff) |
332  ((upper_threshold & 0xfff) << 12) |
333  ((trigger_mask & 0xf) << 24) |
334  ((presamples & 0xf) << 28) |
335  (((unsigned long long) (stretch_samples & 0xff)) << 32);
336  } else {
337  r0 = (lower_threshold & 0xfff) |
338  ((upper_threshold & 0xfff) << 12) |
339  ((trigger_mask & 0xf) << 24) |
340  ((presamples & 0xfff) << 28) |
341  (((unsigned long long) (stretch_samples & 0xfff)) << 40);
342  }
343  unsigned long long r1 =
344  (pulser_period & 0xffffffff) |
345  (((unsigned long long) (led_mode & 0xf)) << 32);
346  unsigned long long r2 = dcm_phase;
347 
348  int frontend = chan/2;
349  if(i == 0xff) {
350  if(frontend == 1) {
351  frontend = 2;
352  } else if(frontend == 2) {
353  frontend = 1;
354  }
355  }
356 
357  if(chan % 2 == 0) {
358  setReg("eth1", i, frontend, 0, r0);
359  setReg("eth1", i, frontend, 1, r1);
360  setReg("eth1", i, frontend, 4, r2);
361  } else {
362  setReg("eth1", i, frontend, 2, r0);
363  setReg("eth1", i, frontend, 3, r1);
364  setReg("eth1", i, frontend, 5, r2);
365  }
366  }
367  }
368  }
369 }
370 
371 INT new_fadc_bor()
372 {
373  // open a socket to receive packets for our protocol
374  packet_socket = socket(PF_PACKET, SOCK_RAW, htons(0x0b04));
375 
376  if(packet_socket < 0) {
377  perror("socket");
378  return FE_ERR_HW;
379  }
380 
381  // request that the packets be placed in a memory-mapped buffer
382  struct tpacket_req req;
383  req.tp_block_size = TP_BLOCK_SIZE;
384  req.tp_block_nr = TP_NUM_BLOCKS;
385  req.tp_frame_size = FRAME_SIZE;
386  req.tp_frame_nr = NUM_FRAMES;
387  int status = setsockopt(packet_socket, SOL_PACKET, PACKET_RX_RING,
388  (void *) &req, sizeof(req));
389  if(status < 0) {
390  perror("setsockopt PACKET_RX_RING");
391  return FE_ERR_HW;
392  }
393 
394  // map the buffer into our process address space
395  packet_space = (unsigned char *) mmap(0, TP_BLOCK_SIZE*TP_NUM_BLOCKS,
396  PROT_READ|PROT_WRITE, MAP_SHARED, packet_socket, 0);
397  if(packet_space == MAP_FAILED) {
398  perror("mmap");
399  return FE_ERR_HW;
400  }
401 
402  setupRegs();
403  forgetPackets();
404 
405  return SUCCESS;
406 }
407 
408 INT new_fadc_eor()
409 {
410  if(packet_space != 0) {
411  munmap(packet_space, TP_BLOCK_SIZE*TP_NUM_BLOCKS);
412  packet_space = 0;
413  }
414  close(packet_socket);
415  return SUCCESS;
416 }
417 
418 static struct timeval tv_start;
419 
420 INT new_fadc_read(char *pevent)
421 {
422  printf("new_fadc_read\n");
423 
424  char bk_name[80];
425  char *pdata;
426 
427  bool timed_out = false;
428  struct timeval t1, t2;
429  gettimeofday(&t1,0);
430 
431  receivePackets();
432 
433  while(!allPacketsReceived()) {
434  sched_yield();
435  receivePackets();
436 
437  gettimeofday(&t2,0);
438  double tdiff = (t2.tv_usec-t1.tv_usec) + 1000000*(t2.tv_sec-t1.tv_sec);
439  if(tdiff > 1000) {
440  printf("Timed out:\n");
441  allPacketsReceived(true); // for diagnostic printout
442  timed_out = true;
443  break;
444  }
445  }
446 
447  for(int i = 0; i < max_boards; i++) {
448  if(board[i].enabled) {
449  printf("Board %d: start %d (%c) - stop %d (%c)\n", i,
450  board[i].start_packet, board[i].start_packet_seen ? '-' : 'X',
451  board[i].stop_packet, board[i].stop_packet_seen ? '-' : 'X');
452  }
453  }
454 
455  bk_init32(pevent);
456 
457 // if(!timed_out) {
458 // printf("Block OK\n");
459  for(int i = 0; i < max_boards; i++) {
460  if(!board[i].enabled) continue;
461 
462  for(int j = 0; j < 4; j++) {
463  sprintf(bk_name, "N%c%02x", 'a' + j, i);
464  bk_create(pevent, bk_name, TID_BYTE, &pdata);
465 
466  int num_packets = board[i].stop_packet - board[i].start_packet + 1;
467  if(num_packets < 0) {
468  num_packets += 0x10000;
469  }
470 
471  for(int k = 0; k < num_packets; k++) {
472  int pn = (board[i].start_packet + k) & 0xffff;
473  struct fadc_packet *pkt = board[i].packets[pn];
474  if(pkt) {
475  int frontend = (pkt->buffer_number - 1) / 3;
476  if(frontend == j) {
477  int len = ntohs(pkt->content_length);
478  char *p = ((char *) pkt) + 20;
479  memcpy(pdata, p, len);
480  if((len % 10) != 0) printf("board %d: content_length = %d !\n", i, len);
481  pdata += len;
482  }
483  }
484  }
485 
486  bk_close(pevent, pdata);
487  }
488  }
489 // }
490 
491  forgetPackets();
492 
493  return SUCCESS;
494 }
495 
496 /* ******************************************************************* */