Google
 

Trailing-Edge - PDP-10 Archives - BB-H348C-RM_1982 - swskit-v21/demos/decnet.mac
There are 6 other files named decnet.mac in the archive. Click here to see a list.
TITLE DECNET DECnet Interface for Cobol and Fortran

COMMENT #

Please read the HELP and DOC files for more information.

#
	SALL
	SEARCH MONSYM,MACSYM

	T1=1	;THESE AC'S ARE SAVED AND RESTORED BY THIS SUBROUTINE
	T2=2
	T3=3
	T4=4

	ARG=16	;ARGUMENT LIST POINTER
	P=17	;PUSH DOWN STACK

MAXLL=^D20	;MAX NUMBER OF LL'S ALLOWED AT ONCE
DISTIM=^D5000	;PERIOD BETWEEN CHECKS FOR LOST INTERRUPTS
COBOL==0	;ASSEMBLE FOR COBOL
FORTRAN==-1	;DO NOT ASSEMBLE FOR FORTRAN

IFNDEF COBOL, <COBOL==0>
IFNDEF FORTRAN, <FORTRAN==0>

; EVENT FLAG DEFINITIONS

EV.CON=1	;CONNECT EVENT HAS OCCURED
EV.ABT=2	;ABORT EVENT HAS OCCURED
EV.INT=4	;INTERRUPT MESSAGE IS AVAILABLE
EV.DAT=10	;DATA IS AVAILABLE
EV.DIS=20	;A DISCONNECT EVENT HAS OCCURED
;
; MACRO TO SAVE T1-T4 AT THE BEGINNING OF SUBROUTINE EXECUTION
;	AND RESTORE THEM JUST PRIOR TO RETURN TO CALLER.
;
DEFINE SAVAC , <
	PUSH P,T1		;SAVE T1
	PUSH P,T2		;SAVE T2
	PUSH P,T3		;SAVE T3
	PUSH P,T4		;SAVE T4
	PUSH P,[[POP P,T4	;RETURN FROM SUBROUTINE COMES
		POP P,T3	;...HERE TO RESTORE REGISTERS
		POP P,T2
		POP P,T1
		POPJ P,]]
>

;
; MACRO USED TO RETURN FROM A SUBROUTINE
;
DEFINE RETURN (B) , <
	JRST 	[MOVX T1,<B>		;STATUS CODE
		MOVEM T1,@RETCOD	;RETURN STATUS
		RET]
>
;
; LOCAL STORAGE
;

; HERE IS STORED THE CANONICAL FORM OF ALL PARAMETERS PASSED
; BETWEEN THE CALLING MODULE AND THE CALLED MODULE. THIS
; STRUCTURE FACILITATES THE USE OF THESE SUBROUTINES BY MANY
; HIGHER LEVEL LANGUAGES.
; CURRENTLY ONLY FORTRAN AND COBOL AVE BEN TESTED.

NETLN:	BLOCK 1			;ADDR OF NETWORK LOGICAL NAME. THIS IS OFFSET
				;...INTO LOGICAL LINK TABLES
TYPE:	BLOCK 1			;ADDR OF SUBROUTINE DEPENDANT VARIABLE
DESC:	BLOCK 1			;BYTE POINTER TO ASCIZ REPRESENTATION
				; OF COMPLETE TOPS20 FILE SPEC FOR
				; THE NETWORK FILE.
WAIT:	BLOCK 1			;ADDR OF WAIT VARIABLE 1=WAIT 0=NOWAIT
COUNT:	BLOCK 1			;ADDR OF BYTE COUNT FOR MESSAGE TRANSFERS
DATA:	BLOCK 1			;BYTE POINTER FOR DATA AND STATUS MESSAGES
EOM:	BLOCK 1			;ADDR OF END OF MESSAGE FLAG  1=END 0=STREAM
CODE:	BLOCK 1			;ADDR OF SUBROUTINE DEPENDANT VARIABLE
TEMPST:	BLOCK ^D100		;TEMPORARY STRING STORAGE
RETCOD:	BLOCK 1			;ADDRESS OF RETURN CODE

;
; HERE ARE STORED OTHER LOCAL VARIABLES
;

START:	0			;SET TO 1 AFTER PSI INITIALIZATION
PC:	BLOCK 1			;SAVE PC DURING INTERRUPTS
LEVTAB:	0
	0
	0,,PC			;PC FOR INTERUPTS
CHNTAB:	REPEAT ^D36, < 0 >	;NOTHING AT FIRST
LEVCHN:	BLOCK 1			; SAVE LEVEL AND CHAN TABLE ADRS
LLJFN:	BLOCK MAXLL		;JFN OF THIS LOGICAL LINK
LLEVNT:	BLOCK MAXLL		;BYTE SIZE,,EVENT FLAGS
LLSTAT:	BLOCK MAXLL		;LL STATUS WORD
T1T2:	BLOCK 2			;SAVE ACS DURING INTTERUPTS
T3T4:	BLOCK 2
NEXT:	0			;FAIRNESS WORD FOR NFGND
CHAN:	BLOCK 1			;CHANNEL NUMBER CHOSEN FOR ALL LL
;
; HERE TO WAIT FOR ANY EVENT TO OCCUR
;
NFGND::	SAVAC			;SAVE AC'S

;*** LANGUAGE DEPENDANT CODE ***
	MOVEI T1,@2(ARG)	;GET THE RETURN CODE ADDRESS
	MOVEM T1,RETCOD		;SAVE IT
	MOVEI T1,@0(ARG)	;ADDRESS OF NETLN
	MOVEM T1,NETLN		;SAVE IT
	MOVEI T1,@1(ARG)	;ADDRESS OF WAIT FLAG
	MOVEM T1,WAIT		;SAVE IT
;*** END OF LANGUAGE DEPENDANT CODE ****

GNDCHK:	MOVE T1,@NETLN		;GET LINK ID
	CAIGE T1,0		;-1?
	JRST CHKALL		;YES, CHECK ALL LINKS
	CALL CHKEVT		;ANYTHING HAPPEN
	CAIE T2,0		;?
	JRST 0(T2)		;YES, PROCESS IT
	SKIPN @WAIT		;WAITING?
	RETURN 0		;NO, RETURN NOTHING
	MOVEI T1,DISTIM
	DISMS%
	JRST GNDCHK		;GO LOOK AGAIN

CHKALL:	MOVE T1,NEXT		;GET NEXT LL TO LOOK AT
CHKA.1:	CALL CHKEVT		;ANYTHING HAPPEN
	CAIE T2,0		;?
	JRST [MOVEM T1,@NETLN	;RETURN LINK NUMBER
		AOS T1		;INCREMENT NEXT COUNTER
		CAIN T1,MAXLL	;END OF LIST?
		SETZ T1,	;YES, START OVER
		MOVEM T1,NEXT	;SAVE IT
		MOVE T1,@NETLN	;RETRIEVE THE OFFSET
		JRST 0(T2)]	;PROCESS THE EVENT]
	AOS T1			;LOOK AT NEXT LINK
	CAIN T1,MAXLL		;END OF LIST?
	SETZ T1,		;YES, START AT BEGGINING
	CAME T1,NEXT		;SEEN ENTIRE LIST?
	JRST CHKA.1		;NO, LOOK AGAIN
	SKIPN @WAIT		;WAITING?
	RETURN 0		;NO
	MOVEI T1,DISTIM
	DISMS%
	JRST CHKALL		;CHECK AGAIN

CHKEVT:	MOVE T2,LLJFN(T1)	;GET JFN
	CAIN T2,0		;IS IT ZERO?
	RET			;YES
	HRRZ T2,LLEVNT(T1)	;GET EVENT FLAGS
	CAIN T2,0		;ANYTHING HAPPEN?
	JRST [SETZ T2,		;REPORT NOTHING HAPPENED
		RET]
	TXNE T2,EV.CON		;CONNECT?
	JRST [MOVEI T2,GND.C
		RET]
	TXNE T2,EV.ABT		;ABBORT?
	JRST [MOVEI T2,GND.A
		RET]
	TXNE T2,EV.INT		;INTERRUPT MESSAGE?
	JRST [MOVEI T2,GND.I
		RET]
	TXNE T2,EV.DAT		;DATA AVAILABLE?
	JRST [MOVEI T2,GND.DA
		RET]
	TXNE T2,EV.DIS		;DISCONNECT EVENT?
	JRST [MOVEI T2,GND.DC
		RET]
	SETZ T2,
	RET

GND.C:	MOVEI T2,EV.CON		;CONNECT EVENT BIT
	XORM T2,LLEVNT(T1)	;TURN IT OFF
	RETURN 1		;RETURN WITH CONNECT STATUS

GND.A:	RETURN 2		;RETURN WITH ABORT STATUS

GND.DC:	MOVEI T2,EV.DIS		;DISCONNECT EVENT BIT
	XORM T2,LLEVNT(T1)	;TURN IT OFF
	RETURN 5		;RETURN WITH DISCONNECT STATUS

GND.I:	RETURN 3		;RETURN WITH INTERRUPT STATUS

GND.DA:	RETURN 4		;RETURN WITH DATA AVAILABLE STATUS
; NFOPN - OPEN A LOGICAL LINK
;
; CALL NFOPN USING NETLN,TYPE,DESC,WAIT,RETCOD.
;

NFOPN::	SAVAC			;SAVE AC'S

; ***HERE MOVE LANGUAGE TYPE VARIABLES TO THE CANONICAL STORAGE AREA***
	MOVEI T1,@5(ARG)	;GET RETURN CODE ADDRESS
	MOVEM T1,RETCOD		;SAVE IT
	MOVEI T1,@0(ARG)	;ADDRESS OF NETLN
	MOVEM T1,NETLN		;SAVE IT
	MOVEI T1,@1(ARG)	;GET TYPE'S ADDRESS
	MOVEM TYPE		;KEEP IT
IFN COBOL, <
	MOVEI T1,@2(ARG)	;ADDRESS OF 2 WORD DESCRIPTOR
	MOVE T2,0(T1)		;BYTE POINTER
	HRRZ T3,1(T1)		;BYTE COUNT
	MOVE T4,[POINT 7,TEMPST] ;DESCRIPTOR BLOCK
DL:	ILDB T1,T2		;LOAD DESCRIPTIOR
	IDPB T1,T4		;SAVE IT
	SOSE T3			;DO ALL BYTES
	JRST DL
	SETZ T1,		;ASCIZ
	IDPB T1,T4		;DO IT
	MOVE T1,[POINT 7,TEMPST] ;POINTER TO DESCRIPTOR
>				;END OF COBOL CODE
IFN FORTRAN, <
	MOVEI T2,@2(ARG)	;FILE SPEC
	HLL T2,[POINT 7,0]	;MAKE A BYTE POINTER
	MOVE T4,[POINT 7,TEMPST] ;WHERE TO PUT DESCRIPTOR
DL:	ILDB T1,T2		;GET A CHAR
	CAIE T1,0		;END OF STRING?
	CAIN T1,40		;END OF STRING?
	JRST ENDST		;YES
	IDPB T1,T4		;SAVE IT
	JRST DL			;DO ENTIRE STRING
ENDST:	SETZ T1,		;ASCIZ STRING
	IDPB T1,T4		;SAVE IT
	MOVE T1,[POINT 7,TEMPST] ;REMEMBER ADDRESS OF STRING
>				;END OF FORTRAN CODE
	MOVEM T1,DESC		;SAVE IT
	MOVEI T1,@4(ARG)	;GET WAIT CODE'S ADDRESS
	MOVEM T1,WAIT		;SAVE IT
	MOVEI T1,@3(ARG)	;ADDRESS OF BYTE SIZE
	MOVEM T1,CODE		;SAVE IT
; ***HERE ENDS THE DATA INITIALIZATION CODE FOR LANGUAGE***

	SKIPN START		;INTERRUPT SYSTEM STARTED YET?
	CALL PSINIT		;NO, GO DO IT
	MOVE T2,[-MAXLL,,0]	;CHECK LL TABLES FOR ROOM
FINDLL:	MOVE T3,LLJFN(T2)	;IN USE?
	JUMPE T3,GOTLL		;GOT A FREE SLOT?
	AOBJN T2,FINDLL		;KEEP LOOKING
	RETURN 1		;FATAL ERROR, NO SLOTS
GOTLL:	HRRZM T2,@NETLN		;SAVE SLOT NUMBER
	MOVX T1,GJ%SHT		;SHORT FORM
	MOVE T2,DESC		;FILE SPEC POINTER
	GTJFN%			;GET A JFN
	 ERJMP JSER		;JSYS ERROR
	MOVE T2,@NETLN		;GET SLOT NUMBER
	HRRZM T1,LLJFN(T2)	;SAVE JFN
	MOVE T3,@CODE		;BYTE SIZE
	ADDI T3,4400		;MAKE A BYTE POINTER
	LSH T3,^D24		;SHIFT IT
	HLLM T3,LLEVNT(T2)	;SAVE BYTE POINTER
	MOVE T3,@CODE		;BYTE SIZE AGAIN
	LSH T3,^D30		;SHIFT AGAIN
	MOVX T2,<OF%RD+OF%WR> ;READ AND WRITE N BIT BYTES
	ADD T2,T3		;INCLUDE IN T2
	OPENF%			;OPEN THE LL
	 ERJMP JSER		;FAILURE
	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T3,[MO%SRV+MO%WFC]	;FAKE STATUS FOR PASSIVE TASK
	MOVE T2,@TYPE		;GET TYPE
	CAIE T2,0		;SKIP IF PASSIVE
	MOVE T3,[MO%WCC]	;FAKE STATUS FOR ACTIVE TASK
	MOVEM T3,LLSTAT(T1)	;SAVE IT
	MOVE T1,@NETLN		;OUR JFN
	MOVE T1,LLJFN(T1)	;OUR JFN
	MOVEI T2,.MOACN		;SET UP INTERRUPTS
	MOVE T4,@NETLN
	MOVE T4,CHAN		;CHANNEL NUMBER
	SETZ T3,		;THIS MAKES THE BIT MASK FOR MTOPR
	LSH T4,^D9
	ADD T3,T4
	LSH T4,^D9
	ADD T3,T4
	LSH T4,^D9
	ADD T3,T4
	MTOPR%			;DO IT
	 ERJMP JSER		;ERROR?
	MOVE T1,@NETLN		;GET OFFSET
	SKIPN @WAIT		;WAIT FOR THE OPEN?
	 RETURN 0		;NO RETURN OK
	CALL UPEVNT		;UPDATE THE EVENT WORD

; HERE WAIT FOR CONNECTION

CHKCON:	MOVE T1,@NETLN
	MOVE T2,LLEVNT(T1)	;GET EVENT WORD
	TRZE T2,EV.CON		;CONNECTED YET?
	JRST [MOVEM T2,LLEVNT(T1) ;TURN OFF EVENT BIT
	      RETURN 0]		;AND RETURN
	TRNE T2,EV.ABT+EV.DIS	;ABORT OR DISCONNECT?
	RETURN 2		;YES, ERROR RETURN
	MOVEI T1,DISTIM
	DISMS%
	JRST CHKCON		;GOT AN INTERRUPT, WAS IT FOR US?
;
; NFACC - ACCEPT A CONNECTION
;
NFACC::	SAVAC			;SAVE ACS

;*** HERE MOVE THE LANGUAGE VARIABLES TO THE CANONICAL STORAGE AREA ***

	MOVEI T1,@3(ARG)	;RETURN CODE ADDRESS
	MOVEM T1,RETCOD		;SAVE IT
	MOVEI T1,@0(ARG)	;ADDRESS OF NETLN
	MOVEM T1,NETLN		;SAVE IT
	MOVEI T1,@1(ARG)	;ADDRESS OF BYTE COUNT
	MOVEM T1,COUNT		;SAVE IT
IFN COBOL, <
	MOVEI T1,@2(ARG)	;ADDRESS OF 2 WORD DESC
	MOVE T1,0(T1)		;BYTE POINTER
>				;END OF COBOL CODE
IFN FORTRAN, <
	MOVEI T1,@2(ARG)	;STRING ADDRESS
	HLL T1,[POINT 7,0]	;MAKE A BYTE POINTER
>				;END OF FORTRAN CODE
	MOVEM T1,DATA		;SAVE IT

;*** HERE ENDS LANGUAGE INITIALIZATION CODE ***

	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T1,LLJFN(T1)	;GET THE JFN
	MOVEI T2,.MOCC		;ACCEPT THE CONNECTION
	MOVE T3,DATA		;GET BYTE POINTER
	MOVE T4,@COUNT		;CHARACTER COUNT FOR DATA
	MTOPR%			;ACCEPT IT
	 ERJMP JSER		;ERROR?
	MOVE T1,@NETLN		;OFFSET
	CALL UPEVNT		;UPDATE EVENT WORD
	RETURN 0
; NFRCV - RECEIVE DATA FROM A LOGICAL LINK
;

NFRCV::	SAVAC			;SAVE THE AC'S

;*** HERE GET LANGUAGE VARIABLES ***
	MOVEI T1,@5(ARG)	;ADDRESS OF RETCOD
	MOVEM T1,RETCOD		;SAVE IT
	MOVEI T1,@0(ARG)	;ADDRESS OF NETLN
	MOVEM T1,NETLN		;SAVE IT
	MOVEI T1,@1(ARG)	;ADDRESS OF BYTE COUNT
	MOVEM T1,COUNT		;SAVE IT
IFN COBOL, <
	MOVEI T1,@2(ARG)	;ADDRESS OF 2 WORD DESC BLOCK
	MOVE T1,0(T1)		;BYTE POINTER
>				;END OF COBOL CODE
IFN FORTRAN, <
	MOVEI T1,@2(ARG)	;STRING ADDRESS
	HLL T1,[POINT 7,0]	;MAKE A BYTE POINTER
>				;END OF FORTRAN CODE
	MOVEM T1,DATA		;SAVE IT
	MOVEI T1,@3(ARG)	;MESSAGE FLAG
	MOVEM T1,EOM		;SAVE IT
	MOVEI T1,@4(ARG)	;WAIT FLAG
	MOVEM T1,WAIT		;SAVE IT

; *** END OF LANGUAGE DEPENDANT CODE ***

CHKDAT:	MOVE T1,@NETLN		;SLOT NUMBER
	MOVE T1,LLEVNT(T1)	;GET EVENT FLAG
	TXNE T1,EV.INT		;INTERRUPT MESSAGE TO READ?
	JRST [SETZM @COUNT	;NO DATA RETURNED
		RETURN 2]
	MOVE T1,@EOM		;MESSAGE MODE FLAG
	JUMPN T1,MESS		;MESSAGE MODE
	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T1,LLJFN(T1)	;GET THE JFN
	SIBE%			;ANY CHARACTERS?
	SKIPA			;HAVE SOME BYTES!
	JRST CHKDS		;NO DATA YET
	SKIPE @WAIT		;WAITING?
	JRST DORCV		;YES, GO WAIT
	CAML T2,@COUNT		;HAVE ENOUGH DATA?
	JRST DORCV		;YES, GET IT
	HRRZM T2,@COUNT		;RETURN HOW MUCH IS THERE
	RETURN 4		;NOT ENOUGH FOR US
CHKDS:	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T1,LLEVNT(T1)	;GET STATUS
	TXNE T1,EV.ABT+EV.DIS	;ABORTED OR DISCONNECTED?
	JRST [SETZM @COUNT	;NO DATA RETURNED
		RETURN 1]
	SKIPN @WAIT		;WAITING?
	JRST [SETZM @COUNT	;NO DATA AVAILABLE YET
		RETURN 4]
	MOVEI T1,DISTIM
	DISMS%
	JRST CHKDAT		;GO CHECK AGAIN
MESS:	MOVE T1,@NETLN		;SLOT NUMBER
	MOVE T1,LLSTAT(T1)	;GET STATUS WORD
	TXNN T1,MO%EOM		;FULL MESSAGE?
	JRST CHKDS		;NO, CHECK IF WE ARE DISCONNECTED
	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T1,LLJFN(T1)	;GET JFN
	SIBE%			;GET CHARACTER COUNT
	CAMG T2,@COUNT		;TOO MANY CHARACTERS?
	JRST DORCV		;NO, DO THE READ
	MOVEM T2,@COUNT		;RETURN RECORD SIZE
	RETURN 3		;TOO MANY CHARACTERS
DORCV:	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T2,DATA		;GET THE BYTE POINTER
	HLL T2,LLEVNT(T1)	;BYTE POINTER
	MOVE T1,LLJFN(T1)	;GET THE JFN
	MOVN T3,@COUNT		;CHARACTER COUNT
	SKIPE @EOM		;MESSAGE MODE?
	JRST XMESS		;YES
	SIN%			;NO
	 ERJMP EOF		;ERROR?
	JRST SINCON		;GO ON
XMESS:	SINR%			;INPUT
	 ERJMP EOF		;ERROR?
SINCON:	ADD T3,@COUNT		;COMPUTE CHARACTERS READ
	MOVEM T3,@COUNT		;RETURN THE COUNT
	MOVE T1,@NETLN		;OFFSETT
	CALL UPEVNT		;UPDATE EVENT WORD
	RETURN 0		;YES
EOF:	ADD T3,@COUNT			;COMPUTE CHARACTERS READ
	MOVEM T3,@COUNT		;RETURN IT
	MOVE T1,@NETLN
	CALL UPEVNT
	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T1,LLEVNT(T1)	;GET EVENT FLAGS
	TXNE T1,EV.DIS+EV.ABT	;DISCONNECT OR ABORT?
	RETURN 1		;YES
	RETURN 5		;SIN OR SINR ERROR
;
; HERE TO SEND DATA
;
NFSND::	SAVAC			;SAVE THE ACS

; *** LANGUAGE DEPENDANT CODE ***
	MOVEI T1,@4(ARG)	;RETURN CODE ADDRESS
	MOVEM T1,RETCOD		;SAVE IT
	MOVEI T1,@0(ARG)	;NETLN
	MOVEM T1,NETLN		;SAVE IT
	MOVEI T1,@1(ARG)	;COUNT ADDRESS
	MOVEM T1,COUNT		;SAVE IT
IFN COBOL, <
	MOVEI T1,@2(ARG)	;DATA POINTER ADDRESS
	MOVE T1,0(T1)		;GET BYTE POINTER
>				;END OF COBOL CODE
IFN FORTRAN, <
	MOVEI T1,@2(ARG)	;STRING ADDRESS
	HLL T1,[POINT 7,0]	;MAKE A BYTE POINTER
>
	MOVEM T1,DATA		;SAVE IT
	MOVEI T1,@3(ARG)	;EOM FLAG ADDRESS
	MOVEM T1,EOM		;SAVE IT
; *** END OF LANGUAGE DEPENDANT CODE ***

	MOVE T1,@NETLN		;SLOT NUMBER
	MOVE T2,DATA		;BYTE POINTER
	HLL T2,LLEVNT(T1)	;BYTE POINTER
	MOVE T1,LLJFN(T1)	;GET THE JFN
	MOVN T3,@COUNT		;CHARACTER COUNT
	SKIPN @EOM		;MESSAGE MODE?
	JRST STREAM		;NO
	SOUTR%			;YES
	 ERJMP JSER		;ERROR?
	RETURN 0		;RETURN
STREAM:	SOUT%			;OUTPUT IT
	 ERJMP JSER		;ERROR?
	RETURN 0
		
;
; HERE TO REJECT A CONNECTION
;
NFREJ::	SAVAC			;SAVE AC'S

;*** LANGUAGE DEPENDENT CODE ***
	MOVEI T1,@4(ARG)	;ADDRESS OF RETURN CODE
	MOVEM T1,RETCOD		;SAVE IT
	MOVEI T1,@0(ARG)	;ADDRESS OF NETLN
	MOVEM T1,NETLN		;SAVE IT
	MOVEI T1,@1(ARG)	;ADDRESS OF CODE
	MOVEM T1,CODE		;SAVE IT
	MOVEI T1,@2(ARG)	;ADDRESS OF COUNT
	MOVEM T1,COUNT		;SAVE IT
IFN COBOL, <
	MOVEI T1,@3(ARG)	;ADDRESS OF DATA DESCRIPTOR
	MOVE T1,0(T1)		;GET BYTE POINTER
>				;END OF COBOL CODE
IFN FORTRAN, <
	MOVEI T1,@3(ARG)	;STRING ADDRESS
	HLL T1,[POINT 7,0]	;MAKE A BYTE POINTER
>				;END OF FORTRAN STUFF
	MOVEM T1,DATA		;SAVE IT
; *** END OF LANGUAGE DEPENDANT STUFF ***

	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T1,LLJFN(T1)	;GET THE JFN
	MOVEI T2,.MOCLZ		;REJECT FUNCTION
	HRL T2,@CODE		;REJECT CODE
	MOVE T3,DATA		;REJECT MESSAGE
	MOVE T4,@COUNT		;CHAR COUNT FOR MESSAGE
	MTOPR%
	 ERJMP JSER		;ERROR?
	MOVE T1,@NETLN
	CALL UPEVNT
	RETURN 0
;
; HERE TO SEND AN INTERRUPT MESSAGE
;
NFINT::	SAVAC			;SAVE THE AC'S

;*** LANGUAGE DEPENDENT CODE ***
	MOVEI T1,@3(ARG)	;ADDRESS OF RETCOD
	MOVEM T1,RETCOD		;SAVE IT
	MOVEI T1,@0(ARG)	;ADDRESS OF NETLN
	MOVEM T1,NETLN		;SAVE IT
	MOVEI T1,@1(ARG)	;ADDRESS OF COUNT
	MOVEM T1,COUNT		;SAVE IT
IFN COBOL, <
	MOVEI T1,@2(ARG)	;ADDRESS OF DATA DESCRIPTOR
	MOVE T1,0(T1)		;BYTE POINTER
>				;END OF COBOL CODE
IFN FORTRAN, <
	MOVEI T1,@2(ARG)	;STRING ADDRESS
	HLL T1,[POINT 7,0]	;MAKE IT A BYTE POINTER
>				;END OF FORTRAN CODE
	MOVEM T1,DATA		;SAVE IT
; *** END OF LANGUAGE DEPENDANT STUFF ***

	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T1,LLJFN(T1)	;GET THE JFN
	MOVEI T2,.MOSIM		;SEND INT MESSAGE FUNCTION
	MOVE T3,DATA		;BYTE POINTER
	MOVE T4,@COUNT		;CHAR COUNT FOR MESSAGE
	MTOPR%			;SEND IT
	 ERJMP JSER		;ERROR?
	RETURN 0
;
; HERE TO RECEIVE AN INTERRUPT MESSAGE
;

NFRCI::	SAVAC			;SAVE THE AC'S

; *** LANGUAGE DEPENDENT CODE ***
	MOVEI T1,@3(ARG)	;ADDRESS OF RETCOD
	MOVEM T1,RETCOD		;SAVE IT
	MOVEI T1,@0(ARG)	;ADDRESS OF NETLN
	MOVEM T1,NETLN		;SAVE IT
	MOVEI T1,@1(ARG)	;ADDRESS OF COUNT
	MOVEM T1,COUNT		;SAVE IT
IFN COBOL, <
	MOVEI T1,@2(ARG)	;ADDRESS OF STRING DESCRIPTOR
	MOVE T1,0(T1)		;BYTE POINTER
>				;END OF COBOL CODE
IFN FORTRAN ,<
	MOVEI T1,@2(ARG)	;STRING ADDRESS
	HLL T1,[POINT 7,0]	;MAKE IT A BYTE POINTER
>				;END OF FORTRAN CODE
	MOVEM T1,DATA		;SAVE IT
;*** END OF LANGUAGE DEPENDENT CODE ***

	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVX T2,EV.INT
	XORM T2,LLEVNT(T1)
	MOVE T1,LLJFN(T1)	;GET THE JFN
	MOVEI T2,.MORIM		;MTOPR FUNCTION
	MOVE T3,DATA		;BYTE POINTER
	MTOPR%
	 ERJMP [RETURN 1]	;NO INTERRUPT MESSAGE
	MOVEM T4,@COUNT		;RETURN COUNT OF BYTES IN MESSAGE
	MOVE T1,@NETLN		;GET SLOT NUMBER
	RETURN 0		;RETURN
;
; HERE TO DISCONNECT OR ABORT THE LINK
;
NFCLS::	SAVAC			;SAVE THE AC'S

;*** LANGUAGE DEPENDENT CODE ***
	MOVEI T1,@5(ARG)	;RETURN CODE ADDRESS
	MOVEM T1,RETCOD		;SAVE IT
	MOVEI T1,@0(ARG)	;NETLN ADDRESS
	MOVEM T1,NETLN		;SAVE IT
	MOVEI T1,@1(ARG)	;ABORT OR DISCONNECT FLAG
	MOVEM T1,TYPE		;SAVE IT
	MOVEI T1,@2(ARG)	;DISCONNECT OR ABORT CODE
	MOVEM T1,CODE		;SAVE IT
	MOVEI T1,@3(ARG)	;BYTE COUNT ADDRESS
	MOVEM T1,COUNT		;SAVE IT
IFN COBOL, <
	MOVEI T1,@4(ARG)	;DATA DESCRIPTOR
	MOVE T1,0(T1)		;BYTE POINTER
>				;END OF COBOL CODE
IFN FORTRAN, <
	MOVEI T1,@4(ARG)	;STRING ADDRESS
	HLL T1,[POINT 7,0]	;MAKE IT A BYTE POINTER
>				;END OF FORTRAN CODE
	MOVEM T1,DATA		;SAVE IT
;*** END OF LANGUAGE DEPENDANT CODE ***

	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T2,LLSTAT(T1)	;GET STATUS
	TXNN T2,MO%CON		;STILL CONNECTED?
	JRST CLOZ		;ONLY CLOSE ALLOWED HERE
	SKIPE @TYPE		;SYN DISCONNECT?
	JRST DOMTR		;NO
	SKIPN @COUNT		;OPTIONAL DATA?
	JRST CLOZ		;NO
DOMTR:	MOVE T1,LLJFN(T1)	;JFN OF THE LINK
	MOVEI T2,.MOCLZ		;DISCONNECT CODE
	MOVE T3,DATA		;BYTE POINTER
	MOVE T4,@COUNT		;CHARACTER COUNT
	SKIPE @TYPE		;SKIP IF SYN DISCONNECT
	HRL T2,@CODE		;ABORT CODE
	MTOPR%
	 ERJMP JSER		;ERROR?
CLOZ:	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T1,LLJFN(T1)	;GET THE JFN
	SKIPE @TYPE		;ABORT OR SYNCHRONOUS?
	TXO T1,CZ%ABT		;ABORT
	CLOSF%			;CLOSE THE LL
	 ERJMP JSER		;ERROR?
	MOVE T2,@NETLN		;SLOT NUMBER
	SETZM LLJFN(T2)		;ZERO THE JFN
	SETZM LLEVNT(T2)	;ZERO THE EVENT WORD
	SETZM LLSTAT(T2)	;AND THE STATUS WORD
	RETURN 0
;
; HERE TO GET INFOR ON LINK
;

NFINF::	SAVAC			;SAVE AC'S

; *** LANGUAGE DEPANDENT CODE ***
	MOVEI T1,@4(ARG)	;ADDRESS OF RETURN CODE
	MOVEM T1,RETCOD		;SAVE IT
	MOVEI T1,@0(ARG)	;ADDRESS OF NETLN
	MOVEM T1,NETLN		;SAVE IT
	MOVEI T1,@1(ARG)	;ADDRESS OF TYPE
	MOVEM T1,TYPE		;SAVE TYPE
	MOVEI T1,@2(ARG)	;ADDRESS OF COUNT
	MOVEM T1,COUNT		;SAVE IT
IFN COBOL, <
	MOVEI T1,@3(ARG)	;ADDRESS OF DATA DESCRIPTOR
	MOVE T1,0(T1)		;BYTE POINTER
>				;END OF COBOL CODE
IFN FORTRAN, <
	MOVEI T1,@3(ARG)	;STRING ADDRESS
	HLL T1,[POINT 7,0]	;MAKE IT A BYTE POINTER
>				;END OF FORTRAN CODE
	MOVEM T1,DATA		;SAVE IT
; *** END OF LANGUAGE DEPENDANT STUFF ***

	MOVE T1,@TYPE		;GET INFO TYPE
	CAILE T1,0		;IS REQUESTED TYPE WITHIN RANGE?
	CAILE T1,^D9		;?
	RETURN 2		;NO, ERROR
	JRST INFDSP(T1)		;GO DO IT

INFDSP:	HALTF%			;NO SUCH FUNCTION
	JRST NODNAM		;RETURN NODE NAME
	JRST OBJTYP		;RETURN OBJECT TYPE
	JRST OBJDSF		;RETURN OBJECT DESCRIPTOR FORMAT
	JRST OBJDSC		;RETURN OBJECT DESCRIPTOR
	JRST USERID		;RETURN USERID
	JRST PASSWD		;RETURN PASSWORD
	JRST ACCT		;RETURN ACCOUNT
	JRST OPTDAT		;RETURN OPTIONAL DATA
	JRST ABTCOD		;GET ABORT CODE

ABTCOD:	MOVE T1,@NETLN		;GET SLOT NUMBER
	HRRZ T2,LLSTAT(T1)	;ABORT OR DISCONNECT CODE
	MOVE T1,DATA		;BYTE PPOINTER
	MOVEI T3,^D10		;RADIX
	NOUT%
	 ERJMP JSER		;ERROR?
	CALL NUMB		;RETURN STRING SIZE
	RETURN 0

NODNAM:	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T1,LLJFN(T1)	;GET THE JFN
	MOVEI T2,.MORHN		;
	MOVE T3,DATA		;
	MTOPR%
	 ERJMP JSER		;ERROR?
	MOVE T1,T3		;UPDATED BYTE POINTER
	CALL NUMB		;CIUNT BYTES
	RETURN 0		;RETURN NODE NAME

OBJTYP:	MOVE T1,@NETLN		;GET LSOT NUMBER
	MOVE T2,LLSTAT(T1)	;GET LL STATUS
	TXNN T2,MO%SRV		;A SERVER?
	RETURN 1		;NO, NO DATA TO RETURN
	MOVE T1,LLJFN(T1)	;GET THE JFN
	MOVEI T2,.MORCN		;
	MTOPR%
	 ERJMP JSER		;ERROR?
	MOVE T1,DATA		;
	MOVE T2,T3		;OBJECT TYPE
	MOVEI T3,^D10		;BASE 10
	NOUT%			;REURN IT
	 JRST JSER		;ERROR?
	CALL NUMB		;STRING SIZE
	RETURN 0

USERID:	MOVE T1,@NETLN		;SLOT NUMBER
	MOVE T2,LLSTAT(T1)	;LL STATUS
	TXNN T2,MO%SRV		;A SERVER?
	RETURN 1		;NO
	MOVE T1,LLJFN(T1)	;GET THE JFN
	MOVEI T2,.MORUS		;
	MOVE T3,DATA
	MTOPR%
	 ERJMP JSER		;ERROR?
	MOVE T1,T3		;UPDATED BYTE POINTER
	CALL NUMB		;STRING LENGTH
	RETURN 0

OBJDSF:	MOVEI T1,1		;STRING LENGTH
	MOVEM T1,@COUNT		;RETURN IT
	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T2,LLSTAT(T1)	;GET LL STATUS
	TXNN T2,MO%SRV		;SEFVER?
	RETURN 1
	MOVE T1,LLJFN(T1)	;GET THE JFN
	MOVEI T2,.MOROD		;FUNCTION
	MOVE T3,[POINT 7,TEMPST]
	MTOPR%
	 ERJMP JSER		;ERROR?
	MOVE T1,DATA		;
	MOVEI T2,"0"
	CAMN T3,[POINT 7,TEMPST]
	JRST [BOUT%
		RETURN 0]
	SKIPN T4		;USER AND GROUP NUMBERS?
	JRST [ADDI T2,1
		BOUT%
		RETURN 0]
	ADDI T2,2		;YES
	BOUT%
	RETURN 0

OBJDSC:	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T2,LLSTAT(T1)	;GET LL STATUS
	TXNN T2,MO%SRV		;SERVER?
	RETURN 1		;NO
	MOVE T1,LLJFN(T1)	;GET JFN
	MOVEI T2,.MOROD		;OBJECT DESCRIPTOR FUNCTION
	MOVE T3,[POINT 7,TEMPST]
	MTOPR%
	 ERJMP JSER		;ERROR?
	CAIN T4,0		;GROUP AND USER CODES?
	JRST [HRROI T1,TEMPST	;FROM TEMP STRING
		MOVE T2,DATA	;TO USER'S BUFFER
		SETZ T3,	;ASCIZ STRING
		SIN%
		MOVE T1,T2	;UPDATED POINTER
		CALL NUMB	;STRING LENGTH
		RETURN 0]
	MOVE T1,DATA		;USER'S BUFFER
	HLRZ T2,T4		;GROUP
	MOVEI T3,^D8		;OCTAL
	NOUT%
	 ERJMP JSER		;ERROR?
	MOVEI T2,","		;COMMA
	BOUT%			;
	HRRZ T2,T4		;USER
	NOUT%
	 ERJMP JSER		;ERROR?
	MOVEI T2,","		;
	BOUT%
	HRROI T2,TEMPST
	SETZ T3,
	SOUT%
	CALL NUMB		;STRING LENGTH
	RETURN 0

PASSWD:	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T2,LLSTAT(T1)	;GET LINK STATUS
	TXNN T2,MO%SRV		;SERVER ONLY
	RETURN 1
	MOVE T1,LLJFN(T1)	;GET THE JFN
	MOVEI T2,.MORPW		;PASSWORD FUNCTION
	MOVE T3,DATA		;
	MTOPR%
	 ERJMP JSER		;ERROR?
	MOVE T1,T3		;UPDATED POINTER
	CALL NUMB
	RETURN 0

ACCT:	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T2,LLSTAT(T1)	;GET LL STATUS
	TXNN T2,MO%SRV		;SERVER?
	RETURN 1		;NO
	MOVE T1,LLJFN(T1)	;GET THE JFN
	MOVEI T2,.MORAC		;ACCOUNT STRING FUNCTION
	MOVE T3,DATA		;
	MTOPR%			;
	 ERJMP JSER		;ERROR?
	MOVE T1,T3		;UPDATED POINTER
	CALL NUMB		;STRING LENGTH
	RETURN 0

OPTDAT:	MOVE T1,@NETLN		;GET SLOT NUMBER
	MOVE T1,LLJFN(T1)	;GET THE JFN
	MOVEI T2,.MORDA		;OPTIONAL DATA FUNCTION
	MOVE T3,DATA		;BYTE POINTER
	MTOPR%
	 ERJMP JSER		;ERROR?
	MOVE T1,T3		;UPDATED POINTER
	CALL NUMB		;STRING LENGTH
	RETURN 0

NUMB:	HRRZ T2,T1		;UPDATED WORD
	HRRZ T3,DATA		;ORIGINAL WORD
	SUB T2,T3		;NUMBER OF WORDS
	IMULI T2,^D5		;NUMBER OF CHARACTERS
	LSH T1,-^D30		;GET P
	MOVEI T3,^D36		;BITS IN A WORD
	SUB T3,T1		;BITS 
	IDIVI T3,^D7		;BYTES
	ADD T2,T3		;TOTAL BYTES
	MOVEM T2,@COUNT		;RETURN IT
	RET
;
; HERE TO INITIALIZE THE INTERRUPT SYSTEM
;
PSINIT:	SETOM START		;WE HAVE BEGUN
	MOVEI T1,.FHSLF		;FOR THIS PROCESS
	RIR%			;CHANNEL AND LEVEL TABLES ALREADY SET UP?
	JUMPE T2,FIRST		;NO, DO IT ALL
	MOVEM T2,LEVCHN		;SAVE IT
CONPSI:	MOVEI T1,PC		;WHERE TO HOLD OUR PC
	HLRZ T3,T2		;LEVEL TABLE ADDRESS
	MOVEM T1,2(T3)		;USE LEVEL 2
	HRRZ T2,T2		;ADDRESS OF CHANNEL TABLE
	MOVE T1,[3,,INT]	;LEVEL,,ROUTINE
	MOVEM T1,^D35(T2)	;SAVE IT
	MOVEI T1,.FHSLF		;THIS PROCESS
	MOVEI T2,1		;CHANNEL 35
	AIC%			;ACTIVATE THIS CHANNEL
	EIR%			;DOESN'T HURT
	MOVEI T1,^D35		;CHANNEL 35
	MOVEM T1,CHAN		;REMEMBER IT
	RET

FIRST:	MOVEI T1,.FHSLF		;FOR THIS PROCESS
	MOVE T2,[LEVTAB,,CHNTAB]
	MOVEM T1,LEVCHN		;SAVE IT
	SIR%			;SET UP LEVEL AND CHANNEL TABLES
	JRST CONPSI		;GO ON


; HERE TO PROCESS INTERRUPTS

INT:	DMOVEM T1,T1T2		; SAVE T1 AND T2
	DMOVEM T3,T3T4		;SAVE ALL 4 ACS
	HRREI T1,-1		;ASK FOR UPDATE ON ALL CHANNELS
	CALL UPEVNT		;UPDATE EVENT FLAGS
	MOVE T1,PC		;ADD OF INTERRUPTED CODE
	MOVE T2,-1(T1)		;GET THE INSTRUCTION
	CAME T2,[DISMS%]		;WAIT INSTRUCTION
	JRST GOBACK		;DEBRK
	TXO T1,1B5		;USER MODE FLAG
	MOVEM T1,PC		;
GOBACK:	DMOVE T1,T1T2		;RESTORE AC'S
	DMOVE T3,T3T4		;RESTORE AC'S
	DEBRK%			;GO BACK

; HERE TO UPDATE THE EVENT FLAGS
;
; T1 MUST CONTAIN THE SLOT NUMBER OF THE LL
; OR -1 TO INDICATE UPDATE OF ALL LINKS

UPEVNT:	CAIL T1,0		;ALL LINKS?
	JRST [CALL ONELL	;UPDATE THE SINGLE LINK
		RET]
	MOVE T4,[-MAXLL,,0]	;AOBJN POINTER
UPLP:	HRRZ T1,T4		;GET LL NUMBER
	SKIPN LLJFN(T1)		;LINK IN USE?
	JRST UPLPE		;NO
	PUSH P,T4		;SAVE T4
	CALL ONELL		;YES
	POP P,T4		;RESTORE T4
UPLPE:	AOBJN T4,UPLP		;DO ALL LINKS
	RET

ONELL:	PUSH P,T1		;SAVE SLOT NUMBER
	MOVE T1,LLJFN(T1)	;GET THE JFN
	MOVEI T2,.MORLS		;GET LINK STATUS
	MTOPR%			;GET IT
	 ERCAL [SETZ T3,	;ZERO STATUS ON ERROR
		RET]		;GO ON
	POP P,T1		;GET SLOT NUMBER
	MOVE T2,LLSTAT(T1)	;GET OLD STATUS
	MOVE T4,LLEVNT(T1)	;GET EVENT WORD
	TXNE T3,MO%SRV		;PASSIVE TASK?
	JRST PASS		;YES, DO IT
	TXNE T3,MO%CON		;NOW CONNECTED?
	JRST [TXNN T2,MO%CON    ;NOT CONNECTED BEFORE?
		TXO T4,EV.CON	;CONNECT EVENT
		JRST .+1]
	JRST COMM		;COMMON CHECKS
PASS:	TXNE T2,MO%WFC		;WERE WAITING FOR CONNECT?
	JRST [TXNN T3,MO%WFC	;BUT NOT NOW
		TXO T4,EV.CON	;YES, CONNECT EVENT
		JRST .+1]
COMM:	TXNE T3,MO%ABT		;ABORT?
	JRST [TXNN T2,MO%ABT	;ABORT BEFORE?
		TXO T4,EV.ABT	;ABORT EVENT
		JRST .+1]
	TXNE T3,MO%INT		;INTERRUPT MESS AVAILABLE?
	JRST [TXNN T2,MO%INT
		TXO T4,EV.INT	;INTERRUPT MESS EVENT
		JRST .+1]
	TXNE T3,MO%SYN		;DISCONNECT?
	JRST [TXNN T2,MO%SYN
		TXO T4,EV.DIS	;DISCONNECT EVENT
		JRST .+1]
	MOVEM T3,LLSTAT(T1)	;SAVE NEW LINK STATUS
	PUSH P,T1		;SAVE SLOT NUMBER
	MOVE T1,LLJFN(T1)	;GET JFN
	SIBE%			;ANY DATA?
	JRST [TXO T4,EV.DAT	;DATA EVENT
		JRST GOTDAT]
	TXZ T4,EV.DAT		;NO DATA
GOTDAT:	POP P,T1		;RESTORE T1
	MOVEM T4,LLEVNT(T1)	;SAVE EVENT WORD
	RET

; HERE WHEN A JSYS FAILS

JSER:	CAIGE T1,600000		;REAL ERROR CODE?
	JRST [MOVEI T1,.FHSLF	;FOR THIS PROCESS
		GETER%		;GET MOST RECENT ERROR
		HRRZ T1,T2	;
		CAIGE T1,600000 ;REAL CODE?
		SETZ T1,
		JRST .+1]
	MOVEM T1,@RETCOD	;
	RET			;RETURN

	END