#define	    ident	"1D08"
#ifdef VAXC
#module	    EL734_Utility	ident
#endif
#ifdef __DECC
#pragma	    module	    EL734_Utility	ident
#endif
/*
** +--------------------------------------------------------------+
** |                  Paul Scherrer Institute                     |
** |                     Department ASQ				  |
** |                                                              |
** | 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  . . . . . . . . : [...LIB.SINQ]EL734_Utility.C
**
** Author   . . . . . . . . . . : D. Maden
** Date of creation . . . . . . : Nov 1995
**
**  To compile this module, use:

	$ import tasmad
	$ define/group sinq_c_tlb mad_lib:sinq_c.tlb
	$ cc /debug /noopt /obj=[]EL734_Utility -
			tasmad_disk:[mad.psi.lib.sinq]EL734_Utility + -
			sinq_c_tlb/lib

**  To include this module in SINQ.OLB, use:

  $ import tasmad
  $ define/group sinq_c_tlb mad_lib:sinq_c.tlb
  $
  $ define/group sinq_olb mad_lib:sinq_dbg.olb
  $ @tasmad_disk:[mad.lib.sinq]sinq_olb EL734_Utility debug
  $
  $ define/group sinq_olb mad_lib:sinq.olb
  $ @tasmad_disk:[mad.lib.sinq]sinq_olb EL734_Utility
**
** Updates:
**  1A01  2-Nov-1995 DM.	Initial version.
**  1B01 21-Mar-1996 DM.	Move from DELTAT.OLB to SINQ.OLB.
**  1C01  3-Mar-1997 DM.	Add "Forced-close" capability.
**  1C02 14-Apr-1997 DM.	Add EL734__BAD_STP to EL734_MoveNoWait.
**  1C11 18-Jun-1998 DM.	Modify EL734_GetZeroPoint.
**  1D01  4-Aug-1998 DM.	Put messages into a .MSG file.
**============================================================================
** The entry points included in this module are described below. Prototypes
** can be defined via:
**
**    #include <sinq_prototypes.h>
**
**	EL734_AddCallStack	- Add a routine name to the call stack.
**	EL734_Close		- Close a connection to a motor.
**	EL734_Config		- Configure a connection to a motor.
**	EL734_EncodeMSR		- Encode the MSR status into text.
**	EL734_EncodeSS		- Encode the SS flags into text.
**	EL734_ErrInfo		- Return detailed status from last operation.
**	EL734_GetAirCush	- Get W and AC register values.
**	EL734_GetEncGearing	- Get FD register values.
**	EL734_GetId		- Get ID register value.
**	EL734_GetLimits		- Get H register values.
**	EL734_GetMotorGearing	- Get FM register values.
**	EL734_GetNullPoint	- Get V register value.
**	EL734_GetPosition	- Get U register value = current position.
**	EL734_GetPrecision	- Get A register value.
**	EL734_GetRefMode	- Get K register value.
**	EL734_GetRefParam	- Get Q register value.
**	EL734_GetSpeeds		- Get G, J and E register values.
**	EL734_GetStatus		- Get MSR/SS/U register values.
**	EL734_GetZeroPoint	- Get zero-point of motor.
**	EL734_MoveNoWait	- Move motor and don't wait for completion.
**	EL734_MoveWait		- Move motor and wait for completion.
**	EL734_Open		- Open a connection to a motor.
**	EL734_PutOffline	- Put the EL734 off-line.
**	EL734_PutOnline		- Put the EL734 on-line.
**	EL734_SendCmnd		- Send a command to RS232C server.
**	EL734_SetAirCush	- Set the air-cushion (AC register).
**	EL734_SetErrcode	- Set up EL734_errcode.
**	EL734_SetHighSpeed	- Set the max speed (J register).
**	EL734_SetLowSpeed	- Set the start/stop speed (G register).
**	EL734_SetRamp		- Set the start/stop ramp (E register).
**	EL734_Stop		- Send a stop command to motor.
**	EL734_WaitIdle		- Wait till MSR goes to zero.
**	EL734_ZeroStatus	- Zero the "ored-MSR" and fault counters.
**---------------------------------------------------------------------
**    int EL734_AddCallStack (&handle, &name)
**	  ------------------
**			    Add a routine name to the call stack (internal use).
**  Input Args:
**	struct EL734info *handle  - The pointer to the structure returned by
**				    EL734_Open.
**	char  *name	- The name to be added to the call stack.
**  Output Args:
**	none
**  Modified Args:
**	none
**  Return status:
**	False if an error is detected, otherwise True.
**  Routines called:
**	none
**  Description:
**	If an error has already occurred (EL734_errcode != 0), the routine
**	simply returns False. Otherwise, *name is added to the call stack.
**	Then *handle is checked.
**	If NULL, error EL734__NOT_OPEN is set and False is returned.
**	Otherwise, the connection's TCP/IP socket number is checked.
**	If zero, error EL734__NO_SOCKET is set and False is returned.
**	If negative, error EL734__FORCED_CLOSE is set and False is returned.
**	Otherwise, True is returned.
**---------------------------------------------------------------------
**    int EL734_Close (&handle, int force_flag)
**	  -----------
**			    Close a connection to a motor.
**  Input Args:
**	int    force_flag - if non-zero, all connections using the same socket
**			    will also be closed (this gets AsynSrv_Close to
**			    actually close the socket and is needed for error
**			    recovery operations).
**  Output Args:
**	none
**  Modified Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**			  On return, the pointer is set to NULL.
**  Return status:
**	True always (error returns from close and free are not checked).
**  Routines called:
**	AsynSrv_Close
**  Description:
**	The routine calls AsynSrv_Close to close the connection to the RS232C
**	server. If 'force_flag' is non-zero, all other connections to the
**	RS232C server which use the same socket will also be closed.
**
**	The 'force_flag' can be useful in error recovery situations. The AsynSrv
**	utility operates by only opening a socket for each separate combination
**	of host/port. Hence, if several connections are open to the
**	motors on an EL734, then calling EL734_Close doesn't actually close
**	the socket until all connections have been closed. In the situation
**	where an error has been detected on a motor, it is often desirable to
**	close and re-open the socket as part of the recovery procedure. Calling
**	EL734_Close with 'force_flag' non-zero will force the socket to be
**	closed and will mark all connections using this socket so that they
**	will be informed of the event when they next call an EL734_utility
**	routine.
**
**	Note:	The force-close action is effected by the AsynSrv package. A
**		force-close will thus also close any connections to other
**		RS-232-C devices (e.g. EL737 neutron cntr) on the same server.
**-------------------------------------------------------------------------
**   int  EL734_Config (&handle, &par_id, par_val, ...)
**	  ------------
**			    Configure a connection to a motor.
**  Input Args:
**	char*	par_id	- Text string identifying the next argument (see below).
**			    NULL indicates the end of the argument list.
**	<??>	par_val - The value to set for the argument. The type of the
**			    argument can depend on par_id.
**  Output Args:
**	none
**  Modified Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**			  It is used to hold the config info for the connection.
**  Return status:
**	True if no problems detected, otherwise False and EL734_errcode
**	is set to indicate the nature of the problem as follows:
**	    EL734__BAD_PAR --> Unrecognised par_id or msecTmo < 100 or
**					msecTmo > 999'999 or bad eot or ..
**  Routines called:
**	none
**  Description:
**	The routine sets values in the EL734info data structure. Values which
**	may be taken by par_id (warning -- par_id is case-sensitive) and the
**	corresponding variable type of par_val are:
**
**	    "msecTmo"	int	The time-out response for commands sent to
**				    the EL734. The valid range is 100 to
**				    999'999. Default is 10'000.
**	    "eot"	char*	The expected terminators in responses to
**				    commands sent to the EL734. The first
**				    character specifies the number of
**				    terminators (max=3). Default is "1\r".
**	    "motor"	int	The index of the motor in the range 1-12 to be
**				    associated with this connection.
**	    "chan"	int	The RS-232-C channel number of the EL734
**				    controller associated with this connection.
**-------------------------------------------------------------------------
**  char  *EL734_EncodeMSR (&text, text_len, msr, ored_msr, fp_cntr, fr_cntr)
**	   ---------------
**			    Encode the MSR status into text.
**  Input Args:
**	int	text_len    - The size of text.
**	int	msr	    - The current MSR.
**	int	ored_msr    - The 'ored' MSR to be encoded.
**	int	fp_cntr	    - The counter of *FP faults.
**	int	fr_cntr	    - The counter of *FR faults.
**  Output Args:
**	char	*text	    - The resulting text string is stored here.
**  Modified Args:
**	none
**  Return status:
**	A pointer to "text".
**  Routines called:
**	none
**  Description:
**	The routine makes an intelligible message out of the MSR input data.
**-------------------------------------------------------------------------
**  char  *EL734_EncodeSS (&text, text_len, ss)
**	   --------------
**			    Encode the SS flags into text.
**  Input Args:
**	int	text_len    - The size of text.
**	int	ss	    - The value of SS register.
**  Output Args:
**	char	*text	    - The resulting text string is stored here.
**  Modified Args:
**	none
**  Return status:
**	A pointer to "text".
**  Routines called:
**	none
**  Description:
**	The routine makes an intelligible message out of the input SS data.
**-------------------------------------------------------------------------
**    void EL734_ErrInfo (&entry_txt_ptr, &errcode, &my_errno, &vaxc_errno)
**	   -------------
**			    Return detailed status from last operation.
**  Input Args:
**	None
**  Output Args:
**	char **entry_txt_ptr - Pointer to a text string giving the call stack
**				at the time that the error was detected.
**	int  *errcode	 - An internal error code indicating the detected error.
**	int  *my_errno	 - Saved value of errno.
**	int  *vaxc_errno - Saved value of vaxc$errno (OpenVMS only).
**  Modified Args:
**	none
**  Return status:
**	none
**  Routines called:
**	none
**  Description:
**	Returns detailed status of the last operation. Once an error has been
**	detected, the error status is frozen until this routine has been called.
**-------------------------------------------------------------------------
**    int EL734_GetAirCush (&handle, &present, &state)
**	  ----------------
**				    Get W and AC register values.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Output Args:
**	int *present	- The W register. If non-zero, motor has an air-cushion.
**	int *state	- The AC register. If non-zero, air-cushion is up.
**  Description:
**	The routine is the same as EL734_GetEncGearing except that it issues
**	a "W" command and then an "AC" command instead of an "FD" command to
**	the controller.
**-------------------------------------------------------------------------
**    int EL734_GetEncGearing (&handle, &numerator, &denominator)
**	  -------------------
**				    Get FD register values.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Output Args:
**	int *numerator	    - The encoder gearing numerator.
**	int *denominator    - The encoder gearing denominator.
**  Modified Args:
**	none
**  Return status:
**	True if no problems detected, otherwise False and EL734_ErrInfo
**	can be called to identify the problem. Values of Errcode set by
**	EL734_GetEncGearing are (other values may be set by the called
**	routines):
**	    EL734__BAD_TMO, BAD_LOC, BAD_CMD, BAD_OFL,
**		BAD_ADR, EMERG_STOP	--> see EL734_Open.
**	    EL734__BAD_ILLG --> the response was probably not 2 integers.
**				This could happen if there is noise on the
**				RS232C connection to the EL734.
**	If an error is detected, *numerator and *denominator are set to 0.
**  Routines called:
**	EL734_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply
**  Description:
**	The routine issues an "FD" command to the controller and analyses
**	the result. The two parameters of the "FD" command are the numerator
**	and denominator respectively.
**-------------------------------------------------------------------------
**    int EL734_GetId (&handle, &id_txt, id_len)
**	  -----------
**			    Get ID register value.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**	int    id_len	- The size of the <id_txt> buffer in bytes.
**  Output Args:
**	char  *id_txt	- The EL734 identifier ("ID" parameter).
**  Description:
**	The routine is the same as EL734_GetEncGearing except that it issues
**	an "ID" command instead of an "H" command to the controller.
**-------------------------------------------------------------------------
**    int EL734_GetLimits (&handle, &lo, &hi)
**	  ---------------
**			    Get H register values.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Output Args:
**	float *lo	- The lower  software limit.
**	float *hi	- The higher software limit.
**  Description:
**	The routine is the same as EL734_GetEncGearing except that it issues
**	an "H" command instead of an "FD" command to the controller.
**-------------------------------------------------------------------------
**    int EL734_GetMotorGearing (&handle, &numerator, &denominator)
**	  ---------------------
**			    Get FM register values.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Output Args:
**	int *numerator	    - The motor gearing numerator.
**	int *denominator    - The motor gearing denominator.
**  Description:
**	The routine is the same as EL734_GetEncGearing except that it issues
**	an "FM" command instead of an "FD" command to the controller. The
**	two parameters of the "FM" command are the numerator and denominator
**	respectively.
**-------------------------------------------------------------------------
**    int EL734_GetNullPoint (&handle, &null_pt)
**	  ------------------
**			    Get V register value.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Output Args:
**	int *null_pt	- The null point ("V" parameter) of the EL734.
**  Description:
**	The routine is the same as EL734_GetEncGearing except that it issues
**	a "V" command instead of an "FD" command to the controller.
**-------------------------------------------------------------------------
**    int EL734_GetPosition (&handle, &ist_posit)
**	  -----------------
**			    Get U register value = current position.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Output Args:
**	float *ist_posit - The current position (U command) of the motor.
**  Description:
**	The routine is the same as EL734_GetEncGearing except that it issues
**	a "U" command instead of an "FD" command to the controller.
**-------------------------------------------------------------------------
**    int EL734_GetPrecision (&handle, &n_dec)
**	  ------------------
**			    Get A register value.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Output Args:
**	int   *n_dec	- The precision ("A" parameter) of the EL734.
**  Description:
**	The routine is the same as EL734_GetEncGearing except that it issues
**	a "A" command instead of an "FD" command to the controller.
**-------------------------------------------------------------------------
**    int EL734_GetRefMode (&handle, &mode)
**	  ----------------
**			    Get K register value.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Output Args:
**	int   *mode	- The reference seek mode ("K" parameter) of the EL734.
**  Description:
**	The routine is the same as EL734_GetEncGearing except that it issues
**	a "K" command instead of an "FD" command to the controller.
**-------------------------------------------------------------------------
**    int EL734_GetRefParam (&handle, &param)
**	  -----------------
**			    Get Q register value.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Output Args:
**	float *param	- The reference seek param ("Q" parameter) of the EL734.
**  Description:
**	The routine is the same as EL734_GetEncGearing except that it issues
**	a "Q" command instead of an "FD" command to the controller.
**-------------------------------------------------------------------------
**    int EL734_GetSpeeds (&handle, &lo, &hi, &ramp)
**	  ---------------
**			    Get G, J and E register values.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Output Args:
**	int   *lo	- The start/stop speed (G register). Units = Steps/sec.
**	int   *hi	- The maximum speed (J register). Units = Steps/sec.
**	int   *ramp	- The start/stop ramp (E register). Units = kHz/sec.
**  Description:
**	The routine is the same as EL734_GetEncGearing except that it issues
**	a "G", "J" and "E" commands instead of an "FD" command to the
**	controller.
**-------------------------------------------------------------------------
**    int EL734_GetStatus (&handle, &msr, &ored_msr, &fp_cntr, &fr_cntr,
**	  ---------------		    &ss, &ist_posit)
**			    Get MSR/SS/U register values.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Output Args:
**	int   *msr	- The MSR register.
**	int   *ored_msr	- The 'ored'-MSR register. This gets zeroed every time
**			    a 'positioning' command is executed.
**	int   *fp_cntr	- A counter of the 'Position Faults' (*FP). This gets
**			    zeroed whenever ored_msr is zeroed.
**	int   *fr_cntr	- A counter of the 'Run Faults' (*FR). This gets
**			    zeroed whenever ored_msr is zeroed.
**	int   *ss	- The SS register. This will be -1 if the motor is busy.
**	float *ist_posit - The current position (U command) of the motor.
**  Modified Args:
**	none
**  Return status:
**	True if no problems detected, otherwise False and EL734_ErrInfo
**	can be called to identify the problem. Values of Errcode set by
**	EL734_GetStatus are (other values may be set by the called routines):
**	    EL734__BAD_TMO, BAD_LOC, BAD_CMD, BAD_OFL,
**		BAD_ADR, EMERG_STOP	--> see EL734_Open.
**	    EL734__BAD_ILLG --> one of the responses could probably not
**				be decoded. This could happen if there is noise
**				on the RS232C connection to the EL734.
**	If an error is detected, ist_posit is set to 0.0 and all other
**	arguments to -1.
**  Routines called:
**	EL734_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply
**  Description:
**	The routine issues an "MSR", "SS" and "U" command to the controller and
**	analyses the result. A count is kept of each time the *FP and *FR bits
**	are found to be set and an inclusive-or value of MSR is maintained.
**-------------------------------------------------------------------------
**    int EL734_GetZeroPoint (&handle, &zero_pt)
**	  ------------------
**			    Get zero-point of motor.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Output Args:
**	float *zero_pt	- The zero point of the EL734.
**  Return status:
**	Any of the errors generated by the called routines is possible plus:
**	    EL734__BAD_OVFL --> The encoder gearing ratio is zero so
**					the conversion would overflow.
**  Routines called:
**	EL734_AddCallStack, EL734_GetEncGearing, EL734_GetNullPoint
**  Description:
**	This routine returns the zero point of the motor in the same units
**	as used by the "P" and "U" commands. In other words, it reads the
**	"V" parameter and converts it from "encoder-step" units to physical
**	units using the encoder-gearing parameters.
**-------------------------------------------------------------------------
**    int   EL734_MoveNoWait (&handle, soll_posit)
**	    ----------------
**			    Move motor and don't wait for completion.
**  Input Args:
**	void  **handle	    - The pntr to the structure returned by EL734_Open.
**	float	soll_posit  - The position to which the motor should move.
**  Output Args:
**	none
**  Modified Args:
**	none
**  Return status:
**	True if no problems detected, otherwise False and EL734_ErrInfo
**	can be called to identify the problem. Values of Errcode set by
**	EL734_MoveNoWait are (other values may be set by the called routines):
**	    EL734__BAD_TMO, BAD_LOC, BAD_CMD, BAD_OFL,
**		BAD_ADR, EMERG_STOP	--> see EL734_Open.
**	    EL734__BAD_RNG  --> Destination is out-of-range.
**	    EL734__BAD_STP  --> Motor is disabled via Hardware "Stop"
**					signal.
**	    EL734__BAD_ILLG --> some other response obtained from EL734.
**					This could happen if there is noise
**					on the RS232C connection to the EL734.
**  Routines called:
**	EL734_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply
**  Description:
**	The appropriate "P" command is sent to the motor and the response
**	checked to check that it has been accepted. The fields "ored_msr",
**	"fp_cntr" and "fr_cntr" in the handle are cleared, if so.
**-------------------------------------------------------------------------
**    int   EL734_MoveWait (&handle, soll_posit, &ored_msr, &fp_cntr, &fr_cntr,
**	    --------------			    &ist_posit)
**			    Move motor and wait for completion.
**  Input Args:
**	void  **handle	    - The pntr to the structure returned by EL734_Open.
**	float	soll_posit  - The position to which the motor should move.
**  Output Args:
**	int	*ored_msr   \
**	int	*fp_cntr     \	Same as EL734_WaitIdle.
**	int	*fr_cntr     /
**	float	*ist_posit  /
**	none
**  Modified Args:
**	none
**  Return status:
**	True if no problems detected, otherwise False. If False, errcode (see
**	EL734_ErrInfo) will have been set by EL734_MoveNoWait or EL734_WaitIdle.
**  Routines called:
**	EL734_AddCallStack, EL734_MoveNoWait, EL734_WaitIdle
**  Description:
**	The routine calls EL734_MoveNoWait and, if successful, EL734_WaitIdle.
**-------------------------------------------------------------------------
**    int EL734_Open (&handle, host, port, chan, motor, id)
**	  ----------
**			    Open a connection to a motor.
**  Input Args:
**	char *host	- Name of host offering the TCP/IP service.
**	int   port	- Number of TCP/IP port of TCP/IP server.
**	int   chan	- RS-232-C Channel number on the TCP/IP server.
**	int   motor	- The motor to be driven.
**	char *id	- The expected ID of the device, normally "STPMC EL734".
**			    If id is NULL, the device ID is not checked.
**  Output Args:
**	void *handle	- A pointer to a structure of type EL734info needed for
**			   subsequent calls to EL734_... routines. Buffer space
**			   for the structure is allocated dynamically. It gets
**			   released via a call to EL734_Close.
**  Modified Args:
**	none
**  Return status:
**	True if no problems detected, otherwise False. If False, EL734_ErrInfo
**	can be called to identify the problem. Values of Errcode set by
**	EL734_Open are (other values may be set by the called routines):
**	  EL734__BAD_TMO     --> Time-out error ("?TMO" - this gets
**					generated by the RS232C server).
**	  EL734__BAD_LOC     --> EL734 off-line ("?LOC"). This should not
**					happen on calls to EL734_Open since it
**					sends an "RMT 1" cmnd.
**	  EL734__BAD_CMD     --> Command error ("?CMD"). This could be
**					caused by noise in the RS-232-C
**					transmission.
**	  EL734__BAD_OFL     --> Connection to EL734 broken ("?OFL").
**					This can get generated by RS232C_SRV
**					if, for example, the connection is via
**					a terminal server and the terminal
**					server loses power.
**	  EL734__BAD_ILLG    --> Some other unrecognised response. This
**					should never occur, of course!
**	  EL734__BAD_SOCKET  --> Call to "AsynSrv_Open" failed.
**	  EL734__BAD_DEV     --> Device has wrong ID
**	  EL734__BAD_MALLOC  --> Call to "malloc" failed
**	  EL734__BAD_ADR     --> Bad motor address ("?ADR"). Probably
**					a non-existent motor has been addressed.
**	  EL734__EMERG_STOP  --> Emergency stop ("*ES") detected.
**  Routines called:
**	AsynSrv_Open, the memory alloc routine "malloc", StrJoin,
**	EL734_Config, AsynSrv_SendCmnds, AsynSrv_GetReply,
**	AsynSrv_Close (if an error is detected).
**  Description:
**	The routine calls AsynSrv_Open to open a TCP/IP connection to a server
**	offering the "RS-232-C" service for an EL734 Motor Controller. "RMT 1"
**	and "ECHO 0" commands are sent to ensure the device is on-line, an "ID"
**	command is sent (only if 'id' is non-NULL) to ensure that an EL734 is
**	being addressed and an "MSR <motor>" command is sent to ensure that
**	the motor exists.
**    Note:
**	For all error status returns, there is no open connection to the server
**	and the handle is set to zero.
**-------------------------------------------------------------------------
**    int   EL734_PutOffline (&handle)
**	    ----------------
**			    Send "ECHO 1" and "RMT 0" commands to EL734 server.
**  Input Args:
**	void   **handle	- The pntr to the structure returned by EL734_Open.
**  Output Args:
**	none
**  Modified Args:
**	none
**  Return status:
**	True if no problems detected, otherwise False and errcode (see
**	EL734_ErrInfo) is set to indicate the nature of the problem.
**	Values of Errcode set by EL734_PutOffline are (other values may be set
**	by the called routines):
**	    EL734__BAD_ASYNSRV --> An error occurred in AsynSrv_Utility.
**					    Call AsynSrv_ErrInfo for more info.
**	    EL734__BAD_ILLG    --> an unrecognised response. This
**					should never occur, of course!
**  Routines called:
**	EL734_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply
**  Description:
**	The routine calls AsynSrv_SendCmnds to execute "RMT 1", "ECHO 1"
**	and "RMT 0" commands. The replies are checked.
**-------------------------------------------------------------------------
**    int   EL734_PutOnline (&handle, echo)
**	    ---------------
**			    Send "RMT 1" and "ECHO x" commands to EL734 server.
**  Input Args:
**	void   **handle	- The pntr to the structure returned by EL734_Open.
**	int      echo	- The value for the ECHO command.
**  Output Args:
**	none
**  Modified Args:
**	none
**  Return status:
**	True if no problems detected, otherwise False and errcode (see
**	EL734_ErrInfo) is set to indicate the nature of the problem.
**	Values of Errcode set by EL734_PutOnline are (other values may be set
**	by the called routines):
**	    EL734__BAD_PAR --> "echo" is not 0, 1 or 2.
**	    EL734__BAD_ASYNSRV --> An error occurred in AsynSrv_Utility.
**					    Call AsynSrv_ErrInfo for more info.
**	    EL734__BAD_ILLG    --> an unrecognised response. This
**					should never occur, of course!
**  Routines called:
**	EL734_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply
**  Description:
**	The routine calls AsynSrv_SendCmnds to execute "RMT 1" and "ECHO x"
**	commands. The replies are checked.
**-------------------------------------------------------------------------
**    int   EL734_SendCmnd (&handle, &cmnd, &rply, rply_size)
**	    --------------
**			    Send a command to RS232C server.
**  Input Args:
**	void   **handle	- The pntr to the structure returned by EL734_Open.
**	char	*cmnd	- A command, terminated by NULL, for sending to the
**			    EL734 counter controller. The command must have
**			    any necessary \r character included.
**	int	 rply_size - the size of the <rply> buffer.
**  Output Args:
**	char	*rply	- A buffer for receiving the reply.
**  Modified Args:
**	none
**  Return status:
**	True if no problems detected, otherwise False and errcode (see
**	EL734_ErrInfo) is set to indicate the nature of the problem.
**	Values of Errcode set by EL734_SendCmnd are (other values may be set
**	by the called routines):
**	    EL734__BAD_ASYNSRV --> An error occurred in AsynSrv_Utility.
**					    Call AsynSrv_ErrInfo for more info.
**  Routines called:
**	EL734_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply
**  Description:
**	The command is passed to AsynSrv_SendCmnds and the reply extracted.
**-------------------------------------------------------------------------
**    int EL734_SetAirCush (&handle, state)
**	  ----------------
**			    Set AC register value.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Input Args:
**	int   state	- The new state of the AC register. 0	     --> down
**							    non-zero --> up
**  Output Args:
**	none
**  Modified Args:
**	none
**  Return status:
**	True if no problems detected, otherwise False and EL734_ErrInfo
**	can be called to identify the problem. Values of Errcode set by
**	EL734_SetAirCush are (other values may be set by the called
**	routines):
**	    EL734__BAD_TMO, BAD_LOC, BAD_CMD, BAD_OFL,
**		BAD_ADR, EMERG_STOP	--> see EL734_Open.
**	    EL734__VFY_ERR --> the value for the AC register returned by the
**				call to EL734_GetAirCush was not the value which
**				was sent via the AC command. This could happen
**				if there is noise on the RS232C connection to
**				the EL734.
**  Routines called:
**	EL734_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply,
**	EL734_GetAirCush
**  Description:
**	The routine issues an "AC" command to the controller to set the air-
**	cushions of the motor up or down. It then calls EL734_GetAirCush
**	to check that the air-cushions were set correctly.
**-------------------------------------------------------------------------
**    int   EL734_SetErrcode (&info_ptr, &response, &cmnd)
**	    ----------------
**			    Set up EL734_errcode (for internal use only)
**  Input Args:
**	struct EL734info *info_ptr - The pntr to the structure returned by
**					EL734_Open.
**	char		 *response - The response received from a command.
**	char		 *cmnd	   - The command which was sent.
**  Output Args:
**	none
**  Modified Args:
**	none
**  Return status:
**	The value of EL734_errcode.
**  Routines called:
**	AsynSrv_SendCmnds
**  Description:
**	The command checks *response for certain keywords. If not recognised,
**	extra action is undertaken to try to see if the emergency stop state
**	is active or not.
**-------------------------------------------------------------------------
**    int EL734_SetHighSpeed (&handle, hi)
**	  ------------------
**			    Set J register value.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Input Args:
**	int   hi	- The maximum speed (J register). Units = Steps/sec.
**  Output Args:
**	none
**  Modified Args:
**	none
**  Return status:
**	True if no problems detected, otherwise False and EL734_ErrInfo
**	can be called to identify the problem. Values of Errcode set by
**	EL734_SetHighSpeed are (other values may be set by the called
**	routines):
**	    EL734__BAD_TMO, BAD_LOC, BAD_CMD, BAD_OFL,
**		BAD_ADR, EMERG_STOP	--> see EL734_Open.
**	    EL734__VFY_ERR --> the value for the J register returned by the call
**				to EL734_GetSpeeds was not the value which was
**				sent via the J command. This could happen if
**				there is noise on the RS232C connection to
**				the EL734.
**  Routines called:
**	EL734_AddCallStack, AsynSrv_SendCmnds, AsynSrv_GetReply, EL734_GetSpeeds
**  Description:
**	The routine issues a "J" command to the controller to set the max speed
**	of the motor. It then calls EL734_GetSpeeds to check that the speed
**	was set correctly.
**-------------------------------------------------------------------------
**    int EL734_SetLowSpeed (&handle, hi)
**	  -----------------
**			    Set G register value.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Input Args:
**	int   lo	- The start/stop speed (G register). Units = Steps/sec.
**  Description:
**	The routine is identical to the EL734_SetHighSpeed routine except that
**	a "G" command rather than a "J" command is issued to the controller to
**	set the start/stop speed.
**-------------------------------------------------------------------------
**    int EL734_SetRamp (&handle, ramp)
**	  -------------
**			    Set E register value.
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Input Args:
**	int   ramp	- The start/stop ramp (E register). Units = kHz/sec.
**  Description:
**	The routine is identical to the EL734_SetHighSpeed routine except that
**	an "E" command rather than a "J" command is issued to the controller to
**	set the start/stop ramp.
**-------------------------------------------------------------------------
**    int EL734_Stop (&handle)
**	  ----------
**			    Send a stop command to motor
**  Input Args:
**	void **handle	- The pointer to the structure returned by EL734_Open.
**  Output Args:
**	None
**  Description:
**	The routine is similar to EL734_GetEncGearing except that it issues
**	a "Q m" command instead of an "FD" command to the controller and
**	a null response (rather than parameter values) is expected.
**-------------------------------------------------------------------------
**    int   EL734_WaitIdle (&handle, &ored_msr, &fp_cntr, &fr_cntr, &ist_posit)
**	    --------------
**			    Wait till MSR goes to zero.
**  Input Args:
**	void  **handle	    - The pntr to the structure returned by EL734_Open.
**  Output Args:
**	int	*ored_msr   \
**	int	*fp_cntr     \	Same as EL734_GetStatus.
**	int	*fr_cntr     /
**	float	*ist_posit  /
**	none
**  Modified Args:
**	none
**  Return status:
**	True if no problems detected, otherwise False and Errcode (see
**	EL734_ErrInfo) will have been set by the called routines to indicate
**	the nature of the problem.
**  Routines called:
**	EL734_AddCallStack, EL734_GetStatus
**  Description:
**	Routine EL734_GetStatus is called repeatedly at a predefined frequency
**	until the MSR__BUSY bit in the MSR register is zero.
**-------------------------------------------------------------------------
**    void EL734_ZeroStatus (&handle)
**	  -----------------
**			    Zero the "ored-MSR" and fault counters.
**  Input Args:
**	void   **handle	- The pntr to the structure returned by EL734_Open.
**  Output Args:
**	none
**  Modified Args:
**	none
**  Return status:
**	none
**  Routines called:
**	none
**  Description:
**	The "ored-MSR" and fault counters in the handle are zeroed.
**============================================================================*/
/*
**---------------------------------------------------------------------------
**					Global Definitions
*/
#include    <stdlib.h>
#include    <stdio.h>
#include    <stdarg.h>
#include    <errno.h>
#include    <signal.h>
#include    <netdb.h>
#include    <sys/socket.h>
#include    <netinet/in.h>

#include    <string.h>

#ifdef	__VMS
#include    <unixio.h>
#else
#include    <unistd.h>
#ifdef FORTIFY
#include    <fortify.h>
#endif
#endif
/*-----------------------------------------------------------------*/
#include    <rs232c_def.h>
#include    <asynsrv_def.h>
#include    <el734_def.h>
#include    <sinq_prototypes.h>

#define True	1
#define False	0
/*--------------------------------------------------------------------------
**					Global Variables
*/
static int EL734_call_depth = 0;
static char EL734_routine[5][64];
static int EL734_errcode = 0;
static int EL734_errno, EL734_vaxc_errno;
char EL734_IllgText[256];
/*
**---------------------------------------------------------------------------
**		EL734_AddCallStack:  Add a routine name to the call stack.
**				     This allows EL734_ErrInfo to generate a
**				     trace-back in case of error.
*/
int EL734_AddCallStack(
/*	==================
*/ struct EL734info *pntr,
                        char *name)
{

  if (EL734_errcode != 0)
    return False;

  if (EL734_call_depth < 5) {
    strcpy(EL734_routine[EL734_call_depth], name);
    EL734_call_depth++;
  }

  if (pntr == NULL) {
    EL734_errcode = EL734__NOT_OPEN;
    return False;
  }

  if (pntr->asyn_info.skt <= 0) {
    memset(pntr->from_host.msg_size,
           '0', sizeof(pntr->from_host.msg_size));
    EL734_errcode = (pntr->asyn_info.skt < 0) ? EL734__FORCED_CLOSED
        : EL734__NO_SOCKET;
    return False;
  }
  return True;
}

/*
**---------------------------------------------------------------------------
**		EL734_Close:  Close a connection to a motor.
*/
int EL734_Close(
/*	===========
*/ void **handle,
                 int force_flag)
{

  struct EL734info *info_ptr;
  char buff[4];

  info_ptr = (struct EL734info *) *handle;
  if (info_ptr == NULL)
    return True;

  if (info_ptr->asyn_info.skt != 0) {
    if (info_ptr->asyn_info.skt > 0) {
      AsynSrv_Close(*handle, force_flag);
    }
  }
  free(*handle);
  *handle = NULL;

  return True;
}

/*
**---------------------------------------------------------------------------
**		EL734_Config:  Configure a connection to a motor.
*/
int EL734_Config(
/*	============
*/ void **handle,
                  ...)
{

  char buff[16];
  va_list ap;                   /* Pointer to variable args */
  char *txt_ptr;
  int intval;
  struct EL734info *info_ptr;
                    /*----------------------------------------------
		    */
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_Config"))
    return False;
                    /*----------------------------------------------
		    */
  va_start(ap, handle);         /* Set up var arg machinery */
  txt_ptr = va_arg(ap, char *); /* Get pntr to first parameter ident */
  while (txt_ptr != NULL) {
    if (strcmp(txt_ptr, "msecTmo") == 0) {
      intval = va_arg(ap, int);
      if ((intval < 100) || (intval > 999999)) {
        EL734_errcode = EL734__BAD_PAR;
        return False;
      }
      sprintf(buff, "%04d", intval / 100);      /* Convert to ASCII as ..
                                                 ** .. deci-secs */
      memcpy(info_ptr->asyn_info.tmo, buff, 4);
    } else if (strcmp(txt_ptr, "eot") == 0) {
      txt_ptr = va_arg(ap, char *);
      if (txt_ptr == NULL) {
        EL734_errcode = EL734__BAD_PAR;
        return False;
      }
      memcpy(info_ptr->asyn_info.eot, "\0\0\0\0", 4);
      switch (txt_ptr[0]) {
      case '3':
        info_ptr->asyn_info.eot[3] = txt_ptr[3];
      case '2':
        info_ptr->asyn_info.eot[2] = txt_ptr[2];
      case '1':
        info_ptr->asyn_info.eot[1] = txt_ptr[1];
      case '0':
        info_ptr->asyn_info.eot[0] = txt_ptr[0];
        break;
      default:
        EL734_errcode = EL734__BAD_PAR;
        return False;
      }
    } else if (strcmp(txt_ptr, "motor") == 0) {
      intval = va_arg(ap, int);
      if ((intval < 1) || (intval > 12)) {
        EL734_errcode = EL734__BAD_PAR;
        return False;
      }
      info_ptr->motor = intval;
    } else if (strcmp(txt_ptr, "chan") == 0) {
      intval = va_arg(ap, int);
      if ((intval < 0) || (intval > 255)) {
        EL734_errcode = EL734__BAD_PAR;
        return False;
      }
      info_ptr->asyn_info.chan = intval;
      sprintf(buff, "%04d", intval);    /* Convert to ASCII */
      memcpy(info_ptr->asyn_info.chan_char, buff, 4);
    } else {
      EL734_errcode = EL734__BAD_PAR;
      return False;
    }
    txt_ptr = va_arg(ap, char *);       /* Get pntr to next parameter ident */
  }

  if (EL734_errcode != 0)
    return False;
  EL734_call_depth--;
  return True;
}

/*
**---------------------------------------------------------------------------
**		EL734_EncodeMSR:    Encode the MSR status into text.
*/
char *EL734_EncodeMSR(char *text, int text_len,
/*	 ===============
*/ int msr,
                      int ored_msr, int fp_cntr, int fr_cntr)
{
  int len;
  char my_text[132];
  char my_text_0[32];

  if (msr == 0) {
    ored_msr = ored_msr & ~(MSR__BUSY); /* Zero "Busy" bit */
    if (ored_msr == MSR__OK) {
      StrJoin(text, text_len, "Status, MSR = Idle. Positioned OK.", "");
    } else {
      if ((ored_msr & MSR__OK) != 0) {
        StrJoin(text, text_len, "Status, MSR = Idle. Positioned OK. ", "");
      } else {
        StrJoin(text, text_len, "Status, MSR = Idle. ", "");
      }
      if ((ored_msr & MSR__REF_OK) != 0) {
        StrJoin(my_text, sizeof(my_text), text, "");
        StrJoin(text, text_len, my_text, "Ref. Pos'n OK. ");
      }
      if ((ored_msr & MSR__LIM_ERR) != 0) {
        StrJoin(my_text, sizeof(my_text), text, "");
        StrJoin(text, text_len, my_text, "Limit Switch Problem. ");
      }
      if ((ored_msr & MSR__AC_FAIL) != 0) {
        StrJoin(my_text, sizeof(my_text), text, "");
        StrJoin(text, text_len, my_text, "Air-Cushion Error. ");
      }
      if ((ored_msr & MSR__REF_FAIL) != 0) {
        StrJoin(my_text, sizeof(my_text), text, "");
        StrJoin(text, text_len, my_text, "Ref. Pos'n Fail. ");
      }
      if ((ored_msr & MSR__POS_FAIL) != 0) {
        StrJoin(my_text, sizeof(my_text), text, "");
        StrJoin(text, text_len, my_text, "Pos'n Fail. ");
      }
      if ((ored_msr & MSR__POS_FAULT) != 0) {
        StrJoin(my_text, sizeof(my_text), text, "");
        if (fp_cntr == 1) {
          StrJoin(text, text_len, my_text, "1 Pos'n Fault. ");
        } else {
          sprintf(my_text_0, "%d Pos'n Faults. ", fp_cntr);
          StrJoin(text, text_len, my_text, my_text_0);
        }
      }
      if ((ored_msr & MSR__RUN_FAIL) != 0) {
        StrJoin(my_text, sizeof(my_text), text, "");
        StrJoin(text, text_len, my_text, "Run Fail. ");
      }
      if ((ored_msr & MSR__RUN_FAULT) != 0) {
        StrJoin(my_text, sizeof(my_text), text, "");
        if (fr_cntr == 1) {
          StrJoin(text, text_len, my_text, "1 Run Fault. ");
        } else {
          sprintf(my_text_0, "%d Run Faults. ", fr_cntr);
          StrJoin(text, text_len, my_text, my_text_0);
        }
      }
      if ((ored_msr & MSR__HALT) != 0) {
        StrJoin(my_text, sizeof(my_text), text, "");
        StrJoin(text, text_len, my_text, "Halt. ");
      }
      if ((ored_msr & MSR__HI_LIM) != 0) {
        StrJoin(my_text, sizeof(my_text), text, "");
        StrJoin(text, text_len, my_text, "Hit HiLim. ");
      }
      if ((ored_msr & MSR__LO_LIM) != 0) {
        StrJoin(my_text, sizeof(my_text), text, "");
        StrJoin(text, text_len, my_text, "Hit LoLim. ");
      }
      if ((ored_msr & MSR__STOPPED) != 0) {
        StrJoin(my_text, sizeof(my_text), text, "");
        StrJoin(text, text_len, my_text, "Stopped. ");
      }
    }
  } else if ((msr & ~(0x2fff)) != 0) {
    StrJoin(text, text_len, "Status, MSR = ??", "");
  } else {
    sprintf(my_text, "%#x ", msr);
    StrJoin(text, text_len, "Status, MSR = ", my_text);
    if ((msr & MSR__LIM_ERR) != 0) {
      StrJoin(my_text, sizeof(my_text), text, "");
      StrJoin(text, text_len, my_text, "Limit Switch Problem/");
    }
    if ((msr & MSR__AC_FAIL) != 0) {
      StrJoin(my_text, sizeof(my_text), text, "");
      StrJoin(text, text_len, my_text, "Air-Cushion Error/");
    }
    if ((msr & MSR__REF_FAIL) != 0) {
      StrJoin(my_text, sizeof(my_text), text, "");
      StrJoin(text, text_len, my_text, "Ref. Pos'n Fail/");
    }
    if ((msr & MSR__POS_FAIL) != 0) {
      StrJoin(my_text, sizeof(my_text), text, "");
      StrJoin(text, text_len, my_text, "Pos'n Fail/");
    }
    if ((msr & MSR__POS_FAULT) != 0) {
      StrJoin(my_text, sizeof(my_text), text, "");
      StrJoin(text, text_len, my_text, "Pos'n Fault/");
    }
    if ((msr & MSR__RUN_FAIL) != 0) {
      StrJoin(my_text, sizeof(my_text), text, "");
      StrJoin(text, text_len, my_text, "Run Fail/");
    }
    if ((msr & MSR__RUN_FAULT) != 0) {
      StrJoin(my_text, sizeof(my_text), text, "");
      StrJoin(text, text_len, my_text, "Run Fault/");
    }
    if ((msr & MSR__HALT) != 0) {
      StrJoin(my_text, sizeof(my_text), text, "");
      StrJoin(text, text_len, my_text, "Halt/");
    }
    if ((msr & MSR__HI_LIM) != 0) {
      StrJoin(my_text, sizeof(my_text), text, "");
      StrJoin(text, text_len, my_text, "Hit HiLim/");
    }
    if ((msr & MSR__LO_LIM) != 0) {
      StrJoin(my_text, sizeof(my_text), text, "");
      StrJoin(text, text_len, my_text, "Hit LoLim/");
    }
    if ((msr & MSR__STOPPED) != 0) {
      StrJoin(my_text, sizeof(my_text), text, "");
      StrJoin(text, text_len, my_text, "Stopped/");
    }
    if ((msr & MSR__REF_OK) != 0) {
      StrJoin(my_text, sizeof(my_text), text, "");
      StrJoin(text, text_len, my_text, "Ref. Pos'n OK/");
    }
    if ((msr & MSR__OK) != 0) {
      StrJoin(my_text, sizeof(my_text), text, "");
      StrJoin(text, text_len, my_text, "OK/");
    }
    if ((msr & MSR__BUSY) != 0) {
      StrJoin(my_text, sizeof(my_text), text, "");
      StrJoin(text, text_len, my_text, "Busy/");
    }
    len = strlen(text);
    text[len - 1] = '\0';
  }
  return text;
}

/*
**---------------------------------------------------------------------------
**		EL734_EncodeSS:    Encode the SS flags into text.
*/
char *EL734_EncodeSS(char *text, int text_len, int ss)
{
/*	 ==============
*/
  int len;
  char my_text[132];
  char my_text_0[32];

  if (ss == 0) {
    StrJoin(text, text_len, "Flags, SS = 0", "");
  } else if ((ss & ~(0x3f)) != 0) {
    StrJoin(text, text_len, "Flags, SS = ??", "");
  } else {
    sprintf(my_text, "Flags, SS = 0x%02X ", ss);
    my_text_0[0] = '\0';
    if ((ss & 0x20) != 0)
      strcat(my_text_0, "LSX/");
    if ((ss & 0x10) != 0)
      strcat(my_text_0, "LS2/");
    if ((ss & 0x08) != 0)
      strcat(my_text_0, "LS1/");
    if ((ss & 0x04) != 0)
      strcat(my_text_0, "STP/");
    if ((ss & 0x02) != 0)
      strcat(my_text_0, "CCW/");
    if ((ss & 0x01) != 0)
      strcat(my_text_0, "HLT/");
    len = strlen(my_text_0);
    my_text_0[len - 1] = '\0';
    StrJoin(text, text_len, my_text, my_text_0);
  }
  return text;
}

/* 
**-------------------------------------------------------------------------
**		EL734_ErrInfo:  Return detailed status from last operation.
*/
void EL734_ErrInfo(
/*	=============
*/ char **entry_txt,
                    int *errcode, int *my_errno, int *vaxc_errno)
{

  int i;
  char buff[80], *txt;
  int asyn_errcode, asyn_errno, asyn_vaxerrno;
  char *asyn_errtxt;

  if (EL734_call_depth <= 0) {
    strcpy(EL734_routine[0], "EL734_no_error_detected");
    *errcode = 0;
    *my_errno = 0;
    *vaxc_errno = 0;
  } else {
    if (EL734_call_depth > 1) { /* Concatenate the names */
      for (i = 1; i < EL734_call_depth; i++) {
        strcat(EL734_routine[0], "/");
        StrJoin(EL734_routine[0], sizeof(EL734_routine),
                EL734_routine[0], EL734_routine[i]);
      }
    }
    *errcode = EL734_errcode;
    *my_errno = EL734_errno;
    *vaxc_errno = EL734_vaxc_errno;
    switch (EL734_errcode) {
    case EL734__BAD_ADR:
      txt = "/EL734__BAD_ADR";
      break;
    case EL734__BAD_ASYNSRV:
      txt = "/EL734__BAD_ASYNSRV";
      break;
    case EL734__BAD_CMD:
      txt = "/EL734__BAD_CMD";
      break;
    case EL734__BAD_DEV:
      txt = "/EL734__BAD_DEV";
      break;
    case EL734__BAD_ILLG:
      txt = "/EL734__BAD_ILLG";
      break;
    case EL734__BAD_LOC:
      txt = "/EL734__BAD_LOC";
      break;
    case EL734__BAD_MALLOC:
      txt = "/EL734__BAD_MALLOC";
      break;
    case EL734__BAD_OFL:
      txt = "/EL734__BAD_OFL";
      break;
    case EL734__BAD_OVFL:
      txt = "/EL734__BAD_OVFL";
      break;
    case EL734__BAD_PAR:
      txt = "/EL734__BAD_PAR";
      break;
    case EL734__BAD_RNG:
      txt = "/EL734__BAD_RNG";
      break;
    case EL734__BAD_SOCKET:
      txt = "/EL734__BAD_SOCKET";
      break;
    case EL734__BAD_STP:
      txt = "/EL734__BAD_STP";
      break;
    case EL734__BAD_TMO:
      txt = "/EL734__BAD_TMO";
      break;
    case EL734__EMERG_STOP:
      txt = "/EL734__EMERG_STOP";
      break;
    case EL734__FORCED_CLOSED:
      txt = "/EL734__FORCED_CLOSED";
      break;
    case EL734__NOT_OPEN:
      txt = "/EL734__NOT_OPEN";
      break;
    case EL734__NO_SOCKET:
      txt = "/EL734__NO_SOCKET";
      break;
    default:
      sprintf(buff, "/EL734__unknown_err_code: %d", EL734_errcode);
      txt = buff;
    }
    StrJoin(EL734_routine[0], sizeof(EL734_routine), EL734_routine[0],
            txt);
  }
  AsynSrv_ErrInfo(&asyn_errtxt, &asyn_errcode, &asyn_errno,
                  &asyn_vaxerrno);
  if (asyn_errcode != 0) {
    strcat(EL734_routine[0], "/");
    StrJoin(EL734_routine[0], sizeof(EL734_routine),
            EL734_routine[0], asyn_errtxt);
  }
  *entry_txt = EL734_routine[0];
  EL734_call_depth = 0;
  EL734_errcode = 0;
}

/*
**---------------------------------------------------------------------------
**		EL734_GetAirCush:  Get W and AC register values.
*/
int EL734_GetAirCush(
/*	================
*/ void **handle,
                      int *present, int *state)
{

  int status;
  struct EL734info *info_ptr;
  char cmnd0[10], cmnd1[10];
  char *rply_ptr, *rply_ptr0, *rply_ptr1;
                    /*----------------------------------------------
		    */
  *present = *state = 0;
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_GetAirCush"))
    return False;
                    /*----------------------------------------------
		    ** Send W and AC cmnds to EL734
		    */
  sprintf(cmnd0, "w %d\r", info_ptr->motor);
  sprintf(cmnd1, "ac %d\r", info_ptr->motor);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, cmnd1, NULL);
  if (!status) {
    *present = *state = 0;
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr1 = NULL;
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 != NULL)
      rply_ptr1 =
          AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
                           rply_ptr0);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (rply_ptr1 == NULL)
      rply_ptr1 = "?no_response";

    if ((sscanf(rply_ptr0, "%d", present) != 1) ||
        (sscanf(rply_ptr1, "%d", state) != 1)) {
      if (*rply_ptr0 == '?') {
        rply_ptr = rply_ptr0;
      } else if (*rply_ptr1 == '?') {
        rply_ptr = rply_ptr1;
      } else {
        rply_ptr = "?funny_response";
      }
      *present = *state = 0;
      EL734_SetErrcode(info_ptr, rply_ptr, "W\" or \"AC");
      return False;
    }
  }
  if (EL734_errcode != 0)
    return False;
  EL734_call_depth--;
  return True;
}

/*
**---------------------------------------------------------------------------
**		EL734_GetEncGearing:  Get FD register values.
*/
int EL734_GetEncGearing(
/*	===================
*/ void **handle,
                         int *nominator, int *denominator)
{

  int status;
  struct EL734info *info_ptr;
  char cmnd0[10];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  *nominator = *denominator = 0;
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_GetEncGearing"))
    return False;
                    /*----------------------------------------------
		    ** Send FD cmnd to EL734
		    */
  sprintf(cmnd0, "fd %d\r", info_ptr->motor);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, NULL);
  if (!status) {
    *nominator = *denominator = 0;
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (sscanf(rply_ptr0, "%d %d", nominator, denominator) == 2) {
      if (EL734_errcode != 0)
        return False;
      EL734_call_depth--;
      return True;
    }
    *nominator = *denominator = 0;
    EL734_SetErrcode(info_ptr, rply_ptr0, "FD");
    return False;
  }
}

/*
**---------------------------------------------------------------------------
**		EL734_GetId:  Get ID register value.
*/
int EL734_GetId(
/*	===========
*/ void **handle,
                 char *id_txt, int id_len)
{

  int status;
  struct EL734info *info_ptr;
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  *id_txt = '\0';
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_GetId"))
    return False;
                    /*----------------------------------------------
		    ** Send ID cmnd to EL734
		    */
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             "id\r", NULL);
  if (!status) {
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if ((rply_ptr0 != NULL) && (*rply_ptr0 != '\0') && (*rply_ptr0 != '?')) {
      StrJoin(id_txt, id_len, rply_ptr0, "");
      if (EL734_errcode != 0)
        return False;
      EL734_call_depth--;
      return True;
    }
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    EL734_SetErrcode(info_ptr, rply_ptr0, "ID");
    return False;
  }
}

/*
**---------------------------------------------------------------------------
**		EL734_GetLimits:  Get H register values.
*/
int EL734_GetLimits(
/*	===============
*/ void **handle,
                     float *lo, float *hi)
{

  int status;
  struct EL734info *info_ptr;
  char cmnd0[10];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  *lo = *hi = 0.0;
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_GetLimits"))
    return False;
                    /*----------------------------------------------
		    ** Send H cmnd to EL734
		    */
  sprintf(cmnd0, "h %d\r", info_ptr->motor);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, NULL);
  if (!status) {
    *lo = *hi = 0.0;
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (sscanf(rply_ptr0, "%f %f", lo, hi) == 2) {
      if (EL734_errcode != 0)
        return False;
      EL734_call_depth--;
      return True;
    }
    *lo = *hi = 0.0;
    EL734_SetErrcode(info_ptr, rply_ptr0, "H");
    return False;
  }
}

/*
**---------------------------------------------------------------------------
**		EL734_GetMotorGearing:  Get FM register values.
*/
int EL734_GetMotorGearing(
/*	=====================
*/ void **handle,
                           int *nominator, int *denominator)
{

  int status;
  struct EL734info *info_ptr;
  char cmnd0[10];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  *nominator = *denominator = 0;
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_GetMotorGearing"))
    return False;
                    /*----------------------------------------------
		    ** Send FM cmnd to EL734
		    */
  sprintf(cmnd0, "fm %d\r", info_ptr->motor);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, NULL);
  if (!status) {
    *nominator = *denominator = 0;
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (sscanf(rply_ptr0, "%d %d", nominator, denominator) == 2) {
      if (EL734_errcode != 0)
        return False;
      EL734_call_depth--;
      return True;
    }
    *nominator = *denominator = 0;
    EL734_SetErrcode(info_ptr, rply_ptr0, "FM");
    return False;
  }
}

/*
**---------------------------------------------------------------------------
**		EL734_GetNullPoint:  Get V register value.
*/
int EL734_GetNullPoint(
/*	==================
*/ void **handle,
                        int *null_pt)
{

  int status;
  struct EL734info *info_ptr;
  char cmnd0[10];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  *null_pt = 0;
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_GetNullPoint"))
    return False;
                    /*----------------------------------------------
		    ** Send V cmnd to EL734
		    */
  sprintf(cmnd0, "v %d\r", info_ptr->motor);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, NULL);
  if (!status) {
    *null_pt = 0;
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (sscanf(rply_ptr0, "%d", null_pt) == 1) {
      if (EL734_errcode != 0)
        return False;
      EL734_call_depth--;
      return True;
    }
    *null_pt = 0;
    EL734_SetErrcode(info_ptr, rply_ptr0, "V");
    return False;
  }
}

/*
**---------------------------------------------------------------------------
**		EL734_GetPosition:  Get U register value, the current position.
*/
int EL734_GetPosition(
/*	=================
*/ void **handle,
                       float *ist_posit)
{

  int status;
  struct EL734info *info_ptr;
  char cmnd0[10];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  *ist_posit = 0.0;
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_GetPosition"))
    return False;
                    /*----------------------------------------------
		    ** Send U cmnd to EL734
		    */
  sprintf(cmnd0, "u %d\r", info_ptr->motor);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, NULL);
  if (!status) {
    *ist_posit = 0.0;
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (sscanf(rply_ptr0, "%f", ist_posit) == 1) {
      if (EL734_errcode != 0)
        return False;
      EL734_call_depth--;
      return True;
    }
    *ist_posit = 0.0;
    EL734_SetErrcode(info_ptr, rply_ptr0, "U");
    return False;
  }
}

/*
**---------------------------------------------------------------------------
**		EL734_GetPrecision:  Get A register value.
*/
int EL734_GetPrecision(
/*	==================
*/ void **handle,
                        int *n_dec)
{

  int status;
  struct EL734info *info_ptr;
  char cmnd0[10];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  *n_dec = 3;
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_GetPrecision"))
    return False;
                    /*----------------------------------------------
		    ** Send A cmnd to EL734
		    */
  sprintf(cmnd0, "a %d\r", info_ptr->motor);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, NULL);
  if (!status) {
    *n_dec = 3;
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (sscanf(rply_ptr0, "%d", n_dec) == 1) {
      if (EL734_errcode != 0)
        return False;
      EL734_call_depth--;
      return True;
    }
    *n_dec = 3;
    EL734_SetErrcode(info_ptr, rply_ptr0, "A");
    return False;
  }
}

/*
**---------------------------------------------------------------------------
**		EL734_GetRefMode:  Get K register value.
*/
int EL734_GetRefMode(
/*	================
*/ void **handle,
                      int *mode)
{

  int status;
  struct EL734info *info_ptr;
  char cmnd0[10];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  *mode = 0;
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_GetRefMode"))
    return False;
                    /*----------------------------------------------
		    ** Send K cmnd to EL734
		    */
  sprintf(cmnd0, "k %d\r", info_ptr->motor);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, NULL);
  if (!status) {
    *mode = 0;
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (sscanf(rply_ptr0, "%d", mode) == 1) {
      if (EL734_errcode != 0)
        return False;
      EL734_call_depth--;
      return True;
    }
    *mode = 0;
    EL734_SetErrcode(info_ptr, rply_ptr0, "K");
    return False;
  }
}

/*
**---------------------------------------------------------------------------
**		EL734_GetRefParam:  Get Q register value.
*/
int EL734_GetRefParam(
/*	=================
*/ void **handle,
                       float *param)
{

  int status;
  struct EL734info *info_ptr;
  char cmnd0[10];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  *param = 0.0;
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_GetRefParam"))
    return False;
                    /*----------------------------------------------
		    ** Send Q cmnd to EL734
		    */
  sprintf(cmnd0, "q %d\r", info_ptr->motor);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, NULL);
  if (!status) {
    *param = 0.0;
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (sscanf(rply_ptr0, "%f", param) == 1) {
      if (EL734_errcode != 0)
        return False;
      EL734_call_depth--;
      return True;
    }
    *param = 0.0;
    EL734_SetErrcode(info_ptr, rply_ptr0, "Q");
    return False;
  }
}

/*
**---------------------------------------------------------------------------
**		EL734_GetSpeeds:  Get G/J/E register values.
*/
int EL734_GetSpeeds(
/*	===============
*/ void **handle,
                     int *lo, int *hi, int *ramp)
{

  int status;
  struct EL734info *info_ptr;
  char cmnd0[10];
  char cmnd1[10];
  char cmnd2[10];
  char *rply_ptr;
  char *rply_ptr0;
  char *rply_ptr1;
  char *rply_ptr2;
                    /*----------------------------------------------
		    */
  *lo = *hi = *ramp = 0;
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_GetSpeeds"))
    return False;
                    /*----------------------------------------------
		    ** Send G, J and E cmnds to EL734
		    */
  sprintf(cmnd0, "g %d\r", info_ptr->motor);
  sprintf(cmnd1, "j %d\r", info_ptr->motor);
  sprintf(cmnd2, "e %d\r", info_ptr->motor);

  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, cmnd1, cmnd2, NULL);
  if (!status) {
    *lo = *hi = *ramp = 0;
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr1 = rply_ptr2 = NULL;
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 != NULL)
      rply_ptr1 =
          AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
                           rply_ptr0);
    if (rply_ptr1 != NULL)
      rply_ptr2 =
          AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
                           rply_ptr1);

    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (rply_ptr1 == NULL)
      rply_ptr1 = "?no_response";
    if (rply_ptr2 == NULL)
      rply_ptr2 = "?no_response";

    if ((sscanf(rply_ptr0, "%d", lo) != 1) ||
        (sscanf(rply_ptr1, "%d", hi) != 1) ||
        (sscanf(rply_ptr2, "%d", ramp) != 1)) {
      if (*rply_ptr0 == '?') {
        rply_ptr = rply_ptr0;
      } else if (*rply_ptr1 == '?') {
        rply_ptr = rply_ptr1;
      } else if (*rply_ptr2 == '?') {
        rply_ptr = rply_ptr2;
      } else {
        rply_ptr = "?funny_response";
      }
      *lo = *hi = *ramp = 0;
      EL734_SetErrcode(info_ptr, rply_ptr, "G\", \"J\" or \"E");
      return False;
    }
  }
  if (EL734_errcode != 0)
    return False;
  EL734_call_depth--;
  return True;
}

/*
**---------------------------------------------------------------------------
**		EL734_GetStatus:  Get MSR/SS/U register values.
*/
int EL734_GetStatus(
/*	===============
*/ void **handle,
                     int *msr,
                     int *ored_msr,
                     int *fp_cntr, int *fr_cntr, int *ss, float *ist_posit)
{

  int status;
  struct EL734info *info_ptr;
  char cmnd0[10];
  char cmnd1[10];
  char cmnd2[10];
  char *rply_ptr;
  char *rply_ptr0;
  char *rply_ptr1;
  char *rply_ptr2;
                    /*----------------------------------------------
		    */
  *msr = *ored_msr = *fp_cntr = *fr_cntr = *ss = -1;
  *ist_posit = 0.0;
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_GetStatus"))
    return False;
                    /*----------------------------------------------
		    ** Send MSR, SS and U cmnds to EL734
		    */
  sprintf(cmnd0, "msr %d\r", info_ptr->motor);
  sprintf(cmnd1, "ss %d\r", info_ptr->motor);
  sprintf(cmnd2, "u %d\r", info_ptr->motor);

  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, cmnd1, cmnd2, NULL);
  if (!status) {
    *msr = *ored_msr = *fp_cntr = *fr_cntr = *ss = -1;
    *ist_posit = 0.0;
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr1 = rply_ptr2 = NULL;
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 != NULL)
      rply_ptr1 =
          AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
                           rply_ptr0);
    if (rply_ptr1 != NULL)
      rply_ptr2 =
          AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
                           rply_ptr1);

    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (rply_ptr1 == NULL)
      rply_ptr1 = "?no_response";
    if (rply_ptr2 == NULL)
      rply_ptr2 = "?no_response";

    if ((sscanf(rply_ptr0, "%x", msr) == 1) &&
        (sscanf(rply_ptr2, "%f", ist_posit) == 1)) {
      info_ptr->ored_msr = info_ptr->ored_msr | *msr;
      if ((*msr & MSR__POS_FAULT) != 0)
        info_ptr->fp_cntr++;
      if ((*msr & MSR__RUN_FAULT) != 0)
        info_ptr->fr_cntr++;
      *ored_msr = info_ptr->ored_msr;
      *fp_cntr = info_ptr->fp_cntr;
      *fr_cntr = info_ptr->fr_cntr;
      /* Remember: we may get "?BSY" for SS and
       ** this should not be treated as an error!
       */
      if (sscanf(rply_ptr1, "%x", ss) != 1)
        *ss = -1;
    } else {
      if (*rply_ptr0 == '?') {
        rply_ptr = rply_ptr0;
      } else if (*rply_ptr1 == '?') {
        rply_ptr = rply_ptr1;
      } else if (*rply_ptr2 == '?') {
        rply_ptr = rply_ptr2;
      } else {
        rply_ptr = "?funny_response";
      }
      *msr = *ored_msr = *fp_cntr = *fr_cntr = *ss = -1;
      *ist_posit = 0.0;
      EL734_SetErrcode(info_ptr, rply_ptr, "MSR\", \"SS\" or \"U");
      return False;
    }
  }
  if (EL734_errcode != 0)
    return False;
  EL734_call_depth--;
  return True;
}

/*
**---------------------------------------------------------------------------
**		EL734_GetZeroPoint: Get zero point (= converted V register value)
*/
int EL734_GetZeroPoint(
/*	==================
*/ void **handle,
                        float *zero_pt)
{

  int status, null_pt, nom, denom;
  struct EL734info *info_ptr;
  char cmnd0[10];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  *zero_pt = 0.0;
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_GetZeroPoint"))
    return False;
                    /*----------------------------------------------
		    ** Get V register value.
		    */
  status = EL734_GetNullPoint(handle, &null_pt);
  if (!status)
    return False;

                    /*----------------------------------------------
		    ** FD register values.
		    */
  status = EL734_GetEncGearing(handle, &nom, &denom);
  if (!status)
    return False;

  if (nom == 0) {
    EL734_errcode = EL734__BAD_OVFL;    /* Encoder gearing ratio is zero */
    return False;
  }

  *zero_pt = ((float) denom) / ((float) nom);
  *zero_pt *= (float) null_pt;

  if (EL734_errcode != 0)
    return False;
  EL734_call_depth--;
  return True;
}

/*
**---------------------------------------------------------------------------
**		EL734_MoveNoWait:  Move motor and don't wait for completion.
*/
int EL734_MoveNoWait(
/*	================
*/ void **handle,
                      float soll_posit)
{

  int status;
  struct EL734info *info_ptr;
  char cmnd0[32];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_MoveNoWait"))
    return False;
                    /*----------------------------------------------
		    ** Send P cmnd to EL734
		    */
  sprintf(cmnd0, "p %d %.3f\r", info_ptr->motor, soll_posit);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, NULL);
  if (!status) {
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (*rply_ptr0 == '\0' || *rply_ptr0 == '\r') {
      /*
       ** The command was accepted - so zero the statistics
       ** fields in the handle and return to caller.
       */
      info_ptr->ored_msr = info_ptr->fp_cntr = info_ptr->fr_cntr = 0;
      if (EL734_errcode != 0)
        return False;
      EL734_call_depth--;
      return True;
    }
    EL734_SetErrcode(info_ptr, rply_ptr0, "P");
    return False;
  }
}

/*
**---------------------------------------------------------------------------
**		EL734_MoveWait:  Move motor and wait for completion.
*/
int EL734_MoveWait(
/*	==============
*/ void **handle,
                    float soll_posit,
                    int *ored_msr,
                    int *fp_cntr, int *fr_cntr, float *ist_posit)
{

  int status;
  struct EL734info *info_ptr;
                    /*----------------------------------------------
		    */
  *ored_msr = *fp_cntr = *fr_cntr = -1;
  *ist_posit = 0.0;
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_MoveWait"))
    return False;
                    /*----------------------------------------------
		    ** Start the movement.
		    */
  status = EL734_MoveNoWait(handle, soll_posit);
  if (status) {
    status = EL734_WaitIdle(handle, ored_msr, fp_cntr, fr_cntr, ist_posit);
  }
  if (status && (EL734_errcode == 0))
    EL734_call_depth--;
  if (EL734_errcode != 0)
    return False;
  return status;
}

/*
**---------------------------------------------------------------------------
**		EL734_Open:  Open a connection to a motor.
*/
int EL734_Open(
/*	==========
*/ void **handle,
                char *host, int port, int chan, int motor, char *device_id)
{

  int my_msr, status;
  struct EL734info *my_handle;
  char tmo_save[4];
  char msr_cmnd[20];
  char *rply_ptr;
  char *rply_ptr0;
  char *rply_ptr1;
  char *rply_ptr2;
  char *rply_ptr3;
/*--------------------------------------------------------
**			Initialise the error info stack and pre-set the
**			routine name (in case of error).
*/
  EL734_errcode = EL734_errno = EL734_vaxc_errno = 0;
  strcpy(EL734_routine[0], "EL734_Open");
  EL734_call_depth = 1;
/*--------------------------------------------------------
**				    Assume trouble
*/
  *handle = NULL;
/*--------------------------------------------------------
**			    Reserve space for the data we need to store.
*/
  my_handle = (struct EL734info *) malloc(sizeof(*my_handle));
  if (my_handle == NULL) {
    EL734_errcode = EL734__BAD_MALLOC;  /* malloc failed!! */
    return False;
  }
  memset(my_handle, 0, sizeof(*my_handle));
/*--------------------------------------------------------
**				    Set up the connection
*/
  StrJoin(my_handle->asyn_info.host, sizeof(my_handle->asyn_info.host),
          host, "");
  my_handle->asyn_info.port = port;
  my_handle->asyn_info.chan = chan;
  status = AsynSrv_Open(&my_handle->asyn_info);
  if (!status) {
    EL734_errcode = EL734__BAD_SOCKET;
    GetErrno(&EL734_errno, &EL734_vaxc_errno);  /* Save errno info */
    fprintf(stderr, "\nEL734_Open/AsynSrv_Open: "
            "Failed to make connection.\n");
    free(my_handle);
    return False;
  }

  memcpy(tmo_save, my_handle->asyn_info.tmo, 4);        /* Save time-out */
  EL734_Config((void *) &my_handle, "msecTmo", 500,     /* Set a short time-out initially since
                                                         ** there should be no reason for the RMT,
                                                         ** ECHO or ID commands to take very long.
                                                         */
               "eot", "1\r", "motor", motor, NULL);
  my_handle->ored_msr = 0;
  my_handle->fp_cntr = 0;
  my_handle->fr_cntr = 0;
  /*
   ** Now ensure the EL734 is on-line. The first "RMT 1" command can
   ** fail due to pending characters in the EL734 input buffer causing
   ** the "RMT 1" to be corrupted. The response of the EL734 to this
   ** command is ignored for this reason (but the AsynSrv_SendCmnds
   ** status must be OK otherwise it indicates a network problem).
   */
  status = AsynSrv_SendCmnds(&my_handle->asyn_info,
                             &my_handle->to_host, &my_handle->from_host,
                             "rmt 1\r", NULL);
  sprintf(msr_cmnd, "msr %d\r", motor);
  if (status) {
    if (device_id != NULL) {
      status = AsynSrv_SendCmnds(&my_handle->asyn_info,
                                 &my_handle->to_host,
                                 &my_handle->from_host, "rmt 1\r",
                                 "echo 0\r", "id\r", msr_cmnd, NULL);
    } else {
      status = AsynSrv_SendCmnds(&my_handle->asyn_info,
                                 &my_handle->to_host,
                                 &my_handle->from_host, "rmt 1\r",
                                 "echo 0\r", "echo 0\r", msr_cmnd, NULL);
    }
  }
  memcpy(my_handle->asyn_info.tmo, tmo_save, 4);        /* Restore time-out */
  if (!status) {
    /* Some error occurred in AsynSrv_SendCmnds */
    EL734_errcode = EL734__BAD_ASYNSRV;
    AsynSrv_Close(&my_handle->asyn_info, False);
    free(my_handle);
    return False;
  } else {
    /* Check the responses carefully. The 3rd response should
     ** be the device identifier (if to be checked). The 4th
     ** response should be a hex integer.
     ** MK: But first we check for *ES, emergency stop. 
     ** The desired behaviour is that we continue in this
     ** case and hope for the best.
     */
    rply_ptr1 = rply_ptr2 = rply_ptr3 = NULL;
    rply_ptr0 =
        AsynSrv_GetReply(&my_handle->asyn_info, &my_handle->from_host,
                         NULL);
    if (rply_ptr0 != NULL)
      rply_ptr1 =
          AsynSrv_GetReply(&my_handle->asyn_info, &my_handle->from_host,
                           rply_ptr0);
    if (rply_ptr1 != NULL)
      rply_ptr2 =
          AsynSrv_GetReply(&my_handle->asyn_info, &my_handle->from_host,
                           rply_ptr1);
    if (rply_ptr2 != NULL)
      rply_ptr3 =
          AsynSrv_GetReply(&my_handle->asyn_info, &my_handle->from_host,
                           rply_ptr2);

    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (rply_ptr1 == NULL)
      rply_ptr1 = "?no_response";
    if (rply_ptr2 == NULL)
      rply_ptr2 = "?no_response";
    if (rply_ptr3 == NULL)
      rply_ptr3 = "?no_response";

    if (strstr(rply_ptr0, "*ES") != NULL) {
      *handle = my_handle;
      EL734_call_depth--;
      return True;
    }

    if (*rply_ptr1 == '?')
      rply_ptr0 = rply_ptr1;
    if (*rply_ptr2 == '?')
      rply_ptr0 = rply_ptr2;
    if (*rply_ptr3 == '?')
      rply_ptr0 = rply_ptr3;
    if (*rply_ptr0 != '?') {
      if (device_id != NULL) {  /* Check device ID? */
        if (*rply_ptr2 == '\0') {       /* Yes. But if response is blank, it
                                         ** may be because Emergency Stop is set.
                                         */
          EL734_SetErrcode(my_handle, rply_ptr2, "ID");
          AsynSrv_Close(&my_handle->asyn_info, False);
          free(my_handle);
          return False;
        } else {
          if (strncmp(rply_ptr2, device_id, strlen(device_id)) != 0) {
            EL734_errcode = EL734__BAD_DEV;     /* Device has wrong ID */
            AsynSrv_Close(&my_handle->asyn_info, False);
            free(my_handle);
            return False;
          }
        }
      }
      if (sscanf(rply_ptr3, "%x", &my_msr) != 1) {
        /* MSR response is bad */
        EL734_SetErrcode(my_handle, rply_ptr3, msr_cmnd);       /* Check for *ES */
        if (EL734_errcode != EL734__EMERG_STOP)
          EL734_errcode = EL734__BAD_DEV;
        AsynSrv_Close(&my_handle->asyn_info, False);
        free(my_handle);
        return False;
      }
      /*
       ** The connection is complete. Pass the data structure
       ** back to the caller as a handle.
       */
      *handle = my_handle;
      if (EL734_errcode != 0)
        return False;
      EL734_call_depth--;
      return True;
    } else {
      EL734_errcode = EL734__BAD_DEV;
      if (strcmp(rply_ptr0, "?OFL") == 0)
        EL734_errcode = EL734__BAD_OFL;
      if (strcmp(rply_ptr0, "?CMD") == 0)
        EL734_errcode = EL734__BAD_CMD;
      if (strcmp(rply_ptr0, "?LOC") == 0)
        EL734_errcode = EL734__BAD_LOC;
      if (strcmp(rply_ptr0, "?ADR") == 0)
        EL734_errcode = EL734__BAD_ADR;
      if (strcmp(rply_ptr0, "*ES") == 0)
        EL734_errcode = EL734__EMERG_STOP;
      if (strncmp(rply_ptr0, "?TMO", 4) == 0)
        EL734_errcode = EL734__BAD_TMO;
      if (EL734_errcode == EL734__BAD_DEV)
        fprintf(stderr, " Unrecognised initial response: \"%s\"\n",
                rply_ptr0);
    }
  }
  AsynSrv_Close(&my_handle->asyn_info, False);
  free(my_handle);
  return False;
}

/*
**---------------------------------------------------------------------------
**		EL734_PutOffline:  put the EL734 off-line
*/
int EL734_PutOffline(
/*	================
*/ void **handle)
{

  int status;
  struct EL734info *info_ptr;
  char *rply_ptr0, *rply_ptr1, *rply_ptr2;
                    /*----------------------------------------------
		    */
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_PutOffline"))
    return False;
                    /*----------------------------------------------
		    ** The problem which this routine has is that the EL734
		    ** may already be off-line. The following is, therefore,
		    ** rather pedantic for most cases which occur in practice.
		    */
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             "\r", "rmt 1\r", "echo 1\r", "rmt 0\r", NULL);
  if (!status) {
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  }

  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             "RMT\r", "", NULL);
  if (!status) {
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  }

  rply_ptr0 =
      AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
  rply_ptr1 =
      AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
                       rply_ptr0);
  if (rply_ptr0 == NULL)
    rply_ptr0 = "?no_response";
  if (rply_ptr1 == NULL)
    rply_ptr1 = "?no_response";
  if ((strcmp(rply_ptr0, "RMT") == 0) && (strcmp(rply_ptr1, "\n0") == 0)) {
    EL734_call_depth--;
    return True;
  }

  EL734_SetErrcode(info_ptr, rply_ptr0, "RMT");
  return False;
}

/*
**---------------------------------------------------------------------------
**		EL734_PutOnline:  put the EL734 on-line
*/
int EL734_PutOnline(
/*	===============
*/ void **handle,
                     int echo)
{

  int status, my_echo;
  struct EL734info *info_ptr;
  char cmnd0[10];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_PutOnline"))
    return False;
                    /*----------------------------------------------
		    */
  if ((echo != 0) && (echo != 1) && (echo != 2)) {
    EL734_errcode = EL734__BAD_PAR;
    return False;
  }
                    /*----------------------------------------------
		    ** The problem which this routine has is that the state
		    ** of the EL734 is not known. The following is, therefore,
		    ** rather pedantic for most cases which occur in practice.
		    */
  sprintf(cmnd0, "echo %d\r", echo);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             "\r", "rmt 1\r", cmnd0, NULL);
  if (!status) {
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  }

  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             "echo\r", NULL);
  if (!status) {
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  }

  rply_ptr0 =
      AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
  if (rply_ptr0 == NULL)
    rply_ptr0 = "?no_response";
  if (strcmp(rply_ptr0, "ECHO") == 0) {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host,
                         rply_ptr0);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
  }
  if ((sscanf(rply_ptr0, "%d", &my_echo) == 1) && (my_echo == echo)) {
    EL734_call_depth--;
    return True;
  }

  EL734_SetErrcode(info_ptr, rply_ptr0, "ECHO");
  return False;
}

/*
**---------------------------------------------------------------------------
**		EL734_SendCmnd - Send a command to RS232C server.
*/
int EL734_SendCmnd(
/*	==============
*/ void **handle,
                    char *cmnd, char *rply, int rply_size)
{

  struct EL734info *info_ptr;
  int my_status;
  char *rply_ptr;
                    /*----------------------------------------------
		    */
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_SendCmnd"))
    return False;
                    /*----------------------------------------------
		    ** Send command to EL734.
		    */
  my_status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                                &info_ptr->to_host, &info_ptr->from_host,
                                cmnd, NULL);
  if (!my_status) {
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr == NULL)
      rply_ptr = "?no_response";
    StrJoin(rply, rply_size, rply_ptr, "");
  }

  if (EL734_errcode != 0)
    return False;
  EL734_call_depth--;
  return True;
}

/*
**---------------------------------------------------------------------------
**		EL734_SetAirCush:  Set the air-cushion register (AC register)
*/
int EL734_SetAirCush(
/*	================
*/ void **handle,
                      int state)
{

  int status, dum1, my_state;
  struct EL734info *info_ptr;
  char cmnd0[32];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_SetAirCush"))
    return False;
                    /*----------------------------------------------
		    ** Send AC cmnd to EL734
		    */
  if (state != 0)
    state = 1;
  sprintf(cmnd0, "ac %d %d\r", info_ptr->motor, state);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, NULL);
  if (!status) {
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (*rply_ptr0 == '\0') {
      /*
       ** The command was accepted - check value is set OK.
       */
      status = EL734_GetAirCush(handle, &dum1, &my_state);
      if (!status)
        return False;
      if (state != my_state) {
        EL734_errcode = EL734__VFY_ERR;
        return False;
      }
      EL734_call_depth--;
      return True;
    }
    EL734_SetErrcode(info_ptr, rply_ptr0, "AC");
    return False;
  }
}

/*
**---------------------------------------------------------------------------
**		EL734_SetErrcode - Set up EL734_errcode
*/
int EL734_SetErrcode(
/*	================
*/ struct EL734info *info_ptr,
                      char *response, char *cmnd)
{

  int status;
  char *rply;
  char tmo_save[4];
  char eot_save[4];

  EL734_errcode = EL734__BAD_ILLG;
  if (strcmp(response, "?OFL") == 0)
    EL734_errcode = EL734__BAD_OFL;
  if (strcmp(response, "?CMD") == 0)
    EL734_errcode = EL734__BAD_CMD;
  if (strcmp(response, "?LOC") == 0)
    EL734_errcode = EL734__BAD_LOC;
  if (strcmp(response, "?ADR") == 0)
    EL734_errcode = EL734__BAD_ADR;
  if (strcmp(response, "?RNG") == 0)
    EL734_errcode = EL734__BAD_RNG;
  if (strcmp(response, "*ES") == 0)
    EL734_errcode = EL734__EMERG_STOP;
  if (strcmp(response, "*MS") == 0)
    EL734_errcode = EL734__BAD_STP;
  if (strncmp(response, "?TMO", 4) == 0)
    EL734_errcode = EL734__BAD_TMO;
  if (EL734_errcode != EL734__BAD_ILLG)
    return EL734_errcode;
  /*
   ** The response is not recognised. Perhaps the emergency stop
   ** signal is set. To check this, it is necessary to turn off
   ** terminator checking since the EL734 prefixes its "*ES"
   ** response with a <Return> character. We also therefore set
   ** a very short time-out.
   */
  memcpy(tmo_save, info_ptr->asyn_info.tmo, 4); /* Save time-out */
  memcpy(eot_save, info_ptr->asyn_info.eot, 4); /* Save terminators */
  AsynSrv_Config(&info_ptr->asyn_info, "msecTmo", 100,  /* Set short time-out */
                 "eot", "0",    /* Set no terminator */
                 NULL);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             "ID\r", NULL);
  memcpy(info_ptr->asyn_info.eot, eot_save, 4); /* Restore terminators */
  memcpy(info_ptr->asyn_info.tmo, tmo_save, 4); /* Restore time-out */
  if (status) {
    rply =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply == NULL)
      rply = "?no_response";
  } else {
    rply = "?no_response";
  }
  if (strstr(rply, "*ES") != NULL)
    EL734_errcode = EL734__EMERG_STOP;

  if ((EL734_errcode == EL734__BAD_ILLG) && (cmnd != NULL)) {
    fprintf(stderr, " Unrecognised response to \"%s\" command: \"%s\"\n",
            cmnd, response);
    strcpy(EL734_IllgText, cmnd);
    strcat(EL734_IllgText, " : ");
    strcat(EL734_IllgText, response);
  }
  return EL734_errcode;
}

/*
**---------------------------------------------------------------------------
**		EL734_SetHighSpeed:  Set the max speed (J register)
*/
int EL734_SetHighSpeed(
/*	==================
*/ void **handle,
                        int hi)
{

  int status, my_lo, my_hi, my_ramp;
  struct EL734info *info_ptr;
  char cmnd0[32];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_SetHighSpeed"))
    return False;
                    /*----------------------------------------------
		    ** Send J cmnd to EL734
		    */
  sprintf(cmnd0, "j %d %d\r", info_ptr->motor, hi);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, NULL);
  if (!status) {
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (*rply_ptr0 == '\0') {
      /*
       ** The command was accepted - check value is set OK.
       */
      status = EL734_GetSpeeds(handle, &my_lo, &my_hi, &my_ramp);
      if (!status)
        return False;
      if (hi != my_hi) {
        EL734_errcode = EL734__VFY_ERR;
        return False;
      }
      EL734_call_depth--;
      return True;
    }
    EL734_SetErrcode(info_ptr, rply_ptr0, "J");
    return False;
  }
}

/*
**---------------------------------------------------------------------------
**		EL734_SetLowSpeed:  Set the start/stop speed (G register)
*/
int EL734_SetLowSpeed(
/*	=================
*/ void **handle,
                       int lo)
{

  int status, my_lo, my_hi, my_ramp;
  struct EL734info *info_ptr;
  char cmnd0[32];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_SetLowSpeed"))
    return False;
                    /*----------------------------------------------
		    ** Send G cmnd to EL734
		    */
  sprintf(cmnd0, "g %d %d\r", info_ptr->motor, lo);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, NULL);
  if (!status) {
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (*rply_ptr0 == '\0') {
      /*
       ** The command was accepted - check value is set OK.
       */
      status = EL734_GetSpeeds(handle, &my_lo, &my_hi, &my_ramp);
      if (!status)
        return False;
      if (lo != my_lo) {
        EL734_errcode = EL734__VFY_ERR;
        return False;
      }
      EL734_call_depth--;
      return True;
    }
    EL734_SetErrcode(info_ptr, rply_ptr0, "G");
    return False;
  }
}

/*
**---------------------------------------------------------------------------
**		EL734_SetRamp:  Set the start/stop ramp (E register)
*/
int EL734_SetRamp(
/*	=============
*/ void **handle,
                   int ramp)
{

  int status, my_lo, my_hi, my_ramp;
  struct EL734info *info_ptr;
  char cmnd0[32];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_SetRamp"))
    return False;
                    /*----------------------------------------------
		    ** Send E cmnd to EL734
		    */
  sprintf(cmnd0, "e %d %d\r", info_ptr->motor, ramp);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, NULL);
  if (!status) {
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (*rply_ptr0 == '\0') {
      /*
       ** The command was accepted - check value is set OK.
       */
      status = EL734_GetSpeeds(handle, &my_lo, &my_hi, &my_ramp);
      if (!status)
        return False;
      if (ramp != my_ramp) {
        EL734_errcode = EL734__VFY_ERR;
        return False;
      }
      EL734_call_depth--;
      return True;
    }
    EL734_SetErrcode(info_ptr, rply_ptr0, "E");
    return False;
  }
}

/*
**---------------------------------------------------------------------------
**		EL734_Stop:  Send a stop command to motor.
*/
int EL734_Stop(
/*	==========
*/ void **handle)
{

  int status;
  struct EL734info *info_ptr;
  char cmnd0[10];
  char *rply_ptr0;
                    /*----------------------------------------------
		    */
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_Stop"))
    return False;
                    /*----------------------------------------------
		    ** Send S cmnd to EL734
		    */
  sprintf(cmnd0, "s %d\r", info_ptr->motor);
  status = AsynSrv_SendCmnds(&info_ptr->asyn_info,
                             &info_ptr->to_host, &info_ptr->from_host,
                             cmnd0, NULL);
  if (!status) {
    EL734_errcode = EL734__BAD_ASYNSRV;
    return False;
  } else {
    rply_ptr0 =
        AsynSrv_GetReply(&info_ptr->asyn_info, &info_ptr->from_host, NULL);
    if (rply_ptr0 == NULL)
      rply_ptr0 = "?no_response";
    if (rply_ptr0[0] == '\0') {
      if (EL734_errcode != 0)
        return False;
      EL734_call_depth--;
      return True;
    }
    EL734_SetErrcode(info_ptr, rply_ptr0, "S");
    return False;
  }
}

/*
**---------------------------------------------------------------------------
**		EL734_WaitIdle:  Wait till MSR goes to zero.
*/
int EL734_WaitIdle(
/*	==============
*/ void **handle,
                    int *ored_msr,
                    int *fp_cntr, int *fr_cntr, float *ist_posit)
{
#ifdef __VMS
#include	<lib$routines.h>
#define hibernate   lib$wait (0.25)
#else
#include    <unistd.h>
#include    <time.h>
  struct timespec delay = { 0, 250000000 };
  struct timespec delay_left;

#ifdef LINUX
#define hibernate   nanosleep(&delay, &delay_left)
#else
#define hibernate   nanosleep_d9 (&delay, &delay_left)
#endif

#endif
  int msr, ss;
  struct EL734info *info_ptr;
                    /*----------------------------------------------
		    */
  *ored_msr = *fp_cntr = *fr_cntr = -1;
  *ist_posit = 0.0;
  info_ptr = (struct EL734info *) *handle;

  if (!EL734_AddCallStack(info_ptr, "EL734_WaitIdle"))
    return False;
                    /*----------------------------------------------
		    ** Poll the motor status till not moving.
		    */
  while (EL734_GetStatus(handle,
                         &msr, ored_msr, fp_cntr, fr_cntr, &ss,
                         ist_posit)) {
    if ((msr & MSR__BUSY) == 0) {
      if (EL734_errcode != 0)
        return False;
      EL734_call_depth--;
      return True;
    }
    hibernate;
  }
  return False;                 /* Error detected in EL734_GetStatus */
}

/*
**---------------------------------------------------------------------------
**		EL734_ZeroStatus:  Zero the "ored-MSR" and fault counters.
*/
void EL734_ZeroStatus(
/*	================
*/ void **handle)
{

  struct EL734info *info_ptr;
  /*
   ** Do nothing if no handle!
   */
  info_ptr = (struct EL734info *) *handle;
  if (info_ptr == NULL)
    return;
  /*
   ** Zero the data structure items.
   */
  info_ptr->ored_msr = 0;
  info_ptr->fp_cntr = 0;
  info_ptr->fr_cntr = 0;
  memset(info_ptr->from_host.msg_size,
         '0', sizeof(info_ptr->from_host.msg_size));
  return;
}

/*-------------------------------------------- End of EL734_Utility.C =======*/
