Google
 

Trailing-Edge - PDP-10 Archives - BB-M080O-SM - monitor-sources/cfssrv.mac
There are 21 other files named cfssrv.mac in the archive. Click here to see a list.
; *** Edit 7507 to CFSSRV.MAC by RASPUZZI on 29-Jul-87 (TCO 7.1029)
; Prevent CFCTNF BUGHLTs.
; *** Edit 7492 to CFSSRV.MAC by MCCOLLUM on 16-Jun-87, for SPR #21459
; Make CFMDSN fail if the DSN specified already exists for a different
; structure 
; *** Edit 7464 to CFSSRV.MAC by LOMARTIRE on 29-Apr-87, for SPR #21438
; Rework CFS structure tokens and structure create/mount handling 
; *** Edit 7445 to CFSSRV.MAC by LOMARTIRE on 13-Apr-87, for SPR #21307
; Use correct algorithm in CFCNCK to determine an open connection 
; *** Edit 7348 to CFSSRV.MAC by LOMARTIRE on 1-Aug-86
; Prevent OPNX9 errors from stale ENQ tokens remaining on system 
; *** Edit 7330 to CFSSRV.MAC by LOMARTIRE on 27-Jun-86, for SPR #21275
; Prevent CFSTUC BUGHLTs 
; *** Edit 7315 to CFSSRV.MAC by LOMARTIRE on 11-Jun-86, for SPR #21144
; Prevent OPNX9 from ENQ tokens remaining after STRTAB is zeroed - for SPR
; 21144A 
;------------------------- Autopatch Tape # 13 -------------------------
; *** Edit 7247 to CFSSRV.MAC by LOMARTIRE on 19-Feb-86
; Implement OFN caching 
;Edit 7247 - Implement file access token caching portion of OFN caching
; *** Edit 7211 to CFSSRV.MAC by GRANT on 18-Dec-85
; Add CI counters for WATCH 
;------------------------- Autopatch Tape # 12 -------------------------
; Edit 7152 to CFSSRV.MAC by GRANT on 15-Oct-85
; Don't BUGHLT if there are more than 4 KLs in the cluster. 
;	Remove check against CFSMAX when making a connection.
; Edit 7144 to CFSSRV.MAC by LOMARTIRE on 10-Sep-85 (TCO 6-1-1534)
; Make sure that CFS connects only to TOPS-20 hosts 
; UPD ID= 2324, SNARK:<6.1.MONITOR>CFSSRV.MAC.380,   5-Sep-85 09:59:41 by LOMARTIRE
;TCO 6.1.1535 - Fix CFSBEF to use the correct transaction number
; UPD ID= 2278, SNARK:<6.1.MONITOR>CFSSRV.MAC.379,  25-Jun-85 14:58:36 by GRANT
;TCO 6.1.1473 - In CFSJYN, check for node in maintenance state
; UPD ID= 2110, SNARK:<6.1.MONITOR>CFSSRV.MAC.378,   3-Jun-85 16:14:30 by LOMARTIRE
;TCO 6.1.1374 - Make the delay time a function of the number of nodes on CI
; UPD ID= 2055, SNARK:<6.1.MONITOR>CFSSRV.MAC.376,   3-Jun-85 14:19:48 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 1998, SNARK:<6.1.MONITOR>CFSSRV.MAC.375,  23-May-85 14:27:36 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1995, SNARK:<6.1.MONITOR>CFSSRV.MAC.374,  21-May-85 12:32:12 by LOMARTIRE
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1960, SNARK:<6.1.MONITOR>CFSSRV.MAC.373,  13-May-85 09:15:29 by LOMARTIRE
;TCO 6.1.1375 - Add missing index register in BRDTIM
; UPD ID= 1867, SNARK:<6.1.MONITOR>CFSSRV.MAC.372,   4-May-85 10:53:46 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1809, SNARK:<6.1.MONITOR>CFSSRV.MAC.371,  24-Apr-85 14:23:31 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1783, SNARK:<6.1.MONITOR>CFSSRV.MAC.370,  23-Apr-85 12:30:13 by MCCOLLUM
;TCO 6.1.1238 - Fix typos in BUG. documentation
; UPD ID= 1778, SNARK:<6.1.MONITOR>CFSSRV.MAC.369,  22-Apr-85 23:12:56 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1763, SNARK:<6.1.MONITOR>CFSSRV.MAC.368,  17-Apr-85 14:01:57 by LOMARTIRE
;TCO 6.1.1327 - Prevent PITRAPs by locking down correct page in CFCARV
; UPD ID= 1722, SNARK:<6.1.MONITOR>CFSSRV.MAC.367,   8-Apr-85 10:43:07 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 1644, SNARK:<6.1.MONITOR>CFSSRV.MAC.366,  18-Mar-85 08:10:55 by GRANT
;More TCO 6.1.1245 - minor enhancements
; UPD ID= 1623, SNARK:<6.1.MONITOR>CFSSRV.MAC.365,  12-Mar-85 15:56:34 by LOMARTIRE
;TCO 6.1.1247 - Improve CFSJYN and update table of contents
; UPD ID= 1615, SNARK:<6.1.MONITOR>CFSSRV.MAC.364,  11-Mar-85 09:57:31 by GRANT
;TCO 6.1.1245 - Add routines CFCBRD, CHKCLC, and CFCEAS for ^ECEASE protocol
; UPD ID= 1548, SNARK:<6.1.MONITOR>CFSSRV.MAC.363,  20-Feb-85 15:26:11 by LOMARTIRE
;TCO 6.1.1200 - Add the CFSDSN routine to handle a swap of a DSN on a DSA disk
; UPD ID= 1533, SNARK:<6.1.MONITOR>CFSSRV.MAC.362,  19-Feb-85 10:33:12 by LOMARTIRE
;TCO 6.1.1207 - Calculate HSHCOD correctly in CFRDSN
; UPD ID= 1531, SNARK:<6.1.MONITOR>CFSSRV.MAC.361,  19-Feb-85 10:10:33 by LOMARTIRE
;TCO 6.1.1194 - Return an error number when returning a no vote response.
; Have the requesting side interpret this number and form a TOPS-20 error code.
; UPD ID= 1447, SNARK:<6.1.MONITOR>CFSSRV.MAC.360,   1-Feb-85 14:17:26 by LOMARTIRE
;Add new symbols to describe the priority used by SC.SMG
; UPD ID= 1440, SNARK:<6.1.MONITOR>CFSSRV.MAC.359,  31-Jan-85 16:14:56 by MOSER
;TCO 6.1.1166 - *PERFORMANCE* - OFN MANAGEMENT - CANNOT USE MAXSPL ANYMORE
; UPD ID= 1405, SNARK:<6.1.MONITOR>CFSSRV.MAC.358,  25-Jan-85 09:35:11 by WAGNER
;TCO 6.1.1155 - *PERFORMANCE* - Change HSHLEN to be Prime
; UPD ID= 1350, SNARK:<6.1.MONITOR>CFSSRV.MAC.357,  16-Jan-85 16:43:02 by MOSER
;TCO 6.1.1139 - *PERFORMANCE* - CHANGE PSKED REFS TO PSKD1
; UPD ID= 1285, SNARK:<6.1.MONITOR>CFSSRV.MAC.356,   8-Jan-85 10:09:05 by GRANT
;Change comments in header of routine CFRDSN.
; UPD ID= 1245, SNARK:<6.1.MONITOR>CFSSRV.MAC.355,  31-Dec-84 09:32:39 by LOMARTIRE
;TCO 6.1.1096 - Make ASC8T7 global for use by new .CFHSC funciton of CNFIG%
; UPD ID= 1213, SNARK:<6.1.MONITOR>CFSSRV.MAC.354,  17-Dec-84 16:30:24 by TBOYLE
;Change use of MAXNDS in CFS tables to HSTSIZ in CNFIG functions..
; UPD ID= 1192, SNARK:<6.1.MONITOR>CFSSRV.MAC.353,  12-Dec-84 09:50:56 by GRANT
;TCO 6.1.1084 - In CFDIAG, put serial number in OLDTAB so CFRECN will happen.
; UPD ID= 1055, SNARK:<6.1.MONITOR>CFSSRV.MAC.351,  13-Nov-84 09:04:51 by LOMARTIRE
;Use new sending priority symbols in SC.SMG calls.
;Rearrange CFSGET routine.
; UPD ID= 4877, SNARK:<6.MONITOR>CFSSRV.MAC.350,  25-Sep-84 14:00:01 by GRANT
;DLYTIM is now the time between loading the KLIPA and reconnecting
; UPD ID= 4862, SNARK:<6.MONITOR>CFSSRV.MAC.349,  21-Sep-84 14:00:26 by HALL
;Add documentation to CFSGFA routine
;Subtitles and comments
; UPD ID= 4782, SNARK:<6.MONITOR>CFSSRV.MAC.348,  30-Aug-84 21:58:53 by MCLEAN
;MOVE CALLS TO PYCOFF AND PYCON
; UPD ID= 4767, SNARK:<6.MONITOR>CFSSRV.MAC.347,  29-Aug-84 13:30:12 by MCLEAN
;MISSED A CALL TO CIONLT FOR BOTH PATH CHANGE
; UPD ID= 4753, SNARK:<6.MONITOR>CFSSRV.MAC.346,  26-Aug-84 21:01:41 by MCLEAN
;REMOVE PHYMPR/PHYUPR NO LONGER NEEDED
; UPD ID= 4667, SNARK:<6.MONITOR>CFSSRV.MAC.345,   8-Aug-84 15:18:34 by LOMARTIRE
;Add subtitles and table of contents
; UPD ID= 4647, SNARK:<6.MONITOR>CFSSRV.MAC.344,   7-Aug-84 10:21:58 by LOMARTIRE
;Fix handling of .SSPBC callback since now we can get an extra one.
; UPD ID= 4640, SNARK:<6.MONITOR>CFSSRV.MAC.343,  31-Jul-84 14:52:25 by PURRETTA
;Add copyright statement, remove brackets in comments.
; UPD ID= 4562, SNARK:<6.MONITOR>CFSSRV.MAC.342,  18-Jul-84 19:31:25 by HALL
;Comments
; UPD ID= 4495, SNARK:<6.MONITOR>CFSSRV.MAC.341,  12-Jul-84 19:52:27 by LOMARTIRE
;Overhaul callback table.  Remove .SSCBD and replace with .SSDDG.
;Code for AC change in .SSDGR/.SSMGR callbacks.
;Remove .SSNWO and .SSMNT from callback table.
; UPD ID= 4423, SNARK:<6.MONITOR>CFSSRV.MAC.340,   3-Jul-84 14:26:05 by LOMARTIRE
;Make call to SC.RCD pass in the address of the argument block.
;Obtain block from free space since SC.RCD no longer does so.
; UPD ID= 4420, SNARK:<6.MONITOR>CFSSRV.MAC.339,   3-Jul-84 09:55:25 by HALL
;CFSJYN - Don't check on nodes until online callback
; UPD ID= 4406, SNARK:<6.MONITOR>CFSSRV.MAC.338,  28-Jun-84 13:24:53 by TBOYLE
;CNFIG% - At .CFCSE, CFCSEB does not have unused bits zeroed.
; UPD ID= 4376, SNARK:<6.MONITOR>CFSSRV.MAC.337,  22-Jun-84 16:28:26 by TBOYLE
;CNFIG% - Put CFS routines in here.
; UPD ID= 4210, SNARK:<6.MONITOR>CFSSRV.MAC.336,  11-May-84 12:14:50 by GRANT
;In CFSJYN, remove call to SRVCFS (it's now at RUNDD2 in MEXEC)
; UPD ID= 4160, SNARK:<6.MONITOR>CFSSRV.MAC.335,   1-May-84 07:35:54 by HALL
;Add Q2 to the AC's saved by CFSRTV. This was confusing SCAPOL.
; UPD ID= 4143, SNARK:<6.MONITOR>CFSSRV.MAC.334,  25-Apr-84 17:50:37 by HALL
;TRY TO GET THE IFNS RIGHT
; UPD ID= 4138, SNARK:<6.MONITOR>CFSSRV.MAC.333,  25-Apr-84 14:38:21 by HALL
;Rearrange SCA interface routines
;CFSCPS - Get rid of BLOCK. (and the bug that went with it), and use a
;subroutine to disconnect duplicate connections.
; UPD ID= 4135, SNARK:<6.MONITOR>CFSSRV.MAC.332,  25-Apr-84 13:03:05 by LOMARTIRE
;Replace all .SCFxx error codes with equivalent SCSxxx error codes
; UPD ID= 4114, SNARK:<6.MONITOR>CFSSRV.MAC.331,  24-Apr-84 12:58:40 by TGRADY
;TCO 6.2041 - ILSPTI BUGHLT's on Non-CFS monitors.
; Remove conditional assembly switches around global job numbers code
; UPD ID= 4085, SNARK:<6.MONITOR>CFSSRV.MAC.330,  15-Apr-84 10:01:36 by HALL
;Add comments and subtitles
; UPD ID= 4042, SNARK:<6.MONITOR>CFSSRV.MAC.329,   3-Apr-84 14:32:59 by LOMARTIRE
;Add node number and connect ID to CFACCF, CFCCLZ, and CFRECN BUGxxx's
; UPD ID= 3974, SNARK:<6.MONITOR>CFSSRV.MAC.328,  25-Mar-84 11:16:44 by HALL
;Add SAVET to ONLINE and OFLINE
; UPD ID= 3947, SNARK:<6.MONITOR>CFSSRV.MAC.327,  20-Mar-84 03:03:37 by HALL
;Add node number and CID to OFLINE and ONLINE
; UPD ID= 3926, SNARK:<6.MONITOR>CFSSRV.MAC.326,  14-Mar-84 13:02:05 by TGRADY
;TCO 6.1999 - Remove edit 3840, and conditionally define MXGLBS in STG
; UPD ID= 3863, SNARK:<6.MONITOR>CFSSRV.MAC.325,   7-Mar-84 05:50:00 by GRANT
;Fix CFFCTB to handle new callbacks.  Clarify some comments.
; UPD ID= 3843, SNARK:<6.MONITOR>CFSSRV.MAC.324,   4-Mar-84 06:26:51 by GRANT
;Add cell CONCID in which the CID for the current connection attempt is saved.
; UPD ID= 3840, SNARK:<6.MONITOR>CFSSRV.MAC.323,   2-Mar-84 15:59:23 by TGRADY
;Correct last edit - use NJOBS, not MXGLBS, for non-CFS range check.
; UPD ID= 3836, SNARK:<6.MONITOR>CFSSRV.MAC.322,   1-Mar-84 15:22:31 by TGRADY
; Make GL2LCL still do range check even on non-cfs monitors.
; UPD ID= 3794, SNARK:<6.MONITOR>CFSSRV.MAC.321,  29-Feb-84 01:41:07 by TGRADY
; One more fix to GL2LCL for Job 0...
; UPD ID= 3777, SNARK:<6.MONITOR>CFSSRV.MAC.320,  28-Feb-84 10:32:12 by MOSER
;TCO 6.1562 - TELL MSCP SERVER WHEN TO OPEN A LISTNER
; UPD ID= 3761, SNARK:<6.MONITOR>CFSSRV.MAC.319,  26-Feb-84 23:53:49 by TGRADY
; Add LCL2GL to look up a Global Job number, given a local job index.
; UPD ID= 3748, SNARK:<6.MONITOR>CFSSRV.MAC.318,  24-Feb-84 20:59:32 by GRANT
;In LSNUP, start a new listener after rejecting an incoming connection.
;Add reporting of CFS disconnect.
; UPD ID= 3742, SNARK:<6.MONITOR>CFSSRV.MAC.317,  23-Feb-84 14:13:47 by GRANT
;STRVER is only for CFS monitors.
; UPD ID= 3722, SNARK:<6.MONITOR>CFSSRV.MAC.316,  22-Feb-84 05:37:15 by GRANT
;Add CFSJ0 to do STRVER stuff
; UPD ID= 3711, SNARK:<6.MONITOR>CFSSRV.MAC.315,  21-Feb-84 12:58:51 by CDUNN
;Change LISNAM to use a 16 byte 8 bit ASCII string. Also change calls to SC.CON
;and SC.LIS to pass the address of the string, not a byte pointer.
; UPD ID= 3678, SNARK:<6.MONITOR>CFSSRV.MAC.314,   8-Feb-84 21:50:15 by MILLER
;Remove call to STRVER for now. Put it back when job 0 knows how to call it
; UPD ID= 3668, SNARK:<6.MONITOR>CFSSRV.MAC.313,   8-Feb-84 10:05:49 by MILLER
;select the A path for the loopback message
; UPD ID= 3667, SNARK:<6.MONITOR>CFSSRV.MAC.312,   8-Feb-84 09:55:20 by MILLER
;Add STRVER and use it during CI joining
; UPD ID= 3661, SNARK:<6.MONITOR>CFSSRV.MAC.311,   7-Feb-84 16:07:27 by MILLER
;Fix CFSSMT and friends for better resolution on DSN conflicts
; UPD ID= 3748, SNARK:<6.MONITOR>CFSSRV.MAC.318,  24-Feb-84 20:59:32 by GRANT
;In LSNUP, start a new listener after rejecting an incoming connection.
;Add reporting of CFS disconnect.
; UPD ID= 3742, SNARK:<6.MONITOR>CFSSRV.MAC.317,  23-Feb-84 14:13:47 by GRANT
;STRVER is only for CFS monitors.
; UPD ID= 3722, SNARK:<6.MONITOR>CFSSRV.MAC.316,  22-Feb-84 05:37:15 by GRANT
;Add CFSJ0 to do STRVER stuff
; UPD ID= 3711, SNARK:<6.MONITOR>CFSSRV.MAC.315,  21-Feb-84 12:58:51 by CDUNN
;Change LISNAM to use a 16 byte 8 bit ASCII string. Also change calls to SC.CON
;and SC.LIS to pass the address of the string, not a byte pointer.
; UPD ID= 3678, SNARK:<6.MONITOR>CFSSRV.MAC.314,   8-Feb-84 21:50:15 by MILLER
;Remove call to STRVER for now. Put it back when job 0 knows how to call it
; UPD ID= 3668, SNARK:<6.MONITOR>CFSSRV.MAC.313,   8-Feb-84 10:05:49 by MILLER
;select the A path for the loopback message
; UPD ID= 3667, SNARK:<6.MONITOR>CFSSRV.MAC.312,   8-Feb-84 09:55:20 by MILLER
;Add STRVER and use it during CI joining
; UPD ID= 3661, SNARK:<6.MONITOR>CFSSRV.MAC.311,   7-Feb-84 16:07:27 by MILLER
;Fix CFSSMT and friends for better resolution on DSN conflicts
; UPD ID= 3657, SNARK:<6.MONITOR>CFSSRV.MAC.310,   4-Feb-84 11:33:29 by MILLER
;fix typeo
; UPD ID= 3655, SNARK:<6.MONITOR>CFSSRV.MAC.309,   4-Feb-84 10:32:23 by MILLER
;Add routine BRDTIM, to send TAD to appropriate other hosts.
; UPD ID= 3610, SNARK:<6.MONITOR>CFSSRV.MAC.308,  31-Jan-84 17:20:47 by TGRADY
; In JBGET1, don't increment & decrement the Global job number assigned.  User
; gets returned the Global Job number +1 when this is done.
; UPD ID= 3594, SNARK:<6.MONITOR>CFSSRV.MAC.307,  31-Jan-84 04:04:53 by TGRADY
;Make GL2LCL RETBAD if the local job number found is out of range (1-NJOBS)
;Make JBGET1 and JBAVAL handle Job 0 (Ignore it)
; UPD ID= 3583, SNARK:<6.MONITOR>CFSSRV.MAC.306,  28-Jan-84 19:14:59 by MILLER
;Remove use of MAXVWT for now
; UPD ID= 3581, SNARK:<6.MONITOR>CFSSRV.MAC.305,  28-Jan-84 17:41:09 by MILLER
;Change MAXVWT to 1
; UPD ID= 3516, SNARK:<6.MONITOR>CFSSRV.MAC.304,  23-Jan-84 18:29:01 by MOSER
;CHANGE MSTX16 AND MSTX17 TO BE MSTX45 AND MSTX46 SO AS NOT TO CONFLICT
; WITH THE OTHER MSTX16 AND MSTX17
; UPD ID= 3501, SNARK:<6.MONITOR>CFSSRV.MAC.303,  20-Jan-84 18:29:40 by MILLER
;Add prcoessor serial number to CFONLN BUGINF
; UPD ID= 3494, SNARK:<6.MONITOR>CFSSRV.MAC.302,  20-Jan-84 11:12:46 by CDUNN
;More TCO 6.1127 - Change call to SC.LIS to not allow buffers to be queued
; UPD ID= 3458, SNARK:<6.MONITOR>CFSSRV.MAC.301,  14-Jan-84 12:43:31 by MILLER
;One more stab at drive online stuff.
; UPD ID= 3443, SNARK:<6.MONITOR>CFSSRV.MAC.300,  12-Jan-84 12:06:49 by MILLER
;Handle credit low and arrival without races
; UPD ID= 3435, SNARK:<6.MONITOR>CFSSRV.MAC.299,  11-Jan-84 10:52:35 by MILLER
; UPD ID= 3432, SNARK:<6.MONITOR>CFSSRV.MAC.298,  10-Jan-84 19:51:36 by MILLER
;More of the previous
; UPD ID= 3417, SNARK:<6.MONITOR>CFSSRV.MAC.297,   6-Jan-84 08:58:25 by MILLER
;use two-word DSNs
; UPD ID= 3401, SNARK:<6.MONITOR>CFSSRV.MAC.296,   3-Jan-84 15:28:59 by MILLER
;Add a BUGCHK to CFSRDR if directory is not locked
; UPD ID= 3395, SNARK:<6.MONITOR>CFSSRV.MAC.295,   3-Jan-84 09:55:31 by MILLER
;CFSRDR should not do ECSKED if DIRECTORY was not locked
; UPD ID= 3392, SNARK:<6.MONITOR>CFSSRV.MAC.294,  30-Dec-83 08:22:56 by MILLER
;Check for both drives the same in CFRDSN
; UPD ID= 3334, SNARK:<6.MONITOR>CFSSRV.MAC.293,  16-Dec-83 15:51:28 by MILLER
;Add CFONLN BUGINF for debugging
; UPD ID= 3300, SNARK:<6.MONITOR>CFSSRV.MAC.292,  13-Dec-83 09:10:39 by MILLER
;Enhance CFCCLZ BUGCHK to include the SCA error code
; UPD ID= 3298, SNARK:<6.MONITOR>CFSSRV.MAC.291,  13-Dec-83 08:34:55 by MILLER
;Add CFDIAG to clean up on "CI OFFLINE" call
; UPD ID= 3289, SNARK:<6.MONITOR>CFSSRV.MAC.290,  11-Dec-83 20:20:35 by GRANT
;In CFSCTH, use new symbol VC.OPN
; UPD ID= 3240, SNARK:<6.MONITOR>CFSSRV.MAC.289,  30-Nov-83 22:01:54 by MILLER
;Add "guard word" to verify VOTE packets
; UPD ID= 3236, SNARK:<6.MONITOR>CFSSRV.MAC.288,  30-Nov-83 17:39:40 by MILLER
;Previsou fix not right. Revert to old way
; UPD ID= 3233, SNARK:<6.MONITOR>CFSSRV.MAC.287,  30-Nov-83 11:24:20 by MILLER
;Fix allocation of vote packets
; UPD ID= 3211, SNARK:<6.MONITOR>CFSSRV.MAC.286,  23-Nov-83 13:36:41 by MILLER
;More work on CI error recovery
; UPD ID= 3195, SNARK:<6.MONITOR>CFSSRV.MAC.285,  18-Nov-83 15:03:44 by MILLER
;More of the previous
; UPD ID= 3194, SNARK:<6.MONITOR>CFSSRV.MAC.284,  18-Nov-83 14:35:53 by MILLER
;Add "temp" code to try out new CI error recovery. More to come!
; UPD ID= 3187, SNARK:<6.MONITOR>CFSSRV.MAC.283,  17-Nov-83 16:21:08 by CDUNN
;More TCO 6.1127 - Fix calls to SC.SMG to conform to new calling sequence
; UPD ID= 3100, SNARK:<6.MONITOR>CFSSRV.MAC.282,   4-Nov-83 16:56:47 by MILLER
; UPD ID= 3099, SNARK:<6.MONITOR>CFSSRV.MAC.281,   4-Nov-83 16:13:40 by MILLER
;Add CFSFDF entry to use from CFSUW0
; UPD ID= 3081, SNARK:<6.MONITOR>CFSSRV.MAC.280,  26-Oct-83 07:41:18 by MILLER
;CFSRTV must refuse a request if this node has a commit (HSHDLY <>0)
; UPD ID= 3080, SNARK:<6.MONITOR>CFSSRV.MAC.279,  26-Oct-83 07:16:31 by MILLER
;Must be CSKED during vote waiting
; UPD ID= 3061, SNARK:<6.MONITOR>CFSSRV.MAC.278,  24-Oct-83 10:20:03 by MILLER
;Fix typeo in CFAREM
; UPD ID= 3053, SNARK:<6.MONITOR>CFSSRV.MAC.277,  21-Oct-83 17:17:37 by MILLER
;Fix storing of node name from connect optional data
; UPD ID= 3050, SNARK:<6.MONITOR>CFSSRV.MAC.276,  20-Oct-83 16:38:22 by MILLER
;Fix bugs in previous edits
; UPD ID= 3048, SNARK:<6.MONITOR>CFSSRV.MAC.275,  19-Oct-83 18:25:13 by MILLER
;Once more. Do NODE% in proper place
; UPD ID= 3047, SNARK:<6.MONITOR>CFSSRV.MAC.274,  19-Oct-83 16:11:29 by MILLER
;Rearrange optional data so we an pass DECnet node name
; UPD ID= 3043, SNARK:<6.MONITOR>CFSSRV.MAC.273,  18-Oct-83 18:21:26 by MILLER
;Fix CFSDAU to handle temoprary entires
; UPD ID= 3035, SNARK:<6.MONITOR>CFSSRV.MAC.272,  13-Oct-83 11:54:36 by MILLER
; UPD ID= 3027, SNARK:<6.MONITOR>CFSSRV.MAC.271,  11-Oct-83 10:25:58 by MILLER
;TCO 6.1824. Add CFSPRT for IPCF to use
; UPD ID= 3018, SNARK:<6.MONITOR>CFSSRV.MAC.270,  10-Oct-83 13:44:37 by MILLER
;Change buffer count
; UPD ID= 3008, SNARK:<6.MONITOR>CFSSRV.MAC.269,   7-Oct-83 20:03:39 by MILLER
; UPD ID= 3007, SNARK:<6.MONITOR>CFSSRV.MAC.268,   7-Oct-83 18:31:25 by MILLER
; UPD ID= 2976, SNARK:<6.MONITOR>CFSSRV.MAC.267,   3-Oct-83 18:40:08 by MILLER
; UPD ID= 2951, SNARK:<6.MONITOR>CFSSRV.MAC.266,  28-Sep-83 07:11:55 by MILLER
;The last typeo
; UPD ID= 2950, SNARK:<6.MONITOR>CFSSRV.MAC.265,  28-Sep-83 05:54:32 by GRANT
;Fix typos in recent edits
; UPD ID= 2948, SNARK:<6.MONITOR>CFSSRV.MAC.264,  27-Sep-83 21:11:12 by MILLER
; UPD ID= 2946, SNARK:<6.MONITOR>CFSSRV.MAC.263,  27-Sep-83 20:48:44 by MILLER
; UPD ID= 2943, SNARK:<6.MONITOR>CFSSRV.MAC.262,  27-Sep-83 20:27:17 by MILLER
;More work for TCO 6.1806
; UPD ID= 2929, SNARK:<6.MONITOR>CFSSRV.MAC.261,  23-Sep-83 13:52:20 by MILLER
; UPD ID= 2927, SNARK:<6.MONITOR>CFSSRV.MAC.260,  23-Sep-83 10:59:38 by MILLER
;Fix typeos in previous edit
; UPD ID= 2925, SNARK:<6.MONITOR>CFSSRV.MAC.259,  23-Sep-83 10:34:05 by MILLER
;TCO 6.1806. Add TAD stuff
; UPD ID= 2923, SNARK:<6.MONITOR>CFSSRV.MAC.258,  23-Sep-83 10:05:01 by MILLER
;Add job number assigner
; UPD ID= 2893, SNARK:<6.MONITOR>CFSSRV.MAC.257,  12-Sep-83 19:53:49 by MILLER
;Turn off OFN bit in CFSUWT
; UPD ID= 2887, SNARK:<6.MONITOR>CFSSRV.MAC.256,  12-Sep-83 11:35:28 by MILLER
;Make sure always in section 1
; UPD ID= 2884, SNARK:<6.MONITOR>CFSSRV.MAC.255,   9-Sep-83 19:16:30 by MILLER
;New buffer management to avoid free space failures
; UPD ID= 2877, SNARK:<6.MONITOR>CFSSRV.MAC.254,   6-Sep-83 09:25:05 by MILLER
;More fixes to CFSSMT
; UPD ID= 2873, SNARK:<6.MONITOR>CFSSRV.MAC.253,   1-Sep-83 10:30:28 by MILLER
;fix CFSSMT
; UPD ID= 2871, SNARK:<6.MONITOR>CFSSRV.MAC.252,  31-Aug-83 15:32:11 by MILLER
; UPD ID= 2830, SNARK:<6.MONITOR>CFSSRV.MAC.251,  12-Aug-83 14:17:17 by MILLER
;prevent MONPDL in CFSDAU
; UPD ID= 2775, SNARK:<6.MONITOR>CFSSRV.MAC.250,  28-Jul-83 12:14:43 by MILLER
; UPD ID= 2774, SNARK:<6.MONITOR>CFSSRV.MAC.249,  27-Jul-83 16:22:10 by MILLER
; UPD ID= 2770, SNARK:<6.MONITOR>CFSSRV.MAC.248,  27-Jul-83 10:09:35 by MILLER
;Add check for illegal reconnect
; UPD ID= 2717, SNARK:<6.MONITOR>CFSSRV.MAC.247,  22-Jul-83 14:52:58 by MILLER
; UPD ID= 2712, SNARK:<6.MONITOR>CFSSRV.MAC.246,  20-Jul-83 16:58:19 by MURPHY
;Take out setup of MSECTB+CFSSEC because it's already done by PGRINI.
; UPD ID= 2710, SNARK:<6.MONITOR>CFSSRV.MAC.245,  20-Jul-83 09:59:36 by MILLER
;Clean up CFSCMC and pending connections in SCABRK
; UPD ID= 2697, SNARK:<6.MONITOR>CFSSRV.MAC.244,  13-Jul-83 14:22:39 by MILLER
;More editing fixes
; UPD ID= 2696, SNARK:<6.MONITOR>CFSSRV.MAC.243,  13-Jul-83 10:24:17 by MILLER
;Add commentary.
; UPD ID= 2693, SNARK:<6.MONITOR>CFSSRV.MAC.242,  11-Jul-83 17:40:35 by MILLER
;Yet more CI error recovery fixes
; UPD ID= 2681, SNARK:<6.MONITOR>CFSSRV.MAC.241,   6-Jul-83 12:56:31 by MILLER
;More fixes for CI error recovery
; UPD ID= 2679, SNARK:<6.MONITOR>CFSSRV.MAC.239,   6-Jul-83 10:09:57 by MILLER
;Add and maintain CFSCMC
; UPD ID= 2670, SNARK:<6.MONITOR>CFSSRV.MAC.238,   5-Jul-83 16:03:15 by MILLER
; UPD ID= 2654, SNARK:<6.MONITOR>CFSSRV.MAC.237,   2-Jul-83 08:37:58 by MILLER
;Must always create a CFSSTK pointer, even if CFSSCA=0
; UPD ID= 2612, SNARK:<6.MONITOR>CFSSRV.MAC.236,  21-Jun-83 09:47:07 by MILLER
; UPD ID= 2611, SNARK:<6.MONITOR>CFSSRV.MAC.235,  20-Jun-83 21:18:24 by MILLER
; UPD ID= 2591, SNARK:<6.MONITOR>CFSSRV.MAC.234,  20-Jun-83 10:05:44 by HALL
;TCO 6.1689 - Move fork tables to extended section
;	Reference FKSTA2 via DEFSTR
; UPD ID= 2587, SNARK:<6.MONITOR>CFSSRV.MAC.233,  17-Jun-83 14:01:37 by MILLER
;Improve handling of HSHLNK and avoid a few bugs as well
; UPD ID= 2583, SNARK:<6.MONITOR>CFSSRV.MAC.232,  15-Jun-83 10:13:49 by MILLER
;Yet more fixes!
; UPD ID= 2582, SNARK:<6.MONITOR>CFSSRV.MAC.231,  15-Jun-83 09:31:03 by MILLER
;More fixes for dual-port devices
; UPD ID= 2576, SNARK:<6.MONITOR>CFSSRV.MAC.230,   8-Jun-83 21:35:17 by MILLER
;Improve recovery when free space queue is exhausted.
; UPD ID= 2571, SNARK:<6.MONITOR>CFSSRV.MAC.229,   8-Jun-83 14:23:03 by MILLER
;Make FILRST correct, but leave it out anyway
; UPD ID= 2570, SNARK:<6.MONITOR>CFSSRV.MAC.228,   8-Jun-83 13:35:43 by MILLER
;Remove FILRST
; UPD ID= 2569, SNARK:<6.MONITOR>CFSSRV.MAC.227,   8-Jun-83 13:29:50 by MILLER
;Don't set CFSSKC in CFSDIN
; UPD ID= 2550, SNARK:<6.MONITOR>CFSSRV.MAC.226,   1-Jun-83 07:40:17 by MILLER
;Remove CFSCFL BUGHLT
; UPD ID= 2542, SNARK:<6.MONITOR>CFSSRV.MAC.225,  31-May-83 14:03:43 by MILLER
; UPD ID= 2530, SNARK:<6.MONITOR>CFSSRV.MAC.224,  26-May-83 14:10:18 by MILLER
; UPD ID= 2529, SNARK:<6.MONITOR>CFSSRV.MAC.223,  26-May-83 14:08:57 by MILLER
;Add more BUGHLTs for whenever SCA fails
; UPD ID= 2525, SNARK:<6.MONITOR>CFSSRV.MAC.222,  26-May-83 11:56:22 by MILLER
;Fix CFSCHK to do CFONLT only after the monitor is initialized
; UPD ID= 2522, SNARK:<6.MONITOR>CFSSRV.MAC.221,  25-May-83 20:14:33 by MILLER
;Only do CI check if CFSSCA
; UPD ID= 2514, SNARK:<6.MONITOR>CFSSRV.MAC.220,  25-May-83 09:17:54 by MILLER
;Do a full CI check every five seconds
; UPD ID= 2500, SNARK:<6.MONITOR>CFSSRV.MAC.219,  23-May-83 11:14:27 by MILLER
;Remove dummy def of CIONLT
; UPD ID= 2478, SNARK:<6.MONITOR>CFSSRV.MAC.218,  17-May-83 10:24:07 by MILLER
;Account for CFSNDO skip return in CFSDEQ
; UPD ID= 2451, SNARK:<6.MONITOR>CFSSRV.MAC.217,  10-May-83 10:31:13 by MILLER
;Fix CFSOVT test on HSHBTF
; UPD ID= 2359, SNARK:<6.MONITOR>CFSSRV.MAC.216,  27-Apr-83 13:29:03 by MILLER
; UPD ID= 2356, SNARK:<6.MONITOR>CFSSRV.MAC.215,  27-Apr-83 11:43:28 by MILLER
; UPD ID= 2355, SNARK:<6.MONITOR>CFSSRV.MAC.214,  27-Apr-83 08:11:58 by MILLER
; UPD ID= 2308, SNARK:<6.MONITOR>CFSSRV.MAC.213,  19-Apr-83 20:04:35 by MILLER
;DOn't need POLCNT test - PHYKLP does it correctly
; UPD ID= 2298, SNARK:<6.MONITOR>CFSSRV.MAC.212,  17-Apr-83 18:45:49 by MILLER
;Add message statistics
; UPD ID= 2273, SNARK:<6.MONITOR>CFSSRV.MAC.211,  13-Apr-83 14:27:48 by MILLER
;TCO 1.1610. Add CFONLT
; UPD ID= 2240, SNARK:<6.MONITOR>CFSSRV.MAC.210,  12-Apr-83 12:07:16 by MILLER
;Remove dummy defs of PHYMPR and PHYUPR
; UPD ID= 2236, SNARK:<6.MONITOR>CFSSRV.MAC.209,  12-Apr-83 09:31:22 by MILLER
;Check SCAFL1 in CFSJYN to see if we should turn on dual-port disks
; UPD ID= 2235, SNARK:<6.MONITOR>CFSSRV.MAC.208,  12-Apr-83 07:12:16 by MILLER
;Fixes to CFSJYN and CFSNDU. 
; UPD ID= 2232, SNARK:<6.MONITOR>CFSSRV.MAC.207,  11-Apr-83 13:22:31 by MILLER
;Fixes to CFSJYN
; UPD ID= 2223, SNARK:<6.MONITOR>CFSSRV.MAC.206,   8-Apr-83 17:33:21 by MILLER
; UPD ID= 2222, SNARK:<6.MONITOR>CFSSRV.MAC.205,   8-Apr-83 15:36:03 by MILLER
;Join only when CFSINI called AND CFSJYN called
; UPD ID= 2184, SNARK:<6.MONITOR>CFSSRV.MAC.204,   7-Apr-83 15:21:54 by MILLER
;Avoid CFSLOK at interrupt level
; UPD ID= 2169, SNARK:<6.MONITOR>CFSSRV.MAC.203,   5-Apr-83 16:23:29 by MILLER
;TCO 6.1094. Move RS defs to STG
; UPD ID= 2155, SNARK:<6.MONITOR>CFSSRV.MAC.202,   4-Apr-83 17:31:32 by MILLER
;TCO 6.1588. Make sure vote buffers are usable
; UPD ID= 2143, SNARK:<6.MONITOR>CFSSRV.MAC.201,   4-Apr-83 07:42:35 by MILLER
;TCO 6.1094. Make length of vote packets an even number of words

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


	SEARCH PROLOG,SCAPAR,PHYPAR
	TTITLE CFSSRV
	EXTN <CFSSEC>
	DEBUG==1		;Do debugging

   IFE CFSSCA,<CFSDUM==0>	;If no SCA, define this as a dummy as well

	SUBTTL	Table of Contents


;		Table of Contents for CFSSRV
;
;
;			   Section			      Page
;   1. Design Notes . . . . . . . . . . . . . . . . . . . . .    3
;   2. Data definitions . . . . . . . . . . . . . . . . . . .    7
;   3. Macros . . . . . . . . . . . . . . . . . . . . . . . .   11
;   4. Initialization
;        4.1.   CFSINI (SCA initialization routine) . . . . .   12
;        4.2.   CFSDIN (Initialize CFS database). . . . . . .   12
;        4.3.   CFSJYN/CFSJYX (Join the CFS network). . . . .   13
;        4.4.   CFSCSC (Create private pages) . . . . . . . .   14
;   5. Support Routines
;        5.1.   CFONLT (Test state of connection) . . . . . .   15
;        5.2.   PRTOFL (Turn off dual port access). . . . . .   15
;        5.3.   PRTONL (Turn on dual port access) . . . . . .   15
;        5.4.   CFSKPR (KLIPA ucode reloaded) . . . . . . . .   15
;        5.5.   DEDKLP (KLIPA is dead). . . . . . . . . . . .   15
;        5.6.   CFSCTH (Connect to host). . . . . . . . . . .   16
;        5.7.   HASHN (Compute hash for resource) . . . . . .   17
;        5.8.   HSHLOK (Locate hash entry for resource) . . .   17
;        5.9.   GNAME (Get structure name). . . . . . . . . .   18
;        5.10.  CFSULL (Unlock CFS database). . . . . . . . .   19
;        5.11.  CFSMAP (Map entries onto function). . . . . .   20
;        5.12.  CFSRSE (Remove stale entries) . . . . . . . .   21
;        5.13.  CFSSPC (Obtain request block space) . . . . .   22
;        5.14.  CFCARV (Carve a block from page pool) . . . .   23
;        5.15.  CFSSBB (Place OFN in SDB) . . . . . . . . . .   24
;        5.16.  CFSWUP (General wait routine) . . . . . . . .   25
;        5.17.  CFSRSV (Restart vote) . . . . . . . . . . . .   26
;        5.18.  CFTADC (Get CFS time and date). . . . . . . .   27
;        5.19.  SNDTIM (Send date and time to new node) . . .   28
;        5.20.  BRDTIM (Send date and time at startup). . . .   28
;        5.21.  CFTADB (Broadcast date and time via STAD) . .   29
;        5.22.  CFSPRT (Return local port number) . . . . . .   29
;        5.23.  CFCNCK (Check for CFS connection to node) . .   29
;   6. Resource manager
;        6.1.   CFSGET (Acquire a resource) . . . . . . . . .   30
;        6.2.   CFSRMV (Remove entry from hash table) . . . .   36
;        6.3.   CFSNDO (Undeclare a resource) . . . . . . . .   37
;        6.4.   CFSOHS (Notify rejected hosts after undeclare)  39
;        6.5.   CFSUGD (Upgrade or downgrade a resource lock)   40
;   7. The voter
;        7.1.   VOTEW (Start vote and wait for results) . . .   42
;        7.2.   GVOTE (Get a vote buffer) . . . . . . . . . .   47
;   8. Periodic check
;        8.1.   CFSCHK (Scheduler poller) . . . . . . . . . .   48
;        8.2.   SCAPOL (Process incoming SCA messages). . . .   49
;   9. Call from SCA. . . . . . . . . . . . . . . . . . . . .   50
;        9.1.   Message Received
;             9.1.1.     SCAIN (Receive message from SCA) . .   51
;             9.1.2.     SCMSG (Process a single received message)  52
;             9.1.3.     CFSRTV (Vote or seize) . . . . . . .   53
;             9.1.4.     CFSRVT (Reply to vote) . . . . . . .   56
;             9.1.5.     CFSRFR (Resource freed). . . . . . .   57
;             9.1.6.     CFSOFC (OFN change). . . . . . . . .   58
;             9.1.7.     CFSEFC (EOF received). . . . . . . .   58
;             9.1.8.     CFTADA (Time and date arrived) . . .   58
;             9.1.9.     CFCEAS (Cease) . . . . . . . . . . .   59
;        9.2.   SCABRK (Node went away) . . . . . . . . . . .   64
;        9.3.   LSNUP (Connect to listen) . . . . . . . . . .   65
;        9.4.   Connect response available
;             9.4.1.     CFSCPS (Connect response available).   66
;             9.4.2.     CFSCPX (Disconnect duplicate connection)   68
;        9.5.   CFSWDN (Write completed). . . . . . . . . . .   69
;        9.6.   CFSNDU (Node up). . . . . . . . . . . . . . .   70
;        9.7.   CFSOKS (Ok to send) . . . . . . . . . . . . .   71
;        9.8.   SCACRA (Credit available) . . . . . . . . . .   72
;  10. Sending Messages
;       10.1.   SCAENQ (Enqueue a SCA message). . . . . . . .   73
;       10.2.   SCASND (Send a message) . . . . . . . . . . .   74
;       10.3.   SENDQ (Maintain send queue) . . . . . . . . .   75
;  11. Queuing Message Buffers
;       11.1.   SCARET (Queue packet as message buffer) . . .   76
;  12. Declare a listener
;       12.1.   CFSLSN (Declare CFS listener) . . . . . . . .   77
;  13. Connection Management
;       13.1.   CHKOLD (Manage connect serial number) . . . .   78
;       13.2.   CHKOL0 (Generate old/new bit) . . . . . . . .   78
;       13.3.   PUTOLD (Install serial number). . . . . . . .   78
;       13.4.   CLRDLY (Clear delay bit in OLDTAB entries). .   78
;       13.5.   CHKDLY (Check for delayed entries). . . . . .   78
;  14. Directory lock resource manager
;       14.1.   CFSLDR (Lock directory) . . . . . . . . . . .   79
;       14.2.   CFSRDR (Unlock directory) . . . . . . . . . .   81
;       14.3.   CFSDAU (Acquire allocation entry) . . . . . .   82
;       14.4.   CFAFND/CFAGET (Find/Get allocation table) . .   82
;       14.5.   CFASTO (Store new allocation value) . . . . .   84
;       14.6.   CFAULK (Unlock allocation entry). . . . . . .   84
;       14.7.   CFAREM (Remove allocation entry). . . . . . .   84
;       14.8.   CFAUPB (Undo keep here bit) . . . . . . . . .   84
;       14.9.   CFAVOK (Vote to be approved). . . . . . . . .   85
;       14.10.  CFADAR (Optional data present). . . . . . . .   85
;       14.11.  CFARMV (Voter remove entry) . . . . . . . . .   85
;       14.12.  GETDBK (Find resource block). . . . . . . . .   86
;  15. File open resource manager
;       15.1.   CFSGFA (Acquire file opening locks) . . . . .   87
;       15.2.   CFSFFL (Release file locks) . . . . . . . . .   88
;       15.3.   CFSURA (Downgrade to promiscuous) . . . . . .   89
;  16. Frozen writer resource manager
;       16.1.   CFSGWL (Get write access) . . . . . . . . . .   90
;       16.2.   CFSFWL (Free write access). . . . . . . . . .   91
;  17. BAT block resource manager
;       17.1.   CFGBBS (Set BAT block lock) . . . . . . . . .   93
;       17.2.   CFFBBS (Release BAT block lock) . . . . . . .   94
;  18. File access token resource manager
;       18.1.   CFSGWT (Get write token value). . . . . . . .   95
;       18.2.   CFSAWP/CFSAWT (Acquire write token) . . . . .   96
;       18.3.   CFSDWT (Write token revoked). . . . . . . . .   99
;       18.4.   CFSOVT (Approve sharing of OFN resource). . .   99
;       18.5.   CFSGOC (Get count of resource sharers). . . .  100
;       18.6.   CFSDAR (Optional data for access token) . . .  101
;       18.7.   CFSFWT (Free write token) . . . . . . . . . .  101
;       18.8.   CFSUWT (Release access token) . . . . . . . .  102
;       18.9.   CFSBOW (Broadcast OFN update) . . . . . . . .  104
;       18.10.  CFSBEF (Broadcast EOF). . . . . . . . . . . .  105
;       18.11.  CFSBRD (Main broadcast routine) . . . . . . .  106
;       18.12.  CFSFOD (DDMP force out done). . . . . . . . .  107
;  19. Structure resource manager
;       19.1.   CFSSMT (Acquire structure resource) . . . . .  109
;       19.2.   CFMNAM (Register structure name). . . . . . .  111
;       19.3.   CFMDSN (Register drive serial number) . . . .  112
;       19.4.   CFSSUG (Upgrade or downgrade mount) . . . . .  113
;       19.5.   CFMDER (Mount/Dismount error) . . . . . . . .  114
;       19.6.   CFSSDM (Release mount resource) . . . . . . .  115
;       19.7.   STRVER (Structure verify) . . . . . . . . . .  116
;  20. File enqueue resource manager
;       20.1.   CFSENQ (Get ENQ resource) . . . . . . . . . .  117
;       20.2.   CFSDEQ (Release ENQ resource) . . . . . . . .  118
;  21. Global Job Number Routines
;       21.1.   JBAVAL (Manage job bit table) . . . . . . . .  119
;       21.2.   JBGET1 (Get global job number for local job).  119
;       21.3.   GL2LCL (Return local job number). . . . . . .  120
;       21.4.   LCL2GL (Return global job number) . . . . . .  120
;       21.5.   CFGTJB (Get jobs at system startup) . . . . .  121
;  22. Miscellaneous Interfaces
;       22.1.   FILRST (Reset all files at startup) . . . . .  122
;       22.2.   CFSERR (Illegal configuration). . . . . . . .  123
;       22.3.   CFRDSN (Read drive serial number) . . . . . .  124
;       22.4.   CFSDSN (Swap drive serial number) . . . . . .  124
;       22.5.   CFCBRD (Broadcast system cease) . . . . . . .  126
;  23. DIAG% JSYS Support
;       23.1.   CFDIAG (Code for Set CI Unavailable). . . . .  128
;  24. CNFIG% JSYS Support
;       24.1.   CFCIN (Return CFS information). . . . . . . .  129
;       24.2.   CFCSE (Return serial numbers of CFS nodes). .  130
;       24.3.   CFCND (Return list of node names) . . . . . .  131
;  25. End of CFSSRV. . . . . . . . . . . . . . . . . . . . .  131
	SUBTTL	Design Notes

COMMENT #

This module is the Common File System (CFS) support module. It contains
the CFS protocol routines, the CFS data base support routines and
the glue that makes a system out of a bunch of machines.

The CFS support code is really a "global lock manager". The manager
supports a "named locking scheme" as follows:

A lock is a multi-part name. The first part of the name is the "root".
The remaining part of the name defines a tree structure under the root.

Locks have names, owners, state and data.

The CFS protocol uses SCA to send and receive packets.

Aside from the lock management function, this module also
implements the CFS configuration manager. It handles nodes
coming into the CFS network as well as nodes leaving the
CFS network. CFSCON relies heavily on SCA to provide
up-to-date information on the physical configuration,
including notification of any configuration change.

Locks are in one of several states. First, a lock may be owned
locally. In this case, any attempts to share this lock
must conform to the current level of ownership. Second, a lock
may reside on the local node, but be unowned. A request for
ownership may be granted as long as the request is equal to
or less than the current level. Finally, a lock may be unknown
on the local node. In any case where the lock cannot be immediately
granted, a vote must be taken. A vote simply is a "braodcasting" of
the lock request to all other CFS nodes. The reqeust is successful
is no reply denies the request. Note this scheme has the advantage
that locks need not be permanent and no single node is ever
responsible for keeping track of a dormant lock. In principle, this
will most likely happen, but it needn't. Furthermore, there is
no a priori assignment of node to lock. This means that if the owner
of a lock crashes, there is no special error recovery method. The
next node to request the lock will simply discover that its vote
is successful.

The obvious disadvantage of this scheme is that requesting a lock
has a fixed cost; the cost being the same to "create" a lock.
However, if the CFS network is small, this cost is negligible
and in fact the trade-off versus an elaborate "permanent owner"
scheme is well justified.

Configurations:

The conditional assemblies control configurations as follows:

CFSDUM: This is a "reduced" CFS. This system is on the CI and uses
SCA to connect to other CI-based systems. However, this processor
will not share structures with any other system but will insure
that the structures it is using are mutually exclusive from structures
used by any other CI-based TOPS-20 system. This implies that this
system will establish connections to other reduced or full CFS systems
and will participate in strcuture mounting votes.

CFSSCA: If zero, this processor is not on a CI with any other processor.
SCA may be in the monitor, but the CFS SYSAP is not present. This
processor offers no assurances that it will not interfere with any
other CI activity. If this is zero, CFSDUM will be defined. If this
is a one, CFSDUM is defined independently of this conditional. If CFSSCA=0,
then this should processor should either not be on a CI at all, or should
be on a CI with no other TOPS-20 host systems. Any other configuration is
unsupported and not likely to operate correctly.

In addition, the CFS network number, MYPOR2, defines the CFS subnet
that this processor is in. This value is only significant if
CFSSCA=1 and CFSDUM is not defined.

The tables CFSHST, CFSHNM, and CFHSTS describe the states of the
connections to the other nodes, and one listener. THe following
indicates the contents of these tables are various stages in the
life of a connection.

			CFSHST		CFSHNM		CFHSTS

Unused			0		-		-

After CFSCTH		SBI,,-1		-1		0

At CFSCPS if close	0		-1		0

At CFSCPS if open	CID		serial		-1,,type


After CFSLSN		-1		CID		0

After LSNUP if reject	0		CID		0

After LSNUP if accept	CID		serial		0,,type

After CFSOKS if disc.	0		serial		0,,type

After CFSOKS if conn.	CID		serial		-1,,type

After SCABRK		0		-		-


Popular combinations

Fully open		CID		serial		-1,,type
Listener		-1		CID		0
Connection requested	SBI,,-1		-1		0
Waiting for OKS		CID		serial		0,,type


The parts of CFHSTS:

L.H.

	-1 when fully open
	0 when being opened
	1B0 turned off when disconnect happens and interlock is set
	1B17 turned off to indicate lack of credit

R.H. is type:

	-1 full CFS node
	0  not full CFS node
Deciding what to disconnect when there is a conflict:

Connect response available (our initiator):

	We're lower: close new one (our initiator)
	They're lower: close already open one (their initiator)

Connect to listener (our listener):

	We're lower: accept connection, wait for OK to send
	They're lower: reject connection

OK to send (our listener):

	We're lower: close already open one (our initiator)
	They're lower: close new one (their initiator)
Major routines for managing resources:

File open			CFSGFA	CFSFFL
Frozen writer of file		CFSGWL	CFSFWL
File access token		CFSAWT	CSFAWP
Directory lock			CFSLDR	CFSRDR
Directory allocation		CFSDAU
Structure mounting		CFSSMT	CFSSDM	CFSSUG
File enqueue			CFSENQ	CFSDEQ
BAT blocks			CFGBBS	CFFBBS


Unique code:

Outgoing vote: HSHUNQ --> CFUNQ
Incoming request to vote: CFUNQ --> HSHVVL
Outgoing response to request to vote: CFUNQ(in) --> CFUNQ(out)

#
	SUBTTL Data definitions

;Special defs

;**;[7152] Remove 1 line at (WRTTIM==^D200)-1	CEG 15-Oct-85
WRTTIM==^D200			;Minimum hold time for token
DIRTIM==^D200			;Minimum hold time for a directory
MAXHLT==^D3000			;Max time to hold token under demand

;Note: The trailing space are required by SCA. The string must be 16 bytes
;padded with spaces as necessary.

LISNAM: ASCI8 (<LCS20$CFS       >) ;Our name

RCRDIT==2			;MIN RECEIVE CREDIT
SCRDIT==2			;MIN SEND CREDIT
MAXVWT==5			;MAX TIME (MS) TO WAIT FOR VOTE RESULTS
BUFSCT==5			;# of receive buffers per CFS circuit
   IFN CFSSCA,<
	HSHLEN==^D509		;SIZE OF HASH TABLE (should be prime)
   >	;IFN CFSSCA
   IFE CFSSCA,<
	HSHLEN==^D251
   >	;IFE CFSSCA
   IFN CFSSCA,<			;If SCA present
CFSSLN==^D100			;Size of CFS stack
   >	;IFN CFSSCA
   IFE CFSSCA,<			;If no SCA
CFSSLN==20			; then small private stack needed
   >	;IFE CFSSCA
 CFNBC==OFNBC
 CFNBSZ==OFNBSZ			;Defs in OFNLEN

;Bits in SCAFLG

	DEFSTR SCRSV,SCAFLG,0,1	;RESTART VOTE BIT
	DEFSTR SCDIS,SCAFLG,1,1 ;Disconnect pending
	DEFSTR SCDDP,SCAFLG,2,1	;Need DDMP soon
	DEFSTR SCCNC,SCAFLG,3,1	;We got connected flag
	DEFSTR SCWKP,SCAFLG,2,3	;Bits to cause a scheduler pass
	DEFSTR SCVER,SCAFLG,4,1	;Set if structure verify needed

;Descriptions of this node. First offset contains serial number

   IFDEF CFSDUM,<		;If we are to be a dummy
RS	MYPORT,4		;Both of these are zero
   >	;IFDEF CFSDUM
   IFNDEF CFSDUM,<		;If we are for real
RSI	MYPORT,<0,<-1,,0>,0,0,-1>  ;Make it so
   >	;IFNDEF CFSDUM
 MYPOR1==:MYPORT+1		;type,, net number
 MYPOR2==:MYPOR1+1		;name
 MYPOR3==:MYPOR2+1		;rest of name + old/new flag
 MYPOR4==:MYPOR3+1		;Our CI node number
RSI	CFSIFL,<-2>		;Init init flag
 TIMSE0==^D600/5		;Ten minutes of five second chunks
RSI	CFSTTM,<TIMSE0>		;Full scheduler check time

;Optional data in connect_request or accept_request

OPDSER==0			;serial number in optional data
OPDTYP==1			;type in optional data,,net number
OPDNAM==2			;first word of name
OPDNEW==3			;last 2 chars of name,,old/new flag
 DEFSTR ONFLG,,31,8		;Old/new byte in optional data
  OF%NEW==0			;Unknown host
  OF%DLY==1			;In dealy for this host
  OF%OLD==2			;It is old

   IFN CFSSCA,<			;If SCA is around
RS	CONCID,1		;CID FOR CURRENT CONNECTION ATTEMPT
RS	OLDTAB,1
RS	DLYLOK,1		;Word to do delay stuff
RSI     DLYTIM,<^D5000>		;Delay time on CI failure per node
;RS	DLYFLG,1		;Flag to say if delay being honored
   >	;IFN CFSSCA
	NSPCQ==5		;NUMBER TO PREALLOCATE
   IFNDEF CFSDUM,<		;For a full CFS, get lots of packets
	NSPCQ0==^D600		;Number to stack from private stock
   >	;IFN CFSDUM
   IFDEF CFSDUM,<		;For a reduced CFS
	NSPCQ0==^D150		;Just get a few for allocation entries
   >	;IFDEF CFSDUM
	NSPCQ1==^D250		;Number of long pakcets to get
 CLCCNT==^D350			;Number to collect when we are desparate
 SKDCNT==^D200			;Number to collect in the background
 CFSCTM==^D10000

RS	CFNXPG,1		;Page pool address
RSI	CFNXSZ,<PGSIZ>		;Space available in pool
RS	CFTADL,1		;Time and date cell
;Definitions for hash table
;Description of a resource block. Offsets HSHROT and HSHQAL are hashed
;to provide offset into HSHTBL. Entries that conflict are chained together
;via offsets HSHLNK and HSHBKP.

HSHLNK==0			;OFFSET FOR LINK WORD
HSHROT==1			;ROOT NUMBER
HSHQAL==2			;QUALIFIER
HSHTIM==3			;TIME STAMP OF GRANT
HSFLAG==4			;Offset for the flags
DEFSTR	HSHWVT,4,0,1		;IF ON, WE ARE VOTING
DEFSTR	HSHYES,4,1,1		;YES/NO VOTE (1 if anyone said no)
DEFSTR	HSHTYP,4,5,4		;TYPE OF ENTRY
	.HTPLH==0		;Place-holder entry
	.HTOAD==1		;OWNED FOR FULL SHARING
	.HTOSH==2		;OWNED READ-ONLY SHARED
	.HTOEX==3		;OWNED EXCLUSIVELY
	.HTOPM==4		;OWNED FOR PROMISCOUS READ
DEFSTR	HSHTWF,4,6,1		;"token" wait flag (see CFSUGW)
DEFSTR	HSHRTY,4,7,1		;RETRY NOW BIT
DEFSTR	HSHLSG,4,8,1		;ENTRY BEING RELEASED
DEFSTR	HSHVRS,4,9,1		;VOTE RESTART FLAG
DEFSTR	HSHLOS,4,10,1		;LONG/SHORT FLAG (1 if block is long)
DEFSTR 	HSHUGD,4,11,1		;VOTING FOR AN UPGRADE
DEFSTR	HSHODA,4,12,1		;OPtional data valid
DEFSTR	HSHKPH,4,13,1		;Don't pruge this entry
DEFSTR	HSHVTP,4,17,4		;TYPE WE ARE VOTING ON
DEFSTR	HSHDWT,4,18,1		;If here, waiting for delay to be up
DEFSTR	HSVUC,4,19,1		;Bit to indicate vote must include HSHCOD
DEFSTR	HSHLCL,4,20,1		;Local exclusive
DEFSTR	HSHRFF,4,21,1		;For tokens only
DEFSTR	HSHAVT,4,22,1		;Vote on all nodes, even reduced CFS nodes
DEFSTR 	HSHBTF,4,23,1		;If set, this is a bit-table file
DEFSTR  HSHTAM,4,24,1		;[7247] Cached file access token (cached OFN)
DEFSTR	HSHCNT,4,35,11		;[7247] Count of sharers
HSHCOD==5			;UNIQUE CODE USED FOR ID
HSHPST==6			;POST ADDRESS WHEN RESOURCE IS WITHDRAWN
HSHVWD==7			;Word used by voter
 DEFSTR	HSHLKF,HSHVWD,11,12	;Lock field
 DEFSTR	HSHVCT,HSHVWD,17,6	;VOTE COUNT
 DEFSTR	HSHUNQ,HSHVWD,35,18	;VOTE CODE
HSHVRW==10			;Vote reply word
 DEFSTR HSHDRC,HSHVRW,35,18	;Reason code for denial on NO return to vote
HSHNBT==11			;NODE BIT TABLE
HSHRET==12			;RETURN ADDRESS ON DEASSIGN
HSHDVD==13			;RELEASE VOTE DATA ("Deferred vote data")
 DEFSTR HSHRHN,HSHDVD,17,18	;DEST PORT I.D.
 DEFSTR HSHVVL,HSHDVD,35,18	;VOTE CODE
HSHMSK==14			;Delay mask and fork word
 DEFSTR HSHDLY,HSHMSK,17,18	;Delay mask
 DEFSTR HSHFRK,HSHMSK,35,18	;Owning fork
HSHOPT==HSHMSK+1		;Optional data from vote
HSHOP1==HSHOPT+1		; Second opt data word
HSHOKV==HSHOP1+1		;Call-back when a vote is OKed
HSHCDA==HSHOKV+1		;Call-back when optional data is present in vote
HSHFCT==HSHCDA+1		;Fairness timer
HSHWTM==HSHFCT+1		;revote wait time
HSHBKP==HSHWTM+1		;Back pointer
HSHSIZ==HSHBKP+1		;SIZE OF A HASH ENTRY

;Start of a long block. Remaining words are bit mask of waiting forks.

HSHBTT==HSHSIZ+1		;FIRST WORD OF BIT TABLE
HSHDRI==1+<NFKS+^D35>/^D36	;ADDITIONAL WORDS FOR DIR LOCKS
WRDHSH==NSPCQ0*HSHSIZ		;Words in hash packets
LNGHSH==NSPCQ1*<HSHSIZ+HSHDRI>	;Words in long packets
;Defs for CFS block

NVOTQ==^D4			;# OF VOTE PACKETS TO STOCK FROM FREE SPACE
   IFNDEF CFSDUM,<		;If a real CFS
 NVOTQ0==^D75			;# of packet to get from private stock
   >	;IFNDEF CFSDUM
   IFDEF CFSDUM,<		;If a reduced CFS
 NVOTQ0==^D10			;Just get a few
   >	;IFNDEF CFSDUM


;Contents of a packet sent via SCA.

SCALEN==.MHSTS+1		;First word past SCA header

DEFSTR CFFLG,SCALEN,11,12	;Flags
 DEFSTR CFODA,SCALEN,0,1	;Opt data present
 DEFSTR CFVUC,SCALEN,1,1	;Vote to include HSHCOD
DEFSTR CFCOD,SCALEN,17,6	;OPCODE FOR VOTING
	.CFVOT==1		;VOTER
	.CFREP==2		;REPLY TO VOTE
	.CFRFR==3		;RESOURCE FREED
	.CFCEZ==4		;SEIZE RESOURCE
	.CFBOW==5		;Broadcast OFN change
	.CFBEF==6		;Broadcast EOF
	.CFTAD==7		;Time and date arrived
	.CFSHT==10		;Shutdown of system is pending
.CFMAX==10			;MAX FNC WE DO
DEFSTR CFUNQ,SCALEN,35,18	;NUMBER OF THIS VOTE OR REQ UNIQUE CODE
CFROT==SCALEN+1			;ROOT CODE FOR THIS VOTE
CFQAL==SCALEN+2			;QUALIFIER CODE FOR THIS VOTE
CFTYP==SCALEN+3			;Access required, or answer
CFDAT==SCALEN+4			;Optional data, it present
CFDT1==SCALEN+5
CFDST0==CFDT1+1			;STR free count in bit table
CFDST1==CFDST0+1		;Transaction count of CFDST0
CFVGRD==CFDST1+1		;Guard word,,Denial reason code
 DEFSTR CFGWD,CFVGRD,17,18	;Unique value - used for debugging
 DEFSTR CFDRC,CFVGRD,35,18	;Field for reason code returned with a NO
	.CDDWT==1		;Denied - we are in VOTDWT
	.CDVUC==2		;Denied - HSHCODs are unequal
	.CDYUX==3		;Denied - voting, HSHYES, we have .HTOEX
	.CDYUN==4		;Denied - voting, HSHYES, unequal access
	.CDVDL==5		;Denied - voting, HSHDLY set
	.CDVLN==6		;Denied - voting, tie, our serial # bigger
	.CDVUX==7		;Denied - voting, tie, HSHUGD, he wants .HTOEX
	.CDVUN==10		;Denied - voting, tie, HSHUGD, unequal access
	.CDOCT==11		;Denied - we own, conflicting access, HSHCNT
	.CDOFC==12		;Denied - we own, conflicting access, HSHFCT

;Values in CFTYP reply:
;	0	OK
;	-1	OK with delay (see call to CFSRMX in CFSRTV)
;	-2	Conditional OK (set when DDMP finishes with delayed yes in CFSFOD)
;	1	NO

VOTSIZ==CFVGRD+1		;Actual size of a packet
VOTSZB==VOTSIZ-1		;SIZE OF BUFFER IN BYTES
 VOTLEN==NVOTQ0*VOTSIZ		;words on all vote packets
;Definitions of "resource names"
;These values are used as qualifiers in numbered resources

DRBASE==<17777,,0>		;DIR BASE OFFSET for DIRECTORY locks
DRBAS0==<37777,,0>		;Allocation table offset for allocation
FILEWL==DSKAB_1			;File write lock (frozen writer)
FILEWT==DSKAB_3			;Access token bias
STRCTK==5B2			;Structure designator
STRCTN==<-2,,0>-DSKAB		;Name register
FILEEQ==DSKAB_2			;File enqueue token
CFJBAS==<47777,,0>		;Base for job number assignment

REPEAT 0,<
RESOURCE		ROOT		QUALIFIER

file open		str. name	XB address

frozen writer		str. name	XB address + FILEWL

file access (OFN)	str. name	XB address + FILEWT

directory lock		str. name	directory no. + DRBASE

directory allocation	str. name	directory no. + DRBAS0

structure name		str. alias	STRCTN

drive serial no.	serial no.	STRCTK + high order D.S.N.

file enqueue		str. name	XB address + FILEEQ

BAT blocks		str. name	-1


RESOURCE		HSHCOD

file open		--

frozen writer		--

file access (OFN)	OFN

directory lock		DRBASE

directory allocation	--

structure name		Drive serial no. words XORd

drive serial no.	Structure alias

file enqueue		--

BAT blocks		--
>

;Random definitions

DEFSTR STCRA,CFHSTS,17,1	;Bit to control "credit available"
	SUBTTL	Macros

;CFS interlock macros

;The CFS interlock exists to insure that the CFS hash table
;does not change.

   DEFINE CFSINO <
	CALL SCAPOL
   >

;MACRO to test if the structure is part of CFS or is local to this machine.
;	T1/	Structure number

   DEFINE TSTRMT <
	CALL RMT.TS
   >


;macro to save P1-P5

   DEFINE SAVEP5,<
	JSP CX,SAVP5>

;Routine to test for a structure being part of CFS or being local
;to this host.
;	T1/ STR index
;Returns:
;	+1 is local
;	+2 is shared

RMT.TS:	PUSH P,T1		;Save STR index
	MOVE T1,STRTAB(T1)	;Get SDB address
	TMNE STEXL,(T1)		;Local?
	JRST PA1		;Yes
	POP P,T1		;No
	RETSKP

;Routine to save P1-P5

SAVP5:	ADJSP P,5		;Get five locs
	DMOVEM P1,-4(P)		;Save
	DMOVEM P3,-2(P)		;Save some more
	MOVEM P5,0(P)		;Finish it up
	CALL 0(CX)		;And return
	 SKIPA
	AOS -5(P)		;Skip return
	DMOVE P1,-4(P)		;Restore
	DMOVE P3,-2(P)		;Some more
	MOVE P5,0(P)		;The rest
	ADJSP P,-5		;Clean up the stack
	RET			;And done
	SUBTTL	Initialization -- CFSINI (SCA initialization routine)

;SCA Initialization routine for CFS code.

;If MEXEC has not yet called CFSJYN, this call to CFSJYX won't do much.

CFSINI::
   IFN CFSSCA,<
	CALL CHKCFS		;Verify the UCODE
	CALL CFSJYX		;See if we need to join the network
   >	;IFN CFSSCA
	RET			;Done

 	SUBTTL	Initialization -- CFSDIN (Initialize CFS database)

;Routine to intialize CFS data base. Called from CFSCSC

CFSDIN:
   IFN CFSSCA,<
	ISB SCDCHN		;And get its attention
   >	;IFN CFSSCA
	SETOM ALCLOK		;INIT CFS allocation lock
	XMOVEI T1,SCAQ		;Get head of queue
	MOVEM T1,SCTAIL		;Init queue
	MOVSI T1,CFSSEC		;form address of hash table
	MOVEM T1,CFHSHT		;Store it
	MOVE T1,APRSER		;GET SERIAL NUMBER
	LSH T1,4		;Use left-most 32 bits
	MOVEM T1,MYPORT
	RET			;And done for now
	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)

;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
	CALL CFSLSN		;OPEN A LISTENER FIRST
	 NOP			;BETTER WORK
	BLCAL. (SC.SOA,<<.,CFSSTS>>) ;Want to know about configuration changes
				;NOTE: This will callback at CFSSTS 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.

	CALL CFSPRT		;(/T1) Get our own port number
	MOVEM T1,MYPOR4		;Store it
	MOVSI P1,-C%SBLL	;Loop for all the nodes
	DO.
	  HRRZ T1,P1		;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
	   EXIT.		;The port is not running - quit
	  TXNN T2,UDB%WA+UDB%WB ;No-response on both wires?
	  JRST CFSJY1		;Yes, skip it
	  TXNE T2,UDB%MA	;No, is node in maintenance mode?
	  JRST CFSJY1		;Yes, skip it
	  SKIPN SBLIST(P1)	;No, have we created a system block yet?
	  JRST CFSJY2		;No, we must wait then
	  HRRZ T2,P1		;Get the node number again
	  CALL ISIT20		;(T2/) Is this a TOPS-20 system?
	   JRST CFSJY1		;No, skip it
	  HRRZ T1,P1		;Get node number
	  CALL CFCNCK		;(T1) Is there is a CFS connection?
	  IFNSK.		;No, there should be so we will wait
CFSJY2:	    MOVX T1,^D1000	;Wait for a second
	    DISMS
	    LOOP.		;Try again
	  ENDIF.
CFSJY1:	  AOBJN P1,TOP.		;Continue with next node
	ENDDO.			;All done - we have joined the cluster
   REPEAT 0,<
	MOVSI P1,-C%SBLL
	DO.
	 MOVEI T1,0(P1)		;Get the index
	 BLCAL. (SC.RCD,<T1>)	;GET DATA FOR THIS INDEX
	 IFNSK.			;IF AN ERROR
	  AOBJN P1,TOP.		;DO MORE IF MORE TO DO
	  EXIT.			;Else, all done
	 ENDIF.
	 CALL RELRES		;Get rid of the data block
	 MOVEI T1,0(P1)		;Get SBI
	 CALL CFSCTH		;Connect to a host on this SBI
	  NOP
	 AOBJN P1,TOP.		;DO ALL CI BLOCKS
	ENDDO.			;NO
   >				;END OF REPEAT 0
	SETONE SCVER		;str verify in job 0
	AOS JB0FLG		; so awake it
   >	;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+PGSIZ+PGSIZ-1 ;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,PGSIZ+CFSSLN	;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 -- CFONLT (Test state of connection)

;Routine to test state of network connection. Called from the scheduler
;on demand

CFONLT::
   IFN CFSSCA,<			;If SCA is around
	SETZ T1,0		;Either path
	CALL CIONLT		;Check out the port
	 CALL DEDKLP		;Oops.
   >	;IFN CFSSCA
	RET			;Done

 	SUBTTL	Support Routines -- PRTOFL (Turn off dual port access)

;Routines to diddle state of the dual-port access
;Turn it off if necessary

PRTOFL:
   IFN CFSSCA,<			;Only if real CFS
	SETOM SCAFL1		;remember we did this
   >	;IFN CFSSCA
	RET			;And done

 	SUBTTL	Support Routines -- PRTONL (Turn on dual port access)

;Turn it back on

PRTONL:
   IFN CFSSCA,<
	SETZM SCAFL1		;It's clear
   >	;IFN CFSSCA
	RET

 	SUBTTL	Support Routines -- CFSKPR (KLIPA ucode reloaded)

;Routine called when KLIPA UCODE is reloaded

CFSKPR::
   IFN CFSSCA,<			;If a full CFS
	;CALLRET DEDKLP		;Then we are in trouble
   >
   IFE CFSSCA,<RET>		;If not a full CFS

 	SUBTTL	Support Routines -- DEDKLP (KLIPA is dead)

DEDKLP:
	SETZM CFSTIM		;Make sure poller works soon
;	TMNN SCCNC		;Anybody ever out there?
	SKIPE SCAFL1		;Already off?
	IFSKP. <CALLRET PRTOFL> ;If allowable
	RET
	SUBTTL	Support Routines -- CFSCTH (Connect to host)

   IFN CFSSCA,<			;Only if supporting SCA interface
;Routine to connect to a host.
;	T1/ SBI
;Returns:
;	+1 couldn't send message
;	+2 connet request sent. T1/ Host number of connect

CFSCTH:	SAVEQ			;Get some work regs
	MOVEI Q2,0(T1)		;Copy SBI
	MOVE T1,[XWD .RESP1,.RDLEN]  ;Priority,,length of free space
	MOVEI T2,.RESGP		;Get space from resident free pool
	CALL ASGRES		;(T1,T2/T1) Obtain block
	 RETBAD()		;Error - could not get a free space block
	BLCAL.(SC.RCD,<<Q2>,<T1>>)  ;Get config data
	IFNSK.			;No. Forget it then
	  EXCH T1,T2		;Get block address and save error code
	  CALL RELRES		;(T1) Return block to pool
	  MOVE T1,T2		;Get error code
	  RETBAD()		;Return failure
	ENDIF.
	LOAD Q3,RDVCST,(T2)	;GET VC STATE
	CAIE Q3,VC.OPN		;OPEN?
	IFNSK.			;No. Forget it then
	  MOVE T1,T2		;Get block address
	  CALL RELRES		;(T1) Return block to pool
	  RET           	;No. Forget it then
	ENDIF.
;**;[7144]  Replace 1 line at CFSCTH:+20		DML	29-Aug-85       
	MOVE Q3,.RDDST(T2)	;[7144] Get destination software type
	MOVE T1,T2		;Get block address
	CALL RELRES		;(T1) Return block to pool
;**;[7144]  Replace 1 line at CFSCTH:+23		DML	29-Aug-85       
	CAME Q3,[BYTE (8) "T","-","2","0"]  ;[7144] Is this a TOPS-20 node?
	RETBAD()		;No. Can't be running CFS then
	MOVSI Q1,-HSTSIZ	;Size of host table
	PIOFF			;Own machine for a bit
	DO.
	 SKIPN CFSHST(Q1)	;This one free?
	 EXIT.			;If so, use it
	 AOBJN Q1,TOP.		;Scan them all
	 PION			;Oops. None free
	 RETBAD()		;Can't do it
	ENDDO.
	HRLOM Q2,CFSHST(Q1)	;Store SBI
	SETOM CFSHNM(Q1)	;Indicate doing connect
	SETZM CFHSTS(Q1)	;INIT status
	PION			;And allow others to proceed
	MOVEI T2,0(Q1)		;Index into table
	AOS CFSCMC		;Note we are doing a connect
	BLCAL. (SC.CON,<<.,LISNAM>,<.,LISNAM>,Q2,[SCRDIT],[RCRDIT],<.,CFSSTS>,T2,<.,MYPORT>,[BUFSCT],[0]>) ;Do connect
	IFNSK.
	 SETZM CFSHST(Q1)	;Didn't make it
	 SETZM CONCID
	 SOS CFSCMC
	 RETBAD()
	ENDIF.
	MOVEM T1,CONCID		;SAVE THE CID
	MOVEI T1,0(Q1)		;Get index we used
	RETSKP			;OK.
   >	;IFN CFSSCA
 	SUBTTL	Support Routines -- HASHN (Compute hash for resource)

;ROUTINE TO COMPUTE HASH FOR NUMBERED RESOURCES

;	T1/ROOT NUMBER
;	T2/ QUALIFIER NUMBER
;RETURNS:
;	+1 ALWAYS. T1=HASH

HASHN:	TSC T1,T2		;Combine them
	IDIVI T1,HSHLEN		;DO MOD FUNCTION
	MOVM T1,T2		;GET RESIDUE
	RET			;AND DONE

 	SUBTTL	Support Routines -- HSHLOK (Locate hash entry for resource)

;ROUTINE TO LOOK FOR A HASH ENTRY IN A TABLE FOR A NUMBERED RESOURCE
;	T1/ ROOT NUMBER
;	T2/ QUALIFER
;RETURNS:
;	+1 NOT FOUND AC1/ POINTER TO ENTRY POINT
;	+2 FOUND. AC1/ PTR TO ENTRY
;		 AC2/ PREVIOUS ENTRY
;Clobbers T1 and T2 only

HSHLOK:	SAVEQ
	DMOVE Q1,T1		;Save args
    IFN DEBUG,<			;If debugging
	TMNN VSECNO,0(P)	;Make sure this is a non-zero section
	BUG.(HLT,CFSSEZ,CFSSRV,SOFT,<CFSSRV - Section 0>,,<

Cause:	HSHLOK was called from section zero. HSHLOK must be called from a
	non-zero section.

Action:	Examine the stack and change the caller of HSHLOK to run in a
	non-zero section
>)
   >	;IFN DEBUG
	CALL HASHN		;GET HASH
	ADD T1,CFHSHT
	DO.
	 SKIPN Q3,(T1)		;ANYTHING HERE?
	 RET

;HAVE A NEW ENTRY TO EXAMINE

	 MOVE T2,T1
	 MOVE T1,Q3
	 CAMN Q1,HSHROT(Q3)	;This match?
	 CAME Q2,HSHQAL(Q3)	;Yes, this one too?
	 LOOP.			;NO
	ENDDO.
	RETSKP			;YEP. ALL DONE THEN
 	SUBTTL	Support Routines -- GNAME (Get structure name)

;Routine to get the structure name given a structure number
;	T1/ structure number
;Returns:	+1 always. Sixbit name in T1
;Clobber only T1

GNAME:	MOVE T1,STRTAB(T1)	;Get SDB address
	SKIPE SDBALS(T1)	;An alias?
	SKIPA T1,SDBALS(T1)	;Yes. Get it
	MOVE T1,SDBNAM(T1)	;No. Use physical name
	RET

;variant of above using AC2

GNAME2:	PUSH P,T1
	MOVE T1,T2
	CALL GNAME
	MOVE T2,T1
	CALLRET PA1		;Done
 	SUBTTL	Support Routines -- CFSULL (Unlock CFS database)

;Called when CFSULK is done
;Returns:	+1 always

CFSULL::
   IFN CFSSCA,<			;If SCA present
	SOSN SCAILK		;Last one?
	IFNSK.			;If so.
	 TMNN SCWKP		;Any need to action?
	 SKIPE SCAQ		;No. ANything here?
	 ANNSK.			;If so
	 SAVET			;Save vulnerable regs
	 CALL CFSCH1		;Yes. Do a check pass now
	ENDIF.
	OKSKED			;Allow scheduling now
   >	;IFN CFSSCA
   IFE CFSSCA,<			;If no SCA
	SKIPG SCAILK		;Need to undo a lock?
	IFSKP.			;If so
	 SOS SCAILK		;Do it
	 OKSKED			;And fix scheduler interlock
	ENDIF.
   >	;IFE CFSSCA
	RET
 	SUBTTL	Support Routines -- CFSMAP (Map entries onto function)

;Routine to map selected entries onto a function.
;	T1/ mask
;	T2/ comparator
;	T3/ routine to call on match. Must be a "global address"
;	T4/ monitor match,, count match
;This routine computes <mask AND cfscod> for each entry
;with the proper count. If the result matches the comparator,
;the routine is called.
;The coroutine in T3 is called:
;	T1/ Resource block
; All Ps are preserved into the coroutine
;Call with CFSLOK or from interrupt left unlocked. Returns same
;Returns:
;	+1 Stop mapping and return
;	+2 continue

CFSMAP::ASUBR <AC1,AC2,AC3,AC4>	;SAVE INCOMING ARGS
	SAVEQ			;SAVE REGS
	MOVEI Q3,HSHLEN		;LENGTH OF THE HASH TABLE
	MOVE Q1,CFHSHT		;GET TO BASE OF HASH TABLE

;LOOK FOR A HASH CHAIN

CFSMP0:	SKIPN Q2,0(Q1)		;ANYTHING HERE?
	JRST CFSMP1		;NO

;FOUND A CHAIN TO START ON

CFSMP2:	HLRZ T1,HSHROT(Q2)	;SEE IF USER OR MONITOR
	MOVE T4,AC4		;GET MATCH TYPES
	TLNN T4,-1		;WANT A FILTER?
	JRST CFSMP5		;NO. ALL OF THEM THEN
	SKIPG T4		;MONITOR?
	JRST [	JUMPE T1,CFSMP4	;YES. IS IT?
		JRST CFSMP5]	;YEP
	JUMPN T1,CFSMP4		;NO.
CFSMP5:	TRNE T4,-1		;ANY MATCH?
	JRST CFSMP3		;YEP
	JN HSHCNT,(Q2),CFSMP4	;NO. MUST BE ZERO
CFSMP3:	MOVE T1,AC1		;GET AND MASK
	AND T1,HSHCOD(Q2)	;DO AND
	CAME T1,AC2		;IS THIS IT?
	JRST CFSMP4		;NO. DON'T USE IT

;FOUND A MATCH

	MOVE T1,Q2		;COPY BLOCK
	MOVE Q2,HSHLNK(Q2)	;DO COPY NOW IN CASE IT IS REMOVED
	CALL @AC3		;DO THE CALL
	 RET			;All done.
	SKIPA

;WALK THE CHAIN

CFSMP4:	MOVE Q2,HSHLNK(Q2)	;NEXT ONE
	JUMPN Q2,CFSMP2

;HERE WHEN CHAIN IS DONE

CFSMP1:	SOJLE Q3,R		;If seen them all, done
	AOJA Q1,CFSMP0		;DO THEM ALL
 	SUBTTL	Support Routines -- CFSRSE (Remove stale entries)

;Maintenance routine called periodically to remove stale entries
;from the hash table.
;This routine scans the resources now held locally and removes
;any unused ones that have been dormant for a "long time". Currently,
;a "long time" is two minutes.
;OFN "access tokens" are never considered stale!

CFSRSE:	MOVE T1,IRJAV		;GET LOAD AVG.
	CAILE T1,^D10
	MOVEI T1,^D10
	IMULI T1,^D15000	;PURGE BASED ON LAOD AVG.
	MOVEI T2,SKDCNT		;Max number to release this pass
CFSRSX:	SAVEAC <P1,P2>		;GET WORK REGS
	MOVE P1,TODCLK		;GET NOW
	SUB P1,T1		;AGE CUTOFF
	SKIPG P2,T2		;COPY COUNT
	MOVX P2,<377777,,0>	;GET A BIG NUMBER
	SETZB T1,T2		;NO MASK, MATCH ALL
	XMOVEI T3,CFSRS0	;WHERE TO GO
	SETZM T4		;ONLY UNUSED ONES PLEASE
	CFSLOK			;Lock up the lock
	CALL CFSMAP		;DO IT
	CALLRET CFSFAL		;And done

;Routine called when an entry is located

;**;[7507] Change 1 line at CFSRS0:+0L	MDR	29-JUL-87
CFSRS0:	JN <HSHUGD,HSHKPH,HSHWVT,HSHTAM>,(T1),RSKP ;[7507] If voting, forced here or cached, then keep it
   IFN DEBUG,<			;If debugging
	TMNE HSHCNT,(T1)	;A debugging check!!!!
	BUG.(HLT,CFSMPB,CFSSRV,SOFT,<CFSSRV - CFSMAP returned in-use entry>,,<

Cause:	CFSMAP has returned a resource block that is already in use. This
	bug is a debugging check.
>)
   >	;IFN DEBUG
	TMNN HSHLKF,(T1)	;Locked?
	CAMGE P1,HSHTIM(T1)	;TOO OLD?
	IFSKP.
	 CALL CFSRMX		;YES, REMOVE IT
	 SOJLE P2,R		;IF HIT LIMIT, ALL DONE
	ENDIF.
	RETSKP			;AND DONE
 	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 clla-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 -- CFSSBB (Place OFN in SDB)

;Routine called when the bit table for a structure is opened and
;the OFN is about to be placed in the SDB.
;	T1/ OFN
;	T2/ STR #
;Returns: +1 always.
; Preserves all temps

CFSSBB::
   IFE CFSSCA,<RET>		;If no SCA, nothing to do
   IFN CFSSCA,<			;If SCA
	SAVET			;Save args
	MOVE T3,T2		;STR #
	ADD T3,CFSSTR		;The entry in the STR table
	SETZM 0(T3)		;No transactions yet
	ADD T1,CFSOFN		;Find the OFN in the OFN table
	CFSLOK
	SKIPN T1,0(T1)		;Get it
	IFSKP.
	 SETONE HSHBTF,(T1)	;Note this is a BT
	 SETZM HSHOP1(T1)	;No data here as yet
	 SETZM HSHOPT(T1)
	ENDIF.
	CALLRET CFSFAL		;And done
   >	;IFN CFSSCA
 	SUBTTL	Support Routines -- CFSWUP (General wait routine)

;General purpose wait routine. Used to select kind of wait to use
;	T1/ scheduler test word
;	T2/ Block address, if appropriate

CFSWUP:	MOVE CX,FORKX		;Get fork handle
	STOR T2,FKST2,(CX)	;Save block address
	SKIPN NSKED		;NOW NOSKED?
	IFSKP.
	 RDISMS			;IF SO, USE SPECIAL TEST
	 NOSKED
	ELSE.
	 HDISMS
	ENDIF.
	RET			;AND DONE
 	SUBTTL	Support Routines -- CFSRSV (Restart vote)
   IFN CFSSCA,<			;Only need this with SCA present

;Routine to set "restart vote" when a node leaves the CFS net.
;This scans the active connections setting the proer bit.
;Call either CFSLOK or from interrupt level without being locked

CFSRSV:	SAVET
	SETZB T1,T2		;MATCH ALL
	XMOVEI T3,CFSRVC
	MOVEI T4,-1
	CALLRET CFSMAP		;DO IT

;The coroutine for above.

CFSRVC:	JE HSHWVT,(T1),RSKP	;IF NOT WAITING, ALL DONE
	SETONE HSHVRS,(T1)	;MAKE IT RESTART
	RETSKP			;AND DONE
   >	;IFN CFSSCA
 	SUBTTL	Support Routines -- CFTADC (Get CFS time and date)

;Routine to return CFS TAD if known.
;	CALL CFTADC
;Returns:	+1 unknown
;		+2 T1/ TAD

CFTADC::SKIPN T1,CFTADL		;have one?
	RET			;No
	SETZM CFTADL		;Clear it
	RETSKP			;Yes
 	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 -- CFCNCK (Check for CFS connection to node)

;Routine used during CI joining to check if we have a
;CFS connection to a specified node.
;
;Accepts:	T1/ node number 
;
;Returns:	+1:	No CFS connection 
;		+2:	CFS connection exists

CFCNCK: SKIPN CFSHCT		;Get count of hosts
	RET			;No connections yet
	MOVEM T1,T4		;Save node number
	MOVSI T3,-HSTSIZ	;Size of host table
	DO.
;**;[7445]  Replace 1 line with 2 at CFCNCK:+5		DML	13-Apr-87
	  SKIPE T1,CFSHST(T3)	;[7445] Is there a CID for this host offset?
	  SKIPL CFHSTS(T3)	;[7445] Is it fully active?
	  IFSKP.		;A valid one did exist
	    CALL SC.NOD		;(T1/T1,T2) Get node number for this CID
	    SKIPL T2		;A valid CID?
	    IFNSK.		;Yes, node number is returned
	      CAMN T4,T2	;Is this the CID for the desired node?
	      RETSKP		;Yes, return success
	    ENDIF.
	  ENDIF.
	  AOBJN T3,TOP.		;Try next host table entry
	ENDDO.
	RET			;Node not found - return failure
	SUBTTL	Resource manager -- CFSGET (Acquire a resource)

;ROUTINE TO ACQUIRE A RESOURCE
;	T1/ POINTER TO REQUEST BLOCK
;	T2/ 0=) return if failed
;	    1=) retry until successful
;Returns:
;	+1 failed.
;		T2=-1	An error occurred in which this system knows about
;			the resource already and there is a conflict on 
;			this system.  No vote has been sent out.
;		T2>0	This system did not know about the requested resource
;			so a vote was sent out to ask for permission to it.
;			A system told us NO and the first reason for the NO
;			(found in HSHDRC) is returned.
;
;	+2 succeeeded.
;		T1=0 =) Block is now owned by CFS server. Block
;			returned to free pool owner.  We linked 
;			the block passed in.
;		T1<>0=) Block is returned as part of operation.
;			We found a queued resource block and used it.
;			Block passed in must be returned by caller.

;entry to figure out out if this is local or not.
;Same as above, but T3/ STR #

CFSGTT:	MOVE T3,STRTAB(T3)
	TMNE STEXL,(T3)		;Shared or exclusive?
	JRST CFSGTL		;Don't need to vote. We have it exclusively.
	JRST CFSGET		;Do need to vote.

;CFSGET is main entry point for resource manager. Call CFSGTL is
;resource is known to be exclusive to this processor.

;Entry for local lock only (caller must verify higher-level interlock)

CFSGTL::SETZRO <HSHYES,HSHWVT>,(T1)
	TDZA T3,T3		;Entry type is local

CFSGET::MOVEI T3,1		;Entry type is remote (have to vote)
	SAVEQ
	STKVAR <EFLAG,RTYFLG,NSFLAG> ;HOLD RETRY FLAG HERE
	MOVEM T3,EFLAG		;Save entry flag
	MOVE Q1,T1		;SAVE BLOCK ADDRESS
	MOVEM T2,RTYFLG		;SAVE FLAG
	MOVE T3,FORKX		;FORK HANDLE
	STOR T3,HSHFRK,(Q1)	;Store it
	; ..
;Here to start getting the resource.
;Also enter here from CFSGTX if retry was specified and wait is up.

CFSGT2:	CFSLOK			;PROTECT DATABASE
       	DMOVE T1,HSHROT(Q1)	;GET ARGS.
	CALL HSHLOK		;SEE IT WE KNOW ABOUT THIS ALREADY
	 JRST CFSGT0		;DON'T KNOW ABOUT IT YET

;Here if we already have it. Check if access is legit.
;At this point:
;	T1/ Address of queued resource block
;	Q1/ Address of new resource block

	CAMN T1,Q1		;ARE WE ONE AND THE SAME?
	JRST CFSG00		;YES. ASSUME WE ARE VOTER THEN
	JN <HSHWVT>,(T1),CFSGTX	;IF VOTING, FAIL

;Not waiting. Therefore we own it.

	LOAD T3,HSHTYP,(Q1)	;GET REQUEST TYPE
	LOAD T2,HSHTYP,(T1)	;GET TYPE WE OWN
	CAIN T2,0(T3)		;ARE THEY THE SAME
	JRST CFSGOD		;YES. IT MIGHT SUCCEED THEN
	JN HSHCNT,(T1),CFSGTX	;NOT THE SAME. IF IN USE, FAIL
	CALL CFSRMV		;NOT IN USE. WE MIGHT BE ABLE TO GET IT
	JRST CFSGT1		;NOW VOTE ON IT

;Request and owner type match. Make sure we can seize it

CFSGOD:	TMNE HSHCNT,(T1)	;Unclaimed?
	IFNSK.			;If not
	 CAIE T3,.HTOEX		;DO we want exclusive access?
	 ANSKP.			;If so
	  JE HSHLCL,(T1),CFSGTX	;If not local exclusive, lose
	ENDIF.
	MOVE T3,FORKX		;Get fork handle

;Accesses match and we can have it.

	STOR T3,HSHFRK,(T1)	;New owner of this block
	INCR HSHCNT,(T1)	;DO IT
	MOVE T2,TODCLK		;GET NOW
	MOVEM T2,HSHTIM(T1)	;STAMP IT
	MOVE T1,Q1		;DON'T NEED THE BLOCK ANYMORE
	CALLRET CFSRSK		;RETURN GOOD
	; ..
;Can't honor the request just now.

CFSGTX:	SKIPN RTYFLG		;WANT TO RETRY?
	IFNSK.			;If not
	 MOVE T1,Q1
	 CALL @HSHRET(T1)	;Release the block
	 SETOM T2		;Conflict on this system. No reason code.
	 CALLRET CFSFAL		;And done
	ENDIF.

;Here if caller specified retry until successful.
;Wait for a bit, and try again.
;At this point:
;	T1/ Address of queued resource block of owner or voter (zero if none)
;	Q1/ Address of new resource block

	IFN. T1			;IF THERE IS A LOCK NOW
	 TMNN HSHLOS,(T1)	;LONG BLOCK?
	 ANSKP.			; If so
		MOVE T2,FORKX
		IDIVI T2,44
		MOVE T3,BITS(T3)
		ADD T2,T1
		IORM T3,HSHBTT(T2) ;SET WAITING BIT IN ORIGINAL BLOCK
	ENDIF.
	SKIPN T1,HSHWTM(Q1)	;Any wait time given?
	MOVEI T1,^D1000		;If not, use 1 sec
	CAIGE T1,^D20		;A reasonable time?
	MOVEI T1,^D20		;No. So make it so
	ADD T1,TODCLK		;Compute wakeup time
	MOVEM T1,HSHTIM(Q1)	;SAVE IT FOR LATER
	SETZRO HSHVRS,(Q1)	;NEED THIS
	CFSULK
	MOVE T2,Q1		;Save block address
	MOVEI T1,CFSRWT
	CALL CFSWUP		;DO A WAIT
	SETZRO <HSHRTY,HSHVRS>,(Q1) ;NO RETRY NOW
	JRST CFSGT2		;TRY AGAIN
;Sheduler test for above

CFSRWT:	LOAD T1,FKST2,(Q3)
	DMOVE T1,HSHROT(T1)	;GET HASH VALUES
	CALL HSHLOK		;LOOK IT UP
	 JRST 1(4)
	JN HSHLSG,(T1),0(4)	;IF STILL BEING RELEASED, WAIT
	OPSTR <CAMN T1,>,FKST2,(Q3)	;ARE THE TWO BLOCKS THE SAME?
	JRST [	MOVE T2,HSHTIM(T1) ;GET AWAKE TIME
		TMNN <HSHVRS,HSHRTY>,(T1) ;IF ANY RESTART CONDITIONS
		CAMG T2,TODCLK	;TIME UP YET?
		JRST 1(4)	;YEP
		JRST 0(4)]	;NOPE
	LOAD T2,FKST2,(Q3)	;GET BLOCK WE ARE WAITING FOR
	JN HSHWVT,(T1),0(4)	;IF NOT THE SAME, AND VOTING, GIVE UP
	TMNN HSHCNT,(T1)	;ANY USERS?
	JRST 1(4)		;NO
	LOAD T3,HSHTYP,(T2)
	CAIN T3,.HTOEX		;TRYING FOR EXCLUSIVE USE?
	JRST 0(4)		;YES. MUST WAIT SOME MORE THEN
	OPSTR <CAME T3,>,HSHTYP,(T1) ;DO THEY NOW MATCH?
	JRST 0(4)		;NO. WAIT SOME MORE
	JRST 1(4)		;YES. TRY TO GET IT
;Here if we don't have the request queued. Must ask for it.
;Enter CFSGT1 when we have found a queued block on the system which was not
;in use and the access was not the same as what we desire.  So, we have 
;removed it.  Now we will use the new block we passed into CFSGET.

CFSGT1:	DMOVE T1,HSHROT(Q1)	;LOOK IT UP AGAIN
	CALL HSHLOK		;We should not find it again
	 SKIPA
	JRST CFSGTX		;Old block should have been removed!!

;First make an entry so we can remember we are doing this.
;	T1/ POINTER TO PLACE TO MAKE AN ENTRY

CFSGT0:	MOVEM Q1,HSHLNK(T1)	;ENQUEUE IT
	MOVEM T1,HSHBKP(Q1)	;And point back as well
	SETZM HSHLNK(Q1)	;And not next for this one

;Here to actually vote for the resource in an attempt to obtain it.
;No vote is required for a local exclusive resource (EFLAG = 0).

CFSG00:	LOAD T1,HSHTYP,(Q1)	;TYPE WE ARE VOTING ON
	SKIPE EFLAG		;Remote or local?
	CALL VOTEW		;Remote, VOTE AND WAIT
	JN HSHYES,(Q1),CFSGT3	;IF FAILED, NOTIFY HIM
	MOVE T2,TODCLK		;GET CLOCK
	MOVEM T2,HSHTIM(Q1)	;STAMP IT
	SETZRO HSHWVT,(Q1)	;NOT VOTING ANY MORE
	INCR HSHCNT,(Q1)	;SEIZE IT
	SETZM T1		;NEED THIS BLOCK
	CALLRET CFSRSK		;AND RETURN GOOD
;HERE IF VOTE FAILED.
;If retry specified, leave the vote packet in the hash table, with
;HSHWVT and HSHYES set. This is done for two reasons:
;	1. So that the resource freed message can find it and
;	   wake up the waiting fork
;	2. So that other requestors can detect that a vote
;	   has failed so that they will not start their own
;	   vote. Although this is not strictly necessary,
;	   it does minimize overhead in the monitor and on the CI.
;Note that leaving HSHWVT and HSHYES set will cause the vote processor
;to allow accesses to this resource since we have already been told "no".

;If "no retry", unlink the packet and release it.  Return the reason for 
;the failed vote (found in HSHDRC) in T2.

CFSGT3:	MOVE T1,Q1		;Copy pointer
	SKIPN RTYFLG		;SHALL WE TRY, TRY AGAIN?
	IFNSK.			;If not
	 LOAD Q1,HSHDRC,(T1)	;Get the reason for the NO
	 CALL HSHULN		;Unlink it
	 CALL @HSHRET(T1)	;release it
	 MOVE T2,Q1		;Move reason code to T2
	 CALLRET CFSFAL		;AND DONE
	ENDIF.
	SETZM T1
	JRST CFSGTX		;FAIL
	ENDSV.

;Common routine to routine good

CFSRSK:	CFSULK
	RETSKP			;AND DONE
	SUBTTL	Resource manager -- CFSRMV (Remove entry from hash table)

;ROUTINE TO REMOVE AN ENTRY FROM THE HASH TABLE
;	T1/ ENTRY
;CFSRMV just removes the entry
;CFSRMX also posts removal
;RETURNS: +1 always
; If CFSRMX is called:
;	T1/ 0 if resource unconditionally available
;		T2= 0 =) not removed even though available
;	   -1 if resource being released but not yet available.
;	   In this case, the resource has not been released.
;Must be called with CFS interlock

CFSRMX:	TDZA T2,T2		;REMEMBER TO POST
CFSRMV:	SETOM T2		;DON'T POST
;**;[7247]  Change 1 line at CFSRMV:+1			DML	19-Feb-86
	SKIPLE HSHPST(T1)	;[7247] Want posting?
	SKIPE T2		;YES. SHOULD WE HONOR IT?
	IFSKP.
	 INCR HSHCNT,(T1)	;MARK IN USE FOR NOW
	 CALL @HSHPST(T1)	;DO POST
	 IFSKP.
	  JUMPE T1,RETO		;If delay release, say so.
	  SETZRO <HSHCNT,HSHTYP>,(T1)	; Clean these up
	  SETZM T2		;Say it is still in the table though
	  CALLRET RETZ		;And done
	 ENDIF.
	ENDIF.
;**;[7247]  Add 2 lines after CFSRMV:+12		DML	19-Feb-86
	TMNE HSHTAM,(T1)   	;[7247] Is this a cached block?
        SOS CFACCT		;[7247] Yes, decrement currently cached count
	CALL HSHULN		;Unlink it
	CALL @HSHRET(T1)	;FREE THE BLOCK
	MOVEI T2,1		;Removed.
	CALLRET RETZ

;Companion routine to unlink an entry from the hash table
;	T1/ pointer to entry to remove
;Returns:	+1 always
;	preserves T1

HSHULN:	MOVE T2,HSHLNK(T1)	;Get forward pointer
	MOVE T3,HSHBKP(T1)	;Get back pointer
	MOVEM T2,HSHLNK(T3)	;Link previous to next
	SKIPE T2		;Was there a next?
	MOVEM T3,HSHBKP(T2)	;Yes. Give it a new previous pointer
	RET			;And done
	SUBTTL	Resource manager -- CFSNDO (Undeclare a resource)

;Routine to undeclare a resource.
;	T1/ ROOT CODE
;	T2/ QAULIFIER

;Returns:
;	+1 /couldn't
;	+2 done

CFSNDS:	TDZA T3,T3		;Make fairness test
CFSNDO::SETOM T3		;No count
	ASUBR<AC1,AC2,AC3>
	CFSLOK
	CALL HSHLOK		;LOOK IT UP
	 JRST [CALLRET CFSFAL]
	LOAD T3,HSHCNT,(T1)
	SOJL T3,[CALLRET CFSFAL]
	STOR T3,HSHCNT,(T1)	;NEW COUNT
	JUMPG T3,[CALLRET CFSRSK] ;IF STILL OWNED, GO ON

;RESOURCE NOW UNDECLARED. SEE IF ANYONE WAITING

	SAVEQ			;SOME WORK REGS
	TMNN HSHLOS,(T1)	;LONG BLOCK?
	JRST CFSND3		;IF NOT, MOVE ON
	MOVE Q1,T1		;BLOCK
	ADDI Q1,HSHBTT		;GET TO THE BIT TABLE
	MOVSI Q2,-<NFKS+^D35>/^D36 ;WORDS IN BIT TABLE

;Loop over bit table looking for a fork to wake up

CFSND1:	SKIPN T2,0(Q1)		;ANYTHING HERE?
	JRST CFSND2		;NOPE
	JFFO T2,.+1		;GET BIT NUMBER
	MOVE T2,BITS(T3)	;GET BIT NUMBER
	ANDCAM T2,0(Q1)		;TURN IT OFF
	MOVEI T1,0(Q2)		;GET WORD NUMBER
	IMULI T1,^D36
	ADDI T1,0(T3)		;FORK NUMBER
	CALL UNBLKF		;UNBLOCK IT
	CALLRET CFSRSK		;AND DONE
CFSND2:	ADDI Q1,1		;NEXT BIT TABLE WORD
	AOBJN Q2,CFSND1		;DO NEXT WORD
	; ..
;Here if no local fork waiting. See if another host is waiting

CFSND3:	SKIPE T3,HSHNBT(T1)	;ANYTING HERE?
	IFNSK.			;If so
	 SKIPN AC3		;Want to leave a record of this?
	 IFNSK.			;If so
	  SETONE HSHRFF,(T1)	;So do it
	 ENDIF.
	 CALL CFNOHS		;Tell them
	ENDIF.
	CALLRET CFSRSK		;And done
	SUBTTL	Resource manager -- CFSOHS (Notify rejected hosts after undeclare)

;Routine to notify other hosts who were rejected for a resource.
;This is called whenever a resource is undeclared and one or more
;bits is set in HSHNBT
;	T1/ hash packet
;Returns:	+1 always
;	call with interlock set, please

CFNOHS:	SAVEAC <P1>		;Where to save packet
   IFN CFSSCA,<			;Only if SCA
	MOVEM P,CFSSVP		;Save incoming stack
	MOVE P,CFSSTK		;Get local stack
	MOVE P1,T1
	DO.
	SKIPN T3,HSHNBT(P1)	;Any body here?
	EXIT.
	CALL GVOTE1		;GET A VOTE BUFFER
	 EXIT.
	JFFO T3,.+1		;GET HOST NUMBER WAITING
	MOVE T3,BITS(T4)	;GET THE CORRESPONDING BIT
	ANDCAM T3,HSHNBT(P1)	;TURN IT OFF
	MOVEI T3,.CFRFR
	STOR T3,CFCOD,(T1)	;CODE
	DMOVE T2,HSHROT(P1)	;GET RESOURCE
	DMOVEM T2,CFROT(T1)	;STASH IT
	MOVE T2,T4		;HOST NUMBER
	CALL SCASND
	IFNSK.			;If failed
	 PIOFF
	 CALL CFSWDN		;Return the buffer
	 PION
	ENDIF.
	LOOP.
	ENDDO.
	MOVE P,CFSSVP		;Restore original stack
   >	;IFN CFSSCA
	RET			;And done

;Pseudo routine to return failure.

CFSFAL:	CFSULK
	RETBAD()		;COULDN'T
	SUBTTL	Resource manager -- CFSUGD (Upgrade or downgrade a resource lock)

;Routine to upgrade (or downgrade) a resource lock.
;	T1/ root code
;	T2/ qualifier
;	T3/ force voting,,new access
; Call with CFS interlock set!
;Returns (interlock cleared)
;	+1 not currently held, or can't upgrade
;		T2=-1	An error occurred in which this system could not
;			find the resource to upgrade or a vote was in
;			progress on this resource and we can't upgrade.
;		T2>0	This system attempted to upgrade the access of the
;			resource by voting for the new access.  This vote
;			request failed.  The first reason we were told NO
;			(found in HSHDRC) is returned.
;
;	+2 did it. Share count incremented
;This routine is used to "seize" a resource without requiring
;the deallocation of resources. The intended use is for file
;access resources that are either "shared", "exclusive" or
;"unowned".

CFSUGZ:	SETO T4,		;Force all votes
	JRST CFSUG2		;And enter
CFSUGA::TDZA T4,T4		;Force vote
CFSUGD::MOVEI T4,1
CFSUG2:	SAVEQ
	DMOVE Q2,T3		;Save incoming args
	CALL HSHLOK		;LOOK UP THE REQUEST
	 JRST CFSUGF		;Can't find the resource!

;FOUND IT.

	JN <HSHWVT>,(T1),CFSUGF	;A vote is pending on this resource - fail
	INCR HSHCNT,(T1)	;Freeze it here
	MOVE Q1,T1		;COPY POINTER
	JUMPL Q3,CFSUG1		;If all force, go to it
	OPSTR <CAME Q2,>,HSHTYP,(T1) ;ALREADY AT THIS TYPE?
	JRST CFSUG0		;NO
	CALLRET CFSRSK		;YES, SUCCESS
;Not at this level

CFSUG0:	LOAD T2,HSHTYP,(Q1)	;GET TYPE OF CURRENT RESOURCE
	CAIE T2,.HTOEX		;ARE WE THE ONLY OWNER?
	JRST CFSUG1		;NO
	STOR Q2,HSHTYP,(Q1)	;Stash new access
	CALLRET CFSRSK		;And succeed

;HERE IF WE MAY NOT BE THE ONLY OWNER. FREEZE CURRENT RESOURCE AND
;TRY TO GET EXCLUSIVE ACCESS FOR THE CHANGE

CFSUG1:	SETONE HSHUGD,(Q1)	;NOTE UPGRADE VOTE
	IFLE. Q3		;If forcing
	 SETONE HSHAVT,(Q1)	;Say to force
	ENDIF.
	MOVE T1,Q2		;Copy desired type for VOTEr
	CALL VOTEWS		;DO IT.
	SETZRO <HSHAVT,HSHUGD,HSHWVT>,(Q1) ;NOT WAITING ANYMORE
	JN HSHYES,(Q1),[
		TMNN HSHCNT,(Q1) ;Any count?
		CALL CFNCNT	;No!
		DECR HSHCNT,(Q1) ;If can't upgrade...
		LOAD T2,HSHDRC,(Q1)  ;...get reason for NO...
		CALLRET CFSFAL]	;...and fail
	STOR Q2,HSHTYP,(Q1)	;SET IT
	CALLRET CFSRSK		;And succeed

CFSUGF:	SETOM T2		;We could not find the resource or 
	CALLRET CFSFAL		;...vote in progress on it.  Fail - no reason.
	SUBTTL	The voter -- VOTEW (Start vote and wait for results)

;ROUTINE TO START VOTE AND WAIT FOR RESULTS.
;	T1/ TYPE WE ARE VOTING ON
;	Q1/ REQUEST TO VOTE ON
;Returns +1 always. Result of vote indicated by HSHYES(Q1)

;This routine sends out requests to all other CFS processors
;and waits for the tallies. Tallies are processed as
;in-coming CFS requests and are therefore handled by the
;scheduler.
;VOTEW does a "regular vote".
;VOTEWS does a "seize" vote

VOTEWS:	TDZA T2,T2		;REMEMBER SEIZE
VOTEW:	MOVEI T2,1		;REMEMBER REGULAR VOTE
   IFN CFSSCA,<			;if SCA is present
	SAVEP5			;Work regs
	MOVE P2,T2		;Save type
	SETONE HSHWVT,(Q1)	;MARK VOTING
;	SETZRO HSHODA,(Q1)	;No optional data yet
	STOR T1,HSHVTP,(Q1)	;Store vote type
	NOSKED
	CFSULK
VOTRST:	SKIPN CFSCMC		;Any connects outstanding?
	IFSKP.			;If so
	 MOVEI T1,DISET		;Wait for equal
	 HRLI T1,CFSCMC		; of this work
	 CALL CFSWUP		;Do it
	ENDIF.
	DO.
	 SKIPE T1,DLYLOK	;A delay in effect?
	 IFNSK.			;If so
	  SUB T1,TODCLK		;Get relative time
	  IFG. T1		;If we still need to wait...
	   CALL SETBKT		;Compute wait time
	   HRRI T1,CFRCNW	;Wait
	   CALL CFSWUP		;Do it
	   MOVE T1,TODCLK	;Get now
	   CAMGE T1,DLYLOK	;Really time to wake up?
	   LOOP.		;No
	  ENDIF.
	  SETZM DLYLOK		;Yes
	  CALL CLRDLY
	 ENDIF.
	ENDDO.
	MOVEM P,CFSSVP		;Save stack pointer
	MOVE P,CFSSTK		;Get new stack
	AOS T1,VOTNUM		;GET A VOTE DIALOGUE
	STOR T1,HSHUNQ,(Q1)	;Set this now
	SETZRO <HSHVRS,HSHYES>,(Q1) ;ASSUME NO NO'S
	SETZRO HSHRTY,(Q1)	;And now resends yet either
	SETZRO HSHDLY,(Q1)	;No delays yet either
	SKIPN P3,CFSHCT		;GET HOST COUNT OF OTHER HOSTS
	IFNSK.			;If nobody out there...
	 MOVE P,CFSSVP		;Restore original stack
	 CFSLOK			;Lock up the data base
	 OKSKED
	 RET			;And return now
	ENDIF.
	SETZRO HSHVCT,(Q1)	;VOTE IS AT ZERO
	SETZRO HSHDRC,(Q1)	;No denial reason code yet
	SETZM HSHWTM(Q1)	;No wait time yet
	SETZM P1		;Nothing done yet
	MOVSI P4,-HSTSIZ	;Loop over entire data base
	; ..
;TOP OF VOTING LOOP. FOR EACH OTHER CFS PROCESSOR, SEND REQUEST.
;THE VOTING BUFFERS ARE PRELLOCATED AT SYSTEM START-UP. VOTE
;BUFFERS ARE ALLOCATED DIRECTLY FROM THE QUEUE AND ARE RETURNED
;TO THE QUEUE BY SCA. IF THE QUEUE IS EXHAUSTED, THE VOTE
;WILL BE DELAYED UNTIL SOME ARE FREED (NOT EXPECTED TO BE LONG)

VOTE1:	TMNE HSHYES,(Q1)	;ALREADY VETOED?
	IFNSK.
	 MOVE P,CFSSVP		;Restore stack
	 CFSLOK			;YES.
	 OKSKED
	 RET
	ENDIF.
	SKIPLE CFSHST(P4)	;THIS HOST UP?
	SKIPL P5,CFHSTS(P4)	;maybe. CTS?
	JRST VOTEW0		;NO
	TRNE P5,-1		;Is this a "reduced" CFS?
	IFSKP.			;If so.
	 TMNE HSHAVT,(Q1)	;Vote anyway?
	 ANSKP.			;If not
	 INCR HSHVCT,(Q1)	;Say it approved
	 AOJA P1,VOTEW0		;Account for it and go on
	ENDIF.
	CALL GVOTE		;GET A VOTE BUFFER
	 NOP
	; ..
	; ..
;BUILD VOTE REQUEST IN THIS BUFFER. IT WILL BE SENT TO HOST (P4)
;A vote message is as follows:
;	word 0= vote opcode,,vote dialogue
;	word 1= root code
;	word 2= qualifier
;	word 3= access required

	LOAD T2,HSHUNQ,(Q1)	;Get code
	STOR T2,CFUNQ,(T1)	;STORE VOTING NUMBER
	MOVEI T2,.CFVOT		;WE ARE VOTING
;	SKIPN P2		;VOTING OR SEIZING?
;	MOVEI T2,.CFCEZ		;SEIZE IT
	STOR T2,CFCOD,(T1)	;STORE IT
	DMOVE T2,HSHROT(Q1)	;GET ROOT AND QUALIFIER
	DMOVEM T2,CFROT(T1)	;STORE IT IN VOTER
	LOAD T2,HSHVTP,(Q1)	;GET REQUEST TYPE
	TRNN P5,-1		;Full vote?
	MOVEI T2,.HTOEX		;No. Must always be exclusive for these
	MOVEM T2,CFTYP(T1)
	HRRZ T2,P4		;HOST NUMBER
	TMNE HSVUC,(Q1)		;Vote to include HSHCOD?
	IFNSK.			;If so
	 SETONE CFVUC,(T1)	;Set it
	 MOVE T3,HSHCOD(Q1)	;Get the code
	 MOVEM T3,CFDAT(T1)	;Send it off
	ENDIF.
	CALL SCASND
	IFNSK.			;If failed
	 PIOFF
	 CALL CFSWDN		;Enqueue the buffer
	 PION
	 MOVE P,CFSSVP		;Restore stack
	 JRST VOTRST		;Do it again
	ENDIF.
	ADDI P1,1		;Did one
VOTEW0:	CAIGE P1,0(P3)		;Found them all yet?
	AOBJN P4,VOTE1		;DO THEM ALL!
	MOVE P,CFSSVP		;Restore stack
	; ..
;VOTES ALL SENT OFF. WAIT FOR ALL REPLIES

	CAIGE P1,0(P3)		;Found all of them (or more)?
	JRST VOTRST		;No. Start over
	CALL UPDTCK		;UPDATE TOD CLOCK
	DO.
	TMNE HSHVRS,(Q1)	;NEED TO RESTART?
	JRST VOTRST		;yes
	TMNE HSHYES,(Q1)	;Someone veto the request?
	IFNSK.			;If so...
	 CFSLOK
	 OKSKED
	 RET
	ENDIF.
	LOAD T2,HSHVCT,(Q1)	;GET COUNT OF RETURNS
	CAIN T2,0(P3)		;NO. ALL IN?
	EXIT.			;YES.
   REPEAT 0,<			;Don't do stall
	CALL GETMST		;GET CURRENT TIME
	SUB T1,TODCLK		;COMPUTE TIME IN THE LOOP
	CAIGE T1,MAXVWT		;WAITED TOO LONG?
	LOOP.			;NO
   >	;Repeat 0

;Here when we have waited a long time for the votes. Dismiss and
;try again later.

	MOVE T2,Q1		;Block address
	MOVEI T1,VOTSWT		;WAIT ROUTINE
	CSKED			;Be critical for the rest of this
	OKSKED
	CALL CFSWUP		;WAIT FOR IT
	NOSKED
	ECSKED
	LOOP.
	ENDDO.
	; ..
;Votes are all in, and no nay-sayers

	TMNN HSHDLY,(Q1)
	IFNSK.
	 CFSLOK
	 OKSKED
	 RET
	ENDIF.

;At least one respondent wants time to release the resource. Wait

	MOVE T1,TODCLK		;Get now
	ADDI T1,^D5000		;When to retry
				;The retry time is simply a precaution
				;against the other node being low on resources.
	MOVEM T1,HSHTIM(Q1)
	MOVE T2,Q1		;Packet address
	MOVEI T1,VOTDWT		;WAIT ROUTINE
	SETONE HSHDWT,(Q1)	;Note this
	CSKED			;Be critical for the rest of this
	OKSKED
	CALL CFSWUP		;WAIT FOR IT
	SETZRO HSHDWT,(Q1)
	TMNN HSHVRS,(Q1)	;RESTART OR SUCCESS?
	IFNSK.
	 CFSLOK
	 ECSKED
	 RET
	ENDIF.
	NOSKED
	ECSKED
	JRST VOTRST		;DO IT AGAIN

;Scheuler tests for above.

VOTDWT:	LOAD T1,FKST2,(Q3)
	TMNE HSHVRS,(T1)
	JRST 1(4)		;Awake to retry
	TMNN HSHDLY,(T1)
	JRST 1(4)
   REPEAT 1,<JRST 0(4)>
   REPEAT 0,<
	MOVE T2,HSHTIM(T1)	;Time to retry?
	CAML T2,TODCLK		;Still want to wait?
	JRST 0(4)		;Yes
	SETONE HSHVRS,(T1)	;No. restart the vote
	JRST 1(4)
   >	;REPEAT 0

VOTSWT:	LOAD T1,FKST2,(Q3)
	TMNE HSHVRS,(T1)	;NEED TO RESTART?
	JRST 1(4)		;YES. AWAKE THEN
	LOAD T2,HSHVCT,(T1)	;GET COUNT OF VOTERS
	TMNN HSHYES,(T1)	;NO IN YET?
	CAMN T2,CFSHCT		; NO. ALL VOTED IN?
	JRST 1(4)		;YES.
	JRST 0(4)		;NO

CFRCNW:	SKIPG DLYLOK		;Still in delay?
	JRST 1(4)		;No. Awake now
	JRST BLOCKT		;Yes. Check on time
	SUBTTL	The voter -- GVOTE (Get a vote buffer)

;Routine to get a vote buffer
;	Returns +1 on failure
;	        +2 success

GVOTE1:	TDZA T1,T1		;NO WAIT
GVOTE:	SETOM T1		;WAIT
	ASUBR <WFLAG>
	DO.
	PIOFF
	SKIPN T1,VOTQ		;GET ONE
	IFNSK.
	 PION
	 SKIPN WFLAG
	 RETBAD()		;IF NO WAIT, ALL DONE
	 MOVEI T1,VBWAIT
	 CALL CFSWUP		;WAIT FOR SOME
	 LOOP.
	ENDIF.
	ENDDO.
	MOVE T2,(T1)
	MOVEM T2,VOTQ		;DEQUEUE THIS ONE
	PION
	SETZM SCALEN(T1)	;Clear the first word
	RETSKP			;AND DONE

;SCHEDULER TEST TO WAIT FOR VOTE BUFFERS

VBWAIT:	SKIPE VOTQ		;ANY HERE?
	JRST 1(4)		;YEP
	JRST 0(4)		;NOPE
   >	;IFN CFSSCA

   IFE CFSSCA,<			;If no SCA
	RET			;No vote
   >	;IFE CFSSCA
	SUBTTL	Periodic check -- CFSCHK (Scheduler poller)

;Scheduler poller
;Must either be INSKED or NOSKED

CFSCHK::SKIPE SCAILK		;OK to do this now?
	RET			;No. Try again next time
	SKIPE SCAFL1		;Is KLIPA off-line?
	IFNSK.			;If so
	SETZ T1,0		;either path
	 CALL CIONLT		;is it sound yet?
	 IFNSK.			;If not
	  MOVX T1,^D1000	;Come back in a sec
	  MOVEM T1,CFSTIM	;To check it again
	 ELSE.
	  CALL PRTONL		;Set dual-port access
	 ENDIF.
	ELSE.
	 MOVX T1,^D5000		;Back in five seconds, please
	 MOVEM T1,CFSTIM		;Store it
	ENDIF.
	SOSLE CFSTTM		;Time for full test?
	RET			;No
	MOVX T1,TIMSE0		;Ten minutes from now
	MOVEM T1,CFSTTM		;Set it
	;CALLRET CFSCH1		;Do a pass

;Worker routine to do the scheduler background tasks.

CFSCH1:	AOS SCAILK		;Interlock it to prevent out-of-order messages
	MOVEM P,CFSSVP		;Save incoming stack
	MOVE P,CFSSTK		;Get a BETTER stack
	CALL SCAPOL		;Check on the message spooler
	MOVE P,CFSSVP		;Recover original stack
	PIOFF			;Prevent races
	TMNN SCWKP		;Anything here?
	SKIPE SCAQ		;Anything here now?
	CALL SKDRUN		;Yes, come back soon
	SETZM SCAILK		;And release the interlock
	PION			;Allow interruptions again
   REPEAT 0,<
	SOSLE PRGCNT		;time to scan hash table?
	RET			;No
	MOVEI T1,^D600		;Do again in one minute
	MOVEM T1,PRGCNT
	CALLRET CFSRSE		;And do it
   >	;REPEAT 0
	RET

;Routine to make the scheduler stuff run ASAP

SKDRUN:	SETZM CFSTIM		;Make next 100ms tick come to us
	SETZM CFSTTM		;And make sure we do all of our stuff
	RET
	SUBTTL	Periodic check -- SCAPOL (Process incoming SCA messages)

;SCAPOL - routine to process incoming SCA messages
;Called periodically either by unlocking the CFS interlock or by
;the scheduler. Scheduler calls are intended for processing requeued
;requests.
;No arguments.

SCAPOL::SAVEQ			;GET SOME WORK REGS
   IFN CFSSCA,<			;Do we have SCA?
	SETZM Q2		;NO REQUEUE NODE YET
	TMNN SCRSV		;RESTART VOTE QUEUED?
	IFSKP.
	 SETZRO SCRSV		;YEP
	 CALL CFSRSV		;DO RESTART
	ENDIF.
	TMNN SCDDP		;Need DDMP to run?
	IFSKP.
	 SETZRO SCDDP		;All done with this
	 AOS DDCFSF		;yes.
	ENDIF.
	TMNN SCDIS		;A pending disconnect?
	IFSKP.			;If so
	 SETZRO SCDIS		;Clear it
	 PIOFF
	 MOVSI Q1,-HSTSIZ	;Scan hosts
	 DO.
	  SKIPLE T1,CFHSTS(Q1)	;This one active?
	  SKIPG CFHSTS(Q1)	;Yes. Is it pending for disconnect?
	  IFSKP.
	   SETZM CFSHST(Q1)	;Yes
	   SETZM CFHSTS(Q1)	;Yepper
	  ENDIF.
	  AOBJN Q1,TOP.		;Do them all
	 ENDDO.
	 PION
	ENDIF.
	SKIPN SCAQ		;Anything to do?
	RET			;No.
	SAVET			;Yes. Save regs
	DO.
	 SKIPN Q1,SCAQ		;ANY STUFF HERE?
	 RET
	 CAMN Q1,Q2		;IS THIS THE END?
	 RET			;YES. DON'T SCAN REQUEUED NODES
	 PIOFF
	 MOVE T2,0(Q1)		;GET FORWARD LINK
	 MOVEM T2,SCAQ		;DEQUEUE IT
	 IFE. T2			;IF EMPTY
	  XMOVEI T2,SCAQ
	  MOVEM T2,SCTAIL	 ;INIT TAIL WHEN EMPTY
	 ENDIF.
	 PION
	 MOVE T1,Q1		;Get pointer to message
	 CALL SCMSG		;Do a message
	 IFNSK.
	  CALL SCAENQ		;ENQUEUE IT FOR RETRY
	  SKIPN Q2
	  MOVE Q2,Q1		;COPY REQUEUED ADDRESS
	 ENDIF.
	LOOP.
	ENDDO.
   >	;IFN CFSSCA
   IFE CFSSCA,<RET>		;If not SCA interface, return now
	SUBTTL	Call from SCA

;Call-back routine from SCS. Here when something about a connection
;changes.
;	T1/ code
;	T2/ connection i.d.
;	T3/ callback related data if used
;	T4/ callback related data if used

   IFN CFSSCA,<

CFSSTS:	CAILE T1,CFMSFX		;KNOWN FUNCTION?
	IFSKP.
	 EXCH T1,T2		;Connect ID in T1
	 CALL @CFFCTB(T2)	;DO IT
	ENDIF.
	RET			;AND DONE

;Function table for above

CFFCTB:	IFIW!R			;.SSDGR - Datagram received
	IFIW!SCAIN		;.SSMGR - Message received
	IFIW!SCABRK		;.SSPBC - Port broke connection
	IFIW!LSNUP		;.SSCTL - Connect to listen
	IFIW!CFSCPS		;.SSCRA - Connect response available
	IFIW!CFSWDN		;.SSMSC - Message/datagram send complete
	IFIW!R			;.SSDDG - Datagram dropped
	IFIW!R			;.SSLCL - Little credit left
	IFIW!CFSNDU		;.SSNCO - Node came online
	IFIW!CFSOKS		;.SSOSD - OK to send data
	IFIW!SCABRK		;.SSRID - Remote initiated disconnect
	IFIW!SCACRA		;.SSCIA - Credit is available
	IFIW!R			;.SSDMA - DMA complete
CFMSFX==.-CFFCTB-1
	SUBTTL	Call from SCA -- Message Received -- SCAIN (Receive message from SCA)

;Interrupt level routine to receive an incoming SCA packet
;	T1/ connect i.d.
;	T3/ packet address
;	T4/ return address

SCAIN:	EXCH T1,T3		;Swap CID and packet address
	LOAD T3,SID,T3		;GET HOST INDEX
	AOS CFRECV(T3)		;Got one
;**;[7211] Add 1 line at SCAIN+3	CEG 18-Dec-85
	AOS CFSRCV		;[7211] ADD TO TOTAL RECEIVED
	MOVEM T3,.MHSCI(T1)	;STASH IT
	MOVEM T4,.MHDCI(T1)	;Save buffer return address
	SKIPN SCAILK		;Need to enqueue?
	SKIPE SCAQ		;?
	IFSKP.			;If not
	 CALL SCMSG		;Do a message now
	  SKIPA			;Need to enqeue it
	 RET			;And done
	ENDIF.
	CALLRET SCAENQ		;ENQUEUE IT NOW
	SUBTTL	Call from SCA -- Message Received -- SCMSG (Process a single received message)

;Routine to process a single received message
;	T1/ pointer to the message
;Returns:	+1 need to requeue. T1/ message pointer
;		+2 success. Message already returned

SCMSG:	SAVEAC <Q1>
	MOVE Q1,T1
	LOAD T2,CFCOD,(Q1)	;GET OPCODE
	CAILE T2,.CFMAX		;KNOW HOW TO DO THIS?
	JRST CFSFRE		;NO. FREE IT AND GO ON
	CALL @[	IFIW!CFSRTV	;Vote
		IFIW!CFSRVT	;Reply to vote
		IFIW!CFSRFR	;Resource freeze
		IFIW!CFSRTV	;Seize
		IFIW!CFSOFC	;OFN change
		IFIW!CFSEFC	;End of file
		IFIW!CFTADA	;Time and date
                IFIW!CFCEAS]-1(T2); Shutdown
	IFNSK.
	 MOVE T1,Q1		;Return pointer
	 RETBAD()
	ENDIF.
	JUMPE T1,RSKP		;If want to keep it, done
	MOVE T1,Q1		;Else, get address for return
CFSFRE:	CALL SCARET		;RETURN SCA BUFFER
	RETSKP			;And done
	SUBTTL	Call from SCA -- Message Received -- CFSRTV (Vote or seize)

;Vote processor. This code is called whenever a request to vote
;Arrives:
;	Q1/ The request packet
;Called from the scheduler
;
;Uses:
;       T1/ Resource block address
;	T2/ Our current access to the resource
;	T3/ The requested access in the vote packet
;       P1/ Resource block address
;	P2/ Delay time if failing
;	P3/ Non-zero if want to release the resource
;	P4/ Reason code for returning a NO to the vote
;	Q2/ Reply type to the vote request
;
;Returns:
;	+1 Please reqeue
;	+2 done

CFSRTV:	SAVEAC <P1,P2,P3,P4,Q2>
	SETZB P3,P2		;No data yet
	SETZM P4		;No reason for NO yet either
	DMOVE T1,CFROT(Q1)	;GET CODES
	CALL HSHLOK		;LOOK IT UP
	IFNSK.			;If not here
       	 SETZM P1		;Indicate so
	 JRST CFSRV2		;And OKAy it
	ENDIF.
	MOVE P1,T1		;Save pointer
;**;[7247]  Add 9 lines after CFSRTV:+9			DML	19-Feb-86
	TMNN HSHTAM,(T1)   	;[7247] Is this a cached block?
	IFSKP.			;[7247] Yes
	  MOVE T1,HSHCOD(T1)	;[7247] Get the OFN
 	  MOVX T2,OFNLAC	;[7247] Get bit indicating loss of access
	  IORM T2,SPTH(T1)	;[7247] Set it
	  AOS CFACUT		;[7247] Count this event
	  SETZM P1		;[7247] Do not release block
	  JRST CFSRV2     	;[7247] Give an immediate YES answer
	ENDIF.			;[7247] 
	MOVE T4,HSFLAG(T1)	;Get the flags
	TXNN T4,HSHDWT		;Are we in a commit?
	IFSKP.			;Yes, he loses
	  MOVX P4,.CDDWT	;Get reason code
	  JRST CFSRV3		;He loses
	ENDIF.

;Found the request. Look it over.

	TMNE CFVUC,(Q1)		;Vote to include HSHCOD?
	IFNSK.			;If so
	 MOVE T2,CFDAT(Q1)	;Get required value
	 CAMN T2,HSHCOD(T1)	;match?
	 ANSKP.			;They do not, he loses
	   MOVX P4,.CDVUC	;Get reason code
	   JRST CFSRV3		;He loses
	ENDIF.
	LOAD T2,HSHTYP,(T1)	;Get our type
	MOVE T3,CFTYP(Q1)	;Get his requested access
	TXNN T4,HSHWVT		;Are we voting?
	JRST CFSRT0		;NO

;We are also voting on this. Decide which one can win

	TXNN T4,HSHYES		;Did we lose already?
	IFSKP.			;If so
	 TXNN T4,HSHUGD		;Upgrading?
	 JRST CFSRV2		; No, he wins
	 JUMPE T2,CFSRV2	;If we've only a place-holder, succeed
	 CAIE T2,.HTOEX		;Do we have it exclusively?
	 IFSKP.			;Yes, he loses
	   MOVX P4,.CDYUX	;Get reason code
	   JRST CFSRV3		;He loses
	 ENDIF.
	 CAIN T2,0(T3)		;Do they agree?
	 JRST CFSRV2		;Yes. Approve then
	 MOVX P4,.CDYUN		;No, get reason code
	 JRST CFSRV3		;He loses
	ENDIF.

	JE HSHDLY,(T1),CFSTV1	;If we do not have a commit, continue
	MOVX P4,.CDVDL		;Otherwise, we have a commit.  Get reason.
	JRST CFSRV3		;He loses
CFSTV1:	LOAD T4,HSHVTP,(T1)	;Get our vote request
	CAIE T3,.HTOEX		;He want exclusive?
	CAIE T3,0(T4)		;No. Do they agree?
	SKIPA T4,.MHSCI(Q1)	;No. One of us has to lose
	JRST CFSRV2		;Yes. Allow it then
	MOVE T4,CFSHNM(T4)	;Get his serial number
	CAMLE T4,MYPORT		;Is he the bigger wheel?
	IFSKP.			;No, we are. He loses
	  MOVX P4,.CDVLN	;Get reason code
	  JRST CFSRV3		;He loses
	ENDIF.
	SETONE HSHYES,(T1)	;Yes, he is bigger. We lose
	JN HSHDRC,(T1),CFSTV2	;If there is already a reason, don't destroy
	MOVX T4,.CDVLN		;Get reason for our loss
	STOR T4,HSHDRC,(T1)	;Store it
CFSTV2:	TMNN HSHUGD,(T1)	;Are we upgrading?
	JRST CFSRV2		;No, he wins
	JUMPE T2,CFSRV2		;If a place-holder, he wins
	MOVEI P2,^D50		;If he loses, try again soon.
	CAIE T3,.HTOEX		;He wants exclusive?
	IFSKP.			;Yes, he loses too
	  MOVX P4,.CDVUX	;Get reason code
	  JRST CFSRV3		;He loses
	ENDIF.
	CAIN T2,0(T3)		;No. Are they compatible?
	JRST CFSRV2		;Yes, he wins
	MOVX P4,.CDVUN		;No, he loses. Get reason code
	JRST CFSRV3		;He loses

;We own this. See if he can share it

CFSRT0:	IFE. T2			;If this is a place-holder
	 JN HSHKPH,(T1),CFSRV2	; And keeping, allow it directly
	 JRST CFSRV5		;Else, try to remove it as a stale entry
	ENDIF.
	CAIE T3,.HTOEX		;Does he want exclusive
	CAIN T2,.HTOEX		;DO WE OWN IT EXCLUSIVELY?
	JRST CFSRT1		;YES. CHECK IF WE CAN GIVE IT UP

;neither is exclusive. See if either is "promiscuous

	CAIE T2,.HTOPM
	CAIN T3,.HTOPM		;Do checks
	JRST CFSRV2		;Yes. allow it then
	CAIE T2,0(T3)		;NO. SEE IF COMPATIBLE
	JRST CFSRT1		;CHECK IF WE CAN GIVE IT UP
	JRST CFSRV2		;OKAY IT
;Here if we aren't using it

CFSRT1:	JE HSHCNT,(T1),CFSRT2	;If not in use, continue
	MOVX P4,.CDOCT		;It is in use.  Get reason code.
	JRST CFSRV3		;He loses.
CFSRT2:	SKIPE T2,HSHFCT(T1)	;Apply fairness?
	CAMG T2,TODCLK		;OK to release it?
	IFSKP.			;If not
	 SUB T2,TODCLK		;Compute difference
	 MOVE P2,T2		;Data to send back (time to try again)
	 MOVX P4,.CDOFC		;Get reason code
	 JRST CFSRV3		;Not okay
	ENDIF.

;We can give it up. Here by falling through or from CFSRT0

CFSRV5:	STOR T3,HSHVTP,(T1)	;Save requested access
	MOVE T2,.MHSCI(Q1)	;GET I.D.
	STOR T2,HSHRHN,(T1)	;STASH IN PACKET
	LOAD T2,CFUNQ,(Q1)	;GET VOTE CODE
	STOR T2,HSHVVL,(T1)
	AOJA P3,CFSRV2		;Approve and do release
   REPEAT 0,<
	CALL CFSRMX		;REMOVE ENTRY
	SKIPE Q2,T1		;Copy type, and test if available
	IFSKP.			;If available
	 IFN. T2		;And it was removed
	  MOVEI P1,0		;No saved entry
	 ENDIF.
	ENDIF.
	JRST CFSRV4
   >	;REPEAT 0
;At this point:
;	P2/ Delay time if failing
;	P3/ non-zero if want to release the resource
;	P1/ resource address, if any
;	Q1/ Request packet from other system
;	P4/ Reason code for saying NO
;	Q2 will be used to indicate reply type
;		0 -- OK
;		1 -- No
;		-1 -- delayed yes

;Here to reply

CFSRV3:	IFE. P2			;Set bit only if not sending data
	 MOVE T2,.MHSCI(Q1)	;GET HOST NUMBER
	 MOVE T2,BITS(T2)	;GET BIT FOR THIS HOST
	 IORM T2,HSHNBT(T1)	;STORE INTO THE PACKET
	ENDIF.
	SKIPA Q2,[1]		;FAIL!
CFSRV2:	MOVEI Q2,0		;SUCCESS
CFSRV4:	CALL GVOTE1		;GET A BUFFER
	 RETBAD()		;FAILED. REQUEST A REQUEUE
	IFE. Q2			;If allowing it
	 SKIPN T2,P1		;Any request here?
	 ANSKP.			;If so
	 SKIPE T3,HSHOKV(P1)	;Yes. Want to know about this?
	 CALL 0(T3)		;Yes. So tell someone (may change Q2)
	 IFG. P3		;Want to try to release it?
	  EXCH T1,P1
;The following call may return -1 in T1, which changes a "yes" vote
;to "will be released, but not yet"
	  CALL CFSRMX		;(T1/T1,T2) And try to remove it
	  MOVE Q2,T1		;Save type of release
	  MOVE T1,P1		;Get back vote packet
	 ENDIF.
	ENDIF.
	IFG. Q2			;If failing
	 SKIPG P2		;And have someting to send
	 ANSKP.
	  MOVEM P2,CFDAT(T1)	;Stash it
	  SETONE CFODA,(T1)	;And say so
	ENDIF.
	MOVEI T2,.CFREP		;WE ARE REPLYING
	STOR T2,CFCOD,(T1)
	LOAD T2,CFUNQ,(Q1)
	STOR T2,CFUNQ,(T1)	;COPY CODE
	DMOVE T2,CFROT(Q1)
	DMOVEM T2,CFROT(T1)	;MOVE LOCK ID
	MOVEM Q2,CFTYP(T1)	;THE VOTE
	STOR P4,CFDRC,(T1)  	;Store the reason for saying NO, if any
	MOVE T2,.MHSCI(Q1)
	CALL SCASND		;SEND IT
	IFNSK.
	 PIOFF
	 CALL CFSWDN		;Return the buffer
	 PION
	ENDIF.
	MOVE T1,Q1		;ENSURE NON-ZERO
	RETSKP			;AND DONE
	SUBTTL	Call from SCA -- Message Received -- CFSRVT (Reply to vote)

;Routine to process returned vote.
;	Q1/ packet
;Called from the scheduler or at PI level

CFSRVT:	DMOVE T1,CFROT(Q1)	;GET VALUES
	CALL HSHLOK		;LOOK IT UP
	 RETSKP

;Found a node

	JE HSHWVT,(T1),RSKP	;IF NOT VOTING, DONE
	LOAD T2,CFUNQ,(Q1)	;GET UNIQUE CODE
	OPSTR <CAME T2,>,HSHUNQ,(T1) ;MATCH?
	JRST RSKP		;NO. SKIP IT THEN
	INCR HSHVCT,(T1)	;YES. ANOTHER COUNTY HEARD FROM
	TMNE CFODA,(Q1)		;Providing optional data?
	IFNSK.			;If so
	 DO.
	  SKIPG CFTYP(Q1)	;If a fail vote
	  IFSKP.
	   MOVE T2,CFDAT(Q1)	;Get the time stamp
	   MOVEM T2,HSHWTM(T1)	;Send it back
	   EXIT.
	  ENDIF.
	  SKIPE T2,HSHCDA(T1)	;Want to be notified?
	  IFNSK.		;If so
	   CALL 0(T2)		;Do so
	    EXIT.		;If +1, don't use it
	  ENDIF.
	  DMOVE T2,CFDAT(Q1)	;Get it
	  DMOVEM T2,HSHOPT(T1)	;Store it in the packet
	  SETONE HSHODA,(T1)	;Say we have some
	 ENDDO.
	ENDIF.
	AOS PSKD1		;MAKE SURE THE SCHEDULER NOTICES THIS
	MOVE T2,CFTYP(Q1)
	JUMPE T2,RSKP		;IF OK, ALL DONE
	IFL. T2			;IF YES, BUT DELAY
	 MOVE T3,.MHSCI(Q1)
	 MOVE T3,BITS+^D18(T3)
	 LOAD T4,HSHDLY,(T1)
	 AOSE T2		;OK WITH DELAY?
	 IFSKP.
	  IORM T3,T4		;YES MARK IT
	 ELSE.
	  ANDCAM T3,T4		;ELSE, UNMARK IT
	  DECR HSHVCT,(T1)	;Discount vote if this
	 ENDIF.
	 STOR T4,HSHDLY,(T1)
	ELSE.
	 SETONE HSHYES,(T1)	;NAY. INDICATE SO
	 JN HSHDRC,(T1),RSKP	;If there is already a reason, don't destroy
	 LOAD T2,CFDRC,(Q1)  	;Get reason for NO
	 STOR T2,HSHDRC,(T1)	;Store it
	ENDIF.
       	RETSKP			;AND DONE
	SUBTTL	Call from SCA -- Message Received -- CFSRFR (Resource freed)

;Routine called when a resource is freed. If anyone is waiting, awake him.
;This routine is used to process an incoming message indicating
;that a resource is now free. The sending node provided this information
;because we requested this resource and were denied. We may or may
;not still require the resource.
;The sender sent this message from CFNOHS!
;	T1/ Block address

CFSRFR:	DMOVE T1,CFROT(Q1)	;GET RESOURCE ID
	CALL HSHLOK		;LOOK IT UP
	 JRST RSKP
	SETONE HSHRTY,(T1)	;AWAKE
	AOS PSKD1		;GET THE SCHEDULER AWAKE TOO
	RETSKP			;AND DONE
	SUBTTL	Call from SCA -- Message Received -- CFSOFC (OFN change)

;Here when a "broadcast OFN change is received.
;	Q1/ message block address

CFSOFC:	DMOVE T1,CFROT(Q1)	;Get stuff
	CALL HSHLOK		;Look it up
	 JRST RSKP		;Not known here

;found the block

	MOVE T2,HSHCOD(T1)	;Get the OFN
;**;[7247]  Add 14 lines after CFSOFC:+6		DML	19-Feb-86
	TMNN HSHTAM,(T1)   	;[7247] Is this a cached block?
	IFSKP.			;[7247] Yes
	  MOVX T1,OFNLAC	;[7247] Get "lost access" bit
	  TDNN T1,SPTH(T2)	;[7247] It had better be set!
	  BUG. (HLT,CFSOAC,CFSSRV,SOFT,<CFSSRV - Invalid access to cached OFN>,,<

Cause:	CFS has received a message from a remote system that an OFN
	has changed and needs to be verified again. But CFS has found
	that the OFN is cached and the OFNLAC bit is not set.  This
	should not happen since this bit should be set when the other
	system was granted access.
>)				;[7247] It's not!
	  RETSKP		;[7247] Ok, just return
	ENDIF.			;[7247] 
   IFN DEBUG,<			;If debugging
	MOVE T3,HSFLAG(T1)	;Get flags
	TXNN T3,HSHTYP		;A place holder?
	IFSKP.			;No.
	 TXNE T3,HSHWVT		;Better be voting then
	 TXNE T3,HSHUGD		;And not upgrading
	 ANNSK.			;If not both...
	 BUG. (HLT,CFSOFB,CFSSRV,SOFT,<CFSSRV - OFN owned at CFSOFC>,,<

Cause:	CFS has received a message from a remote system that an OFN
	has changed and needs to be verified again. But CFS has found
	that it owns the OFN. It should never have received such a
	message.
>)
	ENDIF.
   >	;IFN DEBUG
	JE SPTCDO,(T2),RSKP	;If not yet opened, ignore it
	SETONE SPTSFD,(T2)	;Set "reverify" bit
	RETSKP			;And done

	SUBTTL	Call from SCA -- Message Received -- CFSEFC (EOF received)

;Here when broadcast EOF is received.
;	Q1/ Block address

CFSEFC:	DMOVE T1,CFROT(Q1)	;Get IDs
	CALL HSHLOK		;Look it up
	 JRST RSKP		;We odon't have this file
	CALL CFADAR		;Decide if we should use it
	 JRST RSKP		;No
	SETONE HSHODA,(T1)	;Yes.
	DMOVE T2,CFDAT(Q1)	;Get it
	DMOVEM T2,HSHOPT(T1)	;Copy it
	RETSKP			;And done

 	SUBTTL	Call from SCA -- Message Received -- CFTADA (Time and date arrived)

;Here when TAD arrives

CFTADA:	MOVE T1,CFROT(Q1)	;Get it
	MOVEM T1,CFTADL		;Store it for perusal
	AOS JB0FLG		;Get it noticed
	RETSKP			;And done
	SUBTTL	Call from SCA -- Message Received -- CFCEAS (Cease)

COMMENT *

When a system tells its users "System going down in ........" and the shutdown
time is less than one hour away, we check to see if we have any disks onlined
via the MSCP server.  If so, we broadcast the shutdown time to the other
systems in the cluster;  the same goes for "Shutdown canceled" and 
"Timesharing is over".  This allows the other systems to see if they have any
structures mounted via the MSCP server on the system which is doing the
broadcasting.  If a system finds such mounted structures, it sends to OPR and
the CTY a message stating the remote system's shutdown status and a list of the
structures effected.

Routine CFCBRD is called from MEXEC's shutdown processing to do the broadcast.
Routine CFCEAS processes the incoming message by placing the data (node number,
shutdown time, and node name) in a resident free space block and linking it in
a chain of blocks pointed to by location CCHEAD.

CHKR finds the queued blocks and calls routine CHKCLC.  The interlock between
the CHKR routine and the interrupt level code is an EXCH instruction on 
location CCHEAD.  The data is retrieved from the block, effected structures are
found, and QUEUE% is used to pass the information to OPRs and the CTY.

*
;CFCEAS - PROCESSES CEASE MESSAGE FROM A REMOTE SYSTEM
; Q1/ ADDRESS OF PACKET
;	CALL CFCEAS		;(Q1/T1)
; RETURN +2

CFCEAS:	SAVEP
	DMOVE P1,CFDAT(Q1)	;Get node number and cease time
	DMOVE P3,CFROT(Q1)	;Get both words of node name
	MOVEI T1,CCLEN		;GET LENGTH OF CLUSTER CEASE INFO BLOCK
	HRLI T1,.RESP1		;PRIORITY 1
	MOVE T2,[RS%SE0+.RESGP]	;FROM THE GENERAL POOL
	CALL ASGRES		;(T1,T2/T1) GET THE SPACE
	 IFNSK.
	    BUG. (INF,CFCCML,CFSSRV,SOFT,<CFSSRV - Cluster cease message lost>,,<

Cause:	Another system sent a "cluster cease" that could not be queued
	because there was no available resident free space.
>)
	    JRST CFCEAX		;TOO BAD, BUT NOT CRTITICAL
	 ENDIF.
	SKIPE T2,CCHEAD		;GET HEAD OF QUEUED BLOCKS
	IFSKP.
	   MOVEM T1,CCHEAD	;NONE THERE, MAKE THIS ONE FIRST
	ELSE.
CFCEA1:	   SKIPN T3,CCNXT(T2)	;GET NEXT BLOCK
	   IFSKP.
	      MOVE T2,T3	;WE HAVE ONE
	      JRST CFCEA1	;KEEP GOING
	   ENDIF.
	   MOVEM T1,CCNXT(T2)	;ADD THIS ONE TO THE END
	ENDIF.
	DMOVEM P1,CCNOD(T1)	;PUT NODE NUMBER AND TIME IN BLOCK
	DMOVEM P3,CCNAM1(T1)	;PUT NODE NAME IN BLOCK
CFCEAX:	MOVE T1,Q1		;INSURE T1 IS NON-ZERO SO BUFFER IS RETURNED
	RETSKP
;CHKCLC - CALLED BY CHKR TO SEE IF THERE ARE ANY QUEUED CLUSTER CEASE BLOCKS
;WAITING TO BE PROCESSED
;	CALL CHKCLC		;(/)
; RETURN +1
; LOCAL AC USE:
; Q1,Q2 - EXTEND
;    Q3 - STRING TERMINATOR
;    P1 - FREE SPACE BLOCK
;    P2 - KDB
;    P3 - UDB
;    P4 - SIXBIT STRUCTURE NAME
;    P5 - "WE FOUND AT LEAST ONE STRUCTURE" FLAG

	SWAPCD

	SLEN==^D14		;WORDS TO HOLD STRUCTURE NAMES
	HLEN==^D25		;WORDS TO HOLD HEADER TEXT

CHKCLC::SETZ T1,		;THIS IS THE INTERLOCK
	EXCH T1,CCHEAD		; WITH THE INTERRUPT LEVEL CODE
	JUMPE T1,RTN		;IF NO QUEUED BLOCKS, QUIT
	SAVEPQ
	STKVAR <<SNAMS,SLEN>,<MSG,SLEN+HLEN>>
CHKCL4:	SETZ P5,		;START WITH NO STRUCTURES FOUND
	MOVE P1,T1		;PRESERVE BLOCK ADDRESS
	MOVE T1,CCNOD(P1)	;GET NODE NUMBER
	MOVEI Q1,SNAMS		;MAKE BP
	HRLI Q1,(<POINT 7,>)	; TO STRUCTURE NAME SPACE
	MOVEI Q3," "		;LOAD "SPACE"
	ADD T1,CHNTAB+7		;GET NODE'S
	MOVE P2,CDBUDB(T1)	; KDB
CHKCL1:	SKIPN P3,KDBUDB(P2)	;GET NEXT UDB
	JRST CHKCL2		;DONE
	MOVX T1,US.TPD		;THREE-PORTED
	TDNE T1,UDBSTS(P3)	; HERE?
	JRST CHKCL3		;YES, THEN NO ONE IS USING IT
	SKIPGE T1,UDBSTR(P3)	;NO, PART OF STRUCTURE?
	JRST CHKCL3		;NO, THEN IT'S NOT MOUNTED (NOT EVEN MOUNTR)
	HLRZ T2,T1		;YES, GET LOGICAL UNIT OF STRUCTURE
	JUMPN T2,CHKCL3		;IF NOT 0, MOVE ON (ONLY IDENTIFY IT ONCE!)
	SETO P5,		;FOUND A STRUCTURE MOUNTED THROUGH A SERVER
	HRRZ T1,UDBSTR(P3)	;GET STRUCTURE NUMBER
	CALL GNAME		;(T1/T1) GET STRUCTURE NAME
	MOVE P4,T1		;PUT IT SOMEWHERE
	MOVEI T1,6		;GET MAX CHAR. COUNT OF STR NAME
	MOVEI T2,P4		;MAKE BP
	HRLI T2,(<POINT 6,>)	; TO IT
	SETZB T3,Q2		;SINGLE WORD BYTE POINTERS
	MOVE T4,T1		;GET CHAR. COUNT AGAIN
	EXTEND T1,[MOVSO 40]	;CREATE STR NAME IN ACSII
	 JFCL
	IDPB Q3,Q1		;PUT IN SPACE
CHKCL3:	AOJA P2,CHKCL1		;GO DO NEXT UDB
;...
;...
CHKCL2:	SETZ Q3,
	IDPB Q3,Q1		;TIE OFF STRUCTURE NAMES
	HRROI T1,MSG		;YES, GET BP TO MESSAGE
	HRROI T2,[ASCIZ/
/]
	SETZ T3,
	SOUT			;WAKE UP THE OPERATOR
	HRROI T2,CCNAM1(P1)
	SOUT			;NODE NAME
	SKIPG CCTIM(P1)		;CEASE SCHEDULED?
	IFSKP.

;Cease scheduled

	   HRROI T2,[ASCIZ/ is going down at /]
	   SOUT
	   MOVE T2,CCTIM(P1)	;GET TIME
	   ODTIM		;PUT IT IN MESSAGE
	   HRROI T2,[ASCIZ/.  /]
	   SOUT
	   HRROI T2,CHKMS1	;ASSUME STRUCTURES FOUND
	   SKIPN P5		;WERE THERE ANY?
	   HRROI T2,CHKMS2	;NO, GET DIFFERENT MESSAGE
	ELSE.
	   SKIPE CCTIM(P1)	;SHUTDOWN CANCELED?
	   IFSKP.

;Shutdown canceled

	      SKIPN P5		;ANY STRUCTURES FOUND?
	      JRST CHKCL5	;NO
	      HRROI T2,[ASCIZ/ has canceled its shutdown.  It is no longer
necessary to dismount the following structures:

/]
	   ELSE.

;Timesharing is over

	      HRROI T2,[ASCIZ/ has ceased timesharing.  /]
	      SOUT
	      HRROI T2,CHKMS1	;ASSUME STRUCTURES FOUND
	      SKIPN P5		;WERE THERE ANY?
	      HRROI T2,CHKMS2	;NO, GET DIFFERENT MESSAGE
	   ENDIF.
	ENDIF.
	SOUT			;CREATE HEADER
	SKIPN P5		;ANY STRUCTURES FOUND?
	IFSKP.
	   HRROI T2,SNAMS	;YES, GET BEGINNING OF STRUCTURE NAMES
	   SOUT			;MOVE THEM TO END OF MESSAGE
	ENDIF.
	MOVEI T2,MSG		;GET BEGINNING ADDR OF MESSAGE
	MOVEI T3,.QBSYS		;TYPE IS "SYSTEM MESSAGE"
	CALL WROPR0		;(T1,T2,T3/) WRITE-TO-OPR
;...
;...
CHKCL5:	MOVE P2,CCNXT(P1)	;GET NEXT QUEUED BLOCK
	MOVE T1,P1		;POSITION BLOCK ADDR
	CALL RELRES		;(T1/) RELEASE THIS BLOCK
	SKIPE T1,P2		;IS THERE ANOTHER BLOCK?
	JRST CHKCL4		;YES
	RET
	
	ENDSV.


CHKMS1:	ASCIZ/Before that system
is shutdown, this system should dismount the following
structures:

/

CHKMS2:	ASCIZ/No structure
dismounting is needed on this system.
/

	RESCD
	SUBTTL	Call from SCA -- SCABRK (Node went away)

;Here when a connection is broken for any reason
;	T1/ connection i.d. or -1 for extra callback

SCABR0:	AOS CFSSKC		;Make the scheduler do the check
	ISB SCDCHN		;And make it notice
SCABRK:	SKIPGE T3,T1		;Is this an extraneous callback?
	RET			;Yes, just return
	LOAD T1,SID,T1		;GET HOST INDEX
	SKIPN CFSHST(T1)	;This node active in some way?
	IFSKP.
	 SKIPL T2,CFHSTS(T1)	;If active, is it up (i.e. counted)?
	 IFSKP.			;If so...
	  SOS CFSHCT		;ONE LESS
	  TRNE T2,-1		;A full or reduced?
	  SOS CFSHCM		;Full.
	  CALL MXCIND		;(/T2) Get the max number of nodes ever on CI
	  IMUL T2,DLYTIM	;Multiply by delay per node
	  ADD T2,NDSTTM		;Add allowable time for reloading the KLIPA
	  ADD T2,TODCLK		;Compute time the delay is over
   IFN DEBUG,<
;	  SKIPE DLYFLG		;Doing delay stuff?	
   >	;IFN DEBUG
	  MOVEM T2,DLYLOK	;And lock voting for a bit
	  CALL PHYNOL		;Declare the disk's offline
	  MOVE T2,CFSHNM(T1)	;Get the serial number
	  CALL PUTOLD		;And install it now
	  SKIPE SCAILK		;OK TO DO THIS NOW?
	  IFSKP.
	   SETZM CFSHST(T1)	;Not in use now
	   CALL CFSRSV		;YES, RESTART VOTE
	  ELSE.
	   SETONE <SCRSV,SCDIS>	;NO. SAY WE NEED IT LATER
	   MOVX T2,1B0		;Get the sign bit
	   ANDCAM T2,CFHSTS(T1)	;Mark this entry
	  ENDIF.
	 ELSE.			;If not counted
	  SOS CFSCMC		;One less connection being done
	  SETZM CFSHST(T1)	;And this one is no longer active
	 ENDIF.
	 PIOFF
	 DO.			;Return queued send buffers
	  SKIPN T3,CFSSMQ(T1)	;Anything here?
	  EXIT.			;No. All done
	  MOVE T2,0(T3)		;Get next
	  MOVEM T2,CFSSMQ(T1)
  	  CALL CFSWDN		;Return the buffer
	  LOOP.			;Do them all
	 ENDDO.
	 PION
	ENDIF.
	RET
	SUBTTL	Call from SCA -- LSNUP (Connect to listen)

;Here when listen circuit has a sucker.
;Called at interrupt level or with CFS interlock set
;	T1/ Connect I.D.
;	T3/ Pointer to serial number

LSNUP:	SAVEQ
	LOAD Q1,SID,T1		;GET HOST INDEX
	HRRZ T2,OPDTYP(T3)	;Get net number

;here if we know about this. See if connector is trying to
;connect to us (or we know about it).

	DMOVE Q2,OPDNAM(T3)	;Get its name
	HLLZS Q3		;Get rid of excess
	LSH Q1,1		;Get index
	DMOVEM Q2,CFNNAM(Q1)	;Stash the name
	LSH Q1,-1
	MOVE Q2,T1		;SAVE CID
	MOVE T1,OPDSER(T3)	;GET SERIAL NUMBER
	HLRE Q3,OPDTYP(T3)	;Get type of node
	XOR T2,MYPOR1		;Compare net numbers
	TRNE T2,-1		;Same?
	SETZM Q3		;No. Treat as a reduced node then
	MOVEM T1,CFSHNM(Q1)	;AND PORT NUMBER HERE
	MOVEI T3,HSTSIZ		;SIZE OF HOST TABLE
	CAMG T1,MYPORT		;HIGHER PRIORITY THAN I?
	IFNSK.
	DO.
	 SKIPLE CFSHST(T3)	;ACTIVE?
	 CAME T1,CFSHNM(T3)	;IS THIS ALREADY CONNECTED?
	 IFSKP.
	  SKIPL CFHSTS(T3)	;Make sure is fully active
	  ANSKP.
	  BLCAL. (SC.REJ,<CFSHST(Q1),[0]>)
	   NOP
	  SETZM CFSHST(Q1)	;THIS SLOT NOW AVAILABLE
	  JRST LSNUP1		;GO START A NEW LISTENER
	  RET			;DONE
	 ENDIF.
	 SOJGE T3,TOP.
	ENDDO.
	ENDIF.

;Here if we should accept

	MOVE T1,CFSHNM(Q1)	;Get the serial number
	CALL CHKOL0		;see if we know about this one yet
	STOR T1,ONFLG,MYPOR3	;Store old/new flag byte
	HRRM Q3,CFHSTS(Q1)	;Remember the type
	AOS CFSCMC		;Note we are doing this
	BLCAL.(SC.ACC,<Q2,<.,MYPORT>,[BUFSCT],[0]>); ACCEPT THE OVERTURE
	IFNSK.
	  MOVE T3,T1		;Move error code
	  MOVE T1,Q2		;Get connect ID
	  CALL SC.NOD		;(T1/T1,T2) Get node number
	  BUG. (HLT,CFACCF,CFSSRV,SOFT,<CFSSRV - SC.ACC failed>,<<T2,NODE>,<T1,CID>,<T3,ERR>>,<

Cause:	The call to SC.ACC failed.

Data:	NODE - Node Number
	CID - Connect ID
	ERR - Error returned by SC.ACC
>)
	ENDIF.
	MOVEM Q2,CFSHST(Q1)	;NOW STORE CID

;NOTE: CFSHCT is incremented during the CFSOKS call-back

LSNUP1:	CALL CFSLSN		;GET A NEW LISTENER
	 NOP
	RET			;AND DONE
	SUBTTL	Call from SCA -- Connect response available -- CFSCPS (Connect response available)

;Here on reply to connect request
;	T1/ CID
;	T3/ Reply code
;	T4/ Pointer to serial number

;We tried to connect to another node, and now a response is available.
;If it has accepted, we may already have a connection open to it.
;If that is true, the open connection was initiated by the other node,
;and the following algorithm applies:

;If we have the lower serial number, close this one.
;If they have the lower serial number, close the existing one.

CFSCPS:	SAVEAC<P1,P2>
	LOAD T2,SID,T1		;Get local ID
	SKIPE CFSHST(T2)	;This waiting?
	SKIPL CFSHNM(T2)	;?
	RET			;No. Ignore it then

;Found the waiting entry. See if it was accepted

	SOS CFSCMC		;No more of this
	MOVEM T1,CFSHST(T2)	;Store CID
	IFE. T3			;If rejected
	 SETZM CFSHST(T2)	;We are no longer waiting
	 RET			;And done
	ENDIF.

;It was accepted. Make sure we are not connect another way

	DMOVE P1,OPDNAM(T4)	;get its name
	HLLZS P2		;Get rid of excess
	LSH T2,1		;Get to index
	DMOVEM P1,CFNNAM(T2)	;Stash its name
	LSH T2,-1
	LOAD P2,ONFLG,OPDNEW(T4) ;Get old/new byte
	HLRE P1,OPDTYP(T4)	;Get type of connector
	HRRZ T3,OPDTYP(T4)	;Get network nubmer
	XOR T3,MYPOR1		;Compare with our number
	TRNE T3,-1		;Same as us?
	SETZM P1		;No. Treat it as "reduced"
	MOVE T4,OPDSER(T4)	;Get other node's serial number
	CALL CFSCPX		;(T4/)See if we need to disconnect
	 RET			;Disconnected our initiator. Quit now
	;..
;Here when we want to let this connection proceed. We may have disconnected
;an old connection.

	;..
	SKIPE SCAFL1		;OK to allow this?
	CALL CFSDIE		;No.
	MOVEM T4,CFSHNM(T2)	;OK to store this now
	HRROM P1,CFHSTS(T2)	;Set status
	SETZM CFSENT(T2)
	SETZM CFRECV(T2)
	XMOVEI T3,CFSSMQ(T2)	;Get head of send queue
	MOVEM T3,CFSSQT(T2)	;Link tail to head
	SETZM 0(T3)		;Clear head
	MOVE T1,CFSHNM(T2)	;Get its serial number
	SKIPE P2		;If he thinks it is new
	CAMG T1,MYPORT		;Or I'm a big wheel
	IFSKP.			;If not	
	 EXCH P2,T2		;Save index, get OLD/NEW arg
	 CALL CHKOLD		;Check it we've been here before
	 IFSKP.
	   MOVE T1,CFSHST(P2)	;Get connect ID
	   CALL SC.NOD		;(T1/T1,T2) Get node number
	   BUG. (HLT,CFRECN,CFSSRV,SOFT,<CFSSRV - Illegal reconnect>,<<T2,NODE>,<T1,CID>>,<

Cause:	The VC between this system and another has been continued illegally.

Data:	NODE - Number that has re-established a connection
	CID - Connect ID

>)
	 ENDIF.
	 EXCH T2,P2		;Swap index and OLD/NEW arg
	ENDIF.
	MOVE T1,CFSHNM(T2)	;recover serial number
	CALL CHKDLY		;Check if we are whole again!
	AOS CFSHCT		;Another node in the list
	MOVE T1,T2		;Pass local node number
	CALL ONLINE		;Do a message
	SETONE SCCNC
	TRNE P1,-1		;IS this reduced
	IFNSK.			;If not
	 AOS T3,CFSHCM		;One more full voter on-line
;**;[7152] Remove 2 lines at CFSCPS+75	CEG 15-Oct-85
	ENDIF.
	MOVEI T1,0(T2)		;Copy host index
	CALL SNDTIM		;Send it the TAD
	SKIPE SCAILK		;Data base locked?
	IFSKP.			;If not
	 CALL CFSRSV		;Restart votes (called without the lock)
	ELSE.			;If so
	 SETONE SCRSV		;Note we need to do this ASAP
	 CALL SKDRUN		;Make the scheduler run ASAP
	ENDIF.
	RET			;And done
	SUBTTL	Call from SCA -- Connect response available -- CFSCPX (Disconnect duplicate connection)

;CFSCPX - Disconnect if there's a duplicate connection to this node
;Accepts:
;	T4/ serial number of the other node

;	CALL CFSCPX

;Returns +1: disconnected our initiator (the one that caused this call)
;	 +2: OK to proceed with this connection

;Preserves the temporary AC's except T3.

;Note: this was written to fix a bug in CFSCPS. It is not general-purpose.
;Calling it from anywhere else might be a mistake

CFSCPX:	MOVSI T3,-HSTSIZ	;Scan table for a match
	SAVET
	DO.
	  CAME T4,CFSHNM(T3)	;Here?
	  IFSKP.		;If so, we have a conflict. Must do away with one
	    SKIPE CFSHST(T3)	;Really in use?
	    SKIPL CFHSTS(T3)	;?
	    ANSKP.		; If so...
	    MOVEI T1,0(T2)	;Assume we will zap our connection
	    CAMG T4,MYPORT	;Will we?
	    MOVEI T1,0(T3)	;No zap other side's initiator
	    PUSH P,T1
	    BLCAL. (SC.DIS,<CFSHST(T1),[0]>)
	     NOP
	    POP P,T1
IFN DEBUG,<
	    CALL OFLINE		;(T1) REPORT THE DISCONNECTION
>
	    SETZM CFSHST(T1)	;Clear entry
	    SKIPL T3,CFHSTS(T1)	;Which connection did we kill?
	    RET			;Our initiator. Don't continue connecting, then.

;Here when we disconnected the other side's initiator (the old connection).
;Need to decrement the host count and let the current connection continue.

	    SOS CFSHCT		;Indicate one fewer connections
	    TRNE T3,-1		;Full or reduced?
	    SOS CFSHCM		;It was full
	    RETSKP		;Let the caller proceed
	  ENDIF.
	  AOBJN T3,TOP.		;Scan them all
	ENDDO.
	RETSKP
	SUBTTL	Call from SCA -- CFSWDN (Write completed)

;Here to put a packet on the vote queue
;	T3/ Buffer address

CFSWDN:
   IFN DEBUG,<			;Only for debugging...
	LOAD CX,CFGWD,(T3)  	;Check if special word is here
	CAME CX,[252525]	  ;Is it?
	BUG.(HLT,CFGARD,CFSSRV,SOFT,<CFSSRV - Vote packet address is bad>,,<

Cause: A bad vote packet address has been given to CFSWDN.
>)
   >	;IFN DEBUG
	EXCH T3,VOTQ		;PUT IT ON TOP
	MOVEM T3,@VOTQ		;AND QUEUE REST OF QUEUE TO IT
	RET			;DONE
	>	;IFN CFSSCA
   IFE CFSSCA,<			;If not SCA
CFSWDN==R			;Null routine
   >	;IFE CFSSCA
	SUBTTL	Call from SCA -- CFSNDU (Node up)

;Node up
;	T1/ SBI

   IFN CFSSCA,<
CFSNDU:	SKIPE SCAFL1		;Are ports off?
	CALL DEDKLP		;Yes. We are in trouble
	CALL CFSCTH		;Try to connect to it
	 NOP
	RET			;And done
	SUBTTL	Call from SCA -- CFSOKS (Ok to send)

;Here when a listener is really ready to send
;	T1/ CID

CFSOKS:	SAVEQ
	LOAD Q1,SID,T1		;get ID
	SKIPLE CFSHST(Q1)	;Do we agree?
	SKIPGE CFHSTS(Q1)	;Still?
	RET			;No
	SOS CFSCMC		;Discount this now

;yes. we must do soemthing about this

;Check for a conflict

	MOVSI T2,-HSTSIZ
	MOVE T3,CFSHNM(Q1)	;Get name
	DO.
	 CAME T3,CFSHNM(T2)	;This one match?
	 IFSKP.			;if so.
	  SKIPE CFSHST(T2)	;Make sure is active
	  SKIPL CFHSTS(T2)	;""
	  ANSKP.
	  MOVEI Q2,0(Q1)	;Assume we will close his
	  CAML T3,MYPORT	;Will we?
	  MOVEI Q2,0(T2)	;No. Close ours
	  BLCAL. (SC.DIS,<CFSHST(Q2),[0]>)
	   NOP
IFN DEBUG,<
	  MOVE T1,Q2		;GET LOCAL NODE INDEX
	  CALL OFLINE		;(T1) REPORT THE DISCONNECTION
>
	  SETZM CFSHST(Q2)
	  SKIPL T3,CFHSTS(Q2)	;Was it me or him?
	  RET			;Me. All done then
	  SOS CFSHCT		;Him. One less active node
	  TRNE T3,-1		;Full or reduced?
	  SOS CFSHCM		;Full
	  EXIT.
	 ENDIF.			;And proceed with the connection
	 AOBJN T2,TOP.
	ENDDO.
	SKIPE SCAFL1		;OK to allow this?
	CALL CFSDIE		;No.
	XMOVEI T3,CFSSMQ(Q1)	;Get address of head
	MOVEM T3,CFSSQT(Q1)	;Link head to tail
	SETZM 0(T3)		;Clear head
	AOS CFSHCT		;Another one active
	MOVE T1,Q1		;Pass local node number
	CALL ONLINE
	SETONE SCCNC
	HRROS T3,CFHSTS(Q1)	;Mark it active
	SETZM CFSENT(Q1)
	SETZM CFRECV(Q1)
	TRNE T3,-1		;Full or reduced?
	IFNSK.			;If full
	 AOS T3,CFSHCM		;One more full voter
;**;[7152] Remove 2 lines at CFSOKS+53	CEG 15-Oct-85
	ENDIF.
	MOVEI T1,0(Q1)		;Copy the index
	CALL SNDTIM		;Send it TAD
	SKIPE SCAILK		;Data base locked?
	IFSKP.			;If not
	 CALL CFSRSV		;Restart votes (called without the lock)
	ELSE.			;If so
	 SETONE SCRSV		;Note we need to do this ASAP
	 CALL SKDRUN		;Make the scheduler run
	ENDIF.
	RET			;And done
	SUBTTL	Call from SCA -- SCACRA (Credit available)

;Credit arrived.
;	T1/ CID

SCACRA:	LOAD T1,SID,T1		;Get local port
	SETONE STCRA,(T1)	;Say it arrived
	CALLRET SSENDQ		;Process the queue
	SUBTTL	Sending Messages -- SCAENQ (Enqueue a SCA message)

;ROUTINE TO ENQUEUE AN SCA MESSAGE
;	T1/ MESSAGE TO ENQUEUE
;RETURNS:
;	+1 ALWAYS

SCAENQ:	PIOFF
	MOVEM T1,@SCTAIL	;LINK INTO QUEUE
	MOVEM T1,SCTAIL
	SETZM 0(T1)		;NO FORWARD LINK
	PION
	RET			;DONE

   >	;IFN CFSSCA
	SUBTTL	Sending Messages -- SCASND (Send a message)

;Routine to send a message.
;	T1/ Buffer address
;	T2/ host number
;Returns:	+1/ failed. T3/ buffer address
;		+2 success

   IFE CFSSCA,<
SCASND:	BUG.(HLT,CFSSMC,CFSSRV,SOFT,<CFSSRV - Tried to send a message>,,<

Cause:	CFSSRV tried to send an SCA message and that option is not
	supported in this version of TOPS-20>
)
   >	;IFE CFSSCA
   IFN CFSSCA,<
SCASND:	ASUBR <SCBUFF,SCHOST>
	SKIPE CFSHST(T2)	;Is this on-line?
	SKIPL CFHSTS(T2)	;And up?
	IFNSK.			;If not
	 MOVE T3,T1		;Return message buffer in T3
	 RETBAD()		;And tell caller
	ENDIF.
	PIOFF
	SKIPE CFSSMQ(T2)	;A queue?
	IFNSK.			;If so
	 CALL SENDQ		;Queue it up
	 PION
	 RETSKP			;And done
	ENDIF.
	AOS CFSENT(T2)		;Sent one
;**;[7211] Add 1 line at SCASND+15	CEG 18-Dec-85
	AOS CFSSND		;[7211] ADD TO TOTAL SENT
	PION
	DO.
	 SETZRO STCRA,(T2)	;Say we are about to send
	 BLCAL. (SC.SMG,<CFSHST(T2),[F.RTB+F.SPM],[VOTSZB],T1,[CFSPRI],[0],[0]>)
	 IFNSK.
	  CAIN T1,SCSNEC	;NOT ENOUGH CREDIT?
	  IFNSK.		;If so...
	   MOVE T1,SCBUFF	;YES.
	   MOVE T2,SCHOST	;RESTORE ARGS
	   PIOFF
	   TMNE STCRA,(T2)	;Did credit arrive while we weren't looking?
	   IFNSK.		;If so
	    PION
	    LOOP.
	   ENDIF.
	   CALL SENDQ		;Queue it up
	   PION
	  ELSE.
	   MOVE T3,SCBUFF	;Reuturn buffer address in T3
	   RETBAD()		;Didn't send it
	  ENDIF.
	 ENDIF.
	ENDDO.
	RETSKP			;AND DONE
	ENDAS.
	SUBTTL	Sending Messages -- SENDQ (Maintain send queue)

;Routines to maintain the "send queue"

;Routine to enqueue a send message
;	T1/ Address of message
;	T2/ local port number
;Returns:
;	+1 always
;CALL PIOFF!!!

;messages are queued when an attempt to send them fails due to lack
;of credit.

SENDQ:	MOVEM T1,@CFSSQT(T2)	;Put it on
	SETZM 0(T1)
	MOVEM T1,CFSSQT(T2)
	RET			;And done

;Routine to send message from send queue until exhausted or failed
;	T1/ Local port
;Returns: +1 always

SSENDQ:	SAVEAC <Q1,Q2>
	MOVE Q1,T1		;Copy port
	DO.
	 SKIPN Q2,CFSSMQ(Q1)	;Any more to do?
	 RET			;No
;	 PIOFF
	 MOVE T2,0(Q2)		;Unlink it
	 MOVEM T2,CFSSMQ(Q1)	;New head
	 IFE. T2		;If now empty
	  XMOVEI T2,CFSSMQ(Q1)
	  MOVEM T2,CFSSQT(Q1)	;Init it
	 ENDIF.
;	 PION
	 BLCAL. (SC.SMG,<CFSHST(Q1),[F.RTB+F.SPM],[VOTSZB],Q2,[CFSPRI],[0],[0]>)
	 IFNSK.			;If failed
;	  PIOFF
	  MOVE T1,CFSSMQ(Q1)	;Get new head
	  MOVEM T1,0(Q2)	;Make this one the new head
	  MOVEM Q2,CFSSMQ(Q1)	;
	  SKIPN T1		;Was it empty?
	  MOVEM Q2,CFSSQT(Q1)	;yes.
;	  PION
	  RET			;And done
	 ENDIF.
	 LOOP.			;Do them all
	ENDDO.
	SUBTTL	Queuing Message Buffers -- SCARET (Queue packet as message buffer)

;Still IFN CFSSCA
;Routine to return a packet as a message buffer
;	T1/ address of buffer

SCARET:	MOVE T2,.MHSCI(T1)	;Get local index
	SKIPE CFSHST(T2)	;Is this slot in use?
	SKIPL CFHSTS(T2)	;Still?
	IFNSK.			;If not
	 MOVE T2,.MHDCI(T1)	;Get return address
	 CALLRET 0(T2)		;Return it
	ENDIF.
	BLCAL. (SC.RMG,<CFSHST(T2),[1],T1>)
	 NOP			;JUST IN CASE
	RET
	SUBTTL	Declare a listener -- CFSLSN (Declare CFS listener)

;Routine to declare a CFS listener.
;Returns:
;	+1 failed
;		T1=0 if no more host slots
;		T1<>0 if some SCA error
;Call with CFS interlock set, please

CFSLSN:	SAVEQ
	PIOFF
	MOVSI T1,-HSTSIZ	;SIZE OF HOST TABLE
	DO.			;LOOP TO FIND FREE SLOT
	SKIPE CFSHST(T1)	;FOUND ONE?
	IFSKP.			;IF SO
	 SETOM CFSHST(T1)	;MARK WE ARE LISTENING ON THIS PORT
	 SETZM CFHSTS(T1)	;INIT status
	 PION
	 HRRZ Q1,T1		;GET INDEX
	 BLCAL. (SC.LIS,<<.,LISNAM>,<.,LISNAM>,[-1],<.,CFSSTS>,Q1,[SCRDIT],[RCRDIT]>)
	 IFNSK.
	  SETZM CFSHST(Q1)	;AN ERROR. NO LONGER LISTENING
	  BUG. (HLT,CFLISF,CFSSRV,SOFT,<CFSSRV - SC.LIS failed>,<<T1,ERR>>,<

Cause:	The call to SC.LIS failed.

Data:	ERR - Error code returned by SC.LIS

>)
	  RET			;BAD
	 ENDIF.
	 MOVEM T1,CFSHNM(Q1)	;STASH I.D. HERE FOR NOW
	 RETSKP			;AND SUCCEED
	ENDIF.
	AOBJN T1,TOP.		;TRY THE NEXT
	PION
	ENDDO.			;END OF LOOP ON CFSHST
	CALLRET RETZ		;NONE TO BE FOUND
	SUBTTL	Connection Management -- CHKOLD (Manage connect serial number)

;Routine to manage the connect serial number data base. CFS keeps track
;of all systems it has ever been connected to so it may prevent illegal
;reconnects.
;	CALL CHKOLD
;T1/ Serial number to check
;T2/ Old/ New flag
;Returns:	+1 we've never been connected
;		+2 we have been

CHKOLD:	SAVEP			;Get some work regs
	CAIE T2,OF%OLD		;Does it think we are old?
	TDZA T2,T2		;No
	MOVX T2,1B0
	MOVSI P1,-HSTSIZ	;Size of the table
	MOVE P2,OLDTAB		;The address of the table
	DO.			;Scan it
	 SKIPE P3,0(P2)		;Look at this one
	 TDZ P3,T2		;Do operation of delay bit
	 CAME P3,T1		;Is it the one?
	 SKIPA
	 RETSKP			;Yep
	 ADDI P2,1		;Next slot
	 AOBJN P1,TOP.		;Look at them all
	ENDDO.
	RET			;And say it's new

 	SUBTTL	Connection Management -- CHKOL0 (Generate old/new bit)

;Routine to generate old/new bit
;	CALL CHKOL0
; T1/ serial number to look for
;Returns: +1 T1/ old/new bit

CHKOL0:	SAVEAC<Q1>
	MOVEI T2,HSTSIZ
	MOVE T3,OLDTAB
	MOVE T4,T1		;Copy serial number
	DO.
	 SKIPN Q1,0(T3)		;Get next
	 IFSKP.			;If here
	  TXZ Q1,1B0		;Ignore this for now
	  CAME Q1,T4		;Is it the one we want
	  ANSKP.		;If so
	  SKIPL 0(T3)		;Delay or old?
	  SKIPA T1,[OF%OLD]	;Old
	  MOVX T1,OF%DLY	;Delayed
	  RET
	 ENDIF.
	 ADDI T3,1		;Next
	 SOJG T2,TOP.
	ENDDO.
	MOVX T1,OF%NEW
	RET

 	SUBTTL	Connection Management -- PUTOLD (Install serial number)

;Routine to install a serial number.
;	T2/ the number to install
;Returns:	+1 always

PUTOLD:	SAVEP			;Get some work regs
	MOVSI P1,-HSTSIZ	;Size of the table
	MOVE P2,OLDTAB		;The address of the table
	DO.			;Scan it
	 SKIPN P4,0(P2)		;Look at this one
	 IFSKP.			;If occupied
	  TXZ P4,1B0		;Turn off delay bit
	  CAMN T2,P4		;Is it what we want?
	  IFNSK.		;If so
	   MOVE P3,P2		;Save the index
	   EXIT.		;And reinstall it
	  ENDIF.
	 ELSE.			;If empty
	  MOVE P3,P2		;Save the slot
	 ENDIF.
	 ADDI P2,1		;Next slot
	 AOBJN P1,TOP.		;Look at them all
	ENDDO.
   IFN DEBUG,<
;	SKIPE DLYFLG		;Only do it if flag is set
   >	;IFN DEBUG
	TXO T2,1B0		;Say this is under delay
	MOVEM T2,0(P3)		;It is new. Store it
	RET			;And say it's new

 	SUBTTL	Connection Management -- CLRDLY (Clear delay bit in OLDTAB entries)

;Routine to clear delay bit in OLD table entries

CLRDLY:	MOVEI T1,HSTSIZ		;The size
	MOVE T2,OLDTAB		;The table
	MOVX T3,1B0		;The bit to clear
	DO.
	 ANDCAM T3,0(T2)	;Clear it
	 ADDI T2,1		;Next entry
	 SOJG T1,TOP.		;Do them all
	ENDDO.
	RET

  	SUBTTL	Connection Management -- CHKDLY (Check for delayed entries)

;Routine to check if any delayed entries are still in OLDTAB
;		CALL CHKDLY
; T1/ Entry to remove
;Returns:	+1 Always. DLYLOK cleared if none left
;All regs preserved

CHKDLY:	SAVET
	SAVEAC <Q1>
	MOVEI Q1,HSTSIZ		;Size of the table
	MOVE T2,OLDTAB
	SETZM T4		;Assume none here
	DO.
	 SKIPGE T3,0(T2)	;Delay?
	 IFNSK.			;If so
	  TXZ T3,1B0		;Turn off bit
	  CAME T3,T1		;Is it the one we want?
	  AOSA T4		;No. Say not clear yet
	  SETZM 0(T2)		;Yes. Clear it
	 ENDIF.
	 ADDI T2,1		;Next entry
	 SOJG Q1,TOP.		;Check it all out
	 SKIPN T4		;Found any?
	 SETZM DLYLOK		;No, all clear!
	ENDDO.
	RET
   >	;IFN CFSSCA
	SUBTTL	Directory lock resource manager -- CFSLDR (Lock directory)

;Directory lock support routines. These routines are used by
;DIRECT to lock and maintain directory lock.
;	T1/ Structure number
;	T2/ directory number on structure
;Returns:
;	+1 always

CFSLDR::STKVAR<STRA,<ARGS,2>>	;WHERE TO SAVE ARGS
	MOVEM T1,STRA		;Save structure number
	CALL GNAME		;Get str name
	TXO T2,DRBASE
	DMOVEM T1,ARGS
	CSKED
	CFSLOK
	CALL HSHLOK		;SEE IF WE HAVE IT YET
	 JRST CFSDLN		;NOPE.
	JN <HSHWVT,HSHCNT>,(T1),CFSDLN ;If in use or voting, do vote
	INCR HSHCNT,(T1)	;NOT IN USE. GRAB IT
	MOVE T3,FORKX
	STOR T3,HSHFRK,(T1)	;Store new owner
	MOVE T3,TODCLK		;GET NOW
	MOVEM T3,HSHTIM(T1)	;STORE NOW
	CALLRET CFSFAL		;SUCCEED

;Here if we can't seize it

CFSDLN:	CFSULK
CFSDL0:	CALL CFSSPL		;GET A REQUEST BLOCK
	IFNSK.			;If can't
	 CALL CFSDM0		;Release some
	 JRST CFSDL0		;And try again
	ENDIF.
	;..
;Fill in the request block to ask for the resource

	DMOVE T2,ARGS
	DMOVEM T2,HSHROT(T1)	;STORE LOCK VALUES
	MOVEI T2,.HTOEX		;NEED EXL
	STOR T2,HSHTYP,(T1)	;STORE IT
	MOVX T2,DRBASE
	MOVEM T2,HSHCOD(T1)	;THE UNIQUE CODE FOR THIS
	MOVE T3,TODCLK		;Now
	ADDI T3,DIRTIM		;Keep it for a bit
	MOVEM T3,HSHFCT(T1)	;Stash it
	MOVE T3,STRA		;Get original str number
	CALL CFSGTT
	 CALL ILLGET
	SKIPE T1		;SUCCEEDED
	CALL @HSHRET(T1)	;DIDN'T NEED OUR BLOCK
	RET			;AND DONE

;No space to request the thing.

CFSDM0:	CALLRET SBLOCK		;Use standard routine
	SUBTTL	Directory lock resource manager -- CFSRDR (Unlock directory)

;Routine to unlock a directory.
;	T1/ Structure number
;	T2/ directory number
;Returns:
;	+1 did a resched
;	+2 no resched

CFSRDR::CALL GNAME
	TXO T2,DRBASE
	SETZM T3
	CALL CFSNDO		;RELEASE IT
	IFNSK.			;If can't
	 BUG.(CHK,DIRDNL,CFSSRV,SOFT,<CFSSRV - Directory not locked>,,<

Cause:	CFSRDR was called to unlock a directory, but the directory is not
	locked.
>)
	 RET			;Wasn't locked!
	ENDIF.
	ECSKED
	RET			;AND DONE
	SUBTTL	Directory lock resource manager -- CFSDAU (Acquire allocation entry)

;Directory allocation support routines. These routines create and
;maintain resources representing the allocation of directories.
;
;Acquire allocation entry
;	T1/ Str # or resource node address
;	T2/ Dir # or 0
;	T3/ Flags,,Operation
;	 .CFAGT==:0	;Get and lock current allocation
;	 .CFAST==:1	;Store allocation
;	 .CFARL==:2	;Release allocation table
;	 .CFARM==:3	;remove entry
;	 .CFAUP==:4	;Undo hold bit
;	 .CFAFD==:5	; Find it
;	T4/ Current allocation or -1 if none to set
; Returned allocation in T1
;return resource address in T2 is called without this
;	T3/ transaction number if new block allocated

CFSDAU::ASUBR <STRN0,DIRN,ACCESS,ALLC>
	HRRZS T3
	CAILE T3,.CFAFD		;Still?
	BUG.(HLT,CFBAFN,CFSSRV,SOFT,<CFSSRV - Bad function to CFSDAU>,,<

Cause:	CFSDAU was called with an invalid function.

Action:	Find the caller in the dump and try to determine why it passed a
	bad function code to CFSDAU.

>)
	SAVEQ			;Work regs
	JRST @[IFIW!CFAGET	;Lock allocation entry and get value
	       IFIW!CFASTO	;Store new value and unlock
	       IFIW!CFAULK	;Unlock table
	       IFIW!CFAREM	;Remove entry
	       IFIW!CFAUPB	;Undo hold bit
	       IFIW!CFAFND](T3) ;Find

 	SUBTTL	Directory lock resource manager -- CFAFND/CFAGET (Find/Get allocation table)

;Lock allocation table

CFAFND:	TDZA T4,T4
CFAGET:	MOVEI T4,1
	SAVEAC<P1,P2>
	MOVE P2,T4
	SETZM P1
CFAG00:	MOVEI Q3,.HTOEX		;Assume exclusive
	TMNN CF%HLD,ACCESS	;Need it held?
	MOVEI Q3,.HTOAD		;No. Share it then
	CALL GETDBK
	IFNSK.			;If not here...
	 SKIPE T2,P2		;If finding...
	 AOJA P1,CFSDAO		;Go to it if not
	 CALLRET CFSFAL		;Fail otherwise
	ENDIF.
   IFNDEF CFSDUM,<		;Only if we are a real CFS node
	TMNN CF%PRM,ACCESS	;Want it held?
	IFSKP.
	 SETONE HSHKPH,(T1)	;Hold it here
	ENDIF.
	TMNE <HSHTWF,HSHWVT,HSHUGD>,(T1) ;Anybody else doing this?
	IFNSK.			;If so
	 MOVE T2,T1		;Copy address
	 MOVEI T1,CFGVOT	;Wait for a bit
	 CFSULK
	 CALL CFSWUP		;""
	 AOJA P1,CFAG00
	ENDIF.
	LOAD T2,HSHTYP,(T1)	;Get the type
	CAMGE T2,Q3		;Is it all set for us?
	IFNSK.			;If not

;Here when the access is not correct

	 SETONE HSHTWF,(T1)	;Prevent tampering from others
	 MOVEI T3,0(Q3)		;Get access desired
	 MOVE Q1,T1		;Save block address
	 DMOVE T1,HSHROT(T1)	;Get lookup stuff
	 AOS P1
	 CALL CFSUGD		;Do the upgrade
	 IFNSK.
	  SETZRO HSHTWF,(Q1)	;No longer need this
	  MOVEI T1,CFSRWT	;Wait a bit
	  MOVE T2,Q1		;The block
	  SKIPN T3,HSHWTM(Q1)	;Got a wait time?
	  MOVEI T3,^D500	;No invent one
	  ADD T3,TODCLK		;When to retry
	  MOVEM T3,HSHTIM(Q1)
	  CALL CFSWUP		;Wait a bit
	  DMOVE T1,Q1
	  JRST CFAG00		;And do it again
	 ENDIF.
	 CFSLOK
	 SETZRO HSHTWF,(Q1)	;Not blocked anymore
	 MOVE T1,Q1
	ELSE.
	 INCR HSHCNT,(T1)	;Yes.
	ENDIF.
	TMNE CF%HLD,ACCESS	;Want it held?
	IFSKP.			;If not
	 DECR HSHCNT,(T1)	;So don't
	ENDIF.
   >	;IFNDEF CFSDUM
	MOVE T2,FORKX		;Fork
	STOR T2,HSHFRK,(T1)
	MOVE T2,T1		;Resource address
	MOVE T3,HSHOP1(T1)	;Get resource count as well
	MOVE T1,HSHOPT(T1)	;Get last value of allocation
	CFSULK
	JUMPE P1,RSKP		;If no resched, say so
	RET			;And done, with a resched
;Here if we must vote

CFSDAO:	CALL CFSSPC		;Get some space
	IFNSK.			;If failed
	 CALL CFSDM0		;Standard recovery
	 JRST CFAG00		;Try again
	ENDIF.
	DMOVEM Q1,HSHROT(T1)	;Store indentifier
	STOR Q3,HSHTYP,(T1)	;Store type needed
	TMNN CF%PRM,ACCESS	;Want it held?
	IFSKP.
	 SETONE HSHKPH,(T1)	;Keep this
	ENDIF.
	SETZM HSHOPT(T1)	;No optional data yet
	SETZM HSHOP1(T1)	;No transaction number yet
	XMOVEI T2,CFAVOK	;When we are to approve a vote
	MOVEM T2,HSHOKV(T1)	;Call us here
	XMOVEI T2,CFADAR	;When we get some optional data
	MOVEM T2,HSHCDA(T1)	;Call us here
	XMOVEI T2,CFARMV	;Disallow allocations
	MOVEM T2,HSHPST(T1)	;Don't allow release
	MOVE T3,STRN0		;Get structure number
	CALL CFSGTT
	 CALL ILLGET
	SKIPE T1		;Did we use this?
	CALL @HSHRET(T1)	;No. Return it then
	CFSLOK			;Lock it
	DMOVE T1,Q1
	CALL HSHLOK		;Find the entry
	 BUG.(HLT,CFSNAF,CFSSRV,SOFT,<Allocation entry not found>,,<

Cause:	An allocation entry has just been created and  CFSSRV can't find
	it in the hash table.
>)
	TMNE CF%HLD,ACCESS	;Want it held?
	IFSKP.			;if not
	 DECR HSHCNT,(T1)	;Get rid of it
	ENDIF.
	SKIPE T3,HSHOP1(T1)	;Anything in here?
	IFNSK.			;If so
	 MOVE T2,T1		;Get resource address
	 MOVE T1,HSHOPT(T1)	;Get it
	ELSE.			;If not
	 MOVE T2,ALLC		;Get new value
	 MOVEM T2,HSHOPT(T1)	;Stash
	 TMNN CF%NUL,ACCESS	;Is the value valid?
	 AOS HSHOP1(T1)		;Say we've been here
	 EXCH T1,T2
	ENDIF.
	CALLRET CFSFAL		;And done (we did a resched if we got here)
	SUBTTL	Directory lock resource manager -- CFASTO (Store new allocation value)

;CFSDAU continued.
;CFASTO - Store new value

CFASTO:	CALL GETDBK		;Get block address
CFABUG:	 BUG.(HLT,CFANAE,CFSSRV,SOFT,<CFSSRV - No allocation entry>,,<

Cause:	The caller wanted to update a directory allocation entry, and
	no such entry could be found
>)

	MOVE T2,ALLC		;Get the value
	MOVEM T2,HSHOPT(T1)	;Stash it
	AOS HSHOP1(T1)		;And make this transaction current
	CFSULK			;Unlock it
	DMOVE T1,Q1
;	CALLRET CFAULK		;And release it

 	SUBTTL	Directory lock resource manager -- CFAULK (Unlock allocation entry)

;Unlock allocation entry

CFAULK:	CALL GETDBK		;Get block address
	 CALL CFABUG
	CFSULK
	DMOVE T1,HSHROT(T1)
	CALLRET CFSNDO		;Do it

 	SUBTTL	Directory lock resource manager -- CFAREM (Remove allocation entry)

;Remove entry

CFAREM:	CALL GETDBK		;Find the block
	 CALL CFABUG		;Bad!
	LOAD T2,HSHCNT,(T1)	;Get current share count
	SOSG T2			;Should we do it?
	IFSKP.			;If not
	 STOR T2,HSHCNT,(T1)	;Store new value
	ELSE.
	 CALL CFSRMV		;remove the entry
	ENDIF.
	CALLRET CFSRSK		;And done

 	SUBTTL	Directory lock resource manager -- CFAUPB (Undo keep here bit)

;Undo "keep here" bit

CFAUPB:	CALL GETDBK		;Find it
	 CALL CFABUG		;Oops
	SETZRO HSHKPH,(T1)	;Clear this
	CFSULK
	DMOVE T1,HSHROT(T1)	;Get lookup values
	CALL CFSNDO
	 NOP
	RET
	SUBTTL	Directory lock resource manager -- CFAVOK (Vote to be approved)

   IFNDEF CFSDUM,<		;If doing CFS for real
 
;CFAULK stuff continued.
; Interrupt level support routines

;CFAVOK -  Called when vote is to be approved
;	T1/ vote packet
;	T2/ hash packet

CFAVOK:	DMOVE T3,HSHOPT(T2)	;Yes, get the stuff
	DMOVEM T3,CFDAT(T1)	;Store it
	SETONE CFODA,(T1)	;Say we put something here
	RET			;And done

 	SUBTTL	Directory lock resource manager -- CFADAR (Optional data present)

;Here when optional data arrives on a vote
;	T1/ Hash packet
;	Q1/ Vote pakcet

CFADAR:	SKIPE T2,CFDT1(Q1)	;has he anything to say?
	CAMG T2,HSHOP1(T1)	;A later transaction?
	RET			;No
	RETSKP			;yes.

 	SUBTTL	Directory lock resource manager -- CFARMV (Voter remove entry)

;here when entry is to be removed by voter

CFARMV:	JE HSHKPH,(T1),R	;If not holding, remove it
	SETZRO HSHTYP,(T1)	;If holding, turn it into a place-holder
	RETSKP			;And allow access
   >	;IFNDEF CFSDUM

   IFDEF CFSDUM,<		;If not doing CFS for real
CFADAR:
CFARMV:
CFAVOK:	RET			;Dummies
   >	;IFDEF CFSDUM
	SUBTTL	Directory lock resource manager -- GETDBK (Find resource block)

;CFSDAU continued
;Utility to find resource block
;Args in ASUBR on the stack
;Returns:	+1 not found. Q1, Q2 with names
;		+2 T1/ block. CFS lock locked

GETDBK:	CFSLOK			;Lock it up
	MOVE T1,STRN0		;Get str number
	SKIPN T2,DIRN		;Name or address
	RETSKP			;Address
	CALL GNAME		;Get its name
	MOVE T2,DIRN		;Get directory number
	TXO T2,DRBAS0
	DMOVE Q1,T1		;Save names
	CALL HSHLOK
	 JRST CFSFAL		;Not there
	RETSKP			;Found it
	ENDAS.
	SUBTTL	File open resource manager -- CFSGFA (Acquire file opening locks)

;Routine to acquire file locks on "first opening".
;Called from GETCFL in PAGUTL.
;
;	T1/ STR #
;	T2/ XB address
;	T3/ Access type - either: .CFOPT - Open thawed (full sharing)
;				  .CFOPF - Open frozen
;				  .CFOPR - Restricted
;				  .CFOPP - Promiscuous (unrestricted)
;				  .CFOLE - DUD

   IFNDEF CFSDUM,<		;If CFS
CFSGFA::SAVEQ
	STKVAR <ACCESS>
	MOVE T3,[.HTOAD		;Full sharing
		 .HTOSH		;Read-only sharing
		 .HTOEX		;Exclusive
		 .HTOPM		;Promiscuous
		 1B0!.HTOEX](T3) ;Local exclusive
	DMOVE Q1,T1		;COPY ARGS
	MOVEM T3,ACCESS
	CALL GNAME
	CFSLOK
	CALL HSHLOK		;Look 'er up
	IFSKP.			;If here
	 MOVE Q3,T1		;Save block address
	 DMOVE T1,HSHROT(T1)	;Get root and qualifier
	 MOVE T3,ACCESS		;new access
	 CALL CFSUGD		;Change it
	  RETBAD()		;No way
;	 DECR HSHCNT,(Q3)	;Discount extra sharer
	 RETSKP			;Made it
	ENDIF.
	CFSULK
	CALL CFSSPC		;GET SOME SPACE
	IFNSK.
		MOVEI T1,^D30000 ;PICK UP STALE RESOURCES
		MOVEI T2,10	;JUST DO SOME
		CALL CFSRSX	;FREE UP SOME
		CALL CFSSPC	;TRY AGAIN
		 RETBAD()	;NOPE
	ENDIF.
	MOVE Q3,T1		;COPY BLOCK
	MOVE T2,ACCESS		;Desired access
	STOR T2,HSHTYP,(T1)	;Stash it
	IFL. T2			;If want local exclusive
	 SETONE HSHLCL,(T1)	;Set it
	ENDIF.
	MOVEM Q2,HSHQAL(T1)
	MOVE T2,Q1		;STR #
	CALL GNAME2
	MOVEM T2,HSHROT(T1)
	MOVE T3,Q1		;Copy structure #
	CALLRET CFSFCA		;DO COMMON ACQUISITION CODE
   >	;IFNDEF CFSDUM
 	SUBTTL	File open resource manager -- CFSFFL (Release file locks)

;Release file locks
;T1/	STR #
;T2/	XB address
;Returns:	+1 always

   IFNDEF CFSDUM,<
CFSFFL::CALL GNAME
	CALL CFSNDO		;FREE IT
	 NOP
	RET
   >	;IFNDEF CFSDUM
	SUBTTL	File open resource manager -- CFSURA (Downgrade to promiscuous)

;Routine to "downgrade" file lock from whatever to promiscuous.
;Called when RELOFN (in PAGEM) detects all "real" openings
;are closed
;	T1/ OFN
;Returns:	+1 always

	   IFNDEF CFSDUM,<
CFSURA::SAVET
	SAVEAC<Q1>
	LOAD T2,STGADR,SPTH(T1)	;Get XB address
	LOAD T1,STRX,(T1)
	CALL GNAME
	CFSLOK
	CALL HSHLOK		;Look it up
	IFNSK.			;This shouldn't happen
	 CFSULK
	 RET
	ENDIF.
	MOVE Q1,T1
	DMOVE T1,HSHROT(T1)	;Get codes
	MOVEI T3,.HTOPM		;New mode
	CALL CFSUGD		;Do it
	 CALL CFNCNT
	DECR HSHCNT,(Q1)
	RET			;And done
   >	;IFNDEF CFSDUM

;Versions of above for non-CFS

   IFDEF CFSDUM,<
CFSGFA::RETSKP
CFSURA::RET
   >	;IFDEF CFSDUM
	SUBTTL	Frozen writer resource manager -- CFSGWL (Get write access)

;Routine used by PAGEM to acquire the "write access" lock for a fil.
;This "lock" represents the writer for a frozen file.
;	T1/ STR #
;	T2/ XB address
;Returns:
;	+1 failed. Lock owned elsewhere
;	+2 success

CFSGWL::
   IFDEF CFSDUM,<		;If not a real CFS
	RETSKP			;Done
   >	;IFDEF CFSDUM
   IFNDEF CFSDUM,<		;If real
	SAVEQ
	DMOVE Q1,T1
	CALL CFSSPC		;GET A BLOCK
	IFNSK.
		SETZM T1
		MOVEI T2,10	;JUST DO SOME
		CALL CFSRSX	;FAILED. FREE UP SPACE THEN
		CALL CFSSPC	;TRY AGAIN
		 RETBAD()	;FAILED. NO SPACE
	ENDIF.
	MOVE T2,Q1		;STR #
	CALL GNAME2
	MOVEM T2,HSHROT(T1)	;Stroe it
	TXO Q2,FILEWL		;MARK WRITE LOCK WANTED
	MOVEM Q2,HSHQAL(T1)	;Store the qualifier
	MOVEI T2,.HTOEX		;EXCLUSIVE
	STOR T2,HSHTYP,(T1)
	MOVE T3,Q1		;Copy str #
	;CALLRET CFSFCA

;Pseudo-routine to acquire a file resource

CFSFCA:	SETZM T2		;NO RETRY
	CALL CFSGTT
	 RETBAD()		; It didn't
	SKIPE T1		;NEED TO RETURN THE BLOCK?
	CALL @HSHRET(T1)	;YES
	RETSKP			;AND DONE
   >	;IFNDEF CFSDUM
	SUBTTL	Frozen writer resource manager -- CFSFWL (Free write access)

;Free CFS file write lock
;T1/	STR #
;T2/	XB address
;Returns:
;	+1 always

   IFNDEF CFSDUM,<
CFSFWL::TXO T2,FILEWL		;UNQ
	CALL GNAME
	CALL CFSNDO		;RELEASE IT
	 NOP
	RET
   >	;IFNDEF CFSDUM


;Versions of above for non-CFS

   IFDEF CFSDUM,<
CFSFFL::
CFSFWL::RET
   >	;IFDEF CFSDUM
;LOCAL ROUTINE TO CLEAN UP RESOURCES AND WAIT A LITTLE BIT

SBLOCK:	SETZM T1		;Desparation. Get a bunch
	MOVEI T2,CLCCNT		;Count to collect
	CALL CFSRSX
	MOVE T1,TODCLK
	ANDI T1,377777
	ADDI T1,^D300		;SHORT SLEEP
	MOVSS T1
	HRRI T1,BLOCKW		;THE TEST
	CALL CFSWUP		;WAIT
	RET			;AND DONE
	SUBTTL BAT block resource manager -- CFGBBS (Set BAT block lock)

;Routines to get and release BAT block locks.
;Get lock
;	T1/ Structure number
;	Returns: +1 always

   IFNDEF CFSDUM,<		;If CFS
CFGBBS::ASUBR<STRNO>
CFGBB0:	CALL CFSSPC		;GET SOME SPACE
	IFNSK.
	 CALL SBLOCK		;WAIT A BIT
	 JRST CFGBB0		;TRY AGAIN
	ENDIF.
	MOVE T2,STRNO
	SETOM HSHQAL(T1)	;BAT BLOCK CODE
	CALL GNAME2
	MOVEM T2,HSHROT(T1)
	MOVEI T2,.HTOEX		;NEED EXCLUSIVE ACCESS
	STOR T2,HSHTYP,(T1)	;STASH IT
	MOVE T3,STRNO
	MOVE T3,STRTAB(T3)
	LOAD T3,STEXL,(T3)
	CALL @[	IFIW!CFSGET
		IFIW!CFSGTL](T3)
	 CALL ILLGET
	SKIPE T1		;WANT IT RELEASED?
	CALL @HSHRET(T1)	;YES
	RET			;DONE
	ENDAS.
 	SUBTTL	BAT block resource manager -- CFFBBS (Release BAT block lock)

;Release BAT block lock
;	T1/ Str number
;	Returns: +1 always

CFFBBS::CALL GNAME
	SETOM T2
	CALL CFSNDO
	 NOP			;Who cares?
	RET			;And done
   >	;IFNDEF CFSDUM

;Versions of above for non-CFS

   IFDEF CFSDUM,<
CFFBBS::
CFGBBS::RET
   >	;IFDEF CFSDUM
	SUBTTL	File access token resource manager -- CFSGWT (Get write token value)

;Routines to manage the "write token".

;Fetch current value of token
;	T1/ OFN
;Returns:
;	+1 not here or in use. T1=0= not here. If here, T2/ 0 or 1
;	+2 T1/ 0 or 1
;Called NOSKED!!!

CFSGWT::LOAD T2,STGADR,SPTH(T1)	;GET XB
	TXO T2,FILEWT
	LOAD T1,STRX,(T1)
	CALL GNAME
	CFSLOK
	CALL HSHLOK		;LOOK 'ER UP
	 JRST [	CFSULK
		JRST RETZ]
	MOVE T2,TODCLK		;GET NOW
	MOVEM T2,HSHTIM(T1)	;STAMP IT
	LOAD T2,HSHCNT,(T1)
	LOAD T1,HSHTYP,(T1)	;GET TYPE
	JUMPE T1,[ CFSULK	;If a place-holder
		   JRST RETZ]	; Treat as if not here
	CAIE T1,.HTOEX		;EXCLUSIVE?
	TDZA T1,T1		;No.
	MOVEI T1,1		;Yes
	CFSULK
	IFG. T2
	 MOVE T2,T1		;GET ACCESS TYPE
	 JRST RETO		;AND DONE
	ENDIF.
	RETSKP			;AND DONE
	SUBTTL	File access token resource manager -- CFSAWP/CFSAWT (Acquire write token)

;Routine to acquire the proper "write token".
;	T1/ OFN
;	T2/ type needed
;	 0=) shared, <>0=) exclusive
;Returns:	+1 always
;Called NOSKED

;CFSAWP - reserve to this processor
;CFSAWT - don't reserve to this processor

CFSAWP::TDZA T3,T3		;LEAVE IT LOCKED
CFSAWT::MOVEI T3,1		;UNLOCK WHEN DONE
	TMNE OFNDMO,SPTH(T1)
	RET			;If dismounted, let it go
;**;[7247]  Add 11 lines after CFSAWT::+2		DML	19-Feb-86
	CAIGE T1,NOFN		;[7247] Is the OFN in range?
	TLNE T1,-1		;[7247] And is it positioned correctly?
	BUG.(HLT,CFSION,CFSSRV,SOFT,<CFSSRV - Invalid OFN number>,,<

Cause:	CFSAWT or CFSAWP has been called with an invalid OFN number.
	These routines expect the OFN number to be in the right half
	of T1 and to be in the expected range of values.

Action:	Find the caller in the dump and try to determine why it
	passed a bad OFN number.
>)				;[7247] No, report error
	SAVEP5			;REGS
	STKVAR <WTFLAG,LKFLAG>
	MOVEM T3,LKFLAG		;Save the flag
	SKIPE T2		;Check what kind we need
	SKIPA T2,[.HTOEX]	;Exclusive
	MOVEI T2,.HTOAD		;Full read-share
	DMOVE P1,T1		;SAVE OFN and access type
   IFNDEF CFSDUM,<		;If a real CFS monitor, do this as well
CFSAWL:
	DO.
	 LOAD T1,STRX,(P1)	;GET STR NAME
	 CFSLOK
	 TMNE SPTFO,(P1)	;Being forced out?
	 SKIPGE DDPFRK		;Is this not DDMP
	 IFSKP.			;If so
	  MOVS T1,P1		;Get OFN
	  HRRI T1,WTFOD		;wait here a bit
	  CFSULK
	  CALL CFSWUP		;Wait here
	  LOOP.			;Try again
	 ENDIF.
	ENDDO.
	MOVE T2,CFSOFN		;Get OFN table address
	ADDI T2,0(P1)		;See if we know about this one yet
;**;[7247]  Replace 5 lines with 6 at CFSAWL:+16	DML	19-Feb-86
	SKIPN T1,0(T2)		;[7247] Do we?
	JRST CFSAW1		;[7247] Go on if not around
;[7247] Continue here if the block already exists or is cached and being reused

CFSAWH:				;[7247]
   IFN DEBUG,<
      	HRRZ T2,P1		;Isolate OFN
	CAME T2,HSHCOD(T1)	;Quick check for consistency
	BUG.(HLT,CFSBTP,CFSSRV,SOFT,<CFSSRV - Bad token packet>,,<

Cause:	CFSAWT has been called to acquire an access token for an OFN.
	The OFN access token already exists on this system and the 
	block address is in CFSOFN.  But the OFN recorded in the 
	block does not match the one passed into CFSAWT.
>)
   >	;IFN DEBUG
;**;[7247]  Change 1 line at CFSAWH:+11			DML	19-Feb-86
	SKIPG HSHPST(T1)	;[7247] This one in use and good?
	IFNSK.			;If not
	 XMOVEI T2,CFSDWT	;Where to do it
	 MOVEM T2,HSHPST(T1)	;Fix it up (make it a usable block)
	ENDIF.
	MOVE P5,T1		;Save pointer
	INCR HSHLKF,(P5)	;Lock it
CFSUGX:	TMNE <HSHTWF,HSHUGD,HSHWVT>,(P5) ;Waiting for it somewhere else?
	IFNSK.
	 CFSULK
	 MOVEI T1,CFGVOT	;And wait for vote to complete
	 SETOM WTFLAG		;We didn't set HSHTWF
	 JRST CFSUGW		;And wait a bit
	ENDIF.
	LOAD T3,HSHTYP,(P5)	;Get type we now hold
	LOAD T1,STRX,(P1)	;Get STR #
	MOVE T1,STRTAB(T1)	;Get SDB
	TMNE STEXL,(T1)		;Is this exclusive?
	IFNSK.			;If so
	 MOVEI T3,.HTOEX	;Upgrade it now to the maximum
	 STOR T3,HSHTYP,(P5)	;And store it
	ENDIF.
	CAIN T3,.HTOEX		;Do we hold exclusive rights?
	IFNSK.			;If so
   REPEAT 0,<			;Not using anti-hog device now
	 TMNN HSHRFF,(P5)	;Someone waiting?
	 IFSKP.			;If so
	  MOVE T1,HSHTIM(P5)	;Get last transition time
	  ADDI T1,MAXHLT	;Get constraint
	  CAML T1,TODCLK	;Held it too long?
	  IFSKP.		;If so
	   SETONE HSHTWF,(P5)	;lock it
	   SETZM WTFLAG		;Say we did it
	   MOVEI T1,CFSRWT	;Just stall a bit
	   CFSULK
	   JRST CFSUGW		;Do it
	  ENDIF.
	 ENDIF.
   >	;REPEAT 0
	 DECR HSHLKF,(P5)
	 MOVEI P2,0(T3)		;Copy type
	 SKIPE LKFLAG		;Check the lock flag
	 JRST RTYPE		;All set. Finish up
	 INCR HSHCNT,(P5)	;If hold do it
	 JRST RTYPE		;And set the state
	ENDIF.

;Found the entry. See if we can upgrade it

	SETONE HSHTWF,(P5)	;Set flag to prevent others from getting in
	SETZM WTFLAG
	DMOVE T1,HSHROT(P5)	;CODES
	MOVEI T3,0(P2)		;MUST WANT EXCLUSIVE
	LOAD T4,HSHTYP,(P5)	;Save state we have it in now
	CALL CFSUGD		;Must call with the interlock set!!!
	IFSKP.
	 CFSLOK
	 SETZRO <HSHRFF,HSHTWF>,(P5)
	 MOVE T1,TODCLK		;Get now
	 ADDI T1,WRTTIM		;fairness time
	 SKIPN P4		;Update only if we just seized it
	 MOVEM T1,HSHFCT(P5)
	 DECR HSHLKF,(P5)
	 SKIPN LKFLAG		;Want to hold?
	 IFSKP.			;If not
	  TMNN HSHCNT,(P5)	;Any count?
	  CALL CFNCNT		;No!
	  DECR HSHCNT,(P5)	; release the hold
	 ENDIF.
	 TMNN HSHCNT,(P5)	;is it still locked here?
	 SKIPN HSHNBT(P5)	;If no, anyone to notify?
	 IFSKP.			;If so
	  MOVE T1,P5		;Copy address
	  CALL CFNOHS		;Notify anyone rejected in the interim
	 ENDIF.
	 TMNE HSHODA,(P5)	;Any optional data?
	 IFNSK.			;If so,
	  MOVE T2,HSHOPT(P5)	;Get it
;	  SKIPE HSHOP1(P5)	;Store only if from the owner
	  MOVEM T2,OFNLEN(P1)	;Update length information
	  SETZRO HSHODA,(P5)	;And no longer valid
	 ENDIF.
	 JRST RTYPE		;And go set the state
	ENDIF.
	SETZRO HSHTWF,(P5)	;Clear it now
	SETOM WTFLAG		;And say we didn't set it
	MOVEI T1,CFSRWT		;Do this one if here
	SKIPE T2,HSHWTM(P5)	;gave us a time to wait?
	IFNSK.			;If so
	 CAIGE T2,^D20		;Wait at least this long
	 MOVEI T2,^D20		;""
	 SKIPA
	ENDIF.
	; ..
;Here when couldn't upgrade an entry

CFSUGW:	MOVEI T2,^D500		;Wait a long time if here (we should be
				; notified via the "undo" when to try again
	ADD T2,TODCLK		;Wait time
	MOVEM T2,HSHTIM(P5)
	MOVE T2,P5		;Block address
	CALL CFSWUP		;Do the wait
	CFSLOK			;Lock 'er up
	SKIPN WTFLAG		;Did we set the wait flag?
	IFNSK.			;If so
	 SETZRO HSHTWF,(P5)
	ENDIF.
;**;[7247]  Change 1 line at CFSUGW:+11			DML	19-Feb-86
	SKIPLE HSHPST(P5)	;[7247] Has it been released or uncached?
	IFNSK.			;If not
	 SETZRO <HSHRTY,HSHVRS>,(P5)
	 DECR HSHLKF,(P5)	;No longer need this lock
	 CFSULK			;Don't need this now
	 JRST CFSAWL		;And go to the top
	ENDIF.
	LOAD T1,HSHLKF,(P5)	;Get lock value
	SOSE T1			;Are we the last?
	IFNSK.			;If not
	 STOR T1,HSHLKF,(P5)	;Replace it
	 JRST CFSFAL
	ENDIF.
	MOVE T1,HSHCOD(P5)	;Get the OFN
	ADD T1,CFSOFN		;Point to OFN table entry
	SETZM 0(T1)		;Clear it
;**;[7247]  Replace 2 lines with 25 at CFGVOT:-6       	DML	19-Feb-86

;[7247] Here when a call was made to CFSUWT or CFSUNC while block was locked

	SKIPL HSHPST(P5)	;[7247] Was a token uncache attempted?
	IFSKP.			;[7247] Yes
	  SETZRO HSHTAM,(P5)	;[7247] Uncache just in case it was set
	  SOS CFACCT		;[7247] Decrement currently cached count
	  MOVE T1,P5		;[7247] Get resource block address
	  CALL CFSRMV		;[7247] (T1/T1,T2)Remove it
	  CALLRET CFSFAL	;[7247] And return
	ENDIF.			;[7247] 

;[7247] Here when a call was made to CFSCWT while block was locked

	SUB T1,CFSOFN		;[7247] Get OFN back again
	TMNN OFNDMO,SPTH(T1)	;[7247] Is it dismounted?
	IFSKP.			;[7247] Yes, destroy token
	  MOVE T1,P5		;[7247] Get resource block address
	  CALL CFSRMV		;[7247] (T1/T1,T2)Remove it
	ELSE.			;[7247] Not dismounted, cache it
	  SETZRO <HSHCNT>,(P5)  ;[7247] Clear the count but KEEP bit stays set
;**;[7507] Change 1 line at CFGVOT:-8L	MDR	29-JUL-87
	  SETONE <HSHTAM,HSHKPH>,(P5) ;[7507][7247] Set the cache bit and keep bit
	  SETZM HSHPST(P5)	;[7247] No more post address
	  AOS CFACCT		;[7247] Increment the number we currently have
	ENDIF.			;[7247]
	CALLRET CFSFAL

;test for above

CFGVOT:	LOAD T1,FKST2,(Q3)
	TMNE <HSHTWF,HSHWVT,HSHUGD>,(T1) ;Still waiting
	JRST 0(4)		;Yepper
	JRST 1(4)		;No. Try now
;Here to add an entry. Should happen only once in a while

CFSAW1:
	LOAD T1,STRX,(P1)	;Get STR #
	LOAD T2,STGADR,SPTH(P1)	;Get XB address
   IFN DEBUG,<			;Make sure all is OK
	SKIPN T2		;Is it?
	BUG. (HLT,CFNLTK,CFSSRV,SOFT,<CFSSRV - Null disk address given to CFSAWT>,,<

Cause:	A call was made to create an OFN access token but SPTH for the
	OFN is not set up.
>)
   >	;IFN DEBUG
	TXO T2,FILEWT		;Set token bit
	CALL GNAME		;Get the name of the structure
	DMOVE P3,T1		;Save these for later
;**;[7247]  Add 27 lines after CFSAW1:+13		DML	19-Feb-86
	CALL HSHLOK		;[7247] (T1,T2/T1,T2) Look for the token
	IFSKP.			;[7247] Found so this one better be cached
	  TMNN HSHTAM,(T1)	;[7247] Is it?
          BUG.(HLT,CFSTCM,CFSSRV,SOFT,<CFSSRV - Access token cached but not marked>,,<

Cause:	A cached access token is being requested.  As expected, it
	is in the hash table and not in CFSOFN.  But HSHTAM is not
	set as expected.
>)				;[7247] No, report error
	  CAME P1,HSHCOD(T1)	;[7247] Is this the same OFN?
          BUG.(HLT,CFAOFM,CFSSRV,SOFT,<CFSSRV - OFN mismatch in cached token>,,<

Cause:	A cached access token has been found for a certain OFN
	but the OFN stored in the hash block does not agree.
>)				;[7247] No, report error
	  MOVE T2,CFSOFN	;[7247] Get OFN table address
	  ADDI T2,0(P1)		;[7247] Offset into table for this OFN
	  MOVEM T1,0(T2)      	;[7247] Store token block address in table
	  SETZRO HSHTAM,(T1)	;[7247] Not cached anymore
	  SETONE HSHKPH,(T1)	;[7247] No purging this entry
	  XMOVEI T2,CFSDWT	;[7247] Get correct post address
	  MOVEM T2,HSHPST(T1)	;[7247] Fix it up (make it a usable block)
	  SOS CFACCT		;[7247] One less token currently cached
	  AOS CFACTO		;[7247] One more cache hit
	  JRST CFSAWH		;[7247] Continue at "found" code
	ENDIF.			;[7247] 
        CFSULK			;[7247] Free CFS lock
	DO.
	 CALL CFSSPC		;GET SOME SPACE
	 IFSKP. <EXIT.>
	 CALL CFSDM0		;Clean up and pause
	 LOOP.
	ENDDO.
	DMOVEM P3,HSHROT(T1)	;SAVE CODES
	STOR P2,HSHTYP,(T1)	;STASH IT
	SETONE HSHKPH,(T1)	;No purging this entry
	HRRZM P1,HSHCOD(T1)	;SAVE OFN AS CODE
	XMOVEI T2,CFSDWT
	MOVE P5,T1		;Save block address (to get optional data)
	MOVEM T2,HSHPST(T1)	;WHERE TO GO WHEN RELEASED
	XMOVEI T2,CFSOVT	;Where to go when vote is approved
	MOVEM T2,HSHOKV(T1)	;Store it
	XMOVEI T2,CFSDAR	;Data arrived
	MOVEM T2,HSHCDA(T1)	;Stash it as well
	SETZM HSHOP1(T1)	;No transaction number yet
	MOVE T3,CFSOFN		;The OFN table
	ADDI T3,0(P1)		;Point to this entry
	MOVEM T1,0(T3)		;Stash it for others to see
	LOAD T3,STRX,(P1)	;Get STR #
	MOVE T3,STRTAB(T3)	;Get SDB
	LOAD T3,STEXL,(T3)	;Get shared/exclusive bit
	CALL @[	IFIW!CFSGET
		IFIW!CFSGTL](T3)
	 CALL ILLGET
	MOVE T2,TODCLK		;Get now
	ADDI T2,WRTTIM		;"Fairness" time
	MOVEM T2,HSHFCT(P5)	;Stash it
	TMNE HSHODA,(P5)	;Any optional data?
	IFNSK.			;If so,
	 MOVE T2,HSHOPT(P5)	;Get it
	 MOVEM T2,OFNLEN(P1)	;Update length information
	 SETZRO HSHODA,(P5)	;And no longer valid
	ELSE.
	 MOVE T2,OFNLEN(P1)	;Get our value
	 MOVEM T2,HSHOPT(P5)	;Stash it
	 AOS HSHOP1(P5)		;And init transaction number
	ENDIF.
	SKIPE T1
	CALL @HSHRET(T1)	;?????
	SKIPN LKFLAG		;Hold or no?
	IFSKP.			;If no
	 DMOVE T1,P3		;CODES
	 CALL CFSNDO		;RELEASE IT
	  NOP
	ENDIF.
	CFSLOK
	; ..
   >		;IFNDEF CFSDUM
;Here when WT is seized. Set status in SPT

;**;[7507] Add 1 line at RTYPE:+0L	MDR	29-JUL-87
RTYPE:	JE <HSHKPH>,(P5),NOKEEP	;[7507] We must exit with the keep bit set!
	MOVEI P2,0(P2)		;GET ACCESS TYPE
	CAIE P2,.HTOEX		;EXCLUSIVE?
	SKIPA T1,[.SPSRD]	;NO
	MOVEI T1,.SPSWR		;YES
	STOR T1,SPTST,(P1)
	JRST CFSFAL		;Done

;**;[7507] Add 8 lines at NOKEEP:+0L	MDR	29-JUL-87
NOKEEP:	BUG.(HLT,CFKBNS,CFSSRV,SOFT,<CFSSRV - Keep bit not set>,,<

Cause:	CFSAWT/CFSAWP was called to get a CFS resource block for
	a token. This routine ALWAYS sets the HSHKPH bit when it
	obtains this token. This BUGHLT was arrived at when the
	routine was returning to its caller and the keep bit was
	not set.
>)				;[7507] Keep bit not set?????

	ENDSV.

 	SUBTTL	File access token resource manager -- CFSDWT (Write token revoked)

;HSHPST callback routine
;Here when write token is revoked
;Must queue requesu for background fork to invalidate pages

CFSDWT:
   IFNDEF CFSDUM,<		;Only if a full CFS
	JE HSHTYP,(T1),RSKP	;If a place-holder, allow it now
	MOVE T2,HSHCOD(T1)	;GET OFN
	SETONE SPTFR,(T2)	;SAY WE NEED IT FORCED OUT
	LOAD T3,HSHTYP,(T1)	;Get the type we own
	CAIE T3,.HTOEX		;Exclusive?
	IFSKP.			;If so
	 LOAD T3,HSHVTP,(T1)	;Get type requested
	 CAIN T3,.HTOEX		;Not exclusive?
	 ANSKP.			;If so
	 SETZRO SPTSR,(T2)	;Say so
	ENDIF.
	AOS DDCFSF		;Get DDMP awake
	IDIVI T2,^D36		;Get the bit for this OFN
	MOVE T3,BITS(T3)	;Get the proper bit
	IORM T3,OFNCFS(T2)	;Set the bit for DDMP
;	SETONE SCDDP		;Make sure
	SETZM T1		;Indicate wait
   >	;IFNDEF CFSDUM
	RETSKP			;AND DONE

 	SUBTTL	File access token resource manager -- CFSOVT (Approve sharing of OFN resource)

;Here when we will approve the sharing of an OFN resource.
;	T1/ vote packet
;	T2/ hash packet
;Called from CFSRTV
;Returns:	+1 with vote packet updated

;HSHOKV callback

CFSOVT:
   IFN CFSSCA,<
	SKIPN HSHOP1(T2)	;Anything here?
	IFSKP.			;If so
	 DMOVE T3,HSHOPT(T2)	;Get opt data
	 DMOVEM T3,CFDAT(T1)	;Yes. Store in vote packet
	 SETONE CFODA,(T1)	;And say so
	ELSE.
	 SETZM CFDT1(T1)
	ENDIF.
	TMNE HSHBTF,(T2)	;Is this a bit table OFN?
	CALL SNDFRC		;Send the STR free count
   >	;IFN CFSSCA
	RET			;And done
	SUBTTL	File access token resource manager -- CFSGOC (Get count of resource sharers)

;Routine to get count of resource sharers.
;	T1/ OFN
;Returns:	+1 not here
;		+2 T1/ count

CFSGOC::
   IFNDEF CFSDUM,<		;If CFS
	ADD T1,CFSOFN		;Point to entry in table
	SKIPN T1,0(T1)		;Here?
	IFSKP.			;If so
	 LOAD T1,HSHCNT,(T1)	;Get count
	 RETSKP			;Found it
	ENDIF.
   >	;IFNDEF CFSDUM
	RET			;Not here
	SUBTTL	File access token resource manager -- CFSDAR (Optional data for access token)

;Here when optional data arrives for an access token
;	T1/ HSH node
;	Q1/ vote packet
;Returns:	+1 forget the data
;		+2 store it

   IFN CFSSCA,<
CFSDAR:	TMNN HSHBTF,(T1)	;Is this for a bit table?
	IFSKP.			;If so
	 SKIPN T2,CFDST1(Q1)	;Any STR data?
	 ANSKP.			;If so
	 MOVE T3,HSHCOD(T1)	;Get the OFN
	 LOAD T3,STRX,(T3)	;Get STR #
	 MOVE T4,T3
	 ADD T4,CFSSTR		;Get local transaction count
	 CAMG T2,0(T4)		;Is the new one greater?
	 ANSKP.			;If so
	 MOVEM T2,0(T4)		;Update our transaction number
	 MOVE T4,CFDST0(Q1)	;Get free count
	 CALL STOFRC		;Store it (T3,T4)
	ENDIF.
	CALLRET CFADAR		;And done
   >	;IFN CFSSCA
	SUBTTL	File access token resource manager -- CFSFWT (Free write token)

;Routine to free up write token resource
;	T1/ The OFN
;Returns:
;	+1 always

;**;[7247]  Rewrite portions of routine CFSFWT		DML	19-Feb-86
CFSFWT::
	STKVAR <TROOT,TQAL,TOFN>;[7247] 
	CFSLOK			;[7247] Lock up the CFS database
   IFNDEF CFSDUM,<
	MOVEM T1,TOFN		;[7247] Save the OFN
	LOAD T2,STGADR,SPTH(T1)
	TXO T2,FILEWT
	LOAD T1,STRX,(T1)
	CALL GNAME
	MOVEM T1,TROOT		;[7247] Save the root...
	MOVEM T2,TQAL 		;[7247] ...and qualifier
	CALL CFSNDS		;Free it
	 NOP
	DO.			;[7247]  
	  MOVE T1,TROOT		;[7247] Get root...
	  MOVE T2,TQAL		;[7247] ...and qualifier
	  CALL HSHLOK		;[7247] (T1,T2/T1,T2) Find the resource block
	  IFNSK.		;[7247] Not found
	    MOVE T2,TOFN	;[7247] Get the OFN again
	    TMNE OFNCSH,(T2)	;[7247] Is this OFN cached?
	    BUG.(HLT,CFWTNF,CFSSRV,SOFT,<CFSSRV - Cached OFN not found when freed>,,<

Cause:	CFSFWT was called to free the file access token for an OFN and the 
	OFN is cached.  But the call to HSHLOK did not find the resource
	block for the file access token.  One should be there.
>)				;[7247] Yes so it should be in hash table!
	    JRST CFSFAL		;[7247] Return success and unlock CFS database
	  ENDIF.		;[7247] 

;[7247] Now we must check to see if the token should be recached or removed.
;[7247] First, the share count must be checked to see if the token is 
;[7247] eligible for removal.  If the count is 1, and SPTFR is set, then this
;[7247] really is the last sharer of the token.  This is because CFSRMX does
;[7247] an INCR of HSHCNT.  In this case, CFSFDF is called to notify the other 
;[7247] side and then the token is recached or removed.  If the share count is
;[7247] 0, then the token is also eligible.  Otherwise, no action is taken.

	  LOAD T2,HSHCNT,(T1)	;[7247] Get number of sharers
	  SKIPN T2		;[7247] Are we the last one?
	  EXIT.			;[7247] Yes, continue below
	  CAIE T2,1		;[7247] Is the share count 1?
	  JRST CFSFAL		;[7247] No, just return now
	  MOVE T2,TOFN		;[7247] Get the OFN again
	  TMNN OFNCSH,(T2)	;[7247] Is this OFN cached?
	  JRST CFSFAL		;[7247] No, just return
	  TMNN SPTFR,(T2)	;[7247] Someone waiting for us?
	  JRST CFSFAL		;[7247] No, just return

;[7247] At this point, OFN is cached, share count is 1, and SPTFR is set

	  MOVE T3,T2		;[7247] Copy OFN
	  IDIVI T3,^D36		;[7247] Compute the word it is in
	  MOVE T4,BITS(T4)	;[7247] Get the bit
	  ANDCAM T4,OFNCFS(T3)	;[7247] Zap the bit
	  MOVE T1,T2		;[7247] Get back OFN
       	  SETONE SPTFO,(T1)	;[7247] Lock out others
	  CFSULK		;[7247] Unlock CFS database for a moment
	  CALL CFSFDF		;[7247] Tell the other system they have it
	   NOP			;[7247] 
	  CFSLOK		;[7247] Lock up everything again
	  MOVE T1,TOFN		;[7247] Get the OFN again
       	  SETZRO SPTFO,(T1)	;[7247] Clear the lock
	  LOOP.			;[7247] Check everything again
	ENDDO.			;[7247] 
	SKIPL HSHPST(T1)	;[7247] Was a token uncache attempted?
	IFSKP.			;[7247] Yes
	  SETZRO HSHTAM,(T1)	;[7247] Uncache just in case it was set
	  SOS CFACCT		;[7247] Decrement currently cached count
	  CALL CFSRMV		;[7247] (T1/T1,T2)Remove it
	  CALLRET CFSFAL	;[7247] And return
	ENDIF.			;[7247] 
	MOVE T2,TOFN		;[7247] Get the OFN again
	TMNN OFNCSH,(T2)	;[7247] Is this OFN cached?
	IFSKP.			;[7247] Yes - recache the file access token then
	  ADD T2,CFSOFN		;[7247] Point to OFN table entry
	  SETZM 0(T2)		;[7247] Clear entry in OFN table
	  TMNE HSHTAM,(T1)	;[7247] Already cached?
	  ANSKP.		;[7247] No so re-cache it now
	    SETZRO <HSHCNT>,(T1);[7247] Clear the count but KEEP bit stays set
;**;[7507] Change 1 line at CFSCWT:-25L	MDR	29-JUL-87
	    SETONE <HSHTAM,HSHKPH>,(T1)	;[7507][7247] Set the cache bit and the keep bit
	    SETZM HSHPST(T1)	;[7247] No more post address either
	    AOS CFACCT		;[7247] Increment the count of cached tokens
	ENDIF.			;[7247] 
   >	;IFNDEF CFSDUM
	JRST CFSFAL		;[7247] Return success and unlock CFS database
	ENDSV.			;[7247] 
	SUBTTL	File access token resource manager -- CFSUWT/CFSCWT (Release/Cache access token)

;[7247]  CFSCWT:
;[7247] Routine called when a file is closed to cache the access token
;[7247] 
;[7247]  CFSUWT:
;[7247] Routine called by INVOFN when a structure is dismounted to destroy 
;[7247] the file access token.
;[7247] 
;[7247] Both routines expect the following:
;	T1/ STR #
;	T2/ XB address

;Returns:	+1 always

;**;[7247]  Replace 4 lines with 12 at CFSUWT::+0	DML	19-Feb-86
   IFDEF CFSDUM,<		;[7247] 
CFSCWT::			;[7247] 
CFSUWT:: RET			;[7247] 
>				;[7247] 
   IFNDEF CFSDUM,<		;[7247] 
CFSCWT::ASUBR <STRN0,XB>	;[7247] 
	SAVEAC <Q1>		;[7247] 
	SETZ Q1,		;[7247] Cache the file access token
	JRST CFSUW0		;[7247] 
CFSUWT::ASUBR <STRN0,XB>	;[7247]
	SAVEAC <Q1>		;[7247] 
	SETO Q1,		;[7247] Destroy the file access token
CFSUW0:	TXO T2,FILEWT		;Access token
	CALL GNAME
	CFSLOK
	CALL HSHLOK		;Look it up
	 JRST CFSFAL		;Not here
;**;[7247]  Add 2 lines after CFSUW0:+4			DML	19-Feb-86
	TMNE HSHTAM,(T1)	;[7247] Is this a cached token?
	JRST CFSFAL		;[7247] Yes, so don't need to release it
	MOVE T2,HSHCOD(T1)	;Get the OFN
	TMNE SPTFR,(T2)		;Someone waiting for us?
	IFNSK.			;If so
	 CFSULK
	 MOVE T3,T2		;Copy
	 IDIVI T3,^D36		;Compute the word it is in
	 MOVE T4,BITS(T4)	;Get the bit
	 ANDCAM T4,OFNCFS(T3)	;Zap the bit
	 MOVE T1,T2
	 CALL CFSFDF		;Try now
	  NOP
	 MOVE T1,STRN0
	 MOVE T2,XB
	 JRST CFSUW0		;And do it again
	ENDIF.
	PUSH P,T1		;Save packet
	CALL CFNOHS		;Notify any others
	POP P,T1
	TMNE HSHLKF,(T1)	;Now interlocked?
	IFNSK.			;If so
;**;[7247]  Replace 2 lines with 3 at CFSUW0:+24	DML	19-Feb-86
	 SETZRO <HSHTYP,HSHCNT>,(T1)  ;[7247] Clear type and count but not KEEP
	 SKIPL HSHPST(T1)	;[7247] Has an uncache been attemped already?
	 MOVEM Q1,HSHPST(T1)	;[7247] No, so set release flag in post address
	 JRST CFSFAL		;And give it up
	ENDIF.
	MOVE T3,HSHCOD(T1)	;Get OFN again
	ADD T3,CFSOFN		;Point to entry in table
	SKIPN 0(T3)		;Is one here?
	BUG.(HLT,CFSNOT,CFSSRV,SOFT,<CFSSRV - OFN token table and hash table disagree>,,<

Cause:	CFSSRV is trying to remove a file access token and has found the
	token in the hash table but not in the OFN token table. This indicates
	that one of the data bases is incorrect.
>)
	SETZM 0(T3)		;Clear entry in OFN table

;**;[7247]  Replace 1 line with 13 at CFSNFO::-7	DML 	19-Feb-86
	SKIPL Q1		;[7247] Want to cache the token?
	IFSKP.			;[7247] 
	  CALL CFSRMV		;[7247] (T1/T1,T2)No, remove it
	ELSE.			;[7247] Yes

;[7247] Now cache the token

	  SETZRO <HSHCNT>,(T1)  ;[7247] Clear the count but KEEP bit stays set
;**;[7507] Change 1 line at CFSNFO:-11L	MDR	29-JUL-87
	  SETONE <HSHTAM,HSHKPH>,(T1) ;[7507][7247] Set the cache bit and the keep bit
	  SKIPL HSHPST(T1)	;[7247] Has an uncache been attemped already?
	  SETZM HSHPST(T1)	;[7247] No, so clear post address
	  AOS CFACCT		;[7247] Increment the number we currently have
	ENDIF.			;[7247] 
	JRST CFSFAL		;And done
	ENDAS.
   >	;IFNDEF CFSDUM
;Here when DDMP failed to do the flush
;	T1/ the OFN

CFSNFO::SETONE SCDDP		;Try again
	CALLRET SKDRUN		;Make the scheduler run
;Debugging routine called from DASOFN
;This is called when an OFN is being released to see if the file
;access token has been deleted. If not, we will BUGHLT.

;	T1/ OFN

CFSCON::
   IFDEF CFSDUM,<RET>
   IFNDEF CFSDUM,<
	SAVEAC<T1>		;Save the OFN
	MOVE T2,CFSOFN		;See if it is in the OFN table
	ADDI T2,0(T1)
	SKIPE 0(T2)		;Is it?
	IFSKP.			;If not
	 LOAD T2,STGADR,SPTH(T1) ;Get XB address
	 TXO T2,FILEWT
	 LOAD T1,STRX,(T1)	;Get structure number
	 CALL GNAME		;Get name
	 CFSLOK			;Lock it up
;**;[7247]  Replace 12 lines with 17 at CFSCON::+15	DML	19-Feb-86
	 CALL HSHLOK		;[7247] Look it up
	 IFSKP.			;[7247] It is here!
	   TMNN HSHTAM,(T1)	;[7247] Is it cached?
CFSCND:	   BUG.(HLT,CFSTND,CFSSRV,SOFT,<CFSSRV - Access token not deleted>,,<

Cause:	CFSCON was called to verify that an access token has been deleted
	before an OFN is released. This BUGHLT indicates that the token has
	not been deleted or cached.

>)				;[7247] Found but not cached - error!
	 ENDIF.			;[7247] 
	 CFSULK			;[7247] All is ok - free the lock
	 RET			;[7247] And done
	ENDIF.			;[7247] 
	TMNN OFNCSH,(T1)	;[7247] Not deleted - is this OFN cached?
	JRST CFSCND		;[7247] No - error!
	RET			;[7247] Yes, so it is ok
   >	;IFNDEF CFSDUM
	SUBTTL	File access token resource manager -- CFSUNC (Uncache token)

;**;[7247]  Add routine CFSUNC				DML	19-Feb-86
;[7247] Routine called when an OFN is being deleted and the access token 
;[7247] should be uncached.  This is called from DASOFN.
;[7247] 
;[7247] Accepts:
;[7247] 	T1/ OFN
;[7247] 
;[7247] Returns:	+1 always with T1 preserved

CFSUNC::TMNE OFNDMO,SPTH(T1)	;[7247]
	RET			;[7247] If dismounted, let it go
	SAVEAC <T1>		;[7247] Save OFN
	STKVAR <UCOFN>		;[7247] Location to hold OFN to uncache
	MOVEM T1,UCOFN		;[7247] Save OFN to uncache
	LOAD T2,STGADR,SPTH(T1)	;[7247] Get XB address
	TXO T2,FILEWT		;[7247] Set token bit
	LOAD T1,STRX,(T1)	;[7247] Get structure number
	CALL GNAME		;[7247] (T1/T1) Get the name of the structure
	CFSLOK			;[7247] Lock up the CFS database
	CALL HSHLOK		;[7247] (T1,T2/T1,T2) Look for token
         BUG.(HLT,CFCTNF,CFSSRV,SOFT,<CFSSRV - Could not find cached token while uncaching>,,<

Cause:	CFSUNC has been called to uncache the token for a certain OFN.
	The file access token should have been cached and in the hash
	table but it was not found.
>)				;[7247] Not found - error!!
	TMNE HSHLKF,(T1)	;[7247] Now interlocked?
	IFNSK.			;[7247] If so
	  SETZRO <HSHTYP,HSHCNT>,(T1)  ;[7247] Clear status bits but not KEEP
	  SETOM HSHPST(T1)	;[7247] Set to indicate that uncache attempted
	  JRST CFSFAL		;[7247] Return
	ENDIF.			;[7247]
	TMNN HSHTAM,(T1)	;[7247] Is it cached?
        BUG.(HLT,CFSUCN,CFSSRV,SOFT,<CFSSRV - Uncaching non-cached token>,,<

Cause:	CFSUNC has been called to uncache the token for a certain OFN.
	We found the access token for the OFN but it is not cached.
>)				;[7247] No, error
	MOVE T2,HSHCOD(T1)	;[7247] Get the OFN described by this token
	CAME T2,UCOFN		;[7247] Does it match the one to be uncached?
        BUG.(HLT,CFSUCM,CFSSRV,SOFT,<CFSSRV - Uncaching mismatch>,,<

Cause:	CFSUNC has been called to uncache the token for a certain OFN.
	We found the access token for the OFN but the OFN stored in the
	resource block does not match the one we should be uncaching.
>)				;[7247] No - error
	SETZRO HSHTAM,(T1)	;[7247] Uncache just in case it was set
	SOS CFACCT		;[7247] Decrement currently cached count
	CALL CFSRMV		;[7247] (T1/T1,T2) Remove entry
	JRST CFSFAL		;[7247] Unlock the database and return
	ENDSV.			;[7247] 
	SUBTTL	File access token resource manager -- CFSBOW (Broadcast OFN update)

;Broadcasting routines
;CFS broadcasts information about certain events. Any braodcast
;other than a vote is done using CFSBRD.

;Here when PAGEM is about to update an OFN
;This event is broadcast so that if this system crashes before
;it can pass on access to the file, the next user will know to
;validate the XB before using it. Note this technique also elimiates
;the need for an optional data item on the access token reply to
;indicate that the OFN needs validating!
;	T1/ OFN

   IFNDEF CFSDUM,<		;Only need this for full CFS
CFSBOW::SKIPN CFSHCT		;Anybody out there?
	RET			;No
	LOAD T2,STGADR,SPTH(T1)	;Get XB address
	LOAD T1,STRX,(T1)	;Get structure number
	TSTRMT			;Is it a shared structure?
	 RET			;No. All done then
	TXO T2,FILEWT
	CALL GNAME		;Get the name


;Now send message to each node that is up

	BLCAL. (CFSBRD,<T1,T2,[.CFBOW],[0]>) ;Do the braodcast
	RET			;And done
	SUBTTL	File access token resource manager -- CFSBEF (Broadcast EOF)

;CFSBRD routines, continued

;Routine to broadcast EOF pointer on a file close or CHFDB%.
;This is broadcast so that the OFNLEN entries on other systems will
;be correct over a crash of this system. Since the FDB will be updated
;on the close, it is essential that sharers of this file have the
;correct EOF value.
;
;Accepts:	T1/  OFN to do
;
;This routine does not expect to be called from interrupt level so
;it will protect itself via CFSLOK and CFSULK.
;
;This routine is called from DSKCLZ upon a CLOSF% of a file that has 
;a window page setup and is open for write.  In this case, the FDB
;will be updated with the correct length and CFSBEF will be called to 
;broadcast it to the other systems in the cluster.  This covers the case
;of sequential I/O EOF being broadcast.
;
;This routine is also called from CHFDB% after the FDB has been written
;to disk.  The file must be open at the time of the CHFDB%.  The broadcast
;is done in this case because any entry can be written into the FDB with 
;CHFDB% without having the disk get updated (CF%NUD).  So, the .FBSIZ 
;field could have been written with CF%NUD.  Therefore, in order to insure
;that the file size is broadcast, CFSBEF must be called whenever the 
;directory is updated to disk from CHFDB% regardless of which specific field
;of the FDB was changed.  This covers the case of random (PMAP%) I/O being 
;broadcast since CHFDB% is the method by which the EOF is to be updated.

CFSBEF::SAVEAC<P1,P2>		;Get some regs
	SKIPN P1,OFNLEN(T1)	;Get EOF pointer
	RET			;None here
	LOAD P2,SPTST,(T1)	;Get state
	CAIE P2,.SPSWR		;Are we the owner?
	RET			;No, don't broadcast anything
	CFSLOK			;Yes, lock CFS database
	MOVE T2,T1		;Get the OFN
	ADD T2,CFSOFN		;Point to entry in table
	SKIPN T2,0(T2)		;Here?
	BUG.(HLT,CFSBNO,CFSSRV,SOFT,<CFSSRV - Broadcast of unknown OFN>,,<

Cause:	CFSBEF was called to broadcast the EOF pointer for an OFN.  This
	OFN does not have an entry in the CFSOFN table.
>)				;Report error
	MOVEM P1,HSHOPT(T2)	;Store broadcast value  
 	AOS P2,HSHOP1(T2)	;Bump the transaction number
	CFSULK			;Unlock CFS database
	LOAD T2,STGADR,SPTH(T1)	;Get XB address
	TXO T2,FILEWT		;Make token ID
	LOAD T1,STRX,(T1)
	TSTRMT			;Here?
	 RET			;Yes. Don't do anymore
	CALL GNAME		;Get the name
	BLCAL. (CFSBRD,<T1,T2,[.CFBEF],<.,CFSBF0>>) ;do it
	RET			;And done

;Coroutine of above

CFSBF0:	DMOVEM P1,CFDAT(T1)	;Stash the data
	RET
	SUBTTL	File access token resource manager -- CFSBRD (Main broadcast routine)

;Still IFNDEF CFSDUM and still CFSBRD routines
;Routine to do a broadcast. Called by various routines to send a CI
;broadcast. Since the CI is a point-to-point bus, the broadcasr must
;be simulated by a number of point-to-point messages. The broadcast,
;therefore, is slow but since it uses virtual circuits, it is reliable.

CFSBRD:	BLSUB. (<ROT,QAL,OPR,CB>) ;Lots of args!!!
	SAVEQ			;Get some work ACS
	MOVSI Q3,-HSTSIZ
	MOVE Q1,ROT		;Get root code
	MOVE Q2,QAL		;Get qualifier code
	AOS CFBRDS		;Send a broadcast
	CFSLOK			;Preserve the configuration
	DO.			;Scan them all
	 SKIPLE CFSHST(Q3)	;This one up?
	 SKIPL T2,CFHSTS(Q3)	;Still?
	 IFSKP.			;If so
	  TRNN T2,-1		;Is it real or dummy?
	  ANSKP.		;If real
	  CALL GVOTE		;Get a packet
	   NOP
	  DMOVEM Q1,CFROT(T1)	;Stash it
	  MOVE T2,OPR		;Get operator
	  STOR T2,CFCOD,(T1)	;And stash it
	  HRRZ T2,Q3		;Host number
	  SKIPE T3,CB		;Want to look at it first?
	  CALL 0(T3)		;Yes. Give it a chance then
	  CALL SCASND		;Send it off
	  IFNSK.		;If failed
	   PIOFF
	   CALL CFSWDN		;Return the packet
	   PION
	  ENDIF.
	 ENDIF.
	 AOBJN Q3,TOP.		;Do all hosts
	ENDDO.
	CALLRET CFSFAL		;And done
	ENDBS.
   >	;IFN CFSDUM

;non-CFS dummies

   IFDEF CFSDUM,<
CFSBOW::
CFSBEF::RET
   >	;IFDEF CFSDUM
	SUBTTL	File access token resource manager -- CFSFOD (DDMP force out done)

;Here after DDMP has forced pages out.
;	T1/ OFN
;Returns:	+1 didn't do it
;		+2 OK

   IFDEF CFSDUM,<

CFSFOD::BUG.(HLT,CFSDDD,CFSSRV,SOFT,<CFSFOD called incorrectly>,,<

Cause:	CFSFOD has been called by DDMP to indicate that a force out is
	complete. However, as this is not a real CFS monitor, DDMP should
	never have been requested to do this.
>)
   >	;IFDEF CFSDUM

   IFNDEF CFSDUM,<		;If real CFS
CFSFDF:	TDZA T2,T2		;Entry to force it out
CFSFOD::MOVEI T2,1		;Normal entry from PAGEM
	SAVEQ
	MOVE Q2,T1		;SAVE OFN
;**;[7247]  Replace 9 lines with 15 at CFSFOD::+3	DML	19-Feb-86
	MOVE Q1,T2		;[7247] Save entry flag
	CFSLOK			;[7247] Lock up CFS database
	LOAD T1,STRX,(Q2)	;[7247] Get STR #
	LOAD T2,STGADR,SPTH(Q2)	;[7247] Get XB address
	SKIPN T2		;[7247] Is it still here?
	JRST CFSFO1		;[7247] No, all done
	TXO T2,FILEWT		;[7247] Set token bit
	CALL GNAME		;[7247] Get the name of the structure
	CALL HSHLOK		;[7247] (T1,T2/T1,T2) Look for the token
	IFNSK.			;[7247] If not here
CFSFO1:	 SETZRO <SPTST,SPTFR>,(Q2) ;[7247] No longer have it
	 JRST CFSRSK		;[7247] And done
	ENDIF.			;[7247] 
	LOAD Q3,HSHCNT,(T1)	;[7247] Get share count
	IFN. Q1			;[7247] If normal entry
	 CAILE Q3,2		;correct number of sharers?
	 JRST CFSFAL
	ENDIF.
	MOVE Q1,T1
	LOAD Q3,HSHVVL,(T1)	;GET VOTE CODE
	CFSULK
	CALL GVOTE1		;GET A VOTE PACKET
	 JRST .-1		;It will get one soon
	TMNE HSHODA,(Q1)	;Any data laying here?
	SKIPA T2,HSHOPT(Q1)	;Get it
	MOVE T2,OFNLEN(Q2)	;Else. Get word from SPT data base
	IFN. T2			;If something is here
	 MOVEM T2,HSHOPT(Q1)	;In case
	 MOVEM T2,CFDAT(T1)	;Store it
	 SETONE CFODA,(T1)	;Say we are doing it
	 LOAD T2,HSHTYP,(Q1)	;Get type we are giving up
	 MOVE T3,HSHOP1(Q1)	;Get transaction number
	 CAIN T2,.HTOEX		;Were we the writer?
	 AOS T3,HSHOP1(Q1)	;yes. Bump transaction number
	 MOVEM T3,CFDT1(T1)	;Indicate who we are
	ELSE.
	 SETZM CFDT1(T1)	;No data!
	ENDIF.
	TMNN HSHBTF,(Q1)	;Is this a bit table?
	IFSKP.			;If so
	 MOVE T2,Q1		;Get hash packet
	 CALL SNDFRC		;Send the STR free count
	ENDIF.
	STOR Q3,CFUNQ,(T1)	;STORE CODE
	DMOVE T2,HSHROT(Q1)
	DMOVEM T2,CFROT(T1)
	MOVEI T2,.CFREP
	STOR T2,CFCOD,(T1)
	MOVX T2,<-2>
	MOVEM T2,CFTYP(T1)
	MOVE Q3,T1		;Save pointer to message
	SETZRO HSHRFF,(Q1)
	TMNN SPTSR,(Q2)		;Exclusive?
	IFNSK.			;If not
	 DMOVE T1,[.HTOAD	;Share it
		   .SPSRD]
	ELSE.
	 SETZB T1,T2
	ENDIF.
	STOR T1,HSHTYP,(Q1)	;new type
	STOR T2,SPTST,(Q2)	;New OFN access
;**;[7247]  Add 6 lines after SNDFRC:-20		DML	19-Feb-86
	TMNN OFNCSH,(Q2)	;[7247] Is the OFN cached?
	IFSKP.			;[7247] Yes
 	  MOVX T1,OFNLAC	;[7247] Get bit indicating loss of access
	  IORM T1,SPTH(Q2)	;[7247] Set it
	  AOS CFACUT		;[7247] Count this event
	ENDIF.			;[7247] 
	LOAD T2,HSHRHN,(Q1)	;GET HOST INDEX NOW BEFORE RELEASING THE RESOURCE
	SETZRO SPTFR,(Q2)	;No longer doing this
	TMNN HSHCNT,(Q1)	;Any count?
	CALL CFNCNT		;No
	DECR HSHCNT,(Q1)	;One less unit of count
	MOVE T1,Q3		;recover message pointer
	CALL SCASND		;SEND OFF VOTE
	IFNSK.
	 PIOFF
	 CALL CFSWDN		;Return the buffer
	 PION
	ENDIF.
	RETSKP			;And done
;Routine to fill in STR free count in reply message
;	T1/ Message to send
;	T2/ hash packet
;Returns:	+1 always

SNDFRC:	MOVE T3,HSHCOD(T2)	;Get the OFN
	LOAD T3,STRX,(T3)	;Get STR #
	CALL GETFRC		;Get the current free count
	MOVEM T4,CFDST0(T1)	;Save it
	ADD T3,CFSSTR		;Find STR trnasaction entry
	LOAD T4,HSHTYP,(T2)	;Get type we now own
	CAIN T4,.HTOEX		;Exclusive?
	AOSA T3,0(T3)		;Yep
	MOVE T3,0(T3)		;No
	MOVEM T3,CFDST1(T1)	;Save this
	SETONE CFODA,(T1)	;Say we sent something
	RET			;And done
   >	;IFNDEF CFSDUM
	SUBTTL	Structure resource manager -- CFSSMT (Acquire structure resource)

;Routines to handle structures. Structure resources control the
;use of aliases as well as specify if structures are sharable.

;Acquire structure resource.
;	T1/ Structure number
;	T2/ type of access
;		0=) shared
;		<>0=) exclusive
;Returns:
;	+1 failed. Can't mount it this way
;	+2 OK

;CFSSMT accomplishes two things:
;	1. It insures that the alias for this structure is
;	not already in use for another structure
;	2. It insures that the name being given to this structure
;	is the same as the name used by any other CFS systems.
;These guarantees are sufficient to allow the alias to be used as
;the CFS root name for this structure
;[7464] 
;[7464]  Note that this routine is now only called from MNTPS during system
;[7464]  startup in order to register the PS structure.  All other mounts
;[7464]  (via MSTR) use CFSSMI to acquire the Structure Tokens.

CFSSMT::SAVEAC<Q1,Q2,Q3,P1>
;**;[7464]  Replace 1 line at CFSSMT+1			MAT	21-Apr-87       
	STKVAR <SDBADR,STRNM,SDBOFF>  ;[7464] 
   IFN CFSSCA,<			;Only if SCA is present
	MOVEM T1,STRNM		;Save the structure number
	SKIPL MYPOR1		;Are we a dummy?
	SKIPA			;Yes, force exclusive then
	SKIPE T2		;Share or exclusive?
	SKIPA Q2,[.HTOEX]	;Exclusive
	MOVEI Q2,.HTOAD		;Read-share
	MOVE Q3,T1
	CALL GNAME
	EXCH Q3,T1		;Save name
	MOVE T1,STRTAB(T1)	;Get SDB address
	MOVEM T1,SDBADR
;**;[7464]  Replace 4 lines by 5 at CFSSMT+13		MAT	21-Apr-87       
	MOVE T2,SDBUDB(T1)	;[7464] Get first unit
	MOVE P1,UDBDSH(T2)	;[7464] Get the high-order bits
	TXO P1,STRCTK		;[7464] Make it unique!
	MOVE Q1,UDBDSN(T2)	;[7464] Get DSN
	MOVEM T1,SDBOFF		;[7464] Remember SDBUDB offset
	;..
;CFSSMT continued
;At this point
;	Q1/ DSN, unswapped
;	Q2/ desired access
;	Q3/ Alias
;	P1/ high-order serial number bits

	CALL CFMNAM		;First register the name
	IFNSK.			;Can't
	  CAIN T2,.CDVUC	;Fail due to unmatch serial number?
	  RETBAD(MSTX45)	;Yes, return correct error
	  CALLRET CFMDER	;(T2,Q2) No - analyze error
	ENDIF.
;**;[7464]  Replace 1 line at CFSSMT+29			MAT	21-Apr-87       
CFSSM1:	TLNN Q1,-1		;[7464] See if need to swap DSN
	MOVSS Q1		;We do
	CALL CFMDSN		;Now register the DSN
;**;[7464]  Replace 1 line by 17 at CFSSMT+33		MAT	21-Apr-87       
	IFSKP.			;[7464] Ok
	  CAIE Q2,.HTOEX	;[7464] Got it exclusive?
	  IFSKP.		;[7464] If so
	   MOVE T1,SDBADR	;[7464] Get address of SDB
	   SETONE STEXL,(T1)	;[7464] Set exclusive bit
	  ENDIF.		;[7464]
	  MOVE T1,SDBOFF	;[7464] Get SDBUDB offset
	  ADDI T1,1		;[7464] Get next unit
	  HRRZ T2,SDBUDB(T1)	;[7464] UDB address
	  SKIPN T2		;[7464] Was it last?
	  RETSKP		;[7464] Yes all done
	  MOVEM T1,SDBOFF	;[7464] Save SDBUDB offset
	  MOVE P1,UDBDSH(T2)	;[7464] Get high order bits
	  TXO P1,STRCTK		;[7464] Make it unique
	  MOVE Q1,UDBDSN(T2)	;[7464] Get DSN
	  JRST CFSSM1		;[7464] Do it for this unit
	ENDIF.			;[7464]
	MOVEM T2,Q1		;Save denial reason code from CFMDSN
	MOVE T1,STRNM		;Get the structure number
	CALL CFSSDM		;Undo the mount
	MOVE T2,Q1		;Get denial reason code
	CAIN T2,.CDVUC		;Fail due to unmatch alias name?
	RETBAD(MSTX49)		;Yes, return correct error
	CALLRET CFMDER		;(T2,Q2) No - analyze error
;**;[7464]  Add 1 line after CFMNAM:-13			MAT 	21-Apr-87
	ENDSV.			;[7464] 
	SUBTTL	Structure resource manager -- CFMNAM (Register structure name)

;Subroutine of above to register the name
;	Q1/ DSN, unswapped
;	Q2/ desired access
;	Q3/ Alias
;	P1/ high-order serial number bits
;
;Returns:	+1	Failed to mount structure
;			T2 contains the denial reason code
;		+2	Success

CFMNAM:	DO.
	 CALL CFSSPC		;Get a block
	 IFNSK.			;if none
	  CALL SBLOCK		;Wait here
	  LOOP.			;And do it again
	 ENDIF.
	ENDDO.
	MOVEM Q3,HSHROT(T1)	;Stash name
	MOVX T3,STRCTN		;Bits for this
	MOVEM T3,HSHQAL(T1)	;Stash it
	MOVEI T2,.HTOAD		;Full share this one
	STOR T2,HSHTYP,(T1)	;Store requested access
	MOVE T2,Q1		;Get low-order DSN word
	XOR T2,P1		;Make a hash of the two words
				; We do this to try to improve the precision
				; of the test. However, the REAL protection
				; of DSN is provided in the other resource!
	MOVEM T2,HSHCOD(T1)	;Save code as well
	SETONE <HSHAVT,HSVUC>,(T1) ;Vote must include the code; always vote
	SETZM T2		;No auto retry
	CALL CFSGET		;Try it out
	 RETBAD()		;No luck!  Return reason for NO in T2
	SKIPE T1		;Need the block?
	CALL @HSHRET(T1)	;No
	RETSKP			;Done
	SUBTTL	Structure resource manager -- CFMDSN (Register drive serial number)

;Another subroutine of above. Register DSN
;	Q1/ DSN
;	Q2/ desired access
;	Q3/ Alias
;	P1/ high-order serial number bits
;
;Returns:	+1	Failed to register drive serial number
;			T2 contains the denial reason code
;		+2	Success

CFMDSN:	DO.
	 CALL CFSSPC		;Get a block
	 IFNSK.			;if none
	  CALL SBLOCK		;Wait here
	  LOOP.			;And do it again
	 ENDIF.
	ENDDO.
	MOVEM Q1,HSHROT(T1)	;Stash DSN
	MOVEM P1,HSHQAL(T1)	;Stash high-order bits as the qualifier
	STOR Q2,HSHTYP,(T1)	;Store requested access
	MOVEM Q3,HSHCOD(T1)	;Save code as well
	SETONE <HSHAVT,HSVUC>,(T1) ;Vote must include the code; always vote
	SETZM T2		;No auto retry
	CALL CFSGET		;Try it out
	 RETBAD()		;No luck!  Return reason for NO in T2
;**;[7492] Replace 2 lines with 49. at CFMDSN: + 15. L	JDM	16-Jun-87
	SKIPN T1		;[7492]Need the block?
	IFSKP.			;[7492]NO. THIS MEANS THERE IS ALREADY
				;[7492]A DSN TOKEN. IT'S LIKELY A
				;[7492]DUPLICATE DSN. NOTE THAT HSHCNT
				;[7492]WAS INCREMENTED BY CFSGET. THIS
				;[7492]WILL BE FIXED BY CFSSDI LATER.
	  MOVE Q1,T1		;[7492]SAVE ADDRESS OF UNNEEDED BLOCK
	  DMOVE T1,HSHROT(T1)	;[7492]GET HASH VALUES
	  CALL HSHLOK		;[7492](T1,T2/T1,T2)LOOK UP THE BLOCK
	   BUG.(HLT,CFDGON,CFSSRV,SOFT,<CFMDSN - DSN token has disappeared>,,<

Cause:	In routine CFMDSN, CFSGET has granted us access to an already
	existing DSN token. But when we tried to look up token in the
	CFS data base, it could not be found.

Action:	Examine the dump and try to determine how the DSN token was
	released. The only way a DSN token can be released is by
	dismounting the structure to which it belongs. This should not
	happen because we have the device tables locked while we are
	in CFMDSN.
>)				;[7492]NOT FOUND. WRONG!
	  MOVE T2,HSHCOD(Q1)	;[7492]GET ALIAS NAME
	  CAMN T2,HSHCOD(T1)	;[7492]SAME AS ONE FOR DSN TOKEN?
	  IFSKP.		;[7492]NO
	    MOVE T1,HSHQAL(Q1)	;[7492]GET THE HIGH ORDER DSN
	    HLRZ T2,HSHROT(Q1)	;[7492]GET THE LOW ORDER DSN
	    MOVE T3,HSHCOD(Q1)	;[7492]GET THE STRUCTURE ALIAS
	    BUG.(CHK,CFDDSN,CFSSRV,HARD,<CFSSRV - Duplicate DSN detected>,<<T1,HGHDSN>,<T2,LOWDSN>,<T3,ALIAS>>,<

Cause:	Routine CFMDSN was called to register a DSN for a disk mount.
	However, the DSN supplied was already is use by a structure of
	another name. The most likely cause of this BUGCHK is that
	there is more than one drive with the same serial number
	available to the system.

Action:	Contact Field Service and have them change the serial number
	on one of the drives.

Data:	HSHDSN  - High order disk serial number
	LOWDSN   - Low order disk serial number
	ALIAS - Alias name of the disk being mounted
>)				;[7492]
	    MOVE T1,Q1		;[7492]GET BLOCK ADDRESS BACK IN T1
	    CALL @HSHRET(T1)	;[7492](T1/)RETURN THE BLOCK
	    MOVEI T2,.CDVUC	;[7492]FAIL DUE TO MISMATCHED ALIAS NAMES
	    RET			;[7492]RETURN FAILURE
	  ENDIF.		;[7492]
	CALL @HSHRET(T1)	;[7492](T1/)DON'T NEED THIS BLOCK
	ENDIF.			;[7492]
;**;[7464]  Remove 5 lines at CFMDSN+17			MAT	21-Apr-87       
   >	;IFN CFSSCA
	RETSKP			;And done
;**;[7464]  Remove 1 line at CFMDSN+25			MAT	21-Apr-87       
	SUBTTL	Structure resource manager -- CFSSMI (Acquire structure resource)
;**;[7464] Add new routine CFSSMI			MAT	21-Apr-87
;[7464] CFSSMI - Acquire structure resource when creating a new structure.
;Routines to handle structures. Structure resources control the
;use of aliases as well as specify if structures are sharable.
;
;This routine is called in MSTR whenever a mount is performed to acquire
;the necessary Structure Tokens.  These consist of 1 Structure Name Token, 
;and a DSN Token for each unit in the structure.
;
;Call with:
;	T1/ Pointer to Parameter area in Monitor (set by MSTR)
;	T2/ type of access
;		0=) shared
;		<>0=) exclusive
;	Q3/ Alias
;Returns:
;	+1 failed. Can't mount it this way
;	+2 OK
;
;CFSSMI accomplishes the same things as CFSSMT but is called at structure 
;       creation and we do not have a SDB

CFSSMI::
   IFE CFSSCA,<RETSKP>
   IFN CFSSCA,<			;Only if SCA is present
	SAVEAC<Q1,Q2,Q3,P1>
	STKVAR <UNIADR,AOBPTR,FTIM,BLADR>
	MOVEM T1,BLADR		;Save the parameter  block address
	SETZM FTIM		;First time
	SKIPL MYPOR1		;Are we a dummy?
	SKIPA			;Yes, force exclusive then
	SKIPE T2		;Share or exclusive?
	SKIPA Q2,[.HTOEX]	;Exclusive
	MOVEI Q2,.HTOAD		;Read-share
	MOVEI T2,.MSISU(T1)	;Get address of first unit
	HRRZ T1,.MSIUNU(T1)	;Get number of units
	MOVN T1,T1		;Negate it
	MOVSI T1,(T1)		;Form AOBJN pointer
CFSSI1: MOVEM T1,AOBPTR		;Save it
	MOVEM T2,UNIADR		;Save adress of unit
	MOVE T3,.MSIUN(T2)	;Get Unit
	DMOVE T1,.MSICH(T2)	;Get Chan ,Kont
	CALL CHKCKU		;(T1,T2,T3/T1)Get UDB address
	 RET			;Erreur, code in T1
	MOVE P1,UDBDSH(T1)	;Get high order bits
	TXO P1,STRCTK		;Make it unique
	MOVE Q1,UDBDSN(T1)	;Get DSN
	SKIPE FTIM		;Is it first time?
	IFSKP.			;Yes
	  SETOM FTIM		;There is only one first time
	  CALL CFMNAM		;First register the name
	  IFNSK.		;Can't
	    CAIN T2,.CDVUC	;Fail due to unmatch serial number?
	    RETBAD(MSTX45)	;Yes, return correct error
	    CALLRET CFMDER	;(T2,Q2) No - analyze error
	  ENDIF.
	ENDIF.
	TLNN Q1,-1		;Do we need to swap SN?
	MOVSS Q1		;Yes
	CALL CFMDSN		;Now register DSN
	IFSKP.			;done
	  MOVE T2,UNIADR	;Get unit address
	  MOVE T1,AOBPTR	;get AOBJN pointer
	  ADDI T2,.MSTNO	;Get next unit address
	  AOBJN T1,CFSSI1	;Go do next unit
	  RETSKP		;All done
	ENDIF.
	MOVEM T2,Q1		;Save denial reason code from CFMDSN
	MOVE T1,BLADR		;Get parameter block address
	CALL CFSSDI		;(T1,Q3/)Undo the mount
	MOVE T2,Q1		;Get denial reason code
	CAIN T2,.CDVUC		;Fail due to unmatch alias name?
	RETBAD(MSTX49)		;Yes, return correct error
	CALLRET CFMDER		;(T2,Q2) No - analyze error
	ENDSV.
  >	;IFN CFSSCA
	SUBTTL	Structure resource manager -- CFSSUG (Upgrade or downgrade mount)

;Routine to upgrade or downgrade a CFS mount resource.

;	T1/ Structure number
;	T2/ New access needed
;	 Same as for CFSSMT
;
;Returns:	+1 Can't do it
;		+2 Done

CFSSUG::
   IFN CFSSCA,<			;Only if SCA is present
	SAVEQ			;Get some work regs
;**;[7464]  Add 1 line at CFSSUG+2			MAT	21-Apr-87       
	STKVAR <SDBOFF>		;[7464] For SDBUDB offset
	SKIPL MYPOR1		;Are we a real node?
	RETBAD(MSTX46)		;No.  Can't do this function then
	SKIPE T2		;Share or exclusive?
	SKIPA Q1,[.HTOEX]	;Exclusive
	MOVEI Q1,.HTOAD		;Share
	MOVE T1,STRTAB(T1)	;Get SDB
;**;[7464]  Replace 3 lines by 4 at CFSSUG+9		MAT	21-Apr-87       
CFSSU1:	MOVE T2,SDBUDB(T1)	;[7464] Get SDB address
	MOVEM T1,SDBOFF		;[7464] Save SDB offset
	MOVE T1,UDBDSN(T2)	;[7464] Get DSN
	MOVE T2,UDBDSH(T2)	;[7464] Get the high-order bits
	TLNN T1,-1
	MOVSS T1
	TXO T2,STRCTK
	CFSLOK
	CALL HSHLOK		;Look it up
	 BUG.(HLT,CFSSUF,CFSSRV,SOFT,<CFSSUG - Could not find entry to upgrade>,,<

Cause:	A request was made to change the mount type of a structure, and the
	CFS data base has no record of the structure being mounted.
>)

	LOAD T2,HSHTYP,(T1)	;Get current type
	CAMN T2,Q1		;The same?
;**;[7464]  Replace 1 line at CFSSUG+26			MAT	21-Apr-87       
	IFSKP.			;[7464] No
	  MOVE Q2,T1		;Save entry
 	  DMOVE T1,HSHROT(T1)	;Get codes
	  MOVE T3,Q1		;Access
	  CALL CFSUGA		;Do it
	  IFNSK.
	    MOVE Q2,Q1		;Can't upgrade - get desired access
	    CALLRET CFMDER	;(T2,Q2) Return appropriate error
	  ENDIF.
;**;[7464]  Replace 1 line by 10 at CFSSUG+9		MAT	21-Apr-87       
       	  DECR HSHCNT,(Q2)	;[7464] Don't need this
	ELSE.			;[7464] Type is the same
	  CFSULK		;[7464] Unlock because CFSUGA does it too
	ENDIF.			;[7464]
	MOVE T1,SDBOFF		;[7464] Get SDBUDB offset
	ADDI T1,1		;[7464] Get next unit
	HRRZ T2,SDBUDB(T1)	;[7464] UDB address
	SKIPN T2		;[7464] Was it last?
	RETSKP			;[7464] Yes, done
	JRST CFSSU1	  	;[7464] Do next unit	
   >	;IFN CFSSCA
	RETSKP			;And done
;**;[7464]  Add 1 line after CFMDER:-11			MAT	21-Apr-87
	ENDSV.			;[7464] 
	SUBTTL	Structure resource manager -- CFMDER (Mount/Dismount error)

; This routine is used by CFSSMT and CFSSUG upon failure.
; It will convert the denial reason code (returned from the failed vote)
; into a meaningful TOPS-20 error code and RETBAD with it.
;
; Expects:	T2/ Denial reason code
;		Q2/ Desired access

;**;[7330]  Replace 2 lines with 4 at CFMDER:		DML	16-Jun-86
CFMDER:	SKIPN T2		;[7330] Did we receive an expected error code?
        JRST CFMDE1		;[7330] No - invalid error code
	SKIPG T2		;[7330] Did the mount fail on this system?
	RETBAD(MSTX50)		;[7330] Yes, so say so
	CAIE T2,.CDOCT		;Fail because it is owned on another system?
	RETBAD(MSTX44)		;No, not a special error worth calling out.
	CAIE Q2,.HTOEX		;Did we want exclusive?
	RETBAD(MSTX47)		;No.  Failed because another system had .HTOEX
	RETBAD(MSTX48)		;Yes. Failed because another system had .HTOAD

;**;[7330]  Change BUGHLT text at CFMDE1:		DML	16-Jun-86
CFMDE1: BUG. (HLT,CFSTUC,CFSSRV,SOFT,<CFSSRV - Unexpected error encountered during structure operation>,<<T2,CODE>>,<

Cause:	A structure mount or dismount failed and generated an unexpected or
	illegal error code of zero.  This should never happen.

Data:	CODE - Bogus error code
>)				;[7330]
	SUBTTL	Structure resource manager -- CFSSDM (Release mount resource)

;Routine to undo the MOUNT entry
;	T1/ STRUCTURE number
;Returns:	+1 always

CFSSDM::
   IFE CFSSCA,<RET>
   IFN CFSSCA,<			;Only if SCA is present
	SAVEAC <Q1,Q2,Q3,P1>	;Get some regs to work with
;**;[7464]  Add 1 line at CFSSDM+4			MAT	21-Apr-87       
	STKVAR <SDBOFF>		;[7464] SDBUDB offset
	MOVE Q3,T1		;Save STR number
	CALL GNAME
	EXCH T1,Q3		;Save name, get str num back
	MOVE T1,STRTAB(T1)	;Get SDB
;**;[7464]  Replace 3 lines by 4 at CFSSDM+8		MAT	21-Apr-87       
	MOVE T2,SDBUDB(T1)	;[7464] Get UDB of first unit
	MOVE Q1,UDBDSN(T2)	;[7464] Get serial number
	MOVE P1,UDBDSH(T2)	;[7464] Get the high-order bits
	MOVEM T1,SDBOFF		;[7464] Save SDBUDB Offset
	TXO P1,STRCTK
	TLNN Q1,-1		;Something in the LH?
	MOVSS Q1		;No
;Now have:
;	Q1/ DSN
;	Q3/ name
;	P1/ high-order DSN bits

	CFSLOK			;Lock up the data base
	MOVE T1,Q3		;Copy the name
	MOVX T2,STRCTN		;Get proper qualifier
	CALL HSHLOK		;Look 'er up
	 SKIPA			;If not here, forget it
	CALL CFSRMV		;Remove it
	MOVE T1,Q1		;Get DSN
	MOVE T2,P1		;Get qualifier
;**;[7464]  Replace 1 line at CFSSDM+28			MAT	21-Apr-87       
CFSSD1: CALL HSHLOK		;[7464] (T1,T2/T1,T2)Look it up
	 SKIPA
	CALL CFSRMV		;And remove it
;**;[7464]  Replace 1 line by 13 at CFSSDM+31		MAT	21-Apr-87       
	MOVE T1,SDBOFF		;[7464] Get SDBUDB offset
	ADDI T1,1		;[7464] Get next unit
	HRRZ T2,SDBUDB(T1)	;[7464] UDB address
	SKIPN T2		;[7464] Was it last ?
	CALLRET CFSFAL		;[7464] yes All done	
	MOVEM T1,SDBOFF		;[7464] Save SDB offset
	MOVE T1,UDBDSN(T2)	;[7464] Get serial number
	MOVE T2,UDBDSH(T2)	;[7464] Get high order bits
	TXO T2,STRCTK		;[7464] Make it unique
	TLNN T1,-1		;[7464] Something in the LH?
	MOVSS T1		;[7464] No
	JRST CFSSD1		;[7464] Do it for next unit
	ENDSV.			;[7464] 
  >	;IFN CFSSCA
	SUBTTL	Structure resource manager -- CFSSDI (Release mount resource)

;**;[7464] Add new routine CFSSDI			MAT	21-Apr-87
;[7464] CFSSDI - Routine to undo the MOUNT entry when we do not have SDB yet 
;(in case of structure creation)
;
;Call with:
;	T1/ User block address in monitor space (from MSTR)
;	Q3/ Alias
;Returns:	+1 always

CFSSDI::
   IFE CFSSCA,<RET>
   IFN CFSSCA,<			;Only if SCA is present
	SAVEAC <Q1,Q2,Q3,P1>	;Get some regs to work with
	STKVAR <UNIADR,AOBPTR,FTIM>
	SETZM FTIM		;It is first time
	MOVEI T2,.MSISU(T1)	;Get address of first unit
	HRRZ T1,.MSIUNU(T1)	;Get number of units
	MOVN T1,T1		;Negate it
	MOVSI T1,(T1)		;Form AOBJN pointer
	CFSLOK			;Lock up CFS database
CFSDI1: MOVEM T1,AOBPTR		;Save it
	MOVEM T2,UNIADR		;Save Unit address
	MOVE T3,.MSIUN(T2)	;Get Unit nb
	DMOVE T1,.MSICH(T2)	;Get Chan,Kont
	CALL CHKCKU		;(T1,T2,T3/T1) Get UDB address
	 RET			;Failed erreur code in T1
	MOVE Q1,UDBDSN(T1)	;Get DSN
	MOVE P1,UDBDSH(T1)	;Get high order bits
	TXO P1,STRCTK		;Make it unique
	TLNN Q1,-1		;Do we have to swap?
	MOVSS Q1		;Yes
	SKIPE FTIM		;Is it first time?
	IFSKP.			;Yes
	  SETOM FTIM		;No more first time
	  MOVE T1,Q3		;Get Alias
	  MOVX T2,STRCTN	;Get proper qualifier
	  CALL HSHLOK		;(T1,T2/T1,T2)Look it up
	  SKIPA			;not there
	  CALL CFSRMV		;(T1/)Remove it
	ENDIF.
	MOVE T1,Q1		;Get DSN
	MOVE T2,P1		;Get qualifier
	CALL HSHLOK		;(T1,T2/T1,T2)Look it up
;**;[7492] Replace 2 lines with 5 at CFSDI1: + 23. L	JDM	16-Jun-87
	IFSKP.			;[7492]IF WE FOUND IT
	  DECR HSHCNT,(T1)	;[7492]DECREMENT HASH COUNT
	  OPSTR <SKIPG>,HSHCNT,(T1) ;[7492]STILL SHARED?
	  CALL CFSRMV		;[7492](T1/)NO. REMOVE IT
	ENDIF.			;[7492]
	MOVE T2,UNIADR		;Get address of unit
	MOVE T1,AOBPTR		;Get AOBJN pointer
	ADDI T2,.MSTNO		;Get address of next unit
	AOBJN T1,CFSDI1		;Do it for next unit
	CALLRET CFSFAL		;All done
	ENDSV.
  >   ;IFN CFSSCA
	SUBTTL	Structure resource manager -- STRVER (Structure verify)

;Routine called during "CI joining" to reverify any structure resource.
;This is done in the event one or more nodes have been off of the CI
;and mounted structures without benefit of the voting operation.
;The reverification simply votes on the current state of the structure
;mount resources.

STRVER:
   IFE CFSSCA,<RET>		;NOTHING TO DO FOR NON-CFS SYSTEMS
   IFN CFSSCA,<
	SAVEP			;Get some regs to use
	MOVSI P1,-STRN		;Scan the table
	DO.
	 SKIPN P2,STRTAB(P1)	;Anybody here?
	 IFSKP.			;If so
	  MOVEI T1,0(P1)	;Get STR number
	  CALL GNAME		;Get its name
	  MOVX T2,STRCTN	;Look up resource
	  CALL HSHLOK
	  ANSKP.		;If we have it registered...
	  CALL STRVVT		;Do vote
	  MOVE P2,SDBUDB(P2)	;Get UDB address
	  MOVE T2,UDBDSH(P2)	;Get high order serial number
	  MOVE T1,UDBDSN(P2)	;Get low order
	  TXO T2,STRCTK		;Make it unique
	  TLNN T1,-1
	  MOVSS T1		;Get DSN in right order
	  CALL HSHLOK		;Look this up too
	  ANSKP.		;If here
	  CALL STRVVT		;Do vote
	 ENDIF.			;Done with that one
	 AOBJN P1,TOP.		;Do all entries
	ENDDO.
	RET			;Done

;Local routine of STRVER to do upgrading.
;	T1/ resource block
; uses P3 (temp of STRVER)

STRVVT:	MOVE P3,T1		;Save block
	DMOVE T1,HSHROT(T1)	;Get name
	LOAD T3,HSHTYP,(P3)	;Get current access
	CFSLOK
	CALL CFSUGZ		;do it
	 BUG.(HLT,CFSVFL,CFSSRV,SOFT,<CFSSRV - Structure verify failed>,,<

Cause:	CFS could not verify an existing structure resource during
	the join operation. This probably means there is a structure
	naming conflict.
>)
	DECR HSHCNT,(P3)	;Don't need this count
	RET			;Done
   >	;IFN CFSSCA

;job 0 routine called from CHKR for stuff

CFSJ0::	JE SCVER,,R		;If no bit set, all done
	SETZRO SCVER		;no longer needed
	CALLRET STRVER		;Do it
	SUBTTL	File enqueue resource manager -- CFSENQ (Get ENQ resource)

;Routines to obtain and release ENQ lock on a file. This code is
;the ENQ "detector" that prevents two or more CFS nodes from using
;ENQ on the same file!
;Get ENQ resource.
;	T1/ OFN
;Returns:
;	+1 failed. Another node has it
;	+2 SUCCESS.

   IFDEF CFSDUM,<		;If a reduced CFS
CFSENQ::RETSKP			;Succeed
   >	;IFDEF CFSDUM

   IFNDEF CFSDUM,<
CFSENQ::SAVEQ
;**;[7348]  Add 2 lines after CFSENQ::+0		DML	1-Aug-86
	STKVAR <OFNENQ>		;[7348]
	MOVEM T1,OFNENQ		;[7348] Save the OFN
	LOAD Q3,STRX,(T1)
	CALL ENQSET		;Set up args
	 JRST RSKP		;Local. All set
;**;[7348]  Remove 1 line at CFSENQ:+4			DML	1-Aug-86
	DMOVE Q1,T1
	DO.
	 CALL CFSSPC		;Get some space
	 IFNSK.			;If failed
	  CALL SBLOCK		;Wait a bit
	  LOOP.
	 ENDIF.
	ENDDO.
	DMOVEM Q1,HSHROT(T1)	;Stash it
	MOVEI T2,.HTOEX		;Exclusive please
	STOR T2,HSHTYP,(T1)	;Ask for it
	SETONE HSHLCL,(T1)	;But it is local exclusive
	SETZM T2		;No retry
	MOVE T3,STRTAB(Q3)	;Get SDB
	LOAD T3,STEXL,(T3)	;Get shared/exclusive indicator
	CALL @[	IFIW!CFSGET
		IFIW!CFSGTL](T3)
	 RETBAD()		;Nope. Someone else has it
	SKIPE T1
	CALL @HSHRET(T1)	;If didn't need it
;**;[7348]  Replace 1 line with 17 at CFSDEQ::-8	DML	1-Aug-86
	CFSLOK			;[7348] Lock the database
	DMOVE T1,Q1		;[7348] Get root and qualifier
	CALL HSHLOK		;[7348] (T1,T2/T1,T2)Find the entry
	 BUG.(HLT,CFEQHF,CFSSRV,SOFT,<ENQ token not found>,,<

Cause:	An ENQ token was just created and one already existed so the block
	which was passed has been released.  Now, we are attempting to find
	the original block and this has failed.

Action: Look in CFS free space to try to find the remains of the original 
	block.  Try to determine how the block could have been released even 
	though this routine acquired it.
>)				;[7348] Error!
	MOVE T2,OFNENQ		;[7348] Get the OFN for this ENQ
	MOVEM T2,HSHCOD(T1)	;[7348] Put it in the token
	JRST CFSRSK		;[7348] Unlock database and return success
	ENDSV.			;[7348] End of STKVAR
   >	;IFNDEF CFSDUM
	SUBTTL	File enqueue resource manager -- CFSDEQ (Release ENQ resource)

;Release ENQ resource
;	T1/ OFN
;Returns: +1 always

   IFDEF CFSDUM,<
CFSDEQ::RET
   >	;IFDEF CFSDUM

   IFNDEF CFSDUM,<		;If real CFS
CFSDEQ::CALL ENQSET		;Get args
	 RET			;Local structure
	CALL CFSNDO		;undo it
	 NOP			;??
	RET			;And done

;Utility to set up args for ENQ/DEQ stuff
;	T1/ OFN

;**;[7315]  Replace 3 lines with 26 at ENQSET:		DML	4-Jun-86
ENQSET:	STKVAR <SAVOFN>		;[7315] A place to save the OFN
	TMNN OFNDMO,SPTH(T1)	;[7315] Is this OFN dismounted?
	IFSKP.			;[7315] Yes
	  MOVEM T1,SAVOFN	;[7315] Save this for later
	  HRLZS T1		;[7315] Form OFN,,0 for call
 	  CALL OFNJFD		;[7315] (T1/T1)Convert OFN into JFN
	   BUG.(HLT,CFEQSF,CFSSRV,SOFT,<CFSSRV - Could not convert OFN to JFN>,,<

Cause:	ENQSET was called to set up the root and qualifier for the ENQ token 
	for a certain OFN.  This OFN was dismounted so the routine must look
	in the JFN block for the structure name because the STRTAB entry is 
	zero.  However, the conversion from OFN to JFN failed.

Action:	Investigate the dump to try to determine why the call to OFNJFN failed.
>)				;[7315] Error!
	  HLRZS T1		;[7315] Position the JFN correctly
	  IMULI T1,MLJFN	;[7315] Convert into internal offset
	  LOAD T1,FLDSB,(T1)	;[7315] Get the pointer to the device string
	  CALL ASCSIX		;[7315] (T1/T1,T2)Convert to sixbit
	   NOP			;[7315] This should not fail!
	  MOVE T2,SAVOFN	;[7315] Get back saved OFN
	  LOAD T2,STGADR,SPTH(T2)  ;[7315] Get XB address
	ELSE.			;[7315] OFN is not dismounted
	  LOAD T2,STGADR,SPTH(T1)  ;[7315] Get XB address
	  LOAD T1,STRX,(T1)	   ;[7315] Get structure number
	  CALL GNAME		;[7315] (T1/T1)Get the structure name
	ENDIF.			;[7315]
	TXO T2,FILEEQ		;Ask for this resource
	RETSKP			;And done
;**;[7315] Add 1 line after ENQSET:+5			DML	4-JUN-86
	ENDSV.			;[7315]
   >	;IFNDEF CFSDUM
	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

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)

;Get a free job global for a local job.
;	T1/ Local job number
;Returns:	+1 none available
;		+2 T1/ number

JBGET1::
	SKIPN T1		;Local Job 0 is always Global Job 0
	 RETSKP			;So just return
	MOVE T4,T1		;Save argument
	MOVSI T1,-JBWDS		;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
	  DPB T4,T2		;Store local job number
	  RETSKP		;And done
	 ENDIF.
	 AOBJN T1,TOP.		;Look over them all
	ENDDO.
	RET			;None here
	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,CFSSRV,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 persists, change the CHK to a HLT and determine why
	the caller is passing a bad job number.

>)
	 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)

;Job bit table routines, continued
;Routine to get some jobs. Called at system start up to
;allocate the proper number of job packets and mark the JOBMBT table

CFGTJB::
	SAVEQ			;Get some work regs
	MOVSI Q1,-MXPKTS	;Max,,packet we are on
	MOVEI Q2,LCLPKT		;Number we need
	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 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	Miscellaneous Interfaces -- FILRST (Reset all files at startup)

;Routine called at system start-up to reset all file states to unowned.
;This is used so that we can mount PS: after reading it.

FILRST::
   REPEAT 0,<			;Don't need this while PS: are not shared
	SAVEAC <P1>		;Get a work reg
   IFNDEF CFSDUM,<		;Only if real CFS
;
; NOTE: IT MIGHT BE USEFUL TO ONLY SEARCH THE OFNS POINTED TO BY THE HASH
;	TABLE BUT THIS CODE IS DONE VERY INFREQUENTLY SO IT DOESN'T REALLY 
;	MATTER NOW. TAM 28-JAN-85
;
	MOVEI P1,1		;Start with first OFN
	SETOM DDPFRK		;Pretend we are DDMP
	DO.			;Loop over them all
	 SKIPN SPTH(P1)		;This one in use?
	 IFSKP.			;If so.
	  SETONE SPTFR,(P1)	;Say we need it flushed
	  CALL DDOCFS		;Do it
	  ANNSK.		;But if it failed
	   MOVEI T1,1		;Do a short dismiss
	   DISMS		;""
	   JRST TOP.
	 ENDIF.
	 CAIGE P1,NOFN		;All done?
	 AOJA P1,TOP.		;No. DO them all
	ENDDO.			;All done
	SETZM DDPFRK		;No longer DDMP
   >	;IFNDEF CFSDUM
   >	;REPEAT 0
	RET			;""
	SUBTTL	Miscellaneous Interfaces -- CFSERR (Illegal configuration)

;Here when an illegal CFS confiugration occurs

CFSERR:	BUG.(HLT,CFSICN,CFSSRV,SOFT,<CFSSRV - Illegal configuration>,,<

Cause:	This system has detected an illegal configuration. There may be 
	too many nodes in the network. The caller of this routine should 
	be examined for more details.
>)
	SUBTTL	Miscellaneous Interfaces -- CFRDSN (Read drive serial number)

;Routine called from PHYSIO when a pack that is part of a mounted
;structure is moved to a new drive. The events that cause this are:
;1) operator reassignment (moving the pack), or 2) shadow-set failure.

;This routine handles the case of a pack being moved to a previously
;unused drive; it is called so that the CFS resource may be "renamed".

;It does not handle the case of two packs swapped between their drives.
;This unsupported case seems useless and is very hard to support without
;serious races.

;ACCEPTS:	T1/ new UDB
;		T2/ previous UDB for this
;RETURNS:	+1

CFRDSN::
   IFE CFSSCA,<RET>		;If no SCA, done
   IFN CFSSCA,<			;If an SCA
	EA.ENT			;Need to be extended
;**;[7464]  Replace 1 line at CFRDSN::+4		MAT	21-Apr-87
	SAVEQ			;[7464] Save some work registers
	STKVAR <NUDB,OUDB>
	SETOM Q1		;Indicate we entered at CFRDSN
	MOVEM T1,NUDB		;Save the arguments
	MOVEM T2,OUDB
	JRST CFDSN1		;Continue at common code

 	SUBTTL	Miscellaneous Interfaces -- CFSDSN (Swap drive serial number)

;Routine called from PHYSIO when the drive serial number of a unit
;changes.  This can happen when the HDA of a DSA disk (RA60/RA81) is 
;changed while the system is still running.
;
;PHYSIO will provide the address of the UDB (with the new serial number
;stored in it) and the old drive serial number.  This routine will proceed
;to unlink the old resource blocks, adjust the DSN, and link this new block
;into its appropriate place in the hash table.  Conceptually, the old blocks
;are removed and replaced by the new ones.  But in effect, the old blocks
;are never actually destroyed, just updated and relinked.
;
;This routine only handles the case of a drive being assigned a new DSN and
;this new DSN does not already have a CFS resource which describes it.  If
;a CFS resource exists for the new DSN, and it is for a different structure
;name, then a CFSRNM BUGHLT will result.  This case is not only unsupported 
;but clearly illegal.
;
;Expects: 	T1/ high-order word of old DSN
;		T2/  low-order word of old DSN
;		P3/ UDB updated with new drive serial number
;Returns:	+1 always

CFSDSN::
   IFE CFSSCA,<RET>		;If no SCA, done
   IFN CFSSCA,<			;If an SCA
	EA.ENT			;Need to be extended
;**;[7464]  Replace 1 line at CFSDSN::+4		MAT	21-Apr-87
	SAVEQ			;[7464] Save some work registers
	STKVAR <NUDB,HDSN,LDSN>
	SETZM Q1		;Indicate we entered at CFSDSN
	MOVEM P3,NUDB		;Save arguments
	MOVEM T1,HDSN
	MOVEM T2,LDSN
;	JRST CFDSN1		;Continue at common code
	;..
;This is common code used by both CFRDSN and CFSDSN.

	;..
CFDSN1:	MOVE T1,NUDB		;Get new UDB
	MOVE T3,UDBSTR(T1)	;Get structure "back pointer"
;**;[7464]  Replace 3 lines with 8 at CFDSN1:+3		MAT	21-Apr-87
	SETZM Q3		;[7464] Assume that this is the 1st unit
	TLNE T3,-1		;[7464] Is this the first unit?
	SETOM Q3		;[7464] No. So remember this.

;[7464] Rename the CFS resource.
;[7464] The DSN Token will be unlinked, changed, and relinked.
;[7464] The Name Token will have HSHCOD changed if the first unit is the
;[7464] one which is affected.

       	MOVE T2,UDBDSH(T1)	;Get high-order bits for new DSN from new UDB
	MOVE T1,UDBDSN(T1)	;Get low-order bits
	TXO T2,STRCTK		;Prepare to look up resource based on new DSN
	TLNN T1,-1
	MOVSS T1
	CALL HSHLOK		;(T1,T2/T1,T2) See if it is around
	IFSKP.			;If so, this could be bad
	 MOVE T2,NUDB		;Recover the UDB
	 HRRZ T2,UDBSTR(T2)	;Get SDB pointer
	 CALL GNAME2		;(T2/T2) Get name of this structure
	 CAMN T2,HSHCOD(T1)	;Same as the resources name?
	 RET			;Yes. Nothing to do then.

;If we are here, it is likely the system will crash with a CFSRNM BUGHLT.
;The most likely reason for the crash is the unsupported case of two packs
;swapped between their drives.  This could also indicate another unsupported
;case where a drive is given a new HDA (and thus a new drive serial number)
;and this DSN is already described by a CFS resource for structure of a 
;different name.

	ENDIF.	
	SKIPL Q1		;Did we move the pack to a new drive?
	IFSKP.			;Yes
	  MOVE T2,OUDB		;Recover the old UDB address
	  MOVE T1,UDBDSN(T2)	;Get DSN
	  MOVE T2,UDBDSH(T2)	;Get the high-order bits
	ELSE.			;No, drive received a new serial number
	  MOVE T1,LDSN		;Get the low-order bits of the old DSN
	  MOVE T2,HDSN		;Get the high-order bits of the old DSN
	ENDIF.
	TLNN T1,-1		;Anything in the LH?
	MOVSS T1		;No
	TXO T2,STRCTK		;Qualifier
	CALL HSHLOK		;(T1,T2/T1,T2) Look 'er up
	 RET			;Not here.  Nothing more to do

;Found the entry. Dequeue it and rename it.

	CALL HSHULN		;(T1) Remove it
	MOVE T3,NUDB		;Get new UDB
	DMOVE T3,UDBDSH(T3)	;Get the new DSN
	TLNN T4,-1		;LH OK?
	MOVSS T4		;No.
	MOVEM T4,HSHROT(T1)	;New name
	TXO T3,STRCTK		;Form high-order DSN as qualifier
	MOVEM T3,HSHQAL(T1)
	MOVEM T1,Q2  		;Save pointer to resource block
	DMOVE T1,HSHROT(T1)	;Get name
	CALL HSHLOK		;(T1,T2/T1,T2) Look up new name
	 SKIPA T2,Q2  		;If not here, good, so get packet address
	BUG.(HLT,CFSRNM,CFSSRV,SOFT,<CFRDSN - Could not rename DSN entry>,,<

Cause:	A pack of a mounted structure has been moved to a new unit and
	the new CFS mount resource already exists for the new drive.
      	Or, a drive on which there is a pack of a mounted structure has
	been given a new drive serial number and the new CFS mount 
	resource already exists for the new drive.
	This indicates either the CFS data base is wrong, or PHYSIO's
	data base is wrong.
>)
	MOVEM T2,HSHLNK(T1)	;Enqueue it
	MOVEM T1,HSHBKP(T2)	;And point backwards as well
	SETZM HSHLNK(T2)	;Clear our link
;**;[7464]  Add 1 line after CFCBRD::-32		MAT	21-Apr-87
	IFE. Q3			;[7464]  If this is first unit, fix Name Token
	  MOVE T1,HSHCOD(T2)	;Get the STRUCTURE name
	  MOVX T2,STRCTN	;Look up the name
	  CALL HSHLOK		;(T1,T2/T1,T2) Do it
	  IFSKP.		;We should have found the resource!!
	   MOVE T2,NUDB		;Get the new UDB
	   MOVE T3,UDBDSN(T2)	;Get the low order DSN
	   MOVE T4,UDBDSH(T2)	;Get the high order DSN
	   TXO T4,STRCTK	;Make high order word unique
	   XOR T3,T4		;Make the hash code
	   MOVEM T3,HSHCOD(T1)	;Stash in the packet as the code
	  ENDIF.
;**;[7464]  Add 1 line after CFCBRD::-21		MAT	21-Apr-87
	ENDIF.			;[7464] 
	RET			;And done
	ENDSV.
>	;IFN CFSSCA
	SUBTTL	Miscellaneous Interfaces -- CFCBRD (Broadcast system cease)

;CFCBRD - Cease broadcast, called by MEXEC during the shutdown sequence.
;This routine broadcasts cease, cease canceled, and timesharing is over
;so other systems can take action with regards to structures being accessed
;through the MSCP server.
;	CALL CFCBRD		;(/)
; RETURN +1: No other systems out there
;        +2: Sent the message
;
;USES:	T1,T2/ ASCIZ OF OUR NODE NAME

;******
;FOR A MORE COMPLETE DESCRIPTION OF THE "CLUSTER CEASE" PROCESSING, SEE THE
;LARGE COMMENT PRECEDING ROUTINE CFCEAS.
;******

CFCBRD::
   IFDEF CFSDUM,<RET>		;If reduced CFS, just return
   IFNDEF CFSDUM,<		;Full CFS so do routine
	SKIPN CFSHCT		;Anybody else out there?
	RET			;No, nothing else to do
	DMOVE T1,OURNAM		;Get our node name
	BLCAL. (CFSBRD,<T1,T2,[.CFSHT],<.,CFSHCO>>)  ;Do the broadcast
	RETSKP			;Done

;Coroutine of above.  Used to stash the node number and shutdown time.

CFSHCO:	SAVEAC <T1,T2>		;Do not trash anything
	MOVE T2,T1		;Save vote packet
	CALL CFSPRT		;(/T1) Get our local port number
	MOVEM T1,CFDAT(T2)	;Store it in the vote packet
	MOVE T1,HSYST1		;GET CEASE TIME
	MOVEM T1,CFDT1(T2)	;Store time in the vote packet
				;It is placed in the transaction number word
	RET 			;Return
>				;End of IFNDEF CFSDUM
;Random stuff

;here if CFSGET does anything unexpected

ILLGET:	BUG.(HLT,CFSIGT,CFSSRV,SOFT,<CFSSRV - Illegal return from CFSGET>,,<

Cause:	A call to CFSGET, CFSGTT or CFSGTL returns +1 even though a
	wait-until-successful was requested.
>)

;Routine to crash if someone tries to connect after we've been dead for
;sometime. This routine is called whenever we get connected another
;CFS SYSAP and we had previously been off of the CI for some time.
;We have to crash in that case because the two systems may be out
;of synch wrt the shared structures and may permanently interlock
;one another against referencing those structures.

CFSDIE:	BUG. (HLT,CFSKPD,CFSSRV,HARD,<CFSSRV - The KLIPA failed>,,<

Cause: The KLIPA hardware or the CI has failed and CFS cannot continue.
>)

CFNCNT:	BUG. (HLT,CFZCNT,CFSSRV,SOFT,<CFSSRV - Zero HSHCNT before decrement>,,<

Cause:	A routine wants to decrement the resource share count but the
	count is already zero.
>)

ONLINE:	SAVET
	MOVE T3,CFSHNM(T1)	;Get serial number
	LSH T3,-4		;right-justify it
	MOVE T1,CFSHST(T1)	;Get CID
	CALL SC.NOD		;Get node number
   IFN DEBUG,<
	BUG. (INF,CFCONN,CFSSRV,SOFT,<CFSSRV - CFS connection>,<<T2,NODE>,<T1,CID>,<T3,SERNUM>>,<

Cause:	A CFS connection has been received from another node on the CI-20.

Data:	NODE - Number of connecting node
	CID - Connect ID
	SERNUM - Serial number of remote node
>)
   >	;IFN DEBUG
	CALLRET PYCON		;INFORM PHYSIO OF ONLINE


IFN DEBUG,<
OFLINE:	SAVET
	MOVE T3,CFSHNM(T1)	;Get serial number
	LSH T3,-4		;right-justify it
	MOVE T1,CFSHST(T1)	;Get CID
	CALL SC.NOD		;Get node number
	BUG. (INF,CFDISC,CFSSRV,SOFT,<CFSSRV - CFS disconnect>,<<T2,NODE>,<T1,CID>,<T3,SERNUM>>,<

Cause:	A CFS disconnect request has been received from a remote node on
	the CI-20.

Data:	NODE - Remote node number
	CID - Connect ID
	SERNUM - Serial number of remote node
>)
	RET
   >	;IFN DEBUG


;PHYNOL
;
; T3/ CONNECT ID OF NODE GOING OFFLINE
;

PHYNOL:	SAVET			;Save everything just in case
	MOVE T1,T3		;Get the connect ID
	CALL SC.NOD		;Get the node number
	CALLRET PYCOFF		;And declare offline
	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.

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,CFSSRV,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.

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

	TNXEND
	SUBTTL	End of CFSSRV
	END