Files
sics/sinqhm/SinqHM_srv_routines.c
2000-11-07 11:57:15 +00:00

3321 lines
113 KiB
C
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#define IDENT "1B06"
/*
** +--------------------------------------------------------------+
** | Paul Scherrer Institute |
** | SINQ Division |
** | |
** | This software may be used freely by non-profit organizations.|
** | It may be copied provided that the name of P.S.I. and of the |
** | author is included. Neither P.S.I. nor the author assume any |
** | responsibility for the use of this software outside of P.S.I.|
** +--------------------------------------------------------------+
**
** Module Name . . . . . . . . : [...SinqHM]SinqHM_srv_routines.c
**
** Author . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Dec 1996
**
** Updates:
** 1A01 12-Dec-1996 DM Initial version.
** 1A06 16-Jul-1997 DM Flush fibre-optic FIFO on SQHM_ZERO and SQHM_WRITE.
** 1B01 11-Jun-1999 DM Add SQHM__HRPT mode.
** 1B02 10-Aug-1999 DM Make Lwl_hdr_daq_mask/Lwl_hdr_daq_soll dependent
** on the instrument.
**---------------------------------------------------------------------------
** 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>
#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__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:
printf ("\nchk_config_alloc: "
"histogramming mode SQHM__HM_PSD is not yet supported.\n");
rply_status_setup (reply, KER__BAD_VALUE, 0, "Unsupported hist mem mode");
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_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], status);
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);
}
}
/*
**--------------------------------------------------------------------------*/
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, offs;
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.
*/
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__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;
/*-----------------------------------------------------------*/
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.
*/
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;
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 */
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;
getErrno (&my_errno);
printf ("### Internet Error ###\n");
printf (" ### errno = %d.\n", my_errno);
perror (text);
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
*/
free (Hist_base_addr);
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 = 1000; /* 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;
}
/*
**--------------------------------------------------------------------------*/
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 ========*/