#define	    IDENT	"1B10"
/*
** +--------------------------------------------------------------+
** |                  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_bootParamsConfig.c
**
** Author   . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Jun 1997
**
** Updates:
**  1A01 10-Jun-1997 DM	    Initial version.
**---------------------------------------------------------------------------
**  SinqHM_bootParamsConfig.c is a simple VxWorks utility program for
**  obtaining the "other" field of the VxWorks boot line and using it
**  to automatically start the SINQ Histogram Memory processes.
*/
    /*
    **  The "other" string may be specified as follows:
    **
    **         <action>=<arg0>,..,<argn>/...
    **
    **  There may be no white space characters in the string. Tokens
    **  in the string may be specified in upper or lower case.
    **
    **  <action> may be "sp"   for "Spawn a task"
    **                  "sps"  for "Spawn and suspend a task"
    **                  "cfg"  for "Configure SinqHM_srv"
    **                  "wt"   for "Wait"
    **----------------------------------------------------
    **  If <action> = "sp" or "sps", then
    **
    **     <arg0> = name of task to spawn. This may be:
    **                "SinqHM"   for SinqHM_srv or
    **                "lwl"      for lwl_server or
    **                "bootUtil" for SinqHM_bootUtil or
    **                "focus"    for FOCUS_srv
    **     <arg1>,..<arg9> = integer args for the spawn, as follows:
    **
    **    If <arg0> = "SinqHM"
    **     <arg1> = TCP/IP port number for server (dflt=2400).
    **     <arg2> = <use-level-gen> flag. If non-zero, then use level
    **                  generator to generate timing signals (dflt=0).
    **     <arg3> = base address of VMIO10 level generator
    **                     module (dflt=0x1900).
    **
    **    If <arg0> = "lwl"
    **     <arg1> = TCP/IP port number for lwl_server (dflt=3501).
    **     <arg2> = base address of Histogram Test-generator
    **                     module (dflt=0x1800).
    **     <arg3> = verbosity. If non-zero, be verbose (dflt=0).
    **
    **    If <arg0> = "bootUtil"
    **     <arg1> = TCP/IP port number for SinqHM_bootUtil (dflt=2300).
    **
    **    If <arg0> = "focus"
    **     <arg1> = name of hostM (Mittel-bank) (dflt=localhost).
    **     <arg2> = #-counters in Mittel-bank (dflt=150).
    **     <arg3> = name of hostO (Ober-bank) (dflt=lnse05.vme).
    **     <arg4> = #-counters in Ober-bank (dflt=117).
    **     <arg5> = name of hostU (Unter-bank) (dflt=lnse06.vme).
    **     <arg6> = #-counters in Unter-bank (dflt=116).
    **     <arg7> = Client-side TCP/IP port number (dflt=2500).
    **     <arg8> = Server-side TCP/IP port number (dflt=2400).
    **
    **    In addition, <arg10> will be set to 0 for "sp" and 1 for
    **    "sps". SinqHM_srv, lwl_server and SinqHM_bootUtil will suspend
    **    themselves immediately if they find <arg10> is non-zero. This
    **    cooperation on the part of the spawned task is intended as a
    **    debugging aid.
    **
    **    "SinqHM" and "SinqHM_bootUtil" will be spawned with priority
    **    100, "lwl" with priority 250.
    **
    **  Notes:
    **    a) Lower numbers imply higher priority.
    **    b) "SinqHM_Filler" also gets spawned with priority 250. It is
    **          important that "lwl" and "SinqHM_Filler" have the same
    **          priority.
    **----------------------------------------------------
    **  If <action> = "cfg":
    **     <arg0> = HM_DIG, HM_PSD, TOF, HRPT or TRANS to specify the
    **                      hist memory mode.
    **     <arg8> = sub-mode bits to "or" with <arg0> (dflt=0)
    **     <arg9> = TCP/IP port # of server (dflt=2400)
    **    And for <arg0> = HM_DIG or HRPT,
    **     <arg1> = # bins (no dflt)
    **     <arg2> = # histograms (dflt=1)
    **     <arg3> = bytes per bin (dflt=4)
    **     <arg4> = bin compression (dflt=0)
    **     <arg5> = first bin (dflt=0)
    **
    **    And for <arg0> = TOF,
    **     <arg1> = # counters (no dflt)
    **     <arg2> = # bins per counter (no dflt)
    **     <arg3> = time_span_per_bin (no dflt)
    **     <arg4> = Start delay (dflt=0)
    **     <arg5> = # of first counter (dflt=0)
    **     <arg6> = bytes per bin (dflt=4)
    **
    **     Note: The built-in "cfg" program can only define bins of equal
    **          width. For non-equal width bins, one must send the
    **          SQHM_CONFIG message to SinqHM_srv from a host computer.
    **
    **    And for <arg0> = TRANS,
    **     <arg1> = #-buffers (dflt = 8)
    **     <arg2> = buff-size (dflt = 4096)
    **
    **    And for <arg0> = HM_PSD, the arguments still need defining.
    **----------------------------------------------------
    **  If <action> = "wt", then
    **
    **     <arg0> = number of seconds to wait (may be useful for
    **                FOCUS startup).
    **----------------------------------------------------
    **  For example:
    **
    **     other = "sp=bootUtil/sp=SinqHM/cfg=HM_DIG,400"
    **
    **  will cause bootUtil and SinqHM_srv to be automatically started
    **  after the system has been booted and will configure it in HM_DIG
    **  mode with a single histogram of 400 bins (as used for DMC).
    **----------------------------------------------------
    */
/*
**  Communication with SinqHM_srv is via TCP/IP protocol.
**
**  To compile and link this program for VxWorks on PSS123, use:
**
	    set src = "lnsa09:ud0:[maden.pss123.wind.sinqhm]"
	    rcp "${src}SinqHM_bootParamsConfig.c" SinqHM_bootParamsConfig.c
	    ccvx -I${WIND_BASE}/target/config/all SinqHM_bootParamsConfig.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

**  and, on the target,
**
**   -> ld < /home/pss123/aco/maden/wind/SinqHM/SinqHM_bootParamsConfig.o
**   -> taskSpawn "hmConfig", 100, 8, 20000, SinqHM_bootParamsConfig, <port>
**									^
**									|
**		    TCP/IP port number of SinqHM_srv, e.g. 2400 --------+
**
**====================================================================
*/
#include    "vxWorks.h"			/* always first */
#include    "taskLib.h"
#include    "sockLib.h"
#include    "bootLib.h"
#include    "ioLib.h"

#ifdef MV2600
#include "../config/mv2604/config.h"
#elif MEN_A012
#include "../config/men_824x_ali/config.h"
#else
#if (CPU == PPC603)
#include    "../config/mv1603/config.h"
#elif (CPU == PPC604)
#include    "../config/mv1604/config.h"
#endif
#endif

#include    <stdlib.h>
#include    <stdio.h>
#include    <string.h>
#include    <ctype.h>
#include    <unistd.h>
#include    <errno.h>
#include    <netinet/in.h>
#include    <arpa/inet.h>
#include    <sys/types.h>
#include    <sys/socket.h>
/*
**====================	Global Definitions =====================================
*/
#include    "SinqHM_def.h"


#define	    MAX_ACTIONS	    8
#define	    MAX_ARGS	   10
#define	    NIL		   '\0'
/*
**====================	Global Variables =====================================
*/
  extern uint	Port_base;	/* The base port of SinqHM_srv */
/*
**=============================================================================
**  Local routine prototypes.
*/
    int		sbpc_config (int mode,
			char *a1, char *a2, char *a3,
			char *a4, char *a5, char *a6,
			char *a7, char *a8, char *a9);
    int		sbpc_doAction (char *action);
    void	sbpc_failInet (char *text);
    void	sbpc_getErrno (int *his_errno);
    int		sbpc_spawnBootUtil (int spnd_flg,
			char *a1, char *a2, char *a3, char *a4);
    int		sbpc_spawnFocus (int spnd_flg,
			char *a1, char *a2, char *a3,
			char *a4, char *a5, char *a6,
			char *a7, char *a8);
    int		sbpc_spawnLwl (int spnd_flg,
			char *a1, char *a2, char *a3, char *a4);
    int		sbpc_spawnSinqHM (int spnd_flg,
			char *a1, char *a2, char *a3, char *a4);
    void	sbpc_showHelp (char *errmsg);
/*
**--------------------------------------------------------------------------*/
  int  sbpc_config (
/*     ===========
*/			int	mode,
			char   *p_arg1,
			char   *p_arg2,
			char   *p_arg3,
			char   *p_arg4,
			char   *p_arg5,
			char   *p_arg6,
			char   *p_arg7,
			char   *p_arg8,
			char   *p_arg9) {
    char	errmsg[128];
    int		i, port, sub_mode;
    int		nbins, nhists, ncntrs, bytes_per_bin, compress;
    int		lo_bin, lo_cntr, span, delay, status, my_errno;
    int         xSize, xOff, xFac, ySize, yOff, yFac;
    int		hm_mode, nbuffs, nbytes;

    int		bytes_to_come, skt;
    char	*nxt_byte;

    struct sockaddr_in	lcl_sockname;
    struct sockaddr_in	rmt_sockname;
    int			rmt_sockname_len;


    struct req_buff_struct	    req_buff;
    struct rply_buff_struct	    rply_buff;
	/*-----------------------------------------------------------------
	*/
    printf ("Configuring SinqHM_srv ...\n");

    if (p_arg9 == NULL) {
      port = 2400;
    }else {
      if ((sscanf (p_arg9, "%i", &port) != 1) ||
	  (port < 128) ||
	  (port > 32767)) {
	sprintf (errmsg, "The value for <port>, \"%s\", is illegal!\n", p_arg9);
	sbpc_showHelp (errmsg);
	return False;
      }
    }

    if (p_arg8 == NULL) {
      sub_mode = 0;
    }else {
      if ((sscanf (p_arg8, "%i", &sub_mode) != 1) ||
	  ((sub_mode & (~SQHM__SUB_MODE_MSK)) != 0)) {
	sprintf (errmsg, "The value for <sub-mode>, \"%s\", is illegal!\n",
			p_arg8);
	sbpc_showHelp (errmsg);
	return False;
      }
    }
	/*-----------------------------------------------------------------
	**  If mode is SQHM__HM_DIG, the 5 args should be <#-bins>,
	**						  <#-hists>,
	**						  <bytes-per-bin>,
	**						  <compress> and
	**						  <lo-bin>.
	**
	**  If mode is SQHM__TOF, the 6 args should be	<#-cntrs>,
	**						<#-bins>,
	**						<bin-span>,
	**						<start-delay>,
	**						<lo_cntr> and
	**						<bytes-per-bin>.
	**
	**  If mode is SQHM__TRANS, no arguments are used.
	**
	**  Mode SQHM__HM_PSD, is not yet supported.
	**
	**  If mode is SQHM__HRPT, the 5 args should be <#-bins>,
	**						  <#-hists>,
	**						  <bytes-per-bin>,
	**						  <compress> and
	**						  <lo-bin>.
	*/
    hm_mode = mode | sub_mode;

    if ((mode == SQHM__HM_DIG) || (mode == SQHM__HRPT)) {
					/*---------- <#-bins> */
      if (p_arg1 == NULL) {
	sbpc_showHelp ("No value specified for <#-bins>. No default allowed!");
	return False;
      }else {
	if ((sscanf (p_arg1, "%i", &nbins) != 1) || (nbins <= 0)) {
	  sprintf (errmsg, "The value for <#-nbins>, \"%s\", is illegal!\n"
			 "It must be a positive integer.", p_arg1);
	  sbpc_showHelp (errmsg);
	  return False;
	}
      }
					/*---------- <#-hists> */
      if (p_arg2 == NULL) p_arg2 = "1";
      i = sscanf (p_arg2, "%i", &nhists);
      if ((i != 1) || (nhists <= 0)) {
	sprintf (errmsg, "The value for <#-hists>, \"%s\", is illegal!\n"
			 "It must be a positive integer.", p_arg2);
	sbpc_showHelp (errmsg);
	return False;
      }
					/*---------- <bytes-per-bin> */
      if (p_arg3 == NULL) p_arg3 = "4";
      i = sscanf (p_arg3, "%i", &bytes_per_bin);
      if ((i != 1) ||
	  ((bytes_per_bin != 1) &&
	   (bytes_per_bin != 2) &&
	   (bytes_per_bin != 4))) {
	sprintf (errmsg, "The value for <bytes-per-bin>, \"%s\", is illegal!\n"
			 "It must be 1, 2 or 4.", p_arg3);
	sbpc_showHelp (errmsg);
	return False;
      }
					/*---------- <compress> */
      if (p_arg4 == NULL) p_arg4 = "0";
      if ((sscanf (p_arg4, "%i", &compress) != 1) || (compress < 0)) {
	sprintf (errmsg, "The value for <compress>, \"%s\", is illegal!\n"
			 "It must be a non-negative integer.", p_arg4);
	sbpc_showHelp (errmsg);
	return False;
      }
					/*---------- <lo-bin> */
      if (p_arg5 == NULL) p_arg5 = "0";
      if ((sscanf (p_arg5, "%i", &lo_bin) != 1) || (lo_bin < 0)) {
	sprintf (errmsg, "The value for <lo-bin>, \"%s\", is illegal!\n"
		    "It must be a non-negative integer.", p_arg5);
	sbpc_showHelp (errmsg);
	return False;
      }
      if (mode == SQHM__HM_DIG) {
	printf ("    Histogramming mode           = SQHM__HM_DIG\n");
      }else if (mode == SQHM__HRPT) {
	printf ("    Histogramming mode           = SQHM__HRPT\n");
	hm_mode = SQHM__HRPT | SQHM__REFLECT;	/* Force histogram reflection */
      }
      printf ("    Number of bins per histogram = %d\n", nbins);
      printf ("    Number of histograms         = %d\n", nhists);
      printf ("    Number of bytes per bin      = %d\n", bytes_per_bin);
      printf ("    Bin compression factor       = %d\n", compress);
      printf ("    First bin                    = %d\n", lo_bin);
      if ((hm_mode & SQHM__REFLECT) != 0)
	printf ("    Histogram reflection requested\n");
    }else if (mode == SQHM__HM_PSD) {  /* xSize*/
	if ((sscanf (p_arg1, "%i", &xSize) != 1) || (xSize <= 0)) {
	  sprintf (errmsg, "The value for <#-xSize>, \"%s\", is illegal!\n"
			 "It must be a positive integer.", p_arg1);
	  sbpc_showHelp (errmsg);
	  return False;
	}                            /* xOff*/
	if ((sscanf (p_arg2, "%i", &xOff) != 1)) {
	  sprintf (errmsg, "The value for <#-xOff>, \"%s\", is illegal!\n"
			 "It must be a positive integer.", p_arg1);
	  sbpc_showHelp (errmsg);
	  return False;
	}                           /* xFac */
	if ((sscanf (p_arg3, "%i", &xFac) != 1)|| xFac <= 0) {
	  sprintf (errmsg, "The value for <#-xFac>, \"%s\", is illegal!\n"
			 "It must be a positive integer.", p_arg1);
	  sbpc_showHelp (errmsg);
	  return False;
	}
	                           /* ySize */
	if ((sscanf (p_arg4, "%i", &ySize) != 1) || (ySize <= 0)) {
	  sprintf (errmsg, "The value for <#-ySize>, \"%s\", is illegal!\n"
			 "It must be a positive integer.", p_arg1);
	  sbpc_showHelp (errmsg);
	  return False;
	}                         /* yOff*/
	if ((sscanf (p_arg5, "%i", &yOff) != 1)) {
	  sprintf (errmsg, "The value for <#-yOff>, \"%s\", is illegal!\n"
			 "It must be a positive integer.", p_arg1);
	  sbpc_showHelp (errmsg);
	  return False;
	}                        /* yFac */
	if ((sscanf (p_arg6, "%i", &yFac) != 1) || (yFac <= 0)) {
	  sprintf (errmsg, "The value for <#-yFac>, \"%s\", is illegal!\n"
			 "It must be a positive integer.", p_arg1);
	  sbpc_showHelp (errmsg);
	  return False;
	}
        printf("\tHistogramming Mode  = SINQHM_PSD\n");
        printf("\txSize, xOff, yFac = %5d, %5d, %5d\n",xSize, xOff, xFac);
        printf("\tySize, yOff, yFac = %5d, %5d, %5d\n",ySize, yOff, yFac);
    }else if (mode == SQHM__TOF) {
					/*---------- <#-cntrs> */
      if (p_arg1 == NULL) {
	sbpc_showHelp ("No value specified for <#-cntrs>. No default allowed!");
	return False;
      }else {
	if ((sscanf (p_arg1, "%i", &ncntrs) != 1) || (ncntrs <= 0)) {
	  sprintf (errmsg, "The value for <#-ncntrs>, \"%s\", is illegal!\n"
			 "It must be a positive integer.", p_arg1);
	  sbpc_showHelp (errmsg);
	  return False;
	}
      }
					/*---------- <#-bins> */
      if (p_arg2 == NULL) {
	sbpc_showHelp ("No value specified for <#-bins>. No default allowed!");
	return False;
      }else {
	if ((sscanf (p_arg2, "%i", &nbins) != 1) || (nbins <= 0)) {
	  sprintf (errmsg, "The value for <#-nbins>, \"%s\", is illegal!\n"
			 "It must be a positive integer.", p_arg2);
	  sbpc_showHelp (errmsg);
	  return False;
	}
      }
					/*---------- <bin-span> */
      if (p_arg3 == NULL) {
	sbpc_showHelp ("No value specified for <bin-span>. No default allowed!");
	return False;
      }else {
	if ((sscanf (p_arg3, "%i", &span) != 1) || (span <= 0)) {
	  sprintf (errmsg, "The value for <bin-span>, \"%s\", is illegal!\n"
			 "It must be a positive integer.", p_arg3);
	  sbpc_showHelp (errmsg);
	  return False;
	}
      }
					/*---------- <start-delay> */
      if (p_arg4 == NULL) p_arg4 = "0";
      if ((sscanf (p_arg4, "%i", &delay) != 1) || (delay < 0)) {
	sprintf (errmsg, "The value for <start-delay>, \"%s\", is illegal!\n"
			 "It must be a non-negative integer.", p_arg4);
	sbpc_showHelp (errmsg);
	return False;
      }
					/*---------- <lo-cntr> */
      if (p_arg5 == NULL) p_arg5 = "0";
      if ((sscanf (p_arg5, "%i", &lo_cntr) != 1) || (lo_cntr < 0)) {
	sprintf (errmsg, "The value for <lo-cntr>, \"%s\", is illegal!\n"
		    "It must be a non-negative integer.", p_arg5);
	sbpc_showHelp (errmsg);
	return False;
      }
					/*---------- <bytes-per-bin> */
      if (p_arg6 == NULL) p_arg6 = "4";
      i = sscanf (p_arg6, "%i", &bytes_per_bin);
      if ((i != 1) ||
	  ((bytes_per_bin != 1) &&
	   (bytes_per_bin != 2) &&
	   (bytes_per_bin != 4))) {
	sprintf (errmsg, "The value for <bytes-per-bin>, \"%s\", is illegal!\n"
			 "It must be 1, 2 or 4.", p_arg6);
	sbpc_showHelp (errmsg);
	return False;
      }
      printf ("    Histogramming mode           = SQHM__TOF\n");
      printf ("    Number of counters           = %d\n", ncntrs);
      printf ("    Number of bins per counter   = %d\n", nbins);
      printf ("    Bin span                     = %d\n", span);
      printf ("    Start delay                  = %d\n", delay);
      printf ("    First counter                = %d\n", lo_cntr);
      printf ("    Number of bytes per bin      = %d\n", bytes_per_bin);
    }else if (mode == SQHM__TRANS) {
					/*---------- <#-buffers> */
      if (p_arg1 == NULL) p_arg1 = "8";
      if ((sscanf (p_arg1, "%i", &nbuffs) != 1) || (nbuffs <= 0)) {
	sprintf (errmsg, "The value for <#-buffers>, \"%s\", is illegal!\n"
			 "It must be a positive integer.", p_arg1);
	sbpc_showHelp (errmsg);
	return False;
      }
					/*---------- <#-bins> */
      if (p_arg2 == NULL) p_arg2 = "4096";
      if ((sscanf (p_arg2, "%i", &nbytes) != 1) || (nbytes <= 0)) {
	sprintf (errmsg, "The value for <buff-size>, \"%s\", is illegal!\n"
			 "It must be a positive integer.", p_arg2);
	sbpc_showHelp (errmsg);
	return False;
      }
      printf ("    Histogramming mode           = SQHM__TRANS\n");
      nbuffs = 8;
      nbytes = 4096;
      printf ("    Number buffers = %d\n", nbuffs);
      printf ("    Buffer size    = %d bytes\n", nbytes);
    }
    printf ("\nConnecting to SinqHM_srv via TCP/IP port %d ...\n", port);
/*============================================================================
**  	   Create a TCP/IP socket for connecting to SinqHM_srv root and bind it.
*/
    skt = socket (AF_INET, SOCK_STREAM, 0);
    if (skt == -1) sbpc_failInet ("\nSocket error.");

    lcl_sockname.sin_family = AF_INET;
    lcl_sockname.sin_port   = htons (0);
    lcl_sockname.sin_addr.s_addr = 0;
    status = bind (skt, (struct sockaddr *) &lcl_sockname,
					sizeof (lcl_sockname));
    if (status == -1) sbpc_failInet ("\nBind error.");
/*============================================================================
**		Connect to SinqHM_srv root.
*/
    rmt_sockname_len = sizeof (rmt_sockname);
    rmt_sockname.sin_family	 = AF_INET;
    rmt_sockname.sin_port	 = htons (port);
    rmt_sockname.sin_addr.s_addr = 0;		/* Connect to local machine */
    status = connect (skt, (struct sockaddr *) &rmt_sockname,
				    sizeof (rmt_sockname));
    if (status == -1) {
      sbpc_getErrno (&my_errno);
      sbpc_failInet ("\nConnect error");
    }
/*============================================================================
**		    Set up and send the configure message.
*/
    req_buff.bigend	 = htonl (0x12345678);
    req_buff.cmnd	 = htonl (SQHM_CONFIG);
    req_buff.u.cnfg.mode = htonl (hm_mode);

    if ((mode == SQHM__HM_DIG) || (mode == SQHM__HRPT)) {
      req_buff.u.cnfg.u.hm_dig.n_hists	     = htonl (nhists);
      req_buff.u.cnfg.u.hm_dig.lo_bin	     = htonl (lo_bin);
      req_buff.u.cnfg.u.hm_dig.num_bins	     = htonl (nbins);
      req_buff.u.cnfg.u.hm_dig.bytes_per_bin = htonl (bytes_per_bin);
      req_buff.u.cnfg.u.hm_dig.compress	     = htonl (compress);
    }else if (mode == SQHM__HM_PSD) {
      req_buff.u.cnfg.u.psd.n_extra_bytes = htonl (0);
      req_buff.u.cnfg.u.psd.n_edges	  = htons (1);
      req_buff.u.cnfg.u.psd.n_banks	  = htons (1);
      req_buff.u.cnfg.u.psd.xOffset	  = htonl (xOff);
      req_buff.u.cnfg.u.psd.yOffset	  = htonl (yOff);
      req_buff.u.cnfg.u.psd.xFactor	  = htonl (xFac);
      req_buff.u.cnfg.u.psd.yFactor	  = htonl (yFac);
      req_buff.u.cnfg.u.psd.xSize	  = htons (xSize);
      req_buff.u.cnfg.u.psd.ySize	  = htons (ySize);


      req_buff.u.cnfg.u.psd.edge_0.n_bins   = htonl (1);
      req_buff.u.cnfg.u.psd.edge_0.flag     = htonl (0);    /* Fixed bin span */

      req_buff.u.cnfg.u.psd.edge_0.edges[0] = htonl (0);
      req_buff.u.cnfg.u.psd.edge_0.edges[1] = htonl (10000);
      req_buff.u.cnfg.u.psd.preset_delay    = htonl (0);

      req_buff.u.cnfg.u.psd.bank_0.first         = htons (0);
      req_buff.u.cnfg.u.psd.bank_0.n_cntrs       = htons (xSize*ySize);
      req_buff.u.cnfg.u.psd.bank_0.edge_indx	 = htons (0);
      req_buff.u.cnfg.u.psd.bank_0.bytes_per_bin = htons (4);

    }else if (mode == SQHM__TOF) {
      req_buff.u.cnfg.u.tof.n_extra_bytes = htonl (0);
      req_buff.u.cnfg.u.tof.n_edges	  = htons (1);
      req_buff.u.cnfg.u.tof.n_banks	  = htons (1);

      req_buff.u.cnfg.u.tof.edge_0.n_bins   = htonl (nbins);
      req_buff.u.cnfg.u.tof.edge_0.flag	    = htonl (0);
      req_buff.u.cnfg.u.tof.edge_0.edges[0] = htonl (0);
      req_buff.u.cnfg.u.tof.edge_0.edges[1] = htonl (span);
      req_buff.u.cnfg.u.tof.preset_delay    = htonl (delay);

      req_buff.u.cnfg.u.tof.bank_0.first	 = htons (lo_cntr);
      req_buff.u.cnfg.u.tof.bank_0.n_cntrs	 = htons (ncntrs);
      req_buff.u.cnfg.u.tof.bank_0.edge_indx	 = htons (0);
      req_buff.u.cnfg.u.tof.bank_0.bytes_per_bin = htons (bytes_per_bin);
    }else if (mode == SQHM__TRANS) {
      req_buff.u.cnfg.u.trans.n_buffs = htonl (nbuffs);
      req_buff.u.cnfg.u.trans.n_bytes = htonl (nbytes);
    }

    status = send (skt, (char *) &req_buff, sizeof (req_buff), 0);
    if (status == -1) sbpc_failInet ("\nSend error");
    if (status != sizeof (req_buff)) {
      printf ("\nWrong number of bytes sent: %d", status);
      close (skt);
      return False;
    }
/*============================================================================
**		    Wait for the status response.
*/
    bytes_to_come = sizeof (rply_buff);
    nxt_byte = (char *) &rply_buff;
    while (bytes_to_come > 0) {
      status = recv (skt, nxt_byte, bytes_to_come, 0);
      if (status == -1) {
	sbpc_failInet ("\nRecv error");
	close (skt);
	return False;
      } else if (status <= 0) {
	printf ("Recv error - unexpected byte count: %d/%d\n",
		    sizeof (rply_buff), status);
	close (skt);
	return False;
      }
      bytes_to_come = bytes_to_come - status;
      nxt_byte = nxt_byte + status;
    }
    if (ntohl (rply_buff.bigend) != 0x12345678) {
      printf ("Big-endian/little-endian problem!\n"
	      "    Buffer received in non-network byte order!\n");
      close (skt);
      return False;
    }
    status = ntohl (rply_buff.status);
    if (status != KER__SUCCESS) {
      if (status == KER__BAD_CREATE) {
	printf ("Status response is KER__BAD_CREATE\n");
	printf (" Sub-status = %d\n", ntohl (rply_buff.sub_status));
      }else if (status == KER__BAD_STATE) {
	printf ("Status response is KER__BAD_STATE\n");
      }else if (status == KER__BAD_VALUE) {
	printf ("Status response is KER__BAD_VALUE\n");
      }else if (status == KER__BAD_RECV) {
	printf ("Status response is KER__BAD_RECV\n");
      }else if (status == KER__BAD_ALLOC) {
	printf ("Status response is KER__BAD_ALLOC\n");
      }else {
	printf ("Bad and unrecognised status response: 0x%x\n", status);
      }
      if (rply_buff.u.message[0] != '\0') {
	printf (" Message = \"%s\"\n", &rply_buff.u.message[0]);
      }
      close (skt);
      return False;
    }
/*
**		Close the connection.
*/
    status = close (skt);
    if ((status != 0) && (errno != ECONNRESET))
	    sbpc_failInet ("\nClose error");
    taskDelay (1 * sysClkRateGet ());	    /* Wait for 1 second to let ..
					    ** .. SinqHM_srv to do its printing.
					    */
    printf ("\nSinqHM_srv has been configured.\n");
    return 1;
  }
/*
**--------------------------------------------------------------------------*/
  int  sbpc_doAction (char *action) {
/*     =============
*/
    int			i, j, a_len, n_args, status, spnd_flg;
    char		errmsg[100];
    char	       *p_verb, *p_arg[MAX_ARGS], *p_nxt;

    for (i = 0; action[i] != '\0'; i++) action[i] = tolower (action[i]);
    for (i = 0; i < MAX_ARGS; i++) p_arg[i] = NULL;

    a_len = strlen (action);
    p_verb = strtok (action, "=");	    /* Get the action verb */

    n_args = 0;
    for (i = 0; i < MAX_ARGS; i++) p_arg[i] = NULL;
		    /*
		    ** Now loop to get the args.
		    ** Note:
		    **  The loop does not use strtok since it wants to
		    **  allow null arguments, i.e. adjacent commas may be
		    **  used to indicate default args. This is not possible
		    **  if one uses strtok.
		    */
    p_nxt = p_verb + strlen (p_verb) + 1;   /* Get addr of start of args */
    while ((n_args < MAX_ARGS) &&
	   ((p_nxt - action) < a_len)) {
      p_arg[n_args] = p_nxt;
      n_args++;
      i = strcspn (p_nxt, ",");	    /* Find next comma (or end of string) */
      p_nxt[i] = NIL;		    /* Change it to a NIL */
      p_nxt = p_nxt + i + 1;	    /* Move to next argement */
    }

    if ((strcmp (p_verb, "sp") == 0) || (strcmp (p_verb, "sps") == 0)) {
      spnd_flg = 0;
      spnd_flg = (strcmp (p_verb, "sps") == 0) ? 1 : 0;
      if (n_args == 0) {
        sbpc_showHelp ("\"sp\" action has no arguments!");
	return False;
      }else if (strcmp (p_arg[0], "bootutil") == 0) {
	status = sbpc_spawnBootUtil (spnd_flg,
			    p_arg[1], p_arg[2], p_arg[3], p_arg[4]);
	if (!status) return status;
      }else if (strcmp (p_arg[0], "focus") == 0) {
	status = sbpc_spawnFocus (spnd_flg,
			    p_arg[1], p_arg[2], p_arg[3], p_arg[4],
			    p_arg[5], p_arg[6], p_arg[7], p_arg[8]);
	if (!status) return status;
      }else if (strcmp (p_arg[0], "lwl") == 0) {
	status = sbpc_spawnLwl (spnd_flg,
			    p_arg[1], p_arg[2], p_arg[3], p_arg[4]);
	if (!status) return status;
      }else if (strcmp (p_arg[0], "sinqhm") == 0) {
	status = sbpc_spawnSinqHM (spnd_flg,
			    p_arg[1], p_arg[2], p_arg[3], p_arg[4]);
	if (!status) return status;
      }else {
	sprintf (errmsg, "\"%s\" is an unrecognised thing to spawn!\n",
			    p_arg[0]);
	sbpc_showHelp (errmsg);
	return False;
      }
    }else if (strcmp (p_verb, "cfg") == 0) {
      if (n_args == 0) {
        sbpc_showHelp ("\"cfg\" action has no arguments!");
	return False;
      }else if (strcmp (p_arg[0], "hm_dig") == 0) {
	status = sbpc_config (SQHM__HM_DIG,
		    p_arg[1], p_arg[2], p_arg[3], p_arg[4], p_arg[5],
		    p_arg[6], p_arg[7], p_arg[8], p_arg[9]);
	if (!status) return status;
      }else if (strcmp (p_arg[0], "tof") == 0) {
	status = sbpc_config (SQHM__TOF,
		    p_arg[1], p_arg[2], p_arg[3], p_arg[4], p_arg[5],
		    p_arg[6], p_arg[7], p_arg[8], p_arg[9]);
	if (!status) return status;
      }else if (strcmp (p_arg[0], "hm_psd") == 0) {
	status = sbpc_config (SQHM__HM_PSD,
		    p_arg[1], p_arg[2], p_arg[3], p_arg[4], p_arg[5],
		    p_arg[6], p_arg[7], p_arg[8], p_arg[9]);
	if (!status) return status;
      }else if (strcmp (p_arg[0], "hrpt") == 0) {
	status = sbpc_config (SQHM__HRPT,
		    p_arg[1], p_arg[2], p_arg[3], p_arg[4], p_arg[5],
		    p_arg[6], p_arg[7], p_arg[8], p_arg[9]);
	if (!status) return status;
      }else if (strcmp (p_arg[0], "trans") == 0) {
	status = sbpc_config (SQHM__TRANS,
		    p_arg[1], p_arg[2], p_arg[3], p_arg[4], p_arg[5],
		    p_arg[6], p_arg[7], p_arg[8], p_arg[9]);
	if (!status) return status;
      }else {
	sprintf (errmsg, "\"%s\" is an unrecognised thing to configure!\n",
			    p_arg[0]);
	sbpc_showHelp (errmsg);
	return False;
      }
    }else if (strcmp (p_verb, "wt") == 0) {
      if (n_args == 0) {
        sbpc_showHelp ("\"wt\" action has no arguments!");
	return False;
      }else if ((sscanf (p_arg[0], "%i", &i) != 1) ||
		(i <= 0) || (i > 300)) {
	sprintf (errmsg, "The value for <wt>, \"%s\", is illegal!\n", p_arg[0]);
	sbpc_showHelp (errmsg);
	return False;
      }
      printf ("Waiting for %d secs ", i);
      for (j = 0; j < i; j++) {
	taskDelay (1 * sysClkRateGet ());	    /* Wait as requested .. */
	printf (".");
      }
      printf ("\n");
    }else {
      sprintf (errmsg, "\"%s\" is an unrecognised action!\n", p_verb);
      sbpc_showHelp (errmsg);
      return False;
    }
    return True;
  }
/*
**--------------------------------------------------------------------------*/
  void sbpc_failInet (char *text) {
/*     =============
**		    Output the given text and exit the process.
*/
    int    my_errno;

    sbpc_getErrno (&my_errno);
    printf ("### Internet Error ###\n");
    printf ("                   ### errno = %d.\n", my_errno);
    perror (text);
    exit (EXIT_FAILURE);
  }
/*--------------------------------------------------------------------------*/
  void	sbpc_getErrno (int *his_errno) {
/*      =============
*/
    *his_errno = errno;	    /* Make copy of errno   */
    return;
  }
/*
**--------------------------------------------------------------------------*/
  void	sbpc_showHelp (char *errmsg) {
/*      =============
*/
    if (errmsg != NULL) {
      printf ("\007\n%s\n", errmsg);
      taskDelay (5 * sysClkRateGet ());	    /* Give user time to read message */
    }
    printf ("\n"
 "The \"other\" field may be specified as follows:\n"
 "\n"
 "        <action>=<arg0>,..,<argn>/<action>=...\n"
 "\n"
 "There must be no white space characters in the string. The string may\n"
 "be specified in upper or lower case.\n"
 "\n"
 "<action> may be \"sp\"  for \"spawn a task\" or\n"
 "                \"sps\" for \"spawn and suspend a task\" or\n"
 "                \"cfg\" for \"configure SinqHM_srv (or FOCUS_srv)\"\n"
 "\n"
 "The following \"sp\" (or \"sps\") commands are available:\n"
 "\n"
 "  a)        sp=SinqHM,<port>,<use-lev-gen>,<VMIO10-base>\n"
 "     where\n"
 "          <port>        = TCP/IP port number for server. Dflt=2400.\n"
 "          <use-lev-gen> = flag to indicate if timing levels should be\n"
 "                            generated via a VMIO10 module. If non-zero,\n"
 "                            timing levels are generated. Dflt=0.\n"
 "          <VMIO10-base> = base address of VMIO10 level-generator\n"
 "                            module. Dflt=0x1900.\n"
 "     This action spawns the SinqHM histogram memory server task.\n"
 "\n"
 "  b)        sp=lwl,<port>,<VMIO10-base>,<verbosity>\n"
 "     where\n"
 "          <port>        = TCP/IP port number for server. Dflt=3501.\n"
 "          <VMIO10-base> = base address of VMIO10 test-generator\n"
 "                            module. Dflt=0x1800.\n"
 "          <verbosity>   = verbosity flag. If non-zero, the program is\n"
 "                            verbose. Dflt=0.\n"
 "     This action spawns the lwl_server task which can be used to feed\n"
 "     data packets into the hist memory fibre-optic (Licht-Wellen-Leiter)\n"
 "     link via a VMIO10 test-generator. If the test generator is absent,\n"
 "     the action can be omitted to avoid a boot-time error message.\n"
 "\n"
 "  c)        sp=bootUtil,<port>\n"
 "     where\n"
 "          <port>        = TCP/IP port number for server. Dflt=2300.\n"
 "\n"
 "The following \"cfg\" commands are available:\n"
 "\n"
 "  a)        cfg=HM_DIG,<#-bins>,<#-hists>,<bin-width>,<compress>,<lo-bin>\n"
 "     where\n"
 "          <#-bins>    = number of bins per histogram. No default.\n"
 "          <#-hists>   = number of defined histograms. Dflt=1.\n"
 "          <bin-width> = Number of bytes per bin. Dflt=4.\n"
 "          <compress>  = Bin compression factor. Dflt=1.\n"
 "          <lo-bin>    = First bin. Dflt=0.\n"
 "\n"
 "  b)        cfg=TOF,<#-bins>,<#-cntrs>,<bin-width>,<compress>,<lo-cntr>\n"
 "     where\n"
 "          <#-bins>    = number of bins per histogram. No default.\n"
 "          <#-cntrs>   = number of neutron counters. No default.\n"
 "          <bin-width> = Number of bytes per bin. Dflt=4.\n"
 "          <compress>  = Bin compression factor. Dflt=1.\n"
 "          <lo-cntr>   = # of first counter. Dflt=0.\n"
 "\n"
 "  c)        cfg=HM_PSD,... same arguments as HM_DIG (for now).\n"
 "\n"
 "For example:\n"
 "       other=\"sp=SinqHM/cfg=HM_DIG,400\"\n"
 "\n");
  }
/*
**--------------------------------------------------------------------------*/
  int	sbpc_spawnBootUtil (
/*	==================
*/		int   spnd_flg,	/* Suspend flag (arg10) */
		char *p_arg1,	/* TCP/IP port number. Dflt = 2300 */
		char *p_arg2,	/* Not used */
		char *p_arg3,	/* Not used */
		char *p_arg4) {	/* Not used */

    int		port;
    int		status;

    void SinqHM_bootUtil (void);    /* Define template for SinqHM_bootUtil */

    if (p_arg1 == NULL) {
      port = 2300;
    }else if (p_arg1[0] == NIL) {
      port = 2300;
    }else {
      if (sscanf (p_arg1, "%i", &port) != 1) {
	printf ("bootUtil has not been spawned: invalid argument \"%s\"\n",
				p_arg1);
	return False;
      }
      if (port <= 0) port = 2300;
    }

    printf ("Spawning bootUtil ..\n    TCP/IP port = %d.\n", port);
    status = taskSpawn ("bootUtil", 100, VX_FP_TASK, 20000,
			(FUNCPTR) SinqHM_bootUtil,
			port, 0, 0, 0, 0, 0, 0, 0, 0,
			spnd_flg);
    if (status == ERROR) {
      printf ("\007\nSpawn of SinqHM_bootUtil failed!\n\n");
      return False;
    }
    taskDelay (1 * sysClkRateGet ());	/* Give bootUtil time to get going */
    return True;
  }
/*
**--------------------------------------------------------------------------*/
  int	sbpc_spawnFocus (
/*	===============
*/		int   spnd_flg,	/* Suspend flag (arg10) */
		char *p_arg1,	/* hostM */
		char *p_arg2,	/* #-cntrs for hostM */
		char *p_arg3,	/* hostO */
		char *p_arg4,	/* #-cntrs for hostO */
		char *p_arg5,	/* hostU */
		char *p_arg6,	/* #-cntrs for hostU */
		char *p_arg7,	/* Client side port number */
		char *p_arg8) {	/* Server side port number */

    char	*hostM, *hostO, *hostU;
    int		ndetM, ndetO, ndetU, c_port, s_port;
    int		status;
    char	tsknam[32];
#ifndef FOCUS
    printf ("\n\"/sp=focus\" is only permitted on the FOCUS instrument!\n");
    return False;
#else
    void FOCUS_main (void);	/* Define template for FOCUS_main */

    hostM = (p_arg1 != NULL) ? p_arg1 : "localhost";
    if (hostM[0] == NIL) hostM = "localhost";

    if (p_arg2 == NULL) {
      ndetM = 150;
    }else if (p_arg2[0] == NIL) {
      ndetM = 150;
    }else {
      if ((sscanf (p_arg2, "%i", &ndetM) != 1) ||
	  (ndetM <= 0) ||
	  (ndetM > 1023)) {
	printf ("FOCUS_main has not been spawned: invalid argument \"%s\"\n",
				p_arg2);
	return False;
      }
    }

    hostO = (p_arg3 != NULL) ? p_arg3 : "lnse05.vme";
    if (hostO[0] == NIL) hostO = "lnse05.vme";

    if (p_arg4 == NULL) {
      ndetO = 117;
    }else if (p_arg4[0] == NIL) {
      ndetO = 117;
    }else {
      if ((sscanf (p_arg4, "%i", &ndetO) != 1) ||
	  (ndetO <= 0) ||
	  (ndetO > 1023)) {
	printf ("FOCUS_main has not been spawned: invalid argument \"%s\"\n",
				p_arg4);
	return False;
      }
    }

    hostU = (p_arg5 != NULL) ? p_arg5 : "lnse06.vme";
    if (hostU[0] == NIL) hostU = "lnse06.vme";

    if (p_arg6 == NULL) {
      ndetU = 116;
    }else if (p_arg6[0] == NIL) {
      ndetU = 116;
    }else {
      if ((sscanf (p_arg6, "%i", &ndetU) != 1) ||
	  (ndetU <= 0) ||
	  (ndetU > 1023)) {
	printf ("FOCUS_main has not been spawned: invalid argument \"%s\"\n",
				p_arg6);
	return False;
      }
    }

    if (p_arg7 == NULL) {
      c_port = 2500;
    }else if (p_arg7[0] == NIL) {
      c_port = 2500;
    }else {
      if ((sscanf (p_arg7, "%i", &c_port) != 1) ||
	  (c_port <= 1024) ||
	  (c_port > 65535)) {
	printf ("FOCUS_main has not been spawned: invalid argument \"%s\"\n",
				p_arg7);
	return False;
      }
    }

    if (p_arg8 == NULL) {
      s_port = 2400;
    }else if (p_arg8[0] == NIL) {
      s_port = 2400;
    }else {
      if ((sscanf (p_arg8, "%i", &s_port) != 1) ||
	  (s_port <= 1024) ||
	  (s_port > 65535)) {
	printf ("FOCUS_main has not been spawned: invalid argument \"%s\"\n",
				p_arg8);
	return False;
      }
    }

    printf ("Spawning FOCUS_main ..\n");
    printf ("   Mittel-bank: %3d cntrs, host = \"%s\"\n", ndetM, hostM);
    printf ("   Ober-bank:   %3d cntrs, host = \"%s\"\n", ndetO, hostO);
    printf ("   Unter-bank:  %3d cntrs, host = \"%s\"\n", ndetU, hostU);
    printf ("   Client TCP/IP port = %d.\n", c_port);
    printf ("   Server TCP/IP port = %d.\n", s_port);

    sprintf (tsknam, "Focus%04d", s_port);
    status = taskSpawn (tsknam, 100, VX_FP_TASK, 20000,
			(FUNCPTR) FOCUS_main,
			(long int) hostM, ndetM,
			(long int) hostO, ndetO,
			(long int) hostU, ndetU,
			c_port, s_port, 0,
			spnd_flg);
    if (status == ERROR) {
      printf ("\007\nSpawn of FOCUS_main failed!\n\n");
      return False;
    }
    taskDelay (1 * sysClkRateGet ());	/* Give FOCUS_main time to get going */
    return True;
#endif
  }
/*
**--------------------------------------------------------------------------*/
  int	sbpc_spawnLwl (
/*	=============
*/		int   spnd_flg,	/* Suspend flag (arg10) */
		char *p_arg1,	/* TCP/IP port number. Dflt = 3501 */
		char *p_arg2,	/* Base addr of VMIO10 module. Dflt = 0x1800 */
		char *p_arg3,	/* Verbosity. Dflt = 0 */
		char *p_arg4) {	/* Not used */

    int		port, vmio_base, verbosity;
    int		status;

    void lwl_server (void);	/* Define template for lwl_server */

    if (p_arg1 == NULL) {
      port = 3501;
    }else if (p_arg1[0] == NIL) {
      port = 3501;
    }else {
      if ((sscanf (p_arg1, "%i", &port) != 1) || (port < 0)) {
	printf ("lwl_server has not been spawned: invalid argument \"%s\"\n",
				p_arg1);
	return False;
      }
      if (port == 0) port = 3501;
    }

    if (p_arg2 == NULL) {
      vmio_base = 0x1800;
    }else if (p_arg2[0] == NIL) {
      vmio_base = 0x1800;
    }else {
      if (sscanf (p_arg2, "%i", &vmio_base) != 1) {
	printf ("lwl_server has not been spawned: invalid argument \"%s\"\n",
				p_arg2);
	return False;
      }
    }

    if (p_arg3 == NULL) {
      verbosity = 0;
    }else if (p_arg3[0] == NIL) {
      verbosity = 0;
    }else {
      if (sscanf (p_arg3, "%i", &verbosity) != 1) {
	printf ("lwl_server has not been spawned: invalid argument \"%s\"\n",
				p_arg3);
	return False;
      }
    }

    printf ("Spawning lwl_server ..\n    TCP/IP port = %d.\n", port);
    printf ("    VMIO10 base address = 0x%x\n", vmio_base);
    if (verbosity == 0) {
      printf ("    Terse mode.\n");
    }else {
      printf ("    Verbose mode.\n");
    }
	/*
	** Note:    lwlServer must have exactly the same priority as
	** ====	    the Filler task (hmFill2400).
	**
	**	    If the priority of lwlServer is lower that that of Filler,
	**	    then lwlServer will never get to run because Filler only
	**	    relinquishes the CPU via a "taskDelay (0)" and this only
	**	    lets tasks of the same priority as Filler run.
	**
	**	    If the priority of lwlServer is higher that that of Filler,
	**	    it is possible that the Filler gets blocked by lwlServer
	**	    so that the LWL Fifo gets filled up and overflows.
	*/
    status = taskSpawn ("lwlServer", 250, VX_FP_TASK, 20000,
			(FUNCPTR) lwl_server,
			port, vmio_base, verbosity, 0, 0, 0, 0, 0, 0,
			spnd_flg);
    if (status == ERROR) {
      printf ("\007\nSpawn of lwl_Server failed!\n\n");
      return False;
    }
    taskDelay (1 * sysClkRateGet ());	/* Give lwl_server time to get going */
    return True;
  }

/*
**--------------------------------------------------------------------------*/

#ifdef MEN_A012
    extern int Hist_base_MEN_alloc;
#endif
  int	sbpc_spawnSinqHM (
/*	================
*/		int   spnd_flg,	/* Suspend flag (arg10) */
		char *p_arg1,	/* TCP/IP port number. Dflt = 2400 */
		char *p_arg2,	/* Use VMIO10 module if non-zero. Dflt = 0 */
		char *p_arg3,	/* Base addr of VMIO10 module. Dflt = 0x1900 */
		char *p_arg4) {	/* Not used */

    int		port, use_level_gen, vmio_base;
    int		status;
    char	tsknam[32];

    void SinqHM_srv (void);	/* Define template for SinqHM_srv */

    if (p_arg1 == NULL) {
      port = 2400;
    }else if (p_arg1[0] == NIL) {
      port = 2400;
    }else {
      if ((sscanf (p_arg1, "%i", &port) != 1) || (port < 0)) {
	printf ("SinqHM has not been spawned: invalid argument \"%s\"\n",
				p_arg1);
	return False;
      }
      if (port == 0) port = 2400;
    }

    if (p_arg2 == NULL) {
      use_level_gen = 0;
    }else if (p_arg2[0] == NIL) {
      use_level_gen = 0;
    }else {
      if (sscanf (p_arg2, "%i", &use_level_gen) != 1) {
	printf ("SinqHM has not been spawned: invalid argument \"%s\"\n",
				p_arg2);
	return False;
      }
    }
    if (use_level_gen != 0) use_level_gen = 1;

    if (p_arg3 == NULL) {
      vmio_base = 0x1900;
    }else if (p_arg3[0] == NIL) {
      vmio_base = 0x1900;
    }else {
      if (sscanf (p_arg3, "%i", &vmio_base) != 1) {
	printf ("SinqHM has not been spawned: invalid argument \"%s\"\n",
				p_arg3);
	return False;
      }
    }
#ifdef MEN_A012
    /*
      make sure that the memory allocation flag is properly initialized at
      the first time
    */
    Hist_base_MEN_alloc = 0;
#endif

    printf ("Spawning SinqHM_srv ..\n    TCP/IP port = %d.\n", port);
    if (use_level_gen == 0) {
      printf ("    No timing signal generation requested.\n");
    }else {
      printf ("    Timing signal generation requested.\n");
      printf ("    VMIO10 base address = 0x%x\n", vmio_base);
    }

    sprintf (tsknam, "hmRoot%04d", port);
    status = taskSpawn (tsknam, 100, VX_FP_TASK, 20000,
			(FUNCPTR) SinqHM_srv,
			port, use_level_gen, vmio_base, 0, 0, 0, 0, 0, 0,
			spnd_flg);
    if (status == ERROR) {
      printf ("\007\nSpawn of SinqHM_srv failed!\n\n");
      return False;
    }
    taskDelay (1 * sysClkRateGet ());	/* Give SinqHM_srv time to get going */
    return True;
  }
/*
**==============================================================================
**
**  Main line program
**
**============================================================================*/

  int	    SinqHM_bootParamsConfig () {
/*	    =======================
*/
    char	       *local_mem, *p_item;
    BOOT_PARAMS		my_params;

    int			i, n_actions, status;
    char	       *action_token[MAX_ACTIONS];
    char		recd[132];
/*============================================================================
**	Perform the initialisation of variables ...
*/
    local_mem = (char *) BOOT_LINE_ADRS;    /* Get pointer to the boot line */
/*============================================================================
*/
    bootStringToStruct (local_mem, &my_params);    /* Parse boot line */
    		/*
		** Parse the "other" string
		*/
    if (my_params.other[0] == '\0') {
      printf ("\n"
	    "There is no \"other\" field defined in the boot line.\n"
	    "SinqHM_srv will not be automatically configured!\n");
      sbpc_showHelp (NULL);
      return True;
    }
    printf ("\nParsing the \"other\" field defined in the boot line\n\n"
		"      Other = \"%s\"\n\n", my_params.other);
	/*
	** Start by splitting up into "/" terminated strings.
	** These are "actions".
	*/
    n_actions = 0;
    p_item = strtok (my_params.other, "/");
    while ((n_actions < MAX_ACTIONS) && (p_item != NULL)) {
      action_token[n_actions] = p_item;
      n_actions++;
      p_item = strtok (NULL, "/");	      /* Get the next action token */
    }
	/*
	** Now process the actions in order.
	*/
    for (i = 0; i < n_actions; i++) {
      status = sbpc_doAction (action_token[i]);
      if (!status) return status;
    }
    return True;
  }
/*================================= End of SinqHM_bootParamsConfig.c ========*/
