Google
 

Trailing-Edge - PDP-10 Archives - BB-M080O-SM - monitor-sources/jntman.mac
There are 17 other files named jntman.mac in the archive. Click here to see a list.
; *** Edit 7499 to JNTMAN.MAC by RASPUZZI on 9-Jul-87 (TCO 7.1017)
; Fix stupidity in edit 7497. Engineer needs vacation badly. 
; *** Edit 7497 to JNTMAN.MAC by RASPUZZI on 7-Jul-87 (TCO 7.1017)
; Fix .NDVFY function of NODE% JSYS. Don't let a user give us a string of more
; than 6 characters and tell him that it is a legal DECnet node name. 
;------------------------- Autopatch Tape # 13 -------------------------
;------------------------- Autopatch Tape # 12 -------------------------
; UPD ID= 2210, SNARK:<6.1.MONITOR>JNTMAN.MAC.57,  11-Jun-85 13:49:28 by PALMIERI
;TCO 6.1.1435  Increase the allowable block size on the Ethernet from 1467 to
;1476.
; UPD ID= 2090, SNARK:<6.1.MONITOR>JNTMAN.MAC.56,   3-Jun-85 14:47:49 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 1824, SNARK:<6.1.MONITOR>JNTMAN.MAC.55,  25-Apr-85 16:12:19 by PALMIERI
;TCO 6.1.1343 - Update to the new format for keeping track of port blocks in
; SCJSYS
; UPD ID= 1381, SNARK:<6.1.MONITOR>JNTMAN.MAC.54,  22-Jan-85 11:27:58 by PALMIERI
;Change parameter we use to read node reachability state to 2503.
;Have .NDGLI return error  "no longer supported"
; UPD ID= 1331, SNARK:<6.1.MONITOR>JNTMAN.MAC.53,  14-Jan-85 17:48:55 by GLINDELL
;Set ND%RUK if endnode and NDRCHK returns an error
;Restructure .NDCIN so the interlocks are ok
;Require privs for the .NDRDB  and .NDCIN functions
;Add comments
; UPD ID= 1315, SNARK:<6.1.MONITOR>JNTMAN.MAC.52,  11-Jan-85 16:50:08 by GLINDELL
;Fix SLDOB and SLSOB once again...
; UPD ID= 1200, SNARK:<6.1.MONITOR>JNTMAN.MAC.51,  12-Dec-84 17:08:57 by GLINDELL
;NDINT called SCTAND in section 1...
; UPD ID= 1158, SNARK:<6.1.MONITOR>JNTMAN.MAC.50,   5-Dec-84 17:29:44 by GLINDELL
;RTRNMX now lives in XCDSEC
; UPD ID= 1151, SNARK:<6.1.MONITOR>JNTMAN.MAC.49,   5-Dec-84 17:10:39 by PALMIERI
;Fix update 772 to return byte pointer is user AC3
; UPD ID= 1069, SNARK:<6.1.MONITOR>JNTMAN.MAC.48,  13-Nov-84 20:55:59 by GLINDELL
;Declare %RTEHS EXTERNAL
; UPD ID= 1066, SNARK:<6.1.MONITOR>JNTMAN.MAC.47,  13-Nov-84 16:01:29 by GLINDELL
;Minimum buffer size is 290 bytes
; UPD ID= 1003, SNARK:<6.1.MONITOR>JNTMAN.MAC.46,   7-Nov-84 16:22:55 by PALMIERI
;Remove NRBTBL routine of NDRDB NODE JSYS function
; UPD ID= 986, SNARK:<6.1.MONITOR>JNTMAN.MAC.45,   7-Nov-84 12:47:58 by PALMIERI
;Change maximum blocksize settable by SETSPD
; UPD ID= 934, SNARK:<6.1.MONITOR>JNTMAN.MAC.44,  28-Oct-84 21:02:12 by PRATT
;TCO 6.1.1022 - GETSIX will always return the updated BP in T2
; UPD ID= 881, SNARK:<6.1.MONITOR>JNTMAN.MAC.43,  12-Oct-84 18:07:29 by GLINDELL
;Return NODX17 if value is out of range in .NDSDP
;Implement .NDFLO parameter of the .NDSDP function
; UPD ID= 860, SNARK:<6.1.MONITOR>JNTMAN.MAC.42,  10-Oct-84 15:31:44 by HALPIN
;Return NDVFY1  to global for now
; UPD ID= 858, SNARK:<6.1.MONITOR>JNTMAN.MAC.41,  10-Oct-84 09:40:50 by PALMIERI
;Correct reachability status of executor node and add reachability unknown for
; out of area nodes
; UPD ID= 856, SNARK:<6.1.MONITOR>JNTMAN.MAC.40,   9-Oct-84 10:19:12 by GLINDELL
;Remove ND%KNO, it means the same as ND%EXM
; UPD ID= 855, SNARK:<6.1.MONITOR>JNTMAN.MAC.39,   9-Oct-84 10:05:34 by GLINDELL
;Set bit ND%EXM always if node is known by SCLINK
; UPD ID= 830, SLICE:<6.1.MONITOR>JNTMAN.MAC.35,  26-Sep-84 14:56:56 by NICHOLS
;Change name of SLROB to SLDOB (Dest Obj Type)
; UPD ID= 819, SLICE:<6.1.MONITOR>JNTMAN.MAC.34,  24-Sep-84 17:22:34 by PALMIERI
;Remove routine to read Router circuit blocks
; UPD ID= 785, SNARK:<6.1.MONITOR>JNTMAN.MAC.33,   4-Sep-84 14:34:38 by GLINDELL
;Use NOSKED/OKSKED in NRBCPD routine
; UPD ID= 777, SNARK:<6.1.MONITOR>JNTMAN.MAC.32,  31-Aug-84 14:22:02 by HALPIN
;Wrote new routine, NDRCHK, to check for node reachablity. Use new NMX
;interface designed for NTMAN
;
; UPD ID= 772, SNARK:<6.1.MONITOR>JNTMAN.MAC.31,  31-Aug-84 12:18:11 by PALMIERI
;Return updated byte pointer in NODE% function .NDRNM
; UPD ID= 657, SNARK:<6.1.MONITOR>JNTMAN.MAC.30,   2-Jul-84 16:54:12 by GLINDELL
;Read packets sent/received from SLPK? instead of from ELPK?
; UPD ID= 608, SNARK:<6.1.MONITOR>JNTMAN.MAC.29,   7-Jun-84 18:35:53 by GLINDELL
;Check min and max values in .NDSDP function
; UPD ID= 607, SNARK:<6.1.MONITOR>JNTMAN.MAC.28,   6-Jun-84 17:32:44 by GLINDELL
;Implement .NDSDP and .NDINT functions.
; UPD ID= 597, SNARK:<6.1.MONITOR>JNTMAN.MAC.27,   5-Jun-84 17:32:05 by GLINDELL
;Fix a RESCD/SWAPCD bug
; UPD ID= 563, SNARK:<6.1.MONITOR>JNTMAN.MAC.26,  24-May-84 15:59:08 by GLINDELL
;The world is not yet ready for 16-bit node addresses....
; UPD ID= 553, SNARK:<6.1.MONITOR>JNTMAN.MAC.25,  24-May-84 10:42:44 by GLINDELL
;Pick up default area # from RTRHOM, and store changed area # there
; UPD ID= 526, SNARK:<6.1.MONITOR>JNTMAN.MAC.24,  18-May-84 09:22:56 by GLINDELL
;Change node name/number routines to use IB block
;Accomodate new initialization
;Global job numbers
; UPD ID= 505, SNARK:<6.1.MONITOR>JNTMAN.MAC.23,   7-May-84 13:06:59 by GLINDELL
;RESCD needed in a place + use RTRMXN instead of SCTMXN
; UPD ID= 454, SNARK:<6.1.MONITOR>JNTMAN.MAC.22,  25-Apr-84 11:36:20 by GLINDELL
;Insert missing SWAPCD, and delete unnecessary instruction
; UPD ID= 377, SNARK:<6.1.MONITOR>JNTMAN.MAC.21,   9-Mar-84 10:47:27 by NICHOLS
;Small improvement in INFO DECNET efficiency at NDGNT
; UPD ID= 289, SNARK:<6.1.MONITOR>JNTMAN.MAC.20,  11-Jan-84 12:14:44 by MCINTEE
;Protective code for CTERM stuff
; UPD ID= 243, SNARK:<6.1.MONITOR>JNTMAN.MAC.19,  11-Nov-83 14:27:30 by PALMIERI
;Add minimal support for area numbers
; UPD ID= 233, SNARK:<6.1.MONITOR>JNTMAN.MAC.18,   1-Nov-83 17:09:54 by NICHOLS
;Report destination object type instead of source object type in NDCIN
; UPD ID= 212, SNARK:<6.1.MONITOR>JNTMAN.MAC.17,   7-Oct-83 14:00:18 by MCINTEE
;Add comment to set local name function
; UPD ID= 150, SNARK:<6.1.MONITOR>JNTMAN.MAC.16,  23-Jun-83 13:45:05 by CHALL
;NDGLN- Return updated pointer to node name, to caller.
; UPD ID= 118, SNARK:<6.1.MONITOR>JNTMAN.MAC.15,  27-Apr-83 10:31:50 by MCINTEE
;More of previous
; UPD ID= 115, SNARK:<6.1.MONITOR>JNTMAN.MAC.14,  26-Apr-83 09:54:01 by MCINTEE
;REMOVE PREVIOUS EDIT
; UPD ID= 109, SNARK:<6.1.MONITOR>JNTMAN.MAC.13,  22-Apr-83 11:18:31 by MCINTEE
;In NDGNT, get session control interlock.
; UPD ID= 91, SNARK:<6.1.MONITOR>JNTMAN.MAC.12,  25-Mar-83 14:46:15 by NICHOLS
;Fix NODE JSYS for SYSDPY, if there is no port table for an SJB,
;return zero in all port table fields
; UPD ID= 81, SNARK:<6.1.MONITOR>JNTMAN.MAC.10,  21-Mar-83 13:34:12 by CHALL
;Remove Read-Channel-Table function from NDRDB
; UPD ID= 80, SNARK:<6.1.MONITOR>JNTMAN.MAC.10,  17-Mar-83 14:23:18 by CHALL
;Add reading of RCB to NDRDB
; UPD ID= 77, SNARK:<6.1.MONITOR>JNTMAN.MAC.9,   9-Mar-83 14:40:43 by CHALL
;More changes to make NDRNM, NDCIN, and NDRDB work better
; UPD ID= 74, SNARK:<6.1.MONITOR>JNTMAN.MAC.8,   4-Mar-83 14:32:06 by CHALL
;Fix: NDRNM tried to use a fragged T2 (pointer to user's arg block)
; UPD ID= 73, SNARK:<6.1.MONITOR>JNTMAN.MAC.7,   4-Mar-83 12:27:33 by CHALL
;Add .NDRDB function, to read a table from the monitor
; UPD ID= 65, SNARK:<6.1.MONITOR>JNTMAN.MAC.6,  28-Feb-83 15:58:34 by CHALL
;Make .NDCIN look at NRT and CTERM when it is done with the jobs
; UPD ID= 46, SNARK:<6.1.MONITOR>JNTMAN.MAC.5,  17-Feb-83 15:27:34 by CHALL
;More .NDCIN
; UPD ID= 32, SNARK:<6.1.MONITOR>JNTMAN.MAC.4,  14-Feb-83 12:39:36 by MCINTEE
;ADD SEARCH SCPAR
; UPD ID= 26, SNARK:<6.1.MONITOR>JNTMAN.MAC.3,  14-Feb-83 11:01:18 by MCINTEE
;SIXBIT node names
;Add .NDCIN function, to read per-active-channel data for SYSDPY

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY  BE  USED
;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT  (C)  DIGITAL  EQUIPMENT  CORPORATION  1976, 1985.
;ALL RIGHTS RESERVED.


	SEARCH PROLOG,D36PAR,SCPAR,CTERMD,TTYDEF
	TTITLE (JNTMAN,,< - Network Management JSYS     >)
;DEFINITIONS FOR NETWORK TOPOLOGY CHANGE TABLES
;THESE DEFINITIONS ARE FOR NTCTAB.

DEFSTR (NTCFRK,0,17,18)		;FORK WANTING INTERRUPT AT TOPOLOGY CHANGE
DEFSTR (NTCCHN,0,35,18)		;CHANNEL ON WHICH TO INTERRUPT FORK

EXTERN RTRHOM,RTRMXN,IBBLK,D36IFG,RTRNMX,%RTEHS
SUBTTL	The NODE JSYS

	SWAPCD			;IS SWAPPABLE
.NODE::	MCENT			;MONITOR CONTEXT ENTRY
	EA.ENT			;DECNET RUNS IN EXTENDED SECTIONS

; VALIDATE FUNCTION CODE AND DISPATCH TO PROCESSING ROUTINE

	UMOVE T1,1		;GET FUNCTION CODE FROM USER
	CAIL T1,0		;FUNCTION CODE WITHIN
	CAIL T1,NDTLEN		; VALID RANGE ?
	ITERR (ARGX02)		;NO, RETURN "INVALID FUNCTION" ERROR
	CALL @NODTAB(T1)	;DISPATCH TO PROPER ROUTINE
	 ITERR ()		;FAILED, RETURN ERROR CODE
	MRETNG			;SUCCESS, DONE.

; TABLE OF NODE JSYS FUNCTIONS

;* NOTE THAT FUNCTIONS MARKED WITH AN ASTERISK ARE NO LONGER SUPPORTED WITH
;  DECnet-36 MONITORS (R6.1 AND BEYOND).

NODTAB:	IFIW NDSLN		;(0) SET LOCAL NODE NAME
	IFIW NDGLN		;(1) GET LOCAL NODE NAME
	IFIW NDSNM		;(2) SET LOCAL NODE NUMBER
	IFIW NDGNM		;(3) GET LOCAL NODE NUMBER
	IFIW NDNLS		;(4) SET LOOPBACK PORT *
	IFIW NDNLS		;(5) CLEAR LOOPBACK PORT *
	IFIW NDNLS		;(6) FIND LOOPBACK PORT *
	IFIW NDNLS		;(7) SET NETWORK TOPOLOGY INFO *
	IFIW NDGNT		;(10) GET NETWORK TOPOLOGY INFO
	IFIW NDSIC		;(11) SET INT CHANNEL FOR TOPOLOGY CHANGE
	IFIW NDCIC		;(12) CLEAR INT CHANNEL FOR TOPOLOGY CHANGE
	IFIW NDGVR		;(13) GET NSP VERSION INFORMATION
	IFIW NDGLI		;(14) GET LINE INFORMATION *
	IFIW NDVFY		;(15) VERIFY NODE NAME
	IFIW NDRNM		;(16) RETURN A NODE NAME
	IFIW NDCIN		;(17) GET PER-CHANNEL INFORMATION
	IFIW NDRDB		;(20) GET A TABLE
	IFIW NDSDP		;(21) Set DECnet initial parameters
	IFIW NDINT		;(22) Insert node table
NDTLEN==.-NODTAB

; GET LINE INFORMATION INFORMATION

NDGLI:			 	;ERROR: Function no longer supported
				; use NTMAN% JSYS to obtain this information

NDNLS:	RETBAD (NODX05)		;ERROR: FUNCTION NO LONGER SUPPORTED
				;	USE NTMAN% JSYS INSTEAD
;NDSLN - ROUTINE TO SET THE LOCAL NODE NAME

NDSLN:	MOVE T1,CAPENB		;GET CURRENTLY ENABLED CAPABILITIES
	TXNN T1,SC%WHL!SC%OPR	;WHEEL OR OPERATOR CAPABILITY REQUIRED
	RETBAD (CAPX1)		;NOT ENOUGH CAPABILITY, RETURN ERROR

	SKIPE D36IFG		;DECnet initialized/ing?
	RETBAD (NODX16)		; -yes, return error

;We store the name in OURNAM as well as in the DECnet-36 initialization block
; so the old routines in the rest of the monitor will know the local node name.

	UMOVE T2,2		;GET ADDRESS OF USER'S ARGUMENT BLOCK
	UMOVE T1,.NDNOD(T2)	;GET POINTER TO STRING IN USER SPACE
	MOVEI T2,OURNAM		;WE'LL WRITE PARSED NAME TO OURNAM
	CALL PARNDU		;MAKE SURE NODE NAME IS KOSHER
	  RETBAD()		;FAILED, TELL CALLER WHY
	MOVEM T2,OURCNT		;REMEMBER LENGTH OF OURNAM

	MOVE T1,[POINT 7,OURNAM] ;Make sixbit
	CALL PUTSIX		;(T1,T2/T1) node name
	STOR T1,IBNAM,+IBBLK	;  and store in IB block

	RETSKP			;SUCCESS
;SET LOCAL NODE NUMBER
NDSNM:	MOVE T1,CAPENB		;CHECK PRIVS
	TXNN T1,SC%WHL!SC%OPR
	RETBAD (LOUTX3)		;NO.
	SKIPE D36IFG		;DECnet initialized/ing?
	RETBAD (NODX16)		; -yes
	UMOVE T1,T2		;GET THE
	UMOVE T1,.NDNOD(T1)	; NUMBER
	CAIG T1,0		;Zero node # is not allowed
	RETBAD (GJFX10)		;FAILED. RANDOM ERROR
	LDB T2,[POINTR(T1,RN%ARE)] ;Get area # off node number
	SKIPN T2		;Skip if there is one
	MOVE T2,RTRHOM		; otherwise default to RTRHOM/%RTHOM
	DPB T2,[POINTR(T1,RN%ARE)] ;Put back area #
	MOVEM T2,RTRHOM		; and in RTRHOM as well
	STOR T1,IBADR,+IBBLK	;Store node # in IB block
	LDB T2,[POINTR(T1,RN%NOD)] ;Now get local node index
	MOVEM T2,RTRADR		; and save for ROUTER
	RETSKP
;NDGLN - GET LOCAL NODE NAME

NDGLN:	STKVAR <<NODNAM,WPN>>	;ROOM FOR NODE NAME IN 8-BIT BYTES
	LOAD T1,IBNAM,+IBBLK	;Get local node name
	XMOVEI T2,NODNAM	;POINT TO
	HRLI T2,(POINT 8,0)	; LOCAL STORAGE
	CALL GETSIX		;(T1,T2/T1) GET BYTE COUNT & CONVERT TO 8 BIT
	XMOVEI T2,NODNAM        ;GET POINTER TO NODE NAME AGAIN.

	UMOVE T3,2		;GET USER'S POINTER TO ARG BLOCK
	UMOVE T3,.NDNOD(T3)	; FROM WHICH GET HIS BYTE POINTER
	CALL STONOD		;(T1,T2,T3) STORE NAME TO USER
	UMOVE T1,2		;GET USER'S POINTER TO ARG BLOCK
	UMOVEM T3,.NDNOD(T1)	;SAVE ADJUSTED DESTINATION POINTER
	RETSKP			;RETURN SUCCESS

	ENDSV.			;END STKVAR.

;GET LOCAL NODE NUMBER

NDGNM:	UMOVE T2,2		;GET POINTER TO USER ARG BLOCK
	LOAD T3,IBADR,+IBBLK	;Get local node #
	UMOVEM T3,0(T2)		;STORE NUMBER
	RETSKP			; AND DONE ALREADY
; SET INTERRUPT CHANNEL FOR NETWORK TOPOLOGY CHANGE

NDSIC:	UMOVE T3,T2		;GET USER BLOCK ADDRESS
	XCTU [ MOVEI T1,.NDCHN(T3)]	;POINT TO CHANNEL NUMBER WORD
	UMOVE T1,(T1)		;GET THE CHANNEL NUMBER
	SKIPL T1		;VALIDATE CHANNEL NUMBER
	CAILE T1,^D35		;CHANNEL NUMBER TOO HIGH
	RETBAD (ARGX13)		;NEGATIVE CHANNEL NUMBERS ARE ILLEGAL
	CAIL T1,.ICAOV		;SKIP IF GOOD NUMBER
	CAILE T1,.ICNXP		;SKIP IF BAD NUMBER
	JRST CHANOK		;CHANNEL NUMBER OK.
	RETBAD (ARGX13)		;BAD CHANNEL NUMBER

;** This code should have some interlocks.  Two forks could decide
;** to use the same entry in the notification table.  The consequence
;** will be that one fork will fail to get any topology interrupts.
;** This should be fixed in future. /Gunnar Lindell

CHANOK:	SETZ T4,		;T4 WILL HOLD ADDRESS OF FREE ENTRY
	MOVEI T2,NTCTAB		;POINT TO TOP OF TABLE OF WAITING FORKS

;HERE TO DETERMINE IF FORK ALREADY HAS SET THE INTERRUPT ONCE

CHNOK1:	SKIPN (T2)		;SKIP IF ENTRY IS BEING USED
	 JRST [	MOVE T4,T2	;SAVE FOR FORK NOT CURRENTLY ACTIVATED
		JRST CHNOK2]	;TRY NEXT ENTRY
	LOAD T3,NTCFRK,(T2)	;GET THE FORK NUMBER
	CAME T3,FORKX		;DOES THIS ENTRY BELONG TO THIS FORK
	JRST CHNOK2		;NO, LOOK AT NEXT ENTRY
	STOR T1,NTCCHN,(T2)	;YES. PUT NEW CHANNEL NUMBER IN
	RETSKP			; AND RETURN SUCCESS NOW

CHNOK2:	CAIE T2,NTCTAB+<NTCMAX-1> ;HAVE WE LOOKED AT WHOLE TABLE
	AOJA T2,CHNOK1		;NO - KEEP LOOKING
	SKIPN T4		;DID WE FIND AN ENTRY?
	RETBAD (NSPX26)		;ERROR - TABLE OF TOPOLOGY WATCHERS IS FULL
	STOR T1,NTCCHN,(T4)	;SAVE THE CHANNEL NUMBER
	MOVE T1,FORKX		;NOW GET THE FORK NUMBER
	STOR T1,NTCFRK,(T4)	;AND SAVE
	SETONE FKNTC,(T1)	;FLAG IN FORK DATA BASE
	RETSKP

;NDCIC - CLEAR INTERRUPT CHANNEL FOR NETWORK TOPOLOGY CHANGE

NDCIC:
NTCOFF::MOVEI T1,NTCTAB		;FIND THE FORK'S ENTRY
NDCIC1:	LOAD T2,NTCFRK,(T1)	;GET THE FORK NUMBER FOR THIS ENTRY
	CAMN T2,FORKX		;THIS FORKS ENTRY
	JRST [	SETZM (T1)	;CLEAR ENTRY
		MOVE T1,FORKX	;GET FORK INDEX
		SETZRO FKNTC,(T1)	;CLEAR THE ITEM IN FORK DATA BASE
		RETSKP]
	CAIE T1,NTCTAB+<NTCMAX-1>	;AT END OF TABLE
	AOJA T1,NDCIC1		;NO - KEEP LOOKING
	RETSKP			;INDICATE SUCCESS EVEN WHEN NEVER SET
;NDGVR - GET NSP VERSION INFORMATION

NDGVR:	UMOVE T3,T2		;GET THE USER BLOCK POINTER
	MOVX T2,2		;GET NUMBER OF VERSIONS TO RETURN
	UMOVEM T2,.NDNVR(T3)	;STORE IN USER ARGUMENT BLOCK
	UMOVE T1,.NDCVR(T3)	;GET THE ADDRESS OF THE COMMUNICATION BLOCK
	MOVE T2,NSPVER		;ECL (FORMERLY NSP) VERSION NUMBER
	UMOVEM T2,.NDVER(T1)	;SAVE IN USER SPACE
	MOVE T2,NSPECO		;ECL ECO LEVEL
	UMOVEM T2,.NDECO(T1)	;SAVE IN USER SPACE
	MOVE T2,NSPUEC		;GET THE CUSTOMER CHANGE NUMBER
	UMOVEM T2,.NDCST(T1)	;SAVE IN USER SPACE

;NOW GIVE USER THE ROUTING VERSION INFORMATION

	UMOVE T1,.NDRVR(T3)	;GET THE ADDRESS OF THE ROUTING BLOCK
	MOVE T2,RTRVER		;ROUTING VERSION NUMBER
	UMOVEM T2,.NDVER(T1)	;SAVE IN USER SPACE
	MOVE T2,RTRECO		;ROUTING ECO
	UMOVEM T2,.NDECO(T1)	;SAVE IN USER SPACE
	MOVE T2,RTRCUS		;GET THE CUSTOMER CHANGE NUMBER
	UMOVEM T2,.NDCST(T1)	;SAVE IN USER SPACE
	RETSKP			;RETURN
; GET NETWORK TOPOLOGY INFORMATION

NDGNT:	TRVAR <GNTCNT,GNTLAS,GNTTMP,<NODNAM,WPN>>

; SET UP TO LOOP OVER EACH NODE

	UMOVE T4,2		;GET ADDRESS OF USER'S ARGUMENT BLOCK
	UMOVE T1,.NDNND(T4)	;GET NUMBER OF WORDS IN BLOCK
	ADD T1,T4		;COMPUTE LAST ADDRESS
	SOS T1			; TO USE
	MOVEM T1,GNTLAS		;SAVE LAST ADDRESS IN USER SPACE TO STORE INTO

	MOVE Q2,SCTNDC		;GET THE COUNT OF NODES DEFINED BY SCTL
	UMOVE T1,2		;GET THE USER'S ARGUMENT BLOCK POINTER
	MOVE Q1,T1           	;FIND THE START
	ADDI Q1,.NDBK1		; OF THE POINTERS
	ADD Q2,Q1		;CALCULATE START OF THE LITTLE BLOCKS
	HRRZ T2,Q2		;GET RID OF SECTION NUMBER
	CAMLE T2,GNTLAS		;ARE THE POINTERS GOING TO FIT?
	 RETBAD (ARGX04) 	;ERROR: NOT ENOUGH ROOM FOR FUNCTION
	MOVX T2,.NDNBS		;GET THE SIZE OF A NODE BLOCK
	UMOVEM T2,.NDCNT(T1)	;RETURN THIS COUNT TO THE USER
	MOVEI Q3,1		;INITIALIZE NODE NUMBER
	SETZM GNTCNT		;INITIALIZE THE COUNT OF NODES RETURNED

;Here we have:
;	Q1/ Pointer to pointer area in JSYS arg block
;	Q2/ Pointer to the current "little" node block
;	Q3/ Current node number

NDGNT3:	MOVE T1,Q3		;THE NODE NUMBER
	MOVE T2,RTRHOM		;Default to RTRHOM/%RTHOM
	DPB T2,[POINTR(T1,RN%ARE)] ;Put back area #
	CALL NDRCHK		;Call to check Node Reachablity
	 JRST NDGNT4		;Unreachable
	MOVE T1,Q3		;Reachable, GET OUR NODE NUMBER
	CALL SCTA2N		;(T1/T1)GET SESSION CONTROL'S NAME FOR NODE
	 JRST NDGNT4		;NONE THERE, CHECK NEXT ONE
	XMOVEI T2,NODNAM	;POINT TO
	HRLI T2,(POINT 8,0)	; LOCAL STORAGE
	CALL GETSIX		;(T1,T2/T1) GET BYTE COUNT AND CONVERT TO 8 BIT

	XMOVEI T2,NODNAM        ;GET ADDRESS OF NODE NAME
	MOVX T4,.NDNBS		;LENGTH OF A "LITTLE" BLOCK
	ADDI T4,1		;PLUS
	CAIL T1,5		; EXTRA ROOM (5 CHARS PER WORD)
	ADDI T4,1		; FOR NODE NAME TEXT (MAXIMUM 6 CHARS)
	MOVEM T4,GNTTMP		;STORE IT FOR A WHILE
	HRRI T3,.NDNBS(Q2)	;MAKE UP A BYTE POINTER
	HRLI T3,(POINT 7,)	; TO PUT IN LITTLE NODE BLOCK
	UMOVEM T3,.NDNAM(Q2)	;GIVE THE USER THE BYTE POINTER ALSO
	CALL STONOD		;(T1,T2,T3)STORE THE NAME IN THE "LITTLE" BLOCK

	MOVX T1,.NDSON		;THE STATE IS "ON"
	UMOVEM T1,.NDSTA(Q2)	;STORE THE STATE IN "LITTLE" BLOCK

	UMOVEM Q2,(Q1)		;STORE THE POINTER TO THE LITTLE BLOCK
	ADD Q2,GNTTMP		;POSITION Q2 A HEAD OF NEXT LITTLE BLOCK
	HRRZ T1,Q2		;GET RID OF THE SECTION NUMBER
	AOS GNTCNT		;KEEP TRACK OF HOW MANY WE HAVE DONE
	CAMLE T1,GNTLAS		;IS THE NEXT ONE GOING TO FIT?
	JRST NDGNT5		;NO. ERROR EXIT.
	ADDI Q1,1		;POINT TO THE NEXT POINTER PLACE
NDGNT4:	ADDI Q3,1		;TRY NEXT NODE NUMBER

	MOVE T1,GNTCNT		;GET THE COUNT OF HOW MANY WE'VE DONE
	CAMG T1,SCTNDC		;IS IS HOW MANY WE SAID?
	CAMLE Q3,RTRMXN		; OR IS IT BIGGER THAN NN?
	TRNA			;YES, FINISH UP
	JRST NDGNT3		;NO, DO THE NEXT ONE

	UMOVE T1,2		;GET THE BLOCK POINTER BACK
	MOVE T2,GNTCNT		;GET THE COUNT WE RETURNED
	XCTU [HRLM T2,.NDNND(T1)] ;RETURN THE COUNT TO USER
	RETSKP			; AND RETURN TO SENDER

;HERE ON ERROR - RETURN COUNT AND EXIT.
NDGNT5:	UMOVE T1,2		;GET THE BLOCK POINTER BACK
	MOVE T2,GNTCNT		;GET THE COUNT WE RETURNED
	XCTU [HRLM T2,.NDNND(T1)] ;RETURN THE COUNT TO USER
       	RETBAD (ARGX04)

	ENDTV.			;END TRVAR
;Get the value of the Node State Parameter (Reachable/Unreachable) 
;from ROUTER
;
;	Call:
;	T1/	Node Number
;
;	Return:
;		+1	UNREACHABLE
;		+2	REACHABLE

NDRCHK:	TRVAR<<NFWBLK,NF.LST>>
	STOR T1,NFEID,+NFWBLK	;Put the Node Number into the Arg block
	MOVEI T1,^D2503		;This state parameter is system specific for
	STOR T1,NFPRM,+NFWBLK	; TOPS20 - needed so that I DECNET can work
				; if we are running as an endnode.
	MOVEI T1,.NTNOD		;Get the Node Entity Type value
	STOR T1,NFETY,+NFWBLK	;Put the entity type into arg block
	SETZRO NFBLN,+NFWBLK	;Make sure the rest of the block is cleared
	SETZRO NFBFF,+NFWBLK
	SETZRO NFBUF,+NFWBLK
	SETZRO NFQUA,+NFWBLK
	SETZRO NFUBF,+NFWBLK
	MOVEI T1,NF.RED		;Put the Read Parameter function code into T1
	XMOVEI T2,NFWBLK	;Address of the Arg Block into T2
	XCALL (XCDSEC,RTRNMX)	;Ask router for the information
	 RET			;Error, Say it is unreachable
	LOAD T1,NFBUF,+NFWBLK	;Get the parameter value back
	CAIE T1,RM.REA		;Skip if node is reachable
	 CAIN T1,DS.ON		; of if the executor, if it is on
	  RETSKP		;Skip return is reachable
	RET			;Non-skip return indicates Node is Unreachable

	ENDTV.
;STONOD - ROUTINE TO STORE NODE NAME STRING IN USER SPACE
;
;ACCEPTS IN T1/	COUNT OF BYTES IN STRING
;	    T2/ FULL WORD POINTER TO NODE NAME (8-BIT BYTES)
;	    T3/ DESTINATION BYTE POINTER
;		CALL STONOD
;RETURNS: +1 ALWAYS, WITH
;	    T3/ UPDATED DESTINATION BYTE POINTER

STONOD:	SAVEAC <P1,P2,P3>
	DMOVE P1,T1		;SAVE COUNT AND POINTER
	TLC T3,-1		;IS LH OF DESTINATION PTR -1?
	TLCN T3,-1
	HRLI T3,(POINT 7,)	;YES, RESOLVE IT
	MOVE P3,[POINT 8,(P2)]	;MAKE INDEXED BYTE POINTER TO NODE NAME

STONO1:	ILDB T1,P3		;GET A BYTE
	JUMPE T1,STONO2		;IF NULL, ALL DONE
	XCTBU [IDPB T1,T3]	;STORE BYTE
	SOJG P1,STONO1		;YES - ANY MORE?
	SETZ T1,		;NO, MAKE A NULL

STONO2:	MOVE T2,T3		;END THE STRING WITH A NULL
	XCTBU [IDPB T1,T2]
	RET			;DONE
; NDVFY - VERIFY NODE NAME IS IN MONITOR'S DATABASE OF REACHABLE NODES
;  USES T1-T4

NDVFY:	SAVEAC Q1
;**;[7497] Change 1 line at NDVFY:+1L	MDR	7-JUL-87
	STKVAR <<NDVNOD,WPN>,VFYSTR,VFYARG,VFYPTR> ;[7497]

; GET NODE NAME FROM USER SPACE

	UMOVE Q1,T2		;GET ADDRESS OF USER ARGUMENT BLOCK
	MOVEM Q1,VFYARG		;SAVE IT FOR LATER
	UMOVE T1,.NDNAM(Q1)	;GET POINTER TO NODE NAME IN USER SPACE
;**;[7497] Add 12 lines at NDVFY:+8L	MDR	7-JUL-87
	MOVEM T1,VFYPTR		;[7497] Save it for later use
	TLC T1,-1		;[7497] Did user give us -1,,addr?
	TLCN T1,-1		;[7497]
	HRLI T1,(POINT 7,)	;[7497] If so, make it a 7 bit byte pointer
	SETZ T4,		;[7497] Init a counter register
CHRCNT:	XCTBU [ILDB T2,T1]	;[7497] Get a character from the user
	 ERJMP [RETBAD (ARGX04)] ;[7497] Must have given us a bogus arg block
	SKIPE T2		;[7497] All done?
	AOJA T4,CHRCNT		;[7497] No,
;**;[7499] Change 1 line at CHRCNT:+4L	MDR	8-JUL-87
	CAILE T4,CPN		;[7497][7499] Too many characters from user?
	RETBAD (COMX19)		;[7497] Yes, return error to caller
	MOVE T1,VFYPTR		;[7497] Get byte pointer back for PARNDU
	XMOVEI T2,NDVNOD	;GET ADDRESS OF DESTINATION FOR NAME
	CALL PARNDU		;GET THE NODE NAME FROM USER SPACE
	 RETBAD ()		;FAILED

; VERIFY THAT THE NODE IS IN NAME MAPPING TABLE

	MOVX T1,<POINT 7,>	;FORM POINTER TO NODE NAME
	HRRI T1,NDVNOD		;GET LOCAL ADDRESS OF NODE NAME
	CALL NDVFY1		;DO THE WORK, (LENGTH IS IN T2 FROM PARNDU)

;RETURN INFO TO THE USER

       	MOVE T2,VFYARG		;RETRIEVE ADDR OF USER'S ARG BLOCK
	UMOVEM T1,.NDFLG(T2)	;STORE NEWS FOR THE USER
	RETSKP			;SUCCESS RETURN

	ENDSV.			;END STKVAR AT NDVFY
;VERIFY THAT THE PARSED NODE NAME IS IN NAME MAPPING TABLE AND IS REACHABLE.
;
; T1 - BYTE POINTER TO PARSED NODE NAME IN MONITOR SPACE
; T2 - LENGTH OF THAT NODE NAME
; RETURNS +1 ALWAYS AND OKINT	; FLAGS IN T1 (ND%EXM,ND%LGL,ND%RCH,ND%RUK)
; USES T1-T4
; CALL NDVFY1

NDVFY1::SAVEAC Q1
	CAIG T2,^D6		;CHECK THE BYTE COUNT
	IFSKP.			;TOO LONG,
	  SETZ T1,		; DON'T RETURN ANY FLAGS
	  RET			; AND RETURN
	ENDIF.
	CALL PUTSIX		;(T1,T2/T1) CONVERT TO SIXBIT
	CALL SCTN2A		;(T1/T1)SEE IF SCLINK KNOWS IT
	IFNSK.			;DIDN'T KNOW ABOUT THE NAME,
	  MOVX T1,ND%LGL	; HOWEVER, IT WAS A LEGAL NAME
	  RET			; SO RETURN THAT FLAG
	ENDIF.
	LDB T2,[POINTR (T1,RN%ARE)] ; Get the area number
	CAMN T2,RTRHOM		; Same as ours?
	IFSKP.
	  MOVX T1,ND%LGL!ND%EXM!ND%RUK ; No, then node is legal, in SCLINK's
	  RET			;  database but reachability is unknown
	ENDIF.
	CALL NDRCHK		;Ask ROUTER if this node is reachable
	IFSKP.
	  MOVX T1,ND%LGL!ND%RCH!ND%EXM ; Reachable,legal, and known to SCLINK
	ELSE.
	  MOVX T1,ND%LGL!ND%EXM	; Node is legal and in SCLINK's database
	  LOAD T2,IBRTR,+IBBLK	; Get routing type
	  CAIN T2,RNT.NR	; Endnode?
	  TXO T1,ND%RUK		;  -then set "reachibility unknown"
	ENDIF.
	RET			; AND RETURN WITH FLAGS IN T1

	ENDSV.
; NDRNM - GIVEN A NODE NUMBER, RETURN THE NODE NAME

NDRNM:	STKVAR <<NODNAM,WPN>,ARGADR>
	MOVEM T2,ARGADR		;SAVE THE ADDRESS OF THE USER'S ARG BLOCK
	UMOVE T1,.NDNOD(T2)	;GET NODE NUMBER
	CALL SCTA2N		;(T1/T1) FIND NAME FOR THIS NODE NUMBER
	 RETBAD (NSPX25)	;NO NAME FOUND
	XMOVEI T2,NODNAM	;POINT TO
	HRLI T2,(POINT 8,0)	; LOCAL STORAGE
	CALL GETSIX		;(T1,T2/T1) FIND COUNT & CONVERT TO 8-BIT
	XMOVEI T2,NODNAM	;GET NODE NAME ADDRESS
	MOVE T3,ARGADR		;GET THE ADDRESS OF THE USER'S ARG BLOCK
	UMOVE T3,.NDCVR(T3)	;GET THE USER'S BP
	CALL STONOD		;(T1,T2,T3) AND STORE THE NAME TO HIM
	UMOVEM T3,3		;Return updated byte pointer to user
	RETSKP			;RETURN SUCCESS

	ENDSV.
	SUBTTL TOPOLOGY CHANGE INTERRUPT
;HERE TO NOTIFY INTERESTED USERS THAT LOCAL AREA TOPOLOGY HAS CHANGED
;CALL NTCIN
;RETURNS +1 ALWAYS

	RESCD			;MUST BE SO. CALLED AT SCHEDULER LEVEL.

NTCIN::	SAVEAC <Q1>
	MOVEI Q1,NTCTAB		;START LOOKING AT TOP OF TABLE
NTCIN1:	SKIPN (Q1)		;IS THERE AN ENTRY?
    	JRST NTCIN2		;NO. KEEP LOOKING.
	LOAD T2,NTCFRK,(Q1)	;GET FORK NUMBER
	LOAD T1,NTCCHN,(Q1)	;GET THE CHANNEL NUMBER
	CALL PSIRQ		;INTERRUPT USER
NTCIN2:	CAIE Q1,NTCTAB+<NTCMAX-1> ;DID WE SEARCH WHOLE TABLE?
	AOJA Q1,NTCIN1		;NO - CHECK NEXT ENTRY
	RET

	SWAPCD
SUBTTL NDCIN FUNCTION OF THE NODE JSYS

;HERE FOR FUNCTION NDCIN - READ PER-CONNECTION DATA (FOR SYSDPY)

;CALL WITH USER'S T2/ ADDRESS OF BLOCK:
;		+0/ (IGNORED),,NUMBER WORDS REQUESTED
;		+1/ JOB NUMBER
;		+2/ CHANNEL NUMBER FROM PREVIOUS CALL (0 FOR FIRST)
;		+3.../ SPACE FOR REST OF DATA GIVEN IN NB BEGSTR
;RETURNS +2 ON SUCCESS, +1 ON ERROR, WITH
;		+0/ NUMBER WORDS RETURNED,,NUMBER WORDS REQUESTED
;		+1/ JOB NUMBER (POSSIBLY DIFFERENT FROM CALL; -1 IF NO MORE)
;		+2/ CHANNEL NUMBER OF RETURNED DATA
;		+3.../ REST OF NB DATA BLOCK, FILLED IN

;TO USE THIS FUNCTION, CALL THE FIRST TIME WITH JOB/ 0, CHANNEL/ 0
;THEN KEEP CALLING UNTIL NO-MORE-JOBS ERROR (NODX11)
;THE JSYS RETURNS WITH DATA FOR THE NEXT ACTIVE CHANNEL FOR THE GIVEN JOB.
;IT WILL BUMP THE CHANNEL NUMBER FOR EACH CALL. WHEN ALL CHANNELS
;ARE DONE FOR THE GIVEN JOB, IT WILL BUMP THE JOB NUMBER AND FIND ITS
;FIRST ACTIVE CHANNEL.

;WHEN ALL JOBS HAVE BEEN LOOKED AT, IT RETURNS INFORMATION FOR "SPECIAL"
;NON-JOB SJB'S (LIKE NRT AND CTERM). THE JOB SLOT IN THE USER'S NODE
;BLOCK IS SET TO THE ASCII NAME OF THE PROGRAM WHO OWNS THE CHANNELS.

;WHEN ALL JOBS AND SPECIALS HAVE BEEN LOOKED AT, IT SETS JOB/ -1 TO
;INDICATE THAT IT IS DONE AND RETURNS A NODX11 ERROR (CALLING THE JSYS
;WITH JOB/ -1 IS AN ERROR).

;NUMBER OF WORDS REQUESTED MUST BE AT LEAST NB.LEN.
;NUMBER OF WORDS RETURNED WILL ALWAYS BE NB.LEN.

;LOCAL PERMANENT AC USE:
;  P1/ ADDRESS OF USER'S ARGUMENT BLOCK, IN USER'S CONTEXT
;  P2/ JOB NUMBER [0-MXGLBS] (global job #)
;  P3/ CHANNEL NUMBER WITHIN JOB [1-MAXPRT]
;  P4/ ADDRESS OF SJB

NDCIN:
	MOVE T1,CAPENB		;GET CURRENTLY ENABLED CAPABILITIES
	TXNN T1,SC%WHL!SC%OPR	;DOES THE CALLER HAVE WHEEL OR OPERATOR?
	RETBAD (CAPX1)		;NO - ERROR: INSUFFICIENT CAPABILITIES

	SAVEAC <P1,P2,P3,P4>	;SAVE THE PERMANENT ACS
	UMOVE P1,2		;GET ADDRESS OF USER'S ARGUMENT BLOCK
	ULOAD T1,NBRQW,(P1)	;GET THE NUMBER OF WORDS REQUESTED
	CAIGE T1,NB.LEN		;ENOUGH TO MAKE IT INTERESTING?
	RETBAD (NODX07)		;NO - ERROR: ARGUMENT BLOCK NOT LONG ENOUGH
	USTOR T1,NBRTW,(P1)	;YES - RETURN IT AS WORDS WRITTEN (HA!)

;READ JOB AND CHANNEL NUMBERS
;IF THE CHANNEL IS TOO HIGH, BUMP THE JOB NUMBER & SET TO FIRST CHANNEL
;READ THE JSB; LOOK FOR THE NEXT HIGHER ACTIVE CHANNEL

;NOTE: THE CHANNEL NUMBER IS EFFECTIVELY BUMPED HERE, SINCE THE USER THINKS
;THEY ARE IN THE RANGE 1:N AND THE MONITOR THINKS 0:N-1.

	ULOAD P2,NBJOB,(P1)	;GET THE CALLER'S JOB NUMBER
	ULOAD P3,NBCHN,(P1)	;GET THE CALLER'S PREVIOUS CHANNEL NUMBER
	CAIGE P3,0		;IS THE CHANNEL NUMBER REAL?
	RETBAD (NODX10)		;NO - ERROR
	CAIGE P3,MAXPRT		;YES - WAS THAT THE LAST CHANNEL FOR THIS JOB?
	IFSKP.			; -yes,
	  SETZ P3,		;  SET TO THE FIRST CHANNEL
	  AOJ P2,		;    OF THE NEXT JOB
	ENDIF.

;Since we allow NRT and CTM to be 'special jobs', P2 will be negative
; (because ASCII) if we have any of the 'special' 'jobs'
	JUMPL P2,SPCJOB		;Go handle 'special jobs'

;Now we have what we believe is a good global job number in P2
; It will be range-checked when we convert from global to local.
NDCIN1:	MOVE T1,P2		;Get global job #
	CALL GL2LCL		; and convert to local
	 JRST NDCINJ		;  -no such job, move to next

;Map the JSB, page in the required page, go NOSKED to protect data structures
	CALL MAPJSB		;Map the JSB
	 JRST NDCINJ		; -not there, move to next one
	SKIP JSBSJB(T1)		;Skip in the page so we dont cause NOSKED page
				; faults below.
	NOSKED
	MOVE P4,JSBSJB(T1)	;Get SJB pointer
	CALL CLRJSB		;Clear JSB mapping now
	SKIPE P4		;Test SJB pointer
	IFSKP.			; -there wasnt one,
	  OKSKED		;  allow others in
	  JRST NDCINJ		;   and move to next job
	ENDIF.
	LOAD T2,SJCHC,(P4)	;Get the length of the channel table
	CALL REDSJB		;Read data from SJB
	IFNSK.			; - fail return
	  OKSKED		;   allow others in
	  JRST NDCINJ		;    and move to next job
	ENDIF.
	OKSKED			;Success, allow the rest of the world again
	RETSKP			; and return success

;SPCJOB - come here to handle 'special jobs'
SPCJOB:	CAME P2,[ASCII /NRT/]	;NRT?
	IFSKP.			; -yes,
	  MOVE P4,NRTSJP	;  Get NRT's SJB pointer
	ELSE.
	  CAME P2,[ASCII /CTM/]	; -not NRT, is is CTERM?
	  RETBAD (NODX11)	;  -neither, return error
	  SKIPG P4,CTHSAP	;   CTERM: get SAB pointer
	  JRST NDCIJX		;    -there isnt one, go return error
	  LOAD P4,SASJB,(P4)	;     Get CTERM SJB.
	ENDIF.
	NOSKED			;Protect us
	LOAD T2,SJCHC,(P4)	;Get the length of the channel table
	CALL REDSJB		;Read data from SJB
	IFNSK.			; - fail return
	  OKSKED		;   allow others in
	  JRST NDCINJ		;    and move to next job
	ENDIF.
	OKSKED			;Success, allow the rest of the world again
	RETSKP			; and return success

;NDCINJ - move to 'next job'
NDCINJ:	SETZ P3,		;Channel 0 of next job
	JUMPL P2,NDCIJ1		;Go handle 'special jobs'
	CAIG P2,MXGLBS		;Was that the last job?
	AOJA P2,NDCIN1		; -no, go do next one
;Out of ordinary jobs - set up for NRT
	MOVE P2,[ASCII /NRT/]	;Load identifier
	JRST SPCJOB		; and go handle 'special job'

;NDCIJ1 - come here when we should move to the next 'special job'
NDCIJ1:	CAMN P2,[ASCII /CTM/]	;Did we look at CTERM (last special job)?
	JRST NDCIJX		; -yes, everything is done
	MOVE P2,[ASCII /CTM/]	;No, then its CTERM we should do now
	JRST SPCJOB		; and go do 'special job'

;NDCIJX - return error
NDCIJX:	SETO T1,		;Store -1 as flag to user
	USTOR T1,NBJOB,(P1)
	RETBAD (NODX11)		;Return 'bad job number'

;REDSJB - read the SJB
REDSJB:	CAML P3,T2		;IS THE CHANNEL WITHIN RANGE?
	RET			; -no, return to get next job
	LOAD T3,SJCHT,(P4)	;GET THE ADDRESS OF CHANNEL TABLE FROM SJB
	ADD T3,P3		;FIND THE ENTRY FOR THIS CHANNEL
	SKIPN T4,(T3)		;GET IT (ADDRESS OF SLB) - IS THERE ONE?
	AOJA P3,REDSJB		;NO - TRY THE NEXT CHANNEL

;GOT SJB AND SLB ADDRESSES (IN P4 AND T4):
;COPY DATA FROM THIS CHANNEL'S ENTRY IN PORT TABLE.

NDCIN3:	LOAD T3,SJPRT,(P4)	;ELSE GET THE ADDRESS OF THE SJB'S PORT TABLE
	JUMPN T3,NDCIN4		;IS THERE A PORT TABLE?
	USTOR T3,NBTYP,(P1)	;NO, STORE ZEROS IN ALL
	USTOR T3,NBFRK,(P1)	; PORT TABLE
	USTOR T3,NBJFN,(P1)	; FIELDS
	JRST NDCIN5		;DONE

NDCIN4:	ADDI T3,1(P3)		;Offset by channel number
	MOVE T3,(T3)		;Get the port block
	LOAD T2,PTTYP,(T3)	;GET THE OPEN TYPE
	USTOR T2,NBTYP,(P1)	;SAVE IT FOR THE USER
	LOAD T1,PTFRK,(T3)	;GET THE FORK THAT OWNS THIS CHANNEL
	USTOR T2,NBFRK,(P1)	;SAVE IT
	LOAD T2,PTJFN,(T3)	;GET THE JFN ASSOCIATED WITH THE CHANNEL
	USTOR T2,NBJFN,(P1)	;SAVE IT
NDCIN5:

;COPY DATA FROM THE SLB (ADDRESS IN T4).

	LOAD T2,PTTYP,(T3)	;Get the open type
	SKIPE T2		;DCN: or SRV:?
	IFSKP.			;SRV:
	  LOAD T2,SLSOB,(T4)	;  Get the source object type
	ELSE.			;DCN:
	  LOAD T2,SLDOB,(T4)	;  Get destination object type
	ENDIF.
	USTOR T2,NBOBJ,(P1)	;SAVE IT FOR THE USER
	LOAD T2,SLSTA,(T4)	;GET THE LINK STATE
	USTOR T2,NBSTA,(P1)	;SAVE IT
	LOAD T2,SLXFL,(T4)	;GET THE TRANSMIT FLOW OPTION
	USTOR T2,NBXFL,(P1)	;SAVE IT
	LOAD T2,SLRFL,(T4)	;GET THE RECEIVE FLOW OPTION
	USTOR T2,NBRFL,(P1)	;SAVE IT
	LOAD T2,SLGOL,(T4)	;GET THE RECEIVE DATA REQUEST GOAL
	USTOR T2,NBGOL,(P1)	;SAVE IT
	LOAD T2,SLINQ,(T4)	;GET THE LINK INPUT QUOTA
	USTOR T2,NBINQ,(P1)	;SAVE IT
	LOAD T2,SLOTQ,(T4)	;GET THE LINK OUTPUT QUOTA
	USTOR T2,NBOTQ,(P1)	;SAVE IT
	LOAD T2,SLDNA,(T4)	;GET THE DESTINATION NODE NUMBER
	USTOR T2,NBDNA,(P1)	;SAVE IT
	LOAD T2,SLSIZ,(T4)	;GET THE SEGMENT SIZE IN BYTES
	USTOR T2,NBSSZ,(P1)	;SAVE IT
	LOAD T2,SLRSN,(T4)	;GET THE REASON FOR DISCONNECT OR REJECT
	USTOR T2,NBRSN,(P1)	;SAVE IT

;NOW GET THE ADDRESS OF THE ELB (INTO T3) AND COPY THINGS FROM THERE

	LOAD T3,SLPID,(T4)	;GET THE ELB ADDRESS FROM THE SLB

	LOAD T2,ELLLA,(T3)	;GET THE LOCAL LINK ADDRESS
	USTOR T2,NBLLA,(P1)	;SAVE IT

	LOAD T2,ELRLA,(T3)	;GET THE REMOTE LINK ADDRESS
	USTOR T2,NBRLA,(P1)	;SAVE IT

;Note: the PKS and PKR counts are updated in SCLINK: hence they do not
; include NSP overhead for the links

	LOAD T2,SLPKS,(T4)	;Get packets sent
	USTOR T2,NBPKS,(P1)	;SAVE IT

	LOAD T2,SLPKR,(T4)	;Get packets received
	USTOR T2,NBPKR,(P1)	;SAVE IT

	LOAD T2,ELVER,(T3)	;GET THE REMOTE NSP VERSION
	USTOR T2,NBVER,(P1)	;SAVE IT

;AT END P4/ SJB ADDR, T4/ SLB ADDR, T3/ ELB ADDR, P1/ USER'S BLOCK

	AOJ P3,			;BUMP CHANNEL NUMBER TO MAKE IT RELATIVE TO USER
	USTOR P2,NBJOB,(P1)	;RETURN JOB NUMBER TO CALLER
	USTOR P3,NBCHN,(P1)	;DITTO CHANNEL NUMBER
	JUMPGE P2,RSKP		;RETURN SUCCESS IF NOT SPECIAL
	CAMN P2,[ASCII /NRT/]	;NRT?
	JRST NDCINN		;YES - HANDLE IT
	CAME P2,[ASCII /CTM/]	;ELSE RETURN THE TTY NUMBER - CTERM?
	RETSKP			;NO - RETURN SUCCESS ANYWAY

	MOVE T1,CTHCHP		;GET THE ADDRESS OF THE CTERM DATA BLOCK
	ADD T1,P3		; FROM THE CTERM CHANNEL TABLE
	MOVE T1,(T1)
	LOAD T1,CHLIN,(T1)	;GET THE TTY NUMBER FROM THE CDB
	USTOR T1,NBJFN,(P1)	;SAVE IT IN PLACE OF THE JFN
	RETSKP			;DONE

NDCINN:	LOAD T1,SLPSM,(T4)	;GET THE USER'S TTY NUMBER FROM THE SLB
	ANDI T1,377777
	USTOR T1,NBJFN,(P1)	;SAVE IT IN PLACE OF THE JFN
	RETSKP			;DONE
SUBTTL NDRDB FUNCTION OF THE NODE JSYS

;** Note: this function has interlocking problems.  Functions pick up
;** pointers to data structures without any interlocks.  The data
;** structures may go away causing ILMNRF's.

;HERE FOR FUNCTION NDRDB - READ INTERESTING DATA BLOCKS

;CALL WITH USER'S T2/ ADDRESS OF BLOCK:
;		+0/ NAME OF TABLE TO BE READ
;		+1/ ADDRESS OF USER'S AREA TO PUT THE DATA
;		+2/ JOB NUMBER, SPECIAL, OR TTY NUMBER
;		+3/ DECNET CHANNEL NUMBER, IF APPLICABLE (ELSE IGNORED)
;RETURNS +2 ON SUCCESS, +1 ON ERROR

;THIS FUNCTION RETURNS THE DESIRED TABLE.
;FIRST WORD IS THE ADDRESS OF THE TABLE, FOR FINDING RELATIVE ADDRESSES
;2ND - NTH WORDS ARE THE TABLE ITSELF

;WHEEL OR OPERATOR IS REQUIRED.

;THE KNOWN TABLES ARE: SJ (SJB), SL (SLB), EL (ELB), RC (RCB), CT (CDB).
;THE SYMBOLS TO INCLUDE IN THE CALL ARE .NDBXX (AS, .NDBSJ)

;FOR DECNET, 1ST ARG: EITHER A JOB NUMBER OR ASCIZ FOR A SPECIAL.
;		      THE CURRENT SPECIALS ARE "NRT", "CTM".
;	     2ND ARG: (WHERE APPLICABLE) CHANNEL NUMBER
;FOR ROUTER, 1ST ARG: CIRCUIT I.D.
;FOR CTERM,  1ST ARG: TERMINAL NUMBER OF A CTERM TTY

;POSSIBLE ERRORS:
;	NODX12	BAD TABLE DESIGNATOR
;	NODX13	BAD 1ST ARGUMENT
;	NODX14	BAD 2ND ARGUMENT
;	NODX15	NO SUCH TABLE

;LOCAL PERMANENT AC USE:
;  P1/ ADDRESS OF USER'S ARGUMENT BLOCK, IN USER'S CONTEXT
;  P2/ 1ST ARGUMENT
;  P3/ 2ND ARGUMENT
;  P4/ ADDRESS OF SJB (FOR DECNET FUNCTIONS)

REPEAT 0,<
To add a new function to this JSYS:

1. Define .NDxxx in MONSYM,
2. Add a dispatch to the processing routine to RDBDSP,
3. Add the processing routine, which finds the table address and length.
>

NDRDB:
	MOVE T1,CAPENB		;GET CURRENTLY ENABLED CAPABILITIES
	TXNN T1,SC%WHL!SC%OPR	;DOES THE CALLER HAVE WHEEL OR OPERATOR?
	RETBAD (CAPX1)		;NO - ERROR: INSUFFICIENT CAPABILITIES

	SAVEAC <P1,P2,P3,P4>	;SAVE THE PERMANENT ACS
	UMOVE P1,2		;GET ADDRESS OF USER'S ARGUMENT BLOCK

;READ ARGUMENTS, RANGE CHECK TABLE INDEX, AND DISPATCH TO DO THE WORK

	UMOVE T4,.NDRBT(P1)	;GET THE TABLE DESIRED
	UMOVE P4,.NDRBD(P1)	;AND THE ADDRESS TO RETURN THE DATA
	UMOVE P2,.NDRBJ(P1)	;AND THE DESIRED JOB
	CAIL T4,0		;DOES HE WANT A REAL TABLE?
	CAILE T4,RDBDLN
	RETBAD (NODX12)		;NO - ERROR
	JRST @RDBDSP(T4)	;YES - DISPATCH TO DO THE WORK
				;AND RETURN +1 OR +2

NRBERR:	RETBAD (NODX12)		;NO - ERROR

RDBDSP:	IFIW NRBERR		; * USER-SUPPLIED ADDRESSES * (obsolete)
	IFIW NRBSJB		;SESSION JOB BLOCK
	IFIW NRBSLB		;SESSION LINK BLOCK
	IFIW NRBELB		;END-USER LAYER LINK BLOCK
	IFIW NRBERR		; * Used to be ROUTER circuit block *
	IFIW NRBCDB		;CTERM DATA BLOCK
RDBDLN==.-RDBDSP-1

;HERE TO READ THE SJB OF JOB (P2)

NRBSJB:	CALL NRBGSJ		;(P2/P4) GET THE SJB ADDRESS FOR THIS JOB
	 RETBAD			;REPLICATE THE ERROR
	MOVE T3,P4		;SET UP THE SJB ADDRESS
	MOVEI T4,SJ.LEN		;AND ITS LENGTH
	JRST NRBCPD		;Go copy the data

	RESCD			;Better be resident while nosked...
NRBCPD:	NOSKED			;Lock out scheduler
	CALL NRBCPY		;(T3,T4) COPY IT TO THE USER
	OKSKED			;Allow other jobs to run
	RETSKP			;RETURN SUCCESS

	SWAPCD			;Can be swappable again..

;HERE TO READ THE SLB OF JOB (P2), USER'S CHANNEL

NRBSLB:	CALL NRBGSJ		;(P2/P4) GET THE SJB ADDRESS FOR THIS JOB
	 RETBAD			;REPLICATE THE ERROR
	CALL NRBGSL		;(P2,P3,P4/T3) GET ITS SLB ADDRESS
	 RETBAD			;REPLICATE THE ERROR
	MOVEI T4,SL.LEN		;SET UP THE SLB'S LENGTH
	JRST NRBCPD		;(T3,T4) COPY THE BLOCK AND RETURN

;HERE TO READ THE ELB OF JOB (P2), USER'S CHANNEL

NRBELB:	CALL NRBGSJ		;(P2/P4) GET THE SJB ADDRESS FOR THIS JOB
	 RETBAD			;REPLICATE THE ERROR
	CALL NRBGSL		;(P2,P3,P4/T3) GET ITS SLB ADDRESS
	 RETBAD			;REPLICATE THE ERROR
	LOAD T3,SLPID,(T3)	;GET THE ELB ADDRESS FROM THE SLB
	CAIN T3,0		;IS THERE ONE?
	RETBAD (NODX15)		;NO - ERROR - NO SUCH TABLE
	MOVEI T4,EL.LEN		;SET UP THE ELB'S LENGTH
	JRST NRBCPD		;(T3,T4) COPY THE BLOCK AND RETURN

;HERE TO READ THE CTERM DATA BLOCK FOR TTY (P2)

NRBCDB:	MOVE T1,TT1LIN+TT.CTH	;GET NUMBER OF THE HIGHEST CTERM LINE
	ADDI T1,NTTCTH
	CAML P2,TT1LIN+TT.CTH	;IS THIS A LEGAL CTERM TERMINAL?
	CAMLE P2,T1
	RETBAD (NODX13)		;NO - ERROR - NO SUCH CTERM TERMINAL
	MOVE T2,P2		;YES - GET THE LINE NUMBER
	CALL LCKTTY		;(T2/T2) LOCK THE TTY DYNAMIC DATA
	 RETBAD 		;ERROR - REPLICATE IT
	SKIPN T3,TTDEV(T2)	;GET ADDRESS OF CTERM DATA BLOCK - ANY?
	RETBAD (NODX15)		;NO - ERROR - NO SUCH TABLE
	MOVEI T4,CH.LEN		;YES - GET ITS LENGTH
;Use NRBCPY, not NRBCPD, since LCKTTY goes NOSKED.
	CALL NRBCPY		;(T3,T4) COPY IT TO THE USER
	CALL ULKTTY		;(T2) UNLOCK THE DYNAMIC DATA
	RETSKP			;RETURN SUCCESS

;SUBROUTINE TO COPY (T4) WORDS FROM LOCATION (T3)
;TO THE USER'S LOCATION .NDRBD(P1). RETURNS +1 ALWAYS.

;NOTE: SHOULDN'T USE AC T2, BECAUSE OF LCKTTY-ULKTTY

	RESCD			;Called nosked
NRBCPY:	UMOVE P4,.NDRBD(P1)	;GET THE PLACE TO STORE THE DATA
	UMOVEM T3,(P4)		;SAVE THE TABLE ADDRESS AS THE FIRST WORD
	AOJ P4,			;POINT TO THE FIRST DATA WORD
NRBCP1:	MOVE T1,(T3)		;GET A WORD OF THE TABLE
	UMOVEM T1,(P4)		;SAVE IT
	AOJ P4,			;BUMP SOURCE AND DESTINATION POINTERS
	AOJ T3,
	SOJG T4,NRBCP1		;AND LOOP THROUGH ALL THE WORDS
	RET			;DONE

	SWAPCD

;SUBROUTINE TO GET THE SJB ADDRESS FOR THIS JOB (IN P2)
;RETURNS:
;	+1 ON NO-SUCH-JOB OR -TABLE ERROR
;	+2 WITH P4/ SJB ADDRESS

;NOTE: THIS IS THE ONLY PLACE WHERE DECNET-RELATED FUNCTIONS NEED TO
;CHECK THE JOB NUMBER

NRBGSJ:	JUMPL P2,NRBGSS		;The 'special' job # are ASCII left-justified
				; and will therefore have the sign bit set...
NRBGS1:	MOVE T1,P2		;YES - MAP THE JSB FOR THIS JOB
	CALL GL2LCL		;Convert the global job number to a local one
	 RETBAD (NODX13)	; -error, job is not active
	CALL MAPJSB		;(/T1) (GET JSB POINTER IN T1)
	 RETBAD (NODX13)	;ERROR - JOB IS NOT ACTIVE
	MOVE P4,JSBSJB(T1)	;GET THE ADDRESS OF THE SJB
	CALL CLRJSB		;(T1) UN-MAP THE JSB; GO OKINT
	JUMPN P4,RSKP		;RETURN WITH SJB ADDRESS, IF THERE IS ONE
	RETBAD (NODX15)		;ELSE ERROR - NO SUCH TABLE

NRBGSS:	CAMN P2,[ASCII /NRT/]	;ASKING FOR NRT?
	JRST NRBGSN		;YES - PROCEED
	CAMN P2,[ASCII /CTM/]	;ASKING FOR CTERM?
	JRST NRBGSC		;YES - PROCEED
	RETBAD (NODX13)		;NO - ERROR - NO SUCH JOB

NRBGSN:	MOVE P4,NRTSJP		;POINT TO NRT'S SJB
	RETSKP			;DONE

NRBGSC:	MOVE P4,CTHSAP		;POINT TO CTERM'S SAB
	LOAD P4,SASJB,(P4)	;POINT TO CTERM'S SJB
	RETSKP			;DONE

;SUBROUTINE TO GET THE SLB ADDRESS, GIVEN THE SJB ADDRESS IN P4
;RETURNS:
;	+1 ON NO-SUCH-TABLE ERROR
;	+2 WITH T3/ SLB ADDRESS

NRBGSL:	UMOVE P3,.NDRBC(P1)	;GET THE DESIRED CHANNEL
	LOAD T2,SJCHC,(P4)	;GET THE LENGTH OF THE CHANNEL TABLE
	SOSL P3			;IS THE CHANNEL WITHIN RANGE?
	CAML P3,T2
	RETBAD (NODX14)		;NO - ERROR - NO SUCH CHANNEL
	LOAD T3,SJCHT,(P4)	;YES - GET THE ADDRESS OF CHANNEL TABLE FROM SJB
	ADD T3,P3		;FIND THE ENTRY FOR THIS CHANNEL
	SKIPE T3,(T3)		;GET IT (ADDRESS OF SLB) - IS THERE ONE?
	RETSKP	   		;YES - RETURN IT
	RETBAD (NODX15)		;NO - ERROR - NO SUCH TABLE
	SUBTTL NDSDP function of the NODE% jsys

;NDSDP - NODE% jsys function .NDSDP
;
;	Ac2 ====) .NDPRM
;		  .NDVAL
;	NODE%

NDSDP:	MOVE T1,CAPENB		;Get enabled capabilities
	TXNN T1,SC%WHL!SC%OPR	;Include WHEEL or OPERATOR?
	RETBAD (CAPX1)		; -no, return error

	SKIPE D36IFG		;Is DECnet already initialized?
	RETBAD (NODX16)		; -yes, return error

	UMOVE T2,2		;Get address of users argument block
	UMOVE T1,.NDVAL(T2)	;Get value
	UMOVE T2,.NDPRM(T2)	; and parameter to set

	CAIL T2,.NDRTR		;Range-check
	CAILE T2,.NDFLO		; function code
	RETBAD (ARGX02)		;  -return error

	MOVE T2,SDPTAB(T2)	;Get address to two-word entry
	HLRZ T3,0(T2)		;Get minimum
	HRRZ T4,0(T2)		; and maximum
	CAML T1,T3		;Range
	CAMLE T1,T4		; check value
	RETBAD (NODX17)		;  -bad, return error

	XCT 1(T2)		;Execute instruction to set parameter

	RETSKP			;Success, done

;Define SDP macro
	DEFINE SDP(FUNC,MIN,MAX,INSTR) <
		ASSUME FUNC,EQ,<.-SDPTAB>
		[ XWD MIN,MAX
		  INSTR ]
	>

;Define table
SDPTAB:	SDP(.NDRTR,RNT.L1,RNT.NR,<STOR T1,IBRTR,+IBBLK>)
	SDP(.NDMXA,^D1,^D1023,<STOR T1,IBMXA,+IBBLK>)
	SDP(.NDMXB,^D1,^D500,<STOR T1,IBMXB,+IBBLK>)
	SDP(.NDDBL,^D1,^D100,<STOR T1,IBDBL,+IBBLK>)
	SDP(.NDBSZ,^D290,<<^D1504>-%RTEHS>,<STOR T1,IBBSZ,+IBBLK>)
	SDP(.NDFLO,FCM.NO,FCM.SG,<STOR T1,IBFCM,+IBBLK>)
	SUBTTL NDINT function of the NODE% jsys

;NDINT - insert a node table
;
;	Ac2/ ==) .NDNNN	(Count of nodes)
;		 .NDNTA (Address of node table)
;	   	    ====) sixbit node name
;			  16-bit node address
;				(repeated .NDNNN times)

NDINT:	MOVE T1,CAPENB		;Get enabled capabilities
	TXNN T1,SC%WHL!SC%OPR	;Include WHEEL or OPERATOR?
	RETBAD (CAPX1)		; -no, return error

	SAVEAC <P1,P2>		;Save ACs we will use
	UMOVE T2,2		;Get the user argument block pointer
	UMOVE P1,.NDNNN(T2)	;Get the count of nodes
	UMOVE P2,.NDNTA(T2)	;Get the node table pointer

	DO.			;LOOP over nodes
	  JUMPLE P1,ENDLP.	;  Exit if all nodes done
	  UMOVE T1,0(P2)	;  Get sixbit node name
	  UMOVE T2,1(P2)	;   and 16-bit node address
	  XCALL (XCDSEC,SCTAND)	;  Add the node
	    EXIT.		;    -failed, exit loop
	  ADDI P2,2		;  Move address by the node
	  SOJA P1,TOP.		;   and decrement # of nodes and loop back
	ENDDO.

	;Come here either when all nodes have been read (P1=0) or a failure
	; to insert a node occurred (P1 .GT. 0). Return the # of nodes
	; successfully processed to user in .NDNNN

	UMOVE T2,2		;Get user argument block pointer
	UMOVE T1,.NDNNN(T2)	; and get # of nodes to process
	SUB T1,P1		;Subtract # of nodes left to do
	UMOVEM T1,.NDNNN(T2)	; and return that
	RETSKP			;Always success return
	SUBTTL SIXBIT STUFF

;MOVE SIXBIT NODE NAME TO BYTE POINTER
;CALL GETSIX
;T1/ SIXBIT NODE NAME
;T2/ destination byte pointer (must NOT use T1-T4,CX as index)
;returns +1
; with T1/ byte count,  T2/ updated byte pointer
; and destination filled (but NOT null terminated)
;uses T1-T4
;assumes the destination can hold 6 bytes.

GETSIX::MOVSI T4,-6		;max count is six
	MOVE T3,[POINT 6,T1]	;source
GETSX1:	ILDB CX,T3		;get next byte
	JUMPE CX,GETSX2		;if null exit.
	ADDI CX,40		;no. convert &
	IDPB CX,T2		; put it
	AOBJN T4,GETSX1		;continue if more
GETSX2:	HRRZ T1,T4		;return byte count
	RET			;done.

;convert ASCII node name to SIXBIT
;CALL PUTSIX
;T1/ source byte pointer (must NOT use T1-T4,CX as index)
;T2/ source byte count
;returns +1 always with T1/ SIXBIT name
;uses T1-T4,CX
;stops on null or count, whichever comes first

PUTSIX::MOVE T3,T1
	MOVE T4,[POINT 6,T1]	;destination byte pointer
	SETZ T1,		;the name to be
	CAILE T2,6		;max count
	MOVEI T2,6		; is six
PUTSX1:	ILDB CX,T3		;get byte
	JUMPE CX,RTN		;if null, then done
	CAIL CX,140		;is this a lower case character?
	TRZA CX,100		;yes, make it SIXBIT
	SUBI CX,40		;make it SIXBIT
	IDPB CX,T4		;put byte
	SOJG T2,PUTSX1		;if more, continue.
	RET


	TNXEND
	END