- fixes to amor writing and status code - edited ecbcounter to stop at no beam - updated documentation - fixed a bug in project code affecting SANS
4131 lines
138 KiB
C
Executable File
4131 lines
138 KiB
C
Executable File
#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 ========*/
|