Google
 

Trailing-Edge - PDP-10 Archives - bb-m780d-sm - monitor-sources/pagutl.mac
There are 21 other files named pagutl.mac in the archive. Click here to see a list.
; UPD ID= 8709, RIP:<7.MONITOR>PAGUTL.MAC.17,   6-May-88 07:20:42 by LOMARTIRE
;TCO 7.1285 - Prevent OFJFBDs by stopping CHKLAC from clearing OFN2XB
; UPD ID= 8611, RIP:<7.MONITOR>PAGUTL.MAC.16,  11-Feb-88 17:24:52 by GSCOTT
;More of TCO 7.1005 - Somehow I got the TCO numbers wrong in the comments.
; UPD ID= 8574, RIP:<7.MONITOR>PAGUTL.MAC.15,  11-Feb-88 16:52:43 by GSCOTT
;TCO 7.1218 - Update copyright date.
; UPD ID= 8428, RIP:<7.MONITOR>PAGUTL.MAC.14,   4-Feb-88 13:44:32 by GSCOTT
;TCO 7.1210 - Set ILIBPT, NOOFN, SWPSTL, XBWERR normally not dumpable.
; UPD ID= 8330, RIP:<7.MONITOR>PAGUTL.MAC.13,  23-Dec-87 09:36:31 by SHREFFLER
;TCO 7.1167 - Make LCKXB1 global
; UPD ID= 206, RIP:<7.MONITOR>PAGUTL.MAC.12,  23-Oct-87 15:32:32 by GSCOTT
;TCO 7.1081 - Add UF%FSH flag for UPDPGS
; UPD ID= 147, RIP:<7.MONITOR>PAGUTL.MAC.11,  29-Sep-87 15:41:03 by SHREFFLER
;TCO 7.1067 - Make OC.UNC global so DSKREN can call it
; UPD ID= 144, RIP:<7.MONITOR>PAGUTL.MAC.10,  29-Sep-87 14:24:38 by RASPUZZI
;TCO 7.1066 - Fix mental retardedness in INVDIR.
; UPD ID= 142, RIP:<7.MONITOR>PAGUTL.MAC.9,  25-Sep-87 13:30:16 by RASPUZZI
;TCO 7.1065 - Prevent PLKRPQ BUGHLTs.
; UPD ID= 132, RIP:<7.MONITOR>PAGUTL.MAC.8,  23-Sep-87 15:46:00 by MCCOLLUM
;TCO 7.1063 - Call STROFL in DDOCFS to be sure structure is writeable
; UPD ID= 122, RIP:<7.MONITOR>PAGUTL.MAC.7,  22-Sep-87 16:49:36 by LOMARTIRE
;TCO 7.1062 - Make RELOFN return SPTH again in T2 - allows FILBATs to occur
; UPD ID= 111, RIP:<7.MONITOR>PAGUTL.MAC.6,  15-Sep-87 16:09:37 by RASPUZZI
;TCO 7.1055 - Help prevent CFCTNF/CFKBNS BUGHLTs by uncacheing all OFNs
;that refer to the resource block in ALOC2 before we release this block
;during directory destruction. This is done by adding new routine INVDIR.
; UPD ID= 68, RIP:<7.MONITOR>PAGUTL.MAC.5,  12-Aug-87 10:49:11 by LOMARTIRE
;TCO 7.1036 - Improve OFN lock tracer (SPTDSW)
; UPD ID= 14, RIP:<7.MONITOR>PAGUTL.MAC.4,   2-Jun-87 09:06:39 by GSCOTT
;TCO 7.1005 - Prevent CFZCNT BUGHLTs from DDOCFS
; UPD ID= 6, RIP:<7.MONITOR>PAGUTL.MAC.3,  28-May-87 16:09:06 by RASPUZZI
;TCO 7.1002 - Implement PMOVE/M instructions.
; *** Edit 7441 to PAGUTL.MAC by LOMARTIRE on 7-Apr-87, for SPR #21440
; Prevent DEAUNA BUGCHKs and multiply assigned disk pages 
; *** Edit 7400 to PAGUTL.MAC by LOMARTIRE on 20-Nov-86, for SPR #21385
; Prevent CSHSCF BUGHLTs 
; *** Edit 7387 to PAGUTL.MAC by LOMARTIRE on 27-Oct-86
; Fix bug in CHKOFN where it would return +2 when file was open on another node
; *** Edit 7356 to PAGUTL.MAC by MCCOLLUM on 20-Aug-86, for SPR #21231
; PLKMOD fixes - Re-cache OFN after GETCFS failure and add BUGHLTs. 
; *** Edit 7296 to PAGUTL.MAC by WAGNER on 21-May-86, for SPR #21175
; Fix code such that NPRIVP does not get incremented for Locked pages, only for
; private pages. 
; *** Edit 7294 to PAGUTL.MAC by LOMARTIRE on 19-May-86, for SPR #21062
; Prevent non-zero section file page updates for OF%DUD files in ASGOFW 
; *** Edit 7283 to PAGUTL.MAC by LOMARTIRE on 4-Apr-86, for SPR #21144
; Prevent OPNX9 errors from OF%RDU opens and bug in CHKLAC 
; *** Edit 7247 to PAGUTL.MAC by LOMARTIRE on 19-Feb-86
; Implement OFN caching 
; *** Edit 7215 to PAGUTL.MAC by GRANT on 20-Dec-85, for SPR #20966
; Insure that DDT gets the correct start address for the symbol table 
; *** Edit 7192 to PAGUTL.MAC by GRANT on 12-Nov-85
; In DDMPF, prevent cluster hangs by not turning off OFNCFS bit improperly 
; Edit 7129 to PAGUTL.MAC by GRANT on 13-Aug-85, for SPR #19397
; In SETPST, verify page number 
; UPD ID= 2300, SNARK:<6.1.MONITOR>PAGUTL.MAC.102,  19-Jul-85 16:40:57 by MOSER
;TCO 6.1.1492 - MORE JFNS NO SZCOD
; UPD ID= 2262, SNARK:<6.1.MONITOR>PAGUTL.MAC.101,  21-Jun-85 11:53:56 by MOSER
;TCO 6.1.1463 - ANOTHER CASE OF OFNBDB
; UPD ID= 2209, SNARK:<6.1.MONITOR>PAGUTL.MAC.100,  10-Jun-85 11:16:49 by LOMARTIRE
;TCO 6.1.1438 - Call LGTAD instead of doing GTAD% at BGCTYP
; UPD ID= 2144, SNARK:<6.1.MONITOR>PAGUTL.MAC.99,   5-Jun-85 10:26:25 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 2107, SNARK:<6.1.MONITOR>PAGUTL.MAC.98,   3-Jun-85 15:59:23 by LOMARTIRE
;TCO 6.1.1395 - Always return OPNX10 from BGCTYP
; UPD ID= 2025, SNARK:<6.1.MONITOR>PAGUTL.MAC.97,  28-May-85 15:50:37 by MOSER
;TCO 6.1.1399 - Fix CFS/long file race that causes OFNBDB
; UPD ID= 2021, SNARK:<6.1.MONITOR>PAGUTL.MAC.96,  28-May-85 12:11:14 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1909, SNARK:<6.1.MONITOR>PAGUTL.MAC.95,   6-May-85 11:25:17 by WAGNER
;TCO 6.1.1359 - Fix GETPST to check against NHIPG instead of MAXCOR
; UPD ID= 1906, SNARK:<6.1.MONITOR>PAGUTL.MAC.94,   4-May-85 20:50:28 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1851, SNARK:<6.1.MONITOR>PAGUTL.MAC.93,  30-Apr-85 14:04:55 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1792, SNARK:<6.1.MONITOR>PAGUTL.MAC.92,  23-Apr-85 13:07:28 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1774, SNARK:<6.1.MONITOR>PAGUTL.MAC.91,  22-Apr-85 12:01:06 by LOMARTIRE
;TCO 6.1.1328 - Remove TCO 6.1.1282
; UPD ID= 1738, SNARK:<6.1.MONITOR>PAGUTL.MAC.90,   9-Apr-85 11:35:46 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 1668, SNARK:<6.1.MONITOR>PAGUTL.MAC.89,  22-Mar-85 14:02:22 by LOMARTIRE
;TCO 6.1.1282 - Add CFUNLF to control checking of CFS pages during unlock
; UPD ID= 1547, SNARK:<6.1.MONITOR>PAGUTL.MAC.87,  20-Feb-85 15:16:10 by MOSER
;MORE 6.1.1166 - FIX A BUG WHEN SHARE COUNT 0 AND OFN IS FOUND
; UPD ID= 1443, SNARK:<6.1.MONITOR>PAGUTL.MAC.86,  31-Jan-85 16:17:46 by MOSER
;TCO 6.1.1166 - *PERFORMANCE* - OFN MANAGEMENT
; UPD ID= 1181, SNARK:<6.1.MONITOR>PAGUTL.MAC.85,  11-Dec-84 14:10:54 by LEACHE
;Change EHLJSB conditional to EXTJSB
; UPD ID= 1120, SNARK:<6.1.MONITOR>PAGUTL.MAC.84,  21-Nov-84 08:30:02 by HAUDEL
;TCO 6.1.1062 - Set the "keep" bit for code and data in extended sections.
; UPD ID= 946, SNARK:<6.1.MONITOR>PAGUTL.MAC.83,   4-Nov-84 15:30:14 by GLINDELL
;More TCO 6.1.1021 - ENCOD is now in XCDSEC in 6.1
; Also call pagrst when NRCOD has been mapped to clear temp mapping of CST's
; for EDDT.
; UPD ID= 5018, SNARK:<6.MONITOR>PAGUTL.MAC.82,  26-Oct-84 13:48:44 by LEACHE
;Add code (under EHLJSB conditional) for extended JSB
; UPD ID= 4975, SNARK:<6.MONITOR>PAGUTL.MAC.81,  22-Oct-84 16:31:44 by GRANT
;Remove references to FTCI
; UPD ID= 4938, SNARK:<6.MONITOR>PAGUTL.MAC.80,  15-Oct-84 13:10:07 by GRANT
;The assembly switch CFSCOD has been eliminated
; UPD ID= 4917, SNARK:<6.MONITOR>PAGUTL.MAC.79,  10-Oct-84 17:34:12 by GLINDELL
;TCO 6.1.1021 - 6.1 address space
;	Many changes to initialize XCDSEC, most within IFE FTNSPSRV
; UPD ID= 4820, SNARK:<6.MONITOR>PAGUTL.MAC.78,  17-Sep-84 10:15:44 by PURRETTA
;Update copyright notice
; UPD ID= 4730, SNARK:<6.MONITOR>PAGUTL.MAC.77,  22-Aug-84 14:47:23 by LOMARTIRE
;Add trapping code for use of OFN 0
; UPD ID= 4624, SNARK:<6.MONITOR>PAGUTL.MAC.76,  28-Jul-84 18:38:32 by GLINDELL
;More Tco 6.1127 - initialize section 37 in FPTABL
; UPD ID= 4439, SNARK:<6.MONITOR>PAGUTL.MAC.75,   5-Jul-84 16:44:59 by LEACHE
;TCO 6.2119; QAR 706089 - Don't put BOOT pages on special-memory queue
; UPD ID= 4267, SNARK:<6.MONITOR>PAGUTL.MAC.74,  30-May-84 21:19:08 by MOSER
;MORE 6.2057 - BUT NOT ALL
; UPD ID= 4216, SNARK:<6.MONITOR>PAGUTL.MAC.73,  14-May-84 14:20:42 by MOSER
;MORE 6.2057 - STILL MORE TO COME
; UPD ID= 4205, SNARK:<6.MONITOR>PAGUTL.MAC.72,   9-May-84 17:05:16 by MOSER
;TCO 6.2057 - WORK ON ASGOFN - FIRST PASS FIXES FOR DBMS
; UPD ID= 4071, SNARK:<6.MONITOR>PAGUTL.MAC.71,  11-Apr-84 19:19:21 by MOSER
;ADD MOUSETRAP FOR PAGLCK BUGS
; UPD ID= 4029, SNARK:<6.MONITOR>PAGUTL.MAC.70,  31-Mar-84 20:34:39 by GRANT
;Remove definitions for FTKLIPA
; UPD ID= 3995, SNARK:<6.MONITOR>PAGUTL.MAC.69,  28-Mar-84 14:20:28 by MOSER
;TCO 6.2000 - PREVENT SKDPF1 WHEN GARBAGE COLLECTING
; UPD ID= 3868, SNARK:<6.MONITOR>PAGUTL.MAC.68,   7-Mar-84 11:29:39 by LEACHE
;More TCO 6.1969 - move init of SWPMWF from MEXEC to DDTINI
; UPD ID= 3818, SNARK:<6.MONITOR>PAGUTL.MAC.67,  29-Feb-84 17:11:26 by MOSER
;TCO 6.1127 - MAKE PGRSKD BE A JACKET FOR ASGVAS
; UPD ID= 3813, SNARK:<6.MONITOR>PAGUTL.MAC.66,  29-Feb-84 16:47:31 by LEACHE
;TCO 6.1969 Load swapmon above 256K.
; UPD ID= 3696, SNARK:<6.MONITOR>PAGUTL.MAC.65,  15-Feb-84 21:08:33 by MURPHY
;Load ENCOD into physical memory above 256k.
; UPD ID= 3653, SNARK:<6.MONITOR>PAGUTL.MAC.64,   3-Feb-84 15:49:41 by MURPHY
;Fix SWPMBP.
; UPD ID= 3649, SNARK:<6.MONITOR>PAGUTL.MAC.63,   2-Feb-84 14:36:02 by MURPHY
;Ditto - fix bug.
; UPD ID= 3634, SNARK:<6.MONITOR>PAGUTL.MAC.62,   1-Feb-84 22:09:14 by MURPHY
;Put DDTs and bug stuff in symsec.
; UPD ID= 3628, SNARK:<6.MONITOR>PAGUTL.MAC.61,   1-Feb-84 20:26:10 by MOSER
;MORE 6.1963 - CAN'T USE Q3 IN PAGUTL
; UPD ID= 3624, SNARK:<6.MONITOR>PAGUTL.MAC.59,   1-Feb-84 17:42:07 by MOSER
;TCO 6.1963 - FIX ASGVAS WHEN AV%LOK IS SPECIFIED
; UPD ID= 3472, SNARK:<6.MONITOR>PAGUTL.MAC.58,  17-Jan-84 08:53:15 by HAUDEL
;More TCO 6.1798 MCA25 changes
; UPD ID= 3467, SNARK:<6.MONITOR>PAGUTL.MAC.57,  16-Jan-84 14:02:57 by HAUDEL
;More TCO 6.1798 MCA25 changes,only set keep me if MCA25 is present.
; UPD ID= 3452, SNARK:<6.MONITOR>PAGUTL.MAC.56,  12-Jan-84 19:37:58 by MCLEAN
;TCO 6.1930 MAKE MOVCS2+2 DO THE CORRECT CALCULATION OF NUMBER OF PAGES FOR CSTX'S
; UPD ID= 3263, SNARK:<6.MONITOR>PAGUTL.MAC.55,   6-Dec-83 14:40:20 by MOSER
;TCO 6.1875 FIX PAGLCK/ILMNRF BUGHLT
; UPD ID= 3143, SNARK:<6.MONITOR>PAGUTL.MAC.54,  14-Nov-83 19:49:36 by GROSSMAN
;TCO 6.1863. Set CSWRB when doing a PLOCK (LODPP0) to prevent page faults.
; UPD ID= 3103, SNARK:<6.MONITOR>PAGUTL.MAC.53,   7-Nov-83 09:32:49 by MILLER
;TCO 6.1094. Use PGPTR def. for CFS pointer field
; UPD ID= 3042, SNARK:<6.MONITOR>PAGUTL.MAC.52,  18-Oct-83 18:20:36 by MILLER
;TCO 6.1094. Use CF%NUL in GETCAL
; UPD ID= 3021, SNARK:<6.MONITOR>PAGUTL.MAC.51,  10-Oct-83 16:22:48 by MURPHY
;Make DDTINI breakpoint be in always-writable area.
; UPD ID= 2968, SNARK:<6.MONITOR>PAGUTL.MAC.50,   3-Oct-83 08:24:03 by MILLER
;TCO 6.1814. INVOFN will not scan OFN if XB is on disk already
; UPD ID= 2953, SNARK:<6.MONITOR>PAGUTL.MAC.49,  28-Sep-83 16:20:15 by MOSER
;TCO 6.1789 FIX PTNIC1 AND OTHER PROBLEMS
; UPD ID= 2952, SNARK:<6.MONITOR>PAGUTL.MAC.48,  28-Sep-83 15:08:20 by MILLER
;TCO 6.1809. SAVE P REGS AT DELPT
; UPD ID= 2942, SNARK:<6.MONITOR>PAGUTL.MAC.47,  27-Sep-83 15:38:17 by MILLER
;Clear OFN2XB at GETCFL
; UPD ID= 2917, SNARK:<6.MONITOR>PAGUTL.MAC.46,  21-Sep-83 09:52:11 by MILLER
;Create FRECFL, to release only file open resources, but save the access token
; UPD ID= 2909, SNARK:<6.MONITOR>PAGUTL.MAC.45,  20-Sep-83 11:37:54 by MILLER
;TCO 6.1094. Create UP0SHR for long file count managing
; UPD ID= 2906, SNARK:<6.MONITOR>PAGUTL.MAC.44,  20-Sep-83 10:21:17 by MILLER
;Make FRECFS global. Add GETCFL to diddle CFS resources for a long file
; UPD ID= 2900, SNARK:<6.MONITOR>PAGUTL.MAC.43,  16-Sep-83 23:35:21 by MILLER
;Undo previous edit
; UPD ID= 2897, SNARK:<6.MONITOR>PAGUTL.MAC.42,  16-Sep-83 14:31:17 by MILLER
;TCO 6.1094. Call LCKOFA in the right places
; UPD ID= 2896, SNARK:<6.MONITOR>PAGUTL.MAC.41,  16-Sep-83 13:57:10 by MURPHY
;Symbol DDTINI for always-present DDT breakpoint after paging on.
; UPD ID= 2891, SNARK:<6.MONITOR>PAGUTL.MAC.40,  12-Sep-83 15:41:29 by HALL
;TCO 6.1798 - Add support (possibly temporary) for "keep me" bit in hardware
;		page table
;	Set PTKEEP in MSECTB and MSECTB+1
;	Set PTKEEP in map entries for RSCOD and SZCOD
;	Call STKEEP after we clear the pager around PGRRST
; UPD ID= 2851, SNARK:<6.MONITOR>PAGUTL.MAC.39,  19-Aug-83 14:30:37 by MURPHY
;More - fix bugs.
; UPD ID= 2840, SNARK:<6.MONITOR>PAGUTL.MAC.38,  17-Aug-83 21:38:14 by MURPHY
;Ever more 6.1525 - Separate section 0/1 maps.
;More 6.1700 - Make MLKPG handle SPT ident.
; UPD ID= 2822, SNARK:<6.MONITOR>PAGUTL.MAC.37,  11-Aug-83 12:14:54 by MURPHY
;Bug in SZCOD init.
; UPD ID= 2817, SNARK:<6.MONITOR>PAGUTL.MAC.36,   9-Aug-83 13:49:59 by PURRETTA
;Report correct module name in BUG. macros.
; UPD ID= 2815, SNARK:<6.MONITOR>PAGUTL.MAC.35,   9-Aug-83 12:05:03 by MURPHY
;Finish previous.
; UPD ID= 2811, SNARK:<6.MONITOR>PAGUTL.MAC.34,   9-Aug-83 11:48:27 by MURPHY
;Put call to MOVCST here instead of MEXEC.
;Fix bug where CST3 page with SPMQ is released at startup.
; UPD ID= 2804, SNARK:<6.MONITOR>PAGUTL.MAC.33,   4-Aug-83 13:41:06 by LEACHE
;Use NRCOD as temporary location of CST's
; UPD ID= 2711, SNARK:<6.MONITOR>PAGUTL.MAC.32,  20-Jul-83 10:55:12 by MCINTEE
;More TCO 6.1739 - remove previous edit. the issue is more complex.
; UPD ID= 2708, SNARK:<6.MONITOR>PAGUTL.MAC.31,  19-Jul-83 11:48:37 by MCINTEE
;TCO 6.1739 - In PGRCST, use NRCOD instead of NRVAR for temporary CST mapping
; UPD ID= 2665, SNARK:<6.MONITOR>PAGUTL.MAC.30,   5-Jul-83 13:30:41 by MURPHY
;More 6.1525 - Separate section for symbols, DDT, etc.
; UPD ID= 2618, SNARK:<6.MONITOR>PAGUTL.MAC.29,  21-Jun-83 15:32:09 by MURPHY
;Reorder PSECTS; handle CSTs temp mapping in virt adr differnt from physical.
; UPD ID= 2561, SNARK:<6.MONITOR>PAGUTL.MAC.28,   6-Jun-83 23:24:31 by MURPHY
;Fix screwed up mapping of monitor page tables into RSECMP.
;More 6.1525 - Move BUGPTR and BUGSTRINGS into ext section.
; UPD ID= 2548, SNARK:<6.MONITOR>PAGUTL.MAC.27,  31-May-83 16:47:51 by MURPHY
;Lock EPGMAP in core.
;Map all monitor section PTs into NRPE space.
; UPD ID= 2524, SNARK:<6.MONITOR>PAGUTL.MAC.26,  26-May-83 11:55:24 by MILLER
;Fix race in DDOCFS
; UPD ID= 2511, SNARK:<6.MONITOR>PAGUTL.MAC.25,  24-May-83 17:03:55 by MURPHY
;Fix 2498 - end check wrong.
; UPD ID= 2506, SNARK:<6.MONITOR>PAGUTL.MAC.24, 23-May-83 16:58:19 by LOMARTIRE
;TCO 6.1633 - Add NOOFN BUGINF - issued at most every 30 mins. when no OFNs
; UPD ID= 2502, SNARK:<6.MONITOR>PAGUTL.MAC.23,  23-May-83 13:52:27 by MILLER
;TCO 6.1094. Get rid of ALCLOK
; UPD ID= 2498, SNARK:<6.MONITOR>PAGUTL.MAC.22,  23-May-83 10:40:15 by MURPHY
;Clear the RSE area at startup.
; UPD ID= 2491, SNARK:<6.MONITOR>PAGUTL.MAC.21,  18-May-83 18:21:24 by MURPHY
;Ditto
; UPD ID= 2489, SNARK:<6.MONITOR>PAGUTL.MAC.20,  18-May-83 15:01:06 by MURPHY
;More of previous - fix SCA stuff.
; UPD ID= 2468, SNARK:<6.MONITOR>PAGUTL.MAC.19,  16-May-83 17:15:12 by MURPHY
;TCO 6.1525 - Lock RSE pages.
; UPD ID= 2288, SNARK:<6.MONITOR>PAGUTL.MAC.18,  16-Apr-83 19:15:11 by PAETZOLD
;TCP 6.1557 - TCP Merge
; UPD ID= 2243, SNARK:<6.MONITOR>PAGUTL.MAC.17,  12-Apr-83 13:14:28 by MCINTEE
;Remove IFNDEF FTNSPSRV
; UPD ID= 2195, SNARK:<6.MONITOR>PAGUTL.MAC.16,   7-Apr-83 23:48:08 by MURPHY
;Make some interns.
; UPD ID= 2191, SNARK:<6.MONITOR>PAGUTL.MAC.15,   7-Apr-83 22:19:12 by MURPHY
;More of previous - fix up externs.
; UPD ID= 2188, SNARK:<6.MONITOR>PAGUTL.MAC.14,   7-Apr-83 21:42:17 by MURPHY
;TCO 6.1601 - Merge PAGFIL into PAGEM and PAGUTL.
; UPD ID= 2087, SNARK:<6.MONITOR>PAGUTL.MAC.12,  26-Mar-83 12:07:40 by PAETZOLD
;TCO 6.1577 - Make FPTEPG external
; UPD ID= 2035, SNARK:<6.MONITOR>PAGUTL.MAC.11,  20-Mar-83 12:36:36 by HALL
;TCO 6.1502 - Allow free space in extended section
;	Create section for free space
;	Set extended section available when paging is turned on
; UPD ID= 2031, SNARK:<6.MONITOR>PAGUTL.MAC.10,  20-Mar-83 10:38:09 by MILLER
;TCO 6.1094. Add OFNTKN
; UPD ID= 1994, SNARK:<6.MONITOR>PAGUTL.MAC.9,  15-Mar-83 10:57:26 by MILLER
;TCO 6.1544. Protect BOOT's pages
; UPD ID= 1973, SNARK:<6.MONITOR>PAGUTL.MAC.8,  10-Mar-83 23:35:21 by MURPHY
;A bit more of the previous.
; UPD ID= 1960, SNARK:<6.MONITOR>PAGUTL.MAC.7,  10-Mar-83 15:05:15 by MURPHY
;Setup second PSB page so it may be referenced early in fork life.
; UPD ID= 1955, SNARK:<6.MONITOR>PAGUTL.MAC.6,  10-Mar-83 00:35:30 by CDUNN
;More TCO 6.1127 - Put lost edits back into PGRSKD. Teach it to do reasonable
;things with PI and return number of pages obtained
; UPD ID= 1928, SNARK:<6.MONITOR>PAGUTL.MAC.5,   7-Mar-83 21:00:38 by CDUNN
;Change default to include KLIPA support code
; UPD ID= 1866, SNARK:<6.MONITOR>PAGUTL.MAC.4,  23-Feb-83 13:20:49 by MILLER
;TCO 6.1520. Preallocate disk pages
; UPD ID= 1743, SNARK:<6.MONITOR>PAGUTL.MAC.3,   2-Feb-83 15:59:17 by MURPHY
;More 5.1.1103 - Check is backwards.
; UPD ID= 1677, SNARK:<6.MONITOR>PAGUTL.MAC.2,  18-Jan-83 23:19:30 by CDUNN
;More TCO 6.1127 - Teach MOVCST all about the memory associated with the
;CI simulator.
;TCO 6.1463 - Split PAGEM into three parts
;	Make the following be global: RESPCK,SETXB1,RELCXB,SETCPT,RELCPT,SECPTR,
;		CHKSHC,SKPNLK,WTNLK,FNDFPG,ONSPMQ,OFFSPQ,FRCRRM,SETPP1
;	Move data to STG and PROLOG
; UPD ID= 1600, SNARK:<6.MONITOR>PAGEM.MAC.185,  29-Dec-82 13:33:34 by DONAHUE
;TCO 6.1414 - Don't zero TRPDSP at ILRF2
; UPD ID= 1597, SNARK:<6.MONITOR>PAGEM.MAC.184,  29-Dec-82 10:43:12 by DONAHUE
;TCO 6.1192 - Prevent SWPSTL Bugchk's
; UPD ID= 1538, SNARK:<6.MONITOR>PAGEM.MAC.182,  20-Dec-82 17:12:47 by NICHOLS
;Add FTNSPSRV to distinguish between release 6.0 and 6.1
; UPD ID= 1537, SNARK:<6.MONITOR>PAGEM.MAC.181,  20-Dec-82 11:55:28 by MCINTEE
;TCO 6.1423 - Add a new bughlt to hopefully catch ILSPTH problems earlier.
; UPD ID= 1536, SNARK:<6.MONITOR>PAGEM.MAC.180,  19-Dec-82 22:05:44 by CDUNN
;More TCO 6.1127 - Remove SUBTTL from routine PGRSKD such that entire PAGEM
;listing does not claim to be part of PGRSKD...
; UPD ID= 1524, SNARK:<6.MONITOR>PAGEM.MAC.179,   9-Dec-82 10:17:25 by MILLER
;Fix edit 1516. Need to add a NOINT as well
; UPD ID= 1517, SNARK:<6.MONITOR>PAGEM.MAC.178,   7-Dec-82 20:46:56 by COBB
;TCO 5.1.1113 - MSETST - Don't compress out indirect ptrs. -- on behalf of MURPHY
; UPD ID= 1516, SNARK:<6.MONITOR>PAGEM.MAC.177,   7-Dec-82 17:52:15 by MILLER
;TCO 6.1094. Fix code around ASOF6 to lock OFN properly
; UPD ID= 1510, SNARK:<6.MONITOR>PAGEM.MAC.176,   2-Dec-82 15:08:40 by MILLER
;TCO 6.1094. Reverse OFN lock and file state setting in LCKOFN
; UPD ID= 1509, SNARK:<6.MONITOR>PAGEM.MAC.175,   2-Dec-82 14:47:24 by MOSER
;TCO 6.1191 - PREVENT ILPAG1 BUGHLTS
; UPD ID= 1495, SNARK:<6.MONITOR>PAGEM.MAC.174,  30-Nov-82 20:45:05 by GRANT
;TCO 6.1010 - make a better test in MOVCST
; UPD ID= 1481, SNARK:<6.MONITOR>PAGEM.MAC.173,  29-Nov-82 09:44:52 by GRANT
;TCO 6.1010 - Add MOVCST and a few EA.ENTs
; UPD ID= 1471, SNARK:<6.MONITOR>PAGEM.MAC.172,  22-Nov-82 17:50:05 by MILLER
;TCO 6.1094. Handle write =) read access transition
; UPD ID= 1456, SNARK:<6.MONITOR>PAGEM.MAC.171,  17-Nov-82 15:55:50 by MILLER
;Same as before
; UPD ID= 1451, SNARK:<6.MONITOR>PAGEM.MAC.170,  17-Nov-82 08:13:56 by MILLER
;TCO 6.1094. Clear CSWRB during DDMP force out!
; UPD ID= 1448, SNARK:<6.MONITOR>PAGEM.MAC.169,  16-Nov-82 14:21:35 by CDUNN
; More TCO 6.1127 - Make PGRSKD return the size of the origional request
;when it succeeds.
; UPD ID= 1437, SNARK:<6.MONITOR>PAGEM.MAC.168,  11-Nov-82 17:01:33 by MILLER
;TCO 6.1094. Call FRECFS on any ASGOFN failure
; UPD ID= 1436, SNARK:<6.MONITOR>PAGEM.MAC.167,  11-Nov-82 15:13:28 by MILLER
;TCO 6.1094. Add some debug checks to DASOFN
; UPD ID= 1434, SNARK:<6.MONITOR>PAGEM.MAC.166,  11-Nov-82 12:44:06 by MILLER
;TCO 6.1000. Set CST write bit in SETCST
; UPD ID= 1433, SNARK:<6.MONITOR>PAGEM.MAC.165,  10-Nov-82 16:49:52 by MILLER
;TCO 4.1000. Set CST write bit in FRCRMP
; UPD ID= 1431, SNARK:<6.MONITOR>PAGEM.MAC.164,   9-Nov-82 17:19:05 by MILLER
;TCO 6.1094. Add call to FRECFS to CLROFN
; UPD ID= 1423, SNARK:<6.MONITOR>PAGEM.MAC.163,   8-Nov-82 08:48:03 by GRANT
;TCO 6.1010 - Make MULK1 run in section 1.  Change comments in BSMGP.
; UPD ID= 1421, SNARK:<6.MONITOR>PAGEM.MAC.162,   5-Nov-82 15:50:13 by MURPHY
;TCO 5.1.1103 - Optional data on SWPSTL.
; UPD ID= 1419, SNARK:<6.MONITOR>PAGEM.MAC.161,   5-Nov-82 14:52:56 by MILLER
;TCO 6.1094 again.
; UPD ID= 1417, SNARK:<6.MONITOR>PAGEM.MAC.160,   5-Nov-82 09:54:14 by MILLER
;tco 6.1094. Various CFS fixes
; UPD ID= 1407, SNARK:<6.MONITOR>PAGEM.MAC.159,   3-Nov-82 16:33:09 by MILLER
;TCO 6.1094. More CFS changes to DDMP
; UPD ID= 1404, SNARK:<6.MONITOR>PAGEM.MAC.158,   3-Nov-82 06:52:55 by GRANT
;More TCO 6.1010 - make SWPDON run in section 1
; UPD ID= 1399, SNARK:<6.MONITOR>PAGEM.MAC.157,   1-Nov-82 17:22:36 by MILLER
;TCO 6.1094. Fix PREPG to check for CFS status of files
; UPD ID= 1398, SNARK:<6.MONITOR>PAGEM.MAC.156,   1-Nov-82 15:49:57 by MILLER
;TCO 6.1094. Fix GETT1B to get OFN properly
; UPD ID= 1389, SNARK:<6.MONITOR>PAGEM.MAC.155,  28-Oct-82 12:12:20 by MILLER
;TCO 6.1094. More CFS merges
; UPD ID= 1388, SNARK:<6.MONITOR>PAGEM.MAC.154,  27-Oct-82 23:29:45 by CDUNN
;More TCO 6.1127 - Fix typo in last edit
; UPD ID= 1384, SNARK:<6.MONITOR>PAGEM.MAC.153,  26-Oct-82 19:43:31 by CDUNN
;More TCO 6.1127 - Make PGRSKD abuse the RPLQ the right way
; UPD ID= 1382, SNARK:<6.MONITOR>PAGEM.MAC.152,  26-Oct-82 17:43:20 by MILLER
;Fix call to CFSGWL for CFS
; UPD ID= 1381, SNARK:<6.MONITOR>PAGEM.MAC.151,  26-Oct-82 13:38:24 by MILLER
;tco 6.1094. Eliminate need for DDXBI in most cases
; UPD ID= 1378, SNARK:<6.MONITOR>PAGEM.MAC.150,  25-Oct-82 14:32:12 by MILLER
;TCO 6.1094. Add CFS section support
; UPD ID= 1371, SNARK:<6.MONITOR>PAGEM.MAC.149,  22-Oct-82 14:50:14 by MILLER
;Fix to restore state of FILUB broken by TCO 6.1094
; UPD ID= 1368, SNARK:<6.MONITOR>PAGEM.MAC.148,  22-Oct-82 09:14:59 by MILLER
;Put in more CFS conditionals
; UPD ID= 1365, SNARK:<6.MONITOR>PAGEM.MAC.147,  21-Oct-82 17:20:27 by MILLER
;TCO 6.1094. Merge latest CFS changes
; UPD ID= 1360, SNARK:<6.MONITOR>PAGEM.MAC.146,  20-Oct-82 15:39:09 by MILLER
;Check in DDMP for XB locked (for CFS)
; UPD ID= 1359, SNARK:<6.MONITOR>PAGEM.MAC.145,  20-Oct-82 14:17:22 by MILLER
;TCO 6.1094. Merge in CFS changes
; UPD ID= 1352, SNARK:<6.MONITOR>PAGEM.MAC.144,  18-Oct-82 16:40:51 by MILLER
;TCO 6.1094. Add CFS checking to CHKOFN
; UPD ID= 1350, SNARK:<6.MONITOR>PAGEM.MAC.143,  18-Oct-82 13:57:19 by MILLER
;TCO 6.1094. Merge in latest CFS changes
; UPD ID= 1342, SNARK:<6.MONITOR>PAGEM.MAC.142,  14-Oct-82 17:36:44 by MILLER
;TCO 6.1094. Rewrite code at RELMP2 so as not to cause NOSKED page fault
; UPD ID= 1341, SNARK:<6.MONITOR>PAGEM.MAC.141,  14-Oct-82 13:42:19 by MILLER
;TCO 6.1094. CFS fixes
; UPD ID= 1340, SNARK:<6.MONITOR>PAGEM.MAC.140,  14-Oct-82 09:31:55 by MILLER
;Add CFSCOD conditional to prevent assembly errors
; UPD ID= 1339, SNARK:<6.MONITOR>PAGEM.MAC.139,  14-Oct-82 08:33:57 by MCINTEE
;Add . to ANSKP
; UPD ID= 1336, SNARK:<6.MONITOR>PAGEM.MAC.138,  13-Oct-82 17:37:37 by MILLER
;Numerous changes for CFS
; UPD ID= 1329, SNARK:<6.MONITOR>PAGEM.MAC.137,  12-Oct-82 17:24:51 by MILLER
;Fixes to DDMP
; UPD ID= 1328, SNARK:<6.MONITOR>PAGEM.MAC.136,  12-Oct-82 16:49:28 by MILLER
;Don't use DDXLOK in DDMP
; UPD ID= 1327, SNARK:<6.MONITOR>PAGEM.MAC.135,  12-Oct-82 15:59:28 by MILLER
;TCO 6.1094. Set CSWRB in MAPPHP and CGPLK (for BOOT)
; UPD ID= 1324, SNARK:<6.MONITOR>PAGEM.MAC.134,  11-Oct-82 16:56:24 by MILLER
;Fix to DDMP: SKPNWR must be called while NOSKED
; UPD ID= 1323, SNARK:<6.MONITOR>PAGEM.MAC.133,  11-Oct-82 16:13:05 by MCINTEE
;Fix typo two edits ago - OKSKED at BADD-3 should have been NOSKED
; UPD ID= 1315, SNARK:<6.MONITOR>PAGEM.MAC.132,   9-Oct-82 15:26:07 by MILLER
;Fix race in hadnling of XB reverification
; UPD ID= 1310, SNARK:<6.MONITOR>PAGEM.MAC.131,   8-Oct-82 16:54:42 by MILLER
; UPD ID= 1306, SNARK:<6.MONITOR>PAGEM.MAC.130,   8-Oct-82 16:02:26 by MOSER
;TCO 6.1282 - ADD SWPDIR BUGCHK
; UPD ID= 1304, SNARK:<6.MONITOR>PAGEM.MAC.129,   8-Oct-82 15:30:31 by MOSER
;TCO 6.1285 - NOINT BEFORE LOCKING STRLOK IN DDMP
; UPD ID= 1300, SNARK:<6.MONITOR>PAGEM.MAC.128,   8-Oct-82 14:28:29 by MILLER
; UPD ID= 1297, SNARK:<6.MONITOR>PAGEM.MAC.127,   7-Oct-82 17:22:26 by MILLER
;Fix typeo in DDXBI
; UPD ID= 1296, SNARK:<6.MONITOR>PAGEM.MAC.126,   7-Oct-82 14:18:41 by MILLER
;Many, many CFS fixes
; UPD ID= 1290, SNARK:<6.MONITOR>PAGEM.MAC.125,   6-Oct-82 19:37:22 by MILLER
; UPD ID= 1289, SNARK:<6.MONITOR>PAGEM.MAC.124,   6-Oct-82 17:41:33 by CDUNN
;Fix defaults for shared memory placement and size for CI emulator
; UPD ID= 1288, SNARK:<6.MONITOR>PAGEM.MAC.123,   6-Oct-82 13:54:51 by MILLER
;More CFS fixes
; UPD ID= 1285, SNARK:<6.MONITOR>PAGEM.MAC.122,   6-Oct-82 13:32:55 by MILLER
; UPD ID= 1283, SNARK:<6.MONITOR>PAGEM.MAC.121,   5-Oct-82 19:44:35 by MILLER
; UPD ID= 1282, SNARK:<6.MONITOR>PAGEM.MAC.120,   5-Oct-82 18:41:44 by MILLER
; UPD ID= 1281, SNARK:<6.MONITOR>PAGEM.MAC.119,   5-Oct-82 16:08:41 by MILLER
; UPD ID= 1277, SNARK:<6.MONITOR>PAGEM.MAC.118,   4-Oct-82 19:55:00 by MILLER
; UPD ID= 1276, SNARK:<6.MONITOR>PAGEM.MAC.117,   4-Oct-82 16:30:36 by MILLER
; UPD ID= 1275, SNARK:<6.MONITOR>PAGEM.MAC.116,   4-Oct-82 16:20:39 by CDUNN
;Fix CISRV parameters dealing with memory size and location...
; UPD ID= 1268, SNARK:<6.MONITOR>PAGEM.MAC.115,   1-Oct-82 14:24:34 by MILLER
;FIx typeo in previous
; UPD ID= 1267, SNARK:<6.MONITOR>PAGEM.MAC.114,   1-Oct-82 13:45:25 by MILLER
;Allow OF%RDU access to bygpass all CFS restrictons!!
; UPD ID= 1266, SNARK:<6.MONITOR>PAGEM.MAC.113,   1-Oct-82 13:01:18 by MILLER
;Don't allow OF%RDU if file already opened for exclusive access
; UPD ID= 1250, SNARK:<6.MONITOR>PAGEM.MAC.112,  27-Sep-82 23:29:33 by MILLER
;CFS -- Improve DDMP logic somewhat
; UPD ID= 1248, SNARK:<6.MONITOR>PAGEM.MAC.111,  27-Sep-82 22:36:46 by MILLER
;CFS -- Fix ATP1A to preserve T1
; UPD ID= 1246, SNARK:<6.MONITOR>PAGEM.MAC.110,  27-Sep-82 22:23:26 by MILLER
;CFS -- FIx DDMP
; UPD ID= 1228, SNARK:<6.MONITOR>PAGEM.MAC.109,  23-Sep-82 23:48:17 by MILLER
;More CFS fixes
; UPD ID= 1225, SNARK:<6.MONITOR>PAGEM.MAC.108,  23-Sep-82 21:10:14 by MILLER
;Fix DDXBI to map OFN correctly. FIxes to UPDPGS as well
; UPD ID= 1224, SNARK:<6.MONITOR>PAGEM.MAC.107,  23-Sep-82 19:03:04 by MILLER
;Put call to DDXBI under CFSCOD conditional
; UPD ID= 1219, SNARK:<6.MONITOR>PAGEM.MAC.106,  23-Sep-82 10:34:13 by MILLER
;CFS... Handle error cases in ASGOFN
; UPD ID= 1215, SNARK:<6.MONITOR>PAGEM.MAC.104,  22-Sep-82 20:30:15 by MILLER
;More CFS stuff. Make CHKLAC check with other systems
; UPD ID= 1213, SNARK:<6.MONITOR>PAGEM.MAC.103,  21-Sep-82 22:13:36 by MILLER
; UPD ID= 1212, SNARK:<6.MONITOR>PAGEM.MAC.102,  21-Sep-82 20:35:23 by MILLER
;More edits to DDXBI
; UPD ID= 1211, SNARK:<6.MONITOR>PAGEM.MAC.101,  21-Sep-82 20:18:37 by MILLER
;Fix types in DDXBI
; UPD ID= 1209, SNARK:<6.MONITOR>PAGEM.MAC.100,  21-Sep-82 17:09:02 by MILLER
; UPD ID= 1203, SNARK:<6.MONITOR>PAGEM.MAC.99,  20-Sep-82 22:40:52 by MILLER
;Oce more
; UPD ID= 1202, SNARK:<6.MONITOR>PAGEM.MAC.98,  20-Sep-82 22:36:15 by MILLER
;TCO 6.1094. Make code at GETT1B check for SPTFO
; UPD ID= 1201, SNARK:<6.MONITOR>PAGEM.MAC.97,  20-Sep-82 22:02:51 by MILLER
;TCO 6.1094. More fixes to DDMP
; UPD ID= 1196, SNARK:<6.MONITOR>PAGEM.MAC.96,  17-Sep-82 13:51:59 by MILLER
;TCO 6.1271. Check for page fault in scheuler
; UPD ID= 1194, SNARK:<6.MONITOR>PAGEM.MAC.95,  17-Sep-82 12:53:01 by MILLER
;Once more time!
; UPD ID= 1193, SNARK:<6.MONITOR>PAGEM.MAC.94,  17-Sep-82 11:50:10 by MILLER
;Fixes to "force out" and XB swap in for CFS
; UPD ID= 1192, SNARK:<6.MONITOR>PAGEM.MAC.93,  16-Sep-82 23:22:20 by MILLER
;TCO 1.094 Check for swap from disk of OFN in SWPIN
; UPD ID= 1187, SNARK:<6.MONITOR>PAGEM.MAC.92,  15-Sep-82 19:10:22 by MILLER
;Fix to handling of CST write bit
; UPD ID= 1186, SNARK:<6.MONITOR>PAGEM.MAC.91,  15-Sep-82 16:16:07 by MILLER
;Always set CSWRB for an XB page
; UPD ID= 1185, SNARK:<6.MONITOR>PAGEM.MAC.90,  14-Sep-82 22:55:26 by MILLER
;A few more
; UPD ID= 1184, SNARK:<6.MONITOR>PAGEM.MAC.89,  14-Sep-82 22:42:42 by MILLER
;TCO 6.1094. Add some debug stuff for CFS
; UPD ID= 1169, SNARK:<6.MONITOR>PAGEM.MAC.88,  13-Sep-82 13:11:17 by MILLER
;put call to FRECFS under CFSCOD conditional
; UPD ID= 1165, SNARK:<6.MONITOR>PAGEM.MAC.87,  13-Sep-82 07:54:16 by MILLER
; UPD ID= 1162, SNARK:<6.MONITOR>PAGEM.MAC.86,  10-Sep-82 14:34:42 by MILLER
; UPD ID= 1158, SNARK:<6.MONITOR>PAGEM.MAC.85,   9-Sep-82 22:38:15 by MILLER
;TCO 6.1094 again. More fixes for CFS
; UPD ID= 1150, SNARK:<6.MONITOR>PAGEM.MAC.84,   7-Sep-82 10:43:58 by MILLER
;TCO 6.1255. handle DBUGSW GT 2
; UPD ID= 1137, SNARK:<6.MONITOR>PAGEM.MAC.83,   2-Sep-82 20:30:52 by MILLER
;Remove call to CFSORM
; UPD ID= 1135, SNARK:<6.MONITOR>PAGEM.MAC.82,   2-Sep-82 19:50:57 by MILLER
;Once more
; UPD ID= 1131, SNARK:<6.MONITOR>PAGEM.MAC.80,   1-Sep-82 22:52:13 by MILLER
;More CFS fixes to DDMP
; UPD ID= 1127, SNARK:<6.MONITOR>PAGEM.MAC.79,  31-Aug-82 22:42:53 by MILLER
;More CFS fixes
; UPD ID= 1040, SNARK:<6.MONITOR>PAGEM.MAC.78,   4-Aug-82 21:55:57 by MILLER
; UPD ID= 1035, SNARK:<6.MONITOR>PAGEM.MAC.77,   3-Aug-82 21:20:46 by MILLER
; UPD ID= 1034, SNARK:<6.MONITOR>PAGEM.MAC.76,   3-Aug-82 13:16:26 by MILLER
; UPD ID= 1033, SNARK:<6.MONITOR>PAGEM.MAC.75,   3-Aug-82 11:38:45 by MILLER
; UPD ID= 1030, SNARK:<6.MONITOR>PAGEM.MAC.74,   3-Aug-82 08:00:33 by MILLER
; UPD ID= 1028, SNARK:<6.MONITOR>PAGEM.MAC.73,   2-Aug-82 21:39:02 by MILLER
;More CFS fixes
; UPD ID= 1027, SNARK:<6.MONITOR>PAGEM.MAC.72,   2-Aug-82 18:44:28 by MILLER
;TCO 6.1205. Add WSMGR and support routines.
; UPD ID= 1018, SNARK:<6.MONITOR>PAGEM.MAC.70,  30-Jul-82 09:29:39 by PAETZOLD
;More TCO 6.1010 - Fix up the rest the left halves of some CST?X references
;Delete old edit history from before release 5
; UPD ID= 1013, SNARK:<6.MONITOR>PAGEM.MAC.69,  29-Jul-82 22:16:30 by CDUNN
;TCO 6.1199 Fix GETTPD bug in CFS code
; UPD ID= 1007, SNARK:<6.MONITOR>PAGEM.MAC.68,  27-Jul-82 15:12:37 by COBB
;TCO 6.1193 - Put call to NBNSB under SKEDSW conditional
; UPD ID= 998, SNARK:<6.MONITOR>PAGEM.MAC.67,  21-Jul-82 09:07:21 by WALLACE
;TCO 6.1104 - Make sure PC from dynamic invocation of a Dynamic
;    Library is from User Mode and trap to illegal memory read if not
;  Initialize SPTH for CTS Section(s) to say slot has no home
; UPD ID= 966, SNARK:<6.MONITOR>PAGEM.MAC.66,  29-Jun-82 11:32:48 by HALL
;TCO 6.1000 - Support the 2080
;	In address break code, save address
; UPD ID= 958, SNARK:<6.MONITOR>PAGEM.MAC.65,  23-Jun-82 21:33:35 by LEACHE
;Fix comment
; UPD ID= 949, SNARK:<6.MONITOR>PAGEM.MAC.64,  18-Jun-82 13:19:33 by MILLER
; UPD ID= 948, SNARK:<6.MONITOR>PAGEM.MAC.63,  18-Jun-82 13:00:39 by MILLER
;TCO 6.1094. Fix up KC page fault handling to include CFS checks
; UPD ID= 939, SNARK:<6.MONITOR>PAGEM.MAC.62,  16-Jun-82 16:38:07 by WALLACE
;TCO 6.1104 - More Dynamically Linked Libraries - Rather than linking
;  libraries during page faults, untrap and simulate UUO to establish
;  a JSYS context in which library link operations should be performed
; UPD ID= 870, SNARK:<6.MONITOR>PAGEM.MAC.61,   8-Jun-82 03:14:53 by CDUNN
;TCO 6.1127 - Fix cache bug in CISRV support code
; UPD ID= 867, SNARK:<6.MONITOR>PAGEM.MAC.60,   7-Jun-82 13:00:14 by MILLER
; UPD ID= 843, SNARK:<6.MONITOR>PAGEM.MAC.59,   6-Jun-82 12:42:05 by CDUNN
;Fix ILLIND BUGHLT after BUGS.MAC move...
; UPD ID= 835, SNARK:<6.MONITOR>PAGEM.MAC.58,   4-Jun-82 20:51:44 by MURPHY
;Move bugs in-line.
; UPD ID= 824, SNARK:<6.MONITOR>PAGEM.MAC.57,   3-Jun-82 14:04:49 by HALL
;TCO 6.1000 - In XGCCHK, fake a page fail code.
; UPD ID= 820, SNARK:<6.MONITOR>PAGEM.MAC.56,   3-Jun-82 12:54:45 by MILLER
;General bug fixes to CFS code.
; UPD ID= 810, SNARK:<6.MONITOR>PAGEM.MAC.55,   2-Jun-82 10:38:07 by WALLACE
;TCO 6.1105 - Add Canonical Terminal Support
;  Add code for support of CTS Section: Add dispatch routine FPTACT
;  and place it in FPTABL.  Initialize CTS Section entry in MSECTB with
;  a share pointer and initialize the entry for the pointer, in the SPT,
;  with the page, CTSIDX.
;TCO 6.1104 - Add Dynamically Linked Libraries
;  Dynamic Library Invocation from Hard Page Failure Type Illegal Indirect
; UPD ID= 807, SNARK:<6.MONITOR>PAGEM.MAC.54,   1-Jun-82 13:08:34 by PAETZOLD
;More TCO 6.1010 - Fix up yet some more left halves of some CST?X references
; UPD ID= 803, SNARK:<6.MONITOR>PAGEM.MAC.53,   1-Jun-82 11:09:01 by MURPHY
;TCO 6.1147 - Move bugdefs from BUGS.MAC to here.
; UPD ID= 769, SNARK:<6.MONITOR>PAGEM.MAC.52,  19-May-82 14:46:27 by HALL
;TCO 6.1000 - Support the 2080
;	In PGUNTD, set AC blocks in new flags word if page fault was from user
; UPD ID= 766, SNARK:<6.MONITOR>PAGEM.MAC.51,  19-May-82 14:17:20 by CDUNN
;TCO 6.1127 - Fix the all references to MAXSEC to be references to EPGSEC.
;Also teach ILFPTE and tranfer table all about dynamic section allocation, all
;code is under  IFN <FTCI!FTKLIPA> conditional.
; UPD ID= 755, SNARK:<6.MONITOR>PAGEM.MAC.50,  15-May-82 12:45:06 by MILLER
;Once more.
; UPD ID= 754, SNARK:<6.MONITOR>PAGEM.MAC.49,  15-May-82 12:41:22 by MILLER
;TCO 6.1094. Random bug fixes
; UPD ID= 737, SNARK:<6.MONITOR>PAGEM.MAC.48,  12-May-82 05:45:19 by CDUNN
;More TCO 6.1127 - After rejection of origional free space scheme, add code
;to support final SCA free space solution.
; UPD ID= 713, SNARK:<6.MONITOR>PAGEM.MAC.47,   9-May-82 18:34:23 by CDUNN
;TCO 6.1127 - Add code for init of extended memory allocator for SCA/CISRV
;Note: this code in included if either FTCI or FTKLIPA is non-zero
; UPD ID= 669, SNARK:<6.MONITOR>PAGEM.MAC.46,  28-Apr-82 12:57:14 by HALL
;TCO 6.1000 - Support the 2080
;	Add KC page fault handler
; UPD ID= 657, SNARK:<6.MONITOR>PAGEM.MAC.45,  22-Apr-82 15:36:48 by HALL
;TCO 6.1000 - Fix rewrite of page fault handler to restore page number at WCPY4.
; UPD ID= 655, SNARK:<6.MONITOR>PAGEM.MAC.44,  20-Apr-82 14:23:37 by PAETZOLD
;More TCO 6.1010 - Fix up left halves of some CST?X references
; UPD ID= 652, SNARK:<6.MONITOR>PAGEM.MAC.43,  18-Apr-82 11:13:10 by HALL
;TCO 6.1096 - Clean up exit from the page fault handler
;Fix up new LCKOFN and ULKOFN to do critical section code correctly (MILLER)
; UPD ID= 644, SNARK:<6.MONITOR>PAGEM.MAC.42,  14-Apr-82 15:22:12 by MILLER
;TCO 6.1094. Add CFS support code.
; UPD ID= 639, SNARK:<6.MONITOR>PAGEM.MAC.41,  14-Apr-82 08:57:58 by HALL
;TCO 6.1000 - Write KC version of CHKPAG
; UPD ID= 628, SNARK:<6.MONITOR>PAGEM.MAC.40,  12-Apr-82 09:35:30 by HALL
;TCO 6.1000 - Support the 2080
;	More work on XGCCHK
;	Remove UBPGF code
;	Put more hard errors under KL conditional
; UPD ID= 623, SNARK:<6.MONITOR>PAGEM.MAC.39,  10-Apr-82 16:04:44 by HALL
;TCO 6.1000 - Support the 2080
;	Make PGRTRP use SZPI for both processors (PROLOG has definition for KL)
;	Make page fault handler use TRVAR
;	Make XGCCHK look for a new label to mark end of page fault handler
;	Add KC-specific code to page fault handler
;	Initialize EPT and UPT to request KL compatible mode in super section
;	Add ENDTV to end of page fault handler
;	More work on XGCCHK for the KC
;	Remove redundant XJRSTF at ILRFU
;	Don't use PTPUB for the KC
;	Don't clear or set PTCACH in LODPPG and ULDPAG
;	Don't have PTCACH in the default pointer
; UPD ID= 612, SNARK:<6.MONITOR>PAGEM.MAC.38,   8-Apr-82 14:43:25 by CDUNN
;Fix more of the great PAGEM disaster. Redefine C%MFPG
; UPD ID= 609, SNARK:<6.MONITOR>PAGEM.MAC.37,   7-Apr-82 17:00:22 by CDUNN
;Fix IFNDEF for CI code and remove LCSSEC references (again)
; UPD ID= 605, SNARK:<6.MONITOR>PAGEM.MAC.36,   7-Apr-82 16:14:06 by COBB
;TCO 5.1743 - Fix simultaneous access bug at CHKACC (missing line prob)
;		pointer
; UPD ID= 612, SNARK:<6.MONITOR>PAGEM.MAC.38,   8-Apr-82 14:43:25 by CDUNN
;Fix more of the great PAGEM disaster. Redefine C%MFPG
;TCO 6.1072 - Make PGRINI's memory scan use its own page fault handler, and
;	add code for the KC
; UPD ID= 609, SNARK:<6.MONITOR>PAGEM.MAC.37,   7-Apr-82 17:00:22 by CDUNN
;Fix IFNDEF for CI code and remove LCSSEC references (again)
; UPD ID= 605, SNARK:<6.MONITOR>PAGEM.MAC.36,   7-Apr-82 16:14:06 by COBB
;TCO 5.1743 - Fix simultaneous access bug at CHKACC (missing line prob)
; UPD ID= 570, SNARK:<6.MONITOR>PAGEM.MAC.35,   1-Apr-82 16:16:20 by CDUNN
;Get back edit for TCO 6.1074, lost in programmer mix up...
; UPD ID= 569, SNARK:<6.MONITOR>PAGEM.MAC.34,   1-Apr-82 15:13:24 by CDUNN
;Add code to support CI emulation. Add code under feature test FTCI which
;is off by default.
; UPD ID= 566, SNARK:<6.MONITOR>PAGEM.MAC.31,  31-Mar-82 16:07:10 by MURPHY
;TCO 6.1074 - Revise build procedures, eliminate PROKL, etc.
;
;TCO 6.1074 - Revise build procedures, eliminate PROKL, etc.
; UPD ID= 384, SNARK:<6.MONITOR>PAGEM.MAC.25,   5-Feb-82 14:04:08 by HALL
;TCO 6.1000 - Support the 2080
;	PGRINI - Remove check for EXADDR and initialization of MMAP for
;	  bit table in section 0
;	SETDST - don't handle model A. DST is always in non-zero section
;	PGRTRP and XGCCHK - remove conversion of model A format flags/PC
; UPD ID= 324, SNARK:<6.MONITOR>PAGEM.MAC.24,  19-Jan-82 12:21:26 by MURPHY
;DITTO
; UPD ID= 317, SNARK:<6.MONITOR>PAGEM.MAC.22,  18-Jan-82 17:34:27 by MURPHY
;TCO 5.1686 - reduce SPC0 threshold to prevent SPT full situations.
; UPD ID= 310, SNARK:<6.MONITOR>PAGEM.MAC.21,  18-Jan-82 10:14:02 by PAETZOLD
;TCO 5.1682 - change ILSN to generate ILLX05 as TWWRT is not valid
;TCO 5.1683 - fix GETTPD to generate correct error dispatch for
;	      non-existant section references
; UPD ID= 282, SNARK:<6.MONITOR>PAGEM.MAC.20,   8-Jan-82 13:37:49 by MURPHY
;More 5.1616 - don't wait in RELP3.
; UPD ID= 270, SNARK:<6.MONITOR>PAGEM.MAC.19,   2-Jan-82 13:09:47 by HALL
;A few comments
; UPD ID= 227, SNARK:<6.MONITOR>PAGEM.MAC.18,   2-Dec-81 13:35:57 by MURPHY
;TCO 5.1623
;Change GNPBAS to BALSHC around NICCKS (old fix).  Get rid of GNPBAS completely.
; UPD ID= 226, SNARK:<6.MONITOR>PAGEM.MAC.17,   1-Dec-81 11:20:20 by GRANT
;TCO 5.1621 - fix cause of MONPDL BUGHLT in SETP6 routine
; UPD ID= 223, SNARK:<6.MONITOR>PAGEM.MAC.16,  30-Nov-81 14:45:22 by MURPHY
;fix previous
; UPD ID= 220, SNARK:<6.MONITOR>PAGEM.MAC.15,  30-Nov-81 08:41:07 by PAETZOLD
;More TCO 6.1010 - CST3 linked list references
; UPD ID= 217, SNARK:<6.MONITOR>PAGEM.MAC.14,  23-Nov-81 13:11:37 by MURPHY
;TCO 5.1616 - Check page locked in core in MOVDSK and elsewhere.
; UPD ID= 209, SNARK:<6.MONITOR>PAGEM.MAC.11,  16-Nov-81 17:38:30 by MURPHY
;TCO 5.1615 - call SETPCV at ILRF
; UPD ID= 183, SNARK:<6.MONITOR>PAGEM.MAC.10,   4-Nov-81 10:44:11 by GRANT
;TCO 5.1605 - Fix bug in SWPEX6
; UPD ID= 176, SNARK:<6.MONITOR>PAGEM.MAC.9,  31-Oct-81 14:41:58 by PAETZOLD
;More TCO 6.1010 - CST3 References
; UPD ID= 153, SNARK:<6.MONITOR>PAGEM.MAC.8,  21-Oct-81 14:25:10 by PAETZOLD
;TCO 5.1591 - Have MSETPT unlock the correct OFN when cleaning up during
; failure code
; UPD ID= 145, SNARK:<6.MONITOR>PAGEM.MAC.7,  19-Oct-81 16:14:41 by COBB
;TCO 6.1029 - CHANGE SE1CAL TO EA.ENT
; UPD ID= 110, SNARK:<6.MONITOR>PAGEM.MAC.6,  15-Oct-81 22:43:26 by PAETZOLD
;TCO 5.1574 - Check for overflowing the SPT SHARE COUNT before
; incrementing it
; UPD ID= 89, SNARK:<6.MONITOR>PAGEM.MAC.5,   4-Oct-81 23:51:41 by PAETZOLD
;TCO 5.1554 - ADD CODE TO TRACE SPTLKB STUFF UNDER CONTROL OF SPTDSW
; UPD ID= 77, SNARK:<6.MONITOR>PAGEM.MAC.4,  17-Sep-81 01:49:49 by PAETZOLD
;More TCO 6.1010 - Change mask CST0, CST1 references
; UPD ID= 70, SNARK:<6.MONITOR>PAGEM.MAC.3,  15-Sep-81 16:00:40 by PAETZOLD
;More TCO 6.1010 - Change non mask CST0, CST1, CST2 references
; UPD ID= 68, SNARK:<6.MONITOR>PAGEM.MAC.2,  14-Sep-81 22:50:07 by PAETZOLD
;TCO 6.1010 - MOVE CSTS TO CSTSEC - FILL CSTX TABLES WITH DUMMY ENTRIES
; UPD ID= 141, SNARK:<5.MONITOR>PAGEM.MAC.44,   3-Sep-81 08:40:08 by PAETZOLD
;Add semicolins to comments in previous edit
; UPD ID= 139, SNARK:<5.MONITOR>PAGEM.MAC.43,   2-Sep-81 16:48:37 by HALL
;Comments
; UPD ID= 135, SNARK:<5.MONITOR>PAGEM.MAC.42,   1-Sep-81 17:31:07 by HALL
;Comments
; UPD ID= 111, SNARK:<5.MONITOR>PAGEM.MAC.41,  20-Aug-81 17:28:03 by MURPHY
;TCO 5.1006X - Set OFNWRB in RELADR to prevent DEAUNA bugchks.
;TCO 5.1007X - Fix reference to flags word at PGUNT0.
; UPD ID= 74, SNARK:<5.MONITOR>PAGEM.MAC.40,  24-Jul-81 16:01:55 by SCHMITT
;TCO 5.1433 - Insert page map and section map loop checking in MSETST & SETPT0
; UPD ID= 47, SNARK:<5.MONITOR>PAGEM.MAC.39,  17-Jul-81 16:19:45 by MURPHY
;DITTO - SKIP/NOSKIP RETURN FROM MSETPT
; UPD ID= 29, SNARK:<5.MONITOR>PAGEM.MAC.38,  13-Jul-81 15:23:16 by MURPHY
;YET MORE TCO 5.1398
; UPD ID= 26, SNARK:<5.MONITOR>PAGEM.MAC.37,  13-Jul-81 13:18:20 by MURPHY
;MORE TCO 5.1398
; UPD ID= 15, SNARK:<5.MONITOR>PAGEM.MAC.36,  10-Jul-81 09:19:28 by MOSER
;TCO 5.1406 - IF WCPY IS CALLED FOR A LOCKED PAGE GENERATE AN ILLEGAL MEMORY
; WRITE.
; UPD ID= 9, SNARK:<5.MONITOR>PAGEM.MAC.35,   9-Jul-81 17:13:22 by MURPHY
;TCO 5.1398 - SEPARATE DISK FULL FROM OVER QUOTA, ETC.
; UPD ID= 2187, SNARK:<5.MONITOR>PAGEM.MAC.34,  11-Jun-81 15:55:55 by MURPHY
;CHANGE TQNx TO TMNx REFLECTING CHANGE IN MACSYM
; UPD ID= 1892, SNARK:<5.MONITOR>PAGEM.MAC.33,  27-Apr-81 13:17:01 by GRANT
;Undo REPEAT 0 around GETCPA
; UPD ID= 1887, SNARK:<5.MONITOR>PAGEM.MAC.32,  24-Apr-81 17:33:53 by MURPHY
;TCO 5.1298 - COUNT INDIRECT POINTERS SEEN IN GETTPD AND ELSEWHERE
; UPD ID= 1611, SNARK:<5.MONITOR>PAGEM.MAC.31,  27-Feb-81 18:23:20 by MURPHY
;ASOFN, BUG FROM OF%RDU
; UPD ID= 1601, SNARK:<5.MONITOR>PAGEM.MAC.30,  27-Feb-81 09:51:59 by FLEMMING
;TCO 5.1265 - fix RMAP returning wrong access information
; UPD ID= 1561, SNARK:<5.MONITOR>PAGEM.MAC.29,  13-Feb-81 16:44:11 by MURPHY
;NEW OPENF MODE - OF%RDU - READ-UNRESTRICTED
; UPD ID= 1475, SNARK:<5.MONITOR>PAGEM.MAC.28,  22-Jan-81 12:16:37 by MURPHY
;Fix PM%ABT in new page case
; UPD ID= 1447, SNARK:<5.MONITOR>PAGEM.MAC.27,  15-Jan-81 15:59:22 by FLEMMING
;add code for SMAP/RSMAP
; UPD ID= 1371, SNARK:<5.MONITOR>PAGEM.MAC.26,  22-Dec-80 08:52:24 by GRANT
;TCO 5.1217 - Fix bug in YESBAT
; UPD ID= 1311, SNARK:<5.MONITOR>PAGEM.MAC.25,  24-Nov-80 17:36:57 by MURPHY
;BUG - PREPG1 not returning page number in T1
; UPD ID= 1295, SNARK:<5.MONITOR>PAGEM.MAC.24,  19-Nov-80 12:22:18 by MURPHY
;IN SECMAP - REMEMBER FORKX OF FORK OWNING PRIVATE PAGE
; UPD ID= 1220, SNARK:<5.MONITOR>PAGEM.MAC.23,   2-Nov-80 11:48:23 by HALL
;MORE ON TCO 5.1180 - REMOVE SE1CAL'S FROM SWPOML,GCCOR,REMFPA,DDMP --
;MADE POSSIBLE BY RUNNING SCHED0, GSMDX, AND CHKR IN SECTION 1
; UPD ID= 1219, SNARK:<5.MONITOR>PAGEM.MAC.22,  31-Oct-80 16:58:19 by HALL
;MORE ON TCO 5.1180 - MAKE REMFPA ENTER SECTION 1 BECAUSE EXEC0 CALLS IT
;	VIA SETMPG
; UPD ID= 1209, SNARK:<5.MONITOR>PAGEM.MAC.21,  29-Oct-80 14:24:37 by MURPHY
;DITTO
; UPD ID= 1206, SNARK:<5.MONITOR>PAGEM.MAC.20,  28-Oct-80 17:35:14 by MURPHY
;FIX VERY OLD BUG WITH PM%ABT (IN REMFP1)
; UPD ID= 1200, SNARK:<5.MONITOR>PAGEM.MAC.19,  26-Oct-80 16:59:30 by HALL
;MORE ON TCO 5.1180 -- ADD RETURN TO SETDST
; UPD ID= 1194, SNARK:<5.MONITOR>PAGEM.MAC.18,  25-Oct-80 12:14:45 by HALL
;TCO 5.1180 - MOVE DST TO NON-ZERO SECTION
;	MAKE ALL CALLERS OF GDSTX EXPECT IT TO RETURN AN ADDRESS RATHER THAN AN
;		OFFSET
;	GCCOR - ENTER SECTION 1
;	DDMP - ENTER SECTION 1
;	ADDED SETDST TO SET UP PAGE MAP AND DSTLOC
;	TEMPORARILY MAKE SWPOML DO SE1CAL
; UPD ID= 1137, SNARK:<5.MONITOR>PAGEM.MAC.17,   7-Oct-80 11:50:55 by HALL
;ASFSB - CHANGE ACVAR TO SAVEAC
; UPD ID= 1104, SNARK:<5.MONITOR>PAGEM.MAC.16,   2-Oct-80 09:28:17 by MURPHY
;DITTO
; UPD ID= 1089, SNARK:<5.MONITOR>PAGEM.MAC.15,   1-Oct-80 12:13:57 by MURPHY
;FIX ACVAR
; UPD ID= 1013, SNARK:<5.MONITOR>PAGEM.MAC.14,  13-Sep-80 16:11:29 by HALL
;MAKE PGRTRP RUN IN SECTION 1
;	CLEAR LEFT HALF OF INDEX REGISTERS
;	DO SECTION-RELATIVE JRST AT TRPRST
;	IN XGCCHK, START PROCESS AT PGRTRP IN SECTION 1
; UPD ID= 990, SNARK:<5.MONITOR>PAGEM.MAC.13,   4-Sep-80 18:42:53 by ENGEL
;ADD TABSEC AS SECTION FOR MONITOR TABLES
; UPD ID= 922, SNARK:<5.MONITOR>PAGEM.MAC.12,  20-Aug-80 09:40:34 by MURPHY
;Use open NOSKED/OKSKED in MULK1 because runs at interrupt level
; UPD ID= 912, SNARK:<5.MONITOR>PAGEM.MAC.11,  18-Aug-80 21:41:52 by MURPHY
;NOSKD1 required in MULK1 to prevent possuble SUMNR1, SUMNR2 bugchks
; UPD ID= 898, SNARK:<5.MONITOR>PAGEM.MAC.10,  14-Aug-80 10:36:21 by LYONS
;tco 5.1062 - change swppsb, swppt, swpptp, swpupt into delayed bugchk
; UPD ID= 880, SNARK:<5.MONITOR>PAGEM.MAC.9,  12-Aug-80 16:16:33 by MURPHY
;Private page count; fix INTDF checks at ILRF
; UPD ID= 810, SNARK:<5.MONITOR>PAGEM.MAC.8,  30-Jul-80 10:53:25 by MURPHY
;ADD CHECK OF WEFLAG - 1=DON'T WRITE-PROTECT RES MON
; UPD ID= 809, SNARK:<5.MONITOR>PAGEM.MAC.7,  30-Jul-80 10:34:49 by HALL
;IN PGRINI, IF DBUGSW=1, WRITE-PROTECT THE RESIDENT CODE
; UPD ID= 614, SNARK:<5.MONITOR>PAGEM.MAC.6,   6-Jun-80 16:56:18 by KONEN
;TCO 5.1061 - Add call to STROFL from DDMP to see if structure off-line
; UPD ID= 510, SNARK:<5.MONITOR>PAGEM.MAC.5,   7-May-80 20:47:07 by ENGEL
;ADD THE LCS SECTIN DEFINITIONS
; UPD ID= 420, SNARK:<5.MONITOR>PAGEM.MAC.4,  11-Apr-80 13:50:55 by HALL
;CHANGES TO WRITE-PROTECT THE RESIDENT MONITOR:
;	ADD RSDAT PSECT TO PGRINI (CREATE ENTRY IN MMAP, LOCK PAGE IN
;	MEMORY, AND ADD RSDAT TO DDT'S ALTERNATE MAP)
; UPD ID= 407, SNARK:<5.MONITOR>PAGEM.MAC.3,   3-Apr-80 16:15:37 by HALL
;CHANGES TO WRITE-PROTECT THE RESIDENT MONITOR:
;	NEW ENTRY TO PGRIGR TO SET UP MAP WRITE-PROTECTED
;	PGRINI - SET UP RSCOD WRITE-PROTECTED IF DBUGSW IS 2
;	MAKE SWPMWP WRITE-PROTECT RSCOD, TOO


;	COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1976, 1988.
;	ALL RIGHTS RESERVED.
;
;	THIS SOFTWARE IS FURNISHED UNDER A  LICENSE AND MAY BE USED AND  COPIED
;	ONLY IN  ACCORDANCE  WITH  THE  TERMS OF  SUCH  LICENSE  AND  WITH  THE
;	INCLUSION OF THE ABOVE  COPYRIGHT NOTICE.  THIS  SOFTWARE OR ANY  OTHER
;	COPIES THEREOF MAY NOT BE PROVIDED  OR OTHERWISE MADE AVAILABLE TO  ANY
;	OTHER PERSON.  NO  TITLE TO  AND OWNERSHIP  OF THE  SOFTWARE IS  HEREBY
;	TRANSFERRED.
;
;	THE INFORMATION IN THIS  SOFTWARE IS SUBJECT  TO CHANGE WITHOUT  NOTICE
;	AND SHOULD  NOT  BE CONSTRUED  AS  A COMMITMENT  BY  DIGITAL  EQUIPMENT
;	CORPORATION.
;
;	DIGITAL ASSUMES NO  RESPONSIBILITY FOR  THE USE OR  RELIABILITY OF  ITS
;	SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
	SEARCH PROLOG

	TTITLE PAGUTL

EXTN <TABSEC,MEMSTR,CLRMPE,NXTAJB,CLNXMF,KIPFS,PFSA1,SETPFH>
EXTN <ASGVCS,ASGVBT,IFPTBL,NIFPTL,RSECMP,EMMAPS,SYMSEC,MONEDV>
EXTN <PAGRST,FREMEM,DDTPX,DDTPG,NDDTPG>
EXTN <ULKP1,ULKP2,ULKP3>	;[7247] Add ULKP1 - called in OC.UNC
    IFN FTNSPSRV < ;[6.0]
EXTN <PENCOD,PENCDZ,SYMMV1,SYMMV2>
    >

DEFAC (FX,Q3)			;FORK INDEX

RS (SWPMLF,1)			;COUNT OF LOCKERS OF SWP MON
RS (SWPMWF,1)			;COUNT OF WRITE ENABLERS OF SWP MON

;INDEX BLOCK DEFINTIONS

XBBAT==1B0			;BAT BIT
XBBWRD==4			;WORD FOR XBBAT

SECADR==CPTPGA+USECTO		;WHERE TO FIND SECTION POINTER
NCSTS==4			;NUMBER OF CST'S ASSIGNED AT STARTUP
TMPCST==2			;NUMBER PAGES FOR TEMP CST
N1CST==<MAXCOR+PGSIZ-1>/PGSIZ	;NUMBER OF PAGES FOR ONE CST
NACST==NCSTS*N1CST+1		;NUMBER OF PAGES FOR ALL CSTS AND POINTERS

  IFN FTNSPSRV <
RSI DDTIBP,<NOP>		;PLACE FOR DDT INITIAL BREAKPOINT
  >
	SUBTTL PGRINI - Paging Initialization

;INITIALIZATION, SPT, CST, ETC.
;We will jump to section 1 during this routine once paging is turned on.
;We must stay there because RSCOD and NRCOD will vanish from the section 0
;map.

;Debug facility -
; 0 = sections 0 and 1 the same;
; 1 = different maps but RSCOD and INCOD in section 0 with indirect ptrs
; 2 = different, RSCOD and NRCOD removed from section 0.

MSEC1F::0

PGRINI::
	MOVSI T1,MSEC1		;Make return to be section 1
	HLLM T1,STKPC.(P)
	SAVEPQ
	HLLM T1,STKPC.(P)	;and again for SAVEPQ
	TRVAR <CSTVA>
	HLLM T1,STKPC.(P)	;and yet once more

;Assign a temporary CST0 for physical pages 0-1777 so that paging
;can be turned on and physical memory above 777777 can be referenced.

	MOVEI T1,TMPCST*PGSIZ-1	;ASSUME 512K PHYSICAL MEM
	MOVEM T1,NHIPG		;USE THAT AS HIGHEST PAGE FOR NOW

	MOVE T1,FREMEM		;USE PHYSICAL PAGES AFTER SYMTAB
	MOVEM T1,CSTVA		;REMEMBER ADDRESS FOR TEMP MAPPING
	MOVEI T2,TMPCST*PGSIZ	;ASSUME CST LENGTH IS 2 PAGES
	CALL STCSTN		;(T1,T2) SETUP INDIRECT PTRS
	MOVE T2,FREMEM
	MOVX T1,PSASM!CSWRB	;INIT CST0 AGE AND WRITE
	MOVEM T1,0(T2)
	HRL T1,T2
	HRRI T1,1(T2)		;MAKE BLT WORD
	BLT T1,<TMPCST*PGSIZ>-1(T2)
	CALL PAGRST		;() SET PAGER CONSTANTS TO MICROCODE
	SETZM SPTC
	SETZM NOF
	MOVEI T1,SPTO2+1	;MAKE LIST OF FREE OFN ENTRIES START WITH OFN 1
	MOVEI T2,NOFN-1		;[7247] Number to do
	CALL ILIST
	MOVEM T1,OFNFRE		;SAVE IT
	MOVEI T1,SPT+NOFN	;MAKE LIST OF FREE SPT ENTRIES
	MOVEI T2,SSPT-NOFN
	CALL ILIST
	MOVEM T1,FRESPT		;SAVE IT
	SETOM SPTO4
	MOVE T1,[XWD SPTO4,SPTO4+1]
	BLT T1,SPTO4+NOFN-1	;INIT SPTO4 (XB2DAT)
	SETZM SPTH
	MOVE T1,[XWD SPTH,SPTH+1]
	BLT T1,SPTH+NOFN-1	;ZERO OUT SPTH
	CALL ASSPT		;ASSIGN SPT SLOT FOR JOB BASE REG
	MOVEM T1,JOBBAS
	CALL UPSHR		;INIT SHARE COUNT
   IFN EXTJSB,<
	CALL ASSPT		;ASSIGN spt slot for extended job area
	MOVEM T1,JPTBAS
	CALL UPSHR		;Init share count
   >
	CALL ASSPT		;ASSIGN SPT SLOT FOR FORK BASE REG
	MOVEM T1,PSBBAS
	CALL UPSHR		;INIT SHARE COUNT
	CALL ASSPT		;ASSIGN SPT SLOT FOR FORK BASE REG
	MOVEM T1,PS2BAS
	CALL UPSHR		;INIT SHARE COUNT
	CALL ASSPT		;GET ANOTHER ONE
	MOVEM T1,BTBBAS		;MAKE THIS THE BIT TABLE BASE
	MOVX T2,UAAB		;SET UP ACCESS TO NULL
	MOVEM T2,SPT(T1)	;TO THE SPT
	CALL UPSHR		;INIT SHARE COUNT
	SETZM SPTH(T1)		;SET NO CORRESPONDENCE

	MOVSI T1,-<HGHSEC+1>	;SET UP TO INIT FPTA TRANSFER TABLE
	MOVEI T2,FPTMSS		;INIT TO USUAL DEFAULT
PGR00:	MOVEM T2,FPTABL(T1)	;INIT THIS ENTRY
	AOBJN T1,PGR00		;DO ALL OF THE TABLE
	; ..
;Setup MSECTB for section 0 and FPTABL.

	CALL ASSPT		;ASSIGN SPT SLOT FOR MMAP
	MOVE T2,SHRPTR		;CONSTRUCT SHARE PTR TO MMAP
	STOR T1,SPTX,T2
	APRID T3		;GET HARWARE OPTIONS
	TXNE T3,MCA25		;IS MCA25 OPTION PRESENT?
	TXO T2,PTKEEP		;YES. SET "KEEP ME" IN SECTION POINTERS IN UPT
	MOVEM T2,MSECTB		;SETUP POINTER FOR MON SECTION 0
	MOVEM T2,MSECTB+MSEC1	;SECTIONS 0 AND 1 THE SAME FOR NOW
	MOVEI T2,MMAP/PGSIZ	;GET ADDRESS FIELD
	MOVEM T2,SPT(T1)
	CALL UPSHR		;SET SHARE COUNT
	MOVEM T1,MMSPTN		;SAVE SPT OFFSET FOR MMAP
	MOVEM T1,M1SPTN		;SECTION 1 SAME FOR NOW

;SET UP POINTERS FOR DATA SECTIONS

	;Setup pointer to directory section
	MOVE T3,INDPTR		;Get indirect pointer template
	MOVE T2,PSBBAS		;Get SPT index
	STOR T2,SPTX,T3		;Store it in section pointer
	MOVEI T2,DRMAP		;Find offset for section table
	STOR T2,IPPGN,T3	;Store it in section pointer
	MOVEM T3,MSECTB+DRSECN	;Store section pointer in MSECTB
	;Setup pointer to IDX section
	MOVEI T2,IDXMAP		;Find offset for section table
	STOR T2,IPPGN,T3	;Store it in section pointer
	MOVEM T3,MSECTB+IDXSEC	;Store section pointer in MSECTB
	;Setup pointer to extended JSB section
   IFN EXTJSB,<
	MOVE T3,SHRPTR		;Get share-pointer template
	MOVE T1,JPTBAS		;Get SPT index for extended JSB
	CALL UPSHR		;Account for an additional sharing
	STOR T1,SPTX,T3		;Store it in section pointer
	MOVEM T3,MSECTB+JOBSEC	;Store pointer in MSECTB
   >

	MOVE T1,[IFPTBL,,FPTABL] ;INIT SPECIAL SECTIONS IN FPTABL
	BLT T1,FPTABL+NIFPTL-1

   IFN KCFLG,<
	MOVX T1,KLPTR		;REQUEST KL COMPATIBLE MODE FOR MONITOR
	MOVEM T1,MSSPTB		;STORE IN THE EPT FOR THE HARDWARE
   >				;END OF IFN KCFLG
;ASSIGN SPT SLOT FOR SYMMAP

	CALL HSINI1		;YES
	MOVE T2,SHRPTR		;SETUP SYMBOL SECTION
	MOVE T3,SYMBAS
	STOR T3,SPTX,T2
	MOVEM T2,MSECTB+SYMSEC

;Time to turn paging on.  MMAP is set so that virtual=physical. The temp
;CST0 follows the symbol table and is also mapped there.

	CALL SETPSK		;() SET TO SCHED CONTEXT
	CALL PGRON		;() ENABLE PAGER
;Now we assign the permanent physical pages for the CSTs, and put a temporary
;mapping of them starting after the symbol table.  The permanent mapping in
;SYMSEC will be done near the end of PGRINI.  We DON'T tell the hardware about
;the new location of CST0 however, because it isn't initialized yet.  The
;virtual address is unchanged from that established earlier, i.e.  right after
;the symbol table.

   IFN FTNSPSRV < ;[6.0]
	MOVE T1,[<PENCDZ+PGSIZ-1>&VPGNO] ;START AFTER PHYSICAL ENCOD
   >
   IFE FTNSPSRV < ;[6.1]
;CST's will go in the second 256K of physical memory, after the swappable
; monitor but before the extended code
	MOVE T1,PNRCOD		;Get POSTLD image location of NRCOD
	ADDI T1,<NRCODZ-NRCOD+PGSIZ>&VPGNO ;Get next page after NRCOD
   >
	MOVEM T1,FREMEM
	MOVEM T1,CSTLOC
	LSH T1,-PGSFT		;FIRST PAGE OF CSTS
	IOR T1,IMMPTR		;MAKE PAGE POINTER
	MOVE T2,CSTVA		;VIRTUAL ADDRESS FOR TEMP MAPPING
	LSH T2,-PGSFT
	MOVEI T3,NCSTS		;DO 4 CSTS
     DO.
	HRLI T2,-TMPCST		;NUMBER PAGES FOR CSTS - MAP ONLY 2 FOR NOW
      DO.
	MOVEM T1,MMAP(T2)
	ADDI T1,1
	AOBJN T2,TOP.
      ENDDO.
	ADDI T1,N1CST-TMPCST	;SKIP OVER REST OF THIS CST
	SOJG T3,TOP.		;DO ALL CSTS
     ENDDO.
	MOVE T2,CSTVA		;INIT THE CSTS TO 0
	SETZM 0(T2)
	HRL T1,T2
	HRRI T1,1(T2)
	ADDI T2,TMPCST*NCSTS*PGSIZ
	BLT T1,-1(T2)
	MOVEI T1,NACST*PGSIZ	;SPACE USED BY CSTS
	ADD T1,FREMEM		;UPDATE FREE
	LSH T1,-PGSFT		;FREMEM IS PAGE NUMBER FROM HERE ON
	MOVEM T1,FREMEM
	; ..
;Now init MMAP.  We only put known PSECTS into MMAP, so space between PSECTS
;will not be mapped.  Later we will scan CST0, and put all unmapped pages on
;RPLQ.  The symbol table will go into SYMMAP instead of MMAP.

PGRI19:	MOVE P2,MMSPTN		;LOAD PGRIGR'S CONSTANTS: OWNING MAP
	MOVE P3,[IFIW MMAP(P1)]	;INDIRECT POINTER TO OWNING MAP

	MOVSI P1,-RSCODP	;MAP PAGES BELOW RSCOD
	CALL PGRIGR		;MAP GROUP
	 JRST PGRIX1		;IMPOSSIBLE

	MOVE P1,[RSCODP-RSCODL-1,,RSCODP] ;RESIDENT CODE
	MOVE T1,DBUGSW		;GET DEBUGGING FLAG
	SKIPN WEFLAG		;WANT MONITOR WRITE-ENABLED?
	CAIL T1,2		;ARE WE IN DEBUGGING MODE?
	IFNSK.
	  CALL PGRIGR		;YES. WRITE-ENABLE RESIDENT MONITOR
	   JRST PGRIX1		;IMPOSSIBLE
	ELSE.
	  CALL PGRIGP		;WRITE-PROTECT RESIDENT MONITOR
	   JRST PGRIX1		;IMPOSSIBLE
	ENDIF.


	MOVE P1,[INCODP-INCODL-1,,INCODP] ;INIT CODE
	CALL PGRIGR		;MAP GROUP
	 JRST PGRIX1		;IMPOSSIBLE

;DON'T MAP PPVAR, SINCE THEY'RE JUST TEMP MAP SLOTS

	MOVE P1,[RSDATP-RSDATL-1,,RSDATP]	;RESIDENT DATA, NON-ZEROED
	CALL PGRIGR		;MAP IT
	 JRST PGRIX1		;IMPOSSIBLE

	MOVE P1,[RSVARP-RSVARL-1,,RSVARP]	;RESIDENT VARS
	CALL PGRIGR		;MAP GROUP
	 JRST PGRIX1		;IMPOSSIBLE

	CALL HSINI2		;Setup symbol section

;SET UP LOCATIONS FOR BIT TABLE

	CALL INITBT		;SETUP INITIAL BTB SIZES
;Map the CSTS into SYMSEC.

	MOVE P2,SYMBAS		;SYMSEC ID
  IFN FTNSPSRV < ;[6.0]
	MOVEI P3,RSVAR		;START THEM AFTER RES DATA
  >
  IFE FTNSPSRV < ;[6.1]
;The virtual address of the CST's is just after the symbol table.
; The symbol table begins after BGPTR, and is of length SYMLEN
	HRRZ P3,SYMEND		;Get section-local ending address of symbols
	ADDI P3,PGSIZ		;Move to next page
	ANDX P3,VPGNO		; and make page boundary
  >
	MOVE T1,P3		;CONSTRUCT VIRTUAL ADDRESS
	ANDX T1,-PGSIZ
	HRLI T1,SYMSEC
	MOVEM T1,CSTVA
	LSH P3,-PGSFT
	ADD P3,[IFIW SYMMAP(P1)] ;INDIRECT POINTER TO OWNING MAP
	MOVSI P1,-NACST		;NUMBER PAGES NEEDED FOR CSTS
	MOVE T1,CSTLOC		;GET BEGINNING PHYS ADDRESS OF CSTS
	LSH T1,-PGSFT		;GET PAGE NUMBER
	HRR P1,T1		;-COUNT,,PAGE NUMBER
	SUBM P3,T1		;COMPUTE OFFSET IN MAP POINTER
	HRR P3,T1
	CALL PGRIGL		;MAP CSTS AND LOCK
	 JRST PGRIX1		;IMPOSSIBLE
	MOVE T1,CSTVA
	CALL STCSTX		;SETUP NEW INDIRECT POINTERS

;We can now tell the hardware about the new location of CST0.  The
;temporary one will be forgotten and those pages put on
;the replacable queue eventually.

	CALL PAGRST		;() SET PAGER CONSTANTS TO MICROCODE
;Enough page structure has now been built so that DDT and the symbols
;have appeared in the symbol section. DDT has an entry point that will
;reset DDT's environment when it is called, i.e. it will set inter-section
;breakpoints for all the monitor code.

	MOVSI T1,SYMSEC		;VIRTUAL SECTION FOR SYMBOLS
	MOVEM T1,MONEDV+.EDSEC	;SECTION NUMBER OF SYMTAB

   IFN FTNSPSRV <
	XJRST [SYMSEC,,.+1]	;get into DDT section so breakpoint will work
DDTINI:	XCT DDTIBP		;DDT breakpoint will auto proceed so DDT
				;finds out about new state of world
	XJRST [MSEC1,,.+1]	;GET INTO SECTION 1 AND STAY THERE
   >

   IFE FTNSPSRV < ;RSCOD is not mapped into SYMSEC any more

;Define new symbol table location to EDDT
	MOVE T1,SYMEND		;[7215] GET END OF SYMBOL TABLE
	ADDI T1,1		;[7215] MOVE BEYOND IT
	CALL UDDTSP		;[7215] SET NEW UPPER LIMIT
	XJRST [MSEC1,,.+1]	;Time to move to section 1
	JSR @[SYMSEC,,FAKDDT]	;Set DDT environment
   >

;Finish zeroing the CSTs now that we have all of them mapped.

	MOVE T1,CSTVA
	MOVEI T2,NCSTS		;DO 4 CSTS
      DO.
	ADDI T1,TMPCST*PGSIZ	;SKIP OVER PART PREVIOUSLY CLEARED
	MOVEI T3,<N1CST-TMPCST>*PGSIZ ;AMOUNT LEFT TO DO
       DO.
	SETZM 0(1)
	ADDI T1,1
	SOJG T3,TOP.		;LOOP FOR ONE CST
       ENDDO.
	SOJG T2,TOP.		;LOOP FOR ALL CSTS
      ENDDO.
;Clear the temporary mappings in MMAP and continue setting it up.

	MOVEI T1,NRVAR/PGSIZ	;CLEAR ALL NON-RES AREAS
      DO.
	SETZM MMAP(T1)
	CAIGE T1,PGSIZ-1	;TO END OF MAP?
	AOJA T1,TOP.		;LOOP FOR ALL ENTRIES
      ENDDO.

;Setup the swappable monitor

	MOVE P2,MMSPTN		;LOAD PGRIGR'S CONSTANTS: OWNING MAP
   IFN FTNSPSRV < ;[6.0]
	MOVE P3,[IFIW MMAP-<<MSEC1,,0>/PGSIZ>(P1)]
				;INDIRECT POINTER TO OWNING MAP
	MOVE P1,[NRCODP-NRCODL-1,,<MSEC1,,NRCOD>/PGSIZ]
   >
   IFE FTNSPSRV < ;[6.1]
	MOVE P3,[IFIW (P1)]	;Indirect through P1
	MOVE P1,PNRCOD		;Get POSTLD location of NRCOD
	LSH P1,-PGSFT		; and get page #
	MOVEI T2,MMAP		;Get address of MMAP
	SUB T2,P1		; - POSTLD page #
	ADDI T2,NRCOD_-PGSFT	; + NRCOD page #
	HRR P3,T2		;Finished building indirect word
	HRLI P1,NRCODP-NRCODL-1	;# of pages to map
   >
	MOVE T1,DBUGSW		;GET DEBUGGING FLAG
	SKIPN WEFLAG		;WANT MONITOR WRITE-ENABLED?
	CAIL T1,2		;ARE WE IN DEBUGGING MODE?
	IFNSK.
	  SETZM SWPMWF		;INITIALIZE FLAG
	  CALL PGRIGR		;YES. WRITE-ENABLE SWAPPABLE MONITOR
	   JRST PGRIX1		;IMPOSSIBLE
	ELSE.
	  SETOM SWPMWF		;INITIALIZE FLAG
	  CALL PGRIGP		;WRITE-PROTECT SWAPPABLE MONITOR
	   JRST PGRIX1		;IMPOSSIBLE
	ENDIF.
;Now reset the pager. The reason for doing that here is:
;
; Early in pager initialization temporary CST's are set up.  The translations
; for these pages will get into the translation cache. If we dont call PAGRST
; here, the translations might remain for a long time in the cache. This
; provides a problem for EDDT when it tries to find a virtual address to match
; a physical one.  EDDT searches from virtual page 0 to page 37777; and the MAP
; instruction might indicate (since translation cache wasnt invalidated) the
; temporary CTS's in section 0 instead of the real ones in section SYMSEC.
; Note: these would only be a problem if you set an early breakpoint in EDDT,
; otherwise the translations will get flushed from the cache.

	CALL PAGRST		;Reset pager

;SET UP THE JSB TO INDIRECT THROUGH JOBBAS

	MOVE T4,[JSVARP-JSVARL-1,,JSVARP]
	MOVE T1,INDPTR		;CONSTRUCT INDIRECT PTR
	MOVE T2,JOBBAS
	STOR T2,SPTX,T1
	MOVEI T2,JOBMAP-JSBPGA
	STOR T2,IPPGN,T1
PGRI3:	MOVEM T1,MMAP(T4)	;STORE IN MON MAP
	AOS T2			;BUMP POINTER
	STOR T2,IPPGN,T1
	AOBJN T4,PGRI3		;DO ALL JOB AREA

;SETUP PSB TO INDIRECT THROUGH PSBBAS

	MOVE T4,[PSVARP-PSVARL-1,,PSVARP]
	MOVE T2,PSBBAS		;CONSTRUCT INDIRECT PTR
	STOR T2,SPTX,T1
	MOVEI T2,PSBMAP-PSBPGA
	STOR T2,IPPGN,T1
PGRI5:	MOVEM T1,MMAP(T4)	;STORE IN MON MAP
	AOS T2			;BUMP POINTER
	STOR T2,IPPGN,T1
	AOBJN T4,PGRI5		;DO ALL PROCESS AREA
	; ..
;NOW SET UP SHARE POINTERS TO THE MAP PAGES OF THE JSB AND PSB

PGRI50:	MOVE T1,SHRPTR		;SETUP SHARE POINTER TO PSB AND JSB
	MOVE T2,PSBBAS		; VIA SPECIAL BASE ADDRESS WORDS
	STOR T2,SPTX,T1
	MOVEM T1,MMAP+PSBPG
	MOVE T2,JOBBAS
	STOR T2,SPTX,T1
	MOVEM T1,MMAP+JSBPG
	MOVE T2,PS2BAS
	STOR T2,SPTX,T1
	MOVEM T1,MMAP+PS2PG

;NOW LOCK INIT CODE, SYMBOL TABLE, AND RESIDENT VARS.
;INIT CODE AND SYMBOL TABLE UNLOCKED IF NOT NEEDED AT GETSWM.

	MOVE T1,RSVABP		;BOUND PAIR TO RESIDENT VARS
	XMOVEI P2,MLKSPN	;Lock routine to call
	CALL BSMGP		;LOCK THE RESIDENT VARS
	MOVE T1,INCOBP		;BOUND PAIR FOR INIT CODE
	CALL BSMGP		;LOCK THE INIT CODE
	MOVE T1,RSDABP		;BOUND PAIR FOR RESIDENT DATA
	CALL BSMGP		;LOCK RESIDENT DATA, NON-ZEROED
	MOVE T2,SYMBAS		;SPT index of SYMSEC page table
  IFN FTNSPSRV < ;[6.0]
	MOVE T1,SYTBBP		;BOUND PAIR FOR SYMBOL TABLE
  >
  IFE FTNSPSRV < ;[6.1]
	HRL T1,SYMSTA		;Get section-local part of start address of
				; symbol table
	HRR T1,SYMEND		;  and get section-local part of ending addr
  >
	CALL BSMGG		;Lock the symbol table

  IFN FTNSPSRV < ;[6.0]
	MOVE T1,[ERCOD,,ERCODZ]
  >
  IFE FTNSPSRV < ;[6.1]
	MOVE T1,[ERCOD&777777,,ERCODZ&777777] ;ERCOD
  >
	CALL BSMGG		;Lock EDDT
;Make separate section 1

	SKIPN MSEC1F		;SECTION 0, 1 DIFFERENT?
      IFSKP.
	CALL MMSECN		;(/T1) MAKE A SECTION
	MOVEM T1,P2		;SAVE SECTION 1 ID
	CALL SETSPG		;(T1) MAP THE SECTION 1 PT
	MOVSI Q1,-PGSIZ		;INIT TO FILL SEC 1 PT WITH IND PTRS
	MOVE Q2,INDPTR
	MOVE T1,MMSPTN		; TO SAME PAGE OF SECTION 0
	STOR T1,SPTX,Q2
      DO.
	MOVEM Q2,CSWPGA(Q1)	;STORE POINTER IN SEC 1 MAP
	INCR IPPGN,Q2		;STEP TO NEXT SEC 0 PAGE
	AOBJN Q1,TOP.		;STEP TO NEXT SEC 1 PAGE
      ENDDO.
	MOVE T1,[RSCODP-RSCODL-1,,RSCODP]
	CALL MOVMM1		;(T1) COPY RSCOD PTRS FROM SEC 0 TO SEC 1
	CALL RELSPG		;() RELEASE SEC 1 PT
	MOVE T1,SHRPTR		;MAKE THE SECTION 1 POINTER
	STOR P2,SPTX,T1
	MOVEM T1,MSECTB+MSEC1	;CHANGE TO SEPARATE PT
	MOVEM P2,M1SPTN		;SET NEW SECTION 1 ID
	CALL PGRCLD		;FORCE PAGER REFILL
	MOVX T1,RSCODP		;CLEAR RSCOD PTRS FROM SEC 0 MAP
	MOVX T2,RSCODL
	MOVE T3,MSEC1F
	CAIE T3,1		;SETUP INDIRECT PTRS?
	IFSKP.
	  CALL MM0IND		;(T1,T2) YES
	ELSE.
	  CALL MM0CLR		;(T1,T2) NO, CLEAR SECTION 0
	ENDIF.
      ENDIF.
	XMOVEI T1,MEMOFF
	CALL SETPFH		;MAKE THIS BE PAGE FAULT HANDLER FOR NOW
  IFE FTNSPSRV < ;[6.1]
;Create the extended code section, and set up the map
	CALL XCDINI		;..
GOTXCD:
  >

;Create the monitor sections and init page tables.

	MOVE Q1,[MFSEC0-FFMSEC,,MFSEC0] ;INIT TO CREATE MONITOR SECTIONS
      DO.
	CALL MMSECN		;(/T1) CREATE MONITOR SECTION
	MOVE T2,SHRPTR		;MAKE A SHARE POINTER FOR MSECTB
	STOR T1,SPTX,T2
	MOVEM T2,MSECTB(Q1)
	AOBJN Q1,TOP.		;DO ALL SECTIONS
      ENDDO.
	JRST PGRI60		;CONTINUE
;LOCAL ROUTINES FOR ABOVE

;Create Monitor Section
;Assumes:
; FREMEM/ Next available physical page
;	CALL MMSECN
;Returns +1 always,
; T1/ SPT index of section

MMSECN:	SAVEAC <Q1,P1>
	CALL ASSPT
	MOVEM T1,Q1		;SAVE SPTN
	MOVX T2,USHR
	MOVEM T2,SPT(Q1)	;SETUP SPT SLOT
	MOVE P1,FREMEM
	AOS FREMEM
	STOR P1,STGADR,SPT(Q1)	;MAKE IT POINT TO NEXT FREE CORE PAGE
	SETZM SPTH(Q1)
	MOVX T2,PSASM!CSWRB	;INIT CST ENTRIES FOR PAGE
	MOVEM T2,@CST0X+P1
	MOVX T2,PLKV+UAAB
	MOVEM T2,@CST1X+P1
	MOVEM Q1,@CST2X+P1
	MOVX T2,<FLD(OFNUL,CSTOFK)>
	MOVEM T2,@CST3X+P1
	MOVE T1,Q1
	CALL SETSPG		;(T1) MAP THE PT
	MOVE T1,[CSWPGA,,CSWPGA+1]
	SETZM CSWPGA		;ZERO IT
	BLT T1,CSWPGA+PGSIZ-1
	CALL RELSPG		;()
	MOVE T1,Q1		;RETURN SPTN
	RET
;Move PSECT from section 0 to section 1 by copying pointers.
; T1/ -COUNT,,FIRST PAGE
;	CALL MOVMM1
;Returns +1 always

MOVMM1:	SAVEAC <Q1,Q2>
	MOVEM T1,Q1		;SAVE AOBJN PTR
	MOVE Q2,M1SPTN		;THE SECTION 1 MAP ID
      DO.
	MOVE T1,MMAP(Q1)	;MOVE POINTER FROM SEC 0 PT TO SEC 1 PT
	MOVEM T1,CSWPGA(Q1)
	IFN. T1			;IF POINTER NOT NULL,
	  LOAD T1,STGADR,T1	;LOOK AT ADDRESS OF PAGE
	  TXNN T1,NCORTM		;IN CORE?
	  HRLM Q2,@CST2X+T1	;YES, UPDATE CST2 FOR NEW OWNER
	ENDIF.
	AOBJN Q1,TOP.		;ALL PTRS
      ENDDO.
	RET

;Clear PSECT from section 0 map after pointers moved to section 1 map
;and PC jumped to 1 if necessary.
; T1/ First page number
; T2/ Last page number, inclusive
;	CALL MM0CLR
;Returns +1 always

MM0CLR:
      DO.
	SETZM MMAP(T1)		;CLEAR FIRST PAGE
	CAMGE T1,T2		;DONE ALL OF RANGE?
	AOJA T1,TOP.		;DO ALL
      ENDDO.
	CALL PGRCLD		;CLEAR PAGER
	RET
;Routine called after swpmon loaded to make NRCOD be in section 1 only.
;No args
;	CALL MOVNRC
;Returns +1 always

MOVNRC::MOVE T1,MSEC1F
	CAIE T1,2		;VANISH CODE FROM 0?
	RET			;NO, CHICKEN OUT
	MOVX T1,NRCODP		;FLUSH NRCOD FROM SEC 0
	MOVX T2,NRCODL
	CALL MM0CLR		;(T1,T2)
	RET

;Setup indirect pointers to make section 0 pages point to section 1 map.
; T1/ First page of range
; T2/ Last page of range, inclusive.
;	CALL MM0IND
;Returns +1 always.

MM0IND:	SAVEAC <P1,P2>
	MOVE P1,INDPTR		;BUILD INITIAL INDIRECT PTR
	MOVE P2,M1SPTN
	STOR P2,SPTX,P1
	STOR T1,IPPGN,P1	;TO SAME PAGE IN DEST MAP
      DO.
	MOVEM P1,MMAP(T1)
	INCR IPPGN,P1		;STEP INDIRECT POINTER
	CAMGE T1,T2		;END OF RANGE?
	AOJA T1,TOP.		;DO ALL
      ENDDO.
	CALL PGRCLD		;GET THEM SEEN
	RET
;Get pages for the extended resident storage.  Use the physical
;pages following the section PTs -- the page number was left in FREMEM by
;the above code.

PGRI60:	MOVE P1,FREMEM
	LOAD P2,SPTX,MSECTB+RESSEC	;ID OF PAGE TABLE
	MOVE T1,P2
	CALL SETSPG		;MAP RESSEC PT FOR LOCAL USE
	HRLI P1,-<ERVARZ-ERVAR+PGSIZ>/PGSIZ ;NEG COUNT OF PAGES NEEDED
	MOVE P3,[IFIW CSWPGA+<ERVAR&LPGNO>/PGSIZ(P1)]	;PTR TO MAP
	SUBI P3,0(P1)		;OFFSET FOR RIGHT PLACE IN MAP
	CALL PGRIGL		;GRAB MEM AND SETUP MAP
	 NOP			;DON'T CARE IF BOOT SKIPPED
	MOVE T1,MSECTB+RESSEC	;PUT MAPPING OF SECTION IN ITSELF
	MOVX T2,<RSECMP&LPGNO>/PGSIZ
	MOVEM T1,CSWPGA(T2)

  IFE FTNSPSRV < ;[6.1]
	MOVE T1,MSECTB+XCDSEC	;Get map pointer to extended code section
	MOVX T2,<XCDMAP&LPGNO>/PGSIZ ;And offset to extended page map in RESSEC
	MOVEM T1,CSWPGA(T2)	;Save mapping (XCDMAP now has XCDSEC PT)
  >

	CALL RELSPG		;RELEASE MAPPING OF RESSEC PT


;Map all monitor extended section page tables into an area beginning
;at EMMAPS for convenience in looking at them with DDT.

   REPEAT 0,<			;Maybe this isn't such a hot idea
	MOVEI T2,MFSEC0
      DO.
	MOVE T1,MSECTB(T2)
	LOAD T3,PTRCOD,T1
	CAIE T3,SHRCOD		;SHARE POINTER?
	IFSKP.
	  MOVEI T3,<EMMAPS&LPGNO>/PGSIZ(T2)
	  MOVEM T1,@[EP. RSECMP(T3)]
	ENDIF.
	CAIGE T2,FFMSEC-1
	AOJA T2,TOP.
      ENDDO.
   >				;END REPEAT 0

	MOVEI T1,0		;CLEAR THE RSE AREA
      DO.
	SETZM @[EP. ERVAR(T1)]
	CAIGE T1,ERVARZ-ERVAR
	AOJA T1,TOP.
      ENDDO.
	; ..
	; ..
	SETOM DDXLOK		;INIT XB CHECK LOCK

;Here to set up replaceable queue using all available memory.

	SETZM TOTRC		;INIT TOTRC

;Initialize special memory queue

	SETZM NSPMQ		;INITIALIZE SPMQ
	SETOM SPMLCK		;SPMQ USER INTERLOCK
	SETOM SPMONR		;FORK OWNING SPMLCK
	SETZM NRPLQ
	CLNXMF			;CLEAR APR NXM CONDITION (NOP ON KC)

;Initialize two replaceable queues and SPMQ

	MOVE T2,CSTVA		;START OF CST0
	ADDI T2,3*MAXCOR	;START OF CST3
	MOVE T3,T2		;PRESERVE IT
	ADDI T3,SRPLQO		;SET SWAP
	MOVEM T3,SRPLQ		; REPLACEABLE QUEUE
	MOVE T3,T2
	ADDI T3,DRPLQO		;SET DISK
	MOVEM T3,DRPLQ		; REPLACEABLE QUEUE
	MOVE T3,T2
	ADDI T3,SPMQO		;SET SPECIAL MEMORY
	MOVEM T3,SPMQ		; QUEUE
	MOVE T2,[SRPLQO,,SRPLQO]
	MOVEM T2,@SRPLQ		;INIT RPLQ'S
	MOVE T2,[DRPLQO,,DRPLQO]
	MOVEM T2,@DRPLQ
	MOVSI T1,SPMQO		;SET TAIL POINTER
	MOVEM T1,@SPMQ		; ...

	COMMENT %
	Don't do this for now

;First put BOOT's pages on SPMQ to protect them

	HRRZ Q1,BUTPHY		;Get first pages
	LSH Q1,-PGSFT		;Make a page number
	HLL Q1,BUTPHY		;Get count
	IFN. Q1			;Only if something to do
	 DO.
	  MOVEI T1,0(Q1)	;Page number
	  CALL ONSPMQ		;Put it on the queue
	  AOBJN Q1,TOP.		;Do them all
	 ENDDO.
	ENDIF.
	;..
	%	;End comment
;Here to start scan. Touch all pages that the monitor knows about unless they
;have already been assigned. If they exist, put them on the replaceable
;queue. If not, put them on the special memory queue.

	;..
	MOVE Q1,MONCOR		;START SCAN AT END OF RSCOD
PGRI2:	SKIPE @CST0X+Q1		;PAGE MAPPED BY PGRINI?
	JRST PGRI4A		;YES, NOT AVAILABLE FOR RPLQ
	MOVX T2,PSASM		;SET LEGAL AGE FOR TEST REFERENCE
	MOVEM T2,@CST0X+Q1
	SETZM @CST1X+Q1		;CLEAR CST ENTRIES
	SETZM @CST2X+Q1
	SETZM @CST3X+Q1
	MOVE T1,Q1		;GET PHYS PAGE NUMBER
   IFN KLFLG,<
	CALL MAPRCA		;MAP IT
PGRI2A::MOVE T2,0(T1)		;TRY TO REFERENCE IT
	MOVE T2,1(T1)		;TRY 3 OTHER WORDS IN CASE INTERLEAVED
	MOVE T2,2(T1)
	MOVE T2,3(T1)
   >
   IFN KCFLG,<

; * * * *
;This code may not be necessary in the final version
; * * * *
	LSH T1,^D9		;GET PHYSICAL ADDRESS OF START OF PAGE
PGRI2A::PMOVE T2,T1		;TOUCH FIRST WORD
	AOS T1
	PMOVE T2,T1
	AOS T1
	PMOVE T2,T1
	AOS T1
	PMOVE T2,T1
   >
	;..
;Here when no error occurred. Page exists. At runtime, we can patch NLOWPG
;and NMAXPG to bound memory further, simulating smaller configurations. Place
;on the special memory queue any pages outside of those bounds.

	;..
PGRI6::	CAML Q1,NLOWPG		;EXCLUDE PAGES BELOW BOUNDARY
	CAMLE Q1,NMAXPG		;ABOVE MAX?
	IFNSK.
	  CALL TRNOFF		;TURN PAGE OFF
	ELSE.

;Page exists. Put it on the replaceable queue

	  SETZM @CST0X+Q1		;NO, PAGE EXISTS
	  MOVEM Q1,NHIPG		;REMEMBER HIGHEST PAGE FOUND
	  MOVE T1,Q1
	  CALL ONRQ		;PUT PAGE ON REPLACABLE QUEUE (RETURNS PION)
	  PIOFF
PGRI4A:	  AOS TOTRC		;COUNT PAGES OF CORE FOUND
	ENDIF.
PGRI4:				;RETURN HERE FROM PAGER TRAP
	CAIGE Q1,MAXCOR-1	;CHECK ALL POSSIBLE CORE
	AOJA Q1,PGRI2

;Here when all memory has been scanned.

	XMOVEI T1,KIPFS		;RESTORE NORMAL PAGE FAULT HANDLER
	CALL SETPFH		; IN SCHEDULER CONTEXT
	SETZM PAGDIF		;NO PAGE DIFFERENCES AS OF NOW
	CALL MEMSTR		;SET UP MEM CONTROLLERS IF APPROPRIATE
	; ..
;SETUP VARIOUS CONSTANTS FOR CORE MGT

	CALL MEMMGT		;SET UP PAGING PARAMETERS
	MOVEI T1,LGABOT
	MOVEM T1,CURAGE		;SET INITIAL GCCOR VALUES
	MOVEM T1,CUTAGE
	CALL LDAGER		;LOAD AGE REGISTER
	BLCAL. ASGVAS,<[0],[SECSIZ]> ;ASSIGN A SECTION FOR SCA
	 BUG.(HLT,NOFSEC,PAGUTL,SOFT,<ASGVAS failure at startup>,,<

Cause:	ASGVAS was called to get a free section for SCA at
	startup but failed.
>)
	HLRZM T1,EPGSEC
	MOVE T1,EPGSEC
	MOVE T1,MSECTB(T1)	;MAP EPG PT INTO NRPE SLOT
	MOVX T2,<EPGMAP&LPGNO>/PGSIZ
	MOVEM T1,@[EP. RSECMP(T2)]
	LOAD T1,SPTX,T1
	CALL UPSHR
	CALL MLKPG		;LOCK THE PT--MAY REF AT INTERRUPT LEVEL
	CALL PGRCLD		;CLEAR THE PAGER

	SETZM XRESFL		;INDICATE EXTENDED FREE SPACE CAN BE ALLOCATED
	CALL MOVCST		;() Fixup CSTs - unlock unused pages.
; * * * *
;Set up "keep" bit for RSCOD,RSVAR,RSDAT, and XRCOD
;Don't try to use this while splitting maps

	SKIPE MSEC1F		;SPLITTING MAPS?
	IFSKP.
	  APRID T1		;NO. GET HARDWARE OPTIONS
	  TXNN T1,MCA25		;IS MCA25 HARDWARE PRESENT?
	  IFSKP.
	    MOVX T1,PTKEEP		;GET THE KEEP BIT
	    IORM T1,MSECTB+XCDSEC	;SET IT IN SECTION MAP
	    IORM T1,MSECTB+RESSEC	;SET IT IN SECTION MAP
	    MOVE T2,[RSCODP-RSCODL-1,,RSCODP] ;YES. SETUP AOBJN POINTER
	    HRRZ T3,T2			;SET UP INDEX FOR EXTENDED SECTION
JHLOOP:	    IORM T1,MMAP(T2)		;SET "KEEP ME" FOR THIS PAGE
	    IORM T1,@[EP. XCDMAP(T3)]	
	    AOS T3
	    AOBJN T2,JHLOOP
	    MOVE T2,[RSDATP-RSDATL-1,,RSDATP] ;YES. SETUP AOBJN POINTER
	    HRRZ T3,T2
JHLT2:	    IORM T1,MMAP(T2)		;SET "KEEP ME" FOR THIS PAGE
	    IORM T1,@[EP. XCDMAP(T3)]
	    AOS T3
	    AOBJN T2,JHLT2
	    MOVE T2,[RSVARP-RSVARL-1,,RSVARP] ;YES. SETUP AOBJN POINTER
	    HRRZ T3,T2
JHLP2:	    IORM T1,MMAP(T2)		;SET "KEEP ME" FOR THIS PAGE
	    IORM T1,@[EP. XCDMAP(T3)]
	    AOS T3
	    AOBJN T2,JHLP2
	    MOVE T2,[XRCODP-XRCODL-1,,XRCODP]	;DO EXTENDED RESIDENT CODE
	    TRZ T2,777000		;GET PAGE NUMBER ONLY
	    HRRZ T3,T2
JHLP3:	    IORM T1,@[EP. XCDMAP(T3)]	;SET "KEEP"
	    AOS T3
	    AOBJN T2,JHLP3
	    MOVE T2,[ERVARP-ERVARL-1,,ERVARP]	;DO EXTENDED VARIABLES
	    TRZ T2,777000		;GET PAGE NUMBER ONLY
	    HRRZ T3,T2
JHLP4:	    IORM T1,@[EP. RSECMP(T3)]	;SET "KEEP"
	    AOS T3
	    AOBJN T2,JHLP4
				;NOW DO CST0,CST1,CST2,CST3 IN SYMMAP.
	    HLRZ T2,CST0X	;GET THE SECTION NUMBER
	    ANDI T2,37		;MAKE SURE JUST THE SECTION NUMBER
	    IORM T1,MSECTB(T2)	;SET THE KEEP BIT IN SECTION MAP
	    HRRZ T2,CST0X	;GET STARTING PAGE FOR CST0X.
	    LSH T2,-PGSFT	;JUST THE PAGE.
	    MOVSI T3,-1*NCSTS*N1CST	;MAKE AOBJN POINTER.
	    HRR T3,T2		;CONTINUE MAKING AOBJN POINTER
JHLP5:	    SKIPE SYMMAP(T3)	;IS THERE AN ENTRY
	    IORM T1,SYMMAP(T3)	;YES. SET THE BIT
	    AOBJN T3,JHLP5	;DO ALL CST0,CST1,CST2,CST3 ENTRIES.
	  ENDIF.
	ENDIF.
; * * * *

	CALL PGRCLD		;CLEAR THE PAGER
	CALL STKEEP		;START KEEPING KEPT ENTRIES
	SKIPN MSEC1F		;SECTIONS 0/1 SPLIT?
      IFSKP.
	MOVE T1,M1SPTN		;YES, MAP SEC 1 PT
	CALL SETSPG		;(T1)
	MOVE T1,[NRCODP-NRCODL-1,,NRCODP]
	CALL MOVMM1		;(T1) MAKE NRCOD BE IN SEC 1 (ALL 0'S NOW)
	MOVX T1,NRCODP		;SETUP INDIRECT PTRS FOR NOW
	MOVX T2,NRCODL
	CALL MM0IND		;(T1,T2)
	CALL RELSPG		;()
      ENDIF.
	RET
; PGRSKD -- ALLOCATE LOCKED MEMORY FROM SCHEDULER CONTEXT

;THIS ROUTINE ASSIGNES PAGES FROM A NON-ZERO SECTION OF AVAILABLE SPACE.
; IT FUNCTIONS AS A JACKET FOR ASGVAS
;
; USAGE:
;	CALL
;	T1/	NUMBER OF PAGES TO ASSIGN
;
;	RETURN (+1)
;	T1/	FAILURE
;
;	RETURN (+2)
;	T1/	ADDRESS OF FIRST PAGE
;			 ==> THIS ADDRESS IS THE FIRST PAGE IN A LIST
;					OF N PAGES. THE FIRST WORD OF EACH PAGE
;					CONTAINS THE ADDRESS OF THE NEXT
;					PAGE IN THE LIST. THE LAST PAGE HAS A
;					NEXT POINTER OF ZERO.
;	T2/	NUMBER OF PAGES ACTUALLY RETURNED

PGRSKD::EA.ENT			;BE SURE WE RUN IN A NON-ZERO SECTION
	STKVAR <NPGS>		;PLACE TO SAVE NUMBER OF PAGES
	MOVEM T1,NPGS		;SAVE IT
	IMULI T1,PGSIZ		;CONVERT TO WORDS
	BLCAL. (ASGVAS,<[AV%LOK],T1>) ;GET PAGES AND LOCK THEM IN
	 RET			;CAN'T
;
; WE HAVE THE PAGES LINK THEM IN A CHAIN
;
	MOVE T2,NPGS		;GET NUMBER OF PAGES
	SOS T2			;MINUS 1
	MOVE T3,T1		;ADDRESS OF FIRST PAGE
	MOVE T4,T1		;ADDRESS OF LINK
	JUMPE T2,PGRSK2		;IF A SINGLE PAGE DON'T LOOP
PGRSK1:	ADDI T4,PGSIZ		;POINTER TO NEXT PAGE
	MOVEM T4,(T3)		;STORE NEXT POINTER
	ADDI T3,PGSIZ		;NOW POINT TO NEXT PAGE
	SOJG T2,PGRSK1		;LOOP FOR ENTIRE LIST
PGRSK2:	SETZM (T3)		;LAST PAGE POINTS NOWHERE
	MOVE T2,NPGS		;GET VALUE TO RETURN
	RETSKP			;AND DONE
;PGRIGR - SET UP MMAP/SYMMAP AND CSTS FOR A GROUP OF PAGES
;CALL:
; P1/ AOBJN PTR TO PAGES
; P2/ SPT INDEX OF OWNER MAP
; P3/ INDIRECT WORD TO OWNER MAP INDEXED BY P1
;
;	CALL PGRIGR (FOR WRITE-ENABLED)
;		OR
;	CALL PGRIGP (FOR WRITE-PROTECTED)
;		OR
;	CALL PGRIGL (FOR LOCKED AND WRITE-ENABLED)

;RETURN +1 if pages assigned are not the ones requested, e.g. if BOOT
;	  was skipped.
;	+2: pages assigned as requested.

;Internal flags:
PGRIWP==1B0			;WRITE PROTECT PAGES
PGRILK==1B1			;LOCK IN CORE

PGRIGL:	MOVX T3,PGRILK		;ENTRY FOR LOCK PAGES TOO
	JRST PGRIG

PGRIGR:	TDZA T3,T3		;WANT TO LEAVE FULL ACCESS
PGRIGP:	MOVX T3,PGRIWP		;WANT TO TURN OFF WRITE ACCESS
PGRIG:	SAVEAC <Q1,Q2,P4>
	STKVAR <PGRIC>		;NEG COUNT OF PAGES TO DO
	MOVE Q2,T3		;SAVE FLAGS
	MOVE T3,IMMPTR		;MAKE BASE POINTER
	TXNE Q2,PGRIWP		;WRITE PROTECT?
	TXZ T3,PTWR		;YES, REMOVE BIT
	HRRZ T1,BUTPHY		;GET START OF BOOT
	HLRE Q1,BUTPHY		;CALCULATE END OF BOOT
	MOVM Q1,Q1
	LSH T1,-PGSFT
	JUMPGE P1,R		;CHECK FOR EMPTY GROUP
	HLREM P1,PGRIC		;SAVE COUNT AS NEG FULL WORD
	HRRZ P1,P1		;PAGE NUMBER ONLY IN P1
	MOVE P4,P1		;GET START OF REQUESTED AREA
	CAML P4,T1		;START BELOW BOOT?
	IFSKP.
	  SUB P4,PGRIC		;CALCULATE END
	  CAMLE P4,T1		;END ALSO BELOW BOOT?
	  HRRI P1,1B18		;NO, MUST SKIP BOOT
	ELSE.
	  CAMGE P4,Q1		;REQUESTED AREA ABOVE BOOT?
	  HRRI P1,1B18		;NO, MUST SKIP BOOT
	ENDIF.
	TRNN P1,1B18		;SKIPPING BOOT
	IFSKP.
	  HRR P1,Q1		;YES, START WITH PAGE AFTER BOOT
	  SETZ Q1,		;FLAG FOR RETURN
	ENDIF.
	LOAD P4,STGADR,SPT(P2)	;GET CORE PAGE FOR MAP
				; WRITE ACCESS
PGRIG2:	MOVX T1,PSASM!CSWRB	;INIT CST0
	MOVEM T1,@CST0X+P1	;UNASSIGNED
	MOVX T1,UAAB		;UNASSIGNED
	MOVEM T1,@CST1X+P1	;SET BACKUP ADDR TO UNASSIGNED
	CAML P1,MONCOR		;RESIDENT MONITOR?
	TXNE Q2,PGRILK		;OR LOCKING REQUESTED?
	IFNSK.
	  MOVX T1,PLKV		;YES, ALWAYS LOCKED
	  ADDM T1,@CST1X+P1	;LOCK THE PAGE
	ENDIF.

;*** NOTE THAT THIS MAKES MMAP AND SYMMAP ALWAYS BE LOCKED.
;*** THE ADDM BELOW SHOULD PROPERLY BE WITHIN THE IFSKP, BUT
;*** LCKINI/ULKINI DON'T KEEP UP THE LOCK COUNT OF THE
;*** OWNING PT, AND A HIGH LOCK COUNT IS BETTER THAN A LOW ONE...

	MOVX T1,PLKV		;MAKE SURE SET UP
	ADDM T1,@CST1X+P4	;COUNT ANOTHER LOCKED PAGE IN MAP
	HRL T1,P2		;FORM PTN.PN
	HRRI T1,@P3		; PN IS OFFSET INTO MAP
	TXZ T1,LPGNO
	MOVEM T1,@CST2X+P1	;STORE OWNER
	MOVX T1,<FLD(OFNUL,CSTOFK)>	;UNASSIGNED
	MOVEM T1,@CST3X+P1	;SET PAGE
	STOR P1,STGADR,T3	;ADD PAGE NUMBER TO ACCESS BITS
	MOVEM T3,@P3		;STORE POINTER IN APPROPRIATE MAP
	AOSGE PGRIC		;COUNT PAGES DONE
	AOJA P1,PGRIG2		;STEP PAGE NUMBER AND LOOP
	TRNN Q1,-1		;SKIPPED BOOT?
	RET			;YES
	RETSKP			;NO

;BUGHLT IF CALLER EXPECTS ONLY REQUESTED PAGES TO BE ASSIGNED

PGRIX1:	BUG.(HLT,PGRIXM,PAGUTL,SOFT,<PGRINI - Boot overlaps resident tables>,,<

Cause:	The values in BUTPHY indicate that BOOT has been left in pages
	which are expected to be available for resident code or
	storage areas.  This could be the result of a bad monitor build
	or an attempt to run the monitor with insufficient memory.
>)
;TRNOFF - Routine to turn a page offline during PGRINI's memory scan

;ACCEPTS:
;	Q1/ PAGE NUMBER OF PAGE TO BE PUT ON SPECIAL MEMORY QUEUE

;	CALL TRNOFF

;RETURNS +1: ALWAYS

TRNOFF:	MOVX T2,<FLD(PSDEL,CSTAGE)+FLD(PSTOFL,CSTPST)>
	MOVEM T2,@CST0X+Q1	;CALL IT DELETED
	RET

;MEMOFF - Special page fault handler for PGRINI's memory scan.

;Ordinarily touching a non-existent page will give us a page fault and
;an APR interrupt. This code is executed on the page fault, and it detects
;that the APR interrupt condition bit is on for NXM. However, interrupts are
;not enabled, so the bit will remain lit until we clear it. If this routine
;is reached without the APR bit on, we go handle the page fault in the
;usual manner for hard page faults.

MEMOFF:
   IFN KLFLG,<
	CONSZ APR,APNXM		;DID WE GET A NXM?
	JRST MEMOF1		;YES. THAT'S WHAT WE EXPECTED
	DMOVEM T1,PFSA1		;SAVE SOME AC'S
	MOVE T1,UPTPFW		;GET PAGE FAIL WORD
	JSP T2,PFAID		;GO ANALYZE THIS ERROR
	DMOVE T1,PFSA1		;RESTORE THEM
MEMOF1:	CLNXMF			;CLEAR APR NXM CONDITION
   	CLRMPE			;NXM GENERATED MPE, TOO. CLEAR IT
>
   IFN KCFLG,<
	LOAD T1,TWCOD,KCPFCD
;* * * *
;May have to check for "hard" fail here
; * * * *
	CAIN T1,PFCNXM
	JRST MEMOF1
	DMOVEM T1,PFSA1
	JSP T2,PFAID
	DMOVE T1,PFSA1
MEMOF1:
   >
	CALL TRNOFF
	XMOVEI T1,PGRI4		;GO CONTINUE THE SCAN
	MOVEM T1,TRAPPC
	XJRSTF TRAPFL
;Code for setting up symbol section.  Called once from above.

HSINI1:	CALL ASSPT		;GET AN SPT SLOT FOR THE SYMBOL MAP
	MOVEM T1,SYMBAS		;SAVE IN GLOBAL LOCATION
	MOVEI T2,SYMMAP_-PGSFT	;GET PHYSICAL PAGE # OF SYMMAP
	MOVEM T2,SPT(T1)	;SAVE IN SPT
	CALL UPSHR		;BUMP SHARE COUNT
	MOVE T1,[SYMMAP,,SYMMAP+1]	;CLEAR SYMMAP BEFORE FILLING BELOW
	SETZM SYMMAP		; ..
	BLT T1,SYMMAP+PGSIZ-1	; ..
	RET

;Build the map for the symbol table section
;First fill the entire map with indirect pointers to section 0.
;Some will be overwritten with the actual psects which belong
;in the symbol table section.

HSINI2:	MOVE T4,INDPTR		;canonical indirect pointer
	MOVE T3,MMSPTN		;make it indirect through MMAP
	STOR T3,SPTX,T4
  IFN FTNSPSRV < ;[6.0]
	MOVSI T1,-PGSIZ
      DO.
	STOR T1,IPPGN,T4	;make indirect pointer to same page
	MOVEM T4,SYMMAP(T1)	;put pointer in map
	AOBJN T1,TOP.
      ENDDO.

;Map symbol table

	MOVE P2,SYMBAS		;SPT INDEX OF SYMMAP
	MOVE P3,[IFIW SYMMAP(P1)] ;INDIRECT POINTER TO IT
	MOVEI P4,SYMMAP_-PGSFT	;PAGE NUMBER OF SYMMAP

	HRRZ P1,SYMMV1		;START OF SYMTAB
	LSH P1,-PGSFT		;ROUND DOWN
	MOVN T2,SYMMV2		;END OF SYMTAB
	LSH T2,-PGSFT		;ROUND UP
	ADD T2,P1		;COMPUTE NEG LENGTH IN PAGES
	HRL P1,T2
	CALL PGRIGR		;MAP PAGES OF SYMTAB
	 JRST PGRIX1		;IMPOSSIBLE
;Map psects into symbol section - BGSTR, BGPTR, ERCOD, and ENCOD.
	MOVE P1,[BGSTRP-BGSTRL-1,,BGSTRP]
	CALL PGRIGR		;(P1,P2,P3,P4)
	 JRST PGRIX1
	MOVE P1,[BGPTRP-BGPTRL-1,,BGPTRP]
	CALL PGRIGR		;(P1,P2,P3,P4)
	 JRST PGRIX1
	MOVE P1,[ERCODP-ERCODL-1,,ERCODP]
	CALL PGRIGR		;(P1,P2,P3,P4)
	 JRST PGRIX1
	MOVE P1,[ENCODP-ENCODL-1,,PENCOD_-PGSFT]
	MOVE P3,[IFIW SYMMAP+ENCODP-<PENCOD_-PGSFT>(P1)] ;OFFSET FOR VIRTUAL ADR
	CALL PGRIGR		;(P1,P2,P3,P4)
	 JRST PGRIX1

;Setup indirect pointers for MDDT's variable pages.  MDDT thinks the
;pages are at DDTPGA in its section, but they are really at DDTPXA
;in the PSB map.

	MOVE T1,INDPTR		;make indirect ptr
	MOVE T2,PSBBAS		;to PSBMAP
	STOR T2,SPTX,T1
	MOVEI T4,DDTPX+PSBM0-PSBPGA ;at DDTPXA
	MOVEI T2,DDTPG		;place in SYMMAP
	HRLI T2,-NDDTPG		;number of pages
      DO.
	STOR T4,IPPGN,T1	;set page in indirect ptr
	MOVEM T1,SYMMAP(T2)
	ADDI T4,1		;step destination
	AOBJN T2,TOP.
      ENDDO.
  >
  IFE FTNSPSRV < ;[6.1]
;Map page 0 of SYMSEC indirectly to section 0/1 map. No other parts
; of the section 0/1 map are mapped into section 5. (Page 0 is for
; EDDT/MDDT breakpoint blocks)
	MOVEM T4,SYMMAP+0	;Put pointer to page 0 in map (Page # field
				; in T4 is zero since it is never written..)

;Map symbol table into SYMSEC. The symbol table is at NRVAR(+SYMPAD) with
; length SYMLEN.
	MOVEI P1,NRVAR_-PGSFT	;Get page # of start of symbol table
	MOVN T1,SYMLEN		;Get negative length of symbol table
	LSH T1,-PGSFT		;Make into page #
	HRL P1,T1		;P1 := -count,,page #
	MOVE P2,SYMBAS		;SPT index of SYMMAP
;We can use P1 as index with the following instruction that 'relocates' the
; page # in RH of P1 to the destination index into SYMMAP. The symbol table
; is put right after BGPTR in SYMSEC.
	MOVE P3,[IFIW <SYMMAP-<NRVAR/PGSIZ>+<<BGPTRZ&777777>+PGSIZ>/PGSIZ>(P1)]
	CALL PGRIGR		;Map the symbol table into SYMSEC
	 JRST PGRIX1		; -should never happen

;Map psects into symbol section - BGSTR, BGPTR and ERCOD.
	MOVE P3,[IFIW SYMMAP-PGSIZ(P1)]	;'Relocate' since BGSTR is in section 1
	MOVE P1,[BGSTRP-BGSTRL-1,,<<XWD MSEC1,BGSTR>_-PGSFT>]
	CALL PGRIGR		;(P1,P2,P3,P4)
	 JRST PGRIX1
	MOVE P1,[BGPTRP-BGPTRL-1,,<<XWD MSEC1,BGPTR>_-PGSFT>]
	CALL PGRIGR		;(P1,P2,P3,P4)
	 JRST PGRIX1
	MOVE P3,[IFIW SYMMAP(P1)]
	MOVE P1,[ERCODP-ERCODL-1,,ERCODP&777]
	CALL PGRIGR		;(P1,P2,P3,P4)
	 JRST PGRIX1
  >
	RET
  IFE FTNSPSRV < ;[6.1]

;Create extended code section and set up its map
XCDINI:	CALL MMSECN		;Create monitor section
	MOVEM T1,XCDBAS		;Save SPT index
	MOVE T2,SHRPTR		;Make a
	STOR T1,SPTX,T2		;       share pointer
	MOVEM T2,MSECTB+XCDSEC	;Put in section table

;Map in the page table for XCDSEC into CSWPGA
	MOVE T1,XCDBAS		;Get SPT index
	CALL SETSPG		;Map XCDSEC's page table into CSWPGA

;Fill pages 0 to XRCOD-1 with indirect pointers to section 0/1
	MOVE T4,INDPTR		;Get prototype indirect pointer
	MOVE T3,MMSPTN		; and monitor SPT index
	STOR T3,SPTX,T4		;  and make pointer
	MOVSI T1,-<<XRCOD_-PGSFT>&777> ;Do all pages upto XRCOD
	DO.			;LOOP
	  STOR T1,IPPGN,T4	;  Put in page #
	  MOVEM T4,CSWPGA(T1)	;   and write to page map
	  AOBJN T1,TOP.		;  Loop back and do next page
	ENDDO.

;Now do pages NPVAR to page 777
	MOVE T1,[-1000+<NPVAR_-PGSFT>,,<NPVAR_-PGSFT>]
	DO.			;LOOP
	  STOR T1,IPPGN,T4	;  Put in page #
	  MOVEM T4,CSWPGA(T1)	;   and write to page map
	  AOBJN T1,TOP.		;  Loop back and do next page
	ENDDO.
;Map XRCOD and XNCOD
	XMOVEI P4,PGRIGP	;Assume write-protected
	MOVE T1,DBUGSW		;Get debugging flags
	SKIPN WEFLAG		;Want monitor write-enabled?
	CAIL T1,2		;Are we in debugging mode?
	XMOVEI P4,PGRIGR	; -no to one or both, write-enable
	MOVE P1,[XRCODP-XRCODL-1,,<<XWD MSEC1,XRCOD>_-PGSFT>]
	MOVE P2,XCDBAS		;SPT index
	MOVE P3,[IFIW CSWPGA-1000(P1)] ;Indirect to page map
	CALL (P4)		;Call processing routine
	 JRST PGRIX1		; - should never happen

	MOVE P1,[XNCODP-XNCODL-1,,<<XWD MSEC1,XNCOD>_-PGSFT>]
	CALL (P4)		;Call processing routine
	 JRST PGRIX1		; - should never happen

;Map ENCOD
	MOVE P1,[ENCODP-ENCODL-1,,<<XWD MSEC1,ENCOD>_-PGSFT>]
	CALL PGRIGR		;Always write-enabled
	 JRST PGRIX1		; - should never happen

;Unmap CSWPGA
	MOVE T1,XCDBAS		;Get SPT index
	CALL RELSPG		; and unmap the page

;Lock XRCOD in core
	MOVE T1,[XRCOD&777777,,XRCODZ&777777] ;XRCOD low,,high
	MOVE T2,XCDBAS		;SPT index of page table
	XMOVEI P2,MLKSPN	;Locking routine
	CALL BSMGG		;Call coroutine

;Set up FPTABL
	MOVEI T1,FPTAXC		;Get FPTA routine that handles XCDSEC
	MOVEM T1,FPTABL+XCDSEC	; and set it in FPTABL

	RET			;All done
>
	SUBTTL SETDST - SET UP MAP FOR DST, POINTER TO IT, ETC.

;ACCEPTS:
;	NO ARGUMENTS

;	CALL SETDST

;RETURNS +1: ALWAYS

SETDST::
	EA.ENT			;ENTER SECTION 1 IF NOT ALREADY THEREIN
	SAVEAC <T1,T2,T3,T4,P1,P2,P3>
	HRRZ T1,MSECTB+TABSEC	;GET SPT SLOT
	CALL SWPIN1		;GET A CORE PAGE FOR IT
	HRLZ P3,MSECTB+TABSEC	;GET SPT INDEX FOR SECTION MAP
	MOVEI P1,NDST_-PGSFT	;GET NUMBER OF WORDS IN DST
	AOS P1			;ROUND UP TO NEXT PAGE
	MOVNS P1		;SET UP AOBJN POINTER WITH
	HRLZS P1		; (SPT INDEX,,PAGE NUMBER)
SETDS1:	MOVE T1,P3		;T1/ (SPT,,PAGE NUMBER)
	CALL MLKPG		;GET A CORE PAGE AND LOCK IT
	AOS P3			;INCREMENT PAGE COUNT
	AOBJN P1,SETDS1		;DONE WITH ALL PAGES?
	MOVSI T2,TABSEC		;GET START OF DST
	SETOM (T2)		;INITIALIZE TO FREE
	MOVEI T1,NDST		;NUMBER OF WORDS TO COPY
	MOVE T3,T2		;DESTINATION
	AOS T3			; IS ONE PAST SOURCE
	XBLT. T1		;INITIALIZE DST

	MOVSI T1,TABSEC		;SET UP ADDRESS OF START OF DST
	MOVEM T1,DSTLOC		;TELL SWPALC WHERE IT IS
	RET
;Set CST indirect pointers.
; T1/ virtual address of CST0
; T2/ Size of CST (MAXCOR assumed for STCSTX)

STCSTX::MOVEI T2,MAXCOR		;ASSUME MAX SIZE CSTS
STCSTN::STKVAR <CSTX,CSTN>
	MOVEM T1,CSTX		;SAVE ADR
	MOVEM T2,CSTN		;SAVE SIZE
	MOVSI T1,-20		;MAKE AOBJN POINTER - for number of ACs
PGRCSL:	MOVE T2,CSTX		;VIRT ADR
	TXNN T2,VSECNO		;EXTENDED NOW?
	IFSKP.
	  DPB T1,[POINT 4,T2,5]	;YES, MAKE EFIW
	ELSE.
	  HRL T2,T1		;NO, IFIW
	  TXO T2,IFIW
	ENDIF.
	MOVEM T2,CST0X(T1)
	ADD T2,CSTN		;CST1 POINTER
	MOVEM T2,CST1X(T1)
	ADD T2,CSTN		;CST2 POINTER
	MOVEM T2,CST2X(T1)
	ADD T2,CSTN		;CST3 POINTER
	MOVEM T2,CST3X(T1)
	AOBJN T1,PGRCSL		;LOOP FOR ALL 20 ENTRIES OF TABLES
	RET
	SUBTTL MOVCST - Fixup CSTs after physical mem known

;RETURNS:	+1

MOVCST::PIOFF
	ACVAR <R1,R2>
	STKVAR <NEWLOC>

;NOW THAT WE KNOW THE SIZE OF PHYSICAL MEMORY, UNLOCK UNNECESSARY CST PAGES

	MOVSI R1,-NCSTS		;4 CSTS IN TABSEC
	HRRZ T1,CSTVA		;GET BEGINNING OF CST0
	MOVEM T1,NEWLOC		;SAVE IT
MOVCS2:	MOVE T2,NEWLOC		;GET BEGINNING OF THIS CST
	ADD T2,NHIPG		;PLUS LAST MEMORY PAGE
	ADDI T2,777		;MOVE TO NEXT ENTRY
	LSH T2,-PGSFT		;GET PAGE NUMBER
	MOVE R2,NEWLOC		;GET BEGINNING OF THIS CST AGAIN
	ADDI R2,MAXCOR		;GET BEGINNING OF NEXT CST
	MOVEM R2,NEWLOC		;STASH IT FOR NEXT TIME THROUGH
	LSH R2,-PGSFT		;GET PAGE NUMBER
	SUB R2,T2		;CALC NUMBER OF PAGES TO UNLOCK
	JUMPLE R2,MOVCS4	;IF MAXCOR EQUALS PHYSICAL MEMORY, DONE
	MOVNS R2		;MAKE
	HRLZS R2		; AOBJN
	HRR R2,T2		;  WORD
MOVCS3:	HRRZ T1,SYMMAP(R2)	;GET PHYSICAL PAGE NUMBER
	SETZM SYMMAP(R2)	;FLUSH OBSOLETE POINTER
	SETZM @CST2X+T1		;FORCE IT ON REPLACEABLE QUEUE
	CALL MULKCR		;UNLOCK THE PHYSICAL PAGE
	AOBJN R2,MOVCS3		;DO ALL PAGES
	AOBJN R1,MOVCS2		;DO ALL CSTS

MOVCS4:

;WHILE WE'RE HERE LET'S CLEAN UP CST5, TOO.

	MOVEI T2,CST5		;GET BEGINNING OF THIS CST5
	ADD T2,NHIPG		;PLUS LAST MEMORY PAGE
	LSH T2,-PGSFT		;GET PAGE NUMBER
	AOS T2			;MOVE TO NEXT ENTRY
	MOVEI R2,CST5		;GET BEGINNING OF THIS CST5 AGAIN
	ADDI R2,MAXCOR		;GET END OF CST5+1
	LSH R2,-PGSFT		;GET PAGE NUMBER
	SUB R2,T2		;CALC NUMBER OF PAGES TO UNLOCK
	JUMPLE R2,MOVCS6	;IF NO MORE TO ELIMINATE, DONE
	MOVNS R2		;MAKE
	HRLZS R2		; AOBJN
	HRR R2,T2		;  WORD
MOVCS5:	HRRZ T1,MMAP(R2)	;GET PHYSICAL PAGE NUMBER
	SETZM @CST2X+1		;FORCE IT ON REPLACEABLE QUEUE
	SETZM MMAP(R2)		;CLEAN UP MMAP
	CALL MULKCR		;UNLOCK THE PHYSICAL PAGE
	AOBJN R2,MOVCS5		;DO ALL PAGES
MOVCS6:	PION
	RET

	ENDSV.
	ENDAV.
	SUBTTL
;ROUTINES TO COMPUTE PAGE MANAGEMENT PARAMETERS

MEMMGT:	MOVE T1,TOTRC		;TOTAL REAL MEM FOUND
	SUB T1,NRPMX		;LESS 2 TIMES MARGIN
	SUB T1,NRPMX
	MOVEM T1,MAXNR		;MAX VALUE OF SUMNR
	SUBI T1,10
	SKIPE T2,PGMMAX		;CUSTOMER-SPECIFIED LIMIT?
	JRST [	CAMLE T2,T1	;YES, BELOW CORE LIMIT?
		MOVE T2,T1	;NO, MUST USE CORE LIMIT
		MOVEM T2,NPMAX	;USE FOR BOTH REGULAR AND SMALL LIMIT
		MOVEM T2,SNPMAX
		JRST PGRI9]
	MOVEM T1,NPMAX
	CAIL T1,140		;REASONABLY LARGE SYSTEM?
	SUBI T1,40		;YES, SET SNPMAX 16K SMALLER
	MOVEM T1,SNPMAX		;SMALL NPMAX
PGRI9:	MOVE T1,NRPMX		;INIT NRPMIN
	MOVEM T1,NRPMIN
	MOVE T1,TOTRC
	LSH T1,-3
	MOVEM T1,MAXBP
	RET			;DONE

;SET SWAP SPACE PARAMETERS - CALLED FROM DRMINI AFTER DRUM SPACE KNOWN
;ALSO CALLED WHEN NEW PAGES APPEAR IN SYSTEM

SETSSP::MOVE B,TOTRC		;PREVENT NEW PRIVATE PAGES
	CAIL B,^D1024		;A VERY LARGE SYSTEM?
	MOVEI B,^D1024		;YES. USE CUTOFF THEN
	MOVEM B,DRMLV0		;WHEN FREE DRUM EQUALS TOTAL CORE
	MOVEM B,DRMIN1		;NEW JOB CUTOFF WILL BE 1.5 ABOVE
	ASH B,-1
	ADDM B,DRMIN1
	ADD B,DRMIN1		;DDMP START LEVEL WILL BE 2 TIMES
	MOVEM B,DRMIN0		;TO CAUSE DDMP ACTIVITY
	ASH B,1			;SEE IF ACTUAL SWAP SPACE AT LEAST
	CAMGE B,DRMTPG		; TWICE DDMP LEVEL
	IFSKP.
	  MOVE T2,TOTRC
	  BUG.(CHK,SWPSTL,PAGUTL,SOFT,<Swap space too low at startup>,<<T1,SWPSIZ>,<T2,MEMSIZ>>,<

Cause:	Insufficient swap space has been allocated for reasonable
	operation.  The swapping space should be at least 4 times
	the size of main (MOS/core) memory.

Data:	SWPSIZ - Size of swapping space allocated
	MEMSIZ - Total MOS/core size
>,,<DB%NND>)			;[7.1210] 
	ENDIF.
	RET
;INIT NEW FORK

FKSETP::MOVE T2,SHRPTR		;CONSTRUCT SHARE PTR
	LOAD T1,FKUPT		;GET UPT IDENT
	STOR T1,SPTX,T2		;CONSTRUCT SHARE PTR
	MOVEM T2,PSBM0+UPTPG	;MAP UPT
	MOVEM T2,USECTB		;SET AS USER SECTION 0 ALSO
	LOAD T1,FKPSB
	STOR T1,SPTX,T2		;BUILD SHARE PTR TO PSB
	MOVEM T2,PSBM0+PSBPG	;SET IT IN MON MAP
	LOAD T1,FKPS2		;GET STACK PAGE I.D.
	STOR T1,SPTX,T2		;MAKE A SHARE POINTER TO IT
	MOVEM T2,PSBM0+PS2PG	;POINT TO THE STACK PAGE FROM THE UPT
   IFN KCFLG,<
	MOVX T1,KLPTR		;REQUEST KL COMPATIBLE MODE FOR USER
	MOVEM T1,USSPTB		;STORE IN THE UPT FOR THE HARDWARE
   >				;END OF IFN KCFLG
	RET
;ROUTINE TO CHECK IF A PAGE CAN BE USED (DOESNT NXM)
;T1/ PHYSICAL PAGE
;	CALL CHKPAG
;RETURNS+1(FAILURE):
;	PAGE NOT USEABLE
;RETURNS+2(SUCCESS):
;	PAGE APPEARS OK

   IFN KLFLG,<
CHKPAG:	PIOFF		;PREVENT ANY INTERRUPTS
	PUSH P,@CST0X+T1	;SAVE PRESENT STATE
	PUSH P,T1		;SAVE PAGE NUMBER AS WELL
	MOVX T2,PSASM		;ALLOW REFERENCE
	IORM T2,@CST0X+T1	; ...
	CALL MAPRCA		;MAP PAGE
	POP P,T2		;RESTORE PAGE NUMBER
	SKIP 0(T1)		;REFERENCE FIRST WORD
	CONSZ APR,APNXM		;NXM?
	JRST CHKPG1		;YES - LOSE QUICKLY
	SKIP 1(T1)		;NO - TRY NEXT 3 WORDS
	SKIP 2(T1)		;IN CASE INTERLEAVE
	SKIP 3(T1)		;DEFECTIVE
	CONSZ APR,APNXM		;STILL NO NXM?
	JRST CHKPG1		;NXM - NOT SUITABLE
	POP P,@CST0X+T2		;RESTORE ORIGINAL STATE
	CALL UNMRCA		;CLEAR TEMP MAPPING
	PION
	RETSKP			;SUCCESS RETURN

CHKPG1:	CONO APR,APFCLR+APNXM+APRCHN	;RESET NXM FLAG
	POP P,@CST0X+T2		;RESTORE ORIGINAL STATE
	CALL UNMRCA		;RELEASE TEMP MAPPING
	PION
	RET			;FAILURE
   >				;END OF IFN KLFLG
;CHKPAG - ROUTINE TO CHECK IF A PAGE CAN BE USED (DOESNT NXM)
;T1/ PHYSICAL PAGE
;	CALL CHKPAG
;RETURNS+1(FAILURE):
;	PAGE NOT USEABLE
;RETURNS+2(SUCCESS):
;	PAGE APPEARS OK

;Clobbers the temporary AC's

   IFN KCFLG,<
CHKPAG:	PIOFF			;PREVENT ANY INTERRUPTS
	MOVE T4,KCPFNP		;SAVE OLD PAGE FAULT HANDLER ADDRESS
	MOVE T3,@CST0X+T1	;SAVE PRESENT STATE OF CST0
	XMOVEI T2,CKPPFH
	MOVEM T2,KCPFNP		;SET SPECIAL PAGE FAULT HANDLER
	MOVX T2,PSASM		;ALLOW REFERENCE
	IORM T2,@CST0X+T1	; ...
	LSH T1,^D9		;GET ADDRESS OF START OF PAGE
	PMOVE T2,T1		;REFERENCE FIRST WORD
	AOS T1
	PMOVE T2,T1		;REFERENCE REST IN CASE INTERLEAVED
	AOS T1
	PMOVE T2,T1
	AOS T1
	PMOVE T2,T1

;Here when all references succeeded. Restore state of page and return success

	LSH T1,-^D9		;GET PAGE NUMBER BACK
	MOVEM T3,@CST0X+T1	;RESTORE ORIGINAL STATE
	MOVEM T4,KCPFNP		;SET UP OLD PAGE FAULT HANDLER
	PION
	RETSKP			;SUCCESS RETURN

;Here when reference caused a NXM. Restore state of page and return failure

CHKPG1:	LSH T1,-^D9		;GET PAGE NUMBER BACK
	MOVEM T3,@CST0X+T1	;RESTORE ORIGINAL STATE
	MOVEM T4,KCPFNP		;SET UP OLD PAGE FAULT HANDLER
	PION
	RET			;FAILURE
;Special page fault handler for CHKPAG

;Clobbers only T2

CKPPFH:	LOAD T2,TWCOD,KCPFCD	;GET REASON FOR FAULT
	CAIE T2,PFCNXM		;WAS IT A NXM?
	BUG.(HLT,CKPGPF,PAGUTL,HARD,<CHKPAG - Unexpected page fault>,,<

Cause:	During a call to CHKPAG, a page fault occurred, and the error code did
	not indicate non-existent memory.

>)
	XMOVEI T2,CHKPG1	;GO TO THE FAILURE CODE
	MOVEM T2,KCPFOP		;SET UP PC
	XJRSTF KCPFOF		;GO HANDLE THE ERROR
   >				;END OF IFN KCFLG
;ROUTINES FOR SAVING AND RESTORING SWAPPABLE MONITOR MAP
;AROUND RESTARTS

;SAVE SWAP MON MAP

SAVSMM::MOVEI Q1,NRCODP-1
	SUB Q1,SWCEND		;COMPUTE NUMBER PAGES IN SWAP MON
	HRLZ Q1,Q1		;SETUP AOBJN PTR
SAVSM1:	MOVE T1,MMAP+NRCODP(Q1)	;GET CURRENT MAP PTR
	TXNN T1,NCORTM		;IN CORE?
	JRST [	HRRZS T1	;MASK OFF HIGH BITS
		MOVE T1,@CST1X+T1	;YES, GET DRUM ADDRESS
		JRST .+1]
	MOVEM T1,TMPSMM(Q1)	;SAVE DRUM ADDRESS
	AOBJN Q1,SAVSM1
	RET

;RESTORE SWAP MON MAP FROM TEMP AREA IN LOW CORE

RESSMM::MOVEI Q1,NRCODP-1	;COMPUTE NUMBER PAGES IN SWAP MON
	SUB Q1,SWCEND
	HRLZ Q1,Q1
RESSM1:	LOAD T1,STGADR,TMPSMM(Q1) ;GET DRUM ADR FOR THIS PAGE
	CALL DRMASA		;ASSIGN IT
	 BUG.(HLT,RSMFAI,PAGUTL,HARD,<RESSMM - Failed to assign swap mon page>,,<

Cause:	The monitor is trying to restore the swappable monitor from the
	swapping space after a system crash. It is unable to assign a
	page in the swapping space to which a monitor page was previously
	written. This code is executed only if the monitor is
	manually started at location EVLDGO. This is not a recommended
	procedure.
>)
	LOAD T1,STGADR,TMPSMM(Q1)
	IOR T1,IMMPTR		;MAKE NEW PTR
	MOVEM T1,MMAP+NRCODP(Q1) ;SETUP MON MAP
	AOBJN Q1,RESSM1
	RET
;RESTART SWAPPER - REINITIATE IO OPERATIONS IN PROGRESS AT TIME OF CRASH

SWPRST::EA.ENT			;RUN INSECTION 1
	SETZM IOIP
	MOVE 6,MONCOR		;SCAN CST AND CHECK STATE OF PAGES
SWPRS1:	LOAD 1,CSTAGE,+6	;GET STATE CODE
	CAIN 1,PSRIP		;READ IN PROGRESS?
	JRST SWPRSR		;YES, GO RESTART IT
	CAIN 1,PSWIP		;WRITE?
	JRST SWPRSW		;YES
	CAIL 1,PSASN		;PAGE ASSIGNED TO PROCESS?
	JRST [	MOVE 2,@CST3X+6	;YES, SEE IF BEING WRITTEN
		TLNE 2,(DWRBIT)
		JRST SWPRSW	;WAS BEING WRITTEN, RESTART WRITE
		JRST .+1]	;NOT BEING WRITTEN
SWPRS2:	CAMGE 6,NHIPG		;LOOKED AT ALL PAGES?
	AOJA 6,SWPRS1		;NO
	RET

SWPRSW:	MOVSI 1,(DWRBIT)	;WRITE OPERATION
	AOSA IOIP		;COUNT WRITES IN PROGRESS
SWPRSR:	SETZ 1,			;READ OPERATION
	HRRI 1,0(6)
	MOVE 2,@CST1X+6		;BACKUP ADDRESS
	TLNE 2,(DSKAB)		;DISK?
	JRST SWPRS3		;YES
	TLNN 2,(DRMAB)		;DRUM?
	BUG.(HLT,ILCST1,PAGUTL,SOFT,<Illegal address in CST1 entry, cannot restart>,,<

Cause:	The monitor is attempting to complete I/O that was taking place
	when the system crashed. The backup address in the CST is
	invalid for some core page. Note: This code is executed only
	if the monitor is manually started at location EVRST. This is
	not a recommended procedure.
>)
	CALL DRMIO
	JRST SWPRS2

SWPRS3:	CALL DSKIO
	JRST SWPRS2
;ASSIGN MONITOR VIRTUAL ADDRESS SPACE
; AVFLG - Flags
; AVSIZ - Size of desired space in words, rounded up to page multiple.
;Returns +1: failure
;	+2: success, T1/ address of space (guaranteed on page boundary)

;FLAGS

AV%NCS==:1B0	;Don't create section (i.e., just assign map slot)
AV%LOK==:1B1	;Lock pages in memory

ASGVAS::BLSUB. <AVFLG,AVSIZ>
	SAVEQ			;NOTE: IN PAGUTL Q3 IS DEFINED AS FX
	MOVE Q1,AVSIZ
	ADDI Q1,PGSIZ-1		;ROUND TO EVEN PAGE
	TRZ Q1,PGSIZ-1
	CAMLE Q1,[SECSIZ]	;MORE THAN A SECTION?
	RET			;CAN'T
	CAME Q1,[SECSIZ]	;EXACTLY A SECTION?
	JRST ASGV1		;NO, LESS
	MOVEI T2,FFMSEC		;Get first potentially free section
      DO.
	CAILE T2,HGHSEC		;Range check the section number
	RET			;END, RETURN FAIL
	SKIPE MSECTB(T2)	;Is there a section there?
	AOJA T2,TOP.		;YES, Loop for first available section
	MOVE T3,T2		;CHECK ASSIGNMENT
	IDIVI T3,^D36
	MOVE T1,BITS(T4)
	TDNN T1,ASGVBT(T3)	;ALREADY ASSIGNED?
	AOJA T2,TOP.		;YES, LEAVE IT
      ENDDO.
	ANDCAM T1,ASGVBT(T3)	;MARK SECTION NOT FREE
	MOVEM T2,Q1		;SAVE SECTION NUMBER

; Here when we have the MSECTB slot address in T2. Build a pointer to the
;initial page table.

	TMNE AV%NCS,AVFLG	;CREATE SECTION?
	IFSKP.
	  CALL ASSPT		;Get SPT slot for extended free space section
	  MOVE T3,SHRPTR	;YES, We want a share pointer to the page table
	  STOR T1,SPTX,T3	;Include the SPT index
	  MOVEM T3,MSECTB(Q1)	;Put pointer into mon section table
	ENDIF.
	HRLZ T1,Q1		;RETURN IT AS VIRTUAL ADDRESS
	RETSKP
;Caller wants less than 1 section.  See if partial section available.

ASGV1:	HRRZ T2,ASGVCS		;LOOK AT CURRENT SECTION
	MOVSI T3,1
	SUB T3,T2		;COMPUTE SPACE LEFT
	SKIPE T2		;IS THERE A CURRENT SECTION?
	CAMLE Q1,T3		;ENOUGH FOR REQUEST?
	IFNSK.
	  BLCAL. ASGVAS,<[0],<[SECSIZ]>> ;RECURSE TO CREATE A SECTION
	   RET			;CAN'T, FAIL
	  MOVEM T1,ASGVCS
	ENDIF.
	MOVE T1,ASGVCS		;THIS WILL BE FIRST ADDRESS OF SPACE
	ADD T1,Q1		;COMPUTE END 
	EXCH T1,ASGVCS		;SAVE END, RETURN
	TMNN AV%LOK,AVFLG	;LOCK PAGES?
	IFSKP.
	  IDIVI Q1,PGSIZ	;GET NUMBER OF PAGES TO LOCK
	  CAMLE Q1,NRPLQ	;ENOUGH PAGES IN SYSTEM?
	  JRST [MOVEM T1,ASGVCS	;NO UNDO THIS
	        RET]		;AND RETURN FAILURE
	  MOVEM T1,Q2		;SAVE ADDRESS
	  LOAD FX,LPGNO,Q2	;GET PAGE NUMBER WITHIN SECTION
	  LOAD T2,VSECNO,Q2	;GET VIRTUAL SECTION NUMBER
	  LOAD T2,SPTX,MSECTB(T2) ;BUILD IDENT TO NEW PAGE
	  HRL FX,T2
	DO.
	  MOVE T1,FX		;GET IDENT
	  CALL MLKPG		;CREATE PAGE AND LOCK IT
	  ADDI FX,1		;BUMP ID
	  SOJG Q1,TOP.		;DO ALL PAGES
	ENDDO.
	  MOVE T1,Q2		;RESTORE ADDRESS
	ENDIF.
	RETSKP
;MAP PHYSICAL CORE PAGE
; T1/ DESTINATION IDENT
; T2/ PHYSICAL PAGE NUMBER
;	CALL MAPPHP
; RETURN +1: FAILURE, PAGE LOCKED OR OTHERWISE INACCESSIBLE
; RETURN +2: SUCCESS, PRIVATE POINTER SETUP

MAPPHP::EA.ENT			;RUN IN SECTION 1
	ASUBR <ID,PGNO>
	CAMLE T2,NHIPG		;WITHIN KNOWN RANGE?
	BUG.(HLT,XSCORE,PAGUTL,SOFT,<CST too small for physical core present>,,<

Cause:	A routine has been called to map a specified core page to a
	specified virtual page. The BUGHLT indicates that the caller
	provided a page number of a core page that does not exist.
	(The number is too large). This BUGHLT can occur if a monitor
	that is built for less than 256K is booted on a machine whose
	memory exceeds 256K.

Action:	If the monitor was built for less than 256K, and there
	is more than 256K of memory on the system, rebuild the monitor
	for the correct amount of memory.
>)
	CALL SETCPT		;MAP DESTINATION PT
	SETZM T3		;NO SPECIAL ACCESS BITS
	CALL RELMP5		;CLEAR PREVIOUS CONTENTS
	CALL MONCLA		;CLEAR PAGE MEMORY
	NOSKED
	MOVE T1,PGNO
	CAMGE T1,MONCOR		;RES MONITOR PAGE?
	JRST [	CALL RESPCK	;CHECK RESMON PAGE
		 JRST .+1	;NOT PART OF RESMON
		MOVE T2,ID	;YES, DON'T CHANGE CST
		JRST MAPPH1]
	MOVX T2,-PLKV
	TDNE T2,@CST1X+T1	;PAGE LOCKED?
	JRST MAPPHX		;YES, CAN'T GRAB IT
	CALL RPCST		;RELEASE PAGE FROM PRESENT USE
	CALL AGECHK		;ASSIGN PAGE  HERE
	MOVX T2,UAAB		;SET UNASSIGNED BACKUP ADDRESS
	MOVEM T2,@CST1X+T1
	MOVE T2,ID
	MOVEM T2,@CST2X+T1	;SET OWNER ID
	SETONE CSWRB,+T1
MAPPH1:	IOR T1,IMMPTR		;CONSTRUCT PRIVATE PTR
	HRRZS T2		;PREVENT PAGE FAULT
	MOVEM T1,CPTPGA(T2)	;PUT IN DEST MAP
	HLRZ T1,ID		;GET PT I.D.
	LOAD T1,STGADR,SPT(T1)	;GET MEMORY PAGE NUMBER
	MOVX T2,PLKV		;ONE UNIT OF LOCK COUNT
	ADDM T2,@CST1X+T1	;ONE MORE PAGE IN MEMORY
	CALL UPSWP		;UPDATE PARAMETERS
	OKSKED
	CALL RELCPT		;RELEASE DEST MAP
	MOVE T2,PGNO		;RESTORE ARG
	RETSKP

MAPPHX:	OKSKED
	CALLRET RELCPT
;Entry for MAPPHA that checks if page is on SPMQ and removes it.
;Same args as MAPPHA

MAPPHQ::ACVAR <W1,W2>		;Save ACs
	NOSKED
	DMOVE W1,T1		;Save arg
	LOAD T3,CSTAGE,+T1	;Get state of the pages
	CAIE T3,PSSPQ		;Is it on SPMQ?
	IFSKP.			;If so
	 CALL OFFSPQ		;Get it off
	 MOVX T3,PSTAVL		;Make it available
	 STOR T3,CSTPST,+T1	;""
	 CALL ONRQ		;Put it on RPLQ so it will be safe
	ENDIF.
	OKSKED			;Allow others to run now
	DMOVE T1,W1		;Recover args
;	CALLRET MAPPHP		;And do the work
	ENDAV.
;MAP PHYSICAL PAGE INTO MONITOR ADDRESS
; T1/ PHYSICAL CORE PAGE NUMBER
; T2/ MONITOR VIRTUAL ADDRESS
;	CALL MAPPHA
; SAME AS MAPPHP EXCEPT TAKES MONITOR VIRTUAL ADDRESS

MAPPHA::EXCH T1,T2
	CALL FPTA		;TRANSLATE ADDRESS TO IDENT
	JUMPE T1,SETMPX		;SECTION MUST EXIST
	CALLRET MAPPHP		;DO THE WORK

;ROUTINE TO SEE IF A PAGE LESS THAN MONCOR IS STILL PART
;OF MONITOR MAP.
;ACCEPTS:	T1/ PAGE NUMBER
;RETURNS:	+1 NOT PART OF MONITOR MAP
;		+2 PART OF MONITOR MAP

RESPCK::HLRZ T2,@CST2X+T1	;GET PRESENT OWNER
	CAME T2,MMSPTN		;OWNED BY MONITOR MAP?
	RET			;NO
	RETSKP			;YES
;ROUTINES TO ADJUST SWPMON (THESE ROUTINES MUST BE INTERLOCKED)

;LOCK/UNLOCK SWPMON IN CORE

SWPMLK::AOSE SWPMLF		;FIRST LOCKER?
	RET			;NO, DONT LOCK IT AGAIN
	PUSH P,P2		;SAVE AC
	MOVEI P2,MLKPG		;SUBR TO MAP
SWPML1:	MOVE T1,SWPMBP		;GET BOUND PAIR
	CALL BSMGP		;MAP PAGES
	MOVE T1,INCOBP		;INCOD
	CALL BSMGP		;Lock/unlock in MMAP
  IFN FTNSPSRV < ;[6.0]
	MOVE T1,[<ENCOD&777777>,,<ENCODZ&777777>] ;ENCOD
	MOVE T2,SYMBAS		;SPT index of SYMSEC page table
	CALL BSMGG		;Lock/unlock
  >
  IFE FTNSPSRV < ;[6.1]
	MOVE T1,[<ENCOD&777777>,,<ENCODZ&777777>] ;ENCOD
	MOVE T2,XCDBAS		;SPT index of XCDSEC page table
	CALL BSMGG		;Lock/unlock
	MOVE T1,[<XNCOD&777777>,,<XNCODZ&777777>] ;XNCOD
	CALL BSMGG		;Lock/unlock
  >
	POP P,P2		;RESTORE AC
	RET

SWPMUL::SKIPL SWPMLF		;ALREADY UNLOCKED?
	SOSL SWPMLF		;NO, LAST ONE TO UNLOCK SWP MON?
	RET			;NO, LEAVE IT LOCKED
	PUSH P,P2		;SAVE AC
	MOVEI P2,MULKPG		;UNLOCK PAGES
	JRST SWPML1		;JOIN ABOVE

;WRITE ENABLE/PROTECT SWPMON

SWPMWE::AOSE SWPMWF		;FIRST TIME THRU
	RET			;NO, DONT NEED TO GO ON
	ACVAR <W1>		;GET A WORK REGISTER
	MOVEI W1,MMAPWE		;W1/ADDRESS FOR WRITE-ENABLING
  IFN FTNSPSRV <
	JRST SWPM0		;GO WRITE ENABLE
  >
  IFE FTNSPSRV < ;[6.1]
	CALL SWPM0		;Write enable MMAP
	XMOVEI W1,XMAPWE	;W1/ address for write-enabling
	JRST SWPM1		;Go do it
  >
SWPMWP::SKIPL SWPMWF		;ALREADY WRITE PROTECTED?
	SOSL SWPMWF		;NO, LAST TIME THRU?
	RET			;NO, LEAVE IT WRITE ENABLED
	SAVEAC <W1>		;GET A WORK REGISTER *MATCHES ACVAR ABOVE*
	MOVEI W1,MMAPWP		;W1/ADDRESS FOR WRITE-PROTECTING
  IFE FTNSPSRV < ;[6.1]
	CALL SWPM0		;Go write-protect
	XMOVEI W1,XMAPWP	;W1/ address for write-protecting
	JRST SWPM1		;Go do it
  >

;AC W1 HAS ADDRESS FOR FUNCTION DESIRED.  SET UP ARGUMENTS FOR MMAPWP OR MMAPWE

SWPM0:	MOVEI 1,NRCOD		;1/STARTING ADDRESS OF SWAPPABLE MONITOR
	MOVE 2,SWCEND		;2/LENGTH OF SWAPPABLE MONITOR
	SUBI 2,NRCODP-1
	CALL 0(W1)		;CALL MMAPWE OR MMAPWP TO DO FUNCTION REQUESTED
	MOVEI T1,RSCOD		;T1/ ADDRESS OF RESIDENT CODE
	MOVEI T2,RSCODL-RSCODP+1 ;T2/ NUMBER OF PAGES
	CALL 0(W1)		;CALL ROUTINE TO DO PROPER FUNCTION
	RET

  IFE FTNSPSRV < ;[6.1]

;SWPM1 - write enable/protect extended psects. Set up arguments for XMAPWP or
; XMAPWE. W1 has address to call

SWPM1:	SAVEAC <P1>		;XMAPWx wants page map address in P1
	MOVX P1,XCDMAP		;Load address of page table for XCDSEC
	MOVEI T1,XRCOD		;Get section local address of XRCOD
	MOVEI T2,<XRCODZ-XRCOD+PGSIZ>_-PGSFT ;Get # of pages to do
	CALL (W1)		;Execute
	MOVEI T1,XNCOD		;Get section local address of XNCOD
	MOVEI T2,<XNCODZ-XNCOD+PGSIZ>_-PGSFT ;Get # of pages to do
	CALLRET (W1)		;Execute and return
  >

	ENDAV.			;END ACVAR
;LOCK/UNLOCK EDDT, SYMTAB, AND INITIALIZATION CODE

ULKINI::SETZM DDTPRS		;INDICATE NO EDDT
	MOVEI T1,MULKPG		;ROUTINE TO USE
	JRST LKINI0		;JOIN COMMON CODE

LCKINI::MOVEI T1,MLKPG		; ROUTINE TO LOCK
	SETOM DDTPRS		;INDICATE EDDT PRESENT
LKINI0:	PUSH P,P2		;SAVE AC
	MOVE P2,T1		;COPY ARG
	MOVE T1,INCOBP		;GET INIT CODE PAIR
	CALL BSMGP		;MAP PAGES ONTO ROUTINE
	MOVE T2,SYMBAS		;GET SPT INDEX OF SYMBOL TABLE MAP
	MOVE T1,[ERCOD&777777,,ERCODZ&777777] ;ERCOD
	CALL BSMGG		;Lock/unlock EDDT
  IFN FTNSPSRV < ;[6.0]
	MOVE T1,SYTBBP		;GET SYMBOL PAIR NOW
  >
  IFE FTNSPSRV < ;[6.1]
	HRL T1,SYMSTA		;Get section-local start address of symbols
	HRR T1,SYMEND		; and section-local end address
  >
	CALL BSMGG		;MAP PAGES ONTO ROUTINE
	POP P,P2		;RESTORE AC
	RET			;ALL DONE
;MMAPWE AND MMAPWP- ROUTINES TO WRITE ENABLE OR WRITE PROTECT THE MONITOR'S MAP

;ACCEPTS:
;	T1/VIRTUAL ADDRESS OF FIRST PAGE AFFECTED
;	T2/COUNT OF NUMBER OF PAGES TO AFFECT

;CALL MMAPWE OR CALL MMAPWP

;RETURNS +1 ALWAYS

;THIS ROUTINE MODIFIES THE ACCESS FOR CONSECUTIVE PAGES IN THE MONITOR'S MAP.
;IT MODIFIES MMAP FOR PAGES BELOW THE JSB, JOBMAP FOR PAGES IN THE JSB, AND
;PSBMAP FOR PAGES IN THE PER PROCESS REGION.  IT ASSUMES THAT THE RANGE
;SPECIFIED DOES NOT EXTEND BEYOND THE STARTING REGION.  THAT IS, ALL PAGES
;ARE BETWEEN 0 AND 577, OR 600 AND 677, OR 700 AND 777.

MMAPWE::SKIPA T3,[IORM T4,0(T1)] ;T3/INSTRUCTION TO WRITE-ENABLE
MMAPWP::MOVE T3,[ANDCAM T4,0(T1)] ;T3/INSTRUCTION TO WRITE-PROTECT
	LOAD T1,VPGNO,T1	;GET PAGE NUMBER
	CAIL T1,PSVARP		;BELOW THE PSB?
	CAILE T1,PSVARL		;OR ABOVE IT?
	JRST MM1		;YES, CHECK NEXT AREA
	ADDI T1,PSBMAP-PSVAR	;IN THE PSB.  POINT TO PSBMAP SLOT FOR 1ST PAGE
	JRST MM3		;GO LOOP THROUGH THE PAGES

MM1:	CAIL T1,JSVARP		;BELOW THE JSB?
	CAILE T1,JSVARL		;OR ABOVE IT?
	JRST MM2		;YES, MUST BE IN MMAP
	ADDI T1,JOBMAP-JSVARP	;IN THE JSB. POINT TO JOBMAP SLOT FOR 1ST PAGE
	JRST MM3		;GO LOOP THROUGH THE PAGES

MM2:	ADDI T1,MMAP		;IN MMAP. POINT TO ENTRY FOR THE FIRST PAGE

;T1 HAS THE ADDRESS OF THE FIRST WORD OF THE MAP.  LOOP THROUGH ENTRIES
;ACCORDING TO COUNT IN T2

MM3:	MOVX T4,PTWR		;T4/WRITE ACCESS
MM4:	SKIPE 0(T1)		;IGNORE NON-EXISTANT PAGE
	XCT T3			;WRITE ENABLE OR PROTECT ACCORDING TO T3
	AOS T1			;POINT TO NEXT WORD
	SOJG T2,MM4		;AT THE END?
	CALLRET MONCLA		;YES. MAKE THE PAGER SEE THE CHANGES
  IFE FTNSPSRV <
;XMAPWE and XMAPWP - routines to write enable or write protect monitor
; page maps other than MMAP.
;
;Accepts:
;	T1/ virtual address of first page affected
;	T2/ count of number of pages to do
;	P1/ virtual address of monitor page map
;
;Call XMAPWE or XMAPWP

XMAPWE:	SKIPA T3,[IORM T4,(T1)]	;Instruction to write enable
XMAPWP:	MOVE T3,[ANDCAM T4,(T1)] ;Instruction to write protect
	LOAD T1,VPGNO,T1	;Get page number
	ADD T1,P1		;Point to slot in page map
	MOVX T4,PTWR		;Load write bit
	DO.			;LOOP over pages
	  SKIPE (T1)		;  Non-existant page?
	  XCT T3		;   -no, do instruction
	  AOS T1		;  Move to next page
	  SOJG T2,TOP.		;  Loop back if more pages to do
	ENDDO.			;End loop
	CALLRET MONCLA		;Clear pager
  >
;PUT INDEX BLOCK IN FIXED PAGE (CXBPG) OF PP MAP FOR TEMP USE
; 3/ SPTN

SETXB1::PUSH P,SHRPTR		;CONSTRUCT SHARE PTR
	STOR 3,SPTX,0(P)
	POP P,3
	CAMN 3,PSBM0+CXBPG	;ALREADY THERE?
	RET			;YES
	CALL RELCXB		;RELEASE CURRENT ONE
	NOINT			;NO INTERRUPTS WHILE XB MAPPED
	MOVEM 3,PSBM0+CXBPG	;PUT INTO CURRENT X BLOCK PAGE
	RET

;RELEASE INDEX BLOCK NOW IN FIXED PAGE

RELCXB::SKIPN PSBM0+CXBPG
	RET			;NONE THERE NOW
	PUSH P,T1
	NOSKED
	LOAD T1,SPTX,PSBM0+CXBPG ;GET ID
	MOVE T1,SPT(T1)		;GET ADDRESS
	CALL DECOR		;DEASSIGN PAGE (IF CORE)
	OKSKED
	SETZM PSBM0+CXBPG		;CLEAR MAP
	MOVEI 1,CXBPGA
	CALL MONCLR		;CLEAR MAP ENTRY
	POP P,1
	OKINT
	RET

;[7247]  SET and LOCK index block
;[7247]  T3/ OFN

LCKXB1::SAVET			;[7.1167] Global routine
	STKVAR <TT1>		;[7247] 
	MOVEM T3,TT1		;[7247] Save the OFN
	CALL SETXB1		;[7247] Map index block
	OKSKED			;[7247] 
	SKIP CXBPGA		;[7247] Touch XB while OKSKED
	NOSKED			;[7247] 
	DO.			;[7247] 
	  SKIP CXBPGA		;[7247] Swap in XB, if necessary
	  MOVE T1,TT1		;[7247] Get OFN again
	  LOAD T1,STGADR,SPT(T1);[7247] Get core page
	  CALL SKPNWR		;[7247] Make sure not being written
	  LOOP.			;[7247] Was retry
	ENDDO.			;[7247] 
	MOVX T3,PLKV		;[7247] Get a unit of lock count
	HRRZS T1		;[7247] Turn off unwanted index bits
	ADDM T3,@CST1X+T1	;[7247] Lock XB
	RET			;[7247] 
;MAP CURRENT PAGE TABLE FOR TEMP USE
; 1/ SPTN,,PN			;PN IGNORED

SETCPT::HLRZ 2,1		;GET PTN
	PUSH P,SHRPTR		;CONSTRUCT SHARE PTR
	STOR 2,SPTX,0(P)
	POP P,2
	CAMN 2,PSBM0+CPTPG	;ALREADY THERE?
	RET			;YES
	SKIPE PSBM0+CPTPG	;ALREADY MAPPED?
	BUG.(CHK,CPTMAP,PAGUTL,SOFT,<SETCPT - CPTPG already mapped>,,<

Cause:	A routine was called to setup CPTPG while CPTPG was already setup.
	All callers should call RELCPT if CPTPG is mapped.
>)				;** MAKE THIS A BUGHLT IN THE FUTURE
	CALL RELCPT		;** IF CPTMAP IS A BUGHLT REMOVE THIS
	NOINT
	MOVEM 2,PSBM0+CPTPG
	RET

;RELEASE CURRENT PT MAPPING

RELCPT::SKIPN PSBM0+CPTPG	;ANYTHING THERE?
	RET			;NO
	SETZM PSBM0+CPTPG	;CLEAR MAP
	PUSH P,1
	MOVEI 1,CPTPGA
	CALL MONCLR		;CLEAR MAP ENTRY
	POP P,1
	OKINT
	RET
;ROUTINE TO RETURN A SECTION POINTER
;ACCEPTS:
;	T1/ PSB,,SECN

;	CALL SECPTR

;RETURNS:
;	+1 ALWAYS
;		T1/ SECTION POINTER
;

SECPTR::NOSKED			;PREVENT INTERRUPTION
	PUSH P,T1		;SAVE ARG
	SKIPE T1,PSBM0+CPTPG	;ANYTHING MAPPED NOW?
	CALL RELCPT		;YES, RELEASE IT
	HRLZS T1		;MOVE SPTN TO PROPER PLACE (SPTN,,PN)
	EXCH T1,(P)		;SAVE OLD MAPPING, GET ARG BACK
	CALL SETCPT		;MAP PT
	HRRZS T1		;GET SECTION ONLY
	MOVE T1,SECADR(T1)	;ANYTHING HERE?
	CALL RELCPT		;FREE TABLE
	EXCH T1,(P)		;SAVE SECADR GET OLD MAPPING
	SKIPE T1		;WAS THERE ONE?
	CALL SETCPT		;YES, RESTORE IT
	POP P,T1		;RESTORE SECADR FOR RETURN
	OKSKED			;ALLOW SCHEDULING
	RET
;ACCEPTS:
;	T1/ PSB,,SECN

;	CALL SECJFN

;RETURNS:
;	+1 NOT A FILE SECTION
;		T1/ SECTION POINTER
;	+2 A FILE,
;		T1/ OFN
;		T2/ JFN,,PAGE NUMBER

	SWAPCD			;IS SWAPPABLE
SECJFN::STKVAR <SECSAV>
	CALL SECPTR		;GET SECTION POINTER
	TXNN T1,PTSECM		;MAPPED SECTION?
	RET			;NO. CAN'T BE A FILE THEN
	LOAD T2,STGADR,T1	;GET SPTN
	CAIL T2,NOFN		;YES. AN OFN THEN?
	RET			;NO.
	MOVEM T2,SECSAV		;SAVE OFN
	HRLZ T1,T2		;OFN TO LH
	CALL OFNJFX		;GET MATCHING JFN
	 RETBAD()		;NONE FOUND
	MOVE T2,T1		;JFN,,PAGE NUMBER
	MOVE T1,SECSAV		;RECOVER OFN
	RETSKP			;AND INDICATE FILE

	RESCD
;CHKMAP - ROUTINE TO CHECK IF SECTION IS "MAPPED"
;ACCEPTS:
;	T1/ PT,,SECN

;	CALL CHKMAP

;RETURNS: +1 NOT MAPPED.
;		T1/ 0 IF NO MAP ENTRY
;		T1/ SECTION POINTER IF PRIVATE SECTION
;	+2 MAPPED (PTSECM OR INDIRECT)
;		T1/ SECTION POINTER AFTER FOLLOWING INDIRECTION

CHKMAP::CALL SECPTR		;GET SECTION POINTER
	TXNE T1,PTSECM		;MAPPED SECTION?
	RETSKP			;YES
	STKVAR <PTRSAV>		;MAYBE
	MOVEM T1,PTRSAV		;SAVE THE POINTER
	CALL SECIPT		;SEE IF INDIRECT AND IF SO, FOLLOW POINTERS
	CAMN T1,PTRSAV		;INDIRECT?
	RET			;NO, PRIVATE POINTER
;HERE THE POINTER IS KNOWN TO BE INDIRECT. IF ANYONE NEEDS TO KNOW, MARK IT
; AS SUCH HERE
	RETSKP			;YES, THEN ITS ALSO MAPPED

;CHKMPS - SAME AS CHKMAP, EXCEPT FOR CURRENT FORK
;ACCEPTS:
;	T1/ SECTION #

;	CALL CHKMPS

;RETURNS: +1 NOT MAPPED.
;		T1/ 0 IF NO MAP ENTRY
;		T1/ NON-ZERO IF PRIVATE SECTION
;	+2 MAPPED

CHKMPS::MOVE T1,USECTB(T1)	;GET SECTION POINTER
	TXNN T1,PTSECM		;A MAPPED SECTION?
	RET			;NO
	RETSKP			;YES
;SECIND - ROUTINE TO CHASE INDIRECT SECTION POINTERS
;ACCEPTS:
;	T1/ INDEX INTO USECTB (MAPPED IF NOT CURRENT FORK'S CONTEXT)

;	CALL SECIND or SECINP for section not in core case

;RETURNS:	+1 ALWAYS. T1/ 0 IF NON-EXISTENT SECTION
;			   T1/ FIRST NON-INDIRECT SECTION POINTER
;			       LEFT HALF = AND OF ACCESS BITS
;			   T1/ -1,,SPTX IF SECINP WAS CALLED AND
;				REFERENCE WOULD PAGE FAULT

; ENTRY FOR CALLERS WHO PASS THE SECTION TABLE ENTRY DIRECTLY

SECIPT:	SAVEAC <T2,T3>		;BE TRANSPARENT TO CALLERS
	TDZ T3,T3		;FLAG OK TO FAULT
	JRST SECIN1

SECINP::TLOA T1,-1		;CANNOT PAGE FAULT
SECIND::TLZ T1,-1		;OK TO PAGE FAULT
	SAVEAC <T2,T3>
	HLRE T3,T1		;REMEMBER ENTRY
	HRRZS T1		;RESTORE INDEX
	SKIPN T1,USECTB(T1)	;SECTION EXIST?
	RET			;NO
SECIN1:	LOAD T2,PTRCOD,T1	;GET POINTER TYPE
	CAIE T2,INDCOD		;INDIRECT?
	RET			;NO
	PUSH P,T1		;SAVE ACCESS BITS
	LOAD T2,SPTX,T1		;GET SPT INDEX
	SKIPE T3		;CODE SENSITIVE TO PAGE FAULTS?
	JRST [CALL PFSPXS	;YES WILL THIS PAGE FAULT?
	      JRST .+1		;NO
	      POP P,T1		;YES, FORGET ACCESS BITS
	      HRRO T1,T2	;RETURN -1,,SPTX
	      RET]		;AND RETURN
	LOAD T1,IPPGN,T1	;INDEX INTO INDIRECT SECTION TABLE
	SUBI T1,USECTO
	HRL T1,T2		;PSB,,SECN
	CALL SECPTR		;GET SECTION POINTER
	POP P,T2		;RESTORE ACCESS BITS SO FAR
	TXO T2,-1-PTACB		;PRESERVE ALL EXCEPT ACCESS BIT FIELD
	AND T1,T2		;RUNNING AND OF ACCESS BITS SO FAR
				; ACTUALLY, ONLY PTWR MATTERS
	JRST SECIN1		;LOOP
;PFSPXS - SUBROUTINE OF ABOVE TO DETERMINE IF A REFERENCE WILL FAULT
;
;ACCEPTS:
;		T2/ SPTX
;RETURNS:
;		+1/ REFERENCE WILL NOT PAGE FAULT
;		+2/ REFERENCE WILL PAGE FAULT
PFSPXS:	SAVEAC <T1>
	LOAD T1,STGADR,SPT(T2)	;GET STORAGE ADDRESS
	TXNE T1,NCORTM		;IN CORE
	RETSKP			;NO. DEFINITE FAULT
	MOVE T1,@CST0X+T1	;IN CORE CHECK AGE
	TXNE T1,PSASM		;ASSIGNED?
	RET			;YES. REFERENCE WILL NOT FAULT
	RETSKP			;NOT ASSIGNED. AGE FAULT WILL OCCUR
;ROUTINES TO ADJUST AND FETCH SPT SHARE COUNTS.
;ACCEPTS:	1/ SPT INDEX (EITHER PT OR OFN)
;RETURNS:	+1 ALWAYS

;INCREASE SHARE COUNT

UPSHR::
   IFN DEBUG,<
	SKIPN T1		;OFN 0 was pass in?
OF0HLT:	BUG.(HLT,OFNZRO,PAGUTL,SOFT,<OFN zero was passed as argument>,,<

Cause:	OFN 0 should never be passed as an argument.  

Action:	Trace the stack and eliminate the illegal use of OFN 0.

>)
>				;End of IFN DEBUG
	SAVEAC <Q1,Q2>		;GET A WORK REGISTER
	HRRZ Q2,T1		;GET THE SPT INDEX
	CAIL Q2,NOFN		;AN OFN?
	JRST SHRSPT		;NO
	MOVX Q1,OFSHR		;YES. GET BIT FOR OFN
	ADDB Q1,SPTO(Q2)	;INCREMENT SHARE COUNT
	TLNN Q1,(-OFSHR)	;DID IT OVERFLOW?
UPSHRX:	BUG.(HLT,SHROFN,PAGUTL,SOFT,<UPSHR - OFN share count overflow>,,<
	
Cause:	The share count for an OFN has been incremented beyond the
	maximum value. It should not be possible for a user program
	to cause this.
>)
	RET		;NO. RETURN GOOD

SHRSPT:	MOVX Q1,USHR	;GET SHARE BIT FOR SPT
	ADDB Q1,SPT(Q2)	;INCREMENT IT
	TLNN Q1,(-USHR)	;DID IT OVERFLOW?
	BUG.(HLT,SPTSHR,PAGUTL,SOFT,<UPSHR - SPT share count overflow>,,<

Cause:	The share count for an SPT slot (not an OFN) has been
	incremented beyond the maximum value. This can be caused
	by a pathological program.
>)
	RET		;DONE
;DECREMENT SHARE COUNT
DWNSHR::
   IFN DEBUG,<
	JUMPE T1,OF0HLT		;OFN 0 was pass in
>				;End of IFN DEBUG
	SAVEAC <Q1,Q2>		;GET A WORK REGISTER
	HRRZ Q1,T1		;GET SPT INDEX
	CAIL Q1,NOFN		;AN OFN
	JRST [	DECR SPTSHC,(Q1) ;NO. DECREMENT SPT SHARE COUNT
		RET]		;AND DONE
	MOVSI Q2,(-OFSHR)	;GET DECREMENTER
	TDNN Q2,SPTO(Q1)	;FIRST CHECK FOR OVER DECREMENTING
	BUG.(HLT,SHROFD,PAGUTL,SOFT,<DWNSHR - OFN share count underflow>,,<

Cause:	A routine has been called to decrement the share count for
	an OFN. The BUGHLT indicates that the count was already 0.
>)
	ADDM Q2,SPTO(Q1)	;DO THE DECREMENT
	RET			;AND DONE

;variant of UPSHR used by code that manages long files to
;increase counts for PT0.
;	T1/ The OFN
;Returns:	+1 always

UP0SHR::INCR OFOPC,(T1)		;Another unit of opening
	CALLRET UPSHR
;GET CURRENT VALUE OF SHARE COUNT

GETSHR::SAVEAC <Q1>		;GET A WORK REGISTER
	HRRZ Q1,T1		;GET SPT INDEX
	CAIL Q1,NOFN		;AN OFN?
	JRST [	LOAD T1,SPTSHC,(Q1) ;NO. GET SPT SHARE COUNT
		RET]		;AND DONE
	LOAD T1,OFNSHC,(Q1)	;YES. GET OFN SHARE COUNT
	RET			;AND DONE

; CHECK CURRENT VALUE OF SHARE COUNT
; T1/ SPT INDEX ... NO ACS ARE DESTROYED
; NON-SKIP RETURN IF COUNT WILL OVERFLOW ON AN INCREMENT
; SKIP RETURN IF COUNT WILL NOT OVERFLOW

CHKSHC::			;CHECK THE SHARE COUNT
	SAVEAC <T1,T2>		;SAVE SOME WORK ACS
	HRRZS T1		;ZERO THE LEFT HALF OF SPT INDEX
	CAIGE T1,NOFN		;IS THIS AN OFN?
	 RETSKP			;YES SO SKIP RETURN
	LOAD T2,SPTSHC,(T1)	;NOT AN OFN...SO GET SHARE COUNT
	CAIL T2,MAXSHC		;IS COUNT AT THE MAX VALUE?
	 RET			;AT MAX VALUE SO NON SKIP RETURN
	RETSKP			;NOT AT MAX VALUE SO SKIP RETURN

;SPECIAL ROUTINE TO DO MULTIPLE COUNT
;	T1/ OFN
;	T2/ COUNT

MUPSHR::
   IFN DEBUG,<
	JUMPE T1,OF0HLT		;OFN 0 was pass in
>				;End of IFN DEBUG
	SAVEAC <Q1,Q2>
	MOVE Q2,T2		;SAVE COUNT
	CALL LCKOFA		;LOCK THE OFN
	LOAD Q1,OFNSHC,(T1)	;GET CURRENT COUNT
	ADD Q1,Q2		;NEW COUNT
	TLNE Q1,-1		;OVERFLOW?
	JRST UPSHRX		;YES.
	STOR Q1,OFNSHC,(T1)	;NO. STORE NEW COUNT
	CALL ULKOFN		;UNLOCK THE OFN
	MOVE T2,Q2		;RESTORE COUNT
	RET			;AND DONE
;SKIP IF NO WRITE IN PROGRESS ON CORE PAGE.  OTHERWISE RESCHEDULE
;UNTIL WRITE IS COMPLETED.
; 1/ CORE PAGE NUMBER
;	CALL SKPNWR
; RETURN +1, PAGE WAS BEING WRITTEN, WRITE HAS COMPLETED.
; RETURN +2, PAGE WAS NOT BEING WRITTEN.
;UNLESS THE PAGE IS LOCKED, IT MAY CHANGE STATE ON A RESCHED.  HENCE
;THE +1 RETURNS MEANS THAT THE POINTER TO THE PAGE MUST BE RECHECKED.
;CLOBBERS NO AC'S

SKPNWR::HRRZS A
	SKIPL @CST3X+A		;WRITE IN PROGRESS?
	RETSKP			;NO, SKIP
	SAVEAC <A,B>
	MOVE B,FORKX		;REMEMBER FORK WAITING
	STOR B,CFXRD,+A
	HRLZ A,A		;SETUP SCHED TEST
	HRRI A,DWRTST
	RDISMS			;OKSKED AND DISMISS
	NOSKED			;RESTORE NOSKED STATE
	RET			;RETURN NOSKIP

DWRTST::MOVSI 2,(DWRBIT)	;SCHED TEST FOR WRITE COMPLETED
	TDNE 2,@CST3X+1
	JRST 0(4)
	JRST 1(4)

;SKIP IF PAGE NOT LOCKED IN CORE.  CAN'T DINK WITH LOCKED PAGE.
; T1/ PAGE NUMBER
;	CALL SKPNLK
; RETURN +1: PAGE LOCKED
;	+2: PAGE NOT LOCKED

SKPNLK::PUSH P,T1		;SAVE T1 FOR A BIT
	HRRZS T1		;GET ONLY DESIRED INDEX BITS
	TMNE PLKMSK,@CST1X+T1	;PAGE LOCKED?
	JRST PA1		;YES
	POP P,T1		;NO
	RETSKP			;AND RETURN WITH A SKIP RETURN
;WAIT FOR PAGE TO BE NOT LOCKED.
; T1/ PAGE NUMBER
;	CALL WTNLK
; RETURN +1 ALWAYS WHEN PAGE UNLOCKED.  GOES OKSKED WHILE DISMISSED.

WTNLK::	SAVEAC <T1>
	HRRZS T1		;GET ONLY DESIRED INDEX BITS
	TMNN PLKMSK,@CST1X+T1	;LOCKED NOW?
	RET			;NO, RETURN QUICK
	HRL T1,T1		;SETUP PAGE NUMBER FOR SCHED TEST
	HRRI T1,NLKTST		;AND TEST ROUTINE ADDRESS
	RDISMS			;OKSKED AND BLOCK IN BALSET
	NOSKED			;BACK TO NOSKED
	RET			;AND RETURN TO CALLER

;SCHEDULER TEST
; T1/ PAGE NUMBER
; CALLED WITH JSP T4,

NLKTST::TMNE PLKMSK,@CST1X+T1	;PAGE LOCKED NOW?
	JRST 0(T4)		;YES
	JRST 1(T4)		;UNLOCKED
;HANDLE BAD CORE PAGE--CALLED AS RESULT OF PARITY ERROR OR OTHER
;PROBLEM WITH PHYSICAL PAGE.
; T1/ CORE PAGE NUMBER
;	CALL BADCPG
; RETURN +1, CONTENTS NOT RECOVERABLE
; RETURN +2, CONTENTS RECOVERABLE.

;THE CONTENTS ARE RECOVERABLE IF THE PAGE IS UNMODIFIED, I.E. THE
;DATA CAN BE READ FROM DISK OR DRUM AGAIN.  IN THIS CASE, THE
;POINTERS ARE RESET AND THE NEXT PROCESS REFERENCE SHOULD CAUSE
;THE PAGE TO BE READ INTO A DIFFERENT PHYSICAL CORE PAGE.
;IF THE PAGE HAS BEEN MODIFIED OR IF IT IS LOCKED, IT IS LEFT
;MAPPED AND ANY PROCESSES WHICH REFERENCE THE BAD DATA SHOULD GET
;INTERRUPTS.  IN EITHER CASE, THE PAGE IS LOCKED SO THAT IT WILL
;NOT BE USED AGAIN.

BADCPG::CAMGE T1,MONCOR		;RESIDENT PAGE?
	BUG.(HLT,RPGERR,PAGUTL,HARD,<BADCPG - Fatal error in resident page>,,<

Cause:	A hardware error (AR/ARX parity error or MB parity error) was
	detected when the monitor referenced a page in memory that
	contained part of the resident monitor. The monitor has printed
	an analysis of the error on the CTY, and A SYSERR entry will be
	created when the monitor is rebooted.
>)
	NOSKED
	MOVX T2,-PLKV
	MOVX T3,CORMB
	TDNN T2,@CST1X+T1	;PAGE LOCKED?
	TDNE T3,@CST0X+T1	;OR MODIFIED?
	JRST BADCP3		;YES
	MOVEI T2,PSTERR		;NO, SET PAGE TO ERROR STATUS
	STOR T2,CSTPST,+T1	; ...
	CALL RPCST		;RESET POINTERS
	LOAD T2,CSTAGE,+T1	;GET PRESENT AGE
	CAIN T2,PSRPQ		;ON RPLQ (CANN HAPPEN, BUT IS RARE)
	JRST [	MOVE T2,T1	;YES
		CALL PRLDEQ	;DEQUEUE THE PAGE
		MOVE T1,T2	;GET BACK PAGE NUMBER
		JRST .+1]	;PROCEED
	PIOFF			;INTERLOCK CALL
	CALL ONSPMQ		;PLACE ON SPMQ, RETURNS PION
	AOS NBADCP		;COUNT LOSSAGE
	OKSKED
	RETSKP
;HERE IF CANNOT RELEASE PAGE BECAUSE MODIFIED OR LOCKED

BADCP3:	MOVE T2,@CST2X+T1	;GET OWNER IDENT, FIND OFN IF ANY...
	HLRZ T3,T2
	JUMPN T3,[CAIL T3,NOFN	;HAVE PTN, IS OFN?
		JRST BADCP2	;NO, FORK PAGE
		MOVE T2,T3	;YES
		JRST BADCP1]	;GO MARK OFN
	CAIL T2,NOFN		;IS PAGE AN XB?
	JRST [	HLRZ T2,SPTH(T2) ;NO, GET OWNING PT
		JUMPN T2,BADCP1	;GO MARK IT
		BUG.(HLT,FRKPTE,PAGUTL,HARD,<BADCPG - Fatal error in fork PT page>,,<

Cause:	A hardware error (AR/ARX parity error or MB parity error) was
	detected when the monitor referenced a page in memory that
	contained a process's page table. The monitor has printed
	an analysis of the error on the CTY, and A SYSERR entry will be
	created when the monitor is rebooted.
>)]
BADCP1:	CAIL T2,NOFN		;ARE WE IN OFN SECTION OF SPTH ?
	BUG. (HLT,MARK1,PAGUTL,SOFT,<BADCPG - Not an OFN>,<<T2,SPTIDX>,<T1,COREPG>>,<

Cause: An OFN is in error but the SPT index is not pointing to an OFN.

Data:	SPTIDX - SPT index
	COREPG - Core page number
>)
	MOVX T3,OFNERR		;MARK ERROR IN OFN, REPORTED ON CLOSF
	IORM T3,SPTH(T2)
BADCP2:	MOVEI T2,PSTERR		;INDICATE ERROR IN PAGE
	STOR T2,CSTPST,+T1	; ...
	AOS NBADCP
	OKSKED
	RET			;RETURN NOT RECOVERABLE
;SETUP IO PAGE -- LOCKED AND MAPPED VIA MON MAP
; 1/ IDENT OF SOURCE
; 2/ ACCESS,,MON ADR
;	CALL SETIOP
; RETURN +2, PAGE LOCKED AND MAPPED

SETIOP::ASUBR <SOURCE,BFRP>
	LOAD 2,VPGNO,2		;GET PAGE NUMBER
	HRRM 2,BFRP
	SKIPE 1,MMAP(2)		;PREVIOUS CONTENTS?
	JRST [	SETZM MMAP(2)	;YES, REMOVE
		TXNE T1,NCORTM	;CORE?
		JRST .+1	;NO, FORGET IT
		HRRZ 1,1	;GET CORE PAGE NUMBER
		MOVX T3,-PLKV
		TDNN T3,@CST1X+T1 ;LOCKED?
		JRST .+1	;NO, FORGET IT
		CALL MULKCR	;UNLOCK IT
		JRST .+1]
	SKIPN 1,SOURCE		;GET SOURCE ID
	JRST SETIO1		;NONE, JUST RESETTING PREVIOUS PAGE
	CALL MLKPG		;LOCK PAGE AND GET CORE PAGE NUMBER
	IOR 1,IMMPTR		;CONSTRUCT POINTER
	MOVE 2,BFRP		;GET ACCESS REQUEST
	TXNN 2,PA%WT		;WRITE WANTED?
	TXZ 1,PTWR		;NO, CLEAR IT
	MOVEM 1,MMAP(2)		;PUT PAGE IN MON MAP
	HRRZS T1		;MAKE ADDRESS FOR CST0(T1)
	MOVX T3,CORMB
	TXNE T2,PA%WT		;PAGE WRITABLE?
	IORM T3,@CST0X+T1	;YES, ASSUME IT WILL BE WRITTEN
	CALL KICLKP		;PUT PAGE IN KI MAP
SETIO1:	RETSKP

;MARK MODIFIED PAGE - USED WHEN PAGE IS BEING MODIFIED BY OTHER
;THAN PROCESSOR REFERENCE, E.G. BY IO VIA CHANNEL.
; T1/ CORE PAGE NUMBER
;	CALL MRKMPG
; RETURN +1 ALWAYS, MODIFIED BIT SET FOR SPECIFIED PAGE

MRKMPG::CAML T1,MONCOR		;VALIDATE PAGE
	CAMLE T1,NHIPG
	BUG.(HLT,ILPAGN,PAGUTL,SOFT,<MRKMPG - Invalid page number>,,<

Cause:	A routine has been called to mark a page as modified (to
	set the CORMB flag in CST0). The BUGHLT indicates that the
	core page number provided by the caller is invalid.
>)
	SETONE CORMB,@CST0X+T1	;MARK IT
	RET
;CREATE A GROUP OF PAGES AND LOCK IN CORE
;CALL
;T1/ START ADDR,,END ADDR
;	CALL CGPLK
;RETURNS+1: ERROR IN LOCKING A PAGE
;	+2: ALL OK

CGPLK::	PUSH P,P2		;SAVE AC
	MOVEI P2,[SKIP (P4)	;CREATE PAGE
		CALL MLKPG	;LOCK IT
		JUMPE T1,[POP P,(P) ;SCRAP RETURN
			JRST BSMGPX] ;EXIT
		SETONE CSWRB,+T1
		RET]
	CALL BSMGP		;MAP THE REGION ONTO SUBR IN P2
	POP P,P2		;RESTORE AC
	JUMPE T1,R		;FAILURE?
	RETSKP			;NO.

;SUBROUTINE TO UNLOCK A GROUP OF PAGES OWNED BY MMAP
;T1/ START ADDR,,END ADDR
;	CALL GPULK
;RETURNS+1:	ALWAYS

GPULK::	PUSH P,P2		;SAVE AC
	MOVEI P2,MULKPG		;SUBR TO CALL
	CALL BSMGP		; MAP ONTO SUBR
	POP P,P2		;RESTORE AC
	RET

;SUBROUTINE TO UNLOCK A GROUP OF PAGES IN AN EXTENDED SECTION
;T1/ START ADDR,,END ADDR
;T2/ SPT INDEX OF PAGE TABLE
;	CALL XGPULK
;RETURNS+1:	ALWAYS

XGPULK:	PUSH P,P2		;SAVE AC
	MOVEI P2,MULKPG		;SUBR TO CALL
	CALL BSMGG		; MAP ONTO SUBR
	POP P,P2		;RESTORE AC
	RET
;LOCK, UNLOCK PAGE ON REQUEST (FOR DTA IO, ETC.)
; 1/ ADDRESS (+1B0 IF USER)
;RETURN +1: 1/ CORE PAGE NUMBER

MLKMA::	TLNN 1,(1B0)		;LOCK PAGE GIVEN ADDRESS. USER?
	SKIPA 0(1)		;NO, MON. REF PAGE TO ENSURE EXISTS
	XCTU [SKIP 0(1)]
	CALL FPTA		;TRANSLATE ADDRESS TO OFN.PN
;	JUMPE T1,SETMPX		;CAN'T HAPPEN SINCE REFERENCE TO PAGE
				;SUCCEEDED

;LOCK PAGE GIVEN OFN.PN
; 1/ OFN,,PN

MLKPG::	EA.ENT			;RUN IN SECTION 1
	SKIPE INSKED		;IN SCHED CONTEXT?
	JRST MLKPGM		;YES, SPECIAL HANDLING
	PUSH P,1
	CALL GETONT		;GET PTN.PN OF OWNING PT
	JUMPE T2,MLKPG2		;JUMPE IF PAGE DOES NOT EXIST
	TLNN 2,(NCORTM)		;PAGE NOW IN CORE?
	JRST MLKPG1		;YES.
MLKPG4:	CALL SWPINW		;INITIATE SWAP AND WAIT FOR COMPL.
	POP P,1
	OKSKED
	JRST MLKPG		;TRY AGAIN

MLKPG2:	TLNN T1,-1		;IN SPT?
	JRST [	MOVX T2,UAAB	;YES, SETUP ADDRESS
		STOR T2,STGADR,SPT(T1)
		JRST MLKPG4]
	CALL SETCPT		;IN A PAGE TABLE - MAP IT
	HRRZ T2,T1
	MOVE T3,IMMPTR		;CONSTRUCT PTR WITH UNASSIGNED ADR
	TXO T3,UAAB
	MOVEM T3,CPTPGA(T2)	;PUT IT IN PT
	CALL RELCPT
	JRST MLKPG4
;MLKPG IN SCHED CONTEXT - NONX PAGE IN MONMAP ONLY

MLKPGM:	HLRZ T2,T1		;GET PT IDENT
	JUMPE T2,MLKPG8		;JUMP IF SPT ID GIVEN
	HRRZ T3,T1		;GET PAGE NUMBER
	CAMN T2,MMSPTN		;IN MMAP?
	JRST MLKPG9		;YES. TREAT AS ALWAYS
	CALL SETSPG		;MAP THE PAGE TABLE
	MOVE T2,IMMPTR
	TXO T2,UAAB		;INITIALIZE THE ENTRY
	SKIPE CSWPGA(T3)	;EMPTY NOW?
	CAMN T2,CSWPGA(T3)	;OR CANONICAL UNASSIGNED PTR?
	IFSKP.
	  JRST MLKPGX		;NO, CAN'T HANDLE IT
	ENDIF.
	MOVEM T2,CSWPGA(T3)
	CALL RELSPG
	JRST MLKPG8

MLKPG9:	CAMN T2,MMSPTN		;IN MONMAP?
	SKIPE MMAP(T3)		;PAGE IS NON-EXISTENT?
MLKPGX:	BUG.(HLT,ILPLK1,PAGUTL,SOFT,<MLKPG - Illegal arguments>,,<

Cause:	A routine was called to create a page in the monitor's
	address space. But the caller provided a page identifier that
	pointed to an existing page.
>)
	MOVE T2,IMMPTR		;CONSTRUCT PTR WITH UNASSIGNED ADR
	TXO T2,UAAB
	MOVEM T2,MMAP(T3)	;PUT IN MON MAP
MLKPG8:	CALL SWPIN		;ASSIGN CORE AND CLEAR IT
	HLRZ T1,T1		;GET CORE PAGE NUMBER ASSIGNED
	MOVEI T3,PSASN
	STOR T3,CSTAGE,+T1	;SET STATE TO IN-USE
	MOVEI T3,OFNUL
	STOR T3,CSTOFK,+T1	;SET OWNERSHIP TO UNASSIGNED
	MOVX T3,CFXNUL
	STOR T3,CFXRD,+T1
	JRST MLKCP		;LOCK AND ADJUST VARIABLES

;Lock page given PT.PN, and assume page is already in core
;Used by PGRINI
; Call:	T1/ PT.PN
;	CALL MLKSPN
;Return +1 always

MLKSPN:	SAVEAC <P1>
	HRRZ P1,T1		;Page offset to P1
	HLRZS T1		;SPT index
	CALL SETSPG		;Map page table
	LOAD P1,STGADR,+CSWPGA(P1) ;Get storage address (core page #)
	CALL RELSPG		;Clear temporary mapping
	MOVE T1,P1		;Retrieve core page #
	CALLRET MLKCP		; and let MLKCP do the work
;LOCK PAGE GIVEN CORE PAGE NUMBER
; T1/ PAGE NUMBER
;	CALL MLKCP
; RETURN +1 ALWAYS, T1 PRESERVED

;LOCK PAGE COMMON CODE

MLKCP::	NOSKD1
	SKIPA T2,T1
MLKPG1:	POP P,1
	HRRZS T1,T2
	CAMGE T2,MONCOR		;WITHIN RANGE?
	JRST MLKPG5
	MOVE 1,@CST1X+2
	TLNE 1,(-PLKV)		;PAGE LOCKED NOW?
	JRST MLKPG3
	AOS LOKPGS		;NO, COUNT IT
	AOS BALSHC
	AOS SUMNR
	AOS SUMBNR
	TLO 2,(1B0)		;SET LOCAL FLAG FOR TEST BELOW

;[7.1065]
;Nota importante or we breaka you fingas - There is a big race condition
;here. The monitor foolishly attempts to lock a page and then call AGESET
;to do the right thing. If a swap is in progress, this is bad because the
;SWPDON routine will notice that we have locked the page behind the swapper's
;back. While this isn't all that bad, it isn't good (causes PLKRPQ BUGHLTs).
;Anyway, the following code has been taught to turn PI's off before locking
;the page and then calling AGESET to do the right thing. This will prevent
;the race between the swapper and the page locker. Note that AGESET through
;ATP4 will go PION so the second PION in this routine is a mahvelous NOP.

MLKPG3:	SKIPN INSKED		;[7.1065] If in scheduler, don't PIOFF
	PIOFF			;[7.1065] Don't bother me when I lock
	MOVSI 1,(PLKV)
	ADDM 1,@CST1X+2		;INCREMENT LOCK COUNT
	AOS LOKSUM
	SKIPE INSKED		;IN SCHED CONTEXT?
	RET			;YES, DONE
	HRRZ T1,T2
	CALL AGESET		;SET AGE
	PION			;[7.1065] All lock and cool
	CALL DECOR
	CALL MONCLA
MLKPG5:	OKSKD1
	RET
; FMLKPG - Fast memory page lock.
; This routine locks a virtual page. The routine only assumes that the page
;already exists. Real problems may result if the page does not exist and
;you are in sched context or at interrupt level.
;
; Usage:
;	Call
;	T1/	Virtual address of the page table
;	T2/	Page number within the section
;
;	Return (+1) Always
;	T1/	Physical page associated with callers virtual page
;
FMLKPG::ADD T1,T2		;Get the address of the page table entry
	MOVE T2,(T1)		;Get the page table entry for the given page
	LOAD T1,STGADR,T2	;Get the physical page number of page to lock
	MOVX T2,PLKV		;Get the low order bit of the lock count field
	ADDM T2,@CST1X+T1	;Increment the lock count for the page
	RET			;All done... Nice and quick...
;UNLOCK PAGE
; 1/ PAGE IDENT (OFN,,PN)
;	CALL MULKPG
; RETURN +1 ALWAYS, BUGHLT IF PAGE NOT PREVIOUSLY LOCKED

MULKPG::PUSH P,2
	CALL GETONT		;GET OWNING PT
	CAIE T2,0		;PAGE EXISTING?
	TLNE 2,(NCORTM)		;PAGE NOW IN CORE?
	BUG.(HLT,ILULK1,PAGUTL,SOFT,<MULKPG - Tried to unlock page not locked>,,<

Cause:	A routine was called to unlock a core page, but the page was
	not in core, indicating it could not have been locked.
>)
	CALL MULK1
	POP P,2
	OKSKED
	RET

MULK1:	EA.ENT			;RUN IN SECTION 1
	MOVSI 1,(-PLKV)
	HRRZS 2
	CAMGE T2,MONCOR		;WITHIN RANGE?
	RET			;NO, IGNORE
	TDNN 1,@CST1X+2		;LOCK COUNT NON-ZERO?
	BUG.(HLT,ILULK2,PAGUTL,SOFT,<Tried to unlock page not locked>,,<

Cause:	A routine was called to unlock a core page, but the page's
	lock count was 0.
>)
	SKIPN INSKED
	AOS NSKED		;PREVENT SCHED WHILE COUNTS BEING ADJUSTED
	CALL ULKP2		;DECREMENT LOCK COUNT
	MOVE T1,@CST1X+2	;GET BITS
	TLNE 1,(-PLKV)		;NOW UNLOCKED?
	JRST MULK2		;NO
	SOS LOKPGS
	CALL UPSWP		;ONE MORE SWAPPING PAGE
	SKIPE @CST2X+2		;STILL EXISTS?
	JRST MULK2		;YES
	MOVEI 1,0(2)		;HAS BEEN DELETED, PUT ON RPLQ
	CALL OFRQ		;PUT ON TOP OF RPLQ FOR IMMEDIATE REUSE
MULK2:	SOS LOKSUM
	SKIPN INSKED
	SOS NSKED		;OKSKED
	RET
;UNLOCK PAGE GIVEN MONITOR ADDRESS
;ASSUMED NOSKED OR INSKED

MULKMP::
	CALL FPTA		;GET PTN.PN
	HLRZ T3,T1		;GET OWNING PT
	CAME T3,MMSPTN		;AN MMAP PAGE?
	BUG.(HLT,ILULK3,PAGUTL,SOFT,<MULKMP - Illegal monitor address>,,<

Cause:	A routine was called to unlock a core page in the monitor's
	address space but the caller provided a page identifier that did not
	point to the monitor's map.
>)
	TLZ T1,-1		;SO INDEX BELOW WORKS
	LOAD T1,STGADR,MMAP(T1)	;GET CORE ADDRESS
	JRST MULKCR

;UNLOCK PAGE GIVEN CORE PAGE NUMBER IN 1
;MAY BE CALLED AT INTERRUPT LEVEL

MULKCR::CAML 1,MONCOR		;LEGAL?
	CAMLE 1,NHIPG
	BUG.(HLT,ILULK4,PAGUTL,SOFT,<MULKCR - Illegal core page number>,,<

Cause:	A routine was called to unlock a core page. The caller provided
	a page number that was illegal because of one of the following:

	1. The page is never locked because it is part of the resident
	   monitor

	2. The page does not exist in physical memory.
>)
	PUSH P,2
	MOVEI 2,0(1)
	CALL MULK1
	POP P,2
	RET
;MULKSP - UNLOCK A PAGE IN NON-ZERO SECTION.  THIS ROUTINE  MAY BE
;CALLED AT ANY INTERRUPT LEVEL.

;ACCEPTS:  T1/  VIRTUAL ADDRESS

;RETURNS: +1  ALWAYS

MULKSP::PUSH P,T2		;SAVE T2
	CALL GETCPA		;GET REAL PAGE ADDRESS
	POP P,T2		;RESTORE T2
	HRRZS T1		;RETAIN JUST PAGE NUMBER
	CALLRET MULKCR		;GO UNLOCK THE PAGE

;ROUTINE TO ADJUST SWAPPING WHEN PAGES ARE LOCKED OR
;UNLOCKED

;FIRST. ROUTINE TO ADJUST PARAMETERS ON UNLOCK

UPSWP:	SOS BALSHC		;ONE LESS OVERHEAD PAGE
	SOS SUMNR		;AND REMOVE LIEN FROM BALSET
	SOS SUMBNR
	RET			;DONE

;ROUTINE TO ADJUST SWAPPING/SCHEDULING PARAMETERS
;CALLED BY SCHEDULER OR PAGER  WHENEVER NEW PAGES APPEAR IN SYSTEM
;RECOMPUTES ALL VALUES BASED ON TOTRC (E.G. MAXNR, DRMLV0, ...)

ADJSWP::PIOFF			;PROTECT ALL STRUCTURES
	CALL MEMMGT		;RECOMPUTE BASIC SWAPPING PARAMETERS
	SETZM PAGDIF		;NO NEW PAGES
	PION			;OKAY NOW
	MOVE T1,DRMTPG		;GET NUMBER OF SWAPPING PAGES
	CALLRET SETSSP		;AND RECOMPUTE "DRUM" USAGE
;COMMON SUBROUTINE TO MAP A GROUP OF PAGES FROM LH(T1) TO RH(T1)
;ONTO A SUBR. WHOSE ADDRESS IS IN P2.  IF MMAP IS OWNER OF PAGES,
;CALL BSMGP.  OTHERWISE PUT SPT INDEX IN T2 AND CALL BSMGG.
;T1/ BEGINNING ADDRESS,,ENDING ADDRESS
;T2/ SPT INDEX OF PAGE TABLE OWNING PAGES
;P2/ SUBROUTINE TO BE CALLED

BSMGP::	MOVE T2,MMSPTN		;GET MMAP'S SPT INDEX FOR USUAL CASE
BSMGG:	TDZ T1,[PGSIZ-1,,PGSIZ-1]	;ROUND BOTH ARGS DOWN TO PAGE BOUNDARY
	STKVAR <<ACS1,2>,BSSPN>
	DMOVEM P3,ACS1		;SAVE ACS
	MOVEM T2,BSSPN
	MOVE P3,T1		;COPY ARG
	HLRZ P4,T1		;INITIALIZE CURRENT PAGE
BSMGP1:	HRRZ T1,P4		;BUILD PT.PN
	LSH T1,-PGSFT		; ...
	HRL T1,BSSPN		; ...
	CALL 0(P2)		;CALL SUBR
	ADDI P4,1000		;GO ON TO NEXT PAGE
	CAIG P4,(P3)		;DONE?
	JRST BSMGP1		;NO, LOOP BACK
BSMGPX:	DMOVE P3,ACS1
	MOVE T2,BSSPN
	RET
;GET CORE PAGE GIVEN ADDRESS OR IDENTIFIER
;CLOBBERS T2

GETCPA::CALL FPTA		;CONVERT ADDRESS TO IDENTIFIER
	JUMPE T1,GETCPX		;IF NOT EXISTANT, NOT IN CORE
GETCPP::SAVEQ
	MOVEI Q2,MAXIND		;MAX INDIRECT LEVELS PERMITTED
	HLRZ 2,1		;PT IDENT
	MOVE 2,SPT(2)		;ADR OF IT
	TLNE 2,(NCORTM)		;IN CORE?
GETCPX:	BUG.(HLT,PAGNIC,PAGUTL,SOFT,<GETCPP - Page not in core>,,<

Cause:	A routine was called to convert a virtual address or page id
	to its corresponding core page. But the page table is not in
	core.
>)
	HRRZS T1		;Offset into page
	HRRZS T2		;SAVE ONLY PAGE NUMBER
	LSH T2,PGSFT		;[7.1002] Make page number be an address
	IOR T1,T2		;[7.1002] Put offset and page number together
	PMOVE T1,T1		;[7.1002] MOVE T1,PT(T1)
	LOAD Q1,PTRCOD,1	;GET PTR TYPE
	CAIN Q1,IMMCOD		;PRIVATE?
	RET			;YES
	CAIE Q1,INDCOD		;INDIRECT?
	JRST [	LOAD 2,SPTX,1	;SHARED, GET SPT IDX
		MOVE 1,SPT(2)
		RET]
	LOAD Q1,SPTX,2		;GET PT NUMBER
	LOAD 1,IPPGN,2		;GET PAGE NUMBER
	HRL 1,Q1		;CONSTRUCT IDENT
	SOJG Q2,GETCPP		;LOOP, COUNT INDIRECT LEVELS
	JRST GETCPX		;TOO MANY INDIRECTS
;GET OWNING PAGE TABLE
;GIVEN PTN.PN, LOCATE PT CURRENTLY HAVING ADDRESS OF PAGE

   REPEAT 0,<
GETONM:	SAVEQ			;THIS ENTRY ALLOWS NO IND PTRS
	MOVEI Q2,0
	JRST GETON0
   >

GETONT:	SAVEQ
	MOVEI Q2,MAXIND		;MAX NUMBER INDIRECTS PERMITTED
GETON0:	TLNE T1,-1		;IN SPT?
	IFSKP.
	  LOAD T2,STGADR,SPT(T1) ;YES
	  RET
	ENDIF.
	CALL SETCPT		;MAP GIVEN PAGE TABLE
	NOSKED
	HRRZ 2,1
	MOVE 2,CPTPGA(2)	;GET PTR
	JUMPE T2,GETONX		;RETURN IF NONX PAGE
	LOAD Q1,PTRCOD,2	;GET PTR TYPE
	CAIN Q1,IMMCOD		;PRIVATE?
	JRST GETONX
	CAIE Q1,INDCOD		;INDIRECT?
	JRST GETON1		;NO, SHARE POINTER.
	OKSKED
	HRRZ T1,T1
	CAME T1,MMSPTN		;INDIRECT PTR IN MON MAP?
	SOJLE Q2,[SETZ T2,	;NO, COUNT IT
		JRST GETONX]
	LOAD 1,IPPGN,2		;GET PAGE NUMBER
	LOAD 2,SPTX,2		;GET PT NUMBER
	HRL 1,2			;CONSTRUCT IDENT
	CALL RELCPT		;RELEASE CPT
	JRST GETON0		;LOOP

GETON1:	LOAD 1,SPTX,2		;FOR SHARE POINTER, RETURN SPTN
	MOVE 2,SPT(1)		;AND CURRENT ADDRESS
GETONX:	CALLRET RELCPT		;RELEASE CPT AND RETURN
;LODPPG - LOAD VIRTUAL PAGE INTO PHYSICAL LOCATION
;CALL WITH:
;T1/	PTN.PN
;T2/	BITS,,PHY. PAGE
;T3/	PREVIOUS STATE IF ENTERED AT LODPPS
;BITS ARE:
;LK%NCH		DON'T CACHE PAGE
;LK%PHY IF OFF, FREE CHOICE OF PAGE
;LK%AOL ALLOW LOCKING IN OFF-LINE MEMORY
;	CALL LODPPG
;	 ERROR RETURN, CAN'T LOAD PAGE, CODE IN 1
;	SUCCESS PAGE IS LOADED AND LOCKED
;SHOULD ALWAYS BE CALLED NOINT
;VIRTUAL PAGE MUST BE PRIVATE OR NON-EXISTANT
;POINTER WILL HAVE PTLOK SET WHICH WILL CAUSE IT TO BE UNLOCKED
;BY RELMPG.

LODPPG::TXO T3,1B0		;NO SPECIAL "PREVIOUS STATE"
LODPPS::ASUBR <LODSRC,LODDST,LODPST>
	TXNN T2,LK%PHY		;FREE CHOICE?
	JRST LODFRE		;YES. GO CHOOSE
LODPP3:	HRRZ T1,LODDST		;GET PHY PAGE
	LOAD T2,CSTPST,+T1	;GET CURRENT PAGE STATE
	SKIPGE LODPST		;ALREADY HAVE A "PREVIOUS STATE"?
	MOVEM T2,LODPST		;NO. SAVE HERE
	LOAD T2,CSTAGE,+T1	;GET AGE
	CAIN T2,PSSPQ		;ALREADY ON SPMQ?
	JRST [	MOVX T3,LK%AOL	;YES. SEE IF OFF-LINE LOCKING ALLOWED
		TDNE T3,LODDST	;IS IT?
		JRST LODPP1	;YES. PAGE WILL RETURN TO SPMQ
		RETBAD (LOCKX1)] ;NO. CAN'T DO IT THEN
	MOVEI T2,PSTOFL		;PLACE PAGE OFF LINE
	CALL SETPST		;PUT INTO SPMQ
	 RETBAD(LOCKX2)		;ERROR, CODE IN 1
LODPP1:	NOSKED			;OWN MACHINE FOR A WHILE
	HLRZ T3,LODSRC		;GET SOURCE PAGE
	CALL SETXB1		;MAP IT
	HRRZ T1,LODSRC		;GET PAGE NUMBER
	SKIPN T1,CXBPGA(T1)	;GET POINTER
	JRST LODPP0		;NON-EX. OKAY
	LOAD T2,PTRCOD,T1	;GET TYPE
	CAIE T2,IMMCOD		;PRIVATE?
LODBAD:	RETBAD (LOCKX1,<CALL RELCXB
			OKSKED>)
	ANDX T1,STGADM		;GET ADDRESS ONLY
	MOVX T2,-PLKV		;LOCK FIELD
	TXNN T1,NCORTM		;IN MEMORY?
	TDNN T2,@CST1X+T1	;YES. LOCKED?
	SKIPA			;NO. OKAY TO REPLACE IT
	JRST LODBAD		;LOCKED. CAN'T DO IT. SORRY!
	; ..
LODPP0:	CALL RELCXB		;FREE INDEX BLOCK
	HRRZ T1,LODDST		;GET PHY PAGE NUMBER
	CALL OFFSPQ		;REMOVE FROM SPMQ
	MOVEI T2,PSASN		;GET A GOOD AGE
	STOR T2,CSTAGE,+T1	;MAKE BLT WORK
	SETONE CSWRB,+T1	;ALLOW WRITE ACCESS TO THE PAGE
	MOVE T1,LODSRC		;GET SOURCE ADDRESS
	MOVE T2,[PTRW+FPG2A]	;MAP PAGE
	CALL SETMPG		;DO IT
	SKIP FPG2A		;GET DATA
	PIOFF			;OWN MACHINE
	HRRZ T1,LODDST		;GET DEST PAGE
	CALL MAPRCA		;MAKE IT ADDRESSABLE
	MOVE T2,T1		;SAVE ADDRESS
	HRLI T1,FPG2A		;SOURCE DATA
	BLT T1,PGSIZ-1(T2)	;MOVE DATA
	CALL UNMRCA		;CLEAR MAPPING
	PION			;BREATH A LITTLE NOW
	MOVEI T2,FPG2A		;WHERE WE PUT DATA
	SETZM T1		;UNMAP
	CALL SETMPG		;FREE IT
	MOVE T1,LODSRC		;WHERE NEW DATA IS TO GO
	HRRZ T2,LODDST		;PHYSICAL PAGE NUMBER
	CALL MAPPHP		;MAKE THEM ONE AND THE SAME
	 JFCL			;CAN'T FAIL
	HRRZ T1,LODDST		;GET PHY PAGE
	MOVE T2,LODPST		;GET OLD STATE BACK
	STOR T2,CSTPST,+T1	;WILL RETURN TO STATE WHEN RELEASED
	CALL MLKCP		;LOCK PAGE, SET AGE (REMOVE FROM FORK WS)
	OKSKED			;WE CAN REST NOW
	HLRZ T3,LODSRC		;GET PTN
	CALL SETXB1		;MAP IT
	HRRZ T1,LODSRC		;GET PN
	MOVX T2,PTLOK		;FLAG AS LOCKED POINTER
	IORM T2,CXBPGA(T1)	;IN PAGE TABLE
	JE LK%NCH,LODDST,LODPP2	;JUMP IF NO-CACHE NOT REQUESTED
   IFN KLFLG,<
	MOVX T2,PTCACH		;GET CACHE BIT
	ANDCAM T2,CXBPGA(T1)	;CLEAR IT
   >				;END OF IFN KLFLG
	HRRZ T1,LODDST		;GET PAGE #
	CALL CASHFP		;FLUSH FROM CACHE
LODPP2:	CALL RELCXB		;RELEASE PAGE TABLE
	RETSKP			;RETURN SUCCESS
;ULDPAG - UNLOAD PAGE IF LOCKED
;CALL WITH:
;T1/	PTN.PN
;	CALL ULDPAG
;	 ERROR, PAGE NOT LOCKED OR CAN'T BE SWAPPED, CODE IN 1
;	SUCCESS, PAGE SWAPPED OUT OF MEM.
;PAGE ALWAYS UNLOCKED IF WAS LOCKED AND CACHE BIT TURNED ON AGAIN

ULDPAG::STKVAR <ULDSRC,ULDDST>
	MOVEM T1,ULDSRC		;SAVE PTN.PN
	HLRZ T3,ULDSRC		;GET PTN
	CALL SETXB1		;MAP IT (RETURNS NOINT)
	HRRZ T2,ULDSRC		;USER PAGE
	MOVX T1,PTLOK		;LOCKED POINTER BIT
	NOSKED			;PROTECT THE PAGE POINTER
	LOAD T3,PTRCOD,CXBPGA(T2) ;GET POINTER TYPE
	CAIN T3,IMMCOD		;IMMEDIATE?
	TDNN T1,CXBPGA(T2)	;IS IT STILL LOCKED?
	JRST ULDPG1		;NO, JUST RETURN
	ANDCAM T1,CXBPGA(T2)	;CLEAR LOCKED POINTER BIT
   IFN KLFLG,<
	MOVX T1,PTCACH		;TURN CACHE BIT BACK ON (IF OFF)
	IORB T1,CXBPGA(T2)	;AND PICKUP POINTER
   >				;END OF IFN KLFLG
	ANDX T1,STGADM		;GET PHY ADDR ONLY
	MOVEM T1,ULDDST		;SAVE PAGE NUMBER
	CAML T1,MONCOR		;RES MON PAGE?
	CALL MULKCR		;NO, UNLOCK PAGE
	MOVE T1,ULDDST		;GET PAGE NUMBER AGAIN
ULDPG3:	MOVX T2,-PLKV		;SEE IF STILL LOCKED
	TDNN T2,@CST1X+T1	;IS IT?
	CALL SWPOT0		;NO. SWAP IT OUT THEN
ULDPG2:	MOVE T1,ULDDST		;GET PAGE NUMBER AGAIN
	CALL SKPNWR		;WAIT FOR IT TO FINISH
	 JRST ULDPG2		;TRY AGAIN
	HRRZ T2,ULDSRC		;PAGE NUMBER AGAIN
	LOAD T1,STGADR,CXBPGA(T2) ;GET STORAGE ADDRESS NOW
	TXNE T1,NCORTM		;IM MEMORY?
	JRST ULDPG1		;NO. ALL DONE
	LOAD T2,CSTAGE,+T1	;YES. GET ITS AGE THEN
	CAIN T2,PSRPQ		;ON RPLQ YET?
	JRST ULDPG1		;YES. DONE THEN
	MOVEM T1,ULDDST		;NO. SAVE MEM PAGE NUMBER
	JRST ULDPG3		;AND DO IT AGAIN
   REPEAT 0,<			;FOR NOW, WAIT FOR SWAP OUT
	MOVE T1,ULDSRC		;GET PTN.PN
	CALL SWPPAG		;SWAP PAGE OUT (CXBPG ALREADY HAS PTN)
	 RETBAD()		;RETURN ERROR (ALREADY RELEASED PTN)
	OKSKED			;RETURNED NOSKED
   >				;END OF REPEAT 0
ULDPG1:	OKSKED			;ALLOW SCHEDULING AGAIN
	CALL RELCXB		;RELEASE UPT (DOES OKINT)
	RETSKP

;HERE FROM LODPPG ON FREE CHOICE OF PAGE

LODFRE:	NOSKED			;PROTECT RPLQ
	CALL CHKRPQ		;WAIT FOR PAGES TO SHOW UP
	 JRST .-1		;WAIT SOME MORE
	HRRZ T1,@SRPLQ		;GET TOP PAGE
	CAIN T1,SRPLQO		;SRPLQ EMPTY?
	HRRZ T1,@DRPLQ		;YES, USE DRPLQ
	HRRM T1,LODDST		;MAKE IT THE TARGET PAGE
	OKSKED			;NO NEED FOR THIS NOW
	JRST LODPP3		;AND PROCEED
;SWPPAG - SWAP USER PAGE OUT AND WAIT UNTIL COMPLETE
;CALL WITH:
;T1/	PTN.PN
;	CALL SWPPAG
;	 ERROR, PAGE CAN'T BE SWAPPED, CODE IN 1
;	SUCCESS, PAGE IS NOW SWAPPED (RETURNS NOSKED)
;MUST BE CALLED NOINT
;PAGE MUST BE PRIVATE OR NOT EXIST.
;PAGE MUST NOT BE LOCKED

   REPEAT 0,<			;NOT PRESENTLY NEEDED
SWPPAG::STKVAR <SWPSRC,SWPTRY>
	MOVEM T1,SWPSRC
	MOVEI T2,10		;TRY THIS MANY TIMES
	MOVEM T2,SWPTRY
SWPPG1:	HLRZ T3,SWPSRC		;GET PTN
	CALL SETXB1		;MAP PAGE TABLE (GOES NOINT)
	SKIP CXBPGA		;SWAP IN IF NECESSARY
	NOSKED			;DON'T LET PAGE STATE CHANGE
	HRRZ T1,SWPSRC		;GET PAGE NUMBER
	SKIPN T1,CXBPGA(T1)	;GET POINTER
	JRST SWPPG4		;NON-EX
	CALL RELCXB		;RELEASE MAP (OKINT)
	LOAD T2,PTRCOD,T1	;GET POINTER CODE
	CAIE T2,IMMCOD		;PRIVATE?
	RETBAD(LOCKX1,OKSKED)	;NO, ILLEGAL
	TLNE T1,(NCORTM)	;IN CORE?
	RETSKP			;NO, SKIP RETURN NOSKED
	ANDX T1,STGADM		;GET ADDR ONLY
	MOVSI T2,(-PLKV)	;GET LOCK MASK
	TDNE T2,@CST1X+T1	;IS PAGE LOCKED?
	RETBAD(LOCKX2,OKSKED)	;YES, ERROR
	CALL SKPNWR		;WAIT FOR ANY WRITES TO FINISH
	 JRST SWPPG2		;HAD TO WAIT, CHECK EVERYTHING AGAIN
	LOAD T2,CSTAGE,+T1	;GET AGE
	CAIGE T2,PSASN		;ASSIGNED TO PROCESS?
	JRST SWPPG3		;NO, DEASSIGN
	CALL SWPOT0		;SWAP PAGE OUT
SWPPG2:	OKSKED
	JRST SWPPG1		;AND CHECK AGAIN

SWPPG3:	CALL RPCST		;DEASSIGN CST USAGE (SO WE CAN SWAP IN)
	RETSKP			;RETURN SUCCESS (NOW SWAPPED OUT) (NOSKED)

SWPPG4:	HRRZ B,SWPSRC		;GET VIRT PAGE #
	MOVE A,IMMPTR		;GET IMMEDIATE POINTER
	TXO A,UAAB		;SET UNASSIGNED ADDR BIT
	MOVEM A,CXBPGA(B)	;STORE IN PAGE TABLE
	CALL RELCXB		;RELEASE TEMP MAPPING
	RETSKP			;AND INDICATE SUCCESS
   >				;END OF REPEAT 0
;SETUP PAGER VARIABLES FOR NEW PROCESS
; FORKX/ FORK INDEX
;	CALL SETPPG
; RETURN +1 ALWAYS

SETPPG::MOVE FX,FORKX
SETPP1::LOAD T1,FKPSB		;GET CORE ADR OF PSB
	MOVE T1,SPT(T1)
	TXNE T1,NCORTM
	BUG.(HLT,PSBNIC,PAGUTL,SOFT,<SETPPG - PSB not in core>,,<

Cause:	The monitor is establishing the context for running a
	process by making its per-process area part of the
	monitor's map. It is about to copy the SPT entry for the
	PSB into a special SPT slot but the PSB is not in core.
>)
	STOR T1,PAGUBA		;PUT IT IN DATAO WORD
	MOVE T2,PSBBAS
	STOR T1,STGADR,SPT(T2)	;PUT IT IN MMAP BASE
	LOAD T1,FKPS2		;setup PSB extension
	MOVE T1,SPT(T1)
	MOVE T2,PS2BAS
	STOR T1,STGADR,SPT(T2)
	LOAD T1,FKJSB		;GET CORE ADR OF JSB
	MOVE T1,SPT(T1)
	TXNE T1,NCORTM
	BUG.(HLT,JSBNIC,PAGUTL,SOFT,<SETPPG - JSB not in core>,,<

Cause:	The monitor is establishing the context for running a
	process by making its per-job area part of the
	monitor's map. It is about to copy the SPT entry for the
	JSB into a special SPT slot. But the JSB is not in core.
>)
	MOVE T2,JOBBAS
	STOR T1,STGADR,SPT(T2)	;PUT IT IN MMAP BASE
   IFN EXTJSB,<
	LOAD T1,FKJPT		;Get SPT slot of PT for extended JSB
	MOVE T1,SPT(T1)		;Get the contents
	TXNE T1,NCORTM		;Page-table in core?
	BUG.(HLT,JPTNIC,PAGUTL,SOFT,<SETPPG-PT for JSB not in core>,,<

Cause:	The monitor is establishing the context for running a process by 
	making the PT for its extended per-job area part of the monitor's map. 
	It is about to copy the SPT entry for the extended JSB's page-table 
	into a special SPT slot. But the page-table is not in core.
>)
	MOVE T2,JPTBAS		;Get the magic SPT slot for our mapping game
	STOR T1,STGADR,SPT(T2)	;PUT IT IN MMAP BASE
   >

	MOVE T1,TODCLK		;COMPUTE AGE REGISTER
	IDIVI T1,GLATCK		;GET TIME IN GLOBAL AGE TICK UNITS
	IDIVI T1,AGEWRP		;REM = VALUE IN RANGE FOR AGE REG
	MOVEI T1,LGABOT(T2)	;ADD BIAS
	MOVEM T1,CURAGE		;SAVE FOR GCCOR
	SETZ T2,
	STOR FX,CFXRM,T2	;PUT FX IN CST UPDATE DATA
	STOR T1,AGEMSK,T2	;CONSTRUCT CST UPDATE WORD
	CALL MVAGER		;SET NEW AGE WORD
	RET
;CHKDMO - ROUTINE TO CHECK IF PAGE FAULT HAS OCCURRED ON A DISMOUNTED OFN
;ACCEPTS:	T2/ SPTN OF PAGE TABLE
;RETURNS:	+1 IF PAGE BELONGS TO A FILE ON A DISMOUNTED STRUCTURE
;		+2 IF PAGE IS OK TO FAULT ON

CHKDMO::SAVEAC <Q1,Q2>		;GET SOME REGS
	HRRZ Q2,T2		;GET SPTN FOR CHECKING
	CAIL Q2,NOFN		;AN OFN?
	JRST [	HLRZ Q2,SPTH(Q2) ;NO. SEE IF PAGE BELONGS TO A FILE
		SKIPN Q2	;DOES IT?
		RETSKP		;NO. OK TO USE IT
		JRST .+1]	;YES. MUST LOOK AT IT
	MOVX Q1,OFNDMO		;GET DISMOUNTED BIT
	TDNE Q1,SPTH(Q2)	;IS THIS A DISMOUNTED OFN?
	RET			;YES. SAY SO
	RETSKP			;NO
;ROUTINE CALLED FROM PHYSIO TO GET STRUCTURE NUMBER FOR GIVEN
;CORE PAGE NUMBER. IT WILL HANDLE EITHER FILE PAGE OR SWAPPING REQUESTS
;ACCEPTS:	A/ CORE PAGE NUMBER
;RETURNS: +1	B/ STRUCTURE NUMBER

FNDSTR::EA.ENT			;RUN THIS ROUTINE IN SECTION 1
	HLRZ B,@CST2X+A		;GET PTN FROM CST
	JUMPN B,HAVPT		;IF HAVE ONE GO ANALYZE IT
	HRRZ B,@CST2X+A		;GET SPTN
	CAIGE B,NOFN		;IS THIS AN OFN?
	JRST GOTOFN		;YES. GO CONSIDER IT
	HLRZ B,SPTH(B)		;NO. GET OFN FOR THIS SPT
	JUMPN B,GOTOFN		;IF A FILE PAGE JUMP TO LOOK AT IT
RTZRO:	SETZ B,			;IS NOT A FILE PAGE. ASSUME SWAPPING SPACE
	RET			;DONE

HAVPT:	CAIL B,NOFN		;IS THIS AN OFN?
	JRST RTZRO		;NO
GOTOFN:	LOAD B,STRX,(B)		;YES. GET STRUCTURE NUMBER
	RET			;AND RETURN
;FIND TYPE OF FORK PAGE
; A/ SPTH OF PAGE
;	CALL FNDFPG
; RETURNS +1 ALWAYS,
; A/ 	0 - UNKNOWN PAGE OR HWPT
;	1 - PSB
;	2 - UPT
;	3 - JSB

FNDFPG::SAVEQ
	SKIPE FX,SPTH(A)	;HAVE GOOD FORX INDEX?
	TLNE FX,-1
	JRST RETZ		;NO, RETURN UNKNOWN
	HRRZ Q1,A		;SAVE SPTH
	MOVSI A,-NFNFT		;SETUP TO SCAN TABLE
FNFP1:	XCT FNFTAB(A)		;GET SPTN FOR A FORK PAGE
	CAMN B,Q1		;SAME AS GIVEN ONE?
	RET			;YES, RETURN INDEX IN A
	AOBJN A,FNFP1		;SCAN TABLE
	JRST RETZ		;NOT FOUND

FNFTAB:	LOAD B,FKPS2
	LOAD B,FKPSB
	LOAD B,FKUPT
	LOAD B,FKJSB
   IFN EXTJSB,<
	LOAD B,FKJPT
   >
NFNFT==.-FNFTAB
;HERE TO PLACE A PAGE ON THE SPECIAL MEMORY QUEUE
;MUST BE CALLED PIOFF
;T1/ CORE PAGE NUMBER
;	CALL ONSPMQ
;RETURNS+1(ALWAYS):
;PAGE REMOVED FROM CST, ON SPMQ
;**NOTE**: RETURNS PION

ONSPMQ::CALL DASPAG		;REMOVE PAGE FROM CST
	LOAD T2,CSTAGE,+T1	;GET STATE CODE
	CAIN T2,PSSPQ		;ALREADY ON SPMQ?
	JRST ONSPQX		;YES - DONE
	MOVEI T2,(T1)		;BUILD POINTER
	HLRZ T3,@SPMQ		;GET TAIL POINTER
	HRRM T2,@CST3X+T3	;APPEND TO LIST
	HRLZM T3,@CST3X+T1	;BACK POINTER
	HRLM T2,@SPMQ		;NEW TAIL OF LIST
	MOVEI T2,PSSPQ		;SET PAGE STATE TO ON SPMQ
	STOR T2,CSTAGE,+T1	; ...
	AOS NSPMQ		;NOTE ANOTHER PAGE
	CAMG T1,NHIPG		;A KNOWN PAGE?
	CAMGE T1,MONCOR		;SWAPPABLE?
	JRST ONSPQX		;NO, ALL DONE
	SOS TOTRC		;ONE LESS REAL PAGE
	AOS PAGDIF		;MAKE SHCEDULER NOTICE THIS
ONSPQX:	PION			;ENABLE INTERRUPTS
	RET			;ALL DONE
;ROUTINE TO REMOVE A PAGE FROM SPMQ
;T1/ PHYSICAL PAGE
;	CALL OFFSPQ
;RETURNS+1(ALWAYS):
;	PAGE REMOVED
;CAUTION - THE CALLER MUST BE SURE THE PAGE IS "STABLE" ON SPMQ

OFFSPQ::PIOFF			;INTERLOCK
	LOAD T2,CSTAGE,+T1	;GET CURRENT AGE
	CAIE T2,PSSPQ		;NOW ON THIS QUEUE?
	BUG.(HLT,OFFSPE,PAGUTL,SOFT,<OFFSPQ - Page not on SPMQ>,,<

Cause:	A routine has been called to remove a core page from the special
	memory queue. If a page is on the queue, its age should be
	PSSPQ. The BUGHLT indicates that the age is incorrect. The
	entry may or may not actually be on the queue. The caller is
	expected to ensure that the page is on the queue.
>)
	HRRZ T2,@CST3X+T1	;GET POINTERS
	HLRZ T3,@CST3X+T1
	JUMPE T2,[HRLM T3,@SPMQ	;IF END-OF-LIST, MAKE NEW TAIL
		JRST OFFSP0]	;PROCEED
	HRLM T3,@CST3X+T2	;ADVANCE BACK POINTER
OFFSP0:	HRRM T2,@CST3X+T3		;BACKUP FORWARD LINK
	MOVX T2,UAAB		;UNASSIGNED ADDRESS
	STOR T2,STGADR,@CST1X+T1 ;SET IT
	MOVX T2,<FLD(OFNUL,CSTOFK)>
	MOVEM T2,@CST3X+T1	;SET OWNER TO NULL
	SOS NSPMQ		;ONE FEWER PAGE
	CAMGE T1,MONCOR		;A SWAPPABLE PAGE?
	JRST ONSPQX		;NO. DON'T ACCOUNT IT
	CAMLE T1,NHIPG		;A NEW PAGE COMING IN?
	MOVEM T1,NHIPG		;YES. MAKE XGC AND GCCR0 SCAN IT
	AOS TOTRC		;ANOTHER REAL PAGE
	AOS PAGDIF		;NEW PAGE IN THE SYSTEM
	CALLRET ONSPQX		;DONE
;ROUTINE TO RETURN CSTPST FOR A PHYSICAL PAGE
;T1/ PAGE
;	CALL GETPST
;RETURNS+1(ERROR):
;	INVALID PAGE NUMBER
;RETURNS+2(SUCCESS):
;T2/ SPECIAL PAGE STATE

GETPST::CAMLE T1,NHIPG		;CHECK RANGE
	RET			;INVALID PAGE
	LOAD T2,CSTPST,+T1	;PAGE OK, RETURN CURRENT STATE
	RETSKP
;ROUTINE TO SET THE CSTPST STATE FOR A PHYSICAL PAGE
;ASSUMES PROCESS CONTEXT, AS IT MAY NEED TO BLOCK DEPENDING ON THE
;ACTION TO BE TAKEN

;T1/ PHYSICAL PAGE
;T2/ NEW SPECIAL PAGE STATE
;	CALL SETPST
;RETURNS+1(ERROR):
;	ERROR CODE IN T1
;RETURNS+2(SUCCESS):
;	PAGE ON SPMQ WITH REQUESTED STATE
;	T1/ PREVIOUS STATE OF PAGE

;LOCAL AC USAGE
;Q1/ PHYSICAL PAGE
;Q2/ NEW STATE

SETPST::SAVEQ
	STKVAR <SETOST>		;SAVE ORIGINAL STATE HERE
	MOVE Q1,T1		;COPY ARGUMENTS
	MOVE Q2,T2		; ...
	CAIN T2,PSTSPM		;ATTEMPTING TO USE TRANSITION STATE?
	RETBAD (PMCLX1)		;YES - CANNOT BE SET BY USER
	SKIPL T1		;[7129] IS IT A
	CAMLE T1,NHIPG		;[7129]  LEGAL PAGE?
	RETBAD (ARGX06)		;NO - INVALID PAGE
	CALL LCKSPM		;INTERLOCK USER SIDE OF SPMQ LOGIC
				;PRESERVES T,Q,P ACS
	LOAD T3,CSTPST,+T1	;YES - GET CURRENT PAGE STATE
	MOVEM T3,SETOST		;SAVE ORIGINAL STATE HERE
	LOAD T4,CSTAGE,+T1	;NOW NOINT, IS PAGE ALREADY ON SPMQ
	CAIE T4,PSSPQ		; ?
	JRST STPST1		;NO
	CAMN T3,T2		;SAME AS REQUESTED STATE?
	JRST STPSTX		;YES - RETURN SUCCESS
STPST1:	LSH T3,2		;NO - FORM TRANSITION TABLE INDEX
	IOR T3,T2		; ...
	ADJBP T3,[POINT 2,STPSTA,1] ;INDEX INTO TRANSITION TABLE
	LDB T3,T3		;GET ACTION CODE
	XCT STPSTB(T3)		;PERFORM ACTION

;COMMON EXIT POINT

STPSTX:	CALL ULKSPM		;RELEASE USER SIDE OF SPMQ
	MOVE T1,SETOST		;RETURN ORIGINAL STATE TO CALLER
	RETSKP			;RETURN SUCCESS
;TRANSITION TABLE

STPSTA:	BYTE (2)0,0,1,1,0,0,0,0,2,0,0,3,2,0,3,0

;ACTION TABLE
;ENTERED WITH T1,Q1 = PAGE; T2,Q2 = REQUESTED STATE

STPSTB:	RETBAD (PMCLX1,<CALL ULKSPM>)	;ILLEGAL TRANSITION
	JRST STPSTF		;TRANSITION TO OFFLINE
	JRST STPSTN		;TRANSITION TO ONLINE
	JRST STPSTC		;CHANGE OFFLINE STATE

;HERE TO PLACE A PAGE OFFLINE

STPSTF:	CALL FRCSPM		;FORCE ONTO SPMQ
	  RETBAD (PMCLX2,<CALL ULKSPM>) ;COULDNT FREE PAGE
	MOVE T1,Q1		;GET PAGE AGAIN
	CALL CASHFP		;FLUSH PAGE FROM CACHE
	MOVX T1,PSTOFL		;SET PAGE OFFLINE
	STOR T1,CSTPST,+Q1	; ...
	JRST STPSTX		;EXIT

;HERE TO PLACE A PAGE ONLINE

STPSTN:	CALL FRCSPM		;FORCE ONTO SPMQ
	  RETBAD (PMCLX2,<CALL ULKSPM>)
	MOVE T1,Q1		;COPY PAGE
	CALL CHKPAG		;CHECK PAGE FOR NXM
	  RETBAD (PMCLX3,<CALL ULKSPM>) ;ERRORS, DONT PLACE ONLINE
	MOVE T1,Q1		;COPY PAGE
	CALL OFFSPQ		;REMOVE FROM SPMQ
	MOVE T1,Q1		;COPY PAGE
	MOVX T3,PSTAVL		;SET SPECIAL PAGE STATE TO AVAILABLE
	STOR T3,CSTPST,+T1	; ...
	NOSKED			;PROTECT THIS PAGE
	CAMGE T1,MONCOR		;A RESIDENT MONITOR PAGE?
	JRST [	CALL FRCRRM	;YES. PUT IT BACK IN SERVICE
		JRST STPST0]	;AND DONE
	CALL OFRQ		;PLACE AT HEAD OF RPLQ
STPST0:	OKSKED			;ALL QUEUED
	JRST STPSTX

;HERE TO CHANGE THE STATE OF A PAGE (FROM OFL TO ERR OR ERR TO OFL)

STPSTC:	CALL FRCSPM		;SHOULD BE A NOP
	  RETBAD (PMCLX2,<CALL ULKSPM>)
	STOR Q2,CSTPST,+Q1	;SET TO NEW STATE
	JRST STPSTX
;COMMON ROUTINES FOR USER SPMQ MANIPULATION

;ROUTINE TO INTERLOCK USER MANIPULATION OF SPMQ
;PRESERVES T,Q,P ACS

LCKSPM:	PUSH P,T1		;SAVE T1
LCKSP1:	NOINT
	AOSE SPMLCK		;TEST/SET LOCK
	JRST LCKSP2		;MUST BLOCK
	MOVE T1,FORKX		;HAVE LOCK, INDICATE OWNER
	MOVEM T1,SPMONR		; ...
	POP P,T1		;RESTORE T1
	RET

LCKSP2:	OKINT			;BLOCK OKINT
	MOVEI T1,SPMLCK		;LOCK WORD
	CALL DISL		;WAIT FOR NEGATIVE
	JRST LCKSP1		;TRY AGAIN


;ROUTINE TO RELEASE SPMQ INTERLOCK
;PRESERVES ALL ACS

ULKSPM:	SETOM SPMONR		;NO OWNER
	SETOM SPMLCK		;FREE LOCK
	OKINT			;ALLOW INTERRUPTS
	RET
;ROUTINE TO FORCE A PAGE ONTO SPMQ
;T1/ PHYSICAL PAGE
;	CALL FRCSPM
;RETURNS+1(FAILURE):
;	UNABLE TO FREE PAGE
;RETURNS+2(SUCCESS):
;	PAGE IS ON SPMQ

FRCSPM:	SAVEAC <Q1,Q2,P1>
	MOVE Q1,T1		;COPY ARGUMENT
	MOVEI Q2,^D5		;NUMBER OF TIMES TO TRY
	LOAD P1,CSTPST,+T1	;GET PRESENT STATE
FRCSP1:	LOAD T2,CSTAGE,+Q1	;GET CURRENT STATE
	CAIN T2,PSSPQ		;ON SPMQ NOW?
	RETSKP			;YES - NOTHING TO DO
	MOVX T2,PSTSPM		;SETUP TO CHANGE SPECIAL PAGE STATE
	PIOFF			;INTERLOCK
	LOAD T3,CSTPST,+Q1	;CHECK CURRENT STATE
	CAIN T3,PSTAVL		;CURRENTLY AVAILABLE?
	STOR T2,CSTPST,+Q1	;YES - MAKE UNAVAILABLE
	LOAD T2,CSTAGE,+Q1	;GET SWAPPER STATE CODE
	CAIN T2,PSRPQ		;ON RPLQ?
	JRST FRCSP3		;YES - DIRECTLY TO SPMQ
	CAIGE T2,PSASN		;PAGE IN USE?
	JRST FRCSP4		;NO
	HLRZ T2,@CST2X+Q1	;SEE IF PART OF MONITOR MAP
      DO.
	CAME T2,MMSPTN		;IS IT?
	EXIT.			;NO
	HRRZ T2,@CST2X+Q1 	;YES. GET INDEX
	CAIL T2,NRVAR_-PGSFT 	;IN OR ABOVE SWAPPABLE CODE?
	EXIT.			;YES
	CAMGE T2,MONCOR		;IS IT A RESIDENT PAGE?
	IFSKP.
	  MOVX T3,-PLKV 	;NO. SEE IF LOCKED THEN
	  TDNN T3,@CST1X+Q1 	;IS IT?
	  EXIT.			;NO.
	  MOVE T4,CSTLOC
	  ADDI T4,NACST
	  CAMGE Q1,T4
	  EXIT.
	ENDIF.
	MOVE T1,Q1		;CAN TRY TO MOVE IT THEN
	PION			;TURN ON PI'S FOR A WHILE
	CALL FRCRMP		;SEE IF WE CAN DO IT
	 JRST FRCSP0		;CAN'T. RETURN BAD NEWS
	RETSKP			;DONE. PAGE IS ON SPMQ
     ENDDO.
;HERE IF ABOVE CHECK INDICATES PAGE CAN BE SWAPPED OUT

	CALL SWPCHK		;CAN PAGE BE SWAPPED OUT?
	  SKIPA			;NO - USE LARGE HAMMER
	JRST FRCSP5		;YES - SWAPOUT JUST THIS PAGE
	PION			;MUST UNLOAD MEMORY
	AOS SKEDFC		;INDICATE FORCED CLEAR
	ISB SCDCHN		;REQUEST SCHEDULER CYCLE
FRCSP2:	MOVEM Q1,SPMTPG		;SAVE REQUESTED PAGE
	MOVEI T1,^D2000		;AND WATCHDOG TIME
	ADD T1,TODCLK		; ...
	MOVEM T1,SPMTIM		;TWO SECONDS FROM NOW
	MOVEI T1,SPMTST		;TEST ROUTINE
	MDISMS			;REGRETABLY NOINT
	MOVE T1,Q1		;PUT PAGE NUMBER BACK IN T1
	SOJG Q2,FRCSP1		;TRY AGAIN
FRCSP0:	STOR P1,CSTPST,+Q1	;RESTORE ORIGINAL STATE
	RET			;FAILED

;ON RPLQ - REMOVE FROM RPLQ AND PLACE ON SPMQ

FRCSP3:	MOVE T2,Q1		;PAGE NUMBER
	NOSKED			;PROTECT ALL STRUCTURES
	CALL PRLDEQ		;GET OFF OF RPLQ
	MOVE T1,Q1		;PAGE NUMBER AGAIN
	PIOFF			;PRLDEQ DID A PION
	CALL ONSPMQ		;PLACE ON SPMQ (RETURNS PION)
	OKSKED			;ALLOW SCHEDULING NOW
	RETSKP			;SUCCESS

;HERE WHEN PAGE IS UNASSIGNED AND NOT ON RPLQ

FRCSP4:	PION
	JRST FRCSP2		;SHOULD BE TRANSIENT STATE

;HERE WHEN PAGE IS ASSIGNED AND CAN BE SWAPPED OUT

FRCSP5:	NOSKED			;FOR CALL TO SWPOUT
	PION
	CALL SWPOT0		;START SWAP
	OKSKED
	JRST FRCSP2		;JUST A MATTER OF TIME NOW...
;ROUTINE USED BY FRCSPM TO DEQUEUE A PAGE FROM RPLQ
;	T2/ PAGE NUMBER

PRLDEQ:	SOS NRPLQ		;TAKE PAGE OFF REPLACABLE
	PIOFF
	MOVE 1,@CST3X+2
	HRRZ 3,1
	HLLM 1,@CST3X+3
	HLRZ 3,1
	HRRM 1,@CST3X+3
	PION
	SETZRO CORMB,@CST0X+2
	SETZM @CST3X+2
	RET			;DONE. PAGE DEQUEUED


;SCHEDULER TEST ROUTINE FOR FRCSPM

SPMTST:	MOVE T1,SPMTPG		;SOUGHT AFTER PAGE
	LOAD T2,CSTAGE,+T1	;GET STATE CODE
	CAIN T2,PSSPQ		;ON SPMQ?
	JRST 1(T4)		;YES - UNBLOCK
	MOVE T1,SPMTIM		;NO - TIME UP?
	CAML T1,TODCLK		; ???
	JRST 0(T4)		;NO - REMAIN BLOCKED
	JRST 1(T4)		;TIME IS UP - UNBLOCK AND RETRY
;ROUTINE USED BY FRCSPM TO PLACE A RESIDENT MONITOR PAGE OFF-LINE.
;CALLED WITH:	T1/ PAGE NUMBER
;RETURNS:
;		+1 FAILED. CANNOT MOVE THIS PAGE
;		+2 SUCCESS. PAGE MOVED AND MMAP UPDATED
;PAGE MUST BE LOCKED.

FRCRMP:	STKVAR <SRCPAG,SRCADR>	 ;WHERE TO SAVE SOURCE PAGE
	HRRZ T2,@CST2X+T1	;GET MONITOR VIRTUAL PAGE NUMBER
	MOVEM T2,SRCADR		;SAVE IT
	CALL RMPCHK		;SEE IF CAN MOVE THIS PAGE
	 RETBAD ()		;CAN'T.
	MOVEM T1,SRCPAG		;SAVE ADDRESS OF SOURCE PAGE
FRCRM1:	NOSKD1			;PROTECT RPLQ
	CALL CHKRPQ		;WAIT FOR RPLQ TO BE OKAY
	 JRST .-1		;REVERIFY IF BLOCKED
	HRRZ T2,@SRPLQ		;GET TOP PAGE
	CAIN T2,SRPLQO		;EMPTY?
	HRRZ T2,@DRPLQ		;YES, USE ALTERNATE RPLQ
	CALL PRLDEQ		;USE COMMON ROUTINE TO DEQUEUE THE PAGE
	PUSH P,T2		;SAVE CORE PAGE NUMBER
	MOVE T3,T2		;COPY PAGE NUMBER
	CALL DEPG		;DEASSIGN OWNERSHIP
	SETZM @CST1X+T3		;NO BACKUP NOW
	MOVE T1,T3		;GET CORE PAGE NUMBER IN T1
	MOVX T3,PSRDN		;FAKE AGE
	STOR T3,CSTAGE,+T1	; SO MLKCP WILL DO RIGHT THING
	SETONE CSWRB,+T1	;Set the write bit
	CALL MLKCP		;LOCK IT IN CORE
	POP P,T2		;GET DEST CORE PAGE AGAIN
	MOVE T1,SRCPAG		;GET BACK SOURCE PAGE
	MOVE T3,@CST2X+T1	;GET OWNERSHIP
	MOVEM T3,@CST2X+T2	;NEW PAGE OWNERSHIP
	; ..
;PAGE NOW HAS PROPER I.D. MOVE DATA

	MOVE T3,SRCADR		;GET MONITOR VIRTUAL PAGE NUMBER OF SOURCE
	LSH T3,PGSFT		;AN ADDRESS
	MOVE T1,T2		;GET DEST CORE PAGE
	PIOFF			;OWN THE ENTIRE MACHINE
	CALL MAPRCA		;SET UP MAPPING
	MOVEI T4,PGSIZ-1(T1)	;COMPUTE END OF PAGE
	HRL T1,T3		;SET UP BLT ARG
	BLT T1,0(T4)		;MOVE DATA
	CALL UNMRCA		;UNDO MAPPING NOW THAT DATA IS MOVED
	MOVE T1,SRCADR		;GET BACK SOURCE PAGE
	STOR T2,STGADR,MMAP(T1)	;SET UP NEW MAPPING FOR THIS PAGE
	MOVE T1,T3		;GET SET TO MAKE PAGE USABLE
	CALL MONCLR		;DO IT
	MOVE T1,SRCPAG		;GET SOURCE PAGE # AGAIN
	MOVX T3,-PLKV		;TEST FOR LOCKED
	CAMGE T1,MONCOR		;RESIDENT CODE?
	JRST [	ANDCAM T3,@CST1X+T1 ;YES. TURN OFF LOCK COUNT
		JRST FRCRM2]	;AND PROCEED
	TDNE T3,@CST1X+T1	;NOW LOCKED?
	CALL MULKCR		;YES. UNLOCK IT THEN
	MOVE T1,SRCPAG		;THE PAGE AGAIN
FRCRM2:	SETZM @CST2X+T1		;NOW NOT OWNED
   REPEAT 0,<			;DON'T NEED EPT CODE YET
	CALL TSTEPT		;SEE IF SOURCE PAGE IS NOW THE EPT
	JRST [	EXCH T1,T2	;IT IS. MUST CHANGE EPT THEN
		CALL SETEPT	;MAKE NEW PAGE THE EPT
		EXCH T1,T2
		JRST .+1]	;PROCEED
   >				;END OF REPEAT 0
	CALL ONSPMQ		;PUT PAGE ON SPECIAL QUEUE
	OKSKD1			;TURN ON SCHEDULER AGAIN
	RETSKP			;AND DONE
;ROUTINE TO PUT A RESIDENT MONITOR PAGE BACK ON-LINE.
;	T1/ PAGE NUMBER
;PAGE ALREADY OFF OF SPMQ
;MUST BE CALLED NOSKED OR AT DISK PI LEVEL

FRCRRM::STKVAR <SRCPAG,OLDPAG>	;SAVE PAGE NUMBERS
	MOVEM T1,SRCPAG		;SAVE PAGE TO USE AGAIN
	LOAD T2,STGADR,MMAP(T1)	;GET CURRENT LOC OF DATA
	MOVEM T2,OLDPAG		;SAVE IT TOO
	MOVE T3,@CST2X+T2	;I.D OF PAGE
	MOVEM T3,@CST2X+T1	;SET UP I.D.
	SETONE CSTAGE,+T1	;MAKE NEW PAGE ACCESSIBLE
	MOVX T2,PLKV		;GET A UNIT OF LOCK COUNT
	IORM T2,@CST1X+T1	;AND LOCK THE PAGE AGAIN
	MOVE T2,T1		;GET ADDRESSABLE VALUE FOR CURRENT DATA
	LSH T2,PGSFT		;GET ADDRESS OF CURRENT DATA
	PIOFF			;PREVENT MISHAPS
	CALL MAPRCA		;GET ACCESS TO NEW PAGE
	MOVEI T4,PGSIZ-1(T1)	;GET END OF PAGE
	HRL T1,T2		;SET UP FOR DATA MOVE
	BLT T1,0(T4)		;MOVE THE DATA
	MOVE T1,SRCPAG		;GET NEW PAGE NUMBER AGAIN
	STOR T1,STGADR,MMAP(T1)	;MAKE MMAP POINT TO NEW PAGE
	MOVE T1,T2		;GET ADDRESS
	CALL MONCLR		;MAKE PAGE BE USED
	MOVE T1,OLDPAG		;GET OLD PAGE I.D.
   REPEAT 0,<			;DON'T NEED EPT CODE NOW
	CALL TSTEPT		;IS IT NOW THE EPT?
	JRST [	MOVE T1,SRCPAG	;YES. GET SOURCE PAGE
		CALL SETEPT	;MAKE IT THE NEW EPT
		MOVE T1,OLDPAG	;RESTORE OLD PAGE
		JRST .+1]	;AND PROCEED
   >				;END OF REPEAT 0
	CALL UNMRCA		;CLEAR TEMP MAPPING
	PION			;ALL IS O.K NOW. LET SYSTEM BREATH AGAIN

;DATA NOW RESTORED AND PAGE IN USE. RELEASE OLD PAGE

	SETZM @CST2X+T1		;NO LONGER OWNED
	CALL MULKCR		;UNLOCK PAGE
				;UNLOCKER PUTS PAGE ON RPLQ
	RET			;DONE
;SPECIAL ROUTINES USED BY DIAG MEMORY CONTROL.

;SET MAP TO POINT TO PHYSICAL MEMORY WITHOUT CHANGING STATE
;OF MEMORY PAGES. PROCESS SHOULD BE NOINT AND MUST INSURE
;THAT THE PAGES ARE REFERENCED ONLY WHILE NOSKED.
;ACCEPTS:
;		T1/ SOURCE I.D. (PTN,,PN)
;		T2/ FIRST CORE PAGE (-1 => CLEAR MAP)
;		T3/ COUNT
;RETURNS:	+1 ALWAYS

MAPPV::	ASUBR <SID,CPG,CNT>
	HLRZ T3,T1		;GET PTN OF MAP
	CALL SETXB1		;MAP PT
	MOVE T3,IMMPTR		;FORM AN IMMEDIATE POINTER TO MEMORY
	IOR T3,CPG		;INSERT MEMORY PAGE
	SKIPGE CPG		;WANT TO CLEAR?
	SETZM T3		;YES.
	MOVN T1,CNT		;GET NEG OF COUNT
	MOVSS T1
	HRR T1,SID		;STARTING PAGE IN MAP
MAPPV1:	MOVEM T3,CXBPGA(T1)	;UPDATE MAP
	SKIPE T3		;WANT CLEAR?
	ADDI T3,1		;NO. NEXT PAGE THEN
	AOBJN T1,MAPPV1		;DO ALL OF MAP
	CALL MONCLA		;CLEAR PAGER
	CALLRET RELCXB		;RELEASE PT AND RETURN

;ROUTINE TO SET UP CST0 FOR A PROCESS THAT HAS USED MAPPV.
;THE APPROPRIATE CST0'S ARE SET UP WITH PUFLD=-1 AND
;THE AGE SET TO THE CURRENT AGE OF THE PROCESS.
;MUST BE NOSKED
;ACCEPTS:
;		T1/ FIRST MEMORY PAGE
;		T2/ COUNT
;RETURNS:	+1 ALWAYS

SETCST::MOVX T4,<CSWRB!CFXRD!CORMB> ;PART OF NEW CST0 WORDS
	MOVE T3,FORKX		;CURRENT FORK
	MOVE T3,CURAGE		;Get current page age
	STOR T3,AGEMSK,T4	;SET AGE
SETCS1:	MOVEM T4,@CST0X+T1	;SET NEW CST0
	ADDI T1,1		;NEXT PAGE
	SOJG T2,SETCS1		;DO ALL OF THEM
	CALLRET MONCLA		;CLEAR PAGER
;ROUTINES USED BY LOADBS TO SEE IF THIS FORK'S PT,PSB,ETC
;ARE IN A TRANSITION PAGE.
;ACCEPST:	FX/ FORK HANDLE
;RETURNS:	+1 ONE OR MORE PAGES IN TRANSITION
;		+2 NONE IN TRANSITION

TSTFRP::CAMN FX,SPMONR		;THIS FORK OWN THE LOCK?
	RETSKP			;YES. ALLOW IT THEN
	LOAD T1,FKJSB		;GET JSB
	CALL TSTSPT		;GUILTY?
	 RET			;YES.
   IFN EXTJSB,<
	LOAD T1,FKJPT		;Get extended JSB
	CALL TSTSPT		;In transition?
	RET			;Yes
   >
	LOAD T1,FKPSB		;TRY PSB
	CALL TSTSPT
	 RET			;YES
	LOAD T1,FKUPT		;NO, TRY PT
	CALL TSTSPT		;?
	 RET			;YES. GUILTY
	LOAD T1,FKPS2		;STACK PAGE
	CALLRET TSTSPT		;?

;LOCAL ROUTINE TO TEST A GIVEN FORK PAGE.
;ACCEPTS:	T1/ SPT OFFSET
;RETURNS:	+1 IN TRANSITION
;		+2 NOT

TSTSPT:	LOAD T2,STGADR,SPT(T1) ;GET ADDRESS
	TXNE T2,NCORTM		;IN MEMORY?
	RETSKP			;NO. NOT IN TRANSITION THEN
	JE CSTPST,+T2,RSKP	;IN TRANSITION?
	RET			;YES.
;Utility used by various routines to assign a disk page for an OFN.
;This code implements preallocation.
;	T1/ Address
;	T2/ OFN
;Presently only used by CFS

DSKGET::ACVAR <W1,W2,W3>
	MOVE W1,T2		;Save the OFN
	LOAD W2,STRX,(T2)	;get structure number
	SKIPN T3,SPTD(T2)	;Is there a preallocated chunk?
	IFSKP.			;If so...
	 LOAD T1,STGADR,T3	;Get the address
	 MOVE T2,W2		;Str number
	 CALL DSKINC		;Increment it
	 LOAD T2,STGADR,T3	;Get back starting address
	 STOR T1,STGADR,T3	;Insert new address
	 DECR SPTCT,T3		;One less in the cache
	 TXNN T3,SPTCT		;Any pages left?
	 SETZ T3,		;No.
	 MOVEM T3,SPTD(W1)
	 MOVE T1,T2		;Copy the address
	 RETSKP			;Did it
	ENDIF.
	MOVE T2,W2		;Structure #
	TMNN SPTNA,(W1)		;Want to try for preallocation?
	IFSKP. <CALLRET DSKASW>	;If not, don't ask for it
	CALL DSKAWM
	 RETBAD()		;Oops
	JUMPE T1,RSKP		;resched!
	SOJE T2,RSKP		;If only gave us one, all done
	STOR T2,SPTCT,SPTD(W1)	;Save the count
	MOVE W3,T1		;Save the address
	MOVE T2,W2		;Structure number
	CALL DSKINC		;Increment it
	STOR T1,STGADR,SPTD(W1) ;Stash next address
	MOVE T1,W3
	RETSKP			;And done
	ENDAV.
;Routine to release cached pages for an OFN
;	T1/ The OFN
;Returns: +1. Preserves all ACs

DSKUGT::SKIPN SPTD(T1)		;Any residual disk pages?
	IFSKP.			;If so
	 SAVET
	 LOAD T2,STRX,(T1)	;Get structure number
	 LOAD T3,SPTCT,SPTD(T1)	;Get the count
	 LOAD T4,STGADR,SPTD(T1) ;Get address
	 SETZM SPTD(T1)		;No more
	 MOVE T1,T4		;Address
	 CALL DEDSKM		;release them
	ENDIF.
	RET			;And done

;Routine to "forget" any chached pages;
;	T1/ OFN

CLRDCH::SETZM SPTD(T1)		;Clear the word
	RET			;And done
;Routine to try to "fill" XB with preallocated pages.
;	T1/ The OFN
;	T2/ Address of last word stored.

   REPEAT 0,<

This routine was a good idea, but keeping directory quotas
correct proved too difficult. Perhaps some future generation
will be able to resume the campaign


DSKFIL::SKIPN SPTD(T1)		;Anything here?
	IFSKP.			;If so...
	 SAVEQ
	 DMOVE Q1,T1		;Copy args
	 LOAD T2,STRX,(T1)	;Get structure #
	 DO.			;A loop
	  TRC Q2,PGSIZ-1	;Check if at the end of a page
	  TRCE Q2,PGSIZ-1	;Are we?
	  SKIPE 1(Q2)		;No. Is already occurpied?
	  EXIT.			;yes. Nothing more to do then
	  ADDI Q2,1		;Next address
	  LOAD T1,STGADR,SPTD(Q1) ;Get address
	  TXO T1,DSKNB		;Make sure this is set
	  TDO T1,IMMPTR		;Geta pointer as well
	  MOVEM T1,0(Q2)	;Stash it
	  DECR SPTCT,SPTD(Q1)	;One less
	  TMNN SPTCT,SPTD(Q1)	;Any more here?
	  IFNSK.		;If not
	   SETZM SPTD(Q1)	;Clear this
	   EXIT.		;And done
	  ENDIF.
	  LOAD T1,STGADR,SPTD(Q1) ;Get old address
	  CALL DSKINC		;Get next
	  STOR T1,STGADR,SPTD(Q1)
	  LOOP.
	 ENDDO.
	ENDIF.
	RET
   >	;REPEAT 0
;Routine to make sure a file is accessible. Used by bit table logic
;	T1/ OFN

OFNTKN::
   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<RET>		;Nothing to do if not CFS
   >				;END REPEAT 0
;   IFN CFSCOD,<
	CAIL T1,NOFN		;Is it an OFN?
	IFSKP.			;If so
	 TMNE SPTST,(T1)	;Is it accessible?
	ANSKP.			;If not
	 SETZM T2		;Get any kind of access
	 CALL CFSAWT		;Do it
	ENDIF.
	RET			;Done
;   >	;IFN CFSCOD
;PERIODIC ROUTINE TO TRICKLE PAGES TO DISK

DDMPLF==1B0			;LOCAL FLAG IN F, DRUM SP LOW IF 1
DDFAIL==1B35

DDMP::	SAVEP
	NOINT			;BE NOINT FOR GOOD MEASURE
	LOCK STRLOK		;PREVENT DISMOUNTS
	SETOM DDPFRK		;Indicate we are in DDMP
	SETZ F,			;CLEAR FLAGS
	MOVE 1,DRMFRE
	SKIPE DDTIME		;SYSTEM SHUTDOWN?
	CAMGE 1,DRMIN0		;OR INSUFFICIENT DRUM SPACE?
	TLO F,(DDMPLF)		;YES, TAKE SPECIAL ACTION
	MOVSI P1,-NOFN		;SETUP TO SCAN ALL OFN'S
	AOBJN P1,.+1		;0 NOT USED
DDMP9:	NOSKED
	SKIPN T2,SPTH(P1)	;OFN IN USE?
	JRST DDMP2		;NO
	TMNE OFNCSH,(P1)	;[7247] This OFN cached?
	JRST DDMP2		;[7247] Yes
	TXNE T2,OFNDMO		;This one dismounted?
	JRST DDMP2		;Yes. forget it then
	SETCM 1,SPTH(P1)	;GET THAW AND WRITE BITS
	TXNN 1,FILWB+THAWB	;BOTH 1? (I.E. THAW MODE)
	JRST DDMP3		;YES, UPDATE
	TXNN F,DDMPLF		;DRUM FULL?
	JRST DDMP2		;NO, BYPASS OFN
DDMP3:	MOVX 2,OFNDMO!OFNDUD	;CHECK IF THIS OFN IS DISMOUNTED
				; OR DDMP BEING SUPPRESSED
	TMNE SPTCDO,(P1)	; If open in progress...
	TDNE 2,SPTH(P1)		;IS IT?
	JRST DDMP2		;YES. SKIP IT
DDMM3:	LOAD A,STRX,(P1)	;GET STRUCTURE NUMBER
	CALL STROFL		;IS THIS STRUCTURE OFF-LINE
	JRST DDMP2		;YES. SKIP IT
	HRRZ T1,P1		;MOVE OFN
	MOVX T2,SPTLKB		;LOCK BIT
	TDNE T2,SPTH(T1)	;LOCKED LOCALLY?
	JRST DDMP2		;YEP. SKIP IT
	IORM T2,SPTH(T1)	;NO. LOCK IT
;   IFN CFSCOD,<
;	CFSLOK			;Interlock the data base.
	LOAD T2,SPTST,(P1)	;GET FILE STATE
	TMNN SPTFO,(P1)		;IF FORCING OUT
	CAIN T2,.SPSWR
	IFSKP.			;If neither
	 TMNN SPTSFD,(P1)	;If already flushed
	 TXNN F,DDMPLF		;But if doing swap space low...
	 ANNSK.			;Do it anyway
	 SETZRO SPTLKB,SPTH(P1)	;No need for the lock
	 SETZRO <SPTFR,SPTFO>,(P1)
	 JRST DDMP2		;And done
	ENDIF.
;	CFSULK			;Unlock the CFS data base
;   >	;IFN CFSCOD
IFN SPTDSW,<			;ONLY IF DEBUGING SPTLKB PROBLEMS
	EXCH T1,P1		;GET THE OFN INDEX
	CALL SPTRAC		;TRACE WHO LOCKED THIS
	EXCH T1,P1		;RESTORE THE ACS
 >				;END OF IFN SPTDSW
	HRRZ A,P1		;GET THE OFN IN A
	CALL UPSHR		;ARTIFICIALLY UP THE SHARE COUNT
	OKSKED			;WILL UPDATE OFN, NOW SAFELY LOCKED
	LOAD A,STRX,(P1)	;GET STRUCTURE NUMBER
	TMNE OFNWRB,SPTH(P1)	;Need to do update?
	CALL UPDBTB		;UPDATE BIT TABLE
	HRLZ T1,P1		;Form IDENT
	MOVEI T2,PGSIZ		;Entire XB
	TXNE F,DDMPLF		;No. How about swapping space low?
	IFNSK.			; Yes, to one of them
	 CALL UPDPG0		;Flush pages
	ELSE.
	 CALL UPDPGS		;NO, REGULAR UPDATE PAGES
	ENDIF.
	HRRZ 1,P1		;GET OFN
	CALL UPDOF0		;UPDATE THE INDEX BLOCK
DDMM4:	HRRZ A,P1		;GET THE OFN IN A
	CALL DWNSHR		;DECREMENT THE SHARE COUNT
	MOVX 1,SPTLKB		;LOCK BIT
	ANDCAM 1,SPTH(P1)	;UNLOCK IT
	JRST DDMP1		;DONE WITH THIS OFN
DDMP2:
	OKSKED
DDMP1:	AOBJN P1,DDMP9		;SCAN ALL OFN'S
	SETOM STRLOK		;RELEASE LOCK
	SETZM DDPFRK
	OKINT			;NOW OKAY TO INTERRUPT, ETC.
	TXNE F,DDFAIL		;Failed?
	RET			;Yes.
	RETSKP			;AND RETURN SUCCESSFULLY
;Variant of DDMP used to force out files wanted by another processor
;Called from DDMPA when needed

   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<
DDMPF==:DDMP
   >	;IFE CFSCOD
   >				;END REPEAT 0

;   IFN CFSCOD,<
DDMPF::	SAVEP			;Save regs
	STKVAR <OFN>		;[7192] THE OFN WE ARE WORKING ON
	SETZ F,			;Initialize flags register
	SETOM DDPFRK
	MOVSI P2,-OFNCFW	;Number of words in bit mask
	DO.
	  SKIPN P3,OFNCFS(P2)	;Anything in this word?
	  IFSKP.		;If so
	    MOVEI P5,0(P2)	;Get word offset
	    IMULI P5,^D36	;First OFN in this clump
	    DO.
	      JFFO P3,.+1	;Get next bit
	      TDZ P3,BITS(P4)	;Clear it
	      MOVE P1,P5
	      ADDI P1,0(P4)	;Compute the OFN
	      MOVEM P1,OFN	;[7192] SAVE THE OFN
	      CALL DDOCFS	;Do this file
	      IFSKP.		;If it did it
	        MOVE P4,BITS(P4);Get the bit that said to do it
	        CFSLOK	;[7192] LOCK OUT INTERRUPT LEVEL VOTE PROCESSING
				;[7192] NOTE: WITHOUT THIS LOCK YOU CAN END UP
				;[7192] WITH SPTFR BEING SET IN SPTO2 BUT THE
				;[7192] BIT IN OFNCFS NOT BEING SET.
	        MOVE T1,OFN	;[7192] GET THE OFN WE'RE WORKING ON
	        TMNN SPTFR,(T1)	;[7192] DID SOMEONE ELSE WANT IT RELEASED?
	        ANDCAM P4,OFNCFS(P2) ;[7192] NO, INDICATE IT'S GONE
	        CFSULK		;[7192] LET VOTING CONTINUE
	      ELSE.
	        TXO F,DDFAIL	;If not, remember this
	      ENDIF.
	      JUMPN P3,TOP.	;Do other bits in this word
	    ENDDO.
	  ENDIF.
	  AOBJN P2,TOP.		;Do all words
	ENDDO.
	SETZM DDPFRK
	TXNE F,DDFAIL		;Did we fail on any?
	RET			;Yep.
	RETSKP			;Nope.
	ENDSV.
;Subroutine of above. This does the flush for a single file.
;	P1/ OFN
;Returns:	+1 failed for some reason
;		+2 did it

DDOCFS::NOSKED			;Prevent races for a bit
	HRRZ T1,SPTO		;[7.1063]Get the structure number
	CALL STROFL		;[7.1063](T1/)Is the structure offline?
	IFNSK.			;[7.1063]If no...
	  OKSKED		;[7.1063]Allow scheduling
	  RET			;[7.1063]Return +1
	ENDIF.			;[7.1063]
	MOVX T1,SPTLKB		;Get OFN lock bit
	TMNE SPTCDO,(P1)	;Being opened?
	TDNE T1,SPTH(P1)	;Or is it now locked?
	RETBAD (,<OKSKED>)	;Can't do it
	IORM T1,SPTH(P1)	;Lock the OFN
   IFN SPTDSW,<			;[7.1036] Only if debugging SPTLKB problems
	EXCH T1,P1		;[7.1036] Position the OFN
	CALL SPTRAC		;[7.1036] (T1/)Record who locked SPTLKB
	EXCH T1,P1		;[7.1036] Restore the ACs
   >				;[7.1036] End of IFN SPTDSW
	MOVEI T1,0(P1)		;Get the OFN
	CALL UPSHR		;Increment it so it won't go away

;We can work on the file. See what we should do.

       	SETONE SPTFO,(P1)	;Lock out others
	CSKED
	TMNN OFNCSH,(P1)	;[7247] Is this a cached OFN?
	IFSKP.			;[7247] Yes
	  OKSKED		;[7247] 
	  JRST DDGOD		;[7.1005] OFN got cached, so nothing to do
	ENDIF.			;[7247] 
	OKSKED
	TMNN SPTFR,(P1)		;Does it still need work?
	IFSKP.			;If so
	  LOAD T1,SPTST,(P1)	;Get the state
	  TMNN SPTSFD,(P1)	;Is it flushed from here
	  SKIPN T1		;No, is it really a place-holder
	  IFNSK.
	    MOVEI T1,0(P1)	;Don't need to do anything.
	    CALL CFSFOD		;Tell CFSSRV all is well
	     JRST DDXX		;Not so well, after all
	    JRST DDGOD		;All done!
	  ENDIF.
	  MOVEI T1,0(P1)	;Get the OFN
	  CALL CFSGOC		;See of it's locked here
	  SKIPA			;It's not even here!!!!
	  SOJG T1,DDXX		;It's not, onward
	  TMNE OFNWRB,SPTH(P1)	;IS the OFN modified?
	  IFNSK.		;If so
	    LOAD T1,STRX,(P1)	;Get structure number
	    CALL UPDBTB		;So, update the bit table
	  ENDIF.
	  HRLZ T1,P1		;Form OFN,,0
	  MOVEI T2,PGSIZ	;Pages in an XB
	  TMNE SPTSR,(P1)	;Want exclusive?
	  IFNSK.
	    CALL UPDPGX		;Yes. flush 'em
	  ELSE.
	    CALL UPDPGY		;No. Keep 'em
	  ENDIF.
	  MOVEI T1,0(P1)	;The OFN again
	  CALL UPDOF0		;Update the OFN
	  TMNN SPTSR,(P1)	;Want exclusive?
	  ANSKP.		;If so (If not, we're almost done)
	    LOAD T1,STGADR,SPT(P1) ;Get current address of OFN
	    TXNN T1,NCORTM	;In memory?
	    IFNSK.		;If it is...
	      NOSKED
	      TMNN PLKMSK,@CST1X+T1 ;Is it locked?
	      CALL SKPNWR	;No. Is it being written?
	      IFNSK.		;If one of the above
	        OKSKED
	        JRST DDXX	;Fail!
	      ENDIF.
	      TMNE PSASM,@CST0X+T1 ;Is it assigned?
	      CALL SWPOUX	;Yes, Put it on RPLQ
	      OKSKED
	    ENDIF.		;End of all data moving
	ENDIF.
	MOVEI T1,0(P1)		;[7.1005] Get the OFN we just forced out
	CALL CFSFOD		;[7.1005] (T1/) Have CFSSRV tell others
	 JRST DDXX		;[7.1005] Failure, give non skip return
;	CALLRET DDGOD		;[7.1005] Fall thru to DDGOD
;[7.1005] Here when we successfully moved that data, unlock and skip return

DDGOD:	CALL DDXX		;[7.1005] (P1/) Clear bit, down share, etc.
	RETSKP			;[7.1005] Give the success (skip) return

;Here when we didn't do it

DDXX:	MOVEI T1,0(P1)
	SETZRO SPTFO,(T1)
	CALL DWNSHR
	SETZRO SPTLKB,SPTH(P1)	;Clear OFN lock
	ECSKED
	RET

;   >	;IFN CFSCOD
;Routine of above to swap in a "forced out" XB
;	T1/ OFN

DDXBI::
   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<RET>		;Nothing to do if not CFS monitor
   >				;END REPEAT 0
;   IFN CFSCOD,<
	SAVET
	SAVEP
	MOVEI P1,0(T1)		;Copy OFN
	CSKED
	DO.
	AOSE DDXLOK		;Are we the only ones in here?
	IFNSK.			;If not
	 MOVSI T1,DDXLOK	;Address
	 HRRI T1,DISLT		;Wait for it to be negative
	 SKIPE NSKED
	 IFNSK.
	  RDISMS
	  NOSKED
	  LOOP.
	 ENDIF.
	 HDISMS
	 LOOP.
	ENDIF.
	ENDDO.
	TMNN SPTST,(P1)		;Is it still here?
	JRST DDXDON		;If not, done
	MOVEI T1,0(P1)		;The OFN
	SETZM T2
	CALL CFSAWP		;Lock the resource here
	TMNN SPTSFD,(P1)	;Still need this done?
	JRST DDXBI1		;No.
	SETZM FITPGA		;Get a page here for XB
	NOSKED
	SETZM FITPGA		;Make sure it's here
	HRRZ T1,MMAP+FITPG	;Get Page number
	CALL MLKCP		;Lock it in memory
	OKSKED			;OK to allow schdeuling now
	HRRZ T3,MMAP+FITPG	;Get page number again
	LSH T3,PGSFT		;make address
	LOAD T1,STGADR,SPTH(P1)	;get OFN disk address
	MOVEI T2,PGSIZ		;One page please
	LOAD T4,STRX,(P1)	;Structure number
	CALL UDSKIO		;read it in
	HRRZ T1,MMAP+FITPG	;Get page number, yet again
	CALL MULKCR		;And unlock it for good
;DISK XB now in FPG3A. Verify it

	SETZRO <SPTSFD,SPTDSF>,(P1)
	MOVEI T1,FITPGA		;Where it's at
	CALL DOXSUM		;Do checksum compare
	CAME T1,[-1]
	SKIPN T1		;Any good?
	IFSKP.
	 BUG.(HLT,DDXIN,PAGUTL,HARD,<DDMP - Bad XB>,,<

Cause:	DDXBI was called to swap in a forced out index block but the index
	block is bad.
>)
	ENDIF.
	; ..
;Checksum is good. Now look over the page

	HRRZ T1,P1		;OFN
	TDO T1,SHRPTR		;Make a share pointer
	MOVEM T1,MMAP+PRLPG	;Put it in

;Now compare XBs making our copy (the one in PRLPGA) up-to-date

	MOVSI T3,-PGSIZ		;Scan the page
	DO.
	 MOVE T1,FITPGA(T3)	;get current disk address of this page
	 MOVE T2,PRLPGA(T3)	;Get our pointer
	 SKIPN T2		;Our pointer all zero?
	 MOVEM T1,PRLPGA(T3)	;Yes. use address from XB
	 ANDX T1,STGADR		;get address only
	 SKIPN T1		;Anything here?
	 MOVX T1,UAAB		;No. Invent unassigned address
	 LOAD T4,PTRCOD,T2	;Get pointer type
	 CAIE T4,IMMCOD		;Immediate?
	 IFSKP.			;if so
	  LOAD T4,STGADR,PRLPGA(T3)
	  CAME T1,T4		;Same?
	  STOR T1,STGADR,PRLPGA(T3) ;Update local copy
	 ELSE.			;Otherwise, is shared or non-ex
	  IFN. T4		;If share
	   HRRZS T2		;Get SPT index
	   TMNE SPTSHC,(T2)	;Only if slot is in use
	   STOR T1,STGADR,SPT(T2) ;Replace address in SPT
	  ENDIF.
	 ENDIF.
	 AOBJN T3,TOP.		;Do entire XB
	ENDDO.

;Local XB updated.

DDXBI0:	SETZM MMAP+PRLPG	;Clear this mapping
	LOAD T1,STGADR,MMAP+FITPG ;Get current addres of this guy
	CALL REMFP1		;Destroy all pages
	SETZM MMAP+FITPG	;And the mapping as well
	CLRPT FITPGA		;Clear pager for this page
	CLRPT PRLPGA		; and this as well
DDXBI1:	MOVEI T1,0(P1)		;The OFN
	CALL CFSFWT		;Release lock
DDXDON:	SETOM DDXLOK		;Free the lock
	ECSKED			;Undo critical section
	RET			;And done
;   >	;IFN CFSCOD

;UPDATE OFN--GET INDEX BLOCK WRITTEN TO DISK
; 1/ OFN
;	CALL UPDOFN
; RETURN +1 ALWAYS, BIT TABLE AND INDEX BLOCK UPDATED

UPDOFN::STKVAR <OFN>
	MOVEM A,OFN
	HRRZ B,A		;GET OFN
	CALL CHKDMO		;SEE IF DISMOUNTED
	 RET			;IT IS. IGNORE REQUEST.
	HRRZ A,OFN		;GET OFN
	CALL LCKOFN		;LOCK OFN AGAINST CHANGES
	MOVX B,OFNWRB		;SEE IF OFN MODIFIED
	HRRZ A,OFN		;GET BACK OFN
	TDNN B,SPTH(A)
	JRST UPDOFX		;NOT MODIFIED, DO NOTHING
	LOAD A,STRX,(A)		;GET STRUCTURE NUMBER
	CALL UPDBTB		;UPDATE BIT TABLE
	HRRZ A,OFN		;GET OFN AGAIN
	CALL UPDOF0		;WRITE INDEX BLOCK
UPDOFX:	MOVE A,OFN
	CALL ULKOFN		;UNLOCK OFN
	RET

;UPDATE OFN IF NECESSARY.
;OFN LOCKED. T1/ OFN
;RETURNS: +1 ALWAYS
;	RH OF T1 PRESERVED (I.E. THE OFN)

UPDOFI:	HRRZS T1		;GET RH ONLY
	MOVX T2,OFNWRB		;SEE IF OFN NEEDS UPDATING
	TDNN T2,SPTH(T1)	;DOES IT?
	RET			;NO
	MOVE T2,T1		;YES. GET OFN
	CALL CHKDMO		;SEE IF STILL MOUNTED
	 RET			;NO. ALL DONE THEN
	PUSH P,T1		;YES. SAVE OFN
	LOAD T1,STRX,(T1)	;GET STRUCTURE NUMBER
	CALL UPDBTB		;UPDATE THE BTB
	MOVE T1,0(P)		;GET BACK OFN
	CALL UPDOF0		;UPDATE THE OFN
	CALLRET PA1		;AND DONE
;SCAN INDEX BLOCK AND WRITE IMAGE TO DISK
;ASSUMES OFN LOCKED AGAINST CHANGES
; A/ OFN
;	CALL UPDOF0
; RETURN +1 ALWAYS
;AC USAGE:
; P1 - OFN
; P2 - AOBJN PTR FOR SCANNING PAGE TABLE
; P3, P4 - TEMPS
; P5 - CHECKSUM

UPDOF0::SAVEP			;SAVE P1-P6
	CAILE A,0		;ENSURE LEGAL OFN
	CAIL A,NOFN
	BUG.(HLT,NOTOFN,PAGUTL,SOFT,<UPDOF0 - ARG NOT OFN>,,<

Cause:	A routine has been called to write an updated index block for a file  
	onto the disk. However, the identifier that was provided by the caller  
	is not a valid id for a file.  (It is not an OFN.)
>)
	TMNE OFNCSH,(T1)	;[7247] Is this a cached OFN?
	BUG.(HLT,UPDCSH,PAGUTL,SOFT,<UPDOF0 - Update of cached OFN>,,<

Cause:	A routine has been called to write an updated index block for a file  
	onto the disk. However, the OFN is cached and the index block should
	have been updated when it got cached, not once it is cached.
>)				;[7247] Yes, error!
	MOVEM A,P1		;KEEP OFN AROUND
	LOAD A,STGADR,SPT(P1)	;GET CURRENT ADR OF XB
	TXNE A,DSKAB		;ON DISK?
	RET			;YES, NOTHING TO DO
	MOVX A,OFNWRB
	TDNN A,SPTH(P1)		;CHANGED SINCE LAST UPDATE?
	RET			;NO, NOTHING TO DO
	ANDCAM A,SPTH(P1)	;NOTE OFN NOW UPDATED
	MOVE A,P1
;   IFN CFSCOD,<
	CALL CFSBOW		;Broadcast OFN write
;   >
	MOVE A,P1		;Get back OFN
	MOVE B,[PTRW+FPG2A]
	CALL SETMPG		;MAP XB
	MOVEI A,0
	MOVEI B,FPG3A
	CALL SETMPG		;CLEAR A PAGE TO RECEIVE XB IMAGE
	SETZM FPG3A		;MAKE IT EXIST
	MOVEI P5,0		;INIT CHECKSUM
	JCRY0 .+1
	MOVSI P2,-PGSIZ		;SETUP TO SCAN XB
UOFN1:	SKIPE FPG2A(P2)	;ENTRY EXISTS?
	JRST UOFN2		;YES, GO TRACK DOWN DISK ADR
	ADDI P5,0(P2)		;USE XB INDEX FOR 0 WORD IN CHECKSUM
	JCRY0 [AOJA P5,.+1]	;WRAPAROUND CARRY
UOFN6:	AOBJN P2,UOFN1		;SCAN ALL XB
	MOVX A,OFNBAT		;SEE IF OFN HAS BAT BIT
	MOVX B,XBBAT		;IN CASE IT DOES
	TDNE A,SPTH(P1)		;IS IT SET?
	IORM B,XBBWRD+FPG3A	;YES. MARK XB
	; ..
;UPDOFN...
;HAVE FINISHED SCAN OF XB

	MOVEI A,P5		;POINT TO CHECKSUM
	MOVE B,[XBCKSM+FPG3A]	;PUT IT IN FIRST FOUR WORDS OF XB
	CALL STXBD		;STORE CHECKSUM IN XB
	MOVEI A,FPG3A		;GET IDENT FOR IMAGE PAGE
	CALL FPTA
	MOVEM A,P3		;SAVE IT
	CALL MLKPG		;LOCK IMAGE PAGE IN CORE FOR DSKIO
	MOVEM A,P4		;SAVE CORE PAGE NUMBER
	LOAD A,STGADR,SPTH(P1)	;GET DSK ADR OF XB
	MOVX B,DOP%WR+PGSIZ	;SAY WRITE ONE PAGE
	HRRZ C,P4		;SETUP PHYSICAL CORE ADR
	LSH C,PGSFT
	LOAD D,STRX,(P1)	;GET STRUCTURE NUMBER
	CALL UDSKIO		;WRITE TO DISK
	AOS DSKWR		;COUNT WRITES FOR STATISTICS
	EXCH A,P3		;SAVE ERROR BITS, GET CORE PAGE
	CALL MULKPG		;UNLOCK PAGE
	SKIPE P3		;ERROR ON WRITE?
	BUG.(CHK,XBWERR,PAGUTL,HARD,<UPDOFN - Disk write error on XB>,,<

Cause:	UPDOFO was called to scan an index block and write the image to
	disk. This BUG indicates that there has been a disk write error on
	the index block.
>,,<DB%NND>)			;[7.1210] 

UOFNX:	MOVEI A,0
	MOVEI B,FPG2A
	MOVEI C,2
	CALL MSETMP		;UNMAP BOTH PAGES
	RET
;UPDOFN...
;FIND DISK ADDRESS FOR PAGE IN XB

UOFN2:	NOSKED
	MOVE A,FPG2A(P2)	;GET POINTER
	LOAD B,PTRCOD,A		;GET PTR TYPE
	CAIE B,SHRCOD		;SHARE?
	JRST [	LOAD A,STGADR,A	;NO, PRIVATE. GET ADR.
		JRST UOFN3]
	LOAD A,SPTX,A		;GET SPT INDEX
	LOAD A,STGADR,SPT(A)	;GET ADDRESS OF PAGE
UOFN3:	TXNE A,DSKAB		;HAVE DISK ADDRESS?
	JRST UOFN4		;YES, DONE
	TXNE A,DRMAB		;HAVE DRUM ADDRESS?
	JRST UOFN5		;YES
	TXNE A,NCORTM		;CORE ADDRESS?
	JRST [	SETZ A,		;NO, UNASSIGNED. USE 0
		JRST UOFN4]
	CAML A,MONCOR		;LEGAL PAGE NUMBER?
	CAMLE A,NHIPG
	JRST UOFBPP		;NO
	HRRZS A
	LOAD A,STGADR,@CST1X+A	;GET NEXT LEVEL ADDRESS
	JRST UOFN3		;GO SEE WHAT IT IS

;HAVE DRUM ADDRESS. FIND THE BACKUP ON DISK AND STORE THAT INTO WORK
;COPY OF INDEX BLOCK

UOFN5:	MOVE B,A
	CALL GDSTX		;GET ADDRESS IN DST FOR THIS PAGE
	LOAD A,STGADR,(B)	;GET NEXT LEVEL ADDRESS FROM DST
	TXNN A,DSKAB		;IT MUST BE DISK
	JRST UOFBPP		;LOSSAGE
UOFN4:	OKSKED
	TXNE A,DSKNB		;ADDRESS NOT WRITTEN YET?
	SETZ T1,		;YES, DON'T PUT IT ON DSK
	STOR A,STGADR,FPG3A(P2) ;PUT DSK ADR IN IMAGE PAGE
	SKIPN A			;PAGE EXISTS?
	HRRZ A,P2		;NO, USE XB INDEX FOR CHECKSUM
	JCRY0 .+1		;CLEAR CARRY FLAG
	ADD P5,A		;DO CHECKSUM
	JCRY0 [AOJA P5,.+1]	;WRAPAROUND CARRY
	JRST UOFN6		;CONTINUE SCAN
;CASES OF BAD POINTER

UOFBPP:	BUG.(HLT,ILPPT1,PAGUTL,HARD,<UPDOFN - Bad pointer in page table>,,<

Cause:	The monitor is updating the disk index block for a file.
	The index block contains an address of a file page that is
	incorrect for one of the following reasons:

	1. It is a memory address of non-existent memory or in the
	   resident monitor.
	2. There is no disk address for the page.
>)
	OKSKED
	JRST UOFNX		;RETURN WITHOUT WRITING XB
;LOAD/STORE DATA IN INDEX BLOCK.
;SINCE THE STORAGE ADDRESS IS ONLY 23 BITS, THE REMAINING PORTION
;OF EACH WORD CAN BE USED TO STORE USEFUL INFORMATION, E.G. A
;CHECKSUM OF THE INDEX BLOCK.  THESE ROUTINES PACK AND UNPACK
;THE DATA FROM THE XB USING B0-8 OF SUCCESSIVE WORDS.

; A/ ADDRESS OF WORD(S)
; B/ NUMBER OF XB WORDS,,XB ADDRESS + OFFSET
;	CALL STXBD/LDXBD
; RETURN +1 ALWAYS, DATA MOVED BETWEEN XB AND C(C(A))

;STORE DATA INTO INDEX BLOCK

STXBD:	HRLI A,(<POINT 9,0>)	;INIT PTR TO CALLERS DATA
STXBD1:	ILDB C,A		;GET BYTE FROM CALLER
	DPB C,[POINT 9,0(B),8]	;PUT IT IN XB
	AOBJN B,STXBD1		;INCREMENT THROUGH XB
	RET

;LOAD FROM XB

LDXBD:	HRLI A,(<POINT 9,0>)	;INIT PTR TO CALLERS STORAGE
LDXBD1:	LDB C,[POINT 9,0(B),8]	;GET BYTE FROM XB
	IDPB C,A		;PUT IT IN CALLERS STORAGE
	AOBJN B,LDXBD1		;SCAN THROUGH XB
	RET

;ITEMS IN INDEX BLOCK VECTOR

XBCKSM==<-4,,0>			;CHECKSUM--4 WORDS BEGINNING AT 0
   REPEAT 0,<			;[7247] Don't need now but save anyway
;[7247] PTTLOP - PERFORMS OPERATION IN T1 FOR ALL SECOND LEVEL PTS IN A PTT
;[7247] 
;[7247] T3/ PTT OFN
;[7247] T1/ INSTRUCTION TO DO FOR EACH 2XB OFN
PTTLOP:	SAVEQ			;[7247] 
	STKVAR <INSTR,PTTN>	;[7247] 
	MOVEM T1,INSTR		;[7247] SAVE THE INSTRUCTION TO DO
	LOAD FX,STRX,(T3)	;[7247] GET STRUCTURE
	MOVEM T3,PTTN		;[7247] SAVE THE PTT OFN
	MOVSI Q2,-PGSIZ		;[7247] LOOP THROUGH ALL PTS
PTTL2:	MOVE T3,PTTN		;[7247] GET THE PTTN

;[7247] Note:  The SETXB1 must be called every time through the loop because
;[7247] UPDPGI will clear CXBPGA and an ILMNRF will result.

	CALL SETXB1		;[7247] MAP XB
	OPSTR <SKIPN Q1,>,STGADR,CXBPGA(Q2) ;[7247] GET STGADR OF 2XB
	JRST PTTL1		;[7247] NONE
	CALL OFNSRC		;[7247] OFN AROUND?
	 JRST PTTL1		;[7247] 
	XCT INSTR		;[7247] 
PTTL1:	AOBJN Q2,PTTL2		;[7247] 
	CALL RELCXB		;[7247] RELEASE MAPPING
	RET			;[7247] 
	ENDSV.			;[7247] 
   >				;[7247] End of REPEAT 0

;[7247] SKPOPR - SKIP if file has "regular" (not UNRESTRICTED) openers
;[7247] 
;[7247]  Test is made on 2XB(0) or PTT if present
;[7247]  T1/ OFN

SKPOPR::SAVEAC <T1,T2>		;[7247] 
	SKIPN T2,SPTO4(T1)	;[7247] Long file?
	IFSKP.			;[7247] Yes
	  TRNE T2,777		;[7247] 2XB(0)?
	  HLRZ T1,T2		;[7247] No, get PTT
	ENDIF.			;[7247] 
	TMNN OFOPC,(T1)		;[7247] Any openers?
	RET			;[7247] No regular openers
	RETSKP			;[7247] Regular openers
	
;UPDATE FILE PAGES--CAUSE CHANGED PAGES TO BE WRITTEN TO DISK
; 1/ IDENT OF FIRST FILE PAGE, OFN,,PN
; 2/ FLAGS,,NUMBER OF SEQUENTIAL PAGES TO UPDATE
;	CALL UPDPGS
; RETURN +1 ALWAYS, ALL WRITES COMPLETED

;AC USAGE:
; P1 - OFN
; P2 - AOBJN PTR FOR SCANNING PT
; P3 - FLAGS
; P4 - COPY OF INITIAL AOBJN PTR

;LOCAL FLAGS

UPGSF0==1B1			;0=WRITE PAGES, 1=WAIT FOR COMPLETION
UPGSLF==1B2			;1=DRUM SPACE LOW, FORCE PAGES TO DSK
UPGKPF==1B3			;0 = USE OFRQ, 1 = USE ONRQ ON SWPOUT
UPGNOW==1B4			;NO WAIT. DON'T DO PASS 2
UPGDSK==1B5			;Force to disk
UPGCRB==1B6			;Clear CST write bit for in-memory pages

;ROUTINE SCANS PAGE TABLE TWICE.  FIRST TIME TO REQUEST WRITES ON
;ALL CHANGED PAGES, SECOND TIME TO WAIT FOR COMPLETION OF WRITES.
;THIS IS FASTER THAN WAITING FOR EACH WRITE TO COMPLETE AS IT
;IS REQUESTED.

UPDPGS::SAVEP			;SAVE P1-P6
	TXNE T2,UF%FSH		;[7.1081] Flush incore copy of pages?
	SKIPA P3,[UPGDSK]	;[7.1081] Yes
	MOVX P3,UPGKPF		;[7.1081] No, keep incore copy of pages
	TXNE T2,UF%NOW		;WANT "NO WAIT"?
	TXO P3,UPGNOW		;YES. SET BIT THEN
	JRST UPGS0

UPDPGR::SAVEP			;ENTRY TO REMOVE PAGES QUICKLY
	MOVX P3,0		;CLEAR FLAGS
	JRST UPGS0
;Entry for DDMP to do force out pages

UPDPGX:	SAVEP
	MOVX P3,UPGSLF!UPGDSK!UPGCRB ;Use "swap space low" + flush algorithm
	JRST UPGS0		;Go to it

;Here for downgrading a file to read-only

UPDPGY:	SAVEP
	MOVX P3,UPGKPF!UPGCRB	;keep pages, clear write bit
	JRST UPGS0		;Go to it

;SPECIAL ENTRY FOR DDMP, SET FLAG TO FORCE PAGES TO DSK WHEN DRUM FULL

UPDPG0:	SAVEP
	MOVX P3,UPGSLF+UPGKPF	;SET FULL FLAG AND KEEP PAGES
UPGS0:	MOVEI B,0(B)		;GET COUNT ONLY
	HLRZM A,P1		;SAVE OFN
	HRRM A,P2		;SETUP INITIAL PAGE NUMBER
	HRRZ A,A
	ADD A,B			;COMPUTE FINAL PAGE NUMBER
	CAILE A,PGSIZ		;BEYOND END OF PT?
	BUG.(HLT,PTOVRN,PAGUTL,SOFT,<UPDPGS - Count too large>,,<

Cause:	A routine has been called to update pages of a file on the disk 
	to which a specified index block (OFN) points. The caller
	provides a starting page and a count. The BUGHLT occurs
	because the sum of the two extends beyond the end of the
	index block.
>)
	MOVN B,B
	HRLM B,P2		;CONSTRUCT AOBJN PTR TO SCAN PT
	MOVE B,P1		;GET PT
	CALL CHKDMO		;SEE IF IT IS A DISMOUNTED OFN
	 CALLRET DMOINT		;IT IS. GIVE AN ERROR
	MOVEM P2,P4		;SAVE COPY FOR SECOND PASS
	LOAD A,STGADR,SPT(P1)	;GET CURRENT ADR OF INDEX BLOCK
	TXNE A,DSKAB		;ON DISK?
	RET			;YES, NOTHING TO DO
;   IFN CFSCOD,<
	MOVE A,P1		;MAP PAGE TABLE
	SETZ B,
	SKIPL DDPFRK		;Is this DDMP?
	CALL CFSAWP		;GET AND HOLD FILE ACCESS TOKEN
;   >	;IFN CFSCOD
	MOVE A,P1		;RESTORE OFN
	MOVE B,[PTRW+FPG2A]
	CALL SETMPG
UPGS1:	SKIPE FPG2A(P2)	;PAGE EXISTS?
	JRST UPGS2		;YES, GO CHECK IT OUT
UPGS3:	AOBJN P2,UPGS1		;DO ALL PAGES
	MOVE P2,P4		;REINIT AOBJN PTR
	TXOE P3,UPGSF0		;DONE PASS 2?
	JRST UPGSX		;YES. ALL DONE THEN
	TMNN OFNWRB,SPTH(P1) ;IF OFN NEEDS UPDATING, MUST WAIT
	TXNN P3,UPGNOW		;OFN SET, WANT TO WAIT?
	JRST UPGS1		;YES. GO DO PASS 2 THEN
UPGSX:	MOVEI A,0
	MOVEI B,FPG2A
	CALL SETMPG		;RELEASE PT MAPPING
;   IFN CFSCOD,<
	MOVE A,P1		;THE OFN
	SKIPL DDPFRK		;Is this DDMP?
	CALL CFSFWT		;GIVE IT UP AND RETURN
	RET
;   >	;IFN CFSOCD
   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<RET>
   >				;END REPEAT 0
;UPDPGS...
;INVESTIGATE SPECIFIC PAGE
;	P1/ OFN
;	P2/ PAGE NUMBER

UPGS2:	NOSKED
UPGS7:	MOVE A,FPG2A(P2)	;GET POINTER
	LOAD B,PTRCOD,A		;GET PTR TYPE
	CAIN B,SHRCOD		;SHARE?
	JRST [	LOAD D,SPTX,A	;YES, GET SPT INDEX
		LOAD A,STGADR,SPT(D) ;GET PAGE ADR FROM SPT
		JRST UPGS9]	;GO PROCESS IT
	MOVE D,P2		;IS PRIVATE. FORM ID
	HRL D,P1		; AS OFN.PN
UPGS9:	TXNE A,DSKAB		;ON DISK?
	JRST UPGS4		;YES, NO UPDATE NEEDED
	TXNN A,DRMAB		;ON DRUM?
	JRST UPGS5		;NO
	TXNE P3,UPGSF0		;YES, PASS 2?
	IFNSK.			;If so
	 TXNN P3,UPGDSK		;Flushing?
	 IFSKP.			;If so
	  ANDX T1,STGADR	;Get address only
	  CALL REMFP1		;Delete local storage
	  CALL UPGSTO		;Put it back where it belongs
	  ENDIF.
	 JRST UPGS4		;And done with this page
	ENDIF.
	MOVE B,A		;GET DRUM ADDRESS TO B FOR GDSTX
	CALL GDSTX		;GET ADDRESS IN DST FOR THIS PAGE
	MOVE C,(B)		;GET DRUM INFO
	TXNN C,BWRBIT		;PAGE MODIFIED?
	JRST [	TXNN P3,UPGSLF ;NO, DRUM FULL?
		JRST UPGS4	;NO, BYPASS PAGE
		SETOM (B)	;DRUM FULL, SO PUT PAGE BACK ON DSK
		TLNE D,-1	;IN SPT OR XB?
		CALL [	HRRZ B,D
			STOR C,STGADR,FPG2A(B) ;IN XB
			RETSKP]	;DONE
		STOR C,STGADR,SPT(D) ;SPT
		CALL DASDRM	;ADJUST POINTER AND DEASSN DRM ADR
		JRST UPGS4]
	MOVE A,D		;MUST SWAPIN PAGE, GET SPT INDEX
UPGS6:	CALL SWPINW		;SWAPIN THE PAGE
	JRST UPGS7		;NOW SHOULD BE IN CORE
;PAGE NOT ON DISK OR DRUM

UPGS5:	TXNE A,NCORTM		;IN CORE?
	JRST UPGS4		;NO, UNASSIGNED. IGNORE.
	TXNE P3,UPGSF0		;PASS 2?
	JRST [	CALL SKPNWR	;YES, WRITE STILL IN PROGRESS?
		 JRST UPGS7	;YES, WAITED FOR COMPLETION
		TXNN P3,UPGDSK	;flushing?
		JRST UPGS4	;No. All done with this page
		CALL REMFP1	;Delete local copies
		CALL UPGSTO	;Put address back
		JRST UPGS4]	;And done
	TXNE P3,UPGCRB		;Want to clear the write bit?
	IFNSK.			;If so
	 HRRZ T2,T1		;Get page number
	 SETZRO CSWRB,+T2	;Do it.
	ENDIF.
	MOVX B,CORMB
	HRRZ C,A
	TDNN B,@CST0X+C		;PAGE IN CORE MODIFIED?
	TXNE P3,UPGSLF		;OR SWAPPING BECAUSE DRUM FULL?
	JRST UPGS8		;YES, SWAPOUT PAGE
	LOAD B,STGADR,@CST1X+C	;NO, SEE IF MODIFIED ON DRUM
	TXNN B,DSKAB		;PAGE BACKUP ON DRUM?
	TXNN B,DRMAB
	JRST UPGS4		;NO, DON'T SWAPOUT
	CALL GDSTX		;YES, GET DRUM INFO
	MOVX C,BWRBIT
	TDNN C,(B)		;MODIFIED ON DRUM?
	JRST UPGS4		;NOT MODIFIED, NO UPDATE NEEDED
UPGS8:	CALL SKPNWR		;WRITE IN PROGRESS?
	 JRST UPGS7		;YES, RECHECK PAGE
	CALL AGECHK		;ASSIGN PAGE
	CALL SKPNLK		;SKIP IF PAGE NOT LOCKED IN CORE
	 JRST UPGS4		;LOCKED, SKIP IT
	MOVX B,DSKSWB
	HRRZ C,A		;TURN OFF UNWANTED INDEX BITS
	IORM B,@CST3X+C		;REQUEST SWAP TO DISK
	TXNN P3,UPGKPF		;TEST FOR PAGE USE
	IFSKP.
	 CALL SWPOTK
	ELSE.
	 CALL SWPOT0		;WRITE PAGE
	ENDIF.
UPGS4:	OKSKED
	JRST UPGS3		;CONTINUE SCAN OF PT
repeat 0,<
;CASES OF BAD POINTER

UPGBPP:	BUG(ILPPT2)
	OKSKED
	JRST UPGSX		;QUIT WITHOUT FURTHER ADO
>

;Subroutine og UPGPGS
;Here to replace storage address of page with value in T1
; This is used when "flushing" is requested by caller

;	T1/ New storage address
;	P2/ Page number

UPGSTO:	LOAD T2,PTRCOD,FPG2A(P2) ;Get pointer type
	CAIN T2,SHRCOD		;Share pointer?
	IFSKP.			;If not
	 STOR T1,STGADR,FPG2A(P2) ;Put address into immediate pointer
	ELSE.			;Or if a share pointer
	 LOAD T2,SPTX,FPG2A(P2)	;Get SPT index of share pointer
	 STOR T1,STGADR,SPT(T2)	;Stash address
	ENDIF.
	RET			;And done
;ASSIGN OFN
; FLSTG/ (STGADR) INDEX BLOCK FILE ADDRESS (DISK, DRUM OR CORE)
;    + THE FOLLOWING BITS
;	   0 UNRESTRICTED BIT (FILUB)
;          1 WRITE BIT (FILWB)
;          2 THAWED BIT (THAWB)
;	   3 NEW FILE BIT (FILNB)
;[7247]    9 DON'T UPDATE BIT (OFNDUD)
;[7247]   10 SUBINDEX BLOCK FOR LONG FILE (OFN2XB) - SET BY ASLOFN
;[7247]	   5 OFNDU0 ALLOW DUD SHARING BIT
;[7247]	   6 OFNPTT THIS IS A PTT IN A LONG FILE
; OSTRN/ STRUCTURE NUMBER
; ODIRN/ DIRECTORY NUMBER
; DREMP/ REMAINING PAGES (DRLIQ - DRDCA)
; XB2DAT/ 0 UNLESS OFN2XB IS SET IF SO XB2PT,,XB2PN (PTT OFN,,FILE SECT)
;
;RETURN SKIP WITH OFN IN AC1 IF PROPER OPENING
;RETURN NO-SKIP IF ILLEGAL SHARED OPENING (ILLEGAL CONFIGURATION
;      OF THAWED AND WRITE BITS)
;FILWB AND THAWB PROVIDE FOR 4 MODES OF OPENING:
; 00 - OPEN FOR READ, OTHER READERS AND 1 OTHER WRITER ALLOWED
; 10 - OPEN FOR WRITE, OTHER READERS ALLOWED BUT NO OTHER WRITERS
; 11 - OPEN 'THAWED' - ARBITRARY OTHER READERS AND WRITERS ALLOWED
; 01 - OPEN 'RESTRICTED' - NO OTHER OPENS ALLOWED
;
;STORAGE AND AC USAGE:
; Q1 - XB ADDRESS/CHECKSUM OF XB
; Q2 - OFN
; FX - STRUCTURE NUMBER

	OFN2P2==1B0		;SECOND PASS IN PROGRESS
	OFNLCF==1B1		;[7247] LOCAL CACHED FLAG

; IFLG - INTERNAL FLAGS (OFNPTT, OFNDU0, OFN2P2, OFNLCF)  ;[7247] 
;
;ENTRY WITH OFN2XB ASSIGNS OFN ONLY IF IT ALREADY EXISTS OR
;CURRENT OFN USAGE IS BELOW LONG FILE CUTOFF
ASNOFN::BLSUB. (<FLSTG,OSTRN,ODIRN,DREMP,XB2DAT>,<IFLG,EFLG>) ;[7356]
	SAVEQ
	MOVE T1,FLSTG		;GET FLAGS AND STG
	TXNE T1,OFN2XB		;2XB?
	IFNSK.			;YES
	  SKIPE XB2DAT		;AND NO DATA OR
	  TXNE T1,OFNPTT	;PTT?
	  CALL OFNSRE		;YES! THIS IS IMPOSSIBLE ERROR!
	ELSE.			;NOT 2XB PTT OR NORMAL
	  SKIPE XB2DAT		;DATA FOR 2XB SUPPLIED?
	  CALL OFNSRE		;YES! THIS IS IMPOSSIBLE ERROR!
	ENDIF.

	ANDX T1,OFNPTT!OFNDU0	;GET WIERD BITS
	MOVEM T1,IFLG		;SAVE SPECIALS AND
	ANDCAM T1,FLSTG		;CLEAR THEM IN STGADR FLAG WORD
	
	HRRZ FX,OSTRN		;SAVE STRUCTURE NUMBER
	CAIGE FX,STRN		;A VALID STRUCTURE NUMBER?
	SKIPN STRTAB(FX)	;YES. DOES THE STRUCTURE EXIST?
	BUG.(HLT,STRBAD,PAGUTL,SOFT,<ASOFN - Illegal structure number>,,<

Cause:	A routine was called to assign an OFN (index block). The
	caller provided a structure number that was invalid, either
	because that number can never exist or because it does not
	exist now.
>)
ASOFC:	NOSKED
ASOFCO:	TMNN DSKAB,FLSTG	;DISK?
	JRST [	MOVEI 1,OPNX16	;NO, RETURN BAD
		JRST ASOFXB]
	LOAD Q1,STGADR,FLSTG	;JUST GET STGADR FOR OFNSRC
	CALL OFNSRC		;SEARCH SPTH FOR GIVEN DSK ADR
	 JRST ASOF4		;NOT FOUND, GO ADD TO TABLE
	HRRZ Q2,1		;FOUND, GET OFN
	MOVX 2,SPTLKB		;LOCK BIT
	TDNE 2,SPTH(1)		;IS IT AVAILABLE
ASGOFW:	JRST [	CALL WTOFNS	;WAIT FOR IT
		JRST ASOFC]	;TRY, TRY AGAIN
;   IFN CFSCOD,<
	CSKED
	HRRZ 1,Q2
	CALL UPSHR		;Lock it from release
	SETZM T2		;GET SHARED ACCESS PLEASE
	CALL CFSAWP		;GET TOKEN
	HRRZ T1,Q2		;The OFN again
	CALL DWNSHR		;Undo extra share increment
	MOVX T2,SPTLKB		;Get lock bit again
	TDNE T2,SPTH(T1)	;Still not locked?
	IFNSK.			;If not
	  CALL CFSFWT		;Undo the resoource hold
	  HRRZ T1,Q2		;Recover OFN
	  ECSKED
	  JRST ASGOFW		;And wait for it to be free
	ENDIF.
;   >	;IFN CFSCOD
	IORM 2,SPTH(1)		;LOCK IT UP
   IFN SPTDSW,<			;[7.1036] Only if debugging SPTLKB problems
	CALL SPTRAC		;[7.1036] (T1/)Record who locked SPTLKB
   >				;[7.1036] End of IFN SPTDSW
        TMNN OFNCSH,(Q2)	;[7247] This OFN cached?
	IFSKP.			;[7247] Yes
	  MOVX T1,OFNLAC	;[7247] Did this system lose access to ...
	  TDNN T1,SPTH(Q2)	;[7247] ... OFN while it was cached?
	  IFSKP.		;[7247] Yes
	    ECSKED		;[7247] Undo CSKED from above
	    HRRZ T1,Q2		;[7247] Get OFN
	    CALL CFSFWT		;[7247] (T1/)Release write token (re-caches it)
	    HRRZ T1,Q2		;[7247] Get OFN
	    CALL OC.AUC		;[7247] (T1/)Uncache it
	     NOP		;[7247] Impossible return
	    JRST ASOFCO		;[7247] Try again
	  ELSE.			;[7247] System did not lose access to OFN
	    MOVX T1,OFNLCF	;[7247] Get local cache bit
	    IORM T1,IFLG	;[7247] Remember it
	    AOS NOCH		;[7247] Increment cache hit rate
	    SOS NOC		;[7247] One less cached OFN
	    ECSKED		;[7247]
	    JRST ASOF7		;[7247] And continue at "new" OFN code
	  ENDIF.		;[7247]
	ENDIF.			;[7247] 
	NOINT
	; ..
;SHARED OPEN, CHECK WRITE AND THAWED BITS FOR LEGAL COMBINATION


	MOVE T1,XB2DAT		;CHECK FOR CONSISTENT DB
	OPSTR <SKIPN>,OFNSHC,(Q2) ;FIRST SHARER?
	MOVEM T1,SPTO4(Q2)	;YES, STORE 2XB DATA
	CAMN T1,SPTO4(Q2)	;2XB DATA CONSISTENT WITH OTHER OPENERS?
	IFSKP.			;NO, ERROR!
;**************************************************************************
; NOTE: THIS MIGHT STILL BE OK SEE TCO 6.1.1399. AND 6.1.1463
; IF THIS FILE HAS GONE LONG
; BECAUSE OF CFS THEN JUST FIXUP SPTO4 AND CONTINUE W/O CRASHING.
; IF THIS IS THE CASE THEN SPTO4 WILL BE 0 (SHORT FILE) AND T1 WILL HAVE
; SUPER-OFN,,0 (SINCE THE CURRENT REGULAR OFN IS SECTION 0 OF A LONG FILE)
; TAM 5/28/85
; IT IS ALSO POSSIBLE TO HAVE XB2(0) DIFFER FROM SPTO4 IF A SHORT OPENER "HELD"
; XB2(0) WHILE ALL LONG OPENERS CLOSED IT RESULTING IN DEASSIGNMENT OF THE
; SUPER. THUS ALL CASES OF XB2(0) ARE LEGAL
; TAM 6/21/85
;**************************************************************************
	  SKIPE T1		;CALLER INDICATES SHORT FILE OR
	  TRNE T1,-1		;RIGHT HALF OF NEW DATA NON 0?
	  CALL OFNSRE		;LONG TO SHORT OR NOT 2XB(0) IS FATAL
	  MOVEM T1,SPTO4(Q2)	;FIX UP SPTO4
	ENDIF.
	TMNE OFN2XB,FLSTG	;OFN2XB SECOND PT OF LONG FILE?
	IFSKP. <
	  BLCAL. CHKACC,<Q2,FLSTG> ;NO, CHECK FOR LEGAL SIMUL OPEN
	   JRST ASOFB>		;NOT LEGAL, RETURN BUSY
	TMNN ALOCX,(Q2)		;[7247] Have an ALLOC entry yet?
	CALL ASGALC		;[7247] No, go get one for this OFN
	MOVE T1,Q2		;Get the OFN
	CALL UPSHR		;Increment share count
	MOVX T1,OFNDUD		;Get the DUD bit
	TDNE T1,FLSTG		;[7247] Was this requested?
	IORM T1,SPTH(Q2)	;YES. HONOR THE REQUEST.
	MOVE T1,SPTH(Q2)	;GET THE BITS
	TMNE FILUB,FLSTG	;[7247] An UNRESTRICTED open?
	IFSKP.			;If not
	  LOAD T3,OFOPC,(Q2)	;Save count of real opens
	  INCR OFOPC,(Q2)	;COUNT REGULAR OPENS
;   IFN CFSCOD,<			;If CFS
	  TMNN OFNPTT,FLSTG	;[7294] Is this a PTT (and so needs no update)
	  TXNE T1,FILWB+THAWB	;[7294] Or OFN is write, thawed or restricted?
	  IFSKP.		;[7294] No, OFN is not PTT and is only open READ
	    IFE. T3		;If this is the first real opening
	      OKSKED		;Allow scheduling now
	      HRLZ T1,Q2	;form OFN,,
	      MOVEI T2,PGSIZ	;Scan entire OFN
	      CALL UPDPGX	;And flush the pages
	      NOSKED
	    ENDIF.
	  ENDIF.
;   >	;IFN CFSCOD
	ENDIF.
	MOVE T1,Q2		;GET THE OFN AGAIN
	CALL ULKOFN		;UNLOCK
	JRST ASOFXG		;RETURN GOOD

ASOFB:	HRRZ 1,Q2
	CALL ULKOFN		;UNLOCK OFN
	MOVEI 1,OPNX9		;ERROR NUMBER FOR FILE BUSY
	JRST ASOFXB

;EXITS FROM ASOFN

ASOFXB:	TDZA 2,2		;EXIT "BAD"
ASOFXG:	SETO 2,			;EXIT "GOOD"
	OKSKED
	JUMPE 2,R		;BAD = NOSKIP RETURN
	RETSKP			;GOOD = SKIP RETURN
;Routine to print NOOFN BUGINF.  Issued at most once every 30 minutes

BGCTYP:	CALL LGTAD		;Get time
	CAMGE T1,INFTMR		;IS IT TIME TO ISSUE BUGINF AGAIN?
	IFSKP.			;Yes
	  ADDI T1,^D5461	;ADD 30 MINUTES TO CURRENT TIME
	  MOVEM T1,INFTMR	;STORE AS TIME OF NEXT BUGINF
	  BUG.(INF,NOOFN,PAGUTL,SOFT,<ASOF4 - Attempt to create new OFN failed - no more OFNs available>,,<

Cause:	As a result of an OPENF, an attempt has been made to create a new
	OFN.  This attempt fails because the system has no more OFNs 
	available for use.  The user will receive an OPNX10 error.  This 
	BUGINF will be issued at most once every 30 minutes regardless of 
	how many OPENF attempts are made during the time the OFN space is 
	exhausted.

Action:	If more OFN space is desired, increase the value of NOFN.
>,,<DB%NND>)			;[7.1210] 
	ENDIF.
	MOVEI 1,OPNX10		;SAY 'NO ROOM'
	JRST ASOFXB		;RETURN BAD
;COULD NOT FIND MATCHING OFN. CREATE ONE.

ASOF4:	TMNE OFN2XB,FLSTG	;SECOND LEVEL XB
	JRST [	MOVE Q2,NOF	;YES. GET "OPEN FILE COUNT"
		CAIGE Q2,NOFN-NROFN-1 ;CAN WE OPEN ANOTHER LONGY?
		JRST .+1	;YES. PROCEED
		TMNE OFN2P2,IFLG ;PASS 2?
		JRST BGCTYP	;YES, FAIL
		CALL FREOFN	;YES. CLEAN UP OFNS AND TRY AGAIN
		 JRST BGCTYP	;NONE.
		SETONE OFN2P2,IFLG ;SAY NOW ON PASS 2
		JRST ASOFCO]	;AND TRY AGAIN
	SKIPE T2,OFNFRE		;ANY FREE OFNS?
	JRST ASOF6		;YES
	CALL FREOFN		;TRY RELEASING ALL "UNSHARED" OFN
	 JRST BGCTYP		;NONE
	JRST ASOFCO		;RETRY

ASOF6:	MOVE Q2,0(T2)		;REMEMBER NEW OFN
	EXCH Q2,OFNFRE		;UNLINK OFN FROM CHAIN
	SUBI Q2,SPTO2		;ADJUST TO BE INDEX ONLY
	LOAD T2,OFNHS,(T1)	;GET HEAD OF OFN LIST THIS HASH
	STOR Q2,OFNHS,(T1)	;SAVE NEW OFN AS HEAD OF CHAIN
	STOR T2,OFNNXT,(Q2)	;SAVE OLD HEAD AS NEXT
	SKIPE T2
	STOR Q2,OFNPRV,(T2)	;SAVE THIS OFN AS PREV OF OLD HEAD
	ADDI T1,NOFN		;MAKE PREV OF NEW HEAD POINT TO HASH TABLE
				;**NOTE: HASH TABLE MUST FOLLOW DATA BASE
	STOR T1,OFNPRV,(Q2)
	SKIPL SPTO4(Q2)		;*** TEMP CHECK FOR UNASSIGNED
	CALL OFNSRE		;*** ASSIGNED NOW!
ASOF7:	MOVE T1,XB2DAT		;[7247] Store second level data
	MOVEM T1,SPTO4(Q2)
	MOVE T1,FLSTG		;GET FLAGS AND STGADR
	ANDX 1,FILUB+FILWB+THAWB+FILNB+OFNDUD+OFN2XB+STGADR  ;[7283] Keep valid bits and storage address only
	TXZE T1,FILNB		;NEWLY ASSIGNED XB?
	TXO Q1,DSKNB		;YES, INDICATE IN DISK ADDRESS
	MOVX T2,SPTLKB		;[7247] Get the lock bit
	IOR T1,T2		;[7247] Make sure it gets set
	MOVE T2,T1		;[7247] Get the word to put into SPTH
	EXCH T2,SPTH(Q2)	;[7247] Put in new word and get back old SPTH
   IFN SPTDSW,<			;[7.1036] Only if debugging SPTLKB problems
	EXCH T1,Q2		;[7.1036] Position the OFN
	CALL SPTRAC		;[7.1036] (T1/)Record who locked SPTLKB
	EXCH T1,Q2		;[7.1036] Restore the ACs
   >				;[7.1036] End of IFN SPTDSW
	LOAD T3,SPTST,(Q2)	;[7247] Get current OFN state
	SETZB T1,SPTO2(Q2)	;[7247] Init flags and count
	TMNN FILUB,FLSTG	;[7247] An UNRESTRICTED open?
	SKIPA T1,[1]		;[7247] No, RESTRICTED so count is 1
	SETZ T1,		;[7247] Yes, UNRESTRICTED so do not INCR OFOPC
	TMNE OFNLCF,IFLG	;[7247] Was this OFN "cached"
	IFSKP.			;[7247] 
	   AOS NOF		   ;[7247] No, count open files
	   STOR Q1,STGADR,SPT(Q2)  ;[7247] Put address in SPT
	ELSE.			;[7247] OFN was cached!
	   STOR T3,SPTST,(Q2)	;[7247] Store correct file state
	   LOAD T3,STGADR,SPTH(Q2)  ;[7247] Get new storage address
	   LOAD T2,STGADR,T2	;[7247] Keep only storage address of new value
	   CAME T2,T3		;[7247] The same? Should be since cached
	   BUG.(HLT,OCSPTH,PAGUTL,SOFT,<ASOFN - SPTH values disagree>,,<

Cause:	We are assigning an OFN which is cached and notice that the old
	value of SPTH does not match what was just written.  This is a 
	bug because the cached OFN should not have changed its index block
	address.
>)				;[7247] Not the same - error!
	ENDIF.			;[7247] 
	STOR T1,OFOPC,(Q2)	;[7247] Count of openers
	STOR FX,STRX,(Q2)	;[7247] Put in structure number
	TMNN ALOCX,(Q2)		;[7247] Have an ALLOC entry yet?
	CALL ASGALC		;[7247] Get ALLOC entry for OFN
	MOVEI 1,1		;[7247] Share count will be one
	STOR 1,OFNSHC,(Q2)	;[7247] Store it
	; ...
	; ..
	HRRZ T3,Q2		;GET OFN
	CALL SETXB1		;MAP IT
	HRRZ T1,Q2		;GET OFN AGAIN
	NOINT			;Must be NOINT if locking the OFN
	OKSKED			;OK to allow others to run now
;   IFN CFSCOD,<		;This locking order only works for new OFNs!
	CSKED
	TMNE OFNLCF,IFLG	;[7247] Was this OFN "cached"?
	IFSKP.			;[7247] No
	  SETZM T2		;[7247] Get file state correct
	  CALL CFSAWP		;[7247] ""
	ENDIF.			;[7247] 
	HRRZ T1,Q2		;GET BACK THE OFN
	LOAD T2,OFNDU0,IFLG	;Get DUD flag for GETCFS
	CALL GETCFS		;GET CFS RESOURCE(S)
	 JRST [	NOSKED		;ERROR
		JRST ASCHK5]	;IN VALID ACCESS
;   >	;IFN CFSCOD
	SKIP CXBPGA		;GET XB IN MEMORY
	NOSKED			;TAKE OVER MACHINE AGAIN
	SKIP CXBPGA		;MAKE SURE IT IS STILL THERE
	SETONE SPTCDO,(Q2)	;Open complete.
	TMNN OFNDU0,IFLG
	IFSKP.			;If so
	 SETONE SPTNA,(Q2)	;don't do preallcation
	ENDIF.
	HRRZ T1,SPT(Q2)		;GET MEM ADDRESS
	MOVX T2,SWPERR
	TDNE T2,@CST3X+T1	;SWAP ERROR?
	JRST ASCHK3		;YEP
	TXNE Q1,DSKNB		;NEW XB?
	JRST [	MOVX T1,OFNWRB	;YES. IT IS CHANGED THEN
		IORM T1,SPTH(Q2) ;MARK IT
		JRST ASCHK4]	;NO CHECKSUM
	TMNE OFNLCF,IFLG	;[7247] Was this OFN "cached"?
	JRST ASCHK4		;[7247] Yes, no checksum
	MOVE T1,CXBPGA+XBBWRD	;SEE IF XB HAS A BAD ENTRY
	MOVX T2,OFNBAT		;IN CASE IT DOES
	TXZE T1,XBBAT		;DOES IT?
	IORM T2,SPTH(Q2)	;YES.
	MOVEM T1,CXBPGA+XBBWRD
	MOVEI T1,CXBPGA		;THE ADDRESS
	CALL DOXSUM		;DO CHECKSUM STUFF
	CAME T1,[-1]		;[7247] Checksum OK? (0 OR -1)
	JUMPN T1,ASCHK3		;JUMP IF CHECKSUM BAD
ASCHK4:	TMNN OFNPTT,IFLG	;IS THIS A PAGE TABLE TABLE?
	IFSKP.			;IF SO
	 CALL CHKLAC		;Verify access against PT0 access
	 ANNSK.			;If a conflict
;   IFN CFSCOD,<			;If CFS
	  MOVEI T1,0(Q2)	;get OFN
	  CALL FRECFS		;Free CFS resources
;   >	;IFN CFSCOD
	  JRST ASCHK5		;And return "busy"
	ENDIF.
	CALL RELCXB		;OK, RELEASE XB
	HRRZ 1,Q2		;RETURN OFN IN 1
	CALL ULKOFN		;RELEASE THE OFN
	JRST ASOFXG
;ASOFN...
;HANLDE RELEASING OF OBTAINED INDEX BLOCK

ASCHK5:	SKIPA T1,[OPNX9]	;SHOW INVALID ACCESS
ASCHK3:	MOVEI T1,OPNX16		;INDICATE BAD PAGE ENTRY
ASCHK9:	MOVEM T1,EFLG		;[7356]AND SAVE
	TMNN OFNLCF,IFLG	;[7356]WAS OFN CACHED?
	IFSKP.			;[7356]YES
	  MOVEI T1,0(Q2)	;[7356]GET THE OFN
	  CALL OC.CH2		;[7356](T1/)RE-CACHE IT
	  CALL RELCXB		;[7356]()RELEASE INDEX BLOCK
	  MOVEI T1,0(Q2)	;[7356]GET THE OFN
	  CALL ULKOFN		;[7356](T1/)UNLOCK IT
	  JRST ASCK10		;[7356]AND RETURN ERROR TO USER
	ENDIF.
;   IFN CFSCOD,<			;If CFS stuff
	MOVEI T1,0(Q2)		;Get OFN
	CALL FRECFS		;Free up CFS resources
;   >	;IFN CFSCOD
	CALL RELCXB		;FILE NO GOOD, RELEASE XB
	PUSH P,SPT(Q2)		;SAVE CORE ADR
	HRRZ 1,Q2
	CALL ULKOFN		;FREE THE OFN
	CALL DASOFN		;DEASSIGN OFN SLOT
	POP P,1			;RECOVER CORE ADR
	TXNE T1,NCORTM		;Is it really a memory address?
	IFSKP.			; If not, CFS did the error
	  HRRZS 1
	  SETZM @CST2X+1
	  CALL OFRQ		;PUT ON TOP OF RPLQ SINCE PAGE IS USELESS
	ENDIF.
ASCK10:	MOVE T1,EFLG		;[7356]GET ERROR INDICATOR
	JRST ASOFXB

;ERROR IN ALLOCATION TABLE


ASG6X:	BUG.(HLT,OVFLOW,PAGUTL,SOFT,<ASOFN - Allocation table overflow>,,<

Cause:	The monitor maintains information for disk quota enforcement
	in two parallel tables called the allocation tables. These
	contain one entry for each directory to which at least one OFN
	is assigned (that has at least one file open). The size
	of these tables is the maximum number of OFN's; therefore even
	if every OFN were associated with a unique directory, there
	should be enough room in the allocation tables. The BUGHLT
	indicates that the tables have overflowed.
>)
;Routine to compute checksum and return it.
;	T1/ Address of XB
;returns:
;	+1 always. T1/ computed checksum
;	 also, XB filled with page pointers

DOXSUM:	SAVEQ			;SAVE SOME REGS
	MOVE Q2,T1		;SAVE PAGE
	SETZRO XBBAT,XBBWRD(Q2)
	MOVEI T1,Q1		;POINT TO Q1 TO STORE CHECKSUM
	MOVX T2,XBCKSM		;CHECKSUM IS FIRST 4 WDS OF XB
	HRRI T2,0(Q2)		;ADDRESS
	CALL LDXBD		;GET CHECKSUM FROM XB
	SETCA Q1,		;COMPLEMENT IT, SHOULD THEN ADD TO 0
	JCRY0 .+1
	MOVSI T1,-PGSIZ
ASCHK1:	LOAD T2,STGADR,(Q2)	;GET ADDR FROM XB
	IFE. T2			;IF PTE EMPTY
	 ADDI Q1,0(T1)		;USE XB INDEX
	 JCRY0 [AOJA Q1,ASCHK2]	;1'S COMPLEMENT
	 JRST ASCHK2
	ENDIF.
	ADD Q1,T2		;DO CHECKSUM
	JCRY0 [AOJA Q1,.+1]	;WRAPAROUND CARRY
	IOR T2,IMMPTR		;CONSTRUCT IMMED PTR
ASCHK2:	MOVEM T2,(Q2)
	ADDI Q2,1		;NEXT ADDRESS
	AOBJN T1,ASCHK1
	MOVE T1,Q1
	RET			;AND DONE
;ROUTINE TO LOOK FOR AN APPROPRIATE ALLOC ENTRY

ASGALC:	MOVE T1,ODIRN		;DIRECTORY NUMBER
	MOVE T2,FX		;STRUCTURE NUMBER
	CALL LOKCAL		;SEE IF CURRENT ENTRY
	 JRST ASOF6A		; NO - MAKE NEW ENTRY
	INCR ODIRC,(T2)		;Increment count
	JRST ASOF6B		;And go finish up

;HERE TO CREATE NEW DIRECTORY ALLOCATION ENTRY

ASOF6A:	STKVAR <SVACS>
	MOVE T2,[-<NOFN-1>,,1]	;PREPARE AOBJN PNTR
	TMNE ALCWD,(T2)		;LOOK FOR EMPTY SLOT
	AOBJN T2,.-1		;...
	JUMPGE T2,ASG6X		;ERROR IF NO ROOM
	MOVE T1,ODIRN		;GET DIRECTORY NUMBER
	STOR T1,ADIRN,(T2)	;SAVE IN TABLE
	INCR ODIRC,(T2)		;Seize it
   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<			;For non-CFS stuff
	MOVE T1,DREMP		;PAGES LEFT IN QUOTA
	STOR T1,PGLFT,(T2)	;STORE
   >	;IFE CFSCOD
   >				;END REPEAT 0
;   IFN CFSCOD,<			;For CFS
	MOVEM T2,SVACS
	MOVE T2,T1		;Dir number
	LOAD T1,STRX,(Q2)	;Str number
	MOVX T3,<CF%PRM!.CFAGT>	;Get or store
	MOVE T4,DREMP		;The quota, as we see it
	CALL CFSDAU		;Do it
	 NOP
	MOVE T1,SVACS		;Get index back
	STOR T2,PGPTR,(T1)	;Stash pointer
	MOVE T2,SVACS
;   >	;IFN CFSCOD
ASOF6B:	STOR T2,ALOCX,(Q2)	;TABLE INDEX TO SPT
	SETZM OFNLEN(Q2)	;CLEAR EOF INFO
	RET			;ALL DONE.
	ENDSV.
;ROUTINE TO CHECK THE EXISTANCE AND ACCESS OF THE FIRST OFN
;OF A LONG FILE.  THIS CHECK FIXES A BUG THAT ALLOWS A LONG
;FILE TO BE OPENED WHILE IT'S BEING ACCESSED BY AN OFN WHICH
;KNOWS IT ONLY AS A SHORT FILE.  CHECKING FOR THE EXISTENCE OF
;THE "SHORT" FILE AND IT'S ACCESS GUARANTEES PROPER ACCESS.

;MUST BE CALLED NOSKED
;ACCEPTS:	Q2/ OFN OF LONG FILE

;RETURNS:	+1, INVALID ACCESS
;		+2, ACCESS OK

CHKLAC:	SAVEAC <Q1>		;GET A REG
	STKVAR <<ARGS,2>>
	LOAD Q1,STGADR,CXBPGA	;GET GET DISK ADDRESS OF FIRST FILE SECTION
	CALL OFNSRC		;SEE IF ANYONE HAS IT OPEN AS A SHORT FILE
	IFSKP.
	 TMNE OFNCSH,(T1)	;[7283] This OFN cached?
	 ANSKP.			;[7283] No
	   MOVE T2,FLSTG	;[7283] Get flags and STGADR of new access
	   ANDX T2,FILUB+FILWB+THAWB+FILNB+OFNDUD+OFN2XB+STGADR  ;[7283] Keep valid bits and storage address only
	   BLCAL. CHKACC,<T1,T2>;[7283] DO GENERAL ACCESS CHECK
	    RET			;[7283] FAILED
	   RETSKP		;[7283] OK
	ENDIF.

;Here if not known locally

;   IFN CFSCOD,<
	LOAD T1,STRX,(Q2)	;Get structure
	MOVE T2,SPTH(Q2)	;Get access required
	LOAD T3,STGADR,CXBPGA	;Get PT0 address
	STOR T3,STGADR,T2
	DMOVEM T1,ARGS		;Save args
	OKSKED			;Allow scheduling if need be
	CALL GETCF0		;Check it out
	 RETBAD(,<NOSKED>)
	DMOVE T1,ARGS		;Succeeded. Get back args
	CALL FRECF0		;Free the resource
	NOSKED
;   >	;IFN CFSCOD
	RETSKP			;And done
	ENDSV.

	ENDBS.			;[7247] End of BLSUB at ASNOFN
;GENERAL FILE ACCESS CHECK
; BLCAL. CHKACC,<OFN,BITS FOR THIS OPEN>

CHKACC:	BLSUB. <EOFN,NEWB>
	SAVEAC <Q1,Q2>
	HRRZ Q1,EOFN		;KEEP OFN FOR INDEX
	MOVE T2,NEWB
	LOAD T1,OFOPC,(Q1)	;COUNT OF EXISTING REGULAR OPENS
	SKIPE T1		;[7283] Only unrestricted opens?
	IFSKP.			;[7283] Yes
;   IFN CFSCOD,<		;[7283]
	        TXNE T2,THAWB	;[7283] Is new access possibly restricted?
	        TXNE T2,FILWB	;[7283] Yes. Is it restricted?
	        SKIPA          	;[7283] No. Allow it then
	        RETBAD()	;[7283] Yes. Disallow it then
		OKSKED		;[7283]
	        LOAD T1,STRX,(Q1)  ;[7283] Get structure number
		CALL GETCF0	;[7283] (T1,T2/)Update CFS resource(s)
	         RETBAD(,<NOSKED>) ;[7283] Couldn't upgrade
	        MOVE T1,Q1  	;[7283] Get OFN
		CALL FRECFS	;[7283] (T1/)Release previous access
		NOSKED
		MOVE T2,NEWB
;   >	;IFN CFSCOD
		TXNE T2,FILUB	;Unrestricted?
		RETSKP		;Yes. All done then
		MOVE T1,SPTH(Q1)  ;[7283] Get current flags and storage
		TXZ T1,FILUB	;[7283] Clear unrestricted read status
		MOVEM T1,SPTH(Q1)  ;[7283]  Restore corrected status
		XOR T2,SPTH(Q1) ;IF NONE, THIS IS LIKE A FIRST OPEN
		ANDX T2,FILWB+THAWB+OFNDUD+OFN2XB
		IORM T2,SPTH(Q1);[7.1285] Set the bits
		RETSKP 		;[7283] OK
	ENDIF.			;[7283]
	MOVE T1,SPTH(Q1)
	TXNE T2,FILUB		;Unrestricted?
	IFNSK.			;if so
	 TXNE T1,THAWB		;Is it possibly restricted?
	 TXNE T1,FILWB		;Yes. is it restricted?
	 JRST RSKP		;No. Allow it then
	 RET			;Yes. Disallow it then
	ENDIF.
	TLNE 1,(THAWB)		;FILE NOW OPEN THAWED OR RESTRICTED?
	JRST [	XOR 1,2		;YES, COMPARE EXISTING AND NEW MODES
		TLNN 1,(FILWB+THAWB) ;BOTH THE SAME?
		TLNN 2,(FILWB)	;AND NOT RESTRICTED?
		RET		;NO, REPORT BUSY
		RETSKP]		;THIS OPEN OK
	TLNE 2,(THAWB)		;NEW OPEN CONSISTENT?
	RET			;NO, REPORT BUSY
	TLNN 2,(FILWB)		;NEW OPEN WANTS WRITE?
	RETSKP			;NO, MUST BE OK
	TLOE 1,(FILWB)		;YES, FILE ALREADY HAS WRITER?
	RET			;YES, REPORT BUSY
;   IFN CFSCOD,<
	OKSKED			;ALLOW SCHEDULING FOR NOW
	MOVE Q2,T1		;Save status
	LOAD T1,STRX,(Q1)	;Get structure
	LOAD T2,STGADR,SPTH(Q1)	;Get XB address
	CALL CFSGWL		;TRY TO GET THE LOCK
	 SKIPA
	JRST [	NOSKED
		MOVEM Q2,SPTH(Q1) ;UPDATE NEW ACCESS
		RETSKP]		;SUCCESS
	MOVE T1,Q2
	TXZ T1,FILWB		;No writer still
	NOSKED
	RET
;   >	;IFN CFSCOD
   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<
	MOVEM 1,SPTH(Q1)	;UPDATE NEW ACCESS
	RETSKP			;AND SUCCESS
   >	;IFE CFSCOD
   >				;END REPEAT 0
	ENDBS.
;ROUTINE TO FREE ALL "UNSHARED" OFNS. CALLED WHEN OFN'S
;RUN OUT
;AN UNSHARED OFN MAY STILL BE A VALID PAGE TABLE FOR A FILE. IF THIS IS THE 
;CASE THEN THE OFN WILL HAVE A CORE ADDRESS AND THE CORE PAGE WILL BE LOCKED
;MUST BE CALLED NOSKED
;RETURNS:	+1 NONE FOUND. OFN'S STILL EXHAUSTED
;		+2 AT LEAST ONE FOUND AND FREED

;[7247]  CHKOFN will call FREOFC if it finds that OFNTIM is set to -1.
;[7247]  Currently, this does not happen but this is a useful routine 
;[7247]  to keep around.  This routine will uncache all cached OFNs.

FREOFC::MOVE T1,TODCLK		;[7247] Get now
	ADD T1,OFNGCI		;[7247] Add garbage collection interval
	MOVEM T1,OFNTIM		;[7247] And save it
	MOVEI T1,T1		;[7247] Flag forced free of cached OFNS only
	AOS GCFOFC		;[7247] Count this
	JRST FREOF3		;[7247] Join common code

;[7247] FREOFG is called by CHKOFN as part of a periodic collection system
;[7247] It will mark all cached OFNs for removal.  Any it finds already marked
;[7247] will be uncached.  It only looks at cached OFNs.

FREOFG::MOVE T1,TODCLK		;[7247] Get now
	ADD T1,OFNGCI		;[7247] Add garbage collection interval
	MOVEM T1,OFNTIM		;[7247] And save it
	AOS GCFOFG		;[7247] Count this
	SETZ T1,  		;[7247] Flag garbage collection run
	JRST FREOF3		;[7247] Join common code
;[7247]  FREOFN is called by ASNOFN when an attempt to allocate a new 
;[7247]  OFN fails.  All unused OFNs are removed in an attempt to make 
;[7247]  lower NOFN and stock the free OFN list.  This routine looks at
;[7247]  cached OFNs.  Unshared, non-cached OFNs need not be considered
;[7247]  since this condition is not possible (see below).

FREOFN:	SETO T1,		;[7247] No garbage here
	AOS GCFOFN		;[7247] Count this
FREOF3:	SAVEQ			;[7247] Save Q regs (Q3 is FX here)
	SETZM Q1		;[7247] Init count of OFNS freed
	MOVE FX,T1		;[7247] Remember entry flag
	MOVSI Q2,-NOFN       	;[7247] Make AOBJN ptr
FREOF1:	SKIPN SPTH(Q2)		;[7247] Is this one in use?
	JRST FREOF2		;[7247] No so skip it
       	HRRZ T1,Q2		;[7247] Get the OFN
	CALL GETSHR		;[7247] (T1/T1)See if shared
	JUMPN T1,FREOF2		;[7247] If so, skip it
       	HRRZ T1,Q2		;[7247] Get the OFN again
	IFGE. FX		;[7247] If garbage collecting
	   TMNN OFNCSH,(T1)	;[7247] Cached?
	   JRST FREOF2		;[7247] No.
	   JUMPG FX,FREOF4	;[7247] If forced free, free this cached OFN
	   MOVX T2,OFNLAC	;[7247] Did we lose access to this cached OFN?
	   TDNE T2,SPTH(T1)	;[7247] 
	   JRST FREOF4		;[7247] Yes, free it now
	   MOVX T2,OFNMGB	;[7247] Get garbage bit
	   XORB T2,SPTO2(T1)	;[7247] Set bit or query state
	   TXNE T2,OFNMGB	;[7247] Was it set already?
	   JRST FREOF2		;[7247] No, get it next time
	ENDIF.			;[7247] 
FREOF4:	TMNN OFNCSH,(T1)	;[7247] Cached?
	IFSKP.			;[7247] 
	  CALL OC.UNC		;[7247] Uncache this OFN
	   SKIPA		;[7247] Could not uncache because locked
	  AOS Q1		;[7247] Freed one
;	  JRST FREOF2		;[7247] 
	ENDIF.			;[7247] 
   REPEAT 0,<			;[7247] Code from pre-caching days

;[7247] The following code is no longer needed since, if the share count has
;[7247] gone to zero, the OFN should be cached.  So, if the OFN is not cached,
;[7247] it is automatically not eligible for removal.

	CALL GETSHR		;SEE IF SHARED
	JUMPN T1,FREOF2		;IF SO, JUMP OFF
	HLRZ T1,Q2		;GET CURRENT OFN AGAIN
	LOAD T1,STGADR,SPT(T1)	;GET STORAGE ADDRESS
	MOVX T2,-PLKV		;GET LOCK MASK
	TXNN T1,NCORTM		;IN CORE NOW?
	TDNN T2,@CST1X+T1	;YES. LOCKED IN CORE?
	SKIPA			;NOT IN CORE OR NOT LOCKED. COLLECT IT
	JRST FREOF2		;LOCKED IN CORE. LEAVE IT
	HLRZ T1,Q2		;NOT SHARED OR LOCKED. GET CURRENT OFN
	CALL CLROFN		;COLLECT IT
	AOS Q1			;FOUND ONE
	JRST FREOF2		;AND LOOP FOR REST OF CHAIN

   >				;[7247] End of REPEAT 0

FREOF2:	AOBJN Q2,FREOF1		;[7247] Do all OFNS
	HRRZS Q1		;[7247] Get count only
	JUMPE Q1,R		;IF NONE FOUND. +1
	RETSKP			;IF SOME FOUND. +2
;CHECK OFN -- SEE IF FILE IN USE BUT DO NOT OPEN
; A/ DISK ADR OF XB (SAME AS ASOFN)
; B/ STRUCTURE NUMBER
;	CALL CHKOFN
; RETURN +1, FILE ALREADY OPEN
; RETURN +2, FILE NOT OPEN or OFN IS CACHED

CHKOFN::SAVEQ
	LOCK DIRCLK
	CALL DIRCFL		;FLUSH DIRECTORY CACHE
	MOVE FX,B		;SAVE STRUCTURE NUMBER
	LOAD Q1,STGADR,1	;SETUP XB ADR
	CALL OFNSRC		;SEARCH FOR IT
	IFNSK.			;If not
;   IFN CFSCOD,<
CHKOF1:	 TXO Q1,THAWB		;[7441] Request "exclusive" access
	 MOVE T1,FX		;Structure number
	 MOVE T2,Q1		;XB address
	 CALL GETCF0
	 IFSKP.			;[7387] No other system objected
	  MOVE T1,FX		;str #
	  MOVE T2,Q1		;XB address
	  CALL FRECF0		;Free it
;   >	;IFN CFSCOD
	  UNLOCK DIRCLK
	  RETSKP		;NOT FOUND
	 ENDIF.			;[7387]
	 UNLOCK DIRCLK		;[7387] Held on another system ...
	 RET			;[7387] ... unlock dir cache and fail
	ENDIF.
	MOVE Q1,SPTO2(T1)	;[7247] Get various flags for this OFN
	TXNN Q1,OFNCSH		;[7441][7247] Is this OFN cached?
	IFSKP.			;[7441] Yes, so check other systems
	  LOAD Q1,STGADR,SPTH(T1)  ;[7441] Setup XB address
	  JRST CHKOF1		;[7441] Now ask the other systems
	ENDIF.			;[7441]
	UNLOCK DIRCLK		;[7441] Unlock dir cache
	RET			;[7441] File is legitimately open; say so
;LOCAL ROUTINE TO SEARCH SPTH FOR GIVEN XB ADR
; Q1/ DISK ADR
; FX/ STRUCTURE NUMBER
;	CALL OFNSRC
; RETURN +1, NOT FOUND; 1/ HASH TABLE INDEX FOR INSERT
; RETURN +2, FOUND; 1/ OFN

OFNSRC:	MOVE T1,Q1		;GET STG ADDR
	IDIVI T1,OFNHSD		;HASH IT
	MOVE T3,T2
	MOVE T1,T2		;READY TO FAIL (RETURN INDEX TO TABLE)
	LOAD T3,OFNHS,(T3)	;GET FIRST OFN
OFNSR1:	JUMPE T3,R		;NO MORE
	LOAD T2,STGADR,SPTH(T3)	;GET ADR
	JUMPE T2,OFNSRE		;ERROR!
	CAME T2,Q1		;YES. IS DISK ADDRESS THE SAME?
	JRST OFNSR2		;NO
	LOAD T4,STRX,(T3)	;YES, GET THIS ENTRY'S STRUCTURE NUMBER
	CAIN T4,0(FX)		;SAME AS REQUESTED?
	JRST [	MOVX T2,OFNDMO	;GET DISMOUNTED BIT
		TDNE T2,SPTH(T3) ;IS THIS A DISMOUNTED OFN?
		JRST OFNSR2	;YES, DON'T USE IT
		MOVE T1,T3	;RETURN IN PROPER PLACE
		RETSKP]		;YES, DONE
OFNSR2:	LOAD T3,OFNNXT,(T3)
	JRST OFNSR1

OFNSRE:	 BUG.(HLT,OFNBDB,PAGUTL,SOFT,<OFN bad data base>,,<

Cause:	There are multiple causes of this BUGHLT. They all indicate some
	error in the monitors internal OFN data. The cause of the BUGHLT
	can be found by examining the dump.
>)
;LOCAL ROUTINE TO DELETE OFN SLOT
; T1/ OFN
;	CALL DASOFN
; RETURN +1 ALWAYS

DASOFN::
	NOSKED			;[7247] Be NOSKED during deassignment
;   IFN CFSCOD,<		;For CFS only
	MOVE T2,SPTH(T1)	;Get the flags
	TXNE T2,SPTLKB		;Now locked?
	ECSKED			;yes. unlock it then
   IFN DEBUG,<
	TXNN T2,OFNDMO		;Now mounted?
	CALL CFSCON		;Yes, if debugging, check out the token
   >	;IFN DEBUG
;   >	;IFN CFSCOD
	CALL CFSUNC		;[7247] Uncache CFS tokens
	MOVSI T2,(NCORTM)	;[7356]GET MASK
	TDNE T2,SPT(T1)		;[7356]IS THIS PT IS CORE?
	IFSKP.			;[7356]YES
	 HRRZ T2,SPT(T1)	;[7356]GET CORE ADDRESS
	 MOVSI CX,(-PLKV-PLKV)	;[7356]LOCK COUNT SHOULD BE <= 1
	 TDNE CX,@CST1X+T2	;[7356]IS IT?
	 BUG.(HLT,OFNBLC,PAGUTL,SOFT,<OFN has bad lock count>,,<

Cause:	DASOFN was called to delete an OFN slot but the page table's lock
	count in CST1 is greater than one. This likely indicates that some
	of this OFN's pages have not yet been written to disk.

Action:	Look at the caller to DASOFN. This routine should either call
	SCNOFN to write the pages to disk or should not be calling DASOFN
	at all.
>)				;[7356]NO.
	ENDIF.			;[7356]
	SETZM SPTH(T1)		;FLUSH GIVEN ENTRY
	CALL DASALC		;CLEAR ALLOC DATA
	SETZRO OFNSHC,(T1)	;CLEAR SHARE COUNT IN THE OFN
	SETOM SPTO4(T1)		;NOTE NOW UNASSIGNED
	SOS NOF			;NOTE ONE LESS OPEN FILE
	LOAD T2,OFNNXT,(T1)	;GET NEXT OFN
	LOAD T3,OFNPRV,(T1)	;AND PREVIOUS
	STOR T2,OFNNXT,(T3)	;LINK PREV TO NXT
	SKIPE T2		;IS THERE A NEXT
	STOR T3,OFNPRV,(T2)	;YES
	MOVEI T2,SPTO2(T1)	;GET HEAD OF FREE OFNS
	EXCH T2,OFNFRE		;AND REPLACE IT
	EXCH T2,@OFNFRE
	OKSKED
	RET
;ROUTINE TO CLEAR ALLOC DATA FROM OFN
;	T1/ OFN

DASALC::SAVEAC<T1>		;Preserve the OFN
	LOAD T2,ALOCX,(T1)	;GET INDEX TO ALLOCATION INFO
	JUMPE T2,R		;IF NO TABLE, RETURN
	SETZM OFNLEN(T1)	;ZERO LENGTH INFO
	SETZRO ALOCX,(T1)	;ZERO IT
	DECR ODIRC,(T2)		;DECREMENT OFN COUNT
	JN ODIRC,(T2),R		;OK IF STILL OPEN OFN'S
	SETZRO ALCWD,(T2)	;CLEAR SLOT IF COUNT =0
   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<
	SETZRO PGLFT,(T2)	; ...
	RET
   >	;IFE CFSCOD
   >				;END REPEAT 0
;   IFN CFSCOD,<
	LOAD T1,PGPTR,(T2)	;Get pointer
	SETZRO PGPTR,(T2)
	MOVEI T3,.CFAUP		;Remove it
	SETZM T2
	CALL CFSDAU		;Do it
	 NOP
	RET
;[7.1055]
;INVDIR - Routine to invalidate all cached OFNs associated with 
;a specific entry in ALOC2. This is called when a directory is
;being deleted. It uncaches these OFNs so that they will not
;somehow reattempt to use the no longer valid entry in ALOC2.
;
; Called with:
;	T1/ Directory number
;	CALL INVDIR
;
; Returns:
;	+1 - Error, a live OFN is still using the entry in ALOC2
;	     The action here is to not allow the directory to be
;	     deleted.
;	+2 - All cached OFNs are now uncached that refered to this
;	     ALOC2 entry. Directory can now be deleted.
;
; Preserves all ACs

INVDIR::SAVET			;Save the temps
	SAVEQ			;[7.1066] Also save quasi's that we use
	MOVE T2,T1		;We want dir number in this one
	LOAD T1,CURSTR		;Put structure number here
	MOVEI T3,.CFAGT		;Tell CFS to get the resource block
	SETOM T4
	CALL CFSDAU		;(T1,T2,T3,T4/T2) Do the work
	 NOP			;Should not happen
	MOVE Q2,T2		;[7.1066] Save address of resource block
	MOVSI Q1,-NOFN		;[7.1066] Make AOBJN counter
INVDR1:	HRRZ T1,Q1		;[7.1066] T1 will be our indexer
	LOAD T3,ALOCX,(T1)	;Get allocation index for this OFN
	JUMPE T3,INVDR2		;If none, skip this OFN
	CAMN Q2,ALOC2(T3)	;[7.1066] Is this OFN using this block?
	JRST INVDR3		;Yes it is
INVDR2:	AOBJN Q1,INVDR1		;[7.1066] No, get next OFN
	RETSKP			;All OFNs done no delete the directory
;Here when an OFN is using the block
INVDR3:	TMNN OFNCSH,(T1)	;Is this OFN cached?
	JRST INVDR4		;OFN not cached...
	NOSKED			;OFN is cached, we must uncache it
	CALL OC.UNC		;(T1/) Uncache the OFN
	 NOP			;Will BUGHLT instead of fail
	OKSKED			;OC.UNC needed us to be NOSKED
	JRST INVDR2		;Do next OFN

;Here when an OFN is using the block and is not cached
;Nota biggie - At this point, an OFN may not be in use BUT it may not
;be cached at either. This is a very miniscule chance that an OFN could
;be in the process of getting cached and it could refer to the ALOC2
;entry that we are now getting rid of. While this is unlikely, it is
;bad nonetheless.
INVDR4:	HLRZ T1,SPTO2(T1)	;Get count of opens
	SKIPN T1		;If no one using this OFN,
	JRST INVDR2		;then go onto the next one
	RET			;Else, don't let the directory be deleted
;Routine to remove an allocation entry. Used when the directory is deleted.
;	T1/ Structure number
;	T2/ dir number

REMALC::MOVEI T3,.CFAGT		;Get it here
	SETOM T4
	CALL CFSDAU		;Do it
	 NOP
	MOVE T1,T2		;Copy it
	SETZM T2
	MOVEI T3,.CFARM		;remove it
	CALL CFSDAU
	 NOP
	RET			;And done
;   >	;IFN CFSCOD
;LOCK/UNLOCK OFN
;LOCKING OFN PREVENTS ANY CHANGE TO IT, E.G. ADDING OR DELETING PAGES

;LOCK OFN
; A/ OFN
;	CALL LCKOFN
; RETURN +1 ALWAYS, BLOCK AND WAIT IF ALREADY LOCKED

LCKOFN::TDZA T2,T2		;[7247] Entry type shared
LCKOFA::MOVEI T2,1
;   IFN CFSCOD,<
	PUSH P,T1		;Save the OFN
	CSKED
	TMNN OFNDMO,SPTH(T1)	;If dismounted, don't bother with this
	CALL CFSAWP		;GET IT
	POP P,T1		;Restore the OFN
;   >	;IFN CFSCOD
	CALLRET LCKOFO		;Lock it locally

;Routine to lock SPTLKB only

LCKOFO:				;[7.1036]
     DO.
	NOSKED
	MOVX T2,SPTLKB
	TDNE T2,SPTH(T1)	;NOW LOCKED?
	IFSKP.			;IF SO
 	 IORM T2,SPTH(T1) 	;NO. SET IT
   IFN SPTDSW,<			;[7.1036] Only if debugging SPTLKB problems
	 CALL SPTRC2		;[7.1036] (T1/)Record who called to lock SPTLKB
   >				;[7.1036] End of IFN SPTDSW
	 NOINT			;BE NOINT
	 OKSKED			;NOW CAN BE OKSKED AGAIN
	 RET			;AND DONE
	ENDIF.
	CALL WTOFNS		;WAIT FOR IT TO UNLOCK
	HLRZS T1		;GET BACK OFN
     LOOP.
     ENDDO.
;ROUTINE TO DO OKSKED AND DISMISS FOR OFN LOCK
; A/ OFN,,
;	CALL WTOFNL
; RETURN +1 ALWAYS

WTOFNS::MOVSS T1
WTOFNL:	OKSKED
	HRRI T1,OFNLKT		;WAIT TEST
	MDISMS			;WAIT FOR IT
	RET			;DONE

;SCHED test for OFN locked

OFNLKT:	MOVX T2,SPTLKB		;THE LOCK
	TDNE T2,SPTH(T1)	;STILL LOCKED?
	JRST 0(4)		;YEP
	JRST 1(4)		;NOPE
;UNLOCK OFN
; A/ OFN
;	CALL ULKOFN
; RETURN +1 ALWAYS

ULKOFN::MOVX T2,SPTLKB		;THE BIT
	ANDCAM T2,SPTH(T1)	;CLEAR IT
;   IFN CFSCOD,<
	SAVEAC <T1>
	TMNN OFNDMO,SPTH(T1)	;If dismounted, don't bother
	CALL CFSFWT		;FREE IT UP
	ECSKED
;   >	;IFN CFSCOD
	OKINT
	RET

IFN SPTDSW,<			;ONLY IF DEBUGING SPTLKB PROBLEMS

SPTRAC::			;[7.1036] TRACE WHO LOCKED SPTLKB
	PUSH P,T2		;SAVE AC T2
	HRR T2,-1(P)		;GET OUR CALLING PC
SPTRC3:
	HRL T2,FORKX		;GET OUR FORK INDEX
	MOVEM T2,SPTO3(T1)	;SAVE FORKX,,PC
	POP P,T2		;GET T2 BACK
	RET			;AND RETURN TO CALLER

SPTRC2:				;TRACE WHO CALLED ROUTINE TO LOCK SPTLKB
	PUSH P,T2		;SAVE T2
	HRR T2,-2(P)		;GET CALLERS CALLERS PC
	JRST SPTRC3		;JOIN COMMON CODE

SPTRC7:	PUSH P,T2		;[7.1036] Save T2
	HRR T2,-7(P)		;[7.1036] Get caller to LCKOFI
	JRST SPTRC3		;[7.1036] Join common code

 >				;END OF IFN SPTDSW
;LOCK/UNLOCK FOR CONVENIENCE WHERE PAGE ID IN A

;LOCK OFN

LCKOFI::SAVET
	HLRZ A,A		;GET OFN
   IFN DEBUG,<
	JUMPE T1,OF0HLT		;OFN 0 was pass in
>				;End of IFN DEBUG
	CAIGE A,NOFN		;REALLY AN OFN?
	CALL LCKOFA		;YES, LOCK IT
   IFN SPTDSW,<			;[7.1036] Only if debugging SPTLKB problems
	CAIGE T1,NOFN		;[7.1036] Is this an OFN?
	CALL SPTRC7		;[7.1036] (T1/)Yes, record who locked SPTLKB
   >				;[7.1036] End of IFN SPTDSW
	RET

;UNLOCK

ULKOFI::SAVET
	HLRZ A,A		;GET OFN
   IFN DEBUG,<
	JUMPE T1,OF0HLT		;OFN 0 was pass in
>				;End of IFN DEBUG
	CAIGE A,NOFN		;REALLY AN OFN?
	CALL ULKOFN		;YES, UNLOCK IT
	RET
;RELEASE/DELETE OFN
; A/ FILWB+FILUB,,OFN
;	CALL RELOFN/DELPT
; RETURN +1 ALWAYS, A/ PAGE COUNT IN XB IF FILE COMPLETELY CLOSED,
;		       -1 IF FILE NOT COMPLETELY CLOSED.
;[7.1062]           B/ SPTH if RELOFN called and OFN is not marked dismounted

DELOF==1B0			;LOCAL FLAG IN Q1 FOR DELETE/RELEASE

DELPT::	SAVEPQ
	MOVX Q1,DELOF		;SAY DELETE
	JRST RELOF0

RELOFN::SAVEQ
	MOVEI Q1,0		;SAY RELEASE
RELOF0:	TRVAR <OFNX,XBX,ACCB,<SVACS,2>>
	HLLZM T1,ACCB		;SAVE ACCESS BITS
	HRRZ T1,T1		;OFN ONLY
	MOVEM T1,OFNX		;SAVE IT
	TXNE Q1,DELOF       	;[7441] Want DELETE?
	IFSKP.			;[7441] No, this is a release of an OFN
	  CALL LCKOFN		;[7441] Interlock the OFN shared
	ELSE.			;[7441] This is an OFN DELETE
	  CALL LCKOFA		;[7441] Interlock the OFN exclusively
	ENDIF.			;[7441] 
	MOVE 2,1		;MOVE OFN
	CALL GETSHR		;GET OFN SHARE COUNT
	EXCH 1,2		;COUNT TO 2 AND OFN TO 1
	SOJG 2,RELOF6		;IF NOT LAST, JUMP OFF
	NOSKED
	MOVX 2,OFNDMO		;CHECK IF DISMOUNTED
	TDNE 2,SPTH(1)		;IS IT?
	JRST [	CALL DASOFN	;YES. DEASSIGN THE OFN
		OKSKED		;ALLOW SCHEDULING AGAIN
		OKINT		;ALLOW INTS AGAIN
		RET]		;AND DONE
;********************************************
	MOVEI 3,0(1)
	CALL LCKXB1		;[7247] Map and lock index block
	TXNN Q1,DELOF       	;[7247] Want DELETE?
	JRST RELOF7		;[7247] No
	MOVE T1,OFNX		;[7247] Yes, get OFN back
	CALL SCNOFN		;[7247] Move all of the pages to disk
	 JRST [	EXCH T1,OFNX	;[7247] Save count. Get OFN
	       	CALL ULKOFN	;[7247] Unlock the OFN
		MOVE T1,OFNX	;[7247] Restore count
		JRST RELOF4]	;[7247] And give up.
	SKIPN Q2,T1		;[7247] Any pages found?
	JRST RELOF7		;[7247] No pages found, go on
	MOVEM Q2,XBX		;YES. SAVE COUNT OF PAGES
   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<			;If not CFS
	MOVE 2,OFNX		;GET OFN
	LOAD 3,ALOCX,(2)	;GET INDEX
	OPSTRM <ADDM Q2,>,PGLFT,(3) ;UPDATE COUNT OF PAGES
   >	;IFE CFSCOD
   >				;END REPEAT 0
;   IFN CFSCOD,<			;If CFS
	MOVE T1,OFNX		;Get the OFN
	CALL QCHKH		;Get the allocation
	 MOVE T1,T2		;Copy
	ADD T1,Q2		;New allocation
	MOVE T2,T1		;Copy it
	MOVE T1,OFNX		;The OFN
	CALL QSET		;Set and release lock
	MOVE T2,OFNX
;   >	;IFN CFSCOD
	MOVE 2,SPTH(2)
	TXNN 2,OFNBAT		; A BAD OFN?
	JRST OFNDLN		;NO. DO A FAST DELETE THEN
	JRST DELBAD		;YES, GO DELETE BAD OFN
RELOF7:	TXNE Q1,DELOF		;[7247] Deleting?
	IFSKP.			;[7247] No.
	   MOVE T1,OFNX		;[7247] 
	   CALL OC.CSL		;[7247] (T1/T1) Cache OFN/Free open tokens
	   MOVEM T1,Q2   	;[7247] Save the number of pages cached
	   MOVE T1,OFNX		;[7247] Get OFN back

;[7400]  At this point, an attempt has been made to cache the OFN. 
;[7400]  If the number of pages cached is greater than or equal to zero,  
;[7400]  then the cache succeeded and the OFN can be considered released.
;[7400]  But, if the number of pages cached is -1, then that means the
;[7400]  page table was bad and SCNOFK could not update it to disk.  The 
;[7400]  OFN share count remains 1, the core page for the PT will remain 
;[7400]  locked in core, the OFN will be unlocked, and -1 will be returned  
;[7400]  as the number of pages released.  Note that the core page was locked
;[7400]  by the preceeding call to LCKXB1.

	   SKIPGE Q2		;[7400] Did cache succeed?
	   IFSKP.		;[7400] Yes, so update the counts now
	     CALL DWNSHR	;[7400][7247] (T1/) Discount last sharer
	     LOAD T3,STGADR,SPT(T1)  ;[7400][7247] Get (CORE) address of XB
	     CALL ULKP3		;[7400][7247] (T3/)Unlock XB page
	   ENDIF.		;[7400] 
	   CALL ULKOFN		;[7247] (T1/)Unlock OFN
	   MOVE T2,SPTH(T1)	;[7.1062] Get SPTH for return
	   MOVE T1,Q2   	;[7247] Get page count to return
	   JRST RELOF4		;[7247] And done
	ENDIF.			;[7247] 
;[7247]  This OFN is being deleted

	MOVE 1,OFNX		;RECOVER OFN
	OKSKED
	CALL DSKUGT		;Free any cached disk pages
	NOSKED
	CALL DWNSHR		;DECREMENT SHARE COUNT
;   IFN CFSCOD,<
	CALL FRECFS		;Free CFS locks
	MOVE T1,OFNX		;Refetch OFN
;   >	;IFN CFSCOD
	MOVE 3,SPTH(1)		;SAVE FLAGS
	MOVEM 3,XBX		;SAVE FLAGS
	LOAD C,STRX,(1)		;GET STRUCTURE NUMBER
	MOVEM C,OFNX		;SAVE IT FOR LATER
	CALL DASOFN		;RELEASE SPT SLOT
	LOAD 1,STGADR,SPT(1)	;GET (CORE) ADDRESS OF XB
	HRRZ T3,T1		;GET INDEX BITS ONLY
	CALL ULKP3		;UNLOCK XB
	OKINT			;MATCH NOINT DONE BY LCKOFN
	CALL REMFP1		;FLUSH CORE AND DRUM ADDRESSES
	SKIPN 1
	BUG.(HLT,NOADXB,PAGUTL,SOFT,<RELOFN - No disk address for XB>,,<

Cause:	A routine has been called to release an OFN. The OFN is the
	identifier for the index block of a file that is being closed.
	This routine forces the index block into memory. The backup
	address for the index block should be on the disk. The BUGHLT
	indicates that the backup address is not on the disk.
>)
	MOVE 2,XBX		;RESTORE FLAGS
	MOVE C,OFNX		;GET STRUCTURE NUMBER
	OKSKED			;[7247] 
	CALL DEDSKC		;[7247] Delete disk adr of XB
	NOSKED			;[7247] 
	MOVE 1,Q2		;RETURN PAGE COUNT
RELOF4:	CALL RELCXB		;RELEASE TEMP MAPPING
	OKSKED
	RET
;THIS ROUTINE IS GOTTEN TO WHEN THE CALLER WANTS TO DELETE THE
;OFN AND IT DOES NOT CONTAIN A BAT BLOCK.

OFNDLN:	MOVSI Q2,-PGSIZ		;SCAN WHOLE XB
OFNDL1:	SKIPN CXBPGA(Q2)	;AN ENTRY HERE?
	JRST OFNDL2		;NO
	LOAD 1,STGADR,CXBPGA(Q2) ;GET DISK ADDRESS
	MOVE B,OFNX		;GET OFN
	LOAD B,STRX,(B)		;GET STRUCTURE NUMBER
	OKSKED
	CALL DEDSK		;RELEASE THE PAGE
	NOSKED
	SETZM CXBPGA(Q2)	;CLEAN UP
OFNDL2:	AOBJN Q2,OFNDL1		;DO WHOLE XB
	JRST RELOF7		;NOW GO DO XB ITSELF
;RETURN WHEN FILE NOT CLOSED BECAUSE SHARE COUNT NOT 0

RELOF6:	CALL DWNSHR		;DECREMENT SHARE COUNT
	TMNE FILUB,ACCB		;CLOSING AN UNRESTRICTED ACCESS?
	JRST RELOF2		;[7283] Yes, no change
	DECR OFOPC,(T1)		;COUNT REGULAR OPENS
	MOVE 2,SPTH(1)		;GET CURRENT BITS
;   IFN CFSCOD,<		;[7283]
	CALL SKPOPR    		;[7283] (T1/)Any "real" opens left?
	IFNSK.			;[7283] No, only OF%RDU openers
	  CALL CFSURA		;[7283] (T1/)Convert lock
	  TXO T2,FILUB		;[7283] Reflect current opening state
	ELSE.			;[7283] Yes
	  TXZ T2,FILUB		;[7283] Reflect current opening state
	ENDIF.			;[7283] 
;   >	;IFN CFSCOD		;[7283] 
	TXNN 2,OFNDMO		;DISMOUNTED?
	TLNE 2,(THAWB)		;OPEN IN RESTRICTED OR THAWED MODE?
	JRST RELOF1		;YES, NO UPDATE OF BITS NEEDED
	TMNE FILWB,ACCB		;NO, IS THIS THE WRITER?
	IFNSK.			;IF SO
	 TLZ T2,(FILWB)		;NO MORE WIRTER AFTER THIS
;   IFN CFSCOD,<
	 DMOVEM T1,SVACS	;Save these ACs
	 ANDX T2,STGADR		;Get XB address only
	 LOAD T1,STRX,(T1)	;Get structure number
	 CALL CFSFWL		;Undo the write lock
	 DMOVE T1,SVACS
;   >	;IFN CFSCOD
	ENDIF.
RELOF1:	MOVEM T2,SPTH(1)	;[7283] Update bits
RELOF2:	CALL ULKOFN		;[7283] (T1/)Unlock OFN
	SETO 1,			;RETURN -1 FOR COUNT
	RET
;CLEAR OFN FOUND WHEN SWAPPING OUT PAGE
; A/ OFN
;[7247] 
;[7247] 
;[7247] Note: This routine should no longer be needed since any OFN with
;[7247] a zero share count should be cached.  

CLROFN::STKVAR <SVACS>
	TMNE OFNCSH,(T1)	;[7247] Cached?
	BUG.(CHK,CSHCLR,PAGUTL,HARD,<CLROFN - CACHED OFN FOUND AT CLROFN>,,<

Cause:	The monitor is removing an OFN by calling CLROFN. It is found that 
	the OFN is "cached". CLROFN calls FRECFS and this is incorrect for
	cached OFNs since FRECFS has already been called. This BUG is for
	debugging and the OFN deassignment does not proceed.
>,R)				;[7247] 
;   IFN CFSCOD,<
	MOVEM T1,SVACS
	CALL FRECFS		;Release the resources
	MOVE T1,SVACS
;   >	;IFN CFSCOD
CLROF1:	CALL DASOFN		;[7247] Release OFN slot
	LOAD 1,STGADR,SPT(1)	;GET CORE ADR
	CALLRET REMFP1		;RELEASE STORAGE
	ENDSV.
;ROUTINE TO SCAN AN XB AND MOVE ALL OF ITS PAGES TO DISK.
;CALLED WITH T1/ THE OFN
;AND THE XB MAPPED INTO CXBPGA
;[7400] Returns:	+1: OFN has bad PT entry; T1/ -1
;[7400]  		+2: Success; T1/ Count of pages updated to disk

;[7247] SCNOFK - Just like SCNOFN but keeps pages

SCNOFK:	TXO T1,1B0		;[7247] Remember this
SCNOFN::ACVAR <W1,W2,W3>	;GET SOME WORK REGS
	MOVE W3,T1		;SAVE THE OFN
	MOVSI W1,-PGSIZ		;SCAN XB
	SETZ W2,		;INIT COUNT OF IN-USE PAGES
SCNOF3:	MOVE 2,CXBPGA(W1)	;GET PTR
	JUMPE 2,SCNOF2		;JUMP IF EMPTY
	LOAD T1,PTRCOD,T2	;GET PTR TYPE
	CAIE T1,IMMCOD		;PRIVATE?
	JRST RLBAD		;NO, LOSSAGE
	TXNE 2,DSKAB		;ON DSK?
 	JRST SCNOF5		;YES
	TXNE 2,NCORTM		;IN CORE?
	JRST [	TXNE 2,DRMAB	;[7247] No, private unassigned?
		JRST .+1	;NO. MUST MOVE IT TO DISK THEN
		SETZM CXBPGA(W1) ;FLUSH UNASSIGNED PTR
		JRST SCNOF2]
	MOVE 4,W1		;SET UP ARGUMENT FOR CALL
	HRL 4,W3		;PROVIDE THE OFN AS WELL
	CALL MOVDSK		;MOVE THE PAGE TO DISK
SCNOF4:	MOVE T1,CXBPGA(W1)	;GET PRESENT ADDRESS
	TXNE T1,NCORTM		;STILL IN CORE?
	JRST SCNOF3		;NO
	LOAD T1,STGADR,T1	;GET JUST PAGE NUMBER IN T1
	CALL SKPNWR		;WAIT FOR WRITE TO COMPLETE
	 JRST SCNOF4		;RECHECK
	HRRZ T2,T1		;GET INDEX BITS ONLY
	LOAD T2,CSTAGE,+T2	;CHECK STATUS
	CAIE T2,PSRPQ		;ON RPLQ?
	CALL OFRQ		;NO, PUT IT ON
	SKIPGE W3		;[7247] Keeping?
	JRST SCNOF5		;[7247] Yes, count and continue
	CALL RPCST		;[7247] Not keeping so force disk adr back to XB
	JRST SCNOF3		;[7247] And look at ptr again, should be dsk adr

SCNOF5:
   REPEAT 0,<			;This is needed if doing preallocation
	TXNN T2,DSKNB		;Don't count new pages
   >	;REPEAT 0
	AOS W2			;COUNT THE PAGE
SCNOF2:	AOBJN W1,SCNOF3		;SCAN XB
	MOVE T1,W2		;RETURN COUNT OF PAGES FOUND
	RETSKP			;AND DONE
;BAD PAGE FOUND IN OFN

RLBAD:	BUG.(CHK,ILIBPT,PAGUTL,HARD,<Bad pointer type in index block>,,<

Cause:	SCNOFN was called to scan an index block and move all its pages to
	disk but the index block contains a pointer that is not an
	immediate pointer.

>,,<DB%NND>)			;[7.1210] 
	SETO 1,			;SAY FILE NOT CLOSED
	RET			;RETURN BAD


	ENDAV.			;END ACVAR
;HERE TO DELETE A FILE (OFN) WHICH HAS ONE OR MORE BAT PAGES IN IT

DELBAD:	OKSKED			;ALLOW SCHEDULING FOR A WHILE
	NOINT			;BUT PREVENT LOCAL INTERRUPTS
	MOVEI 1,FPG3A		;YES. LOCK DOWN A PAGE
	CALL MLKMA		;GET IT
	LSH 1,PGSFT		;MAKE IT A CORE ADDRESS
	MOVE P3,1		;AND SAVE IT
OFNFIN:	SETZ P5,		;NO ERROR HERE
	MOVSI P1,-PGSIZ		;SIZE OF XB
	SETO P2,		;NO DRIVE FOUND YET
	NOSKED			;PROTECT XB SCANNING
TOPOFN:	LOAD 1,STGADR,CXBPGA(P1) ;GET ENTRY
	JUMPE 1,NOPGH		; ANYTHING HERE?
	TXZ 1,DSKAB		;CLEAR DEVICE TYPE
	MOVE B,OFNX		;GET OFN
	LOAD D,STRX,(B)		;GET STRUCTURE NUMBER
	MOVE B,STRTAB(D)	;GET SDB INDEX
	IDIV A,SDBSIZ(B)	;COMPUTE UNIT NUMBER AND LOCAL ADDRESS
	MOVE P4,2		;SAVE DISK ADDRESS
	SKIPL P2		;HAVE A DRIVE YET?
	JRST HAVBAT		;YES. GO LOOK AT IT
	OKSKED			;ALLOW INTS FOR BAT BLOCK LOGIC
	MOVE P2,1		;ESTABLISH THIS DRIVE
	MOVE B,P3		;CORE ADDRESS
	MOVEI C,FPG3A		;VIRTUAL ADDRESS
	CALL RDBAT		;GO READ THE BAT BLOCKS
	 JRST BUMBAT		;NO THERE
	MOVE B,P4		;RESTORE LOCAL DISK ADDRESS
	NOSKED			;PROTECT THE SCANNING
	JRST YESBAT
;HAVE BAT BLOCKS IN FOR THIS UNIT. NOW GO DO COMPARE

HAVBAT:	CAIE A,0(P2)		;IS THIS THE PROPER UNIT?
	JRST NOPGH		;NO
YESBAT:	JUMPN P5,NOTBD1		;IS OK.
	MOVE A,B		;GET LOCAL ADDRESS
	MOVEI B,FPG3A		;WHERE THE BAT BLOCK IS
	MOVE C,OFNX		;GET OFN
	LOAD C,STRX,(C)		;GET STRUCTURE NUMBER
	MOVE C,STRTAB(C)	;GET SDB ENTRY
	LOAD C,STRUDB,(C)	;GET A UDB ADDRESS FOR ONE OF THIS TYPE
	CALL SEEADR		;SEE IF THIS IS THERE
	 JRST NOTBD1		;NO
	JRST BADD		;YES.

NOTBD1:	LOAD 1,STGADR,CXBPGA(P1) ;GET DISK ADDRESS
	MOVE B,OFNX		;GET OFN
	LOAD B,STRX,(B)		;GET STRUCTURE NUMBER
	OKSKED
	CALL DEDSK		;RELEASE PAGE
	NOSKED			;Be NOSKED again
BADD:	SETZM CXBPGA(P1)	;CLEAR SLOT
	SOSG XBX		;ALL DONE?
	JRST ALLDNE		;YES.
NOPGH:	AOBJN P1,TOPOFN		;GO DO REST
	OKSKED			;ALLOW SCHEDULING
	JRST OFNFIN		;AND DONE

BUMBAT:	MOVEI P5,1		;SAY NO BAT BLOCKS HERE
	NOSKED			;PREVENT SCHEDULING
	JRST NOTBD1		;GO FREE THE PAGE

;FINISHED THE SCAN OF THE BAD INDEX BLOCK. NOW RELEASE WORK
;PAGE AND PROCEED TO FREE THE INDEX BLOCK ITSELF.

ALLDNE:	OKSKED			;ALLOW SCHEDULING
	MOVE A,P3		;GET PHYSICAL ADDRESS
	LSH A,-PGSFT		;MAKE IT A PAGE NUMBER
	CALL MULKCR		;AND RELEASE IT
	OKINT			;PAGE IS RELEASED, ALLOW INTERRUPTS AGAIN
	NOSKED			;PROTECT THE XB RELEASE
	JRST RELOF7
;[7247]               OFN CACHE and UNCACHE routines
;[7247]
;[7247] Routine to "CACHE" an OFN
;[7247] Must be called NOSKED (once) and with CFS write token obtained (CFSAWP)
;[7247] T1/	OFN
;[7247] 
;[7247] Returns: +1 Always with T1/ Number of pages written by SCNOFK
;[7400] 		        T1/ -1 if SCNOFK failed - OFN not cached!

OC.CSL:	STKVAR <OFN,PGS,FFLG>	;[7247] 
	SETZM FFLG		;[7247] From RELOF7 - free open token(s) also
	JRST OC.CH1		;[7247] Continue at common code

OC.CSH::STKVAR <OFN,PGS,FFLG>	;[7247] 
	SETOM FFLG		;[7247] From RELP4 - do not free open token(s)
OC.CH1:	MOVEM T1,OFN		;[7247] Save OFN
	CSKED			;[7247] 
	CALL SCNOFK		;[7400][7247] (T1/T1)Update disk - pages in core
	IFNSK.			;[7400] Failed!  Bad page table entry.
	  BUG.(CHK,CSHSCF,PAGUTL,SOFT,<Unable to flush cached pages to disk>,,<

Cause:	An OFN is being cached so SCNOFK was called to write its pages to disk
	but not flush them from memory.  However, SCNOFK was not able to 
	write the OFN pages to disk.  This BUGCHK should have followed a
	ILIBPT BUGCHK since this is the only way that SCNOFK can fail.
>)				;[7400][7247] Could not cache the OFN
	  ECSKED		;[7400] Undo CSKED from above
	  SETO T1,		;[7400] Say file not closed
	  RET			;[7400] Return with T1 set to -1
	ENDIF.			;[7400] 
	OKSKED			;[7247] 
	MOVEM T1,PGS		;[7247] Save the page count
	MOVE T1,OFN		;[7247] 
	CALL DSKUGT		;[7247] Free cached disk pages
	CALL UPDOFI		;[7247] Put OFN on disk if needed
	NOSKED			;[7247] 
	MOVE T1,OFN		;[7247] Get OFN again
	SKIPE FFLG		;[7247] Should CFS open tokens be freed?
	IFSKP.			;[7247] Yes
	  CALL FRECFL		;[7247] (T1/)Free file open tokens only
	  MOVE T1,OFN		;[7247] Get OFN back
	ENDIF.			;[7247]
	CALL OC.CH2		;[7356](T1/)CLEAN UP THE STRUCTURES
	ECSKED			;[7247] 
	MOVE T1,PGS		;[7247] Get page count to return
	RET			;[7247] 
	ENDSV.			;[7247] 
;[7356] OC.CH2
;[7356]
;[7356] Called to set up the data structures needed make an OFN "cached"
;[7356]
;[7356] T1/ OFN
;[7356]
;[7356] Returns +1 always
;[7356]

OC.CH2:	SETZRO FILWB!THAWB!OFNDUD,SPTH(T1) ;[7356][7247] Clear these
	SETZRO OFOPC,(T1)	;[7356][7247] And this
	SETZM OFNLEN(T1)	;[7356][7247] And this too
	SETONE OFNCSH,(T1)	;[7356][7247] This baby is now cached
	AOS NOC			;[7356][7247] Count the number of cached OFNS
	RET			;[7356] Done
;[7247] Uncache OFN
;[7247] 
;[7247] Must be called NOSKED.
;[7247] Note: This routine calls SCNOFN without benifit of CFSAWP or
;[7247] any other CFS interlock - it assumes that the OFN is unused on local sys
;[7247] and "dumped" - that is no pages will be written to the disk ie no change
;[7247] to the file hence no need for CFS.
;[7247] 
;[7247] T1/	OFN
;[7247]
;[7247] Returns:	+1 - Failed because OFN is locked locally (SPTLKB)
;[7247]			+2 - Success; OFN is now uncached

OC.AUC: TDZA T2,T2		;[7247] Entering from ASNOFN
OC.UNC::SETO T2,		;[7.1067] Entering from FREOFN, MRKOFN or DSKREN
	SKIPN SPTH(T1)		;[7247] Is it still here?
	RET			;[7247] No, just return
	STKVAR <OFN>		;[7247] 
	MOVEM T1,OFN		;[7247] Save OFN
	JUMPE T2,OC.UN1		;[7247] Skip SPTLKB check if from ASNOFN
	MOVX T2,SPTLKB		;[7247] Lock bit
	TDNN T2,SPTH(T1)	;[7247] Locked locally?
	IFSKP.			;[7247] Yes, so skip it now
	  MOVX T2,OFNMGB	;[7247] Get garbage bit
	  IORM T2,SPTO2(T1)	;[7247] Set bit so that it will get collected next
	  RET        		;[7247] ... time since we could not this time
	ENDIF.			;[7247] 
	IORM T2,SPTH(T1)	;[7247] No. Lock it
   IFN SPTDSW,<			;[7.1036] Only if debugging SPTLKB problems
	CALL SPTRAC		;[7.1036] (T1/)Record who locked SPTLKB
   >				;[7.1036] End of IFN SPTDSW
OC.UN1:	CSKED			;[7247] Go CSKED because DASOFN will go ECSKED
	MOVE T3,OFN		;[7247] 
	CALL LCKXB1		;[7247] Lock and map XB
	MOVE T1,OFN		;[7247] 
	LOAD T2,STGADR,SPT(T1)	;[7247] Get core page
	TXNE T2,NCORTM		;[7247] In core now?
	BUG.(HLT,UCXBNC,PAGUTL,SOFT,<Uncaching OFN not in core>,,<

Cause:	An OFN is being uncached but the storage address is not a core
	address.  It should be since it is cached.
>)				;[7247] No!
	CALL SCNOFN		;[7247] (T1/T1)Call SCNOFN
	 JFCL			;[7247] Unused return
	MOVE T1,OFN		;[7247] 
	MOVX T2,OFNWRB		;[7247] See if modified
	TDNE T2,SPTH(T1)	;[7247] Was it?
	BUG.(HLT,UCHMOD,PAGUTL,SOFT,<OFN is modified while uncaching>,,<

Cause:	An OFN is being uncached but the system believes that it has been
	modified.  This is bad because there should be no users of this
	cached OFN.
>)				;[7247] Error - OFN has been modified!?
	CALL DASOFN		;[7247] (T1)Delete OFN and ALLOC entry go ECSKED
	MOVE T1,OFN		;[7247] 
	LOAD T1,STGADR,SPT(T1)	;[7247] Get core address of XB
	CALL ULKP1		;[7247] (T1)Unlock it
	CALL REMFP1		;[7247] (T1)Remove it
	CALL RELCXB		;[7247] Release temp mapping
	SOS NOC			;[7247] One less cached OFN
	RETSKP			;[7247] Return success
	ENDSV.			;[7247] 
;Routine to free all CFS resources when a file is closed.
;T1/	The ofn

;   IFN CFSCOD,<
FRECFD:	MOVEI T4,1		;[7247] Free CFS resources upon dismounting
	JRST FRECF1		;[7247] Continue at common code
FRECFL::TDZA T4,T4		;Preserve the write token
FRECFS:	SETOM T4		;Free the write token
FRECF1:	MOVE T2,SPTH(T1)	;[7247] Get access
	LOAD T1,STRX,(T1)	;Get structure number
	CALLRET FRECFX		;And enter the worker

;Worker routine for above.

FRECF0:	SETOM T4		;Free the write token
FRECFX:	SAVEQ
	DMOVE Q1,T1		;Save args
	ANDX T2,STGADR		;XB address only
	SKIPE T4		;[7247] Want to release the write token?
	IFNSK.			;[7247] Yes
	  SKIPL T4		;[7247] Should it be cached upon release?
	  IFSKP.		;[7247]
	    CALL CFSCWT		;[7247] Yes, undo and cache the write token
	  ELSE.			;[7247] 
	    CALL CFSUWT		;[7247] No, undo and destroy write token
	  ENDIF.		;[7247] 
	ENDIF.			;[7247] 
	TXNE Q2,OFN2XB		;A secondary index block?
	RET			;If so, done
	DMOVE T1,Q1
	ANDX T2,STGADR
	CALL CFSFFL		;FREE THE LOCK
	TXNN Q2,THAWB		;SHARED OPEN?
	TXNN Q2,FILWB		;A WRITER LEFT?
	RET
	DMOVE T1,Q1
	ANDX T2,STGADR
	CALLRET CFSFWL		;FREE THE WRITE LOCK AS WELL
;Routine to acquire necessary resources on "first" opening
;T1/	The OFN
;T2/	Allow DUD flag
;T4/	Honor OFN2XB if zero
;Returns:
;	+1 access conflict
;	+2 OK

GETCFL::TMNE OFN2XB,SPTH(T1)	;*** OFN2XB SET FOR THIS FILE?
	CALL OFNSRE		;*** YES!
	TLOA T4,-1		;Get a non-zero
GETCFS:	SETZM T4		;Honor the OFN2XB bit
	MOVE T3,T2		;Copy the flag
	MOVE T2,SPTH(T1)	;Get access and XB address
	LOAD T1,STRX,(T1)	;Get structure number
	JRST GETCFX		;Enter worker routine
;Worker routine for above

GETCF0:	SETZM T4		;Honor OFN2XB
	SETOM T3		;No DUD allow
GETCFX:	SAVEQ
	STKVAR <DUDFLG>
	MOVEM T3,DUDFLG		;Save DUD flag entry value
	DMOVE Q1,T1		;Save args
	SKIPN T4		;Honor OFN2XB?
	TXNN Q2,OFN2XB		;Secondary index block?
	IFSKP. <JRST RSKP>	;If secomdary, done
	TXNN Q2,THAWB		;Thawed?
	IFSKP.			;If so
	 TXNE Q2,FILWB		;Restricted?
	 IFNSK.			;If not
	  TXNE Q2,OFNDUD	;Want DUD?
	  SKIPE DUDFLG		;If so, allow it to be shared anyway?
	  SKIPA T3,[.CFOPT]	;Allow full sharing
	  MOVEI T3,.CFOLE	;No. Must be only here then
	 ELSE.
	  MOVEI T3,.CFOPR	;Yes, restricted
	 ENDIF.
	ELSE.
	 MOVEI T3,.CFOPF	;Frozen
	ENDIF.
	TXNE Q2,FILUB		;Unrestricted?
	MOVEI T3,.CFOPP		;Yes.
	DMOVE T1,Q1
	ANDX T2,STGADR
	CALL CFSGFA		;GET FILE ACCESS
	 RETBAD()		;CAN'T

;Have desired file access. See if we need the write lock as well.

	TXNE Q2,FILWB		;NOT WRITE?
	TXNE Q2,THAWB		;OR THAWED?
	JRST RSKP		;YEP. DONE THEN

;Need to get the write lock as well

	DMOVE T1,Q1
	ANDX T2,STGADR
	CALL CFSGWL		;GET IT
	 SKIPA T1,Q1		;DIDN'T
	JRST RSKP		;DID IT
	MOVE T2,Q2
	CALLRET FRECF0		;RELEASE SHARE LOCK AS WELL
;   >	;IFN CFSCOD
;ROUTINE TO MARK THAT AN OFN IS ON A DISMOUNTED STRUCTURE.
;ACCEPTS:	A/ THE OFN
;MUST BE CALLED WITH THE OFN LOCKED AND THE PROCESS NOINT.
;THIS ROUTINE WILL RELEASE ALL LOCAL STORAGE ASSOCIATED WITH THE
;OFN AND WITH ANY SHARE POINTERS ASSOCIATED WITH THE OFN. IN
;ADDITION IT WILL MARK THE OFN AS INVALID SO THAT SUBSEQUENT PAGE
;FAULTS ON IT OR ANY OF ITS PAGES CAN BE CONVERTED INTO MEMORY
;TRAPS.

	SWAPCD			;CALLED FROM PROCESS CONTEXT

INVOFN:	SAVEP			;GET SOME WORK REGISTERS
	HRRZ P2,A		;SAVE OFN HERE

;NOW MAP OFN AND SCAN IT RELEASING ALL PRIVATE STORAGE

	MOVEI T3,0(P2)		;GET OFN IN T3
	JN DSKAB,SPT(P2),INVOFX	;If already on disk, don't fault it in
	CALL SETXB1		;MAP INDEX BLOCK
INVRTY:	MOVSI P1,-PGSIZ		;SCAN ENTIRE INDEX BLOCK
	SKIP CXBPGA		;FAULT IN PAGE BEFORE NOSKED
	NOSKED			;PROTECT THE XB
INOF2:	SKIPN T1,CXBPGA(P1)	;ANYTHING HERE?
	JRST INOF3		;NO. GO ON
	LOAD T2,PTRCOD,T1	;GET POINTER
	CAIN T2,IMMCOD		;IMMEDIATE?
	JRST [	LOAD T1,STGADR,T1 ;GET STORAGE ADDRESS
		CALL REMPGI	;GO ZAP THE PAGE
		 JRST INVRTY	;HAD TO BLOCK. GO CHECK IT AGAIN
		STOR T1,STGADR,CXBPGA(P1) ;PUT SOMETHING BACK
		JRST INOF3]	;AND PROCEED
	LOAD P3,SPTX,T1		;GET SPT INDEX
	LOAD T1,STGADR,SPT(P3)	;GET SPT ADDRESS
	CALL REMPGI		;GO ZAP THE PAGE
	 JRST INVRTY		;HAD TO BLOCK. GO TRY IT AGAIN
	STOR T1,STGADR,SPT(P3)	;PUT IN A NEW ADDRESS
INOF3:	AOBJN P1,INOF2		;DO ENTIRE INDEX BLOCK
;NOW RELEASE STORAGE ASSOCIATED WITH THE OFN

	LOAD A,STGADR,SPT(P2)	;GET CURRENT LOCATION
	CALL REMPGI		;RELEASE THE STORAGE
	 JRST INVRTY		;HAD TO BLOCK. TRY AGAIN
	STOR A,STGADR,SPT(P2)	;PUT IN HOME ADDRESS
	MOVE T1,P2
	CALL CLRDCH		;And get rid of any cached disk pages
INVOFX:	SETZRO <SPTST,SPTFR,SPTDSF>,(P2) ;Make sure no longer being forced out
	MOVX T2,OFNDMO		;GET DISMOUNTED BIT
	IORM T2,SPTH(P2)	;MARK THE OFN
;   IFN CFSCOD,<
	MOVE T1,P2
	CALL FRECFD		;[7247] Free resources upon dismount
;   >	;IFN CFSCOD
	MOVE A,P2		;GET OFN
	CALL DASALC		;RELEASE ALOC ENTRY
	OKSKED			;ALLOW SCHEDULING AGAIN
	CALLRET RELCXB		;RELEASE XB MAPPING

;ROUTINE TO RELEASE STORAGE FOR INVOFN. WAITS FOR ANY WRITES TO COMPLETE
;BEFORE CALLING REMFP1

REMPGI:	TXNE T1,DSKAB!DRMAB	;IS THIS A CORE PAGE?
	JRST REMPG2		;NO. GO RELEASE IT NOW
	PUSH P,T1		;YES. SAVE I.D.
REMPG1:	CALL SKPNWR		;WAIT FOR WRITE TO COMPLETE
	IFSKP.
	  CALL SKPNLK		;PAGE LOCKED?
	ANSKP.
	ELSE.
	  CALL WTNLK		;LOCK OR WRITE WAS IN PROGRESS, WAIT FOR UNLOCK
	  POP P,0(P)
	  OKSKED
	  RET			;RETURN FOR RETRY
	ENDIF.
	POP P,T1		;RESTORE I.D.
REMPG2:	CALL REMFP1		;GO RELEASE STORAGE
	RETSKP			;AND RETURN SUCCESSFULLY
;ROUTINE CALLED FROM JSYS CODE TO SCAN OFN'S AND MARK EACH ONE
;ON THE STRUCTURE IN QUESTION DISMOUNTED.
;ACCEPTS:	A/ STRUCTURE NUMBER
;RETURNS:	+1 ALWAYS. WITH ALL OFN'S MARKED AND ALL
;		   LOCAL STORAGE RELEASED

MRKOFN::ASUBR<STRMRK>		;SAVE STRUCTURE NUMBER
	STKVAR <LOOPER>		;SAVE LOOP COUNTER
	MOVSI A,-NOFN		;SEARCH ALL OFN'S
MRKOF3:	MOVEM A,LOOPER		;REMEMBER CURRENT LOOPER
MRKOF4:	NOSKED			;GAIN CONTROL OF THE SYSTEM
   IFN DEBUG,<
	MOVE T3,SPTH(A)		;Get SPTH entry for this OFN
	MOVE T2,T3		;Save a copy
	ANDX T3,STGADR		;Isolate storage address
	SKIPE T3		;Is the address zero?
	IFSKP.			;Yes
	  ANDCM T2,[STGADR]	;Isolate flag bits
	  SKIPE T2		;Do they contain something?
	  BUG.(HLT,SPTHNZ,PAGUTL,SOFT,<SPTH flags non-zero and address zero>,,<

Cause:	The monitor is scanning SPTH for OFN entries to mark.  It assumes that 
	when the address is zero, the flag bits will be also.  For this OFN
	entry, the flag bits were non-zero but the address was zero.
>)				;Yes, report inconsistency
	ENDIF.
>	  			;End of IFN DEBUG
	SKIPN T3,SPTH(T1)	;[7247] This OFN in use?
	JRST MRKOF1		;[7247] No, skip it
	TXNN T3,SPTLKB  	;[7247] Now locked?
	IFSKP.			;[7247] Yes
	  HRLZS T1		;[7247] 
	  CALL WTOFNL		;[7247] Wait for it to be unlocked
	  MOVE T1,LOOPER	;[7247] 
	  JRST MRKOF4 		;[7247] Try again
	ENDIF.			;[7247] 
	TMNN OFNCSH,(T1)	;[7247] Cached?
	IFSKP.			;[7247] Yes
	  LOAD T2,STRX,(T1)	;[7247] Get its structure number
	  CAME T2,STRMRK	;[7247] The same as the one dismounting?
	  JRST MRKOF1  		;[7247] No. Skip it
	  MOVX T2,OFNDMO	;[7247] See if dismounted
	  TDNE T2,SPTH(T1)	;[7247] Is it?
	  JRST MRKOF1		;[7247] Yes. Skip it
	  HRRZS T1		;[7247] Position OFN correctly
	  CALL OC.UNC		;[7247] (T1/)Uncache the OFN
	   NOP			;[7247] Ignore since this should not happen
	  JRST MRKOF1		;[7247] 
	ENDIF.			;[7247] 
	HRRZS T1		;[7247] Position OFN correctly
	MOVX T3,SPTLKB		;[7247] Get lock bit
	IORM T3,SPTH(T1)	;[7247] Lock OFN
IFN SPTDSW,<			;ONLY IF DEBUGING SPTLKB PROBLEMS
	CALL SPTRAC		;RECORD WHO LOCKED THIS
 >				;END OF IFN SPTDSW
;   IFN CFSCOD,<
	CSKED
;   >	;IFN CFSCOD
	NOINT			;PREVENT INTERRUPTION
	OKSKED			;AND ALLOW SCHEDULING AGAIN
;  IFN CFSCOD,<
	SETZM B			;GET WT
	CALL CFSAWP		;SHARED
;   >	;IFN CFSCOD
;
	HRRZ A,LOOPER		;Get OFN
	LOAD B,STRX,(A)		;GET ITS STRUCTURE NUMBER
	CAME B,STRMRK		;THE SAME AS THE ONE DISMOUNTING?
	JRST MRKOF2		;NO. SKIP IT
	MOVX B,OFNDMO		;SEE IF DISMOUNTED
	TDNE B,SPTH(A)		;IS IT?
	JRST MRKOF2		;YES. SKIP IT
	CALL INVOFN		;[7247] (T1/)Mark it and its share pointers
	HRRZ A,LOOPER		;[7247] Restore OFN
MRKOF2:	CALL ULKOFN		;[7247] Unlock the OFN
	SKIPA			;[7247] Don't need to OKSKED again
MRKOF1:	OKSKED			;[7247] 
	MOVE A,LOOPER		;[7247] Get back loop control
       	AOBJN A,MRKOF3		;[7247] Do all of them
	RET			;DONE

	RESCD			;RETURN TO RESIDENT CODE
;ROUTINE TO SEARCH FOR THE QUOTA ALLOCATION ENTRY FOR
;A GIVEN DIRECTORY.
;CALL:
; T1/ DIRECTORY NUMBER
; T2/ STRUCTURE NUMBER
;	CALL GETCAL
;Non-CFS version:
; RETURN +1, DIRECTORY NOT OPENED (NO OFN FOR THIS DIRECTORY)
; RETURN +2, FOUND, T1/ CURRENT QUOTA, T2/ INDEX INTO ALCWD
;CFS version:
; RETURN +1 Not found
;	 +2 T1/ allocation.
;	  If GETCAH called, T2/ resource block

GETCAH:	TDZA T3,T3		;Get and hold
GETCAL::MOVEI T3,1
   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<			;If not CFS
	CALLRET LOKCAL		;Look it up
   >	;IFE CFSCOD
   >				;END REPEAT 0

;   IFN CFSCOD,<			;If CFS
	SAVEAC <Q1>		;Save the flag
	EXCH T1,T2		;Swap dir # and strcuture #
	MOVE Q1,T3		;Save the flag
	MOVX T3,<CF%NUL+CF%HLD+.CFAGT>	;hold and get
	SETOM T4
	CALL CFSDAU		;Get directory information
	 NOP			;Who cares?
	IFG. T3			;If found a good one
	 IFN. Q1		;Want it held?
	  MOVE Q1,T1		;No. Get allocation
	  MOVE T1,T2		;Copy block address
	  SETZM T2
	  MOVEI T3,.CFARL	;Release the hold
	  CALL CFSDAU		;Do it
	   NOP
	  MOVE T1,Q1		;Recover the allocation
	 ENDIF.
	 RETSKP
	ENDIF.
	MOVE T1,T2		;Copy entry
	SETZM T2
	MOVEI T3,.CFARM		;Remove the new entry
	CALL CFSDAU		;""
	 NOP
	RET			;And say none here
;   >	;IFN CFSCOD
	
;Routine used by CFS monitor to get allocation.
;Args same as above

   REPEAT 0,<
GETALF::SASUBR<DIRN,STRNO,DALLOC> ;Incoming args
	CALL GETCAL		;Look for it above
	 RET			;None there
	MOVEM T1,DIRN		;Return this
	RETSKP			;Found it
   >	;REPEAT 0
;Routine to look up an entry in the allocation table.
;	T1/ DIR
;	T2/ STR
;Returns: +1 not found
;	  +2 found. T1/ C(PGLFT)  T2/ offset

LOKCAL:	SAVEAC<Q1,Q2>
	HRRZ Q2,T1
	HRRZ Q1,T2
;
; NOTE: IT WOULD BE USEFUL TO ONLY SEARCH THE OFNS POINTED TO BY THE HASH
;	TABLE AS THIS WOULD IN ALL PROBABILITY BE FASTER. THIS CODE DOES
;	NOT GET EXECUTED TOO MUCH SO THE DIFFERENCE IS SMALL UNLESS THERE
;	ARE "VERY MANY" MORE OFN SLOTS THAN OFN IN USE. TAM 28-JAN-85
;
	HRLZI T3,-NOFN		;GET SPT LENGTH
	HRRI T3,1		;MAKE AOBJN START WITH OFN 1
GETC1:	LOAD T2,ALOCX,(T3)	;GET INDEX
	JUMPE T2,GETCN		;SKIP NULL ENTRIES
	LOAD T1,ADIRN,(T2)	;GET DIR #
	CAME T1,Q2		;WANT THIS ONE?
	JRST GETCN		;NO - TRY NEXT
	LOAD T1,STRX,(T3)	;GET STR #
	CAME T1,Q1		;CORRECT STR?
	JRST GETCN		;NO - TRY SOME MORE
	LOAD T1,PGLFT,(T2)	;YES - GET QUOTA LEFT
	RETSKP			;GIVE GOOD RETURN

GETCN:	AOBJN T3,GETC1		;LOOP TILL DONE
	RET			;FAILED (NOT FOUND)
;ADJALC - ADJUST ALLOCATION TABLE ENTRY FOR THIS DIRECTORY

;ACCEPTS:
;	T1/ DIRECTORY NUMBER
;	T2/ STRUCTURE NUMBER
;	T3/ AMOUNT TO ADD TO THE ALLOCATION FOR THIS DIRECTORY

;	CALL ADJALC

;RETURNS +1: ALWAYS

ADJALC::STKVAR <ADJADL>
	MOVEM T3,ADJADL		;SAVE CHANGE
	NOSKED			;NOSKED WHILE FINDING AND CHANGING SLOT
	CALL GETCAH		;GET CURRENT AVAILABLE PAGE COUNT
	 JRST ADJAL1		;NO OPEN FILES IN THIS DIRECTORY
	ADD T1,ADJADL		;ADD THE INCREMENT
   REPEAT 0,<			;CFSCOD NO LONGER USED
   IFE CFSCOD,<
	STOR T1,PGLFT,(T2)	;STORE UPDATED VALUE IN ALLOCATION ENTRY
   >	;IFE CFSCOD
   >				;END REPEAT 0
;   IFN CFSCOD,<
	MOVE T4,T1		;Copy it
	MOVE T1,T2		;Copy block address
	SETZM T2		;No dir
	MOVEI T3,.CFAST		;Set new value
	CALL CFSDAU		;Do it
	 NOP
;   >	;IFN CFSCOD
ADJAL1:	OKSKED			;ALLOW SCHEDULING AGAIN

	RET
;ASSIGN PAGE TABLE USING LOCAL VALUES. CALLED FROM DSKALC TO
;ASSIGN AN SPT FOR THE NASCENT BITTABLE.

ASSPTL::SAVEQ			;SAVE REGISTERS
	MOVE FX,FORKX		;USE LOCAL FORK INDEX

;ASSIGN PSB FOR NEW PROCESS
; FX/ FORK INDEX

ASSPT::	SKIPG 1,FRESPT		;ANY FREE CELLS?
	BUG.(HLT,SPTFL1,PAGUTL,SOFT,<SPT completely full>,,<

Cause:	The monitor is attempting to assign to a process a slot in the
	non-OFN part of the SPT tables. Normally a linked list points to
	the free slots. The header is now 0, indicating either that there
	is confusion in the list or there is not available slot. The
	monitor normally protects against this event by refusing to
	assign additional SPT slots when the available number falls
	below a fixed minimum. This BUGHLT indicates a failure of
	this mechianism or corruption of the free list.
>)
	HRRZ 1,0(1)
	EXCH 1,FRESPT
	SUBI 1,SPT
	AOS SPTC		;ASSIGN SPT SLOT
	MOVX 2,UAAB		;NO ACCESS
	MOVEM 2,SPT(1)		;SHARE COUNT OF 1, NO ADDRESS
	CALL UPSHR		;SET SHARE COUNT TO ONE
	HRRZM FX,SPTH(1)	;SPTH HOLD OWNER FORK INDEX
	RET
;DEASSIGN SPT AND RELEASE STORAGE

DESPT::	CALL DWNSHR		;DECREMENT SHARE COUNT
	PUSH P,1		;SAVE SPT INDEX
	CALL GETSHR		;GET CURRENT SHARE COUNT
	SKIPE 1			;IS IT NOW UNSHARED?
	BUG.(HLT,SHRNO0,PAGUTL,SOFT,<DESPT - Share count non-zero>,,<

Cause:	The monitor is attempting to deassign a slot in the non-OFN
	part of the SPT tables. The caller is expected to have ensured
	that the SPT slot is no longer in use. The BUGHLT indicates
	that the share count for the SPT slot is non-zero, indicating
	that some process is using the slot.
>)
	POP P,1			;YES. RESTORE SPT
	LOAD 2,STGADR,SPT(1)	;GET STORAGE ADDRESS
	TXNN 2,NCORTM		;PAGE IN CORE?
	JRST [	MOVSI 3,(-PLKV)	;YES
		TDNE 3,@CST1X+2	;LOCKED?
		JRST DESPX1
		JRST .+1]	;NO, OK
	PUSH P,1
	MOVE 1,2		;MOVE STORAGE ADDRESS
	CALL REMFP1		;RELEASE CORE AND/OR DRUM
	SKIPE 1			;BE SURE NOTHING LEFT TO DELETE
	BUG.(HLT,PTDEL,PAGUTL,SOFT,<DESPT - PT not deleted>,,<

Cause:	The monitor is attempting to deassign a slot in the non-OFN
	part of the SPT tables. It assumes that the slot was used as a
	page table. The BUGHLT occurs because the SPT entry or its
	backup address is on disk. The caller probably has used the
	wrong routine in releasing an OFN.
>)
	POP P,1
	MOVEI 1,SPT(1)		;CONSTRUCT PTR
	EXCH 1,FRESPT		;PUT ON FREE LIST
	EXCH 1,@FRESPT
	SOS SPTC
	RET
DESPX1:	BUG.(HLT,PAGLCK,PAGUTL,SOFT,<DESPT - Page locked>,,<

Cause:	The monitor is attempting to deassign a slot in the non-OFN
	part of the SPT tables. The caller is expected to ensure that
	the SPT is no longer in use. The BUGHLT indicates that the
	SPT slot is associated with a page that has been locked into
	memory even though the SPT share count is 0. This indicates
	an inconsistency in the monitor's data base. Probably the page
	was used as a page table, and not all its page pointers were
	cleared properly. A page table is locked in memory once for
	each page in memory to which it points.
>)

;ASSIGN FORK STORAGE BLOCK (JSB, PSB, UPT)

ASFSB::CALLRET ASSPT		;ASSIGN SPT SLOT ONLY
   REPEAT 0,<			;FOLLOWING NOT PRESENTLY USED
	SAVEAC <Q1>
	CALL ASSPT		;ASSIGN SPT SLOT
	MOVEM T1,Q1		;SAVE IT
	CALL DRMASN		;ASSIGN SWAP STORAGE
	 BUG(DRMFL1)
	STOR T1,STGADR,SPT(Q1)	;PUT ADR IN SPT
	MOVEM T1,T2
	CALL GDSTX		;GET DST INDEX
	MOVX T1,UAAB		;SET DST
	MOVEM T1,(T2)
	MOVE T1,Q1		;RETURN SPT INDEX
	RET

	ENDAV.			;END ACVAR
   >				;END REPEAT 0

;SPECIAL ROUTINE USED BY SCHEDULER TO DELETE SECOND PSB PAGE.
;CALLED FROM HLTFK1.

   REPEAT 0,<
DESSTK::SKIPN T1,PSBM0+PS2PG ;SEE IF PAGE EXISTS
	RET			;NO. NOTHING TO DO THEN
	LOAD T1,STGADR,T1	;GET STORAGE ADDRESS ONLY
	SETZM PSBM0+PS2PG	;ASSUME IT IS NOW CLEARED
	CALLRET REMFP1		;AND GET RID OF IT
   >				;END OF REPEAT 0
	TNXEND
	END