	SUBROUTINE DIAL_RIXON
C
C	This routine dials the phone number for the RIXON R212A modem.
C
	INCLUDE 'COM.INC/NOLIST'

	CHARACTER*(*) NFG_MSG, BAD_MSG
	PARAMETER TMO = 10		! Read timeout count.

	INTEGER*4 AUTO_RETRY, STATUS

	PARAMETER (NFG_MSG = SS//
	1 '*** The modem is not responding, aborting... ***'//BELL//SS)
	PARAMETER (BAD_MSG = SS//
	1 '*** Bad response from the modem, aborting... ***'//BELL//SS)

	IF (PHONE_SIZE .EQ. 0) RETURN	! No phone number to dial.
C
C	Setup the terminator table to terminate the read on the
C	RIXON prompt character (dollar sign "$" = 36 decimal).
C
	CALL SET_TERMINATOR(TPTR,TTBL,%REF('$'))

	AUTO_RETRY = 0			! Initialize retry counter.
C
C	Now queue up a read to the remote.
C
100	IF (.NOT. POST_READ(RBUFFER,TMO,TPTR)) RETURN
C
C	To put the RIXON in autodial (interactive) mode, we must
C	send two carriage returns and then wait for the read.
C
	XBUFFER(1) = CR			! Fill in a carraige return.
	CALL WRITE_REMOTE(XBUFFER(1),1)	! Second gets appended later.
	IF (.NOT. WAIT_FOR_READ(RBUFFER,RDESC)) THEN
		IF (CONTROLC_TYPED) RETURN ! Return if aborted.
		AUTO_RETRY = AUTO_RETRY + 1 ! Bump the retry count.
		IF (AUTO_RETRY .EQ. AUTODIAL_LIMIT) THEN
			CALL WRITE_USER(NFG_MSG)
			RETURN
		ELSE
			GO TO 100	! Try it again ...
		ENDIF
	ENDIF
	AUTO_RETRY = 0			! Reinitialize the retry counter.
C
C	Now we'll do a keyboard dial command.
C
C	$ K
C	*** NUMBER:
C
	CALL SET_TERMINATOR(TPTR,TTBL,%REF(':'))! Terminate read on colon.
	IF (.NOT. POST_READ(RBUFFER,TMO,TPTR)) RETURN ! Read the prompt echo.
	CALL WRITE_RIXON(%REF('K'),1)		! Doing a keyboard dial.
	IF (.NOT. WAIT_FOR_READ(RBUFFER,RDESC)) THEN
		CALL WRITE_USER(BAD_MSG)	! Tell user its no good.
		RETURN
	ENDIF
C
C	Now send the phone number.
C
	IF (.NOT. POST_READ(RBUFFER,TMO,TPTR)) RETURN ! Read "DIALING:".
	CALL WRITE_RIXON(%REF(PHONE_NUMBER),PHONE_SIZE) ! Send the number.
	CALL WRITE_RIXON(CR,1)			! Finish with RETURN.
300	IF (.NOT. WAIT_FOR_READ(RBUFFER,RDESC)) THEN
310		CALL WRITE_RIXON(CR,1)		! Any character to abort.
		CALL WRITE_USER(BAD_MSG)	! Tell user its no good.
		RETURN
	ENDIF
C
C	Now set the read terminator to '>'.  The RIXON will display
C	one of the following messages after dialing:
C
C	*** DIALING: phone_number <ON LINE>
C				  <RINGING...NO ANSWER...CALL ABORTED>
C				  <DEAD PHONE....CALL ABORTED>
C				  <BUSY.....CALL ABORTED>
C
	CALL SET_TERMINATOR(TPTR,TTBL,%REF('>'))
	IF (.NOT. POST_READ(RBUFFER,30,TPTR)) RETURN ! Get the dial response.
	IF (.NOT. WAIT_FOR_READ(RBUFFER,RDESC)) GO TO 310
C
C	If the response from the modem was no answer, try again.
C	If we need to redial, the response from the RIXON is:
C
C	$ R
C	*** DIALING: phone_number <responses listed above>
C
	IF (FIND_SUBSTRING('NO ANSWER',RDESC) .GT. 0) THEN
		AUTO_RETRY = AUTO_RETRY + 1	! Bump the retry counter.
		IF (AUTO_RETRY .EQ. AUTODIAL_LIMIT) RETURN
		CALL WRITE_RIXON(%REF('R'),1)	! Tell RIXON to redial.
		CALL SET_TERMINATOR(TPTR,TTBL,%REF(':'))
		IF (.NOT. POST_READ(RBUFFER,TMO,TPTR)) RETURN
		GO TO 300
	ENDIF
C
C	If the modem is really online, set the flags to say so.
C
	IF (FIND_SUBSTRING('<ON LINE>',RDESC) .GT. 0) THEN
		MODEM_ONLINE = .TRUE.		! Show modem is online.
		REMOTE = .TRUE.			! Make VMS look online.
C
C	The RIXON also echos <CR><LF><BELL> once online.  These
C	characters must be cleared to prevent auto login problems.
C
		CALL SET_TERMINATOR(TPTR,TTBL,%REF(BELL))
		IF (.NOT. POST_READ(RBUFFER,2,TPTR)) RETURN
		CALL WAIT_FOR_READ(RBUFFER,RDESC)! Wait for the read.
	ENDIF
	RETURN
	END

	SUBROUTINE SIGNOFF_RIXON
C
C	This routine is used to signoff the RIXON (place in auto-answer)
C	mode after hanging up the modem.
C
	INCLUDE 'COM.INC/NOLIST'

C
C	Since the terminal driver turns DTR off for approximatly 5 seconds,
C	we issue a read with this timeout.  The read will be terminated by
C	a RIXON prompt ($) if we were online.
C
	CALL SET_TERMINATOR(TPTR,TTBL,%REF('$'))
	IF (.NOT. POST_READ(RBUFFER,5,TPTR)) RETURN ! Read the prompt (if any).
	CALL WAIT_FOR_READ(RBUFFER,RDESC)	! Wait for the read.
C
C	Now signoff the RIXON by send a Q for quit.  The response from
C	the RIXON takes up to 3 seconds at 300 baud.
C
	CALL WRITE_RIXON(%REF('Q'),1)		! Tell the RIXON to quit.
	IF (.NOT. POST_READ(RBUFFER,3,TPTR)) RETURN ! Read the prompt (if any).
	CALL WAIT_FOR_READ(RBUFFER,RDESC)	! Wait for the read.
	RETURN
	END

	LOGICAL FUNCTION POST_READ(BUFFER,TMO_COUNT,TTABLE)
C
C	This routine is used to queue a read request to the remote
C	terminal.
C
C	Inputs:
C		BUFFER - buffer to read into. 
C		TMO_COUNT - read timeout count.
C		TTABLE - termination table address.
C
C	Outputs:
C		Returns status of QIO system service.
C
	INCLUDE 'COM.INC/NOLIST'

	LOGICAL*1 BUFFER(1)
	INTEGER*4 TMO_COUNT, TTABLE

	POST_READ = SYS$QIO(%VAL(REFN_IN),%VAL(RCHAN_IN),
	1	%VAL(IO$_READLBLK + IO$M_NOECHO + IO$M_TIMED),
	1	RIOSB,,,BUFFER,%VAL(READ_SIZE),
	1	%VAL(TMO_COUNT),TTABLE,,)

	CALL CHECK_STATUS('POST_READ',POST_READ)
	RETURN
	END

	LOGICAL FUNCTION WAIT_FOR_READ(BUFFER,DESC)
C
C	This routine is used to wait for a posted read, and display
C	the data read (if any).
C
C	Inputs:
C		BUFFER = Buffer to read data into.
C		DESC = Address of descriptor to fill in.
C
C	Outputs:
C		Returns .TRUE. if read was successful, else
C			.FALSE. if unsuccessful (includes timeout).
C
	INCLUDE 'COM.INC/NOLIST'

	LOGICAL*1 BUFFER(1)
	INTEGER*4 DESC(2)

	DESC(1) = 0			! Initialize the count
	DESC(2) = %LOC(BUFFER)		! 	and the address.
	WAIT_FOR_READ = .FALSE.		! Presume failure.
	CALL SYS$WAITFR(%VAL(REFN_IN))	! Wait for the read.
	IF (CONTROLC_TYPED) RETURN	! Return if aborted.
	STATUS = RIOSB(1)		! Copy the I/O status code.
	IF (.NOT. STATUS) THEN
		IF (STATUS .NE. SS$_TIMEOUT) THEN
			CALL CHECK_STATUS('WAIT_FOR_READ',STATUS)
			RETURN
		ENDIF
		NBYTES = RIOSB(2)	! Copy the byte count.
	ELSE
		NBYTES = RIOSB(2) + 1	! Byte count + terminator.
		WAIT_FOR_READ = .TRUE.	! Show read was successful.
	ENDIF
	DESC(1) = NBYTES		! Fill in the byte count.
	CALL WRITE_USER(DESC)		! Display what we received.
	RETURN
	END

	SUBROUTINE WRITE_RIXON(BUFF,BYTES)
C
C	This routine is used to write characters to the RIXON modem.
C	Each character is written with .25 second delays between them
C	so the RIXON doesn't get overrun.  Although the documentation
C	states that three nulls can be sent between characters, our
C	RIXON still gets overrun.  Also the computer mode sending
C	characters between angle brakets <...> gets overrun.
C
	INTEGER*4 BYTES, I
	LOGICAL*1 BUFF(1)

	DO 100 I = 1,BYTES
	CALL WAITABIT('00.25')		! Wait for a short time.
	CALL WRITE_BYTE(BUFF(I),1)	! Write the next character.
100	CONTINUE
	RETURN
	END
