Google
 

Trailing-Edge - PDP-10 Archives - bb-m080w-sm_t20_v7_0_02_mon_src_mod - monitor-sources/cfsusr.mac
There are 13 other files named cfsusr.mac in the archive. Click here to see a list.
; Edit= 8973 to CFSUSR.MAC on 28-Sep-88 by GSCOTT
;Only output [Successfully joined CFS cluster] if we have seen another TOPS-20
;node on our CI.
; Edit= 8967 to CFSUSR.MAC on 13-Sep-88 by RASPUZZI, for SPR #21879
;Revamp edit 8871 such that CFS joining takes care of checking out the wire
;status of the local node before joining the CFS cluster.
; Edit= 8966 to CFSUSR.MAC on 13-Sep-88 by GSCOTT
;Always output the [Successfully joined CFS cluster] message if we did. 
; Edit= 8959 to CFSUSR.MAC on 1-Sep-88 by GSCOTT
;Wait 10 seconds before output of message in CFSJYN.
; Edit= 8957 to CFSUSR.MAC on 30-Aug-88 by GSCOTT
;Lowercase that join message.
; Edit= 8873 to CFSUSR.MAC on 10-Aug-88 by RASPUZZI
;Update BUG. documentation again.
; Edit= 8871 to CFSUSR.MAC on 29-Jul-88 by LOMARTIRE
;Prevent CFSVFL BUGHLTs and duplicate job numbers and other bad things that
;can happen when CFSJYN does not do its job!
; UPD ID= 8605, RIP:<7.MONITOR>CFSUSR.MAC.5,  11-Feb-88 17:11:11 by RASPUZZI
;TCO 7.1220 - Modify CFS global job assignments. Make JBGET1 get more global
;	      jobs if we are out of them and make CFGTJB have another (local)
;	      entry point (CFSGJB) that obtains that extra job chunk.
; UPD ID= 8489, RIP:<7.MONITOR>CFSUSR.MAC.4,   9-Feb-88 12:17:47 by GSCOTT
;TCO 7.1218 - Insert copyright notice.
; UPD ID= 8466, RIP:<7.MONITOR>CFSUSR.MAC.3,   7-Feb-88 18:25:26 by RASPUZZI
;TCO 7.1210 - Correct module name for BUG.s.
; UPD ID= 8358, RIP:<7.MONITOR>CFSUSR.MAC.2,  20-Jan-88 11:41:32 by RASPUZZI
;TCO 7.1190 - Split CFSSRV up. Make CFSPAR and CFSUSR to allow CFSSRV
;             to be assembled and have the ability to obtain a CREF.

;	COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1988.
;	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 THAT IS NOT SUPPLIED BY DIGITAL.
	SEARCH CFSPAR,SCAPAR,PHYPAR,PROLOG

	TTITLE (CFSUSR,,< - CFS User related routines>)
;	M. Raspuzzi January 88

	SALL
	EXTN <HSHDRI,LNGHSH,NSPCQ0,NSPCQ1,WRDHSH>
	DEBUG==1		;Do debugging

	RESCD			;Unless otherwise noted
	Subttl	Table of Contents

;		     Table of Contents for AM70-CFSUSR
;
;				  Section		      Page
;
;
;    1. Initialization
;        1.1    CFSJYN/CFSJYX (Join the CFS network) . . . . .   4
;        1.2    CFSCSC (Create private pages)  . . . . . . . .   7
;    2. Support Routines
;        2.1    CFSSPC (Obtain request block space)  . . . . .  10
;        2.2    CFCARV (Carve a block from page pool)  . . . .  12
;        2.3    SNDTIM (Send date and time to new node)  . . .  13
;        2.4    BRDTIM (Send date and time at startup) . . . .  14
;        2.5    CFTADB (Broadcast date and time via STAD)  . .  15
;        2.6    CFSPRT (Return local port number)  . . . . . .  16
;        2.7    CFSNOD (Routine to get node name)  . . . . . .  17
;    3. Global Job Number Routines
;        3.1    JBAVAL (Manage job bit table)  . . . . . . . .  19
;        3.2    JBGET1 (Get global job number for local job) .  20
;        3.3    GL2LCL (Return local job number) . . . . . . .  21
;        3.4    LCL2GL (Return global job number)  . . . . . .  22
;        3.5    CFGTJB (Get jobs at system startup)  . . . . .  23
;    4. DIAG% JSYS Support
;        4.1    CFDIAG (Code for Set CI Unavailable) . . . . .  24
;    5. CNFIG% JSYS Support
;        5.1    CFCIN (Return CFS information) . . . . . . . .  26
;        5.2    CFCSE (Return serial numbers of CFS nodes) . .  27
;        5.3    CFCND (Return list of node names)  . . . . . .  28
;    6. End of CFSUSR  . . . . . . . . . . . . . . . . . . . .  31
	SUBTTL	Initialization -- CFSJYN/CFSJYX (Join the CFS network)

;Routine to join the CFS network. This is called after SETSPD has run
;so that all of the system configuration options have been selected.
;Accepts no arguments, and gives no backtalk (a fair arrangement)

;[7.1011] This routine will print out descriptive messages whenever the
;[7.1011] joining process encounters any problems.

;CFSIFL starts at -2. CFSINI calls CFSJYX, which increments it and
;returns.

CFSJYN::			;Do the join
   IFN CFSSCA,<			;If want an SCA interface
	MOVEI T1,.NDGLN		;Set up to get our name
	MOVEI T2,T3		;The argument block
	MOVE T3,[POINT 8,MYPOR2] ;Where to stash the name
	NODE%			;Get it
	 ERJMP .+1		;If no name, move on
CFSJYX::AOSE CFSIFL		;Time to join up?
	RET			;No
	SAVEAC <P1>		;Save a reg
	STKVAR <DTIMER,REASON,SEEN20> ;[8973][7.1011] Get some space on stack
	SETZM SEEN20		;[8973] KL has not been seen yet
	CALL CFDLSN		;[7.1021] () Open a dump listener
	 NOP			;[7.1021] Don't care about failure
	CALL CFSLSN		;OPEN A LISTENER FIRST
	 NOP			;BETTER WORK
	BLCAL. (SC.SOA,<<.,CFSINT>>) ;[7.1190] Want to know about configuration changes
				;NOTE: This will callback at CFSINT for nodes
				; that are already online
	 NOP
; Now we must wait until we have a CFS connection open to every TOPS-20 system
; already up.  This will allow for a deterministic way to insure that we are
; fully joined to the CI once we return from this routine.  [8959] We wait ten
; seconds before printing out a message for a node.  We wait 60 seconds
; between messages.

	CALL CFSPRT		;(/T1) Get our own port number
	MOVEM T1,MYPOR4		;Store it
	MOVSI P1,-C%SBLL	;Loop for all the nodes
	MOVEI T1,^D10		;[8959][7.1011] Initial time of 10 seconds
	MOVEM T1,DTIMER		;[7.1011] Store the initial delay time value

;[8959] Here to check the next node number.

CFSJY0:	MOVE T1,MYPOR4		;[8967] Get our node
	CALL PTHSTS		;[8967] (T1/T1,T2) Is it sick?
	 JRST CFSJY5		;[8967] It's ill, don't join cluster
	TXNN T2,UDB%WA!UDB%WB	;[8967] Is path A or B good?
	JRST CFSJY5		;[8967] Neither is good, leave now
	HRRZ T1,P1		;[8959] Get the current node
	CAMN T1,MYPOR4		;Is this our node?
	JRST CFSJY1		;Yes, skip it
	CALL PTHSTS		;(T1/T1,T2) What is path status to node
	 JRST CFSJY5		;[8959] The port is not running - quit
	TXNN T2,UDB%MA		;[8959] In maintenance mode?
	TXNN T2,UDB%WA+UDB%WB	;[8959] Response on either wire?
	JRST CFSJY1		;[8959] No response or in maint mode, quit
	SKIPE T1,SBLIST(P1)	;[8871][7.1011] No, is System Block created?
	IFSKP.			;[7.1011] No, so we must wait
	  HRROI T1,[ASCIZ/No System Block created/] ;[7.1011] Save message
	  MOVEM T1,REASON	;[7.1011] 
	  JRST CFSJY2		;[7.1011] Go and wait a second
	ENDIF.			;[7.1011] 
        LOAD T1,SBVCST,(T1)	;[8871] Get VC state
	CAIN T1,VC.OPN		;[8871] Is it open?
	IFSKP.			;[8871] No, so we must wait
	  HRROI T1,[ASCIZ/No open Virtual Circuit/] ;[8871] Save message
	  MOVEM T1,REASON	;[8871] 
	  JRST CFSJY2		;[8871] Go and wait a second
	ENDIF.			;[8871] 
	HRRZ T2,P1		;Get the node number again
	CALL ISIT20		;(T2/) Is this a TOPS-20 system?
	 JRST CFSJY1		;No, skip it
	AOS SEEN20		;[8973] We have seen a TOPS-20 system out there
	HRRZ T1,P1		;Get node number
	CALL CFCNCK		;(T1/) Is there a CFS connection?
	 SKIPA T1,[XWD -1,[ASCIZ/No CFS connection/]] ;[8959] Nope, load mess
	JRST CFSJY1		;[8959] Yes, go check the next node
	MOVEM T1,REASON		;[8959] Save reason and fall through
;	JRST CFSJY2		;[8959]  to publish the message
;[8959] Here if this node doesn't smell right.  Output a message if the DTIMER
;has counted down to zero.

CFSJY2:	SOSL DTIMER		;[7.1011] Should a message be given?
	IFSKP.			;[7.1011] Yes
	  HRROI T1,[ASCIZ/
% Cannot join cluster with node /] ;[8957][7.1011] Print first part of message
	  CALL PMES		;[7.1011] (T1/)
	  HRRZ T1,P1		;[7.1011] Now print the node number in decimal
	  CALL PNUM		;[7.1011] (T1/)
	  HRROI T1,[ASCIZ/ because: /] ;[8957][7.1011]
	  CALL PMES		;[7.1011] (T1/)
	  MOVE T1,REASON	;[7.1011] Finally, print the reason
	  CALL PMES		;[7.1011] (T1/)
	  HRROI T1,CRLF		;[7.1011] End with a CRLF
	  CALL PMES		;[7.1011] (T1/)
	  MOVEI T1,^D60		;[7.1011] Now, set the delay timer to 60 to...
	  MOVEM T1,DTIMER	;[7.1011] ...delay message for about 1 minute.
	ENDIF.			;[7.1011] 
	MOVEI T1,^D1000		;Wait for a second
	DISMS			; to hope that things get solid
	JRST CFSJY0		;[8959] Wait is over, check this node again

;[8959] Here to check the next node number.

CFSJY1: MOVEI T1,^D10		;[8959] Load ten second count
        MOVEM T1,DTIMER		;[7.1011] Reset delay time value
	AOBJN P1,CFSJY0		;[8959] Continue with next node

;[8959] Here if we have checked all nodes.  Output message saying we are done
;if we output a "cannot join" message.  We have to do a TTMSG since the "System
;restarting, wait..." message would come out ahead of this message, which would
;be confusing.  Using a TTMSG insures that this message comes out first.

	MOVE T1,CTYLNO		;[8959] Load the CTY's line number
	TXO T1,.TTDES		;[8959] Turn that into a terminal designator
	HRROI T2,[ASCIZ/
[Successfully joined CFS cluster]
/]				;[8959] Load a good message
	SKIPE SEEN20		;[8973] Did we ever see a TOPS-20 node?
	TTMSG%			;[8959] Yes, indicate that all is OK now
	 ERJMP .+1		;[8959] Avoid MONNEJ (if this fails we are SOL)

CFSJY5:	SETONE SCVER		;[8959] Set verify in job 0
	AOS JB0FLG		; so awake it
	ENDSV.			;[7.1011]
   >	;IFN CFSSCA
	RET			;AND DONE
	SUBTTL	Initialization -- CFSCSC (Create private pages)

;Routine called from JOB 0 start up to create private stock of pages.

CFSCSC::EA.ENT
	SAVEQ
	CALL CFSDIN		;Do basic set up
   REPEAT 0,<			;DONE IN PGRINI, NOT NEEDED HERE
	CALL ASSPTL		;Get an SPT slot for the map
	TDO T1,SHRPTR		;Make a share pointer out of it
	MOVEM T1,MSECTB+CFSSEC	;Stash in the EPT

;Section map all set up. Now put a page in it.

	HRRZS T1		;Get SPT index only
	CALL SWPIN1		;Create a page table for our use
   >
	MOVEI Q1,LNGHSH		;Get words in long entries
	ADDI Q1,WRDHSH		;Add words in short entries
	ADDI Q1,HSHLEN+CFSSLN+DMPSLN+PGSIZ+PGSIZ-1 ;[7.1021] Add extra words
   IFN CFSSCA,<			;If an SCA interface...
	ADDI Q1,NOFN+HSTSIZ	;Add in extra data bases
	ADDI Q1,VOTLEN+STRN	;And the extras if SCA is supported
   >	;IFN CFSSCA
	LSH Q1,-PGSFT
	MOVNI Q1,1(Q1)		;Get -(n+1)
	HRLZS Q1
	DO.
	  MOVSI T1,CFSSEC	;The section
	  HRRI T1,0(Q1)		;The page
	  CALL MLKMA		;Lock it down
	  ADDI Q1,PGSIZ-1	;Increase by appropriate amount
	  AOBJN Q1,TOP.		;Do them all
	ENDDO.			;All pages now created
;Now create queue entries
;First, the vote queues

	MOVSI Q2,CFSSEC		;Start at the beginning
	HRRI Q2,HSHLEN		;Start after the hash table
   IFN CFSSCA,<			;Only need this if doing SCA stuff
	MOVEM Q2,OLDTAB		;Base of OLDTAB
	ADDI Q2,HSTSIZ
	MOVEI Q1,NVOTQ0		;Number of vote packets
	DO.
	  LOAD T1,PGWD,Q2	;Get page offset in the address
	  ADDI T1,VOTSIZ-1	;See if this fits on the page
	  CAIL T1,PGSIZ		;Does it?
	  IFNSK.		;If not
	    MOVE T1,Q2		;No. See if they are usable anyway
	    CALL CPPCON		;Check if they are contiguous
	    ANNSK.		;If not
	      TXZ Q2,PGWD	;put on page boundary
	      ADDI Q2,PGSIZ	; next page, that is
	  ENDIF.
IFN DEBUG,<
	  MOVE T3,[252525]
	  STOR T3,CFGWD,(Q2)  	;Store unique guard word
  >				;IFN DEBUG
	  MOVE T3,Q2		;The address
	  PIOFF
	  CALL CFSWDN		;Enqueue this one
	  PION
	  ADDI Q2,VOTSIZ	;Next address
	  SOJG Q1,TOP.		;Do them all
	ENDDO.			;Vote packets on the queue
   >	;IFN CFSSCA
;Now do the hash packest

	MOVEI Q1,NSPCQ0		;The number to do
	DO.
	  MOVE T1,Q2		;Next one
	  EXCH T1,CFSPCQ	;Put it on
	  MOVEM T1,@CFSPCQ	;And link rest to it
	  ADDI Q2,HSHSIZ	;Next entry
	  SOJG Q1,TOP.		;Do them all
	ENDDO.			;All done

;Now allocate long packets. Always need these, even for non-SCA systems

	MOVEI Q1,NSPCQ1		;Number to get
	DO.
	  MOVE T1,Q2		;Next one
	  EXCH T1,CFSPQL	;Enqueue it
	  MOVEM T1,@CFSPQL	;Link it in
	  ADDI Q2,HSHSIZ+HSHDRI	;Length of an entry
	  SOJG Q1,TOP.
	ENDDO.
   IFN CFSSCA,<			;If SCA present
	MOVEM Q2,CFSSTR		;STR transaction table
	ADDI Q2,STRN		;# of structures
	MOVEM Q2,CFSOFN		;Beginning of OFN pointer table
	ADDI Q2,NOFN
   >	;IFN CFSSCA
	MOVEM Q2,CFSSTK		;Put the stack here
	ADDI Q2,CFSSLN		;[7.1021] Goto beginning of dump stack
	MOVEM Q2,DMPSTK		;[7.1021] Save the address
	ADDI Q2,PGSIZ+DMPSLN	;[7.1021] Get to the guard page
	MOVE T1,Q2		;Copy it
	ADDI Q2,PGSIZ		;Get to the next page
	TXZ Q2,PGSIZ-1		;And to the first word
	MOVEM Q2,CFNXPG		;Next free cell
	CALL FPTA		;Get ID
	MOVX T2,PTCACH		;Read-only
	CALLRET MSPACS		;Set it
 	SUBTTL	Support Routines -- CFSSPC (Obtain request block space)

;Routine to acquire a request block.
;Returns:
;	+1/ no space
;	+2 /success. T1/ block address

CFSSPC::PIOFF
	SKIPN T1,CFSPCQ		;A PACKET HERE?
	IFSKP.			;If so
	  MOVE T2,0(T1)		;Get the link
	  MOVEM T2,CFSPCQ	;Pop the stack
	  PION
	  AOS CFGTSH		;Count this event
	  XMOVEI T2,SHTADD
	  SETZM HSHPST(T1)
	  SETZM HSHOKV(T1)	;No clla-back for voting
	  MOVEM T2,HSHRET(T1)
	  SETZM HSFLAG(T1)	;And the flags
	  RETSKP		;AND SUCCESS
	ENDIF.
	PION			;Nothing here.
	CALL SPCCOL		;Collect some
	SKIPE CFSPCQ		;Any appear?
	JRST CFSSPC		;Yep. Go get it
	MOVEI T1,HSHSIZ		;Size we need
	CALL CFCARV		;Get one please
	CALL SHTADD		;Add it
	JRST CFSSPC		;And try again
;Entry for a long block

CFSSPL::PIOFF
	SKIPN T1,CFSPQL		;Any packets here?
	IFSKP.			;If so
	  AOS CFGTLG		;Count this event
	  MOVE T2,0(T1)		;Pop it
	  MOVEM T2,CFSPQL	;And update the list
	  PION
	  XMOVEI T2,LNGADD
	  SETZM HSHPST(T1)
	  SETZM HSHOKV(T1)	;No call-back for voting
	  MOVEM T2,HSHRET(T1)
	  MOVX T2,HSHLOS	;Say it is long
	  MOVEM T2,HSFLAG(T1)	; and clear other flags
	  RETSKP		;AND SUCCESS
	ENDIF.
	PION
	CALL SPCCOL		;Collect some
	SKIPE CFSPQL		;Any appear?
	JRST CFSSPL		;Yep. Go get it
	MOVEI T1,HSHDRI+HSHSIZ	;Size needed
	CALL CFCARV		;Get one
	CALL LNGADD		;Put it in
	JRST CFSSPL		;And continue

;Coroutine to add a short block to the CFSPCQ queue

SHTADD:	PIOFF
	EXCH T1,CFSPCQ		;Make it the head.
	MOVEM T1,@CFSPCQ	;And link old queu back in
	PION
	RET			;Done

;Coroutine to add a long block to the CFSPQL queue

LNGADD:	PIOFF
	EXCH T1,CFSPQL		;Make it the head
	MOVEM T1,@CFSPQL	;Link old queue back in
	PION
	RET
 	SUBTTL	Support Routines -- CFCARV (Carve a block from page pool)

;Routine to "carve" another block from the page pool
;	T1/ Size Needed
;Returns:	+1 always.
;	T1/ address of block

CFCARV:	NOSKED
	DO.
	  MOVE T2,CFNXSZ	;Get size remaining in pool
	  SUB T2,T1		;Compute remainder
	  IFL. T2		;If not enough
	    PUSH P,T1		;Save size needed
	    MOVE T1,CFNXPG	;Get current address
	    ADD T1,CFNXSZ	;Increment to the next page
	    CALL MLKMA		;Create and lock it
	    POP P,T1		;Recover size
	    MOVEI T2,PGSIZ	;Increment of size
	    ADDM T2,CFNXSZ	;Add it
	    LOOP.
	  ENDIF.
	ENDDO.
	MOVEM T2,CFNXSZ		;Store new size
	EXCH T1,CFNXPG		;Get address
	ADDM T1,CFNXPG		;And increment by new count
	OKSKED
	RET			;And done

;Routine to collect some space when a queue is empty. Used by above routines

SPCCOL:	MOVEI T1,CFSCTM		;Time
	MOVEI T2,SKDCNT		;# to collect
	CALLRET CFSRSX		;Do it
 	SUBTTL	Support Routines -- SNDTIM (Send date and time to new node)

;Send date and time to newly on-line host
;Called from various places in CFSSRV
;	T1/ Local host index
;Sends date and time if it can
;Clobbers T1-T4

   IFN CFSSCA,<			;If SCA support
SNDTIM::ACVAR <W1,W2>
	MOVE W1,T1
	CALL LGTAD		;Do we have TAD?
	CAMN T1,[-1]		;Have it?
	RET			;No. DOn't bother doing the rest
	MOVE W2,T1		;Save it
	CALL GVOTE1		;Get a buffer
	 RET			;None
	MOVEI T2,.CFTAD		;Get function
	STOR T2,CFCOD,(T1)
	MOVEM W2,CFROT(T1)	;Stash the TAD
	MOVEI T2,0(W1)		;Host number
	CALL SCASND		;Send it off
	IFNSK.			;If failed
	  PIOFF
	  CALL CFSWDN		;Return the buffer
	  PION
	ENDIF.
	RET			;And done
	ENDAV.
>	;IFN CFSSCA
  	SUBTTL	Support Routines -- BRDTIM (Send date and time at startup)

;Routine called from MEXEC after date and time is typed in to send
;date and time to any processors that are "inferior" to us.

BRDTIM::
   IFE CFSSCA,<RET>		;If no SCA support, nothing to do
   IFN CFSSCA,<			;If SCA support...
	SAVEQ			;Get some work regs
	CFSLOK			;keep things stable for a bit
	MOVSI Q1,-HSTSIZ	;Set to loop over the host table
	MOVE Q2,MYPORT		;Get our serial number
	DO.
	  SKIPLE CFSHST(Q1)	;Is this one possible around?
	  SKIPL CFHSTS(Q1)	;yes. Still?
	  IFSKP.			;If it is here
	    CAMG Q2,CFSHNM(Q1)	;Are we a bigger wheel?
	    ANSKP.		;If so
	      MOVEI T1,0(Q1)	;Get host index
	      CALL SNDTIM		;Send it the time
	  ENDIF.
	  AOBJN Q1,TOP.		;Do all hosts
	ENDDO.
	CALLRET CFSFAL		;And done
   >	;IFN CFSSCA
 	SUBTTL	Support Routines -- CFTADB (Broadcast date and time via STAD)

;Routine to broadcast date and time. Called from STAD JSYS

CFTADB::
   IFN CFSSCA,<
	CALL LGTAD		;Get local date and time
	BLCAL. (CFSBRD,<T1,[0],[.CFTAD],[0]>) ;Do the sends
   >	;IFN CFSSCA
	RET			;And done
  	SUBTTL	Support Routines -- CFSPRT (Return local port number)

;Routine to return the local port ID to whoever needs it.
;		CALL CFSPRT
;Returns:	+1
;		  T1/ ID

CFSPRT::
   IFE CFSSCA,<CALLRET RETZ>	;If no SCA, return a zero
   IFN CFSSCA,<			;If SCA is present
	CALL SC.PRT		;Ask SCA for the amswer
	 SETZM T1		;If no port, trouble!!!
	RET
   >	;IFN CFSSCA
	SUBTTL	Support Routines -- CFSNOD (Routine to get node name)
;[7.1074]
;CFSNOD - This routine will return the name of a node within a CFS
;cluster given its node number.
;
;Called with:
;	T1/ CI node number
;	CALL CFSNOD
;
;Returns:
;	+1 - Failure, error code in T1
;	+2 - Success with:
;		T1/ CI node number
;		T2 & T3/ 8-bit CI node name

	SWAPCD			;Called from TTMSG% JSYS

CFSNOD::SAVEQ			;Preserve these (Q1 is our counter)
	STKVAR <NODNUM>		;Place holder for node number
	CAIL T1,0		;Too small?
	CAIL T1,C%SBLL		;Or too large?
	RETBAD (TTMSX3)		;Yep, CI node is out of range
	MOVEM T1,NODNUM		;Stash it
	CALL SC.PRT		;(/T1) Get our CI node number
	 RETBAD ()		;Let the caller know an error occurred
	CAME T1,NODNUM		;Is the node supplied ours?
	IFSKP.			;Yes,
	  HRLI Q1,(POINT 7,)	;Get 7 bit byte pointer
	  HRRI Q1,OURNAM	;For our node name
	  HRLI Q2,(POINT 8,)	;Get 8 bit byte pointer for destination
	  HRRI Q2,T2		;It goes here
	  SETZ T3,		;Be sure no garbage is left over
	  DO.			;Do all characters until a null is hit
	    ILDB Q3,Q1		;Get character
	    SKIPN Q3		;Is it a null?
	    EXIT.		;Yes, all done
	    IDPB Q3,Q2		;Not null, stick it in return place
	    LOOP.		;End of loop
	  ENDDO.
	  RETSKP		;Return node name to caller
	ENDIF.
	CIOFF			;No interruptions while we check this
	MOVSI Q1,-HSTSIZ	;Init AOBJN counter
	DO.			;Loop over all entries
	  MOVE T1,CFSHST(Q1)	;Get host entry's CID
	  SKIPL T1		;Just a listener?
	  SKIPN T1		;Or nothing?
	  JRST CFSNO2		;Yes to one, so do next entry
	  CALL SC.NOD		;(T1/T1,T2) Get CI node number for this
	  CAME T2,NODNUM	;Is this the node we want?
	  IFSKP.		;If so
	    LOAD T2,SID,T1	;Get index into CFNNAM table from SID field
	    LSH T2,1		;CFNNAM has 2 words per entry
	    DMOVE T2,CFNNAM(T2)	;Retrieve node name and stash in T2 & T3
	    CION		;And done
	    RETSKP		;Return to user
	  ENDIF.
CFSNO2:	  AOBJN Q1,TOP.		;Do next CFS entry
	ENDDO.
	CION			;Turn CI back on before going back
	RETBAD (TTMSX3)		;All nodes checked, found no match
	SUBTTL	Global Job Number Routines -- JBAVAL (Manage job bit table)

;Routines to manage job bit table.
;First, routine to make a job available
;	T1/ Job to make available
;Returns:	+1
; clobbers all temps

	RESCD

JBAVAL::SKIPN T1		;Job 0 is not reserved, so
	RET			;Just return
	MOVE T4,T1		;Copy ti
	IDIVI T1,^D36		;Compute word and bit offset
	MOVE T2,BITS(T2)	;Get the bit
	IORM T2,JOBMBT(T1)	;Make it available
	ADJBP T4,GLBPTR		;Point to entry in translation table
	MOVEI T3,0		;Get a zero
	DPB T3,T4		;Clear the entry
	RET			;Done
 	SUBTTL	Global Job Number Routines -- JBGET1 (Get global job number for local job)
;[7.1220]
;JBGET1 - Get a free job global for a local job. If there are no free global
;job slots from this system, then try to get another set of 32 jobs. Do this
;only if we have less global jobs than we have NJOBS.
;
; Called with:
;	T1/ Local job number
;	CALL JBGET1
;
; Returns:
;	+1 - Failure, no more global jobs or all jobs in use
;	+2 - Success,
;	     T1/ Global job number

JBGET1::STKVAR <PASS1,JOB>	;[7.1220] Temp storage
	SKIPN T1		;Local Job 0 is always Global Job 0
	RETSKP			;So just return
	SETZM PASS1		;[7.1220] Say we are on pass 1
	MOVEM T1,JOB		;[7.1220] Save argument
JBGET2:	MOVSI T1,-JBWDS		;[7.1220] Scan the table
	DO.
	  SKIPN T2,JOBMBT(T1)	;Anything here?
	  IFSKP.		;If so
	    JFFO T2,.+1		;Find the first
	    MOVE T2,BITS(T3)	;Get the bit
	    ANDCAM T2,JOBMBT(T1) ;Clear it
	    MOVEI T1,0(T1)
	    IMULI T1,^D36	;Compute jobs ahead of this one
	    ADDI T1,(T3)	;Add in the bit
	    MOVEI T2,(T1)	;Copy it
	    ADJBP T2,GLBPTR	;Point to entry in translation table
	    MOVE T4,JOB		;[7.1220] Get local job number back
	    DPB T4,T2		;Store local job number
	    RETSKP		;And done
	  ENDIF.
	  AOBJN T1,TOP.		;Look over them all
	ENDDO.
	SKIPE PASS1		;[7.1220] On pass 1?
	RET			;[7.1220] No, we already tried this
	MOVE T1,GBLCNT		;[7.1220] Get current count of jobs allocated
	CAIL T1,NJOBS		;[7.1220] Do we have enough jobs already?
	RET			;[7.1220] No, all done and no more jobs
	SETOM PASS1		;[7.1220] Flag pass 1 finishing up
	NOINT			;[7.1220] Not interruptable while grabbing resources
	CALL CFSGJB		;[7.1220] (/) Try to get some more jobs
	OKINT			;[7.1220] Can be interrupted now.
	JRST JBGET2		;[7.1220] Now see if we can assign a global job

	ENDSV.			;[7.1220]
	SUBTTL	Global Job Number Routines -- GL2LCL (Return local job number)

;Routine to return the local job number for a global job number.
;	T1/ Global job number
;Returns:	+1 not a local job. T1/ Error code
;		+2 T1/ local job number
;
;Note:	This routine is also called by Non-CFS monitors, since they
;	depend upon it to check the range of the job number supplied.

GL2LCL::SKIPN T1		;Job 0 always returns 0
	RETSKP
	SKIPL T1		;Must be positive
	CAILE T1,MXGLBS		;And must be within range
	RETBAD(GTJIX3)		;Invalid
	IFG. T1
	  ADJBP T1,GLBPTR	;Point to entry
	  LDB T1,T1		;Get the value
	  SKIPE T1		;SKIP if it's zero
	  CAILE T1,NJOBS	;SKIP if it's below the max.
	  RETBAD(GTJIX4)	;Illegal job number
	ENDIF.
	RETSKP			;Else, return the local job number
 	SUBTTL	Global Job Number Routines -- LCL2GL (Return global job number)

;Routine to return the Global Job number, given the local job number.
;Search the Global job number table serially, comparing each entry to
;the desired local job number.  This routine can be very slow, and not
;recommended unless absolutely necessary.
;
;	T1/	Local Job number
;Returns:	+1 No Global job assigned to this local index
;			T1/ Error code
;		+2 T1/ Global Job number
;

LCL2GL::SKIPN T1		;Local Job 0 is always Global Job 0
	RETSKP			;So return good
	CAIL T1,1		;Check for legal local index
	CAILE T1,NJOBS		;Like so
	IFNSK.			;If that didn't skip, job index is bad
	  BUG.(CHK,CFSILJ,CFSUSR,SOFT,<CFSSRV - Illegal Local Job Number>,,<

Cause:	LCL2GL as been called to convert a local job number to a global index,
	but the local job number is invalid.

Action:	If this problem is reproducible, set this BUGCHK dumpable and send in
	an SPR along with the dump and instructions on reproducing the problem.
>)
	  RETBAD(GTJIX3)	;Return error code for invalid job index
	ENDIF.
	SAVEP			;Save P registers.
	MOVE P1,T1		;Save requested local job number
	MOVSI P4,-MXGLBS	;Build counter
	MOVE P3,GLBPTR		;Get pointer to start of table
	DO.			;Loop through the table
	  MOVEI T1,1(P4)	;Get Current Global Job number in T1
	  ILDB P2,P3		;Get a table entry
	  CAIN P2,(P1)		;Does it match requested number?
	  RETSKP		;Yes.  Simply return
	  AOBJN P4,TOP.		;No, bump counter, and continue loop
	ENDDO.			;end of loop, job not found
	RETBAD(GTJIX4)		;Return 'No such job'.
	SUBTTL	Global Job Number Routines -- CFGTJB (Get jobs at system startup)

;[7.1220]
;CFGTJB/CFSGJB - Routine called to get a block of jobs for this system.
;CFGTJB is called at system startup to get the initial set of jobs and
;CFSGJB is called when all of those jobs are used up.
;
; Called with:
;	no arguments
;	CALL CFGTJB/CFSGJB
;
; Returns:
;	+1 - Always

CFSGJB:	SAVEQ			;[7.1220] Save work registers
	MOVEI Q2,1		;[7.1220] Only want one set of jobs
	JRST CFGTJ1		;[7.1220] Join common code
CFGTJB::SAVEQ			;Get some work regs
	MOVEI Q2,LCLPKT		;[7.1220] Number we need
CFGTJ1:	MOVSI Q1,-MXPKTS	;[7.1220] Max,,packet we are on
	DO.			;Loop
	  CALL CFSSPC		;Get some space
	   CALL CFSERR
	  MOVX T2,CFJBAS	;Assign job numbers
	  MOVEM T2,HSHROT(T1)	;Store root code
	  MOVX T2,.HTOEX	;Need exclusive
	  STOR T2,HSHTYP,(T1)	;Stash it	
	  HRRZM Q1,HSHQAL(T1)	;Store slot needed
	  SETZM T2		;No retry
	  CALL CFSGET		;Get it
	  IFSKP.		;If we got this one
	    MOVEI T1,JBPCKT	;[7.1220] This is how many jobs we got
	    ADDM T1,GBLCNT	;[7.1220] Account for this chunk
	    MOVEI Q3,0(Q1)	;Get slot
	    IMULI Q3,JBPCKT	;Jobs in a slot
	    HRLI Q3,-JBPCKT
	    DO.
	      HRRI T1,1(Q3)	;Get job number
	      CALL JBAVAL	;Make it available
	      AOBJN Q3,TOP.	;Do them all
	    ENDDO.
	    SOJLE Q2,R		;If all done, return
	  ENDIF.
	  AOBJN Q1,TOP.		;Try next slot
	ENDDO.
	RET			;Done
	SUBTTL	DIAG% JSYS Support -- CFDIAG (Code for Set CI Unavailable)

;Routine called from DIAG code when the CI is placed off-line. This
;routine closes all of the CFS connections.

	SWAPCD			;More JSYS support

CFDIAG::
   IFE CFSSCA,<RET>		;If nothing to do, don't do anything
   IFN CFSSCA,<			;If we might have something to do
	SAVEQ
	CFSLOK			;Lock everything up
	MOVSI Q1,-HSTSIZ	;Scan the table
	DO.
	  SKIPE CFSHST(Q1)	;Anybody here?
	  SKIPL CFHSTS(Q1)	;Yes, and opened?
	  IFSKP.		;If this is opened
	    BLCAL. (SC.DIS,<CFSHST(Q1),[0]>) ;Close it
	    IFNSK.
	      MOVE T3,T1	;Save error code
	      MOVE T1,CFSHST(Q1) ;Get connect ID
	      CALL SC.NOD	;(T1/T1,T2) Get node number
	      BUG.(CHK,CFCCLZ,CFSUSR,SOFT,<CFSSRV - Can't close CFS connection>,<<T2,NODE>,<T1,CID>,<T3,ERROR>>,<

Cause:	A "set CI offline" has been requested and SCA refuses to close a CFS
	connection.  The call to SC.DIS to disconnect from the remote node
	failed.  This may result in a CFRECN BUGHLT when the CI is put on-line.

Action:	It is unlikely that this can be caused by a software problem.  Field
	Service should run diagnostics on the CI20.  Field Service should make
	sure that you have up to date hardware (most recent link boards) in
	your CI20.  If this problem is reproducible, set this BUGCHK dumpable
	and send in an SPR along with the dump and instructions on reproducing
	the problem.

Data:	NODE  - node number of remote
	CID   - connect ID
	ERROR - error code returned by SCA
>)
	    ELSE.
	      MOVE T3,CFSHST(Q1) ;Get the connect ID
	      CALL PHYNOL	;Declare the disk's offline
	      SETZM CFSHST(Q1)	;It is closed
	      MOVE T1,CFHSTS(Q1)
	      SETZM CFHSTS(Q1)
	      SOS CFSHCT	;One less of this
	      TRNE T1,-1	;Full?
	      SOS CFSHCM	;Yes
	    ENDIF.
	    HRRZ Q2,Q1		;GET POSITION
	    ADD Q2,OLDTAB	; IN OLD CONNECTIONS TABLE
	    MOVE T1,CFSHNM(Q1)	;GET REMOTE SYSTEM'S SERIAL NUMBER
	    MOVEM T1,(Q2)	;SAVE IT
	  ENDIF.
	  AOBJN Q1,TOP.		;Do all of the table
	ENDDO.
	CALLRET CFSFAL		;And done
   >	;IFN CFSSCA
	SUBTTL	CNFIG% JSYS Support -- CFCIN (Return CFS information)

IFN CFSSCA,<

; CNFIG% JSYS SUPPORT ROUTINES FOR CFS
; THEY ALSO USE CNFIG% SUPPORT ROUTINES IN JSYSA.MAC
; THE FOLLOWING CONVENTIONS ARE USED FOR PRESERVED REGISTERS
;
;	Q1/ MONITOR BLOCK ADDRESS (ESTABLISHED IN THESE ROUTINES)
;	Q2/ USER BLOCK ADDRESS
;	Q3/ WORDS PROCESSED,,WORDS SUPPLIED

CFCIN::	TRVAR <<CFCINB,.CFCLN>>
	XMOVEI Q1,CFCINB	;Q1 POINTS TO MONITOR BLOCK
	MOVEI T1,.CFCLN
	CALL CFLNDO		;PROCESS .CFLEN
	MOVE T1,CFSHCT		;NUMBER OF OTHER CFS HOSTS UP
	ADDI T1,1
	MOVEM T1,.CFNCN(Q1)	;NUMBER OF CFS NODES
	SETZM T2
	LOAD T1,SCCNC		;GOT CONNECTED FLAG
	SKIPE T1
	TXO T2,CF%CFR		;NONZERO MEANS WE DID
	MOVEM T2,.CFCDO(Q1)	;DYNAMIC SOFTWARE OPTIONS
	CALL CFRET		;RETURN STUFF TO USER
	RETSKP
	ENDTV.
	SUBTTL	CNFIG% JSYS Support -- CFCSE (Return serial numbers of CFS nodes)

;RETURN SERIAL NUMBERS OF OTHER HOSTS UP

CFCSE::	TRVAR <<CFCSEB,MAXNDS+2>> ;MAX NUMBER OF OTHER HOSTS + OURS + .CFLEN
	XMOVEI Q1,CFCSEB	;ADDRESS OF MONITOR BLOCK
	MOVE T1,CFSHCT		;NUMBER OF OTHER HOSTS CURRENTLY UP
	ADDI T1,2		;PLUS US PLUS .CFLEN
	CALL CFLND2
	XMOVEI P1,.CFCS1(Q1)	; P1/ PLACE TO STORE SERIAL NUMBERS
	SETZM 0(P1)		;INITIALIZE TO ZEROS
	MOVE T1,APRSER		;APR SERIAL NUMBER IN RIGHT HALF
	STOR T1,CF%HSN,0(P1)	;STORE AWAY OUR SERIAL NUMBER
	CALL SC.PRT		;GET OUR CI NODE NUMBER
	 ERJMP .+1		;IGNORE ERRORS
	STOR T1,CF%CIN,0(P1)	;STASH IT
	ADDI P1,1

; HERE IS OUR MAIN LOOP TO GET THE SERIAL NUMBERS AND STASH THEM

	MOVEI P2,CFSHST		; P2/ PRESENCE TABLE
	MOVEI P3,CFHSTS		; P3/ ACTIVENESS TABLE
	MOVEI P4,CFSHNM		; P4/ SERIAL NUMBER TABLE
	MOVEI P5,HSTSIZ		; P5/ LOOP
	DO.
	  SKIPLE 0(P2)		;ANYTHING HERE?
	  SKIPL 0(P3)		;ANYTHING ACTIVE?
	  IFSKP.	
	    SETZM 0(P1)		;INITIALIZE TO ZEROS
	    MOVE T1,0(P4)	;GET SERIAL NUMBER
	    LSH T1,-4		;NORMALIZE
	    STOR T1,CF%HSN,0(P1) ;STASH IT
	    MOVE T1,0(P2)	;Get connect ID
	    CALL SC.NOD		;(T1/T1,T2) Get CI node number
	    STOR T2,CF%CIN,0(P1) ;Save CI node number
	    ADDI P1,1		;BUMP STASH POINTER
	  ENDIF.
	  ADDI P2,1		;BUMP ALL LOOP VARIABLES
	  ADDI P3,1
	  ADDI P4,1
	  SOJG P5,TOP.		;END WHEN WHOLE TABLE SEARCHED
	ENDDO.
	CALL CFRET		;RETURN STUFF TO USER SPACE
	RETSKP
	ENDTV.
	SUBTTL	CNFIG% JSYS Support -- CFCND (Return list of node names)

CFCND::	TRVAR <<CFCNDB,MAXNDS*3+4>>
	XMOVEI Q1,CFCNDB
	MOVE T1,CFSHCT		;NUMBER OF OTHER HOSTS CURRENTLY UP
	IMULI T1,3
	ADDI T1,4		;MAX WORDS RETURNABLE
	CALL CFLND2
	MOVE T1,CFSHCT
	ADDI T1,1
	STOR T1,CF%NND,.CFNND(Q1) ; SET NUMBER OF NODES
	XMOVEI P1,.CFBP1(Q1)	; P1/ PLACE TO STORE BYTE POINTERS
	XMOVEI P2,.CFBP1+1(Q1)
	ADD P2,CFSHCT		; P2/ PLACE TO STORE HOST NAMES
	MOVEI T3,.CFBP1+1(Q2)
	ADD T3,CFSHCT		; T3/ RUNNING ADDRESS FOR BYTE POINTERS
	HRR T1,T3
	HRLI T1,(POINT 7,)
	MOVEM T1,0(P1)		; STORE B.P. FOR OUR NAME
	ADDI P1,1		; BUMP POINTER
	ADDI T3,2
	DMOVE T1,OURNAM
	DMOVEM T1,0(P2)
	ADDI P2,2		; BUMP POINTER
; HERE IS OUR MAIN LOOP TO GET THE NAMES AND STATES AND STASH THEM

	MOVEI P3,CFSHST		; P3/ PRESENCE TABLE
	MOVEI P4,CFHSTS		; P4/ ACTIVENESS TABLE
	MOVEI P5,CFNNAM		; P5/ HOST NAME TABLE
	MOVEI T4,HSTSIZ		; T4/ LOOP
	DO.
	  SKIPLE 0(P3)		;ANYTHING HERE?
	  SKIPL 0(P4)		;ANYTHING ACTIVE?
	  IFSKP.	
	    HRR T1,T3
	    HRLI T1,(POINT 7,)
	    MOVEM T1,0(P1)	; STORE B.P. FOR OUR NAME
	    ADDI P1,1		; BUMP POINTER
	    ADDI T3,2
	    CALL ASC8T7		; COPY 0,1(P5) TO 0,1(P2) AND CONVERT
	    ADDI P2,2		; BUMP POINTER
	  ENDIF.
	  ADDI P3,1
	  ADDI P4,1
	  ADDI P5,2
	  SOJG T4,TOP.
	ENDDO.

	CALL CFRET
	RETSKP
	ENDTV.
; THE FOLLOWING CONVERTS 0,1(P5) FROM 8 TO 7 BIT ASCII
; AND STORES THE RESULT IN 0,1(P2)

ASC8T7::SAVET
	HRLI T1,(<POINT 8,0>)
	HRRI T1,0(P5)		; BYTE POINTER TO SOURCE
	HRLI T2,(<POINT 7,0>)
	HRRI T2,0(P2)		; BYTE POINTER TO DESTINATION
	SETZM 1(P2)		; ZERO DESTINATION NOT TOUCHED
	MOVEI T3,8		; COUNT, 8 BYTES

LOP8T7:	ILDB T4,T1		; THIS IS OUR COPY LOOP
	IDPB T4,T2
	SOJG T3,LOP8T7
	RET
>	;IFN CFSSCA
	SUBTTL End of CFSUSR

	END