/* **********************************************************************
 * *                                                                    *
 * *            Support Routines for RDA Configuration Files            *
 * *                                                                    *
 * **********************************************************************
 * File: libs/config/rda_limits.c
 *
 *                     COPYRIGHT (c) 2001, 2003  BY
 *          SIGMET INCORPORATED, WESTFORD MASSACHUSETTS, U.S.A.
 * 
 * THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
 * ONLY  IN  ACCORDANCE WITH  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
 * INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE  OR  ANY OTHER
 * COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
 * OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
 * TRANSFERED.
 */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include "sigtypes.h"
#include "sigversion.h"
#include "pcicards_lib.h"
#include "softplane_lib.h"
#include "user_lib.h"

#define LIM_DEFINITIONS
#define LIM_KERNEL rda_limits_kernel
#include "config_lib.h"

static void       splConfigText( FILE *pFile_a, void *arg_a ) ;
static void      splTriggerText( FILE *pFile_a, void *arg_a ) ;
static void      splTxPhaseText( FILE *pFile_a, void *arg_a ) ;
static void       splSharedText( FILE *pFile_a, void *arg_a ) ;
static void      splSerial0Text( FILE *pFile_a, void *arg_a ) ;
static void splIo62ExtPanelText( FILE *pFile_a, void *arg_a ) ;

static MESSAGE LIM_KERNEL
( const char *sname_a,		/* Name of structure */
  void *item_a,			/* Pointer to structure */
  SINT4 ioper_a,		/* Operation to perform */
  const char *spath_a,		/* Full path name of fields */
  void *ioarg_a ) ;		/* Diagnostic messages, or NULL */

MESSAGE rda_limits
( const char *sname_a,		/* Name of structure */
  volatile void *item_a,	/* Pointer to structure */
  SINT4 ioper_a,		/* Operation to perform */
  void *file_a )		/* Diagnostic messages, or NULL */
{
  return( lim_toplevel( sname_a, item_a, ioper_a, file_a, LIM_KERNEL ) ) ;
}

/* ======================================================================
 * Internal routine to recursively descend the RDA structures.
 */
static MESSAGE LIM_KERNEL
( const char *sname_a,		/* Name of structure */
  void *item_a,			/* Pointer to structure */
  SINT4 ioper_a,		/* Operation to perform */
  const char *spath_a,		/* Full path name of fields */
  void *ioarg_a )		/* Diagnostic messages, or NULL */
{
  char spath[PATHNAME_SIZE], *sItem ; struct lim_inLine **pLine ;
  SINT4 idim1=0, idim2=0 ; MESSAGE istatus = SS_NORMAL ;
  UINT1 lActualSizes = USEACTUALSIZES( ioper_a ) ;

  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  if( 0 == strcmp( "splIoLinePair", sname_a ) ) {
    struct splIoLinePair *item = item_a ;

    COMMENTEXT( "\n" ) ;
    SCALAR( lRS422,  0, 1, FALSE ) ;
    SCALAR(  iTerm, -1, 1,     0 ) ;
    STRING( pinPos, "" ) ;
    STRING( pinNeg, "" ) ;
  }
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  else if( 0 == strcmp( "splCpDb25GpTTL", sname_a ) ) {
    struct splCpDb25GpTTL *item = item_a ;

    STRING( pin01, "" ) ; STRING( pin02, "" ) ; STRING( pin03, "" ) ;
    STRING( pin04, "" ) ; STRING( pin05, "" ) ; STRING( pin06, "" ) ;
    STRING( pin07, "" ) ; STRING( pin08, "" ) ; STRING( pin09, "" ) ;
    STRING( pin10, "" ) ; STRING( pin11, "" ) ; STRING( pin12, "" ) ;
    STRING( pin13, "" ) ; STRING( pin14, "" ) ; STRING( pin15, "" ) ;
    STRING( pin16, "" ) ; STRING( pin17, "" ) ; STRING( pin18, "" ) ;
    STRING( pin19, "" ) ; STRING( pin20, "" ) ;
  }
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  else if( 0 == strcmp( "splB2B", sname_a ) ) {
    struct splB2B *item = item_a ;

    STRING( bit00, "" ) ; STRING( bit01, "" ) ; STRING( bit02, "" ) ;
    STRING( bit03, "" ) ; STRING( bit04, "" ) ; STRING( bit05, "" ) ;
    STRING( bit06, "" ) ; STRING( bit07, "" ) ;
#if IO62B2B_NBITS != 8
#error Please manually maintain all B2B definitions in this file
#endif
  }
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  else if( 0 == strcmp( "splCpAssembly", sname_a ) ) {
    struct splCpAssembly *item = item_a ;

    COMMENTEXT( "\n# TTL/CMOS on J1\n#\n" ) ; SUBSTRUCTURE( splCpDb25GpTTL, J1 ) ;
    COMMENTEXT( "\n# TTL/CMOS on J2\n#\n" ) ; SUBSTRUCTURE( splCpDb25GpTTL, J2 ) ;
    COMMENTEXT( "\n# TTL/CMOS on J4\n#\n" ) ; SUBSTRUCTURE( splCpDb25GpTTL, J4 ) ;
    COMMENTEXT( "\n# TTL/CMOS on J5\n#\n" ) ; SUBSTRUCTURE( splCpDb25GpTTL, J5 ) ;
    COMMENTEXT( "\n# TTL/CMOS on J7\n#\n" ) ; SUBSTRUCTURE( splCpDb25GpTTL, J7 ) ;

    COMMENTEXT( "\n# Eight IO62 line pairs on J3\n#" ) ;
    SUBSTRUCTURE( splIoLinePair, J3_01_14 ) ;
    SUBSTRUCTURE( splIoLinePair, J3_02_15 ) ;
    SUBSTRUCTURE( splIoLinePair, J3_03_16 ) ;
    SUBSTRUCTURE( splIoLinePair, J3_04_17 ) ;
    SUBSTRUCTURE( splIoLinePair, J3_05_18 ) ;
    SUBSTRUCTURE( splIoLinePair, J3_06_19 ) ;
    SUBSTRUCTURE( splIoLinePair, J3_07_20 ) ;
    SUBSTRUCTURE( splIoLinePair, J3_08_21 ) ;

    COMMENTEXT( "\n# Two RS-422 Tx/Rx chips on J3\n#\n" ) ;
    STRING( J3_09_22, "" ) ;
    STRING( J3_10_23, "" ) ;

    COMMENTEXT( "\n# Seven IO62 line pairs on J9\n#" ) ;
    SUBSTRUCTURE( splIoLinePair, J9_01_14 ) ;
    SUBSTRUCTURE( splIoLinePair, J9_02_15 ) ;
    SUBSTRUCTURE( splIoLinePair, J9_03_16 ) ;
    SUBSTRUCTURE( splIoLinePair, J9_04_17 ) ;
    SUBSTRUCTURE( splIoLinePair, J9_05_18 ) ;
    SUBSTRUCTURE( splIoLinePair, J9_06_19 ) ;
    SUBSTRUCTURE( splIoLinePair, J9_07_20 ) ;

    COMMENTFUNC( splTxPhaseText, NULL ) ;
    STRING( TxPhaseLines, "" ) ;

    COMMENTFUNC( splSharedText, NULL ) ;
    STRING( SharedStsModel, "" ) ;

    COMMENTFUNC( splSerial0Text, NULL ) ;
    STRING( ioSerial0_TxRx, "" ) ;

    COMMENTEXT( "\n# Relays and relay drivers on J6\n#\n" ) ;
    STRING( J6_IntRelay1, "" ) ;
    STRING( J6_IntRelay2, "" ) ;
    STRING( J6_IntRelay3, "" ) ; COMMENTEXT( "\n" ) ;
    STRING( J6_ExtRelay1, "" ) ;
    STRING( J6_ExtRelay2, "" ) ;
    STRING( J6_ExtRelay3, "" ) ;
    STRING( J6_ExtRelay4, "" ) ;

    COMMENTEXT( "\n# BNC testpoint monitors\n#\n" ) ;
    STRING( J13_BNC, "" ) ;
    STRING( J16_BNC, "" ) ;

    COMMENTFUNC( splTriggerText, NULL ) ;
    STRING( J14_BNC, "" ) ; STRING( J15_BNC, "" ) ;
    STRING( J17_BNC, "" ) ; STRING( J18_BNC, "" ) ;

    COMMENTEXT( "\n# RS232 TTY Transmitters/Receivers from IO62\n#\n" ) ;
    STRING( TTY0_Tx, "" ) ; STRING( TTY1_Tx, "" ) ;
    STRING( TTY0_Rx, "" ) ; STRING( TTY1_Rx, "" ) ;

    COMMENTEXT( "\n# Relays from IO62 (requires jumper settings on the IO62"
		"\n# which may conflict with using the above TTY/Trig lines)."
		"\n#    Relay1  -  NO:J17      Arm:J18      NC:J15"
		"\n#    Relay2  -  NO:J11,3    Arm:J11,2    NC:J11,4"
		"\n#\n" ) ;
    STRING( Relay1, "" ) ;
    STRING( Relay2, "" ) ;
  }
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  else if( 0 == strcmp( "splIo62Assembly", sname_a ) ) {
    struct splIo62Assembly *item = item_a ;

    COMMENTEXT( "\n# Twenty general purpose digital line pairs\n#" ) ;
    SUBSTRUCTURE_1D( splIoLinePair, io, 20 ) ;

    COMMENTFUNC( splTxPhaseText, NULL ) ;
    STRING( TxPhaseLines, "" ) ;

    COMMENTFUNC( splSharedText, NULL ) ;
    STRING( SharedStsModel, "" ) ;

    COMMENTFUNC( splSerial0Text, NULL ) ;
    STRING( ioSerial0_TxRx, "" ) ;

    COMMENTEXT( "\n# Onboard relays\n#\n" ) ;
    STRING( Relay1, "" ) ;
    STRING( Relay2, "" ) ;

    COMMENTEXT( "\n# RS232 TTY transmitters/Receivers\n#\n" ) ;
    STRING( TTY0_Tx, "" ) ; STRING( TTY1_Tx, "" ) ;
    STRING( TTY0_Rx, "" ) ; STRING( TTY1_Rx, "" ) ;

    COMMENTFUNC( splTriggerText, NULL ) ;
    STRING( Trig0, "" ) ; STRING( Trig1, "" ) ;
    STRING( Trig2, "" ) ; STRING( Trig3, "" ) ;

    COMMENTEXT( "\n# Board-to-Board serial Tx/Rx bits\n#\n" ) ;
    SUBSTRUCTURE( splB2B, TxB2B ) ; COMMENTEXT( "\n" ) ;
    SUBSTRUCTURE( splB2B, RxB2B ) ;
  }
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  else if( 0 == strcmp( "splRcp88dAssembly", sname_a ) ) {
    struct splRcp88dAssembly *item = item_a ;

    COMMENTEXT( "\n# Panel LED controls (active low)\n#\n" ) ;
    STRING( dauOkay_, ""   ) ;
    STRING( dcuOkay_, ""   ) ;
    STRING( rcpGoLed_, ""  ) ;

    COMMENTEXT( "\n# Status inputs from WSR88D\n#\n" ) ;
    STRING( phmodFail,   "" ) ;
    STRING( chanFail,    "" ) ;
    STRING( opFreqRefFl, "" ) ;
    STRING( cohoRefFail, "" ) ;

    COMMENTEXT( "\n# Control outputs to WSR88D\n#\n" ) ;
    STRING( driveSig40dB , "" ) ;
    STRING( driveSig32dB , "" ) ;
    STRING( driveSig16dB , "" ) ;
    STRING( driveSig8dB  , "" ) ;
    STRING( driveSig4dB  , "" ) ;
    STRING( driveSig2dB  , "" ) ;
    STRING( driveSig1dB  , "" ) ; COMMENTEXT( "\n" ) ;
    STRING( noiseCtrlIn  , "" ) ;
    STRING( p5Ion        , "" ) ;
    STRING( shortBeamPulse, "" ) ;
    STRING( shortRFPulse , "" ) ; COMMENTEXT( "\n" ) ;
    STRING( drSigBit4    , "" ) ;
    STRING( drSigBit3    , "" ) ;
    STRING( drSigBit2    , "" ) ;
    STRING( drSigBit1    , "" ) ; COMMENTEXT( "\n" ) ;
    STRING( drSigPos4    , "" ) ;
    STRING( drSigPos3    , "" ) ;
    STRING( drSigPos2    , "" ) ;
    STRING( drSigPos1    , "" ) ;

    COMMENTEXT( "\n# Spare and misc lines from IO62 card\n#" ) ;
    SUBSTRUCTURE( splIoLinePair, spare1 ) ;
    SUBSTRUCTURE( splIoLinePair, spare2 ) ;
    SUBSTRUCTURE( splIoLinePair, spare3 ) ;
    SUBSTRUCTURE( splIoLinePair, spare4 ) ;
    SUBSTRUCTURE( splIoLinePair, spare5 ) ; COMMENTEXT( "\n" ) ;
    STRING( analogMux0, "" ) ;
    STRING( analogMux1, "" ) ;

    COMMENTEXT( "\n# Board-to-Board serial Tx/Rx bits\n#\n" ) ;
    SUBSTRUCTURE( splB2B, TxB2B ) ; COMMENTEXT( "\n" ) ;
    SUBSTRUCTURE( splB2B, RxB2B ) ;
  }
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  else if( 0 == strcmp( "splRvp88dAssembly", sname_a ) ) {
    struct splRvp88dAssembly *item = item_a ;

    COMMENTEXT( "\n# Spare lines from IO62 card\n#" ) ;
    SUBSTRUCTURE( splIoLinePair, spare1 ) ;
    SUBSTRUCTURE( splIoLinePair, spare2 ) ;
    SUBSTRUCTURE( splIoLinePair, spare3 ) ;
  }
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  else if( 0 == strcmp( "splTdwrV1Assembly", sname_a ) ) {
    struct splTdwrV1Assembly *item = item_a ;

    COMMENTEXT( "\n# TTL/CMOS on J1\n#\n" ) ; SUBSTRUCTURE( splCpDb25GpTTL, J1 ) ;
    COMMENTEXT( "\n# TTL/CMOS on J2\n#\n" ) ; SUBSTRUCTURE( splCpDb25GpTTL, J2 ) ;
    COMMENTEXT( "\n# TTL/CMOS on J4\n#\n" ) ; SUBSTRUCTURE( splCpDb25GpTTL, J4 ) ;
    COMMENTEXT( "\n# TTL/CMOS on J5\n#\n" ) ; SUBSTRUCTURE( splCpDb25GpTTL, J5 ) ;
    COMMENTEXT( "\n# TTL/CMOS on J7\n#\n" ) ; SUBSTRUCTURE( splCpDb25GpTTL, J7 ) ;

    COMMENTEXT( "\n# Eight IO62 line pairs on J3\n#" ) ;
    SUBSTRUCTURE( splIoLinePair, J3_01_14 ) ;
    SUBSTRUCTURE( splIoLinePair, J3_02_15 ) ;
    SUBSTRUCTURE( splIoLinePair, J3_03_16 ) ;
    SUBSTRUCTURE( splIoLinePair, J3_04_17 ) ;
    COMMENTEXT( "\n# (Note J3_05_18 and J3_06_19 hardwired to ARP/ACP)\n" ) ;
    SUBSTRUCTURE( splIoLinePair, J3_07_20 ) ;
    SUBSTRUCTURE( splIoLinePair, J3_08_21 ) ;

    COMMENTEXT( "\n# Two RS-422 Tx/Rx chips on J3\n#\n" ) ;
    STRING( J3_09_22, "" ) ;
    STRING( J3_10_23, "" ) ;

    COMMENTFUNC( splTriggerText, NULL ) ;
    STRING( J14_BNC, "" ) ; STRING( J15_BNC, "" ) ;
    STRING( J17_BNC, "" ) ; STRING( J18_BNC, "" ) ;
  }
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  else if( 0 == strcmp( "splOrdaPanelTest", sname_a ) ) {
    struct splOrdaPanelTest *item = item_a ;

    SCALAR( iIo62UnitExtA,   0,    3,   0 ) ;
    SCALAR( iIo62UnitExtB,   0,    3,   3 ) ;
    SCALAR( iIo62UnitRvp8,   0,    3,   2 ) ;
    SCALAR( iIo62UnitRcp8,   0,    3,   1 ) ;
    SCALAR( fCathodeVolts, 0.0, 20.0, 7.5 ) ;
  }
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  else if( 0 == strcmp( "splIo62Instance", sname_a ) ) {
    struct splIo62Instance *item = item_a, itemref = *item ;

    SCALAR( lInUse, 0, 1, FALSE ) ;
    if( (!lActualSizes) || item->lInUse ) {

      COMMENTFUNC( splIo62ExtPanelText, NULL ) ;
      STRING( sExtPanel, SPLEXTP_STDCP ) ;
      CONDITIONAL_DISCRIMINANT {
	strncpy( itemref.sExtPanel, item->sExtPanel, sizeof(item->sExtPanel) ) ;
      }
      if( 0  == strcasecmp( itemref.sExtPanel, SPLEXTP_STDCP ) ) {
	SUBSTRUCTURE(   splCpAssembly, Opt.Cp ) ;
      }
      else if( 0 == strcasecmp( itemref.sExtPanel, SPLEXTP_DIRECT ) ) {
	SUBSTRUCTURE( splIo62Assembly, Opt.Io ) ;
      }
      else if( 0 == strcasecmp( itemref.sExtPanel, SPLEXTP_RCP88D ) ) {
	SUBSTRUCTURE( splRcp88dAssembly, Opt.Rcp88d ) ;
      }
      else if( 0 == strcasecmp( itemref.sExtPanel, SPLEXTP_RVP88D ) ) {
	SUBSTRUCTURE( splRvp88dAssembly, Opt.Rvp88d ) ;
      }
      else if( 0 == strcasecmp( itemref.sExtPanel, SPLEXTP_TDWRV1 ) ) {
	SUBSTRUCTURE( splTdwrV1Assembly, Opt.TdwrV1 ) ;
      }
    }
  }
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  else if( 0 == strcmp( "splConfig", sname_a ) ) {
    struct splConfig *item = item_a ;

    COMMENTFUNC( splConfigText, NULL ) ;
    STRING( sVersion, IRIS_VERSION ) ;

    COMMENTEXT( "\n# ------------------- IO62 Slot #0 -------------------\n#\n" ) ;
    SUBSTRUCTURE( splIo62Instance, Io62[0] ) ;
    COMMENTEXT( "\n# ------------------- IO62 Slot #1 -------------------\n#\n" ) ;
    SUBSTRUCTURE( splIo62Instance, Io62[1] ) ;
    COMMENTEXT( "\n# ------------------- IO62 Slot #2 -------------------\n#\n" ) ;
    SUBSTRUCTURE( splIo62Instance, Io62[2] ) ;
    COMMENTEXT( "\n# ------------------- IO62 Slot #3 -------------------\n#\n" ) ;
    SUBSTRUCTURE( splIo62Instance, Io62[3] ) ;
#if IO62MAXUNITS != 4
#error Please manually maintain IO62 code
#endif
    COMMENTEXT( "\n# ----------------- ORDA Panel Tester ----------------\n#\n" ) ;
    SUBSTRUCTURE( splOrdaPanelTest, OrdaPanelTest ) ;
  }
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  else
    istatus = iMessageMod_va( CONFIG_LIM_BADSTRUCT, 1, sname_a ) ;

  return( istatus ) ;
}

/* ------------------------------
 * Print the automated comments that appear at the header of the
 * softplane configuration file.  This includes the current list of
 * exactly which control and status signals are defined for the
 * current software release.
 */
static void splConfigText( FILE *pFile_a, void *arg_a )
{
struct lookupItem {		/* Logical name listings */
  const char *sProto;
  char  *sNull ;
} ;
#define LOGICCNTBIT(ARG) NULL	/* To make the two initializers */
#define LOGICSTSBIT(ARG) NULL	/*   work properly... */
  const struct lookupItem cntItems[] = SPLLOGICCNT_INITIALIZER, *pCnt = cntItems ;
  const struct lookupItem stsItems[] = SPLLOGICSTS_INITIALIZER; 
  const struct lookupItem *pSts = stsItems ;

  fprintf( pFile_a, 
	   "# **********************************\n"
	   "# *                                *\n"
	   "# *  Softplane Configuration File  *\n"
	   "# *                                *\n"
	   "# **********************************\n\n" ) ;

  fprintf( pFile_a,
	   "# The following general purpose control and status signals\n"
	   "# can be routed to/from any available hardware pin.  The '~'\n"
	   "# prefix character may be used for signal inversion. \n"
	   "#\n"
	   "#         Control Outputs            Status Inputs\n"
	   "#        -----------------          ---------------\n" ) ;

  while( pCnt->sProto || pSts->sProto ) {
    const char *pCntName = ""; 
    const char *pStsName = "" ;
    if( pCnt->sProto ) 
    { pCntName = pCnt->sProto ; pCnt++ ; }
    if( pSts->sProto ) { pStsName = pSts->sProto ; pSts++ ; }
    fprintf( pFile_a, "#%24s %24s\n", pCntName, pStsName ) ;
  }
  fprintf( pFile_a, "\n" ) ;
}

/* ------------------------------
 * Automated comments for trigger driver outputs.
 */
static void splTriggerText( FILE *pFile_a, void *arg_a )
{
  fprintf( pFile_a,
	   "\n"
	   "# BNC 75-Ohm trigger drivers direct from IO62 PCI card.\n"
	   "# Special trigger assignments may also be used here:\n"
	   "#    Driver-0:  'trigger[1]'  or  'trigger[5]\n"
	   "#    Driver-1:  'trigger[2]'  or  'trigger[6]\n"
	   "#    Driver-2:  'trigger[3]'  or  'polar[1]\n"
	   "#    Driver-3:  'trigger[4]'  or  'polar[2]\n"
	   "#\n" ) ;
}
/* ------------------------------
 * Automated comments for transmit phase line outputs.
 */
static void splTxPhaseText( FILE *pFile_a, void *arg_a )
{
  fprintf( pFile_a,
	   "\n"
	   "# Parallel Tx phase control outputs.  Options are:\n"
	   "# %16s : Eight IO62 RS-422 outputs #4-11.  These are\n"
	   "#                      wired to J3 on the standard backpanel.\n"
	   "#\n",
	   SPLTXPHZ_IO4TO11 ) ;
}
/* ------------------------------
 * Automated comments for shared status line hookup model.
 */
static void splSharedText( FILE *pFile_a, void *arg_a )
{
  fprintf( pFile_a,
	   "\n"
	   "# Hookup model for shared status/counter inputs.  Options are:\n"
	   "# %16s : MIT/LL Custom TDWR patchpanel, Ver.1\n"
	   "#\n",
	   SPLSHMOD_TDWR_V1 ) ;
}
/* ------------------------------
 * Automated comments for hookup of generic serializer #0
 */
static void splSerial0Text( FILE *pFile_a, void *arg_a )
{
  fprintf( pFile_a,
	   "\n"
	   "# Pin assignments for generic serializer #0.  Options are:\n"
	   "# %16s : Rx/Tx on TTY0 RS-232 line pair\n"
	   "# %16s : Rx/Tx on lines 12/16 (J9 Pins 1/5)\n"
	   "#\n",
	   SPLSERIAL0_TTY0, SPLSERIAL0_RX12_TX16 ) ;
}
/* ------------------------------
 * Automated comments for type of remote backpanel.
 */
static void splIo62ExtPanelText( FILE *pFile_a, void *arg_a )
{
  fprintf( pFile_a,
	   "\n"
	   "# The remote backpanel type must be one of the following:\n"
	   "#   %8s : Direct I/O with IO62 connector itself\n"
	   "#   %8s : Standard IO62-CP connector panel\n"
	   "#   %8s : RCP8 portion of WSR88D panel\n"
	   "#   %8s : RVP8 portion of WSR88D panel\n"
	   "#   %8s : MIT/LL TDWR customization of IO62-CP\n"
	   "#\n",
	   SPLEXTP_DIRECT, SPLEXTP_STDCP, SPLEXTP_RCP88D, SPLEXTP_RVP88D,
	   SPLEXTP_TDWRV1 ) ;
}

/* ======================================================================
 * These routines load/save new values to the softplane config file
 */
MESSAGE spl_load_conf
( const char *sRemoteHostname_a, volatile struct splConfig *pSplConfig_a )
{
  memset( (void *)pSplConfig_a, 0, sizeof(struct splConfig) ) ;

  return( lim_loadFile( sRemoteHostname_a, "softplane.conf", "splConfig",
			pSplConfig_a, rda_limits ) ) ;
}
MESSAGE spl_save_conf
( const char *sRemoteHostname_a, volatile const struct splConfig *pSplConfig_a )
{
  struct splConfig SplConfig = *pSplConfig_a ;

  strncpy( SplConfig.sVersion, IRIS_VERSION, 8 ) ; SplConfig.sVersion[7] = '\0' ;

  return( lim_saveFile( sRemoteHostname_a, "softplane.conf", "splConfig",
			&SplConfig, rda_limits ) ) ;
}
