Files
sics/sinqhm/SinqHM_srv_routines.c
cvs 4ebf207325 - Many fixes to tas code
- fixes to amor writing and status code
- edited ecbcounter to stop at no beam
- updated documentation
- fixed a bug in project code affecting SANS
2003-05-05 07:49:26 +00:00

4131 lines
138 KiB
C
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#define IDENT "1B06"
/*
** +--------------------------------------------------------------+
** | Paul Scherrer Institute |
** | SINQ Division |
** | |
** | This software may be used freely by non-profit organizations.|
** | It may be copied provided that the name of P.S.I. and of the |
** | author is included. Neither P.S.I. nor the author assume any |
** | responsibility for the use of this software outside of P.S.I.|
** +--------------------------------------------------------------+
**
** Module Name . . . . . . . . : [...SinqHM]SinqHM_srv_routines.c
**
** Author . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Dec 1996
**
** Updates:
** 1A01 12-Dec-1996 DM Initial version.
** 1A06 16-Jul-1997 DM Flush fibre-optic FIFO on SQHM_ZERO and SQHM_WRITE.
** 1B01 11-Jun-1999 DM Add SQHM__HRPT mode.
** 1B02 10-Aug-1999 DM Make Lwl_hdr_daq_mask/Lwl_hdr_daq_soll dependent
** on the instrument.
** 1B03 May-2001 MK Added code for AMOR/TRICS PSD
** 1B04 August 2001 MK Added code for AMOR to PROJECT handling
**---------------------------------------------------------------------------
** SinqHM_srv_routines.c is part of the SINQ Histogram Memory process
** which will run in a front-end processor and perform the necessary
** operations for a SINQ multi-detector. It provides various utility routines.
**
** To compile this program for VxWorks on PSS123, use:
**
ccvx SinqHM_srv_routines.c
** where
ccvx = ccppc -O0 \
-mcpu=603 \
-I${WIND_BASE}/target/h \
-fno-builtin \
-fno-for-scope \
-nostdinc \
-DCPU=PPC603 \
-D_GNU_TOOL \
-gdwarf -c -Wimplicit
**====================================================================
*/
#include <vxWorks.h>
#include <taskLib.h>
#include <msgQLib.h>
#include <sockLib.h>
#include <hostLib.h>
#include <inetLib.h>
#include <sysLib.h>
#ifdef MEN_A012
/*
#include <MEN/men_typs.h>
#include <sysLib_men.h>
*/
extern PART_ID sysHighMemPart;
#endif
#include <tickLib.h>
#include <stdlib.h>
#include <stdio.h>
#include <ioLib.h>
#include <signal.h>
#include <timers.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <unistd.h>
#include <setjmp.h>
#include <vme.h>
/*
**==================== Global Definitions =====================================
*/
#include "SinqHM_def.h"
#include "SinqHM_gbl.h"
#include "vmio10_def.h"
extern char *vxWorksVersion; /* Version string of vxWorks */
extern char *creationDate; /* Creation Date string of vxWorks */
/*========================== Define some prototypes ================*/
/*
**=============================================================================
** Routines in this Module:
**
** SinqHM_routines_setup_id : copy some ident information to global vars.
**
** catch_int_signal : SIGINT signal catching routine.
** catch_machine_check : SIGBUS signal catching routine.
** catch_signal : Signal catching routine.
** chk_config_alloc : Check a configuration request and allocate memory.
** cleanup_children : Find out which child(ren) have exited.
** close_down_offspring : Close down FILLER and, possibly, other children.
** do_SQHM__HM_DIG_alloc: SQHM__HM_DIG aux routine for chk_config_alloc.
** do_SQHM__HRPT_alloc : SQHM__HRPT aux routine for chk_config_alloc.
** do_SQHM__TOF_alloc : SQHM__TOF aux routine for chk_config_alloc.
** do_SQHM__PSD_alloc : SQHM__PSD aux routine for chk_config_alloc.
** do_SQHM__TRANS_alloc : SQHM__TRANS aux routine for chk_config_alloc.
** do_command : Routine to handle a network command.
** do_daq : Action routine for SINQHM_DAQ command.
** do_project : Read projected histogram data.
** do_read : Read a block of the histogram memory.
** do_write : Write a block of the histogram memory.
** do_zero : Action routine for SINQHM_ZERO command.
** failInet : Call to report fatal network failure.
** failInet_port : Call to failInet with an extra parameter.
** free_HM_memory : Release any allocated data structures.
** getErrno : Get local copy of errno.
** get_pid : Get our process ID (= TaskID under VxWorks).
** kill_children : Send stop signals to all children to stop them.
** lwl_Fifo_Flush : Flush out any data in the fibre-optic FIFO.
** lwl_Packet_Read : Read out current packet from the fibre-optic FIFO.
** make_child : Make a child process and activate it.
** make_filler : Make the filler process and activate it.
** net_flush : Flush out data from socket.
** process_coinc_tsi : Process a "coincidence" type TSI packet.
** process_no_coinc_tsi : Process a "normal" type TSI packet.
** rply_status_send : Send a reply status message to client.
** rply_status_setup : Setup a reply status message to client.
** rply_status_setup_and_send : Setup & send a reply status msg to client.
** selectNewBuffer : Move to new buffer in SQHM_TRANS mode.
** setupLevelGenerator : Set up VMIO10 module for generating timing signals.
** setup_inet_info : Used to get Internet Node name and addr from system.
** sleep : Go to sleep for a bit.
** StrJoin : join 2 strings.
**==============================================================================
*/
void SinqHM_routines_setup_id () {
/* ========================
** Simply copy some ident information to global variables
** for use by the SQHM_IDENT request.
*/
StrJoin (Sqhm_rout_ident, sizeof (Sqhm_rout_ident), IDENT, "");
StrJoin (Sqhm_rout_date, sizeof (Sqhm_rout_date), __DATE__, ", ");
StrJoin (Sqhm_rout_date, sizeof (Sqhm_rout_date), Sqhm_rout_date, __TIME__);
}
/*
**--------------------------------------------------------------------------*/
void catch_int_signal (int signo) {
/* ================
** Action Routine for catching SIGINT signals. This is a signal
** from the parent to get its child to exit. An exit will be performed.
*/
int i, is;
pid_t my_pid;
my_pid = get_pid ();
/*
** Try to find our index by searching the PID list
*/
if (my_pid == Filler_pid) {
if (FillTimer_active) { /* If Filler, kill off timer */
is = timer_cancel (FillTimerId);
if (is != 0) printf ("Problem cancelling FillTimer\n");
is = timer_delete (FillTimerId);
if (is != 0) printf ("Problem deleting FillTimer\n");
FillTimer_active = False;
}
}else {
for (i = MAX_CLIENTS; i > 0; i--) if (my_pid == Child_pid[i]) break;
if (i > 0) {
if (Child_rw_skt[i] != 0) {
printf ("\nClosing r/w socket of task %s\n", Tsk_name[i]);
close (Child_rw_skt[i]);
Child_rw_skt[i] = 0;
}
if (Child_cnct_skt[i] != 0) {
printf ("\nClosing connect socket of task %s\n", Tsk_name[i]);
close (Child_cnct_skt[i]);
Child_cnct_skt[i] = 0;
}
}
}
if (Dbg_lev0) printf ("catch_int_signal: Signal %d received by PID 0x%x.\n",
signo, my_pid);
switch (signo) {
case SIGINT: /* A SIGINT signal has been received. Exit. */
exit (KER__SUCCESS);
break;
default:
printf ("catch_int_signal: Unexpected signal %d received by PID 0x%x.\n",
signo, my_pid);
}
}
/*
**--------------------------------------------------------------------------*/
void catch_machine_check (int signo) {
/* ===================
*/
longjmp (Vmio_trap_env, 1); /* Return to trapped code */
}
/*
**--------------------------------------------------------------------------
*/
void catch_signal (int signo) {
/* ============
** Action Routine for catching signals from Child Processes.
*/
pid_t my_pid;
my_pid = get_pid ();
if (Dbg_lev0) printf ("catch_signal: Signal %d received by PID 0x%x.\n",
signo, my_pid);
switch (signo) {
case SIGUSR1: /* A child is about to exit. */
Cnt_SIGUSR1++;
sleep (1); /* Give it a chance to disappear! */
break;
default:
printf ("catch_signal: Unexpected signal received by PID 0x%x: %d.\n",
my_pid, signo);
}
}
/*
**--------------------------------------------------------------------------*/
int chk_config_alloc (
/* ================
*/ int skt,
struct req_buff_struct *request,
struct rply_buff_struct *reply) {
/*
**
** Routine to check a configuration request and reserve the
** space for the histogram data.
** Return OK if configuration request OK.
** ERROR if error.
*/
int i, mask, s_stat;
Hm_mode_ALL = ntohl (request->u.cnfg.mode); /* The histogramming mode */
Hm_mode = Hm_mode_ALL & (~SQHM__SUB_MODE_MSK);
Hm_mode_DEBUG = Hm_mode_ALL & SQHM__DEBUG;
Hm_mode_UD = Hm_mode_ALL & SQHM__UD;
Hm_mode_BO = Hm_mode_ALL & SQHM__BO_MSK;
Hm_mode_STROBO = Hm_mode_ALL & SQHM__STROBO;
Hm_mode_REFLECT = Hm_mode_ALL & SQHM__REFLECT;
Hm_mode_NO_STAT = Hm_mode_ALL & SQHM__NO_STAT;
switch (Hm_mode) {
/*----------------------------*/
case SQHM__TRANS:
s_stat = do_SQHM__TRANS_alloc (request, reply);
if (s_stat != OK) return ERROR;
break;
/*----------------------------*/
case SQHM__HM_DIG:
s_stat = do_SQHM__HM_DIG_alloc (request, reply);
if (s_stat != OK) return ERROR;
break;
/*----------------------------*/
case SQHM__HRPT:
s_stat = do_SQHM__HRPT_alloc (request, reply);
if (s_stat != OK) return ERROR;
break;
/*----------------------------*/
case SQHM__HM_PSD:
s_stat = do_SQHM__PSD_alloc (skt, request, reply);
if (s_stat != OK) return ERROR;
break;
/*----------------------------*/
case SQHM__TOF:
s_stat = do_SQHM__TOF_alloc (skt, request, reply);
if (s_stat != OK) return ERROR;
break;
/*----------------------------*/
default:
printf ("\nchk_config_alloc: "
"unrecognised histogramming mode: %d.\n", Hm_mode);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Unrecognised hist mem mode");
return ERROR;
/*----------------------------*/
}
Cfgn_done = 1;
return OK;
}
/*
**--------------------------------------------------------------------------*/
void cleanup_children () {
/* ================
** Find out which child(ren) have exited and update the
** list of task PID's so the associated task slot becomes
** free.
**
** If FILLER has fallen off, then any active children will
** be told to exit and we shall set our state to "deconfig".
*/
int i, status, n_active;
char *t_name;
pid_t pid;
if (Filler_pid != 0) {
if (Dbg_lev0) printf ("\n ... checking state of %s ...", Filler_name);
t_name = taskName (Filler_pid);
if (t_name == NULL) {
if (Dbg_lev0) printf (" it has exited.");
Filler_pid = 0;
}else {
if (Dbg_lev0) printf (" it is still active.");
}
}
n_active = 0;
for (i = 1; i <= MAX_CLIENTS; i++) {
if (Child_pid[i] != 0) {
if (Dbg_lev0) printf ("\n ... checking state of SRV_%02d ...", i);
t_name = taskName (Child_pid[i]);
if (t_name == NULL) {
if (Dbg_lev0) printf (" it has exited.");
Child_pid[i] = 0;
}else {
if (Dbg_lev0) printf (" it is still active.");
n_active += 1;
}
}
}
Cnt_SIGUSR1 = 0;
if ((Filler_pid == 0) && (n_active > 0)) { /* Must we force a de-config? */
for (;;) { /* Loop for ever till programmed */
printf ("\n\007hmFill has terminated abnormally. A de-configure must"
"be forced\n"
"This has not yet been programmed.\n"
"Re-boot the histogram memory!!\n");
sleep (5);
}
}
}
/*
**--------------------------------------------------------------------------*/
int close_down_offspring (
/* ====================
*/ struct req_buff_struct *request,
struct rply_buff_struct *reply) {
/*
** Close down FILLER and, if directed, other children too.
*/
int i, j;
int n_children = 0, new_c = 0;
n_children = 0; /* See if any server children are active */
for (i = 1; i <= MAX_CLIENTS; i++) {
if (Child_pid[i] != 0) n_children += 1;
}
if (n_children > 0) { /* If so, only proceed if asked to be ruthless */
if (ntohl (request->u.decnfg.sub_code) == 0) {
printf ("\nDe-configure error. ");
if (n_children == 1) printf ("1 server is");
if (n_children != 1) printf ("%d servers are", n_children);
printf (" still active.\n");
return KER__BAD_STATE;
}else {
if (n_children == 1) printf (" -- 1 server is still active. It");
if (n_children != 1) printf (" -- %d servers are still active. They",
n_children);
printf (" will be terminated.\n");
}
}
kill_children (); /* Kill FILLER and any server children */
sleep (1); /* Give them chance to exit */
cleanup_children (); /* Update the PIDs */
for (j = 0; j < n_children; j++) { /* Check to see if all gone */
if (Filler_pid == 0) new_c = 0; else new_c = 1; /* Count remainder */
for (i = MAX_CLIENTS; i > 0; i--) {
if (Child_pid[i] != 0) new_c += 1;
}
if (new_c == 0) break;
sleep (1);
cleanup_children ();
}
if (new_c != 0) {
printf (" ... failed to tidy up. %d children still active.\n", new_c);
return KER__BAD_STATE;
}else {
return KER__SUCCESS;
}
}
/*
**--------------------------------------------------------------------------*/
int do_SQHM__HM_DIG_alloc (
/* =====================
*/ struct req_buff_struct *request,
struct rply_buff_struct *reply) {
/*
** Routine to allocate memory for the SQHM__HM_DIG
** configure request.
**
*/
int i;
N_hists = ntohl (request->u.cnfg.u.hm_dig.n_hists); /* The # of
** histograms (used in strobo (gummi)
** and Up/Down mode).
*/
Lo_bin = ntohl (request->u.cnfg.u.hm_dig.lo_bin); /* The index of
** first bin in histogram
*/
N_bins = ntohl (request->u.cnfg.u.hm_dig.num_bins); /* The # of bins
** in each histogram
*/
Bytes_per_bin = ntohl (request->u.cnfg.u.hm_dig.bytes_per_bin); /* The # of
** bytes per bin
*/
Compress = ntohl (request->u.cnfg.u.hm_dig.compress); /* The compression
** factor
*/
Curr_hist = 0; /* The selected histogram */
if (Compress == 0) Compress = 1;
if (Bytes_per_bin == 0) Bytes_per_bin = 4;
if (N_hists > N_HISTS_MAX) {
printf ("do_SQHM__HM_DIG_alloc: Illegal number of histograms: %d.\n",
N_hists);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad number of histograms");
return ERROR;
}else if (Hm_mode_UD && (N_hists & 1)) {
printf ("do_SQHM__HM_DIG_alloc: SQHM_UD is set.\n"
" Number of histograms should be multiple of 2.\n"
" %d is therefore illegal.\n", N_hists);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Number of histograms not multiple of 2");
return ERROR;
}else if (Hm_mode_STROBO && (N_hists & 15)) {
printf ("do_SQHM__HM_DIG_alloc: SQHM_STROBO is set.\n"
" Number of histograms should be multiple of 16.\n"
" %d is therefore illegal.\n", N_hists);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Number of histograms not multiple of 16");
return ERROR;
}else if (Hm_mode_UD && Hm_mode_STROBO && (N_hists & 31)) {
printf ("do_SQHM__HM_DIG_alloc: SQHM_UD and SQHM_STROBO are both set.\n"
" Number of histograms should be multiple of 32.\n"
" %d is therefore illegal.\n", N_hists);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Number of histograms not multiple of 32");
return ERROR;
}
if (Lo_bin > N_BINS_MAX) {
printf ("do_SQHM__HM_DIG_alloc: Illegal first bin: %d.\n", Lo_bin);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad first bin");
return ERROR;
}
if (N_bins > (N_BINS_MAX + 1)) {
printf ("do_SQHM__HM_DIG_alloc: Illegal number of bins: %d.\n", N_bins);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad # bins");
return ERROR;
}
Hi_bin = Lo_bin + N_bins - 1;
if (Hi_bin > N_BINS_MAX) {
printf ("do_SQHM__HM_DIG_alloc: Illegal first-bin and/or number-of-bins:"
" %d %d.\n", Lo_bin, N_bins);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad bin definition");
return ERROR;
}
if ((Bytes_per_bin != 1) && (Bytes_per_bin != 2) && (Bytes_per_bin != 4)) {
printf ("do_SQHM__HM_DIG_alloc: Illegal bin width: %d.\n", Bytes_per_bin);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad bytes-per-bin");
return ERROR;
}
Total_bytes = N_hists * N_bins * Bytes_per_bin;
if (Total_bytes > N_TOTAL_BYTES) { /* Check it's not too much */
printf ("do_SQHM__HM_DIG_alloc: Illegal overall size: %d.\n", Total_bytes);
printf (" Permitted max: %d.\n", N_TOTAL_BYTES);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Total histogram size too big");
return ERROR;
}
printf ("\n Histogramming mode is \"SQHM__HM_DIG\"\n");
printf (" Number of histograms = %5d\n", N_hists);
printf (" First bin = %5d\n", Lo_bin);
printf (" Number of bins = %5d\n", N_bins);
printf (" Bytes per bin = %5d\n", Bytes_per_bin);
printf (" Bin compression factor = %5d\n", Compress);
if (Hm_mode_UD != 0)
printf (" Up/Down mode selected\n");
if (Hm_mode_STROBO != 0)
printf (" Stroboscopic mode selected\n");
if (Hm_mode_REFLECT != 0)
printf (" Histograms will be reflected\n");
printf (" Bin-overflow action is ");
switch (Hm_mode_BO) {
case SQHM__BO_IGN: printf ("\"Ignore\"\n"); break;
case SQHM__BO_SMAX: printf ("\"Stop-at-Max\"\n"); break;
case SQHM__BO_CNT: printf ("\"Count\"\n"); break;
default: printf ("\"Undefined\"\n");
}
i = memFindMax (); /* Get size of biggest free memory block */
if (i > Total_bytes) {
Hist_base_addr = calloc (Total_bytes, sizeof (char));
}else {
Hist_base_addr = NULL;
}
if (Hist_base_addr == NULL) {
printf ("\007do_SQHM__HM_DIG_alloc:\n"
" Unable to reserve %d bytes of memory!\n"
" Largest block available = %d.\n", Total_bytes, i);
rply_status_setup (reply, KER__BAD_ALLOC, i,
"Failed to get buffer for histograms");
return ERROR;
}
Cnts_lo = Cnts_hi = 0;
N_events = N_skipped = N_no_coin_tsi = N_coin_tsi = 0;
Print_hdr = True;
printf (" Histogram base address = 0x%08x\n", Hist_base_addr);
printf (" SQHM__HM_DIG mode configured.\n");
return OK;
}
/*
**--------------------------------------------------------------------------*/
int do_SQHM__HRPT_alloc (
/* ===================
*/ struct req_buff_struct *request,
struct rply_buff_struct *reply) {
/*
** Routine to allocate memory for the SQHM__HRPT
** configure request.
**
*/
int i;
N_hists = ntohl (request->u.cnfg.u.hm_dig.n_hists); /* The # of
** histograms (used in strobo (gummi)
** and Up/Down mode).
*/
Lo_bin = ntohl (request->u.cnfg.u.hm_dig.lo_bin); /* The index of
** first bin in histogram
*/
N_bins = ntohl (request->u.cnfg.u.hm_dig.num_bins); /* The # of bins
** in each histogram
*/
Bytes_per_bin = ntohl (request->u.cnfg.u.hm_dig.bytes_per_bin); /* The # of
** bytes per bin
*/
Compress = ntohl (request->u.cnfg.u.hm_dig.compress); /* The compression
** factor
*/
Curr_hist = 0; /* The selected histogram */
if (Compress == 0) Compress = 1;
if (Bytes_per_bin == 0) Bytes_per_bin = 4;
if (N_hists > N_HISTS_MAX) {
printf ("do_SQHM__HRPT_alloc: Illegal number of histograms: %d.\n",
N_hists);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad number of histograms");
return ERROR;
}else if (Hm_mode_UD && (N_hists & 1)) {
printf ("do_SQHM__HRPT_alloc: SQHM_UD is set.\n"
" Number of histograms should be multiple of 2.\n"
" %d is therefore illegal.\n", N_hists);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Number of histograms not multiple of 2");
return ERROR;
}else if (Hm_mode_STROBO && (N_hists & 15)) {
printf ("do_SQHM__HRPT_alloc: SQHM_STROBO is set.\n"
" Number of histograms should be multiple of 16.\n"
" %d is therefore illegal.\n", N_hists);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Number of histograms not multiple of 16");
return ERROR;
}else if (Hm_mode_UD && Hm_mode_STROBO && (N_hists & 31)) {
printf ("do_SQHM__HRPT_alloc: SQHM_UD and SQHM_STROBO are both set.\n"
" Number of histograms should be multiple of 32.\n"
" %d is therefore illegal.\n", N_hists);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Number of histograms not multiple of 32");
return ERROR;
}
if (Lo_bin > N_BINS_MAX) {
printf ("do_SQHM__HRPT_alloc: Illegal first bin: %d.\n", Lo_bin);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad first bin");
return ERROR;
}
if (N_bins > (N_BINS_MAX + 1)) {
printf ("do_SQHM__HRPT_alloc: Illegal number of bins: %d.\n", N_bins);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad # bins");
return ERROR;
}
Hi_bin = Lo_bin + N_bins - 1;
if (Hi_bin > N_BINS_MAX) {
printf ("do_SQHM__HRPT_alloc: Illegal first-bin and/or number-of-bins:"
" %d %d.\n", Lo_bin, N_bins);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad bin definition");
return ERROR;
}
if ((Bytes_per_bin != 1) && (Bytes_per_bin != 2) && (Bytes_per_bin != 4)) {
printf ("do_SQHM__HRPT_alloc: Illegal bin width: %d.\n", Bytes_per_bin);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad bytes-per-bin");
return ERROR;
}
Total_bytes = N_hists * N_bins * Bytes_per_bin;
if (Total_bytes > N_TOTAL_BYTES) { /* Check it's not too much */
printf ("do_SQHM__HRPT_alloc: Illegal overall size: %d.\n", Total_bytes);
printf (" Permitted max: %d.\n", N_TOTAL_BYTES);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Total histogram size too big");
return ERROR;
}
printf ("\n Histogramming mode is \"SQHM__HRPT\"\n");
printf (" Number of histograms = %5d\n", N_hists);
printf (" First bin = %5d\n", Lo_bin);
printf (" Number of bins = %5d\n", N_bins);
printf (" Bytes per bin = %5d\n", Bytes_per_bin);
printf (" Bin compression factor = %5d\n", Compress);
if (Hm_mode_UD != 0)
printf (" Up/Down mode selected\n");
if (Hm_mode_STROBO != 0)
printf (" Stroboscopic mode selected\n");
if (Hm_mode_REFLECT != 0)
printf (" Histograms will be reflected\n");
printf (" Bin-overflow action is ");
switch (Hm_mode_BO) {
case SQHM__BO_IGN: printf ("\"Ignore\"\n"); break;
case SQHM__BO_SMAX: printf ("\"Stop-at-Max\"\n"); break;
case SQHM__BO_CNT: printf ("\"Count\"\n"); break;
default: printf ("\"Undefined\"\n");
}
i = memFindMax (); /* Get size of biggest free memory block */
if (i > Total_bytes) {
Hist_base_addr = calloc (Total_bytes, sizeof (char));
Frame_base_addr = calloc (((N_bins + 2) * Bytes_per_bin), sizeof (char));
}else {
Hist_base_addr = NULL;
Frame_base_addr = NULL;
}
if (Hist_base_addr == NULL) {
free_HM_memory (NULL);
printf ("\007do_SQHM__HRPT_alloc:\n"
" Unable to reserve %d bytes of memory!\n"
" Largest block available = %d.\n", Total_bytes, i);
rply_status_setup (reply, KER__BAD_ALLOC, i,
"Failed to get buffer for histograms");
return ERROR;
}
if (Frame_base_addr == NULL) {
free_HM_memory (NULL);
printf ("\007do_SQHM__HRPT_alloc:\n"
" Unable to reserve %d bytes of memory for frame buffer!\n"
" Largest block available = %d.\n", ((N_bins + 2) * Bytes_per_bin), i);
rply_status_setup (reply, KER__BAD_ALLOC, i,
"Failed to get frame buffer");
return ERROR;
}
Cnts_lo = Cnts_hi = 0;
N_events = N_skipped = N_no_coin_tsi = N_coin_tsi = 0;
Print_hdr = True;
printf (" Histogram base address = 0x%08x\n", Hist_base_addr);
printf (" Frame buffer base address = 0x%08x\n", Frame_base_addr);
printf (" SQHM__HRPT mode configured.\n");
return OK;
}
/*
**--------------------------------------------------------------------------*/
int do_SQHM__TRANS_alloc (
/* ====================
*/ struct req_buff_struct *request,
struct rply_buff_struct *reply) {
/*
** Routine to allocate memory for the SQHM__TRANS
** configure request.
*/
int i;
N_hists = ntohl (request->u.cnfg.u.trans.n_buffs); /* The # of buffers */
N_bins = ntohl (request->u.cnfg.u.trans.n_bytes); /* The buffer size */
Bytes_per_bin = 1;
Curr_hist = 0; /* Start with the first buffer */
Bytes_free = N_bins;
Lo_cntr = Lo_bin = Hi_bin = Compress = Cnts_lo = Cnts_hi = 0;
if ((N_hists == 0) || (N_hists > N_HISTS_MAX)) {
printf ("do_SQHM__TRANS_alloc: Illegal number of buffers: %d.\n",
N_hists);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad number of buffers");
return ERROR;
}
if ((N_bins < 23) || (N_bins > (N_BINS_MAX + 1))) {
printf ("do_SQHM__TRANS_alloc: Illegal buffer size: %d.\n", N_bins);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Illegal buffer size");
return ERROR;
}
Total_bytes = N_hists * (N_bins + 4);
if (Total_bytes > N_TOTAL_BYTES) { /* Check it's not too much */
printf ("do_SQHM__TRANS_alloc: Illegal overall size: %d.\n", Total_bytes);
printf (" Permitted max: %d.\n", N_TOTAL_BYTES);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Total buffer size too big");
return ERROR;
}
printf ("\n Histogramming mode is \"SQHM__TRANS\"\n");
printf (" Number of buffers = %5d\n", N_hists);
printf (" Buffer size = %5d bytes\n", N_bins);
i = memFindMax (); /* Get size of biggest free memory block */
if (i > Total_bytes) {
Hist_base_addr = calloc (Total_bytes, sizeof (char));
}else {
Hist_base_addr = NULL;
}
if (Hist_base_addr == NULL) {
printf ("\007do_SQHM__TRANS_alloc:\n"
" Unable to reserve %d bytes of memory!\n"
" Largest block available = %d.\n", Total_bytes, i);
rply_status_setup (reply, KER__BAD_ALLOC, i,
"Failed to get space for buffers");
return ERROR;
}
Tran_buff_base = Hist_base_addr;
Next_char = Tran_buff_base + 4;
printf (" Buffer base address = 0x%08x\n", Hist_base_addr);
printf (" SQHM__TRANS mode configured.\n");
return OK;
}
/*
**--------------------------------------------------------------------------*/
int do_SQHM__TOF_alloc (
/* ==================
*/ int skt,
struct req_buff_struct *request,
struct rply_buff_struct *reply) {
/*
** Routine to allocate memory for the SQHM__TOF
** configure request.
**
** Definitions:
** Edge-Array
** An 'edge-array' is a structure which specifies the lower edge
** of each bin in the histogram. This is to allow variable width
** histogram bins.
** Counter Bank
** A 'counter bank' is a contiguous group of counters, all of
** which share the same parameters. In particular, all the counters
** in the bank have the same number of bins and same bin edges.
*/
int i, j, k, n_bytes_got;
uint n_extra_bytes, n_banks, com2, nchar;
uint first, n_cntrs, edge_indx, bytes_per_bin;
uint n_bins, flag, edge_0, edge_1, bin_span, top_edge;
uint bytes_needed, sizeof_edge_arr;
uint time_span, n_total_bins;
struct tof_edge_info *edge_info_pntr;
struct tof_edge_arr *edge_arr_pntr;
struct tof_bank *bank_pntr;
void *nxt_hist_addr;
struct req_buff_struct *my_rqst;
char *p_addr, buff[64];
Total_bytes = 0;
n_extra_bytes = ntohl (request->u.cnfg.u.tof.n_extra_bytes); /* The # of
** extra bytes needed to be read from
** the client to complete the configure
** request.
*/
if (n_extra_bytes == 0) {
my_rqst = request;
}else {
/*
** There is extra data to be read. Get buffer space for the
** extra stuff plus space to copy over what has already been
** read so that everything is in a contiguous buffer.
*/
bytes_needed = n_extra_bytes + sizeof (*request);
bytes_needed = (bytes_needed + 3) & (~3); /* Round up to multiple of 4 */
p_addr = calloc (bytes_needed, sizeof (char));
if (p_addr == NULL) {
printf ("\007do_SQHM__TOF_alloc:\n"
" cannot allocate memory for extra config data!\n");
net_flush (skt, n_extra_bytes);
rply_status_setup (reply, KER__BAD_ALLOC, 0,
"Failed to get buffer for extra config data");
return ERROR;
}
memcpy (p_addr, request, sizeof (*request)); /* Copy in what has already
** been read.
*/
my_rqst = (struct req_buff_struct *) p_addr;
bytes_needed = n_extra_bytes; /* And read the rest */
p_addr = p_addr + sizeof (*request);
while (bytes_needed > 0) {
n_bytes_got = recv (skt, p_addr, bytes_needed, 0);
if (n_bytes_got <= 0) break;
Rw_bytes_got += n_bytes_got;
bytes_needed -= n_bytes_got;
p_addr += n_bytes_got;
}
if (n_bytes_got < 0) {
printf ("\007"
"%s -- R/W-Socket recv error\n", Tsk_name[0]);
printf ("%s -- Connection will be closed.\n", Tsk_name[0]);
rply_status_setup (reply, KER__BAD_VALUE, 0, "recv failed");
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
}
printf ("\n Histogramming mode is \"SQHM__TOF\"\n");
if (Hm_mode_UD != 0)
printf (" Up/Down mode selected\n");
if (Hm_mode_STROBO != 0)
printf (" Stroboscopic mode selected\n");
printf (" Bin-overflow action is ");
switch (Hm_mode_BO) {
case SQHM__BO_IGN: printf ("\"Ignore\"\n"); break;
case SQHM__BO_SMAX: printf ("\"Stop-at-Max\"\n"); break;
case SQHM__BO_CNT: printf ("\"Count\"\n"); break;
default: printf ("\"Undefined\"\n");
}
N_tof_edges = ntohs (my_rqst->u.cnfg.u.tof.n_edges); /* The # of
** different 'edge-arrays' which are
** to be defined.
*/
printf (" Number of Edge Arrays = %2d\n", N_tof_edges);
if (N_tof_edges > MAX_TOF_EDGE) {
printf ("do_SQHM__TOF_alloc: Illegal number of edge-arrays: %u.\n",
N_tof_edges);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Too many edge-arrays");
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
n_banks = ntohs (my_rqst->u.cnfg.u.tof.n_banks); /* The # of
** 'banks' of counters which are
** to be defined.
*/
printf (" Number of Counter Banks = %2d\n", n_banks);
if (n_banks == 0) {
rply_status_setup (reply, KER__BAD_VALUE, 0, "Illegal n_banks");
printf ("do_SQHM__TOF_alloc: Illegal number of banks: %u.\n",
n_banks);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
Tof_dts_soll = ntohl (my_rqst->u.cnfg.u.tof.preset_delay); /* The
** required "Delay-Time-to-Start" */
if ((Tof_dts_soll & (~LWL_TSI_DTS_MSK)) != 0) {
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad Delay-Time-to-Start");
printf ("do_SQHM__TOF_alloc: Delay-Time-to-Start illegal: 0x%x\n",
Tof_dts_soll);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
com2 = open ("/tyCo/1", O_RDWR, 0); /* Send DTS to MDI via COM2 port */
if (com2 == ERROR) {
rply_status_setup (reply, KER__BAD_VALUE, 0, "COM2 open failed");
printf ("do_SQHM__TOF_alloc: error opening COM2 port. "
"Delay-Time-to-Start not set.\n");
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}else {
ioctl (com2, FIOBAUDRATE, 9600);
write (com2, "\r", 1);
write (com2, "RMT 1\r", 6);
nchar = sprintf (buff, "DT %d\r", Tof_dts_soll);
if (write (com2, buff, nchar) != nchar) {
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Setting D-T-to-S failed");
printf ("do_SQHM__TOF_alloc: error setting Delay-Time-to-Start.\n");
if (n_extra_bytes != 0) free (my_rqst);
close (com2);
return ERROR;
}else {
printf (" Delay-Time-to-Start = %d\n", Tof_dts_soll);
}
close (com2);
}
/*
** Loop over all the edge arrays
*/
edge_arr_pntr = &my_rqst->u.cnfg.u.tof.edge_0;
for (i = 0; i < N_tof_edges; i++) {
n_bins = ntohl (edge_arr_pntr->n_bins);
flag = ntohl (edge_arr_pntr->flag);
edge_0 = ntohl (edge_arr_pntr->edges[0]);
edge_1 = ntohl (edge_arr_pntr->edges[1]);
printf (" Edge Array %d:\n", i);
printf (" Number of bins = %5d\n", n_bins);
printf (" Flag = %5d\n", flag);
printf (" Lower edge = %5d\n", edge_0);
if ((n_bins == 0) || (n_bins > MAX_TOF_NBINS)) {
printf ("do_SQHM__TOF_alloc: Illegal # bins: %u.\n",
n_bins);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad number of bins");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
if ((edge_0 & (~LWL_HDR_TS_MASK)) != 0) {
printf ("do_SQHM__TOF_alloc: histog start is > 20 bits: %u\n",
edge_0);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Bin edges overflow 20 bits");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
if ((edge_1 & (~LWL_HDR_TS_MASK)) != 0) {
printf ("do_SQHM__TOF_alloc: first bin is > 20 bits: %u\n",
edge_1);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"First bin overflows 20 bits");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
bytes_needed = OffsetOf (struct tof_edge_info, edges) +
((n_bins + 1) * sizeof (int));
Tof_edges[i] = calloc (bytes_needed, sizeof (char)); /* Allocate space for
** edge-array structure */
if (Tof_edges[i] == NULL) {
printf ("do_SQHM__TOF_alloc: unable to alloc memory for edge array.\n");
rply_status_setup (reply, KER__BAD_ALLOC, 0,
"Failed to get memory for edge-array");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
Tof_edges[i]->n_bins = n_bins;
Tof_edges[i]->flag = flag;
if ((flag & FLAG__VAR_BIN) == 0) { /* Fixed width bins? */
printf (" Bin width = %5d\n", (edge_1 - edge_0));
if (edge_0 >= edge_1) { /* Yes. Check bin width */
printf ("do_SQHM__TOF_alloc: bin width is zero or negative!\n");
rply_status_setup (reply, KER__BAD_VALUE, 0, "illegal bin width");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
bin_span = edge_1 - edge_0;
Tof_edges[i]->bin_span = bin_span;
top_edge = edge_0 + (n_bins * bin_span) - 1;
if ((top_edge & (~LWL_HDR_TS_MASK)) != 0) {
printf ("do_SQHM__TOF_alloc: histog last bin is > 20 bits: %u\n",
top_edge);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Last bin overflows 20 bits");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
for (j=0; j <= n_bins; j++) Tof_edges[i]->edges[j] = edge_0+j*bin_span;
Tof_edges[i]->hi_edge = top_edge;
sizeof_edge_arr = OffsetOf (struct tof_edge_arr, edges) +
2 * sizeof (uint);
}else {
/* Variable width bins */
bin_span = edge_1 - edge_0; /* Note: even though the edges are
** defined as variable, they may, in
** fact, all be the same width. Check
** for this so that we can make a brief
** report rather than listing all
** the bin edges.
*/
Tof_edges[i]->bin_span = 0;
Tof_edges[i]->edges[0] = edge_0;
for (j = 1; j <= n_bins; j++) {
Tof_edges[i]->edges[j] = ntohl (edge_arr_pntr->edges[j]);
if ((Tof_edges[i]->edges[j] & (~LWL_HDR_TS_MASK)) != 0) {
printf ("do_SQHM__TOF_alloc: histog bin is > 20 bits: %d %u\n",
j, Tof_edges[i]->edges[j]);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Bin edge overflows 20 bits");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
if (Tof_edges[i]->edges[j-1] >= Tof_edges[i]->edges[j]) {
printf ("do_SQHM__TOF_alloc: bin edges are not in sequence: %d %d\n",
i, j);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Bin edges not in sequence");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
if ((Tof_edges[i]->edges[j] - Tof_edges[i]->edges[j-1]) != bin_span)
bin_span = 0; /* Set bin_span to zero if bin widths really are
** variable */
}
if (bin_span != 0) {
printf (" Variable width bins but width of all bins = %d\n",
bin_span);
}else {
printf (" Variable width bins. Upper bin edges are:\n");
for (j = 1; j <= n_bins; j += 10) {
for (k = 0; ((k + j) <= n_bins) && (k < 10); k++)
printf ("%7d", Tof_edges[i]->edges[j+k]);
printf ("\n");
}
}
Tof_edges[i]->hi_edge = Tof_edges[i]->edges[n_bins] - 1;
sizeof_edge_arr = OffsetOf (struct tof_edge_arr, edges) +
((n_bins + 1) * sizeof (uint));
}
edge_arr_pntr = (struct tof_edge_arr *) ( /* Move to next edge array */
(char *) edge_arr_pntr + sizeof_edge_arr);
}
/*
** Loop over all the counter banks
*/
bank_pntr = (struct tof_bank *) edge_arr_pntr;
for (i = 0; i < n_banks; i++) {
first = ntohs (bank_pntr->first);
n_cntrs = ntohs (bank_pntr->n_cntrs);
edge_indx = ntohs (bank_pntr->edge_indx);
bytes_per_bin = ntohs (bank_pntr->bytes_per_bin);
printf (" Counter Bank %d:\n", i);
printf (" Number of counters = %5d\n", n_cntrs);
printf (" First counter = %5d\n", first);
if (N_tof_edges > 1) {
printf (" Edge array #%d\n", edge_indx);
}
printf (" Bytes per bin = %5d\n", bytes_per_bin);
if (first >= MAX_TOF_CNTR) {
printf ("do_SQHM__TOF_alloc: Illegal first counter number: %u.\n",
first);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Bad first counter number");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
if ((n_cntrs == 0) || ((first+n_cntrs) > MAX_TOF_CNTR)) {
printf ("do_SQHM__TOF_alloc: Illegal # counters: %u %u.\n",
first, n_cntrs);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad # counters");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
if (edge_indx >= N_tof_edges) {
printf ("do_SQHM__TOF_alloc: Illegal edge index: %u.\n",
edge_indx);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad edge-array index");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
edge_info_pntr = Tof_edges[edge_indx];
n_bins = edge_info_pntr->n_bins;
flag = edge_info_pntr->flag;
if (bytes_per_bin == 0) bytes_per_bin = 4;
if ((bytes_per_bin != 1) &&
(bytes_per_bin != 2) &&
(bytes_per_bin != 4)) {
printf ("do_SQHM__TOF_alloc: Illegal bytes per bin: %d.\n",
bytes_per_bin);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad bytes-per-bin");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
Total_bytes += (n_cntrs * n_bins * bytes_per_bin);
if (Hm_mode_UD != 0) Total_bytes += (n_cntrs * n_bins * bytes_per_bin);
for (j = first; j < (first + n_cntrs); j++) {
if (Tof_descr[j] != NULL) {
printf ("do_SQHM__TOF_alloc: Doubly defined counter: %d.\n",
(j));
rply_status_setup (reply, KER__BAD_VALUE, 0, "Doubly defined counter");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
Tof_descr[j] = calloc (1, sizeof (struct tof_histog));
if (Tof_descr[j] == NULL) {
printf ("do_SQHM__TOF_alloc: unable to alloc memory for "
"histogram structure.\n");
rply_status_setup (reply, KER__BAD_ALLOC, 0,
"Failed to get buffer for Tof_descr structure");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
Tof_descr[j]->cntr_nmbr = first + j;
Tof_descr[j]->lo_edge = edge_info_pntr->edges[0];
Tof_descr[j]->hi_edge = edge_info_pntr->hi_edge;
Tof_descr[j]->flag = flag;
Tof_descr[j]->bytes_per_bin = bytes_per_bin;
Tof_descr[j]->n_bins = n_bins;
Tof_descr[j]->cnt_early_up = 0;
Tof_descr[j]->cnt_late_up = 0;
Tof_descr[j]->cnt_early_down = 0;
Tof_descr[j]->cnt_late_down = 0;
Tof_descr[j]->bin_edge = edge_info_pntr->edges;
Tof_descr[j]->u.b_bin_data = NULL;
}
if (i == 0) { /* Use the first counter bank to define some .. */
N_hists = n_cntrs; /* .. globals since we expect there usually to .. */
/* .. be only 1 counter bank. */
N_bins = n_bins;
Lo_cntr = first;
Lo_bin = edge_info_pntr->edges[0];
Hi_bin = edge_info_pntr->hi_edge;
Compress = ((flag & FLAG__VAR_BIN) == 0) ?
edge_info_pntr->edges[1] - edge_info_pntr->edges[0] :
0;
Bytes_per_bin = bytes_per_bin;
Cnts_lo = Cnts_hi = 0;
}
bank_pntr++; /* Move to next counter bank */
}
if (n_extra_bytes != 0) free (my_rqst);
i = memFindMax (); /* Get size of biggest free memory block */
if (i > Total_bytes) {
Hist_base_addr = calloc (Total_bytes, sizeof (char));
}else {
Hist_base_addr = NULL;
}
if (Hist_base_addr == NULL) {
printf ("\007do_SQHM__TOF_alloc:\n"
" Unable to reserve %d bytes of memory!\n"
" Largest block available = %d.\n", Total_bytes, i);
rply_status_setup (reply, KER__BAD_ALLOC, i,
"Failed to get buffer for histograms");
reply->sub_status = htonl (i);
return ERROR;
}
nxt_hist_addr = Hist_base_addr;
for (i = 0; i < MAX_TOF_CNTR; i++) {
if (Tof_descr[i] != NULL) {
Tof_descr[i]->u.b_bin_data = nxt_hist_addr;
j = Tof_descr[i]->n_bins * Tof_descr[i]->bytes_per_bin;
if (Hm_mode_UD != 0) j = j * 2;
nxt_hist_addr += j;
}
}
Cnts_lo = Cnts_hi = 0;
N_events = N_skipped = N_no_coin_tsi = N_coin_tsi = 0;
Print_hdr = True;
printf (" Histogram base address = 0x%08x\n", Hist_base_addr);
printf (" SQHM__TOF mode configured.\n");
return OK;
}
/*
**--------------------------------------------------------------------------*/
int do_SQHM__PSD_alloc (
/* ==================
*/ int skt,
struct req_buff_struct *request,
struct rply_buff_struct *reply) {
/*
** Routine to allocate memory for the SQHM__PSD
** configure request.
**
** Definitions:
** Edge-Array
** An 'edge-array' is a structure which specifies the lower edge
** of each bin in the histogram. This is to allow variable width
** histogram bins.
** Counter Bank
** A 'counter bank' is a contiguous group of counters, all of
** which share the same parameters. In particular, all the counters
** in the bank have the same number of bins and same bin edges.
*/
int i, j, k, n_bytes_got;
uint n_extra_bytes, n_banks, com2, nchar;
uint first, n_cntrs, edge_indx, bytes_per_bin;
uint n_bins, flag, edge_0, edge_1, bin_span, top_edge;
uint bytes_needed, sizeof_edge_arr;
uint time_span, n_total_bins;
struct tof_edge_info *edge_info_pntr;
struct tof_edge_arr *edge_arr_pntr;
struct tof_bank *bank_pntr;
void *nxt_hist_addr;
struct req_buff_struct *my_rqst;
char *p_addr, buff[64];
Total_bytes = 0;
/*
switch debugging on by default
Dbg_lev1 = 0;
*/
/*
read additional configuration information
*/
n_extra_bytes = ntohl (request->u.cnfg.u.psd.n_extra_bytes); /* The # of
** extra bytes needed to be read from
** the client to complete the configure
** request.
*/
if (n_extra_bytes == 0) {
my_rqst = request;
}else {
/*
** There is extra data to be read. Get buffer space for the
** extra stuff plus space to copy over what has already been
** read so that everything is in a contiguous buffer.
*/
bytes_needed = n_extra_bytes + sizeof (*request);
bytes_needed = (bytes_needed + 3) & (~3); /* Round up to multiple of 4 */
p_addr = calloc (bytes_needed, sizeof (char));
if (p_addr == NULL) {
printf ("\007do_SQHM__PSD_alloc:\n"
" cannot allocate memory for extra config data!\n");
net_flush (skt, n_extra_bytes);
rply_status_setup (reply, KER__BAD_ALLOC, 0,
"Failed to get buffer for extra config data");
return ERROR;
}
memcpy (p_addr, request, sizeof (*request)); /* Copy in what has already
** been read.
*/
my_rqst = (struct req_buff_struct *) p_addr;
bytes_needed = n_extra_bytes; /* And read the rest */
p_addr = p_addr + sizeof (*request);
while (bytes_needed > 0) {
n_bytes_got = recv (skt, p_addr, bytes_needed, 0);
if (n_bytes_got <= 0) break;
Rw_bytes_got += n_bytes_got;
bytes_needed -= n_bytes_got;
p_addr += n_bytes_got;
}
if (n_bytes_got < 0) {
printf ("\007"
"%s -- R/W-Socket recv error\n", Tsk_name[0]);
printf ("%s -- Connection will be closed.\n", Tsk_name[0]);
rply_status_setup (reply, KER__BAD_VALUE, 0, "recv failed");
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
}
printf ("\n Histogramming mode is \"SQHM__PSD\"\n");
/*
decode general configuration information
*/
if (Hm_mode_UD != 0)
printf (" Up/Down mode selected\n");
if (Hm_mode_STROBO != 0)
printf (" Stroboscopic mode selected\n");
printf (" Bin-overflow action is ");
switch (Hm_mode_BO) {
case SQHM__BO_IGN: printf ("\"Ignore\"\n"); break;
case SQHM__BO_SMAX: printf ("\"Stop-at-Max\"\n"); break;
case SQHM__BO_CNT: printf ("\"Count\"\n"); break;
default: printf ("\"Undefined\"\n");
}
N_tof_edges = ntohs (my_rqst->u.cnfg.u.psd.n_edges); /* The # of
** different 'edge-arrays' which are
** to be defined.
*/
printf (" Number of Edge Arrays = %2d\n", N_tof_edges);
if (N_tof_edges > MAX_TOF_EDGE) {
printf ("do_SQHM__PSD_alloc: Illegal number of edge-arrays: %u.\n",
N_tof_edges);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Too many edge-arrays");
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
n_banks = ntohs (my_rqst->u.cnfg.u.psd.n_banks); /* The # of
** 'banks' of counters which are
** to be defined.
*/
printf (" Number of Counter Banks = %2d\n", n_banks);
if (n_banks == 0) {
rply_status_setup (reply, KER__BAD_VALUE, 0, "Illegal n_banks");
printf ("do_SQHM__PSD_alloc: Illegal number of banks: %u.\n",
n_banks);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
psdXOffset = ntohs(my_rqst->u.cnfg.u.psd.xOffset);
psdXFactor = ntohs(my_rqst->u.cnfg.u.psd.xFactor);
printf("\tX-Offset = %4d, X-Factor = %4d\n",
psdXOffset, psdXFactor);
psdYOffset = ntohs(my_rqst->u.cnfg.u.psd.yOffset);
psdYFactor = ntohs(my_rqst->u.cnfg.u.psd.yFactor);
printf("\tY-Offset = %4d, Y-Factor = %4d\n",
psdYOffset, psdYFactor);
psdFlashCount = 0;
psdHitCount = 0;
psdXSize = ntohs(my_rqst->u.cnfg.u.psd.xSize);
psdYSize = ntohs(my_rqst->u.cnfg.u.psd.ySize);
printf("\txSize = %4d, ySize = %4d\n",
psdXSize, psdYSize);
N_hists = psdXSize*psdYSize+MAX_PSD_ED;
Tof_dts_soll = ntohl (my_rqst->u.cnfg.u.psd.preset_delay); /* The
** required "Delay-Time-to-Start" */
if ((Tof_dts_soll & (~LWL_TSI_DTS_MSK)) != 0) {
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad Delay-Time-to-Start");
printf ("do_SQHM__PSD_alloc: Delay-Time-to-Start illegal: 0x%x\n",
Tof_dts_soll);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
/*
send DTS to MDI through COM2 port. But only if we have more then one
time channel. Else we are operating in non-TOF mode.
*/
if(N_tof_edges > 1) {
com2 = open ("/tyCo/1", O_RDWR, 0);
if (com2 == ERROR) {
rply_status_setup (reply, KER__BAD_VALUE, 0, "COM2 open failed");
printf ("do_SQHM__PSD_alloc: error opening COM2 port. "
"Delay-Time-to-Start not set.\n");
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}else {
ioctl (com2, FIOBAUDRATE, 9600);
write (com2, "\r", 1);
write (com2, "RMT 1\r", 6);
nchar = sprintf (buff, "DT %d\r", Tof_dts_soll);
if (write (com2, buff, nchar) != nchar) {
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Setting D-T-to-S failed");
printf ("do_SQHM__PSD_alloc: error setting Delay-Time-to-Start.\n");
if (n_extra_bytes != 0) free (my_rqst);
close (com2);
return ERROR;
}else {
printf (" Delay-Time-to-Start = %d\n", Tof_dts_soll);
}
close (com2);
}
}
/*
** Loop over all the edge arrays
*/
edge_arr_pntr = &my_rqst->u.cnfg.u.psd.edge_0;
for (i = 0; i < N_tof_edges; i++) {
n_bins = ntohl (edge_arr_pntr->n_bins);
N_bins = n_bins;
flag = ntohl (edge_arr_pntr->flag);
edge_0 = ntohl (edge_arr_pntr->edges[0]);
edge_1 = ntohl (edge_arr_pntr->edges[1]);
printf (" Edge Array %d:\n", i);
printf (" Number of bins = %5d\n", n_bins);
printf (" Flag = %5d\n", flag);
printf (" Lower edge = %5d\n", edge_0);
if ((n_bins == 0) || (n_bins > MAX_TOF_NBINS)) {
printf ("do_SQHM__PSD_alloc: Illegal # bins: %u.\n",
n_bins);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad number of bins");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
if ((edge_0 & (~LWL_HDR_TS_MASK)) != 0) {
printf ("do_SQHM__PSD_alloc: histog start is > 20 bits: %u\n",
edge_0);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Bin edges overflow 20 bits");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
if ((edge_1 & (~LWL_HDR_TS_MASK)) != 0) {
printf ("do_SQHM__PSD_alloc: first bin is > 20 bits: %u\n",
edge_1);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"First bin overflows 20 bits");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
bytes_needed = OffsetOf (struct tof_edge_info, edges) +
((n_bins + 1) * sizeof (int));
Tof_edges[i] = calloc (bytes_needed, sizeof (char)); /* Allocate space for
** edge-array structure */
if (Tof_edges[i] == NULL) {
printf ("do_SQHM__PSD_alloc: unable to alloc memory for edge array.\n");
rply_status_setup (reply, KER__BAD_ALLOC, 0,
"Failed to get memory for edge-array");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
Tof_edges[i]->n_bins = n_bins;
Tof_edges[i]->flag = flag;
if ((flag & FLAG__VAR_BIN) == 0) { /* Fixed width bins? */
printf (" Bin width = %5d\n", (edge_1 - edge_0));
if (edge_0 >= edge_1) { /* Yes. Check bin width */
printf ("do_SQHM__PSD_alloc: bin width is zero or negative!\n");
rply_status_setup (reply, KER__BAD_VALUE, 0, "illegal bin width");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
bin_span = edge_1 - edge_0;
Tof_edges[i]->bin_span = bin_span;
top_edge = edge_0 + (n_bins * bin_span) - 1;
if ((top_edge & (~LWL_HDR_TS_MASK)) != 0) {
printf ("do_SQHM__PSD_alloc: histog last bin is > 20 bits: %u\n",
top_edge);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Last bin overflows 20 bits");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
for (j=0; j <= n_bins; j++) Tof_edges[i]->edges[j] = edge_0+j*bin_span;
Tof_edges[i]->hi_edge = top_edge;
sizeof_edge_arr = OffsetOf (struct tof_edge_arr, edges) +
2 * sizeof (uint);
}else {
/* Variable width bins */
bin_span = edge_1 - edge_0; /* Note: even though the edges are
** defined as variable, they may, in
** fact, all be the same width. Check
** for this so that we can make a brief
** report rather than listing all
** the bin edges.
*/
Tof_edges[i]->bin_span = 0;
Tof_edges[i]->edges[0] = edge_0;
for (j = 1; j <= n_bins; j++) {
Tof_edges[i]->edges[j] = ntohl (edge_arr_pntr->edges[j]);
if ((Tof_edges[i]->edges[j] & (~LWL_HDR_TS_MASK)) != 0) {
printf ("do_SQHM__PSD_alloc: histog bin is > 20 bits: %d %u\n",
j, Tof_edges[i]->edges[j]);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Bin edge overflows 20 bits");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
if (Tof_edges[i]->edges[j-1] >= Tof_edges[i]->edges[j]) {
printf ("do_SQHM__PSD_alloc: bin edges are not in sequence: %d %d\n",
i, j);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Bin edges not in sequence");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
if ((Tof_edges[i]->edges[j] - Tof_edges[i]->edges[j-1]) != bin_span)
bin_span = 0; /* Set bin_span to zero if bin widths really are
** variable */
}
if (bin_span != 0) {
printf (" Variable width bins but width of all bins = %d\n",
bin_span);
}else {
printf (" Variable width bins. Upper bin edges are:\n");
for (j = 1; j <= n_bins; j += 10) {
for (k = 0; ((k + j) <= n_bins) && (k < 10); k++)
printf ("%7d", Tof_edges[i]->edges[j+k]);
printf ("\n");
}
}
Tof_edges[i]->hi_edge = Tof_edges[i]->edges[n_bins] - 1;
sizeof_edge_arr = OffsetOf (struct tof_edge_arr, edges) +
((n_bins + 1) * sizeof (uint));
}
edge_arr_pntr = (struct tof_edge_arr *) ( /* Move to next edge array */
(char *) edge_arr_pntr + sizeof_edge_arr);
}
/*
** Loop over all the counter banks
*/
bank_pntr = (struct tof_bank *) edge_arr_pntr;
for (i = 0; i < n_banks; i++) {
first = ntohs (bank_pntr->first);
n_cntrs = psdXSize*psdYSize;
edge_indx = ntohs (bank_pntr->edge_indx);
bytes_per_bin = ntohs (bank_pntr->bytes_per_bin);
Bytes_per_bin = bytes_per_bin; /* update global var */
printf (" Counter Bank %d:\n", i);
printf (" Number of counters = %5d\n", n_cntrs);
printf (" First counter = %5d\n", first);
if (N_tof_edges > 1) {
printf (" Edge array #%d\n", edge_indx);
}
printf (" Bytes per bin = %5d\n", bytes_per_bin);
if (first >= MAX_PSD_CNTR) {
printf ("do_SQHM__PSD_alloc: Illegal first counter number: %u.\n",
first);
rply_status_setup (reply, KER__BAD_VALUE, 0,
"Bad first counter number");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
if ((n_cntrs == 0) || ((first+n_cntrs) > MAX_PSD_CNTR)) {
printf ("do_SQHM__PSD_alloc: Illegal # counters: %u %u.\n",
first, n_cntrs);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad # counters");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
if (edge_indx >= N_tof_edges) {
printf ("do_SQHM__PSD_alloc: Illegal edge index: %u.\n",
edge_indx);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad edge-array index");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
edge_info_pntr = Tof_edges[edge_indx];
n_bins = edge_info_pntr->n_bins;
flag = edge_info_pntr->flag;
if (bytes_per_bin == 0) bytes_per_bin = 4;
if ((bytes_per_bin != 1) &&
(bytes_per_bin != 2) &&
(bytes_per_bin != 4)) {
printf ("do_SQHM__PSD_alloc: Illegal bytes per bin: %d.\n",
bytes_per_bin);
rply_status_setup (reply, KER__BAD_VALUE, 0, "Bad bytes-per-bin");
free_HM_memory (NULL);
if (n_extra_bytes != 0) free (my_rqst);
return ERROR;
}
/*
here there is a tricky bit: AMOR has two additional single
detectors which need to be binned. They are appended after the
normal PSD-histogram
*/
Total_bytes += ((n_cntrs + MAX_PSD_ED) * n_bins * bytes_per_bin);
if (Hm_mode_UD != 0)
Total_bytes += ((n_cntrs + MAX_PSD_ED) * n_bins * bytes_per_bin);
if (i == 0) { /* Use the first counter bank to define some .. */
N_hists = n_cntrs+MAX_PSD_ED;
/* .. globals since we expect there usually to .. */
/* .. be only 1 counter bank. */
N_bins = n_bins;
Lo_cntr = first;
Lo_bin = edge_info_pntr->edges[0];
Hi_bin = edge_info_pntr->hi_edge;
Compress = ((flag & FLAG__VAR_BIN) == 0) ?
edge_info_pntr->edges[1] - edge_info_pntr->edges[0] :
0;
Bytes_per_bin = bytes_per_bin;
Cnts_lo = Cnts_hi = 0;
}
bank_pntr++; /* Move to next counter bank */
}
if (n_extra_bytes != 0) free (my_rqst);
#ifdef MEN_A012
Hist_base_addr = NULL;
printf("Calling memPartAlloc with %d, %d\n",
(int)sysHighMemPart, Total_bytes);
Hist_base_addr = memPartAlloc(sysHighMemPart,Total_bytes);
Hist_base_MEN_alloc = 1;
#else
i = memFindMax (); /* Get size of biggest free memory block */
if (i > Total_bytes) {
Hist_base_addr = calloc (Total_bytes, sizeof (char));
}else {
Hist_base_addr = NULL;
}
#endif
printf("Successfully allocated %d bytes\n", Total_bytes);
if (Hist_base_addr == NULL) {
printf ("\007do_SQHM__PSD_alloc:\n"
" Unable to reserve %d bytes of memory!\n"
" Largest block available = %d.\n", Total_bytes, i);
rply_status_setup (reply, KER__BAD_ALLOC, i,
"Failed to get buffer for histograms");
reply->sub_status = htonl (i);
return ERROR;
}
Cnts_lo = Cnts_hi = 0;
N_events = N_skipped = N_no_coin_tsi = N_coin_tsi = 0;
Print_hdr = True;
printf (" Histogram base address = 0x%08x\n", Hist_base_addr);
printf (" SQHM__PSD mode configured.\n");
return OK;
}
/*
**--------------------------------------------------------------------------*/
int do_command (
/* ==========
*/ int index,
int skt,
int pkt_size,
struct req_buff_struct *rqst,
struct rply_buff_struct *reply) {
/*
** Action routine for an SQHM_??? command.
** The command is processed (including returning a
** status response message).
*/
int status, indx, is, suspendMode, i, j, sub_cmnd;
int txt_len, txt_offset, bytes_to_go;
int my_first_bin, my_nbins, my_bytes_per_bin, my_hist_no;
int my_sub_code, my_x_lo, my_nx, my_y_lo, my_ny, my_xdim, my_h_slct;
time_t secs;
char *msge, *p_buff, *p_txt;
reply->bigend = htonl (0x12345678); /* Put in the "endian" flag. */
rply_status_setup (reply, KER__SUCCESS, 0, "All OK");
switch (ntohl (rqst->cmnd)) {
case SQHM_CLOSE: /* Close the connection. */
return ERROR; /* Do nothing. */
case SQHM_CNCT: /* Make a new connection. */
printf ("%s -- connecting ..", Tsk_name[index]);
time (&secs);
secs = secs - Sqhm_start_time;
reply->u.cnct.up_time = htonl (secs);
if (Cfgn_done == 0) { /* Check we've been configured */
printf ("\007 but not yet configured!\n");
is = rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
"Not configured");
}else if (index != 0) {
printf ("\007 but not issued to SinqHM-master!\n");
is = rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
"Not SinqHM-master");
}else {
pkt_size = ntohl (rqst->u.cnct.max_pkt);
if ((pkt_size < 1024) || (pkt_size > 8192)) pkt_size = 8192;
pkt_size = pkt_size & ~3; /* Ensure pkt_size is multiple of 4 */
indx = make_child (SinqHM_server,
ntohl (rqst->u.cnct.strt_mode),
pkt_size);
if (indx <= 0) { /* Child created and ready? */
printf ("\n\007%s -- creation of child failed: %d.\n",
Tsk_name[0], indx);
switch (indx) {
case -1: msge = "Spawn failed"; break;
case -2: msge = "No more ports"; break;
case -3: msge = "Time-out of child start-up"; break;
case -4: msge = "Child could not get started"; break;
default: msge = "Bad status from make_child";
}
is = rply_status_setup_and_send (skt, reply, KER__BAD_CREATE,
indx, msge);
}else { /* Yes, child is up and ready. */
reply->u.cnct.port = htonl (Port_base + indx);
reply->u.cnct.pkt_size = htonl (pkt_size);
reply->u.cnct.hm_mode = htonl (Hm_mode_ALL);
reply->u.cnct.n_hists = htonl (N_hists);
reply->u.cnct.num_bins = htonl (N_bins);
reply->u.cnct.bytes_per_bin = htonl (Bytes_per_bin);
reply->u.cnct.curr_hist = htonl (Curr_hist);
reply->u.cnct.max_block = htonl (memFindMax ()); /* Max free mem */
reply->u.cnct.total_bytes = htonl (Total_bytes);
reply->u.cnct.lo_cntr = htonl (Lo_cntr);
reply->u.cnct.lo_bin = htonl (Lo_bin);
reply->u.cnct.compress = htonl (Compress);
printf (" %s started. Packet size = %d.\n", Tsk_name[indx], pkt_size);
is = rply_status_send (skt, reply);
}
}
if (is != OK)
printf ("\n%s -- send of status reply failed.\n", Tsk_name[index]);
return is;
case SQHM_CONFIG:
printf ("%s: Configure ..", Tsk_name[index]);
if (Cfgn_done) {
is = rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
"Already configured");
printf ("\007 already configured!\n");
return ERROR;
}
free_HM_memory (NULL); /* There should be no memory allocated but
** go and release it anyway!
*/
is = chk_config_alloc (skt, rqst, reply); /* No, check config msg .. */
if (is != OK) { /* .. and alloc mem */
rply_status_send (skt, reply);
return ERROR;
}
suspendMode = (Hm_mode_DEBUG != 0) ? 1 : 0; /* The mode for Filler */
is = make_filler (suspendMode); /* If OK so far, start FILLER. */
if (is <= 0) { /* Was FILLER created OK? */
rply_status_setup_and_send (skt, reply, KER__BAD_CREATE, is, /* No */
"Filler creation failed");
printf ("\n%s -- creation of FILLER failed: %d.\n",
Tsk_name[index], is);
free_HM_memory (NULL);
Cfgn_done = 0;
return ERROR;
}else { /* Yes, child is up and ready. */
printf (" .. configuration complete, %s has been started.\n",
Filler_name);
is = rply_status_send (skt, reply);
if (is != OK)
printf ("\n%s -- send of status reply failed.\n", Tsk_name[index]);
return is;
}
case SQHM_DAQ: /* Start or stop data acquisition. */
printf ("%s: DAQ", Tsk_name[index]);
if (!Cfgn_done) { /* Configured yet? */
rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0, /* No */
"Not configured");
printf ("\007: not configured!\n");
return ERROR;
}
sub_cmnd = ntohl (rqst->u.daq.sub_cmnd);
if (sub_cmnd == DAQ__CLR) printf ("/DAQ__CLR:");
if (sub_cmnd == DAQ__GO) printf ("/DAQ__GO:");
if (sub_cmnd == DAQ__INH) printf ("/DAQ__INH:");
if (sub_cmnd == DAQ__STOP) printf ("/DAQ__STOP:");
if (sub_cmnd == DAQ__TST) printf ("/DAQ__TST:");
do_daq (reply, index, sub_cmnd);
if (SinqHM_Dsbl_Mask == 0) {
printf (" data acquisition is active.\n");
}else {
printf (" data acquisition is inhibited.\n");
}
is = rply_status_send (skt, reply);
if (is != OK)
printf ("\n%s -- send of status reply failed.\n", Tsk_name[index]);
return is;
case SQHM_DBG: /* Set debug parameters. */
Dbg_mask = ntohl (rqst->u.dbg.mask);
Dbg_lev0 = ((Dbg_mask & 1) != 0) ? 1 : 0;
Dbg_lev1 = ((Dbg_mask & 2) != 0) ? 1 : 0;
Dbg_lev2 = ((Dbg_mask & 4) != 0) ? 1 : 0;
Dbg_lev3 = ((Dbg_mask & 8) != 0) ? 1 : 0;
printf ("%s: Debug mask = 0x%x\n", Tsk_name[index], Dbg_mask);
is = rply_status_setup_and_send (skt, reply, KER__SUCCESS, 0, NULL);
if (is != OK)
printf ("\n%s -- send of status reply failed.\n", Tsk_name[index]);
return is;
case SQHM_DECONFIG: /* Close down FILLER (and any servers)? */
printf ("%s: De-configure", Tsk_name[index]);
if (!Cfgn_done) { /* Anything to do? */
printf (" -- already de-configured!\n");
is = rply_status_setup_and_send (skt, reply, KER__SUCCESS, 0, NULL);
}else if (index != 0) {
printf ("\007 -- not issued to SinqHM-master!\n");
is = rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
"Not SinqHM-master");
}else {
is = close_down_offspring (rqst, reply);
if (is == KER__SUCCESS) {
printf (" done.\n");
Cfgn_done = 0;
is = rply_status_setup_and_send (skt, reply, KER__SUCCESS, 0, NULL);
}else {
printf ("\n\007Failed! Problem terminating children.\n");
is = rply_status_setup_and_send (skt, reply, KER__BAD_STATE, is,
"Problem terminating children");
}
free_HM_memory (NULL); /* Release all reserved memory */
}
if (is != OK)
printf ("\n%s -- send of status reply failed.\n", Tsk_name[index]);
return is;
case SQHM_EXIT: /* Rundown */
printf ("%s: Run-down", Tsk_name[index]);
if (index != 0) {
printf ("\007 -- not issued to SinqHM-master!\n");
is = rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
"Not SinqHM-master");
}else {
rqst->u.decnfg.sub_code = htonl (1); /* Set "harshness" = 1 */
is = close_down_offspring (rqst, reply);
if (is == KER__SUCCESS) {
printf (" done.\n");
Cfgn_done = 0;
is = rply_status_setup_and_send (skt, reply, KER__SUCCESS, 0, NULL);
}else {
printf ("\007 -- warning -- problem terminating children.\n");
is = rply_status_setup_and_send (skt, reply, KER__BAD_STATE, is,
"Problem terminating children");
}
free_HM_memory (NULL); /* Release all reserved memory */
}
if (is != OK)
printf ("\n%s -- send of status reply failed.\n", Tsk_name[index]);
return OK;
case SQHM_IDENT: /* Give info on software identification. */
txt_len = IDENT_MSGE_LEN;
txt_offset = 0;
p_buff = calloc (txt_len, 1); /* Get a buffer for text info */
if (p_buff == NULL) {
printf ("\n\007%s -- SQHM_IDENT: failed to get buffer!\n",
Tsk_name[index]);
rply_status_setup_and_send (skt, reply, KER__BAD_ALLOC, 0,
"Failed to get buffer for composing Ident");
return ERROR;
}
time (&secs);
secs = secs - Sqhm_start_time;
reply->u.ident.up_time = htonl (secs);
reply->u.ident.n_extra_bytes = htonl (IDENT_MSGE_LEN);
p_txt = p_buff;
reply->u.ident.offset_vxWorks_ident = htons (txt_offset);
StrJoin (p_txt, txt_len, vxWorksVersion, "");
i = strlen (p_txt) + 1;
txt_offset += i; p_txt += i; txt_len -= i;
reply->u.ident.offset_vxWorks_date = htons (txt_offset);
StrJoin (p_txt, txt_len, creationDate, "");
i = strlen (p_txt) + 1;
txt_offset += i; p_txt += i; txt_len -= i;
reply->u.ident.offset_instr = htons (txt_offset);
StrJoin (p_txt, txt_len, Instr_name, "");
i = strlen (p_txt) + 1;
txt_offset += i; p_txt += i; txt_len -= i;
reply->u.ident.offset_def_ident = htons (txt_offset);
StrJoin (p_txt, txt_len, Def_ident, "");
i = strlen (p_txt) + 1;
txt_offset += i; p_txt += i; txt_len -= i;
reply->u.ident.offset_sinqhm_main_ident = htons (txt_offset);
StrJoin (p_txt, txt_len, Sqhm_main_ident, "");
i = strlen (p_txt) + 1;
txt_offset += i; p_txt += i; txt_len -= i;
reply->u.ident.offset_sinqhm_main_date = htons (txt_offset);
StrJoin (p_txt, txt_len, Sqhm_main_date, "");
i = strlen (p_txt) + 1;
txt_offset += i; p_txt += i; txt_len -= i;
reply->u.ident.offset_sinqhm_server_ident = htons (txt_offset);
StrJoin (p_txt, txt_len, Sqhm_serv_ident, "");
i = strlen (p_txt) + 1;
txt_offset += i; p_txt += i; txt_len -= i;
reply->u.ident.offset_sinqhm_server_date = htons (txt_offset);
StrJoin (p_txt, txt_len, Sqhm_serv_date, "");
i = strlen (p_txt) + 1;
txt_offset += i; p_txt += i; txt_len -= i;
reply->u.ident.offset_sinqhm_filler_ident = htons (txt_offset);
StrJoin (p_txt, txt_len, Sqhm_fill_ident, "");
i = strlen (p_txt) + 1;
txt_offset += i; p_txt += i; txt_len -= i;
reply->u.ident.offset_sinqhm_filler_date = htons (txt_offset);
StrJoin (p_txt, txt_len, Sqhm_fill_date, "");
i = strlen (p_txt) + 1;
txt_offset += i; p_txt += i; txt_len -= i;
reply->u.ident.offset_sinqhm_routines_ident = htons (txt_offset);
StrJoin (p_txt, txt_len, Sqhm_rout_ident, "");
i = strlen (p_txt) + 1;
txt_offset += i; p_txt += i; txt_len -= i;
reply->u.ident.offset_sinqhm_routines_date = htons (txt_offset);
StrJoin (p_txt, txt_len, Sqhm_rout_date, "");
i = strlen (p_txt) + 1;
txt_offset += i; p_txt += i; txt_len -= i;
is = rply_status_send (skt, reply);
/*
** Now send the data
*/
p_txt = p_buff;
bytes_to_go = IDENT_MSGE_LEN;
while (bytes_to_go > 0) {
i = (bytes_to_go > pkt_size) ? pkt_size : bytes_to_go;
is = send (skt, p_txt, i, 0);
if (is > 0) {
Rw_bytes_put += is;
bytes_to_go -= is;
p_txt += is;
}else {
free (p_buff);
printf ("\n\007%s -- SQHM_IDENT: failed to send extra data!\n",
Tsk_name[index]);
return ERROR; /* Fatal error on send */
}
}
free (p_buff);
return OK;
case SQHM_PROJECT: /* Read a projected "rectangle" of the HM. */
if (Cfgn_done == 0) { /* Check we've been configured */
printf ("\007%s -- projecting but not yet configured!\n", Tsk_name[index]);
is = rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
"Not configured");
return ERROR;
}else {
if (Dbg_lev0) printf ("%s -- projecting ..", Tsk_name[index]);
my_sub_code = ntohl (rqst->u.project.sub_code);
my_x_lo = ntohl (rqst->u.project.x_lo);
my_nx = ntohl (rqst->u.project.nx);
my_y_lo = ntohl (rqst->u.project.y_lo);
my_ny = ntohl (rqst->u.project.ny);
my_xdim = ntohl (rqst->u.project.xdim);
my_h_slct = ntohl (rqst->u.project.nhist);
is = do_project (index, reply, skt, pkt_size,
my_sub_code, my_x_lo, my_nx, my_y_lo, my_ny, my_xdim, my_h_slct);
if (is != OK) {
printf ("\n%s -- SQHM_PROJECT fatal error sending status reply or "
"histo data.\n", Tsk_name[index]);
}else {
if (Dbg_lev0) printf (" done.\n");
}
return is;
}
case SQHM_READ: /* Read a section of the HM. */
if (Cfgn_done == 0) { /* Check we've been configured */
printf ("\007%s -- reading but not yet configured!\n", Tsk_name[index]);
is = rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
"Not configured");
return ERROR;
}else {
if (Dbg_lev0) printf ("%s -- reading ..", Tsk_name[index]);
my_hist_no = ntohl (rqst->u.read.hist_no);
my_first_bin = ntohl (rqst->u.read.first_bin);
my_nbins = ntohl (rqst->u.read.n_bins);
is = do_read (index, reply, skt, pkt_size,
my_nbins, my_first_bin, my_hist_no);
if (is != OK) {
printf ("\n%s -- SQHM_READ fatal error sending status reply or "
"histo data.\n", Tsk_name[index]);
}else {
if (Dbg_lev0) printf (" done.\n");
}
return is;
}
case SQHM_SELECT: /* SQHM_SELECT still needs to be programmed. */
printf ("%s: Select ..\n", Tsk_name[index]);
is = rply_status_setup_and_send (skt,
reply, KER__BAD_VALUE, 0, "Not yet available!");
if (is != OK) {
printf ("\n%s -- send of status reply failed.\n", Tsk_name[index]);
}else {
printf (" has been ignored but acknowledged.\n");
}
return is;
case SQHM_STATUS: /* Get-Status request */
if (Dbg_lev0) printf ("%s: Status ..", Tsk_name[index]);
/*
** Build up info
*/
reply->status = htonl (KER__SUCCESS); /* Indicate success */
strcpy ((char *) &reply->sub_status, /* Set up the Ident */
SINQHM_DEF_ID); /* This does not need htonl! */
reply->u.status.max_n_hists = htonl (N_HISTS_MAX);
reply->u.status.max_num_bins = htonl (N_BINS_MAX + 1);
reply->u.status.max_srvrs = MAX_CLIENTS;
reply->u.status.max_block = htonl (memFindMax ()); /* Max free mem */
if (Cfgn_done == 0) {
reply->u.status.cfg_state = 0;
reply->u.status.n_hists = 0;
reply->u.status.curr_hist = 0;
reply->u.status.num_bins = 0;
reply->u.status.act_srvrs = 0;
reply->u.status.bytes_per_bin = 0;
reply->u.status.compress = 0;
reply->u.status.daq_now = 0;
reply->u.status.filler_mask = 0;
reply->u.status.tsi_status = 0;
reply->u.status.flags = 0;
reply->u.status.dt_or_dts.both = 0;
reply->u.status.num_bad_events = 0;
}else {
reply->u.status.cfg_state = htonl (Hm_mode_ALL);
reply->u.status.n_hists = htons (N_hists);
reply->u.status.curr_hist = htons (Curr_hist);
reply->u.status.num_bins = htonl (N_bins);
for (j = 0, i = MAX_CLIENTS; i > 0; i--) if (Child_pid[i] != 0) j++;
reply->u.status.act_srvrs = j;
reply->u.status.bytes_per_bin = Bytes_per_bin;
reply->u.status.compress = Compress;
reply->u.status.daq_now = htons (SinqHM_Dsbl_Mask);
reply->u.status.filler_mask = htons (Server_masks[0]);
reply->u.status.tsi_status = htons (Tsi_status_info);
reply->u.status.flags = htons (Tsi_flags);
reply->u.status.dt_or_dts.both = htonl (Dt_or_dts.both);
reply->u.status.num_bad_events = htonl (Num_bad_events);
}
time (&secs);
secs = secs - Sqhm_start_time;
reply->u.status.up_time = htonl (secs);
is = rply_status_send (skt, reply);
if (Dbg_lev0) {
if (is != OK) {
printf ("\n%s -- send of status reply failed.\n", Tsk_name[index]);
}else {
printf (" has been sent.\n");
}
}
return is;
case SQHM_WRITE: /* Write a section of the HM.
**
** NOTE: always call do_write, even if not configured
** ==== since network data has always to be read.
*/
printf ("%s: writing ..", Tsk_name[index]);
my_hist_no = ntohl (rqst->u.write.hist_no);
my_first_bin = ntohl (rqst->u.write.first_bin);
my_nbins = ntohl (rqst->u.write.n_bins);
my_bytes_per_bin = ntohl (rqst->u.write.bytes_per_bin);
is = do_write (index, rqst, reply, skt, pkt_size,
my_nbins, my_first_bin, my_bytes_per_bin, my_hist_no);
if (is != OK) {
printf ("\n%s -- send of status reply failed.\n", Tsk_name[index]);
}else {
printf (" done.\n");
}
return is;
case SQHM_ZERO:
if (Cfgn_done == 0) { /* Check we've been configured */
printf ("\007%s -- zeroing but not yet configured!\n", Tsk_name[index]);
is = rply_status_setup_and_send (skt, reply, KER__BAD_STATE, 0,
"Not configured");
return ERROR;
}else {
printf ("%s -- zeroing ..", Tsk_name[index]);
my_hist_no = ntohl (rqst->u.zero.hist_no);
my_first_bin = ntohl (rqst->u.zero.first_bin);
my_nbins = ntohl (rqst->u.zero.n_bins);
do_zero (reply, index, my_nbins, my_first_bin, my_hist_no);
is = rply_status_send (skt, reply);
if (is != OK) {
printf ("\n%s -- send of status reply failed.\n", Tsk_name[index]);
}else {
printf (" done.\n");
}
return is;
}
default:
printf ("%s: Unrecognised command received ..\n", Tsk_name[index]);
is = rply_status_setup_and_send (skt,
reply, KER__BAD_VALUE, 0, "Unrecognised command!");
if (is != OK) {
printf ("\n%s -- send of status reply failed.\n", Tsk_name[index]);
}else {
printf (" it has been acknowledged.\n");
}
return is;
}
printf ("\007Software error in do_command - switch statement completed!\n");
return ERROR;
}
/*
**--------------------------------------------------------------------------*/
void do_daq (
/* ======
*/ struct rply_buff_struct *reply,
int index,
int sub_cmnd) {
/*
** Action routine for SQHM_DAQ command. Send a
** message to SinqHM-filler to get the command done.
**
** To send a message to SinqHM-filler:
** a) Claim Sem_Filler to gain access to the messageQ to filler;
** b) Set Filler_flag = 1 to warn SinqHM-filler that a message
** is coming. If SinqHM-filler is taking data, this gets it
** to break out of its data acquisition loop and wait for
** a message. This is to avoid SinqHM-filler having to do
** a system call in its innermost daq loop.
** c) Send the message with msgQSend (remembering to set up the
** index in the message correctly so that SinqHM-filler knows
** to whom it should send a reply).
** d) Wait for the reply with msgQReceive.
** e) Release Sem_Filler.
*/
int is, status;
char recd[80];
struct msg_to_filler_struct msg;
reply->status = htonl (KER__SUCCESS); /* Assume success */
reply->u.daq.daq_was = htons (SinqHM_Dsbl_Mask); /* Return old daq state */
reply->u.daq.filler_mask = htons (Server_masks[0]); /* Filler's mask */
reply->u.daq.server_mask = htons (Server_masks[index]); /* Server's mask */
if (sub_cmnd == DAQ__TST) { /* DAQ__TST is special - we just give the ..
** .. caller a snapshot without invoking ..
** .. SinqHM-filler. */
reply->u.daq.daq_now = reply->u.daq.daq_was;
return;
}
if (Dbg_lev0) printf ("\nDO_DAQ_%02d - claiming Sem_Filler\n", index);
if (Use_sem_tmo) {
is = (int) semTake (Sem_Filler, Sem_tmo);
}else {
is = (int) semTake (Sem_Filler, WAIT_FOREVER);
}
if (Dbg_lev0)
printf ("DO_DAQ_%02d - completed Sem_Filler claim: %d\n", index, is);
if (is != OK) {
kill (Parent_pid, SIGUSR1); /* Inform parent that we are in trouble */
sprintf (recd, "DO_DAQ_%02d - sem claim err\n", index);
perror (recd);
exit (KER__BAD_VALUE);
}
Filler_flag = 1; /* Warn SinqHM-filler that a message is coming */
msg.u.uu.cmnd = sub_cmnd;
msg.u.uu.index = index;
is = msgQSend (MsgQ_to_filler,
(char *) &msg,
sizeof (msg),
WAIT_FOREVER, MSG_PRI_NORMAL);
if (is != OK) {
printf ("do_daq -- error status from msgQSend: %d\n", is);
exit (KER__BAD_VALUE);
}
is = msgQReceive (MsgQ_to_server[index],
(char *) &msg,
sizeof (msg),
WAIT_FOREVER);
if (is <= 0) {
printf ("do_daq -- error status from msgQReceive: %d\n", is);
exit (KER__BAD_VALUE);
}
/* Complete the status response message */
reply->u.daq.daq_now = htons (msg.u.uu.new_mask); /* New daq state */
if (Dbg_lev0) printf ("DO_DAQ_%02d - releasing sem\n", index);
is = (int) semGive (Sem_Filler); /* Release the semaphore */
if (Dbg_lev0)
printf ("DO_DAQ_%02d - completed sem release: %d\n", index, is);
if (is != OK) {
kill (Parent_pid, SIGUSR1); /* Inform parent that we are in trouble */
sprintf (recd, "DO_DAQ_%02d - sem release err\n", index);
perror (recd);
exit (KER__BAD_VALUE);
}
}
/**
* --------------------------------------------------------------------------
* project_frame reads one time frame of a TOF or PSD histogram
*/
static int project_frame(int rw_skt, int pkt_size, int nx){
struct rply_buff_struct rply;
uint *buffer = NULL;
uchar *bufPtr;
int i, bytesToSend, nSend, bytesSent;
register union {
void *base;
uchar *ch;
usint *i2;
uint *i4;
} hm_pntr;
long sum;
printf("PROJECT: Trying to retrieve time frame: %d\n", nx);
/*
check arguments
*/
if(nx < 0 || nx >= N_bins){
printf("PROJECT FRAME: bad time frame requested: 0 < %d < %d\n",
nx,N_bins);
rply_status_setup (&rply, KER__BAD_VALUE, 0, "Bad argument");
rply_status_send (rw_skt, &rply);
return OK;
}
/*
allocate space
*/
buffer = (uint *)malloc(N_hists*sizeof(uint));
if(!buffer){
printf ("\n\007 -- SQHM_PROJECT-FRAME: failed to get buffer!\n");
rply_status_setup_and_send (rw_skt, &rply, KER__BAD_ALLOC, 0,
"Failed to get buffer for projecting data");
return OK;
}
/*
fill buffer
FIX: This works only OK with 4 byte HM data.
*/
hm_pntr.i4 = Hist_base_addr;
for(i = 0, sum = 0; i < N_hists;i++){
buffer[i] = htonl(*(hm_pntr.i4 + (i*N_bins) + nx));
sum += *(hm_pntr.i4+(i*N_bins) +nx);
}
printf("Frame %d contained %d counts \n",nx,sum);
/*
build reply and send data
*/
rply.bigend = 0x12345678;
rply.u.project.n_bins = htonl(N_hists);
rply.u.project.bytes_per_bin = htonl(4);
rply.u.project.cnts_lo = 0;
rply.u.project.cnts_hi = 0;
rply_status_setup_and_send (rw_skt, &rply, KER__SUCCESS, 0, NULL);
bufPtr = (uchar *)buffer;
bytesToSend = N_hists*4;
while(bytesToSend > 0){
nSend = (bytesToSend > pkt_size) ? pkt_size : bytesToSend;
bytesSent = send(rw_skt,bufPtr,nSend,0);
if(bytesSent > 0){
bytesToSend -= bytesSent;
bufPtr += bytesSent;
} else {
return ERROR;
}
}
free(buffer);
return OK;
}
/*
**--------------------------------------------------------------------------*/
int do_project (
/* ==========
*/ int index,
struct rply_buff_struct *rply_bf,
int rw_skt,
int pkt_size,
uint sub_code,
uint x_lo,
uint nx,
uint y_lo,
uint ny,
uint xdim,
uint h_slct) {
/*
** Read a "rectangular" region of Hist Mem and send it
** to the client.
*/
register int i, j, k, offs, dataPtr, nTime;
register uint my_bin_lo, my_bin_hi;
register uint my_hist_lo, my_hist_hi;
uint my_xdim, eff_nhists;
int my_nbins, is, status, bytes_to_go, nput, nxtbin, nb;
int my_daq_save;
struct rply_buff_struct dummy_rply;
uchar *buff_pntr, *last_byte;
uchar buff[pkt_size];
register union {
void *base;
uchar *ch;
usint *i2;
uint *i4;
} my_pntr, hm_pntr;
rply_status_setup (rply_bf, KER__BAD_VALUE, 0, "Bad argument"); /* Assume ..
** .. we shall find a bad arg */
/*--------------------------------------------------------------------
** The SQHM_PROJECT command is histogram mode dependent. Switch
** accordingly.
*/
/*
printf("\nProject with hm-mode : %d, subcode = %d\n", Hm_mode, sub_code);
*/
switch (Hm_mode) {
/*-----------------------------------------------------------*/
case SQHM__HM_DIG: /* SQHM__HM_DIG and SQHM__HRPT are handled the same. */
case SQHM__HRPT:
if ((sub_code & PROJECT__1_DIM) == 0) { /* Check for pseudo-2-dim mode */
/* Non-pseudo-2-dim mode. Check the args */
my_hist_lo = y_lo;
if (my_hist_lo >= N_hists) {
printf ("\n\007%s -- SQHM_PROJECT: Bad y_lo!\n", Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
my_hist_hi = (ny != 0) ? (y_lo + ny - 1) : (N_hists - 1);
if ((my_hist_hi < my_hist_lo) || (my_hist_hi >= N_hists)) {
printf ("\n\007%s -- SQHM_PROJECT: Bad ny!\n", Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
my_bin_lo = x_lo;
if (my_bin_lo >= N_bins) {
printf ("\n\007%s -- SQHM_PROJECT: Bad x_lo!\n", Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
my_bin_hi = (nx != 0) ? (x_lo + nx - 1) : (N_bins - 1);
if ((my_bin_hi < my_bin_lo) || (my_bin_hi >= N_bins)) {
printf ("\n\007%s -- SQHM_PROJECT: Bad nx!\n", Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
}else { /* It is pseudo-2-dim mode */
if (h_slct >= N_hists) {
printf ("\n\007%s -- SQHM_PROJECT: Bad h_slct!\n", Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
if ((xdim == 0) ||
(xdim > N_bins) ||
((N_bins % xdim) != 0)) {
printf ("\n\007%s -- SQHM_PROJECT: Bad xdim!\n", Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
eff_nhists = N_bins/xdim;
my_hist_lo = y_lo;
if (my_hist_lo >= eff_nhists) {
printf ("\n\007%s -- SQHM_PROJECT: Bad y_lo!\n", Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
my_hist_hi = (ny != 0) ? (y_lo + ny - 1) : (eff_nhists - 1);
if ((my_hist_hi < my_hist_lo) || (my_hist_hi >= eff_nhists)) {
printf ("\n\007%s -- SQHM_PROJECT: Bad ny!\n", Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
my_bin_lo = x_lo;
if (my_bin_lo >= xdim) {
printf ("\n\007%s -- SQHM_PROJECT: Bad x_lo!\n", Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
my_bin_hi = (nx != 0) ? (x_lo + nx - 1) : (xdim - 1);
if ((my_bin_hi < my_bin_lo) || (my_bin_hi >= xdim)) {
printf ("\n\007%s -- SQHM_PROJECT: Bad nx!\n", Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
}
/*
** All the arguments are OK. Drop through to common code
** for reserving buffer space.
*/
break;
/*-----------------------------------------------------------*/
case SQHM__TOF: /* Time-of-Flight Mode */
if(sub_code == PROJECT__FRAME){
return project_frame(rw_skt,pkt_size,nx);
}
if ((sub_code & PROJECT__1_DIM) != 0) {
printf ("\n\007%s -- SQHM_PROJECT: SQHM__TOF+PROJECT__1_DIM not yet "
"implemented!\n", Tsk_name[index]);
is = rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_VALUE, 0,
"Not yet implemented");
return OK;
}
/* Check the arguments */
my_hist_lo = y_lo;
if (my_hist_lo >= MAX_TOF_CNTR) {
printf ("\n\007%s -- SQHM_PROJECT: Bad y_lo!\n", Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
my_hist_hi = (ny != 0) ? (y_lo + ny - 1) : (N_hists - 1);
if ((my_hist_hi < my_hist_lo) || (my_hist_hi >= MAX_TOF_CNTR)) {
printf ("\n\007%s -- SQHM_PROJECT: Bad ny!\n", Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
/*
** Check that all hists are defined
*/
for (i = my_hist_lo; i <= my_hist_hi; i++) {
if (Tof_descr[i] == NULL) {
printf ("\n\007%s -- SQHM_PROJECT: Bad counter range!\n",
Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
}
/*
** Check that all have the same edge array.
*/
for (i = (my_hist_lo + 1); i <= my_hist_hi; i++) {
if (Tof_descr[i]->bin_edge != Tof_descr[i-1]->bin_edge) {
printf ("\n\007%s -- SQHM_PROJECT: Bad histogram edges!\n",
Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
}
my_bin_lo = x_lo;
if (my_bin_lo >= Tof_descr[my_hist_lo]->n_bins) {
printf ("\n\007%s -- SQHM_PROJECT: Bad x_lo!\n", Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
my_bin_hi = (nx != 0) ?
(x_lo + nx - 1) : (Tof_descr[my_hist_lo]->n_bins - 1);
if ((my_bin_hi < my_bin_lo) ||
(my_bin_hi >= Tof_descr[my_hist_lo]->n_bins)) {
printf ("\n\007%s -- SQHM_PROJECT: Bad nx!\n", Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
/*
** All the arguments are OK. Drop through to common code
** for reserving buffer space.
*/
break;
case SQHM__HM_PSD:
/*
** code for TRICS, AMOR PSD
*/
if( (sub_code & PROJECT__FRAME) == 0){
return project_frame(rw_skt,pkt_size,nx);
}
if(sub_code == PROJECT__COLL){
my_nbins = psdXSize * psdYSize;
nTime = Tof_edges[0]->n_bins;
} else if(sub_code == PROJECT__SAMPLE) {
if(x_lo < 0 || x_lo + nx > psdXSize){
printf ("\n\007%s -- SQHM_PROJECT:Bad x_range lo %d, n %d,max %d\n",
Tsk_name[index], x_lo,nx,psdXSize);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
if(y_lo < 0 || y_lo + ny > psdYSize){
printf ("\n\007%s -- SQHM_PROJECT:Bad y_range lo %d, n %d,max %d\n",
Tsk_name[index], y_lo,ny,psdYSize);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
my_nbins = Tof_edges[0]->n_bins;
nTime = Tof_edges[0]->n_bins;
} else {
printf ("\n\007%s -- SQHM_PROJECT:Bad subcode for PSD\n",
Tsk_name[index]);
is = rply_status_send (rw_skt, rply_bf);
return OK;
}
break;
/*-----------------------------------------------------------*/
default: /* SQHM_PROJECT is not supported in other modes. */
printf ("\n\007%s -- SQHM_PROJECT: bad Hm_mode!\n", Tsk_name[index]);
is = rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_VALUE, 0,
"Bad Hm_mode");
return OK;
}
/*-------------------------------------------------------------------------
*/ /*
** All the arguments have been checked. Reserve some space
** for projecting the data. The amount of space that we
** need for the projection depends on whether the
** projection is onto the x-axis or y-axis.
*/
if(Hm_mode != SQHM__HM_PSD){
my_nbins = ((sub_code & PROJECT__ON_Y) == 0) ?
(my_bin_hi - my_bin_lo + 1) : (my_hist_hi - my_hist_lo + 1);
}
my_pntr.base = calloc (my_nbins, sizeof (uint));
if (my_pntr.base == NULL) {
printf ("\n\007%s -- SQHM_PROJECT: failed to get buffer!\n",
Tsk_name[index]);
rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_ALLOC, 0,
"Failed to get buffer for projecting data");
return OK;
}
/*-----------------------------------------------------
** We got some buffer space so inhibit data acqu ...
*/
my_daq_save = SinqHM_Dsbl_Mask & Server_masks[index]; /* Remember the ..
** .. state of our ..
** .. inhibit bit */
if (my_daq_save == 0) do_daq (&dummy_rply, index, DAQ__INH);
/*-----------------------------------------------------
** ... then do the projection ...
*/
switch (Hm_mode) {
case SQHM__HM_DIG: /* HM_DIG & HRPT Mode */
case SQHM__HRPT:
if ((sub_code & PROJECT__1_DIM) == 0) { /* Check for pseudo-2-dim mode */
/* Non-pseudo-2-dim mode. Do a simple proj'n */
if ((sub_code & PROJECT__ON_Y) == 0) {
for (i = my_hist_lo; i <= my_hist_hi; i++) {
hm_pntr.base = Hist_base_addr + (i * N_bins * Bytes_per_bin);
for (j = my_bin_lo; j <= my_bin_hi; j++) {
switch (Bytes_per_bin) {
case 1: my_pntr.i4[j-my_bin_lo] += hm_pntr.ch[j]; break;
case 2: my_pntr.i4[j-my_bin_lo] += hm_pntr.i2[j]; break;
case 4: my_pntr.i4[j-my_bin_lo] += hm_pntr.i4[j];
}
}
}
}else {
for (i = my_hist_lo; i <= my_hist_hi; i++) {
hm_pntr.base = Hist_base_addr + (i * N_bins * Bytes_per_bin);
offs = i - my_hist_lo;
for (j = my_bin_lo; j <= my_bin_hi; j++) {
switch (Bytes_per_bin) {
case 1: my_pntr.i4[offs] += hm_pntr.ch[j]; break;
case 2: my_pntr.i4[offs] += hm_pntr.i2[j]; break;
case 4: my_pntr.i4[offs] += hm_pntr.i4[j];
}
}
}
}
}else { /* It is pseudo-2-dim mode */
hm_pntr.base = Hist_base_addr + (h_slct * N_bins * Bytes_per_bin);
if ((sub_code & PROJECT__ON_Y) == 0) {
for (i = my_hist_lo; i <= my_hist_hi; i++) {
for (j = my_bin_lo; j <= my_bin_hi; j++) {
switch (Bytes_per_bin) {
case 1: my_pntr.i4[j-my_bin_lo] += hm_pntr.ch[xdim*i+j]; break;
case 2: my_pntr.i4[j-my_bin_lo] += hm_pntr.i2[xdim*i+j]; break;
case 4: my_pntr.i4[j-my_bin_lo] += hm_pntr.i4[xdim*i+j];
}
}
}
}else {
for (i = my_hist_lo; i <= my_hist_hi; i++) {
offs = i - my_hist_lo;
for (j = my_bin_lo; j <= my_bin_hi; j++) {
switch (Bytes_per_bin) {
case 1: my_pntr.i4[offs] += hm_pntr.ch[xdim*i+j]; break;
case 2: my_pntr.i4[offs] += hm_pntr.i2[xdim*i+j]; break;
case 4: my_pntr.i4[offs] += hm_pntr.i4[xdim*i+j];
}
}
}
}
}
break;
case SQHM__TOF: /* Time-of-Flight Mode */
if ((sub_code & PROJECT__ON_Y) == 0) {
for (i = my_hist_lo; i <= my_hist_hi; i++) {
hm_pntr.base = (void *) Tof_descr[i]->u.l_bin_data;
for (j = my_bin_lo; j <= my_bin_hi; j++) {
switch (Bytes_per_bin) {
case 1: my_pntr.i4[j-my_bin_lo] += hm_pntr.ch[j]; break;
case 2: my_pntr.i4[j-my_bin_lo] += hm_pntr.i2[j]; break;
case 4: my_pntr.i4[j-my_bin_lo] += hm_pntr.i4[j];
}
}
}
}else {
for (i = my_hist_lo; i <= my_hist_hi; i++) {
hm_pntr.base = (void *) Tof_descr[i]->u.l_bin_data;
offs = i - my_hist_lo;
for (j = my_bin_lo; j <= my_bin_hi; j++) {
switch (Bytes_per_bin) {
case 1: my_pntr.i4[offs] += hm_pntr.ch[j]; break;
case 2: my_pntr.i4[offs] += hm_pntr.i2[j]; break;
case 4: my_pntr.i4[offs] += hm_pntr.i4[j];
}
}
}
}
break;
case SQHM__HM_PSD:
/*
** code for TRICS/AMOR PSD
**
*/
if(sub_code == PROJECT__COLL){
hm_pntr.base = Hist_base_addr;
for(i = 0; i < psdXSize; i++){
for(j = 0; j < psdYSize; j++){
offs = j * psdXSize + i;
dataPtr = j*psdXSize*nTime + i*nTime;
my_pntr.i4[offs] = 0;
for(k = 0; k < nTime; k++){
switch(Bytes_per_bin)
{
case 1:
my_pntr.i4[offs] += hm_pntr.ch[dataPtr + k];
break;
case 2:
my_pntr.i4[offs] += hm_pntr.i2[dataPtr + k];
break;
case 4:
my_pntr.i4[offs] += hm_pntr.i4[dataPtr + k];
break;
}
}
}
}
} else if(sub_code == PROJECT__SAMPLE){
hm_pntr.base = Hist_base_addr;
for(i = 0; i < nTime; i++){
my_pntr.i4[i] = 0;
}
for(i = x_lo; i < x_lo + nx; i++){
for(j = y_lo; j < y_lo + ny; j++){
dataPtr = j*psdXSize*nTime + i*nTime;
for(k = 0; k < nTime; k++){
my_pntr.i4[k] += hm_pntr.i4[dataPtr +k];
}
}
}
}
break;
default:
}
/*-----------------------------------------------------
** ... projection complete so let Filler continue and
** send data back to client.
*/
if (my_daq_save == 0) do_daq (&dummy_rply, index, DAQ__CLR);
rply_bf->u.project.n_bins = htonl (my_nbins);
rply_bf->u.project.bytes_per_bin = htonl (sizeof (uint));
rply_bf->u.project.cnts_lo = htonl (Cnts_lo);
rply_bf->u.project.cnts_hi = htonl (Cnts_hi);
if (rply_bf->bigend != 0x12345678) { /* If byte swapping needed, ...
** .. then swap them! */
for (i = 0; i < my_nbins; i++) my_pntr.i4[i] = htonl (my_pntr.i4[i]);
}
is = rply_status_setup_and_send (rw_skt, rply_bf, KER__SUCCESS, 0, NULL);
bytes_to_go = my_nbins * sizeof (uint);
buff_pntr = (uchar *) my_pntr.base;
while (bytes_to_go > 0) {
nput = (bytes_to_go > pkt_size) ? pkt_size : bytes_to_go;
is = send (rw_skt, buff_pntr, nput, 0);
if (is > 0) {
Rw_bytes_put += is;
bytes_to_go -= is;
buff_pntr += is;
}else {
free (my_pntr.base);
return ERROR; /* Fatal error on send */
}
}
free (my_pntr.base); /* Release our bit of memory */
return OK;
}
/*
**--------------------------------------------------------------------------*/
int do_read (
/* =======
*/ int index,
struct rply_buff_struct *rply_bf,
int rw_skt,
int pkt_size,
uint nbins,
uint first,
uint hist_no) {
/*
** Read a consecutive region of 'nbins' bins of the Hist Mem
** starting with bin 'first' and send it to the client.
*/
register int i, my_fstbin, my_topbin;
int is, my_nbins, status, bytes_to_go, nput, nxtbin, nb;
int my_daq_save;
struct rply_buff_struct dummy_rply;
uchar *buff_pntr, *last_byte;
uchar buff[pkt_size];
register union {
void *base;
uchar *ch;
usint *i2;
uint *i4;
} my_pntr, hm_pntr;
rply_status_setup (rply_bf, KER__BAD_VALUE, 0, "Bad argument"); /* Assume ..
** .. we shall find a bad arg */
/*--------------------------------------------------------------------
** SQHM__TRANS mode is a special case since we must always suspend
** data acq so that we can move FILLER on to the next buffer safely
** and take a private copy of the current buffer.
*/
if (Hm_mode == SQHM__TRANS) {
/*
** SQHM__TRANS mode: start by ensuring user's buffer size is OK.
*/
nbins = nbins & (~3); /* Ensure <nbins> is a multiple of 4 */
if (nbins < 16) {
if (Dbg_lev0) printf ("\n");
printf ("\007%s -- SQHM_READ: bad NBINS!\n", Tsk_name[index]);
is = rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_VALUE, 0,
"\"n_bins\" < 16");
return OK;
}
/*
** Ensure data acq is disabled
*/
my_daq_save = SinqHM_Dsbl_Mask & Server_masks[index]; /* Remember the ..
** .. state of our inhibit bit */
if (my_daq_save == 0) do_daq (&dummy_rply, index, DAQ__INH);
/*
** Now we can manipulate the buffer "safely". Actually,
** we should really use semaphore access to the buffer
** pointers since another SinqHM client could be running
** in parallel with us. We shall ignore this refinement
** for the time being!
*/
hm_pntr.base = Tran_buff_base;
last_byte = Next_char;
selectNewBuffer (last_byte); /* Move data acquisition to next buffer */
bytes_to_go = (last_byte - hm_pntr.ch + 4) & (~3);
my_pntr.base = malloc (bytes_to_go);
if (buff_pntr == NULL) {
rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_ALLOC, 0,
"Failed to get buffer for data transfer");
return OK;
}
*my_pntr.i4 = htonl (*hm_pntr.i4);
memcpy (my_pntr.ch+4, hm_pntr.ch+4, bytes_to_go-4);
/*
** Copy complete so let Filler continue.
*/
if (my_daq_save == 0) do_daq (&dummy_rply, index, DAQ__CLR);
if (bytes_to_go > nbins) bytes_to_go = nbins;
/*
** Everything seems to be OK.
** Tell client he's about to get some data!
*/
rply_bf->u.read.first_bin = htonl (0);
rply_bf->u.read.n_bins = htonl (bytes_to_go);
rply_bf->u.read.bytes_per_bin = htonl (1);
rply_bf->u.read.cnts_lo = htonl (0);
rply_bf->u.read.cnts_hi = htonl (0);
is = rply_status_setup_and_send (rw_skt, rply_bf, KER__SUCCESS, 0, NULL);
/*
** Now send the data
*/
buff_pntr = my_pntr.ch;
while (bytes_to_go > 0) {
nput = (bytes_to_go > pkt_size) ? pkt_size : bytes_to_go;
is = send (rw_skt, buff_pntr, nput, 0);
if (is > 0) {
Rw_bytes_put += is;
bytes_to_go -= is;
buff_pntr += is;
}else {
free (my_pntr.base);
return ERROR; /* Fatal error on send */
}
}
free (my_pntr.base);
return OK;
}
/*--------------------------------------------------------------------
** Non-transparent mode: Start by checking arguments.
*/
if ((hist_no == -1) && (first == -1) && (nbins == -1)) {
my_fstbin = 0;
my_nbins = N_hists * N_bins;
}else {
if (nbins < 0) {
if (Dbg_lev0) printf ("\n");
printf ("\007%s -- SQHM_READ: bad NBINS!\n", Tsk_name[index]);
is = rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_VALUE, 0,
"\"n_bins\" < 0");
return OK;
}
if (first < 0) {
if (Dbg_lev0) printf ("\n");
printf ("\007%s -- SQHM_READ: bad FIRST!\n", Tsk_name[index]);
is = rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_VALUE, 0,
"\"first_bin\" < 0");
return OK;
}
my_nbins = nbins;
if (hist_no == -1) {
my_fstbin = first;
my_topbin = my_fstbin + my_nbins;
if ((my_topbin <= 0) || (my_topbin > N_hists * N_bins)) {
if (Dbg_lev0) printf ("\n");
printf ("\007%s -- SQHM_READ: bad parameters!\n", Tsk_name[index]);
is = rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_VALUE, 0,
"Bad parameters");
return OK;
}
}else {
if ((hist_no < 0) || (hist_no >= N_hists)) {
if (Dbg_lev0) printf ("\n");
printf ("\007%s -- SQHM_READ: bad HIST_NO!\n", Tsk_name[index]);
is = rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_VALUE, 0,
"Bad \"hist_no\"");
return OK;
}
my_fstbin = (hist_no * N_bins) + first;
my_topbin = my_fstbin + my_nbins;
}
}
/*
** The args are OK.
** Tell client he's about to get some data!
*/
rply_bf->u.read.first_bin = htonl (my_fstbin);
rply_bf->u.read.n_bins = htonl (my_nbins);
rply_bf->u.read.bytes_per_bin = htonl (Bytes_per_bin);
rply_bf->u.read.cnts_lo = htonl (Cnts_lo);
rply_bf->u.read.cnts_hi = htonl (Cnts_hi);
is = rply_status_setup_and_send (rw_skt, rply_bf, KER__SUCCESS, 0, NULL);
/*
** See if we can reserve some space for making a
** copy of the histogram data.
*/
my_pntr.base = NULL;
i = memFindMax (); /* Get size of biggest free memory block */
if (i > (my_nbins * Bytes_per_bin)) my_pntr.base =
malloc (my_nbins * Bytes_per_bin);
/*
** If we got a private buffer, inhibit Filler whilst we
** make a quick copy.
*/
if (my_pntr.base != NULL) {
/*
** We got a private copy
*/
my_daq_save = SinqHM_Dsbl_Mask & Server_masks[index]; /* Remember the ..
** .. state of our ..
** .. inhibit bit */
if (my_daq_save == 0) do_daq (&dummy_rply, index, DAQ__INH);
memcpy (my_pntr.base,
((char *) Hist_base_addr) + (my_fstbin * Bytes_per_bin),
(my_nbins * Bytes_per_bin));
/*
** Copy complete so let Filler continue.
*/
if (my_daq_save == 0) do_daq (&dummy_rply, index, DAQ__CLR);
bytes_to_go = my_nbins * Bytes_per_bin;
buff_pntr = (char *) my_pntr.base;
while (bytes_to_go > 0) {
nput = (bytes_to_go > pkt_size) ? pkt_size : bytes_to_go;
is = send (rw_skt, buff_pntr, nput, 0);
if (is > 0) {
Rw_bytes_put += is;
bytes_to_go -= is;
buff_pntr += is;
}else {
free (my_pntr.base);
return ERROR; /* Fatal error on send */
}
}
free (my_pntr.base); /* Release our bit of memory */
}else {
/*
** We did not get a private copy. We'll have to copy
** out of the HM area as we send - this would cause a much
** longer inhibit of Filler so we let Filler keep running.
** If the user wants unskewed data, he must inhibit DAQ
** first using DAQ__INH.
*/
bytes_to_go = my_nbins * Bytes_per_bin;
nxtbin = my_fstbin;
my_pntr.base = buff;
hm_pntr.base = Hist_base_addr;
while (bytes_to_go > 0) {
nput = (bytes_to_go > pkt_size) ? pkt_size : bytes_to_go;
nb = nput/Bytes_per_bin;
switch (Bytes_per_bin) {
case 1:
for (i=0; i<nb; i++) my_pntr.ch[i] = hm_pntr.ch[nxtbin+i];
break;
case 2:
for (i=0; i<nb; i++) my_pntr.i2[i] = htons (hm_pntr.i2[nxtbin+i]);
break;
case 4:
for (i=0; i<nb; i++) my_pntr.i4[i] = htonl (hm_pntr.i4[nxtbin+i]);
break;
}
buff_pntr = buff;
while (nput > 0) {
is = send (rw_skt, buff_pntr, nput, 0);
if (is > 0) {
Rw_bytes_put += is;
nput -= is;
bytes_to_go -= is;
buff_pntr += is;
}else {
return ERROR; /* Fatal error on send */
}
}
nxtbin += nb;
}
}
return OK;
}
/*
**--------------------------------------------------------------------------*/
int do_write (
/* ========
*/ int index,
struct req_buff_struct *req_bf,
struct rply_buff_struct *rply_bf,
int rw_skt,
int pkt_size,
int nbins,
int first,
int bytes_per_bin,
int hist_no) {
/*
** Preset a consecutive region of the Hist Mem. The number of
** bins to preset is 'nbins' starting with bin 'first'. The
** data for the bins is read from the client.
*/
int i, is, status, bytes_to_come, nget;
uchar *b_pntr;
usint *w_pntr;
uint *l_pntr;
if ((nbins <= 0) || (bytes_per_bin <= 0)) { /* If nothing to do, do nothing! */
is = rply_status_setup_and_send (rw_skt, rply_bf, KER__SUCCESS, 0, NULL);
return is;
}
/*
** Check that we've been configured. If not, flush the data from
** the client and return an error.
*/
if (Cfgn_done == 0) {
printf ("\007 but not yet configured!\n");
net_flush (rw_skt, nbins * bytes_per_bin);
is = rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_STATE, 0,
"Not configured!");
return ERROR;
}
/*
** Check that parameters are valid.
*/
if ((bytes_per_bin != Bytes_per_bin) ||
(first < 0) ||
((first+nbins) > (N_hists*N_bins))) {
printf ("\007 but invalid parameters!\n");
net_flush (rw_skt, nbins * bytes_per_bin);
is = rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_VALUE, 0,
"Bad \"first_bin\", \"n_bins\" or \"bytes_per_bin\"!");
return ERROR;
}
bytes_to_come = nbins * Bytes_per_bin;
b_pntr = (char *) Hist_base_addr;
while (bytes_to_come > 0) {
nget = (bytes_to_come > pkt_size) ? pkt_size : bytes_to_come;
is = recv (rw_skt, b_pntr, nget, 0);
if (is > 0) {
Rw_bytes_got += is;
bytes_to_come -= is;
b_pntr += is;
}else {
net_flush (rw_skt, bytes_to_come);
is = rply_status_setup_and_send (rw_skt, rply_bf, KER__BAD_RECV, is,
"DO_WRITE: recv error status");
return ERROR;
}
}
if (0x12345678 != ntohl (0x12345678)) { /* Swap bytes, if necessary */
switch (Bytes_per_bin) {
case 1:
break;
case 2:
w_pntr = (usint *) Hist_base_addr;
for (i=0; i<nbins; i++) w_pntr[i] = ntohs (w_pntr[i]);
break;
case 4:
l_pntr = (uint *) Hist_base_addr;
for (i=0; i<nbins; i++) l_pntr[i] = ntohl (l_pntr[i]);
break;
}
}
lwl_Fifo_Flush (); /* Ensure the fibre-optic FIFO is empty */
is = rply_status_setup_and_send (rw_skt, rply_bf, KER__SUCCESS, 0, NULL);
return is;
}
/*
**--------------------------------------------------------------------------*/
void do_zero (
/* =======
*/ struct rply_buff_struct *reply,
int index,
int nbins,
int first_bin,
int hist_no) {
/*
** Action routine for SQHM_ZERO command.
*/
register int i, my_first_bin, my_topbin;
int is, my_nbins;
int my_daq_save;
char recd[80];
struct rply_buff_struct dummy_rply;
register uchar *b_pntr;
register usint *w_pntr;
register uint *l_pntr;
reply->status = KER__BAD_VALUE; /* Assume we shall find a bad arg */
if ((hist_no == -1) && (first_bin == -1) && (nbins == -1)) {
my_first_bin = 0;
my_nbins = N_hists * N_bins;
my_topbin = my_first_bin + my_nbins;
}else {
if (nbins < 0) return;
if (first_bin < 0) return;
if (hist_no == -1) {
my_first_bin = first_bin;
my_nbins = nbins;
my_topbin = my_first_bin + my_nbins;
if ((my_topbin <= 0) || (my_topbin > N_hists * N_bins)) return;
}else {
if ((hist_no < 0) || (hist_no >= N_hists)) return;
my_first_bin = (hist_no * N_bins) + first_bin;
my_topbin = my_first_bin + my_nbins;
}
}
reply->status = KER__SUCCESS; /* The args are OK -- inhibit Filler */
my_daq_save = SinqHM_Dsbl_Mask & Server_masks[index]; /* Remember the ..
** .. state of our ..
** .. inhibit bit */
if (my_daq_save == 0) {
do_daq (&dummy_rply, index, DAQ__INH);
}
switch (Bytes_per_bin) {
case 1:
b_pntr = (uchar *) Hist_base_addr;
for (i = my_first_bin; i < my_topbin; i++) b_pntr[i] = 0;
break;
case 2:
w_pntr = (usint *) Hist_base_addr;
for (i = my_first_bin; i < my_topbin; i++) w_pntr[i] = 0;
break;
case 4:
l_pntr = (uint *) Hist_base_addr;
for (i = my_first_bin; i < my_topbin; i++) l_pntr[i] = 0;
break;
}
Cnts_lo = Cnts_hi = 0;
N_events = N_skipped = N_no_coin_tsi = N_coin_tsi = 0;
Print_hdr = True;
lwl_Fifo_Flush (); /* Ensure the fibre-optic FIFO is empty */
/*
clear PSD counts
*/
psdHitCount = 0;
psdFlashCount = 0;
if (my_daq_save == 0) {
do_daq (&dummy_rply, index, DAQ__CLR); /* Remove our inhibit on Filler */
}
}
/*
**--------------------------------------------------------------------------*/
void failInet (char *text) {
/* ========
** Output the given text and exit the process.
*/
int my_errno;
static int showMem = 0;
if(showMem == 0)
{
memShowInit();
showMem = 1;
}
getErrno (&my_errno);
printf ("### Internet Error ###\n");
printf (" ### errno = %d.\n", my_errno);
perror (text);
memShow(1);
exit (EXIT_FAILURE);
}
/*--------------------------------------------------------------------------*/
void failInet_port (char *text, int port) {
/* =============
** Call to failInet with an extra parameter.
*/
char my_buff[132];
kill (Parent_pid, SIGUSR1); /* Inform the parent that we are in trouble */
sprintf (my_buff, text, port);
failInet (my_buff);
}
/*
**--------------------------------------------------------------------------*/
void free_HM_memory (void *extras) {
/* ===============
** Free any memory allocated for TOF histograms
*/
int i;
/*
** Release a possible pending buffer
*/
free (extras);
/*
** Release any allocated histogram buffer
*/
#ifdef MEN_A012
if(Hist_base_MEN_alloc == 1){
memPartFree(sysHighMemPart, Hist_base_addr);
} else {
free (Hist_base_addr);
}
Hist_base_MEN_alloc = 0;
#else
free(Hist_base_addr);
#endif
Hist_base_addr = NULL;
free (Frame_base_addr);
Frame_base_addr = NULL;
/*
** Release the tof_edge_info structures
*/
for (i = 0; i < MAX_TOF_EDGE; i++) {
free (Tof_edges[i]);
Tof_edges[i] = NULL;
}
/*
** Release the tof_edge_info structures
*/
for (i = 0; i < MAX_TOF_CNTR; i++) {
free (Tof_descr[i]);
Tof_descr[i] = NULL;
}
}
/*
**--------------------------------------------------------------------------*/
void getErrno (int *his_errno) {
/* ========
*/
*his_errno = errno; /* Make copy of errno */
return;
}
/*
**--------------------------------------------------------------------------*/
pid_t get_pid () {
/* =======
*/
int my_tid;
my_tid = taskIdSelf ();
return (pid_t) my_tid;
}
/*
**--------------------------------------------------------------------------*/
void kill_children () {
/* =============
** Send signals to all our offspring to cause them to terminate
*/
int i, is;
if (Filler_pid != 0) {
printf (" .. closing down %s ..", Filler_name);
is = kill (Filler_pid, SIGINT);
if (is == ERROR) printf ("Bad status killing FILLER.\n");
}
for (i = MAX_CLIENTS; i > 0; i--) {
if (Child_pid[i] != 0) {
printf ("\n Terminating %s ..", Tsk_name[i]);
is = kill (Child_pid[i], SIGINT);
if (is == ERROR) printf ("Bad status killing server.\n");
}
}
}
/*
**--------------------------------------------------------------------------*/
void lwl_Fifo_Flush () {
/* ==============
** Flush out any data in the fibre-optic FIFO.
*/
register int i;
register uint *my_lwl_fifo;
register union {
uint ui4;
usint ui2[2];
uchar byte[4];
} lwl_hdr;
uchar my_buff[32];
my_lwl_fifo = Lwl_fifo;
/*
** Note: The following loop runs at a rate of about 570 nsec
** per cycle. Since it takes 2 executions of the loop to
** read 1 packet in Hist Mode and this corresponds to
** 6 bytes, this loop should manage to empty the FIFO
** for neutron rates below about 875 kHz. This
** corresponds to a data rate over the fibre-optic link
** of 5.2 Mbyte/sec. Since the link can theoretically
** go faster than this, the code sets a finite limit
** for itself and, if the limit is hit, flushes to the
** end of a packet.
*/
for (i = 0; i < 10000000; i++) {
lwl_hdr.ui4 = *my_lwl_fifo;
if (lwl_hdr.ui4 == LWL_FIFO_EMPTY) return;
}
/*
** We did not succeed in emptying the FIFO. We are therefore
** likely to be in trouble!! However, we shall try our best
** to please by finding a header marker and then flushing to
** the end of that packet to leave things tidy.
*/
for (i = 0; i < 100; i++) {
lwl_hdr.ui4 = *my_lwl_fifo;
if (lwl_hdr.ui4 == LWL_FIFO_EMPTY) return;
if (lwl_hdr.byte[0] != 0) { /* Packet header? */
lwl_Packet_Read (lwl_hdr.ui4, my_buff); /* Yes! Flush and .. */
break; /* .. quit */
}
}
return;
}
/*
**--------------------------------------------------------------------------*/
int lwl_Packet_Read (uint hdr, uchar *buff) {
/* ===============
** Read current packet from the fibre-optic FIFO.
** <hdr> is the packet header and is used to calculate
** the amount of reading required. The data (including
** the header) is copied into *buff, which must be at
** least 22 bytes long.
** Return value: Number of bytes read (including 4 bytes for hdr).
*/
register uint *my_lwl_fifo;
register union {
uint ui4;
usint ui2[2];
uchar byte[4];
} lwl_data;
int i, do_print, bytes_read = 4;
ULONG tick_now;
static ULONG lPF_tick[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static int lPF_indx = 0;
static int lPF_clockRate = 0;
static int lPF_skipped = 0;
if (lPF_clockRate == 0) lPF_clockRate = sysClkRateGet (); /* Ticks/second */
my_lwl_fifo = Lwl_fifo;
lwl_data.ui4 = hdr;
buff[0] = lwl_data.byte[0];
buff[1] = lwl_data.byte[1];
buff[2] = lwl_data.byte[2];
buff[3] = lwl_data.byte[3];
/*
** Switch according to header type ...
*/
switch (hdr & LWL_HDR_TYPE_MASK) {
case LWL_HM_NC_C9: /* Cases with 18 more bytes ..
** .. Also includes LWL_HM_CO_C9
** .. LWL_SM_NC_C9
** .. LWL_SM_CO_C9
*/
lwl_data.ui4 = *my_lwl_fifo; /* Read remaining bytes */
buff[bytes_read++] = lwl_data.byte[2];
buff[bytes_read++] = lwl_data.byte[3];
case LWL_HM_NC_C8: /* Cases with 16 more bytes ..
** .. Also includes LWL_HM_CO_C8
** .. LWL_SM_NC_C8
** .. LWL_SM_CO_C8
*/
lwl_data.ui4 = *my_lwl_fifo; /* Read remaining bytes */
buff[bytes_read++] = lwl_data.byte[2];
buff[bytes_read++] = lwl_data.byte[3];
case LWL_HM_NC_C7: /* Cases with 14 more bytes ..
** .. Also includes LWL_HM_CO_C7
** .. LWL_SM_NC_C7
** .. LWL_SM_CO_C7
*/
lwl_data.ui4 = *my_lwl_fifo; /* Read remaining bytes */
buff[bytes_read++] = lwl_data.byte[2];
buff[bytes_read++] = lwl_data.byte[3];
case LWL_HM_NC_C6: /* Cases with 12 more bytes ..
** .. Also includes LWL_HM_CO_C6
** .. LWL_SM_NC_C6
** .. LWL_SM_CO_C6
*/
lwl_data.ui4 = *my_lwl_fifo; /* Read remaining bytes */
buff[bytes_read++] = lwl_data.byte[2];
buff[bytes_read++] = lwl_data.byte[3];
case LWL_HM_NC_C5: /* Cases with 10 more bytes ..
** .. Also includes LWL_HM_CO_C5
** .. LWL_SM_NC_C5
** .. LWL_SM_CO_C5
*/
lwl_data.ui4 = *my_lwl_fifo; /* Read remaining bytes */
buff[bytes_read++] = lwl_data.byte[2];
buff[bytes_read++] = lwl_data.byte[3];
case LWL_HM_NC_C4: /* Cases with 8 more bytes ..
** .. Also includes LWL_HM_CO_C4
** .. LWL_SM_NC_C4
** .. LWL_SM_CO_C4
*/
lwl_data.ui4 = *my_lwl_fifo; /* Read remaining bytes */
buff[bytes_read++] = lwl_data.byte[2];
buff[bytes_read++] = lwl_data.byte[3];
case LWL_HM_NC_C3: /* Cases with 6 more bytes ..
** .. Also includes LWL_HM_CO_C3
** .. LWL_SM_NC_C3
** .. LWL_SM_CO_C3
*/
case LWL_TSI_HM_C: /* Other cases with 6 more bytes ..
** .. Also includes LWL_TSI_SM_C
*/
lwl_data.ui4 = *my_lwl_fifo; /* Read remaining bytes */
buff[bytes_read++] = lwl_data.byte[2];
buff[bytes_read++] = lwl_data.byte[3];
case LWL_HM_NC_C2: /* Cases with 4 more bytes ..
** .. Also includes LWL_HM_CO_C2
** .. LWL_SM_NC_C2
** .. LWL_SM_CO_C2
*/
lwl_data.ui4 = *my_lwl_fifo; /* Read remaining bytes */
buff[bytes_read++] = lwl_data.byte[2];
buff[bytes_read++] = lwl_data.byte[3];
case LWL_HM_NC_C1: /* Cases with 2 more bytes ..
** .. Also includes LWL_HM_NC_C1
*/
case LWL_TR_C1: /* Other cases with 2 more bytes */
case LWL_TR_C2: /* Also includes LWL_TOF_C1 - LWL_TOF_C9 */
case LWL_TR_C3:
case LWL_TR_C4:
case LWL_TR_C5:
case LWL_TR_C6:
case LWL_TR_C7:
case LWL_TR_C8:
case LWL_TR_C9:
case LWL_TSI_TR: /* Yet more cases with 2 more bytes ..
** .. Also includes LWL_TSI_HM_NC
** .. LWL_TSI_TOF
** .. LWL_TSI_SM_NC
*/
lwl_data.ui4 = *my_lwl_fifo; /* Read remaining bytes */
buff[bytes_read++] = lwl_data.byte[2];
buff[bytes_read++] = lwl_data.byte[3];
case LWL_FIFO_EMPTY: /* FIFO empty - no more bytes */
break;
default:
/*
** Suppress messages if too many! Record times of last
** 10 messages to see if this one should be printed.
*/
tick_now = tickGet ();
if (lPF_indx == 9) { /* Only suppress after 10th message */
if ((tick_now - lPF_tick[0]) > (5 * 60 * lPF_clockRate)) {
do_print = True; /* No more than 10 message per 5 mins */
for (i = 0; i < 9; i++) lPF_tick[i] = lPF_tick[i+1];
lPF_tick[9] = tick_now;
}else if ((tick_now - lPF_tick[9]) > (60 * lPF_clockRate)) {
do_print = True; /* No more than 1 message per min */
for (i = 0; i < 9; i++) lPF_tick[i] = lPF_tick[i+1];
lPF_tick[9] = tick_now;
}else {
do_print = False; /* Suppress this message */
lPF_skipped++;
}
}else {
do_print = True;
lPF_tick[lPF_indx] = tick_now;
lPF_indx++;
}
if (do_print) {
printf ("lwl_Packet_Read -- unrecognised packet header 0x%08x\n", hdr);
if (lPF_skipped > 0) {
printf ("lwl_Packet_Read -- %d packets skipped\n", lPF_skipped);
}
lPF_skipped = 0;
}
}
return bytes_read;
}
/*
**--------------------------------------------------------------------------*/
int make_child (int (* proc) (), int flag, int pkt_size) {
/* ==========
** Find a free child index, create a child process and
** invoke procedure proc in the child procedure.
** Return value > 0 if child successfully created;
** = 0 if this is the child which is executing;
** = -1 if error returned by fork;
** = -2 if there are too many children already;
** = -3 if time-out waiting for child to signal.
** = -4 the child indicated a start-up error.
*/
int i, status, tmo;
pid_t created_pid;
char tsknam[20];
/*
** Find a free PID index. Zero is not a permitted value.
*/
for (i = 1; i <= MAX_CLIENTS; i++) {
if (Child_pid[i] == 0) break;
}
if (i <= MAX_CLIENTS) { /* Free index found? */
Cnt_SIGUSR1 = 0;
semTake (Sem_Server, NO_WAIT); /* Ensure that Sem_Server is claimed. ..
** .. Child will release it when ready */
Child_exit_status[i] = 0; /* Zero child's status indicator */
sprintf (tsknam, "hmSrv%02d", i);
created_pid = taskSpawn ( /* Make a child */
tsknam, /* Name */
100, /* Priority */
VX_FP_TASK, /* Options - fl.pt. usage assumed */
20000, /* Stack size */
proc, /* The entry point */
flag,
i,
pkt_size, 0,0,0,0,0,0,0);
if (created_pid == ERROR) { /* Error? */
return -1; /* Yes. */
}else { /* Parent */
Child_pid[i] = created_pid;
tmo = 1000; /* Normally give child 1000 ticks to ..
** .. get going */
if (flag != 0) {
tmo = WAIT_FOREVER; /* But in debug mode, wait forever! */
}
status = semTake (Sem_Server, tmo); /* Wait for child to get going */
if (status == ERROR) { /* Timeout? */
taskDelete (Child_pid[i]); /* Yes, kill child. */
Child_pid[i] = 0;
return -3; /* Return with error. */
}else { /* No timeout so child is ready. */
if (Child_exit_status[i] == 0) { /* Did the child have startup a ..
** .. problem */
return i; /* No, so return its index */
}else {
return -4; /* Yes, so return error */
}
}
}
}
return -2; /* There are already too many children. */
}
/*
**--------------------------------------------------------------------------*/
int make_filler (int suspendMode) {
/* ===========
** Create a child process to execute the FILLER procedure.
** Return value = 1 if FILLER successfully created;
** = 0 if this is FILLER which is executing;
** = -1 if error returned by fork;
** = -2 if FILLER already running;
** = -3 if time-out waiting for FILLER to signal.
*/
int i, status, tmo;
int created_pid;
if (Filler_pid == 0) {
Cnt_SIGUSR1 = 0;
semTake (Sem_Filler, NO_WAIT); /* Ensure that Sem_Filler is claimed. ..
** .. FILLER will release it when set up */
sprintf (Filler_name, "hmFill%04d", Port_base);
created_pid = taskSpawn ( /* Make a child */
Filler_name, /* Name */
250, /* Priority (0=highest, 255=lowest ) */
VX_FP_TASK, /* Options - fl.pt. usage assumed */
20000, /* Stack size */
SinqHM_filler, /* The entry point */
suspendMode,
0,0,0,0,0,0,0,0,0);
if (created_pid == ERROR) { /* Error? */
return -1; /* Yes. */
}else { /* No */
Filler_pid = created_pid;
tmo = 10000; /* Normally give FILLER 1000 ticks to ..
** .. get going */
if (suspendMode != 0) {
tmo = WAIT_FOREVER; /* But in debug mode, wait forever! */
}
if (Dbg_lev0) printf ("make_filler: waiting for %s to get going ..\n",
Filler_name);
status = semTake (Sem_Filler, tmo); /* Wait for FILLER to get going */
if (status == ERROR) { /* Timeout? */
taskDelete (Filler_pid); /* Yes, kill FILLER. */
Filler_pid = 0;
return -3; /* Return with error. */
}else { /* No timeout so FILLER is ready. */
if (Dbg_lev0)
printf ("make_filler: %s is up and running.\n", Filler_name);
semGive (Sem_Filler); /* Release Sem_Filler */
return 1;
}
}
}
return -2; /* FILLER already active. A configure has been repeated. */
}
/*
**--------------------------------------------------------------------------*/
int net_flush (int skt, int nbytes) {
/* =========
*/
int is, bytes_to_come, nget;
char buff[1024];
bytes_to_come = nbytes;
while (bytes_to_come > 0) {
nget = (bytes_to_come > sizeof (buff)) ? sizeof (buff) : bytes_to_come;
is = recv (skt, buff, nget, 0);
if (is > 0) {
bytes_to_come -= is;
}else {
return ERROR;
}
}
return OK;
}
/*
**--------------------------------------------------------------------------*/
void process_coinc_tsi (
/* =================
*/ uint hdr) {
/* Routine to process a "coincidence" Timing-Status-Info
** Packet. These packets have 10 bytes altogether. The first
** 4 bytes are in hdr.
*/
int i, j, is;
register union {
uint ui4;
usint ui2[2];
uchar ui1[4];
} lwl_data;
usint words[3];
for (j=0; j<3; j++) { /* Get the remaining 6 bytes */
for (i=0; i<1000; i++) {
lwl_data.ui4 = *Lwl_fifo; /* Get the last 16 bits */
if (lwl_data.ui4 != LWL_FIFO_EMPTY) {
break;
}
taskDelay (0); /* But wait if FIFO is slow! */
}
if (lwl_data.ui4 == LWL_FIFO_EMPTY) {
printf ("Time-out getting last 6 bytes of a \"coincidence\" "
"TSI packet!\n");
return;
}
words[j] = lwl_data.ui2[1];
}
N_coin_tsi++;
Dt_or_dts.both = hdr & LWL_TSI_DT_MSK;
Nrl_active = ((hdr & LWL_HDR_NRL_MASK) != 0) ? True : False;
Daq_active = ((hdr & Lwl_hdr_daq_mask) == Lwl_hdr_daq_soll) ? True : False;
Tsi_status_info = words[0];
Tsi_flags = (Nrl_active) ? STATUS_FLAGS__NRL : 0;
if ((hdr & LWL_HDR_PF_MASK) != 0) Tsi_flags |= STATUS_FLAGS__PF;
if ((hdr & LWL_HDR_SWC_MASK) != 0) Tsi_flags |= STATUS_FLAGS__SWC;
if (Daq_active) Tsi_flags |= STATUS_FLAGS__DAQ;
if ((hdr & LWL_HDR_SYNC0_MASK) != 0) Tsi_flags |= STATUS_FLAGS__SYNC0;
if ((hdr & LWL_HDR_SYNC1_MASK) != 0) Tsi_flags |= STATUS_FLAGS__SYNC1;
if ((hdr & LWL_HDR_SYNC2_MASK) != 0) Tsi_flags |= STATUS_FLAGS__SYNC2;
if ((hdr & LWL_HDR_SYNC3_MASK) != 0) Tsi_flags |= STATUS_FLAGS__SYNC3;
if ((hdr & LWL_HDR_UD_MASK) != 0) Tsi_flags |= STATUS_FLAGS__UD;
if ((hdr & LWL_HDR_GU_MASK) != 0) Tsi_flags |= STATUS_FLAGS__GU;
lwl_data.ui2[0] = words[1];
lwl_data.ui2[1] = words[2];
Num_bad_events = lwl_data.ui4;
}
/*--------------------------------------------------------------------------
process_gummi_monitor processes special monitor datagrams as emitted by
SANS. In gummi mode a sample environment is cycled and data continously
collected during various steps of the cycle. Naturally, monitor values are
needed at each step in order to be able to scale the data measured
appropriatetly. The monitors are sent in a special datagram consisting of.
7 packets. The first is the header and handed down as a function
call parameter. This header also holds the gummi cycle number to which this
monitor belongs. The following six packets are the monitor values, separate
as low byte, high byte.
The monitors are then stored into the last three counters of the first
detector (and only) detector bank. The looser is supposed to give three
additional detectors additional to the normal ones.
Look at this again when one of the following conditions is violated:
- More then one detector bank.
--------------------------------------------------------------------------*/
void process_gummi_monitor(uint hdr){
uint gummiBin, readbuf[6], mon[3];
int i, imon;
struct tof_histog *my_tof_descr;
union {
uint ui4;
usint ui2[2];
uchar ui1[4];
} lwl_data, monitor;
/*
collect those monitor values
*/
for(imon = 0; imon < 6; imon++){
readbuf[imon] = LWL_FIFO_EMPTY;
for (i=0; i<1000; i++) {
readbuf[imon] = *Lwl_fifo;
if (readbuf[imon] != LWL_FIFO_EMPTY) break;
taskDelay (0); /* But wait if FIFO is slow! */
}
if(readbuf[imon] == LWL_FIFO_EMPTY){
printf("Timeout reading monitor %d in SANS GUMMI mode\n", imon);
return;
}
}
/*
put them together again
*/
for(imon = 0; imon < 3; imon++){
lwl_data.ui4 = readbuf[imon*2];
monitor.ui2[0] = lwl_data.ui2[1];
lwl_data.ui4 = readbuf[imon*2+1];
monitor.ui2[1] = lwl_data.ui2[1];
mon[imon] = monitor.ui4;
}
gummiBin = hdr & LWL_HDR_TS_MASK;
if(gummiBin < 0 || gummiBin >= N_bins){
printf("Invalid gummiBin %d detected \n", gummiBin);
return;
}
if(Dbg_lev1){
printf(" Gummi monitors: %d, %d, %d registered for gummi bin %d\n",
mon[0],mon[1],mon[2],gummiBin);
}
for(imon = 0; imon < 3; imon++){
my_tof_descr=Tof_descr[N_hists-3+imon];
/*
printf(" detector %d receives %d\n", N_hists-3+imon, mon[imon]);
*/
switch (my_tof_descr->bytes_per_bin) {
case 1:
my_tof_descr->u.b_bin_data[gummiBin] += mon[imon];
break;
case 2:
my_tof_descr->u.w_bin_data[gummiBin] += mon[imon];
break;
default:
my_tof_descr->u.l_bin_data[gummiBin] += mon[imon];
break;
}
}
}
/*
**--------------------------------------------------------------------------*/
void process_psd_tsi (
/* =================
*/ uint hdr) {
/* Routine to process a PSD Timing-Status-Info
** Packet. These packets have 10 bytes altogether. The first
** 4 bytes are in hdr.
*/
int i, j, is;
register union {
uint ui4;
usint ui2[2];
uchar ui1[4];
} lwl_data;
usint words[3];
for (j=0; j<3; j++) { /* Get the remaining 6 bytes */
for (i=0; i<1000; i++) {
lwl_data.ui4 = *Lwl_fifo; /* Get the last 16 bits */
if (lwl_data.ui4 != LWL_FIFO_EMPTY) break;
taskDelay (0); /* But wait if FIFO is slow! */
}
if (lwl_data.ui4 == LWL_FIFO_EMPTY) {
printf ("Time-out getting last 6 bytes of a PSD "
"TSI packet!\n");
return;
}
words[j] = lwl_data.ui2[1];
}
/* printf(" %X %X %X\n", words[0], words[1], words[2]); */
N_coin_tsi++;
Dt_or_dts.both = hdr & LWL_TSI_DT_MSK;
Nrl_active = ((hdr & LWL_HDR_NRL_MASK) != 0) ? True : False;
Daq_active = ((hdr & Lwl_hdr_daq_mask) == Lwl_hdr_daq_soll) ? True : False;
Tsi_status_info = words[0];
Tsi_flags = (Nrl_active) ? STATUS_FLAGS__NRL : 0;
if ((hdr & LWL_PSD_PWF) != 0) Tsi_flags |= STATUS_FLAGS__PF;
if ((hdr & LWL_HDR_SWC_MASK) != 0) Tsi_flags |= STATUS_FLAGS__SWC;
if (Daq_active) Tsi_flags |= STATUS_FLAGS__DAQ;
if ((hdr & LWL_HDR_SYNC0_MASK) != 0) Tsi_flags |= STATUS_FLAGS__SYNC0;
if ((hdr & LWL_HDR_SYNC1_MASK) != 0) Tsi_flags |= STATUS_FLAGS__SYNC1;
if ((hdr & LWL_HDR_SYNC2_MASK) != 0) Tsi_flags |= STATUS_FLAGS__SYNC2;
if ((hdr & LWL_HDR_SYNC3_MASK) != 0) Tsi_flags |= STATUS_FLAGS__SYNC3;
/*
if ((hdr & LWL_HDR_UD_MASK) != 0) Tsi_flags |= STATUS_FLAGS__UD;
if ((hdr & LWL_HDR_GU_MASK) != 0) Tsi_flags |= STATUS_FLAGS__GU;
*/
psdHitCount += words[1];
psdFlashCount += words[2] & LWL_PSD_FLASH_MASK;
if((words[2] & LWL_PSD_XORF) != 0) {
psdXORF = 1;
}else {
psdXORF = 0;
}
if((words[2] & LWL_PSD_CONF) != 0) {
psdConf = 0;
}else {
psdConf = 1;
}
}
/*
**--------------------------------------------------------------------------*/
void process_no_coinc_tsi (
/* ====================
*/ uint hdr) {
/* Routine to process a "normal" Timing-Status-Info Packet.
** These packets have 6 bytes altogether. The first 4 bytes are
** in hdr.
*/
int i;
register union {
uint ui4;
usint ui2[2];
uchar ui1[4];
} lwl_data;
for (i=0; i<1000; i++) {
lwl_data.ui4 = *Lwl_fifo; /* Get the last 16 bits */
if (lwl_data.ui4 != LWL_FIFO_EMPTY) {
break;
}
taskDelay (0); /* But wait if FIFO is slow! */
}
if (lwl_data.ui4 == LWL_FIFO_EMPTY) {
printf ("Time-out getting last 16 bits of a \"normal\" TSI packet!\n");
return;
}
N_no_coin_tsi++;
Dt_or_dts.both = hdr & LWL_TSI_DT_MSK;
Nrl_active = ((hdr & LWL_HDR_NRL_MASK) != 0) ? True : False;
Daq_active = ((hdr & Lwl_hdr_daq_mask) == Lwl_hdr_daq_soll) ? True : False;
Tsi_status_info = lwl_data.ui2[1];
Tsi_flags = (Nrl_active) ? STATUS_FLAGS__NRL : 0;
if ((hdr & LWL_HDR_PF_MASK) != 0) Tsi_flags |= STATUS_FLAGS__PF;
if ((hdr & LWL_HDR_SWC_MASK) != 0) Tsi_flags |= STATUS_FLAGS__SWC;
if (Daq_active) Tsi_flags |= STATUS_FLAGS__DAQ;
if ((hdr & LWL_HDR_SYNC0_MASK) != 0) Tsi_flags |= STATUS_FLAGS__SYNC0;
if ((hdr & LWL_HDR_SYNC1_MASK) != 0) Tsi_flags |= STATUS_FLAGS__SYNC1;
if ((hdr & LWL_HDR_SYNC2_MASK) != 0) Tsi_flags |= STATUS_FLAGS__SYNC2;
if ((hdr & LWL_HDR_SYNC3_MASK) != 0) Tsi_flags |= STATUS_FLAGS__SYNC3;
if ((hdr & LWL_HDR_UD_MASK) != 0) Tsi_flags |= STATUS_FLAGS__UD;
if ((hdr & LWL_HDR_GU_MASK) != 0) Tsi_flags |= STATUS_FLAGS__GU;
}
/*
**--------------------------------------------------------------------------*/
int rply_status_send (
/* ================
*/ int skt,
struct rply_buff_struct *rply_bf) {
int is;
is = send (skt, (char *) rply_bf, sizeof (*rply_bf), 0);
if (is == sizeof (*rply_bf)) {
Rw_bytes_put += is;
return OK;
}else {
return ERROR;
}
}
/*
**--------------------------------------------------------------------------
** rply_status_setup: Routine to set up a Status-response to client.
** If <msg> is not NULL, <msg> will be copied
** to the message field of the response. Otherwise,
** only the status and sub_status fields will be
** set up.
*/
void rply_status_setup (
/* =================
*/ struct rply_buff_struct *rply_bf,
int status,
int sub_status,
char *msg) {
rply_bf->bigend = htonl (0x12345678);
rply_bf->status = htonl (status);
rply_bf->sub_status = htonl (sub_status);
if (msg != NULL) {
if (strlen (msg) < sizeof (rply_bf->u.message)) {
strcpy (rply_bf->u.message, msg);
}else {
strcpy (rply_bf->u.message, "Message overflow!");
}
}
}
/*
**--------------------------------------------------------------------------*/
int rply_status_setup_and_send (
/* ==========================
*/ int skt,
struct rply_buff_struct *rply_bf,
int status,
int sub_status,
char *msg) {
int is;
rply_status_setup (rply_bf, status, sub_status, msg);
is = rply_status_send (skt, rply_bf);
return is;
}
/*
**--------------------------------------------------------------------------*/
uchar *selectNewBuffer (uchar *nxt) {
/* ===============
**
** Move to new buffer in SQHM_TRANS mode.
**
** *nxt = next free byte in current buffer.
** Return value is first free byte in next buffer.
*/
int i;
/*
** Close off the current buffer
*/
*nxt = 0;
i = nxt - Tran_buff_base; /* Get number of bytes used in this buffer */
memcpy (Tran_buff_base, &i, sizeof (i)); /* Put at front of buffer */
/*
** Move to next buffer
*/
Curr_hist++;
if (Curr_hist > N_hists) Curr_hist = 0;
Tran_buff_base = ((uchar *) Hist_base_addr) + (Curr_hist * N_bins);
Next_char = Tran_buff_base + 4;
return Next_char;
}
/*
**--------------------------------------------------------------------------*/
void setupLevelGenerator (int use_level_gen, char *base_addr) {
/* ===================
** Set up VME access to a VMIO10 module at address 0x1900
** to be used for generating timing signals.
**
** If (use_level_gen == 0), the level generator will not
** be used. The VME address will point to a memory
** location.
*/
STATUS status;
char aux;
void (* sig_status) (int);
if (use_level_gen == 0) {
VmioBase = Vmio_Dummy;
printf ("Timing signal generation via VMIO10 module disabled.\n");
return;
}
if (base_addr == NULL) {
status = sysBusToLocalAdrs (VME_AM_USR_SHORT_IO, (char *) VMIO_BASE_ADDR,
(char **) &VmioBase);
}else {
status = sysBusToLocalAdrs (VME_AM_USR_SHORT_IO, base_addr,
(char **) &VmioBase);
}
if (status != OK) {
printf ("Error status from sysBusToLocalAdrs -- VMIO10 disabled.\n");
VmioBase = Vmio_Dummy;
return;
}
/*
** The "setjmp" and "signal" stuff it to trap a possible machine
** check if the VMIO10 module is absent. This is rather obscure
** code -- sorry about that but blame Unix thinking, not me, if
** you don't like it!
*/
sig_status = signal (SIGBUS, catch_machine_check);
if (setjmp (Vmio_trap_env) != 0) {
/*
** We get to this code only if the VMIO10 module is absent.
*/
printf ("\007Bus error detected on trying to access the VMIO10 module!\n"
"Timing signals will not be generated via the VMIO10.\n");
VmioBase = Vmio_Dummy;
return;
}
/*
** Now set up Ports A & B of the VMIO10, i.e. the first Z8536-CIO.
** If the module is absent, the first access will trap and exit via
** the "setjmp" condition block above.
**
** Start with a "reset" ..
*/
aux = VmioBase[VMIO_AB_CNTL]; /* Read Cntrl to ensure not State 1 */
VmioBase[VMIO_AB_CNTL] = 0x00; /* Write zero to Cntrl to ensure not in ..
** .. "Reset State" */
aux = VmioBase[VMIO_AB_CNTL]; /* Read Cntrl to ensure State 0 */
VmioBase[VMIO_AB_CNTL] = Z8536_MICR; /* Select the Mstr Int Ctrl Reg */
VmioBase[VMIO_AB_CNTL] = 0x01; /* Set the reset bit */
VmioBase[VMIO_AB_CNTL] = 0x00; /* Then clr it to complete reset */
/*
** Now set polarity and direction ..
*/
VmioBase[VMIO_AB_CNTL] = Z8536_DPPR_A; /* Port A Data Path Pol */
VmioBase[VMIO_AB_CNTL] = 0x00; /* Non-inverting */
VmioBase[VMIO_AB_CNTL] = Z8536_DPPR_B; /* Port B Data Path Pol */
VmioBase[VMIO_AB_CNTL] = 0x00; /* Non-inverting */
VmioBase[VMIO_AB_CNTL] = Z8536_DDR_A; /* Port A Data Direction */
VmioBase[VMIO_AB_CNTL] = 0x00; /* All bits output */
VmioBase[VMIO_AB_CNTL] = Z8536_DDR_B; /* Port B Data Direction */
VmioBase[VMIO_AB_CNTL] = 0x00; /* All bits output */
/*
** Now enable Ports A & B ..
*/
VmioBase[VMIO_AB_CNTL] = Z8536_MCCR; /* Select Master Config Ctrl Reg */
VmioBase[VMIO_AB_CNTL] = 0x84;
/*
** Finally zero Ports A & B ..
*/
VmioBase[VMIO_PORT_A] = 0x00;
VmioBase[VMIO_PORT_B] = 0x00;
sig_status = signal (SIGBUS, SIG_DFL); /* Reset trap handler to default */
printf ("Timing signal generation via VMIO10 module enabled.\n");
return;
}
/*
**--------------------------------------------------------------------------
** setup_inet_info: Get Internet Nodename and Address from System.
*/
void setup_inet_info (
/* ===============
*/ char *host,
int host_size,
char *addr,
int addr_size) {
int status;
struct in_addr my_addr;
char my_addr_c[INET_ADDR_LEN];
status = gethostname (host, host_size);
if (status != 0) StrJoin (host, host_size, "Undefined", "");
my_addr.s_addr = hostGetByName (host);
inet_ntoa_b (my_addr, my_addr_c);
StrJoin (addr, addr_size, my_addr_c, "");
}
/*--------------------------------------------------------------------------*/
int sleep (int secs) {
/* =====
** Go to sleep for secs seconds.
*/
int ticks;
ticks = secs * sysClkRateGet ();
taskDelay (ticks);
return 0;
}
/*
**---------------------------------------------------------------------------
** StrJoin - join 2 strings.
**
** The routine joins 2 strings, checking for total string
** length and ensuring the result will be zero terminated.
** The "result" arg may be the same as "str_a" or "str_b".
**
** Note: strncat is used exclusively rather than
** strncpy to be sure result is always
** null terminated.
*/
char *StrJoin (
/* =======
*/ char *result,
int result_size,
char *str_a,
char *str_b) {
int i, size, size_a, size_b;
size = result_size - 1;
if (size < 0) return result;
if (result == str_a) { /* Are the result and str_a the same? */
size_a = strlen (str_a); /* Yes */
if (size_a > size) { /* Check sizes anyway. */
result[size] = NIL; /* Truncate str_a. No room for str_b! */
}else {
size = size - strlen (result); /* And append str_b */
if (size > 0) {
strncat (result, str_b, size);
}
}
}else if (result == str_b) { /* Are the result and str_b the same? */
size_a = strlen (str_a); /* Yes, this is a bit complicated! */
size_b = strlen (str_b);
if (size_a >= size) { /* If str_a completely fills result, .. */
result[0] = NIL; /* .. then just copy in str_a */
strncat (result, str_a, size);
}else {
/*
** Otherwise, str_b must first be moved to
** make room for str_a and then str_a must
** be put at the front of the result.
*/
if ((size_a + size_b) > size) size_b = size - size_a;
result[size_a+size_b] = NIL;
for (i = (size_b-1); i >= 0; i--) result[size_a+i] = str_b[i];
memcpy (result, str_a, size_a);
}
}else { /* Result is neither str_a nor str_b so .. */
result[0] = NIL; /* .. str_a needs to be copied */
strncat (result, str_a, size);
size = size - strlen (result); /* And str_a appended */
if (size > 0) strncat (result, str_b, size);
}
return result;
}
/*===================================== End of SinqHM_srv_routines.c ========*/