Trailing-Edge
-
PDP-10 Archives
-
cuspbinsrc_1of2_bb-x128c-sb
-
10,7/galaxy/quasar/qsrnet.mac
There are 36 other files named qsrnet.mac in the archive. Click here to see a list.
TITLE QSRNET - NETWORK DATA BASE MANAGER
;
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1975,1976,1977,1978,1979,
;1980,1981,1982,1983,1984,1985,1986,1987. ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; AND COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE
; AND WITH THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS
; SOFTWARE OR ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR
; OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON. NO TITLE TO
; AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.
;
; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE
; WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT
; BY DIGITAL EQUIPMENT CORPORATION.
;
; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY
; OF ITS SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY
; DIGITAL.
SEARCH QSRMAC,ORNMAC,GLXMAC
PROLOG (QSRNET)
%%.QSR==:%%.QSR
QSRVRS==:QSRVRS
SUBTTL LOCAL STORAGE
NETMSG: BLOCK 1 ;PAGE ADDR OF NODE ON-LINE/OFF-LINE MESSAGES
NETDAT: BLOCK 1 ;COUNT FO DATA WORDS IN MESSAGE
NETCNT: BLOCK 1 ;BYTE COUNT
NETHDR: BLOCK 1 ;HEADER FLAG
NETHDA: BLOCK 1 ;HEADER STRING ADDRESS
NETLIN: BLOCK 1 ;NODES/LINE OF TEXT COUNTER
NETPAG: BLOCK 1 ;SAVE AREA FOR THE NODE UUO/JSYS DATA PAGE
NETADR: BLOCK 1 ;SAVE AREA FOR THE ADDR OF THE NODE BLK ADDRESS
NETDUP: BLOCK 1 ;FLAG FOR DUPLICATE NODE DB ENTRIES
RTEQUE:: BLOCK 1 ;DEVICE ROUTING TABLE ID
NETPTR: BLOCK 1 ;BYTE POINTER FOR $TEXT
NETBYT: IDPB S1,NETPTR ;$TEXT ACTION ROUTINE
$RETT ;RETURN
TOPS10 <
DEFINE X (OBJ,TYP),<XWD .OT'OBJ,TYP>
ANFTBL: EXP 3+NETOBL ;ARGUMENT BLOCK LENGTH
BLOCK 2 ;STORAGE FOR NODE NUMBER AND MBZ WORD
ANFOBJ ;GENERATE ANF-10 DEVICE TYPE CODES
ANFBLK: BLOCK 3+NETOBL ;WORKING COPY OF ARGUMENT BLOCK
> ;END TOPS10
NWAMSG: $BUILD .OHDRS+ARG.DA+OBJ.SZ
$SET(.MSTYP,MS.CNT,.OHDRS+ARG.DA+OBJ.SZ)
$SET(.MSTYP,MS.TYP,.QONWA)
$SET(.OARGC,,1)
$SET(.OHDRS+ARG.HD,AR.LEN,OBJ.SZ+1)
$SET(.OHDRS+ARG.HD,AR.TYP,.OROBJ)
$EOB
; Local storage to support the signon file processing
TOPS20<
SONDIR: ASCIZ /D60:/
> ; End of TOPS20
SONFD: XWD 5,0 ;FD for signon file
TOPS10< SIXBIT /D60/ ;Device name
EXP 0 ;File name to be added later based on node name
SIXBIT /SON/ ;Extension
EXP 0 ;Path
> ; End of TOPS10
TOPS20< BLOCK 4> ;Just leave room for ascii string for filename
SONFOB: SONFD ;FOB for signon file
7 ;Ascii file
SONFST: BLOCK 1 ;Signon file status
; -1 file just open or has characters
; 0 EOL has been found
; +1 EOF has been found
DEFTAB: ASCIZ /Red/ ;Table of action taken (define or redefine)
ASCIZ /D/
INTERN N$INIT ;NETWORK INITIALIZATION
INTERN N$NODE ;CHECK FOR NODE ONLINE/OFFLINE STATUS
INTERN N$GNOD ;Get the node entry
INTERN N$INTR ;ADD A NODE TO THE DATA BASE
INTERN N$INT ;NETWORK CHANGE INTERRUPT PROCESSOR.
INTERN N$NRTE ;NETWORK ROUTING ROUTINE
INTERN N$CSTN ;PERFORM STATION RE-ROUTING
INTERN N$LOCL ;VALIDATE A LOCAL NODE NAME/NUMBER
INTERN N$MTCH ;SEE IF 2 NODE NAME/NUMBERS ARE EQUIVALENT
INTERN N$NONL ;IBM NODE ONLINE PROCESSOR
INTERN N$NOFF ;IBM NODE OFFLINE PROCESSOR
INTERN N$CKND ;Routine to check if DEFINE or SET is ok
INTERN N$SACT ;Routine to process signon file
INTERN N$PORT ;ROUTINE TO CHECK FOR MULTIPLE IBM PORT/LINES
INTERN N$RTAS ;CONVERT A ROUTE TABLE ENTRY TO ASCIZ
EXTERN G$MSG ;TEXT BUFFER
SUBTTL N$INIT - ROUTINE TO INITIALIZE THE NETWORK DATA BASE MANAGER.
N$INIT: $CALL I%HOST ;GET HOST NODE NAME AND NUMBER
MOVEM S1,G$LNAM## ;SAVE THE LOCAL NODE NAME
MOVEM S2,G$LNBR## ;SAVE THE LOCAL NODE NUMBER
PUSHJ P,N$ANET ;CREATE A NETWORK QUEUE ENTRY
MOVE AP,S2 ;GET ENTRY ADDRESS
MOVE S1,AP ;COPY NET QUEUE ADDRESS
PUSHJ P,NETDEV ;GET DEVICES ON NODE
MOVX S1,NETNSV+NETONL ;GET VALID STATUS+ONLINE
MOVEM S1,NETSTS(AP) ;SAVE IT
PUSHJ P,I$NINT## ;GO SETUP FOR NETWORK INTERRUPTS
SETOM G$CNET## ;FAKE A NETWORK CHANGE INTERRUPT
$CALL L%CLST ;CREATE A LIST FOR DEVICE ROUTING
MOVEM S1,RTEQUE ;SAVE IT
$RETT ;RETURN
SUBTTL N$INT - ROUTINE TO PROCESS NETWORK TOPOLOGY CHANGES
N$INT: $BGINT 1,
SETOM G$CNET## ;INDICATE A NETWORK CHANGE OCCURED
$DEBRK ;LEAVE INTERRUPT LEVEL
SUBTTL N$INTR - ROUTINE TO ANALYZE THE NETWORK CHANGES
;CALL: PUSHJ P,N$INTR
; TRUE ALWAYS
N$INTR: PUSHJ P,.SAVE2 ;SAVE P1 AND P2
MOVEI S1,[ASCIZ |Nodes on-line:|] ;NODE ON-LINE MESSAGE
MOVEM S1,NETHDA ;STORE HEADER ADDRESS
SETOM NETHDR ;INDICATE NO HEADER SETUP YET
SETOM NETLIN ;INDICATE WE NEED A CRLF TO START OFF
PUSHJ P,NETSET ;SET UP NETWORK REPORTING POINTERS
SETZM G$CNET## ;CLEAR THE INTERRUPT FLAG
DOSCHD ;FORCE A SCHEDULING PASS ON NETWORK INTERRUPTS
MOVEI H,HDRNET## ;GET THE NETWORK DB HEADER ADDRESS
LOAD AP,.QHLNK(H),QH.PTF ;GET THE FIRST ENTRY
MOVX S1,NETNSV ;GET THE NETWORK-STATUS-VALID BITS
MOVE S2,G$LNAM## ;[1464] GET LOCAL NODE NAME
;CLEAR THE NETWORK-STATUS-VALID BITS FOR ALL NETWORK ENTRIES
INTR.1: JUMPE AP,INTR.2 ;NO MORE,,CONTINUE PROCESSING
CAME S2,NETNAM(AP) ;[1464] LOCAL NODE STATUS ALWAYS VALID
ANDCAM S1,NETSTS(AP) ;CLEAR THE STATUS BIT
LOAD AP,.QELNK(AP),QE.PTN ;GET THE NEXT ENTRY ADDRESS
JRST INTR.1 ;AND GO PROCESS IT
;DO NECESSARY PROCESSING FOR ON-LINE NODES
INTR.2: PUSHJ P,GET.NETWORK.TOPOLOGY ;READ THE NETWORK TOPOLOGY
JUMPF INTR.3 ;NO MORE,,GO PROCESS OFF-LINE NODES
MOVE AP,S2 ;RETRIEVE THE NODE ENTRY
MOVE S1,NETSTS(AP) ;GET STATUS WORD
TXNN S1,NETONL ;ARE WE ONLINE,,THEN TELL THE OPR
PUSHJ P,NETRPT ;REPORT NODE STATUS
MOVE S1,NETSTS(AP) ;RELOAD THE STATUS WORD
TXZ S1,NETADD ;CLEAR THE 'JUST ADDED' STATUS BIT
TXO S1,NETNSV+NETONL ;ADD VALID STATUS+ONLINE
MOVEM S1,NETSTS(AP) ;SAVE IT
JRST INTR.2 ;AND GO GET ANOTHER NODE
;NOW DO SOME PROCESSING FOR THE OFF-LINE NODES
INTR.3: MOVEI S1,[ASCIZ |Nodes off-line:|] ;NODE ON-LINE MESSAGE
MOVEM S1,NETHDA ;STORE HEADER ADDRESS
SETOM NETHDR ;INDICATE NO HEADER SETUP YET
SETOM NETLIN ;INDICATE WE NEED A CRLF TO START OFF
LOAD AP,.QHLNK(H),QH.PTF ;GET THE FIRST DB ENTRY
SKIPA ;SKIP THE FIRST TIME THROUGH
INTR.4: LOAD AP,.QELNK(AP),QE.PTN ;GET THE NEXT NODE DB ENTRY
JUMPE AP,NETSND ;SNED MESSAGE TO ORION WHEN DONE
MOVE S1,NETSTS(AP) ;GET THIS NODES STATUS BITS
TXC S1,NETONL ;FLIP THE ONLINE BIT
TXNE S1,NETNSV+NETONL+NETIBM;MUST BE STATUS INVALID+ONLINE+NOT IBM
JRST INTR.4 ;NO,,GET THE NEXT ENTRY
MOVX S1,NETONL ;GET THE ONLINE BIT
ANDCAM S1,NETSTS(AP) ;TURN IT OFF (MAKE IT OFFLINE)
PUSHJ P,NETRPT ;REPORT NODE STATUS
MOVE S1,NETCOL(AP) ;GET THE NODE NAME/NUMBER
MOVEM S1,NWAMSG+.OHDRS+ARG.DA+OBJ.ND ;SAVE THE NODE NAME/NUMBER
MOVE P2,NETNAM(AP) ;GET THE NODE NAME
MOVE P3,NETNBR(AP) ;GET THE NODE NUMBER
PUSH P,AP ;SAVE THIS ADDR SINCE IT GETS TRASHED
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;LOOP THROUGH THE OBJECT QUEUE LOOKING FOR OBJECTS STARTED AND
;SETUP FOR THE NODE WHICH WENT DOWN
LOAD P1,HDROBJ##+.QHLNK,QH.PTF ;GET THE FIRST ENTRY
SKIPA ;SKIP THE FIRST TIME THROUGH
INTR.5: LOAD P1,.QELNK(P1),QE.PTN ;POINT TO THE NEXT OBJECT
JUMPE P1,INTR.6 ;NO MORE,,FINISH UP
CAME P2,OBJNOD(P1) ;IS THIS OBJECT
CAMN P3,OBJNOD(P1) ; ON THIS NODE?
SKIPA S1,OBJSCH(P1) ;YES - GET THE SCHEDULING BITS
JRST INTR.5 ;NO,,SKIP THIS
TXC S1,OBSSTA+OBSSUP ;MUST BE STARTED+SETUP !!!
TXNE S1,OBSSTA+OBSSUP ;IS IT ???
JRST INTR.5 ;NO,,SKIP THIS
HRLI S1,OBJTYP(P1) ;GET THE SOURCE OBJECT ADDRESS
HRRI S1,NWAMSG+.OHDRS+ARG.DA+OBJ.TY ;GET THE DESTINATION ADDRESS
BLT S1,NWAMSG+.OHDRS+ARG.DA+OBJ.SZ-1 ;COPY IT OVER
MOVE S1,OBJPID(P1) ;GET THE PID TO SEND TO.
MOVEM S1,G$SAB##+SAB.PD ;SAVE AS THE RECIEVERS PID
MOVEI S1,NWAMSG ;GET THE MESSAGE ADDRESS
MOVEM S1,G$SAB##+SAB.MS ;SAVE IT IN THE SAB
MOVEI S1,.OHDRS+ARG.DA+OBJ.SZ ;GET THE MESSAGE LENGTH
MOVEM S1,G$SAB##+SAB.LN ;SAVE IT IN THE SAB
PUSHJ P,C$SEND## ;SEND THE MESSAGE OFF
JRST INTR.5 ;AND GO SEE IF THERE ARE ANY MORE
INTR.6: POP P,AP ;RESTORE AP
PUSHJ P,SNDORN ;SEND THE MESSAGE OFF TO ORION
JRST INTR.4 ;AND GO CHECK THE NEXT NODE
; Set up network on-line/off-line data page
; Call: PUSHJ P,NETSET
;
NETSET: $CALL M%GPAG ;GET A PAGE FOR OUTPUT.
MOVEM S1,NETMSG ;SAVE PAGE ADDRESS
HRLI S1,(POINT 7,) ;MAKE A BYTE POINTER
MOVEM S1,NETPTR ;SAVE IT
MOVEI S1,<<PAGSIZ-1>*5>-1 ;GET BYTE COUNT WE'LL ALLOW
MOVEM S1,NETCNT ;SAVE IT
POPJ P, ;RETURN
; Here to report node status
; Call: PUSHJ P,NETRPT
;
NETRPT: AOSN NETHDR ;NEED OUT OUTPUT A HEADER?
$TEXT (NETBYT,<^M^J^T/@NETHDA/^A>) ;YES - DO IT NOW
SOSLE NETLIN ;COUNT NODES/LINE OF TEXT
JRST NETR.1 ;STILL ROOM
PUSHJ P,NETCRL ;ADD A CRLF
MOVEI S1,5 ;5 NODES/LINE
MOVEM S1,NETLIN ;RESET COUNTER
NETR.1: $TEXT (NETBYT,<^T/NETCLM(AP)/ ^A>) ;DISPLAY 'NAME (NBR)' <TAB>
POPJ P, ;RETURN
; Add a CRLF to the text
; Call: PUSHJ P,NETCRL
NETCRL: MOVEI S1,.CHCRT ;GET <CR>
PUSHJ P,NETBYT ;STORE IT
MOVEI S1,.CHLFD ;GET <LF>
PJRST NETBYT ;STORE IT AND RETURN
; WTO the message off to ORION and delete the message page
;
NETSND: SKIPN @NETMSG ;ANY NETWORK CHANGES TO REPORT?
JRST NETS.1 ;NO - JUST RELEASE THE PAGE AND GO AWAY
PUSHJ P,NETCRL ;ADD A CRLF TO THE END
$WTO (< Network topology >,<^T/@NETMSG/>,,$WTFLG(WT.SJI!WT.NFO))
NETS.1: MOVE S1,NETMSG ;GET PAGE ADDRESS
$CALL M%RPAG ;RELEASE THE PAGE
POPJ P, ;RETURN
SUBTTL N$NODE - ROUTINE TO VERIFY THAT THE NODE IS ONLINE.
;CALL: S1/A SIXBIT NODE NAME OR A NODE NUMBER
;
;RET: TRUE IF ONLINE, FALSE IF OFFLINE.
; S1/ THE NODE NBR(-10), NODE NAME(-20)
; S2/ THE ENTRY ADDRESS
N$NODE: PUSHJ P,N$GNOD ;SEE IF THE NODE EXISTS
JUMPT NODE.1 ;FOUND IT
PUSHJ P,N$NNET ;OTHERWISE, ADD NODE TO THE DATA BASE
NODE.1: SKIPN S1,NETCOL(S2) ;GET THE NODE ID IN S1
SKIPN G$LNBR## ;Does local node have a number??
TRNA ;No, networks turned off (0 allowed)
MOVE S1,NETLOC(S2) ;TRY THE OTHER
MOVE TF,NETSTS(S2) ;GET THE STATUS BITS
TXNE TF,NETONL ;IS IT ONLINE ???
$RETT ;ONLINE !!
$RETF ;OFFLINE !!!
SUBTTL N$GNOD - Routine to try to find (not create) a node entry
;CALL: S1/A SIXBIT NODE NAME OR A NODE NUMBER
;
;RET: TRUE if found
; S1/ preserved
; S2/ THE ENTRY ADDRESS
;
; FALSE if not found
; S1/ preserved
; S2/ Undefined
; This routine will try to return the collating node name if possible,
; otherwise either will match
N$GNOD:
;**;[1206]CHANGE 1 AND ADD 1 LINE AT N$GNOD:+0L 20-APR-84/CTK
$SAVE <S1,P1> ;[1206]SAVE S1 and P1 FOR A MINUTE
$CALL CONOD ;[1206]CHECK THE NODE IDENTIFER
SETZ P1, ;Clear P1
LOAD S2,HDRNET##+.QHLNK,QH.PTF ;GET THE FIRST LINK
GNOD.1: JUMPE S2,GNOD.2 ;All out, finish up
CAMN S1,NETCOL(S2) ;Match collating?
JRST GNOD.3 ;Yes, go finish up
CAMN S1,NETLOC(S2) ;Match other?
MOVE P1,S2 ;Yes, remember it
LOAD S2,.QELNK(S2),QE.PTN ;GET THE POINTER TO THE NEXT NODE.
JRST GNOD.1 ;AND TRY IT.
GNOD.2: SKIPN S2,P1 ;If second best found, set AP and use it
$RETF ;Did not find it
GNOD.3: $RETT ;Did find it
SUBTTL Add entries to the network queue
; Add an entry to the network queue. The following will happen:
;
; 1) Any duplicate node entries will be purged
; 2) Any objects started for the duplicate entries will be purged
; 3) The ASCIZ node text NAME(NBR) will be generated
;
; Call: MOVE S1, sixbit node name or octal node number
; PUSHJ P,N$NNET
; <RETURN>
;
; or
;
; Call: MOVE S1, sixbit node name
; MOVE S2, octal node number (or zero)
; PUSHJ P,N$ANET
; <RETURN>
;
; On return, S2:= entry address
;
N$NNET::MOVE TF,S1 ;COPY ARGUMENT
SETZB S1,S2 ;CLEAR NODE NAME AND NUMBER
TLNE TF,-1 ;HAVE A NODE NAME?
SKIPA S1,TF ;YES - LOAD IT
MOVE S2,TF ;NO - LOAD NODE NUMBER
;FALL INTO COMMON CODE
N$ANET::$SAVE <P1,P2> ;SAVE
$SAVE <T1,T2,T3,T4> ; LOTS
$SAVE <AP,E,H> ; OF ACS
MOVE P1,S1 ;COPY NODE NAME
MOVE P2,S2 ;COPY NODE NUMBER
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
; First want to scan for any duplicate nodes and purge them
MOVEI H,HDRNET## ;POINT TO THE NETWORK QUEUE
LOAD AP,.QHLNK(H),QH.PTF ;GET THE FIRST ENTRY IN THE NODE DB
SKIPA ;SKIP THE FIRST TIME THROUGH
ANET.0: LOAD AP,.QELNK(AP),QE.PTN ;GET THE NEXT ENTRY IN THE DATA BASE
ANET.1: JUMPE AP,ANET.3 ;Done with purge cycle
PUSHJ P,CMPNOD ;COMPARE NODE NAMES AND NUMBERS
JUMPF ANET.0 ;NOT A MATCH, GET NEXT
; Here on a match, want to purge the node entry and any related objects
LOAD S1,.QELNK(AP),QE.PTN ;Get the next entry
PUSH P,S1 ;and remember it
PUSHJ P,M$DLNK## ;DE-LINK THIS ENTRY
MOVE S1,NETSTS(AP) ;PICK UP THE NODE STATUS
TXNE S1,NETONL ;WAS IT ONLINE ???
JRST ANET.2 ;NO - DON'T NEED TO PURGE
MOVEM P1,NETNAM(AP) ;SAVE NODE NAME AND NUMBER SO
MOVEM P2,NETNBR(AP) ;THE PURGE IS SURE TO FIND ALL OBJECTS
PUSHJ P,PURGE.DUP.OBJS ;PURGE THE OBJECT QUEUE
ANET.2: POP P,AP ;RESTORE THE NEXT ENTRY ADDRESS
JRST ANET.1 ;Go try for some more duplicates
; Here to add the node after deleting any previous duplicates
ANET.3: MOVEI H,HDRNET## ;POINT TO THE NETWORK QUEUE
LOAD AP,.QHLNK(H),QH.PTF ;GET THE FIRST ENTRY IN THE NODE DB
SKIPA ;SKIP THE FIRST TIME THROUGH
ANET.4: LOAD AP,.QELNK(AP),QE.PTN ;GET THE NEXT ENTRY IN THE DATA BASE
SKIPN E,AP ;Set E in case this is where we link
JRST ANET.5 ;Add entry to end of node data base
PUSHJ P,SRTNOD ;Sort
JUMPF ANET.4 ;Not here, try next
ANET.5: PUSHJ P,M$GFRE## ;GET A FREE CELL FOR THE ENTRY
MOVEM P1,NETNAM(AP) ;SAVE THE NODE NAME
MOVEM P2,NETNBR(AP) ;SAVE THE NODE NUMBER
MOVX S1,NETADD ;GET THE ADDED BITS
MOVEM S1,NETSTS(AP) ;SET IT
PUSHJ P,M$LINK## ;LINK IT IN
PUSHJ P,GENNOD ;GENERATE ASCIZ NAME(NBR)
MOVE S2,AP ;GET ENTRY ADDRESS
POPJ P, ;RETURN
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
; Compare the node name in P1 and the node number in P2 with
; the node name and number in the entry pointed to by AC 'AP'
;
CMPNOD: JUMPE P1,CMPN.1 ;ONLY NODE NUMBER?
CAME P1,NETNAM(AP) ;NODE NAMES MATCH?
CAMN P1,NETNBR(AP) ;NODE NUMBERS MATCH?
$RETT ;YES TO EITHER
JUMPE P2,.RETF ;ONLY NODE NAME, NOTHING ELSE TO TRY
;Forward and try to match P2
CMPN.1: CAME P2,NETNAM(AP) ;NODE NAMES MATCH?
CAMN P2,NETNBR(AP) ;NODE NUMBERS MATCH?
$RETT ;YES
$RETF ;NO
; Sort node entries
SRTNOD:
TOPS10< MOVE S1,P2> ;Sort on number on the 10
TOPS20< MOVE S1,P1> ; and name on the 20.
JUMPE S1,SRTN.1 ;Primary key failed
SKIPE NETCOL(AP) ;Any value set for this node?
CAMG S1,NETCOL(AP) ;Key less than entry's collating value?
$RETT ;YES - INSERT HERE
$RETF ;NO - DON'T INSERT YET
SRTN.1: SKIPE NETCOL(AP) ;The primary entry value must washout
$RETF ;Isn't - Don't insert yet
TOPS10< MOVE S1,P1> ;Get secondary key
TOPS20< MOVE S1,P2>
SKIPE NETLOC(AP) ;Any value set for this node?
CAMG S1,NETLOC(AP) ;VALUE LESS THAN ENTRY'S?
$RETT ;YES - INSERT HERE
$RETF ;NO - DON'T INSERT YET
; Generate ASCIZ node name and number
; NETASC(AP):= node text for most displays
; NETCLM(AP):= node text for columnized displays
;
GENNOD: SKIPN S1,NETCOL(AP) ;GET COLLATING
MOVE S1,NETLOC(AP) ;NO GOOD, TRY THE OTHER
$TEXT (<-1,,NETASC(AP)>,<^N/S1/^0>)
TOPS10< MOVEI S1,[ITEXT (<(^O/NETNBR(AP)/)>)]> ;ASSUME NODE NUMBER FOR 10
TOPS20< MOVEI S1,[ITEXT (<(^N/NETNBR(AP)/)>)]> ;ASSUME NAME/NUMBER FOR 20
SKIPN NETNBR(AP) ;CHECK
MOVEI S1,[ITEXT (< >)] ;JUST A NAME
$TEXT (<-1,,NETCLM(AP)>,<^W6L /NETNAM(AP)/ ^I/(S1)/^0>)
POPJ P, ;RETURN
SUBTTL N$NRTE - ROUTINE TO PROCESS OPERATOR ROUTE MESSAGES
;CALL: M/ The Message Address
;
;RET: True Always
N$NRTE: PUSHJ P,.SAVE3 ;SAVE P1 - P3
DOSCHD ;FORCE A SCHEDULING PASS
MOVX S1,.RTEFM ;GET 'FROM' OBJECT BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
JUMPF E$IMO## ;NOT THERE,,THATS AN ERROR
MOVE P1,S1 ;SAVE THE BLOCK ADDRESS
SETZM P2 ;CLEAR P2
MOVX S1,.RTETO ;GET 'TO' OBJECT BLOCK TYPE
PUSHJ P,A$FNDB## ;FIND IT IN THE MESSAGE
SKIPF ;NOT THERE,,SKIP
MOVE P2,S1 ;SAVE THE BLOCK ADDRESS
PUSHJ P,NRTE.A ;VALIDATE THE 'FROM'/'TO' OBJ BLOCKS
JUMPF .RETF ;NO GOOD,,THATS AN ERROR
MOVE S1,P1 ;GET THE SOURCE OBJ BLOCK ADDRESS
PUSHJ P,FNDRTE ;GO FIND THE ROUTE TABLE ENTRY
JUMPF [JUMPE P2,E$RTE## ;IF NO 'TO' OBK BLK,,THATS AN ERROR
JUMPN S1,NRTE.4 ;ADD AFTER THE CURRENT ENTRY
JRST NRT.4A ] ;ELSE ADD AFTER THE CURRENT ENTRY
MOVE P3,S1 ;SAVE THE ENTRY ADDRESS
;Here to update a route table entry
NRTE.3: JUMPE P2,NRTE.6 ;JUMP IF DELETING THIS TABLE ENTRY
MOVSI S1,0(P2) ;GET SOURCE,,0
HRRI S1,RTEOB2(P3) ;GET SOURCE,,DESTINATION FOR BLT
BLT S1,RTEOB2+OBJ.SZ-1(P3) ;COPY NEW 'TO' FIELD INTO ROUTE TABLE
JRST NRTE.5 ;AND EXIT
;Here to add an entry to the route table
NRTE.4: MOVE S1,RTEQUE ;GET THE ROUTE TABLE ID
MOVX S2,RTELEN ;GET THE TABLE ENTRY LENGTH
PUSHJ P,L%CBFR ;CREATE A NEW TABLE ENTRY
JRST NRT.4B ;LETS MEET AT THE PASS
NRT.4A: MOVE S1,RTEQUE ;GET THE ROUTE TABLE ID
MOVX S2,RTELEN ;GET THE TABLE ENTRY LENGTH
PUSHJ P,L%CENT ;CREATE A NEW TABLE ENTRY
NRT.4B: SKIPT ;Did we get an entry successfully?
PUSHJ P,S..CCE## ;Stop if not
MOVE P3,S2 ;SAVE THE ENTRY ADDRESS
MOVSI S1,0(P1) ;GET SOURCE,,0
HRRI S1,RTEOB1(P3) ;GET SOURCE,,DESTINATION FOR BLT
BLT S1,RTEOB1+OBJ.SZ-1(P3) ;COPY NEW 'FROM' FIELD INTO ROUTE TABLE
MOVSI S1,0(P2) ;GET SOURCE,,0
HRRI S1,RTEOB2(P3) ;GET SOURCE,,DESTINATION FOR BLT
BLT S1,RTEOB2+OBJ.SZ-1(P3) ;COPY NEW 'TO' FIELD INTO ROUTE TABLE
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
NRTE.5: MOVE S1,P3 ;GET THE ENTRY ADDRESS
PUSHJ P,N$RTAS ;GEN THE ROUTE TEXT
$ACK ( ^T/G$MSG/ ,,,.MSCOD(M)) ;SEND IT OFF
$RETT ;RETURN
;Here to delete a route table entry
NRTE.6: MOVE S1,[POINT 7,G$MSG] ;GET BYTE POINTER TO TEXT BUFFER
MOVEM S1,NETPTR ;AND SAVE IT
MOVE S1,P3 ;POINT TO THE TABLE ENTRY
PUSHJ P,GENFRM ;GENERATE THE 'FROM' DESCRIPTION
SETZM S1 ;GET A NULL BYTE
PUSHJ P,NETBYT ;MAKE THE DESCRIPTION ASCIZ
MOVE S1,RTEQUE ;GET THE ROUTE TABLE ID
PUSHJ P,L%DENT ;DELETE THE ENTRY
$ACK (Routing for ^T/G$MSG/ Deleted,,,.MSCOD(M)) ;TELL OPR
$RETT ;AND RETURN
;Here to validate the object blocks passed in the ROUTE message
;CALL: P1/ The 'FROM' object block address
; P2/ The 'TO' object block address or 0
;
;RET: True if blocks are valid, False otherwise
NRTE.A: MOVE S1,OBJ.TY(P1) ;GET THE 'FROM' OBJECT TYPE
TXZ S1,<1B0> ;CLEAR SIGN BIT
CAXE S1,.INFIN ;IS THIS ALL DEVICES ???
CAXG S1,.OTMAX ;NO,,IS IT A VALID OBJECT TYPE ???
SKIPA ;SKIP IF ALL DEVICES OR GOOD OBJECT
JRST E$ISO## ;RETURN INVALID SOURCE OBJECT !!!
MOVEM S1,OBJ.TY(P1) ;SAVE THE OBJECT TYPE
JUMPE P2,NRT.A1 ;NO 'TO' OBJECT BLOCK,,SKIP THIS
MOVE S2,OBJ.TY(P2) ;GET THE 'TO' OBJECT TYPE
TXZ S2,<1B0> ;CLEAR SIGN BIT
CAXE S2,.INFIN ;IS THIS ALL DEVICES ???
CAXG S2,.OTMAX ;NO,,IS IT A VALID OBJECT TYPE ???
SKIPA ;SKIP IF ALL DEVICES OR GOOD OBJECT
JRST E$IDO## ;RETURN INVALID DESTINATION OBJECT !!!
MOVEM S2,OBJ.TY(P2) ;SAVE THE OBJECT TYPE
CAME S1,S2 ;OBJECT TYPES MUST MATCH !!!
JRST E$IDO## ;NO,,RETURN INVALID DESTINATION OBJ !!
NRT.A1: MOVE S1,OBJ.UN(P1) ;GET THE 'FROM' UNIT
TXZ S1,<1B0> ;CLEAR SIGN BIT
CAXE S1,.INFIN ;IS THIS ALL DEVICES ???
CAXG S1,77 ;NO,,IS IT A VALID UNIT NUMBER ???
SKIPA ;SKIP IF ALL DEVICES OR GOOD UNIT
JRST E$ISO## ;RETURN INVALID SOURCE OBJECT !!!
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
MOVEM S1,OBJ.UN(P1) ;SAVE THE OBJECT UNIT
MOVE S2,OBJ.TY(P1) ;GET THE 'FROM' OBJECT TYPE
CAXN S2,.INFIN ;IF 'ALL' DEVICES,,THEN
CAXN S1,.INFIN ; CAN SPECIFY SPECIFIC UNITS !!!
SKIPA ;VALID,,CONTINUE
JRST E$CRG## ;NO,,THATS AN ERROR
JUMPE P2,NRT.A2 ;NO 'TO' OBJECT BLOCK,,SKIP THIS
MOVE S2,OBJ.UN(P2) ;GET THE 'TO' OBJECT UNIT
TXZ S2,<1B0> ;CLEAR SIGN BIT
CAXE S2,.INFIN ;IS THIS ALL UNITS ???
CAXG S2,77 ;NO,,IS IT A VALID UNIT NUMBER ???
SKIPA ;SKIP IF ALL DEVICES OR GOOD UNIT
JRST E$IDO## ;RETURN INVALID SOURCE OBJECT !!!
MOVEM S2,OBJ.UN(P2) ;SAVE THE OBJECT TYPE
CAXN S1,.INFIN ;IF SOURCE UNIT IA 'ALL' THEN
CAXN S2,.INFIN ; DESTINATION UNIT MUST BE 'ALL' !!!
SKIPA ;VALID UNIT,,SKIP
JRST E$CRG## ;NO,,CAN'T ROUTE A GENERIC UNIT !!!
NRT.A2: MOVE S1,OBJ.ND(P1) ;GET THE 'FROM' OBJECT NODE
CAMN S1,[-1] ;IS IT ALL NODES ???
TXZ S1,<1B0> ;YES,,CLEAR SIGN BIT
MOVEM S1,OBJ.ND(P1) ;SAVE THE NODE NAME/NUMBER
CAXN S1,.INFIN ;IS THIS ALL NODES ???
JRST .+3 ;YES,,SKIP OVER N$NODE CALL
PUSHJ P,N$NODE ;FIND/ADD THE NODE IN/TO OUR DATA BASE
MOVEM S1,OBJ.ND(P1) ;AND SAVE IT
JUMPE P2,.RETT ;NO 'TO' OBJECT BLOCK,,RETURN
MOVE S1,OBJ.ND(P2) ;GET THE 'TO' OBJECT NODE
CAMN S1,[-1] ;IS IT ALL NODES ???
JRST E$IDO## ;YES,,THATS AN ERROR !!!
PUSHJ P,N$NODE ;FIND/ADD THE NODE IN/TO OUR DATA BASE
MOVEM S1,OBJ.ND(P2) ;AND SAVE IT
$RETT ;RETURN
SUBTTL FNDRTE - FOUND A ROUTE TABLE ENTRY
;CALL: S1/ The source object block address
;
;RET: True S1/ The entry address if entry was found
; False S1/ 0 if add a new entry after current
; S1/ -1 if Add a new entry before current
FNDRTE: PUSHJ P,.SAVE2 ;SAVE P1 AND P2
MOVE P1,S1 ;SAVE THE SOURCE OBJ ADDRESS
MOVE S1,RTEQUE ;GET THE ROUTE QUEUE ID
PUSHJ P,L%FIRST ;GET THE FIRST ENTRY
JRST FNDR.2 ;JUMP THE FIRST TIME THROUGH
FNDR.1: MOVE S1,RTEQUE ;GET THE ROUTE TABLE QUEUE ID
PUSHJ P,L%NEXT ;GET THE NEXT ENTRY
FNDR.2: JUMPF [SETZM S1 ;NO MORE,,LITE 'AFTER' RETURN CODE
$RETF ] ;AND RETURN
MOVE P2,S2 ;SAVE THE ENTRY ADDRESS
MOVE S1,OBJ.ND(P1) ;GET THE SOURCE NODE NAME/NUMBER
MOVE S2,OBJ.ND(P2) ;GET THE OBJECT NODE NAME/NUMBER
CAMN S1,S2 ;DO THEY MATCH ???
JRST FNDR.3 ;YES,,CONTINUE ONWARD !!!
CAXN S1,.INFIN ;IS IT 'ALL' SOURCE NODES ???
JRST FNDR.1 ;YES,,TRY NEXT ENTRY
CAXN S2,.INFIN ;IS IT 'ALL' ENTRY NODES ???
JRST [SETOM S1 ;YES,,END OF THE LINE !!!
$RETF ] ;SO RETURN
PUSHJ P,N$MTCH ;DO THE NODE IDS MATCH ???
JUMPT FNDR.3 ;YES,,CONTINUE ONWARD
MOVE S1,OBJ.ND(P1) ;NO,,GET THE SOURCE NODE NAME/NUMBER
CAML S1,OBJ.ND(P2) ;STILL IN RANGE ???
JRST FNDR.1 ;YES,,TRY NEXT ENTRY
JRST [SETOM S1 ;NO,,SET 'AFTER' RETURN CODE
$RETF ] ;AND RETURN
FNDR.3: MOVE S1,OBJ.TY(P1) ;GET THE SOURCE OBJECT TYPE
CAMLE S1,OBJ.TY(P2) ;LESS OR MATCH ???
JRST FNDR.1 ;NO,,TRY NEXT ENTRY
CAME S1,OBJ.TY(P2) ;DO WE MATCH ???
JRST [SETOM S1 ;NO,,SET 'AFTER' RETURN CODE
$RETF ] ;AND RETURN
MOVE S1,OBJ.UN(P1) ;GET THE SOURCE UNIT NUMBER
CAMLE S1,OBJ.UN(P2) ;LESS OR MATCH ???
JRST FNDR.1 ;NO,,TRY NEXT ENTRY
CAME S1,OBJ.UN(P2) ;DO WE MATCH ???
JRST [SETOM S1 ;NO,,SET 'AFTER' RETURN CODE
$RETF ] ;AND RETURN
MOVE S1,P2 ;GET THE ENTRY ADDRESS
$RETT ;AND RETURN
SUBTTL N$RTAS - ROUTINE TO CONVERT A ROUTE TABLE ENTRY TO ASCIZ
;CALL: S1/ The table Entry Address
;
;RET: G$MSG/ The Asciz Description
N$RTAS: PUSHJ P,.SAVE1 ;SAVE P1 FOR A SECOND
MOVE P1,S1 ;SAVE THE TABLE ENTRY ADDRESS
MOVE S1,[POINT 7,G$MSG] ;GET A BYTE POINTER TO THE BUFFER
MOVEM S1,NETPTR ;SAVE IT FOR $TEXT
MOVEI S1,RTEOB1(P1) ;POINT TO THE 'FROM' OBJECT BLOCK
PUSHJ P,GENFRM ;GEN THE 'FROM' TEXT
MOVEI S1,RTEOB2(P1) ;POINT TO THE 'TO' OBJECT BLOCK
PUSHJ P,GENTOO ;GEN TO 'TO' TEXT
$RETT ;RETURN
SUBTTL GENFRM - ROUTINE TO GENERATE 'FROM' ROUTE TABLE DESCRIPTIONS
;CALL: S1/ The Route Table Object Block Address
;
;RET: G$MSG/ The Asciz Text Description
GENFRM: PUSHJ P,.SAVE2 ;SAVE P1 AND P2
MOVE P1,S1 ;SAVE THE OBJECT BLOCK ADDRESS
MOVEI P2,1 ;DEFAULT TO ALL DEVICES
MOVE S1,OBJ.TY(P1) ;GET THE OBJECT TYPE
MOVE S2,OBJ.UN(P1) ;GET THE UNIT NUMBER
CAXN S1,.INFIN ;IS THIS ALL DEVICES ???
CAXE S2,.INFIN ; AND ALL UNITS ???
SKIPA ;NO TO EITHER,,SKIP
JRST GENF.1 ;YES,,SKIP THIS
CAXN S2,.INFIN ;IS IT ALL UNITS ???
MOVEI P2,2 ;YES,,GET CODE
CAXE S2,.INFIN ;IS IT A PARTICULAR UNIT ???
MOVEI P2,3 ;YES,,GET CODE
GENF.1: MOVE S1,OBJ.ND(P1) ;GET THE NODE NAME/NUMBER
MOVEI S2,4 ;DEFAULT TO A PARTICULAR NODE
CAXN S1,.INFIN ;IS IT ALL NODES ???
MOVEI S2,5 ;YES,,GET CODE
$TEXT (NETBYT,<^I/@RTEASC(P2)/^I/@RTEASC(S2)/^A>)
$RETT ;RETURN
GENTOO: PUSHJ P,.SAVE1 ;SAVE P1 FOR A SECOND
MOVE P1,S1 ;SAVE THE 'TO' OBJECT BLOCK ADDRESS
MOVEI S1,4 ;DEFAULT TO 'TO NODE XXX'
MOVX S2,.INFIN ;GET 'ALL' CODE
CAME S2,OBJ.TY(P1) ;'ALL' OBJECTS ???
CAMN S2,OBJ.UN(P1) ; OR 'ALL' UNITS ???
SKIPA ;YES TO EITHER,,SKIP
MOVEI S1,6 ;ELSE A SPECIFIC DEVICE !!!
$TEXT (NETBYT,< Routed to ^I/@RTEASC(S1)/^0>) ;FINISH TEXT
$RETT ;AND RETURN
RTEASC: [0,,0] ;ZERO OFFSET IS INVALID
[ITEXT(All Devices )] ;ALL DEVICES ...
[ITEXT(All ^1/OBJ.TY(P1)/s )] ;ALL PRINTERS, ETC...
[ITEXT(^1/OBJ.TY(P1)/ ^D/OBJ.UN(P1)/ )] ;PRINTER X ...
[ITEXT([^N/OBJ.ND(P1)/])] ;ON NODE XXX...
[ITEXT(on all Nodes)] ;ON ALL NODES
[ITEXT(^I/@RTEASC+3/^I/@RTEASC+4/)] ;...PRINTER XXX ON NODE YYY
SUBTTL N$CSTN - PERFORM DEVICE ROUTINE AND DEVICE CHECKING
;CALL: S1/ The .QEROB Address
; S2/ The OBJTYP object block address OR 0
;
;RET: If S2 = 0 then return through N$NODE
;
N$CSTN: PUSHJ P,.SAVE4 ;SAVE P1 AND P2 AND P3 AND P4
DMOVE P1,S1 ;SAVE THE OBJ BLOCK ADDRESSES
MOVE S1,.ROBTY(P1) ;GET THE OBJECT TYPE
CAXN S1,.OTBAT ;IS IT BATCH ???
JRST CSTN.4 ;YES,,JUST CHECK ATTRIBUTES
MOVE S1,RTEQUE ;GET THE ROUTE QUEUE ID
PUSHJ P,L%FIRST ;GET THE FIRST ENTRY
JRST CSTN.2 ;JUMP THE FIRST TIME THROUGH
CSTN.1: MOVE S1,RTEQUE ;GET THE ROUTE TABLE QUEUE ID
PUSHJ P,L%NEXT ;GET THE NEXT ENTRY
CSTN.2: JUMPF CSTN.4 ;NOT THERE,,CHECK DEVICE ATTRIBUTES
MOVE P3,S2 ;SAVE THE ENTRY ADDRESS
MOVE S1,.ROBND(P1) ;GET THE SOURCE NODE NAME/NUMBER
MOVE S2,OBJ.ND(P3) ;GET THE OBJECT NODE NAME/NUMBER
CAXN S2,.INFIN ;IS IT 'ALL' ENTRY NODES ???
JRST CSTN.3 ;YES,,CONTINUE ONWARD !!!
PUSHJ P,QOMTCH ;DO THE NODE IDS MATCH ???
JUMPT CSTN.3 ;YES,,CONTINUE ONWARD
MOVE S1,.ROBND(P1) ;NO,,GET THE SOURCE NODE NAME/NUMBER
CAML S1,OBJ.ND(P3) ;STILL IN RANGE ???
JRST CSTN.1 ;YES,,TRY NEXT ENTRY
JRST CSTN.4 ;NOT THERE,,CHECK DEVICE ATTRIBUTES
CSTN.3: MOVE S1,.ROBTY(P1) ;GET THE SOURCE OBJECT TYPE
MOVE S2,OBJ.TY(P3) ;GET THE ENTRY OBJECT TYPE
CAXN S2,.INFIN ;IS IT 'ALL' DEVICES ???
MOVE S1,S2 ;YES,,MAKE SOURCE OBJ TYPE MATCH !!
CAMLE S1,S2 ;LESS OR MATCH ???
JRST CSTN.1 ;NO,,TRY NEXT ENTRY
CAME S1,S2 ;DO WE MATCH ???
JRST CSTN.4 ;NOT THERE,,CHECK DEVICE ATTRIBUTES
MOVE S1,OBJ.UN(P3) ;GET THE ENTRY UNIT NUMBER
CAXN S1,.INFIN ;IS IT ALL UNITS ???
JRST CST.3A ;YES,,THEN WE MATCH ALL ATTRIBUTES
LOAD S1,.ROBAT(P1),RO.ATR ;GET THE REQUESTED DEVICE ATTRIBUTES
LOAD S2,.ROBAT(P1),RO.UNI ;GET THE REQUESTED UNIT (0 IS OK)
CAXN S1,%PHYCL ;DID HE REQUEST A SPECIFIC UNIT ???
CAME S2,OBJ.UN(P3) ;DOES THE UNIT MATCH ???
SKIPA ;NO MATCH OR NOT PHYSICAL UNIT,,SKIP !
JRST CST.3A ;YES,,THEN CONTINUE
CAXN S1,%PHYCL ;DIS HE REQUEST A SPECIFIC UNIT ???
CAML S2,OBJ.UN(P3) ;YES,,ARE WE STILL IN RANGE ???
JRST CSTN.1 ;YES,,TRY NEXT ENTRY
JRST CSTN.4 ;NO,,RETURN CHECKING ATTRIBUTES AGAIN
;CONTINUED ON THE NEXT PAGE
;Here to check that scheduling object matches routed object
CST.3A: MOVEI P3,RTEOB2(P3) ;POINT TO THE ROUTED OBJECT BLOCK
JUMPE P2,[MOVE S1,OBJ.ND(P3) ;NO OBJECT,,GET ROUTED NODE NAME
PJRST N$NODE ] ;RETURN THROUGH N$NODE
MOVE S1,OBJ.ND(P3) ;GET THE ENTRY NODE NAME/NUMBER
MOVE S2,OBJNOD(P2) ;GET THE OBJECT NODE NAME/NUMBER
PUSHJ P,N$MTCH ;DO THEY MATCH ???
$RETIF ;No, object does not match route dest.
MOVE S1,OBJ.UN(P3) ;GET THE ENTRY OBJECT UNIT
CAXE S1,.INFIN ;IS IT 'ALL' UNITS ???
CAMN S1,OBJUNI(P2) ;OR DOES IT MATCH THE OBJECT UNIT ???
$RETT ;YES,,RETURN TRUE
$RETF ;No, object does not match route dest.
;Here to check for device attributes match
CSTN.4: MOVE S1,.ROBND(P1) ;GET DEST NODE
JUMPE P2,N$NODE ;NO OBJECT,,RETURN DEST NODE
MOVE S2,OBJNOD(P2) ;GET OBJECT NODE
PUSHJ P,QOMTCH ;DOES IT MATCH?
JUMPF .RETF ;NO,,RETURN FAILURE
LOAD S2,.ROBAT(P1),RO.ATR ;GET THE ATTRIBUTES
CAXN S2,%PHYCL ;DID HE SPECIFY PHYSICAL?
JRST [LOAD S1,.ROBAT(P1),RO.UNI ;YES, GET PHYSICAL UNIT
CAME S1,OBJUNI(P2) ;DO THEY COMPARE
$RETF ;NO,,LOSE !!!
$RETT ] ;WIN IF A MATCH !!!
MOVX S1,OBSDAA ;BIT TO TEST
TDNN S1,OBJSCH(P2) ;DEVICE ATTRIBUTES KNOWN?
$RETT ;NO--FORCE SETUP
LOAD S1,OBJDAT(P2),RO.ATR ;YES,,GET OBJECT ATTRIBUTES
CAMN S1,S2 ;DO THE ATTRIBUTES MATCH?
$RETT ;YES,,RETURN OK
CAXE S2,%GENRC ;DOES USER WANT GENERIC DEVICE ???
$RETF ;NO,,RETURN
CAXE S1,%LOWER ;IS DEVICE LOWER
CAXN S1,%UPPER ; OR UPPER ????
$RETT ;YES,,HE WINS
$RETF ;NO,,RETURN NO GOOD
SUBTTL QOMTCH - Routine to match q entry with object
;CALL: S1/ Node identifier from Q entry
; S2/ Node name from object
;RET: True if match
; False if otherwise
QOMTCH: CAMN S1,S2 ;Get lucky?
$RETT ;Yes
EXCH S1,S2 ;Flip
PUSH P,S2 ;Save the Q entry identifier
PUSHJ P,N$GNOD ;Look for it
POP P,S1 ;Get back Q entry identifier
$RETIF ;Return if object entry not found??
CAMN S1,NETCOL(S2) ;Names match?
$RETT ;Yes, win
; Only the collating entry makes sense for T20.
TOPS10< MOVX TF,NETIBM ;Get the bit for IBM
CAMN S1,NETLOC(S2) ;Did we match other
TXNE TF,NETSTS(S2) ;And not IBM?
SKIPA ;No to either
$RETT ;Yes to both
> ;End of TOPS10
$RETF
SUBTTL N$LOCL - ROUTINE TO VERIFY THAT A NODE NAME/NUMBER IS LOCAL
;CALL: S1/NODE NAME or NODE NUMBER
;
;RET: TRUE if S1 contains a local node name or number
; FALSE if s1 is not local
N$LOCL: CAME S1,G$LNAM## ;IS IT THE LOCAL NODE NAME ???
CAMN S1,G$LNBR## ;OR IS IT THE LOCAL NODE NUMBER ???
$RETT ;YES TO EITHER,,RETURN TRUE
$RETF ;ELSE RETURN FALSE
SUBTTL N$WHER - ROUTINE TO RETURN DEVICE STATION
;CALL: S1/DEVICE NAME
;
; ;RET: TRUE AND S1 CONTAINING LOCAL NODE NAME/NUMBER
; FALSE IF NO SUCH DEVICE
N$WHER::
TOPS10 <
WHERE S1, ;GET ANF-10 STATION
$RETF ;GIVE UP
>
$RETT ;RETURN
SUBTTL N$MTCH - SEE IF 2 REMOTE STATION ID'S ARE EQUIVALENT
;CALL: S1/ First node name/number
; S2/ Second node name/number
;
;RET: True if they match
; False otherwise
N$MTCH: CAMN S1,S2 ;YOU NEVER KNOW,,WE MIGHT GET LUCKY !!
$RETT ;THEY'RE EQUAL,,WE WIN BIG !!!
PUSH P,S2 ;SAVE THIS NODE NAME FOR A MINUTE
PUSHJ P,N$NODE ;FIND THE FIRST NAME IN OUR DATA BASE
POP P,S1 ;RESTORE SECOND NODE NAME TO S1
;**;[1206]ADD 1 LINE AT N$MTCH:+5L 20-APR-84/CTK
$CALL CONOD ;[1206]CHECK THE NODE IDENTIFIER
CAME S1,NETNAM(S2) ;S2 POINTS TO FIRST NAME'S DB ENTRY
CAMN S1,NETNBR(S2) ;DO WE MATCH EITHER THE NODE NAME
$RETT ;OR THE NODE NUMBER .. IF SO WE WIN !!
$RETF ;ELSE LOSE !!!
SUBTTL N$NONL / N$NOFF - IBM ONLINE/OFFLINE PROCESSING ROUTINES
;CALL: S1/ The Node DB Entry Address
; S2/ The Object Block Address
; M/ The Response-to-Setup message address (if N$NONL)
;
;RET: True Always
; This routine is only called if the node is an IBM remote.
N$NONL: TDZA T1,T1 ;INDICATE 'ONLINE' ENTRY POINT
N$NOFF: SETOM T1 ;INDICATE 'OFFLINE' ENTRY POINT
$SAVE <P1,P2,AP> ;SAVE SOME ACS
STKVAR <OFLINE,NOTIFY> ;GEN STORAGE FOR OFFLINE FLAG
; and for notify flag for telling ORION
MOVEM T1,OFLINE ;SAVE THE ENTRY POINT FLAG
SETOM NOTIFY ;No notify needed yet
MOVE AP,S1 ;SAVE THE NODE DB ADDRESS
MOVE P2,S2 ;SAVE THE OBJECT BLOCK ADDRESS
SKIPE OFLINE ;IF WE ARE OFFLINE,,THEN
JRST NOFF.1 ; GO PROCESS IT
; Here if we are Online
NONL.1:
; First check to see if already online
LOAD S1,NETSTS(AP),NETONL ;GET NODE ONLINE BIT
JUMPN S1,.RETT ;IF ONLINE,,THATS AN ERROR
; Find if emulation online and if so, skip this magical stuff
MOVE S1,OBJTYP(P2) ;GET THE OBJECT TYPE
LOAD S2,NETSTS(AP),NT.MOD ;GET THE MODE
CAXN S1,.OTBAT ;Is it emulation batch stream?
CAXE S2,DF.EMU ; and emulation node?
SKIPA ;No,, continue
JRST NONL.6 ;Yes to both, skip all this
; Find if termination and proto and if not, just return
CAXN S1,.OTRDR ;Is it termination reader
CAXE S2,DF.PRO ; and prototype node?
$RETT ;No to either, error
; Find the actual node in the data base and do some checking
MOVE S1,RSU.PN(M) ;Get the actual node name
CAMN S1,RSU.NO(M) ;Is proto and actual the same?
JRST [MOVE P1,AP ;Yes, set actual pointer as proto
JRST NONL.2] ;Skip some of this node setup
$CALL N$GNOD ;Get node if there
JUMPF NONL.7 ;Not there, error
LOAD TF,NETSTS(S2),NETIBM ;Get IBM bit
JUMPE TF,NONL.7 ;Not defined IBM node, error
LOAD TF,NETSTS(S2),NETONL ;Get online bit
JUMPN TF,[$WTO(<IBM Node ^N/S1/ has signed on twice in error>)
$RETT] ;Quit
MOVE P1,S2 ;Remember the node data base
; Move the same info to the actual node
HRLZI S1,NETSTS(AP) ;Get the source
HRRI S1,NETSTS(P1) ;Get the destination
BLT S1,NETIDN(P1) ;Make things the same
; Now set the appropriate bits in the appropriate nodes
NONL.2: MOVEI S1,1
STORE S1,NETSTS(AP),NETPRO ;Say we are online prototype
STORE S1,NETSTS(P1),NETNSV ;Say we are valid online/offline
STORE S1,NETSTS(P1),NETONL ;Say we are online actual
MOVEI S1,DF.TRM ;Get termination mode
STORE S1,NETSTS(P1),NT.MOD ;Set it in actual
MOVE S1,NETCOL(AP) ;Get the proto node name
MOVEM S1,NETLOC(P1) ;Save it in the actual
MOVE S1,NETCOL(P1) ;Get the actual node name
MOVEM S1,NETLOC(AP) ;Save it in the proto
; And put the reader on the actual node
MOVEM S1,OBJNOD(P2) ;Make the reader on the actual node
SETZM NOTIFY ;Want to start an OPR
; Now start-up the line printer on the actual node
MOVEM S1,RSU.NO(M) ;Put actual into origional message
MOVEI S1,.OTLPT ;Get a printer type
MOVEM S1,RSU.TY(M) ;Save it into origional message
MOVEI S1,RSU.TY(M) ;Get address of object block
$CALL A$ISTA## ;Start up the printer
EXCH P1,AP ;Switch names
$TEXT (<-1,,NETASC(AP)>,<^N/NETNAM(AP)/(^N/NETNBR(AP)/)^0>)
$TEXT (<-1,,NETCLM(AP)>,<^W6L /NETNAM(AP)/ (^N/NETNBR(AP)/)^0>)
;Force generation of correct
;online node name
NONL.6: MOVX S1,NETONL ;GET THE NODE ONLINE BIT
IORM S1,NETSTS(AP) ;AND SET IT
MOVE P1,NETCOL(AP) ;GET SIGNED ON NODE NAME
SETZM T1 ;MAKE SURE WE RETURN TRUE
JRST PASS.1 ;MEET AT THE PASS
; Here if signed-on node is not defined as IBM
NONL.7: $WTO (<Prototype node ^N/RSU.NO(M)/ is being shut down>,<Node ^N/S1/ , trying to signon, is not defined as an IBM node>)
MOVEM S1,OBJNOD(P2) ;Change the object so it can be shutdwn
MOVE S1,P2 ;Get the object address
$CALL S$SHUT## ;Shutdown the bad reader
$RETT ;And quit
;Here if we are Offline
NOFF.1: MOVE S1,OBJTYP(P2) ;Get the object type
CAXE S1,.OTBAT ;Is it emulation?
JRST NOFF.2 ;No, skip this
MOVE P1,NETCOL(AP) ;Get the node name
SETZ T1, ;Remember to delete the batch stream
JRST NOFF.9 ;Go finish up
NOFF.2: CAXE S1,.OTRDR ;Is it the reader?
$RETT ;No, don't care about this one
; Given an entry, find if it is the proto, and if so, skip most of this.
; Otherwise, get the proto out of the node data base
LOAD S1,NETSTS(AP),NT.MOD ;Get the mode
CAIN S1,DF.PRO ;Is it the prototype only?
JRST NOFF.8 ;Yes, just shut it down
MOVE S1,NETLOC(AP) ;Get the proto name
PUSHJ P,N$NODE ;Find it in the data base
MOVE P1,S2 ;Remember the entry
; Fix the node data base entries
;P1 is the proto
;AP is the actual
SETZM NETLOC(AP) ;Clear the pointer to the proto
SETZM NETLOC(P1) ;Clear the pointer to the actual
SETZ S1, ;Clear S1 for help
CAME AP,P1 ;Are the nodes the same?
STORE S1,NETSTS(AP),NT.TYP ;No, clear type of actual node
STORE S1,NETSTS(P1),NETPRO ;Clear online proto flag
MOVEI S1,DF.PRO ;Get proto mode
STORE S1,NETSTS(P1),NT.MOD ;Set it in proto
; Here we want to shutdown the printer if any
MOVEI S1,.OTLPT ;Get LPT object type
MOVEM S1,OBJTYP(P2) ;Change our objoct block
MOVE S1,P2 ;Get object block address
PUSHJ P,A$FOBJ## ;Get LPT entry in object queue
JUMPF NOFF.7 ;None there, don't have to do this
PUSHJ P,S$SHUT## ;Shut it down, in all cases
NOFF.7: MOVEI S1,.OTRDR ;Get RDR object type
MOVEM S1,OBJTYP(P2) ;Put it back, just in case
SETZM NOTIFY ;Tell ORION OPR is gone
LOAD S1,NETSTS(P1),NETSHT ;Get shutdown flag of proto
SKIPE S1 ;Is it to be shutdown also?
JRST NOFF.8 ;Yes, go do that
MOVE S1,NETCOL(P1) ;Get the proto name
MOVEM S1,OBJNOD(P2) ;Change the reader
SETO T1, ;Remember to keep the reader
JRST NOFF.9
; Here if shutdown of proto
NOFF.8: SETZ T1, ;Remember to get rid of the reader
NOFF.9: MOVE P1,NETCOL(AP) ;Get node name to tell ORION if needed
MOVX S1,NETONL ;GET THE NODE ONLINE BIT
ANDCAM S1,NETSTS(AP) ;PUT THE NODE OFFLINE
;Here we tell the OPR whats happening and tell ORION also.
PASS.1: MOVEI S1,[ASCIZ/online/] ;DEFAULT TO ONLINE
SKIPE OFLINE ;ARE WE OFFLINE ???
MOVEI S1,[ASCIZ/offline/] ;YES,,MAKE IT OFFLINE
$WTO(< Network Node ^T/NETASC(AP)/ is ^T/0(S1)/ >,,,<$WTFLG(WT.SJI)>)
SKIPN OFLINE ;NO, ARE WE OFFLINE ???
JRST PAS1.1 ;No, skip this
LOAD S1,NETSTS(AP),NT.MOD ;Get the mode
CAXE S1,DF.PRO ;Prototype node?
JRST [PUSHJ P,GENNOD ;No, get regular names
JRST PAS1.1] ; and continue on
;Yes, generate correct node name string
$TEXT (<-1,,NETASC(AP)>,<^N/NETCOL(AP)/^0>)
$TEXT (<-1,,NETCLM(AP)>,<^N6L /NETCOL(AP)/ ^0>)
PAS1.1: SKIPE NOTIFY ;Do we want to tell ORION?
JRST PASS.2 ;NO,,EXIT
MOVE S1,NETPTL(AP) ;YES,,GET THE NODES PORT,,LINE NUMBER
MOVEM S1,NWAMSG+.OFLAG ;SAVE IT IN THE MESSAGE
MOVX S1,%ONLINE ;GET THE NODE ONLINE STATUS BITS
SKIPN OFLINE ;DID THE NODE COME ONLINE ???
MOVEM S1,NWAMSG+.MSFLG ;YES,,MAKE THE MESSAGE AN ONLINE MESSAGE
MOVEM P1,NWAMSG+.OHDRS+ARG.DA+OBJ.ND ;SAVE THE NODE NAME/NUMBER
PUSHJ P,SNDORN ;SEND THE MSG OFF TO ORION
SETZM NWAMSG+.MSFLG ;DONE,,CLEAR THE FLAG WORD
SETZM NWAMSG+.OFLAG ; AND THIS ONE TOO
PASS.2: JUMPN T1,.RETF ;IF PROTOTYPE OFFLINE,,RETURN FALSE
$RETT ;ELSE RETURN
SUBTTL SNDORN - ROUTINE TO SEND A NODE WENT AWAY MSG OFF TO ORION
SNDORN: MOVE S1,G$OPR## ;GET ORION'S PID
MOVEM S1,G$SAB##+SAB.PD ;SAVE AS THE RECIEVERS PID
MOVEI S1,NWAMSG ;GET THE MESSAGE ADDRESS
MOVEM S1,G$SAB##+SAB.MS ;SAVE IT IN THE SAB
MOVEI S1,.OHDRS+ARG.DA+OBJ.SZ ;GET THE MESSAGE LENGTH
MOVEM S1,G$SAB##+SAB.LN ;SAVE IT IN THE SAB
MOVX S1,.OTOPR ;GET THE OPR OBJECT TYPE
STORE S1,NWAMSG+.OHDRS+ARG.DA+OBJ.TY ;SAVE IT
SETZM NWAMSG+.OHDRS+ARG.DA+OBJ.UN ;ZAP ANY UNIT NUMBER
PUSHJ P,C$SEND## ;SEND IT OFF
$RETT ;AND RETURN
SUBTTL N$CKND - Check state of node for IBM DEFINEs and SETs
;CALL S1/ Node name
; S2/ -1 if prototype and online devices are to be checked
; 0 if online device check need not be performed
;
;Ret: True if OK. I.E. Not online and no objects started
; S1/ Node name
; S2/ Node address or 0 if not defined
;
; False if not OK. I.E. Either online or objects started
; S1/ Address of ITEXT error message
; S2/ Node address
N$CKND: $SAVE P1
MOVE P1,S2 ;Remember the flag
$CALL N$GNOD ;Try for the node name
JUMPF [SETZ S2, ;Not found, set address
$RETT] ;Return true
LOAD TF,NETSTS(S2),NETONL ;Get the online bit
JUMPN TF,[MOVEI S1,[ITEXT(Can't perform function on a node which is online)]
JRST CKND.1] ;Cannot allow online
LOAD TF,NETSTS(S2),NETPRO ;Get the proto-actual is online
JUMPN TF,[MOVEI S1,[ITEXT(Can't perform function on a proto node which has an actual node started)]
JRST CKND.1] ;Cannot allow when proto in use
JUMPE P1,.RETT ;If not proto, we don't care about
; online devices
$CALL FNDDEV ;Check for objects started on node
JUMPF [MOVE S1,NETCOL(S2) ;Get back the name
$RETT] ;Return true
MOVEI S1,[ITEXT(Can't perform function on a node which has devices started)]
CKND.1: $RETF
SUBTTL FNDDEV - CHECK FOR ANY DEVICE STARTED FOR THE SPECIFIED NODE
;CALL: S2/ The Node DB Entry Address for the Node we are looking for
; (preserved)
;
;RET: True - If we find a device started for the specified node
; False - If there are no devices started for the node
FNDDEV: PUSHJ P,.SAVE1 ;SAVE P1 FOR A MINUTE
LOAD P1,HDROBJ+.QHLNK,QH.PTF ;GET PTR TO FIRST OBJ QUEUE ENTRY
SKIPA ;SKIP FIRST TIME THROUGH
FNDD.0: LOAD P1,.QELNK(P1),QE.PTN ;GET THE NEXT OBJ ENTRY ADDRESS
JUMPE P1,.RETF ;NO MORE,,RETURN FALSE
MOVE S1,OBJNOD(P1) ;GET THE OBJECTS NODE NAME
;**;[1206]ADD 1 LINE AT FNDD.0:+3L 20-APR-84/CTK
$CALL CONOD ;[1206]CHECK THE NODE NUMBER
CAME S1,NETNAM(S2) ;DO
CAMN S1,NETNBR(S2) ; WE
$RETT ; MATCH ??? YES - RETURN TRUE
JRST FNDD.0 ;NO,,CHECK NEXT OBJECT
SUBTTL N$SACT - Set up actual IBM termination nodes
;Call: S1/ Name of prototype node
; S2/ Address of node entry or 0 if none.
;Ret: True if all nodes succeeded
; S2/ Address of node entry
; False if any node failed
; S1/ Address of ITEXT error message if failed
; S2/ Any argument needed for ITEXT
N$SACT: $SAVE <P1,P2,P3> ;Save needed ac's
;P1 is IFN of signon file
;P2 is char count in file
;P3 is byte pointer into file
STKVAR <NODNAM,NODADD> ;NODNAM is name of proto
;NODADD is address of node entry of
; proto
MOVEM S1,NODNAM ;Save node name till later
MOVEM S2,NODADD ;And address if known
; First need to find the signon file, get the file name
TOPS10< MOVEM S1,SONFD+.FDNAM > ;Just save the node name
TOPS20< $TEXT <-1,,SONFD+1>,<^T/SONDIR/^N/S1/.SON^0> > ;Make the ASCIZ string
MOVX S1,FOB.MZ ;Get the size of our FOB
MOVEI S2,SONFOB ;And the address of our FOB
$CALL F%IOPN ;Open file for input
JUMPF NSAC.7 ;No signon file
; send message then quit false
MOVE P1,S1 ;Remember the IFN
SETZ P2, ;Read no chars yet
SETOM SONFST ;Note file open
; Now loop through the file getting the node names
NSAC.0: $CALL GETNNM ;Get next node name
JUMPF NSAC.9 ;Go to return success
; Check the node out
SETZ S2, ;Do not check onliness
$CALL N$CKND ;Go check for the actual node
JUMPF NSAC.8 ;Give error (already in S1) and return
JUMPN S2,NSAC.2 ;If already defined, skip this
; Need to create the node
$CALL N$NNET ;Add the node
MOVEI TF,1 ;Say this is a definition
SKIPA ;Skip the next
NSAC.2: SETZM TF ;Say this is a redifinition
; Now want to set approp. bits in the node data base
SETZM NETSTS(S2) ;Clear the status word
MOVEI S1,1 ;Get a bit
STORE S1,NETSTS(S2),NETIBM ;Light the IBM bit
MOVEI S1,DF.TRM ;Get the termination mode
STORE S1,NETSTS(S2),NT.MOD ;Set it
; Tell the operator what we did
MOVE S1,TF ;Get the define type
$ACK (<^T/DEFTAB(S1)/efine for Node ^T/NETASC(S2)/ Accepted>,,,.MSCOD(M))
JRST NSAC.0 ;Go for another
NSAC.7: SETO S2, ;Say we want last GLXLIB error
MOVEI S1,[ITEXT(<Failed to open signon file - ^E/S2/>)]
$RETF
NSAC.8: $CALL CLSSON ;Close the signon file
$RETF
NSAC.9: $CALL CLSSON ;Close the signon file in either case
SKIPE S1 ;Was it really ok?
$RETF ;No
TOPS10< SETZ S1, ;Lie, say we have no node name
MOVE S2,NODNAM> ; but have a number
TOPS20< MOVE S1,NODNAM ;The reverse lie for the 20
SETZ S2,> ;
$CALL N$ANET ;Add the node our way purging
; any previous entries
;Now need to force the node name to look correct
$TEXT (<-1,,NETASC(S2)>,<^N/NETCOL(S2)/^0>)
$TEXT (<-1,,NETCLM(S2)>,<^W6L /NETCOL(S2)/ ^0>)
$RETT ;Return true
; Work routine to close the signon file
CLSSON: DMOVE P2,S1 ;Save S1,S2 a sec
MOVE S1,P1 ;Get the IFN
$CALL F%REL ;Release the file
DMOVE S1,P2 ;Get S1,S2 back
$RET ;Just return, don't care about errors
SUBTTL GETNNM - Routine to get the next node name from signon file
; This routine should only be called by N$SACT!
;Call: Assumes: P1/ IFN of signon file
; P2/ Char count of input
; P3/ Byte pointer to input
;Ret: True S1/ Node name
; False End of file encountered S1/ 0
; or error with node name or file
; S1/ Address of ITEXT that explains error
; S2/ Argument for ITEXT if needed
GETNNM: $SAVE <T1,T2,T3,T4>
$CALL EATLIN ;Get rid of the signon card
JUMPF [SETZ S1, ;No more cards
$RETF] ;Return the EOF
; Get node name
TOPS20< MOVE T3,[POINT 6,T2]> ;Setup byte pointer on T20 only
MOVEI T4,6 ;Only 6 chars allowed
SETZ T2, ;Start with nothing
GETN.1: $CALL GETCHR ;Get a character
JUMPF GETN.3 ;Go do EOL processing
; Do character processing
TOPS20< ;Alpha is only valid for T20 (node names) not for T10 (numbers)
CAIL T1,"A" ;Check for valid alpha
CAILE T1,"Z"
SKIPA ;Not a letter
JRST GETN.2 ;Add a letter
> ;End of TOPS20
CAIL T1,"0" ;Check for number
TOPS20< CAILE T1,"9">
TOPS10< CAILE T1,"7"> ;Must be octal on T10
JRST GETN.4 ;Bad character
; Add a character to the node name/number
GETN.2:
TOPS20< ;Make node name on T20
SUBI T1,40 ;Make it sixbit
IDPB T1,T3 ;Add it to the name
> ; End of TOPS20
TOPS10< ;Make node number on T10
SUBI T1,60 ;Make it a number
IMULI T2,10 ;Shift what is already there (OCTAL)
ADD T2,T1 ;Add it
> ; End of TOPS10
SOJG T4,GETN.1 ;go for more
; Do EOL processing
GETN.3: $CALL EATLIN ;Finish line
SKIPE S1,T2 ;Any name?
$RETT ;Yes, return ok.
MOVEI S1,[ITEXT(<Error reading signon file, blank signon node name>)]
$RETF ;Must have node name
; Invalid character processing
GETN.4: PUSH P,T1 ;Save the invalid character
$CALL EATLIN ;Finish line
MOVEI S1,[ITEXT(<Error reading signon file, invalid character -^7/S2/->)]
POP P,S2 ;Get the invalid character back
$RETF ;Pass error up
; Now the work routine for checking through characters
;GETCHR gets the next character and returns it in T1. If no more
; characters on the line/in the file return false with T1/0.
; P2 (number of characters) is -1 if EOF has been encountered.
GETCHR: SKIPL SONFST ;Everything OK?
JRST GTCH.3 ;EOF or EOL already encountered
GTCH.1: SOJGE P2,GTCH.2 ;Any characters?
MOVE S1,P1 ;No, get IFN
$CALL F%IBUF ;Read some more
DMOVE P2,S1 ;Save returned arguments
JUMPT GTCH.1 ;If some characters, go get them
MOVEI TF,1 ;Must have EOF
MOVEM TF,SONFST ;Remember it
JRST GTCH.3 ;Go to EOL processing
GTCH.2: ILDB T1,P3 ;Get next char
CAIN T1,11 ;Map tabs
MOVEI T1,40 ;Into spaces
CAIN T1,15 ;Check for end
JRST GTCH.1 ;End - but don't stop on cr
CAIE T1,12 ;Check for linefeed
$RETT ;No, good char
SETZM SONFST ;Mark EOL
GTCH.3: SETZ T1, ;No character
$RETF ;Tell the caller
;EATLIN is a routine to find the end of the current line
; It returns true if EOL, false if EOF
EATLIN: $CALL GETCHR ;Get the next character
JUMPT EATLIN ;Go get another
SKIPE SONFST ;Consider the state
$RETF ;EOF
SETOM SONFST ;Just EOL, clear it
$RETT
SUBTTL N$PORT - Routine to look for multiple devices on same port/line
;CALL: S1/ The node name to be checked
;
;RET: S2/ Entry address of node or 0 if not defined
; True if there are devices on same PORT/LINE
; S1/ Matching node's DB address
; False if there are no devices on same PORT/LINE
N$PORT: PUSHJ P,N$NODE ;Find the node DB address
LOAD S1,NETSTS(S2),NETIBM ;Is it an IBM station ???
JUMPE S1,.RETF ;No,,then OK
$SAVE <P1,AP> ;Save P1 and AP
MOVE AP,S2 ;Save the Node DB address
LOAD P1,HDROBJ##+.QHLNK,QH.PTF ;Get the first objectc address
SKIPA ;Skip the first time through
PORT.1: LOAD P1,.QELNK(P1),QE.PTN ;Get the next object address
JUMPN P1,PORT.2 ;Jump if not done
MOVE S2,AP ;Remember the node entry
$RETF ;Tell the caller
PORT.2: MOVE S1,OBJNOD(P1) ;Get the node name
PUSHJ P,N$NODE ;Find its DB entry
CAMN S2,AP ;Same node ???
JRST PORT.1 ;Yes,,try next
LOAD S1,NETSTS(S2),NETIBM ;Is it an IBM station ???
JUMPE S1,PORT.1 ;No,,Try next
LOAD S1,NETPTL(AP),NT.PRT ;Get source port number
LOAD TF,NETPTL(S2),NT.PRT ;Get the previous port number
CAME S1,TF ;Do they match ???
JRST PORT.1 ;No,,try next
LOAD S1,NETPTL(AP),NT.LIN ;Get source line number
LOAD TF,NETPTL(S2),NT.LIN ;Get the previous line number
CAME S1,TF ;Do they match ???
JRST PORT.1 ;No,,try next
LOAD S1,OBJSCH(P1),OBSSTA ;Has device been started ???
JUMPE S1,PORT.1 ;No,,try next
MOVE S1,S2 ;Get the node DB address
MOVE S2,AP ;Remember the node entry
$RETT ;And return
SUBTTL GET.NETWORK.TOPOLOGY - ROUTINE TO GET THE NETWORK TOPOLOGY
;CALL: PUSHJ P,GET.NETWORK.TOPOLOGY
;
;RET: S2/Address of node entry
; FALSE IF NO MORE NODES IN THE SYSTEM DATA BASE
GET.NETWORK.TOPOLOGY:
TOPS20 <
SKIPE S1,NETPAG ;HAVE WE READ THE TOPOLOGY YET ???
JRST GET.1 ;YES,,GET NEXT AND RETURN
MOVEI S1,2 ;WANT 2 CONSECUTIVE PAGES
PUSHJ P,M%AQNP ;GET THEM
PG2ADR S1 ;CONVERT PAGE NUMBER TO AN ADDRESS
MOVEM S1,NETPAG ;SAVE THE PAGE ADDRESS
MOVEI S2,<PAGSIZ*2>-4 ;GET THE BLOCK LENGTH
MOVEM S2,.NDNND(S1) ;SAVE IT IN THE DATA BLOCK
MOVX S1,.NDGNT ;GET NETWRK TOPOLOGY INFO FUNCTION
MOVE S2,NETPAG ;GET THE ARGUMENT BLOCK ADDRESS IN S2
NODE ;GET THE NETWORK TOPOLOGY
ERJMP GET.2 ;NO GOOD,,RELEASE THE PAGE & RETURN
MOVE S1,NETPAG ;GET THE DATA ADDRESS
HLRZ S2,.NDNND(S1) ;GET THE NODE COUNT
JUMPE S2,GET.2 ;NONE THERE,,RELEASE DATA PAGE & RETURN
MOVEM S2,.NDNND(S1) ;SAVE THE TOTAL COUNT
MOVEI S2,.NDBK1-1(S1) ;POINT TO THE FIRST NODE BLK POINTER
MOVEM S2,NETADR ;SAVE THE ADDRESS FOR LATER
GET.1: SOSGE .NDNND(S1) ;SUBTRACT 1 FRON NODE COUNT
JRST GET.2 ;IF NO MORE,,RELEASE THE DATA PAGE
AOS S2,NETADR ;POINT TO THE NEXT NODE BLK ADDRESS
MOVE S1,0(S2) ;GET THE POINTER TO THE NODE BLOCK
MOVE S1,.NDNAM(S1) ;GET THE BYTE PTR TO THE NODE NAME
PUSHJ P,S%SIXB ;CONVERT IT TO SIXBIT
MOVE S1,S2 ;GET THE NODE NAME IN S1
SETZ S2, ;NO NODE NUMBERS ON THE -20
PUSHJ P,N$NODE ;MAKE CERTAIN NODE IS IN DATA BASE
$RETT ;RETURN
GET.2: MOVEI S1,2 ;WANT TO RELEASE 2 PAGES
MOVE S2,NETPAG ;GET THE DATA PAGE ADDRESS
ADR2PG S2 ;CONVERT PAGE ADDRESS TO PAGE NUMBER
PUSHJ P,M%RLNP ;RELEASE THEM
SETZM NETPAG ;CLEAR THE DATA PAGE FLAG
$RETF ;AND RETRUN
> ;END TOPS20 CONDITIONAL
TOPS10 <
SKIPE S1,NETPAG ;HAVE WE READ THE TOPOLOGY YET ???
JRST GET.1 ;YES,,GET NEXT AND RETURN
PUSHJ P,M%GPAG ;GET A PAGE FOR THE DATA
MOVEM S1,NETPAG ;SAVE THE PAGE ADDRESS
MOVEM S1,NETADR ;SAVE THE DATA ADDRESS
MOVEI S2,776 ;GET THE DATA BLOCK LENGTH
MOVEM S2,0(S1) ;SAVE THE NODE. PARAMETER
HRLI S1,12 ;GET THE NODE. TOPOLOGY FUNCTION
NODE. S1, ;GET THE NETWORK TOPOLOGY
JRST GET.4 ;CANT DO IT,,NO NETWORK HERE
MOVEM S1,@NETPAG ;SAVE THE NODE COUNT
MOVE S1,NETPAG ;GET THE NODE. BLOCK ADDRESS
GET.1: SOSGE 0(S1) ;COUNT DOWN THE NODE COUNT
JRST GET.4 ;NO MORE,,FINISH UP AND RETURN
AOS S2,NETADR ;BUMP DATA ARG COUNT BY 1
MOVE S2,0(S2) ;GET A NODE NUMBER
LOAD AP,HDRNET##+.QHLNK,QH.PTF ;POINT TO THE FIRST NETWORK ENTRY
SKIPA ;SKIP THE FIRST TIME THROUGH
GET.2: LOAD AP,.QELNK(AP),QE.PTN ;GET THE NEXT NETWORK ENTRY
JUMPE AP,GET.3 ;NOT THERE,,GET THE NAME
CAME S2,NETNBR(AP) ;HAVE WE FOUND IT ???
JRST GET.2 ;NO,,TRY NEXT ENTRY
SKIPN S1,NETNAM(AP) ;GET THE NODE NAME
JRST GET.3 ;NO NAME SO FAR - TRY TO GET IT
MOVE S1,NETSTS(AP) ;GET THE NETWORK STATUS
TXNE S1,NETONL ;WAS IT ALREADY ONLINE ???
JRST [MOVE S2,AP ;RETURN THE NODE ENTRY ADDRESS
$RETT] ;YES,,JUST RETURN
GET.3: MOVEI S1,2 ;BLOCK LENGTH OF 2
MOVE TF,[2,,1] ;GET PARAMETER LIST (WANT NODE NAME)
NODE. TF, ;GET THE NODE NAME (GIVEN NODE NBR)
TDZA S1,S1 ;INCASE THERE'S NO NAME YET
MOVE S1,TF ;GET THE NODE NAME IN S1
PUSHJ P,N$ANET ;NEED TO UPDATE NODE ENTRY
PUSH P,S2 ;SAVE NET QUEUE ENTRY
MOVE S1,S2 ;COPY
PUSHJ P,NETDEV ;GET DEVICES ON NODE
POP P,S2 ;RESTORE NET QUEUE ENTRY
$RETT ;RETURN
GET.4: MOVE S1,NETPAG ;GET THE DATA PAGE ADDRESS
PUSHJ P,M%RPAG ;RELEASE THE PAGE
SETZM NETPAG ;CLEAR THE DATA PAGE FLAG
$RETF ;AND RETURN
> ;END TOPS10 CONDITIONAL
; ROUTINE TO DETERMINE THE DEVICES ON A NODE
; CALL: MOVE S1, NET QUEUE ADDRESS
; PUSHJ P,NETDEV
NETDEV:
TOPS10 <
$SAVE <AP> ;SAVE AP
MOVE AP,S1 ;COPY NET QUEUE ADDRESS
MOVE S1,[ANFTBL,,ANFBLK] ;SET UP BLT
BLT S1,ANFBLK+3+NETOBL-1 ;COPY
MOVE S1,NETNBR(AP) ;GET NODE NUMBER
MOVEM S1,ANFBLK+1 ;SAVE
MOVE S1,[.NDRCI,,ANFBLK] ;SET UP UUO AC
NODE. S1, ;READ DEVICE INFO
$RETT ;???
MOVSI S1,-NETOBL ;-NUMBER OF DEVICES
MOVEI S2,NETOBJ(AP) ;POINT TO START OF STORAGE
NETD.1: HLLZ TF,ANFBLK+3(S1) ;GET DEVICE COUNT
HLR TF,ANFTBL+3(S1) ;INCLUDE OBJECT TYPE
MOVEM TF,(S2) ;SAVE
AOS S2 ;ADVANCE STORAGE POINTER
AOBJN S1,NETD.1 ;COPY ALL DEVICE COUNTS
MOVE S1,ANFBLK+1 ;GET TARGET NODE NUMBER
CAMN S1,G$LNBR## ;CENTRAL STATION?
SKIPA S1,[INPCEN] ;YES
MOVEI S1,INPREM ;REMOTE STATION
HLRZ TF,NETBAT(AP) ;GET COUNT OF TTYS ON STATION
SKIPN TF ;MUST BE NON-ZERO FOR BATCH
SETZ S1, ;ISN'T
HRLM S1,NETBAT(AP) ;UPDATE FOR START NODE COMMAND
> ;END TOPS10
$RETT ;AND RETURN
SUBTTL PURGE.DUP.OBJS - ROUTINE TO PURGE DUPLICATE OBJECTS
;This routine is called because it is possible to start the same
;device at the same node using both the node name and node number.
;This works only if the node is offline, since QUASAR cannot
;validate the Node. For example, if an operator said:
;Start Pr 0/Node:MUMBLE and Start Pr 0/Node:10 and node MUMBLE
;and node 10 are the same node, then you have a problem when
;the node comes online. This routine is called when a node comes
;online and it schedules a shutdown for the duplicate node.
;CALL: AP/ Node DB Address of Node which came online
;
;RET: True Always
PURGE.D: LOAD T1,HDROBJ##+.QHLNK,QH.PTF ;GET THE FIRST OBJECT ADDRESS
SKIPA ;SKIP THE FIRST TIME THROUGH
PURG.1: LOAD T1,.QELNK(T1),QE.PTN ;GET THE NEXT OBJECT ENTRY ADDRESS
JUMPE T1,.RETT ;DONE,,COMPLETE NODE ONLINE PROCESSING
MOVE S1,OBJNOD(T1) ;GET THE OBJECTS NODE NAME/NUMBER
CAME S1,NETNAM(AP) ;LETS SEE IF WE MATCH
CAMN S1,NETNBR(AP) ;MUST TRY BOTH VALUES
SKIPA ;YES,,CONTINUE ON
JRST PURG.1 ;NO,,TRY NEXT OBJECT
SKIPN S1,NETCOL(AP) ;GET THE COLLATING HANDLE
MOVE S1,NETLOC(AP) ;USE THE ALTERNATE
MOVEM S1,OBJNOD(T1) ;SAVE THE NODE ID
MOVX S1,OBSIGN ;GET THE IGNORE BIT
ANDCAM S1,OBJSCH(T1) ;CLEAR IT UNCONDITIONALLY
MOVE T2,T1 ;GET THE OBJECT ADDRESS
;HAVING FOUND 1 OBJECT STARTED FOR THIS NODE,,ARE THERE ANY MORE ???
PURG.2: LOAD T2,.QELNK(T2),QE.PTN ;POINT TO THE NEXT OBJECT ENTRY
JUMPE T2,PURG.1 ;NO MORE,,CONTINUE ON
MOVE S1,OBJNOD(T2) ;GET THIS OBJECTS NAME/NUMBER
CAME S1,NETNAM(AP) ;DO WE MATCH BY NAME
CAMN S1,NETNBR(AP) ;OR BY NUMBER ???
SKIPA ;YES,,CHECK REST OF BLOCK
JRST PURG.2 ;NO,,GO CHECK THE NEXT OBJECT BLOCK
;WE FOUND ANOTHER OBJECT STARTED FOR THIS NODE,,ARE THEY FOR
;THE SAME DEVICE ??? IF SO, THATS A NO-NO
MOVE S1,OBJTYP(T1) ;GET THE FIRST OBJ'S TYPE
CAME S1,OBJTYP(T2) ;DO WE MATCH ???
JRST PURG.2 ;NO,,WE'RE OK SO FAR
MOVE S1,OBJUNI(T1) ;GET THE FIRST OBJ'S UNIT
CAME S1,OBJUNI(T2) ;DO WE MATCH ???
JRST PURG.2 ;NO,,THATS OK TOO !!!
$SAVE <H,AP> ;SAVE 'H', AND 'AP'
MOVEI H,HDROBJ## ;GET OBJECT HEADER ADDRESS
MOVE AP,T2 ;GET THE DUPLICATES ADDRESS
PUSHJ P,M$RFRE## ;DELETE THE DUPLICATE OBJECT
$RETT ;CANT HAVE MORE THEN 2 DUPLICATE OBJECTS
SUBTTL CONOD COMPARE NODE TO ZERO
;**;[1206] Add a new routine at the end of the module.
; Called with S1 containing a node identifier. If 0, then set to
; zero the local node name if the local node number is 0.
;
CONOD: SKIPE S1 ;[1206]IS THE NODE NUMBER ZERO ???
JRST CONO.1 ;[1206]...NO
SKIPN G$LNBR ;[1206]LOCAL NODE ZERO ?
MOVE S1,G$LNAM ;[1206]USE LOCAL NODE NAME
CONO.1: $RET ;[1206]AND RETURN
END