; Edit= 9148 to CLUDGR.MAC on 21-Feb-90 by GSCOTT
;Update copyright date.
; Edit= 9105 to CLUDGR.MAC on 13-Jun-89 by WONG (TCO none)
;Prevent XBLTAL BUGHLTs from CLUFRK by always including the correct CI node
;number in the node change message.
; Edit= 9071 to CLUDGR.MAC on 21-Feb-89 by RASPUZZI
;Prevent RELRNG BUGCHKs and mysterious KLPPCB BUGHLTs by not releasing trashy
;freespace in INFCFG. Also, set up T1 with a freespace address before calling
;RELSWP.
; Edit= 9041 to CLUDGR.MAC on 13-Dec-88 by RASPUZZI
;Finish off some of the security features that were started at one time (like
;password expiration). Also, add new features to help a system manager secure
;the system.
; Edit= 9036 to CLUDGR.MAC on 15-Nov-88 by RASPUZZI
;Make sure that the system's name gets sent over during PHYKLP START/STACK/ACK
;sequence. Also, when the NODE% JSYS changes the name, have the local system
;notify remote systems. Finally, make CLUDGR send over the node name in the
;last 2 words of the optional connection data. I'm out of breath.
; Edit= 9027 to CLUDGR.MAC on 8-Nov-88 by LOMARTIRE
;Merge Production changes to BUG text
; Edit= 8972 to CLUDGR.MAC on 27-Sep-88 by RASPUZZI
;Place CLUEIN BUGINFs under CIBUGX. Heavy sigh over this SCA bug.
; Edit= 8964 to CLUDGR.MAC on 8-Sep-88 by RASPUZZI
;Add CLUDGR joining sequence to occur after CFSJYN has finished.
;Add CLUJYN routine to be called during system initialization. This routine
;will make sure that we have connected to all nodes lower than us.
; Edit= 8885 to CLUDGR.MAC on 12-Aug-88 by RASPUZZI
;Prevent CLUHST from filling up with stale entries by handling the -1 .SSPBC
;callback from SCA. Also, be CIOFF in CLUVAC.
; Edit= 8876 to CLUDGR.MAC on 10-Aug-88 by RASPUZZI
;Update BUG. documentation.
; Edit= 8867 to CLUDGR.MAC on 22-Jul-88 by RASPUZZI
;Make a mnemonic for 2*NFKS called MAXBUF.
; Edit= 8866 to CLUDGR.MAC on 21-Jul-88 by RASPUZZI
;Make the CLUDGR SYSAP correctly handle CLUBUF (SYSAP buffer count) and also
;make CLNEED handle little credit left situations.
; Edit= 8859 to CLUDGR.MAC on 12-Jul-88 by RASPUZZI
;Prevent ILFPTE BUGHLTs by using the correct AC in CHKSND.
; Edit= 8850 to CLUDGR.MAC on 31-May-88 by RASPUZZI
;Add code to do the TMON% version of .SFSEA and .SFLTS. Also, teach INFO% how
;it must handle ethernet addresses for .SFSEA between remote systems.
; Edit= 8825 to CLUDGR.MAC on 12-Apr-88 by RASPUZZI (TCO 7.1273)
;Prevent CLUDGR from waking up forks that are waiting for information from
;another system and not the crashing one. Sure, have another wine cooler.
; Edit= 8809 to CLUDGR.MAC on 23-Mar-88 by RASPUZZI (TCO 7.1262)
;Again, prevent XBLTAL BUGHLTs by having the local system send over the local
;system port number and not the destination port number.
; Edit= 8808 to CLUDGR.MAC on 22-Mar-88 by RASPUZZI
;Prevent XBLTAL BUGHLTs by making the interrupt level code bypass any requests
;that have CL%ALL set in their flag words.
; UPD ID= 8687, RIP:<7.MONITOR>CLUDGR.MAC.28, 17-Mar-88 19:27:37 by RASPUZZI
;TCO 7.1259 - Make call to LCLWAT scheduler test be right.
; UPD ID= 8678, RIP:<7.MONITOR>CLUDGR.MAC.27, 4-Mar-88 19:39:06 by RASPUZZI
;Fix mishandling of the SCA buffers when more than one comes in as a
;response for the CLRCVQ. This never worked. Also, clean up some gross
;code.
; UPD ID= 8672, RIP:<7.MONITOR>CLUDGR.MAC.26, 1-Mar-88 15:23:29 by RASPUZZI
;TCO 7.1247 - Add some DEBUG code to ensure that CLUID is used once.
; UPD ID= 8669, RIP:<7.MONITOR>CLUDGR.MAC.25, 26-Feb-88 08:50:26 by RASPUZZI
;Remove code that no longer has any meaning.
; UPD ID= 8668, RIP:<7.MONITOR>CLUDGR.MAC.24, 25-Feb-88 18:27:46 by RASPUZZI
;Make CLUID obtainment be one instruction.
; UPD ID= 8491, RIP:<7.MONITOR>CLUDGR.MAC.23, 9-Feb-88 12:17:58 by GSCOTT
;TCO 7.1218 - Insert copyright notice.
; UPD ID= 8461, RIP:<7.MONITOR>CLUDGR.MAC.22, 5-Feb-88 09:38:49 by GSCOTT
;TCO 7.1210 - Set CLDISC, CLUCON, and CLUNFE normally not dumpable.
; UPD ID= 8424, RIP:<7.MONITOR>CLUDGR.MAC.21, 4-Feb-88 13:24:59 by RASPUZZI
;TCO 7.1212 - Prevent ILMNRFs on remote systems by making sure that when
; this system can't make a request block, we tell the remote
; system there was an error here (light CL%ERR in PUNTIT).
; UPD ID= 8400, RIP:<7.MONITOR>CLUDGR.MAC.20, 2-Feb-88 14:55:34 by RASPUZZI
;TCO 7.1205 - Fix all IMCALLs for JSYSes that now exist in XCDSEC.
; UPD ID= 8387, RIP:<7.MONITOR>CLUDGR.MAC.19, 27-Jan-88 10:30:09 by GSCOTT
;TCO 7.1200 - GETRTL is now in XCDSEC.
; UPD ID= 306, RIP:<7.MONITOR>CLUDGR.MAC.18, 19-Nov-87 14:52:30 by RASPUZZI
;TCO 7.1141 - When ACJ denies an INFO% request, make sure we ITERR from
; section 1 right away.
; UPD ID= 304, RIP:<7.MONITOR>CLUDGR.MAC.17, 17-Nov-87 16:21:56 by RASPUZZI
;Fix problem in INFALO. Local test is not succeeding.
; UPD ID= 303, RIP:<7.MONITOR>CLUDGR.MAC.16, 17-Nov-87 13:51:53 by RASPUZZI
;User right test when checking for GALAXY jobs.
; UPD ID= 297, RIP:<7.MONITOR>CLUDGR.MAC.15, 14-Nov-87 11:52:42 by RASPUZZI
;When asking ACJ, use global job number.
; UPD ID= 279, RIP:<7.MONITOR>CLUDGR.MAC.14, 10-Nov-87 14:59:58 by RASPUZZI
;TCO 7.1121 - Move CLDISC, CLUCON and CLORBF under CIBUGX.
; UPD ID= 257, RIP:<7.MONITOR>CLUDGR.MAC.13, 5-Nov-87 14:42:58 by RASPUZZI
;TCO 7.1114 - Prevent ILMNRFs, KLPHOGs and various sundries of RELxxx BUGHLTs
; out of INFLNS because of improper free space useage.
; UPD ID= 238, RIP:<7.MONITOR>CLUDGR.MAC.12, 3-Nov-87 10:49:46 by RASPUZZI
;TCO 7.1105 - Make sure we use CLASSF instead AVALON for class scheduling
; UPD ID= 232, RIP:<7.MONITOR>CLUDGR.MAC.11, 29-Oct-87 16:05:08 by RASPUZZI
;TCO 7.1102 - Take out check for <SYSTEM>INFO in CHKPID.
; UPD ID= 229, RIP:<7.MONITOR>CLUDGR.MAC.10, 28-Oct-87 19:00:35 by RASPUZZI
;Add missing portions of TCO 7.1090 that I didn't REDIT in.
; UPD ID= 224, RIP:<7.MONITOR>CLUDGR.MAC.9, 28-Oct-87 14:16:31 by RASPUZZI
;TCO 7.1094 - Make sure .MSGSS of MSTR done through .INMSR returns the
; correct information in the user space. Also, don't trash
; user's byte pointers.
; UPD ID= 220, RIP:<7.MONITOR>CLUDGR.MAC.8, 28-Oct-87 10:26:38 by RASPUZZI
;TCO 7.1090 - ***PERFORMANCE*** Have the CLUDGR SYSAP send over the exact
; Amount of words to the remote system. Add another argument
; in the BLSUB. FILLIN.
; UPD ID= 198, RIP:<7.MONITOR>CLUDGR.MAC.7, 23-Oct-87 12:49:32 by RASPUZZI
;TCO 7.1080 - Make CHKGAL now recognize NEBULA as part of GALAXY
; UPD ID= 197, RIP:<7.MONITOR>CLUDGR.MAC.5, 22-Oct-87 18:20:48 by RASPUZZI
;More of TCO 7.1076 - Make CHKGAL use global job and not local job number
; UPD ID= 195, RIP:<7.MONITOR>CLUDGR.MAC.4, 22-Oct-87 08:26:32 by RASPUZZI
;More of TCO 7.1076 - Make SC.CON send connection data address
; UPD ID= 194, RIP:<7.MONITOR>CLUDGR.MAC.3, 22-Oct-87 08:17:50 by RASPUZZI
;More of TCO 7.1076 - Fix problem in .INMTO for local system
; UPD ID= 187, RIP:<7.MONITOR>CLUDGR.MAC.2, 21-Oct-87 17:31:40 by RASPUZZI
;TCO 7.1076 - Add CLUDGR SYSAP. This file contains connection management,
; JSYS support (INFO%, SMON%/TMON%, TTMSG%) and SCA buffer
; management.
; COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1988, 1990.
; 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.

;Note - We only need to check all CI nodes that are lower than us. Therefore,
;our loop counter starts at our node number and counts down to 0. This will
;save some looping time.
DO. ;Loop over all nodes
SOJL Q1,ENDLP. ;Step to next lowest CI node
SKIPN SBLIST(Q1) ;Is there a CI node here?
IFSKP. ;If so,
MOVE T2,Q1 ;Put node number in a good AC
CALLX (MSEC1,IS7020) ;(T2/) Is this TOPS-20, 7.0?
IFSKP. ;If so,
MOVEI Q2,CLUNOD ;Use this table to check on CID
ADD Q2,T2 ;Find node's place in the sun
SKIPE (Q2) ;Do we have a connect ID?
JRST TOP. ;Yes, do next node
CALL NEWCLU ;(T2/) No CID, establish a connection
NOP ;Ignore this. Error has been reported
SKIPE CIBUGX ;[8972] Wanna see this?
BUG.(INF,CLUEIN,CLUDGR,SOFT,<CLUDGR - Establishing initial connection>,<<Q1,NODE>>,<
Cause: This BUG. appears when the CLUDGR joining code stumbles on a CI node
that a CLUDGR connection has not been established for. CLUJYN then
attempts to make a CLUDGR connection to this node. Theoretically,
SCA should have notified CLUDGR of all nodes that are online. This
BUG. is simply telling you that one of them has been missed by SCA
and CLUDGR noticed it.
Action: CLUJYN will attempt to establish a connection to the missing node.
There is no manual intervention required.
Data: NODE - CI node that SCA didn't tell us about
>) ;Let someone know what we are doing
ENDIF.
ENDIF.
JRST TOP. ;Loop over all nodes
OD.
CION ;Turn this back on
RET ;And done

ENDDO. ;End of loop
BUG.(CHK,CLUNFE,CLUDGR,SOFT,<CLUDGR - No free entry in table>,,<
Cause: CLULSN was called to set up a CLUDGR listener for the local
system. However, this routine could not find a free entry in
the CLUHST table. This indicates a possible coding problem,
SCA malfunction, or an oversized cluster (possibly too many
KLs in the cluster).
Action: Check to see if there are more than the supported number of
KLs in the cluster. If so, remove the excess machines. If this
is not the cause and this problem becomes persistent, change
the BUGCHK to a BUGHLT and submit an SPR.
>,,<DB%NND>) ;[7.1210]
SETZ T1, ;Could not find an entry
RET

SUBTTL Connection Management -- BADSCA (Bad SCA callback)
;BADSCA - This routine is called by CL.SCA when SCA gives it a callback
;that it is not prepared to handle. It simply BUGCHKs and returns.
;
; Called with:
; T1/ Bogus SCA callback function code
; CALL BADSCA
;
; Returns:
; +1 - Always, with the CLUNKR BUGINF issued
XRESCD ;Called from PI level
BADSCA: BUG.(CHK,CLUNKR,CLUDGR,SOFT,<CLUDGR - Unknown callback, returning>,<<T1,CBACK>>,<
Cause: The CLUDGR SYSAP received an unexpected callback from SCA. It
was not prepared to handle this callback. Therefore, a BUGCHK
is issued and the monitor simply returns to SCA. This could be
due to a malfunction in SCA.
Action: If this BUGCHK occurs often, change it to a BUGHLT and submit
an SPR.
Data: CBACK - Callback function from SCA
>)
RET ;Back to the caller

SUBTTL Connection Management -- NEWCLU (New node in cluster)
;NEWCLU - Called when CL.SCA has a new node for us to check out. Connection
;is made only if the system has a lower CI node than ours.
;
; Call with:
; T2/ CI node number
; CALL NEWCLU
;
; Returns:
; +1 - Always
XRESCD ;Called from PI level
NEWCLU: CAML T2,MYPOR4 ;[8964] Should we try to talk to this guy?
RET ;No, he has a higher CI node than us
SAVEQ ;Don't trash good things
MOVE Q2,T2 ;Put node here.
CALLX (MSEC1,IS7020) ;(T2/) Do we want to talk to this node?
RET ;No, no chance he is running CLUDGR
MOVSI Q1,-HSTSIZ ;Make AOBJN pointer
CIOFF ;Turn CIOFF for now
DO.
SKIPN CLUHST(Q1) ;Is this entry free?
EXIT. ;Yes, use it.
AOBJN Q1,TOP. ;Do next entry
CION ;Turn CION
SETZM T1 ;Indicate no more entries in table
JRST NEWCL1
ENDDO.

CION ;Turn CI back on
MOVE T1,[POINT 7,OURNAM] ;[9036] Here's our node
MOVE T2,[POINT 8,CLUND1] ;[9036] And here's where we want it
DO. ;[9036] So let's move it!
ILDB T3,T1 ;[9036] Get a character
IDPB T3,T2 ;[9036] and spit it out
JUMPN T3,TOP. ;[9036] If not a null, continue upchucking
OD. ;[9036]
MOVE T2,Q1 ;Get table index back
BLCAL. (<XENT SC.CON>,<<.,CLUNAM>,<.,CLUNAM>,Q2,[SCRDIT],[RCRDIT],<.,CL.SCA>,T2,[CLUSET],[BUFINI],[0]>) ;Do connect
IFNSK.
NEWCL1: BUG.(CHK,CLULES,CLUDGR,SOFT,<No CLUDGR connection established with remote node>,<<T1,WHY>>,<
Cause: The call to SC.CON failed to allow this machine to establish a
CLUDGR connection with the remote machine or there are no more
entries in the CLUHST table.
Action: If this is due to no more entries in CLUHST (WHY=0) then there may
be too many systems in this cluster. If the cause is a failing
call to SC.CON (WHY<>0) and this problem becomes chronic then
change this to a BUGHLT and submit an SPR.
Data: WHY - 0 if CLUHST table is full or
Error code from call to SC.CON
>)
SETZM CLUHST(Q1) ;If failed, no longer listening
SETZM CLUSTS(Q1) ;And no status
RETBAD() ;Pass error back from SCA
ENDIF.
SETZM CLUSTS(Q1) ;Init status
MOVEM T1,CLUHST(Q1) ;Save CID in table
MOVX T1,CL%OPN ;Indicate connection becoming open...
IORM T1,CLUSTS(Q1) ;...for this system
MOVEI T1,BUFINI ;Note that CLUDGR just queued up buffers
ADDM T1,CLUBUF ;By adding the count to the buffer count word
ADDM T1,CLUSTS(Q1) ;Say how many buffers in use by this connection
MOVEI T1,MAXBUF ;[8867] Get max buffers for this CID
ADDM T1,BUFMAX ;[8866] And add to overall max count
RETSKP ;Done

; ...
;Here when buffer must go on CLREQQ or CLRCVQ
MOVE T1,CLDFLG(T3) ;Get flags
TXNE T1,CL%REQ ;Is this a request for us to work?
CALLRET PUTREQ ;Yes, put it on CLREQQ
MOVE T1,CLRCVQ ;Get first entry in receive queue
DO. ;Loop over all entries until we find ours
JUMPE T1,ENDLP. ;Is there another entry?
LOAD Q1,REQNUM,(T1) ;Get request number for this block
LOAD Q2,.CLREQ,(T3) ;Get request number this SCA buffer belongs to
CAME Q1,Q2 ;Are they the same
IFSKP. ;Yes,
SKIPE Q1,REQSCA(T1) ;Follow SCA buffer chain
IFSKP. ;If no chain,
MOVEM T3,REQSCA(T1) ;Make this the first SCA buffer
JRST GOTCL1 ;And go on
ENDIF. ;If so, then follow SCA buffer chain
DO. ;Until the last one is reached
SKIPN Q2,.CLFLI(Q1) ;Is there more to look at?
EXIT. ;No, we have reached the end of the chain
MOVE Q1,Q2 ;Save last buffer looked at
JRST TOP. ;And follow it
ENDDO. ;Chain followed
MOVEM T3,.CLFLI(Q1) ;Tack this buffer on the end of the chain
GOTCL1: LOAD Q1,.CLPKT,(T3) ;Get position in buffer chain
LOAD Q2,.CLTPK,(T3) ;Get count of total expected in chain
CAME Q1,Q2 ;Is this the last packet?
IFSKP. ;Yes,
MOVE Q1,CLDFLG(T3) ;Get flag word
TXNE Q1,CL%ERR ;Was there an error on remote?
SKIPA Q1,[CL%ALL!CL%RER] ;Yes, the gang's all here with an error
MOVX Q1,CL%ALL ;Say all buffers here for this request
IORM Q1,REQFLG(T1);Set it up
ENDIF.
RET ;Finished, go back
ENDIF.
;Here when we must move to next entry in the CLRCVQ
MOVE T1,REQFLK(T1) ;Get next entry in receive queue
JRST TOP. ;And go process it
ENDDO.
SKIPE CIBUGX ;[7.1121] Crash if debugging
BUG.(INF,CLORBF,CLUDGR,SOFT,<Orphaned buffer received by CLUDGR>,,<
Cause: The CLUDGR SYSAP received an SCA buffer from a remote system
but it could not find a request to associate it with. Somehow,
the request block dissappeared. This could be due to a cluster
state transition.
>) ;[7.1121] Could not find request
SETZ T2, ;[7.1121] No connect ID
MOVE T3,Q1 ;[7.1121] Get SCA buffer here
CALLRET GIVBCK ;[7.1121] (T2,T3/) Give it back to SCA

;Here when an SCA buffer has arrived for the CLUDGR fork. Make
;an entry in the CLREQQ if necessary. Otherwise, put this buffer
;in the existing entry and wake up the CLUDGR fork when all buffers
;have arrived for the request.
PUTREQ: MOVE T1,CLREQQ ;Get first entry in request queue
XMOVEI Q1,CLREQQ ;Remember where we started
DO. ;Loop over all entries until we find ours
JUMPE T1,ENDLP. ;Is there another entry?
LOAD Q1,REQFLG,(T1) ;[8808] Get request flags
TXNE Q1,CL%ALL ;[8808] All here for this request?
JRST PUTRQ1 ;[8808] Yes, skip to next entry
LOAD Q1,.RQNOD,(T1) ;Get node number
LOAD Q2,.CLNOD,(T3) ;Get node number of request
CAME Q1,Q2 ;Are they the same?
JRST PUTRQ1 ;No, don't bother checking request ID
;Nodes match, make sure it is the correct request ID.
LOAD Q1,REQNUM,(T1) ;Get request number for this block
LOAD Q2,.CLREQ,(T3) ;Get request number this SCA buffer belongs to
CAME Q1,Q2 ;Are they the same
IFSKP. ;Yes,
MOVE Q1,REQSCA(T1) ;Follow SCA buffer chain
;At this point, there should be a request block and at least one SCA
;buffer hanging off it. This is true because the request block is made
;when the first SCA buffer arrives.
DO. ;Until the last one is reached
JUMPE Q1,ENDLP. ;Are we there yet?
MOVE Q2,Q1 ;Save last buffer looked at
MOVE Q1,.CLFLI(Q1);Get next buffer in chain
JRST TOP. ;And follow it
ENDDO. ;Chain followed
MOVEM T3,.CLFLI(Q2) ;Tack this buffer on the end of the chain
LOAD Q1,.CLPKT,(T3) ;Get position in buffer chain
LOAD Q2,.CLTPK,(T3) ;Get count of total expected in chain
CAME Q1,Q2 ;Is this the last packet?
IFSKP. ;Yes,
MOVX Q1,CL%ALL ;Say all buffers here for this request
IORM Q1,REQFLG(T1);Set it up
AOS CLUFLG ;Now wakeup CLUDGR fork
ENDIF.
RET ;Finished, go back
ENDIF.
;Here when we must move to next entry in the CLREQQ
PUTRQ1: MOVE Q1,T1 ;Save previous block in case new one needs to be made
MOVE T1,REQFLK(T1) ;Get next entry in receive queue
JRST TOP. ;And go process it
ENDDO.

;Here when insufficient resources to make new request block. Check to
;see if this packet is 1 of N. If it is not, then just toss it. If it
;is the first one, then tell remote node we have insufficient system
;resources.
PUNTIT: MOVE T3,Q2 ;Get SCA buffer back
MOVE T2,Q3 ;Get connect ID
LOAD T1,.CLPKT,(T3) ;Get this packet's number
CAIE T1,1 ;Is it the first one of N?
CALLRET GIVBCK ;No, pitch it
STOR T1,.CLTPK,(T3) ;Say response will be 1 of 1
MOVX T1,CL%REQ ;This is not a request for the remote node
ANDCAM T1,CLDFLG(T3) ;So turn off the request bit
MOVX T1,CL%ERR ;[7.1212] We had a remote error
IORM T1,CLDFLG(T3) ;[7.1212] Flag it so
MOVEI T1,INFX08 ;Send this error code back
MOVEM T1,CLDATA(T3) ;Place in buffer
MOVEI T1,<CLDATA-CLDFUN>;Get offset to data
STOR T1,.CLPTR,(T3) ;And tell remote system where it is
BLCAL. (<XENT SC.SMG>,<T2,[F.RTB+F.SPM],[CLDATA+1],T3,[CLUPRI],[0],[0]>) ;[7.1090]
NOP ;Don't care about failure
RET ;Now wait for response

SUBTTL Buffer Management -- CLUCRD (Credit is available)
;CLUCRD - This routine is called when a remote system has indicated
;that it has queued up some buffers. If a fork was trying to send to
;this system, it was failing because of little credit available over
;on that node. That node has just indicated that it has credit.
;
; Call with:
; T2/ Connect ID
; T3/ Current send credit
; T4/ Current receive credit
; CALL CLUCRD
;
; Returns:
; +1 - Always
XRESCD ;Called at PI level by SCA
CLUCRD: LOAD T1,SID,T2 ;Get index into CLUSTS table
MOVX T2,CL%LCL ;Little credit left on this node?
ANDCAM T2,CLUSTS(T1) ;Not any more. Let forks push on, McDuff.
RET ;This is a quickie

SUBTTL Buffer Management -- CLNEED (CLUDGR needs buffers)
;CLNEED - Routine called by CL.SCA when it notices that the CLUDGR SYSAP
;is getting low on queued buffers.
;
; Call with:
; T2/ Connect ID
; T3/ Minimum buffers to get over threshold
; CALL CLNEED
;
; Returns:
; +1 Always, with (hopefully) BUFQUE more buffers queued up
XRESCD ;Called by PI code
CLNEED: MOVE T3,CLUBUF ;[8866] Get SYSAP buffer count
CAMG T3,BUFMAX ;[8866] Is it less than the max?
IFSKP.
BUG.(CHK,CLABIU,CLUDGR,SOFT,<CLUDGR - All buffers in use>,<<T2,ID>,<T3,BUF>>,<
Cause: The CLUDGR SYSAP is only allowed to use 2*NFKS buffers per CID.
When it reaches this limit, it cannot queue up anymore. The CLUDGR
fork is supposed to return buffers when it is done with them. Also,
any user process that uses SCA buffers is supposed to return them.
This BUGCHK is telling you that all buffers are in use by the
CLUDGR SYSAP.
Action: Determine who is using up all of the SCA buffers.
Data: ID - Connect ID using lots of buffers
BUF - Number of buffers in use by this CID
>)
RET ;Simply return with no more queued up
ENDIF.
MOVEI T4,BUFQUE ;Get count we are going to increase CID by
ADDM T4,CLUSTS(T1) ;Keep track of how many going to this CID
ADDM T4,CLUBUF ;Also, update overall SYSAP usage
BLCAL. (<XENT SC.RMG>,<T2,[BUFQUE],[0]>) ;Queue up some buffers
NOP ;SCAMPI told the CTY about problems already
RET ;Back to the future

MOVSI Q3,-HSTSIZ ;This is our loop counter
CIOFF ;No annoyances while we check the table
DO. ;Loop over all nodes
SKIPG T1,CLUHST(Q3) ;Get connect ID for this node
IFSKP. ;If this is a valid entry,
CALL <XENT SC.NOD> ;(T1/T1,T2) Get node number
CAIE T1,SCSIID ;Invalid connect ID?
IFSKP. ;If so,
SETZM CLUHST(Q3) ;Say this is not here no more
SETZM CLUSTS(Q3) ;And this too
JRST INFCN1 ;Proceed to the next entry
ENDIF.
MOVEM T2,CURNOD ;Save current node
MOVE T1,T2 ;Find out if its OK to do this node
CALL INFALO ;(T1/T1) See if INFO%'s allowed on this node
JRST INFCN1 ;Not allowed, so we don't give this back to user
MOVE T1,CURNOD ;Get current node back
XCTU [HRRZM T1,(Q1)] ;Give this node number to user
AOS Q1 ;Bump past this memory location to next one
AOS Q2 ;Increment our running counter
ENDIF.
INFCN1: AOBJN Q3,TOP. ;Do next node
ENDDO.
CION ;Allow interrupts
MOVE T1,INFARG ;Get INFO% arg block back
UMOVE T1,.INAC1(T1) ;This is where we have to store the count
UMOVEM Q2,(T1) ;Give count of how many words we returned
SETZ T1, ;Indicate no error happened
RETSKP ;And go back to caller
ENDSV.

EXCH T1,CFGFSP ;Save one free space and return the other
MOVEM T2,CFGLEN ;Save free space length too
MOVEI T2,2 ;This is how long the other free space was
CALLX (MSEC1,RELSWP) ;(T1,T2/) Return our sent block
MOVE T2,CFGLEN ;Get returned length
CAIE T2,1 ;Did we just get one word back from remote?
IFSKP. ;If so, then we had an error
MOVE T1,CFGFSP ;[9071] Get back freespace block that has error
MOVE Q1,(T1) ;Get error code from remote system
CALLX (MSEC1,RELSWP) ;(T1,T2/) Give back the error code free space
OKINT ;Interruptions are OK now
TXO Q1,IN%RER ;Make sure error shows up
MOVE T1,Q1 ;Put error code in T1
RETSKP ;But take good return
ENDIF.
MOVE T1,CFGFUN ;Get function we just did

;At this point we will have to get the device designator or the byte
;pointer to the structure name. If it is a byte pointer, then we must
;copy the structure name to monitor space and pass it over to other
;system.
MOVE T1,UMSBLK ;Get user's MSTR% block
UMOVE T2,(T1) ;Get first word of block
TLNN T2,-1 ;Device designators don't have left half
JRST INFMS1 ;It is a device designator
MOVE T1,MSBLK ;Get our free space block
SETOM .INMAX(T1) ;Indicate that a byte pointer is going after the argument block
ADDI T1,<.MSRLN+.INMAX> ;We want this address for CPYFU6
MOVEI T3,MAXLC ;No more than this many characters
SETO T4, ;Don't trim this please
CALLX (MSEC1,CPYFU6) ;(T1-T4/T1-T4) Copy the user's string please
NOP ;We never return here
MOVE T1,MSFUN ;Get function back
CAIE T1,.MSGSS ;If this function, then still another byte pointer!
JRST INFMS1 ;Not this function, go on
MOVE T1,MSLEN ;Get user's MSTR% block length
CAIGE T1,.MSGLN ;Is it at least this long?
JRST INFMS1 ;No, then he doesn't want physical name
MOVE T1,MSBLK ;Get address of block we are sending
ADDI T1,<.INMAX+.MSGLN> ;This is where the physical name byte pointer is
SETOM (T1) ;Let remote know we need this
; JRST INFMS1 ;Go on

SUBTTL INFO% -- CL.ENT (Entry point to CLUDGR from user level)
;CL.ENT - Called when it is time to send a request to a remote system
;to do work. The current process will block until a response is received.
;
; Called with:
; T1/ Function code
; T2/ SCA buffer flags,,CI node to send to
; T3/ Address of data to be sent in monitor space or user space
; T4/ Length of block specified in T3
; CALL CL.ENT if T3 is user space
; or
; CALL CL.EN1 if T3 is monitor space
;
; Returns:
; +1 - Error, could not send to remote system
; T1/ Error code
; +2 - Success, data sent and response received
; T1/ Free space address with response
; T2/ Number of words in free space
;
;Note: caller must call RELSWP to get rid of the free space. Also,
;must be called NOINT to prevent free space lossage.
XSWAPCD ;Process context bro'
CL.ENT::SAVEPQ ;[7.1090] We love these scratch registers
STKVAR <USER,FUNC,FLAGS,CINOD,SENDAT,SENLEN,RETADR,CL.CID> ;Must be same as below
SETOM USER ;Flag we are user space
JRST CL.EN2 ;And join common code
CL.EN1::SAVEPQ ;[7.1090] We love these scratch registers
STKVAR <USER,FUNC,FLAGS,CINOD,SENDAT,SENLEN,RETADR,CL.CID> ;Same as CL.ENT!
SETZM USER ;Flag we have monitor space

MOVEM T1,CL.CID ;Save its connect ID here
LOAD T1,SID,CL.CID ;Get index into status table
MOVE T2,CLUSTS(T1) ;Get the status on this node
TXNE T2,CL%LCL ;Can we send to this node?
RETBAD (INFX16) ;Say not enough credit to send
NOSKED ;Don't let anyone else in yet
AOS Q3,CLUID ;Increment our INFO% id counter
IFN DEBUG,< ;[7.1247] If debugging,
CAMG Q3,PREVID ;[7.1247] Are we still increasing?
BUG.(HLT,CLUFUD,CLUDGR,SOFT,<CLUDGR - Found Used Id>,,<
Cause: Each request made to a remote system is supposed to be unique.
Unfortunately, the monitor has found that more than one person
is using the same unique ID code from the same system. This is
an illegal case and is only detected with DEBUGging code turned
on.
>) ;[7.1247] Used this twice!
MOVEM Q3,PREVID ;[7.1247] Save the newest old CLUID
> ;[7.1247]
OKSKED ;It's OK now to have someone else use CLUID

SUBTTL INFO% -- REMQ (Remove from receive queue)
;REMQ - Routine called to remove an entry from the CLRCVQ. Must
;be called with CIOFF!
;
; Called with:
; T1/ address of REQ block
; CALL REMQ
;
; Returns:
; +1 - Always, with block removed from CLRCVQ and given
; back to free space with CI still OFF
XSWAPCD ;JSYS code
REMQ: XMOVEI T3,CLRCVQ ;Get start of queue
DO. ;Loop over entire CLRCVQ
CAME T1,REQFLK(T3) ;So remove entry from CLRCVQ while still CIOFF
IFSKP. ;Found the entry
MOVE T2,REQFLK(T1) ;Get next one after us
MOVEM T2,REQFLK(T3) ;And make it the next one in the queue
EXIT. ;Now release SCA buffers
ENDIF.
MOVE T3,REQFLK(T3) ;Get next entry in receive queue
JRST TOP. ;And check it
ENDDO.
XCALLRET (MSEC1,RELRES) ;(T1/) Give it back to the system

SUBTTL INFO% -- CHKGAL (Check to see if we are GALAXY)
;CHKGAL - Routine that is called to check and see if the current
;job is part of the GALAXY subsystem. This routine bases the
;decision on what PIDs are being used by this job (IPCF PIDs)
;and the system PIDs in SPIDTB.
;
; Call with:
; no arguments
; CALL CHKGAL
;
; Returns:
; +1 - Error, job is not a GALAXY job
; +2 - Job is part of GALAXY
;Clobbers no ACs!!
XSWAPCD
CHKGAL::SAVET ;Preserve work registers
STKVAR <ARGBLK,WRDCNT,ERROR> ;Temp storage
MOVE T2,JOBNO ;Get the current job number
LOAD T1,PIDPC,(T2) ;Get PID count for this job
JUMPE T1,R ;If zero, than this can't be a GALAXY job
LSH T1,1 ;Need 2*PID_COUNT+4 words of free space
ADDI T1,4 ;Make sure we have enough words
MOVEM T1,WRDCNT ;Save free space length here
;Count of free space words is now in the right of T1.
NOINT ;Prevent free space lossage
HRLI T1,.RESP3 ;Put priority in left half of T1
MOVEI T2,.RESGP ;Get free space from the general pool
CALLX (MSEC1,ASGRES) ;(T1,T2/T1) Get free space
IFNSK. ;If failure,
OKINT ;Go OKINT
JRST CHKGL3 ;Couldn't get free space, trouble
ENDIF.
MOVEM T1,ARGBLK ;Save address of this free space
MOVEI T2,.MUFJP ;Get all PIDs for this job
MOVEM T2,(T1) ;Save MUTIL% function in arg block
MOVE T2,GBLJNO ;Get global job number
MOVEM T2,1(T1) ;And put it in second word of arg block
MOVE T1,WRDCNT ;Get arg block length for MUTIL%
MOVE T2,ARGBLK ;Put address of arg block here
MUTIL% ;Do MUTIL%
IFNSK. ;If failed,
MOVEM T1,ERROR ;Save error code
MOVE T1,ARGBLK ;Free space to give back
CALL CHKG21 ;(T1/) Return free space and go OKINT
MOVE T1,ERROR ;Get JSYS error code back
JRST CHKGL3 ;MUTIL% failed us
ENDIF.
CHKGL1: ADDI T2,2 ;Every second word is a PID
SKIPN T1,(T2) ;No more PIDs?
CALLRET CHKGL2 ;All done, no match
CALL CHKPID ;(T1/) See if this PID is of the GALAXY persuasion
JRST CHKGL1 ;It wasn't, do next PID
MOVE T1,ARGBLK ;Now you see the free space...
CALLX (MSEC1,RELRES) ;(T1/) And now you don't
OKINT ;Interrupts are once again copacetic
RETSKP ;And get back to the caller

CHKGL2: MOVE T1,ARGBLK ;Return the free space
CHKG21: CALLX (MSEC1,RELRES) ;(T1/) Do it
OKINT ;Free space gone, ^C if you dare
RET ;Back to the caller
CHKGL3: BUG.(CHK,GALCHF,CLUDGR,SOFT,<GALCHK failed>,<<T1,ERROR>>,<
Cause: The call to GALCHK failed because GALCHK could not get
enough free space from the system pool to do an MUTIL%
JSYS or the call to MUTIL% failed. Therefore, it could
not verify whether or not this job was part of GALAXY.
Action: If this BUGCHK appears, use the DOB% facility to take a
dump and submit an SPR about this problem.
Data: ERROR - Error code returned from MUTIL% or ASGRES.
>)
RET ;And go back to caller
ENDSV.

SUBTTL INFO% -- CHKPID (Check for GALAXY PID)
;CHKPID - Routine called to see if the given PID belongs to
;a GALAXY component. A GALAXY component is considered to be
;one of the following processes:
; <SYSTEM>INFO, QUASAR, ORION, MOUNTR, NEBULA
;
; Call with:
; T1/ PID
; CALL CHKPID
;
; Returns:
; +1 - Given PID is not a GALAXY PID
; +2 - Given PID is a GALAXY PID
;Clobbers no ACs
XSWAPCD
CHKPID: SAVEAC <T2> ;Save used ACs
XMOVEI T2,SPIDTB ;Here's where the system PIDs are
;[7.1102]
;Note - the following code has been repeat 0'ed out. This is because
;the system going down message comes from the CHKR fork and since
;<SYSTEM>INFO runs under job 0, this is considered GALAXY and hence,
;there is no way to stop the system going down message from appearing
;on other systems. If <SYSTEM>INFO ever does INFO%'s or sends, this
;code must be put back.
REPEAT 0,< ;Don't let job 0 do this
CAMN T1,.SPINF(T2) ;Is this <SYSTEM>INFO?
RETSKP ;Yes
> ;End repeat 0
CAMN T1,.SPQSR(T2) ;Is it QUASAR?
RETSKP ;That it is
CAMN T1,.SPMDA(T2) ;Is it MOUNTR?
RETSKP ;Yes
CAMN T1,.SPOPR(T2) ;How about ORION?
RETSKP ;Yes
CAMN T1,.SPNEB(T2) ;Is it NEBULA?
RETSKP ;Yes
RET ;It is not a GALAXY function at all
ENDTV. ;For INFO%'s TRVAR

;Note - the following code may seem a little out of the ordinary but if
;you knew what I went through to realize it must be as is, you can appreciate
;it. Basically, TTMSG%'s routine GETSAL that makes a sendall buffer has a
;slight crock in that it pads each linefeed in the string with 4 nulls.
;The following loop attempts to remove these when sending a string over
;to a remote system and have it do a sendall for us. It appears that these
;4 nulls were stuck in because of slow devices many years ago (like teletype
;33s) and these nulls were used as padding for when the rubber band was yanking
;the type writer ball back after doing a CRLF. These 4 nulls apparently were
;enough to prevent further output in that time frame. Yuk. Also, the loop
;strips off the parity that GETSAL may have stuck on because we don't need
;parity right now.
MOVE T1,REMMSG ;Here's the free space
AOS T1 ;Start here
TXO T1,<OWGP. 7> ;Make one-word global byte pointer
MOVE T2,MSG ;Here's our send all stuff
HRLI T2,(POINT 9,) ;Would you believe they are in 9-bit
SETZ P2, ;Indicate CR not seen yet
DO. ;Loop over each character
ILDB T3,T2 ;Get a send all byte
ANDI T3,177 ;Strip off that parity
IDPB T3,T1 ;Save byte in send all string
CAIE T3,.CHCRT ;<CR> seen?
IFSKP. ;If so,
SETO P2, ;Say we have finally seen a CR
JRST TOP. ;And do next character
ENDIF.
CAIE T3,.CHLFD ;<LF> seen?
IFSKP. ;If so,
IFL. P2 ;Was <CR> previously seen?
MOVEI T4,4 ;Adjust the byte pointer by 4 bytes
ADJBP T4,T2 ;Skip over the 4 nulls
MOVE T2,T4 ;Now get the updated byte pointer back
ENDIF.
ENDIF.
CAIN T3,.CHNUL ;Was it a legitimate null?
EXIT. ;Yes, then we have done our duty
SETZ P2, ;Was normal character, reset <CR> flag
JRST TOP. ;Do more fun stuff
ENDDO.
HRRE T1,TONODE ;Get CI node
JUMPGE T1,CLTMS1 ;Doing all nodes or just one?
MOVEI P2,<C%SBLL-1> ;This is max CI nodes
DO. ;Loop over all nodes
CALL SC.PRT ;(/T1) Get our port number
RETBAD () ;Can't do remote sends with out a port
CAMN T1,P2 ;Is this our node?
JRST CLTMS2 ;Yes, can't send to self through port