Google
 

Trailing-Edge - PDP-10 Archives - BB-M081Z-SM - monitor-sources/cfssrv.mac
There are 21 other files named cfssrv.mac in the archive. Click here to see a list.
; Edit= 9148 to CFSSRV.MAC on 21-Feb-90 by GSCOTT
;Update copyright date. 
; Edit= 9122 to CFSSRV.MAC on 22-Sep-89 by GSCOTT
;Prevent two systems from using a shared tape drive at the same time by
;returning OPNX32 (OPENF%) or ASNDX4 (ASND%).
; Edit= 9038 to CFSSRV.MAC on 9-Dec-88 by RASPUZZI
;Prevent CFSOFB BUGHLTs. Also, obtain exclusive access when updating an OFN.
; Edit= 9030 to CFSSRV.MAC on 8-Nov-88 by LOMARTIRE
;Merge Production changes to BUG text
; Edit= 8960 to CFSSRV.MAC on 1-Sep-88 by GSCOTT
;*Performance* Change IFNSK to IFSKP wherever possible.
; Edit= 8956 to CFSSRV.MAC on 30-Aug-88 by GSCOTT
;Fix badly formatted BUG.
; Edit= 8951 to CFSSRV.MAC on 26-Aug-88 by LOMARTIRE
;Improve BUG. documentation some more
; Edit= 8874 to CFSSRV.MAC on 10-Aug-88 by RASPUZZI
;Update BUG. documentation again.
; Edit= 8863 to CFSSRV.MAC on 21-Jul-88 by RASPUZZI
;Increase STKVAR for structure names and shutdown messages so that we don't
;trash stacks and cause ILMNRFs.
; UPD ID= 8488, RIP:<7.MONITOR>CFSSRV.MAC.19,   9-Feb-88 12:17:31 by GSCOTT
;TCO 7.1218 - Update copyright notice.
; UPD ID= 8406, RIP:<7.MONITOR>CFSSRV.MAC.18,   4-Feb-88 10:23:20 by GSCOTT
;TCO 7.1210 - Set CFCCML, CFCCDF, CFCONN, CFDISC to be not normally dumpable.
; UPD ID= 8357, RIP:<7.MONITOR>CFSSRV.MAC.17,  20-Jan-88 11:40:51 by RASPUZZI
;TCO 7.1190 - Split CFSSRV into CFSPAR, CFSUSR and CFSSRV so that we can
;             obtain CREFs. Note that no functional change of CFS has
;             occurred.
; UPD ID= 298, RIP:<7.MONITOR>CFSSRV.MAC.16,  16-Nov-87 15:02:50 by MCCOLLUM
;TCO 7.1138 - Do not search ENQPAR anymore; CFSSRV won't build.  Call new
;  routine ENQCST from CFSRSV upon a cluster state change.
; UPD ID= 260, RIP:<7.MONITOR>CFSSRV.MAC.15,   5-Nov-87 15:42:04 by LOMARTIRE
;TCO 7.1115 - Move setting of VPRTY and clearing of EQFKFL into CFSRSV
; UPD ID= 227, RIP:<7.MONITOR>CFSSRV.MAC.14,  28-Oct-87 14:24:00 by LOMARTIRE
;TCO 7.1096 - Replace CALL ENQRSV with SETOM EQCSTF to notify ENQSRV of
;  cluster state change.
; UPD ID= 174, RIP:<7.MONITOR>CFSSRV.MAC.13,  20-Oct-87 18:21:15 by GSCOTT
;TCO 7.1075 - Update table of contents, repaginate a few places.  
; Change mistyped TCO number 7.7012 to 7.1012.
; UPD ID= 172, RIP:<7.MONITOR>CFSSRV.MAC.12,  20-Oct-87 15:59:31 by RASPUZZI
;TCO 7.1074 - Add routine CFSNOD for usage.
; UPD ID= 158, RIP:<7.MONITOR>CFSSRV.MAC.11,  19-Oct-87 17:08:42 by LOMARTIRE
;TCO 7.1072 - Add code to support cluster-wide ENQ
; UPD ID= 61, RIP:<7.MONITOR>CFSSRV.MAC.10,   6-Aug-87 15:41:09 by LOMARTIRE
;TCO 7.1033 - Prevent PITRAP from EA.ENT with extended stack pointer
; UPD ID= 58, RIP:<7.MONITOR>CFSSRV.MAC.8,  29-Jul-87 08:20:31 by RASPUZZI
;TCO 7.1029 - Prevent CFCTNF BUGHLTs.
; UPD ID= 48, RIP:<7.MONITOR>CFSSRV.MAC.7,  23-Jul-87 08:41:07 by LOMARTIRE
;More of TCO 7.1021 - Create and use a new stack for CFSDMP
; UPD ID= 44, RIP:<7.MONITOR>CFSSRV.MAC.6,  15-Jul-87 14:49:30 by LOMARTIRE
;More of TCO 7.1021 - Really update the TOC this time!
; UPD ID= 39, RIP:<7.MONITOR>CFSSRV.MAC.5,  15-Jul-87 14:39:05 by LOMARTIRE
;TCO 7.1021 - Add code to support cluster dump facility.  Update TOC.
; UPD ID= 22, RIP:<7.MONITOR>CFSSRV.MAC.4,  16-Jun-87 15:17:46 by MCCOLLUM
; TCO 7.1012 - Make CFMDSN fail if the DSN specified already exists
;  for a different structure 
; UPD ID= 19, RIP:<7.MONITOR>CFSSRV.MAC.3,  16-Jun-87 12:19:27 by LOMARTIRE
;TCO 7.1011 - Add cluster joining messages to CFSJYN.  Also, update TOC.
; *** 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 
; *** 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 
; 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

;	COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1984, 1990.
;	ALL RIGHTS RESERVED.
;
;	THIS SOFTWARE IS FURNISHED UNDER A  LICENSE AND MAY BE USED AND  COPIED
;	ONLY IN  ACCORDANCE  WITH  THE  TERMS OF  SUCH  LICENSE  AND  WITH  THE
;	INCLUSION OF THE ABOVE  COPYRIGHT NOTICE.  THIS  SOFTWARE OR ANY  OTHER
;	COPIES THEREOF MAY NOT BE PROVIDED  OR OTHERWISE MADE AVAILABLE TO  ANY
;	OTHER PERSON.  NO  TITLE TO  AND OWNERSHIP  OF THE  SOFTWARE IS  HEREBY
;	TRANSFERRED.
;
;	THE INFORMATION IN THIS  SOFTWARE IS SUBJECT  TO CHANGE WITHOUT  NOTICE
;	AND SHOULD  NOT  BE CONSTRUED  AS  A COMMITMENT  BY  DIGITAL  EQUIPMENT
;	CORPORATION.
;
;	DIGITAL ASSUMES NO  RESPONSIBILITY FOR  THE USE OR  RELIABILITY OF  ITS
;	SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
	SEARCH CFSPAR,PROLOG,SCAPAR,PHYPAR ;[7.1190]
	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 . . . . . . . . . . . . . . . . . . . . .   7
;    2. Data Storage . . . . . . . . . . . . . . . . . . . . .  12
;    3. CFS Macro Supporting Routines  . . . . . . . . . . . .  15
;    4. Initialization
;        4.1    CFSINI (SCA initialization routine)  . . . . .  16
;        4.2    CFSDIN (Initialize CFS database) . . . . . . .  17
;    5. Support Routines
;        5.1    CFONLT (Test state of connection)  . . . . . .  18
;        5.2    PRTOFL (Turn off dual port access) . . . . . .  19
;        5.3    PRTONL (Turn on dual port access)  . . . . . .  20
;        5.4    CFSKPR (KLIPA ucode reloaded)  . . . . . . . .  21
;        5.5    DEDKLP (KLIPA is dead) . . . . . . . . . . . .  22
;        5.6    CFSCTH (Connect to host) . . . . . . . . . . .  23
;        5.7    HASHN (Compute hash for resource)  . . . . . .  25
;        5.8    HSHLOK (Locate hash entry for resource)  . . .  26
;        5.9    GNAME (Get structure name) . . . . . . . . . .  27
;        5.10   CFSULL (Unlock CFS database) . . . . . . . . .  28
;        5.11   CFSMAP (Map entries onto function) . . . . . .  29
;        5.12   CFSRSE (Remove stale entries)  . . . . . . . .  31
;        5.13   CFSSBB (Place OFN in SDB)  . . . . . . . . . .  32
;        5.14   CFSWUP (General wait routine)  . . . . . . . .  33
;        5.15   CFSRSV (Restart vote)  . . . . . . . . . . . .  34
;        5.16   CFTADC (Get CFS time and date) . . . . . . . .  35
;        5.17   CFCNCK (Check for CFS connection to node)  . .  36
;    6. Resource manager
;        6.1    CFSGET (Acquire a resource)  . . . . . . . . .  37
;        6.2    CFSRMV (Remove entry from hash table)  . . . .  43
;        6.3    CFSNDO (Undeclare a resource)  . . . . . . . .  44
;        6.4    CFSOHS (Notify rejected hosts after undeclare)  46
;        6.5    CFSUGD (Upgrade or downgrade a resource lock)   47
;    7. The voter
;        7.1    VOTEW (Start vote and wait for results)  . . .  49
;        7.2    GVOTE (Get a vote buffer)  . . . . . . . . . .  56
;    8. Periodic check
;        8.1    CFSCHK (Scheduler poller)  . . . . . . . . . .  57
;        8.2    SCAPOL (Process incoming SCA messages) . . . .  59
	Subttl	Table of Contents (page 2)

;		     Table of Contents for CFSSRV
;
;				  Section		      Page
;
;
;    9. Call from SCA  . . . . . . . . . . . . . . . . . . . .  61
;        9.1    Message Received
;            9.1.1    SCAIN (Receive message from SCA) . . . .  62
;            9.1.2    SCMSG (Process a single received message  63
;            9.1.3    CFSRTV (Vote or seize) . . . . . . . . .  64
;            9.1.4    CFSRVT (Reply to vote) . . . . . . . . .  70
;            9.1.5    CFSRFR (Resource freed)  . . . . . . . .  72
;            9.1.6    CFSOFC (OFN change)  . . . . . . . . . .  73
;            9.1.7    CFSEFC (EOF received)  . . . . . . . . .  74
;            9.1.8    CFTADA (Time and date arrived) . . . . .  75
;            9.1.9    CFCEAS (Cease) . . . . . . . . . . . . .  76
;        9.2    SCABRK (Node went away)  . . . . . . . . . . .  81
;        9.3    LSNUP (Connect to listen)  . . . . . . . . . .  82
;        9.4    Connect response available
;            9.4.1    CFSCPS (Connect response available)  . .  85
;            9.4.2    CFSCPX (Disconnect duplicate connection)  88
;        9.5    CFSWDN (Write completed) . . . . . . . . . . .  89
;        9.6    CFSNDU (Node up) . . . . . . . . . . . . . . .  90
;        9.7    CFSOKS (Ok to send)  . . . . . . . . . . . . .  91
;        9.8    SCACRA (Credit available)  . . . . . . . . . .  93
;   10. Sending Messages
;       10.1    SCAENQ (Enqueue a SCA message) . . . . . . . .  94
;       10.2    SCASND (Send a message)  . . . . . . . . . . .  95
;       10.3    SENDQ (Maintain send queue)  . . . . . . . . .  97
;   11. Queuing Message Buffers
;       11.1    SCARET (Queue packet as message buffer)  . . .  99
;   12. Declare a dump listener
;       12.1    CFDLSN (Declare CFS dump listener) . . . . . . 100
;   13. Declare a listener
;       13.1    CFSLSN (Declare CFS listener)  . . . . . . . . 102
;   14. Connection Management
;       14.1    CHKOLD (Manage connect serial number)  . . . . 103
;       14.2    CHKOL0 (Generate old/new bit)  . . . . . . . . 104
;       14.3    PUTOLD (Install serial number) . . . . . . . . 105
;       14.4    CLRDLY (Clear delay bit in OLDTAB entries) . . 106
;       14.5    CHKDLY (Check for delayed entries) . . . . . . 107
	Subttl	Table of Contents (page 3)

;		     Table of Contents for CFSSRV
;
;				  Section		      Page
;
;
;   15. Directory lock resource manager
;       15.1    CFSLDR (Lock directory)  . . . . . . . . . . . 108
;       15.2    CFSRDR (Unlock directory)  . . . . . . . . . . 110
;       15.3    CFSDAU (Acquire allocation entry)  . . . . . . 111
;       15.4    CFAFND/CFAGET (Find/Get allocation table)  . . 112
;       15.5    CFASTO (Store new allocation value)  . . . . . 116
;       15.6    CFAULK (Unlock allocation entry) . . . . . . . 117
;       15.7    CFAREM (Remove allocation entry) . . . . . . . 118
;       15.8    CFAUPB (Undo keep here bit)  . . . . . . . . . 119
;       15.9    CFAVOK (Vote to be approved) . . . . . . . . . 120
;       15.10   CFADAR (Optional data present) . . . . . . . . 121
;       15.11   CFARMV (Voter remove entry)  . . . . . . . . . 122
;       15.12   GETDBK (Find resource block) . . . . . . . . . 123
;   16. File open resource manager
;       16.1    CFSGFA (Acquire file opening locks)  . . . . . 124
;       16.2    CFSFFL (Release file locks)  . . . . . . . . . 126
;       16.3    CFSURA (Downgrade to promiscuous)  . . . . . . 127
;   17. Frozen writer resource manager
;       17.1    CFSGWL (Get write access)  . . . . . . . . . . 128
;       17.2    CFSFWL (Free write access) . . . . . . . . . . 129
;   18. BAT block resource manager
;       18.1    CFGBBS (Set BAT block lock)  . . . . . . . . . 131
;       18.2    CFFBBS (Release BAT block lock)  . . . . . . . 132
;   19. File access token resource manager
;       19.1    CFSGWT (Get write token value) . . . . . . . . 133
;       19.2    CFSAWP/CFSAWT (Acquire write token)  . . . . . 134
;       19.3    CFSDWT (Write token revoked) . . . . . . . . . 144
;       19.4    CFSOVT (Approve sharing of OFN resource) . . . 145
;       19.5    CFSGOC (Get count of resource sharers) . . . . 146
;       19.6    CFSDAR (Optional data for access token)  . . . 147
;       19.7    CFSFWT (Free write token)  . . . . . . . . . . 148
;       19.8    CFSUWT/CFSCWT (Release/Cache access token) . . 151
;       19.9    CFSUNC (Uncache token) . . . . . . . . . . . . 154
;       19.10   CFSBOW (Broadcast OFN update)  . . . . . . . . 156
;       19.11   CFSBEF (Broadcast EOF) . . . . . . . . . . . . 157
;       19.12   CFSBRD (Main broadcast routine)  . . . . . . . 159
;       19.13   CFSFOD (DDMP force out done) . . . . . . . . . 160
;   20. Structure resource manager
;       20.1    CFSSMT (Acquire structure resource)  . . . . . 164
;       20.2    CFMNAM (Register structure name) . . . . . . . 166
;       20.3    CFMDSN (Register drive serial number)  . . . . 167
;       20.4    CFSSMI (Acquire structure resource)  . . . . . 169
;       20.5    CFSSUG (Upgrade or downgrade mount)  . . . . . 171
;       20.6    CFMDER (Mount/Dismount error)  . . . . . . . . 173
;       20.7    CFSSDM (Release mount resource)  . . . . . . . 174
;       20.8    CFSSDI (Release mount resource)  . . . . . . . 175
;       20.9    STRVER (Structure verify)  . . . . . . . . . . 177
	Subttl	Table of Contents (page 4)

;		     Table of Contents for CFSSRV
;
;				  Section		      Page
;
;
;   21. File enqueue resource manager
;       21.1    CFSENQ (Get ENQ resource)  . . . . . . . . . . 179
;       21.2    CFSDEQ (Release ENQ resource)  . . . . . . . . 181
;   22. ENQ Lock resource manager
;       22.1    CFEQLK (Lock ENQ database) . . . . . . . . . . 183
;       22.2    CFEQUL (Unlock ENQ database) . . . . . . . . . 185
;   23. MTA Lock resource manager
;       23.1    CFSMTA (Acquire MTA resource)  . . . . . . . . 186
;       23.2    CFSMTR (Release MTA resource)  . . . . . . . . 189
;       23.3    CFSMTS (Get MTA root and qualifier)  . . . . . 190
;   24. Miscellaneous Interfaces
;       24.1    FILRST (Reset all files at startup)  . . . . . 191
;       24.2    CFSERR (Illegal configuration) . . . . . . . . 192
;       24.3    CFRDSN (Read drive serial number)  . . . . . . 193
;       24.4    CFSDSN (Swap drive serial number)  . . . . . . 194
;       24.5    CFCBRD (Broadcast system cease)  . . . . . . . 197
;       24.6    CFSDMP (Force cluster dump)  . . . . . . . . . 198
;       24.7    ILLGET (Illegal return from CFSGET)  . . . . . 200
;       24.8    CFSKPD (KLIPA Failure) . . . . . . . . . . . . 201
;       24.9    ONLINE (CFS connection BUGINF) . . . . . . . . 202
;       24.10   CFDISC (CFS disconnect BUGINF) . . . . . . . . 203
;       24.11   PHYNOL (Declare the disks offline) . . . . . . 204
;   25. End of CFSSRV  . . . . . . . . . . . . . . . . . . . . 205
	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 CFDLSN		-2		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
Dump Listener		-2		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
MTA allocation			CFSMTA	CFSMTR

Unique code:

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

#
	SUBTTL Data Storage

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

LISDMP: ASCI8 (<LCS20$CFS$DUMP  >) ;[7.1021] The name of our dump listener
LISNAM: ASCI8 (<LCS20$CFS       >) ;Our name

RS DMPSTK			;[7.1021] The address of the dump stack
RS DMPSVP			;[7.1021] The stack at the time of the dump

;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
   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		;[7.1190] Number to stack from private stock
   >	;IFN CFSDUM
   IFDEF CFSDUM,<		;For a reduced CFS
	NSPCQ0==:^D150		;[7.1190] Just get a few for allocation entries
   >	;IFDEF CFSDUM
	NSPCQ1==:^D250		;[7.1190] Number of long packets to get

RS	CFNXPG,1		;Page pool address
RSI	CFNXSZ,<PGSIZ>		;Space available in pool
RS	CFTADL,1		;Time and date cell

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

HSHDRI==:1+<NFKS+^D35>/^D36	;[7.1190] Additional words for dir locks
WRDHSH==:NSPCQ0*HSHSIZ		;[7.1190] Words in hash packets
LNGHSH==:NSPCQ1*<HSHSIZ+HSHDRI>	;[7.1190] Words in long packets
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

MTA access		.MTTxx,,'MTA'	low order device serial number

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		--
>
	SUBTTL CFS Macro Supporting Routines
;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	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
	CAIN Q3,VC.OPN		;[8960] Open?
	IFSKP.			;[8960] No. Forget it then
	  MOVE T1,T2		;Get block address
	  CALLRET RELRES	;[8960] (T1) Return block to pool and return
	ENDIF.
	MOVE Q3,.RDDST(T2)	;[7144] Get destination software type
	MOVE T1,T2		;Get block address
	CALL RELRES		;(T1) Return block to pool
	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],<.,CFSINT>,T2,<.,MYPORT>,[BUFSCT],[0]>) ;[7.1190] 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.  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
	SOSE SCAILK		;[8960] Last one?
	IFSKP.			;[8960] 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

CFSRS0:	JN <HSHUGD,HSHKPH,HSHWVT,HSHTAM>,(T1),RSKP ;[7.1029] 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 -- 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
   IFN CLEQIN,<			;[7.1072]
	CALL ENQCST		;[7.1138] Notify ENQSRV of cluster state change
   >				;[7.1072]
	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 -- 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.
	  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
	    IFGE. T2		;[8960] A valid CID?
	      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:	TMNN HSHCNT,(T1)	;[8960] Unclaimed?
	IFSKP.			;[8960] 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:	SKIPE RTYFLG		;[8960] Want to retry?
	IFSKP.			;[8960] 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
	SKIPE RTYFLG		;[8960] Shall we try, try again?
	IFSKP.			;[8960] 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
	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.
	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:	SKIPN T3,HSHNBT(T1)	;[8960] Anything here?
	IFSKP.			;[8960] If so
	  SKIPE AC3		;[8960] User want to leave a record of this?
	  IFSKP.		;[8960] Yes
	    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		;(T1,T2/T3)
	  IFSKP.		;[8960] If it worked
	    LOOP.		;[8960] Loop for the next one
	  ENDIF.		;[8960] Otherwise it failed
	  PIOFF
	  CALL CFSWDN		;Return the buffer
	  PION
	  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
;Here to restart voting

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.
	  SKIPN T1,DLYLOK	;[8960] A delay in effect?
	  IFSKP.		;[8960] 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
	SKIPE P3,CFSHCT		;[8960] Get host count of other hosts
	IFSKP.			;[8960] If nobody out there...
	  MOVE P,CFSSVP		;Restore original stack
	  CFSLOK		;Lock up the data base
	  OKSKED		;Turn on scheduling
	  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:	TMNN HSHYES,(Q1)	;[8960] Already vetoed?
	IFSKP.			;[8960] Yes
	  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
	TMNN HSVUC,(Q1)		;[8960] Vote to include HSHCOD?
	IFSKP.			;[8960] 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
	  TMNN HSHYES,(Q1)	;[8960] Someone veto the request?
	  IFSKP.		;[8960] 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

	TMNE HSHDLY,(Q1)	;[8960] 
	IFSKP.			;[8960] 
	  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)
	TMNE HSHVRS,(Q1)	;[8960] Restart or success?
	IFSKP.			;[8960] 
	  CFSLOK
	  ECSKED
	  RET
	ENDIF.
	NOSKED
	ECSKED
	JRST VOTRST		;DO IT AGAIN
;Scheduler 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		;[7.1072] 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
	SKIPE T1,VOTQ		;[8960] Get one
	IFSKP.			;[8960] If none there
	  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
	SKIPN SCAFL1		;[8960] Is KLIPA off-line?
	IFSKP.			;[8960] If so
	  SETZ T1,0		;either path
	  CALL CIONLT		;is it sound yet?
	  IFSKP.		;[8960] If yes
	    CALL PRTONL		;[8960] Set dual-port access
	  ELSE.			;[8960] If not
	    MOVX T1,^D1000	;[8960] Come back in a sec
	    MOVEM T1,CFSTIM	;[8960] To check it again
	  ENDIF.		;[8960] 
	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,<

CFSINT::CAILE T1,CFMSFX		;[7.1190] 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
	AOS CFSRCV		;[7211] ADD TO TOTAL RECEIVED
	MOVEM T3,.MHSCI(T1)	;STASH IT
	MOVEM T4,.MHDCI(T1)	;Save buffer return address
   IFN CLEQIN,<			;[7.1072] If cluster ENQ code present
	LOAD T2,CFCOD,(T1)	;[7.1072] Get opcode
	CAIE T2,.CFENQ		;[7.1072] Is this an ENQ packet?
	IFSKP.			;[7.1072] Yes so bypass CFS lock
	  CALL SCMSG		;[7.1072] (T1/) Process message and requeue buffer
	   NOP			;[7.1072] Never returns here!
	  RET			;[7.1072] Done
	ENDIF.			;[7.1072]
   >				;[7.1072]
	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
   IFE CLEQIN,< IFIW!CFCEAS]-1(T2);[7.1072] Shutdown
   >				;[7.1072] 
   IFN CLEQIN,< IFIW!CFCEAS	;[7.1072] Shutdown
		XADDR. (EQMSG)]-1(T2)  ;[7.1072] ENQ message
   >				;[7.1072]
	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
	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.

	TMNN CFVUC,(Q1)		;[8960] Vote to include HSHCOD?
	IFSKP.			;[8960] 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.			;[8960] Failed
	  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
	TMNN CFODA,(Q1)		;[8960] Providing optional data?
	IFSKP.			;[8960] 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.
	    SKIPN T2,HSHCDA(T1)	;[8960] Want to be notified?
	    IFSKP.		;[8960] 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
	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.

Action:	If this becomes persistent, find out why there is no freespace
	available.  Run SYSDPY and use the RE display to see if the general
	pool is being used.  If there is no one particular freespace hog,
	consider building your monitor with an increase in the freespace
	general pool.  If this problem is reproducible, set this BUGINF
	dumpable and submit an SPR along with the dump and instructions on
	reproducing the problem.
>,,<DB%NND>)			;[7.1210]
	  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

;[8863]
;Milestone - These values were increased because of ILMNRFs. The
;more structures you have served, the higher potential exists for
;ILMNRFs when this routine scribbles on the stack.

	SLEN==^D20		;[8863] Words to hold structure names
	HLEN==^D30		;[8863] 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
	MOVE T2,CFSHST(Q1)	;[7.1021] Get the listener type
	CAME T2,[-2]		;[7.1021] Is this a dump listener?
	IFSKP.			;[7.1021] Yes
	  AOS CLDWRD		;[7.1021] Enable cluster dump facility
	  RET			;[7.1021] Done, we will be crashing soon
	ENDIF.			;[7.1021]
	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
	CAMLE T1,MYPORT		;[8960] Higher priority than I?
	IFSKP.			;[8960] 
	  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 to accept a connection failed.  This indicates a
	possible problem with SCAMPI.

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.
	This BUGHLT only occurs in a cluster and on the system
	with the lowest CPU serial number. It happens when a system joins the
	cluster and that system has been away longer than the CFS vote delay
	period.  This time period is calculated to be
	(DLYTIM*maximum_CI_node_seen)+NDSTTM.  Currenty this is 5 seconds per
	CI node plus 10 seconds grace period.

Action:	This BUGHLT usually occurs when a system has been hung for a long
	period of time on the CI or if someone has stopped and continued a
	halted system in the cluster (using EDDT breakpoints or other methods).
	If this problem is persistent, there is a good chance that one of the
	systems in the cluster is having CI problems.  Another step which could
	be taken would be to increase the value in DLYTIM and see if this
	provides enough time for the cluster to stablize.

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
	AOS T3,CFSHCM		;[8960] One more full voter on-line
	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 CLEQIN,<			;[7.1072] If ENQ code present
	LOAD CX,CFCOD,(T3)	;[7.1072] Get opcode
	CAIE CX,.CFENQ		;[7.1072] Is this an ENQ packet?
	IFSKP.			;[7.1072] Yes
	  SKIPN -C%BINV(T3)	;[7.1072] Is this the VRB?
	  IFSKP.		;[7.1072] No, this is a vote buffer
	    MOVE T1,T3		;[7.1072] Position buffer address for call
	    CALL @-C%BINV(T1)	;[7.1072] (T1/)Return the buffer to SCA
	  ENDIF.		;[7.1072]
	  RET			;[7.1072] Done
	ENDIF.			;[7.1072]
   >				;[7.1072]
   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.  The guard word did
	not contatin 252525.
>)
   >	;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?
	AOS T3,CFSHCM		;[8960] Full, one more full voter
	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
	SKIPN CFSSMQ(T2)	;[8960] A queue?
	IFSKP.			;[8960] If so
	  CALL SENDQ		;Queue it up
	  PION
	  RETSKP		;And done
	ENDIF.
	AOS CFSENT(T2)		;Sent one
	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.		;[8960] If failure
	    CAIE T1,SCSNEC	;[8960] Not enough credit?
	    IFSKP.		;[8960] If so...
	      MOVE T1,SCBUFF	;YES.
	      MOVE T2,SCHOST	;RESTORE ARGS
	      PIOFF		;[8960] Turn off PI system
	      TMNN STCRA,(T2)	;[8960] Credit arrive while we weren't looking?
	      IFSKP.		;[8960] If so
	        PION		;[8960] Turn PI back on
	        LOOP.		;[8960]  and call SC.SMG again
	      ENDIF.		;[8960]
	      CALL SENDQ	;Queue it up
	      PION		;[8960] Turn PI back on and continue
	    ELSE.		;[8960] Not little credit left, error
	      MOVE T3,SCBUFF	;Return buffer address in T3
	      RETBAD()		;Didn't send it
	    ENDIF.
	  ENDIF.		;[8960] End of SMG failure code
	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 dump listener -- CFDLSN (Declare CFS dump listener)

;[7.1021] CFDLSN - Declare a cluster dump listener.
;
;This  listener  will  set  CLDWRD  to  non-zero when it receives a connect
;request from a remote node. Then, when this remote  node  crashes,  PHYKLP
;will  notice that a cluster dump is in progress, and issue a KLPDMP BUGHLT
;(instead of the usual KLPCVC BUGINF).
;
;  Accepts no arguments
;
;  CALL CFDLSN
;
;Returns:
;	+1 Failure, with:
;	   T1=0 if no more host slots
;	   T1<>0 if some SCA error
;	+2 Success
;
;Called at startup only from CFSJYN.

CFDLSN::SAVEQ
	PIOFF			;Prevent host table interruptions
	MOVSI T1,-HSTSIZ	;Size of host table
;Loop thorugh each host in the host table and listen for the request to dump.

	DO.			;Loop to find free slot
	SKIPE CFSHST(T1)	;Found one?
	IFSKP.			;If so
	  SETOM CFSHST(T1)	;Mark we are listening on this port
	  SOS CFSHST(T1)	;And indicate that this is a dump listener
	  SETZM CFHSTS(T1)	;Init status
	  PION
	  HRRZ Q1,T1		;Get index
	  BLCAL. (SC.LIS,<<.,LISDMP>,<.,LISDMP>,[-1],<.,CFSINT>,Q1,[0],[0]>) ;[7.1190]
	  IFNSK.
	    SETZM CFSHST(Q1)	;An error. No longer listening
	    BUG.(INF,CFDLSF,CFSSRV,SOFT,<CFSSRV - Failed to get dump listener>,<<T1,ERR>>,<

Cause:	The call to SC.LIS to set up the dump listener failed.  This system
	does not participate in any cluster dump.

Action:	If this problem is reproducible, set this BUGINF dumpable and submit an
	SPR along with the dump and instructions on reproducing the problem.

Data:	ERR - Error code returned by SC.LIS
>)
	    RET			;Return failure
	  ENDIF.
	  MOVEM T1,CFSHNM(Q1)	;Put CID here for now
	  RETSKP		;Return success
	ENDIF.
	AOBJN T1,TOP.		;Try the next slot
	PION			;Turn on interrupts again
	ENDDO.			;End of loop on CFSHST
	CALLRET RETZ		;No free table entries, fail
	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],<.,CFSINT>,Q1,[SCRDIT],[RCRDIT]>) ;[7.1190]
	 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 in CFSLSN.  This indicates a possible problem
	with SCAMPI.

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
	    CAME T2,P4		;[8960] Is it what we want?
	    IFSKP.		;[8960] 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.
	  SKIPL T3,0(T2)	;[8960] Delay?
	  IFSKP.		;[8960] 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.

Action:	If this problem is reproducible, set this BUGINF dumpable and submit an
	SPR along with the dump and instructions on reproducing the problem.
>)
	 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.
>)
	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.
	TMNN <HSHTWF,HSHWVT,HSHUGD>,(T1) ;[8960] Anybody else doing this?
	IFSKP.			;[8960] 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
	CAML T2,Q3		;[8960] Is it all set for us?
	IFSKP.			;[8960] 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.
	SKIPN T3,HSHOP1(T1)	;[8960] Anything in here?
	IFSKP.			;[8960] 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.			;Error
	  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.			;If error
	  SETZM T1
	  MOVEI T2,10		;Just do some space
	  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
	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.  The caller in the dump should be
	examined 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
	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
	SKIPLE HSHPST(T1)	;[8960][7247] This one in use and good?
	IFSKP.			;[8960] 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:	TMNN <HSHTWF,HSHUGD,HSHWVT>,(P5) ;[8960] Waiting for it somewhere else?
	IFSKP.			;[8960] If any of the above
	  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
	TMNN STEXL,(T1)		;[8960] Is this exclusive?
	IFSKP.			;[8960] If so
	 MOVEI T3,.HTOEX	;Upgrade it now to the maximum
	 STOR T3,HSHTYP,(P5)	;And store it
	ENDIF.
	CAIE T3,.HTOEX		;[8960] Do we hold exclusive rights?
	IFSKP.			;[8960] 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.
	 TMNN HSHODA,(P5)	;[8960] Any optional data?
	 IFSKP.			;[8960] 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
	SKIPN T2,HSHWTM(P5)	;[8960] gave us a time to wait?
	IFSKP.			;[8960] If so
	  CAIGE T2,^D20		;Wait at least this long
	  MOVEI T2,^D20		;""
	  JRST CFSUGT		;[8960] Enter below
	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
CFSUGT:	ADD T2,TODCLK		;[8960] Wait time
	MOVEM T2,HSHTIM(P5)
	MOVE T2,P5		;Block address
	CALL CFSWUP		;Do the wait
	CFSLOK			;Lock 'er up
	SKIPE WTFLAG		;[8960] Did we set the wait flag?
	IFSKP.			;[8960] If so
	  SETZRO HSHTWF,(P5)
	ENDIF.
	SKIPG HSHPST(P5)	;[8960][7247] Has it been released or uncached?
	IFSKP.			;[8960] 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
	SOJE T1,CFSUGL		;[8960] Decrement lock value, are we the last?
	STOR T1,HSHLKF,(P5)	;We are not the last, replace new count
	JRST CFSFAL		;Unlock and return
;[8960] Here when we are the last (HSKLKF=1)

CFSUGL:	MOVE T1,HSHCOD(P5)	;[8960] Get the OFN
	ADD T1,CFSOFN		;Point to OFN table entry
	SETZM 0(T1)		;Clear it

;[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
	  SETONE <HSHTAM,HSHKPH>,(P5) ;[7.1029][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
	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
	TMNN HSHODA,(P5)	;[8960] Any optional data?
	IFSKP.			;[8960] 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

RTYPE:	JE <HSHKPH>,(P5),NOKEEP	;[7.1029] 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

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.  The dump should reveal how the keep bit got
	cleared or who cleared it.
>)				;[7.1029] 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

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
	    SETONE <HSHTAM,HSHKPH>,(T1)	;[7.1029][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

   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
	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
	TMNN SPTFR,(T2)		;[8960] Someone waiting for us?
	IFSKP.			;[8960] 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
	TMNN HSHLKF,(T1)	;[8960] Now interlocked?
	IFSKP.			;[8960] If so
	  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
	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
	  SETONE <HSHTAM,HSHKPH>,(T1) ;[7.1029][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
	 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] 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.  To diagnose the problem, attempt to locate the token in
	question and find out where it is (probably on the free list).  It 
	is not easy to determine how the token got there.
>)				;[7247] Not found - error!!
	TMNN HSHLKF,(T1)	;[8960][7247] Now interlocked?
	IFSKP.			;[8960][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
	STKVAR <COFN>		;[9038] Temp storage
	MOVEM T1,COFN		;[9038] Hang onto this
	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
	MOVE T3,CFSOFN		;[9038] Get CFS resource block table
	ADD T3,COFN		;[9038] Find place where CFS resource block is
	MOVE T3,(T3)		;[9038] Get CFS resource block
	LOAD T4,HSHTYP,(T3)	;[9038] Get access type
	CAIE T4,.HTOEX		;[9038] Do we own it exclusively?

;If we were to broadcast the update, then other systems in the cluster
;might have crashed with CFSOFB BUGHLTs. This prevents that from happening.

	BUG.(HLT,CFTYAM,CFSSRV,SOFT,<CFSSRV - Type of Access Mismatch>,,<

Cause:	The local system was going to broadcast to all other systems that
	it was about to update an OFN. However, it was found that the local
	system does not have exclusive access to the OFN. If an OFN has been
	changed in anyway, it should have acquired the write token and this
	should theoretically never happen.
>)				;[9038] We have the wrong access, crash

;Now send message to each node that is up

	BLCAL. (CFSBRD,<T1,T2,[.CFBOW],[0]>) ;Do the braodcast
	RET			;And done

	ENDSV.			;[9038]
	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.  This was probably caused by a bad
	monitor build.
>)
   >	;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
	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)
	TMNE SPTSR,(Q2)		;[8960] Exclusive?
	IFSKP.			;[8960] If not
	  DMOVE T1,[EXP .HTOAD,.SPSRD] ;Share it
	ELSE.
	  SETZB T1,T2
	ENDIF.
	STOR T1,HSHTYP,(Q1)	;new type
	STOR T2,SPTST,(Q2)	;New OFN access
	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>
	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
	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.
CFSSM1:	TLNN Q1,-1		;[7464] See if need to swap DSN
	MOVSS Q1		;We do
	CALL CFMDSN		;Now register the DSN
	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
	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
;[7.1012] If T1 is nonzero this means there is already a DSN token. It is
;[7.1012] likely a duplicate DSN.  Note that HSHCNT was incremented by CFSGET.
;[7.1012] This will be fixed by CFSSDI later.

	IFN. T1			;[7.1075][7.1012] Need the block?
	  MOVE Q1,T1		;[7.1012] Save address of unneeded block
	  DMOVE T1,HSHROT(T1)	;[7.1012] Get hash values
	  CALL HSHLOK		;[7.1012](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.  Examination of the dump should 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.
>)				;[7.1012] Not found. wrong!
	  MOVE T2,HSHCOD(Q1)	;[7.1012] Get alias name
	  CAMN T2,HSHCOD(T1)	;[7.1012] Same as one for DSN token?
	  IFSKP.		;[7.1012] No
	    MOVE T1,HSHQAL(Q1)	;[7.1012] Get the high order DSN
	    HLRZ T2,HSHROT(Q1)	;[7.1012] Get the low order DSN
	    MOVE T3,HSHCOD(Q1)	;[7.1012] 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
>)				;[7.1012]
	    MOVE T1,Q1		;[7.1012] Get block address back in T1
	    CALL @HSHRET(T1)	;[7.1012](T1/) Return the block
	    MOVEI T2,.CDVUC	;[7.1012] Fail due to mismatched alias names
	    RET			;[7.1012] Return failure
	  ENDIF.		;[7.1012]
	CALL @HSHRET(T1)	;[7.1012](T1/) Don't need this block
	ENDIF.			;[7.1012]
   >	;IFN CFSSCA
	RETSKP			;And done
	SUBTTL	Structure resource manager -- CFSSMI (Acquire structure resource)
;[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
	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
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?
	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.
       	  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
	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

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

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
	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
	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
CFSSD1: CALL HSHLOK		;[7464] (T1,T2/T1,T2)Look it up
	 SKIPA
	CALL CFSRMV		;And remove it
	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] 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
	IFSKP.			;[7.1012] If we found it
	  DECR HSHCNT,(T1)	;[7.1012] Decrement hash count
	  OPSTR <SKIPG>,HSHCNT,(T1) ;[7.1012] Still shared?
	  CALL CFSRMV		;[7.1012](T1/) No, remove it
	ENDIF.			;[7.1012]
	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.

	There is one known scenario for this BUGHLT.  If the CFS joining
	process did not complete properly, then this system may have acquired
	some of the resources exclusively when they were also held on other
	nodes.  By the time STRVVT is called to verify the structure access,
	all the CFS connections have completed.  So, now that all the other 
	cluster systems are voted with, the verification of exclusive access 
	has failed.

Action:	Insure that there is no naming conflict or drive serial number conflict
	with the structures.  Insure that the BS: and PS: are not mounted
	exclusively by any other system in the cluster.  If the structures all
	appear to be in order, submit an SPR with the dump and a copy of
	MONITR.EXE.
>)
	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 version 6.1 CFS  nodes  from
;using ENQ on the same file!
;
;As  of  version  7.0,  this routine creates the ENQ token with shared
;access for 7.0 ENQ implementations and with exclusive access for  6.1
;ENQ implementations.
;
;  T1/ OFN
;
;       CALL CFSENQ             ;(T1/)
;
;Returns +1: Failed, another node has the token
;        +2: Success

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

   IFNDEF CFSDUM,<
CFSENQ::SAVEQ
	STKVAR <OFNENQ>		;[7348]
	MOVEM T1,OFNENQ		;[7348] Save the OFN
	LOAD Q3,STRX,(T1)
	CALL ENQSET		;Set up args
	 JRST RSKP		;Local. All set
	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
   IFN CLEQIN,<			;[7.1072] If cluster ENQ code present
	MOVE T3,ENQWRD		;[7.1072] Get ENQ word for process
	TXNE T3,EQ%ENA		;[7.1072] Did process enable cluster wide ENQ?
	MOVEI T2,.HTOAD		;[7.1072] Yes, so access is shared
   >				;[7.1072]
	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
	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.  To diagnose this problem, 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

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.  To diagnose this
	problem, 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
	ENDSV.			;[7315]
   >	;IFNDEF CFSDUM
 	SUBTTL	ENQ Lock resource manager -- CFEQLK (Lock ENQ database)

   IFN CLEQIN,<			;[7.1072] Assemble only if cluster ENQ desired

;[7.1072] CFEQLK - Lock the ENQ database
;Routine to obtain the ENQ Database Lock Token. This routine is called
;from  ENQ.MAC  to  lock  the ENQ database. Since this is an exclusive
;token, this implies that there is only one ENQ  activity  ongoing  in
;the cluster at a time.  The process is CRSKED while the Lock is held.
;
;Must be called NOINT.
;
;       CALL CFEQLK             ;()
;
;Returns +1: Always when the ENQ Database Lock is obtained.
;	     Process is CSKED upon return.
;
;	     Preserves ACs T1 - T4.

CFEQLK::SAVET			;Preseve the temps
	CSKED			;Be CSKED while lock is owned
	CFSLOK			;Prevent CFS interruptions
	MOVX T1,EQLROT		;Get root
	MOVX T2,EQLQAL		;Get qualifier
	CALL HSHLOK		;(T1,T2/T1,T2) See if we have it
	 JRST CFEQL1		;No so we need to vote for it
	JN <HSHWVT,HSHCNT>,(T1),CFEQL1 ;If in use or voting already, do vote
	INCR HSHCNT,(T1)	;Its on the system but not in use - get it
	MOVE T3,FORKX
	STOR T3,HSHFRK,(T1)	;Store new owner
	MOVE T3,TODCLK		;Get now
	MOVEM T3,HSHTIM(T1)	;Store in resource block
	CALLRET CFSFAL		;Succeed but don't update fairness timer

;Here if we need to vote for the Lock

CFEQL1:	CFSULK			;Unlock CFS database while voting
	DO.
	  CALL CFSSPC		;(/T1) Get a short request block
	  IFNSK.		;If failed
	    CALL SBLOCK		;() Release some and wait awhile
	    LOOP.		;Try again
	  ENDIF.
	ENDDO.
;Fill in the request block and ask for the resource

	MOVX T2,EQLROT		;Get root
	MOVEM T2,HSHROT(T1)	;Store in resource block
	MOVX T2,EQLQAL		;Get qualifier
	MOVEM T2,HSHQAL(T1)	;Store in resource block
	MOVEI T2,.HTOEX		;This resource is always exclusive
	STOR T2,HSHTYP,(T1)	;Store in resource block
	SETZM HSHCOD(T1)	;No unique code required
	MOVE T3,TODCLK		;Get the time
	ADDI T3,EQFTIM		;Add fairness value to it
	MOVEM T3,HSHFCT(T1)	;Stash it as the minimum hold time
	CALL CFSGET		;(T1,T2/T1,T2) Get the resource
	 CALL ILLGET		;This retries till successful so crash if failed
	SKIPE T1		;We now have the lock!  Did our block get used?
	CALL @HSHRET(T1)	;No, so return it
	RET			;Return successful
	SUBTTL	ENQ Lock resource manager -- CFEQUL (Unlock ENQ database)

;[7.1072] CFEQUL - Unlock the ENQ database
;Routine  to  release  the  ENQ  Database  Lock Token. This routine is
;called from ENQ.MAC to unlock the ENQ database.
;
;Always called NOINT and CSKED.
;
;       CALL CFEQUL             ;()
;
;Returns +1: Always with the database lock unlocked.
;	     An ECSKED is done to undo the CSKED done in CFEQLK.
;
;	     Preserves ACs T1 - T4.

CFEQUL::SAVET			;Preserve the temps
	MOVX T1,EQLROT		;Get root
	MOVX T2,EQLQAL		;Get qualifier
	CALL CFSNDO		;(T1,T2/) Release the Lock
	IFNSK.			;If can't then it wasn't locked!
	  BUG.(CHK,ENQLNL,CFSSRV,SOFT,<CFSSRV - ENQ Database Lock not locked>,,<

Cause:	CFEQUL was called to unlock the ENQ Database Lock, but the Lock
        was found not to be locked.

Action:	If this problem is reproducible, set this BUGCHK dumpable and submit an
	SPR along with the dump and instructions on reproducing the problem.
>)
	  RET			;Issue warning and quit
	ENDIF.
	ECSKED			;Undo CSKED done when lock was acquired
	RET			;Return success

   >				;[7.1072] End of IFN CLEQIN
	SUBTTL	MTA Lock resource manager -- CFSMTA (Acquire MTA resource)

;[9122] This routine is called by ASND% and OPENF% to insure that only one
;system is using a shared tape drive.
;
;Called with T1/ index into device tables
;Returns +1 if access is not allowed
;Returns +2 if access is allowed

CFSMTA::SAVET			;[9122] Save some temps
	HRRZ T2,DEVDSP(T1)	;[9122] Get the address of device dispatch
	CAIE T2,MTADTB		;[9122] Is this a MTA: (and not a MT:) device?
	RETSKP			;[9122] Nope, return OK

;[9122] Insure that the MTA device is not currently assigned.

	HLRZ T2,DEVUNT(T1)	;[9122] Get owning job number or -1 if unass
	CAMN T2,JOBNO		;[9122] This job has it assigned already?
	RETSKP			;[9122] Yes, allow access always
	CAIE T2,-1		;[9122] Is it unassigned now?
	BUG.(CHK,CFSMTU,CFSSRV,SOFT,<CFSSRV - CFSMTA called for assigned device>,,<

Cause:	CFSMTA was called to acquire the MTA access token for a MTA device,
	but the MTA device was already assigned to a different job.  This check
	should have been done by the calling code.

Action:	If this problem is reproducible, set this BUGCHK dumpable and submit an
	SPR along with the dump and instructions on reproducing the problem.
>,RSKP)				;[9122] Skip return to allow even if problem
;[9122] We have a legal device for assignment, get the root and qualifier.

	CALL CFSMTS		;[9122] (T1/T1,T2) Get root and qual set up
	 RETSKP			;[9122] Allow access if no MTA UDB or serial no

	SAVEQ			;[9122] Get some work regs
	DMOVE Q1,T1		;[9122] Save the root and qualifier for later

;[9122] We now have the root and qualifier and we are dealing with a MTA
;assignment.  Try to find the resource block on this system for this MTA drive.

	CFSLOK			;[9122] Prevent CFS interruptions
	CALL HSHLOK		;[9122] (T1,T2/T1,T2) See if we have MTA token
	IFSKP.			;[9122] We have it!
	  LOAD T3,HSHCNT,(T1)	;[9122] Load the count of locks on this
	  SKIPE T3		;[9122] Share count must be zero now
	  BUG.(CHK,CFSMTF,CFSSRV,SOFT,<CFSSRV - MTA resource lock fouled>,,<

Cause:	CFSMTA was called to acquire the MTA access token for a MTA device,
	but the share count for the token was not zero.  This indicates that
	CFSMTA has been called twice for the same MTA access token.

Action:	If this problem is reproducible, set this BUGCHK dumpable and submit an
	SPR along with the dump and instructions on reproducing the problem.
>,CFSRSK)			;[9122] Something is fouled up, skip return
	  INCR HSHCNT,(T1)	;[9122] Indicate we are now using it
	  MOVE T3,FORKX		;[9122] Get our fork number
	  STOR T3,HSHFRK,(T1)	;[9122] Store it in the hash block
	  MOVE T3,TODCLK	;[9122] Get the uptime
	  MOVEM T3,HSHTIM(T1)	;[9122]  and store it in the block
	  JRST CFSRSK		;[9122] Unlock CFS and skip return
	ENDIF.			;[9122] Otherwise we need to vote
	CFSULK			;[9122] Unlock CFS database
;[9122] We need to vote for the MTA token.  First get a block for voting.

	DO.			;[9122] Look to get space
	  CALL CFSSPC		;[9122] (/T1) Get a short request block
	  IFNSK.		;[9122] If failed to get one
	    CALL SBLOCK		;[9122] (/) Wait awhile
	    LOOP.		;[9122] Try again
	  ENDIF.		;[9122] Fall out when
	OD.			;[9122]  we have the block

;[9122] Fill in the request block, Q1 has root, Q2 has qualifier.

	DMOVEM Q1,HSHROT(T1)	;[9122] Save the root and qualifier
	MOVEI T2,.HTOEX		;[9122] Load exclusive type
	STOR T2,HSHTYP,(T1)	;[9122] This token is exclusive
	SETZM HSHFCT(T1)	;[9122] No hold time required
	SETZM HSHCOD(T1)	;[9122] No unique code required

;[9122] Now ask for the resource, skip return if we get it.

	SETZ T2,		;[9122] No retry on this vote
	CALL CFSGET		;[9122] (T1,T2/T1,T2) Get the resource
	 RET			;[9122] Access not allowed to the device
	SKIPE T1		;[9122] Did our block get used?
	CALL @HSHRET(T1)	;[9122] No, so return it now
	RETSKP			;[9122] We now own it, allow access 
	SUBTTL	MTA Lock resource manager -- CFSMTR (Release MTA resource)

;[9122] This routine is called by RELD% and CLOSF% to give up the MTA access
;token when a MTA drive is no longer in use.  
;
;Called with T1/ index into device tables
;Returns +1 always, with token released

CFSMTR::SAVET			;[9122] Save some temps
	HRRZ T2,DEVDSP(T1)	;[9122] Get the address of device dispatch
	CAIE T2,MTADTB		;[9122] Is this a MTA: (and not a MT:) device?
	RET			;[9122] Nope, return OK

;[9122] Set up root and qualifier for this, and release the resource.

	CALL CFSMTS		;[9122] (T1/T1,T2) Set up root and qualifier
	 RET			;[9122] No UDB or no serial number

	CALL CFSNDO		;[9122] (T1,T2/) Release the resource
	 BUG.(CHK,CFSMTO,CFSSRV,SOFT,<CFSSRV - MTA resource not owned at release>,,<

Cause:	CFSMTR was called to release the MTA access token for a MTA device,
	but the resource was not locked.  This indicates a problem in getting
	the resource at the time that the MTA device was assigned to the job.

Action:	If this problem is reproducible, set this BUGCHK dumpable and submit an
	SPR along with the dump and instructions on reproducing the problem.
>)				;[9122] Something is fouled up somewhere 
	RET			;[9122] Return
	SUBTTL	MTA Lock resource manager -- CFSMTS (Get MTA root and qualifier)

;[9122] Utility routine to set up root and qualifier for CFA MTA resource
;The root is ".MTTxx,,'MTA'" and the qualifier is the device serial number.
;
;Call with T1/ index to device tables
;Returns +1 if no serial number for device or device doesn't exist
;Returns +2 with T1/ root and T2/ qualifier

CFSMTS:	HRRZ T3,DEVUNT(T1)	;[9122] Get MTA unit number
	HRRZ T3,MTCUTB(T3)	;[9122] Load the address of the MTA UDB
	JUMPE T3,R		;[9122] Return +1 if there is no UDB
	LOAD T2,USTYP,(T3)	;[9122] Get unit type 
	HRLZ T1,T2		;[9122] Get unit type,,0
	HRRI T1,'MTA'		;[9122] Finish up the root word
	HRRZ T2,UDBDSN(T3)	;[9122] Now load the drive serial number
	JUMPN T2,RSKP		;[9122] Return +2 with root and qual set up
	RET			;[9122] Return +1 if no serial number
	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
	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
	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"
	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 database is wrong, or PHYSIO's
	database is wrong.
>)
	MOVEM T2,HSHLNK(T1)	;Enqueue it
	MOVEM T1,HSHBKP(T2)	;And point backwards as well
	SETZM HSHLNK(T2)	;Clear our link
	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.
	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
	SUBTTL	Miscellaneous Interfaces -- CFSDMP (Force cluster dump)

;[7.1021] CFSDMP - Force a cluster dump
;
;This  routine  can  be  called  anytime a cluster dump is desired. It will
;attempt to connect to the cluster dump  listener  of  every  TOPS-20  node
;which  is  answering  REQUEST-IDs on the CI. If a connection is made, then
;word CLDWRD will be set non-zero on that node. Once we have completed  our
;attempts  at  connecting to all the cluster dump listeners, this node will
;crash with a CFCLDP BUGHLT. When the other nodes see this  node  go  down,
;then they will also crash with a KLPDMP BUGHLT.
;
;Note  that  this has been designed so that a "DEP TEN 67=1;QUIT" issued at
;the PARser will perform a cluster dump. Or, a "DEP TEN 66=1;QUIT"  command
;can be given at each system, and then a "Jump 71" can be issued (this will
;result in a KPALVH on one system, and a KLPDMP on the others). This second
;method  should  be  used  if  there is any doubt about the ability of this
;system to make connections to the remote cluster dump listeners.
;
;  Accepts no arguments
;
;  CALL CFSDMP
;    - or -
;  PAR> DEP TEN 67=1;QUIT
;
;Never returns.  Always issues a CFCLDP BUGHLT.

CFSDMP::MOVEM P,DMPSVP		;Save incoming stack
	MOVE P,DMPSTK		;Get local dump stack
	XJRST [MSEC1,,.+1]	;[7.1033] Enter section 1
	PIOFF			;Own the system for awhile
	SAVEQ			;Save some work registers
	MOVSI Q1,-C%SBLL	;Loop for all the nodes
	DO.
	  XCT KEPALV		;Update keep alive counter
	  HRRZ T1,Q1		;Get the current node
	  CAMN T1,MYPOR4	;Is this our node?
	  JRST CFSDM1		;Yes, skip it
	  CALL PTHSTS		;(T1/T1,T2) What is path status to node
	   EXIT.		;Our port is not running - quit
	  TXNN T2,UDB%WA+UDB%WB ;No-response on both wires?
	  JRST CFSDM1		;Yes, skip it
	  TXNE T2,UDB%MA	;No, is node in maintenance mode?
	  JRST CFSDM1		;Yes, skip it
	  SKIPN SBLIST(Q1)	;No, have we created a system block yet?
	  JRST CFSDM1		;No, skip it
	  HRRZ T2,Q1		;Get the node number again
	  CALL ISIT20		;(T2/) Is this a TOPS-20 system?
	   JRST CFSDM1		;No, skip it
;Here if we found a node that needs to have a dump taken

	  HRRZ T1,Q1		;Get node number
	  MOVEM T1,Q2		;Save it in case error occurs
	  CSKED			;Make us more important
	  PION			;Turn on interrupts again
	  BLCAL. (SC.CON,<<.,LISDMP>,<.,LISDMP>,T1,[0],[0],<.,CFSINT>,T1,[0],[0],[0]>) ;[7.1190] Do connect
           BUG.(INF,CFCDCF,CFSSRV,SOFT,<CFSSRV - Cluster dump connect attempt failed>,<<Q2,NODE>,<T1,ERR>>,<

Cause:	An attempt to connect to the cluster dump listener on another node has
	failed.  Thus, when this node crashes, the remote node does not.  
	Chances are, this BUGINF does not appear on the CTY or in ERROR.SYS, 
	but it should be queued in the dump.

Action:	If this problem is reproducible, set this BUGCHK dumpable and submit an
	SPR along with the dump and instructions on reproducing the problem.

Data:	NODE - CI node number of remote system
	ERR - Error code returned by SC.CON
>,,<DB%NND>)			;[7.1210]
	  ECSKED		;Back to normal again
	  PIOFF			;Interrupts off again
CFSDM1:	  AOBJN Q1,TOP.		;Continue with next node
	ENDDO.			;All done - we have notified the cluster
	PION			;Allow interrupts again
        BUG.(HLT,CFCLDP,CFSSRV,SOFT,<CFSSRV - Forced cluster dump>,,<

Cause:	A call was made to CFSDMP to force a cluster dump.  The other systems
	in the cluster should have crashed with a KLPDMP BUGHLT.  This occurs
	when location 67 has a non-zero value or it the code actually calls
	into CFSDMP directly.

Action:	If the cluster dump was not performed legitimately, then it is possible
	that the monitor mistakenly trashed location 67 causing the cluster
	dump.  In this case, an SPR should be submitted along with the dump(s)
	from the systems and any insturctions on reproducing the problem.
>)
	SUBTTL	Miscellaneous Interfaces -- ILLGET (Illegal return from CFSGET)

;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.
>)
	SUBTTL	Miscellaneous Interfaces -- CFSKPD (KLIPA Failure)

;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.

Action:	Have field service check out the system's CI20.
>)

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.
>)
	SUBTTL	Miscellaneous Interfaces -- ONLINE (CFS connection BUGINF)

;Call ONLINE when this node is getting a connection from another node.

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 CI20.

Data:	NODE - Number of connecting node
	CID - Connect ID
	SERNUM - Serial number of remote node
>,,<DB%NND>)			;[7.1210]
   >	;IFN DEBUG
	CALLRET PYCON		;INFORM PHYSIO OF ONLINE
	SUBTTL	Miscellaneous Interfaces -- CFDISC (CFS disconnect BUGINF)

;Call OFLINE when a disconnect is read from a remote node on the CI.

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
	CI20.

Data:	NODE - Remote node number
	CID - Connect ID
	SERNUM - Serial number of remote node
>,,<DB%NND>)			;[7.1210]
	RET
   >	;IFN DEBUG
	SUBTTL	Miscellaneous Interfaces -- PHYNOL (Declare the disks offline)	

;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	End of CFSSRV

	TNXEND

	END