Trailing-Edge
-
PDP-10 Archives
-
decuslib20-02
-
decus/20-0063/commps.mac
There are 2 other files named commps.mac in the archive. Click here to see a list.
TITLE COMMPS
SUBTTL COMMUNICATION WITH PDP-11/45 MUMPS SYSTEM
;P. HURLEY/R. SCHMIDT MAYNARD OCT-72
;*** COPYRIGHT 1972 DIGITAL EQUIPMENT CORP. MAYNARD MASS. ***
CUSTVER== 0 ;CUSTOMER VERSION NUMBER
DECVER== 1 ;DEC VERSION NUMBER
DECMVR== 0 ;DEC MINOR VERSION
DECEVR== 101 ;DEC EDIT VERSION
LOC 137 ;SET UP VERSION NUMBER
BYTE (3)CUSTVER(9)DECVER(6)DECMVR(18)DECEVR
RELOC
;modified 14 sept 80 for DECUS by paul t. robinson, wesleyan univ.
;edits were made to revise the calling conventions; FORTRAN and the
;COBOL "ENTER MACRO" phrase now both generate the same calling sequence
;of MOVEI 16,[arglist]
; PUSHJ 17,routine
;and therefore the entry points of the routines have been rewritten,
;argument references rewritten, and F4FLG has been eliminated.
;my edits are all in lower case for easy identification;
;eliminated code is preceded by triple semicolons.
;ASSEMBLY CONDITIONS:
;ASSEMBLE WITH C.MAC
;IF CC (3RD HEADER WORD IN A MESSAGE) IS TO BE SETUP AND
;CHECKED FOR ODD PARITY, ASSEMBLE WITH FTODCC==1
IFNDEF FTODCC, <FTODCC==0 ;NO PARITY CHECK ON CC>
;DEFINE ACCUMULATORS AND CONSTANTS
TIME= 10 ;KEEPS DAYTIME
CHR= 1 ;KEEPS CURRENT CHARACTER
CRC= 2 ;KEEPS CYCLIC REDUNDANCY CHECK
T1= CRC+1 ;TEMP
T2= T1+1 ;TEMP
CNT= 5 ;CHARACTER COUNT AC
Q= 16 ;FOR PC FOR FORTRAN CALL
P= 17 ;PUSH DOWN POINTER
SOH= 001 ;START OF HEADER
STX= 002 ;START OF TEXT (DATA)
ETX= 203 ;END OF TEXT
ACK= 240 ;ACKNOWLEDGE
NAK= 120 ;NOT ACKNOWLEDGE
SLPTIM= ^D3000 ;MSEC TO HIBERNATE BEFORE NEXT TRY
HNGACK= ^D5000 ;M-SEC BEFORE SENDING RETRANSMISSION
HNGMES= ^D30000 ;MSEC TO TRY BEFORE GIVING UP
TRYMAX= 10 ;MAXIMUM NO. OF RETRIES (EITHER TO
;SEND A MESS. OR TO ACK AN OLD ONE)
MSLMAX= ^D80 ;MAXIMUM LENGTH OF MESSAGE
TXLMAX= ^D72 ;MAXIMUM LENGTH OF TEXT
HB.RTC=1B14 ;WAKE ON CHARACTER READY
;DEFINE MACROS
DEFINE SAVE(N) ;AC SAVE MACRO
< MOVEM N,ACSAV+N ;SAVE AC N
HRRZI N,ACSAV ;SET UP BLT WORD
BLT N,N-1 ;SAVE OTHER ACS
> ;
DEFINE RESTOR(N) ;RETORE AC MACRO
< HRLZI N,ACSAV ;SET UP BLT WORD
BLT N,N ;RESTORE ACS
> ;
ENTRY RECVC,SENDC ;COBOL ENTRY POINTS
ENTRY RECVF,SENDF ;FORTRAN ENTRY POINTS
entry recv, send ;keep old names around for compatibility
INTERNAL TABGEN,MSN ;###
IFNDEF FTDEBUG,<FTDEBUG==0>
IFE FTDEBUG,< ;DEFINE NULL MACRO IF SWITCH IS 0
DEFINE DEBUG(A)
<>>
IFN FTDEBUG,< ;DEFINE MACRO FOR WHEN SWITCH IS ON
DEFINE DEBUG(A)
< PUSH P,0 ;SAVE AC 0
MOVSI 111111 ;SET UP LEFT HALF WORD
HRRI A ;SET UP DEBUG NUMBER
PUSHJ P,DEBPNT## ;WRITE OUT DEBUG ENTRY POINT
POP P,0 ;RESTORE 0
>> ;END OF DEFINE
SUBTTL GENERAL ROUTINES TO HANDLE CHARACTERS AND MESSAGES
;G E T C H R
;CALLED BY PUSHJ P,GETCHR
; ERROR RETURN ;NO CHAR FOUND
; NORMAL RETURN ;RETURNS CHAR IN CHR
EXTERNAL GETCHR ;ROUTINE TO GETR A CHARACTER IN C
;N O C H R
;CALLED BY PUSHJ P,NOCHR
;PUTS JOB INTO SLEEP UNTIL CHAR AVAILABLE. TRIES UNTIL TIMEOUT
;OCCURS.
NOCHR: DEBUG(1) ;NO CHARACTER READY, WAIT FOR ONE
MSTIME T1, ;GET CURRENT TIME
MOVEM T1,CURTIM# ;STORE FOR LATER USE
MOVSI T1,(HB.RTC) ;SETUP WAKE CONDITIONS
HRRI T1,SLPTIM ;AND SLEEP TIME
HIBER T1, ;WAIT
JRST NOHIB ;UUO NOT IMPLEMENTED
CHKTIM: MSTIME T1, ;GET DAYTIME
SUB T1,CURTIM ;DID WE TRY
CAIL T1,SLPTIM ;LONG ENOUGH?
POPJ P, ;YES, GIVE ERROR RETURN
GET: PUSHJ P,GETCHR ;NOT YET.
JRST NOCHR ;STILL NO CHAR THERE.
JRST CPOPJ1## ;RETURN WITH CHAR
NOHIB: MOVEI T1,SLPTIM/^D1000 ;SLEEP TIME IN SECONDS
SLEEP T1, ;SLEEP
JRST CHKTIM ;CHECK ELAPSED TIME
;P U T C H R
;CALLED BY MOVE CHR,CHAR ;CHARACTER IN CHR
; PUSHJ P,PUTCHR ;SEND IT
EXTERNAL PUTCHR ;ROUTINE TO SEND ONE CHARACTER OUT
;R C V B C C
;CALLED BY PUSHJ P,RCVBCC
;RETURNS NEXT BYTE IN CHR WITHOUT AFFECTING CHECKSUM.
;EXITS IN CASE OF TIMEOUT.
RCVBCC: DEBUG(2)
PUSHJ P,GET ;GET CRC BYTE
POPJ P, ;NONE THERE
MSTIME TIME, ;RESET TIMER
JRST CPOPJ1 ;SKIP RETURN
;R C V C H R
;CALLED BY PUSHJ P,RCVCHAR
;UPDATES ACCUMULATED CHECKSUM.
;RETURNS NEXT CHAR IN CHR OR EXITS IN CASE OF TIMEOUT.
RCVCHR: DEBUG(3)
PUSHJ P,GET ;GET A BYTE
POPJ P, ;NONE THERE
MSTIME TIME, ;RESET TIMER
MOVE T1,CHR ;COMPUTE CRC:
XOR T1,CRC ; MAKE 8 BIT INDEX
ANDI T1,377 ; CLEAR UNWANTED BITS
LSH CRC,-10 ; SHIFT CRC 8 BITS
XOR CRC,CRCTAB(T1) ; UPDATE IT
JRST CPOPJ1 ;RETURN WITH CHAR
;S A C K
;CALLED BY MOVE T1,MSN ;MESSAGE NUMBER IN T1
; PUSHJ P,SACK ;SEND ACKNOWLEDGE
SACK: IORI T1,ACK ;BUILD MESS. IDENT.
SACK1: MOVEM T1,MSI ;STORE IT
DEBUG(4)
SETZ CRC, ;CLEAR CRC
MOVEI CHR,SOH ;GET START OF HEADER CHARACTER
PUSHJ P,SNDCHR ;1ST BYTE OUT
MOVE CHR,MSI
PUSHJ P,SNDCHR ;2ND BYTE OUT
ROT CRC,-10 ;GET BCC0
MOVE CHR,CRC
PUSHJ P,PUTCHR ;SEND IT. DO NO CRC
ROT CRC,10 ;RESTORE CRC
MOVE CHR,CRC
PUSHJ P,PUTCHR ;SEND BCC1
PUSHJ P,CLRINP## ;CLEAR ANY CHARACTERS IN INPUT BUFFER
PUSHJ P,PUTOUT## ;OUTPUT THE MESSAGE
JRST CPOPJ ;RETURN
;S N A K
;ENTERED BY JRST SNACK
;NOT ACKNOWLEDGES CURRENT MESSAGE, RETURNS TO RCVNXT.
SNAK: DEBUG(5)
MOVE T1,MSN ;GET MESSAGE NUMBER TO NAK
IORI T1,NAK ;MESS. IDENTIFICATION
PUSHJ P,SACK1 ;SEND NAK MESSAGE
MOVEI CNT,MSLMAX ;RESET COUNTER
JRST RCVNXT ;GET NEXT MESSAGE
;S N D C H R
;CALLED BY MOVE CHR,CHAR ;CHARACTER IN CHR
; PUSHJ P,SNDCHR
;SENDS A BYTE AND UPDATES CYCLIC REDUNDANCY CHECK.
SNDCHR: DEBUG(6)
MOVE T1,CHR ;SAVE CHR FOR CRC
PUSHJ P,PUTCHR ;SEND BYTE
XOR T1,CRC ;COMPUTE CRC
ANDI T1,377
LSH CRC,-10
XOR CRC,CRCTAB(T1)
JRST CPOPJ ;RETURN
;T A B G E N
;CALLED BY PUSHJ P,TABGEN
;GENERATES CRCTAB (256 WORDS) WITH 16 BIT BYTE DEPENDENT
;CRC RIGHT JUSTIFIED. BIT 35 IS 1 IFF BYTE HAS ODD PARITY.
TABGEN: MOVEI CHR,377 ;START WITH LAST BYTE
CRCNXT: MOVEI T2,7 ;HERE ONCE FOR EACH BYTE
MOVE CRC,CHR ;GET CURRENT CHAR
CRCSHF: LSHC CRC,-1 ;SHIFT IT AND
SKIPGE CRC+1 ;CHECK RIGHT END BIT
XORI CRC,120001 ;HERE IF BIT WAS ON
SOJGE T2,CRCSHF ;NEXT BIT
MOVEM CRC,CRCTAB(CHR) ;STORE CRC
SOJGE CHR,CRCNXT ;NEXT BYTE
CPOPJ: POPJ P, ;NON-SKIP RETURN
SUBTTL RECV - TO RECEIVE MESSAGES FROM PDP-11
;R E C V
COMMENT %
CALL FROM COBOL:
77 NUMBER
77 FLAG
01 DUMMY
02 ARRAY OCCURS 211 TIMES
...
ENTER MACRO RECVC USING ARRAY, NUMBER, FLAG.
...
COBOL SHOULD GENERATE THE FOLLOWING MACRO CODE:
PUSHJ 17,RECVC
ARG [ARRAY]
ARG 0,NUMBER
ARG 0,FLAG
ARG 0,TYPE
[see note on changed calling convention at beginning of file. ptr]
RECVC RECEIVES MESSAGES FROM PDP-11/45 MUMPS (A INIT11
CALL MUST HAVE ESTABLISHED CONNECTION AND
INITIALIZED THE APPROPRIATE PDP-11 ROUTINE).
EXTRACTS THE DATA AND STORES THEM AS 8 BIT BYTES
RIGHT JUSTIFIED IN ARRAY. CONTINUES UNTIL EITHER
THE NUMBER'TH BYTE HAS BEEN STORED, OR A TIME-
OUT OCCURS.
RETURNS IN FLAG -1, IF THE REQUEST HAS COMPLETELY
BEEN SATIESFIED.
N, IF THERE OCCURED A TIMEOUT
AFTER THE N'TH BYTE WAS PROPER-
LY RECEIVED.
A TIMEOUT OCCURS, WHEN WITHIN 30 SECONDS
NO SOH COULD BE RECOGNIZED BY RECV11, OR
NO CHARACTER AT ALL COULD BE RECEIVED. %
;;;;COME IN HERE FOR FORTRAN CALL.
;;;
;;;RECVF: Z ;TO SAVE Q
;;; PUSH P,Q ;Q ONTO STACK (ARG POINTER)
;;; SETOM F4FLG ;MARK THAT THIS CALL CAME FROM FORTRAN
;;; JRST RECV ;GO RECEIVE
;;;;COME IN HERE IN CASE OF COBOL CALL:
;;;
;;;RECVC: SETZM F4FLG ;MARK THAT THIS WAS A COBOL CALL
recvc: ;all entry points are now the same
recvf:
RECV: SAVE 5 ;SAVE 5 ACS
;;; HRRZ T1,(P) ;GET ADR OF 1ST ARG
;;; HRRZ T1,(T1) ;GET ARRAY ADDRESS
;;; SKIPN F4FLG ;COBOL CALL?
;;; HRRZ T1,(T1) ;YES, GET REAL ARRAY ADDRESS
movei t1,@(q) ;get array adr into t1
HRLI T1,TXTBUF
MOVEM T1,BLTPTR ;INITIALIZE BLT POINTER
;;; AOS (P) ;INCREMENT ARG POINTER
;;; HRRZ T1,(P)
;;; MOVE T1,@(T1) ;GET 2ND ARG
move t1,@1(q) ;get second arg into t1
MOVEM T1,NUMBER ;SAVE IT
;;; AOS (P) ;INCREMENT ARG POINTER
AOS T1,MSN ;UPDATE MESS NO.
ANDI T1,17 ;TRUNCATE TO 4 BITS
MOVEM T1,MSN ;SAVE 4 BIT MESSAGE NUMBER
SETZM FLAG ;INITIALIZE FLAG
SETZM RESEND ;AND RESEND COUNTER
RCVNXT: DEBUG(7)
MSTIME TIME, ;INITIALIZE TIMER
RCVNX1: MOVEI CNT,MSLMAX ;INITIALIZE COUNTER
PUSHJ P,RCVMES ;GO RECEIVE A MESSAGE
JRST NOMESS ;THERE WASN'T A COMPLETE ONE
SKIPE ACKCHR ;DID WE GET AN ACK INSTEAD?
JRST NOMESS ;YES, GO HANDLE IT
MOVE T1,MSNRCV ;NOW CHECK MESSAGE NUM
CAME T1,MSN ;IS THIS THE CORRECT MESSAGE
AOJA T1,BADMSN ;NO SEE IF IT IS MESS-1
DEBUG(21)
PUSHJ P,SACK ;ACKNOWLEDGE
RCVOK: DEBUG(22)
SETZM RESEND
MOVE CNT,CCRCV# ;GET TEXT COUNT
CAMLE CNT,NUMBER ;ALL DATA BYTES WANTED?
MOVE CNT,NUMBER ;NO.
ADDM CNT,FLAG ;NO. OF PROPERLY RECEIVED BYTES
MOVE T1,BLTPTR ;GET BLT POINTER
HRRZ T2,T1 ;SET UP LAST BLT ADDRESS
ADD T2,CNT
BLT T1,-1(T2) ;TRANSFER TO USER'S ARRAY
MOVN T1,CNT
ADDM T1,NUMBER
SKIPG NUMBER ;MORE BYTES WANTED?
JRST RCVXIT ;NO.
ADDM CNT,BLTPTR ;YES. UPDATE BLT POINTER
AOS T1,MSN ;NO. OF NEXT MESS.
ANDI T1,17 ;CLEAR CARRY
MOVEM T1,MSN
JRST RCVNXT ;GET IT
RCVXT1: TDZA T2,T2 ;ERROR EXIT, SET IERR TO 0
RCVXIT: SETO T2, ; SUCCESFUL EXIT, SET IERR TO -1
;;; HRRZ T1,(P) ;GET ADDR OF ERROR FLAG
;;; MOVEM T2,@(T1) ;STORE ERROR FLAG
;;; AOS (P) ;INCREMENT ARG POINTER
;;; HRRZ T1,(P) ;GET ADDR OF TYPE
movem t2,@2(q) ;store error flag
DEBUG(23)
MOVE T2,FLAG ;GET TYPE
;;; MOVEM T2,@(T1) ;SET UP FLAGWORD
;;; AOS (P) ;SET UP RETURN ADR
movem t2,@3(q) ;set up flagword
RESTOR 5 ;RESTORE ACS
;;; SKIPE F4FLG ;WAS IT FORTRAN CALL?
;;; JRST EXITF4 ;YES.
JRST CPOPJ ;RETURN
NOMESS: DEBUG(24)
CAIGE CNT,MSLMAX ;HAVE WE RECEIVED ANY LEGAL CHARACTERS
JRST SNAK ;YES, SEND A NAK OUT
DEBUG(25)
MSTIME T1, ;GET CURRENT TIME
SUB T1,TIME ;CALCULATE TIME SINCE START
CAIGE T1,HNGMES ;HAVE WE WAITED LONG ENOUGH
JRST RCVNX1 ;YES, GIVE TIMED OUT ERROR RETURN
DEBUG(26)
JRST RCVXT1 ;GO GIV ERROR RETURN
BADMSN: DEBUG(27)
ANDI T1,17 ;GET MESSAGE NUMBER RECEIVED
CAMN T1,MSN ;IS IT SAME AS LAST ONE
JRST MESM1 ;YES, GO SEND AN ACK
MOVE T1,MSNRCV ;NO, ASSUME A RESTART IN OTHER SYSTEM
MOVEM T1,MSN ;AND INITIALIZE MESSAGE NUMBER TO THE ONE RECEIVED
PUSHJ P,SACK ;SEND AN ACK OF THIS MESSAGE NUMBER
JRST RCVOK ;GO BACK TO MAIN STREAM
MESM1: MOVE T1,MSNRCV ;MESSAGE MINUS ONE WAS RECEIVED
PUSHJ P,SACK ;SO SEND OUT AN ACK FOR IT
JRST RCVNXT ;THEN GO WAIT FOR THE RIGHT MESSAGE
;ROUTINE TO RECEIVE MESSAGES OR ACK/NAK'S
;CALLED BY: PUSHJ P,RCVMES
; ERROR RETURN ;NO CORRECT MESSAGE RECIEVED
; NORMAL RETURN
RCVMES:
;CHECK FOR START OF HEADER.
RCVSOH: DEBUG(10)
SETZ CRC, ;INITIALIZE CRC
PUSHJ P,RCVCHR ;GET A BYTE
POPJ P, ;TIMED OUT
CAIN CHR,SOH ;IS IT SOH?
SOJG CNT,RCVMSN ;YES. CHECK MESS. NO.
BADCHR: DEBUG(11)
JRST RCVSOH ;GO WAIT FOR A SOH
;CHECK MESSAGE IDENTIFICATION. EXPECTED
;NUMBER IS MSN. IF ONE LESS: SEND ACK FOR PREVIOUS MESSAGE.
RCVMSN: DEBUG(12)
PUSHJ P,RCVCHR ;GET A BYTE
POPJ P, ;TIMED OUT
SETZM ACKCHR# ;INITIALIZE FLAG
TRNE CHR,360 ;IS THIS AN ACK OR A NAK?
JRST CHKMSI ;POSSIBLY
MOVEM CHR,MSNRCV# ;STORE MESSAGE NUMBER
SOJG CNT,RCVCC ;YES. CHECK CC
JRST BADCHR ;RECEIVED TOO MANY CHARACTERS
;CHECK CHARACTER COUNT (ODD PARITY, COUNT.LE.TXLMAX).
RCVCC: DEBUG(13)
PUSHJ P,RCVCHR ;GET A BYTE
POPJ P, ;TIMED OUT
IFN FTODCC,
< MOVE T1,CRCTAB(CHR) ;LOOK INTO TABLE
TRNN T1,1 ;WHETHER BYTE HAS
;ODD PARITY.
JRST BADCHR ;IT HASN'T.
ANDI CHR,177 ;GET CHAR COUNT
>
CAILE CHR,TXLMAX ;TOO MANY?
JRST BADCHR ;YES.
MOVEM CHR,CCRCV ;SAVE COUNT
MOVN T2,CHR ;FOR DATA POINTER
HRLI T2,TXTBUF ;SET UP TO SEND OUT TEXT
SOJG CNT,RCVSTX ;STILL GOT ROOM
JRST BADCHR ;NO, TOO MANY CHARACTERS RECEIVED
;CHECK START OF TEXT.
RCVSTX: DEBUG(14)
PUSHJ P,RCVCHR ;GET A BYTE
POPJ P, ;TIMED OUT
SOSLE CNT ;RECEIVED TOO MANY CHARS YET?
CAIE CHR,STX ;IS IT STX?
JRST BADCHR ;NO.
;READ IN TEXT AND STORE IN TXTBUF.
MOVSS T2 ;DATA POINTER IN CNT
RCVTXT: DEBUG(15)
PUSHJ P,RCVCHR ;GET A DATA ITEM
POPJ P, ;TIMED OUT
MOVEM CHR,(T2) ;STORE IT
SOSG CNT
JRST BADCHR ;RECEIVED TOO MANY CHARACTERS!
AOBJN T2,RCVTXT ;NEXT DATA ITEM
;CHECK FOR ETX
RCVETX: DEBUG(16)
PUSHJ P,RCVCHR ;GET A BYTE
POPJ P, ;TIMED OUT
SOSLE CNT ;MESSAGE TOO LONG?
CAIE CHR,ETX ;IS IT ETX?
JRST BADCHR ;NO.
;CHECK CRC. USE RCVBCC INSTEAD RCVCHR TO NOT INCLUDE
;BCC0 AND BCC1 IN CHECKSUM.
RCVBC0: DEBUG(17)
PUSHJ P,RCVBCC ;GET A BYTE
POPJ P, ;TIMED OUT
LSHC CRC,-10 ;GET HIGH ORDER PART OF CRC
SOSLE CNT
CAME CRC,CHR ;OK?
JRST BADCHR ;NO.
LSHC CRC,10 ;RESTORE CRC
ANDI CRC,377 ;GET LOW ORDER PART
DEBUG(20)
PUSHJ P,RCVBCC ;GET A BYTE
POPJ P, ;TIMED OUT
CAME CRC,CHR ;CRC OK?
JRST BADCHR ;NO
JRST CPOPJ1 ;MESSAGE OK
CHKMSI: LDB T1,ANPTR ;GET ACK FIELD
MOVEM T1,ACKCHR ;STORE FOR LATER
DEBUG(35)
ANDI CHR,17 ;CLEAR ACK FIELD
MOVEM CHR,ACKMSN# ;STORE MSN NUMBER
SOJG CNT,CHKBCC ;GO GET CRC
JRST BADCHR ;TOO MANY CHARACTERS RECEIVED
CHKBCC: DEBUG(36)
PUSHJ P,RCVBCC ;GET CRC 1
POPJ P, ;NONE THERE GIVE ERROR RETURN
LSHC CRC,-10 ;SHIFT IT
SOSLE CNT ;CHECK COUNT
CAME CRC,CHR ;IS THIS CHARACTER CORRECT
JRST BADCHR ;NO
LSHC CRC,10 ;RESTORE ORIGINAL CRC
ANDI CRC,377 ;CLEAR LEFTMOST BITS
PUSHJ P,RCVBCC ;GET LOWORDER CRC BITS
POPJ P, ;NONE THERE
CAME CRC,CHR ;IS THIS CHARACTER OK
JRST BADCHR ;NO
JRST CPOPJ1 ;YES, GIVE SKIP RETURN
SUBTTL SEND - TO SEND MESSAGES TO PDP-11
;S E N D
COMMENT %
CALL FROM COBOL:
...
ENTER MACRO SENDC USING ARRAY, NUMBER.
...
%
;;;;COME IN HERRE FOR FORTRAN CALL.
;;;
;;;SENDF: 0 ;CALL SENDF(ARRAY,NUMBER,IERR,ITYPE)
;;; PUSH P,Q ;STORE RETURN AC
;;; SETOM F4FLG ;MARK THAT A FORTRAN CALL WAS DONE
;;; JRST SEND ;GO SEND
;;;
;;;;COME IN HERE IN CASE OF COBOL CALL.
;;;
;;;SENDC: SETZM F4FLG ;MARK THAT A COBOL CALL WAS DONE
sendf:
sendc:
SEND: SAVE 5 ;SAVE 5 ACS
;;; HRRZ T2,(P) ;GET ADR OF 1ST ARGUMENT
;;; HRRZ T2,(T2) ;GET ARRAY ADDRESS
;;; SKIPN F4FLG ;COBOL CALL?
;;; HRRZ T2,(T2) ;YES, GET CORRECT ARRAY ADDRESS
movei t2,@(q) ;get array address into t2
MOVEM T2,ARYPTR ;STORE AS ARRAY POINTER
;;; AOS (P) ;ADVANCE ARG POINTER
;;; HRRZ T1,(P) ;GET 2ND ARGUMENT
;;; MOVE T1,@(T1) ;GET NUMBER OF CHARACTERS TO SEND
move t1,@1(q) ;get number of characters to send
MOVEM T1,NUMBER ;STORE IT
;;; AOS (P) ;ADVANCE ARG POINTER
AOS T1,MSN ;UPDATE MESS NO.
ANDI T1,17 ;TRUNCATE MSN TO 4 BITS
MOVEM T1,MSN ;SAVE TRUNCATED MSN
SETZM FLAG ;CLEAR FLAG
SETZM RESEND ;ZERO RESEND COUNT
SNDNXT: DEBUG(30)
MOVEI T1,TXLMAX ;TO SET UP CC
CAMLE T1,NUMBER ;MORE THAN TXLMAX CHAR'S LEFT?
MOVE T1,NUMBER ;NO. THIS IS LAST MESS.
MOVEM T1,CCSEND# ;SAVE CHAR COUNT
;SEND THE MESSAGE.
;SEND SOH:
SETZ CRC, ;INITIALIZE CRC
MOVEI CHR,SOH ;GET START OF HEADER CHARACTER
PUSHJ P,SNDCHR ;SEND IT OUT
;SEND MSN:
MOVE CHR,MSN ;GET MSN
PUSHJ P,SNDCHR ;SEND IT OUT
;SEND CC, ODD PARITY:
MOVE CHR,CCSEND ;GET CHARACTER COUNT
IFN FTODCC,
< MOVE T1,CRCTAB(CHR)
TRNN T1,1 ;HAS BYTE ODD PAR?
TRO CHR,200 ;NO. MAKE IT ODD
>
PUSHJ P,SNDCHR ;SEND OUT CHARACTER COUNT
;SEND STX:
MOVEI CHR,STX ;GET START OF TEXT
PUSHJ P,SNDCHR ;SEND STX OUT
;SEND THE TEXT (CC BYTES):
MOVN T1,CCSEND ;POINTER
HRL T2,T1 ;ARRAY ADDR IN T2
SNDTXT: MOVE CHR,(T2) ;GET NEXT CHARACTER TO SEND
PUSHJ P,SNDCHR ;SEND IT
AOBJN T2,SNDTXT ;LOOP BACK FOR MORE
;SEND ETX:
MOVEI CHR,ETX ;GET END OF TEXT CHARACTER
PUSHJ P,SNDCHR ;SEND OUT ETX
;SEND BCC0:
ROT CRC,-10 ;GET HIGH ORDER CRC BITS
MOVE CHR,CRC ;...
PUSHJ P,PUTCHR ;SEND OUT BCC1
;SEND BCC1:
ROT CRC,10 ;GET LOW ORDER CRC BITS
MOVE CHR,CRC ;...
PUSHJ P,PUTCHR ;SEND OUT BCC2
PUSHJ P,CLRINP ;CLEAR THE TTY INPUT BUFFER
PUSHJ P,PUTOUT ;SEND OUT THE MESSAGE
;RECEIVE AN ACK OR NAK MESSAGE:
DEBUG(31)
MSTIME TIME, ;READ CURRENT TIME FOR TIMEOUT PURPOSES
RCVACK: MOVEI CNT,MSLMAX ;INITIALIZE COUNT TO MAX MESSAGE SIZE
SETZM NAKFLG ;INITIALIZE NAK FLAG
PUSHJ P,RCVMES ;GET ACK OR NAK
JRST NOACK ;NONE THERE
SKIPN T1,ACKCHR ;WAS THIS AN ACK/NAK
JRST GOTMES ;NO, IT WAS ANOTHER MESSAGE
CAIN T1,ACK_-4 ;IS THIS AN ACK?
JRST CHKMSN ;YES
CAIE T1,NAK_-4 ;IS THIS A NAK?
JRST NOACK ;NO, THIS IS A BAD MESSAGE
SETOM NAKFLG ;MARK THAT A NAK WAS SEEN
CHKMSN: MOVE T1,ACKMSN ;GET MSN RECEIVED
CAMN T1,MSN ;IS THIS THE ONE WE EXPECT
SKIPE NAKFLG ;AND WAS THIS AN ACK
JRST BADACK ;NO, GO RESEND
;ACKNOWLEDGE RECEIVED. CHECK FOR MORE CHAR'S TO BE SENT.
SNDMOR: DEBUG(37)
MOVN T1,CCSEND ;GET CHARACTERS SENT COUNT
ADDM T1,NUMBER ;SUBTRACT FROM NUMBER LEFT
SKIPG NUMBER ;ANY MORE TO GO OUT
JRST SNDXIT ;NO, WE ARE THROUGH
SETZM RESEND ;YES, GO SEND OUT NEXT GROUP
MOVE T2,CCSEND ;GET CHARACTERS SENT COUNT
ADDB T2,ARYPTR ;UPDATE ARRAY POINTER
AOS T1,MSN ;UPDATE MSN
ANDI T1,17 ;TRUNCATE TO 4 BITS
MOVEM T1,MSN ;STORE TRUNCATED MSN
JRST SNDNXT ;GO SEND OUT NEXT MESSAGE
NOACK: DEBUG(40)
CAIGE CNT,MSLMAX ;ANY LEGAL CHARACTERS SEEN
JRST BADACK ;YES, GO RESEND
NOACK1: DEBUG(41)
MSTIME T1, ;GET TIME
SUB T1,TIME ;CALCULATE TIME WAITED
CAIG T1,HNGACK ;HAVE WE TIMED OUT
JRST RCVACK ;NO, GO WAIT SOME MORE
BADACK: DEBUG(42)
AOS T1,RESEND ;UPDATE COUNTER
CAIL T1,TRYMAX ;DID WE TRY ENOUGH?
JRST SNDXT1 ;YES. QUIT.
;NOT ACKNOWLEDGE RECEIVED. RETRANSMIT MESSAGE.
SNDAGN: DEBUG(43)
MOVE T2,ARYPTR ;NO
JRST SNDNXT ;GO RETRANSMIT THE MESSAGE
;WAITING FOR ACK OR NAK BUT GOT A MESSAGE
GOTMES: MOVE T1,MSNRCV ;GET MSN RECEIVED
CAMN T1,MSN ;IS IT WHAT WE ARE TRYING TO SEND
JRST SNDXT0 ;YES, GIVE ERROR RETURN. BOTH PROGRAMS ARE SENDING
AOS T1 ;INCREMENT MSN
ANDI T1,17 ;TRUNCATE
CAME T1,MSN ;IS THIS MSN-1
JRST NOACK1 ;NO, THEN IGNORE THIS MESSAGE
MOVE T1,MSNRCV ;YES, THEN SEND OUT AN ACK FOR THIS MSN
PUSHJ P,SACK ;THE OTHER PROGRAM PROBABLY LOST OUR ACK
JRST NOACK1 ;NOW GO WAIT SOME MORE
SNDXT0: SETOM RESEND ;SET ERROR FLAG
SNDXT1: TDZA T2,T2 ;IERR = 0
SNDXIT: SETO T2, ;IERR = -1 OK RETURN
;;; HRRZ T1,(P) ;GET ADDRESS OF IERR
;;; MOVEM T2,@(T1) ;STORE ERROR FLAG
;;; AOS (P) ;INCREMENT ARG POINTER
movem t2,@2(q) ;store error flag
MOVE T2,RESEND ;GET TYPE
;;; HRRZ T1,(P) ;GET ITYPE ADDRESS
;;; MOVEM T2,@(T1) ;STORE ITYPE
;;; AOS (P) ;INCREMENT ARG POINTER
movem t2,@3(q) ;store itype
RESTOR 5 ;RESTORE THE ACS
;;; SKIPE F4FLG ;WAS THIS CALL FROM A FORTRAN PROGRAM
;;; JRST EXITF4 ;YES, GO RETURN
POPJ P, ;NO JUST POPJ RETURN
;;;EXITF4: POP P,Q ;RESTORE RETURN ADDRESS
;;; JRA Q,(Q) ;RETURN
ANPTR: POINT 4,CHR,31 ;TO DECODE MSI
ARYPTR: Z ;POINTS TO 1ST BYTE IN
;USER ARRAY TO BE SENT
BLTPTR: XWD TXTBUF,0 ;TO FILL USER'S ARRAY
;;;F4FLG: Z ;IF -1: CALL FROM F4
;ELSE FROM COBOL
FLAG: Z ;TO COUNT NO. OF ACTUALLY
;XMITTED BYTES AND TO INDICATE
;TIMEOUT
MSI: Z ;MESS. IDENTIFICATION
MSN: Z ;NO. OF CURRENT MESSAGE
NAKFLG: Z ;IF -1: LAST MESSAGE
;RECEIVED WAS NAK
NUMBER: Z ;FOR 2ND ARGUMENT
RESEND: Z ;NO. OF TRIES OF RETRANSMITS
ACSAV: BLOCK 7 ;ACC. SAVE AREA
CRCTAB: BLOCK 400 ;TABLE FOR CRC
TXTBUF: BLOCK ^D72 ;TO STORE TEXT
END ;END OF COMMPS