Google
 

Trailing-Edge - PDP-10 Archives - PCL_FOR_701 - daemon.mac
There are 17 other files named daemon.mac in the archive. Click here to see a list.
TITLE DAEMON - PROGRAM TO SERVICE USER REQUESTS V21(761) - 30-SEP-80
SUBTTL D BLACK/DAL/RCC/JSL/CER/RLD/SMM/BAH/PMW/WRS/KPY/TJW/ISM/DBD/JLG/GMU/RKB

VWHO==0			;WHO LAST UPDATED THIS CUSP
VDAEMON==21
VMINOR==0		;MINOR VERSION NUMBER
VEDIT==761








;COPYRIGHT (C) 1971,1978,1979,1980 BY
;DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
;
;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 WHICH IS NOT SUPPLIED BY DIGITAL.
;	UPDATE SUMMARY AS OF VERSION 7(52)

;053	PARAMETER NOT SET UP CORRECTLY FOR GETLCH UUO IN ERROR
;	INTERCEPTING ROUTINE AT INTRES+5 (SPR 10-11,097).

;054	NEW ROUTINES INTRODUCED TO PROVIDE ERROR REPORTING FOR
;	MAGTAPES AS PART OF THE 507/601 RELEASE.  NEW ROUTINES ARE
;	COMPLETELY BACKWARD COMPATIBLE AND WILL NOT BE EXERSIZED FOR
;	MONITORS PRIOR TO  50622.

;055	ERROR.SYS UPTIME INCORRECT BY FACTOR OF 4.  ERRINI+14,
;	MAKE ASHC OPERAND DECIMAL 17 RATHER THAN OCTAL.

;056	RANDOM PROTECTION OF FACT FILES.  APPNDF+4, STORE AC A,
;	RATHER THAN 0.

;057	FT1975, SUPPORT FOR NEW FORMAT FACT FILE ENTRIES, IN WHICH
;	THE DATE LASTS PAST 1975.

;060	FIXES TO MAKE EDIT 54 WORK.

;061	FIX TO TAKE CARE OF AOBJN DIFFERENCE FROM KA TO KI. CLOCK
;	REQUEST FOR HIGHEST JOB NUMBER WAS NOT GETTING SERVICED ON KA.

;062	ADD DEFENSIVE CODE TO HANDLE ERRORS ON ERROR.SYS. DAEMON WILL
;	NOW WRITE ERROR.X01 TO ERROR.X77 IF NECESSARY.

;063	GENERATE CORRECT FORMAT DATE/TIME WORD IN FACT ENTRIES

;064	FIX FOR UNDEFINED SYMBOL NXTWAK IF USING CERTAIN NONSTANDARD
;	FEATURE TEST SETTINGS

;065	CLEAR .JBINT ON EXIT

;066	INSURE THAT DUMP DOESN'T GET DONE IF AN ERROR THAT WILL PREVENT
;	IT FROM WORKING IS DETECTED

;067	QPNTR IS STILL SET UP WRONG (ON KA AND KI).RH NEEDS TO BE
;	-(# OF INTERNAL CLOCK REQUESTS -1). (SINCE 0 REPRESENTS 
;	A QUEUE IN JBTCLK.
;070	IMPLEMENTS 6.01 SUPPORT

;071	COMPLETES IMPLEMENTATION OF 6.01 SUPPORT AND INCLUDES THE
;	SOURCE FOR SCANER AS PART OF DAEMON.MAC.

;072	MINOR EDIT TO CLEAN UP SOME SMALL DEFICIENCIES LEFT OVER FROM 
;	EDIT 71 AND TO PROVIDE A COMMON FATHER FOR SOUPS OF FUTURE
;	DEVELOPMENT AND INTEGRATION OF IPCF STUFF

;073	EDITS PREPARING THE INTEGRATION OF [SYSTEM] INFO
;	ALL [SYSTEM]INFO DEPENDENCIES ARE DETERMINED BY THE
;	FEATURE SWITCH FTIPCF.THIS SWITCH IS DEFINED AS OFF
;	FOR STANDARD RELEASES AND SHOULD NOT BE TURNED ON
;	NOTE: THAT TURNING ON FTIPCF IMPLIES AN IMPURE VERSION.
;	IT MIGHT BE REMARKED THAT A PURE DAEMON IS A RATHER
;	IMPURE IDEA

;074	ADD THE CAPABILITY TO DAEMON TO RESTART ON ILLEGAL UUO'S
;	ILL. MEM.REF ADDRESS CHECK EXTERNAL JOB ERROR,NXM ,PDL
;	OVERFLOW

;075	FIX SOME BUGS AND CHANGE THE FORMAT OF A SAVE FILE SO THAT
;	NON-CONTIGUOUS LOW SEGMENTS CAN BE 'GOTTEN' INTO A CORE IMAGE
;	THAT RESEMBLES THE ORIGINAL.  THIS IS DONE BY OUTPUTTING A NULL
;	IOWD FOR EACH EXISTANT BUT ZERO PAGE.

;076	INSERT A NEW SUBROUTINE 'SCNBRK' TO FORCE TTY SCANNING
;	TO GO TO END OF LINE FOR EACH DAEMON COMMAND.

;077	FIX A BUG INVOLVING USING THE WRONG HALF OF 'SEGSWP' TO STORE
;	A SWAPPING POINTER BEFORE CALL TO REDPEC

;100	A BLIND ATTEMPT TO FIX WHAT MIGHT BE A PROBLEM GETTING UPMP'S
;	OFF THE SWAPPING SPACE.

;101	START DAEMON AT DAEMON +2 WHEN RESTARTING IT,THIS WILL IDENTIFY
;	THAT IT HAS TO DETACH FROM THE CURRENT TERMINAL AND SUPPRESS OTHER OUTPUT
;	NOTE THAT RESTART ALWAYS DEFINED AND ALWAYS IS ZERO WHEN
;	NO IPCF OR RESTART FUNCTIONS ARE WISHED

;102	FIX A SECURITY LEAK IN THE DCORE COMMAND

;103	CHANGE NAME TO DAE AND NO TO DUMMY

;104	INIT DSK:[1,4] INSTEAD OF SYS:[1,4] FOR FACT.SYS UPDATES
;	AS ELSEWISE THE ENABLING OF NEW E.G. WILL LET
;	THE UPDATE MODE ACCESS FAIL

;105	IF ANOTHER DAEMON IS RUNNING THEN JUST EXIT
;	AND LET OPERATOR DECIDE WHAT TO DO

;106	AS 104 ERROR.SYS CANNOT BE UPDATED WITH AMBIGUOUS SYS

;107	A REENTER OF DAEMON FAILED TO EXIT WITH THE TERMINAL ATTACHED
;	THIS WAS DUE TO THE OMISSION OF A JFCL AFTER THE ZAPRUN CALL

;110	EDIT ERROR IN EDIT 102 IN DAEOPN CODE

;110(A)	WHEN A SECOND DAEMON IS RUNNING DAEMON SHOULD CALL
;	DAEREN TO EXIT

;110(B)	GIVE MORE INFORMATION THEN COULD NOT GET AT SWAP POINTER

;EDITS 111-210 RESERVED FOR SPECIAL RELEASES

;VERSION 10(110) RELEASED WITH ALL ABOVE EDITS
;ALL LATER EDITS IN VERSION 11

;211	FIX CODE TO HANDLE NEW SWAPPING POINTERS FOR
;	6.01 CORRECTLY

;212	REMOVE CRLF FROM JOB SAVED MESSAGE TO LOOK LIKE MONITOR

;213	FIX EXAMINE AND DEPOSIT COMMANDS FOR HIGH SEGMENTS

;214	CHECK FOR OUTPUT DEVICE OF NUL AND FINISH WITH NO IO IF TRUE

;215	FIX HIGH SEGMENT SAVE TO ONLY WRITE EXACT
;	NUMBER OF WORD IN LAST BLOCK OF HGH OR SHR FILE

;216	FIX TO EDIT 62 TO MAKE DAEMON WRITE IN LAST ERROR.X?? FILE
;	WHICH EXISTS ON ERRDEV

;217	FIX UNDEFINED GLOBALS ILIST AND OLIST IF FTFACT!FTCHKPNT=0

;220	FIX TO MAKE DAEMON SAVE DO SAME AS MONITOR DEPENDENT ON CONTENTS
;	OF .JBCOR AND .JBHRL.

;221	FIX TO NOT ERROR INTERCEPT ON ALL IO.BKT ERRORS SO WE CAN
;	REPORT THEM ON COMMANDS

;222	FIX 220 AND 215 TO DO THE RIGHT THING TOGETHER

;223	ADD EXTERNAL SYMBOLS SO SYSINF KNOWS START AND END OF DAEMON

;224	FIX TO 220/222 TO NOT SAVE .LOW IF .JBCOR<140

;EDITS 225-324 RESERVED FOR SPECIAL RELEASES.

;VERSION 11(224) RELEASED WITH ALL ABOVE EDITS. ALL LATER EDITS IN
;VERSION 12.

;325	ADD A FEATURE TEST TO CREATE THE ABILITY TO ASSEMBLE AS TWO
;	SEPARATE PROGRAMS, ONE TO DO ALL COMMANDS AND THE DCORE FUNCTION
;	OF THE UUO, AND ONE TO DO ERROR REPORTING, CHECKPOINTING,
;	ACCOUNTING, OTHER UUO FUNCTIONS, AND SYSTEM INFO.  THE FEATURE
;	TEST IS FTSAVE, EQUAL -1 FOR SAVE ONLY, 0 FOR BOTH, AND +1
;	FOR DAEMON ONLY.  NOTE THAT FTIPCF=-1 OR FTRSTR=-1 WILL NOT 
;	WORK WITH FTSAVE=-1.

;326	ADD SUPPORT FOR RH10 DEVICES. THIS IMPLEMENTS THE SPECIAL DRIVE
;	REGISTERS ON MASSBUS DEVICES. THIS EDIT IS ONLY INTENDED FOR
;	RP04'SAND RS04'S ON SYSTEMS WITH THE RP04 LIR. IT WILL HAVE NO
;	EFFECT ON SYSTEMS WITHOUT THE RP04 LIR.


;327	FIX SOME INCONSISTENCIES IN BEHAVIOR ON SAVE

;330	SAVE ADDRESS OF DDB ALONG WITH LENGTH SO USER CAN ASSOCIATE
;	DDB'S WITH CHANNELS (SPR 14451)

;331	FINISH EDIT 325 -- MAKE TYPEOUT SAY THE RIGHT THINGS

;332	FIX BUG IN FINCHK WHICH CAUSED JOB 8 (AC J =8 ) TO BE CHECKED
;	RATHER THAN THE JOB WE WERE INTERESTED IN. THIS BUG CAUSED
;	RANDOM ERROR CODE 3 TO DAEMON UUO'S AND ALSO WRITING IN RANDOM
;	PAGES.

;333	FIX DAEMON TO TAKE ADVANTAGE OF THE GETTABS ADDED IN 507/601
;	FOR ITS BENEFIT.

;334	ADD CODE TO DUMP UNILOG AS LAST ITEM IN CODE 10 ENTRY IN
;	ERROR FILE

;335	MAKE UNKNOWN COMMANDS GIVE ERROR MESSAGE, INSTEAD OF DOING
;	DCORE AS IN PREVIOUS VERSIONS

;336	FIX SWAPPING POINTERS FOR 507. THEY ARE THE SAME ON
;	BOTH 507 AND 601, NOT DIFFERENT AS PREVIOUSLY CODED
;	SEE EDIT 211 FOR SIMILAR CHANGE FOR 601.

;337	FIX BUGS ADDED BY CHANGE TO DAEMON/SAVER(EDIT 325), AND
;	IN USING NEW GETTABS(EDIT 333)
;340	FIX RACE ADDED BY EDIT 325

;341	SPEED UP COMPRS (IGNORE NONEXISTENT PAGES, DON'T LOOK AT EVERY
;	WORD ON THEM)

;EDITS 342-441 RESERVED FOR SPECIAL EDITS

;342	ADD SUPPORT FOR TAPSER MAGTAPE ERROR REPORTING.

;VERSION 12A(342)RELEASED WITH TAPSER LIR.
;VERSION 12(341) RELEASED WITH ALL ABOVE EDITS
;ALL LATER EDITS IN VERSION 13

;442	ADD CODE TO USE ERRPT. UUO INSTEAD OF SCANNING FOR ERRORS

;443	FIX HSVADR TO NOT NEED UPMP IN CORE. ALSO FIX CALLS TO NOT READ
;	UPMP IF NOT NECESSARY FOR OTHER REASONS.

;444	FIX DCORE TO DO CORRECT THING WITH FIRST PAGE OF HIGH SEG

;445	CHANGE ALL SUPER I/O TO USE SUSET.

;446	CHANGE REFERENCES TO SYMBOLS IN UPMP TO USE GETTABS, NOT DEFINED
;	SYMBOLS

;447	FIX SETUP OF PARAMETERS FOR SWAPPING TO USE GETTABS
;	AND WIN WITH UNITS MISSING

;450	FIX CODE FOR HANDLING ERROR FILE TO ADD WORD AT START
;	OF EACH BLOCK POINTING AT FIRST COMPLETE ENTRY
;	IN BLOCK.  ALSO, PAD LAST BLOCK WITH ZEROS.

;451	ADD SUPPORT FOR CODE 50 IN ERROR.SYS, DL10 ERRORS
;	602 AND LATER MONITORS ONLY.

;452	ADD FUNCTION 5 TO DAEMON UUO, APPEND TO ERROR.SYS

;453	ADD SUPPORT FOR OSAVE AND OSSAVE COMMANDS FOR 6.02

;454	ADD CODE TO GET JOB # FROM DDB ON BOTH 602 AND EARLIER MONITORS
;	JOB # WAS MOVED TO NEW WORD IN 602

;455	ADD CODE TO SYNCHRONIZE ERROR REPORTING WITH STOPPED JOBS. NO
;	JOBS WILL NOW BE STARTED AT THE JOB LOOP -- ALL WILL NOW BE 
;	STARTED AFTER THE ERROR THAT STOPPED THEM IS REPORTED

;456	ADD CODE TO SUPPORT SOME NEW ERRORS REPORTED IN 6.02
;	NEW ERRORS ARE: .ESCSC (CONFIGURATION STATUS CHANGE) = 15
;			ER.MSE (MONITOR SOFTWARE ERROR)      =  2
;			.ESNXM (NON-EX-MEM, NEVER BEFORE SUPPORTED) = 4

;457	CORRECT IMPLEMENTATION OF ER.MSE

;460	FIX BUG IN IMPLEMENTATION OF DL10 (ER.DLE) ERRORS

;461	FIX TAPSER ERROR REPORTING TO USE TAPOP'S TO GET THE POINTERS
;	TO THE INITIAL AND FINAL ERROR STATUS AREAS, RATHER THAN
;	ABSOLUTE OFFSETS RELATIVE TO TUBRID

;462	FIX UP MASSBUSS ERRORS TO REPORT USER'S PPN AND FILENAME CORRECTLY

;463	ADD USERS ID ETC TO CODE 3 & 10,ADD BAD BLOCKS SLOTS
;	TO CODE 10 & 11, ADD EXPECTED TERM. WD TO CODE 6 (RLD)

;464	CHANGE ERROR FILE HEADER LENGTH TO 4 AND INCLUDE SYS SER. # AND
;	CHAGE HEADER VERSION TO 1, INCREASE MAX ENTRY SIZE TO 777 VICE
;	77 BY MOVING HEADER LENGTH LEFT 3 PLACES (RLD)

;465	ANSWER TO SPR#15908

;466	MODIFICATIONS TO CORRECT FOR VERSION 1 HEADERS IN ERROR FILE

;467	ADD CODE TO REPORT NXM AND SET MEMORY OFFLINE TYPE ERRORS.
;	THIS ALSO CHANGES THE WHY RELOAD ERROR ENTRY SINCE IT
;	KEEPS A COPY OF THE ORIGINAL NXM TABLE IN OUR CORE.

;470	FIX CODE TO USE SUPER USETI./O IF SUSET. FAILS.

;471	(16349)MAKE DCORE, DUMP, AND SAVE ABORT ON DSK ERRORS

;472	FIX BUGS IN CODE 4(NXM), CODE 15(MEMORY ON/OFF LINE), AND IN 
;	EDIT 466.

;473	FIX SOME USES OF MONITOR VERSION NUMBER TO BE USES OF "VMMON"
;	INSTEAD

;474	FIX BYTE POINTER TO STORE ENTRY LENGTH IN ERROR FILE HEADER
;	TO STORE 9 BITS, NOT 6. PART OF EDIT 466

;EDITS 475-507 RESERVED FOR SPECIAL RELEASES
;VERSION 13(474) RELEASED WITH ALL ABOVE EDITS
;ALL LATER EDITS IN VERSION 14

;510	FIX BUG IN COMPUTING POINTER TO PARITY SUBTABLE IN CODE 3
;	ERROR FILE ENTRY

;511	DON'T REPORT MEMORY ON-LINE AT RELOAD ON 507/601 AND EARLIER
;	MONITORS

;512	ALLOW ERROR FILE ENTRIES TO SPAN MORE THAN ONE BLOCK, I.E.
;	DO THE RIGHT THING IF AN ENTRY HAS TWO BLOCK BOUNDARIES
;	IN IT

;513	ADD SUPPORT FOR KL10 PROCESSOR ERRORS, CODE 60-AR/ARX PARITY
;	TRAP, CODE 61- PARITY INTERRUPT, CODE 67-ADDRESSING FAILURE
;VERSION 14(513) RELEASED WITH ALL ABOVE EDITS
;ALL LATER EDITS IN VERSION 15

;EDITS 514-517 RESERVED FOR SPECIAL RELEASES

;520	PERFORM PROPER ADDRESS CHECKING FOR ALLOCATED BUT ZERO PAGE

;521	CORRECT ADDRESS CHECK CODE TO PREVENT POSSIBLE
;	OVERWRITING OF JOB DATA AREA

;522	SET UP JBINT TO PREVENT HANG IN TO STATE ON OPR
;	ACTION REQUESTED CONDITIONS

;523	UUOSYMIZE DAEMON

;524	IN CASE OF STRUUO FAILURE WHEN RESETTING DAEMON SEARCH LIST,
;	PURGE INVALID STRUCTURES AND RETRY STRUUO.

;525	FIX ERRORS IN WRTSWP (ROUTINE TO WRITE SWAPPING SPACE)

;526	FIX IMPROPER ADDI AT UADOLD-2 (FROM EDIT 521)

;527	ELLIMINATE MILLIONS OF  HRRI T1,.GTSTS 'S

;530	USE XOR IN PLACE OF ANDCA TO SEE IF A BLOCK CROSSES PAGE BOUNDARIES

;531	FIX POTENTIAL LOOP IN FINCHK BY CHECKING FOR PROPER SEGMENTS

;532	GET RID OF UNNEEDED  MOVSI T1,(J) 'S

;533	MAKE DAEMON FUNCTION TO APPEND TO ERROR.SYS WORK

;534	ZERO TRAILING SPACE ON ERROR.SYS ON OUTPUT

;535	REASSIGN CHANNELS TO OUR JOB ON RELEASE OF CHANNEL.  THUS IF
;	WE ARE ASKED TO LOG AN ERROR FOR THAT FILE, THE DDB WILL STILL
;	EXIST.

;536	RIP OUT SCANER AND REPLACE WITH REASONABLE COMMAND SCANNER.
;	MAKE MINOR NECESSARY CHANGES TO THE DEVIL HIMSELF, INCLUDING
;	REMOVAL OF EDIT 76

;537	FIX UP INTERRUPT ROUTINE SO IT WON'T DESTROY T1 OR SELF-DESTRUCT

;540	WRITE DAEMON FILES ON SYS ONCE AGAIN.  DISENABLE NEW TO AVOID
;	ANY PROBLEMS.  HACK OUT CODE WHICH RESETS DAEMON SEARCH LIST,
;	SINCE THIS ISN'T NECESSARY WHEN WRITING ON ERSATZ DEVICES

;541	FIX IMPROPER INDEX AC TO PREVENT PROBLEMS WHEN READING ARG
;	BLOCK FROM USER WHICH IS SPLIT ACROSS PAGES.

;542	MAKE SURE USER HAS RENAME PRIV'S WHEN DELETING .SAV, .HGH, ETC.
;	ALSO FIX CHCACC FUNCTION IN ACCCHK TO CHECK WRITE PRIV'S INSTEAD
;	OF RENAME PRIV'S WHEN TRYING TO WRITE
;543	PUT PATCHING SPACE AND JUNK UNDER FTDEBG

;544	SET UP INTADR SO WE CAN'T LEAVE USER IN DAEMON ERROR PAUSE
;	IF WE BLOW UP WHILE RECORDING ERROR

;545	ON DISK ERROR, DON'T GIVE EXPECTED CHANNEL TERMINATION WORD
;	UNLESS HAVE A 601 OR GREATER MONITOR, SINCE THIS VALUE IS NOT
;	STORED FOR THE LAST ERROR ON PREVIOUS MONITORS, AND THE BEST
;	WE CAN DO IS PICK UP THE LAST EXPECTED CHANNEL TERMINATION WORD,
;	WHICH MAY BE FOR A MORE RECENT TRANSFER THAN THE LAST ERROR.

;546	ADD SUPPORT FOR KL10 CPU ERROR INFORMATION OBTAINED FROM
;	RSX20 FRONT END -11

;547	CHANGE FORMAT OF KL ERROR ENTRY IN ERROR.SYS TO INCLUDE
;	COUNT OF 8 BIT DATA BYTES
;550	ADD DEFINITION OF %CVPTR&.ESDRE UNTIL UUOSYM GETS
;	UPDATED.  ALSO ADD SUPPORT FOR LP100-CODE 71
;551	ADD FUNCTION TO SUPPORT READING PENDING ENTRIES AND OTER INFO
;	FROM CRASH.EXE FILES.
;552	FIXES TO CORRECTLY RECORD OVER 200 WORD ERROR FILE ENTRIES
;553	FIX PREV.CHANGES & MAKE UNUSED AND ILLEGAL ERROR CODES
;	GO TO JOBFIN VOCE CPOPJ

;554	FIX EDIT 545 SO THAT MONVER GETS SET UP CORRECTLY
;555	MAKE WORK CORRECTLY FOR RPO6'S

;556	FIX KLERR STUFF


;557 PUT CRASH STUFF IN FTSAVE CONDITIONALS
;560 FIX EDIT 557

;561	SAVE PDBPTR AROUND CRASH CHECK STUFF AND FIX TYPO'S

;562	GET UDT FROM %CNDTM NOT %CNDAT

;563	FIX GTUPMP CODE

;564	DON'T SMASH TWO PACK STRUCTURES WITH CRASH STUFF

;565	FIX EDIT 544

;566	FIX MAGTAPE ERROR REPORTING

;567	FIX REDSWP ON VM

;570	MAKE DAEMON EXIT GRACEFULLY ON RE-ENTER

;571	DCORE SPOOLED DDB'S CORRECTLY.

;572	HANDLE AN ARGUMENT BLOCK SPLIT ACROSS FRAGMENTED PAGES
;	ON THE SWAPPING SPACE CORRECTLY ON A VM SYSTEM.
;573	FIX MAGTAPE STATISTICS REPORTING.  THE UNIT NAME WAS BEING
;	OUTPUT AS GARBAGE.
;574	FIX MAGTAPE STATISTICS SO THAT THERE IS SOME USEFUL INFORMATION
;	IN THE ERROR.SYS FILE.
;575	FIX PATH. UUO SO WE DON'T WASTE A PPB
;576	FIX CALL TO GETZ AT CRSIN3+5
;577	HISTORICALLY THE MAXIMUM FACT FILE SIZE WAS 2048 BLOCKS
;	WITH SAID MAXIMUM ACHIEVED WHEN P2 EXCEED 777577 AND
;	RESULTING ARITHMETIC ERRONEOUSLY POINTED TO THE WRONG BLOCK.
;	RECODE TO TEST FOR THIS CONDITION AND EXIT ACCORDINGLY.
;600	FIX BUG WHERE DATA FROM TAPE UNLOAD IS NOT SAVED.
;	CURE: AT GTPST1+1 ADJUST T1 NOT P1
;601	ADD USER'S P,PN AND PROGRAM NAME TO MAGTAPE ERROR REPORTING
;602	ADD IPCF SUPPORT FOR SYSERR
;603	5-10-78	ISM	CHECK FOR 0 LENGTH DAEMON QUEUE TABLE IN
;	CRASH.EXE FILE. THIS FIXES A PROBLEM WITH DAEMON LOOPING
;	WHILE READING CERTAIN CRASH.EXE FILES DURING STARTUP.
;604	5-15-78	ISM	FIX EDIT 544. INTADR IMPROPERLY SET UP
;	SO THAT DAEMON MAY GO INTO TO STATE WHILE DETACHED.
;605	5-19-78	ISM	DCORE FILES GET WRITTEN INTO [1,2] IF SIGN
;	BIT IS SET IN THE PPN. CHECK FOR SIGN BIT ON AND BOMB THE USER.
;606	6-5-78	ISM	DAEMON DOES NOT HANDLE DUMP COMMAND FOLLOWED BY
;	SPACES PROPERLY. THROW AWAY THE SPACES.
;607	RELEASE DISK CHANNEL UPON EXITING CRSCHK SINCE WE ARE DONE WITH IT
;610	AFTER DOING A DCORE, CHECK IF USER JOB IS DETACHED.  IF NOT
;	DO NOT REATTACH JOB.
;611	8-22-78	ISM	FILES WITH PROTECTION GREATER THAN <400>
;	(FILE DAEMON CALLABLE) CAN GET WIPED OUT BY DCORE FUNCTION. USE
;	"IN YOUR BEHALF" FILOP. TO CHECK PROTECTION PROPERLY.
;612	18-SEP-78/BAH DAEMON SENDS A PACKET WITH AN INCORRECT INDEX INTO
;	ERROR.SYS WHEN USING THE /NOW SWITCH IN SYSERR. ALSO SYSERR ALWAYS
;	REPORTS 0 FOR CHAR/H/S FOR READ/WRITE ERRORS IN MAGTAPE STATS
;	BECAUSE DAEMON USES WRONG OFFSET TO GET THE DATA.
;VERSION 17
;700	ADD SUPPORT FOR KS10 SYSTEM ERROR ENTRIES
;701	CHANGE THE REFERENCES TO WORD 36 TO .JBSYM (WORD 116). (USED
;	AS THE FLAG WORD FOR DETERMINING IF A CRASH FILE HAS BEEN PROCESSED
;	BY DAEMON OR NOT)
;702	FIX MAGTAPE STATS ENTRY ROUTINE
;703	(SPR 10-26436) ALLOW CONTROLLER NUMBER TO BE REPORTED TO
;	SYSERR.  AREA AFFECTED: MBDVDN
;704	ADD CODE TO LOG DX20 DEVICE ERRORS.  AT PRESENT THIS MEANS
;	TU7X TAPE ERRORS REPORTED BY TAPSER.
;705	REMOVE ALL CODE SPECIFIC TO PRE-603 MONITORS.  THIS IS THE FIRST
;	STEP IN UPDATING DAEMON FOR 701.
;706	ADD CODE TO DUMP THE CPU STATUS BLOCK VIA ERROR CODE 63 (.ESCSB)
;707	ADD CODE TO DUMP THE DEVICE STATUS BLOCK VIA ERROR CODE 64
;	(.ESDSB)
;710	ADD CODE TO SEND THE DATE/TIME INCREMENTAL CHANGE TO %SIACT
;	IF THE SYSTEM DATE/TIME CHANGES.  INVOKED BY SUBFUNCTION 3
;	OF ERROR CODE 15.
;711	BRING ALL THE CODE UP TO 7.01 LEVEL.  ALSO FIX A LARGE NUMBER
;	OF BUGS IN THE ERROR REPORTING CODE.
;712	ADD CODE TO LOG SOFTWARE EVENTS OF INTEREST VIA CODE 14.
;713	REWRITE MISCELANEOUS PARTS OF THE CODE TO CLEAN IT UP
;	AND FIX A LOT OF BUGS.
;714	TO BE ABLE TO MEASURE SOME SORT OF GENERIC "AVAILABILITY"
;	FOR A SYSTEM,  MAKE DAEMON WAKE UP EVERY 6 MINUTES AND
;	LOOK AROUND TO SEE WHAT THE SYSTEM STATE IS.  LOG THIS
;	INFORMATION TO A NEW FILE, SYS:AVAIL.SYS.
;715	FOR SYSTEMS WITH JOBN+SEGN-1 .GT. 511 (7.01 REMEMBER),
;	THE GETTAB SIMULATION FAILS FOR TABLES INDEXED BY JOB
;	OR SEGMENT NUMBER IF THE INDEX IS LARGER THAN 511.
;	NUMTAB ONLY HAS 9 BITS FOR THE MAXIMUM TABLES SIZE.  THE
;	MONITOR USES JBTMXL EXPLICITLY FOR SUCH TABLES.
;716	FOR SYSTEMS WITH A LARGE NUMBER OF (POSSIBLY DUAL PORTED)
;	DISKS, ERROR CODE 5, INFORMATION EXTRACTED FROM A CRASH
;	MAY OVERFLOW WHILE WRITING THE ENTRIES FOR EACH DISK.
;	REMOVE THE DISK STUFF FROM ERROR CODE 5 AND WRITE A
;	NEW ENTRY (45) WHICH CONTAINS THE INFORMATION.
;717	LOG NODE OFF AND ON-LINE VIA SUB-CODES 6 AND 7 OF THE
;	CONFIGURATION STATUS CHANGE ENTRY.
;720	IF THE ERPTBK TABLE IN A CRASHED MONITOR IS FULL AND EPKIDX
;	IS 0, DAEMON WILL LOOP PROCESSING THE ENTRIES.  REDO THE CODE
;	AT READCR TO AVOID THIS PROBLEM.
;721	DAEMON MAY REATTACH THE WRONG JOB TO A TERMINAL AFTER PROCESSING
;	A REQUEST IF THE USER ATTACHES AND LOGS OUT THE JOB DOING THE
;	REQUEST AND ANOTHER USER LOGS IN AND DETACHES BEFORE THE REQUEST
;	IS COMPLETED.  DON'T REATTACH A JOB TO A TERMINAL IF THE JOB'S
;	LOGIN TIME DOESN'T MATCH THAT SAVED AT THE START OF THE REQUEST
;722	FIX PROBLEM WHERE DAEMON WAS RETURNING A UUO ERROR CODE WHILE
;	PROCESSING HARDWARE ERRORS.
;723	IF AN ERROR OCCURS WHEN DAEMON IS DETACHED, THE ERROR MESSAGE,
;	IF ANY, IS THROWN ON THE FLOOR.  USE TRMOP. FUNCTION .TODSP
;	TO PRINT THE ERROR MESSAGE ON DEVICE OPR.
;724	AVOID PROBLEMS WITH USERS GETTING A [1,2] JOB BY ALWAYS
;	SETTING DSKFUL ERROR WHEN DAEMON STARTS UP.
;725	SINCE THE 700 MONITOR IS CAPABLE OF CHANGING THE ACTIVE
;	SWAPPING LIST ON THE FLY, WE CAN NO LONGER READ SWPTAB
;	WHEN DAEMON STARTS UP.  READ THE INFORMATION FROM SWPTAB
;	ON EACH REQUEST TO READ/WRITE THE SWAPPING SPACE.
;726	TC10C TAPE ERRORS ARE REPORTED BY SYSERR AS DX10 ERRORS.
;	THE DEVICE CODE FOR TC10C'S IS 724 AND THE CODE ASSUMED
;	THAT ANY DEVICE CODE LARGER THAT 540 WAS AN RH20.  A COMPLEMENTING
;	BUG IN SYSERR THEN TURNED THAT INTO A DX10 ERROR REPORT.
;727	FIX BUG IN PEKUSR THAT CAUSED SWAP POINTER INCONSISTENCIES
;	WHILE READING FUNNY SPACE ADDRESSES.
;730	FIX RANDOM ERROR CODE 3 FAILURES IN DAEMON UUO FACT FUNCTION
;	CAUSED BY RELEASING THE JOB WITHOUT PROCESSING IT
;	IF JS.DPM WAS SET.
;731	YET ANOTHER SECURITY FIX TO PREVENT A USER GETTING A [1,2]
;	JOB.
;732	FIX ROUTINE TO DUMP KS10 HALT STATUS BLOCK
;START VERSION 20 HERE WITH 7.01 FIELD TEST
;
;733	FIX KLERR ROUTINE TO CORRECTLY PROCESS ENTRIES ON CPUS OTHER
;	THAN THE BOOT CPU
;734	CHANGE THE FORMAT OF THE ERPTBK TABLE TO USE 4 WORD ENTRIES SO
;	THAT THE CPU NUMBER CAN BE INCLUDED IN THE ERROR DATA RETURNED
;	BY THE MONITOR.
;735	ADD SUPPORT FOR NEW SYSERR ENTRIES FOR 7.01 MONITOR. THESE ARE
;	ERROR TYPES 6,51,52,54,55,56 AND 57.
;736	FIX DATA GATHERING PROBLEM IN ENTRY TYPE 56.
;737	FIX SBDIAG POINTER IN ENTRY TYPE 52
;740	MAKE ANOTHER ATTEMPT AT FIXING THE KLERR REPORT.
;741	FIX ILL MEM REF IN MASSBUS ERROR ROUTINE.
;742	MONBTS NOW WRITES DUMPS THAT ARE NOT A CONTIGUOUS PHYSICAL
;	CORE IMAGE.  CHANGE PEKSPY TO READ AND FOLLOW THE .EXE
;	DIRECTORY WHEN READING WORDS FROM THE DISK.
;743	IF A USER ^C'S DAEMON WHILE IT IS WRITING A DUMP/DCORE/SAVE
;	FILE, DAEMON DOESN'T RELEASE THE CHANNEL WHICH CAUSES THE
;	USER TO GET AN FBM ERROR WHEN HE TRYS TO DELETE THE TMP FILE.
;744	DEVICE OPR0 DOESN'T EXIST IF FTNET IS TURNED OFF OR IF A SITE
;	HACKS THEIR MONITOR.  MAKE DAEMON TRY HARDER TO FIND A TTY TO
;	TRMOP. TO.
;745	AVAIL HAS TROUBLE FIGURING OUT WHEN AVAIL.SYS STARTED AND WHEN
;	IT ENDED.  DEFINE 2 NEW ENTRIES, 46 AND 47 WHICH ARE THE FIRST
;	AND LAST ENTRIES IN AVAIL.SYS.  THESE ENTRIES PROVIDE TIMESTAMPS
;	FOR AVAIL.
;746	MAKE PROCESSING OF ERRORS DURRING INITIALIZATION CLEANER
;747	LIMIT THE NUMBER OF ENTRIES MADE IN THE DISK STATISTICS
;	ENTRY TO AVOID INFINITE ERROR FILES IF THE UDB CHAINS GET
;	SCREWED UP.
;750	CHANGE DAEMON TO USE %CNSUP AS THE UPTIME INSTEAD OF %NSUPT
;	SO THAT IT GETS CLOCK REQUESTS RIGHT IF CPU0 ISN'T RUNNING.
;751	FIX BUG THAT CAUSED ERROR CODE 2 FROM JOBPEK WHEN READING
;	FRAGMENTED CORE.
;752	ADD CODE TO LOG RP20 DISK DEVICE ERRORS
;753	SPR #10-29485 	RKB	2-JUN-80
;	FIX ROUTINE "CHECK" TO FORCE A FACT.SYS UPDATE AT EACH CHECK-
;	POINT.  THIS HELPS PRESERVE MORE ACCOUNTING DATA.
;754	AVAIL.SYS UPDATE ROUTINES DON'T USE ERRDEV AND ERRPPN TO
;	DO THEIR UPDATES.
;755	SPR #10-29218	RKB	11-JUN-80
;	FIX ROUTINE "COMPRS" TO AVOID CREATING IOWDS OVER 128K.
;756	ALLOW A USER HAVING POKE PRIVILEGES TO DO THE APPEND TO
;	ERROR.SYS DAEMON UUO FUNCTION.
;757	LOOK FOR CRASH FILES TO PROCESS ON THE UNION OF THE
;	SYSTEM SEARCH LIST AND THE SYSTEM DUMP LIST.
;760	CLEAN UP THE RP20 ERROR REPORTING LOGIC TO MAKE IT LESS DEPENDENT
;	ON ASSEMBLED-IN PARAMETERS.
;START VERSION 21 HERE WITH 7.02
;
;761	UPDATE EDIT NUMBER FOR 7.02, REMOVE THE FT603 CONDITIONAL AND
;	MAKE SOME COSMETIC CHANGES.
;
; END OF EDIT HISTORY
SUBTTL SYMBOL DEFINITIONS

;DEBUGGING NOTE:
;IF DAEMON IS LOOPING AND YOU WANT TO STOP IT AND SAVE THE CORE
;IMAGE FOR LATER ANALYSIS, DO THE FOLLOWING:
;	.ATTACH 5[1,2]		;ATTACH TO IT FROM A [1,2] JOB
;	.HALT			;STOP IT
;	.REENTER		;STOP IT GRACEFULLY
;	.NSAVE BADDAE		;SAVE FOR LATER
;THIS PROCEDURE WILL CAUSE DAEMON TO SAVE ITS AC'S SO THAT YOU GET
;A DUMP WITH SOME USEFUL INFORMATION.

	.JBVER==137
	LOC	.JBVER
	BYTE	(3)VWHO(9)VDAEMON(6)VMINOR(18)VEDIT
	RELOC

	SEARCH MACTEN,UUOSYM

	DEFINE	ND(SYMBOL,VALUE),<
	IFNDEF SYMBOL,<SYMBOL==VALUE>
	SYMBOL==SYMBOL	>

ND	FTDEBG,0	;NON-ZERO FOR DEBUGGING FEATURES
ND	FTMCNF,0	;NON-ZERO TO INCLUDE MAXCNF.SYS STUFF
			;THIS SWITCH SHOULD REMAIN ZERO UNTIL
			;WE DECIDE WHAT TO PUT IN MAXCNF
ND	MAXUCR,1000	;MAXIMUM BLOCK TO READ FROM USER CORE
ND	MAXUPM,^D512	;SIZE OF BLOCK TO USE AS UPMP BUFFER
ND	EVASIZ,^D128	;NUMBER OF WORDS TO READ FROM FUNNY SPACE IN PEKUSR
			;THIS **MUST** BE ONE OF 128, 256, OR 512. ANY
			;OTHER VALUE WILL CAUSE PEKUSR TO RETURN WRONG
			;VALUES IF IT READS THE CORE FROM THE SWAPPING
			;SPACE.
ND	PDLEN,50	;LENGTH OF PUSH DOWN LIST

ND	CPUN,2		;MAX NO OF CPU'S TO LOG ERRORS ON
ND	CHNN,20		;NO OF CHANNELS  TO LOG ERRORS
ND	ERRDEV,SIXBIT/SYS/	;**[540] SYS IS THE RIGHT PLACE
	IFE <ERRDEV-'DSK   '>,<
		ND	FTSVSL,1	;SAVE SEARCH LIST IF USING DISK
	>
ND	ERRPPN,<0>	;UFD (DEFAULT SYS:) FOR HARDWARE ERROR LOG FILE
ND	ERRSIZ,777	;LARGEST ERROR-FILE TRANSACTION
ND	FTFACT,1	;0 TO SUPPRESS FACT FILE AND CALLS
			;-1 TO RETURN ERROR ON .FACT FUNCTION
IFE FTFACT,<ND FTCHKPNT,0>	;RE-DEFAULT CHKPNT IF FACT TURNED OFF
ND	FTCHKPNT,1	;0 TO SUPPRESS CHKPNT FCN
ND	FCTDEV,SIXBIT/SYS/	;**[540] SYS IS UNAMBIGUOUS
	IFE <FCTDEV-'DSK   '>,<
		ND	FTSVSL,1	;SAVE SEARCH LIST IF USING DSK
	>
ND	FTSVSL,0	;DON'T SAVE SEARCH LIST UNLESS WE HAVE TO
ND	FCTPPN,<0>	;UFD (DEFAULT SYS:) FOR FACT.SYS
ND	TRNSIZ,20	;LARGEST SINGLE FACT-FILE TRANSACTION
ND	MAXINT,^D100000	;NUMBER OF ERROR INTERCEPTS BEFORE STOPING
			;AUTOMATICALLY
ND	MAXFCT,^D800	;WORDS IN FACT BUFFER
			; - ADJUST TO BRING DAEMON CLOSE TO EVEN K BOUNDARY
ND	MAXAGE,^D600	;MAX TIME (SECS) A FACT ENTRY MAY SIT IN DAEMON
ND	CHKTIM,^D600	;SECONDS BETWEEN CHECKPOINTS
ND	AVLTIM,^D360	;SECONDS BETWEEN AVAIL.SYS UPDATES
ND	ERRTIM,^D60	;SECONDS BETWEEN RETRIES ON ERROR.SYS
ND	SLPTIM,^D60	;TIME TO SLEEP IF NO WORK
ND	ICLKRQ,4	;NO OF INTERNAL CLOCK REQUEST TYPES
ND	CHKRQ,0		;CHECKPOINT REQUEST DUMMY JOB #
ND	AGERQ,-1	;DUMMY JOB TO FORCE OUT OLD FACT ENTRIES
ND	IOERQ,-2	;TIMER TO RETRY ERRORS ON ERROR.SYS
ND	AVLRQ,-3	;UPDATE AVAIL.SYS REQUEST
;AC'S

SF=0		;SCANNER FLAGS
S1=1		;SCANNER PARAM REG
T1=1		;TEMP AC'S
T2=2
T3=3
T4=4
P1=5		;PERMANENT AC'S
P2=6
P3=7
J=10		;JOB NUMBER BEING SERVICED
P4=11		;PERMANENT AC
S=12		;SEGMENT NUMBER OF HIGH SEGMENT IF ANY
F=13		;FLAGS
SN=14		;SCANER'S NAME OR NUMBER ACCUMULATOR
BP=15		;BYTE POINTER FOR OUTPUT
SC=16		;16 USED AS CHAR AC IN COMMAND SCANNER
P=17		;PUSH DOWN LIST PTR


;I/O CHANNELS

DSK==6
SWP==7
FCT==10
DSKX==11


;OPDEFS

	OPDEF	PJRST	[JRST]
	OPDEF	PJSP	[JSP]
	OPDEF	PJUMPE	[JUMPE]
;MACROS

	ER.STP==1B12	;STOP PROGRAM ON THIS ERROR
	ER.OPR==1B11	;NOTIFY OPR ON THIS ERROR
	ER.NCR==1B10	;NO CRLF AT END OF MESSAGE

DEFINE	ERROR (MSG,FLG,LBL),<
	ERRWRN (<?>,<MSG>,FLG,LBL)
>

DEFINE	WARN  (MSG,FLG,LBL),<
	ERRWRN (<%>,<MSG>,FLG,LBL)
>

DEFINE	TELL  (MSG,FLG,LBL),<
	ERRWRN (< >,<MSG>,FLG,LBL)
>

DEFINE	ERRWRN (PFX,MSG,FLG,LBL),<
	PUSHJ	P,ERRMSG
	XLIST
	..XX==0
	..YY==0
	IRP FLG,<
	IFIDN <FLG>,<STOP>,<..XX==..XX!<ER.STP_-^D23>>
	IFIDN <FLG>,<NOCRLF>,<..XX==..XX!<ER.NCR_-^D23>>
	IFIDN <FLG>,<OPR>,<..XX=..XX!<ER.OPR_-^D23>>
	>
	IFNB <PFX>,<..YY=="'PFX'">
	IFB  <LBL>,<CAI ..XX,[XWD ..YY,[ASCIZ\MSG\]]>
	IFNB <LBL>,<CAIA ..XX,[XWD ..YY,[ASCIZ\MSG\]]
		    JRST LBL>
	LIST
>
;FLAGS IN F

L.DUMP==(1B0)		;SET IF DUMP, NOT IF DCORE
L.ANY==(1B1)		;SET IF ANY JOBS REQUIRING DAEMON SERVICE FOUND DURING SCAN
L.WJ==(1B2)		;SET IF WANT GETTAB FOR JOB
L.WS==(1B3)		;SET IF WANT GETTAB FOR HIGH SEGMENT
L.TTYA==(1B4)		;SET IF TTY IS ATTACHED
L.UUO==(1B5)		;SET IF DAEMON STARTED BY UUO
L.OPR==(1B6)		;SET IF MESSAGE SHOULD GO TO OPR
L.FORC==(1B7)		;SET TO FORCE DUMP OF FACT.SYS BUFFER
L.INI==(1B8)		;SET DURING INITIALIZATION TO INHIBIT TYPING
			;ERROR MESSAGES ON OPR
L.SAVE==(1B13)		;SET IF SAVE (AS OPPOSED TO DUMP OR DCORE)
L.UPMP==(1B14)		;SET IF USER'S UPMP IS IN USRUPM
L.ZPGF==(1B15)		;SET TO INDICATE CURRENTLY SCANNING A POTENTIAL ZERO PAGE IN COMPRS
L.NHRL==(1B16)		;SET IF WE ARE SAVING A HIGH SEG WHERE LH(115)=0
L.DSK==(1B17)		;SET IF WE ARE PROCESSING A CRASH FILE
R.SWIN==1B18		;SET BY FINCHK IF JOB BEING SWAPPED IN
R.AVL==1B19		;APPEND THIS ENTRY TO AVAIL.SYS IN ADDITION
			;TO ERROR.SYS (USED BY ERRFIN)
R.PAE==1B20		;THIS PASS THROUGH ERRFIN IS APPENDING THE
			;ENTRY TO AVAIL.SYS
R.NEB==1B21		;NO ERROR BLOCK FOR THIS CALL TO ERRINI, USE
			;BOOT CPU SERIAL NUMBER

;FLAGS IN SF (SCANER'S FLAGS)

S.EOF==1B33		;EOF ON INPUT
CRSBLK==5		;BLOCK # WHICH CONTAINS 1ST 200 WDS OF CORE IMAGE
;GETTAB ITEM FOR VARIOUS TABLES

DACODE=='JD'	;STSTBL - QUEUE CODE FOR DAEMON QUEUE

;BITS IN JBTSTS WORD - LH

JSHR==200000	;MEANS HIGH SEGMENT IS SHARABLE
JNSWP==10000	;JOB IS NOT TO BE SWAPPED
JSWP==2000	;SWAPPED OR SWAPPING BIT
JLOG==4		;LOGGED IN
JACCT==1	;THE GODLY BIT
RUN==400000	;RUNNING(ACTUALLY, NOT IN MONITOR MODE)

;BITS IN JBTSTS WORD - RH

JDC==100000	;SET IF JOB REQUIRES SERVICE BY DAEMON
JS.DEP==10000	;JOB WAITING IN DAEMON ERROR PAUSE
JS.DPM==100	;JOB HAS BEEN WAITING FOR DAEMON TO SERVICE IT
		;FOR A MINUTE.  IF THIS BIT IS SET, WE FREE THE
		;JOB SINCE IT'S BETTER TO MISS SOMETHING THAT
		;HANG UP THE SYSTEM.

;BITS IN PAGE MAP ENTRY

PM.ACC==400000	;PAGE ACCESSABLE
PM.ZER==40000	;PAGE ALLOCATED BUT ZERO IF ONLY THIS BIT IS SET
;DDB ENTRIES

DEVNAM==0	;NAME OF DEVICE
DEVSER==3	;LH POINTS TO NEXT DDB
DEVMOD==4	;CONTAINS DEVCHR BITS
DEVSTA==12	;[571] DEVSTA WORDS OD DDB
DEPSPL==1B0	;[571] THIS IS A SPOOLED DB.

;CHANNEL DATA BLOCK ITEMS

.CHSYS==1	;LH - POINTER TO NEXT CHAN DATA BLOCK
.CHLUE==1	;RH - POINTER TO UDB WITH MOST RECENT ERROR
.CHICW==2	;INITIAL CONTROL WORD FROM LAST ERROR
.CHDW0==11	;DATA WORD POINTED TO BY .CHFCW
.CHMPE==12	;COUNT OF MEM PAR ERRS ON THIS CHANNEL
.CHDPE==13	;COUNT OF DEVICE PARITY ERRORS ON THIS CHANNEL
.CHNXM==14	;COUNT OF NON-EX MEMS ON THIS CHANNEL
.CHTCW==16	;EXPECTED CHANNEL TERMINATION WORD OF LAST ERROR
		; THIS VALUE IS GETTABED, BUT DEFINED FOR GETTAB FAILURE
;UNIT DATA BLOCK ITEMS

UNINAM==0	;UNIT NAME
UNILOG==1	;LOGICAL UNIT WITHIN STR
UNIHID==2	;SIXBIT HOME-BLOCK ID NAME (PACK ID)
UNISYS==3	;LH - ADDR OF NEXT UNIT DATA BLOCK IN SYSTEM
		;0 = NO MORE
		;RH - UP POINTER TO STR DATA BLOCK
UNICHN==5	;LH - ADDR OF NEXT UDB ON SAME CHANNEL (RING)
		;RH - UP POINTER TO CHAN DATA BLOCK
UNIKON==6	;POINTER TO CONTROLLER DATA BLOCK FOR THIS UNIT
UNIHCT==10	;HARD (UNRECOVERABLE) ERRORS ON THIS UNIT
		;LH - DEVICE & SEARCH ERRORS
		;RH - DATA ERRORS
UNISCT==11	;SOFT (RECOVERABLE) ERRORS - INCREMENTED WHEN
		;RECOVERY SUCCEEDS. HALVES SAME AS UNIHCT.
UNIMCT==12	;SOFTWARE-DETECTED ERRORS (3 FIELDS OF 12 BITS)
		;SAT FAILURES, RIB REDUNDANCY ERRORS, FOLDED CHKSUM
UNIERR==13	;LAST ERROR STATUS ON DEVICE AFTER FIRST RECOVERY ATTEMPT
UNISOF==14	;ERROR STATUS BEFORE RECOVERY ATTEMPT
UNIHBN==15	;LOGICAL BLOCK NO OF LAST HARD ERROR
UNIBRC==16	;BLOCKS READ IN BUFFERED MODE
UNIBWC==17	;BLOCKS WRITTEN IN BUFFERED MODE
UNIDRC==20	;BLOCKS READ IN DUMP MODE (INCLUDING GET'S)
UNIDWC==21	;BLOCKS WRITTEN IN DUMP MODE (INCLUDING SAVE'S)
UNIMRC==22	;BLOCKS READ FOR MONITOR (SAT,UFD,MFC,BAT,SWAP)
UNIMWC==23	;BLOCKS WRITTEN FOR MONITOR
UNIICT==24	;SWAP READS (ALSO COUNTED IN UNIMWC)
UNIOCT==25	;SWAP WRITES (ALSO IN UNIMWC)
UNIMSC==26	;NO OF MONITOR & SWAPPING SEEKS
UNIUSC==27	;NO OF USER (INCLUDING GET & SAVE) SEEKS
UNIPCT==30	;SEEK INCOMPLETE ERRORS
UNISDI==32	;DATAI WORD ON LAST ERROR BEFORE RECOVERY ATTEMPT
UNIHDI==33	;DATAI WORD AFTER FAILURE OF FIRST RECOVERY ATTEMPT
UNIECT==34	;NO OF RETRIES+INITIAL ATTEMPT WHICH FAILED
		;BIT 0 SET IF SUCCESSFUL OPERATIONS SINCE ERROR
UNIHNG==35	;HUNG RECOVERYS (4 FIELDS OF 9 BITS)
		;# NOT RECOVERED BY STOPPING UNIT IN TRANSFER STATE
		;# RECOVERED BY STOPPING UNIT IN TRANSFER STATE
		;# CAUSED BY UNIT IN POSITION STATE AND RECOVERED AUTOMATICALLY
		;# RECOVERED BY RESTARTING UNIT, WHICH WAS IDLE OR TRANSFER WAIT
UNICDA==40	;RH - ADDR OF DDB FOR CURRENT FILE
UNIDES==55	;[551] UNIT DESCRIPTION(FOR DSKCHR)
		;[551] BOTH UNICDA AND UNIDES ARE GETTABED, BUT ARE DEFINED
		;HERE IN CASE OF GETTAB FAILURE
;TAPSER UNIT DATA BLOCK ITEMS (TUB)
;ALL ARE RELATIVE TO OFFSET OF TUBRID IN TUB, SINCE GETTAB RETURNS
;OFFSET OF TUBRID IN TUB
;AREA FROM TUBRID TO TUBDDA IS STATIC IN MONITOR, I.E. NO NEW WORDS
;WIIL BE ADDED. ALL WORDS ARE DEFINED HERE, EVEN IF NOT USED

;***************THESE TWO ITEMS ARE NOT RELATIVE TO TUBRID BUT SHOULD
;***************REMAIN STATIC. IF THEY CHANGE, A GETTAB SHOULD BE ADDED
;***************TO THE MONITOR TO RETURN THEM
TUBKDB==1	;OFFSET OF UPWARD POINTER TO CONTROLLER DATA BLOCK IN TUB
TKBCDB==11	;OFFSET OF UPWARD POINTER TO CHANNEL DATA BLOCK IN KDB
;**********************************

TUBRID==0	;REELID OF CURRENT TAPE
TUBFIL==1	;# OF FILES FROM BOT
TUBREC==2	;# OF RECORDS FROM EOF
TUBCRD==3	;# OF CHARACTERS READ SINCE LAST UNLOAD
TUBCWR==4	;# OF CHARACTERS WRITTEN SINCE LAST UNLOAD
TUBSRE==5	;# OF SOFT READ ERRORS SINCE LAST UNLOAD
TUBHRE==6	;# OF HARD READ ERRORS SINCE LAST UNLOAD
TUBSWE==7	;# OF SOFT WRITE ERRORS SINCE LAST UNLOAD
TUBHWE==10	;# OF HARD WRITE ERRORS SINCE LAST UNLOAD
TUBTRY==14	;# OF RETRIES TO RESOLVE ERROR
TUBCCR==15	;CHARACTER COUNT ON LAST RECORD
TUBPBE==16	;POSITION BEFORE ERROR (FILE,,RECORD)
TUBFES==17	;FINAL ERROR STATE
TUBDDA==21	;BEGINNING OF SHADOW BLOCK FOR STATISTICS ON UNLOAD
TUBPGM==33	;[601] USER'S PROGRAM IN SIXBIT
TUBUID==34	;[601] USERS PPN


;TAPSER TUBFEP ENTRIES FOR DX20 DEVICE ERRORS.  THESE ENTRIES ARE
;RELATIVE TO THE START OF THE TUBFEP BLOCK.

TD2ZRO==0	;ZERO WORD; ALL UNDEFINED ENTRIES MAP TO HERE
TD2CNI==1	;CONI INITIAL
TD2CIF==2	;CONI FINAL
TD2RED==3	;NUMBER OF FRAMES READ
TD2WRT==4	;NUMBER OF FRAMES WRITTEN
TD2D1I==5	;DATAI PTCR INITIAL
TD2D1F==6	;DATAI PTCR FINAL
TD2D2I==7	;DATAI PBAR INITIAL
TD2D2F==10	;DATAI PBAR FINAL
TD2CS0==11	;CHANNEL LOGOUT 0
TD2CS1==12	;CHANNEL LOGOUT 1
TD2CS2==13	;CHANNEL LOGOUT 2
TD2CC1==14	;FIRST CCW
TD2CC2==15	;SECOND CCW
TD2MPE==16	;COUNT OF MPE
TD2NXM==17	;COUNT OF NXM
TD2OVR==20	;NUMBER OF OVERRUNS
TD2ICR==21	;CONTENTS OF INITIAL CONTROL REG
TD2VER==22	;BYTE (9)DX20 ADDRESS(9)0(18)MICROCODE VERSION NUMBER
TD2MBR==23	;# OF MASSBUS REGS,,OFFSET TO FIRST
TD2DVL==24	;# OF DEVICE REFS,,OFFSET TO FIRST
;THE FOLLOWING VALUES AND OFFSETS INTO THE UNIEBK BLOCK FOR THE
;RP20 DISK MUST AGREE WITH THOSE DEFINED IN RNXKON.  IF RNXKON CHANGES
;YOU MUST CHANGE THE FOLLOWING DEFINITIONS ALSO.

RNXCS0==1		;OFFSET TO THE WORD CONTAINING CHANNEL LOGOUT 0
RNXNXM==7		;OFFSET TO THE WORD CONTAINING COUNT OF NXM'S
;CODES IN ERROR.SYS

EL.HED==4	;LENGTH OF STANDARD HEADER[464]
EL.VER==1	;FORMAT VERSION OF ERROR.SYS[464]
EL.CRS==2	;[551]ENTRY EXTRACTED FROM CRASH.EXE

;OFFSETS IN HEADER FOR AVAIL.SYS WORKING ENTRY

AWEHDR==0	;BYTE(9).ESMRV(9)0(6)EL.VER(3)EL.HED(9)BODY LENGTH
AWEDAT==1	;UNIVERSAL DATE/TIME OF ENTRY
AWECDA==2	;UNIVERSAL DATE/TIME OF FILE CREATION
AWECDM==3	;15 BIT DATE,,TIME OF MAXCNF.SYS CREATION

;OFFSETS IN AVAIL.SYS MONITOR RUN VALUES (.ESMRV) BODY

MRVPSN==0	;-LEN,,OFFSET FROM MRVPSN TO ASCIZ SYSTEM NAME
MRVVER==1	;MONITOR VERSION NUMBER
MRVUPT==2	;UPTIME IN UNIVERSAL DATE/TIME FORMAT
MRVCTM==3	;MONITOR CRASH TIME (+/- 6 MIN) IN UNIVERSAL DATE/TIME FMT
MRVRTM==4	;MONITOR RELOAD TIME IN UNIVERSAL DATE/TIME FORMAT
MRVWHY==5	;WHY RELOAD CODE IN SIXBIT
MRVIDT==6	;SUM OF ALL INCREMENTAL DATE/TIME CHANGES SINCE RELOAD
MRVSNM==7	;FIRST OF 5 WORDS OF ASCIZ SYSTEM NAME
;DEFINITIONS IN KL ERROR BLOCK

.KEDEV==0	;DEVICE, LINE
.KECNT==0	;COUNT
.KECPU==1	;CPU
.KEDTE==1	;DTE NUMBER
.KELNK==1	;LINK
.KEDAT==2	;FIRST DATA WORD

;SPECIAL DEFINITIONS FOR MASSBUS ERROR PROCESSING

RH10CD==1
RH20CD==2
RH11CD==3
MAXREG==20	;MAXIMUM NUMBER OF DRIVE REGISTERS ON A MASSBUS DEVICE

;MISC

BLKSPP==2	;BITS TO SHIFT TO CONVERT PAGES TO BLOCKS
B2WLSH==7	;BITS TO SHIFT TO CONVERT BLOCKS TO WORDS
BLKSIZ==^D128 	;NUMBER OF WORDS PER BLOCK
AVLWRK==<<ERRSIZ+EL.HED+BLKSIZ-1>_-B2WLSH> ;NUMBER OF BLOCKS USED FOR
		;WORKING ENTRY AT THE BEGINNING OF AVAIL.SYS
P2WLSH==^D9	;BITS TO SHIFT TO CONVERT PAGES TO WORDS
PG.BDY==777	;MASK FOR OFFSET IN PAGE
PG.SIZ==1000	;SIZE OF PAGE IN WORDS
C.CR==15	;ASCII CARRIAGE RETURN
C.LF==12	;ASCII LINE FEED
.USSDT==5	;CODE TO SEND TO %SIACT ON ERROR CODE 100
EXESIZ==^D512	;[551]SIZE OF EXE DIRECTORY
LN.BUF==200
ABSGTB==410	;ABSOLUTE LOCATION OF ADDRESS OF GETTAB TABLES
IFG MAXUCR-1000,<MAXUCR==1000>	;IMPOSE JOBPEK LIMIT
IFL MAXUCR-BLKSIZ,<MAXUCR==BLKSIZ>	;AT LEAST ONE BLOCK
MAXUCR==MAXUCR&<-1_B2WLSH>	;FORCE BLOCK BOUNDARY

;LOCATIONS SET UP BY SAVGET CODE IN COMCON

SGAEXT==1
SGAHGH==16

	SALL
SUBTTL INITIALIZE

DAEMON:	JFCL			;IN CASE OF CCL ENTRY
	RESET			;GET ALL RESET
	MOVE	P,PDL		;GET A STACK POINTER(IS A RUN UUO ACCU!!)
	MOVEI	T1,DAEREE	;REENTER FOR [SYSTEM]INFO SHUT DOWN
	MOVEM	T1,.JBREN	;STORE IN REENTER ADDRESS
	SETZB	J,ZER		;J=VALUE OF QUEUE CODE FOR DAEMON QUEUE
	MOVE	T1,[ZER,,ZER+1]
	BLT	T1,EZER		;CLEAR STORAGE LOCATIONS
	MOVSI	F,L.TTYA!L.INI	;CLEAR FLAGS, NOTE TTY ATTACHED
	MOVEI	T1,E.EINT	;REENTER ADDRESS TO START WITH
	MOVEM	T1,INTADR
	MOVE	T1,[XWD 4,INTRES]	;ROUTINE TO RESTART AFTER ERROR INTERCEPTS
	MOVEM	T1,INTBLK	;STORE IN INTERCEPT BLOCK
	MOVEI	T1,777747		;ENABLE FOR ALL ERRORS
	TLO	T1,400000	;SUPRESS ERROR TYPEOUTS
	MOVEM	T1,INTBLK+1	;STORE CONDITIONS IN INTERCEPT BLOCK
	MOVEI	T1,INTBLK
	MOVEM	T1,.JBINT	;SET UP JOB INTERCEPT BLOCK
	PUSHJ	P,FNDOPR	;FIND OPR TTY
	  ERROR	<Can't find OPR terminal>,STOP
	MOVEM	T1,OPRLIN	;SAVE FOR MESSAGES
	HRROI	T1,.GTPPN
	GETTAB	T1,		;GET OUR PPN
	  JRST	E.GTBF
	MOVE	T2,[%LDFFA]
	GETTAB	T2,		;GET FULL FILE ACCESS PPN
	  JRST	E.GTBF
	MOVEM	T2,OPRPPN	;STORE AWAY FOR LATER
	CAME	T1,T2		;SKIP IF HAVE FULL FILE ACCESS
	ERROR	<Job not privileged>,,DAEREN

	PJOB	T1,		;OUR JOB NUMBER
	MOVEM	T1,THSJOB	;SAVE FOR LATER

	SETOM	THSLIN		;INDICATE OUR LINE
	GETLCH	THSLIN		;GET CONTROLLING LINE NO & BITS

	MOVE	T1,[%CNSJN]
	GETTAB	T1,		;GET LOWEST HIGH SEG NUMBER
	  JRST	E.GTBF		;CAN'T GIVE UP
	SOJ	T1,		;DECR TO HIGHEST JOB NUMBER
	HRRZM	T1,HJOB		;SAVE FOR JOB SCANS
	HLRE	T2,T1		;GET -SEGN
	MOVNS	T2		;MAKE IT POSITIVE
	ADDI	T2,(T1)		;COMPUTE MAX JOB+SEG NUMBER
	MOVEM	T2,JBTMXL	;SAVE FOR GETTAB SIMULATION
;HERE TO BUILD COPY OF GETTAB TABLE FOR GTBSPY
	MOVE 	T1,[%CNPDB]	;FIND WHERE JBTPDB IS
	GETTAB	T1,		; FROM MONITOR
	  JRST	E.GTBF		;CAN'T, ERROR
	MOVEM	T1,PDBPTR	;STORE FOR USE IN GETTAB SIMULATOR
	SETZB	T3,T4		;IN CASE WE CAN'T SPY
	MOVE	T1,[%CNSIZ]	;GET SIZE OF SYSTEM
	GETTAB	T1,
	  JRST	E.GTBF		;CAN'T, ERROR
	SUBI	T1,1		;HIGHEST LOC IN MONITOR
	SPY	T1,		;SET SPY
	  ERROR	<Can't SPY on the monitor>,STOP

	MOVEI	T1,.GTSLF	;GET TABLE NUMBER FOR NUMTAB
	HRLI	T1,(T1)		;WANT THE NUMTAB ENTRY FOR .GTSLF
	GETTAB	T1,		;GET IT
	  JRST	E.GTBF		;FAILED
	LSH	T1,-^D27	;KEEP JUST MAX ENTRY IN NUMTAB
	MOVEI	T2,1(T1)	;PLUS ONE FOR LENGTH OF NUMTAB
	PUSHJ	P,GETCOR	;GET THAT MUCH CORE
	  ERROR	<Can't get core for NUMTAB>,STOP
	MOVEM	T2,GTBST	;SAVE ADDRESS OF START OF TABLE
NXTGTB:	HRLZ	T1,T3		;NEXT TABLE PTR
	HRRI	T1,.GTSLF
	GETTAB	T1,		;GET NEXT TABLE PTR
	  JRST	ENDGTB		;THAT'S ALL
	TLZE	T1,37		;CLEAR MONITOR XR AND INDIRECT
	TLO	T1,P3		;SET OUR AC IF TABLE EXISTS
				; (IE, IF POINTER WAS INDEXED)
	TRO	T1,400000	;SET SPY BIT
	MOVEM	T1,(T2)		;STORE IN TABLE OF TABLE PTRS
	ADDI	T2,1		;BUMP TABLE POINTER
	AOJA	T3,NXTGTB	;LOOP FOR ALL POSSIBLE GETTABS

ENDGTB:	SUBI	T3,1		;COMPUTE MAX NUMBER OF GETTABS
	MOVEM	T3,MAXGTB	;SAVE MAX GETTAB NUMBER
	MOVE	T2,GTBST	;GET ADDRESS OF START OF POINTERS
	CAIGE	T3,.GTIDX	;DO WE HAVE A RANGE TABLE?
	TDZA	T3,T3		;NO, MAKE IT ZERO
	HRRZ	T3,.GTIDX(T2)	;GET SPYSEG ADDRESS OF RANGE TABLE
	TRZ	T3,400000	;TURN OFF SPYSEG BIT
	MOVEM	T3,RNGTAB	;SAVE FOR GETTAB SIMULATION

;HERE TO FIND QUEUE # FOR DAEMON WAIT

	SETZ	T2,
FNDDAQ:	HRLZ	T1,T2		;LH T1=NEXT WORD IN TABLE
	HRRI	T1,.GTWSN	;RH=QUEUE CODES TABLE
	PUSHJ	P,GTBSPY	;GET NEXT WORD IN QUEUE CODES TABLE
	  JRST	E.GTBF		;MUST FIND IT
	MOVE	T3,[POINT 12,T1]
FNDDA1:	TLNN	T3,770000	;SKIP IF MORE CODES IN THIS WORD
	AOJA	T2,FNDDAQ	;NO MORE, TRY NEXT WORD
	ILDB	T4,T3		;T4=NEXT CODE IN SIXBIT
	CAIE	T4,DACODE	;SKIP IF FOUND DAEMON QUEUE CODE
	AOJA	J,FNDDA1	;NO, TRY NEXT, COUNT CODES SKIPPED

;HERE WHEN FOUND DAEMON QUEUE CODE, NOW FIND CTY LINE NUMBER

NODAEQ:	MOVEM	J,DAQNAM	;SAVE DAEMON QUEUE CODE
	MOVE	T1,[%CNPTY]
	PUSHJ	P,GTBSPY	;GET OFFSET FOR PTY'S
	  JRST	E.GTBF		;CAN'T GET IT
	HLRES	T1		;T1=OFFSET FOR PTY=LINE NUM OF CTY+1
	SUBI	T1,1		;LINE NUMBER OF CTY
	MOVEM	T1,CTYLIN	;STORE LINE NUMBER OF CTY
	SKIPGE	T1		;GET SWAPPING PARAMETERS IF OK
	ERROR	<Can't get CTY line number>,STOP

	MOVE T1,[%CNVER]	;GET MONITOR VERSION
	PUSHJ	P,GTBSPY
	  JRST	E.GTBF		;CAN'T GET IT
	MOVEM	T1,MONVER	;[545] SAVE VERSION

	MOVE	T1,[%VMUPJ]	;GETTAB OFFSET OF UPJOB
	PUSHJ	P,GTBSPY
	  JRST	E.GTBF		;CAN'T GET IT
	MOVEM	T1,.UPJOB	;AND SAVE OFFSET FOR LATER

	MOVE	T1,[%VMLST]	;GETTAB OFFSET OF .UPLST
	PUSHJ	P,GTBSPY	;GET IT
	  MOVEI	T1,0		;CAN'T, USE ZERO AS A FLAG LATER
	MOVEM	T1,.UPLST	;SAVE OFFSET FOR USE LATER

;FALL THROUGH TO GET SWAP STUFF
	MOVE	T1,[%LDESZ]	;GETTAB TO RETURN SIZE OF ERPTBK ENTRY
	PUSHJ	P,GTBSPY	;GET IT
	  MOVEI	T1,2		;MUST BE AN OLD MONITOR
	MOVEM	T1,ERPTSZ	;SAVE FOR LATER


;HERE TO SET UP SWAPPING TABLES

	MOVE	T1,[%LDSLP]	;GET POINTER TO %LDSLP
	PUSHJ	P,GTBSPY
	  ERROR <Can't get pointer to SWPTAB>,STOP
	HRRZM	T1,SWPTAB	;SAVE ADDRESS OF SWPTAB
	HLRES	T1		;COMPUTE -LEN OF SWPTAB
	MOVNM	T1,SWPMAX	;SAVE LENGTH FOR COMPARES
	MOVE	T1,[%LDSLB]	;GET POINTER TO OFFSET OF UNISLB
	PUSHJ	P,GTBSPY	;GET IT
	  ERROR	<Can't get offset of UNISLB>,STOP
	MOVEM	T1,UNISLB	;SAVE FOR LATER TESTS
;GET, SAVE ORIGINAL FILE STRUCTURE SEARCH LIST FOR THIS JOB

GETSWE:	MOVE	T1,[3,,[.PTFSL	;DEFINE ADDITIONAL PATH TO BE SEARCHED
			0	;NO LIB, NO SYS, NO NEW, NO PROBLEMS
			0]]	;[575] DON'T WASTE A PPB
	PATH.	T1,		;SET UP
	  JFCL			;WHAT ISN'T IMPLEMENTED CAN'T HURT US
	MOVE	T1,[5,,[.PTFSN	;FUNCTION TO DEFINE LOGICAL NAMES
			PT.UDF	;DELETE THIS LOGICAL NAME
			SIXBIT/SYS/ ;NAME IS SYS
			0	;2 ZERO TERMINATORS
			0]]
	PATH.	T1,		;MAKE SURE SYS ISN'T A LOGICAL NAME
	  JFCL			;NOT DEFINED IN THE FIRST PLACE
	MOVE	T1,[.STDFL,,.DFERR] ;ARG TO SET DSKFUL ERROR
	SETUUO	T1,		;DO IT
	  WARN	<SETUUO to set DSKFUL ERROR failed>,OPR
	MOVEI	T1,.FSDSL	;DEFINE SEARCH LIST FUNCTION
	MOVEM	T1,USRLST	;[540] STORE IN FUNCTION BLOCK
	SETOM	USRLST+1	;[540] OUR JOB
	SETOM	USRLST+2	;[540] OUR PPN
IFN .FSDSL-1,<MOVEI T1,1>
	MOVEM	T1,USRLST+3	;[540] SET TO REMOVE UNLISTED STR'S,
				;RATHER THAN PUTTING INTO PASSIVE LIST
IFN FTSVSL,<	;ONLY CARE ABOUT OUR SEARCH LIST IF WE SAVE IT
	MOVE	T1,[XWD USRLST,SRCLST]	;[540]
	BLT	T1,SRCLST+3	;[540] COPY SAME TO SEARCH LIST AREA
	MOVEI	T3,SRCLST+3	;AND USE THIS AREA, PLEASE
	SETOB	T1,T2		;OUR JOB, PPN
	PUSHJ	P,GETSRC	;GET OUR SEARCH LIST
	SUBI	T3,SRCLST-1	;END MINUS BEGINNING=LENGTH
	MOVSI	T3,(T3)		;THATS IN LEFT HALF
	HRRI	T3,SRCLST	;WITH ADDR IN RIGHT
	MOVEM	T3,PSRCH	;SAVE SO WE CAN GET THIS BACK
	STRUUO	T3,		;TRY TO SET THIS SEARCH LIST TO SEE IF IT WORKS
	  WARN	<Search list definition failed>
>	;END CONDITIONAL ON FTSVSL

GETSW0:	MOVE	T1,[%LDMFD]
	PUSHJ	P,GTBSPY
	  JRST	E.GTBF
	MOVEM	T1,MFDPPN

;HERE TO FIND OUT IF JOBPEK UUO WORKS

TSTJPK:	MOVEI	T1,T2
	HRLZ	T2,THSJOB	;OUR JOB NUMBER
	HRRI	T2,1		;1 WORD FROM OUR JOB TO OUR JOB
	MOVE	T3,[SECBUF,,SECBUF]
	JOBPEK	T1,		;TRANSFER A WORD FROM US TO US
	  ERROR <JOBPEK UUO failed>,STOP
;HERE TO CHECK FOR OTHER DAEMON'S RUNNING AROUND

	HRLZ	T1,THSJOB
	HRRI	T1,.GTPRG	;GET OUR NAME
	PUSHJ	P,GTBSPY
	  JRST	E.GTBF		;CAN'T
	CAME	T1,[SIXBIT/DAEMON/]
	JRST	GETJIF		;IF THIS ISN'T DAEMON, NO PROBLEM
	MOVE	J,HJOB		;HIGHEST JOB IN SYSTEM
DAELUP:	CAMN	J,THSJOB	;DO NOT LOOK AT OUR JOB
	SOJG	J,DAELUP
	JUMPLE	J,GETJIF	;QUIT AFTER LOOKING AT ALL JOBS
	HRROI	T1,.GTPRG	;GETTAB POINTER FOR PROGRAM NAME
	PUSHJ	P,GTBSPY
	  JRST	E.GTBF		;CAN'T
	CAME	T1,[SIXBIT /DAEMON/]
	SOJA	J,DAELUP	;THAT'S NOT DAEMON, TRY NEXT
	HRROI	T1,.GTSTS	;GETTAB TABLE FOR JOB STATUS
	PUSHJ	P,GTBSPY	;MUST CHECK JACCT, SINCE ANYBODY
	  JRST	E.GTBF		;  CAN USE A NAME
	TLNN	T1,JACCT	;IS THIS THE SYS:DAEMON?
	SOJA	J,DAELUP	;NO--AREN'T YOU GLAD WE CHECKED?
	ERROR	<DAEMON already running
?Please kill one of us>,STOP
;HERE TO GET SYSTEM CLOCK RATE (JIFFIES/SECOND)

GETJIF:	MOVE	T1,[%CNTIC]
	PUSHJ	P,GTBSPY
	  JRST	E.GTBF
	MOVEM	T1,JIFSEC	;STORE JIFFIES PER SECOND
	IMULI	T1,^D24*^D3600	;JIFFIES PER DAY
	MOVEM	T1,JIFDAY	;HOLD FOR DIVIDE
	MOVEI	T1,^D1000	;MILLISECONDS PER SECOND
	IDIV	T1,JIFSEC	;GET MILLISECONDS PER JIFFY
	MOVEM	T1,MILJIF	;STORE THAT, TOO

;HERE TO SET UP CLOCK FUNCTION TABLE

	MOVEI	T2,ICLKRQ-1	;[67]GET NUMBER OF  QUEUES LESS THAN 0
	MOVNM	T2,QPNTR	;[67]SAVE IN QPNTR AS MOST NEG. QUEUE NO
	ADD	T2,.JBFF	;[67]POINT TO JOB 0
	HRRM	T2,JBTCLK	;STORE THE POINTER
	HRRZ	T1,HJOB		;HIGHEST JOB # IN SYSTEM
	MOVNI	T3,ICLKRQ+1(T1)	;-VE LENGTH OF TABLE
	HRLM	T3,QPNTR	;STORE IN POINTER
	MOVEI	T2,ICLKRQ+1(T1)	;GET NUMBER OF WORDS IN TABLE
	PUSHJ	P,GETCOR	;ALLOCATE THAT MUCH CORE
	  ERROR	<Can't get core for clock table>,STOP
IFN FTFACT!FTCHKPNT,<

;HERE TO SAVE RELOAD INFORMATION IN FACT.SYS

	PUSHJ	P,BUFAGE	;DON'T LET THIS ENTRY SIT TOO LONG
	MOVE	T1,[XWD 371000,3] ;GET NEW FORMAT RELOAD ENTRY[7(57)]
	HRRZM	T1,FACTSZ	;NOTE 3 WORDS IN BUFFER
	MOVE	T2,THSJOB	;GET OUR JOB NO
	DPB	T2,[POINT 9,T1,17]
	MOVE	T2,THSLIN	;GET OUR LINE & CHARACTERISTICS
	TLNE	T2,(GL.CTY)	;IS IT THE CTY?
	SETO	T2,		;YES, SPECIAL CODE FOR THAT
	DPB	T2,[POINT 12,T1,29]
	MOVEM	T1,FACTBF	;(0) HEADER WORD
	MOVE	T1,OPRPPN	;(1) THIS JOB'S PPN
	MOVEM	T1,FACTBF+1
	PUSHJ	P,FACTIM	;12 BITS DATE, 24 BITS TIME
	MOVEM	T1,FACTBF+2	;(2) DATE AND TIME

;ADD HERE OTHER RELOAD INFORMATION AS DESIRED
>

;HERE TO START INTERNAL TIMERS

IFN FTCHKPNT,<
IFN CHKTIM,<
	HRREI	J,CHKRQ		;INSERT THE CHECKPOINT REQUEST
	MOVEI	T1,CHKTIM	;INTERVAL
	PUSHJ	P,CLKREQ	;PUT IN THE REQUEST
>;END OF CHKTIM COND
>;END OF FTCHKPNT COND

IFN AVLTIM,<
	HRREI	J,AVLRQ		;INSERT THE AVAIL.SYS UPDATE SCAN
	MOVEI	T1,AVLTIM	;INTERVAL
	PUSHJ	P,CLKREQ	;PUT IN THE REQUEST
>;END IFN AVLTIM
;HERE TO GET CREATE COPY OF NXMTAB IN CORE

	MOVE	T1,[%CNNXM]	;GETTAB POINTER TO NXMTAB
	PUSHJ	P,GTBSPY
	  JRST	E.GTBF		;CAN'T
	MOVE	T3,T1		;MOVE POINTER TO T3 FOR LATER LOOP
	HLRE	T2,T1		;GET 36 BIT NEGATIVE LENGTH
	MOVMS	T2		;MAKE IT POSITIVE
	MOVEM	T2,NXMLEN	;SAVE LENGTH
	PUSHJ	P,GETCOR	;ALLOCATE THAT MUCH CORE
	  ERROR	<Can't get core for NXMTAB>,STOP
	MOVEM	T2,NXMTAB	;SAVE ADDRESS OF START OF NXMTAB
NXMLUP:	HRRZ	T1,T3		;GET CURRENT ADDR INTO T1
	PUSHJ	P,PEKSPY	;GO PICK IT UP FROM MONITOR
	MOVEM	T1,(T2)		;STASH IT AWAY
	AOS	T2		;INCREMENT T2
	AOBJN	T3,NXMLUP	;INCREMENT T3 AND LOOP

;HERE TO INSURE THAT MAXCNF.SYS EXISTS AND BITCH AT THE OPERATOR
;IF IT DOESN'T.  ALSO BUILD/REBUILD THE AVAIL.SYS WORKING ENTRY IN
;CORE.

CHKCFG:
IFN FTMCNF,<
	MOVE	T1,[SIXBIT/MAXCNF/] ;FILENAME TO LOOKUP
	PUSHJ	P,OPNFIL	;OPEN THE FILE
	  WARN	<File SYS:MAXCNF.SYS does not exist>,,CHKCF1
	PUSHJ	P,RELFCT	;RELEASE THE CHANNEL
CHKCF1:
>;END IFN FTMCNF
	PUSHJ	P,REDAVL	;READ WORKING ENTRY OR BUILD NEW ONE
;HERE TO SAVE WHY-RELOAD CODE AND OPR COMMENTS IN ERROR.SYS

RELSTR:	PUSHJ	P,ERRSTR	;SET UP EXTENSION FOR ERROR FILE
	MOVSI	T1,.ESDRE_9	;[550]SET UP RESTART CODE
	PUSHJ	P,ERRINI	;[550]STORE HEADER, SET P4 AND CLR BUFF
	PUSH	P4,.JBVER	;[550]GET JBVER
	PUSHJ	P,ERRFIN	;[550]AND STUFF IT

	MOVE	T1,[%LDMBR]	;GETTAB KONREG+UNISCR
	PUSHJ	P,GTBSPY
	  JRST	E.GTBF
	HRRZM	T1,UNISCR	;RH IS UNISCR
	HLRZM	T1,KONREG	;LH IS KONREG
	MOVE	T1,[%LDBBP]	;[463]
	PUSHJ	P,GTBSPY
	  JRST	E.GTBF
	MOVEM	T1,UNICCT	;[463] OFFSET TO UNICCT IN UDB
	MOVE	T1,[%LDEXP]
	PUSHJ	P,GTBSPY
	  JRST	E.GTBF
	MOVEM	T1,CHNTCW	;[545] OFFSET TO EXP TERM WD IN CDB

;HERE TO GET ADDRESS OF EXECT1 IN JOB DATA AREA

GETET1:	MOVE	T1,[%CNET1]	;GETTAB THE ADDRESS OF EXEC T1
	PUSHJ	P,GTBSPY
	  JRST	E.GTBF
	MOVEM	T1,EXECT1	;AND SAVE FOR LATER

;HERE TO GET DDB LENGTHS

	MOVE	T1,[%CNLSD]	;GETTAB SHORT DDB LENGTH
	PUSHJ	P,GTBSPY
	  JRST	E.GTBF
	MOVEM	T1,LDDBSH	;AND SAVE AS LENGTH OF SHORT DDB
	MOVE	T1,[%CNLLD]	;NOW GET LONG LENGTH
	PUSHJ	P,GTBSPY
	  JRST	E.GTBF
	MOVEM	T1,LDDBLN	;AND SAVE FOR UUO'S, ETC.
	MOVE	T1,[%CNLDD]	;AND LAST, GET DISK DDB LENGTH
	PUSHJ	P,GTBSPY
	  JRST	E.GTBF
	MOVEM	T1,LDDBDS	;AND SAVE FOR DCORE OF DDB'S

;HERE TO DETACH TTY

	HRLZ	T1,THSLIN	;LH IS NOW LINE NUMBER, RH=0 TO DETACH
	HRRZ	T2,.JBDDT	;GET ADDR OF DDT IF ANY
	JUMPN	T2,NODET	;DONT DETACH IF DDT
	TELL	<Detaching>
	ATTACH	T1,		;DETACH OUR TTY
	  ERROR <DETACH failed>,STOP
NODET:	TLZ	F,L.TTYA!L.INI	;NOTE NO TTY ATTACHED

	MOVEI	T1,E.CRSE	;RESET INTERRUPT ADDRESS
	MOVEM	T1,INTADR	;  TO TRAP ERRORS READING THE CRASH FILES
	PUSHJ	P,CRSCHK	;[551]BEFORE WRITING ANY OTHER ENTRIES
				;FOR THIS MONITOR LOAD, GO LOOK AT CRASH
				;FILES

CRSDON:	MOVEI	T1,DALOOK	;[604]
	MOVEM	T1,INTADR	;[604]
	SETOM	WTUERR		;INIT FLAG TO CATCH RECURSIVE EXIT ATTEMPTS
SUBTTL	CHECK FOR MONITOR-INITIATED DAEMON REQUEST

;HERE WHEN DAEMON AWAKENED
; IF A HARDWARE ERROR HAS BEEN DETECTED BY THE MONITOR, RECORD THE INFO
;COLLECTED INTO ERROR.SYS.  MONITOR COUNTERS GET BUMPED ON EVERY ERROR

DALOOK:	CAME	P,PDL		;VERIFY STACK CORRECTNESS
	MOVEM	P,PDLGUF	;OR SAVE THE BAD GUY
	MOVE	P,PDL		;RESTORE GOODNESS
NEWLOK:	SETZM	EVAADR		;CLEAR POINTER TO FUNNY SPACE BUFFER
	SETZM	MSGLIN		;CLEAR MESSAGE LINE NUMBER
	TLZ	F,L.DUMP!L.UUO!L.SAVE!L.UPMP!L.OPR ;CLEAR ASSORTED BITS
	SETZM	ERPTBK+2	;DEFAULT CPU NUMBER CORRECTLY FOR OLD MONITOR
	SETZM	ERPTBK+3	;...
	MOVS	T1,ERPTSZ	;GET LENGTH OF ENTRY IN LH
	HRRI	T1,ERPTBK	;GET ADDRESS OF BLOCK FOR ERRPT. UUO
	ERRPT.	T1,		;ASK MONITOR FOR NEXT ERROR TO REPORT
	  JRST	DALOKJ		;NO MORE, GO LOOK AT JOBS
	PUSHJ	P,DSPERR	;DISPATCH TO CORRECT ROUTINE OFF CODE IN T1
	JRST	NEWLOK		;AND LOOP BACK FOR MORE
;ROUTINE TO SET UP AND DISPATCH TO APPROPRIATE REPORTING
;ROUTINE FROM CODE RETURNED IN T1 BY
;ERRPT. UUO.  

DSPERR:	LDB	T2,[POINT 9,(T1),35]	;GET CODE INTO T2
	LDB	J,[POINT 9,(T1),26]	;[544] GET JOB NUMBER, IF ANY
	JUMPLE	T2,JOBFIN		;IGNORE IF OUT OF
	CAILE	T2,DSPMAX		; RANGE
	JRST	JOBFIN
	JRST	@DSPTAB(T2)		;DISPATCH ON CODE

DSPTAB:	PJRST	JOBFIN	;0-ILLEGAL CODE
	SRLERR		;1-SYSTEM RELOAD
	SCNSTD		;2-CONTINUABLE MONITOR ERROR
	SCPERR		;3-CPU MEMORY PARITY (NOT KL)
	SNXMER		;4-NON-EXISTENT MEMORY (NOT KL10)
	PJRST	JOBFIN	;5-EXTRACTED CRASH INFO, NOT REPORTED THIS WAY
	CHNERR		;6-CHANNEL ERROR
	PJRST	JOBFIN	;7-DAEMON STARTED, NOT REPORTED THIS WAY
	SDVERR		;10-RP10,RC10 DISK ERROR
	SMDVER		;11-MASS BUS DEVICE ERROR
	DX2ERR		;12-DX20 DEVICE ERROR
	PJRST	JOBFIN	;13-NOT IMPLEMENTED
	SWEERR		;14-SOFTWARE EVENT OF INTEREST (POKE, SNOOP., ETC)
	SCSCER		;15-CONFIGUATION STATUS CHANGE
	PJRST	JOBFIN	;16-SYSTEM ERROR LOG, NOT REPORTED THIS WAY
	SDIERR		;17-SOFTWARE REQUEST
	PJRST	JOBFIN	;20-NOT IMPLEMENTED
	STPERR		;21-TAPSER MAGTAPE ERROR
	PJRST	JOBFIN	;22-NOT IMPLEMENTED
	PJRST	JOBFIN	;23-NOT IMPLEMENTED
	PJRST	JOBFIN	;24-NOT IMPLEMENTED
	PJRST	JOBFIN	;25-NOT IMPLEMENTED
	PJRST	JOBFIN	;26-NOT IMPLEMENTED
	PJRST	JOBFIN	;27-NOT IMPLEMENTED
	KLEERR		;30-KL10 FRONT END ERROR DATA
	PJRST	JOBFIN	;31-FRONT-END RELOAD, NOT REPORTED THIS WAY
	PJRST	JOBFIN	;32-NOT IMPLEMENTED
	PJRST	JOBFIN	;33-KS10 HALT STATUS BLOCK, NOT REPORTED THIS WAY
	PJRST	JOBFIN	;34-NOT IMPLEMENTED
	PJRST	JOBFIN	;35-NOT IMPLEMENTED
	PJRST	JOBFIN	;36-NOT IMPLEMENTED
	PJRST	JOBFIN	;37-NOT IMPLEMENTED
	PJRST	JOBFIN	;40-DISK STATISTICS, NOT REPORTED THIS WAY
	PJRST	JOBFIN	;41-NOT IMPLEMENTED
	STPERR		;42-TAPE STATISTICS FOR TAPSER
	PJRST	JOBFIN	;43-MAX CONFIGURATION IN AVAIL.SYS, NOT REPORTED THIS WAY
	PJRST	JOBFIN	;44-MONITOR RUN VALUES IN AVAIL.SYS, NOT REPORTED THIS WAY
	PJRST	JOBFIN	;45-DISK STATISTICS (USUALLY FROM A CRASH)
	PJRST	JOBFIN	;46-BEGINNING OF AVAIL.SYS TIMESTAMP
	PJRST	JOBFIN	;47-END OF AVAIL.SYS TIMESTAMP
	SDIERR		;50-DL10 ERROR
	KPARNX		;51-KI PARITY/NXM INTERRUPT (7.01)
	KPARNX		;52-KL PARITY/NXM INTERRUPT (7.01)
	PJRST	JOBFIN	;53-NOT IMPLEMENTED
	KLSTRP		;54-KS NXM TRAP (7.01)
	KLSTRP		;55-KL/KS PARITY TRAP (7.01)
	NXMSWP		;56-NXM SWEEP (7.01)
	PARSWP		;57-PARITY SWEEP (7.01)
	PJRST	JOBFIN	;60-NOT IMPLEMENTED
	SKLTRP		;61-KL10 DATA PARITY TRAP
	SCPERR		;62-KL10 CPU PARITY INTERRUPT ERROR
	CSBERR		;63-CPU STATUS BLOCK
	DSBERR		;64-DEVICE STATUS BLOCK
	PJRST	JOBFIN	;65-NOT IMPLEMENTED
	PJRST	JOBFIN	;66-NOT IMPLEMENTED
	SNXMER		;67-KL10 ADDRESSING FAILURE
	SDIERR		;70-IMPLEMENTED FOR PCL20 REPORTING
	SDIERR		;71-LP100 REPORT [550]
	SDIERR		;72-UNIT RECORD DEVICE ERROR
	PJRST	JOBFIN	;73-NOT IMPLEMENTED
	PJRST	JOBFIN	;74-NOT IMPLEMENTED
	PJRST	JOBFIN	;75-NOT IMPLEMENTED
	PJRST	JOBFIN	;76-NOT IMPLEMENTED
	PJRST	JOBFIN	;77-NOT IMPLEMENTED
DSPMAX=.-DSPTAB
;INITIALLY PUSHJ HERE IF A JOB IS PAUSED FOR US
;THIS WILL FREE THAT JOB IN CASE OF FATAL ERROR OR WHEN WE POPJ

PROTJB:	PUSH	P,[PROTJ1]	;[544] [565] GET PLACE TO GO ON CRASH
	POP	P,INTADR	;[544] AND PUT IT IN INTADR
	POP	P,(P)		;[544] TAKE RETURN ADDR OFF STACK
	PUSHJ	P,@1(P)		;[544] AND CALL CALLER
;AUTOMATICALLY RETURN HERE WHEN DONE.  THE USER IF FREED.
;	PJRST	JOBFIN		;[544] FINISH UP


;SUBROUTINE TO RESTART JOB WAITING FOR ERROR TO BE REPORTED
;ARGS	J=JOB NUMBER

JOBFIN:	HRLZI	T1,(J)		;[527] GET JOB NUMBER INTO LH OF T1
	IFN .GTSTS,<HRRI T1,.GTSTS>	;SET UP TO GET JOBS JBTSTS WORD
	PUSHJ	P,GTBSPY
	  SETZ	T1,		;OH WELL
	TRNN	T1,JS.DEP	;IS JOB WAITING?
	POPJ	P,		;[565 -PUT IT BACK] NOPE, RETURN
	MOVEI	T1,J		;GET ADDR OF ARGUMENT FOR DAEFIN
	DAEFIN	T1,		;AND SET JOB FREE
	  AOS	FINGUF		;REMEMBER # OF LOSSAGES
	POPJ	P,


;HERE IF DAEMON CRASH BEFORE USER FREED

PROTJ1:	PUSHJ	P,JOBFIN	;[544] FINISH UP
	JRST	DALOOK		;[544] CONTINUE
SUBTTL LOOK FOR A JOB REQUIRING DAEMON SERVICE

DALOKJ:	HRRZ	J,HJOB		;J=HIGHEST JOB NUMBER IN SYSTEM
DALOO1:	TLZ	F,L.DUMP!L.SAVE!L.NHRL!L.OPR ;CLEAR DUMP FLAG AND SAVE FLAG
	MOVEM	J,CURJOB	;SAVE LAST JOB EXAMINED FOR DEBUG
	HRROI	T1,.GTSTS
	PUSHJ	P,GTBSPY	;GET JBTSTS WORD FOR JOB
	  JRST	DALOO2		;CANT GET IT?
	TRNE	T1,JDC		;IF JOB WANTS SERVICE FOR A COMMAND
	JRST	DASERV		;GO SERVICE IT
	LDB	T2,QUECOD	;GET CODE FOR DAEMON QUEUE
	CAMN	T2,DAQNAM	;SKIP IF NO IN DAEMON QUEUE
	JRST	UUSERV		;GO PROCESS THE UUO
	TRNN	T1,JS.DPM	;IF JOB HAS BEEN WAITING FOR A MINUTE
	JRST	DALOO2		; AND WE DID NOT PROCESS IT, RELEASE
	AOS	DPMCNT		; IT SO THAT THE OPR DOESN'T GET
	MOVEM	J,DPMJOB	; OBSCURE MESSAGES
	JRST	DETUSR
DALOO2:	SOJG	J,DALOO1	;LOOP FOR ALL JOBS IN SYSTEM
	TLZE	F,L.ANY		;SKIP IF NO JOBS FOUND
	JRST	DALOOK		;DID SOMETHING, GO THROUGH AGAIN

IFN FTFACT!FTCHKPNT,<
	MOVE	T1,[%NSKTM]
	PUSHJ	P,GTBSPY	;CHECK FOR KSYS SOON
	  SETZ	T1,		;IF CAN'T GET IT, ASSUME NOT
	JUMPE	T1,.+2		;NO KSYS--CHECK FORCE BIT
	SOJLE	T1,.+2		;IF PAST, OR LESS THAN 1 MINUTE, FORCE
	TLZE	F,L.FORC	;SHOULD WE FORCE OUT THE FACT BUFFER?
	SKIPN	T1,FACTSZ	;YES, IF ANYTHING IN IT
	JRST	NXTWAK		;NO, OR NOTHING THERE
	HRLZI	P1,(T1)		;SIZE IN P1 LEFT
	HRRI	P1,FACTBF	;POINTER
	PUSHJ	P,APPEND	;GET RID OF IT
	JRST	DALOOK
NXTWAK:				;[64]
>;END OF FTFACT!FTCHKPNT COND
;HERE TO CHECK FOR EXPIRED CLOCK REQUESTS

	SKIPN	T2,NEXTUP	;[64]GET THE NEXT JOB TO WAKE
	JRST	ZZZ		;THERE WAS NONE
	PUSHJ	P,GETUPT	;GET THE UPTIME IN TICKS
	SUB	T2,T1		;GET THE DIFFERENCE
	JUMPLE	T2,WAKJOB	;WAKE ANY JOBS THAT NEED IT,
				; AND RESCAN FROM DALOOK
	IMUL	T2,MILJIF	;CONVERT TO MILLISECONDS
	TLNE	T2,-1		;IS LEFT HALF EMPTY?
	MOVEI	T2,-1		;NO, SET MAX SLEEP TIME

ZZZ:
	MOVEI	T1,SLPTIM	;TIME TO SLEEP
	HRLI	T2,(HB.RWJ!HB.RTL)	;ONLY MONITOR CAN WAKE US
	HIBER	T2,		;HIBERNATE
	  SLEEP	T1,		;ON SECOND THOUGHT SLEEP
	JRST	DALOOK		;NOW LOOK AGAIN
DAEREE:	TLO	F,L.INI		;AVOID DETACH ON REENTER
DAEREN:	SKIPE	CRSHAC+P	;ALREADY HAVE THE AC'S?
	JRST	DAERE1		;YES, DON'T OVERWRITE THEM
	MOVEM	17,CRSHAC+17	;SAVE AC 17
	MOVEI	17,CRSHAC	;MAKE BLT POINTER
	BLT	17,CRSHAC+16	;SAVE THE REST
DAERE1:	TLNN	F,L.INI		;IN INITIALIZATION?
	SKIPE	.JBDDT		;  OR DDT LOADED?
	JRST	DAERE2		;YES, DON'T DETACH
	SETOM	T1		;INDICATE OUR LINE
	GETLCH	T1		;GET CURRENT LINE
	HRLZS	T1		;SETUP FOR DETACH
	ATTACH	T1,		;MAKE SURE WE ARE DETACHED
	  JFCL			;NOT ATTACHED
DAERE2:	SETZM	.JBINT		;DO NOT INTERCEPT EXIT (ESTOP2 CODE)
	MOVSI	T1,(SIXBIT /DAE/)	;**[103] MAKE NAME DAE
	SETNAM	T1,		;CHANGE THE NAME TO CHEAT THE SYSTEM
	RESET			;KILL PSI INTERRUPTS IF ANY
	EXIT			;FORGET THE THING
;HERE TO PROCESS JOB ISSUING DAEMON UUO

;FOR DAEMON UUO'S:
;P1=USER LOCATION EXECT1=EXEC AC T1, AND CONTAINS FUNCTION REQUESTED
;P2=USER LOCATION EXECT2=EXEC AC T2, AND CONTAINS +LENGTH,ADDR OF ARGUMENT LIST

;DAEMON RETURNS BY STORING AN ERROR CODE (OR THE ORIGINAL CONTENTS OF EXECT2)
;IN EXECT1 (NOTE, T1), WHICH WILL BE PASSED BACK TO THE USER IN HIS
;CALLING REGISTER, AND 0 IN EXECT2 FOR A SUCCESSFUL (SKIP) RETURN,
;OR NON-ZERO IN EXECT2 FOR A NON-SKIP RETURN.

UUSERV:	SETZM	EVAADR		;CLEAR FUNNY SPACE ADDRESS
	MOVEM	J,UUOJOB	;SAVE JOB NUMBER FOR DEBUGGING
	TLO	F,L.ANY!L.UUO	;SOMETHING HAPPENED, A UUO
	MOVEI	T1,DETUSR	;NEW RESTART ADDRESS
	MOVEM	T1,INTADR
	SETZM	THSOFF		;OFFSET=0 FORLOW SEGMENT
	MOVSI	T1,.JBDA	;GET JOB DATA AREA
	MOVE	T2,J		;JOB NUMBER
	PUSHJ	P,GTUCOR	;GET JOB'S JOB DATA AREA
	MOVE	T1,EXECT1	;GET ADDRESS IN JOBDAT OF EXEC T1
	MOVE	P1,USRCOR(T1)	 ;EXEC AC T1=FUNCTION REQUESTED
	MOVEM	P1,UUOFNC	;SAVE FUNCTION FOR DEBUGGING
	JUMPLE	P1,UUERR1	;- OR 0 IS ILLEGAL
	CAILE	P1,MAXFNC	;SKIP IF LEGAL FUNCTION
	JRST	UUERR1		;TOO BIG
	MOVE	P2,USRCOR+1(T1) ;P2=XWD
	MOVEM	P2,SAVXWD	;SAVE XWD
	JRST	@FNCADR-1(P1)	;CALL ROUTINE TO PROCESS REQUEST

FNCADR:
	EXP	DMPUUO		;.DCORE WRITE A DCORE FILE
	EXP	CLKUUO		;.CLOCK WAKE A JOB IN THE FUTURE
	EXP	FCTUUO		;.FACT APPEND TO FACT FILE
	EXP	UUERR1		;4 (.DMQUE) RESERVED FOR QUEUE FUNCTION
	EXP	EAPUUO		;5 (.DMERR) APPEND TO ERROR.SYS
MAXFNC==.-FNCADR
;HERE FOR .DCORE FUNCTION
;CALL:
;	MOVE	AC,[XWD ARGLEN,ARGLST]
;	DAEMON	AC,
;	  ERROR RETURN
;	GOOD RETURN
;ARGLST:1	;.DCORE
;	DEVICE	;0 IMPLIES DSK
;	FILNAM	;0 IMPLIES NNNDAE WHERE NNN IS JOB # ISSUEING UUO
;	EXT	;0 IMPLIES TMP
;	PROT	;0 IMPLIES MONITOR DEFAULT
;	PPN	;OR POINTER TO PATH SPEC. 0 IMPLIES DEFAULT PATH.
;		;RESERVED FOR JOB # TO DUMP

DMPUUO:
	HRROI	T1,.GTSTS	;GET THIS GUY'S JOB STATUS
	PUSHJ	P,GTBSPY
	  SETZ	T1,		;OOPS
	LDB	T1,QUECOD	;GET WAIT STATE CODE
	CAME	T1,DAQNAM	;IF NOT IN DAEMON QUEUE, FUNNY RACE
	JRST	NULEXT		;JUST FINISH QUIETLY
	MOVE	T1,P2		;T1=XWD
	TLNN	T1,-1		;WAS LENGTH GIVEN?
	HRLI	T1,1		;NO, DEFAULT EVERYTHING
	HLRZ	T2,T1		;COPY NUMBER OF ARGUMENTS
	CAILE	T2,6		;MORE THAN 6 ARGUMENTS
	JRST	UUERR3		;YES--WRONG NUMBER OF ARGS
	PUSHJ	P,UADCHK	;CHECK ADDRESS
	  JRST	UUERR2		;INVALID ADDRESS
	PUSHJ	P,GTUCOR	;COPY  HIM INTO ME
	SKIPN	T1,USRCOR+1	;GET DEVICE NAME
	MOVSI	T1,'DSK'	;NONE--USE DSK:
	MOVEM	T1,D.DEV	;STORE AWAY
	SKIPE	T4,USRCOR+2	;GET FILE NAME
	JRST	WASFNM		;THER WAS ONE SO DO NOT REINVENT
	MOVEI	T2,(J)		;JOB NUMBER
	PUSHJ	P,MAKPJN	;MAKE CCL NUMBER
	HRRI	T4,'DAE'	;DEFAULT FILENAME
WASFNM:	MOVEM	T4,D.NAM	;STORE FILENAME
	SKIPN	T1,USRCOR+3	;GET EXTENSION
	MOVSI	T1,'TMP'	;DEFAULT EXTENSION
	MOVEM	T1,D.EXT	;STORE EXTENSION
	LDB	T1,[POINT 9,USRCOR+4,8] ;GET PROTECTION
	MOVEM	T1,D.PROT		;STORE PROTECTION
	SKIPE	T1,USRCOR+5	;GET PPN
	JRST	CHKPTH		;HANDLE PATH OR PPN
	PUSHJ	P,GETPTH	;READ USER'S DEFAULT PATH
	JRST	STOPPN		;STORE THE PPN
CHKPTH:	TLNE	T1,-1		;IS THIS A PATH POINTER, OR A PPN?
	JRST	[TLNE	T1,400000	;[605] SIGN BIT ON?
		 JRST	UUER10		;[605] YES,BOMB HIM
		JRST	STOPPN]		;[605] HE'S CLEAN
	ADDI	T1,.PTPPN	;PATH POINTER, IGNORE FIRST .PTPPN WORDS
	HRLI	T1,.PTMAX-.PTPPN-1 ;READ UP TO MAX LENGTH
	PUSHJ	P,UADCHK	;VALIDATE PATH ADDRESS
	  JRST	UUERR2		;BOMB NOW
	PUSHJ	P,GTUCOR	;READ PATH SPEC
	MOVSI	T1,-.PTMAX+.PTPPN+1 ;READ THIS MANY WORDS
	MOVE	T2,USRCOR(T1)	;[605] GET PPN FROM PATH BLOCK
	TLNE	T2,400000	;[605] SIGN BIT ON?
	 JRST	UUER10		;[605] YES,OUT HE GOES
CPYPTH:	SKIPN	T2,USRCOR(T1)	;PICK NEXT WORD OF PATH SPEC
	JRST	ENDPTH		;ZERO MARKS END
	MOVEM	T2,D.DPTH+.PTPPN(T1)	;STORE FOR OUR PURPOSES
	AOBJN	T1,CPYPTH	;COPY MORE IF WE HAVE ROOM
	JRST	UUER10		;NOTE INVALID PATH TO USER

ENDPTH:	SETZM	D.DPTH+.PTPPN(T1)	;FLAG END OF PATH
	MOVEI	T1,D.DPTH	;SETUP DIRECTORY POINTER
STOPPN:	MOVEM	T1,D.DIR	;STORE DIRECTORY
	JRST	NODEFT		;DUMP. NO NEED TO SETUP DEFAULTS
;HERE FOR .CLOCK FUNCTION
;CALL:
;	MOVE	AC,[XWD ARGLEN,ARGLST]
;	DAEMON	AC,
;	  ERROR RETURN
;	GOOD RETURN
;ARGLST:2	;.CLOCK
;	# SECS BEFORE WAKE ;OVERRIDES ANY PENDING REQUEST, 
;			; 0 IMPLIES IMMEDIATE WAKE

CLKUUO:	MOVE	T1,P2		;T1=XWD
	TLNN	T1,-1		;LENGTH GIVEN?
	HRLI	T1,2		;NO, DEFAULT TO 2
	HLRZ	T2,T1		;COPY THE LENGTH
	CAILE	T2,2		;NEED 2 ARGS, 0 IMPLIES 2
	JRST	UUERR3		;WRONG NUMBER OF ARGUMENTS
	PUSHJ	P,UADCHK	;CHECK THE ADDRESS
	  JRST	UUERR2		;ADDRESS CHECK
	PUSHJ	P,GTUCOR	;READ HIS CORE IMAGE
	MOVE	T1,USRCOR+1	;GET THE TIME
	PUSHJ	P,CLKREQ	;PUT IN QUEUE
	JRST	UUOKX		;EXIT
;HERE FOR .FACT FUNCTION
IFG FTFACT,<

FCTUUO:
	HRROI	T1,.GTSTS	;GET JOB'S STATUS
	PUSHJ	P,GTBSPY	;GO READ THE MONITOR
	  JRST	UUERR4		;YOU CAN'T WIN THEM ALL
	TLNE	T1,JACCT	;LOGIN OR LOGOUT
	JRST	GTFACT		;YES--WIN
	PUSHJ	P,GETPPN	;GET CALLER'S PPN
	CAME	T1,OPRPPN	;ARE YOU A GOOD GUY?
	JRST	UUERR6		;NO--GET LOST
GTFACT:	PUSHJ	P,BUFAGE	;MARK TIME OF FIRST FACT ENTRY
	MOVE	T1,P2		;PICK UP XWD
	TLNN	T1,-1		;WAS LENGTH GIVEN?
	HRLI	T1,1		;NO, DEFAULT TO TEST NOP
	PUSHJ	P,UADCHK	;VALIDATE THE BLOCK AND SET UP FOR GTUCOR
	  JRST	UUERR2		;INVALID
	HLRZ	T4,T1		;COPY LENGTH
	SOJL	T4,UUERR3	;TOO SHORT
	CAILE	T4,TRNSIZ	;TOO LONG
	JRST	UUERR3		;YES--WRONG NUMBER OF ARGS
	JUMPE	T4,UUOKX	;ALLOW A 0-LENGTH WRITE, AS A TEST NOP UUO
	HRL	T1,T4		;PUT BACK NEW LENGTH
	AOJ	T1,		;BUMP POINTER PAST FUNCTION
	PUSHJ	P,GTUCOR	;GET USER'S ARGUMENT LIST=FACT FILE ENTRY IN USRCOR
	SKIPN	T1,USRCOR+2	;DID USER PROVIDE DATE AND TIME?
	PUSHJ	P,NBSDAT	;NO, GET IT NOW
	MOVEM	T1,USRCOR+2	;AND INSERT IT IN BUFFER
	HLRZ	T1,P2		;[63]GET LENGTH OF ARG LIST
	MOVE	T2,USRCOR	;PICK UP HEADER WORD FOR VALIDITY CHECKING
	TLZE	T2,777000	;CHECK FOR AND CLEAR TYPE IDENTIFIER
	TLZN	T2,777		;SAME FOR JOB #.  WERE BOTH GIVEN?
	JRST	UUERR7		;NO, REFUSE REQUEST
	ANDI	T2,77		;REMOVE LINE NO
	CAIE	T2,-1(T1)	;AND VERIFY LENGTH ACCURACY
	JRST	UUERR7		;REFUSE ON ANY SUCH ERROR
	HRRZ	T1,FACTSZ	;ADDR IN FACT FILE BUFFER TO STORE
	ADDB	T2,FACTSZ	;NEW SIZE OF BUFFER CONTENTS
	MOVEI	T1,FACTBF(T1)	;"TO" ADDR IN FACT FILE BUFFER
	HRLI	T1,USRCOR	;"FROM" IS CORE COPIED FROM CALLER
	BLT	T1,FACTBF-1(T2)	;TRANSFER TO FACT FILE BUFFER
	CAIG	T2,MAXFCT	;TOO MUCH IN BUFFER?
	JRST	UUOKX		;NO--GIVE OK RETURN
	HRLZI	P1,(T2)		;SIZE OF WHOLE MESS
	HRRI	P1,FACTBF	;POINTER TO BEGINING
	PUSHJ	P,APPEND	;UPDATE FACT.SYS
	JRST	UUOKX		;RETURN TO USER

>;END COND ON FTFACT
;HERE FOR APPEND TO ERROR.SYS FUNCTION

;CALL:
;	MOVE AC,[XWD ARGLEN,ARGLST]
;	DAEMON	AC,
;	  ERROR RETURN
;	GOOD RETURN
;ARGLST:5	;.DMERR
;	CODE		;CODE FOR ENTRY IN ERROR FILE
;	BODY		;BLOCK OF ARGLEN-2 WORDS TO PUT IN ERROR FILE

EAPUUO:	HRROI	T1,.GTSTS	;GET JOB'S STATUS
	PUSHJ	P,GTBSPY	;GO READ THE MONITOR
	  JRST	UUERR4		;YOU CAN'T WIN THEM ALL
	MOVE	T2,T1		;SAVE THE WORD
	HRROI	T1,.GTPRV	;GET PRIVILEGE WORD
	PUSHJ	P,GTBSPY	;GET IT
	  JRST	UUERR4		;SHOULDN'T HAPPEN
	TLNN	T1,(JP.POK)	;POKE PRIVILEGE?
	TLNE	T2,JACCT	;PRIVLEGED?
	JRST	EAPUU1		;YES--WIN
	PUSHJ	P,GETPPN	;GET CALLER'S PPN
	CAME	T1,OPRPPN	;ARE YOU A GOOD GUY?
	JRST	UUERR6		;NO--GET LOST
EAPUU1:	MOVE	T1,P2		;GET XWD INTO T1
	HLRE	T2,T1		;[533] GET LENGTH INTO T2
	JUMPLE	T2,UUERR3	;WRONG NUMBER  OF ARGS
	CAIN	T2,1		;[533] ONLY 1 ARG (NULL ENTRY)?
	  JRST	UUOKX		;[533] YES, GOOD RETURN BUT DO NOTHING
	CAILE	T2,MAXUCR	;[533] ARG BIGGER THAN OUR BUFFER?
	  JRST	UUERR3		;[533] YES, WRONG NUMBER OF ARGS
	PUSHJ	P,UADCHK	;CHECK ADDRESS
	  JRST	UUERR2		;ILLEGAL ADDRESS
	PUSHJ	P,GTUCOR	;GO READ HIS CORE
	MOVE	T1,USRCOR+1	;GET CODE FOR ERROR FILE INTO T1
	LSH	T1,^D27		;[533] AND SHIFT IT TO GOOD PLACE
	PUSHJ	P,ERRINB	;GO PUT HEADER IN BUFFER
	HLRZ	T2,P2		;[533] RESTORE LENGTH OF ARG BLOCK
	SUBI	T2,2		;MAKE T2 NUMBER OF DATA WORDS OF ENTRY
	JUMPE	T2,EAPUU2	;[533] SKIP ON IF NO DATA
	HRLS	T2		;PUT IT INTO BOTH HALVES
	HRRZI	T1,1(P4)	;[533] GET FIRST WORD TO TRANSFER TO INTO  T1
	HRLI	T1,USRCOR+2	;AND FROM INTO LH
	ADD	P4,T2		;UPDATE PUSHDOWN PONTER TO ERROR BUFFER
	JUMPG	P4,UUERR3	;[533] CHECK FOR OVERFLOW OF IOWD
	BLT	T1,(P4)		;AND BLT STUFF TO BUFFER
	MOVE	T1,USRCOR+1	;GET CODE FOR THIS ERROR
	CAIE	T1,.ESFER	;CONSOLE FRONT END RELOAD?
	CAIN	T1,.ESNDL	;  OR DOWN LINE LOAD?
	CAIA			;YES
	CAIN	T1,.ESNUD	;  OR UP LINE DUMP?
	TRO	F,R.AVL		;YES, APPEND IT TO AVAIL.SYS ALSO
EAPUU2:	PUSHJ	P,ERRFIN	;WRITE ENTRY AND CLOSE FILE
	JRST	UUOKX		;GIVE GOOD RETURN
UUER10:	MOVEI	T1,DMPTH%	;INVALID PATH SPEC
	JRST	UUERRX

UUERR7:	MOVEI	T1,DMFFB%	;FACT FORMAT BAD
	JRST	UUERRX

UUERR6:	MOVEI	T1,DMNPV%	;NO PRIVS TO DO THAT UUO
	JRST	UUERRX		;EXIT

UUERR5:	MOVEI	T1,DMCWF%	;CAN'T WRITE FILE
	JRST	UUERRX		;EXIT

UUERR4:	MOVEI	T1,DMSNH%	;SHOULD NEVER HAPPEN
	JRST	UUERRX		; BUT...

UUERR3:	MOVEI	T1,DMWNA%	;WRONG NUMBER OF ARGS
	JRST	UUERRX

UUERR2:	MOVEI	T1,DMACK%	;ADDRESS CHECK
	JRST	UUERRX		;ERROR EXIT

IFL FTFACT,<FCTUUO:	>
UUERR1:	MOVEI	T1,DMILF%	;ILLEGAL FUNCTION ERROR CODE
;	JRST	UUERRX


;HERE FOR DAEMON UUO ERRORS, T1=ERROR CODE

UUERRX:	SETOM	USRCOR+1	;NOTE ERROR IN FUNCTION
	MOVE	P,PDL		;RESTORE P, SINCE ERROR MAY HAVE BEEN
				;AT ANY LEVEL ON THE STACK
	JRST	UUEXIT		;AND EXIT UUO

;HERE WHEN FUNCTION COMPELETED PROPERLY, T1=RETURN CODE

IFE FTFACT,<FCTUUO:	>
UUOKX:	SETZM	USRCOR+1	;NOTE FUNCTION COMPLETED PROPERLY
	MOVE	T1,SAVXWD	;GET OLD CONTENTS OF USERS REG
UUEXIT:	MOVEM	T1,USRCOR	;STORE CODE TO RETURN TO USER
	MOVEM	T1,UUXCOD	;SAVE FOR DEBUGGING
	MOVEM	J,UUXJOB	;  ALONG WITH THE JOB NUMBER
	MOVSI	T1,2		;WRITE 2 WORDS
	HRR	T1,EXECT1	;AT EXEC T1 IN USER'S JOBDAT
	MOVE	T2,J		;WRITE IN JOB'S LOW SEGMENT
	SETZM	THSOFF		;NO OFFSET
	AOSG	WTUERR		;CHECK FOR RECURSION IN EXIT PROCESS
	PUSHJ	P,WTUCOR	;WRITE USER'S CORE
	SETOM	WTUERR		;RESET FLAG
	JRST	DETUSR		;AND FINISH USER'S REQUEST
SUBTTL PROCESS JOB REQUESTING DAEMON SERVICE


DASERV:	SETZM	EVAADR		;CLEAR FUNNY SPACE ADDRESS
	SETZM	MSGLIN		;CLEAR MESSAGE LINE NUMBER
	TLZ	F,L.UUO!L.UPMP!L.OPR ;NOT A UUO, NO UPMP IN CORE
	TRNE	T1,JS.DEP	;IF IN ERROR PAUSE
	AOS	JDPCNT		;NOTE WE NOTICED
	TRNN	T1,JDC		;IF NOT COMMAND REQUEST,
	JRST	EDUMP1		;RESTART THE JOB


;HERE TO PROCESS COMMAND WHICH INVOKED DAEMON

	MOVEM	J,CMDJOB	;SAVE JOB NUMBER FOR DEBUGGING
	MOVEI	T1,DETUSR	;NEW RESTART ADDRESS
	MOVEM	T1,INTADR
	TLO	F,L.ANY		;NOTE THAT WE DID SOMETHING
	PUSHJ	P,GETTTY	;GET JOB'S TTY NUMBER
	  JRST	DETUSR		;CAN'T FIND IT
	JUMPGE	T1,HAVLIN	;GO UNLESS CTY
	SKIPGE	T1,CTYLIN	;GET CTY LINE NO IF KNOWN
	JRST	DETUSR		;OTHERWISE, MUST GIVE UP

HAVLIN:	HRLM	T1,LINE		;SAVE LINE NUMBER, IT MAY BE USEFUL
	MOVEI	T2,.UXTRM(T1)	;GET UDX OF TERMINAL
	MOVEM	T2,MSGLIN	;SAVE FOR MESSAGES

;HERE SHOULD CHECK FOR CTL/C IN JOB STATUS, DETUSR IF SET

	HRLOS	T1		;LH=LINE NUMBER, RH=DAEMON JOB
	PUSH	P,T1		;SAVE AC FOR ATTACH BELOW
	HRROI	T1,.GTJLT	;GETTAB TO RETURN LOGIN TIME
	PUSHJ	P,GTBSPY	;GET IT
	  MOVEI	T1,0		;FAILED, USE 0
	MOVEM	T1,JOBJLT	;SAVE FOR REATTACH CHECK
	POP	P,T1		;RESTORE LINE NUMBER
	ATTACH	T1,		;ATTACH USER TTY TO US
	  JRST	DETUSR		;GIVE UP IF CANT ATTACH USER'S TTY
	TLO	F,L.TTYA	;NOTE TTY ATTACHED
	MOVEI	T1,EDCORE	;NEW RESTART ADDRESS
	MOVEM	T1,INTADR

	HRROI	T1,.GTWCH	;WATCH BITS TABLE
	PUSHJ	P,GTBSPY
	  SETZ	T1,		;FEATURE PROBABLY OFF
	TLNE	T1,(JW.WVR)	;IS VERSION WATCHING ENABLED?
	PUSHJ	P,PDAEVR	;YES, PRINT DAEMON VERSION
;HERE TO SET UP DEFAULTS FOR CORE-IMAGE FILE NAME

	MOVSI	T1,'DSK'	;DEVICE DSK
	MOVEM	T1,D.DEV
	MOVE	T2,J
	PUSHJ	P,MAKPJN	;COMPUTE SIXBIT JOB NUMBER IN LH
	MOVEM	T4,CCLFIL	;SAVE SIXBIT JOB NUMBER
	HRRI	T4,'DAE'	;NAME DAE
	MOVEM	T4,D.NAM	;IS FILE NAME
	MOVSI	T1,'TMP'	;EXTENSION
	MOVEM	T1,D.EXT
	HRROI	T1,.GTDFL	;[536] GETTAB DEFAULT PROTECTION
	PUSHJ	P,GTBSPY	;[536] GET IT
	  SETZ	T1,		;[536] NOT IMPLEMENTED
	ROT	T1,^D9		;[536] MOVE PROTECTION TO LOW ORDER 9 BITS
	SKIPL	T1		;[536] CODE VALID IF BIT 9 SET
	  TRZ	T1,777		;[536] NOT VALID, USE DEFAULT
	HRRZM	T1,D.PROT	;[536] SAVE FOR LATER
	PUSHJ	P,GETPTH	;READ USER'S PATH
	MOVEM	T1,D.DIR	;STORE POINTER AS DIRECTORY

;HERE ON, CODE IS COMMON TO UUO AND COMMAND

NODEFT:	PUSHJ	P,GETPPN	;PICK UP USER'S PPN
	MOVEM	T1,USRPPN	;SAVE FOR ACCESS CHECKING

;HERE TO SET SEARCH LIST TO BE SAME AS USER'S JOB

	MOVE	T2,T1		;USER'S PPN
	MOVE	T1,J		;JOB NUMBER
	MOVEI	T3,USRLST+3	;SPACE RESERVED FOR USER'S SEARCH LIST
	PUSHJ	P,GETSRC	;GET USER'S SEARCH LIST
	HRRZS	T3		;LAST ADDRESS STORED IN
	MOVEI	T1,USRLST	;RE-GET USER LIST ADDRESS
	SUBI	T3,USRLST-1	;T3=LENGTH-1 OF LIST
	HRLI	T1,(T3)		;FUNCTION, ETC, ALREADY SET UP IN USRLST
	STRUUO	T1,		;SET OUR SEARCH LIST TO BE SAME AS USER'S
	  WARN	<Can't set to user search list>

;HERE TO INITIALIZE COMMAND SCANNER

	TLNN	F,L.UUO		;IS THIS THE UUO
	PUSHJ	P,ATTCHK	;JUST MAKE SURE USER DIDN'T MANAGE TO DETACH
	  JRST	DAEOPN		;IF HE DID, ASSUME DCORE AND DON'T GO INTO TI WAIT
	MOVE	S1,[IOWD COMLEN,COMLST] ;TABLE OF MONITOR COMMANDS
	PUSHJ	P,.ISCAN	;INITIALIZE COMMAND SCANNER
	MOVEM	S1,CMDCMD	;SAVE COMMAND INDEX FOR DEBUGGING
	JUMPGE	S1,@COMDSP(S1)	;DISPATCH IF VALID COMMAND
	ERROR	<Unknown DAEMON command>
	JRST	EDCORE
;HERE IF E COMMAND.  CALLED ONLY IF VIRTUAL MEMORY USER ON 6.01 AND LATER MONITORS

ECOM:	PUSHJ	P,SAVE4		;SAVE P1-P4
	MOVE	T2,J		;GET JOB NUMBER INTO T2
	MOVSI	T1,BLKSIZ	;SIZE OF BLOCK ON SWAPPING SPACE
	SETZM	THSOFF		;CLEAR OFFSET OF SEGMENT
	PUSHJ	P,GTUCOR	;GET JOB DATA AREA+
	MOVE	T1,[%CNEXM]
	PUSHJ	P,GTBSPY	;GET ADDRESS OF JOBEXM
	  JRST	EDUMP		;???
	HRRZ	P4,USRCOR(T1)	;GET ADDRESS TO EXAMINE(ALREADY UPDATED BY COMCON)
	PUSHJ	P,HSVADR	;GO GET START AND END ADDRESSES OF HIGHSEG
	SETZM	THSOFF		;CLEAR OFFSET IN CASE OF LOW SEG
	CAML	P4,HGHOFF	;ADDRESS BELOW START OF HIGH SEG?
	CAMLE	P4,HGHREL	;OR ABVE END OF HIGH SEG?
	JRST	ECOM2		;ADDRESS IS IN LOW SEG,WE'RE ALL SET
	MOVE	T1,HGHOFF	;NO, ADDRESS IS IN HIGH SEG
	MOVEM	T1,THSOFF	;STORE OFFSET FOR SEGMENT TO EXAMINE
	SUB	P4,THSOFF	;MAKE P4 RELATIVE TO BEGINNING OF SEGMENT
	HRROI	T1,.GTSGN	;[532] JBTSGN FOR JOB IN J
	PUSHJ	P,GTBSPY	;GET HIGH SEGMENT NUMBER
	  JFCL			;???
	SKIPA	T2,T1		;GET SEGMENT NUMBER TO T2
ECOM2:	MOVE	T2,J		;LOW SEGMENT, USE JOB NUMBER
	MOVSI	T1,1		;SET TO GET ONE WORD
	HRRI	T1,(P4)		;ADDRESS TO EXAMINE
	PUSHJ	P,GTUCOR	;GET THE WORD
	HRRZ	T1,P4		;GET ADDRESS TO EXAMINE
	PUSHJ	P,TOCTAL	;OUTPUT TO TTY
	TELL	</	>,NOCRLF
	HLRZ	T1,USRCOR	;GET LH TO TYPE
	PUSHJ	P,TOCTAL	;
	TELL	< >,NOCRLF	;PRINT A SPACE
	HRRZ	T1,USRCOR	;GET RH
	PUSHJ	P,TOCTAL	;OUTPUT
	PUSHJ	P,TABDOT	;TYPE A TAB AND A DOT
	PUSHJ	P,DMPBUF	;DUMP MESSAGE BUFFER
	JRST	EECOM		;AND EXIT
;HERE IF D COMMAND.  USED ONLY FOR VIRTUAL MEMORY JOBS IF 6.01 AND LATER MONITOR

DCOM:	PUSHJ	P,SAVE4		;SAVE P1-P4
	MOVE	T2,J		;GET JOB NUMBER INTO T2
	MOVSI	T1,BLKSIZ	;GET SIZE OF DISK BLOCK
	SETZM	THSOFF		;CLEAR OFFSET OF SEGMENT
	PUSHJ	P,GTUCOR	;GET JOB DATA AREA+
	PUSHJ	P,OCTINW	;GET LH TO DEPOSIT
	MOVSI	P4,(SN)		;AND SAVE IN P4
	PUSHJ	P,OCTINW	;GET RH TO DEPOSIT
	HRRI	P4,(SN)		;STORE IN RH(P4)
	PUSH	P,P4		;AND SAVE ON STACK
	MOVE	T1,[%CNEXM]
	PUSHJ	P,GTBSPY	;GET ADDRESS OF JOBEXM
	  JRST	EDUMP		;???
	HRRZ	P4,USRCOR(T1)	;GET ADDRESS TO DEPOSIT INTO
	PUSHJ	P,HSVADR	;SET UP START AND END OF HIGH SEG
	SETZM	THSOFF		;CLEAR OFFSET IN CASE LOW SEG
	CAML	P4,HGHOFF	;ADDRESS BELOW START OF HIGH SEG?
	CAMLE	P4,HGHREL	;OR ABOVE END OF HIGH SEG?
	JRST	DCOM2		;ADDRESS IS IN LOW SEG, WE'RE ALL SET
	MOVE	T1,HGHOFF	;GET OFFSET FOR HIGH SEG
	MOVEM	T1,THSOFF	;AND SAVE IT AS OFFSET FOR THIS SEGMENT
	SUB	P4,T1		;MAKE P4 RELATIVE TO START OF HIGH SEG
	HRROI	T1,.GTSGN	;[532] JBTSGN
	PUSHJ	P,GTBSPY	;GET HIGH SEGMENT NUMBER FOR JOB
	  JFCL			;???
	SKIPA	T2,T1		;GET INTO T2 FOR WTUCOR
DCOM2:	MOVE	T2,J		;JOB NUMBER FOR LOW SEGMENT
	MOVSI	T1,1		;SET TO WRITE ONE WORD
	HRRI	T1,(P4)		;ADDRESS TO WRITE TO T1
	POP	P,USRCOR	;GET CONTENTS OFF STACK
	PUSHJ	P,WTUCOR	;WRITE THE WORD
	JRST	EDCORE		;AND RETURN
;HERE ON VERSION COMMAND FOR HIGH SEGMENT THAT IS NOT IN CORE.  USED
;ONLY FOR VIRTUAL MEMORY JOBS ON 6.01 AND LATER MONITORS.

VERCOM:	PUSHJ	P,SAVE4		;SAVE P1-P4
	MOVE	T2,J		;GET JOB NUMBER
	MOVSI	T1,BLKSIZ	;SIZE OF DISK BLOCK
	SETZM	THSOFF		;SET UP TO LOOK AT LOW SEGMENT
	PUSHJ	P,GTUCOR	;GET JOB DATA AREA INTO CORE
	MOVE	P4,USRCOR+.JBVER ;GET LOW SEGMENT VERSION NUMBER INTO P4
	HRROI	T1,.GTPRG	;[532] PROGRAM NAME FOR JOB IN J
	PUSHJ	P,GTBSPY	;GET JBTNAM
	  JFCL			;???
	MOVE	P3,T1		;SAVE LOW SEGMENT VERSION NUMBER IN P3
	HRROI	T1,.GTSGN	;[532]
	PUSHJ	P,GTBSPY	;GET JOB'S HIGH SEGMENT NUMBER
	  JFCL			;???
	MOVE	P2,T1		;SAVE HIGH SEGMENT NUMBER IN P2
	PUSHJ	P,HSVADR	;GET RELOC/PROT FOR HIGH SEG
	MOVE	T1,HGHOFF	;GET ADDRESS OF START OF HIGH SEGMENT
	MOVEM	T1,THSOFF	;AND SAVE IN THSOFF
	MOVE	T1,HGHREL	;GET TOP ADDRESS OF HIGH SEGMENT
	MOVEM	T1,SEGREL	;AND SAVE
	MOVE	T2,P2		;GET SEGMENT NUMBER
	MOVSI	T1,BLKSIZ	;GET SIZE OF DISK BLOCK
	PUSHJ	P,GTUCOR	;READ IN LOW 128 WORDS OF HIGH SEG
	MOVS	T1,P2		;GET HIGH SEG NUMBER
	HRRI	T1,.GTPRG	;JBTNAM
	PUSHJ	P,GTBSPY	;GET NAME OF HIGH SEG
	  JFCL			;???
	SKIPN	T2,T1		;WAS THERE ONE
	MOVEI	P1,USRCOR	;GET ADDRESS OF  BUFFER 
	MOVE	T2,.JBHNM(P1)	;NO, GET FROM USER'S CORE IMAGE
	SKIPE	T1,.JBHVR(P1)	;GET HIGH SEG VERSION
	CAMN	T1,P4		;COMPARE TO LOW IF PRESENT
	CAME	T2,P3		;COMPARE LOW NAME
	JRST	VERCM1		;DIFFERENT, MUST PRINT
	JRST	VERCM5		;SAME, JUST GET OUT
;HERE WHEN IT IS DETERMINED THAT WE MUST TYPE SOMETHING TO USER

VERCM1:	MOVE	P1,T1		;SAVE VERSION
	PUSHJ	P,TSIXN		;PRINT HIGH SEGMENT NAME
	TELL	< >,NOCRLF	;FOLLOWED BY A SPACE
	MOVE	T1,P1		;RESTORE VERSION
	LSH	T1,-^D24	;GET MAJOR VERSION NUMBER
	ANDI	T1,777		;ELIMINATE GARBAGE
	SKIPE	T1
	PUSHJ	P,TOCT		;PRINT MAJOR VERSION NUMBER
	HLRZ	T1,P1		;GET MINOR VERSION NUMBER
	ANDI	T1,77		;REMOVE GARBAGE
	JUMPE	T1,VERCM3	;JUMP IF NO MINOR 
	SUBI	T1,1
	IDIVI	T1,^D26
	JUMPE	T1,VERCM2
	PUSH	P,T2
	MOVEI	SC,"A"-1(T1)
	PUSHJ	P,TYPCHR
	POP	P,T2
VERCM2:	MOVEI	SC,"A"(T2)
	PUSHJ	P,TYPCHR
VERCM3:	HRRZ	T1,P1		;GET EDIT NUMBER
	JUMPE	T1,VERCM4	;NO EDIT NUMBER?
	TELL	<(>,NOCRLF	;PRINT LEFT PAREN
	PUSHJ	P,TOCT		;PRINT EDIT NUMBER
	TELL	<)>,NOCRLF	;PRINT RIGHT PAREN
VERCM4:	LSH	P1,-^D33	;GET CUSTOMER VERSION NUMBER
	JUMPE	P1,VERCM5	;IF NONE, CRLF.
	TELL	< - >,NOCRLF
	MOVEI	SC,"0"(P1)	;GET VERSION NUMBER
	PUSHJ	P,TYPCHR
VERCM5:	JRST	EDCORE		;AND EXIT
;HERE IF DUMP COMMAND - REWRITE COMMAND AS DUMP CCL FILE
;NOTE: FILE MUST BE ON DSK, NOT TMPCOR, BECAUSE TMPCOR
; CANNOT COMMUNICATE ACROSS JOBS.

DUMP:	TLO	F,L.DUMP	;NOTE DUMP
	MOVSI	T1,DSK+<(FO.PRV)> ;CHANNEL NUMBER AND INVOKE PRIVS
	HRRI	T1,.FOWRT	;WRITE FUNCTION
	MOVEM	T1,D.FLOP+.FOFNC ;STORE IN BLOCK
	MOVEI	T1,.IOASC	;MODE IS ASCII
	MOVEM	T1,D.FLOP+.FOIOS ;STORE IN BLOCK
	MOVE	T1,D.DEV	;GET DEVICE ON WHICH TO WRITE
	MOVEM	T1,D.FLOP+.FODEV ;STORE IN BLOCK
	MOVSI	T1,C.BH		;OUTPUT BUFFER HEADER
	MOVEM	T1,D.FLOP+.FOBRH ;STORE IN BLOCK
	MOVSI	T1,1		;USE ONE OUTPUT BUFFER
	MOVEM	T1,D.FLOP+.FONBF ;STORE IN BLOCK
	MOVEI	T1,D.LKB	;POINT TO ENTER BLOCK
	MOVEM	T1,D.FLOP+.FOLEB ;STORE IN BLOCK
	SETZM	D.FLOP+.FOPAT	;NO PATH POINTER
	MOVE	T1,USRPPN	;GET PPN OF USER WHO WOULD WRITE
	MOVEM	T1,D.FLOP+.FOPPN ;STORE IN BLOCK FOR PRIV CHECK
	SETZM	D.LKB		;CLEAR FIRST WORD OF ENTER BLOCK
	MOVE	T1,[D.LKB,,D.LKB+1] ;MAKE BLT POINTER
	BLT	T1,D.LKB+.RBSIZ	; CLEAR THE BLOCK
	MOVE	T1,CCLFIL	;GET LH OF CCL FILE NAME
	HRRI	T1,'DMP'	;MAKE IT NNNDMP
	MOVEM	T1,D.LKB+.RBNAM	;STORE IN BLOCK
	MOVSI	T1,'TMP'	;EXTENSION IS TMP
	MOVEM	T1,D.LKB+.RBEXT	;STORE IN BLOCK
	MOVE	T1,D.DIR	;GET PPN OR PATH POINTER
	MOVEM	T1,D.LKB+.RBPPN	;STORE IN BLOCK
	MOVEI	T1,.RBSIZ	;LEN OF WORDS TO FOLLOW
	MOVEM	T1,D.LKB+.RBCNT	;STORE IN BLOCK
	PUSH	P,.JBFF		;SAVE .JBFF
	MOVEI	T1,SECBUF	;PUT BUFFER HERE
	MOVEM	T1,.JBFF	;FAKE OUT THE MONITOR
	MOVE	T1,[.FOPPN+1,,D.FLOP] ;POINT TO BLOCK
	FILOP.	T1,		;OPEN THE FILE
	  JRST	[POP	P,.JBFF ;RESTORE POINTER TO .JBFF
		 JRST	E.CCLE]	;AND GIVE ERROR
	POP	P,.JBFF		;RESTORE .JBFF

	CAIN	SC," "		;COMMAND SCANNER STOP ON A BLANK?
	PUSHJ	P,STYIA		;YES, FLUSH THEM
	JUMPL	SC,QUIKIE	;USE QUICKIE DUMP IF DUMP <CR>
CLOOP:	JUMPL	SC,CDONE	;ALL DONE IF AT END OF LINE
	CAIE	SC,"/"		;THIS A SLASH
	JRST	CLOOP1		;NO
	PUSHJ	P,CCCRLF	;YES, TRANSLATE IT TO A CRLF
	JRST	CLOOP2		;AND JOIN COMMON CODE
CLOOP1:	PUSHJ	P,CCOUT		;OUTPUT THE CHARACTER
CLOOP2:	PUSHJ	P,TYIA		;GET THE NEXT CHARACTER
	JRST	CLOOP		;AND LOOP FOR NEXT

QUIKIE:	MOVE	T1,[POINT 7,QIKNAM]
QUIKI1:	ILDB	SC,T1		;NEXT CHARACTER OF NAME
	JUMPE	SC,CDONE
	PUSHJ	P,CCOUT		;OUTPUT CHARACTER
	JRST	QUIKI1

CDONE:	PUSHJ	P,CCCRLF	;END THE LAST LINE
	MOVEI	T1,DSK		;[535] SET UP CHANNEL
	PUSHJ	P,RELDSK	;[535] AND GO RELEASE IT
	JRST	DAEOPN		;GO WRITE DAEMON FILE
;HERE IF SAVE OR SSAVE COMMAND.  CALLED ONLY IF VIRTUAL MEMORY
;USER ON 6.01 OR LATER MONITORS.

SAVE:	TLO	F,L.SAVE	;NOTE SAVE IN PROGRESS
	PUSHJ	P,SAVE4		;SAVE P1-P4
	MOVE	T2,J		;GET JOB NUMBER INTO T2
	MOVSI	T1,MAXUCR	;FILL THE INPUT BUFFER
	SETZM	WRDCNT		;CLEAR COUNT OF OUTPUT FILE
	SETZM	REMBLK		;CLEAR REGISTER TO HOLD BLOCK FOR LAST IOWD
	SETZM	REMWRD		;LAST ADDRESS FOR IOWD
	SETZM	THSOFF		;CLEAR OFFSET FOR THIS SEGMENT
	PUSHJ	P,GTUCOR	;GET JOB DATA AREA +
	MOVEI	P1,USRCOR	;SET UP INDEX TO JOB DATA AREA
	MOVE	T1,.SGDEV(P1)	;GET DEVICE TO DO THE SAVE ON
	MOVEM	T1,D.DEV	;AND SAVE ON ARGUMENT LIST
	MOVE	T1,.SGNAM(P1)	;GET NAME OF SAVED FILE
	MOVEM	T1,D.NAM	;AND SAVE
	SKIPE	T1,.SGPPN(P1)	;USE DEFAULT PATH IF USER GAVE NO PPN
	TLNE	T1,-1		;SETUP PATH BLOCK IF THIS IS A POINTER
	JRST	SAVE00		;EITHER 0 OR PPN, JUST STORE
	ADDI	T1,(P1)		;POINT TO START OF PPN IN OUR CORE
	HRLI	T1,D.DPTH	;MAKE SWAPPED BLT POINTER
	MOVSS	T1		;SWAP THE HALVES
	BLT	T1,D.DPTH+.PTMAX-1 ;BLT THE PATH BLOCK TO OUR CORE
	MOVEI	T1,D.DPTH	;AND POINT TO THE BLOCK
SAVE00:	SKIPE	T1		;USE DEFAULT IF NO PPN OR POINTER
	MOVEM	T1,D.DIR	;STORE PPN OR POINTER
	MOVE	P3,SGAHGH(P1)	;GET HIGH SEGMENT EXTENSION
	HLLZM	P3,D.EXT	;AND SAVE FOR HIGH SEGMENT SAVE
	MOVE	P4,.SGLOW(P1)	;SAVE LOW SEGMENT EXTENSION FOR LATER
	HRROI	T1,.GTSGN	;[532] GETTAB INDEX TO JBTSGN
	PUSHJ	P,GTBSPY	;GET THE HIGH SEGMENT NUMBER FOR THIS JOB
	  JFCL			;???
	MOVE	P2,T1		;SAVE SEGMENT NUMBER FOR LATER
	PUSHJ	P,HSVADR	;GET RELOC/PROT FOR HIGH SEG
	JUMPLE	P2,SAVE04	;JUMP IF NO HIGH SEGMENT
	TLNE	P2,JSHR		;SHARABLE HIGH SEGMENT?
	JRST	SAVE01		;YES, DONT SAVE DATA FOR VESTIGIAL JOB DATA AREA
	MOVS	T1,P2		;NO, GET DATA FOR VESTIGIAL JOB DATA AREA
	HRRI	T1,.GTUPM	;INDEX TO JBTUPM
	PUSHJ	P,GTBSPY	;GET POINTER TO UPMP
	  JFCL			;???
	LDB	T2,[POINT 9,T1,8] ;GET JBYHSO BYTE
	PUSH	P,T2		;AND SAVE ON STACK
	PUSH	P,D.NAM		;SAVE .SGNAM
	PUSH	P,.JBVER(P1)	;SAVE VERSION NUMBER
	HRR	T2,.JBREN(P1)
	HLL	T2,.JBHRL(P1)
	PUSH	P,T2
	PUSH	P,.JBCOR(P1)
	PUSH	P,.JB41(P1)
	PUSH	P,.JBSA(P1)	;ALL DATA FOR VESTIGIAL JOB DATA AREA NOW SAVED
SAVE01:	MOVE	T1,HGHOFF	;GET ADDRESS OF START OF HIGH SEGMENT
	MOVEM	T1,THSOFF	;AND STORE FOR CALL TO GTUCOR
	MOVE	T1,HGHREL	;GET LAST ADDRESS OF HIGH SEG
	HLRZ	T2,.JBHRL(P1)	;GET LENGTH OF HIGH SEG
	MOVEM	T1,SEGREL	;SAVE SIZE OF HIGH SEGMENT
	SKIPE	T2		;IF LH(.JBHRL)NON ZERO,
	MOVEM	T2,SEGREL	;THEN THATS WHAT WE USE
	SKIPN	T1		;IF LH(.JBHRL)=0,
	TLO	F,L.NHRL	; THEN REMEMBER FOR LATER
	MOVE	T2,P2		;GET SEGMENT NUMBER TO T2
	MOVSI	T1,MAXUCR	;SET UP TO GET FIRST BLOCK OF HIGH SEG INTO CORE
	PUSHJ	P,GTUCOR	;GET THE BLOCK
	TLNE	P2,JSHR		;SHARABLE HIGH SEGMENT??
	JRST	SAVE02		;YES, NO NEED TO SET UP VESTIGIAL JOB DATA AREA
	MOVEI	T1,USRCOR-1	;SET UP POINTER
	POP	P,T2		;GET BACK .JBSA
	PUSH	T1,T2		;AND STORE IN VESTIGIAL JOB DATA AREA
	POP	P,T2		;GET BACK .JB41
	PUSH	T1,T2		;AND STORE
	POP	P,T2		;GET .JBCOR
	PUSH	T1,T2
	POP	P,T2		;GET .JBREN & .JBHRL
	PUSH	T1,T2
	POP	P,T2		;GET .JBVER
	PUSH	T1,T2
	POP	P,T2		;GET .SGNAM
	PUSH	T1,T2
	AOBJN	T1,.+1
	PUSH	T1,[EXP 0]
	POP	P,T2		;GET BACK JBYHSO BYTE
	DPB	T2,[POINT 9,(T1),17] ;AND STORE
SAVE02:	JRST	DAEOPN		;AND GO OPEN HIGH SEGMENT SAVE FILE

;HERE TO PROCESS DCORE COMMAND

DCORE:	JUMPL	SC,DAEOPN	;USE DCORE DEFAULTS IF NO NAME SPECIFIED
	PUSHJ	P,FILIN		;GET FILE NAME TO WRITE
	  JRST	EDCORE		;[536] COMMAND ERROR, FINISH UP
	SKIPE	T1,F.DEV 	;[536] SKIP IF NO DEVICE
	MOVEM	T1,D.DEV
	SKIPE	T1,F.NAM	;[536] SKIP IF NO NAME SPECIFIED
	MOVEM	T1,D.NAM
	JUMPE	T1,DCORE1	;JUMP IF NO NAME SPECIFIED
	MOVSI	T1,'DAE'	;IF FILE NAME SPECIFIED, DEFAULT EXT IS DAE
	MOVEM	T1,D.EXT
DCORE1:	SKIPE	T1,F.EXT	;[536] SKIP IF NO EXT SPECIFIED
	MOVEM	T1,D.EXT
	SKIPE	T1,F.DIR	;SKIP IF NO DIRECTORY SPECIFIED
	MOVEM	T1,D.DIR
SUBTTL WRITE CORE-IMAGE FILE

;HERE TO OPEN CORE-IMAGE FILE

DAEOPN:	MOVE	T1,D.DEV	;DEVICE TO WRITE ON
	DEVCHR	T1,		;GET DEVICE CHARACTERISTICS
	TLNN	T1,(DV.DSK)	;SKIP IF IT IS A DISK
	  JRST	E.NDSK		;NOT A DISK
	TLNE	T1,(DV.MTA)	;IS IT ALSO A MAG TAPE?
	JRST	[TLNE F,L.SAVE	;YES, MUST BE NULL
		 JRST SAVE10	;FINISH SAVE
		 TLNE F,L.DUMP	;DUMP OR DCORE?
		 JRST EDUMP	;FINISH DUMP
		 JRST EDCORE	;FINISH DCORE
		]
	PUSHJ	P,DELETE	;DELETE ANY EXISTING FILE
	MOVSI	T1,DSK+<(FO.PRV)> ;DSK CHANNEL PLUS PRIVS
	HRRI	T1,.FOMAU	;FUNCTION IS MULTI-ACCESS UPDATE
	MOVEM	T1,D.FLOP+.FOFNC ;STORE IN BLOCK
	MOVEI	T1,.IODMP	;DUMP MODE
	MOVEM	T1,D.FLOP+.FOIOS
	MOVE	T1,D.DEV	;GET DEVICE NAME
	MOVEM	T1,D.FLOP+.FODEV
	SETZM	D.FLOP+.FOBRH	;NO BUFFER HEADERS
	SETZM	D.FLOP+.FONBF	;  AND NO COUNT
	MOVEI	T1,D.LKB	;ADDRESS OF LOOKUP BLOCK
	MOVEM	T1,D.FLOP+.FOLEB
	SETZM	D.FLOP+.FOPAT	;NO PATH BLOCK
	MOVE	T1,USRPPN	;GET PPN OF USER WHO WOULD WRITE
	MOVEM	T1,D.FLOP+.FOPPN
	SETZM	D.LKB		;ZERO FIRST WORD OF ENTER BLOCK
	MOVE	T1,[D.LKB,,D.LKB+1] ;MAKE BLT POINTER
	BLT	T1,D.LKB+.RBSIZ	;CLEAR THE BLOCK
	MOVE	T1,D.NAM	;GET FILENAME
	MOVEM	T1,D.LKB+.RBNAM	;SAVE IN BLOCK
	HLLZ	T1,D.EXT	;GET EXTENSION
	MOVEM	T1,D.LKB+.RBEXT
	HRLZ	T1,D.PROT	;GET PROTECTION
	LSH	T1,^D9		;POSITION IT
	MOVEM	T1,D.LKB+.RBPRV
	MOVEI	T1,.RBSIZ	;COUNT OF WORDS TO FOLLOW
	MOVEM	T1,D.LKB+.RBCNT
	MOVEI	P1,5		;NUMBER OF TIMES TO RETRY IF FILE BEING MODIFIED
DAEOP1:	MOVE	T1,D.DIR	;GET PPN OR POINTER
	MOVEM	T1,D.LKB+.RBPPN
	HLLZS	D.LKB+.RBEXT	;CLEAR ANY ERROR CODE
	MOVE	T1,[.FOPPN+1,,D.FLOP] ;POINT TO BLOCK
	FILOP.	T1,		;CREATE THE FILE
	  JRST	[PUSHJ	P,FBMTRY ;CHECK FOR ERFBM%
		   JRST	DAEOP1	;IS, RETRY
		 JRST	E.DAEF]
	SETZM	CURWRD		;START AT WORD 0
	SETZB	BP,CURBLK	;START AT FIRST BLOCK OF FILE
	MOVEI	T1,NOHGH1	;NEW RESTART ADDR
	MOVEM	T1,INTADR
	TLNE	F,L.SAVE	;SKIP IF NOT DOING A SAVE
	JRST	SAVE03		;ARE, CONTINUE
SUBTTL WRITE JOB INFORMATION

;HERE TO WRITE JOB INFORMATION

	MOVEI	T1,.CAJOB	;CATEGORY NUMBER FOR JOB INFORMATION
	PUSHJ	P,CATSTA	;START UP CATEGORY
	MOVE	T1,.JBVER	;(0)DAEMON VERSION NUMBER
	PUSHJ	P,DWRITE	;WRITE IT
	DATE	T1,		;(1)TODAY'S DATE
	PUSHJ	P,DWRITE	;WRITE THAT
	MSTIME	T1,		;(2)TIME OF DAY IN MILLISECONDS
	PUSHJ	P,DWRITE	;WRITE IT
	HRROI	T1,.GTSGN	;SEGMENT TABLE
	PUSHJ	P,GTBSPY	;GET HIGH SEGMENT NUMBER IF ANY
	  SETZ	T1,
	MOVE	S,T1		;SAVE SEGMENT NUMBER IN S
	HRL	T1,J		;(3)LH=JOB NUMBER, RH=SEGMENT NUMBER
	PUSHJ	P,DWRITE	;WRITE THAT
	HLRZ	T1,LINE		;(4)LH=RESERVED, RH=LINE NUMBER
	PUSHJ	P,DWRITE	;AND WRITE THAT

;HERE TO WRITE GETTAB ENTRIES FOR JOB

	SKIPL	P1,[-GTTBLN,,GTTABL] ;SKIP IF ANY GETTABS WANTED
	JRST	GTTBJE		;NO GETTABS DESIRED
GTTBLP:	HLRZ	T2,(P1)		;T2=INDEX INTO ROUTINE
	HRRZ	T1,(P1)		;T1=GETTAB TABLE
	PUSHJ	P,WGTBTH(T2)	;GET JOB OR SEGMENT OR BOTH
	AOBJN	P1,GTTBLP	;LOOP FOR GETTABS DESIRED

;HERE AFTER ALL GETTABS FOR JOB WRITTEN - WRITE SYSTEM GETTABS

GTTBJE:	PUSHJ	P,CATEND	;END OF JOB INFORMATION CATEGORY

;HERE TO WRITE CONFIGURATION TABLE

	MOVEI	T1,.CACNF	;BEGIN CONFIGURATION TABLE CATEGORY
	PUSHJ	P,CATSTA
	MOVEI	P1,.GTCNF
	PUSHJ	P,GTTBAL	;WRITE ALL OF TABLE
	PUSHJ	P,CATEND	;END OF CONFIGURATION CATEGORY

;HERE TO WRITE FEATURE TABLE

	MOVEI	T1,.CAFET	;BEGIN FEATURE TABLE CATEGORY
	PUSHJ	P,CATSTA	;INITIALIZE IT
	MOVEI	P1,.GTFET	;THE TABLE WE WANT
	PUSHJ	P,GTTBAL	;DUMP IT ALL
	PUSHJ	P,CATEND	;END OF CATEGORY
SUBTTL WRITE DDB'S FOR JOB

;HERE TO WRITE ALL DDB'S FOR THIS JOB.  WE FOLLOW THE LOW CORE DDB
;CHAIN INSTEAD OF LOOKING AT USRJDA BECAUSE USRJDA ONLY POINTS TO
;THOSE DDB'S WHICH HAVE A CHANNEL ASSIGNED.  WE ALSO DUMP ALL
;FUNNY SPACE DDB'S BY FOLLOWING THE CHAIN POINTED TO BY .UPLST IN
;THE UPMP.


	MOVEI	T1,.CADDB	;CATEGORY NUMBER FOR DDB'S
	PUSHJ	P,CATSTA	;START UP THE CATEGORY
	MOVE	T1,[%CNDEV]
	PUSHJ	P,GTBSPY	;GET PTR TO LIST OF DDB'S
	  SKIPA			;UNLIKELY
	PUSHJ	P,DMPDDB	;DUMP ALL DDB'S FOR THIS JOB
	PUSHJ	P,GTUPMP	;GET UPMP FOR THIS JOB
	  JRST	DDBCA2		;CAN'T, GIVE UP
	SKIPE	T1,.UPLST	;HAVE THE OFFSET FOR .UPLST?
	SKIPN	T1,USRUPM(T1)	;YES, HAVE ANY DDB'S IN FUNNY SPACE
	SKIPA			;NO
	PUSHJ	P,DMPDDB	;DUMP THOSE ALSO
DDBCA2:	PUSHJ	P,CATEND	;END OF DDB CATEGORY
SUBTTL WRITE LOW SEGMENT AND HIGH SEGMENT IF ANY

;HERE WHEN ALL DDB'S DONE, GATHER CORE FROM JOB'S LOW SEGMENT

EDDBS:	MOVEI	T1,.CACOR	;CATEGORY NUMBER FOR USER CORE
	PUSHJ	P,CATSTA	;START UP CATEGORY
	SETZM	THSOFF		;OFFSET FOR THIS SEGMENT=0
	HRLZI	T1,MAXUCR	;GET FIRST BLOCK OF USER CORE
	HRRZ	T2,J		;SEGMENT NUMBER=JOB NUMBER
	PUSHJ	P,GTUCOR	;GET THE CORE
	MOVE	T1,J		;GET JOB NUMBER INTO T1
	PUSHJ	P,JSSIZE	;GET SIZE OF LOW SEGMENT
	  JRST	EDUMP		;???
	MOVEM	T1,SEGREL	;=SIZE OF THIS SEGMENT
	PUSHJ	P,HSVADR	;GET START AND END OF HI SEG
	MOVEI	T1,.JBHRL	;ADDR OF .JBHRL
	SKIPN	USRCOR(T1)	;GET SIZE OF HI SEG FROM .JBHRL IN JOBDAT
			;IF ITS ZERO,EDIT 465
	SETZM	HGHREL		;REMEMBER FOR LATER
	MOVE	T1,J
	SETZB	T2,USRADR	;START COMPRESSION AT LOCATION 0
	PUSHJ	P,COMPRS	;OUTPUT LOW SEGMENT AS ZERO-COMPRESSED DATA

;HERE TO WRITE HIGH SEGMENT IF ANY

	SKIPN	T1,HGHREL	;SKIP IF ANY HIGH SEGMENT
	JRST	NOHIGH
	JUMPLE	S,NOHIGH	;EVEN IF HIGH SEG MUST KNOW ITS NUMBER
	MOVEM	T1,SEGREL	;SIZE OF HIGH SEGMENT
	MOVE	T1,HGHOFF	;OFFSET FOR HIGH SEGMENT
	MOVEM	T1,THSOFF	;=SIZE OF THIS SEGMENT
	HRLZI	T1,MAXUCR
	HRRZ	T2,S		;SEGMENT NUMBER FOR HIGH SEGMENT
	PUSHJ	P,GTUCOR	;GET FIRST BLOCK OF HIGH SEGMENT
	SETZB	T2,USRADR	;START COMPRESSION AT ADDRESS 0 IN SEGMENT
	MOVE	T1,S
	PUSHJ	P,COMPRS	;WRITE HIGH SEGMENT AS ZERO-COMPRESSED DATA
SUBTTL CLOSE OUT CORE-IMAGE FILE AND FINISH UP

;HERE WHEN ALL DATA WRITTEN

NOHIGH:	MOVE	T1,PATTERN	;END FILE WITH STANDARD PATTERN
	PUSHJ	P,DWRITE
	PUSHJ	P,CATEND
	JUMPGE	BP,NOHGH1	;JUMP IF NEVER WROTE ANYTHING
	PUSHJ	P,BLKWRT	;WRITE LAST PARTIAL BUFFER
NOHGH1:

;HERE WHEN CORE-IMAGE FILE WRITTEN
	;FALL INTO RELEASE

;HERE TO FINISH OFF DCORE

EDCORE:	MOVEI	T1,DSK		;[536] SET UP CHANNEL
	PUSHJ	P,RELDSK	;[536] RELEASE IT
	TLNE	F,L.DUMP	;SKIP IF DCORE, NOT IF DUMP
	JRST	EDUMP
	TLNE	F,L.UUO		;SKIP IF COMMAND
	JRST	UUOKX		;IF UUO, QUIT NOW
	PUSHJ	P,CRLFPD	;PRINT <CR><LF>. TO INDICATE MONITOR MODE
	PUSHJ	P,DMPBUF	;DUMP BUFFER
EECOM:	MOVSI	T2,(AT.UMM)	;ENSURE RE-ATTACH IS AT MONITOR LEVEL
	IORM	T2,LINE		;BY SETTING BIT IN ATT FUNCTION

EDUMP:	TLNE	F,L.UUO		;ATTACHED?
	JRST	UUOKX		;NO--RETURN TO UUO.
	HRROI	T1,.GTJLT	;GETTAB FOR JOB LOGIN TIME
	PUSHJ	P,GTBSPY	;GET IT
	  MOVEI	T1,0		;FAILED, USE ZERO
	MOVEI	T2,(J)		;[610] GET JOB NUMBER
	TRMNO.	T2,		;[610] IS IT DETACHED?
	  CAME	T1,JOBJLT	;YES, LOGIN TIMES MATCH?
	JRST	[MOVSI	T2,-1	;[610] NO--DON'T REATTACH THIS JOB TO IT
		 JRST	EDUMP0] ;[610] JUST DETACH THIS JOB

	HLLZ	T2,LINE		;LH=LINE NUMBER OF USER'S TTY
	HRRI	T2,(J)		;RH=USER'S JOB NUMBER
EDUMP0:	SETZM	MSGLIN		;CLEAR MESSAGE LINE
	ATTACH	T2,		;[610]  GIVE USER BACK HIS TTY
	  ERROR <Can't reattach TTY to user job>,OPR
	TLZ	F,L.TTYA	;NOTE TTY NO LONGER ATTACHED

;HERE TO UUO USER OUT OF DAEMON REQUEST

DETUSR:	HRRZ	T1,.JBDDT	;ADDR OF DDT IF ANY
	JUMPE	T1,NOREAT	;DONT REATTACH ORIGINAL TTY IF NO DDT
	HRLZ	T1,THSLIN	;LH T1=OUR ORIGINAL LINE NUMBER
	HRR	T1,THSJOB	;RH=OUR JOB NUMBER
	TLO	T1,(AT.UUM)	;SET TO USER LEVEL
	ATTACH	T1,		;REATTACH TO OUR ORIGINAL LINE
	  AOS	ATTGUF
NOREAT:	MOVEI	T1,DALOOK	;NEW RESTART ADDR
	MOVEM	T1,INTADR
	TLNN	F,L.DUMP	;SKIP IF DUMP - MUST FORCE CCL RUN OF DUMP
	JRST	EDUMP1		;NO, DONT BOTHER
	MOVEI	T1,T2		;ADDRESS OF ARGUMENT LIST
	MOVE	T2,[SIXBIT /.DUMP/] ;COMMAND TO FORCE
	MOVE	T3,J		;JOB NUMBER
	FRCUUO	T1,		;FORCE COMMAND TO RUN DUMP AT CCL ENTRY POINT
	  AOS	FRCGUF		;DEBUG - COUNT SHOULD NEVER HAPPEN'S
EDUMP1:	MOVEM	J,DFNJOB	;SAVE JOB NUMBER FOR DEBUGGING
	MOVEI	T1,J		;T1=ADDRESS OF ARGUMENT LIST=JOB NUMBER
	DAEFIN	T1,		;ALL DONE, REQUE USER'S JOB
	  AOS	FINGUF		;DEBUG - NOTE AN SNH
	JRST	NULEXT		;FINISH UP
;HERE TO RESET SEARCH LIST TO ORIGINAL STATE

IFE FTSVSL,<	NULEXT=DALOO2	;IF DON'T CARE ABOUT SEARCH LIST, FORGET THIS>


IFN FTSVSL,<	;IF PRESERVING OUR SEARCH LIST
NULEXT:	MOVE	T1,PSRCH	;POINTER TO ORIGINAL SEARCH LIST
	STRUUO	T1,		;RESTORE ORIGINAL SEARCH LIST
	  AOSA	STRGUF		;[524] COUNT ERROR, SKIP
	    JRST DALOO2		;[524] I HAVE NO PROBLEMS WITH CRUMMY STRUUO!
	CAIE	T1,FSSNF%	;[524] RECOVERABLE IF FAILED BECAUSE UNIT NOT FOUND
	CAIN	T1,FSSSA%	;[524] OR IF FAILED BECAUSE UNIT SINGLE ACCESS
	  SKIPA	T1,PSRCH	;[524] THIS IS RECOVERABLE!  PICK UP POINTER
	    JRST DALOO2		;[524] GIVE UP
	HLRZ	T2,T1		;[524] GET LENGTH OF ARG LIST (=4+(3*# OF STR'S))
	IDIVI	T2,3		;[524] GETS # OF STR'S + 1 IN T2
	SOJE	T2,DALOO2	;[524] SNH -- CHECK FOR NO STR'S
NULEX1:	ADDI	T1,3		;[524] INCREMENT PTR BY ONE STR
NULX1A:	MOVEI	T3,1(T1)	;[524] T3 POINTS TO SIXBIT STR NAME
	HRLI	T3,.DCNAM+1	;[524] LH SHOWS SINGLE ARG FOR DSKCHR
	DSKCHR	T3,		;[524] GET BITS ABOUT THIS STR IN AC
	  JRST	NULEX2		;[524] STR MUST HAVE BEEN DISMOUNTED
	TLNN	T3,(DC.OFL!DC.SAF!DC.STS!DC.NNA)	;[524] CHECK FOR
				;[524]  ANYTHING BAD ABOUT THIS FILE STR
	  JRST	NULEX3		;[524] NO REASON IT SHOULD NOT BE ON OUR SEARCH LIST
NULEX2:	MOVSI	T3,-3		;[524] HERE TO REMOVE STR -- GET -3
	ADDB	T3,PSRCH	;[524] DECREMENT LENGTH OF ARG LIST, GET IN T3
	MOVEI	T4,1(T1)	;[524] T4 PNTS TO START OF BAD 3 WORD BLOCK
	SUBI	T4,(T3)		;[524] SUBTRACT BASE TO GET OFFSET
	HLRZ	T3,T3		;[524] GET NEW LENGTH IN T3
	SUBI	T3,(T4)		;[524] NOW SUBTRACT OFFSET TO SEE HOW MUCH TO BLT
	MOVEI	T4,1(T1)	;[524] NOW POINT TO BLOCK TO REMOVE
	HRLI	T4,3(T4)	;[524] LH OF BLT PTR SHOWS WHERE TO READ FROM
	ADDI	T3,-1(T4)	;[524] POINT TO LAST WORD TO WRITE TO
	CAIE	T2,1		;[524] IF THIS IS LAST STR, NOTHING TO WRITE
	  BLT	T4,(T3)		;[524] MOVE END OF STR LIST
	SOJG	T2,NULX1A	;[524] IF REMOVED STR, DON'T INCREMENT PTR
NULEX3:	SOJG	T2,NULEX1	;[524] LOOP FOR ALL STR'S
	MOVE	T1,PSRCH	;[524] NOW GET NEW (SHOULD BE, ANYWAY) PTR
	STRUUO	T1,		;[524] SET OUR SEARCH LIST
	  JRST	DALOO2		;[524] CAN'T DO IT
	SOS	STRGUF		;[524] WE ARE SAVED -- DON'T COUNT ERROR
	JRST	DALOO2		;[524] MOVING RIGHT ALONG ...
>	;END OF FTSVSL CONDITIONAL
SAVE03:	SKIPN	THSOFF		;HIGH SEGMENT SAVE?
	JRST	SAVE09		;NO,
	MOVE	T1,P2		;YES, GET SEGMENT NUMBER
	PUSHJ	P,SAVHGH	;SAVE THE HIGH SEGMENT
	CLOSE	DSK,		;AND CLOSE THE SAVE HIGH SEGMENT
	HRLZM	P3,D.EXT	;GET EXTENSION TO TRY TO DELETE
	PUSHJ	P,DELETE	;AND GO TRY
	MOVSI	T1,'SAV'	;GET EXTENSION .SAV
	MOVEM	T1,D.EXT	;AND SET UP TO DELETE
	PUSHJ	P,DELETE	;AND WIPE OUT ANY OLD .SAV FILES
	MOVE	T2,J
	MOVSI	T1,MAXUCR	;SIZE OF BLOCK ON SWAPPING SPACE
	SETZM	THSOFF		;CLEAR OFFSET FOR LOW SEGMENT
	PUSHJ	P,GTUCOR	;GET JOB DATA AREA
	JRST	SAVE05		;THEN GET DO LOW SEGMENT

SAVE04:	PUSHJ	P,DELETE	;NO HIGH SEGMENT, DELETE .SHR
	HRLZM	P3,D.EXT		;GET EXTENSION .HGH
	PUSHJ	P,DELETE	;AND WIPE OUT ANY OF THOSE
SAVE05:	MOVEI	P1,USRCOR	;SET UP POINTER TO JOB DATA AREA
	SKIPE	T1,SGAEXT(P1)	;DID USER SUPPLY AN EXTENSION?
	JRST	SAVE06		;YES, USE IT
	JUMPE	P2,SAVE07	;JUMP IF NO HIGH SEGMENT SAVED
	MOVSI	T1,'LOW'	;WAS A HIGH SEG, DELETE .LOW
SAVE06:	MOVEM	T1,D.EXT	;SAVE EXTENSION TO DELETE
	PUSHJ	P,DELETE	;AND TRY TO WIPE IT OUT
	JRST	SAVE08		;THEN DO LOW SEG
SAVE07:	SKIPN	T1,.SGLOW(P1)	;USER SUPPLIED A LOW EXTENSION?
	MOVSI	T1,'SAV'	;NO, USE .SAV
	MOVEM	T1,D.EXT	;STORE
SAVE08:	HLRZ	T1,.JBCOR(P1)	;GET LH OF JOBCOR
	CAIGE	T1,.JBDA	;IF NOT GREATER THAN END OF  JOBDAT
	JUMPN	SAVE11		;AND NOT 0,NO LOWSEG TO SAVE
	JRST	DAEOPN		;AND GO OPEN LOW SEGMENT SAVE FILE

SAVE09:	MOVEI	P1,USRCOR	;SET UP POINTER TO INPUT BUFFER
	MOVE	T1,.JB41(P1)	;GET USER'S UUO DISPATCH
	MOVEM	T1,.SG41(P1)	;AND SAVE
	MOVE	T1,.JBDDT(P1)	;GET DDT STARTING ADDRESS
	MOVEM	T1,.SGDDT(P1)	;AND SAVE
	MOVE	T1,.JBSA(P1)	;GET STARTING ADDRESS
	HRRZM	T1,STRADR	;AND SAVE FOR JRST WORD
	MOVEI	T2,.SGDDT	;ADDRESS AT WHICH TO START SAVE
	SETZM	USRADR
	JUMPE	P2,SAVE1A	;HAVE A HIGH SEGMENT?
	MOVE	T1,HGHREL	;GET END OF HIGH SEG
	HRLI	T1,1(T1)	;SET UP T1 LIKE .JBHRL
	ADD	T1,HGHOFF	; IS SET UP BY MONITOR
	HLRZ	T2,.JBHRL(P1)	;GET LH OF .JBHRL
	SKIPN	T2		;ONLY SAVE IF NOTHING THERE
	MOVEM	T1,.JBHRL(P1)	;NOT SET UP, SAVE IT AWAY
	MOVEI	T2,.SGDDT	;ADDRESS AT WHICH TO START SAVE
	MOVE	T1,HGHOFF	;GET START ADDRESS
	SUBI	T1,1		;POINT TO LAST ADDRESS OF PREVIOUS PAGE
	MOVEM	T1,SEGREL	;STORE HIGHEST ADDRESS TO COMPRESS
	MOVE	T1,J		;GET JOB NUMBER
	PUSHJ	P,COMPRS	;GO COMPRESS LOW PART OF LOW SEG
	MOVE	T2,J		;GET JOB NUMBER
	MOVSI	T1,MAXUCR
	HRR	T1,HGHREL	;GET TOP ADDRESS OF HIGH SEG
	ADD	T1,HGHOFF	;AND ADD OFFSET
	AOS	T1		;POINT TO START OF POTENTIAL HIGH PART OF LOW SEG
	PUSHJ	P,GTUCOR	;GET IT INTO BUFFER
	MOVE	T2,HGHREL	;GET END OF HIGH SEG AGAIN
	ADD	T2,HGHOFF	;AND ADD OFFSET
	AOS	T2
	MOVEM	T2,USRADR	;START COMPRESSION OF HIGH PART HERE
SAVE1A:	MOVEI	T1,-1		;AND SAVE TO TOP OF IMAGE
	MOVEM	T1,SEGREL
	MOVE	T1,J		;GET JOB NUMBER INTO T1 AGAIN
	PUSHJ	P,COMPRS	;WRITE OUT ZERO-COMPRESSED LOW SEG
	SKIPE	T1,STRADR	;WAS THERE A NON-ZERO START ADDRESS
	TLOA	T1,(JRST)	;YES, MAKE A JRST WORD
	MOVSI	T1,(HALT)	;NO, MAKE A HALT
	PUSHJ	P,DWRITE	;PUT IT IN OUTPUT FILE
	JUMPGE	BP,SAVE10	;JUMP IF NEVER WROTE ANYTHING
	PUSHJ	P,BLKWRT	;OUT ANY PARTIAL BUFFER REMAINING
SAVE10:	CLOSE	DSK,		;CLOSE FILE
SAVE11:	CLOSE	DSK,CL.DAT	;[536] CLOSE FILE BUT DON'T WRITE IT
	MOVE	T2,D.NAM	;[536] GET FILE NAME
	PUSHJ	P,TSIXN		;[536] TYPE IT
	TELL	< saved>,NOCRLF	;[536] PRINT REASSURING MESSAGE
	JRST	EDCORE		;END EXIT
SUBTTL ERRORS

E.GTBF:	ERROR	<Necessary GETTAB failed>,STOP

E.SPTR:	AOS	SPTGUF	;COUNT THE ERROR
	ERROR	<Can't get swapping pointer for job>,OPR
	PJRST	SNH

E.HSTS:	AOS	HSSGUF
	ERROR	<Can't get high segment status for job>,OPR
	PJRST	SNH

E.UPMP:	AOS	UPMGUF
	ERROR	<Can't get UPMP for job>,OPR
	PJRST	SNH

E.SOPN:	AOS	SUOGUF
	ERROR	<Can't OPEN swap unit >,NOCRLF
	MOVE	T2,T3		;GET SWAP UNIT NAME
	PUSHJ	P,TSIXN
	JRST	E.SWP1		;JOIN COMMON CODE

E.SWPE:	AOS	SWPGUF		;COUNT ERROR
	ERROR	<Swap pointer inconsistency >,NOCRLF
	MOVE	T2,SEGSWP	;GET THE POINTER
	PUSHJ	P,THALF		;TYPE AS HALFWORDS
E.SWP1:	PUSHJ	P,OCRLF		;FORCE MESSAGE TO OPR
	PJRST	SNH

E.NDSK:	PUSHJ	P,CWF		;CHECK FOR UUO
	ERROR	<File must be written on disk>
	JRST	E.DCOR

E.CCLE:	PUSHJ	P,CWF		;CHECK FOR UUO
	ERROR	<Error writing CCL file, code = >,NOCRLF
	JRST	E.DAE1

E.DAEF:	PUSHJ	P,CWF		;CHECK FOR UUO AND ATTACH
	ERROR	<Error writing file, code = >,NOCRLF
E.DAE1:	PUSH	P,T1		;SAVE CODE
	PUSHJ	P,TOCT		;TYPE CODE
	POP	P,T1		;GET CODE BACK
	CAILE	T1,MAXERR	;BIGGER THAN ASCIZ TABLE?
	JRST	E.DAE2		;YES
	MOVEI	T1,@ERRTBL(T1)	;POINT TO APPROPRIATE STRING
	PUSHJ	P,TYPSTR	;TYPE IT
E.DAE2:	PUSHJ	P,PCRLF		;PLUS CRLF
;;	PJRST	E.DCOR		;FALL INTO E.DCOR

E.DCOR:	TLZ	F,L.DUMP	;TURN OFF DUMP FLAG
	PJRST	EDCORE		;AND END DUMP

FBMTRY:	SOJLE	P1,CPOPJ1	;EXIT IF FINISHED RETRYING
	CAIE	T1,ERFBM%	;SKIP IF FILE BEING MODIFIED
	JRST	CPOPJ1		;NO, SOME OTHER ERROR
	MOVEI	T1,1
	SLEEP	T1,
	POPJ	P,

CWF:	TLNN	F,L.UUO		;THIS A UUO?
	POPJ	P,		;NO, RETURN
	POP	P,(P)		;FLUSH RETURN ADDRESS FROM STACK
	PJRST	UUERR5		;AND GIVE UUO ERROR

ERRTBL:	[ASCIZ/, File not found/]
	[ASCIZ/, No directory for PPN/]
	[ASCIZ/, Protection failure/]
	[ASCIZ/, File being modified/]
	[ASCIZ/, File already exists/]
	[ASCIZ/, Illegal sequence of UUOs/]
	[ASCIZ/, RIB error/]
MAXERR==.-ERRTBL-1
SNH:	TLNN	F,L.UUO		;THIS A UUO?
	POPJ	P,		;NO, RETURN
	POP	P,(P)		;FLUSH RETURN ADDRESS FROM STACK
	PJRST	UUERR4		;AND GIVE UUO ERROR

ATTCHK:	PUSH	P,T1		;SAVE T1
	GETLIN	T1,		;GET OUR LINE NO
	TLNN	T1,-1		;DO WE HAVE ONE?
	AOSA	OUTGUF		;COUNT NUMBER OF FAILURES
TPOPJ1:	AOS	-1(P)		;BUMP RETURN
TPOPJ:	POP	P,T1		;YES, RESTORE T1
	POPJ	P,		;RETURN

CRLFPD:	PUSHJ	P,PCRLF		;START WITH A CRLF
DOT:	MOVEI	SC,"."		;GET A PERIOD
	PJRST	TYPCHR		;TYPE IT AND RETURN

OCRLF:	TLO	F,L.OPR		;FORCE MESSAGE TO OPR
	PUSHJ	P,PCRLF		;OUTPUT THE CRLF
	TLZ	F,L.OPR		;CLEAR THE BIT
	POPJ	P,		;RETURN

PCRLF:	MOVEI	SC,.CHCRT	;GET A CARRIAGE RETURN
	PUSHJ	P,TYPCHR	;TYPE IT
	MOVEI	SC,.CHLFD	;GET A LINE FEED
	PJRST	TYPCHR		;TYPE IT AND RETURN

TABDOT:	MOVEI	SC,"	"	;GET A TAB
	PUSHJ	P,TYPCHR	;TYPE IT
	PJRST	DOT		;TYPE A DOT AND RETURN
;ROUTINE TO PROCESS THE ERROR, WARN, AND TELL MACROS.
;CALL	PUSHJ	P,ERRMSG
;	CAI	BITS,[PREFIX,[MESSAGE]]
;	RETURN HERE UNLESS ER.STP IS SET

ERRMSG:	PUSH	P,T1		;SAVE ALL THE AC'S THAT
	PUSH	P,SC		;WE USE IN THIS ROUTINE
	PUSH	P,P1		;...
	MOVE	P1,@-3(P)	;GET CAI WORD
	TLNE	P1,(ER.STP!ER.OPR) ;WANT THIS MESSAGE ISSUED TO OPR?
	TLO	F,L.OPR		;YES, TELL TYPCHR
	HLRZ	SC,(P1)		;GET MESSAGE PREFIX
	SKIPE	SC		;ANY THERE?
	PUSHJ	P,TYPCHR	;YES, TYPE IT
	HRRZ	T1,(P1)		;GET MESSAGE ADDRESS
	PUSHJ	P,TYPSTR	;TYPE IT
	TLNN	P1,(ER.NCR)	;WANT CRLF AT END OF THIS MESSAGE?
	PUSHJ	P,PCRLF		;YES, ADD ONE
	TLZ	F,L.OPR		;CLEAR OPR MESSAGE FLAG
	TLNE	P1,(ER.STP)	;STOP ON THIS ERROR?
	PJRST	DAEREN		;YES, TAKE IT DOWN
	POP	P,P1		;RESTORE THE AC'S SAVED ON ENTRY
	POP	P,SC		;...
	JRST	TPOPJ1		;AND RETURN
DEFINE	.ADCHR	(CHR),<
.STRG==.STRG+<<CHR>_.SHFT>
.SHFT==.SHFT-7
IFL .SHFT,<EXP	.STRG
.STRG==0
.SHFT==^D29	>>

DEFINE	.ADSTR	(STR),<
IRPC STR,<.ADCHR	("STR")	>>

DEFINE	VERSTR	(NAME,MAJOR,MINOR,EDIT,WHO),<
	XLIST
.STRG==0
.SHFT==^D29
	.ADSTR	(['NAME' )
	.ADSTR	(\MAJOR)
IFN MINOR,<.ADCHR	(MINOR+"A"-1)>
IFN EDIT,<.ADCHR	"("
	.ADSTR	(\EDIT)
	.ADCHR	")">
IFN WHO,<.ADCHR	("-")
	.ADSTR	(\WHO)>
	.ADCHR	("]")
	.ADCHR	(15)
	.ADCHR	(12)
	EXP	.STRG
LIST>

PDAEVR:	PJSP	T1,TYPSTR	;TYPE STRING AND RETURN
DAEVER:
	VERSTR	(DAEMON,VDAEMON,VMINOR,VEDIT,VWHO)

	PURGE	.ADCHR,.ADSTR,VERSTR,.STRG,.SHFT
SUBTTL SUBROUTINES

;SUBROUTINE TO START A CATEGORY
;ARGS	T1=CATEGORY NUMBER

CATSTA:	PUSHJ	P,DWRITE	;WRITE THE CATEGORY NUMBER
	PJRST	MRKSPT		;AND MARK THE SPOT FOR THE LENGTH TO BE WRITTEN LATER

;SUBROUTINE TO END A CATEGORY

CATEND:	MOVE	T1,WRDCNT	;WORDS WRITTEN
	PJRST	WRTSPT		;REWRITE THE SPOT MARKED FOR THE LENGTH OF THE CAT

;SUBROUTINE TO GET VALUES FOR JOB AND SEGMENT AND WRITE
;ARGS	T1=GETTAB TABLE
;	J=JOB NUMBER
;	S=SEGMENT NUMBER
;ENTER	WGTJOB TO WRITE JOB ENTRY
;	WGTSEG TO WRITE SEGMENT ENTRY
;	WGTBTH TO WRITE JOB THEN SEGMENT ENTRIES

WGTBTH:	TLO	F,L.WS		;WRITE JOB AND SEGMENT
WGTJOB:	TLOA	F,L.WJ		;WRITE JOB
WGTSEG:	TLO	F,L.WS		;WRITE SEGMENT
	TLZN	F,L.WJ		;SKIP IF WANT JOB ENTRY
	JRST	WGTSG1		;NO, TRY FOR SEGMENT
	HRLM	T1,(P)		;SAVE GETTAB TABLE
	HRLI	T1,(J)		;LH=JOB NUMBER
	PUSHJ	P,GTBSPY	;GET VALUE
	  SETZ	T1,		;0 OTHERWISE
	PUSHJ	P,DWRITE	;WRITE THAT
	HLRZ	T1,(P)		;RESET THE GETTAB TABLE
WGTSG1:	TLZN	F,L.WS		;SKIP IF SEGMENT ENTRY WANTED
	POPJ	P,		;NO, EXIT
	JUMPLE	S,WGTSG2	;DON'T TRY IF NO HIGH SEG (INCLUDING SPY)
	HRLI	T1,(S)		;LH=SEGMENT NUMBER
	PUSHJ	P,GTBSPY	;GET VALUE
WGTSG2:	  SETZ	T1,		;0 OTHERWISE
	PJRST	DWRITE		;WRITE AND EXIT
;TABLE OF GETTAB'S TO WRITE FOR JOB INFORMATION
;RH=TABLE NUMBER
;LH=0 IF BOTH JOB AND SEGMENT ENTRIES WANTED
;  =1 IF JOB ONLY
;  =2 IF SEGMENT ONLY
;G MACRO HAS PARAMETERS TABLE NAME, B OR J OR S FOR BOTH OR JOB OR SEGMENT
 
	DEFINE G(X,Y)<
	XLIST
..Z==3
IFIDN <Y> <B>,<..Z==0>
IFIDN <Y> <J>,<..Z==1>
IFIDN <Y> <S>,<..Z==2>
	XWD	..Z,X
	LIST
>

GTTABL:	G	.GTSTS,B
	G	.GTPPN,B
	G	.GTPRG,B
	G	.GTTIM,J
	G	.GTKCT,J
	G	.GTPRV,J
	G	.GTSWP,B
	G	.GTRCT,J
	G	.GTWCT,J
	G	.GTTDB,J
	G	.GTDEV,S
	G	.GTNM1,J
	G	.GTNM2,J
	G	.GTCNO,J
	G	.GTTMP,J
	G	.GTWCH,J
	G	.GTSPL,J
	G	.GTRTD,J
	G	.GTLIM,J
	G	.GTSPS,J
	G	.GTRSP,J
	G	.GTTRQ,J
	G	.GTUPM,B
	G	.GTCVL,J
	G	.GTMVL,J
	G	.GTIPA,J
	G	.GTIPP,J
	G	.GTIPI,J
	G	.GTIPQ,J
	G	.GTDVL,J
	G	.GTABS,J
	G	.GTVRT,J
GTTBLN==.-GTTABL
;SUBROUTINE TO OUTPUT ALL ENTRIES OF A GETTAB TABLE
;ARGS	P1=TABLE NUMBER

GTTBAL:	MOVSS	P1		;LH=TABLE NUMBER, RH=0
GTTBA1:	MOVS	T1,P1		;T1=ENTRY NUMBER,TABLE NUMBER
	PUSHJ	P,GTBSPY
	  POPJ	P,		;NO MORE
	PUSHJ	P,DWRITE	;WRITE THE WORD
	AOJA	P1,GTTBA1	;LOOP TIL END OF TABLE

;SUBROUTINE TO FOLLOW A DDB CHAIN AND DUMP ALL DDB'S FOR THIS JOB
;ARGS	T1=FIRST DDB ADDR,,0
;	J=JOB NUMBER

DMPDDB:	PUSHJ	P,SAVE1		;SAVE P1
DMPDD1:	HLRZS	T1		;MOVE NEXT ADDRESS TO RH
	JUMPE	T1,CPOPJ	;DONE IF AT END OF CHAIN
	MOVEI	P1,(T1)		;COPY TO P1
	PUSHJ	P,DDBJOB	;GET JOB NUMBER FROM THIS DDB
	CAIE	T1,(J)		;THIS ONE OF OURS?
	JRST	DMPDD2		;NO, TRY NEXT
	MOVN	T2,LDDBSH	;ASSUME SHORT DDB
	MOVEI	T1,DEVSTA(P1)	;ADDRESS OF DEVSTA
	PUSHJ	P,PEKSPY	;GET IT
	TLNE	T1,(DEPSPL)	;IS IT SPOOLED DEVICE?
	MOVN	T2,LDDBDS	;YES, REALLY A DISK
	MOVEI	T1,DEVMOD(P1)	;GET DEVMOD WORD
	PUSHJ	P,PEKSPY	;    FROM DDB
	TLNE	T1,(DV.LNG)	;LONG DDB?
	MOVN	T2,LDDBLN	;YES.
	TLNE	T1,(DV.DSK)	;DISK DDB?
	MOVN	T2,LDDBDS	;YES
	HRLI	P1,(T2)		;P1=-LENGTH,ADDR
	PUSHJ	P,WRTDDB	;WRITE OUT THE DDB
DMPDD2:	MOVEI	T1,DEVSER(P1)	;ADDR OF PTR TO NEXT DDB
	PUSHJ	P,PEKSPY	;GET IT
	JRST	DMPDD1		;LOOP FOR NEXT

;SUBROUTINE TO OUTPUT A DDB
;ARGS	P1=XWD -WORDS, ADDR OF BEGINNING OF DDB
;VALUES	P1=ADDR OF DDB

WRTDDB:	HRLM	P1,(P)		;SAVE ADDR OF DDB
	HLRE	T1,P1		;T1=MINUS LENGTH OF DDB
	MOVNS	T1		;POSITIVE LENGTH OF DDB
	HRL	T1,P1		;SAVE ADDR ALONG WITH LENGTH
	PUSHJ	P,DWRITE	;WRITE OUT LENGTH OF NEXT DDB
WRTDD1:	MOVEI	T1,(P1)		;ADDR OF NEXT WORD
	PUSHJ	P,PEKSPY	;GET NEXT WORD FROM DDB
	PUSHJ	P,DWRITE	;WRITE THE WORD
	AOBJN	P1,WRTDD1	;LOOP FOR THE DDB
	HLRZ	P1,(P)		;RESET ADDR OF DDB
	POPJ	P,		;AND EXIT
SUBTTL SUBROUTINE TO COMPRESS AND OUTPUT A SEGMENT

;SUBROUTINE TO COMPRESS AND OUTPUT A SEGMENT
;ARGS	T1=INDEX OF SEGMENT=JOB OR SEGMENT NUMBER
;	T2=ADDRESS AT WHICH TO START COMPRESSION
;	SEGREL=ADDRESS AT WHICH TO END COMPRESSION
;	THSOFF=OFFSET FOR ADDR OF FIRST WORD OF THE SEGMENT
;	USRADR=ADDRESS OF START OF BLOCK IN USRCOR
;	USRCOR=FIRST BLOCK OF USER'S CORE FOR SEGMENT

COMPRS:	PUSHJ	P,SAVE4		;SAVE P1-P4
	PUSH	P,REMBLK	;SAVE POINTER TO BEGINNING OF CATAGORY
	PUSH	P,REMWRD
	PUSH	P,WRDCNT
	MOVE	P1,T2		;GET ADDRESS AT WHICH TO START
	MOVE	P2,T2		;AND ALSO INTO P2
	ANDI	P2,PG.BDY	;GET START MODULO PAGE SIZE
	MOVEM	T1,THSSEG	;SAVE SIZE OF THIS SEGMENT
COMPR1:	SKIPE	USRCOR(P2)
	JRST	COMPR2		;FOUND NEXT NON-ZERO WORD
	SETCM	T1,P1		;GET COMPLEMENT OF ADDRESS
	TRNE	T1,PG.BDY	;SKIP IF END OF PAGE
	JRST	COMP1A		;NOT END, PROCEED
	TLZN	F,L.ZPGF	;SKIP IF JUST FINISHED A ZERO PAGE
	JRST	COMP1B		;NO, PROCEED ON TO NEXT PAGE
	HRRO	T1,P1		;GET CURRENT ADDRESS
	SUBI	T1,1000		;MAKE AN IOWD FOR START OF PAGE
	PUSHJ	P,DWRITE	;WRITE IT
	SETZ	T1,		;THEN MAKE A ZERO WORD
	PUSHJ	P,DWRITE	;AND WRITE IT
COMP1A:	TRNE	P1,PG.BDY	;START OF NEW PAGE?
	JRST	COMP1B		;NO, JUST KEEP ROLLING ALONG
	TLNN	F,L.UPMP	;HAVE UPMP IN CORE?
	JRST	COMP1B		;NO, PROBABLY MEANS WE JUST GOT PAGE VIA JOBPEK
	MOVE	T1,P1		;YES, MEANS PAGE COULD BE NON-EXISTANT
	PUSHJ	P,VIRADR	;GET UPMP ENTRY FOR THE PAGE
	JUMPE	T1,COMP1C	;IF NON-ZERO, PAGE EXISTS
	TLO	F,L.ZPGF	;PAGE EXISTS, SET ZERO PAGE FLAG
COMP1B:	CAML	P1,SEGREL	;SKIP IF MORE IN SEGMENT
	JRST	CPREND		;NO, END OF COMPRESSING
	ADDI	P1,1		;BUMP COUNTER TO NEXT ADDR
	CAIGE	P2,MAXUCR-1	;SKIP IF END OF BUFFER
	AOJA	P2,COMPR1	;NO, KEEP GOING
	PUSHJ	P,NXTUBK	;GET NEXT BLOCK OF USER CORE
	SETZ	P2,		;RESET PTR TO BEGINNING OF BUFFER
	JRST	COMPR1		;AND KEEP GOING

;HERE FOR NON EXISTENT PAGE
COMP1C:	ADDI	P1,PG.BDY	;BUMP TO END OF PAGE
	ADDI	P2,PG.BDY	;AND STEP THAT FAR IN BUFFER
	JRST	COMP1B		;AND CONTINUE
COMPR2:	HRRZM	P1,PTRADR	;SAVE ADDR OF BEGINNING OF NON-ZERO REGION
	TLZ	F,L.ZPGF	;FOUND A NON-ZERO WORD, CLEAR FLAG
	PUSHJ	P,MRKSPT	;MARK THE SPOT SO CAN WRITE IOWD LATER
	SETZ	P3,		;[755] ZERO A COUNTER FOR WORDS IN IOWD
COMP2A:	ADDI	P2,1		;BUMP PTR IN BUFFER, LOOK AT NEXT WORD
	SKIPE	T1,USRCOR-1(P2)	;SKIP IF FOUND A ZERO WORD
	JRST	COMPR3		;NO, JUST WRITE AND KEEP ON
	CAML	P1,SEGREL	;SKIP IF MORE IN SEGMENT
	JRST	CPREND		;END OF COMPRESSING
	CAIGE	P2,MAXUCR	;SKIP IF THE FIRST ZERO WAS THE END OF THE BUFFER
	JRST	COMP2B		;NO, GO AHEAD
	PUSHJ	P,NXTUBK	;YES, GET NEXT BLOCK
	SETZB	P2,T1		;RESET TO BEGINNING OF BUFFER AND REMEMBER ZERO DATA
COMP2B:	SKIPN	USRCOR(P2)	;IF ONLY 1 ZERO, PRETEND REGULAR DATA
	JRST	COMPR4		;2 CONSECUTIVE ZEROS END THIS PIECE
COMPR3:	PUSHJ	P,DWRITE	;WRITE THE WORD
	CAIL	P3,400000	;[755] MORE THAN 17 BITS FOR THE IOWD?
	 JRST	COMPR4		;[755] IF SO, END THIS PIECE OF DATA
	CAML	P1,SEGREL	;SKIP IF NOT END OF SEGMENT
	JRST	COMPR4		;END OF SEGMENT, END OF THIS PIECE
	ADDI	P1,1		;BUMP ADDR
	ADDI	P3,1		;[755] INCREMENT THE IOWD COUNTER
	CAIGE	P2,MAXUCR	;SKIP IF NOW OFF END OF BUFFER
	JRST	COMP2A		;NO, LOOK AT NEXT WORD
	PUSHJ	P,NXTUBK	;YES, GET NEXT BLOCK OF USER CORE
	SETZ	P2,		;RESET PTR TO BEGINNING OF BUFFER
	JRST	COMP2A		;AND KEEP GOING
COMPR4:	SOS	T1,PTRADR	;T1=ADDR-1 IN SEGMENT OF BEGINNING OF THIS PIECE
	ADD	T1,THSOFF	;ADD OFFSET FOR SEGMENT
	MOVN	T2,WRDCNT	;-WORDS WRITTEN
	HRL	T1,T2		;T1=IOWD PTR FOR PIECE
	PUSHJ	P,WRTSPT	;REWRITE THE IOWD IN THE FILE
	AOS	T1,WRDCNT	;WORDS WRITTEN INCLUDING THE IOWD
	ADDM	T1,(P)		;COUNT WORDS IN THIS CATEGORY
	SETZ	P3,		;[755] ZERO THE IOWD COUNTER
	CAMGE	P1,SEGREL	;SKIP IF END OF THIS SEGMENT
	AOJA	P1,COMPR1	;NO, LOOK FOR NEXT NON-ZERO PIECE
CPREND:	POP	P,WRDCNT	;RESTORE WORDS WRITTEN
	POP	P,REMWRD	;AND THE REST OF THE CATAGORY POINTERS
	POP	P,REMBLK
	POPJ	P,
;SUBROUTINE TO SET UP HGHOFF AND HGHREL FOR ANY JOB WITH HIGH SEGMENT
;ARGS	J=JOB NUMBER
;	USRUPM=USER'S UPM
;VALUES	HGHOFF=STARTING ADDRESS OF HIGH SEGMENT
;	HGHREL=LAST ADDRESS IN HIGH SEGMENT

HSVADR:	HRROI	T1,.GTSGN	;[532] GETTAB INDEX TO JBTSGN
	PUSHJ	P,GTBSPY	;GET SEGMENT NUMBER
	  JFCL			;???
	JUMPLE	T1,HSVAD1	;SPY SEG (ALWAYS STARTS AT 400000)
	MOVE	T4,T1		;SAVE HIGH SEGMENT NUMBER
	MOVSS	T1
	HRRI	T1,.GTUPM	;JBTUPM
	PUSHJ	P,GTBSPY
	  JFCL			;???
	LDB	T3,[POINT 9,T1,8] ;GET JBYHSO BYTE
	JUMPE	T3,HSVAD1	;IF JBYHSO=0, GO TRY KA STYLE
	LSH	T3,P2WLSH	;MAKE AN ADDRESS
	JRST	HSVAD2		;NOW STORE T3 AS START OF HI SEG
HSVAD1:	HRROI	T1,.GTADR	;[532] GETTAB INDEX TO JBTADR
	PUSHJ	P,GTBSPY	;GET LOW SEG PROT,,RELOC
	  JFCL			;???
	MOVEI	T2,377777	;ASSUME START AT 400000
	TRNE	T1,400000	;DOS IT START HIGHER?
	MOVE	T2,T1		;NO, START AT NEXT K ABOVE LOW END
	MOVEI	T3,1(T2)	;T3=START OF HI SEG
HSVAD2:	MOVE	T1,T4		;RESTORE HIGH SEGMENT NUMBER
	MOVEM	T3,HGHOFF	;STORE START OF HIGH SEGMENT
	JUMPL	T1,HSVAD3	;SPY SEG?
	MOVS	T1,T1		;NO, GET SIZE OF HIGH SEG
	HRRI	T1,.GTADR	;INDEX OF JBTADR
	PUSHJ	P,GTBSPY	;
	  JFCL			;???
	HLRZ	T1,T1		;SIZE OF HIGH SEGMENT
	JUMPN	T1,HSVAD3	;JUMP	IF IN CORE
	MOVS	T1,T4		;GET HIGH SEGMENT NUMBER
	HRRI	T1,.GTSWP	;JBTSWP
	PUSHJ	P,GTBSPY	;GET SIZE IN SOME FORM
	  JFCL			;???
	MOVE	T2,T4		;GET HIGH SEGMENT NUMBER AGAIN
	TLNN	T2,JSHR		;SHARABLE HIGH SEG?
	MOVSS	T1		;NO,GET LEFT HALF
	ANDI	T1,PG.BDY	;NUMBER OF PAGES IN HIGH SEG
	LSH	T1,P2WLSH	;CONVERT TO WORDS
	SUBI	T1,1	;AND GET HIGHEST ADDRESS
HSVAD3:	HRRZS	T1		;CLEAR POSSIBLE SPYSEG BIT
	MOVEM	T1,HGHREL	;AND STORE HIGHEST ADDRESS
	POPJ	P,		;AND RETURN
SUBTTL	SUBROUTINE TO OUTPUT A NON-COMPRESSED HIGH SEGMENT

;SUBROUTINE TO OUTPUT A NON-COMPRESSED HIGH SEGMENT
;ARGS	T1=SEGMENT NUMBER
;	SEGREL=LENGTH OF SEGMENT
;	THSOFF=OFFSET FOR ADR OF FIRST WORD OF SEGMENT
;	USRCOR=FIRST BLOCK OF USER'S CORE FOR SEGMENT

SAVHGH:	PUSHJ	P,SAVE4		;SAVE P1-P4
	PUSH	P,REMBLK
	PUSH	P,REMWRD
	PUSH	P,WRDCNT
	SETZB	P1,USRADR	;START AT ADDRESS 0 IN SEGMENT
	SETZ	P2,		;POINTER TO BUFFER OF USER'S CORE
	MOVEM	T1,THSSEG	;SAVE SEGMENT NUMBER
SAVHG1:	ADDI	P2,1		;BUMP POINTER IN BUFFER
	MOVE	T1,USRCOR-1(P2)	;GET PREVIOUS WORD
	PUSHJ	P,DWRITE	;WRITE THE WORD
	CAML	P1,SEGREL	;SKIP IF NOT END OF SEGMENT
	JRST	SAVHG2		;END OF SEGMENT, EXIT
	ADDI	P1,1		;BUMP ADDR
	CAIGE	P2,MAXUCR	;SKIP IF NOW OFF END OF BUFFER
	JRST	SAVHG1		;NOT, GET NEXT WORD
	PUSHJ	P,NXTUBK	;GET NEXT BLOCK OF USER CORE
	SETZ	P2,		;RESET POINTER TO START OF BUFFER
	JRST	SAVHG1		;AND CONTINUE
SAVHG2:	ANDI	P1,177		;COMPUTE NUMBER OF WORDS IN LAST BLOCK
	TLZE	F,L.NHRL	;WAS LH(.JBHRL)=0
	MOVEI	P,200		;YES, THEN LAST IS ALWAYS FULL BLOCK
	MOVNS	P1,P1		;SET UP IOWD FOR
	HRLS	P1,P1		;EXACT NUMBER OF WORDS
	HRR	P1,DLIST	;IN P1
	EXCH	P1,DLIST	;AND SET UP TO USE IT FOR OUTPUT
	PUSHJ	P,BLKWRT	;OUTPUT LAST PARTIAL BLOCK
	EXCH	P1,DLIST	;RESTORE OLD IOWD FOR FULL BLOCK
	POP	P,WRDCNT
	POP	P,REMWRD
	POP	P,REMBLK
	POPJ	P,
;SUBROUTINE TO DELETE THE FILE NAMED IN D.XXX

DELETE:	MOVSI	T1,DSK+<(FO.PRV)> ;CHANNEL+INVOKE PRIVS
	HRRI	T1,.FODLT	;DELETE FUNCTION
	MOVEM	T1,D.FLOP+.FOFNC ;SAVE IN BLOCK
	MOVEI	T1,.IODMP	;DUMP MODE
	MOVEM	T1,D.FLOP+.FOIOS ;SAVE IN BLOCK
	MOVE	T1,D.DEV	;GET DEVICE NAME
	MOVEM	T1,D.FLOP+.FODEV ;SAVE IN BLOCK
	SETZM	D.FLOP+.FOBRH	;NO BUFFERS
	SETZM	D.FLOP+.FONBF	;AND NO BUFFER COUNT
	MOVEI	T1,D.LKB	;ADDRESS OF LOOKUP BLOCK
	MOVEM	T1,D.FLOP+.FOLEB ;SAVE IN BLOCK
	SETZM	D.FLOP+.FOPAT	;NO PATH BLOCKS
	MOVE	T1,USRPPN	;PPN OF USER WHO WOULD DELETE
	MOVEM	T1,D.FLOP+.FOPPN ;SAVE IN BLOCK
	SETZM	D.LKB		;CLEAR FIRST WORD OF LOOKUP BLOCK
	MOVE	T1,[D.LKB,,D.LKB+1] ;MAKE BLT POINTER
	BLT	T1,D.LKB+.RBSIZ	;CLEAR BLOCK
	MOVE	T1,D.NAM	;GET FILENAME
	MOVEM	T1,D.LKB+.RBNAM ;SAVE IN LOOKUP BLOCK
	MOVE	T1,D.EXT	;GET EXTENTION
	MOVEM	T1,D.LKB+.RBEXT
	MOVE	T1,D.DIR	;GET PPN
	MOVEM	T1,D.LKB+.RBPPN ;SAVE IN BLOCK
	MOVEI	T1,.RBSIZ	;NUMBER OF WORDS IN LOOKUP BLOCK
	MOVEM	T1,D.LKB+.RBCNT ;SAVE IN BLOCK
	MOVE	T1,[.FOPPN+1,,D.FLOP] ;POINT TO FILOP. BLOCK
	FILOP.	T1,		;DELETE THE FILE
	  JFCL			;OH WELL
	POPJ	P,		;RETURN
SUBTTL SUBROUTINES TO WRITE USER CORE

;SUBROUTINE TO WRITE IN USER'S CORE - MAKES NO ADDRESS CHECKS
;ARGS	T1=+LENGTH, ADDR IN SEGMENT
;	T2=INDEX OF SEGMENT=JOB OR SEGMENT NUMBER
;	J=JOB NUMBER
;	THSOFF=OFFSET FOR BEGINNING OF SEGMENT
;	USRCOR CONTAINS CORE TO BE WRITTEN OUT

WTUCOR:	PUSHJ	P,SAVE4		;SAVE P1-P4
	MOVEM	T2,SEGSWP	;SAVE SEGMENT NUMBER
	MOVSI	T3,<(JK.WRT)>(J) ;JOB NUMBER AND WRITE FLAG TO LH
	HLR	T3,T1		;NUMBER OF WORDS TO RH
	HRRZ	T4,T1		;ADDR IN SEGMENT
	ADD	T4,THSOFF	;PLUS OFFSET FOR BEGINNING=ACTUAL ADDRESS
	HRLI	T4,USRCOR	;SOURCE=USRCOR
	MOVEI	T2,T3		;ADDR OF JOBPEK BLOCK
	PUSHJ	P,FINCHK	;WAIT A SEC IF HE'S BEING SWAPPED
WRTPEK:	PUSHJ	P,DOJBPK	;TRY TO WRITE USER'S CORE
	  JRST	WRTSWP		;NOT IN CORE, MUST REWRITE SWAPPING SPACE
	POPJ	P,

;HERE IF MUST REWRITE SWAPPING SPACE

WRTSWP:	PUSHJ	P,FINCHK	;IF LOST BECAUSE HE'S BEING SWAPPED, WAIT
	TRZE	F,R.SWIN	;DID HE JUST COME IN?
	JRST	WRTPEK		;YES, GO PEEK AGAIN
	PUSH	P,T3		;SAVE JOBPEK ARGS
	PUSH	P,T4		; ..
	MOVE	P1,T1		;SAVE PTR TO CORE TO BE WRITTEN
	MOVEI	P2,USRCOR	;CURRENT ADDR IN OUR BUFFER
	HRRZ	T3,P1		;ADDR OF USER'S CORE TO BE WRITTEN
	IDIVI	T3,BLKSIZ	;T3=BLOCKS TO SKIP, T4=WORDS TO SKIP IN BLOCK
	MOVE	P3,T3		;REMEMBER BLOCKS TO SKIP
	MOVE	P4,T4		;SAVE T4, (CLOBBERRED BY GTUPMP)
	PUSHJ	P,GTUPMP	;GET THE JOBS UPMP
	  JRST	E.SPTR		;???
	MOVE	T4,P4		;RESTORE T4
WRTSW3:	MOVEI	T1,(P1)		;GET ADDRESS TO WRITE
	PUSHJ	P,VIRADR	;GET UPMP ENTRY FOR THIS PAGE
	HRLM	T1,SEGSWP	;SAVE SWAPPING POINTER
	MOVEI	T3,(P3)		;[525] GET BLOCK OFFSET FROM PAGE 0
	ANDI	T3,3		;[525] MAKE BLOCK OFFSET FROM THIS PAGE

;HERE IF NOT FRAGMENTED

WRTSW0:	SKIPA	P3,T3		;REMEMBER BLOCKS SKIPPED
WRTSW1:	AOS	T3,P3		;SKIP ANOTHER BLOCK THIS TIME
	TRNE	T3,4		;[525] ABOUT TO CROSS PAGE BOUNDARY?
	  JRST	WRTSW3		;[525] YES, FIND NEW PAGE ON SWAP SPACE
WRTSW4:	PUSHJ	P,WRTPEC	;DO WHAT YOU CAN IN THIS BLOCK
	SETZ	T4,		;SKIP NO MORE WORDS IN BLOCKS
	TLNE	P1,-1		;SKIP IF ALL DONE
	JRST	WRTSW1		;NO, DO NEXT BLOCK
	JRST	REDEN1		;ALL DONE, RELEASE SWP AND EXIT
;SUBROUTINE TO REWRITE ONE BLOCK ON THE SWAPPING SPACE
;ARGS	T3=BLOCKS TO SKIP IN THIS PIECE OF THE SWAPPING SPACE
;	T4=WORDS TO SKIP IN THIS BLOCK
;	SEGSWP=SWAPPING PTR
;	P1=XWD +WORDS LEFT, ADDR IN USER'S SEGMENT
;	P2=ADDR IN USRCOR OF CURRENT BEGINNING OF DATA

WRTPEC:	PUSH	P,T4		;SAVE WORDS TO SKIP
	MOVE	T2,UPDLST	;IOWD TO AVAILABLE UPDATE BUFFER
	PUSHJ	P,REDPEC	;READ IN THE BLOCK
	POP	P,T2		;RESTORE WORDS TO PRESERVE IN THIS BLOCK
	MOVEI	T3,BLKSIZ	;WORDS IN THE BLOCK
	SUB	T3,T2		;T3=WORDS AVAILABLE IN THIS BLOCK
	HLRZ	T4,P1		;T4=WORDS YET TO TRANSFER
	CAMLE	T3,T4		;MINIMUM OF AVAILABLE, LEFT TO TRANSFER
	MOVE	T3,T4		;=WORDS TO WRITE IN THIS BLOCK
	MOVE	T4,T3		;SAVE IN T4
	ADDI	T2,SECBUF	;ADDR OF FIRST AVAILABLE WORD
	HRL	T2,P2		;ADDR OF NEXT DATA WORD
	ADDI	T3,(T2)		;+WORDS TO TRANSFER=LAST WORD+1
	BLT	T2,-1(T3)	;TRANSFER NEW DATA INTO BUFFER
	MOVEI	T2,SWP+4000	;SET UP LH FOR SUSET.
	PUSH	P,T1		;SAVE T1 IN CASE SUSET. LOSES
	DPB	T2,[POINT 13,T1,12]
	SUSET.	T1,
	  USETO	SWP,(P)		;TRY SUPER USETO
	POP	P,T1		;GET T1 BACK
	OUTPUT	SWP,UPDLST	;REWRITE BLOCK
	HLRZ	T2,P1		;WORDS LEFT
	SUB	T2,T4		;-WORDS DONE=NEW WORDS LEFT
	HRL	P1,T2
	ADDI	P1,(T4)		;NEW ADDR IN USER'S SEGMENT
	ADDI	P2,(T4)		;AND NEW ADDR IN USRCOR
	STATO	SWP,IO.ERR	;SKIP IF ERRORS
	POPJ	P,
	AOS	SWWGUF		;NOTE SWAP WRITE ERROR
	ERROR	<Swap write error unit >,NOCRLF
	PJRST	SWPIO1		;REPORT REST OF ERROR
SUBTTL SUBROUTINES TO READ USER CORE

;SUBROUTINE TO GET NEXT BLOCK OF USER CORE

NXTUBK:	MOVEI	T1,MAXUCR	;SIZE OF BLOCK TO GET
	ADDB	T1,USRADR	;ADDR OF THIS BLOCK IN SEGMENT
	MOVEI	T2,MAXUCR	;MAXIMUM TRANSFER POSSIBLE
	ADDI	T2,-1(T1)	;T2=ADDR OF LAST POSSIBLE WORD
	CAMLE	T2,SEGREL	;SKIP IF WITHIN SEGMENT
	MOVE	T2,SEGREL	;LAST WORD OF SEG IS LAST WORD OF TRANSFER
	SUBI	T2,(T1)		;MINUS START OF TRANSFER=WORDS-1
	HRLI	T1,1(T2)	;WORDS THIS TRANSFER TO LEFT HALF
	MOVE	T2,THSSEG	;SEGMENT NUMBER
;	PJRST	GTUCOR		;FALL INTO GTUCOR

;SUBROUTINE TO GET CORE FROM USER'S JOB - MAKES NO ADDRESS CHECKS
;ARGS	T1=+LENGTH, ADDR IN SEGMENT
;	T2=INDEX OF SEGMENT=JOB OR SEGMENT NUMBER
;	J=JOB NUMBER
;	THSOFF=OFFSET FOR BEGINNING OF THIS SEGMENT

GTUCOR:	PUSHJ	P,SAVE4		;SAVE P1-P4
	SETZM	USRCOR		;FIRST CLEAR THE BUFFER IN CASE SOMETHING GOES WRONG
	MOVE	T3,[USRCOR,,USRCOR+1]
	BLT	T3,USRCOR+MAXUCR-1
	HRRZM	T2,SEGSWP	;SAVE SEGMENT NUMBER
	HLRZ	T3,T1		;RH=NUMBER OF WORDS
	HRL	T3,J		;LH=JOB NUMBER
	HRRZ	T4,T1		;ADDR IN SEGMENT
	ADD	T4,THSOFF	;ADD OFFSET FOR BEGINNING OF SEGMENT
	HRLZS	T4		;LH=ADDR
	HRRI	T4,USRCOR	;RH=ADDR OF OUR BUFFER
	MOVEI	T2,T3
	MOVE	P1,T1		;SAVE POINTER TO CORE WANTED
	TLNN	F,L.UPMP	;HAVE UPMP IN CORE?
	JRST	GTUCR1		;NO, PROCEED
	TLZ	T1,-1		;CLEAR LH OF T1
	PUSHJ	P,VIRADR	;GET UPMP ENTRY
	JUMPE	T1,CPOPJ	;EXIT WITH EMPTY BUFFER IF NO PAGE
	CAIN	T1,PM.ZER	;ALLOCATED BUT ZERO?
	POPJ	P,		;YES, EXIT
GTUCR1:	PUSHJ	P,FINCHK	;WATCH OUT FOR HIS GETTING SWAPPED
REDPEK:	PUSHJ	P,DOJBPK	;TRY TO READ CORE
	  JRST	REDSWP		;NOT IN CORE, READ SWAPPING SPACE
	POPJ	P,		;THAT WAS NICE

;HERE TO CHECK WHETHER JOB IN J IS BEING SWAPPED NOW.
; IF SO, WAIT UNTIL HE GETS IN OR OUT, AND GIVE
; NON-SKIP RETURN IF HE JUST CAME IN
;READS THSOFF AND ASSUMES HI SEG WANTED IF NON-ZERO

FINCHK:	PUSH	P,T1		;SAVE WORK REG
	TRZ	F,R.SWIN	;ASSUME NO KNOWLEDGE
FINCK1:	HRROI	T1,.GTSGN	;[531] GET SEGMENT NUMBER FOR JOB
	SKIPE	THSOFF		;[531] SKIP IF EXAMINING LOW SEG
	 PUSHJ	P,GTBSPY	;[531] DON'T COME BACK WITHOUT IT!
	  MOVEI	T1,(J)		;[531] IF NO HI SEG, USE JOB NUMBER
	MOVEM	T1,FNCJBJ	;SAVE FOR DEBUGGING
	MOVSI	T1,(T1)		;[531] INDEX IN LH
	HLLM	T1,-1(P)	;[531] REMEMBER THIS!
	IFN .GTSTS,<HRRI T1,.GTSTS>	;[531] PLAN AHEAD
	PUSHJ	P,GTBSPY	;[531] GET STATUS
	  JRST	TPOPJ		;[531] WE TRIED
	MOVEM	T1,FNCJBS	;SAVE FOR DEBUGGING
	TLNN	T1,JNSWP	;[531] RETURN IF SEGMENT LOCKED
	TLNN	T1,JSWP		;[531] LEARN MORE IF SWAPPED OR SWAPPING
	  JRST	TPOPJ		;[531] GO HOME, BOY
	HLL	T1,-1(P)	;[531] RESTORE INDEX
	HRRI	T1,.GTADR	;[531] GET PROTECTION AND RELOCATION
	PUSHJ	P,GTBSPY	;[531] FIND IT
	  JRST	TPOPJ		;[531] LOSE
	MOVEM	T1,FNCJBA	;SAVE FOR DEBUGGING
	JUMPE	T1,FINCK2	;JUMP IF SWAPPED AND QUIESCENT
	TRO	F,R.SWIN	;SWAPPING NOW, ASSUME COMING IN
	MOVEI	T1,1		;GET A SMALL CONSTANT
	HIBER	T1,		;WAIT A JIFFIE
	  SLEEP	T1,		;OR A SECOND IF NO HIBER
	JRST	FINCK1		;LOOK AGAIN
FINCK2:	TRZ	F,R.SWIN	;ON SWAPPING SPACE, CAN'T BE COMING IN
	JRST	TPOPJ		;AND PROCEED

;SUBROUTINE TO GET UPMP ENTRY FOR VIRTUAL ADDRESS
;ARGS	T1=VIRTUAL ADDRESS
;	THSOFF=START OF THIS SEGMENT
;	USRUPM=USER'S PAGE MAP PAGE
;VALUES	T1=UPMP ENTRY FOR PAGE

VIRADR:	ADD	T1,THSOFF	;GET START OF SEGMENT
	ROT	T1,-^D10	;GET (PAGE NUMBER)/2
	SKIPGE	T1		;IF NEGATIVE, USE RH(POINTER) FROM UPMP
	SKIPA	T1,USRUPM(T1)	;GET RH (POINTER) AND SKIP
	MOVS	T1,USRUPM(T1)	;GET LH(POINTER)
	TLZ	T1,-1		;CLEAR LH
	POPJ	P,		;AND RETURN
;HERE IF MUST READ SWAPPING SPACE

REDSWP:	PUSHJ	P,FINCHK	;DID WE LOSE BECAUSE MON DECIDED TO SWAP?
	TRZE	F,R.SWIN	;DID WE SEE HIM COME IN?
	JRST	REDPEK		;YES, AND HE'S NOW IN CORE
	PUSH	P,T3		;SAVE JOBPEK ARGS
	PUSH	P,T4
	HRRZ	T1,SEGSWP	;GET SEGMENT NUMBER
	CAIN	T1,(J)		;HIGH SEGMENT?
	JRST	REDSW7		;NO,PROCEED
	HRLZ	T1,SEGSWP	;YES, GET SEGMENT NUMBER
	IFN .GTSTS,<HRRI T1,.GTSTS>	;JOB STATUS TABLE
	PUSHJ	P,GTBSPY	;GET HIGH SEGMENT STATUS
	  JRST	[PUSHJ	P,E.HSTS ;PRINT MESSAGE
		 JRST	REDEND]
	TLNE	T1,JSHR		;SHARABLE HIGH SEGMENT?
	JRST	REDSW1		;YES, TREAT AS PER PRE 6.01
REDSW7:	PUSHJ	P,GTUPMP	;GET THE JOB'S UPMP
	  JRST	[PUSHJ	P,E.UPMP ;PRINT MESSAGE
		 JRST	REDEND]
	MOVEI	T1,(P1)		;GET SOURCE ADDRESS
	PUSHJ	P,VIRADR	;GET UPMP ENTRY FOR ADDRESS
	HRLM	T1,SEGSWP	;SET UP POINTER FOR REDPEC
	HLRZ	T1,P1		;GET LENGTH
	ADDI	T1,-1(P1)	;GET LAST ADDRESS
	XORI	T1,(P1)		;[530] CANCEL ALL BITS WHICH AGREE
	TRNN	T1,-1-PG.BDY	;IF LEFTMOST 9 BITS=0, ALL ON ONE PAGE
	JRST	REDSW6		;ON ONE PAGE, CONTINUE

;HERE IF "FRAGMENTED"  I.E. CORE TO GET FLOWS ACROSS PAGE BOUNDARY
	MOVEI	P2,USRCOR-1	;FIRST ADR FOR IOWD
	HLRZ	P3,P1		;GET NUMBER OF WORDS TO GET
	HRRZ	T1,P1		;GET ADDRESS OF FIRST WORD
	TRZ	T1,-BLKSIZ	;WORDS TO BE SKIPPED IN FIRST BLOCK
	ADD	P3,T1		;MUST READ NOT WANTED WORDS TOO
	MOVE	P4,T3		;SAVE POINTER TO UPMP
	MOVE	T4,P1		;GET ADDRESS
	PUSH	P,P1		;SAVE USER ARGUMENT POINTER
REDSW3:	MOVE	T3,-2(P)	;GET JOBPEK ARG
	TRZ	T4,BLKSIZ-1	;[567] ROUND OFF ADR TO BLOCK SIZE
	HRLI	T4,1(P2)	;SET UP DESTINATION ADDRESS
	HRRZ	T1,T4		;[572]GET START ADDRESS
	TRZ	T1,PG.BDY	;GET FIRST ADDRESS IN PAGE
	ADDI	T1,PG.SIZ	;GET NEXT PAGE ADDRESS
	HRRZ	T2,T4		;[572]GET START ADDRESS AGAIN
	SUB	T1,T2		;GET WORD COUNT
	CAIL	T1,(P3)		;LESS THAN TOTAL?
	MOVEI	T1,(P3)		;NO, USE SHORTER OF TOTAL OR BOUND
	HRR	T3,T1		;AND SET UP JOBPEC ARG
	MOVEI	T2,T3		;SET UP JOBPEK POINTER AC
	PUSHJ	P,DOJBPK	;AND TRY TO GET FROM CORE
	  JRST	REDSW4		;FAIL, GET FROM SWAPPING SPACE
	ADDI	P2,(T3)		;UPDATE ADDRESS IN BUFFER
	SUB	P3,T1
	JRST	REDSW5
REDSW4:	SUB	P3,T1
	MOVN	T2,T1
	HRLZS	T2
	HRR	T2,P2
	ADDM	T1,P2
	HLRZ	T4,SEGSWP	;GET SWAPPING POINTER
	JUMPE	T4,REDSW5	;IF DOESN'T EXIST, DON'T TRY TO READ
	HRRZ	T3,P1		;[567] ADDR IN USER SPACE
	LSH	T3,-B2WLSH	;[567] CONVERT TO BLOCKS
	ANDI	T3,<1_BLKSPP>-1	;[567] BLOCK OFFSET WITHIN PAGE
	CAIE	T4,PM.ZER	;SKIP IF ALLOCATED BUT ZERO PAGE
	PUSHJ	P,REDPEC	;READ FROM SWAPPING SPACE
REDSW5:	JUMPE	P3,REDSW8	;FINISHED IF ZERO, CLEAN UP BUFFER
	MOVEI	T1,(P1)		;GET ORIGINAL ADDRESS
	ADDI	T1,PG.SIZ	;BUMP TO NEXT PAGE
	PUSHJ	P,VIRADR
	HRLM	T1,SEGSWP	;SET UP POINTER FOR REDPEC
	ADDI	P1,PG.SIZ
	TRZ	P1,PG.BDY
	MOVEI	T4,(P1)		;NEXT ADDRESS IN USER CORE
	JRST	REDSW3		;GET REST OF USER CORE

REDSW8:	POP	P,P1		;RESTORE USER CORE POINTER
	JRST	REDEND		;AND CLEAN UP

REDSW1:	HRLZ	T1,SEGSWP	;LH=SEGMENT NUMBER
	HRRI	T1,.GTSWP	;SWAPPING PTR TABLE
	PUSHJ	P,GTBSPY	;GET SWAP PTR
	  JRST	[PUSHJ P,E.SPTR
		 JRST REDEND]
	HLLM	T1,SEGSWP	;SAVE PTR TO SEGMENT ON SWAPPING SPACE
	HLRE	T3,T1		;T1=SWAP PTR OR -1 IF IN CORE
	AOJE	T3,REDEN2	;EXIT IF IN CORE - TRY JOBPEK AGAIN
	HRRZ	T3,P1		;ADDR DESIRED
	LSH	T3,-B2WLSH	;T3=BLOCKS TO SKIP
	JUMPL	T1,FRAG		;JUMP IF FRAGMENTED
	JRST	REDSW2		;ALL ONE PIECE


REDSW6:	MOVEI	T3,(P1)		;GET START ADDRESS
	ANDI	T3,600		;GET BLOCK RELATIVE TO PAGE START
	ROT	T3,-7		;GET INTO PROPER POSITION FOR REDPEC
;HERE IF NOT FRAGMENTED, ALL ONE PIECE

REDSW2:	HLRZ	T2,P1		;LENGTH IN WORDS
	HRRZ	T1,P1		;ADDR DESIRED
	TRZ	T1,-BLKSIZ	;MAKE WORDS TO SKIP IN FIRST BLOCK
	ADD	T2,T1		;MUST READ THE WORDS TO SKIP TOO
	MOVNS	T2		;MINUS LENGTH
	HRLZS	T2		;IN LH
	HRRI	T2,USRCOR-1	;MAKE IOWD PTR
	HLRZ	T4,SEGSWP	;GET POINTER FROM UPMP
	JUMPE	T4,REDEND
	CAIE	T4,PM.ZER	;SKIP IF 'ALLOCATED BUT ZERO' PAGE
	PUSHJ	P,REDPEC	;READ IT
	JRST	REDEND		;ALL DONE
;HERE IF FRAGMENTED ON SWAPPING SPACE

FRAG:	TLZ	T1,400000	;LH T1=ADDR OF BLOCK OF PTRS
	HLRZ	T2,T1		;IN RH OF T2
	MOVEI	P2,USRCOR-1	;FIRST ADDR FOR IOWD
	HLRZ	P3,P1		;LENGTH OF PIECE DESIRED=WORDS LEFT TO DO
	HRRZ	T1,P1		;ADDR OF FIRST WORD
	TRZ	T1,-BLKSIZ	;WORDS WHICH WILL BE SKIPPED IN FIRST BLOCK
	ADD	P3,T1		;MUST READ THEM TOO
	PUSHJ	P,FRGFND	;FIND FIRST BLOCK TO READ
	JUMPE	T1,REDEND	;EXIT IF NO MORE TO READ
FRAGS1:	HRLM	T1,SEGSWP	;SAVE THE PTR, SWAPPED FOR BYTE PTRS
	HLRZS	T1		;K IN THIS PIECE
	LSH	T1,BLKSPP	;CONVERT TO BLOCKS
	SUB	T1,T3		;MINUS BLOCKS TO SKIP IN THIS PIECE
	LSH	T1,B2WLSH	;T1=TOTAL DATA WORDS IN THIS PIECE
	CAML	T1,P3		;SKIP IF LESS THAN WORDS STILL NOT READ
	MOVE	T1,P3		;THAT'S ALL WE NEED
	SUB	P3,T1		;SUBTRACT FROM WORDS LEFT TO DO
	MOVN	T2,T1		;T2=-WORDS THIS TRANSFER
	HRLZS	T2
	HRR	T2,P2		;ADDR IN CORE FOR THIS PIECE
	ADDM	T1,P2		;NEW ADDR AFTER THIS PIECE READ
	PUSHJ	P,REDPEC	;READ THIS PIECE
	JUMPE	P3,REDEND	;JUMP IF NO MORE NEEDED
	AOS	T1,SWPADR	;ADDR OF NEXT SWAPPING PTR
FRAG4:	PUSHJ	P,PEKSPY	;GET NEXT PTR
	JUMPE	T1,REDEND	;QUIT NOW IF NO MORE PTRS
	SETZ	T3,
	TLC	T1,-1		;SET TO TEST IF PTR TO NEW PTRS
	TLCE	T1,-1		;SKIP IF PTR TO NEW BLOCK OF PTRS
	JRST	FRAGS1		;COME BACK THROUGH
	MOVEM	T1,SWPADR	;STORE ADDR OF NEW BLOCK OF PTRS
	JRST	FRAG4		;AND LOOK FOR NEXT PTR
;SUBROUTINE TO FIND FIRST BLOCK TO READ
;ARGS	T2=ADDR OF NEXT WORD OF SWAPPING PTRS
;	T3=BLOCKS TO SKIP
;VALUES	T1=NEXT SWAPPING PTR
;	SWPADR=ADDR OF SWAPPING PTR

FRGFND:	HRRZ	T1,T2		;T1=ADDR OF NEXT WORD OF SWAPPING PTRS
	PUSHJ	P,PEKSPY	;T1=NEXT SWAPPING PTR
	JUMPE	T1,CPOPJ	;QUIT NOW IF NO MORE
	TLC	T1,-1		;SET TO TEST IF REAL PTR
	TLCN	T1,-1		;SKIP IF REAL PTR
	JRST	FRAG2		;ADDR OF NEW BLOCK OF PTRS
	JUMPE	T3,FRAGST	;START HERE IF NO MORE BLOCKS TO SKIP
	HLRZ	T4,T1		;T4=K IN THIS PIECE
	LSH	T4,BLKSPP	;CONVERT TO BLOCKS
	SUB	T3,T4		;T3=BLOCKS LEFT TO SKIP
	JUMPL	T3,FRAG3	;USE THIS IF STARTS IN THIS PIECE
	AOJA	T2,FRGFND	;RH=ADDR OF NEXT PTR
FRAG2:	HRRZ	T2,T1		;RH=ADDR OF NEW BLOCK OF PTRS
	JRST	FRGFND		;START CHASING THAT
FRAG3:	ADD	T3,T4		;T3=BLOCKS TO SKIP IN THIS PIECE
FRAGST:	MOVEM	T2,SWPADR	;SAVE ADDR OF THIS PTR
	POPJ	P,
;HERE WHEN ALL THE PIECES READ

REDEND:	HRRZ	T1,P1		;ADDR DESIRED
	TRZ	T1,-BLKSIZ	;CLEAR OUT ALL BUT ADDR IN 1ST BLOCK
	JUMPE	T1,REDEN0	;JUMP IF FIT EXACTLY AT BEGINNING OF BLOCK
	HRLZI	T1,USRCOR(T1)	;ADDR OF ACTUAL START OF DATA
	HRRI	T1,USRCOR	;BEGINNING OF BUFFER
	HLRZ	T2,P1		;LENGTH OF DATA
	BLT	T1,USRCOR-1(T2)	;MOVE UP DATA TO BEGINNING OF BUFFER
REDEN0:	HLRZ	T2,P1		;RE-GET LEN IN CASE JUMPED HERE
	CAIE	T2,MAXUCR	;UNLESS FULL BUFFER,
	SETZM	USRCOR(T2)	;CLEAR FIRST UNUSED LOC
	CAIL	T2,MAXUCR-1	;MORE THAN 1 UNUSED LOC?
	JRST	REDEN1		;NO, CLEAR NO MORE
	HRLZI	T1,USRCOR(T2)	;FIRST UNUSED LOC
	HRRI	T1,USRCOR+1(T2)	;SECOND "  "
	BLT	T1,USRCOR+MAXUCR-1 ;CLEAR TO END OF BUFFER
REDEN1:	MOVEI	T1,SWP		;[535] SET UP CHANNEL
	PUSHJ	P,RELDSK	;[535] GO RELEASE IT
REDEN2:	POP	P,T4		;RESTORE JOBPEK ARGS
	POP	P,T3
	MOVEI	T2,T3		;ADDR OF JOBPEK BLOCK
	PUSHJ	P,DOJBPK	;TRY AGAIN IN CASE JUST CAME INTO CORE
	  JFCL			;COULD HAPPEN FOR SHARABLE HIGH SEG
	POPJ	P,

;SUBROUTINE TO READ SWAPPING SPACE
;ARGS	T2=IOWD
;	T3=BLOCKS TO SKIP
;	SEGSWP=SWAPPING PTR
;VALUES	T1=BLOCK NUMBER READ

REDPEC:	PUSH	P,T2		;SAVE IOWD
	LDB	T4,JBYSUN	;LOGICAL UNIT IN SWAPPING LIST
	LDB	T1,JBYLKN	;LOGICAL K IN SWAPPING SPACE
	LSH	T1,BLKSPP	;CONVERT TO BLOCKS
	PUSHJ	P,GETSWP	;SETUP SWPUNI AND SWPSLB
	  JRST	E.SWPE		;ERROR
	ADD	T1,SWPSLB	;+FIRST BLOCK FOR SWAPPING=BEGINNING ON SWAP SPACE
	ADD	T1,T3		;PLUS BLOCKS TO SKIP
	MOVEI	T2,.IODMP	;DUMP MODE
	MOVE	T3,SWPUNI	;GET NAME OF UNIT
	SETZ	T4,
	OPEN	SWP,T2
	  JRST	[POP	P,T2	;RESTORE T2
		 JRST	E.SOPN]	;GIVE MESSAGE AND RETURN
	PUSH	P,T1		;SAVE BLOCK NUMBER
	TLO	T1,SWP_5	;(555) (WAS HRLI)PUT CHANNEL NUMBER IN LH
	SUSET.	T1,		;DO THE SUSET.
	  USETI	SWP,(P)		;TRY SUPER USETI IF SUSET. FAILS
	POP	P,T1		;RESTORE THE BLOCK NUMBER
	POP	P,T2		;RESTORE IOWD
;CONTINUED
	SETZ	T3,
	INPUT	SWP,T2		;READ
	STATO	SWP,IO.ERR!IO.EOF ;SKIP IF ERRORS
	POPJ	P,
	AOS	SWRGUF		;COUNT SWAP READ ERROR
	ERROR	<Swap read error unit >,NOCRLF
SWPIO1:	PUSH	P,T1		;SAVE BLOCK NUMBER READ
	GETSTS	SWP,T1		;READ ERROR STATUS
	HRLM	T1,-1(P)	;SAVE NEXT TO RETURN ADDR
	LDB	T2,JBYSUN	;GET SWAP UNIT NUMBER
	MOVE	T2,SWPUNI	;T2=UNIT NAME
	PUSHJ	P,TSIXN		;TYPE IT
	TELL	< Status >,NOCRLF
	HLRZ	T1,-1(P)	;SAVE STATUS
	PUSHJ	P,TOCT		;TYPE STATUS
	TELL	< Pntr >,NOCRLF
	MOVE	T1,SEGSWP	;GET BAD POINTER
	PUSHJ	P,TOCT		;TYPE IN OCTAL
	TELL	< SLB >,NOCRLF
	MOVE	T1,SWPSLB	;GET 1ST LOGICAL BLOCK FOR SWAPPING
	PUSHJ	P,TOCT		;TYPE IN OCTAL
	PUSHJ	P,OCRLF		;FORCE MESSAGE TO OPR
	HLRZ	T1,-1(P)	;RESTORE STATUS
	TRZ	T1,IO.ERR!IO.EOF ;CLEAR ERROR BITS
	SETSTS	SWP,(T1)	;CLEAR ERROR
	PUSHJ	P,SNH		;CHECK FOR UUO
	JRST	TPOPJ		;RESTORE T1 AND EXIT


;SUBROUTINE TO SETUP SWPUNI AND SWPSLB FOR THE SWAP UNIT WHICH
;WE WANT TO READ.
;ARGS	T4=OFFSET IN SWPTAB
;VALUES	SWPUNI=SIXBIT NAME OF UNIT
;	SWPSLB=LOGICAL BLOCK OF START OF SWAPPING SPACE ON THIS UNIT
;RETURNS CPOPJ IF INCONSISTENCY DETECTED
;	 CPOPJ1 IF ALL OK

GETSWP:	CAML	T4,SWPMAX	;IS SWPTAB OFFSET LEGAL?
	POPJ	P,		;NO, RETURN ERROR
	PUSH	P,T1		;SAVE T1
	MOVE	T1,SWPTAB	;GET ADDRESS OF SWPTAB
	ADD	T1,T4		;INCLUDE OFFSET
	PUSHJ	P,PEKSPY	;GET ADDRESS OF UDB
	JUMPE	T1,TPOPJ	;ERROR IF ZERO
	PUSH	P,T1		;SAVE ADDRESS FOR LATER
	PUSHJ	P,PEKSPY	;READ UNINAM
	JUMPE	T1,[POP  P,(P)	;CLEAN UP STACK
		    JRST TPOPJ]	;GIVE NON-SKIP RETURN
	MOVEM	T1,SWPUNI	;SAVE FOR CALLER
	POP	P,T1		;GET UDB ADDRESS BACK
	ADD	T1,UNISLB	;PLUS OFFSET TO UNISLB
	PUSHJ	P,PEKSPY	;READ FIRST BLOCK FOR SWAPPING
	JUMPLE	T1,TPOPJ	;MUST BE POSITIVE
	MOVEM	T1,SWPSLB	;SAVE FOR CALLER
	JRST	TPOPJ1		;GIVE SUCCESS RETURN
SUBTTL SUBROUTINES

;SUBROUTINE TO OUTPUT A CARRIAGE RETURN LINE FEED FOR DUMP CCL FILE

CCCRLF:	MOVEI	SC,C.CR		;CARRIAGE RETURN
	PUSHJ	P,CCOUT		;OUTPUT CHAR TO CCL FILE
	MOVEI	SC,C.LF		;LINE FEED - FALL INTO CCOUT

;SUBROUTINE TO OUTPUT A CHARACTER ON DUMP CCL FILE
;ARGS	SC(=16)=CHAR

CCOUT:	SOSG	C.BH+2
	OUTPUT	DSK,
	IDPB	SC,C.BH+1
	POPJ	P,
;SUBROUTINE TO COPY USER'S SEARCH LIST
;ARGS	T1=JOB NUMBER
;	T2=PPN
;	T3=ADDRESS-1 OF BLOCK TO STORE SEARCH LIST

GETSRC:	MOVEM	T1,GOBBUF+.DFGJN ;USER'S JOB NUMBER
	MOVEM	T2,GOBBUF+.DFGPP
	SETOM	GOBBUF+.DFGNM	;START AT BEGINNING OF JOB'S SEARCH LIST

GETSR1:	MOVE	T1,[.DFGST+1,,GOBBUF]
	GOBSTR	T1,		;GET NEXT STR IN JOB'S SEARCH LIST
	  POPJ	P,		;ALL DONE
	MOVE	T1,GOBBUF+.DFGNM ;NEXT STR
	JUMPE	T1,CPOPJ	;EXIT IF FENCE OR
	AOJE	T1,CPOPJ	; IF END OF LIST
	PUSH	T3,GOBBUF+.DFGNM ;STORE NAME
	PUSH	T3,GOBBUF+.DFGNM+1 ;AND UNUSED WORD
	PUSH	T3,GOBBUF+.DFGST ;AND STATUS WORD
	JRST	GETSR1		;LOOP TILL END OF LIST

;SUBROUTINE TO GET JOB'S DEFAULT PATH
;ARGS	J=JOB NUMBER WHOSE PATH TO READ
;VALUE	T1=POINTER TO PATH SPEC, OR PPN IF SFD'S NOT IMPLEMENTED

GETPTH:	HRLOI	T1,(J)		;READ JOB'S PATH FUNCTION
	MOVEM	T1,D.DPTH	;AT TOP OF PATH BLOCK
	MOVE	T1,[XWD .PTMAX,D.DPTH]
	PATH.	T1,
	  PJRST	GETPPN		;NO SFD'S-RETURN PPN
	MOVEI	T1,D.DPTH	;POINT TO PATH LIST
	POPJ	P,

;SUBROUTINE TO GET JOB'S PPN
;ARGS	J=JOB NUMBER
;VALUE	T1=PPN

GETPPN:	HRROI	T1,.GTPPN	;SETUP JBTPPN INDEX
	PUSHJ	P,GTBSPY
	  SETZ	T1,
	POPJ	P,

;SUBROUTINE TO GET JOB # FROM DDB
;ARGS	T1=ADDRESS OF DDB
;VALUES	T1=JOB #

DDBJOB:	ADD	T1,LDDBSH	;ADD IN LENGTH OF SHORT DDB
	SUBI	T1,1		;DEVJOB IS LAST WORD IN SHORT DDB
	PUSHJ	P,PEKSPY	;GO PICK IT UP
	ANDI	T1,777		;ONLY RIGHT 9 BITS ARE JOB NUMBER
	POPJ	P,		;RETURN
;HERE TO RELEASE A CHANNEL
;ARG=CHANNEL # IN T1		T1,T2,T3 DESTROYED
;THIS ROUTINE KEEPS CHANNEL DDB AROUND IN CASE OF A SOFT ERROR
;  ON OURSELF THAT WE MAY SHORTLY BE ASKED TO RECORD

RELFCT:	MOVEI	T1,FCT		;ENTER HERE TO GIVE UP FCT CHANNEL
RELDSK:	DPB	T1,[POINT 4,RELINS,12]	;[535] PUT CHANNEL IN RELEASE INSTR.
	SETZ	T2,		;[535] GIVE TO JOB 0 (DEASSIGN)
	MOVSI	T3,'KLG'	;[535] LOGICAL NAME WE WANT
	REASSI	T2,		;[535] GIVE AWAY IF ALREADY EXISTS
	MOVSI	T2,'KLG'	;[535] SET UP KLUDGE AGAIN
	DEVLNM	T1,		;[535] GIVE OUR CHANNEL THAT LOGICAL NAME
	  JRST	RELDS1		;[535] SNH
	SETO	T1,		;[535] REASSIGN TO OUR JOB
	LDB	T2,[POINT 4,RELINS,12]	;[535] CHANNEL NO. TO ASSIGN
	REASSI	T1,		;[535] GET IT
RELDS1:	XCT	RELINS		;[535] NOW RELEASE FOR REAL
	POPJ	P,		;[535] DONE
;SUBROUTINE TO PERFORM A JOBPEK UUO AND CHECK THE ERROR CODE IF
;THE UUO TAKES THE ERROR RETURN.
;CALL:	MOVE	T2,JOBPEK ARG
;	PUSHJ	P,DOJBPK
;RETURNS CPOPJ IF JOB NOT IN CORE
;RETURNS CPOPJ1 IF DATA READ/WRITTEN
;RESPECTS T1

DOJBPK:	JOBPEK	T2,		;TRANSFER THE DATA
	  CAIA			;FAILED, ANALYZE ERROR CODE
	JRST	CPOPJ1		;AND GIVE SKIP RETURN
	CAIE	T2,JKSWP%	;JOB SWAPPED?
	CAIN	T2,JKPNC%	;  OR PAGE NOT IN CORE?
	POPJ	P,		;YES, GIVE NON-SKIP RETURN
	WARN	<JOBPEK failed with unexpected error code >,NOCRLF
	MOVE	T1,T2		;GET THE ERROR CODE
	PUSHJ	P,TOCT		;TYPE IT
	TELL	< for job >,NOCRLF
	MOVE	T1,J		;GET JOB NUMBER
	PUSHJ	P,TDEC		;TYPE IT
	PUSHJ	P,E.SWP1	;CLEAN UP LINE; DON'T RETURN IF UUO
	JSP	T1,INTRE1	;ABORT FUNCTION
;ROUTINE TO RESTART AFTER ERROR INTERCEPT
;ARGS	INTRES CONTAINS ADDRESS TO RESTART AT

INTRES:	PUSH	P,INTBLK+2	;[537] SAVE INT PC
	PUSH	P,T1		;[537] SAVE AC FOR INT ROUTINE
	SETZB	T1,INTBLK+2	;[537] AND ENABLE INTERRUPTS AGAIN
	EXCH	T1,INTBLK+3	;[537] GRAB & CLEAR REASONS
	MOVEM	T1,INTFLG	;SAVE FOR DEBUG
	TLNE	F,L.SAVE	;ARE WE IN THE MIDDLE OF A SAVE?
	TLNN	T1,2		;[537] AND IS THIS A CONTROL-C
	SKIPA	T1,-1(P)	;NO, GET PC AND CONTINUE
	JRST	TPOPJ		;[537] RESTORE T1 AND RETURN
INTRE1:	TLZ	F,L.OPR		;MAKE SURE OPR MESSAGE BIT IS CLEAR
	SETZM	MSGLIN		;CLEAR MESSAGE LINE
	MOVEM	T1,INTPC	;SAVE PC FOR DEBUG
	GETLIN	T1,		;GET LINE NUMBER
	TLNN	F,L.INI		;ERROR DURING INITIALIZATION?
	TLNN	T1,-1		;ATTACHED?
	JRST	REGO		;NO--RESTART
	SETO	T1,		;INDICATE CURRENT LINE "7-53"
	GETLCH	T1		;GET LINE NUMBER
	HRLZI	T1,(T1)		;LH=LINE, RH=DETACH
	ATTACH	T1,		;DO A DET
	  AOS	ATTGUF		;WE TRIED
REGO:	HRRZ	T1,.JBDDT	;ADDR OF DDT IF ANY
	JUMPE	T1,REGO1	;DONT ATTACH ORIGINAL LINE IF NO DDT
	HRLZ	T1,THSLIN	;OUR LINE NUMBER
	HRR	T1,THSJOB	;OUR JOB NUMBER
	TLO	T1,(AT.UUM)	;SET TO USER LEVEL
	ATTACH	T1,		;TRY TO REATTACH OUR TTY
	  AOS	ATTGUF		;DEBUG - COUNT ATTACH FAILURES
REGO1:	AOS	T1,INTGUF	;COUNT THE INTERCEPTS
	CAIL	T1,MAXINT	;TOO MANY?
	  ERROR	<Error intercept count exceeded>,STOP
	HRRZ	T1,-1(P)	;[537] RETURN WITH PC IN T1
	MOVE	P,PDL		;RESET PUSH DOWN POINTER
	TLZ	F,L.TTYA!L.DUMP	;NOW DETACHED
				;DUMP BECOMES DCORE, SINCE DUMP INCOMPLETE
	JRST	@INTADR
;COME HERE ON INTERCEPT DURING STARTUP

E.EINT:	PUSHJ	P,TYPIPC	;TYPE MESSAGE AND PC
	PUSHJ	P,OCRLF		;END LINE
	JRST	DAEREN		;QUIT


;COME HERE ON INTERCEPT DURING CRASH FILE PROCESSING

E.CRSE:	PUSHJ	P,TYPIPC	;TYPE MESSAGE AND PC
	MOVEI	T1,[ASCIZ/ reading crash file from /]
	PUSHJ	P,TYPSTR	;TYPE MESSAGE
	MOVE	T2,D.DEV	;GET DEVICE
	PUSHJ	P,TSIX		;TYPE IT
	PUSHJ	P,OCRLF		;END THE LINE
	JRST	CRSDON		;GIVE UP


;HERE TO TYPE MESSAGE AND PC FOR ERROR DURING STARTUP

TYPIPC:	ERROR	<Error intercept @PC >,NOCRLF
	PJRST	TOCT		;PRINT IN OCTAL
;SUBROUTINE TO CHECK USER ADDRESS
;ARGS	T1=XWD +LENGTH,START
;	J=JOB NUMBER
;VALUES	T1=XWD +LENGTH, ADDR IN SEGMENT
;	T2=JOB OR SEGMENT
;	THSOFF SET IF HISEG
;RETURN	CPOPJ IF BAD ADDRESS
;	CPOPJ1 IF ADDRESS IS VALID
;ALL AC'S RESPECTED

UADCHK:	PUSH	P,T1		;PRESERVE LEN,START
	HLRE	T2,T1
	SOJL	T2,TPOPJ	;NEG OR ZERO LEN NO FAIR
	PUSHJ	P,GTUPMP	;YES, GET THE UPMP FOR THE JOB
	  JRST	TPOPJ		;CAN'T FIND ONE??
	HLRZ	T2,(P)		;GET LENGTH OF BLOCK
	HRRZ	T1,(P)		;GET STARTING ADDRESS
	SETZ	T4,		;CLEAR STORAGE POINTER
UADCK1:	PUSHJ	P,CHKADR	;CHECH C(T1)+C(T4)
	  JRST	UADCK3		;BAD.. CHECK HIGH SEGMENT
	ADDI	T4,^D512	;ADD SIZE OF PAGE TO STORAGE
	CAIGE	T4,(T2)		;SIZE .GT. 512 WORDS
	JRST	UADCK1		;YES, CHECK START+512
	MOVEI	T4,-1(T2)		;NO, NOW CHECK END OF BLOCK
	PUSHJ	P,CHKADR	;CHECK C(T1)+C(T4)
	  JRST	UADCK3	;DOESN'T CHECK, LOOK AT HIGH SEG
	MOVE	T1,(P)		;RESTORE LEN,START
	ADDI	T2,-1(T1)	;[526] ADDR OF LAST WORD IN GROUP
UADCK2:	POP	P,T1		;RESTORE LEN,,START
	CAIGE	T2,17		;END IN AC'S?
	JRST	LOSOK		;YES, ITS OK
	MOVEI	T2,(T1)		;GET START
	CAIGE	T2,.JBPFI	;PAST MONITOR RESERVED AREA?
	POPJ	P,		;NO, ERROR
LOSOK:	MOVEI	T2,(J)		;RETURN JOB NUMBER
	SETZM	THSOFF		;AND LOW SEG FLAG
	JRST	CPOPJ1		;GOOD RETURN

;HERE IF BLOCK NOT IN LOW SEGMENT, CHECK HIGH

UADCK3:	ADDI	T2,(T1)		;T2=END OF GROUP
	HRROI	T1,.GTSGN	;SEGMENT TABLE
	PUSHJ	P,GTBSPY	;GET SEGMENT NUMBER FOR JOB
	  JRST	TPOPJ		;VERY STRANGE!!
	JUMPLE	T1,TPOPJ	;NO HIGH SEGMENT, FAIL
	MOVSI	T1,(T1)		;SEGMENT NUMBER AS ITEM
	HLLM	T1,-1(P)	;SAVE ON STACK
	HRRI	T1,.GTUPM	;JBTUPM TABLE
	PUSHJ	P,GTBSPY	;GET ADDRESS
	  JRST	TPOPJ		;???
	HLRZ	T1,T1		;GET LEFT HALF
	TRZ	T1,PG.BDY	;CLEAR LOW ORDER BITS
	MOVEM	T1,THSOFF	;USE THAT AS OFFSET
	SUBI	T2,(T1)		;GET END RELATIVE TO HIGH SEG
	JUMPL	T2,TPOPJ	;TOO LOW FOR HIGH SEG
	EXCH	T1,0(P)		;PREPARE TO...
	SUBB	T1,0(P)		;GET ADJUSTED LEN,,START ON STACK
	TRNE	T1,400000	;TROUBLE IF
	JRST	TPOPJ		;START NOT IN HIGH SEG
	HRROI	T1,.GTSGN	;SEGMENT TABLE
	PUSHJ	P,GTBSPY	;FIND SEG NO FOR HI SEG
	  JRST	TPOPJ		;STRANGE INDEED
	JUMPLE	T1,TPOPJ	;BOMB IF NO HIGH SEGMENT
	HRLM	T1,-1(P)	;SAVE WITH RETURN ADDR
	PUSHJ	P,JSSIZE	;GET HIGH SEG SIZE
	  JRST	TPOPJ
	CAILE	T2,(T1)		;IS END WITHIN HIGH SEG?
	JRST	TPOPJ		;NO
	HLRZ	T2,-1(P)	;GET SEG NO
	JRST	TPOPJ1		;RESTORE ADJUSTED LEN,,START AND GIVE GOOD RETURN
;SUBROUTINE TO GET THE LENGTH OF A JOB OR SEGMENT
;ARGS	T1=JOB OR SEGMENT #
;VALUES	T1=0,,HIGHEST LEGAL ADDR RELATIVE TO START OF SEGMENT
;RETURN	CPOPJ IF NO SUCH JOB OR SEG NO
;	CPOPJ1 IF SUCCESSFUL

JSSIZE:	MOVSI	T1,(T1)		;JOB OR SEG NO AS ITEM
	HLLM	T1,0(P)		;SAVE IT
	HRRI	T1,.GTADR	;PROT,,RELOC TABLE IF JOB IN CORE
	PUSHJ	P,GTBSPY
	  POPJ	P,
	HLRZS	T1		;PROT = LEN OF SEGMENT
	JUMPN	T1,CPOPJ1	;RETURN UNLESS SWAPPED OUT
	HLLZ	T1,0(P)		;RE-GET JOB (SEG) NO
	HRRI	T1,.GTSWP	;JOBS SWAPPING PARAMS
	PUSHJ	P,GTBSPY
	  POPJ	P,
	ANDI	T1,-1-PG.BDY	;NO OF PAGES ON SWAPPING DEVICE
	SOJA	T1,CPOPJ1	;SUCCESSFUL

;SUBROUTINE TO CHACK AN ADDRESS FOR A 6.01 AND LATER MONITOR
;ARGS	T1=0,,BASE ADDRESS
;	T3=POINTER TO UPMP
;	T4=0,,DISPLACEMENT
;RETURN	CPOPJ IF BAD ADDRESS
;	CPOPJ1 IF OK
;ALL AC'S RESPECTED

CHKADR:	PUSH	P,T1		;SAVE T1
	ADD	T1,T4		;AND BUILD ADDRESS WE WANT
	PUSHJ	P,VIRADR	;GET UPMP ENTRY FOR ADDRESS
	SKIPE	T1		;IF ZERO, BAD CHECK
	CAIN	T1,PM.ZER	;SKIP IF NOT AN ALLOCATED BUT ZERO PAGE
	JRST	TPOPJ		;ERROR RETURN
	JRST	TPOPJ1		;GOOD RETURN
;SUBROUTINE TO READ A JOB'S USER PAGE MAP PAGE (UPMP) INTO CORE
;EITHER VIA A JOBPEK OR BY READING THE JOB'S SWAPPING SPACE.
;DEBUGGERS, NOTE:  THIS JOBPEK WORKS INCORRECTLY FOR YOUR OWN JOB!!
;ARGS	J=JOB NUMBER
;VALUES	T3=0,,ADDRESS OF UPMP BUFFER
;RETURN CPOPJ IF CAN'T GET UPMP FOR ANY REASON
;	CPOPJ1 IF SUCCESSFUL
;T1,T2,T4 NOT RESPECTED

GTUPMP:	TLZ	F,L.UPMP	;CLEAR IN CASE WE FAIL
	SETZM	EVAADR		;FORCE NEW READ IN PEKUSR
	SETZM	USRUPM		;CLEAR UPMP BUFFER
	MOVE	T3,[USRUPM,,USRUPM+1]
	BLT	T3,USRUPM+MAXUPM-1
	MOVSI	T3,<(JK.UPM)>(J) ;GET JOB NUMBER AND UPMP BIT IN LH
	HRRI	T3,MAXUPM	;PLUS NUMBER WORDS TO READ IN RH
	HRRZI	T4,USRUPM	;SET UP DESTINATION ADDRESS
	MOVEI	T2,T3		;SET UP JOBPEK AC
	PUSHJ	P,DOJBPK	;TRY TO READ UPMP FROM CORE
	  JRST	GTUPM1		;NOT IN CORE, TRY SWAPPING SPACE
	JRST	GTUPM2		;AND RETURN
GTUPM1:	PUSHJ	P,FINCHK	;MAKE SURE JOB IS NOT CURRENTLY BEING SWAPPED
	HRROI	T1,.GTSWP	;[532] SWAPPING POINTER TABLE
	PUSHJ	P,GTBSPY	;GET SWAPPING POINTER
	  JRST	CPOPJ		;CAN'T FIND IT??
	HLLM	T1,SEGSWP	;SAVE POINTER FOR REDPEC
	HLRE	T2,T1		;GET THE POINTER
	AOJE	T2,CPOPJ	;IF -1, WE HAVE A PROBLEM
	MOVSI	T2,-MAXUPM	;GET WORD COUNT OF BUFFER
	HRRI	T2,USRUPM-1	;MAKE AN IOWD
	SETZ	T3,		;CLEAR BLOCK OFFSET
	PUSHJ	P,REDPEC	;READ THE SWAPPING SPACE
GTUPM2:	MOVE	T1,.UPJOB	;GET OFFSET OF JOB # WORD IN UPMP
	CAME	J,USRUPM(T1)	;GOT THE RIGHT UPMP?
	POPJ	P,		;NO, ERROR
	TLO	F,L.UPMP	;MARK THAT A UPMP IS NOW IN CORE
	MOVEI	T3,USRUPM	;[563]
	JRST	CPOPJ1		;AND GIVE GOOD RETURN
SUBTTL OUTPUT SUBROUTINES

;SUBROUTINE TO MARK THE SPOT FOR DATA TO COME LATER IN THE CORE-IMAGE FILE

MRKSPT:
	MOVE	T1,PATTERN	;WRITE STANDARD PATTERN
	PUSHJ	P,DWRITE
	MOVE	T1,CURBLK	;CURRENT BLOCK IN FILE
	MOVEM	T1,REMBLK	;SAVE FOR REWRITING LATER
	MOVEM	BP,REMWRD	;AND WORD ADDR
	SETZM	WRDCNT		;START COUNTING WORDS WRITTEN
	POPJ	P,

;SUBROUTINE TO WRITE ONE WORD IN THE CORE-IMAGE FILE
;ARGS	T1=WORD TO WRITE

DWRITE:	AOS	WRDCNT		;COUNT WORDS WRITTEN
	AOBJN	BP,DWRT1	;JUMP IF BUFFER NOT FULL
	SKIPE	CURBLK		;SKIP IF FIRST BLOCK OF FILE
	PUSHJ	P,BLKWRT	;NO, WRITE OUT OLD BLOCK
	SETZM	DAEBUF+1
	MOVE	BP,[DAEBUF+1,,DAEBUF+2]
	BLT	BP,DAEBUF+177
	MOVE	BP,BPSTRT	;RESET BYTE PTR TO BEGINNING OF BLOCK
	ADDI	BP,1		;POINT TO BUFFER
	AOS	CURBLK		;AND BUMP CURRENT BLOCK NUMBER
DWRT1:	MOVEM	T1,(BP)		;STORE WORD IN BLOCK
	POPJ	P,

;SUBROUTINE TO WRITE A BLOCK
;ARGS	CURBLK=BLOCK NUMBER TO WRITE

BLKWRT:	MOVE	T2,CURBLK	;BLOCK NUMBER IN FILE
	SKIPE	UPDFLG		;SKIP IF DON'T NEED TO DO USETO
	USETO	DSK,(T2)	;SET TO WRITE THIS BLOCK
	SETZM	UPDFLG		;NOTE THAT WE DONT NEED USETO NEXT TIME
	OUTPUT	DSK,DLIST	;WRITE THE BLOCK
	STATO	DSK,IO.ERR!IO.EOF ;SKIP IF ERRORS ON THE WRITE
	POPJ	P,
	JRST	E.OERR
;SUBROUTINE TO UPDATE THE WORD MARKED BEFORE FOR UPDATING
;ARGS	T1=ACTUAL DATA
;	REMBLK=BLOCK NUMBER IN FILE CONTAINING WORD TO WRITE
;	REMWRD=ADDR IN DAEBUF OF WORD TO WRITE

WRTSPT:	MOVE	T2,REMBLK	;T2=BLOCK WHICH CONTAINS THE WORD
	MOVE	T4,REMWRD	;T4=ADDR OF WORD IN DAEBUF
	CAME	T2,CURBLK	;SKIP IF STILL IN CURRENT BLOCK
	JRST	WRTSP1		;NO, MUST UPDATE PREVIOUSLY WRITTEN BLOCK
	EXCH	T1,(T4)		;STORE IN CORE
	CAME	T1,PATTERN	;AND SEE IF WE FOUND THE RIGHT WORD
	JRST	E.BPT		;NO, SOMETHING WENT WRONG
	POPJ	P,		;BEAUTIFUL!

;HERE TO UPDATE A PREVIOUSLY WRITTEN BLOCK

WRTSP1:	USETI	DSK,(T2)	;SET TO READ THE BLOCK
	INPUT	DSK,UPDLST	;READ THE BLOCK
	STATZ	DSK,IO.ERR!IO.EOF ;TEST FOR ERRORS
	JRST	E.WRD		;DIDN'T MAKE IT
	ADDI	T4,SECBUF-DAEBUF;CHANGE ADDR TO POINT TO SECBUF
	EXCH	T1,(T4)		;STORE DATA, GET OLD WORD
	CAME	T1,PATTERN	;COMPARE WITH PATTERN
	JRST	E.BPT		;SOMETHING WENT WRONG
	USETO	DSK,(T2)	;NOW SET TO WRITE THE BLOCK BACK OUT
	SETOM	UPDFLG		;NOTE THAT NEXT REGULAR OUTPUT MUST DO USETO
	OUTPUT	DSK,UPDLST	;REWRITE THE BLOCK
	STATO	DSK,IO.ERR!IO.EOF ;CHECK FOR ERRORS
	POPJ	P,		;OK

E.OERR:	AOS	WRTGUF		;NOTE ERROR
	ERROR	<Output>,NOCRLF
	JRST	E.WRD1
E.WRD:	ERROR	<Input>,NOCRLF
E.WRD1:	TELL	< error, status = >,NOCRLF
	GETSTS	DSK,T1
	PUSHJ	P,TOCT
	PUSHJ	P,PCRLF
	PUSHJ	P,SNH		;CHECK FOR UUO
	JRST	E.EEND		;[471]CLOSE AND ABORT

E.BPT:	EXCH	T1,(T4)		;RESTORE ORIGINAL WORD
	ERROR	<Tried to overwrite data word>,OPR
	PUSHJ	P,SNH

E.EEND:	MOVEI	T2,DSK		;[471]SET UP AND THEN
	RESDV.	T2,		;[471]RELEASE DSK
	  JFCL			;[471]OH WELL...
	POP	P,(P)		;[471]CLEAN UP TE STACK
	JRST	EDCORE		;[471]ABORT THE FUNCTION

;HERE TO OUTPUT A HALF WORD OCTAL NUMBER WITHOUT SUPRESSING LEADING ZEROS

TOCTAL:	HRLI	T1,400000	;PUT A FLAG IN LH(T1)
TOCTA1:	MOVEI	T2,7		;GET MASK TO T2
	AND	T2,T1		;EXTRACT LOW ORDER 3 BITS
	LSH	T1,-3		;SHIFT THREE BITS TO RIGHT
	HRLM	T2,(P)		;SAVE LAST NUMBER ON PUSH DOWN LIST
	TRNN	T1,400000	;FLAG REACHED RH YET?
	PUSHJ	P,TOCTA1	;NO, LOOP BACK ON PDL
	HLRZ	T1,(P)		;GET LAST NUMBER
	MOVEI	SC,"0"(T1)	;CONVERT TO ASCII
	PUSHJ	P,TYPCHR	;TYPE IT
	POPJ	P,		;AND RETURN
;SUBROUTINE TO PERFORM GETTAB VIA SPY IF POSSIBLE
;ARGS	T1=GETTAB ARG
;VALUES	T1=GETTAB VALUE
;THERE IS NO NEED TO SUPPORT -2 ITEM (JOBS HIGH SEG)

GTBSPY:	TLNE	F,L.DSK		;[551]ARE WE READING FROM DSK?
	  PJRST	GTBDSK		;YES, GET FROM DISK
	PUSHJ	P,SAVE4		;SAVE P1-P4
	MOVEI	P1,(T1)		;P1=TABLE NUMBER
	CAMLE	P1,MAXGTB	;SKIP IF LEGAL TABLE
	JRST	GTBGTB		;NO, TRY GETTAB ANYWAY
	ADD	P1,GTBST	;ADDR OF PTR FOR THIS TABLE
	LDB	P3,[POINT 3,0(P1),11] ;GET TYPE OF TABLE
	CAIE	P3,.SLIXI	;RANDOM TABLE?
	CAIN	P3,.SLIXR	; OR RANGED GETTAB?
	JRST	GTBSP2		;YES, LH=-1 IS NOT OUR JOB
	JUMPGE	T1,GTBSP2	;IF LH IS NEGATIVE, MAKE INDEX
	HRLI	T1,(J)		;  JOB IN J
GTBSP2:	CAIN	P3,.SLIXP	;IS DATUM IN THE PDB?
	JRST	GTBPDB		;YES, GO GET IT
	CAIN	P3,.SLIXS	;INDEXED BY JOB OR SEGMENT NUMBER?
	SKIPA	P2,JBTMXL	;YES, MAX IS JOBN+SEGN-1
	LDB	P2,[POINT 9,0(P1),8] ;NO. GET MAX ITEM VALUE
	CAIE	P3,.SLIXR	;IS THIS A RANGED GETTAB?
	JRST	GTBSP1		;NO, P2 CONTAINS 0,,MAX
	SKIPN	P3,RNGTAB	;DO WE HAVE THE ADDRESS OF RNGTAB?
	JRST	GTBGTB		;NO, USE A GETTAB
	ADDI	P2,(P3)		;ADD OFFSET INTO RNGTAB FOR THIS ENTRY
	MOVE	P2,400000(P2)	;GET MIN,,MAX FROM RNGTAB ENTRY
GTBSP1:	HLRE	P3,T1		;GET ITEM NUMBER CALLER WANTS
	HRRE	P4,P2		;GET MAX VALUE OF TABLE
	CAMLE	P3,P4		;.LE. MAX?
	JRST	GTBGTB		;NO, TRY A GETTAB
	HLRE	P4,P2		;KEEP JUST MIN
	CAMGE	P3,P4		;AND .GE. MIN?
	JRST	GTBGTB		;NO, TRY A GETTAB
	MOVE	T1,@(P1)	;GET VALUE
	JRST	CPOPJ1		;GOOD RETURN

GTBPDB:	SKIPN	PDBPTR		;IS JBTPDB BASE AVAILABLE?
	JRST	GTBGTB		;NO. USE A GETTAB
	HLRZS	T1		;JOB NUMBER
	ADD	T1,PDBPTR	;PLUS JBTPDB ADDRESS
	MOVE	T1,400000(T1)	;GET ADDRESS OF WD 0 OF JOBS PDB
	JUMPE	T1,CPOPJ1	;RETURN ZERO IF NO PDB
	ADD	T1,(P1)		;ADD ON SPY OFFSET AND ITEM NUMBER
				; WHICH WERE BOTH IN GTBST TABLE
	MOVE	T1,(T1)		;GET THE WORD FROM THE PDB
	JRST	CPOPJ1		;GIVE GOOD RETURN

GTBGTB:	GETTAB	T1,		;TRY GETTAB
	  POPJ	P,
	AOS	GTBGUF		;DEBUG--COUNT TIMES WE THOUGHT GETTAB
				; WOULD LOSE BUT IT DIDNT
	JRST	CPOPJ1		;WINS
;SUBROUTINE TO GET DATA FROM GETTAB SUB-TABLE
;ARGS	T3= GETTAB ARG FOR SUB-TABLE POINTER
;	T2= SUBTABLE ARG: TABLE# CONTAINING SUBTABLE,,ITEM #
;VALUE	T1= DESIRED ITEM
;SKIP RETURN IF ITEM DEFINED

GSUBTB:	PUSH	P,T3		;SAVE THAT ARG
	CAMN	T3,LSTSTP	;SAME SUBTABLE POINTER AS LAST TIME?
	JRST	[MOVE	T1,LSTSTV ;YES, GET LAST VALUE
		 JRST	GSUBT1]	  ;AND JOIN COMMON CODE
	MOVEM	T3,LSTSTP	;SAVE THIS SUBTABLE POINTER FOR NEXT TIME
	MOVE	T1,T3		;GET SUBTABLE POINTER
	PUSHJ	P,GTBSPY
	  JRST	GSUBTX		;TOO BAD, NO SUBTABLE
	MOVEM	T1,LSTSTV	;SAVE VALUE OF POINTER FOR QUICK CHECK
GSUBT1:	JUMPE	T1,GSUBTX	;NO SUBTABLE EXISTS
	LDB	T3,[POINT 9,T1,8] ;GET UPPER LIMIT ON SUBTABLE
	CAIGE	T3,0(T2)	;COMPARE DESIRED ITEM #
	JRST	GSUBTX		;OOPS, OFF THE END
	HRRZS	T1		;SUBTABLE POINTER IS AN ITEM NUMBER
	ADD	T1,T2		;WITH SUB-ITEM AND TABLE
	MOVSS	T1		;SWAP TO GETTAB FORM
	PUSHJ	P,GTBSPY	;GETTAB THAT
	  JRST	GSUBTX		;LOSE
	AOS	-1(P)		;WIN, TAKE SKIP RETURN
GSUBTX:	POP	P,T3		;RESTORE T3
	POPJ	P,


;SUBROUTINE TO READ MONITOR LOW SEGMENT VIA SPY OR PEEK.  ALSO HANDLES
;PER-PROCESS ADDRESSES FOR THE CURRENT JOB (340000-377777)
;ARGS	T1=ADDR OF LOCATION DESIRED
;VALUES	T1=CONTENTS OF LOCATION

PEKSPY:	TLNE	F,L.DSK		;READING FROM DSK?
	PJRST	PEKDSK		;YES, GET FROM DISK
	MOVEI	T1,(T1)		;CLEAR JUNK FROM LH
	CAIL	T1,400000	;ADDRESS IN MONITOR HIGH SEG?
	JRST	PEKSP1		;YES, JUST DO PEEK
	CAIL	T1,340000	;ADDRESS IN FUNNY SPACE FOR THIS JOB?
	PJRST	PEKUSR		;YES, GET IT FROM THERE

	SKIPL	MAXGTB		;SKIP IF SPY ILLEGAL
	SKIPA	T1,400000(T1)	;OK, GET CONTENTS OF LOC

PEKSP1:	PEEK	T1,		;CANT, TRY PEEK
	POPJ	P,
;SUBROUTINE TO READ A WORD FROM THE PER-PROCESS AREA FOR A JOB.
;ARGS	T1=EXEC VIRTUAL ADDRESS MAPPED THROUGH JOB'S UPMP
;	   IN THE RANGE 340000-377777
;	J=JOB NUMBER
;VALUES	T1=CONTENTS OF LOCATION OR 0 IF ERROR

PEKUSR:	PUSHJ	P,SAVE2		;SAVE P1-P2
	MOVE	P1,EVAADR	;GET ADDR OF FIRST WORD IN CORE
	CAIL	T1,(P1)		;IF WORD WE WANT IS ALREADY IN
	CAILE	T1,EVASIZ-1(P1) ;  CORE, JUST PICK IT UP
	CAIA			;NO, MUST READ IT
	JRST	PEKUS1		;GET IT FROM CORE
	SETZM	EVAADR		;FORCE READ NEXT TIME
	MOVSI	P1,<(JK.EVA)>(J) ;JOB NUMBER+READ EVA FLAG TO LH
	HRRI	P1,EVASIZ	;NUMBER WORDS TO READ TO RH
	MOVSI	P2,(T1)		;ADDRESS TO READ IN LH
	TLZ	P2,EVASIZ-1	;MOVE BACK TO BUFFER BOUNDARY
	HRRI	P2,EVABUF	;ADDR IN OUR CORE TO RH
	PUSH	P,T2		;SAVE T2 (USE T2 BECAUSE OF DOJBPK)
	MOVEI	T2,P1		;POINT TO BLOCK
	PUSHJ	P,DOJBPK	;READ IT
	  JRST	PEKUS2		;HAVE TO READ IT FROM SWAPPING SPACE
	POP	P,T2		;RESTORE T2
	HLRZM	P2,EVAADR	;UPDATE FIRST ADDRESS IN CORE
PEKUS1:	SUB	T1,EVAADR	;COMPUTE OFFSET IN BLOCK
	MOVE	T1,EVABUF(T1)	;GET WORD FROM BUFFER
	POPJ	P,		;RETURN

;HERE TO READ THE DATA FROM THE SWAPPING SPACE
PEKUS2:				;PEKSPY ONLY DESTROYS T1 SO WE HAVE
	PUSH	P,T3		;TO SAVE ALL THE TEMP REGISTERS WHICH
	PUSH	P,T4		;ARE ZAPPED BY GTUPMP, REDPEC, ETC.
	PUSH	P,THSOFF	;ALSO SAVE THIS FOR SAFETY
	SETZM	THSOFF		;INSURE THAT ALL THE CALCULATIONS WORK
	MOVEI	P1,(T1)		;COPY ADDRESS CALLER WANTED
	PUSHJ	P,GTUPMP	;GET THE PAGE MAP FROM THE SWAPPING
				; SPACE.  GTUPMP CALLS FINCHK.
	  JRST	PEKUS3		;FAILED FOR SOME REASON
	MOVEI	T1,(P1)		;RESTORE DESIRED ADDRESS
	ADDI	T1,440000	;ADD OFFSET THAT WILL POINT US TO THE
				;PER-PROCESS SLOTS IN THE UPMP (400-417)
	PUSHJ	P,VIRADR	;GET MAP SLOT FOR THIS PAGE
	JUMPE	T1,PEKUS3	;RETURN ZERO IF NO PAGE THERE
	HRLM	T1,SEGSWP	;STORE PAGE POINTER FOR REDPEC
	MOVEI	T3,(P1)		;GET ADDRESS BACK
	TRZ	T3,EVASIZ-1	;FORCE ADDRESS TO BLOCK BOUNDARY
	MOVEM	T3,EVAADR	;AND STORE AS NEW CORE ADDRESS
	ANDI	T3,PG.BDY	;ISOLATE OFFSET OF BLOCK IN PAGE
	IDIVI	T3,BLKSIZ	;AND COMPUTE BLOCK OFFSET IN PAGE
	MOVSI	T2,-EVASIZ	;-NUMBER WORDS TO READ IN LH
	HRRI	T2,EVABUF-1	;MAKE IOWD TO OUR BUFFER
	PUSHJ	P,REDPEC	;READ THE BLOCK(S) FROM THE SWAPPING SPACE
	SKIPA	T1,P1		;GET ADDRESS USER WANTED BACK
PEKUS3:	MOVEI	T1,0		;RETURN ZERO ON ERROR
	POP	P,THSOFF	;RESTORE THE STUFF WE SAVED
	POP	P,T4		;...
	POP	P,T3		;...
	POP	P,T2		;...
	JUMPN	T1,PEKUS1	;IF NO ERROR, GET DATA FROM BUFFER
	POPJ	P,		;ELSE RETURN A ZERO
SUBTTL	CLOCK QUEUE SUBROUTINES

;HERE WHEN A TIMER RUNS OUT
WAKJOB:	HRRE	J,NEXTJB	;GET THE JOB NUMBER
	SETZM	@JBTCLK		;CLEAR OUT ENTRY
	PUSHJ	P,CLEANQ	;CLEAN THE QUEUE
	JUMPLE	J,WAKSLF	;JOBS .LE. 0 ARE INTERNAL
	WAKE	J,		;WAKE THE JOB
	  AOS	WAKGUF		;WE TRIED
	JRST	DALOOK		;RESCAN THE QUEUE

WAKSLF:	PUSHJ	P,@CLKDSP(J)	;INVOKE INTERNAL ROUTINE
	JRST	DALOOK

	EXP	AVLSCN		;(-3) AVAIL.SYS UPDATE SCAN
	EXP	IOECLR		;(-2)CLEAR I/O ERROR ON ERROR.SYS
	EXP	FRCFCT		;(-1) FORCE OUT THE FACT BUFFER
CLKDSP:	EXP	CHECK		;(0) CHECKPOINT JOBS

	DEFINE	.IFNFT	(FT,LBL),<
IFE FT,<LBL:	..IFFT==1>>
..IFFT==0

.IFNFT	(FTCHKPNT,CHECK)
.IFNFT	(FTFACT!FTCHKPNT,FRCFCT)
.IFNFT	(MAXAGE,FRCFCT)
IFN ..IFFT,<
	AOS	CLKGUF		;NOTE A REQUEST THAT SNH
	POPJ	P,
>
	PURGE	.IFNFT,..IFFT


AVLSCN:	PUSHJ	P,AVLAGE	;SEE IF TIME TO START A NEW AVAIL.SYS
	HRREI	J,AVLRQ		;SET FOR NEXT WAKEUP
	MOVEI	T1,AVLTIM	;FOR AVAIL.SYS SCAN
	PJRST	CLKREQ		;ENTER THE REQUEST AND RETURN
;SUBROUTINE TO ENTER A REQUEST INTO THE QUEUE
;ARGS	T1=NUMBER OF SEC TO SLEEP
;	J=JOB NUMBER
;USES T1-T4

CLKREQ:	JUMPE	T1,NULREQ	;NULL REQUEST - CLEAN Q AND WAKE IMMEDIATELY
	MUL	T1,JIFSEC	;CONVERT TO JIFFIES IN T2
	PUSHJ	P,GETUPT	;GET THE UPTIME IN TICKS
	ADD	T2,T1		;TIME TO GET UP
	MOVEM	T2,@JBTCLK	;STORE IN QUEUE
	PJRST	CLEANQ		;CLEAN THE QUEUE

NULREQ:	SETZM	@JBTCLK		;CLEAR THE REQUEST
	JUMPLE	J,CLEANQ	;NO WAKE IF INTERNAL REQUEST
	WAKE	J,		;WAKE THE JOB IMMEDIATELY
	  AOS	WAKGUF		;WE TRIED AND FAILED
;	PJRST	CLEANQ		;FALL THROUGH TO RE-SCAN Q

;HERE TO SORT THE QUEUE

CLEANQ:	SETZB	T2,NEXTUP	;FLAG QUEUE EMPTY
				; T2 GETS NEXT JOB TO WAKE
	PUSH	P,J		;SAVE AC J
	MOVE	J,QPNTR		;GET THE AOBJN POINTER
	HRLOI	T1,377777	;T1_UPTIME OF NEXT WAKE
FNDMIN:	SKIPE	T3,@JBTCLK	;GET FIRST TIME
	CAMG	T1,T3		;YES--IS IT BETTER
	JRST	NXTREQ		;NO--TRY NEXT
	MOVE	T1,T3		;T1_SHORTEST TIME
	HRREI	T2,(J)		;T2_JOB WITH THAT TIME
NXTREQ:	AOBJN	J,FNDMIN	;LOOP OVER ALL JOBS
	MOVEM	T1,NEXTUP	;SAVE T1
	MOVEM	T2,NEXTJB	;SAVE JOB NUMBER
	POP	P,J
	POPJ	P,
;SUBROUTINE TO ENSURE THAT ANY FACT FILE ENTRY
;GETS OUT IN MAXAGE SECONDS

IFN FTFACT!FTCHKPNT,<
IFN MAXAGE,<
BUFAGE:	SKIPE	FACTSZ		;IF ANYTHING THERE, REQUEST IS ALREADY IN
	POPJ	P,
	PUSH	P,J		;SAVE J
	HRREI	J,AGERQ		;SET OUR REQUEST TYPE
	MOVEI	T1,MAXAGE	;SET MAX TIME IN BUFFER
	PUSHJ	P,CLKREQ	;MAKE THE REQUEST
	POP	P,J
	POPJ	P,		;DONE

FRCFCT:	TLO	F,L.FORC	;ENSURE IT GETS DUMPED SOON
	POPJ	P,
>;END MAXAGE COND
IFE MAXAGE,<BUFAGE==CPOPJ>
>;END FTFACT!FTCHKPNT COND

IOECLR:	SETZM	IOERR		;[62]CLEAR FLAG SO ERRFIN RETRIES NOW
	POPJ	P,		;[62]

;SUBROUTINE TO RETURN JOB'S CONTROLLING TTY NUMBER
;ARG	J=JOB NUMBER
;VALUE	T1=TTY NUMBER (-1 IF CTY)
;NON-SKIP RETURN IF JOB DETACHED

GETTTY:	HRROI	T1,.GTTTY	;GET JOB'S TTY DDB ADDR
	PUSHJ	P,GTBSPY	;GET ADDR OF DDB FOR USER JOB
	  POPJ	P,		;CAN'T FIND IT!!!
	JUMPE	T1,CPOPJ	;GIVE UP IF JOB IS DETACHED
IFN DEVNAM,<MOVEI T1,DEVNAM(T1)>
	PUSHJ	P,PEKSPY	;GET TTY NAME FROM DDB
	TLNN	T1,-1		;LEFT HALF 0 IF DETACHED
	POPJ	P,		;LOSE...
	HRLZI	T2,(T1)		;LINE NUMBER IN SIXBIT TO LEFT HALF
	JUMPE	T2,TTYCTY	;ONLY CTY HAS NO LINE NO
	SETZ	T1,
DAGLIN:	LSH	T2,3		;IGNORE 3 BITS OF OCTAL SIXBIT CODE
	LSHC	T1,3		;BUT GET THE NUMERIC QUANTITY
	JUMPN	T2,DAGLIN	;LOOP IF ANY MORE DIGITS
	JRST	CPOPJ1		;THAT'S ALL THERE IS TO IT

TTYCTY:	SETO	T1,		;NOTE CTY
	JRST	CPOPJ1		;AND RETURN SUCCESSFUL
SUBTTL	ROUTINES TO RECORD HARDWARE ERROR INFO IN ERROR.SYS

;ROUTINE TO DUMP DISK STATISTICS INTO ONE OR MORE .ESDSC ENTRIES.

DSCNBK==<ERRSIZ-DSC1ST>/<ZUSCL-XUSCL+1> ;NUMBER OF BLOCKS THAT WILL FIT
					;INTO EACH .ESDSC ENTRY
DSCNEN==^D250/DSCNBK		;LIMIT THE NUMBER OF UNITS DUMPED TO
				;250 TO AVOID LOOPS IN THE UDB'S

DMPDSK:	PUSHJ	P,SAVE3		;SAVE P1-P3
	MOVEI	P3,DSCNEN	;GET MAX NUMBER OF ENTRIES TO DUMP
	MOVE	T1,[%LDUNI]	;POINTER TO UDB CHAIN
	PUSHJ	P,GTBSPY	;GET IT
	  POPJ	P,		;NONE, FORGET IT
	HLRZ	P2,T1		;FIRST ADDRESS TO RH OF P2
	JUMPE	P2,CPOPJ	;NONE THERE
DMPDS1:	MOVSI	T1,.ESDSC_9	;ERROR CODE FOR ERRINI
	PUSHJ	P,ERRINI	;SETUP BUFFER AND P4
DSCSTP==0			;OFFSET OF POINTER TO FIRST BLOCK
	PUSH	P4,[0,,DSC1ST]	;MAKE IT 0,,OFFSET TO FIRST BLOCK
DSC1ST==1			;OFFSET OF FIRST BLOCK
	MOVSI	P1,-DSCNBK	;AOBJN POINTER OF BLOCKS TO DO
DMPDS2:	MOVE	T2,XUSCL	;GET AOBJN POINTER OF WORDS IN BLOCK
	HLLZ	T1,T2		;-WORDS,,0
	PUSH	P4,T1		;SAVE AS POINTER FOR SYSERR
	PUSHJ	P,UNIDMP	;DUMP THE WORDS FOR THIS BLOCK
	MOVEI	T1,UNISYS(P2)	;POINT TO LINK WORD IN UDB
	PUSHJ	P,PEKSPY	;READ IT
	HLRZ	P2,T1		;MOVE TO RH OF P2
	AOBJP	P1,DMPDS3	;QUIT IF FILLED THIS ENTRY
	JUMPN	P2,DMPDS2	;LOOP IF MORE TO DO
DMPDS3:	MOVNI	T1,(P1)		;GET -BLOCKS IN ENTRY
	HRLM	T1,ERABFS+DSCSTP ;STORE IN ENTRY
	PUSHJ	P,ERRFIN	;CLOSE THIS ENTRY AND WRITE FILE
	SOSLE	P3		;QUIT IF DUMPED TOO MANY
	JUMPN	P2,DMPDS1	;LOOP IF MORE BLOCKS
	POPJ	P,		;DONE


;SUBROUTINE TO DUMP SELECTED MONITOR ITEMS
;ARGS	T2=AOBJN WORD FOR LIST OF ITEMS
;	P4=AOBJN WORD FOR OUTPUT BUFFER
;VALUES	P4=UPDATED BUFFER POINTER
;RETURN	CPOPJ, T1-2 BLOWN, OTHERS INTACT

UNIDMP:	MOVEI	T1,@(T2)	;GET ADDRESS TO DUMP
	PUSHJ	P,PEKSPY
	PUSH	P4,T1		;STORE IN ERROR.SYS BUFFER
	AOBJN	T2,UNIDMP	;LOOP FOR ALL ITEMS
	POPJ	P,
;TABLES FOR UNIT DATA BLOCK ITEMS TO BE DUMPED


XDVEL:	XWD	.-ZDVEL,.+1
	Z	UNINAM(P3)	;(R0) PHYSICAL UNIT NAME
	Z	UNIHID(P3)	;(R1) PACK (HOME BLOCK) ID
	Z	UNIHCT(P3)	;(R2) HARD ERROR COUNT
	Z	UNISCT(P3)	;(R3) SOFT ERROR COUNT
	Z	UNIECT(P3)	;(R4) RETRY COUNT
	Z	UNISOF(P3)	;(R5) 1CONI - ERROR CONI AFTER INITIAL ATTEMPT
	Z	UNIERR(P3)	;(R6) 2CONI - ERROR CONI AFTER 1ST RECALIBRATE
	Z	UNISDI(P3)	;(R7) 1DATAI - AFTER INITIAL ATTEMPT
	Z	UNIHDI(P3)	;(R10) 2DATAI - AFTER 1ST RECALIBRATE
	Z	UNIHBN(P3)	;(R11) BLOCK NO OF LAST HARD ERROR
	Z	UNIMCT(P3)	;(R12) SOFTWARE-DETECTED ERROR COUNTS
	Z	UNIPCT(P3)	;(R13) SEEK INCOMPLETE ERRORS
	Z	UNIHNG(P3)	;(R14) HUNG COUNTS
ZDVEL==.-1


XUSCL:	XWD	.-ZUSCL,.+1	;AOBJN WORD FOR TABLE OUTPUT BY DMPDSK
	Z	UNINAM(P2)	;(R1) DEV NAM
	Z	UNIHID(P2)	;(R2) PACK ID
	Z	UNIHCT(P2)	;(R3) HARD ERROR COUNT
	Z	UNISCT(P2)	;(R4) SOFT ERROR COUNT
	Z	UNIPCT(P2)	;(R5) SEEK ERROR COUNT
	Z	UNIHNG(P2)	;(R6) HUNG COUNTS
	Z	UNIMCT(P2)	;(R7) SOFTWARE-DETECTED ERRORS
	Z	UNIBRC(P2)	;(R10) BUFFERED READS
	Z	UNIBWC(P2)	;(R11) BUFFERED WRITES
	Z	UNIDRC(P2)	;(R12) DUMP READS
	Z	UNIDWC(P2)	;(R13) DUMP WRITES
	Z	UNIMRC(P2)	;(R14) MONITOR READS
	Z	UNIMWC(P2)	;(R15) MONITOR WRITES
	Z	UNIICT(P2)	;(R16) SWAP READS
	Z	UNIOCT(P2)	;(R17) SWAP WRITES
	Z	UNIMSC(P2)	;(R20) MONITOR SEEKS
	Z	UNIUSC(P2)	;(R21) USER SEEKS
ZUSCL==.-1
XMDVEL:	XWD	.-ZMDVEL,.+1
	Z	UNINAM(P3)	;(R0)PHYSICAL UNIT NAME
	Z	UNIHID(P3)	;(R1)PACK ID (HOME BLOCK ID)
	Z	UNILOG(P3)	;(R2)LOGICAL NAME OF UNIT (STR NAME)
	Z	UNIHBN(P3)	;(R3)BLOCK OF LAST HARD ERROR
	Z	UNIECT(P3)	;(R4)RETRY COUNT
	Z	UNISOF(P3)	;(R5)1CONI - ERROR CONI AFTER INITIAL ATTEMPT
	Z	UNIERR(P3)	;(R6)2CONI - ERROR CONI AFTER 1ST RECALIBRATE
	Z	UNIMCT(P3)	;(R7)SOFTWARE DETECTED ERROR COUNTS
	Z	UNIPCT(P3)	;(R10)SEEK INCOMPLETE ERRORS
	Z	UNIHNG(P3)	;(R11)HUNG COUNTS
ZMDVEL==.-1


XTPEL:	XWD	.-ZTPEL,.+1
	Z	TUBRID(P1)	;(R1)REELID
	Z	TUBFIL(P1)	;(R2)FILES FROM BOT
	Z	TUBREC(P1)	;(R3)RECORDS FROM LAST EOF
	Z	TUBTRY(P1)	;(R4)RETRY COUNT + HARD ERROR BIT
	Z	TUBCCR(P1)	;(R5)CHARACTERS INTO CURRENT RECORD
	Z	TUBPBE(P1)	;(R6)POSITION BEFORE ERROR
	Z	TUBFES(P1)	;(R7)FINAL ERROR STATE
ZTPEL==.-1

XTPUL:	XWD	.-ZTPUL,.+1
	Z	DEVNAM(P3)	;(R0)DEVICE NAME
	Z	TUBRID(P1)	;(R1)REELID
	Z	TUBCRD(P1)	;(R2)CHARACTERS READ
	Z	TUBCWR(P1)	;(R3)CHARACTERS WRITTEN
	Z	TUBSRE(P1)	;(R4)SOFT READ ERRORS
	Z	TUBHRE(P1)	;(R5)HARD READ ERRORS
	Z	TUBSWE(P1)	;(R6)SOFT WRITE ERRORS
	Z	TUBHWE(P1)	;(R7)HARD WRITE ERRORS
ZTPUL==.-1

XTPEL1:	XWD .-ZTPEL1,.+1	;
	Z	TUBUID(P1)	;(R12)P,PN OF USER
	Z	TUBPGM(P1)	;(R13) SIXBIT PROGRAM NAME
	ZTPEL1==.-1		;
XD2EL:	XWD	.-ZD2EL,.+1
	Z	TUBPBE(P3)	;(R3) POSITION BEFORE ERROR
	Z	TUBFES(P3)	;(R4) FINAL ERROR STATE
	Z	TD2CNI(P1)	;(R5) CONI INITIAL
	Z	TD2CIF(P1)	;(R6) CONI FINAL
	Z	TD2ZRO(P1)	;(R7) NUMBER OF SEEKS (0 FOR MAGTAP)
	Z	TD2RED(P1)	;(R10) NUMBER OF FRAMES READ
	Z	TD2WRT(P1)	;(R11) NUMBER OF FRAMES WRITTEN
	Z	TD2ZRO(P1)	;(R12) SIXBIT FILENAME
	Z	TUBUID(P3)	;(R13) [P,PN] OF USER MAKING REQUEST
	Z	TUBPGM(P3)	;(R14) SIXBIT NAME OF PROGRAM RUNNING
	Z	TD2D1I(P1)	;(R15) DATAI PTCR INITIAL
	Z	TD2D1F(P1)	;(R16) DATAI PTCR FINAL
	Z	TD2D2I(P1)	;(R17) DATAI PBAR INITIAL
	Z	TD2D2F(P1)	;(R20) DATAI PBAR FINAL
	Z	TUBSRE(P3)	;(R21) SOFT READ ERRORS
	Z	TUBSWE(P3)	;(R22) SOFT WRITE ERRORS
	Z	TUBHRE(P3)	;(R23) HARD READ ERRORS
	Z	TUBHWE(P3)	;(R24) HARD WRITE ERRORS
	Z	TUBFIL(P3)	;(R25) FILE POSITION
	Z	TUBREC(P3)	;(R26) RECORD POSITION
	Z	TD2CS0(P1)	;(R27) CHANNEL LOGOUT 0
	Z	TD2CS1(P1)	;(R30) CHANNEL LOGOUT 1
	Z	TD2CS2(P1)	;(R31) CHANNEL LOGOUT 2
	Z	TD2CC1(P1)	;(R32) FIRST CCW
	Z	TD2CC2(P1)	;(R33) SECOND CONTROL WORD
	Z	TD2MPE(P1)	;(R34) COUNT OF MPE
	Z	TD2NXM(P1)	;(R35) COUNT OF NXM
	Z	TD2ZRO(P1)	;(R36) SOFT POSITIONING ERRORS
	Z	TD2ZRO(P1)	;(R37) HARD POSITIONING ERRORS
	Z	TD2OVR(P1)	;(R40) NUMBER OF OVERRUNS
	Z	TD2ICR(P1)	;(R41) CONTENTS OF INITIAL CONTROL REG
	Z	TD2VER(P1)	;(R42) DX20 MICRO-CODE VERSION #
ZD2EL==.-1
XR2EL1:	XWD	.-ZR2EL1,.+1
	Z	UNINAM(P3)	;(R0) SIXBIT DEVICE NAME
	Z	UNILOG(P3)	;(R1) VOLUME ID
ZR2EL1==.-1

XR2EL2:	XWD	.-ZR2EL2,.+1
	Z	UNIHBN(P3)	;(R3) LOC OF ERROR
	Z	UNIECT(P3)	;(R4) FINAL ERROR STATE
	Z	UNISOF(P3)	;(R5) CONI INITIAL
	Z	UNIERR(P3)	;(R6) CONI FINAL
ZR2EL2==.-1

XR2EL3:	XWD	.-ZR2EL3,.+1
	Z	0(P1)		;(R15) DATAI PTCR INITIAL (UNISCR)
	Z	1(P1)		;(R16) DATAI PTCR FINAL (UNIHCR)
	Z	2(P1)		;(R17) DATAI PBAR INITIAL (UNISDR)
	Z	3(P1)		;(R20) DATAI PBAR FINAL (UNIHDR)
	Z	UNIHCT(P3)	;(R21) HARD ERROR STATISTICS
	Z	UNISCT(P3)	;(R22) SOFT ERROR STATISTICS
	Z	UNIMCT(P3)	;(R23) SOFTWARE ERROR STATISTICS
	Z	UNIHNG(P3)	;(R24) HUNG COUNTS
ZR2EL3==.-1
;ROUTINES TO SET UP FOR CALL TO ROUTINE TO PUT ACTUAL ENTRY INTO ERROR
; FILE
;ALL HAVE SAME CALLING SEQUENCE
;ARGS:	T2 -- CODE FOR ERROR SYS ENTRY
;	T1 -- ADDRESS OF BLOCK RETURNED BY ERRPT. UUO
;RETURNS CPOPJ, NO AC'S PRESERVED


;ROUTINE TO REPORT SYSTEM RELOAD (CODE 1)

SRLERR:	MOVSI	T1,.ESWHY_9	;CODE FOR WHY RELOAD
	PUSHJ	P,ERRINI	;STORE HEADER, SETUP P4 AND CLEAR BUFFER
	MOVE	T2,[%CNFG0]	;5 WORDS OF SYSTEM NAME, 2 DATE
	SUB	T2,[%CNDT1+<1,,0>]
	HLR	T2,[%CNFG0]
CNFLUP:	MOVEI	T1,.GTCNF	;FROM CNFTBL
	HRLI	T1,(T2)
	PUSHJ	P,GTBVAR	;(R0-R6) SAVE NEXT WORD OF SYSTEM NAME/DATE
	AOBJN	T2,CNFLUP	;GET IT ALL
	MOVE	T1,[%CNSTS]
	PUSHJ	P,GTBVAR	;(R7) SAVE STATES WORD
	PUSH	P4,MONVER	;(R10) MONITOR VERSION
	MOVE	T1,[%CNSER]
	PUSHJ	P,GTBVAR	;(R11) SAVE CPU0 SERIAL NUMBER
	MOVE	T1,[%CNWHY]
	PUSHJ	P,GTBVAR	;(R12) SAVE WHY RELOAD CODE IN SIXBIT
	PUSH	P,T1		;SAVE FOR AVAIL BELOW
EW%COM==13			;RELATIVE LOC'N OF POINTER WORD
	AOBJN	P4,.+1		;(R13) LEAVE SPACE FOR POINTER WORD
	MOVEI	T1,1		;FLAG WHICH SAYS 1 BIT=1 PAGE
	HRLI	T1,707070	;ADD A STRANGE CODE FOR SYSERR TO RECOGNIZE THIS WORD
	PUSH	P4,T1		;(R14) AND SAVE IN ERROR BUFFER
EW%NPT==15			;OFFSET FOR POINTER TO NXMTAB IN ENTRY
	AOBJN	P4,.+1		;(R15) LEAVE ROOM FOR POINTER
	PUSH	P,P4		;SAVE CURRENT BUFFER LOC
	MOVEI	T2,0		;START AT FIRST WORD OF OPR COMMENTS
WHYLUP:	MOVEI	T1,.GTWHY	;GETTAB FOR WHY-RELOAD COMMENTS IN ASCIZ
	HRLI	T1,(T2)		;DESIRED WORD THEREOF
	PUSHJ	P,GTBSPY	;GET IT
	  JRST	WHYCLS		;MUST NOT BE ONE
	JUMPE	T1,WHYCLS	;STOP AT END OF STRING
	PUSH	P4,T1		;(R16-) SAVE 5 CHARACTERS
	AOJA	T2,WHYLUP	;GO FOR NEXT WORD
WHYCLS:	POP	P,T1		;GET BACK START LOC OF COMMENTS
	MOVNI	T2,(T2)		;GET -VE LENGTH OF COMMENTS
	JUMPE	T2,WHYOUT	;LEAVE POINTER ZERO IF NONE
	HRLI	T2,1-ERABFH(T1)	;MAKE SWAPPED AOBJN POINTER TO COMMENTS
	MOVSM	T2,ERABFS+EW%COM ;SAVE AOBJN POINTER TO COMMENTS
WHYOUT:	MOVN	T2,NXMLEN	;GET -VE LENGTH OF NXMTAB
	JUMPGE	T2,SRLERX	;IF NONE, QUIT NOW
	HRLZS	T2		;MOVE TO LH
	HRRI	T2,1-ERABFH(P4)	;OFFSET TO FIRST TO RH
	MOVEM	T2,ERABFS+EW%NPT ;SAVE AS POINTER TO NXMTAB
	HRR	T2,NXMTAB	;GET CORE POINTER TO NXMTAB
	PUSH	P4,(T2)		;SAVE NEXT WORD IN BUFFER
	AOBJN	T2,.-1		;LOOP FOR ALL WORDS
SRLERX:	PUSHJ	P,ERRFIN	;CLOSE FILE

IFN FTMCNF,<
	PUSHJ	P,APPCNF	;APPEND MAXCNF ENTRY AS NECESSARY
>
	MOVSI	T1,.ESMRV_9	;GET ENTRY CODE FOR MONITOR RUN VALUES
	PUSHJ	P,ERRINI	;SETUP THE BUFFER
	MOVE	T1,[MRVBDY,,ERABFS] ;MAKE BLT POINTER
	BLT	T1,ERAEND	;MOVE TO BUFFER
	POP	P,ERABFS+MRVWHY ;SAVE RELOAD CODE IN BUFFER
	PUSHJ	P,NBSDAT	;GET CURRENT DATE/TIME
	MOVE	T3,T1		;SAVE
	PUSHJ	P,UPTIME	;GET UPTIME
	SUB	T3,T1		;COMPUTE TIME OF RELOAD
	MOVEM	T3,ERABFS+MRVRTM ;SAVE IN BUFFER
	PUSHJ	P,SYSNAM	;UPDATE MRV BLOCK TO REFLECT NEW
	MOVE	T1,MONVER	;  MONITOR NAME AND VERSION
	MOVEM	T1,MRVBDY+MRVVER ; FOR NEXT RELOAD
	SETZM	MRVBDY+MRVIDT	;START WITH NO DATE/TIME CHANGES
	LDB	P4,[POINT 9,MRVBLK,35] ;GET LENGTH OF BODY
	ADDI	P4,ERABFS-1	;ADJUST FOR CALCULATION AT ERFILL
	PUSHJ	P,AVLFIN	;APPEND THE ENTRY TO AVAIL
	PJRST	UPDAVL		;  AND DO AN IMMEDIATE UPDATE
;ROUTINE TO REPORT DISK AND MASSBUS ERRORS, CODES 10 AND 11
SDVERR:	TDZA	P1,P1		;SET FLAG FOR DISPATCH LATER
SMDVER:	MOVEI	P1,1		;DITTO FOR MASSBUS DEVICE ERROR
	PUSHJ	P,PROTJB	;INSURE THAT JOB WILL BE FREED
	HRRZ	P3,1(T1)	;GET UDB ADDR INTO P3 FOR GIVE ROUTINE
	HLRZ	P2,1(T1)	;ADDR OF DDB INTO P2 
	JUMPE	P2,CPOPJ	;IF NO DDB, EXIT
	JUMPE	P3,CPOPJ	;LIKEWISE IF NO UDB
	MOVEI	T1,UNIKON(P3)	;ADDRESS OF KONTROLLER DATA BLOCK
	PUSHJ	P,PEKSPY
	ADD	T1,KONREG	;NUMBER OF DRIVE REGS ON THIS CONTROLLER
	PUSHJ	P,PEKSPY
	MOVE	T3,T1		;PUT NUMBER OF REGS INTO T3
	SKIPN	P1		;IF THIS IS A MASSBUS ERROR
	SKIPN	T3		;OR NOT A DISK ERROR WITH REGISTERS
	JRST	SDVER1		;THEN ALL IS OK
	ADDI	T2,.ESMDE-.ESHDE ;MUST BE PRE-701, MAKE IT MASSBUS ERROR
				;IF A DISK ERROR WITH REGISTERS
	MOVEI	P1,1		;AND SET FLAG FOR MASSBUS ERROR DISPATCH
SDVER1:	MOVEI	T1,UNIDES(P3)	;GET ADDRESS OF UNIDES OF UDB
	PUSHJ	P,PEKSPY	;GET UNIDES
	LDB	T1,[POINTR T1,DC.CNT] ;GET CONTROLLER TYPE
	CAIE	T1,.DCCRN	;RP20?
	JRST	SDVER2		;NO
	MOVEI	P1,2		;SETUP DISPATCH OFFSET
	MOVEI	T2,.ESDXE	;MAKE IT A DX20 DEVICE ERROR
SDVER2:	MOVEI	T1,0		;CLEAR T1
	DPB	T2,[POINT 9,T1,8] ;STORE CODE IN T1 FOR ERRINI
	PJRST	@[EXP GDVERR,GMDVER,D2DSER](P1) ;DISPATCH TO CORRECT ROUTINE

;ROUTINE TO REPORT TAPE ERRORS, CODE 21 AND TAPE STATS, CODE 41
STPERR:	PUSHJ	P,PROTJB	;ASSURE JOB WILL BE FREED FROM ^D
	HLRZ	P3,1(T1)		;GET DDB ADDR IN P3
	HRRZ	P4,1(T1)		;MAKE P4 A POINTER TO THE TUB
	MOVE	T1,[%CNMER]		;GETTAB FOR MAGTAPE INFO
	PUSHJ	P,GTBSPY
	  JRST	CPOPJ		;OOPS
	HLRZ	P2,T1		;GET OFFSET  OFTUBRID IN RH OF P2
	ADDI	P4,(P2)		;AND MAKE P4 POINTER TO CURR. TUBRID
	SETZ	T1,		;CLEAR T1
	DPB	T2,[POINT 9,T1,8]	;PUT ERROR CODE IN T1
	CAIN	T2,.ESTPS	;IS THIS MAG TAPE STATS?
	PJRST	GTPSTU		;YES, RECORD THEM
	PJRST	GTPERR		;GO REPORT TAPE ERROR
;ROUTINE TO REPORT DX20 DEVICE ERRORS, CODE 12.

DX2ERR:	PUSHJ	P,PROTJB	;INSURE JOB WILL BE FREED FROM ^D
	HLRZ	P2,1(T1)	;GET DDB ADDRESS IN P2
	HRRZ	P3,1(T1)	;GET UBD ADDRESS IN P3
	MOVEI	T1,0		;CLEAR T1
	DPB	T2,[POINT 9,T1,8] ;PUT ERROR CODE IN T1
	PJRST	D2TPER		;PROCESS TU7X TAPE ERROR

;ROUTINE TO REPORT SOFTWARE ERROR (CODE 17), DL10 ERROR (CODE 50),
;LP100 ERROR (CODE 71), OR HARD COPY CONTROLLER ERROR (CODE 72)

SDIERR:	PUSHJ	P,PROTJB	;[544] [550] MAKE SURE JOB WILL BE FREED
	HLRZ	T1,(T1)	;GET  POINTER TO AOBJN WORD INTO RH  OF T1
	PUSHJ	P,PEKSPY	;GET AOBJN WORD
	MOVE	P1,T1		;PUT IT INTO P1
	SETZ	T1,		;CLEAR T1
	DPB	T2,[POINT 9,T1,8]	;PUT CODE INTO T1
	PUSHJ	P,ERRINI	;INITIALIZE ERROR ENTRY
DLELP:	HRRZ	T1,P1		;GET POINTER  PART INTO T1
	PUSHJ	P,PEKSPY	;GET NEXT WORD
	PUSH	P4,T1		;AND SAVE IT IN BUFFER
	AOBJN	P1,DLELP	;STEP POINTER
	PJRST	ERRFIN		;[544] [550] ALL DONE, WRITE ENTRY AND CLOSE FILE
;ROUTINE TO REPORT SOFTWARE EVENT OF INTEREST, CODE 14.

SWEERR:	HLRZ	P1,(T1)		;GET EVENT TYPE
	MOVE	P2,1(T1)	;GET FUNCTION SPECIFIC DATA
	PUSHJ	P,PROTJB	;INSURE THE JOB IS RELEASED
	MOVEI	T1,0		;CLEAR T1
	DPB	T2,[POINT 9,T1,8] ;STORE ERROR CODE
	PUSHJ	P,ERRINI	;SETUP BUFFER AND P4
	PUSH	P4,P1		;(R0) SAVE EVENT CODE
	PUSH	P4,J		;(R1) SAVE JOB NUMBER
	HRROI	T1,.GTPPN	;NEED USER'S PPN
	PUSHJ	P,GTBVAR	;(R2) SAVE IT
	HRROI	T1,.GTPRG	;NEED USER'S PROGRAM NAME
	PUSHJ	P,GTBVAR	;(R3) SAVE IT ALSO
	MOVEI	P1,0		;START OUT WITH NO TTY NUMBER
	PUSHJ	P,GETTTY	;GET NUMBER OF CONTROLLING TTY
	  JRST	SWEER1		;CAN'T, SKIP THE REST
	SKIPGE	T1		;IF THIS IS THE CTY
	MOVE	T1,CTYLIN	;GET THE CTY
	DPB	T1,[POINT 12,P1,35] ;SAVE IN P1
	TRO	T1,.UXTRM	;MAKE IT A UDX FOR GTNTN.
	TLNN	F,L.DSK		;FORGET REST IF READING FROM DISK
	GTNTN.	T1,		;GET NODE,,LINE ON NODE
	  JRST	SWEER1		;CAN'T, USE ZERO
	DPB	T1,[POINT 12,P1,23] ;SAVE LINE ON NODE IN P1
	HLRZS	T1		;MOVE NODE TO RH
	DPB	T1,[POINT 12,P1,11] ;SAVE IN P1
SWEER1:	PUSH	P4,P1		;(R4) BYTE (12) NODE,LINE ON NODE,TTY
	PUSH	P4,[-1,,SWEDTA]	;(R5) POINTER TO FUNCTION SPECIFIC DATA
SWEDTA==6			;OFFSET TO FIRST WORD OF FUNCTION DATA
	PUSH	P4,P2		;(R6-) FUNCTION SPECIFIC DATA
	PJRST	ERRFIN		;CLOSE FILE AND RETURN
;HERE TO REPORT CONFIGURATION STATUS CHANGE, CODE = 15

SCSCER:	LDB	T3,[POINT 6,(T1),17]	;GET BYTE WHICH TELLS US WHAT CHANGE
	CAILE	T3,CSCTBL	;GREATER THAN WE KNOW ABOUT?
	POPJ	P,		;YES, GIVE UP
	PJRST	@CSCTAB(T3)	;NO, DISPATCH

;DISPATCH TABLE INDEXED BY CHANGE CODE
CSCTAB:	EXP	ATTUNI		;(0) ATTACH
	EXP	ATTUNI		;(1) DETATCH
	EXP	XCHNGE		;(2) EXCHANGE
	EXP	DATCHG		;(3) DATE/TIME CHANGE
	EXP	CPOPJ		;(4) UNDEFINED
	EXP	CPOPJ		;(5) UNDEFINED
	EXP	NODONL		;(6) NODE OFF-LINE
	EXP	NODONL		;(7) NODE ON-LINE
	EXP	MEMOFL		;(10) MEMORY ONLINE
	EXP	MEMOFL		;(11) MEMORY OFFLINE
	EXP	MEMOFL		;(12) MONITOR SET MEMORY OFFLINE
CSCTBL==.-CSCTAB-1

ATTUNI:	HRRZ	P1,1(T1)	;ATT OR DET- GET UDB ADDR
	HLLZ	P2,(T1)		;AND GET COMMENT+COD INTO P2
	SETZ	T1,		;CLEAR T1
	DPB	T2,[POINT 9,T1,8];PUT ERROR CODE INTO T1
	PUSHJ	P,ERRINI	;AND CALL ERROR INITIALIZER
	MOVEI	T1,UNINAM(P1)	;GET UDB ADDR INTO T1
	PUSHJ	P,PEKSPY	;AND GET FIRST WORD (UNINAM)
	PUSH	P4,T1		;(R0) STOREIT AWAY FOR ERROR FILE
	PUSH	P4,[0]		;(R1) STORE SECOND NAME OF ZERO
	PUSH	P4,P2		;(R2) AND STORE COMMENTS+CODE
	PJRST	SCSEND		;CLOSE ERROR FILE AND RETURN

XCHNGE:	HLRZ	P1,1(T1)	;GET FIRST UDB ADDR INTO P1
	HRRZ	P2,1(T1)	;AND SECOND UDB ADDR INTO P2
	HLLZ	P3,(T1)		;GET COMMENTS+CODE INTO P3
	SETZ	T1,		;NOW CLEAR T1
	DPB	T2,[POINT 9,T1,8];AND PUT .ESCSC INTO T1
	PUSHJ	P,ERRINI	;INITIALIZE FOR ERROR
	MOVEI	T1,UNINAM(P1)	;ADDR OF FIRST UDB
	PUSHJ	P,PEKSPY	;PICK UP UNIT NAME
	PUSH	P4,T1		;(R0) AND PUT IT INTO ERROR BUFFER
	MOVEI	T1,UNINAM(P2)	;NOW SAME FOR SECOND UNIT
	PUSHJ	P,PEKSPY	;...
	PUSH	P4,T1		;(R1) ...
	PUSH	P4,P3		;(R2) AND NOW COMMENTS+CODE
	PJRST	SCSEND		;CLOSE FILE AND RETURN
MEMOFL:	HLLZ	P3,(T1)		;COMMENTS+CODE INTO P3
	SETZ	T1,		;CLEAR T1
	DPB	T2,[POINT 9,T1,8];AND PUT .ESCSC INTO T1
	PUSHJ	P,ERRINI	;INITIALIZE FOR ERROR
	MOVN	T1,NXMLEN	;GET NEGATIVE LENGTH OF NXMTAB
	HRLZS	T1		;AND PUT IN LH FOR POINTER
CSCNAM==0			;OFFSET OF POINTER TO FIRST TABLE
	PUSH	P4,T1		;(R0) SAVE -LEN,,0 FOR POINTER
CSCNM2==1			;OFFSET OF POINTER TO SECOND TABLE
	PUSH	P4,T1		;(R1) SAVE -LEN,,0 FOR THIS ONE ALSO
	HRRI	P3,1		;FLAG WHICH SAYS 1 BIT=1 PAGE
	PUSH	P4,P3		;(R2) COMMENTS+CODE
	MOVEI	T2,1-ERABFH(P4) ;GET OFFSET OF START OF FIRST NXM TABLE
	HRRM	T2,ERABFS+CSCNAM ;SAVE IN RH OF POINTER
	HRR	T1,NXMTAB	;MAKE AOBJN POINTER TO NXMTAB
	PUSH	P4,(T1)		;PUSH A WORD ONTO THE BUFFER
	AOBJN	T1,.-1		;AND STEP TO NEXT WORD
	MOVEI	T2,1-ERABFH(P4) ;GET OFFSET OF START OF SECOND NXM TABLE
	HRRM	T2,ERABFS+CSCNM2 ;SAVE IN RH OF POINTER
	MOVE	T1,[%CNNXM]	;GETTAB POINTER TO NXMTAB
	PUSHJ	P,GTBSPY
	  SETZ	T1,		;CAN'T HAPPEN
	MOVE	T3,T1		;USE T3 AS AOBJN POINTER
	MOVE	T2,NXMTAB	;AND T2 AS WHERE TO STORE
MOFLOP:	HRRZ	T1,T3		;GET CURRENT ADDR INTO T1
	PUSHJ	P,PEKSPY	;GO PICK IT UP FROM MONITOR
	MOVEM	T1,(T2)		;STASH IT AWAY
	PUSH	P4,(T2)		;PUT IT INTO ERROR BUFFER ALSO
	AOS	T2		;INCREMENT T2
	AOBJN	T3,MOFLOP	;INCREMENT T3 AND LOOP
	JRST	SCSEND		;JOIN COMMON CODE
DATCHG:	PUSHJ	P,PROTJB	;INSURE THAT JOB IS RELEASED FROM ^D
	MOVE	P1,1(T1)	;GET DATE/TIME INCREMENT
	ADDM	P1,MRVBDY+MRVIDT ;SUM DATE/TIME INCREMENTS
	HLLZ	P2,(T1)		;GET CODE
	MOVEI	T1,0		;CLEAR T1
	DPB	T2,[POINT 9,T1,8] ;STORE ENTRY CODE IN T1 FOR ERRINI
	PUSHJ	P,ERRINI	;SETUP BUFFER
	PUSH	P4,P1		;(R0) INCREMENTAL DATE/TIME CHANGE
	PUSHJ	P,FLSPAK	;FLUSH INPUT QUEUE AND CLEAR BLOCK
	MOVEI	T1,.USSDT	;GET CODE FOR DATE CHANGE FOR %SIACT
	MOVEM	T1,SSELBK	;STORE IN BLOCK
	MOVEM	P1,SSELBK+1	;SAVE INCREMENT IN MESSAGE BLOCK
	PUSHJ	P,NBSDAT	;GET CURRENT UNIVERSAL DATE/TIME
	MOVEM	T1,SSELBK+2	;SAVE IN BLOCK
	PUSH	P4,T1		;(R1) CURRENT DATE/TIME
	PUSH	P4,P2		;(R2) REASON CODE (I.E., DATE/TIME)
	MOVE	T1,[SIXBIT/DAEMON/] ;GET OUR NAME
	MOVEM	T1,SSELBK+3	;SAVE IN BLOCK
	MOVE	T1,.JBVER	;GET OUR VERSION NUMBER
	MOVEM	T1,SSELBK+4	;SAVE IN BLOCK
	PUSHJ	P,FNDACT	;FIND PID OF [SYSTEM]ACCOUNTING
	  JRST	SCSEND		;NOT THERE, JUST WRITE FILE
	PUSHJ	P,SNDPAK	;SEND MESSAGE TO %SIACT
	JRST	SCSEND		;JOIN COMMON CODE

NODONL:	HLLZ	P1,0(T1)	;GET SUB-CODE IN P1
	HRRZ	P2,1(T1)	;GET NODE NUMBER IN P2
	HLRZ	P3,1(T1)	;GET ADDITIONAL INFORMATION IN P3
	MOVEI	T1,0		;SETUP FOR ERRINI
	DPB	T2,[POINT 9,T1,8] ;STORE CODE
	PUSHJ	P,ERRINI	;SETUP BUFFER AND P4
	PUSH	P4,P2		;(R0) NODE NUMBER
	PUSH	P4,P3		;(R1) ADDITIONAL INFO
	PUSH	P4,P1		;(R2) CODE FOR NODE ON/OFF LINE
;;	JRST	SCSEND		;JOIN COMMON CODE

SCSEND:	TRO	F,R.AVL		;APPEND THIS ENTRY TO AVAIL.SYS ALSO
	PJRST	ERRFIN		;CLOSE FILE AND RETURN
;HERE TO REPORT NXM ERROR - CODE 4 OR 67

SNXMER:	HLRZ	P3,(T1)		;GET CDB ADDR FOR CDB WITH ERROR
	PUSHJ	P,FNDCPU	;GOT FIND WHICH CPU ERROR WAS ON
	  POPJ	P,		;NOT ANY CPU, GIVE IT UP
	MOVEI	P2,(P1)		;GET CPU NUMBER
	LSH	P2,1		;DOUBLE IT
	PUSHJ	P,ISKL10	;IS THIS A KL10?
	  SKIPA			;NO
	MOVEI	T2,.ESKAE	;FUDGE CODE FOR KL10 NXM
	SETZ	T1,		;CLEAR T1
	DPB	T2,[POINT 9,T1,8]	;PUT ERROR CODE INTO T1 FOR ERRINI
	PUSHJ	P,ERRINI	;INITIALIZE THE ERROR BUFFER
	MOVE	T1,[%CCPHY]	;PHYSICAL CPU NAME
	PUSHJ	P,GCPVAR	;(R0) PHYSICAL CPU NAME
	MOVE	T1,[%CVTNE]	;COUNT OF ERROR ON SWEEP OF CORE
	PUSHJ	P,GCPVAR	;(R1)STASH IT
	MOVE	T1,[%CVSNE]	;NOT REPRODUCIBLE ERROR COUNT
	PUSHJ	P,GCPVAR	;(R2)
	MOVE	T1,[%CVMPP]	;PC AT TIME OF ERROR
	PUSHJ	P,GCPVAR	;(R3)
	MOVE	T1,[%CVNJA]	;NUMBER OF JOBS AFFECTED BY THIS NXM
	PUSHJ	P,GCPVAR	;(R4)
	MOVE	T1,[%CVMNA]	;FIRST BAD ADDR FROM SWEEP
	PUSHJ	P,GCPVAR	;(R5)
	MOVE	T3,[%CCNXT]	;GET POINTER TO NXM SUBTABLE
	ADD	T3,P2		;POINTER IS IN CONSTANTS TABLE
	MOVSI	T2,.GTC0V(P2)	;SUBTABLE IS IN VARIABLES TABLE
NXMSLP:	PUSHJ	P,GSUBTB	;GET AN ITEM FROM THE SUBTABLE
	  JRST	ENXSTB		;END OF THE SUBTABLE
	PUSH	P4,T1		;(R6-R15)STICK IT IN THE BUFFER
	AOJA	T2,NXMSLP	;LOOP OVER ENTIRE SUBTABLE
ENXSTB:	MOVEI	T1,1		;FLAG WHICH SAYS 1 BIT=1 PAGE
	HRLI	T1,707070	;FLAG FOR SYSERR
	PUSH	P4,T1		;(R16)SAVE IT
	MOVN	T2,NXMLEN	;GET NEGTIVE LENGTH OF NXMTAB
	HRLZS	T2		;PUT IT IN LH OF T2 FOR POINTER
EN%BEF==17			;OFFSET OF FIRST POINTER TO NXMTAB
	PUSH	P4,T2		;(R17)SAVE AS POINTER TO FIRST COPY OF NXMTAB
	PUSH	P4,T2		;(R20)SAVE AS POINTER TO SECOND COPY OF NXMTAB
EN%BAT==21			;OFFSET FOR POINTER TO BAD ADDR SUBTABLE
	AOBJN	P4,.+1		;(R21)SPACE FOR BAD ADDRESS SUBTABLE
	MOVE	T1,[%SYSPP]	;GETTAB FOR PPN OF USER CRASHED BY NXM
	PUSHJ	P,GTBVAR	;(R22) SAVE PPN
	MOVE	T1,[%SYSPN]	;PROGRAM NAME ON NXM
	PUSHJ	P,GTBVAR	;(R23) SAVE PROGRAM NAME
	PUSHJ	P,KLCPU		;(R24-R26 ON KL)REPORT CONI APR, AND RDERA IF KL10
	MOVEI	T1,1-ERABFH(P4)	;GET RELATIVE POSITION TO NXM TABLE
	HRRM	T1,ERABFS+EN%BEF ;SAVE AS RIGHT HALF OF POINTER
	HLLZ	T2,ERABFS+EN%BEF ;GET BACK NEG LENGTH
	HRR	T2,NXMTAB	;AND GET POINTER TO TABLE
	PUSH	P4,(T2)		;PUSH WORD OF NXMTAB INTO BUFFER
	AOBJN	T2,.-1		;STEP TO NEXT WORD
	MOVEI	T1,1-ERABFH(P4)	;GET RELATIVE OFFSET TO 2ND TABLE
	HRRM	T1,ERABFS+EN%BEF+1 ;SAVE IT AS RIGHT HALF OF POINTER
	MOVE	T1,[%CNNXM]	;GETTAB POINTER TO NXMTAB
	PUSHJ	P,GTBSPY
	  SETZ	T1,		;CAN'T HAPPEN
	MOVE	T3,T1		;USE T3 AS AOBJN POINTER
	MOVE	T2,NXMTAB	;AND T2 AS WHERE TO STORE
NXELOP:	HRRZ	T1,T3		;GET CURRENT ADDR INTO T1
	PUSHJ	P,PEKSPY	;GO PICK IT UP FROM MONITOR
	MOVEM	T1,(T2)		;STASH IT AWAY
	PUSH	P4,T1		;PUT IT INTO ERROR BUFFER ALSO
	AOS	T2		;INCREMENT T2
	AOBJN	T3,NXELOP	;INCREMENT T3 AND LOOP
	PUSH	P,P4		;SAVE CURRENT LOC IN BUFFER
	MOVE	T3,[%CCNXT]	;SUBTABLE POINTER FOR NXM
	ADD	T3,P2		;IN THE CONSTANTS TABLE
	MOVSI	T2,.GTC0V(P2)	;THE SUBTABLE IS IN VARIABLES TABLE
	HRRI	T2,%CVNTS	;ITEM FOR # OF NXM'S FOUND ON SWEEP
	PUSHJ	P,GSUBTB	;GO GET IT
	  JRST	CKLSBD		;NONE IF NO POINTER
	JUMPE	T1,CKLSBD	;OR IF POINTER IS ZERO
	MOVE	T4,T1		;GET COUNT INTO T4
	HLL	T3,[%CCMPT]	;LOOK IN BAT SUBTABLE NOW
	HLLZS	T2		;AND START AT ITEM 0
NBTSLP:	PUSHJ	P,GSUBTB	;GET A WORD
	  JRST	ENBTTB		;ALL DONE
	PUSH	P4,T1		;SAVE IT IN BUFFER
	AOJ	T2,		;STEP TO NEXT ENTRY
	SOJG	T4,NBTSLP	;LOOP BACK FOR NUMBER OF ENTRIES
ENBTTB:	POP	P,T1		;GET BACK START LOC OF TABLE
	MOVNI	T2,(T2)		;GET NEGATIVE NUMBER OF ITEMS STORED
	JUMPE	T2,KLSBDG	;IF NONE, JUST FINISH
	HRLI	T2,1-ERABFH(T1)	;COMPUTE RELATIVE OFFSET OF TABLE
	MOVSM	T2,ERABFS+EN%BAT ;SAVE POINTER IN BUFFER
	PJRST	KLSBDG		;WRITE SBDIAG SUBTABLE IF KL10, THEN CLOSE ERROR FILE
;HERE TO REPORT CPU PARITY ERROR - CODE 3 OR 62

SCPERR:	HLRZ	P3,(T1)		;GET CDB ADDR FOR CDB WITH ERROR
	PUSHJ	P,FNDCPU	;FIND CPU WHICH HAD ERROR
	  POPJ	P,		;NOT ANY CPU, GIVE IT UP
	MOVEI	P2,(P1)		;COPY CPU #
	LSH	P2,1		;DOUBLE IT
	PUSHJ	P,ISKL10	;IS THIS A KL10?
	  SKIPA			;NO
	MOVEI	T2,.ESMOT	;YES, FUDGE CODE FOR KL10 PARITY INTERRUPT
	SETZ	T1,		;CLEAR T1
	DPB	T2,[POINT 9,T1,8]	;PUT ERROR CODE INTO T1 FOR ERRINI
	PJRST	GCPERR		;LOG THE ERROR

;HERE TO REPORT CONTINUABLE STOPCD - CODE =2
SCNSTD:	MOVSI	P1,-21		;NUMBER OF CRASH AC'S + CRASH PI
	HLR	P1,(T1)		;LOCATION SAVED AT IN MONITOR
	SETZ	T1,		;CLEAR T1
	DPB	T2,[POINT 9,T1,8] ;PUT ERROR CODE INTO T1
	PUSHJ	P,ERRINI	;AND INITIALIZE ERROR
	MOVE	T2,[%CNFG0]	;5 WORDS OF SYSTEM NAME, 2 DATE
	SUB	T2,[%CNDT1+<1,,0>]
	HLR	T2,[%CNFG0]
MONLUP:	MOVEI	T1,.GTCNF	;FROM CNFTBL
	HRLI	T1,(T2)
	PUSHJ	P,GTBVAR	;(R0-R6) SAVE A WORD OF SYSTEM NAME/DATE
	AOBJN	T2,MONLUP	;GO GET NEXT WORD
	MOVE	T1,[%CNSER]	;GET CPU0 SERIAL NUMBER
	PUSHJ	P,GTBVAR	;(R7) SAVE CPU0 SERIAL NUMBER
	PUSH	P4,MONVER	;(R10) SAVE MONITOR VERSION
	MOVE	T1,[%SYSPC]	;GET NAME OF LAST STOPCD
	PUSHJ	P,GTBVAR	;(R11) SAVE NAME OF LAST STOPCODE
	MOVE	T1,[%SYSJN]	;JOB # ON LAST STOPCD
	PUSHJ	P,GTBVAR	;(R12) SAVE JOB NUMBER ON LAST STOPCODE
	MOVE	T1,[%SYSTN]	;TTY NAME ON LAST STOPCD
	PUSHJ	P,GTBVAR	;(R13) SAVE TTY ON LAST STOPCODE
	MOVE	T1,[%SYSPN]	;PROG NAME ON LAST STOPCD
	PUSHJ	P,GTBVAR	;(R14) SAVE PROGRAM NAME ON LAST STOPCODE
	MOVE	T1,[%SYSPP]	;PPN OF USER, LAST STOPCD
	PUSHJ	P,GTBVAR	;(R15) SAVE PPN
	MOVE	T1,[%SYNJS]	;NUMBER OF JOB STOPCDS
	PUSHJ	P,GTBVAR	;(R16) SAVE NUMBER
	MOVE	T1,[%SYNDS]	;NUMBER OF DEBUG STOPCD
	PUSHJ	P,GTBVAR	;(R17) SAVE NUMBER
CACLUP:	MOVEI	T1,(P1)		;ADDRESS OF NEXT CRASH AC (OR PI STATUS)
	PUSHJ	P,PEKSPY
	PUSH	P4,T1		;(R20-R40)
	AOBJN	P1,CACLUP	;NOW GO TO NEXT ONE
	TRO	F,R.AVL		;APPEND THIS ENTRY TO AVAIL.SYS ALSO
	PJRST	ERRFIN		;ALL DONE, CLOSE FILE AND RETURN
;HERE TO REPORT KL10 DATA PARITY TRAP -- CODE 60

SKLTRP:	PUSHJ	P,PROTJB	;[544] MAKE SURE JOB IS FREED
	HLRZ	P3,(T1)		;GET CPU DATA BLOCK ADDR INTO P3
	PUSHJ	P,FNDCPU	;GOT FIND WHICH CPU ERROR WAS ON
	  POPJ	P,		;NOT ANY CPU, GIVE IT UP
	MOVEI	P2,(P1)		;COPY CPU NUMBER 
	LSH	P2,1		;AND DOUBLE IT FOR GETTABS
	SETZ	T1,		;CLEAR T1
	DPB	T2,[POINT 9,T1,8] ;PUT ERROR CODE INTO T1
	PUSHJ	P,ERRINI	;WRITE ENTRY HEADER
	MOVE	T1,[%CVPFW]	;PAGE FAIL WORD
	PUSHJ	P,GCPVAR	;(R0)
	MOVE	T1,[%CVTBD]	;BAD DATA
	PUSHJ	P,GCPVAR	;(R1)
	MOVE	T1,[%CVTGD]	;GOOD DATA
	PUSHJ	P,GCPVAR	;(R2)
	MOVE	T1,[%CVBPA]	;BAD PHYSICAL ADDR
	PUSHJ	P,GCPVAR	;(R3)
	MOVE	T1,[%CVPTR]	;RETRY WORD
	PUSHJ	P,GCPVAR	;(R4)
	MOVE	T1,[%CVSPT]	;NUMBER OF SOFT TRAPS
	PUSHJ	P,GCPVAR	;(R5)
	MOVE	T1,[%CVHPT]	;NUMBER OF HARD TRAPS
	PUSHJ	P,GCPVAR	;(R6)
	MOVE	T1,[%CVPPC]	;PC AT TIME OF TRAP
	PUSHJ	P,GCPVAR	;(R7)
	PJRST	ERRFIN		;CLOSE FILE AND RETURN
;HERE TO REPORT FRONT END SUPPLIED KL CPU ERROR INFORMATION

KLEERR:	LDB	P1,[POINT 3,2(T1),17] ;GET CPU NUMBER FROM ERROR BLOCK
	PUSH	P,P1		;SAVE ON STACK FOR LATER
	TLNN	F,L.DSK		;READING FROM DISK?
	JRST	KLEER1		;NO
	MOVEI	P2,1		;GET A BIT TO SHIFT
	LSH	P2,(P1)		;POSITION FOR THIS CPU
	TDNE	P2,KLEFLG	;ALREADY BEEN HERE FOR THIS CPU?
	JRST	TPOPJ		;YES, DONE THEM ALL ALREADY
	IORM	P2,KLEFLG	;SET FLAG FOR NEXT TIME
KLEER1:	HLRZ	P1,(T1)		;GET ADDRESS OF FIRST ERROR BLOCK IN MONITOR
	PUSH	P,T2		;SAVE CODE ON STACK

KLEER2:	JUMPE	P1,KLEER6	;DONE IF ZERO
	TLNE	F,L.DSK		;READING FROM DISK?
	JRST	KLEER3		;YES, IT'S NOT GOING TO GO AWAY
	MOVE	T1,[.DTERT,,T3]
	HRLZ	T3,-1(P)	;GET CPU,,0 FROM STACK
	DTE.	T1,		;RESET THE TIMER SO THE KL ERROR DATA DOESN'T GO AWAY
	  JRST	KLEER6		;SORRY, IT'S ALREADY GONE.
KLEER3:	MOVE	T2,0(P)		;GET CODE OFF STACK
	SETZ	T1,		;CLEAR T1
	DPB	T2,[POINT 9,T1,8] ;PUT CODE IN T1
	PUSHJ	P,ERRINI	;SETUP P4 (0-2)
	PUSH	P4,[-1]		;(R0)JOB NUMBER
	PUSH	P4,[0]		;(R1)DIRECTORY
	PUSH	P4,[0]		;(R2)FRONT END SOFTWARE VERSION
	PUSH	P4,[0]		;(R3)SIXBIT NAME OF PROGRAM (NONE)
	MOVEI	T1,.KEDEV(P1)	;GET ADDRESS IN BLOCK WHERE PROTOCOL DEVICE IS
	PUSHJ	P,PEKSPY	;GET THE DATA
	LDB	T2,KLEDEV	;GET PROTOCOL DEVICE CODE
	LDB	T3,KLEUNI	;AND UNIT NUMBER
	HRL	T2,T3		;UNIT#,,PROTOCOL DEVICE CODE
	PUSH	P4,T2		;(R4)PROTOCOL DEVICE CODE
	LDB	T1,KLECNT	;GET SIZE OF ERROR DATA IN 8 BIT BYTES
	PUSH	P,T1		;SAVE FOR LATER
	ADDI	T1,^D36/^D8-1	;ROUND UP TO NEAREST 36 BIT WORD
	ASH	T1,-2		;CONVERT TO 36 BIT WORD COUNT
	MOVNS	T1		;GET MINUS COUNT
	HRLZS	T1		;-COUNT,,0
FE%OFF==5			;OFFSET OF SUB-BLOCK POINTER
	PUSH	P4,T1		;(R5)-LENGTH,,0
	HLLZ	P3,T1		;GET -COUNT,,0 IN P3 FOR AOBJN LATER
	MOVEI	T1,.KECPU(P1)	;WORD WITH CPU, DTE, LINK
	PUSHJ	P,PEKSPY	;GET NEXT WORD IN T1
	LDB	T2,KLEDTN	;GET DTE NUMBER
	LDB	T3,KLECPN	;AND CPU NUMBER
	HRL	T2,T3		;CPU#,,DTE#
	PUSH	P4,T2		;(R6)CPU#,,DTE#
	POP	P,T2		;GET SAVED COUNT OF 8 BIT DATA BYTES
	PUSH	P4,T2		;(R7)COUNT OF 8 BIT DATA BYTES
	LDB	P2,KLELNK	;GET LINK ADDRESS
	JUMPE	P3,KLEER5	;GO IF NO DATA TO STORE
	HRRI	P3,.KEDAT(P1)	;GET ADDRESS OF DATA
	MOVEI	T1,1-ERABFS(P4)	;GET RELATIVE OFFSET OF START OF TABLE
	HRRM	T1,ERABFS+FE%OFF ;SAVE IN POINTER
KLEER4:	HRRZ	T1,P3		;GET ADDRESS IN MONITOR IN T1
	PUSHJ	P,PEKSPY	;GET THE DATA
	PUSH	P4,T1		;(R10-)SAVE THE DATA
	AOBJN	P3,KLEER4	;LOOP FOR ALL WORDS
KLEER5:	PUSHJ	P,ERRFIN	;OK, CLOSE OFF ENTRY
	MOVE	P1,P2		;GET NEW NEXT BLOCK
	JRST	KLEER2		;GO SEE IF THERE IS MORE
KLEER6:	POP	P,(P)		;FLUSH CODE FROM STACK
	MOVE	T1,[.DTERC,,T3]	;RELEASE THE ERROR CORE NOW
	POP	P,T3		;GET CPU NUMBER
	HRLZS	T3		;MAKE IT CPU,,0
	TLNN	F,L.DSK		;DON'T TOUCH RUNNING MONITOR IF FROM DISK
	DTE.	T1,		;DO IT
	  JFCL			;GIVES NO ERROR RETURN
	POPJ	P,		;RETURN


KLEDEV:	POINT	9,T1,8		;PROTOCOL DEVICE CODE
KLEUNI:	POINT	9,T1,17		;UNIT NUMBER
KLECNT:	POINT	18,T1,35	;COUNT OF 8 BIT BYTES
KLECPN:	POINT	9,T1,8		;CPU NUMBER
KLEDTN:	POINT	9,T1,17		;DTE NUMBER
KLELNK:	POINT	18,T1,35	;LINK TO NEXT BLOCK IF ANY
;HERE TO DUMP CPU STATUS BLOCK - CODE 63

CSBERR:	HLRZ	P3,(T1)		;GET CDB ADDRESS
	PUSHJ	P,FNDCPU	;FIND CPU NUMBER THAT WANTS TO DUMP BLOCK
	  POPJ	P,		;NONE, GIVE UP
	LSH	P1,1		;DOUBLE IT
	MOVEI	T1,0		;CLEAR T1
	DPB	T2,[POINT 9,T1,8] ;PUT ERROR CODE INTO T1
	PUSHJ	P,ERRINI	;SETUP BUFFER AND P4
	MOVE	T3,[%CCCSB]	;SUBTABLE POINTER TO CPU STATUS BLOCK
	ADDI	T3,(P1)		;  FROM THIS CPU CONSTANT TABLE
	MOVSI	T2,.GTC0V(P1)	;SUBTABLE IS IN CPU VARIABLE TABLE
CSBER1:	PUSHJ	P,GSUBTB	;GET ENTRY FROM SUBTABLE
	  PJRST	CSBER2		;END OF TABLE, CLEAN UP
	PUSH	P4,T1		;PLACE IN BUFFER
	AOJA	T2,CSBER1	;LOOP FOR ENTIRE TABLE
CSBER2:	MOVEI	T1,1(P4)	;GET CURRENT BUFFER ADDRESS
CSBSBD==142			;OFFSET IN BLOCK OF SBDIAG POINTER
	CAILE	T1,ERABFS+CSBSBD ;DID WE DO THAT MANY ENTRIES?
	SKIPL	ERABFS+CSBSBD	;AND SBDIAG POINTER LOOK OK?
	PJRST	ERRFIN		;NO TO ONE, DON'T TOUCH POINTER
	MOVEI	T3,CSBSBD	;GET OFFSET OF SBDIAG POINTER
	ADDM	T3,ERABFS+CSBSBD ;MAKE IT OFFSET FROM START OF BLOCK
	PJRST	ERRFIN		;CLOSE ERROR FILE AND RETURN
;HERE TO DUMP DEVICE STATUS BLOCK - CODE 64

DSBERR:	HLRZ	P3,(T1)		;GET CDB ADDRESS
	PUSHJ	P,FNDCPU	;FIND CPU THAT WANTS TO DUMP BLOCK
	  POPJ	P,		;NONE, GIVE UP
	LSH	P1,1		;DOUBLE IT
	MOVEI	T1,0		;CLEAR T1
	DPB	T2,[POINT 9,T1,8] ;STORE ERROR CODE IN T1
	PUSHJ	P,ERRINI	;SETUP BUFFER AND P4
DSBIOI==0			;OFFSET OF POINTER TO I/O INSTRUCTIONS
	AOBJN	P4,.+1		;(R0) LEAVE ROOM FOR POINTER
DSBRSV==1			;OFFSET OF POINTER TO RESULTANT VALUES
	AOBJN	P4,.+1		;(R1) LEAVE ROOM FOR POINTER
	PUSH	P,P4		;SAVE INITIAL VALUE OF BUFFER POINTER
	MOVEI	T2,0		;INITIALIZE COUNT
DSBER1:	HRLI	T1,(T2)		;ITEM NUMBER TO LH
	HRRI	T1,.GTDCD	;TABLE NUMBER TO RH
	PUSHJ	P,GTBSPY	;GET NEXT I/O INSTRUCTION FROM DVCSTS
	  JRST	DSBER2		;END OF TABLE
	PUSH	P4,T1		;SAVE IN BUFFER
	AOJA	T2,DSBER1	;BUMP ITEM NUMBER AND LOOP
DSBER2:	MOVNI	T2,(T2)		;GET NEGATIVE LOOP COUNT
	POP	P,T1		;RESTORE POINTER TO INITIAL LOC
	JUMPE	T2,DSBER3	;IF NONE, LEAVE POINTER ZERO
	HRLI	T2,1-ERABFS(T1) ;MAKE SWAPPED AOBJN POINTER TO I/O INSTNS
	MOVSM	T2,ERABFS+DSBIOI ;SAVE POINTER IN BUFFER
DSBER3:	PUSH	P,P4		;SAVE CURRENT BUFFER LOC FOR NEXT POINTER
	MOVE	T3,[%CCDSB]	;SUBTABLE POINTER TO DEVICE STATUS BLOCK
	ADDI	T3,(P1)		;  FROM THIS CPU CONSTANT TABLE
	MOVSI	T2,.GTC0V(P1)	;SUBTABLE IS IN CPU VARIABLE TABLE
DSBER4:	PUSHJ	P,GSUBTB	;GET VALUE FROM SUBTABLE
	  JRST	DSBER5		;END OF TABLE
	PUSH	P4,T1		;SAVE VALUE IN BUFFER
	AOJA	T2,DSBER4	;BUMP INDEX AND LOOP
DSBER5:	MOVNI	T2,(T2)		;GET NEGATIVE COUNT
	POP	P,T1		;GET BACK START LOC OF TABLE
	PJUMPE	T2,ERRFIN	;IF NONE, CLOSE ERROR FILE
	HRLI	T2,1-ERABFS(T1) ;MAKE SWAPPED AOBJN POINTER TO TABLE
	MOVSM	T2,ERABFS+DSBRSV ;SAVE IN BUFFER
	PJRST	ERRFIN		;CLOSE FILE AND RETURN
;SUBROUTINE TO RECORD A CPU-DETECTED ERROR
;ARGS	T1=ERROR.SYS CODE IN BITS 0-8
;	P1=CPU #
;	P2=CPU # TIMES 2 (FOR GETTAB CPU TABLES)
;RETURNS CPOPJ, P1 AND P2 INTACT, P4, T1-4 BLOWN

GCPERR:	PUSHJ	P,ERRINI	;SETUP BUFFER AND P4
	MOVE	T1,[%CCPHY]	;PHYSICAL CPU NAME
	PUSHJ	P,GCPVAR	;(R0) PHYSICAL CPU NAME
	MOVE	T1,[%CVTPE]
	PUSHJ	P,GCPVAR	;(R1)TOTAL ERRORS WHICH RECURRED ON SWEEP OF CORE
	MOVE	T1,[%CVSPE]
	PUSHJ	P,GCPVAR	;(R2) TOTAL NOT REPRODUCABLE
	MOVE	T1,[%CVMPC]	;MEM PAR CONTINUES
	PUSHJ	P,GCPVAR	;(R3)
	MOVE	T1,[%CVMPP]	;PC AT TIME OF ERROR
	PUSHJ	P,GCPVAR	;(R4) PC (EXEC OR USER)
	MOVE	T1,[%CVMPW]	;1ST WORD FOUND IN ERROR
	PUSHJ	P,GCPVAR	;(R5)
	MOVE	T1,[%CVMPA]	;FIRST BAD ADDRESS
	PUSHJ	P,GCPVAR	;(R6)
EC%PAR==7			;PARITY DATA SUBTABLE POINTER
	AOBJN	P4,.+1		;(R7) SAVE SPACE FOR IT
EC%BAT==10			;BAD ADDRESS SUBTABLE POINTER
	AOBJN	P4,.+1		;(R10) SAVE SPACE FOR IT
	MOVE	T1,[%SYSPP]	;[463]PPN OF USER, LAST STOPCD
	PUSHJ	P,GTBVAR	;(R11) SAVE PPN
	MOVE	T1,[%SYSPN]	;PROG NAME ON LAST STOPCD
	PUSHJ	P,GTBVAR	;(R12) SAVE PROGRAM NAME
	PUSHJ	P,KLCPU		;(R13-R15 ON KL)REPORT KL10 CONI AND RDERA
;KLCPU SET UP P3 WITH LOCATION OF POINTER TO SBDIAG SUBTABLE FOR
;CALL TO KLSBDG
	PUSH	P,P4		;SAVE START ADDRESS OF SUBTABLE
	MOVE	T3,[%CCPAR]	;SUB-TABLE POINTER FOR OTHER PAR STUFF
	ADD	T3,P2		;FROM THIS CPU CONSTANTS TABLE
	MOVSI	T2,.GTC0V(P2)	;SUBTABLE IS IN CPU VAR TABLE
PARSLP:	PUSHJ	P,GSUBTB	;GET ENTRY FROM SUBTABLE
	  JRST	EPARTB		;END OF PARITY SUBTABLE
	PUSH	P4,T1		;GIVE
	AOJA	T2,PARSLP	;GET WHOLE SUBTABLE
EPARTB:	POP	P,T1		;GET BACK START LOC OF SUBTABLE
	MOVNI	T4,(T2)		;GET -LEN OF TABLE FROM LOOP COUNT
	JUMPE	T4,KLSBDG	;IF NONE, THEN NO BAD ADDR'S EITHER
	HRLI	T4,1-ERABFH(T1)	;MAKE SWAPPED AOBJN POINTER TO SUBTABLE
	MOVSM	T4,ERABFS+EC%PAR ;SAVE AS POINTER TO SUBTABLE
	PUSH	P,P4		;SAVE START LOC OF BAD ADDR SUBTABLE

;HERE TO RECORD BAD ADDRESSES

	HRRI	T2,%CVPTS	;OTHER POINTERS ARE ALREADY SET
	PUSHJ	P,GSUBTB	;NO OF BAD ADDRESSES SAVED
	  JRST	CKLSBD		;NONE IF NO TABLE FOR THEM
	MOVEI	T4,(T1)		;KEEP THE COUNT
	JUMPE	T4,CKLSBD	;QUIT IF NONE
	HLL	T3,[%CCMPT]	;LOOK IN BAT SUBTABLE NOW
	HLLZS	T2		;START AT BEGINNING OF TABLE
BATSLP:	PUSHJ	P,GSUBTB	;GET NEXT BAD ADDRESS
	  JRST	EBATTB		;END OF SUB-TABLE
	MOVEM	T1,1(P4)	;SAVE THE BAD ADDR
	AOBJP	P4,EBATTB	;CHECK FOR BUFFER OVERFLOW
	AOJ	T2,		;READY FOR NEXT ENTRY
	SOJG	T4,BATSLP	;GET IT IF ONE WAS STORED
EBATTB:	POP	P,T1		;GET BACK START LOC OF TABLE
	MOVNI	T4,(T2)		;GET -LEN OF TABLE FROM LOOP COUNT
	JUMPE	T4,KLSBDG	;GO IF NONE
	HRLI	T4,1-ERABFH(T1)	;MAKE SWAPPED AOBJN POINTER TO SUBTABLE
	MOVSM	T4,ERABFS+EC%BAT ;STORE AS POINTER TO SUBTABLE
	PJRST	KLSBDG		;GET SBDIAGS IF ON A KL


GCPVAR:	ADD	T1,P2		;CUT DOWN THE TYPING BY PUTTING THIS
GTBVAR:	PUSHJ	P,GTBSPY	; ALL IN ONE PLACE
	  SETZ	T1,
	PUSH	P4,T1		;SAVE AN ITEM IN THE ERROR FILE
	POPJ	P,

;HERE TO FIND CPU NUMBER CORRESPONDING TO CDB ADDRESS
;CALLED WITH P3 CONTAINING CDB ADDR
;RETURNS WITH P1 CONTAINING CPU # IN RIGHT HALF
;NON SKIP RETURN MEANS NO CPU MATCHED
FNDCPU:	MOVSI	P1,-CPUN	;GET NUMBER OF CPUS WE KNOW ABOUT
FNDCP1:	HRRZ	T1,P1		;GET CPU NUMBER INTO T1
	LSH	T1,1		;DOUBLE IT FOR .GTC0C, ETC.
	HRLI	T1,.GTC0C(T1)	;GET .GTCNC FOR THIS CPU
	HRRI	T1,.GTSLF	;SET UP TO GETTAB START OF .GTCNC
	PUSHJ	P,GTBSPY
	  SETZ	T1,		;OOPS
	CAIN	P3,(T1)		;IS THIS THE CPU
	JRST	CPOPJ1		;YES, GIVE SKIP RETURN
	AOBJN	P1,FNDCP1	;NO, TRY NEXT
	POPJ	P,		;NONE MATCH, GIVE ERROR RETURN

;HERE TO DETERMINE IS THIS IS A KL10 PROCESSOR
;ALL REGS PRESERVED
;SKIPS IF CPU IS A KL10
ISKL10:	PUSH	P,T1		;SAVE T1
	MOVEI	T1,0		;CLEAR AN AC
	BLT	T1,0		;AND DO A ZERO LENGTH BLT
	SKIPE	T1		;IF NON-ZERO, NO KL10
	AOS	-1(P)		;IF KL, SKIP
	POP	P,T1		;GET OLD T1 BACK
	POPJ	P,		;AND RETURN

;HERE TO PUT SPECIAL STUFF INTO ERROR FILE ENTRY IF THIS IS A KL10
KLCPU:	PUSHJ	P,ISKL10	;IS THIS A KL10?
	  POPJ	P,		;NO, EXIT
	MOVE	T1,[%CVPCN]	;RESULTS OF CONI APR,
	PUSHJ	P,GCPVAR
	MOVE	T1,[%CVAER]	;RESULTS OF RDERA
	PUSHJ	P,GCPVAR
	AOBJN	P4,.+1	;RESERVE THE SPACE ALSO
	HRRZ	P3,P4		;SAVE CURRENT ERROR FILE LOC FOR LATER
	POPJ	P,		;AND RETURN

;HERE TO WRITE SBDIAG SUBTABLE IF PROCESSOR IS A KL10
;ARGS	P2=CPU NUMBER TIMES 2
;	P3=ADDRESS IN BUFFER OF POINTER
CKLSBD:	POP	P,(P)		;BRING STACK INTO PHASE AND
				;FALL INTO KLSBDG
KLSBDG:	PUSHJ	P,ISKL10	;IS THIS A KL10?
	  PJRST	ERRFIN		;NO, EXIT CLOSING FILE
	MOVE	T3,[%CCSDP]	;GET POINTER TO SBDIAG SUBTABLE
	ADDI	T3,(P2)		;IN THIS CPU'S CONSTANT TABLE
	MOVSI	T2,.GTC0V(P2)	;TABLE IS IN CDB VARIABLE TABLE
	PUSHJ	P,GSUBTB	;GET FIRST WORD (-# BLKS,,OFFSET TO 1ST)
	  PJRST	ERRFIN		;NOT DEFINED, FORGET IT
	JUMPGE	T1,ERRFIN	;IF NO BLOCKS, GIVE UP
	ADDI	T2,(T1)		;BUMP ITEM NUMBER BY OFFSET OF FIRST
	HRRI	T1,1-ERABFH(P4)	;MAKE IT OFFSET TO START OF BLOCK
	MOVEM	T1,(P3)		;SAVE IN POINTER WORD IN BUFFER
KLSBD1:	PUSHJ	P,GSUBTB	;GET NEXT ITEM IN TABLE
	  PJRST	ERRFIN		;DONE, CLOSE FILE
	PUSH	P4,T1		;SAVE ITEM IN BUFFER
	AOJA	T2,KLSBD1	;BUMP ITEM NUMBER AND LOOP
;SUBROUTINE TO RECORD A CHANNEL-DETECTED PARITY ERROR OR NON-EX MEM

CHNERR:	HLRZ	P2,(T1)		;GET CDB ADDRESS
	SETZ	T1,		;CLEAR T1
	DPB	T2,[POINT 9,T1,8] ;PUT ERROR CODE INTO T1 FOR ERRINI
	PUSHJ	P,ERRINI	;HEADER, SET UP P4, CLEAR BUFFER
	MOVEI	T1,.CHLUE(P2)	;GET POINTER TO LAST UNIT WITH ERROR
	PUSHJ	P,PEKSPY
	ANDI	T1,-1		;RH ONLY
	JUMPE	T1,CHNER1	;STORE 0 IF DEVICE UNKNOWN
IFN UNINAM,<ADDI T1,UNINAM>	;ADDR OF NAME OF ERROR UNIT
	PUSHJ	P,PEKSPY	;PICK UP UNIT NAME
CHNER1:	PUSH	P4,T1		;(R0) UNIT NAME
	MOVEI	T1,.CHNXM(P2)
	PUSHJ	P,PEKSPY	;GET NXM COUNT FOR THIS CHANNEL
	PUSH	P4,T1		;(R1) NON-EX MEM COUNT
	MOVEI	T1,.CHMPE(P2)
	PUSHJ	P,PEKSPY
	PUSH	P4,T1		;(R2) MEM PAR ERR COUNT THIS CHANNEL
;	MOVEI	T1,.CHDPE(P2)
;	PUSHJ	P,PEKSPY
;	PUSH	P4,T1		;(R3) DEVICE PARITY ERRORS
	AOBJN	P4,.+1		;(R3) OBSOLETE
	MOVSI	T2,<.CHICW-.CHDW0-1>	;SETUP AOBJN WORD
	HRRI	T2,.CHICW(P2)	;WITH POINTER TO CHAN DATA BLOCK
CHNER2:	MOVEI	T1,(T2)		;GET ADDR TO EXAMINE
	PUSHJ	P,PEKSPY
	PUSH	P4,T1		;(R4-R13) CONTROL AND DATA WORDS
	AOBJN	T2,CHNER2
	SKIPN	T1,CHNTCW	;[545] GET OFFSET IF ANY
	  JRST	CHNER3		;[545] NONE, STORE ZERO
	ADDI	T1,0(P2)	;ADD OFFSET
	PUSHJ	P,PEKSPY
CHNER3:	PUSH	P4,T1		;(R14)EXPECTED TERM WD[463]
	PJRST	ERRFIN		;WRITE THE STUFF AND RETURN
;SUBROUTINE TO RECORD MAGTAPE STATISTICS ON UNLOAD (TAPSER)
;ARGS	P2=OFFSET OF TUBRID IN TUB
;	P3=DDB ADDRESS
;	P4=POINTER TO TUBRID IN CURRENT TUB
;RETURN CPOPJ,P1-P4 INTACT,T1-T4 BLOWN

GTPSTU:	PUSH	P,P1		;PRESERVE P1
	PUSH	P,P4		;PRESERVE P4
	PUSH	P,P3		;PRESERVE P3
	MOVEI	P1,TUBDDA-TUBRID(P4) ;GET ADDRESS OF SHADOW AREA FOR CURRENT
				; TUB INTO P1
	PUSHJ	P,ERRINI	;HEADER, SETUP P4 AND BUFFER
	MOVE	T1,[%CNTDB]	;FIND TUBDDB
	PUSHJ	P,GTBSPY
	 JRST	GTPST1		;NOT THERE, USE OLD STYLE
	ADDI	T1,(P1)		;COMPUTE TUBDDB
	SUBI	T1,TUBDDA-TUBRID(P2)
	PUSHJ	P,PEKSPY
	MOVEI	P3,(T1)		;USE DDB ADDRESS FROM TUB
GTPST1:	MOVE	T2,XTPUL	;LIST OF ITEMS TO DUMP
	PUSHJ	P,UNIDMP	;(R0-R7)DUMP THEM
	POP	P,P3		;RESTORE P3
	MOVEI	T1,(P3)		;DDB ADDR TO T1
	PUSHJ	P,DDBJOB	;GET OWNER'S JOB NUMBER
	MOVEI	J,(T1)		;AND PUT IT INTO J
	PUSHJ	P,GETPPN	;GET PPN
	PUSH	P4,T1		;(R10)SAVE IT IN BUFFER
	PUSHJ	P,ERRFIN	;CLOSE ERROR FILE
	POP	P,P4		;RESTORE ADDR OF TUB+TUBRID
	POP	P,P1		;RESTORE AOBJN WORD FOR ALL UNITS
	POPJ	P,		;RETURN

;SUBROUTINE TO RECORD A MAGTAPE ERROR (TAPSER)
;ARGS AS IN GTPSTU ON LAST PAGE

GTPERR:	PUSH	P,P1		;PRESERVE POINTER TO BLOCK FOR TAPES
	PUSH	P,P3		;SAVE DDB ADDRESS
	PUSH	P,P4		;SAVE POINTER TO TUBRID
	MOVEI	P1,0(P4)	;GET OFFSET TO TUBRID IN TUB INTO P1
	PUSHJ	P,ERRINI	;SET UP P4, PRODUCE HEADER
	MOVE	T1,[%CNTDB]	;FIND TUBDDB
	PUSHJ	P,GTBSPY
	 JRST	GTPER1		;NOT THERE, USE OLD STYLE
	ADDI	T1,(P1)		;COMPUTE TUBDDB
	SUBI	T1,(P2)
	PUSHJ	P,PEKSPY
	MOVEI	P3,(T1)		;SAVE DDB ADDRESS FROM TUB TO P3
GTPER1:	MOVEI	T1,DEVNAM(P3)
	PUSHJ	P,PEKSPY
	PUSH	P4,T1		;(R0)PUT IT INTO BUFFER
	MOVEM	T1,ERPTBK+1	;REMEMBER DEVICE NAME IN ERPTBK TO USE FOR TAPOP
	MOVE	T2,XTPEL	;SET UP LIST OF ITEMS TO DUMP
	PUSHJ	P,UNIDMP	;(R1-R7)DUMP THEM
	MOVE	T1,[2,,ERPTBK]	;SETUP FOR TAPOP. CALL
	MOVEI	T2,.TFKTP	;FUNCTION FOR TAPOP.
	MOVEM	T2,ERPTBK	;SAVE IT IN BLOCK FOR UUO
	TAPOP.	T1,		;WHAT KIND OF DEVICE?
	  SETZ	T1,		;OOPS
TAPTRY==4			;WORD CONTAINING CONTROLLER TYPE
	DPB	T1,[POINT 3,ERABFS+TAPTRY,14] ;SAVE IN BUFFER
	MOVE	T1,[2,,T2]	;SET UP FOR DIAG.
	MOVEI	T2,7		;GET CONTROLLER NUMBER
	MOVE	T3,ERPTBK+1	;UNIT NAME
	DIAG.	T1,		;WHAT CONTROLLER?
	  SETZ	T1,		;BEFORE 603, ASSUME RH10
	HLRZS	T1		;MOVE DEVICE CODE TO RH, CLEAR LH
	CAIL	T1,540		;IS IT IN THE RANGE OF
	CAILE	T1,574		;LEGAL RH20 DEVICE CODES?
	TDZA	T2,T2		;NO
	MOVSI	T2,(1B11)	;YES--1B11 FOR RH20
	MOVE	T1,[%FTERR]	;GET OPTIONS
	PUSHJ	P,GTBSPY
	  SETZ	T1,
	TRNE	T1,F%KS10&777777;ARE WE REPORTING FOR A KS10 SYSTEM?
	MOVSI	T2,(1B10)	;YES--ONLY RH11 CONTROLLERS
	IORM	T2,ERABFS+TAPTRY ;SET CHANNEL TYPE IN RETRY WORD
	MOVE	T1,[2,,ERPTBK]	;SETUP FOR TAPOP.
	MOVEI	T2,.TFIEP	;AND GET ARG FOR POINTER TO INITIAL
	MOVEM	T2,ERPTBK	; ERROR AREA INTO BLOCK FOR TAPOP.
	TAPOP.	T1,		;GO GET IT
	  SETZ	T1,		;OOPS
	MOVE	T4,T1		;SAVE UNRELOCATED POINTER IN T4
TAPIEP==10			;OFFSET OF POINTER TO INITIAL BLOCK
	PUSH	P4,T1		;(R10)PUT IT IN BUFFER
	MOVEI	T1,.TFFEP	;FUNCTION FOR TAPOP. TO GET POINTER
	MOVEM	T1,ERPTBK	; TO FINAL ERROR STATUS AREA
	MOVE	T1,[2,,ERPTBK]	;SETUP FOR TAPOP.
	TAPOP.	T1,		;GO GET FINAL ERROR POINTER
	  SETZ	T1,		;OOPS
	MOVE	T3,T1		;SAVE UNRELOCATED POINTER IN T3
TAPFEP==11			;OFFSET OF POINTER TO FINAL BLOCK
	PUSH	P4,T1		;(R11)PUT IN BUFFER
	MOVE	T2,XTPEL1	;GET EXTRA ITEMS
	PUSHJ	P,UNIDMP	;(R12-R13)
	MOVEI	T1,1-ERABFH(P4)	;GET OFFSET OF IEP BLOCK
	HRRM	T1,ERABFS+TAPIEP ;COMPLETE POINTER
	ADDI	T4,(P1)		;RELOCATE INITIAL POINTER WITH
	SUBI	T4,(P2)		;START OF UDB
IERLUP:	MOVEI	T1,(T4)		;GET NEXT WORD TO RECORD
	PUSHJ	P,PEKSPY	;PICK IT UP
	PUSH	P4,T1		;AND PUT IT IN THE BUFFER
	AOBJN	T4,IERLUP	;LOOP ON INITIAL ERROR AREA
	MOVEI	T1,1-ERABFH(P4)	;GET OFFSET OF FEP BLOCK
	HRRM	T1,ERABFS+TAPFEP ;COMPLETE POINTER
	ADDI	T3,(P1)		;ADD OFFSET OF TUBRID+START OF TUB
	SUBI	T3,(P2)		;SUBTRACT OFFSET OF TUBRID IN TUB
FERLUP:	MOVEI	T1,(T3)		;GET NEXT WORD TO RECORD
	PUSHJ	P,PEKSPY	;PICK IT UP
	PUSH	P4,T1		;AND PUT IT IN THE BUFFER
	AOBJN	T3,FERLUP	;LOOP ON FINAL ERROR AREA
	PUSHJ	P,ERRFIN	;CLOSE ERROR FILE
	POP	P,P4		;RESTORE P4
	POP	P,P3		;RESTORE P3
	POP	P,P1		;RESTORE POINTER TO MAGTAPE ERROR AREA
	POPJ	P,
;SUBROUTINE TO RECORD DX20 DEVICE ERRORS FROM TAPSER
;ARGS	T1=WORD 0 OF HEADER BLOCK FOR ERRINI
;	P2=DDB ADDRESS
;	P3=UDB ADDRESS
;RETURN CPOPJ, P1-P3 INTACT; P4, T1-T4 DESTROYED

D2TPER:	PUSH	P,P1		;SAVE P1-P3
	PUSH	P,P2		;...
	PUSH	P,P3		;...
	PUSHJ	P,ERRINI	;SETUP P4, PRODUCE HEADER
	MOVE	T1,[%CNTDB]	;GETTAB TO RETURN VALUE OF TUBDDB
	PUSHJ	P,GTBSPY	;GET IT
	  JRST	D2TPE1		;USE WHAT TAPSER GAVE US
	ADDI	T1,(P3)		;ADD IN BASE OF TUB
	PUSHJ	P,PEKSPY	;GO GET DDB ADDRESS
	MOVEI	P2,(T1)		;MOVE TO P2
D2TPE1:	MOVEI	T1,DEVNAM(P2)	;POINT TO DEVICE NAME
	PUSHJ	P,PEKSPY	;GET IT
	MOVEM	T1,ERPTBK+1	;SAVE FOR TAPOP'S/DIAG'S
	PUSH	P4,T1		;(R0) SAVE IN BUFFER
	MOVEI	P1,.TFFEP	;TAPOP. FUNCTION TO RETURN TUBFEP
	MOVEM	P1,ERPTBK	;BUILD UUO BLOCK
	MOVE	P1,[2,,ERPTBK]	;POINT TO IT
	TAPOP.	P1,		;GET TUBFEP FOR THIS UDB
	  MOVEI	P1,0		;CAN'T DO MUCH
	ADDI	P1,(P3)		;OFFSET TO FIRST WORD OF TUBFEP ENTRIES
	MOVE	T1,[%CNMER]	;GETTAB TO RETURN TUBRID,,MT0DDB
	PUSHJ	P,GTBSPY	;GET VALUE
	  MOVSI	T1,11		;TAKE A GUESS
	HLRZS	T1		;REALLY ONLY NEED TUBRID
	ADDI	P3,(T1)		;COMPUTE UDB+TUBRID
	MOVEI	T1,TUBRID(P3)	;POINT AT REELID IN TUB
	PUSHJ	P,PEKSPY	;GET IT
	PUSH	P4,T1		;(R1) SAVE IN BUFFER
	MOVE	T1,[2,,T2]	;LEN,,ADR FOR DIAG.
	MOVEI	T2,7		;FUNCTION=READ KON NUMBER
	MOVE	T3,ERPTBK+1	;GET DEVICE NAME BACK
	DIAG.	T1,		;READ RH20 DEVICE CODE
	  MOVEI	T1,0		;FAILED, USE 0
	MOVE	T2,T1		;SAVE IN T2
	MOVEI	T1,TD2VER(P1)	;GET POINTER TO DX20 ADDRESS
	PUSHJ	P,PEKSPY	;READ IT
	IOR	T2,T1		;OR TOGETHER
	HRRI	T2,001001	;CODES FOR RH20/MAGTAP
	PUSH	P4,T2		;(R2) SAVE IN BUFFER
	MOVE	T2,XD2EL	;GET AOBJN POINT TO INFO TO DUMP
	PUSHJ	P,UNIDMP	;(R3-R42) DUMP REST
	MOVEI	T1,TD2MBR(P1)	;POINTER TO MASSBUS REGISTER POINTER
	PUSHJ	P,PEKSPY	;READ IT
DXEMBR==43	;OFFSET IN DX20 ERROR ENTRY OF MBR SUB-BLOCK POINTER
	SKIPE	T2,T1		;SKIP IF ZERO, SAVE IN T2
	ADDI	T1,DXEMBR	;OFFSET FROM START OF ERROR BLOCK
	PUSH	P4,T1		;(R43) SAVE IN BUFFER
	MOVEI	T1,TD2DVL(P1)	;POINTER TO DEVICE SUB-BLOCK POINTER
	PUSHJ	P,PEKSPY	;READ IT
	PUSH	P,T1		;SAVE FOR LATER
DXEDVL==44	;OFFSET IN DX20 ERROR ENTRY OF DX20 REG SUB-BLOCK POINTER
	SKIPE	T1		;SKIP IF NO REGISTERS
	ADDI	T1,DXEDVL	;OFFSET FROM START OF ERROR BLOCK
	PUSH	P4,T1		;(R44) SAVE IN BUFFER
	JUMPE	T2,D2TPE5	;SKIP LOOP IF NO MASSBUS REGISTERS
	ADDI	T2,TD2MBR(P1)	;OFFSET TO START OF BLOCK
	HLRZ	T1,T2		;GET +NUMBER OF REGS TO READ
	MOVNS	T1		;MAKE IT NEGATIVE
	HRL	T2,T1		;MAKE AN AOBJN POINTER
D2TPE4:	MOVEI	T1,(T2)		;GET ADDRESS OF NEXT WORD OF BLOCK
	PUSHJ	P,PEKSPY	;READ IT
	PUSH	P4,T1		;SAVE IN BUFFER
	AOBJN	T2,D2TPE4	;LOOP FOR ALL ENTRIES
D2TPE5:	POP	P,T2		;GET BACK DEVICE BLOCK POINTER
	JUMPE	T2,D2TPE7	;SKIP IF NONE
	ADDI	T2,TD2DVL(P1)	;OFFSET TO START OF BLOCK
	HLRZ	T1,T2		;GET +NUMBER OF REGS TO READ
	MOVNS	T1		;MAKE IT NEGATIVE
	HRL	T2,T1		;MAKE AN AOBJN POINTER
D2TPE6:	MOVEI	T1,(T2)		;GET ADDRESS OF NEXT WORD OF BLOCK
	PUSHJ	P,PEKSPY	;READ IT
	PUSH	P4,T1		;SAVE IN BUFFER
	AOBJN	T2,D2TPE6	;LOOP FOR ALL ENTRIES
D2TPE7:	PUSHJ	P,ERRFIN	;CLOSE ERROR FILE
	POP	P,P3		;RESTORE UDB ADDRESS
	MOVEI	T1,TUBKDB(P3)	;OFFSET TO KDB POINTER
	PUSHJ	P,PEKSPY	;READ KDB ADDRESS
	MOVEI	T1,TKBCDB(T1)	;OFFSET TO CDB POINTER
	PUSHJ	P,PEKSPY	;READ CDB ADDRESS
	POP	P,P2		;RESTORE DDB ADDRESS
	POP	P,P1		;AND P1
	POPJ	P,		;RETURN
;SUBROUTINE TO RECORD DX20 DEVICES ERRORS FROM FILIO (RP20)
;ARGS	T1=WORD 0 OF HEADER BLOCK FOR ERRINI
;	P2=DDB ADDRESS
;	P3=UDB ADDRESS
;RETURN CPOPJ

D2DSER:	PUSHJ	P,ERRINI	;SETUP BUFFER, P4
	MOVE	T2,XR2EL1	;GET ARG FOR UNIDMP
	PUSHJ	P,UNIDMP	;(R0-R1) STORE VALUES IN BUFFER
DXENAM==0	;OFFSET OF UNIT NAME IN ENTRY
	PUSH	P4,[001002]	;(R2) CODE FOR RH20/DISK
DXETYP==2	;OFFSET IN ENTRY OF DX20/CONTROLLER ADDRESS
	MOVE	T2,XR2EL2	;GET ARG FOR UNIDMP
	PUSHJ	P,UNIDMP	;(R3-R6) STORE VALUES IN BUFFER
	MOVEI	T1,UNIMSC(P3)	;POINT TO COUNT OF MONITOR SEEKS
	PUSHJ	P,PEKSPY	;GET IT
	MOVE	P1,T1		;SAVE IN P1
	MOVEI	T1,UNIUSC(P3)	;POINT TO COUNT OF USER SEEKS
	PUSHJ	P,PEKSPY	;GET IT
	ADD	T1,P1		;ADD TOGETHER
	PUSH	P4,T1		;(R7) NUMBER OF SEEKS
	MOVEI	T1,UNIBRC(P3)	;POINT TO BUFFERED READ COUNT
	PUSHJ	P,PEKSPY	;GET IT
	MOVE	P1,T1		;SAVE IN P1
	MOVEI	T1,UNIDRC(P3)	;POINT TO DUMP READ COUNT
	PUSHJ	P,PEKSPY	;GET IT
	ADD	P1,T1		;ACCUMULATE TOTAL
	MOVEI	T1,UNIMRC(P3)	;POINT TO MONITOR READ COUNT
	PUSHJ	P,PEKSPY	;GET IT
	ADD	P1,T1		;ACCUMULATE TOTAL
	PUSH	P4,P1		;(R10) NUMBER OF BLOCKS READ
	MOVEI	T1,UNIBWC(P3)	;POINT AT BUFFERED WRITE COUNT
	PUSHJ	P,PEKSPY	;GET IT
	MOVE	P1,T1		;SAVE IN P1
	MOVEI	T1,UNIDWC(P3)	;POINT AT DUMP WRITE COUNT
	PUSHJ	P,PEKSPY	;GET IT
	ADD	P1,T1		;ACCUMULATE TOTAL
	MOVEI	T1,UNIMWC(P3)	;POINT AT MONITOR WRITE COUNT
	PUSHJ	P,PEKSPY	;GET IT
	ADD	P1,T1		;ACCUMULATE TOTAL
	PUSH	P4,P1		;(R11) NUMBER OF BLOCK WRITTEN
	MOVE	T1,LDDBSH	;DEVFIL=DEVJOB+1=LEN(SHORT DDB)
	ADDI	T1,(P2)		;MAKE IT AN ADDRESS
	PUSHJ	P,PEKSPY	;GET IT
	PUSH	P4,T1		;(R12) STORE FILENAME
	MOVEI	T1,(P2)		;PUT DDB ADDRESS IN T1
	PUSHJ	P,DDBJOB	;GET JOB NUMBER FROM DDB
	MOVSS	P1,T1		;PUT IN LH AND SAVE IN P1
	HRRI	T1,.GTPPN	;SETUP TO GET PPN OF USER
	PUSHJ	P,GTBVAR	;(R13) SAVE PPN IN BUFFER
	MOVE	T1,P1		;GET JOB NUMBER BACK
	HRRI	T1,.GTPRG	;SETUP TO GET NAME OF PROGRAM RUNNING
	PUSHJ	P,GTBVAR	;(R14) SAVE PROGRAM NAME IN BUFFER
	HRRZ	P1,UNISCR	;GET OFFSET TO UNISCR
	ADDI	P1,(P3)		;MAKE IT AN ADDRESS
	MOVE	T2,XR2EL3	;SETUP ARG FOR UNIDMP
	PUSHJ	P,UNIDMP	;(R15-R24) STORE VALUES IN BUFFER
	PUSH	P4,[0]		;(R25) UNUSED
	PUSH	P4,[0]		;(R26) UNUSED
	MOVEI	T1,.DIAKU	;FUNCTION CODE FOR DIAG.
	MOVE	T2,ERABFS+DXENAM ;GET UNIT NAME
	MOVE	T3,[2,,T1]	;POINT AT BLOCK
	DIAG.	T3,		;GET DEVICE CODE
	  MOVEI	T3,0		;FAILED?
	HRRZ	P1,UNISCR	;GET OFFSET OF UNISCR
	ADDI	P1,4(P3)	;UNIEBK=UNISCR+4
	MOVEI	T1,(P1)		;MOVE POINTER TO T1
	PUSHJ	P,PEKSPY	;GET DX20/CONT ADDR,,MICROCODE VER
	PUSH	P,T1		;SAVE MICROCODE VERSION FOR LATER
	IOR	T1,T3		;OR DX20 ADDRESS WITH RH20 DEVICE CODE
	HLLM	T1,ERABFS+DXETYP ;STORE ADDRESSES IN BLOCK
	HRLI	P1,-<RNXNXM-RNXCS0+1> ;SETUP AOBJN POINTER TO VALUES
D2DSE1:	MOVEI	T1,1(P1)	;GET NEXT ADDRESS
	PUSHJ	P,PEKSPY	;GET NEXT VALUE FROM UNIEBK
	PUSH	P4,T1		;(R27-R35) SAVE VALUE IN BLOCK
	AOBJN	P1,D2DSE1	;LOOP FOR ALL
	PUSH	P4,[0]		;(R36) UNUSED
	PUSH	P4,[0]		;(R37) UNUSED
	PUSH	P4,[0]		;(R40) UNUSED
	MOVEI	T1,UNIKON(P3)	;GET KDB ADDRESS
	PUSHJ	P,PEKSPY	;READ IT
	ADD	T1,KONREG	;OFFSET TO NUMBER OF REGS TO SAVE
	PUSHJ	P,PEKSPY	;READ THAT
	ADD	T1,UNISCR	;SKIP PAST THE REGS TO GET THE INITIAL
	ADDI	T1,4(P3)	; CONTROL REGISTER (UNIEBK=UNISCR+4)
	PUSHJ	P,PEKSPY	;READ THE INITIAL CONTROL REGISTER
	PUSH	P4,T1		;(R41) SAVE IN THE BUFFER
	POP	P,T1		;GET MICROCODE VERSION BACK
	TLZ	T1,-1		;CLEAR JUNK
	PUSH	P4,T1		;(R42) SAVE IN BUFFER
	AOS	T1,P1		;STEP TO POINTER TO MASSBUS REGISTERS
	PUSHJ	P,PEKSPY	;READ IT
	SKIPE	T2,T1		;DON'T DO ADD IF ZERO, MOVE TO T2
	ADDI	T1,DXEMBR	;OFFSET FROM FIRST WORD IN ENTRY
	PUSH	P4,T1		;(R43) SAVE IN BUFFER
	AOS	T1,P1		;STEP TO POINTER TO DEVICE REGISTERS
	PUSHJ	P,PEKSPY	;READ IT
	PUSH	P,T1		;SAVE FOR LATER
	SKIPE	T1		;DON'T DO ADD IF ZERO
	ADDI	T1,DXEDVL	;OFFSET FROM FIRST WORD IN ENTRY
	PUSH	P4,T1		;(R44) SAVE IN BUFFER
	JUMPE	T2,D2DSE3	;GO IF NO MASSBUS REGISTERS TO READ
	ADDI	T2,-1(P1)	;COMPUTE FIRST MASSBUS REGISTER ADDR
	HLRZ	T1,T2		;GET THE LENGTH OF THE BLOCK
	MOVNS	T1		;MAKE IT NEGATIVE
	HRL	T2,T1		;MAKE T2 AN AOBJN POINTER TO THE BLOCK
D2DSE2:	MOVEI	T1,(T2)		;GET NEXT ADDRESS
	PUSHJ	P,PEKSPY	;READ THE NEXT REGISTER
	PUSH	P4,T1		;SAVE IN BUFFER
	AOBJN	T2,D2DSE2	;LOOP FOR ALL MASSBUS REGISTERS
D2DSE3:	POP	P,T2		;RESTORE DEVICE REGISTER POINTER
	JUMPE	T2,D2DSE5	;GO IF NONE TO READ
	ADDI	T2,(P1)		;COMPUTE FIRST DEVICE REGISTER ADDR
	HLRZ	T1,T2		;GET LENGTH OF BLOCK
	MOVNS	T1		;MAKE IT NEGATIVE
	HRL	T2,T1		;MAKE T2 AN AOBJN POINTER TO THE BLOCK
D2DSE4:	MOVEI	T1,(T2)		;GET NEXT ADDRESS
	PUSHJ	P,PEKSPY	;READ THE NEXT REGISTER
	PUSH	P4,T1		;STORE IN BUFFER
	AOBJN	T2,D2DSE4	;LOOP FOR ALL WORDS IN BLOCK
D2DSE5:	PJRST	ERRFIN		;CLOSE FILE AND RETURN
;SUBROUTINE TO RECORD A DISK ERROR
;ARGS	P2=ADDR OF DDB WITH ERROR
;	P3=ADDR OF UNIT DATA BLOCK IN ERROR
;RETURN	CPOPJ, P1-P3 INTACT; P4,T1-4 BLOWN

GDVERR:	PUSHJ	P,ERRINI	;HEADER, SETUP P4, CLEAR BUFER
	MOVE	T2,XDVEL	;LIST OF ITEMS TO DUMP
	PUSHJ	P,UNIDMP	;(R0-R14) DUMP THEM
	MOVEI	T1,UNIBRC(P3)	;BUFFERED READ COUNT
	PUSHJ	P,PEKSPY
	MOVE	T2,T1
	MOVEI	T1,UNIDRC(P3)	;DUMP-MODE READ COUNT
	PUSHJ	P,PEKSPY
	ADD	T2,T1
	MOVEI	T1,UNIMRC(P3)	;MONITOR READ COUNT
	PUSHJ	P,PEKSPY
	ADD	T2,T1		;GET THEM ALL TOGETHER
	PUSH	P4,T2		;(R15) TOTAL READS ON THIS UNIT
	MOVEI	T1,UNIBWC(P3)	;BUFFERED WRITE COUNT
	PUSHJ	P,PEKSPY
	MOVE	T2,T1
	MOVEI	T1,UNIDWC(P3)	;DUMP MODE WRITES
	PUSHJ	P,PEKSPY
	ADD	T2,T1
	MOVEI	T1,UNIMWC(P3)	;MONITOR WRITES
	PUSHJ	P,PEKSPY
	ADD	T2,T1
	PUSH	P4,T2		;(R16) TOTAL WRITES ON THIS UNIT
	MOVEI	T1,UNIMSC(P3)	;MONITOR SEEK COUNT
	PUSHJ	P,PEKSPY
	MOVE	T2,T1
	MOVEI	T1,UNIUSC(P3)	;USER SEEK COUNT
	PUSHJ	P,PEKSPY
	ADD	T2,T1
	PUSH	P4,T2		;(R17) TOTAL SEEKS ON THIS UNIT
	MOVEI	T1,UNINAM(P3)
	PUSHJ	P,PEKSPY	;RE-GET UNIT NAME
	MOVEI	T2,T1		;SET POINTER TO IT
	DSKCHR	T2,
	  SETZ	T2,		;LOSE
	PUSH	P4,T2		;(R20) DSKCHR INFO FOR THIS UNIT
	MOVEI	T1,UNILOG(P3)	;LOGICAL NAME OF UNIT
	PUSHJ	P,PEKSPY
	PUSH	P4,T1		;(R21) SAVE  UNILOG
	MOVE	T1,UNICCT
	ADDI	T1,0(P3)	;OFFSET
	PUSHJ	P,PEKSPY
	PUSH	P4,T1		;(R22) # BAT SLOTS LEFT
	MOVEI	T2,(P2)		;GET DDB ADDRESS IN T2
	ADD	T2,LDDBSH	;LEN OF SHORT DDB=DEVFIL IN DSK DDB
	HRLI	T2,-2		;WANT 2 WORDS FROM THE DDB
GDVER1:	MOVEI	T1,(T2)		;GET ADDRESS FOR PEKSPY
	PUSHJ	P,PEKSPY	;READ THE WORD IN THE DDB
	PUSH	P4,T1		;(R23-R24) SAVE IN BUFFER
	AOBJN	T2,GDVER1	;LOOP FOR ALL
	HLLZS	0(P4)		;SAVE ONLY LH OF EXTENSION WORD
	MOVEI	T1,(P2)		;GET DDB ADDRESS INTO T1
	PUSHJ	P,DDBJOB	;GET JOB # OWNING THIS DDB
	MOVE	T2,T1		;REMEMBER JOB NUMBER IN T2 FOR 2ND GETTAB
	MOVSI	T1,(T2)		;SET UP T1 TO GETTAB USERS PPN
	HRRI	T1,.GTPPN	; FOR THIS JOB
	PUSHJ	P,GTBVAR	;(R25) SAVE PPN
	MOVSI	T1,(T2)		;AND SET UP T1 TO GETTAB PROGRAM
	HRRI	T1,.GTPRG	; NAME FOR THIS JOB
	PUSHJ	P,GTBVAR	;(R26) SAVE PROGRAM NAME
	PJRST	ERRFIN		;FALL INTO CLOSE AND RETURN
;SUBROUTINE TO RECORD A MASSBUS DEVICE ERROR (CODE 11) IN ERROR.SYS
;ARGS	T3=NUMBER OF DRIVE REGISTRS SAVED ON THIS UNIT
;	P2=ADDR OF DDB WITH ERROR
;	P3=ADDR OF UNIT DATA BLOCK IN ERROR
;RETURN CPOPJ, P1-P3 INTACT; T1-T4,P4 BLOWN

GMDVER:	PUSH	P,T3		;SAVE T3 FOR LATER
	PUSHJ	P,ERRINI	;WRITE HEADER
	MOVE	T2,XMDVEL	;GET AOBJN WORD FOR TABLE
	PUSHJ	P,UNIDMP	;(R0-R11) AND DUMP THE TABLE'S ITEMS
	MOVEI	T2,(P2)		;GET DDB ADDRESS INTO T2
	ADD	T2,LDDBSH	;LEN OF SHORT DDB=DEVFIL IN DSK DDB
	HRLI	T2,-2		;WANT FILENAME AND EXT FROM DDB
GMDVR1:	MOVEI	T1,(T2)		;GET ADDRESS OF WORD
	PUSHJ	P,PEKSPY	;GET THE WORD
	PUSH	P4,T1		;(R12-R13) SAVE IN BUFFER
	AOBJN	T2,GMDVR1	;LOOP FOR ALL
	HLLZS	0(P4)		;SAVE ONLY LH OF EXTENSION WORD
	MOVEI	T1,(P2)		;GET DDB ADDRESS INTO T1
	PUSHJ	P,DDBJOB	;GET JOB # OWNING THIS DDB
	MOVE	T2,T1		;REMEMBER JOB NUMBER IN T2 FOR 2ND GETTAB
	MOVSI	T1,(T2)		;SET UP T1 TO GETTAB USERS PPN
	HRRI	T1,.GTPPN	; FOR THIS JOB
	PUSHJ	P,GTBVAR	;(R14) SAVE PPN
	MOVSI	T1,(T2)		;AND SET UP T1 TO GETTAB PROGRAM
	HRRI	T1,.GTPRG	; NAME FOR THIS JOB
	PUSHJ	P,GTBVAR	;(R15) SAVE PROGRAM NAME
	MOVNI	T3,MAXREG	;GET TOTAL NUMBER OF REGS TO WRITE
	POP	P,T2		;AND NUMBER SAVED BY MONITOR
	ADD	T3,T2		;T3=-NUMBER LEFT OVER
	SKIPL	T3		;IF T3 NOT LT 0, 
	SETZ	T3,		;DEVICE MUS BE NEW-JUST SAVE MAXREG REGISTERS
	MOVNI	T2,4(T2)	;T2=-(NUMBER TO SAVE+4 DATAI'S)
	HRLZS	T2		;T2=AOBJN WORD FOR REGS TO SAVE
	HRR	T2,UNISCR	;MUST POINT INTO UDB
	ADDI	T2,(P3)		;INTO THIS UDB
MBDRLP:	MOVEI	T1,(T2)		;GET POINTER TO NEXT REG
	PUSHJ	P,PEKSPY
	PUSH	P4,T1		;(R16-R41) SAVE THIS REGISTER
	AOBJN	T2,MBDRLP	;AND LOOP TO NEXT REGISTER
	JUMPE	T3,MBDVDN	;NO MORE REGS, MONITOR SAVED ALL?
	SETZ	T1,		;SAVE SOME ZEROES FOR
	PUSH	P4,T1		; SYSERR
	AOJL	T3,.-1		;T3 HAS NUMBER TO SAVE
MBDVDN:	MOVE	T1,UNISCR	;GET OFFSET OF UNISCR IN UDB
	ADDI	T1,-1(P3)	;UNILAS=UNISCR-1
	PUSHJ	P,PEKSPY
	PUSH	P4,T1		;(R42) PUT IT IN ERABUF
	MOVE	T1,UNICCT	;[463]
	ADDI	T1,0(P3)	;OFFSET
	PUSHJ	P,PEKSPY
	PUSH	P4,T1		;(R43) # OF BAT SLOTS 
	MOVEI	T1,(P3)		;ADDRESS OF UDB
	PUSHJ	P,PEKSPY	;GET UNIT NAME
	MOVE	T3,T1		;SAVE FOR DIAG.
	MOVE	T1,[2,,T2]	;SET UP CALL
	MOVEI	T2,7		;GET CONTROLLER UNIT
	DIAG.	T1,		;DO IT
	  SETZ	T1,		;BEFORE 603 ASSUME RH10
	HLRZ	T2,T1		;[703]MOVE KONT ADDR TO T2
	LSH	T2,-2		;[703]RIGHT JUSTIFY FOR BYTE
MDETYP==4			;WORD CONTAINING DEVICE CODE AND TYPE
	DPB	T2,[POINT 7,ERABFS+MDETYP,11]	;[703] SAVE FOR SYSERR
	CAMGE	T1,[540,,0]	;RH10?
	SKIPA	T2,[RH10CD]	;YES
	MOVEI	T2,RH20CD	;NO
	MOVE	T1,[%FTERR]	;GET OPTIONS
	PUSHJ	P,GTBSPY
	  SETZ	T1,
	TRNE	T1,F%KS10&777777;ARE WE REPORTING FOR A KS10 SYSTEM?
	MOVEI	T2,RH11CD	;YES, THEN ONLY RH11 CONTROLLERS
	DPB	T2,[POINT 3,ERABFS+MDETYP,14] ;SAVE CODE IN RETRIES WORD
	PJRST	ERRFIN		;CLOSE FILE AND RETURN
;SUBROUTINE TO RECORD KI/KL PARITY/NXM INTERRUPTS

KPARNX:	HLRZ	P3,(T1)		;GET CDB ADDR FOR CDB WITH ERROR
	PUSHJ	P,FNDCPU	;FIND CPU WHICH HAD ERROR
	  POPJ	P,		;NOT ANY CPU, GIVE IT UP
	MOVEI	P2,(P1)		;COPY CPU #
	LSH	P2,1		;DOUBLE IT
	SETZ	T1,		;CLEAR T1
	DPB	T2,[POINT 9,T1,8] ;PUT ERROR CODE INTO T1 FOR ERRINI
	PUSH	P,T2		;SAVE IT FOR A WHILE
	PUSHJ	P,ERRINI	;SETUP BUFFER AND P4
	MOVE	T1,[%CCPHY]	;PHYSICAL CPU NAME
	PUSHJ	P,GCPVAR	;(R0) PHYSICAL CPU NAME
	MOVE	T1,[%CVMPP]	;PC AT TIME OF ERROR
	PUSHJ	P,GCPVAR	;(R1) PC (EXEC OR USER)
	MOVE	T1,[%CVPCN]	;CONI APR, AT ERROR
	PUSHJ	P,GCPVAR	;(R2) CONI APR,
	MOVE	T1,[%CVPPI]	;CONI PI, AT ERROR
	PUSHJ	P,GCPVAR	;(R3) CONI PI,
	POP	P,T2		;GET BACK ERROR CODE
	CAIE	T2,.ESKIP	;IS THIS A KI?
	JRST	KPARN1		;NO--A KL
	MOVE	T1,[%CVEJN]	;PPN OF USER
	PUSHJ	P,GTBVAR	;(R4) SAVE PPN
	MOVE	T1,[%CVEPN]	;PROGRAM NAME
	PUSHJ	P,GTBVAR	;(R5) SAVE PROGRAM NAME
	PJRST	ERRFIN		;END OF KI ENTRY
KPARN1:	MOVE	T1,[%CVAER]	;RDERA
	PUSHJ	P,GCPVAR	;(R4) RDERA
	AOBJN	P4,.+1		;(R5) SPACE FOR SBDIAG POINTER
	HRRZ	P3,P4		;SAVE CURRENT LOCATION HERE
	PJRST	KLSBDG		;WRITE THE SBDIAG SUB-TABLE
;SUBROUTINE TO RECORD KS NXM TRAPS AND KL/KS PARITY TRAPS

KLSTRP:	HLRZ	P3,(T1)		;GET CDB ADDR FOR CDB WITH ERROR
	PUSHJ	P,FNDCPU	;FIND CPU WHICH HAD ERROR
	  POPJ	P,		;NOT ANY CPU, GIVE IT UP
	MOVEI	P2,(P1)		;COPY CPU #
	LSH	P2,1		;DOUBLE IT
	SETZ	T1,		;CLEAR T1
	DPB	T2,[POINT 9,T1,8] ;PUT ERROR CODE INTO T1 FOR ERRINI
	PUSHJ	P,ERRINI	;SETUP BUFFER AND P4
	MOVE	T1,[%CCPHY]	;PHYSICAL CPU NAME
	PUSHJ	P,GCPVAR	;(R0) PHYSICAL CPU NAME
	MOVE	T1,[%CVPPC]	;PC AT TIME OF TRAP
	PUSHJ	P,GCPVAR	;(R1) PC AT TIME OF TRAP
	MOVE	T1,[%CVPFW]	;PAGE FAIL WORD
	PUSHJ	P,GCPVAR	;(R2) PAGE FAIL WORD
	MOVE	T1,[%CVBPA]	;MAPPED PHYSICAL ADDRESS
	PUSHJ	P,GCPVAR	;(R3) MAPPED PHYSICAL ADDRESS
	MOVE	T1,[%CVTBD]	;INCORRECT DATA
	PUSHJ	P,GCPVAR	;(R4) INCORRECT DATA
	MOVE	T1,[%CVTPI]	;CONI PI, AT TRAP
	PUSHJ	P,GCPVAR	;(R5) CONI PI, AT TRAP
	MOVE	T1,[%CVEJN]	;JOB NUMBER
	PUSHJ	P,GCPVAR	;(R6) JOB NUMBER THAT TRAPPED
	MOVE	T1,[%CVEPN]	;JOB NAME
	PUSHJ	P,GCPVAR	;(R7) JOB NAME THAT TRAPPED
	MOVE	T1,[%CVTGD]	;CORRECT DATA
	PUSHJ	P,GCPVAR	;(R8) CORRECT DATA
	MOVE	T1,[%CVPTR]	;RETRY WORD
	PUSHJ	P,GCPVAR	;(R9) RETRY WORD
	MOVE	T1,[%CVSPT]	;NUMBER OF RECOVERABLE TRAPS
	PUSHJ	P,GCPVAR	;(R10) RECOVERABLE TRAP COUNT
	MOVE	T1,[%CVHPT]	;NUMBER OF NON-RECOVERABLE TRAPS
	PUSHJ	P,GCPVAR	;(R11) NON-RECOVERABLE TRAP COUNT
	MOVE	T1,[%CVTGD]	;CORRECT DATA
	PJRST	ERRFIN		;CLOSE OUT ENTRY
;HERE TO RECORD NXM SWEEPS - CODE 56

NXMSWP:	HLRZ	P3,(T1)		;GET CDB ADDR FOR CDB WITH ERROR
	PUSHJ	P,FNDCPU	;GOT FIND WHICH CPU ERROR WAS ON
	  POPJ	P,		;NOT ANY CPU, GIVE IT UP
	MOVEI	P2,(P1)		;GET CPU NUMBER
	LSH	P2,1		;DOUBLE IT
	SETZ	T1,		;CLEAR T1
	DPB	T2,[POINT 9,T1,8] ;PUT ERROR CODE INTO T1 FOR ERRINI
	PUSHJ	P,ERRINI	;INITIALIZE THE ERROR BUFFER
	MOVE	T1,[%CCPHY]	;PHYSICAL CPU NAME
	PUSHJ	P,GCPVAR	;(R0) PHYSICAL CPU NAME
	MOVE	T1,[%CVTNE]	;COUNT OF ERROR ON SWEEP OF CORE
	PUSHJ	P,GCPVAR	;(R1)STASH IT
	MOVE	T1,[%CVSNE]	;NOT REPRODUCIBLE ERROR COUNT
	PUSHJ	P,GCPVAR	;(R2)
	MOVE	T1,[%CVMNA]	;FIRST BAD ADDR FROM SWEEP
	PUSHJ	P,GCPVAR	;(R3)
	MOVE	T3,[%CCNXT]	;GET POINTER TO NXM SUBTABLE
	ADD	T3,P2		;POINTER IS IN CONSTANTS TABLE
	MOVSI	T2,.GTC0V(P2)	;SUBTABLE IS IN VARIABLES TABLE
NXMSW1:	PUSHJ	P,GSUBTB	;GET AN ITEM FROM THE SUBTABLE
	  JRST	NXMSW2		;END OF THE SUBTABLE
	PUSH	P4,T1		;(R4-R11)STICK IT IN THE BUFFER
	AOJA	T2,NXMSW1	;LOOP OVER ENTIRE SUBTABLE
NXMSW2:	MOVEI	T1,1		;FLAG WHICH SAYS 1 BIT=1 PAGE
	HRLI	T1,707070	;FLAG FOR SYSERR
	PUSH	P4,T1		;(R12)SAVE IT
	MOVN	T2,NXMLEN	;GET NEGTIVE LENGTH OF NXMTAB
	HRLZS	T2		;PUT IT IN LH OF T2 FOR POINTER
EN%NX1==13			;OFFSET OF FIRST POINTER TO NXMTAB
	PUSH	P4,T2		;(R13)SAVE AS POINTER TO FIRST COPY OF NXMTAB
	PUSH	P4,T2		;(R14)SAVE AS POINTER TO SECOND COPY OF NXMTAB
EN%BTB==15			;OFFSET FOR POINTER TO BAD ADDR SUBTABLE
	AOBJN	P4,.+1		;(R15)SPACE FOR BAD ADDRESS SUBTABLE
	MOVEI	T1,1-ERABFH(P4)	;GET RELATIVE POSITION TO NXM TABLE
	HRRM	T1,ERABFS+EN%NX1 ;SAVE AS RIGHT HALF OF POINTER
	HLLZ	T2,ERABFS+EN%NX1 ;GET BACK NEG LENGTH
	HRR	T2,NXMTAB	;AND GET POINTER TO TABLE
	PUSH	P4,(T2)		;PUSH WORD OF NXMTAB INTO BUFFER
	AOBJN	T2,.-1		;STEP TO NEXT WORD
	MOVEI	T1,1-ERABFH(P4)	;GET RELATIVE OFFSET TO 2ND TABLE
	HRRM	T1,ERABFS+EN%NX1+1 ;SAVE IT AS RIGHT HALF OF POINTER
	MOVE	T1,[%CNNXM]	;GETTAB POINTER TO NXMTAB
	PUSHJ	P,GTBSPY
	  SETZ	T1,		;CAN'T HAPPEN
	MOVE	T3,T1		;USE T3 AS AOBJN POINTER
	MOVE	T2,NXMTAB	;AND T2 AS WHERE TO STORE
NXMSW3:	HRRZ	T1,T3		;GET CURRENT ADDR INTO T1
	PUSHJ	P,PEKSPY	;GO PICK IT UP FROM MONITOR
	MOVEM	T1,(T2)		;STASH IT AWAY
	PUSH	P4,T1		;PUT IT INTO ERROR BUFFER ALSO
	AOS	T2		;INCREMENT T2
	AOBJN	T3,NXMSW3	;INCREMENT T3 AND LOOP
	PUSH	P,P4		;SAVE CURRENT LOC IN BUFFER
	MOVE	T3,[%CCNXT]	;SUBTABLE POINTER FOR NXM
	ADD	T3,P2		;IN THE CONSTANTS TABLE
	MOVSI	T2,.GTC0V(P2)	;THE SUBTABLE IS IN VARIABLES TABLE
	HRRI	T2,%CVNTS	;ITEM FOR # OF NXM'S FOUND ON SWEEP
	PUSHJ	P,GSUBTB	;GO GET IT
	  JRST	CRRFIN		;NONE IF NO POINTER
	JUMPE	T1,CRRFIN	;OR IF POINTER IS ZERO
	MOVE	T4,T1		;GET COUNT INTO T4
	HLL	T3,[%CCMPT]	;LOOK IN BAT SUBTABLE NOW
	HLLZS	T2		;AND START AT ITEM 0
NXMSW4:	PUSHJ	P,GSUBTB	;GET A WORD
	  JRST	NXMSW5		;ALL DONE
	PUSH	P4,T1		;SAVE IT IN BUFFER
	AOJ	T2,		;STEP TO NEXT ENTRY
	SOJG	T4,NXMSW4	;LOOP BACK FOR NUMBER OF ENTRIES
NXMSW5:	POP	P,T1		;GET BACK START LOC OF TABLE
	MOVNI	T2,(T2)		;GET NEGATIVE NUMBER OF ITEMS STORED
	JUMPE	T2,ERRFIN	;IF NONE, JUST FINISH
	HRLI	T2,1-ERABFH(T1)	;COMPUTE RELATIVE OFFSET OF TABLE
	MOVSM	T2,ERABFS+EN%BTB ;SAVE POINTER IN BUFFER
	PJRST	ERRFIN		;CLOSE OUT ENTRY
;HERE TO RECORD PARITY SWEEPS - CODE 57

PARSWP:	HLRZ	P3,(T1)		;GET CDB ADDR FOR CDB WITH ERROR
	PUSHJ	P,FNDCPU	;FIND CPU WHICH HAD ERROR
	  POPJ	P,		;NOT ANY CPU, GIVE IT UP
	MOVEI	P2,(P1)		;COPY CPU #
	LSH	P2,1		;DOUBLE IT
	SETZ	T1,		;CLEAR T1
	DPB	T2,[POINT 9,T1,8] ;PUT ERROR CODE INTO T1 FOR ERRINI
	PUSHJ	P,ERRINI	;SETUP BUFFER AND P4
	MOVE	T1,[%CCPHY]	;PHYSICAL CPU NAME
	PUSHJ	P,GCPVAR	;(R0) PHYSICAL CPU NAME
	MOVE	T1,[%CVTPE]
	PUSHJ	P,GCPVAR	;(R1)TOTAL ERRORS WHICH RECURRED ON SWEEP OF CORE
	MOVE	T1,[%CVSPE]
	PUSHJ	P,GCPVAR	;(R2) TOTAL NOT REPRODUCABLE
	MOVE	T1,[%CVMPW]	;CONTENTS OF FIRST BAD WORD
	PUSHJ	P,GCPVAR	;(R3)
	MOVE	T1,[%CVMPA]	;FIRST BAD ADDRESS
	PUSHJ	P,GCPVAR	;(R4)
EC%PRT==5			;PARITY DATA SUBTABLE POINTER
	AOBJN	P4,.+1		;(R5) SAVE SPACE FOR IT
EC%BTA==6			;BAD ADDRESS SUBTABLE POINTER
	AOBJN	P4,.+1		;(R6) SAVE SPACE FOR IT
	PUSH	P,P4		;SAVE START ADDRESS OF SUBTABLE
	MOVE	T3,[%CCPAR]	;SUB-TABLE POINTER FOR OTHER PAR STUFF
	ADD	T3,P2		;FROM THIS CPU CONSTANTS TABLE
	MOVSI	T2,.GTC0V(P2)	;SUBTABLE IS IN CPU VAR TABLE
PARSW1:	PUSHJ	P,GSUBTB	;GET ENTRY FROM SUBTABLE
	  JRST	PARSW2		;END OF PARITY SUBTABLE
	PUSH	P4,T1		;GIVE
	AOJA	T2,PARSW1	;GET WHOLE SUBTABLE
PARSW2:	POP	P,T1		;GET BACK START LOC OF SUBTABLE
	MOVNI	T4,(T2)		;GET -LEN OF TABLE FROM LOOP COUNT
	JUMPE	T4,ERRFIN	;IF NONE, THEN NO BAD ADDR'S EITHER
	HRLI	T4,1-ERABFH(T1)	;MAKE SWAPPED AOBJN POINTER TO SUBTABLE
	MOVSM	T4,ERABFS+EC%PRT ;SAVE AS POINTER TO SUBTABLE
	PUSH	P,P4		;SAVE START LOC OF BAD ADDR SUBTABLE
	HRRI	T2,%CVPTS	;OTHER POINTERS ARE ALREADY SET
	PUSHJ	P,GSUBTB	;NO OF BAD ADDRESSES SAVED
	  JRST	CRRFIN		;NONE IF NO TABLE FOR THEM
	MOVEI	T4,(T1)		;KEEP THE COUNT
	JUMPE	T4,CRRFIN	;QUIT IF NONE
	HLL	T3,[%CCMPT]	;LOOK IN BAT SUBTABLE NOW
	HLLZS	T2		;START AT BEGINNING OF TABLE
PARSW3:	PUSHJ	P,GSUBTB	;GET NEXT BAD ADDRESS
	  JRST	PARSW4		;END OF SUB-TABLE
	MOVEM	T1,1(P4)	;SAVE THE BAD ADDR
	AOBJP	P4,PARSW4	;CHECK FOR BUFFER OVERFLOW
	AOJ	T2,		;READY FOR NEXT ENTRY
	SOJG	T4,PARSW3	;GET IT IF ONE WAS STORED
PARSW4:	POP	P,T1		;GET BACK START LOC OF TABLE
	MOVNI	T4,(T2)		;GET -LEN OF TABLE FROM LOOP COUNT
	JUMPE	T4,ERRFIN	;GO IF NONE
	HRLI	T4,1-ERABFH(T1)	;MAKE SWAPPED AOBJN POINTER TO SUBTABLE
	MOVSM	T4,ERABFS+EC%BTA ;STORE AS POINTER TO SUBTABLE
	PJRST	ERRFIN		;CLOSE OUT ENTRY
;SUBROUTINE TO APPEND TO ERROR.SYS
;ARGS	P4=LAST ADDR STORED IN ERRBUF
;BLOWS T1-3
;ALWAYS RETURNS CPOPJ

CRRFIN:	POP	P,(P)		;PRUNE STACK
ERRFIN:	SKIPE	IOERR		;[62]CAN WE WRITE IN ERROR.SYS
	JRST	ERRFIX		;NO, CLEAR FLAGS AND RETURN
	MOVEM	P4,SAVEP4	;SAVE P4
	PUSHJ	P,FLSPAK	;FLUSH INPUT QUEUE AND CLEAR BLOCK
	TRZA	F,R.PAE		;INSURE THAT R.PAE IS NOT SET
AVLFIN:	TRO	F,R.PAE		;SET PROCESSING AVAIL.SYS FLAG
	INIT	FCT,17		;[62]OPEN A CHANNEL FOR THE PURPOSE
	ERRDEV			;OPEN DESIRED DEVICE
	0
	  JRST	E.IEF		;CAN'T INIT ERROR FILE
	MOVE	T1,[ERRDEV]	;[602] GET DEVICE WHERE ERROR.SYS LIVES
	MOVEM	T1,SSELBK+4	;[602]INTO THE IPCF MSG
	MOVEI	T1,RBSIZE-RBCNTE ;LENGTH OF DESIRED EXTENDED LOOKUP
	MOVEM	T1,RBCNTE
	MOVE	T1,[ERRPPN]	;GET PPN OF ERROR FILE
	MOVEM	T1,RBPPNE	;STORE DIRECTORY
	MOVEM	T1,SSELBK+7	;[602] IN IPCF MSG TOO
	MOVE	T1,[SIXBIT/ERROR/]
	TRNE	F,R.PAE		;DOING AVAIL.SYS?
	MOVE	T1,[SIXBIT/AVAIL/] ;YES, CHANGE NAME
	MOVEM	T1,RBNAME	;STORE FILNAM
	MOVEM	T1,SSELBK+5	;[602]IN IPCF PACKET TOO
	HRLZ	T1,ERREXT	;[62]GET CURRENT ERROR EXTENSION
	TRNE	F,R.PAE		;DOING AVAIL.SYS?
	MOVSI	T1,'SYS'	;YES, EXTENSION IS ALWAYS SYS
	MOVEM	T1,RBEXTE	;STORE EXT
	MOVEM	T1,SSELBK+6	;[602]IN IPCF TOO
	MOVSI	T1,(155B8)	;IF NOT FOUND, MAKE IT READ-ONLY
	MOVEM	T1,RBPRVE
	SETZM	RBSIZE		;IF LOOKUP FAILS, LEN IS ZERO
	MOVEI	T1,ERRBUF-1	;PREPARE IOWD
	HRRM	T1,ILIST	; FOR INPUT
	HRRM	T1,OLIST	; AND FOR OUTPUT
	MOVEI	T1,-200		;PUT WORD COUNT INTO OUTPUT
	HRLM	T1,OLIST	; IOWD FOR FULL BLOCK
	MOVEI	T1,-1		;MASK IN RIGHT HALF FOR ERROR CODE
	LOOKUP	FCT,EBLOCK	;DO EXTENDED LOOKUP
	  TDZN	T1,RBEXTE	;IF FILE NOT FOUND, MAKE ONE. ELSE BOMB
	ENTER	FCT,EBLOCK	;DO UPDATE
	  JRST	E.EEF		;WHAT?
	MOVE	T1,RBSIZE	;GET SIZE IN WORDS
	TRNE	F,R.PAE		;IF WE ARE DOING AVAIL.SYS AND
	CAIE	T1,BLKSIZ*AVLWRK ;THE SIZE IS THE LENGTH OF THE
	SKIPA			;WORKING ENTRY, JUST APPEND
	JRST	ERFIL5		;TO THE FILE
	SOJL	T1,ERFIL0	;DECR FOR LAST WORD
	ROT	T1,-B2WLSH	;COMPUTE LAST BLOCK
	MOVEI	T2,1(T1)	;START AT BLOCK 1
	MOVEM	T2,SSELBK+1	;[602]PUT LAST BLOCK NUMBER IN IPCF PACKET
	USETI	FCT,(T2)	;READ LAST BLOCK
	ROT	T1,B2WLSH	;RESTORE WORD COUNT
	ANDI	T1,BLKSIZ-1	;RELATIVE LAST WORD IN BLOCK
	INPUT	FCT,ILIST	;READ THE LAST BLOCK
	STATZ	FCT,IO.ERR	;OK?
	  JRST	E.INEF		;OOPS
;HERE TO CHECK FOR MESS-UPS IN ERROR.SYS

	MOVS	T3,ERRBUF(T1)	;PICK UP LAST WORD
	JUMPE	T3,ERBAK	;IF 0, BACK UP TO FIND GOOD ENTRY
	CAIN	T3,.ESEOF_9	;IS IT EOF?
	JRST	ERFILL		;YES, INSERT NEW ENTRY OVER IT
ERPHIA:	MOVSI	T3,.ESHIA_9	;MARK HIATUS
	MOVEM	T3,ERRBUF(T1)	;IN THE BUFFER
	USETO	FCT,(T2)	;WHEN WE MARK HAITUS,
	OUTPUT	FCT,OLIST	;WE USE NEW BLOCK
	STATZ	FCT,IO.ERR	;OK
	  JRST	E.OUEF		;NOPE!
	AOJA	T2,ERFIL3	;[534] AND GO PUT THIS ENTRY INTO NEXT BLOCK

ERBAK:	JUMPE	T1,ERPHIA	;STOP BACKING AT BEGINNING OF BUFFER
	SOJ	T1,		;ELSE BACK UP
	MOVS	T3,ERRBUF(T1)
	JUMPE	T3,ERBAK	;BACK UP AGAIN IF STILL 0
	CAIE	T3,.ESEOF_9	;IS THIS EOF ENTRY?
	AOJA	T1,ERPHIA	;NO, DO NOT OVERWRITE IT
	MOVEM	T1,SSELBK	;[602]SAVE WC FOR IPCF PACKET
	JRST	ERFILL		;YES, THIS IS OKAY;STORE ENTRY OVER IT

ERFIL0:	TRNE	F,R.PAE		;THINGS ARE VERY BAD IF AVAIL.SYS DOESN'T
	JRST	ERRFIX		;EXIST, SO GIVE UP NOW
	SKIPA	T2,[1]		;SO USETO WILL WRITE FIRST BLOCK
ERFIL5:	MOVEI	T2,AVLWRK+1	;APPEND TO WORKING ENTRY IN AVAIL.SYS
ERFIL3:	SETZM	ERRBUF		;[534] CLEAR FIRST WORD
	MOVE	T1,[ERRBUF,,ERRBUF+1]	;[534] SET UP TO CLEAR ANY JUNK
	BLT	T1,ERRBUF+177	;[534] BLITTTT!
	MOVE	T1,[.ESOFF_9,,1];[534] PUT POINTER TO FIRST ENTRY IN BLOCK
	MOVEM	T1,ERRBUF	;[534] INTO FIRST WORD OF BLOCK
ERFILL:	SUBI	P4,ERABFS-1		;CALCULATE WORDS STORED
	DPB	P4,[POINT 9,ERABUF,35]	;STORE LENGTH
	ADDI	P4,EL.HED(T1)		;TOTAL WORDS TO WRITE
	MOVEI	T1,ERRBUF(T1)	;TO LOCATION
	HRLI	T1,ERABUF	;FROM
	MOVEI	T3,ERRBUF-1(P4)		;GET LOCATION LAST WORD WILL GO INTO
	SUBI	T3,ERABUF-1		;SUBTRACT END OF BUFFER 
	JUMPGE	T3,ESPLIT	;IF T3 .GE. THEN ENTRY IS SPLIT ACROSS BLOCKS
ERFIL1:	BLT	T1,ERRBUF-1(P4)	;COPY INTO BUFFER
ERFIL2:	MOVSI	T1,.ESEOF_9	;MARK END OF FILE
	MOVEM	T1,ERRBUF(P4)	;AT LAST LOC
	USETO	FCT,(T2)	;SET TO WRITE LAST BLOCK
	OUTPUT	FCT,OLIST
	STATZ	FCT,IO.ERR	;OK?
	  JRST	E.OUEF		;BAD EGGS
	TRNE	F,R.PAE		;DOING AVAIL.SYS?
	JRST	ERFIL4		;YES, DON'T SEND ANOTHER MESSAGE
	MOVE	T1,ERABUF	;[602]GET HEADER WD 0
	MOVEM	T1,SSELBK+2	;[602]INTO THE IPCF PACKET
	MOVE	T1,ERABUF+1	;[602] GET HEADER WD 1
	MOVEM	T1,SSELBK+3	;[602] INTO IPCF PACKET
	PUSHJ	P,SNDSEL	;SEND PACKET TO SYSTEM ERROR LOGGER
	MOVEI	T1,^D10		;[62]REINITIALIZE NUMBER
	MOVEM	T1,IERCNT	;[62]OF ERROR RETRIES
	MOVEM	T1,NEWEXT	;[62]AND COUNT ON NEW EXTENSIONS IN ROW
ERFIL4:	PUSHJ	P,RELFCT	;RELEASE THE FCT CHANNEL
	TRZN	F,R.AVL		;WANT THIS ENTRY APPENDED TO AVAIL.SYS?
	JRST	ERRFIX		;NO, EXIT CLEARING ALL FLAGS
	MOVE	P4,SAVEP4	;RESTORE ORIGINAL VALUE OF P4
	PJRST	AVLFIN		;AND CALL OURSELVES


ESPLIT:	SUBI	P4,(T1)		;CONVERT P4 BACK TO JUST LENGTH
	ADDI	P4,ERRBUF	;...
ESPLI1:	BLT	T1,ERABUF-1	;BLT AS MUCH AS WILL FIT CURRENT BLOCK
	USETO	FCT,(T2)	;SET THE BLOCK
	OUTPUT	FCT,OLIST	;AND OUTPUT IT
	STATZ	FCT,IO.ERR	;OK
	  JRST	E.OUEF		;NOPE!
	AOS	T2		;STEP TO NEXT BLOCK
	SETZM	ERRBUF		;CLEAR OUT ERRBUF
	MOVE	T1,[ERRBUF,,ERRBUF+1]
	BLT	T1,ERABUF-1
	MOVEI	T1,1(T3)	;T3 IS NUMBER OF WORDS THAT DIDN'T FIT
	CAIL	T1,BLKSIZ	;ARE THERE STILL MORE THAN A BLOCKS WORTH
				; OF WORDS TO OUTPUT?
	MOVEI	T1,BLKSIZ	;POINT AT START OF NEXT BLOCK FOR SYSERR
	HRLI	T1,.ESOFF_9	;PUT CODE FOR FIRST WORD IN LH
	MOVEM	T1,ERRBUF	;SO +1 IS LOC OF NEXT ENTRY
	HRRZI	T1,ERABUF(P4)	;GET VERY LAST WORD TO TRANSFER
	SUBI	T1,(T3)		;AND SUBTRACT # WORDS NOT TRANSFERED
	HRLS	T1		;PUT IN LH OF AC FOR BLT
	HRRI	T1,ERRBUF+1	;AND GET LAST LOC TO TRANSFER TO
	JUMPN	T3,ESPLI2	;IF NON-ZERO, MORE TO DO
	HRRZI	P4,1(T3)	;AND SET UP P4 TO STOP BLT
	JRST	ERFIL2		;JUST WRITE LAST WORD
ESPLI2:	SUBI	T3,BLKSIZ-1	;SUBTRACT OUT WORDS FOR NEXT BLOCK
	JUMPGE	T3,ESPLI1	;IF T3 STILL GE ZERO, SPLIT AGAIN
	HRRZI	P4,200(T3)	;AND SET UP P4 TO STOP BLT
	JRST	ERFIL1		;AND GO OUTPUT REST OF ENTRY
;SUBROUTINE TO INITIALIZE FOR WRITING IN ERROR.SYS OR AVAIL.SYS
;ARGS	T1=FIRST (TYPE) WORD OF ENTRY
;VALUES	P4=IOWD ERRSIZ,ERABUF	SUITABLE FOR PUSH-ING
;	HEADER WORD SETUP (EXCEPT LENGTH)
;	DATE & TIME IN WORD 1
;	UPTIME IN WORD 2
;	CPU SERIAL NUMBER IN WORD 3
;RETURN	CPOPJ, T1-4 BLOWN

ERRINB:	TROA	F,R.NEB		;SET FLAG TO CALL BOOTCP
ERRINI:	TRZ	F,R.NEB		;CLEAR FLAG FOR CALL TO ERRINI
	TLO	F,L.ANY		;NOTE SOMETHING DONE
	SETZM	ERABUF		;CLEAR BUFFER
	MOVE	T2,[XWD ERABUF,ERABUF+1]
	BLT	T2,ERAEND	;CLEAR TO END
AVLINI:	HRR	T1,HEADR0	;[464]FORMAT VERS & HEADER LEN
	TLNE	F,L.DSK	;[551]ENTRY COMING FROM A CRASH FILE?
	 TLO	T1,EL.CRS	;[551]YES-SAY SO
	MOVEM	T1,ERABUF	;(0) HEADER TYPE IDENTIFIER
	PUSHJ	P,NBSDAT	;GET DATE AND TIME
	MOVEM	T1,ERABUF+1	;(1) DATE (LH) AND TIME (RH)
	PUSHJ	P,UPTIME	;COMPUTE UPTIME
	MOVEM	T1,ERABUF+2	;(2) UPTIME IN STD FORMAT
	TRNN	F,R.NEB		;WANT BOOT CPU SERIAL NUMBER?
	PUSHJ	P,CPUASN	;NO, GET CPU SERIAL NUMBER
	TRZE	F,R.NEB		;REVERSE SENSE OF TEST
	PUSHJ	P,BOOTCP	;AND GET BOOT CPU SERIAL NUMBER
	MOVEM	T1,ERABUF+3	;(3) CPU S/N [464]
	MOVE	P4,[IOWD ERRSIZ,ERABUF+EL.HED] ;SETUP FOR PUSHING
	POPJ	P,		;SO FAR SO GOOD
;ROUTINE TO COMPUTE UPTIME IN UNIVERSAL DATE/TIME FORMAT.
;ENTER AT UPTCNV IF HAVE UPTIME IN JIFFIES IN T1.

UPTIME:	PUSHJ	P,GETUPT	;GET THE UPTIME IN TICKS
UPTCNV:	SETZ	T2,
	ASHC	T1,-^D17	;JIFFIES*2**18 IN T2[7(55)]
	DIV	T1,JIFDAY	;DAYS IN LH, FRACTION IN RH
	POPJ	P,		;RETURN


;ROUTINE TO RETURN THE UPTIME IN TICKS IN T1.

GETUPT:	MOVE	T1,[%CNSUP]	;GETTAB ARG FOR SYSTEM UPTIME
	PUSHJ	P,GTBSPY	;GET IT
	  SKIPA	T1,[%NSUPT]	;SHOULDN'T FAIL, BUT TRY THIS ONE ANYWAY
	POPJ	P,		;RETURN
	PUSHJ	P,GTBSPY	;GET THE CPU0 UPTIME
	  MOVEI	T1,0		;CAN'T HAPPEN
	POPJ	P,		;RETURN


;ROUTINE TO RETURN THE CPU SERIAL NUMBER OF THE CPU ON WHICH AN ERROR
;WAS DETECTED.

CPUASN:	LDB	T1,[POINT 3,ERPTBK+2,17] ;GET CPU NUMBER FROM ERROR BLOCK
	LSH	T1,1		;TIMES 2
	ADD	T1,[%CCSER]	;SET TO READ CPU SERIAL NUMBER
	SKIPE	ERPTBK+2	;IS THIS AN OLD MONITOR?
	PUSHJ	P,GTBSPY	;NO, GET IT
	  CAIA			;FAILED, DO IT THE OLD WAY
	POPJ	P,		;RETURN WITH NUMBER IN T1
BOOTCP:	MOVE	T1,[%CNSER]	;GET SERIAL NUMBER OF BOOT CPU
	PUSHJ	P,GTBSPY	;GET IT
	  MOVEI	T1,0		;USE ZERO
	POPJ	P,		;RETURN
;NEW ROUTINES TO PROCESS I/O ERRORS ON ERROR.SYS

;HERE IF INIT FAILS
E.IEF:	TRNN	F,R.PAE		;DOING AVAIL.SYS?
	SETOM	IOERR		;SET FLAG SO WE STOP TRYING
	PUSHJ	P,RELFCT	;RELEASE FCT CHANNEL
ERRFIX:	TRZ	F,R.AVL!R.PAE	;CLEAR ALL FLAGS
	POPJ	P,		;AND RETURN

;HERE IF LOOKUP/ENTER ERROR
E.EEF:	CAIN	T1,-1		;LOOKUP HAS CODE IN T1
	TDZ	T1,RBEXTE	;ENTER HAD -1 IN T1, THIS GETS CODE
	XORI	T1,-1		;CODE WAS IN ONE'S COMPLEMENT
	CAIN	T1,ERTRN%	;BAD RIB OR UFD?
	JRST	NEREXT		;YES, TRY NEW FILE NOW
	CAIE	T1,ERFBM%	;FILE BEING MODIFIED?
	CAIN	T1,ERNRM%	;OR DISK FULL?
	JRST	ERRCLK		;YES, DO SOME RETRIES
	CAIE	T1,ERNET%	;NO MONITOR FREE CORE?
	CAIN	T1,ERSLE%	;OR EMPTY SEARCH LIST
	JRST ERRCLK		;YES, DO SOME RETRIES
	PJRST	E.IEF		;ALL OTHERS FATAL, TREAT LIKE INIT ERROR

;HERE ON INPUT/OUTPUT ERROR
E.INEF:
E.OUEF:	GETSTS	FCT,T1		;GET STATUS IN T1
	TRNE	T1,IO.BKT	;DISK FULL
	PJRST	ERRCLK		;YES,DO SOME RETRIES

;ROUTINE TO TRY NEW EXTENSIONS.INPUT/OUTPUT ERRORS FALL THROUGH
;EXCEPT IO.BKT
NEREXT:	TRNN	F,R.PAE		;DOING AVAIL.SYS?
	SOSG	NEWEXT		;HERE TOO MANY TIMES IN A ROW?
	PJRST	E.IEF		;YES, GIVE UP
	HRRZ	T1,ERREXT	;TRY NEW FILE. FIRST GET CURRENT EXT
	CAIN	T1,'SYS'	;IS IT SYS?
	MOVEI	T1,'X00'	;YES, SET UP X00
	ADDI	T1,1		;INCREMENT TO GET NEW EXTENSION
	TRNN	T1,7		;SHOULD WE CARRY TO SECOND DIGIT?
	ADDI	T1,100-10	;YES,CAUSE THE SIXBIT TO CARRY
	CAILE	T1,'X77'	;HAS THE EXTENSION OVERFLOWED?
	PJRST	E.IEF		;YES, FATAL
	HRRZM	T1,ERREXT	;GOOD NEW EXT., STORE IT
	PUSHJ	P,RELFCT	;RELEASE THE FCT CHANNEL
	PJRST	ERRFIN		;AND TRY THE NEW FILE

;ROUTINE FOR RETRIES ON SAME FILE. USES INTERNAL CLOCK REQUEST TO
;WAIT BETWEEN RETRIES. AFTER 10 RETRIES WITH NO LUCK,IT TRIES A NEW FILE
ERRCLK:	TRNN	F,R.PAE		;DOING AVAIL.SYS?
	SOSG	IERCNT		;DECREMENT COUNT OF RETRIES LEFT
	PJRST	NEREXT		;TOO MANY RETRIES, TRY NEW FILE
	SETOM	IOERR		;NO IO TO ERROR FILE UNTIL CLOCK EXPIRES
	PUSHJ	P,RELFCT	;RELEASE FCT CHANNEL
	PUSH	P,J		;SAVE J
	HRREI	J,IOERQ		;SET UP Q # FOR INTERNAL CLOCK REQUEST
	MOVEI	T1,ERRTIM	;SET UP TIME FOR CLOCK REQUEST
	PUSHJ	P,CLKREQ	;DO THE CLOCK REQUEST
	POP	P,J		;RESTORE J
	POPJ	P,		;RETURN

;SUBROUTINE TO INITIALIZE EXTENSION FOR ERROR FILE
;NO ARGS
;CHANGES ERREXT TO THE EXTENSION OF THE LAST ERROR FILE
; FOUND ON ERRDEV
;RETURNS CPOPJ, DESTROYS T1
ERRSTR:	INIT	FCT,.IODMP		;INIT A CHANNEL FOR LOOKUPS
	ERRDEV				;DESIRED DEVICE
	0
	  JRST	E.IEF			;CAN'T INIT ERRDEV
	MOVEI	T1,RBEXTE-RBCNTE	;LENGTH FOR EXTENDED LOOKUP
	MOVEM	T1,RBCNTE		;SAVE IN LOOKUP BLOCK
	MOVE	T1,[ERRPPN]		;SET UP DIRECTORY
	MOVEM	T1,RBPPNE		; FOR LOOKUP
	MOVE	T1,[SIXBIT/ERROR/]	;AND SET UP NAME
	MOVEM	T1,RBNAME		; FOR LOOKUP
	MOVEI	T1,'X01'		;START AT X01
ENAMLP:	HRLZM	T1,RBEXTE		;SAVE EXT FOR LOOKUP
	LOOKUP	FCT,EBLOCK		;LOOK UP THIS ONE
	  POPJ	P,			;ALL DONE WHEN A LOOKUP FAILS
	ADDI	T1,1			;INCREMENT EXTENSION
	TRNN	T1,7			;SHOULD WE CARRY TO SECOND DIGIT?
	ADDI	T1,100-10		;YES, CAUSE THE SIXBIT TO CARRY
	CAILE	T1,'X77'		;HAS THE EXTENSION OVERFLOWED?
	PJRST	E.IEF			;YES, GIVE UP
	JRST	ENAMLP			;NO, LOOK UP THIS ONE


;SUBROUTINE TO RETURN DATE AND TIME IN NBS FORMAT,
; DAYS SINCE NOV 17, 1858 IN LH, FRACTION OF DAY IN RH

FACTIM:
NBSDAT:	MOVE	T1,[%CNDTM]	;[562]  WAS %CNDAT
	PUSHJ	P,GTBSPY	;GET DATE IN UNIVERSAL FORMAT
	  SETZ	T1,		;[562] ???
	POPJ	P,		;[562] RETURN
;ROUTINE TO FLUSH ANY IPCF PACKETS IN DAEMON'S INPUT QUEUE CAUSED
;BY PREVIOUS SENDS THAT FAILED.  ALSO CLEARS BLOCK BEFORE RETURN.
;CALL:	PUSHJ	P,FLSPAK
;	RETURN
;DESTROYS T1,T2

FLSPAK:	MOVEI	T2,0		;START WITH ZERO FLAGS
FLSPA1:	PUSHJ	P,CLRIPC	;CLEAR RECEIVE BLOCK
	TLO	T2,(IP.CFB!IP.CFT) ;NON-BLOCKING AND TRUNCATE LENGTH
	MOVEM	T2,IPCPDB+.IPCFL ;STORE IN FLAGS WORD
	MOVEI	T1,SSELBK	;LEN=0,,ADDRESS OF MESSAGE BLOCK
	MOVEM	T1,IPCPDB+.IPCFP ;STORE IN BLOCK
	MOVE	T1,[4,,IPCPDB]	;GET LEN,,ADDR OF BLOCK
	IPCFR.	T1,		;GET ANY PACKETS
	  JRST	[CAIE	T1,IPCPR%	;PAGE MODE?
		 PJRST	CLRIPC		;NO, CLEAR IPCF BLOCK AND RETURN
		 MOVEI	T2,IP.CFV	;GET PAGE MODE FLAG
		 JRST	FLSPA1]		;TRY IT THIS WAY
	JRST	FLSPAK		;GET ANY REMAINING PACKETS


;ROUTINE TO CLEAR THE IPCF MESSAGE AREA.
;CALL:	PUSHJ	P,CLRIPC
;	RETURN
;DESTROYS T1

CLRIPC:	MOVE	T1,[IPCPDB,,IPCPDB+1] ;SETUP FOR BLT
	SETZM	IPCPDB+.IPCFL	;CLR FIRST WD
	BLT	T1,SSELBK+7	;CLEAR THE REST
	POPJ	P,0		;RETURN


;ROUTINE TO SEND A MESSAGE TO THE ON-LINE SYSTEM ERROR LOGGER TO
;TELL IT THAT AN ERROR HAS OCCURRED.  CALL WITH DATA TO SEND IN SSELBK.
;CALL:	PUSHJ	P,SNDSEL
;	RETURN
;DESTROYS T1

SNDSEL:	MOVEI	T1,001001	;MSG TYPE,FORMAT
	HRLM	T1,SSELBK	;INTO THE MSG
	PUSHJ	P,FNDSEL	;FIND SEL
	  POPJ	P,		;NOT THERE, GIVE UP
;;	PJRST	SNDPAK		;AND SEND HIM A PRESENT
;ROUTINE TO SEND A MESSAGE TO ANOTHER PROCESS.
;CALL:	MOVEI	T1,PID OF RECEIVER
;	PUSHJ	P,SNDPAK
;	RETURN
;DESTROYS T1

SNDPAK:	MOVEM	T1,IPCPDB+.IPCFR ;SAVE RECEIVER'S PID
	MOVE	T1,[^D8,,SSELBK] ;GET POINTER TO MESSAGE
	MOVEM	T1,IPCPDB+.IPCFP;INTO THE PDB
	MOVE	T1,[6,,IPCPDB]	;GET LEN,,ADDR OF BLOCK
	IPCFS.	T1,		;SEND THE MSG
	 JFCL			;DON'T CARE ABOUT ERRORS
	POPJ	P,0		;RETURN


;ROUTINE TO FIND THE PID OF A SYSTEM PROCESS.  ENTER AT FNDSEL TO
;FIND THE SYSTEM ERROR LOGGER PID,  FNDACT TO FIND THE ACCOUNTING
;PID.
;CALL:	PUSHJ	P,FNDXXX
;	  NOT THERE
;	RETURN WITH T1=PID

FNDACT:	SKIPA	T1,ACTPTR	;SETUP TO GET [SYSTEM]ACCOUNTING PID
FNDSEL:	MOVE	T1,SELPTR	;SET UP TO GET SEL'S PID
	PUSHJ	P,GTBSPY	; GET IT
	  POPJ	P,		;NOT THERE, GIVE ERROR
	SKIPE	T1		;GET BACK ONE?
CPOPJ1:	AOS	(P)		;YES RETURN +1
CPOPJ:	POPJ	P,0		;NO RETURN NORMALLY
SUBTTL	AVAIL.SYS UPDATE ROUTINE

;ROUTINE TO UPDATE THE WORKING ENTRY IN AVAIL.SYS.

UPDAVL:	PUSHJ	P,SAVE4		;SAVE P1-P4
	MOVE	T1,[MRVBLK,,ERABUF] ;MAKE BLT POINTER
	BLT	T1,ERAEND	;MOVE THE ENTRY TO THE BUFFER
	LDB	P2,[POINT 9,ERABUF,35] ;GET LEN OF BODY FOR LATER
	MOVSI	T1,FCT+<(FO.PRV)> ;CHANNEL IS FCT
	HRRI	T1,.FOSAU	;FUNCTION IS SINGLE ACCESS UPDATE
	MOVEM	T1,D.FLOP+.FOFNC;STORE IN BLOCK
	MOVEI	T1,.IODMP	;USE DUMP MODE
	MOVEM	T1,D.FLOP+.FOIOS
	MOVE	T1,[ERRDEV]	;DEVICE IS ERRDEV
	MOVEM	T1,D.FLOP+.FODEV
	SETZM	D.FLOP+.FOBRH	;NO BUFFERS
	SETZM	D.FLOP+.FONBF	;AND NO BUFFER COUNT
	MOVEI	T1,D.LKB	;POINT AT LOOKUP BLOCK
	MOVEM	T1,D.FLOP+.FOLEB
	SETZM	D.LKB		;CLEAR FIRST WORD OF LOOKUP BLOCK
	MOVE	T1,[D.LKB,,D.LKB+1] ;MAKE BLT POINTER
	BLT	T1,D.LKB+.RBSIZ ;CLEAR ENTIRE BLOCK
	MOVE	T1,[SIXBIT/AVAIL/] ;FILENAME IS AVAIL
	MOVEM	T1,D.LKB+.RBNAM
	MOVSI	T1,'SYS'	;EXTENSION IS SYS
	MOVEM	T1,D.LKB+.RBEXT
	MOVSI	T1,155000	;MAKE PROTECTION 155
	MOVEM	T1,D.LKB+.RBPRV
	MOVEI	T1,.RBSIZ	;COUNT IS .RBSIZ
	MOVEM	T1,D.LKB+.RBCNT
	MOVEI	P1,5		;NUMBER OF TIMES TO RETRY ON ERFBM%
UPDAV1:	MOVE	T1,[ERRPPN]	;GET PPN INTO WHICH TO WRITE FILE
	MOVEM	T1,D.LKB+.RBPPN ;STORE IN BLOCK
	HLLZS	D.LKB+.RBEXT	;CLEAR ANY ERROR CODE
	MOVE	T1,[.FOLEB+1,,D.FLOP] ;POINT TO FILOP. BLOCK
	FILOP.	T1,		;OPEN THE FILE
	  JRST	[PUSHJ	P,FBMTRY ;CHECK FOR ERFBM%
		   JRST	UPDAV1	;IS, RETRY
		 POPJ	P,]	;NOT, GIVE UP
	MOVNI	T1,EL.HED(P2)	;GET -VE LENGTH OF BODY PLUS HEADER
	HRLI	T1,ERABUF-1	;MAKE SWAPPED IOWD
	MOVSS	T1		;MAKE IT RIGHT
	MOVEI	T2,0		;MAKE IOWD TERMINATE ON A ZERO
	OUTPUT	FCT,T1		;WRITE THE WORKING ENTRY
	STATZ	FCT,IO.ERR	;ANY ERRORS?
	JRST	RELFCT		;YES, RELEASE CHANNEL AND QUIT
	ADDI	P2,EL.HED+BLKSIZ-1 ;ROUND UP TO A BLOCK BOUNDARY
	LSH	P2,-B2WLSH	;COMPUTE NUMBER BLOCKS WRITTEN
	SUBI	P2,AVLWRK	;COMPUTE -NUMBER BLOCKS LEFT IN AVLWRK
	SETZM	ERABUF		;CLEAR FIRST WORD OF BLOCK
	MOVE	T3,[ERABUF,,ERABUF+1] ;MAKE BLT POINTER
	BLT	T3,ERABUF+BLKSIZ-1 ;CLEAR ENTIRE BLOCK
	HRLI	T1,-BLKSIZ	;SETUP IOWD TO ZERO FILL BLOCK
UPDAV2:	AOJG	P2,RELFCT	;LOOP UNTIL ALL AVLWRK BLOCKS ARE
	OUTPUT	FCT,T1		;  ZERO FILLED
	STATO	FCT,IO.ERR	;ANY ERRORS?
	JRST	UPDAV2		;NO, LOOP
	PJRST	RELFCT		;RELEASE CHANNEL AND RETURN
;ROUTINE TO SEE IF THE AGE OF AVAIL.SYS IS GREATER THAN 7 DAYS
;AND RENAME IT TO AVAIL.ANN IF IT IS.
;RETURNS CPOPJ ALWAYS WITH DISK COPY UPDATED IF LESS THAN 7 DAYS
;	 AND NEW FILE CREATED IF OLDER THAN 7 DAYS

AVLAGE:	PUSHJ	P,NBSDAT	;GET CURRENT UNIVERSAL DATE/TIME
	SUB	T1,MRVBLK+AWECDA ;SUBTRACT CREATION DATE OF THIS AVAIL
	HLRZS	T1		;KEEP JUST DIFFERENCE IN DAYS
	CAIGE	T1,7		;OLDER THAN A WEEK?
	JRST	[PUSHJ	P,MRVSCN ;NO, UPDATE CORE COPY OF MRV ENTRY
		 PJRST	UPDAVL]	 ;AND UPDATE FILE COPY OF WORKING ENTRY
	PUSHJ	P,SAVE1		;GET A REGISTER TO USE
	PUSHJ	P,ENDAVL	;APPEND .ESEAV ENTRY TO FILE
	MOVEI	P1,'A01'	;FIRST EXTENSION TO TRY IS A01
AVLAG1:	MOVE	T1,[SIXBIT/AVAIL/] ;FILENAME IS AVAIL
	MOVEI	T4,(P1)		;EXTENSION IS XNN
	PUSHJ	P,OPNFIE	;TRY TO LOOKUP THE FILE
	  TRNE	T2,-1		;ERROR CODE MUST BE FILE NOT FOUND
	SKIPA			;TRY NEXT EXTENSION
	JRST	AVLAG2		;FOUND ONE, RENAME TO THAT
	ADDI	P1,1		;BUMP EXTENSION BY 1
	TRNN	P1,7		;NEED TO CARRY INTO THE 10S DIGIT?
	ADDI	P1,100-10	;YES, CARRY
	CAILE	P1,'A77'	;TRIED THEM ALL?
	PJRST	RELFCT		;YES, RELEASE CHANNEL AND GIVE UP
	JRST	AVLAG1		;LOOP FOR NEXT
AVLAG2:	MOVE	T1,[SIXBIT/AVAIL/] ;FILENAME IS AVAIL
	PUSHJ	P,OPNFIL	;LOOKUP AVAIL.SYS
	  PJRST	RELFCT		;NOT THERE?
	HRLI	T2,(P1)		;GET EXTENSION WE FOUND
	RENAME	FCT,T1		;RENAME THE FILE
	  PJRST	RELFCT		;FAILED, GIVE UP
	PJRST	REDNAV		;CREATE NEW FILE AND RETURN


;ROUTINES TO APPEND BEGINNING/END OF AVAIL.SYS TIMESTAMPS.
;RETURNS CPOPJ ALWAY

BEGAVL:	SKIPA	T1,[.ESBAV_9,,0] ;GET CODE FOR BEGINNING OF AVAIL.SYS
ENDAVL:	MOVSI	T1,.ESEAV_9	;DITTO FOR END OF AVAIL.SYS
	PUSH	P,P4		;SAVE P4
	PUSHJ	P,ERRINI	;SETUP BUFFER, P4
	PUSH	P4,.JBVER	;BODY CONTAINS DAEMON VERSION #
	PUSHJ	P,AVLFIN	;APPEND ENTRY TO FILE
	POP	P,P4		;RESTORE P4
	POPJ	P,		;RETURN
;ROUTINE TO BUILD A NEW CORE COPY OF THE AVAIL.SYS WORKING ENTRY.
;RETURNS CPOPJ ALWAYS

MRVNEW:	MOVSI	T1,.ESMRV_9	;GET ENTRY CODE
	HRR	T1,HEADR0	;HEADER INFO TO RH
	MOVEM	T1,MRVBLK+AWEHDR ;SAVE IN BLOCK
	SETZM	MRVBLK+AWECDM	;FORCE APPEND OF MAXCNF BY CLEARING DATE
	PUSHJ	P,NBSDAT	;GET CURRENT UNIVERSAL DATE/TIME
	HLRZS	T1		;KEEP ONLY DATE
	MOVEI	T2,-4(T1)	;MOVE TO T2 AND SHIFT SO THAT THE
				;IDIVI GIVES 0=SUNDAY, 1=MONDAY, ETC.
	IDIVI	T2,7		;DIVIDE BY DAYS/WEEK.  REMDR=DAY IN WEEK
	SUBI	T1,(T3)		;COMPUTE DATE OF PREVIOUS SUNDAY
	HRLZM	T1,MRVBLK+AWECDA ;MAKE CREATION DATE BE SUNDAY AT 00:00
	PUSHJ	P,MRVSCN	;BUILD NEW BODY
	MOVE	T1,MONVER	;GET CURRENT MONITOR VERSION
	MOVEM	T1,MRVBDY+MRVVER ;SAVE IN BLOCK
	SETZM	MRVBDY+MRVIDT	;START WITH NO DATE/TIME INCREMENT
	PJRST	SYSNAM		;GET NEW SYSTEM NAME AND RETURN

;ROUTINE TO UPDATE THE CORE COPY OF THE AVAIL.SYS WORKING ENTRY.
;RETURNS CPOPJ ALWAYS.

MRVSCN:	PUSH	P,P4		;SAVE CALLER'S P4
	MOVE	P4,[IOWD ERRSIZ,MRVBDY]	;SETUP BUFFER POINTER
	AOBJN	P4,.+1		;(R0) AOBJN POINTER TO SYSTEM NAME
	AOBJN	P4,.+1		;(R1) MONITOR VERSION NUMBER
	PUSHJ	P,UPTIME	;GET MONITOR UPTIME
	PUSH	P4,T1		;(R2) MONITOR UPTIME (UNIV DATE/TIME)
	PUSHJ	P,NBSDAT	;GET CURRENT UNIVERSAL DATE/TIME
	MOVEM	T1,MRVBLK+AWEDAT ;SAVE IN BLOCK
	PUSH	P4,T1		;(R3) MONITOR CRASH TIME (+/- 6 MIN)
	AOBJN	P4,.+1		;(R4) MONITOR RELOAD TIME
	AOBJN	P4,.+1		;(R5) SIXBIT WHY RELOAD CODE
	AOBJN	P4,.+1		;(R6) SUM OF INCREMENTAL DATE/TIME CHANGES
	ADD	P4,[5,,5]	;(R7-R13) ASCIZ MONITOR NAME
	SUBI	P4,MRVBDY-1	;COMPUTE LENGTH OF BODY
	DPB	P4,[POINT 9,MRVBLK,35] ;SAVE IN HEADER
	POP	P,P4		;RESTORE P4
	POPJ	P,		;AND RETURN
;ROUTINE TO READ THE WORKING ENTRY FROM AVAIL.SYS INTO CORE WHEN
;DAEMON STARTS UP.  IF AVAIL.SYS DOESN'T EXIST OR THE WORKING
;ENTRY IS BAD FOR SOME REASON, A NEW ENTRY IS BUILT.

REDAVL:	SETZM	MRVBLK		;CLEAR FIRST WORD OF BLOCK
	MOVE	T1,[MRVBLK,,MRVBLK+1] ;MAKE BLT POINTER
	BLT	T1,MRVEND	;CLEAR ENTIRE BLOCK
	MOVE	T1,[SIXBIT/AVAIL/] ;FILENAME IS AVAIL
	PUSHJ	P,OPNFIL	;OPEN THE FILE
	  JRST	REDNAV		;BUILD NEW ENTRY
	HLRES	T4		;GET 36 BIT NEGATIVE SIZE OF FILE
	MOVNS	T4		;MAKE IT POSITIVE
	CAIGE	T4,AVLWRK*BLKSIZ ;BETTER BE AT LEAST THIS LONG
	JRST	REDNAV		;MUST BE BAD
	MOVSI	T1,-<ERRSIZ+EL.HED> ;ONLY NEED THIS MANY WORDS
	HRRI	T1,MRVBLK-1	;MAKE AN IOWD
	MOVEI	T2,0		;TERMINATE LIST WITH A ZERO
	INPUT	FCT,T1		;READ THE OLD ENTRY
	STATZ	FCT,IO.ERR!IO.EOF ;ANY ERRORS?
	JRST	REDNAV		;YES, REBUILD IT
	LDB	T1,[POINT 9,MRVBLK,8] ;GET ENTRY CODE
	CAIN	T1,.ESMRV	;HAS TO BE THE RIGHT ONE
	PJRST	RELFCT		;RELEASE CHANNEL AND RETURN

;HERE IF WE HAVE TO BUILD A NEW FILE FOR SOME REASON

REDNAV:	PUSHJ	P,RELFCT	;RELEASE CHANNEL
	PUSHJ	P,MRVNEW	;BUILD NEW ENTRY ON ERRORS
	PUSHJ	P,UPDAVL	;UPDATE WORKING ENTRY IN FILE
	PUSHJ	P,BEGAVL	;TIMESTAMP BEGINNING OF FILE
IFN FTMCNF,<
	PUSHJ	P,APPCNF	;APPEND MAXCNF ENTRY
>
	POPJ	P,		;RETURN


;ROUTINE TO UPDATE THE SYSTEM NAME IN THE AVAIL.SYS WORKING
;ENTRY IN CORE.

SYSNAM:	MOVE	T2,[-5,,MRVSNM] ;GET AOBJN POINTER TO SYSTEM NAME
	MOVEM	T2,MRVBDY+MRVPSN ;SAVE AS POINTER TO NAME IN BLOCK
	MOVS	T3,[%CNFG0]	;GETTAB POINTER TO FIRST WORD OF NAME
SYSNA1:	MOVS	T1,T3		;GET CURRENT WORD POINTER
	PUSHJ	P,GTBSPY	;GET THE WORD
	  MOVEI	T1,0		;UNLIKELY
	MOVEM	T1,MRVBDY(T2)	;SAVE IN BLOCK
	ADDI	T3,1		;BUMP GETTAB ITEM NUMBER
	AOBJN	T2,SYSNA1	;LOOP FOR ALL 5 WORDS
	POPJ	P,		;RETURN
IFN FTMCNF,<
;ROUTINE TO APPEND THE MAX CONFIGURATION ENTRY FROM MAXCNF.SYS TO
;AVAIL.SYS IF IT HAS CHANGED.
;RETURNS CPOPJ ALWAYS

APPCNF:	MOVE	T1,[SIXBIT/MAXCNF/] ;FILENAME IS MAXCNF
	PUSHJ	P,OPNFIL	;OPEN THE FILE, RETURN LOOKUP BLK IN T1-T4
	  PJRST	RELFCT		;FILE NOT THERE
	LDB	T1,[POINT 3,T2,20] ;GET HIGH 3 BITS OF CREATION DATE
	LSH	T1,^D12		;MAKE ROOM FOR OTHER 12
	LDB	T2,[POINT 12,T3,35] ;GET OTHER 12
	IORI	T1,(T2)		;OR TOGETHER
	LDB	T2,[POINT 11,T3,23] ;GET CREATION TIME
	HRLI	T2,(T1)		;MAKE IT DATE,,TIME
	CAMN	T2,MRVBLK+AWECDM ;SAME AS THE LAST TIME?
	PJRST	RELFCT		;YES, RELEASE CHANNEL AND RETURN
	MOVEM	T2,MRVBLK+AWECDM ;SAVE FOR NEXT CHECK
	SKIPL	T1,T4		;INSURE THAT SIZE OF FILE IS OK
	PJRST	RELFCT		;EITHER ZERO OR HUGE, FORGET IT
	HLRES	T4		;GET 36 BIT NEGATIVE SIZE
	MOVNS	T4		;MAKE IT POSITIVE
	CAILE	T4,EL.HED+ERRSIZ ;TOO BIG FOR OUR BUFFER?
	PJRST	RELFCT		;YES, MUST BE BAD
	HRRI	T1,ERABUF-1	;MAKE IOWD TO OUR BUFFER
	MOVEI	T2,0		;TERMINATE IOWD LIST WITH ZERO
	INPUT	FCT,T1		;READ IN THE FILE
	STATZ	FCT,IO.ERR!IO.EOF ;GET IT OK?
	PJRST	RELFCT		;NO, RELEASE CHANNEL AND RETURN
	LDB	T1,[POINT 9,ERABUF,8] ;GET ENTRY CODE
	LDB	P4,[POINT 9,ERABUF,35] ;GET LENGTH OF BODY
	CAIN	T1,.ESCFG	;ENTRY CODE BETTER BE THIS
	CAIE	P4,-EL.HED(T4)	;AND FILE SIZE BETTER MATCH BODY LEN
	PJRST	RELFCT		;MUST BE BAD
	PUSH	P,P4		;SAVE LENGTH OF BODY AROUND CALLS
	PUSHJ	P,RELFCT	;RELEASE THE CHANNEL
	MOVSI	T1,.ESCFG_9	;SETUP HEADER CODE FOR MAXCNF
	PUSHJ	P,AVLINI	;BUILD ENTRY HEADER
	POP	P,P4		;RESTORE LEN OF BODY
	ADDI	P4,ERABFS-1	;REVERSE CALCULATION AT ERFILL
	PJRST	AVLFIN		;APPEND MAXCNF ENTRY TO AVAIL AND RETURN
>;END IFN FTMCNF
;ROUTINE TO LOOKUP ERRDEV:??????.SYS ON CHANNEL FCT.
;CALL WITH T1=FILENAME
;RETURNS CPOPJ IF OPEN OR LOOKUP FAILED,
;	 CPOPJ1 WITH CHANNEL OPEN AND LOOKUP BLOCK IN T1-T4

OPNFIL:	MOVEI	T4,'SYS'	;EXTENSION IS SYS
OPNFIE:	PUSH	P,T1		;SAVE FILENAME
	MOVEI	T1,.IODMP	;USE DUMP MODE
	MOVE	T2,[ERRDEV]	;DEVICE IS ERRDEV
	MOVEI	T3,0		;NO BUFFERS
	OPEN	FCT,T1		;OPEN THE CHANNEL
	  JRST	TPOPJ		;CAN'T, GIVE ERROR RETURN
	POP	P,T1		;RESTORE FILENAME
	MOVSI	T2,(T4)		;SETUP EXTENSION
	MOVEI	T3,0		;NO PROTECTION
	MOVE	T4,[ERRPPN]	;GET PPN
	LOOKUP	FCT,T1		;LOOKUP THE FILE
	  POPJ	P,		;NOT THERE, RETURN
	JRST	CPOPJ1		;GIVE SKIP RETURN


;ROUTINE TO ALLOCATE A BLOCK OF CORE.
;ARGS	T2=NUMBER OF WORDS TO ALLOCATE
;RETURNS CPOPJ IF CAN'T GET THE CORE
;	 CPOPJ1 WITH CORE ZEROED AND T2=ADDRESS OF FIRST WORD

GETCOR:	PUSH	P,.JBFF		;SAVE CURRENT VALUE OF .JBFF
	ADDB	T2,.JBFF	;COMPUTE NEW .JBFF
	CAMG	T2,.JBREL	;HAVE THAT MUCH?
	JRST	GETCO1		;YES
	CORE	T2,		;GET ANOTHER PAGE
	  JRST	[POP	P,.JBFF	;CAN'T, RESTORE ORIGINAL .JBFF
		 POPJ	P,]	;AND RETURN
GETCO1:	SETZM	@0(P)		;ZERO FIRST WORD OF CORE
	HRRZ	T2,(P)		;GET ADDRESS OF FIRST WORD
	HRLI	T2,1(T2)	;MAKE SWAPPED BLT POINTER
	MOVSS	T2		;MAKE IT ADDR,,ADDR+1
	BLT	T2,@.JBFF	;CLEAR THROUGH NEW .JBFF
	POP	P,T2		;RETURN ADDRESS OF FIRST WORD
	JRST	CPOPJ1		;GIVE GOOD RETURN
SUBTTL	ROUTINE TO WRITE CHKPNT INFO INTO FACT FILE

IFN FTCHKPNT,<
CHECK:
	PUSHJ	P,SAVE4		;SAVE THE ACS
	MOVE	P4,FACTSZ	;CURRENT SIZE OF BUFFER CONTENTS
	MOVN	J,HJOB		;HIGHEST JOB # IN SYS
	HRLZS	J
	HRRI	J,1		;START WITH JOB 1 (0 IS NULL)
CHKLUP:	HRROI	T1,.GTSTS	;JOB'S STATUS
	PUSHJ	P,GTBSPY
	  JRST	CHKEND		;NO MORE JOBS
	TLNN	T1,JLOG		;IS THIS JOB LOGGED IN?
	JRST	CHKNXT		;NO, LOOK AT NEXT
	PUSHJ	P,BUFAGE	;ENABLE BUFFER DUMP WHEN IT GETS TOO OLD
	MOVE	T1,[201000,,10] ;FIRST WORD, NEW TYPE[7(57)]
	MOVEM	T1,FACTBF(P4)	;(0) CONTROL WORD WITH LENGTH
	DPB	J,[POINT 9,FACTBF(P4),17] ;(0) JOB NUMBER
	PUSHJ	P,GETTTY	;GET JOB'S TTY NUMBER
	  MOVNI	T1,2		;DETACHED-MARK SO
	DPB	T1,[POINT 12,FACTBF(P4),29]	;(0) LINE NUMBER

;STILL IN FTCHKPNT CONDITIONAL
;HERE TO FILL IN REST OF ENTRY

	HRROI	T1,.GTPPN	; JBTPPN
	PUSHJ	P,GTBSPY	;GET THE DATA
	  JRST	CHKEND		;END OF TABLE
	MOVEM	T1,FACTBF+1(P4)	;(1) PPN
	PUSHJ	P,FACTIM	;GET TIME AND DATE
	MOVEM	T1,FACTBF+2(P4)	;(2) DATE AND TIME
	HRROI	T1,.GTTIM	;RUNTIME
	PUSHJ	P,GTBSPY	;GO GET IT
	  SETZ	T1,		;MAYBE THERE'S NO SUCH TABLE
	IMULI	T1,^D1000	;AVOID MILJIF FOR PRECISION
	IDIV	T1,JIFSEC	;CONVERT TO MILLISECONDS
	MOVEM	T1,FACTBF+3(P4)	;(3) RUN TIME
	HRROI	T1,.GTKCT	;KILLO-CORE-TICKS
	PUSHJ	P,GTBSPY	;GO READ THEM
	  SETZ	T1,		;NO TABLE, MAYBE?
	IMULI	T1,^D100		;CONVERT JIFFIES TO 1/100THS[7(57)]
	IDIV	T1,JIFSEC	;[7(57)]
	MOVEM	T1,FACTBF+4(P4)	;(4) KCT
	HRROI	T1,.GTRCT	;READ COUNT
	PUSHJ	P,GTBSPY	;GET OUT OF MONITOR
	  SETZ	T1,
	TLZ	T1,777700	;CLEAR OUT JUNK BITS
	MOVEM	T1,FACTBF+5(P4)	;(5) DISK READS
	HRROI	T1,.GTWCT	;WRITE COUNT
	PUSHJ	P,GTBSPY	;GET FROM MONITOR
	  SETZ	T1,
	TLZ	T1,777700	;CLEAR INCR. BITS
	MOVEM	T1,FACTBF+6(P4)	;(6) DISK WRITES
	HRROI	T1,.GTPRG	;NAME TABLE
	PUSHJ	P,GTBSPY	;GET BY SPYING
	  SETZ	T1,
	MOVEM	T1,FACTBF+7(P4)	;(7) PROGRAM NAME
	ADDI	P4,10		;UPDATE SIZE TO NOTE 10 WORDS STORED
	CAIGE	P4,MAXFCT	;HAVE WE FILLED THE BUFFER?
	JRST	CHKNXT		;NO, LOOK FOR NEXT JOB
	HRLZI	P1,(P4)		;YES, GET LEN IN P1 LEFT
	HRRI	P1,FACTBF	;AND ADDRESS IN P1 RIGHT
	PUSHJ	P,APPEND	;UPDATE FILE
	SETZ	P4,		;NOTE BUFFER EMPTY
CHKNXT:	AOBJN	J,CHKLUP	;LOOP FOR MORE JOBS
CHKEND:	SKIPE	P4		;[753] ANYTHING IN OUTPUT BUFFER?
	TLO	F,L.FORC	;[753] FORCE A FACT.SYS UPDATE ON NEXT PASS
	MOVEM	P4,FACTSZ	;RESTORE SIZE OF FACT THINGS
	MOVEI	T1,CHKTIM	;SETUP TIME FOR NEXT CHECKPOINT
	HRREI	J,CHKRQ		;DUMMY JOB NO FOR CHKPNT
	PJRST	CLKREQ		;MAKE THE CLOCK REQUEST AND QUIT

>;END FTCHKPNT CONDITIONAL
SUBTTL FACT FILE UPDATE ROUTINE

IFN FTFACT!FTCHKPNT,<
;SUBROUTINE TO APPEND AN ENTRY TO A FILE IN THE ACCOUNTING SYSTEM.
; THIS ROUTINE FIRST ATTEMPTS TO APPEND TO THE FILE NAMED FACT.SYS, BUT IF THIS FILE
; IS UNAVAILABLE, THEN FILES NAMED FACT.X01, FACT.X02,..., FACT.X77 WILL BE ATTEMPTED
;
;CALLING SEQUENCE:
;		MOVE P1,[XWD SIZE,ADDRESS] ;POINTER TO ENTRY TO BE APPENDED.
;		PUSHJ P,APPEND
;		RETURNS HERE IN ANY EVENT. BLOWING P1 AND P2, T1-4
;		GUARANTEE 200 WORDS FREE ABOVE ENTRY
;
APPEND:	HLRZ	P2,P1		;CONVERT P1 TO
	MOVNI	P2,(P2)		; AN AOBJN POINTER
	HRL	P1,P2		; ..
	PUSH	P,P1		;SAVE P1
	MOVEI	T2,(SIXBIT /SYS/)	;TRY FACT.SYS FIRST.
APPLUP:	PUSH	P,T2		;SAVE LAST EXTENSION TRIED.
APPLP1:	MOVSS	T2		;SET UP ACCUMULATORS FOR THE APPNDF
	MOVE	P1,-1(P)	; SUBROUTINE (WHICH DOES THE ACTUAL APPEND).
	PUSHJ	P,APPNDF	;TRY TO APPEND ENTRY TO TRANSACTION FILE.
	  JRST	APPERR		;ERROR ON THAT TRANSACTION FILE--TRY NEXT.
	 JRST	APPBZY		;TRANSACTION FILE BUSY--TRY ANOTHER.
	POP	P,T2		;NORMAL EXIT--FILE SUCCESSFULLY UPDATED.
APPXIT:	POP	P,P1		;RESTORE STACK AND P1

	SETZM	FACTSZ
	POPJ	P,		;*** SUBROUTINE EXIT. ***

APPERR:	POP	P,T2		;NON-RECOVERABLE ERROR--TRY NEXT FILE.
	CAIN	T2,(SIXBIT /SYS/)	;WAS .SYS THE LAST EXTENSION ATTEMPTED?
	MOVEI	T2,(SIXBIT /X00/)	;YES, TRY .X01 NEXT.
APPERB:	CAIN	T2,(SIXBIT /X77/)	;NO, TRIED ALL 64 POSSIBLE FILES ?
	JRST	APPXIT		;YES, GIVE UP.
	ADDI	T2,1		;NO, TRY NEXT FILE IN SEQUENCE.
	TRNN	T2,7		;CARRY INTO SECOND DIGIT ?
	ADDI	T2,100-10	;YES, CAUSE SIXBIT CARRY.
	JRST	APPLUP		;TRY AGAIN.

APPBZY:	POP	P,T2		;SPECIFIED FILE WAS BUSY--GET ITS EXTENSION.
	CAIE	T2,(SIXBIT /SYS/)	;WAS IT .SYS ?
	JRST	APPERB		;NO, GO TRY NEXT FILE IN SEQUENCE.
	PUSH	P,[SIXBIT /   X00/]	;TRY .SYS TWICE JUST TO BE SURE.
	JRST	APPLP1

;STILL IN FTFACT!FTCHKPNT CONDITIONAL
;SUBROUTINE TO APPEND A TRANSACTION ENTRY TO THE END OF THE ACCOUNTING FILE
; (NORMALLY, THIS IS THE FILE NAMED FACT.SYS, BUT THE EXTENSION IS A PARAMETER
; SUPPLIED TO THIS SUBROUTINE SO THAT IF FACT.SYS BECOMES FOULED UP, AN ENTRY
; MAY BE APPENDED TO AN ALTERNATE FACT.XXX FILE.)

;CALLING SEQUENCE:
;	MOVSI T2,(SIXBIT /EXT/)   ;DESIRED EXTENSION FOR FACT FILE (NORMALLY .SYS)
;	MOVE P1,[XWD  -SIZE,ADDRESS]	;POINTER TO ENTRY TO BE APPENDED
;	PUSHJ P,APPNDF
;	NON-RECOVERABLE ERROR RETURN -- CAN'T APPEND TO FILE.
;	BUSY ERROR RETURN -- FILE HAS BEEN BUSY EVERY SECOND FOR TEN SECONDS.
;	NORMAL RETURN -- ENTRY HAS BEEN SUCCESSFULLY APPENDED TO THE FILE.

APPNDF:	MOVE	T1,[XWD APPBLK,EBLOCK]
	BLT	T1,RBNAME	;MOVE COUNT,PPN, & NAME INTO EBLOCK
	MOVEM	T2,RBEXTE	;SAVE REQUESTED EXTENSION FOR FILENAME FACT
	MOVSI	T1,(177B8)	;SETUP PROTECTION
	MOVEM	T1,RBPRVE	;[7(56)]
	SETZM	RBSIZE		;AND FILE SIZE
	MOVEI	P2,^D10
	MOVEM	P2,TRYCTR	;SET NUMBER OF TIMES TO TRY IF BUSY.
	INIT	FCT,.IODMP	;OPEN SOFTWARE I/O CHANNEL FOR FACT FILE
	FCTDEV			; IN DUMP MODE
	0
	  JSP	P2,APPNDR	;IMMEDIATE ERROR RETURN IF CAN'T GET DEVICE SYS.

APPNDL:	LOOKUP	FCT,EBLOCK	;ATTEMPT TO OPEN FACT FILE FOR READING.
	  JRST	APPNDN		;LOOK-UP FAILED--PERHAPS FILE DOESN'T EXIST.
	PUSHJ	P,APPNDE	;ATTEMPT TO GRAB THE FACT FILE.
	SKIPN	P2,RBSIZE	;FILE SIZE IN WORDS
	JRST	APPNDM		;IF ZERO LEN, NO INPUT
	SOJ	P2,		;POINT TO LAST WORD
	CAMLE	P2,[0,,777577]	;[577]  WILL WE EXCEED 2**18?
	 JSP	P2,APPNDR	;[577]  YES--TAKE ERROR EXIT
	MOVEI	T3,200(P2)
	LSH	T3,-7		;COMPUTE LAST BLOCK OF FILE
	ANDI	P2,177		;P2 NOW HAS RELATIVE DEPTH (0-127) OF
	USETI	FCT,(T3)	; LAST WORD IN LAST BLOCK.
	MOVEI	T4,-201(P1)	;ADDR OF AVAILABLE CORE-1
	HRRM	T4,ILIST		;SAVE IN IOWDS
	HRRM	T4,OLIST
	AOJ	T4,		;BUMP FOR BUFFER POINTER
	HRLI	T4,P2		;MAKE INDEXABLE
	INPUT	FCT,ILIST	;READ LAST BLOCK OF FACT FILE INTO DUMP BUFFER.
	STATZ	FCT,IO.ERR
	  JSP	P2,APPNDR	;ERROR OR EOF WILL YIELD ERROR RETURN.

;STILL IN FTFACT!FTCHKPNT CONDITIONAL
APPNDA:	MOVS	T1,@T4		;GET LAST WORD OF CURRENT FACT FILE.
	CAIN	T1,777000	;END-OF-FILE ENTRY ?
	JRST	APPNDB		;YES, THINGS ARE LOOKING GOOD.
	SKIPN	T1		;NO, FACT FILE SCREWED UP!  IS LAST WORD NON-ZERO ?
	TRNN	P2,-1		;OR IS THIS THE FIRST WORD OF A 200-WORD BLOCK ?
	JSP	P2,APPNDR	;YES TO EITHER QUESTION. TAKE ERROR EXIT.
	SUB	P2,[XWD 1,1]	;TRY BACKING UP OVER ZERO WORDS ATTEMPTING TO FIND
	JRST	APPNDA		; THE END-OF-FILE ENTRY.

APPNDB:	TLNN	P2,-1		;WAS END-OF-FILE ENTRY WHERE IT WAS SUPPOSED TO BE ?
	JRST	APPNDC		;YES, PROCEED.
	MOVE	T1,[XWD 377000,1]	;NO, FILL WITH DUMMY ONE-WORD ENTRIES TO
	MOVEM	T1,@T4		; SHOW WHERE DATA LOSS MAY HAVE OCCURED.
	AOBJN	P2,.-1

APPNDC:	MOVE	T1,0(P1)	;PICK UP ENTRY AS SPECIFIED IN CALLING SEQUENCE.
	MOVEM	T1,@T4		;STORE IN FACT FILE OUTPUT BUFFER.
	AOJ	P2,		;NEXT
	AOBJN	P1,APPNDC
	MOVSI	T1,777000	;LAY DOWN END-OF-FILE ENTRY AGAIN.
	MOVEM	T1,@T4	
	SETCA	P2,0		;(IN PLACE OF AOS P2 FOLLOWED BY MOVNS P2)
	HRLM	P2,OLIST	;STORE CORRECT NUMBER OF WORDS TO BE WRITTEN.
	USETO	FCT,(T3)
	OUTPUT	FCT,OLIST	;OUTPUT UPDATED FACT FILE.
	STATZ	FCT,IO.ERR
	  JSP	P2,APPNDR	;ERROR OR EOF WILL YIELD ERROR EXIT.
	AOSA	0(P)		;DOUBLE SKIP EXIT
FCTBSY:	AOS	BSYFCT		;COUNT BUSY ERRORS
	AOS	0(P)		;SINGLE SKIP EXIT
	PJRST	RELFCT		;RELEASE FCT CHANNEL

APPNDR:	AOS	FCTGUF		;COUNT ERRORS IN FACT FILE
	HRLM	P2,FCTGUF	;AND SAVE ADDRESS WHERE DETECTED
	PJRST	RELFCT		;EXIT AFTER RELEASING CHANNEL

;STILL IN FTFACT!FTCHKPNT CONDITIONAL
APPNDE:	ENTER	FCT,EBLOCK
	  JRST	.+2
	POPJ	P,		;**GOOD EXIT. THE FACT FILE IS OPEN FOR WRITING.**
	POP	P,(P)		;CORRECT THE STACK, SINCE WE WON'T POPJ
	HRRZ	P2,RBEXTE
	CAIE	P2,ERFBM%	;ERROR CODE=3 FROM DSKSER MEANS FILE BEING MODIFIED
	JSP	P2,APPNDR	; BY SOMEONE ELSE. ANY OTHER ERROR CODE LOSES.
	SOSG	TRYCTR		;TRIED OFTEN ENOUGH?
	JRST	FCTBSY		;YES, GIVE UP AFTER 10 TRIES
	MOVEI	P2,1		;WAIT A SECOND
	SLEEP	P2,
	JRST	APPNDL		;NO, TRY AGAIN BEGINNING WITH LOOK-UP. (FILE COULD
	 			; HAVE COME INTO EXISTENCE OR DIED IN THE INTERIM.)

APPNDN:	HRRZ	P2,RBEXTE	;ONLY ERROR CODE 0 IS REASONABLE ON LOOKUP FAILURE.
	JUMPN	P2,APPNDR	;ERROR EXIT ON ANY OTHER LOOKUP FAILURE.
	PUSHJ	P,APPNDE	;FACT FILE DIDN'T EXIST.  TRY TO CREATE IT.
APPNDM:	MOVEI	T3,1		;POINT TO BEGIN OF FILE
	MOVEI	T4,-201(P1)	;ADDR OF AVAILABLE CORE-1
	HRRM	T4,OLIST
	AOJ	T4,		;BUMP TO BEGINNING OF BUFFER
	HRLI	T4,P2		;INDEX FOR INDIRECT ADDRESSING
	JRST	APPNDC		;GO MOVE TRANSACTION ENTRY INTO FILE AND EXIT.

;STILL IN FTFACT!FTCHKPNT COND
TRYCTR:	BLOCK	1	;#OF TIMES TO TRY IF FACT FILE IS BUSY
APPBLK:	EXP	<RBSIZE-RBCNTE>	;LEN OF EXT LOOKUP,ENTER
	EXP	FCTPPN		;PPN FOR FACTFILE
	SIXBIT	/FACT/		;NAME
>;END FTFACT!FTCHKPNT CONDITIONAL
SUBTTL ROUTINES TO READ CRASH.EXE


;GENERAL PROCEDURE IS TO GET EACH STR IN THE SYSTEM SEARCH LIST
;LOOK UP "CRASH.EXE", IF PRESENT, READ THE FIRST REAL DATA BLOCK AND
;CHECK TO SEE IF THIS FILE HAS BEEN PROCESSED. WORD 116, .JBSYM, WILL BE NON-
;ZERO IF THIS FILE HASN'T BEEN PROCESSED.  IF TRUE, EXTRACT ANY PENDING ENTRIES
;FROM THE CRASH VIA GETTAB AND PEKSPY SIMULATION,
;THEN CREATE A SEPARATE ENTRY  CONTAINING INTERESTING INFORMATION FROM THIS 
;CRASH SUCH AS UPTIME, DISK STATISTICS, PERFORMANCE STATS, DEVICE STATUS
;ETC.  ALL ITEMS MUST BE EITER DIRECTLY GETTAB'D OR THE STARTING
;ADDRESS MUST BE GETTABABLE.  INFO ADDED TO THE LIST
;VIA FIELD EDITS WILL BE PRESERVED BUT ONLY LISTED IN
;OCTAL BY SYSERR.  OTHERS WILL BE DECENTLY FORMATED INCLUDING ITEM NAME,ETC.
;ROUTINE TO LOOK FOR AND PROCESS UN-CHECKED CRASH.EXE FILES.
;CALL  PUSHJ, RETURNS POPJ AND USES ALL AC'S

CRSCHK:	TLO	F,L.DSK		;PEEK/SPY ARE SIMULATED TO DSK
	PUSH	P,PDBPTR	;SAVE VALUES FOR CALLER SINCE WE
	PUSH	P,MAXGTB	;CHANGE THESE VALUES IN OPNSTR
	PUSH	P,RNGTAB	;...
	PUSH	P,MONVER	;...
	PUSH	P,GTBST		;...
	PUSH	P,JBTMXL	;...
	PUSH	P,ERPTSZ	;...
	PUSH	P,.JBFF		;TO RECOVER CORE USED ON EXIT
	SETZM	P1		;1ST STR NAME TO GET
CRSNXT:	PUSHJ	P,NXTSTR	;GET A STR IN SSL OR SDL
	JUMPE	P1,CRSEND	;END OF LIST, CLEAN UP AND RETURN
	MOVEM	P1,D.DEV	;STORE STR NAME
	PUSHJ	P,GETFIL	;DO A LOOKUP ON THIS STR
	 JRST	CRSNX1		;***LOOKUP FAILED
	SETZM	KLEFLG		;ZERO KLERR FLAG
	USETI	DSKX,CRSBLK	;SET TO READ 1ST 200 WDS
	IN	DSKX,DSKIOW	;GET THAT NLOCK
	SKIPA			;SKIP OVER ERROR
	 JRST	CRSNX1		;***READ FAILED
	SKIPE	DSKBUF+.JBSYM	;IF 0,FILE AS BEEN PROCESSED
	 PUSHJ	P,READCR	;GO PROCESS THIS FILE
	USETI	DSKX,0		;GET THE RIB
	IN	DSKX,DSKIOW	;READ IT
	SKIPA
	 JRST	CRSNX1		;***IN FAILED
	MOVE	T1,DSKBUF+177	;GET RIB'S SELF BLOCK #
	ADDI	T1,CRSBLK	;POINT AT CORRECT BLOCK
	PUSH	P,T1			;SAVE IT
	MOVEI	T1,DSKX		;GET [564] GET CHANNEL
	MOVEM	T1,DSKBUF+.DCNAM	;[564] FOR DSKCHR
	MOVE	T1,[XWD .DCUPN+1,DSKBUF]
	DSKCHR	T1,
	  JRST	CRSNX2
	CLOSE	DSKX,		;CLOSE THE FILE
	MOVEI	T1,.IODMP	;DUMP MODE
	MOVE	T2,DSKBUF+.DCUPN;GET ACTUAL PACK NAME[564]
	MOVEI	T3,0		;NO BUFFERS
	OPEN	DSKX,T1		;REOPEN FOR SUSET
	  JRST CRSNX2		;   TO GET RIGHT WORD
	MOVE	T1,0(P)
	HRLI	T1,DSKX_5
	SUSET.	T1,		;SUPER IO
	 USETI	DSKX,(P)
	IN	DSKX,DSKIOW	;READ THE BLOCK
	SKIPA
	 JRST	CRSNX2
	SETZM	DSKBUF+.JBSYM	;CLEAR THAT WORD
	MOVE	T1,0(P)
	HRLI	T1,<4000+DSKX>_5
	SUSET.	T1,
	 USETO	DSKX,(P)
	POP	P,T1
	OUT	DSKX,DSKIOW	;REWRITE IT
	JFCL
	JRST	CRSNX1	;DON'T CARE IF WRITE FAILED
CRSNX2:	POP	P,T1
CRSNX1:	MOVE	T1,0(P)		;GET ORIGINAL CONTENTS OF .JBFF BACK
	MOVEM	T1,.JBFF	;RECOVER GTBST TABLE SPACE
	MOVE	P1,D.DEV	;STR WE JUST USED
	JRST	CRSNXT		;GET NEXT

CRSEND:	TLZ	F,L.DSK	;USE REAL PEEK/SPY NOW
	RELEASE	DSKX,		;[607]  RELEASE THE CHANNEL
	POP	P,T1		;RESTORE ORIGINAL
	MOVEM	T1,.JBFF	;  CONTENTS OF .JBFF
	CORE	T1,		;GET RID OF IT
	  JFCL			;DON'T CARE
	POP	P,ERPTSZ
	POP	P,JBTMXL
	POP	P,GTBST
	POP	P,MONVER
	POP	P,RNGTAB
	POP	P,MAXGTB	;RESTORE THESE VALUES
	POP	P,PDBPTR	;TO THEIR VALUE ON ENTRY
	POPJ	P,0		;WER'E DONE
;ROUTINES TO CHECK FOR AND EXTRACT ENTRIES OR DATA FROM A CRASH.EXE
;FILE.
;CALL:	PUSHJ	P,READCR
;	  ALWAYS RETURN HERE

READCR:	PUSHJ	P,SIMSPY	;SETUP TO SIMULATE SPY FROM DISK
	  POPJ	P,		;SOMETHING BAD, GIVE UP
	MOVE	T1,[%LDESZ]	;GETTAB TO RETURN LENGTH OF ERPTBK ENTRY
	PUSHJ	P,GTBSPY	;GET IT FOR THIS CRASH
	  MOVEI	T1,2		;MUST BE OLD MONITOR
	MOVEM	T1,ERPTSZ	;SAVE FOR LATER
	MOVE	T1,[%LDERT]	;GETTAB ADDR FOR ST OF DAEMON Q TABLE
	PUSHJ	P,GTBSPY	;GET IT
	  PJRST	CRSINF		;JUST RECORD CRASH ENTRY
	MOVEM	T1,ESVIDX	;SAVE AS START ADDR OF TABLE
	MOVE	T1,[%LDPT1]	;GETTAB FOR PNTR TO EXTRACT ENTRIES
	PUSHJ	P,GTBSPY	;GET IT
	  PJRST	CRSINF		;LEAVE HERE
	PUSHJ	P,PEKSPY	;NOW GET CONTENTS OF THE PNTR
	SKIPN	T1		;IF INITIAL IS ZERO
	MOVE	T1,ERPTSZ	;0TH ENTRY IS BLANK
	MOVEI	T3,(T1)		;COPY INITIAL OFFSET TO T3
	MOVE	T1,[%LDLTH]	;NOW GET MAX TABLE LENGTH
	PUSHJ	P,GTBSPY	;GET IT
	 PJRST	CRSINF		;[603] TABLE IS BAD,EXIT.
	MOVEM	T1,ERPTMX	;SAVE IT TOO
	IDIV	T1,ERPTSZ	;COMPUTE NUMBER OF ENTRIES IN TABLE
	MOVNI	T1,(T1)		;MAKE IT NEGATIVE
	MOVSI	T1,(T1)		;MOVE TO LH
	HRRI	T1,(T3)		;MAKE AOBJN POINTER TO TABLE
READC1:	MOVEM	T1,EPKIDX	;SAVE NEW AOBJN POINTER
	MOVEI	T2,(T1)		;COPY TO T2
	CAML	T2,ERPTMX	;OFF END?
	HLLZS	T2,EPKIDX	;YES, RESET TO TOP
	ADD	T2,ESVIDX	;OFFSET TO START OF TABLE
	MOVN	T3,ERPTSZ	;GET -COUNT OF WORDS IN EACH ENTRY
	MOVSI	T3,(T3)		;MAKE AOBJN POINTER
	SETZM	ERPTBK+2	;MAKE CPU NUMBER DEFAULT CORRECTLY
	SETZM	ERPTBK+3	;  FOR OLD MONITORS
READC2:	MOVEI	T1,(T2)		;COPY ADDRESS TO T1
	PUSHJ	P,PEKSPY	;GET NEXT WORD
	MOVEM	T1,ERPTBK(T3)	;SAVE IN NEXT WORD OF BLOCK
	MOVEI	T2,1(T2)	;INCREMENT POINTER TO NEXT WORD
	AOBJN	T3,READC2	;LOOP FOR ALL WORDS
	MOVEI	T1,ERPTBK	;POINT TO THE BLOCK
	SKIPN	(T1)		;THIS ENTRY EMPTY?
	PJRST	CRSINF		;YES, ALL DONE
	PUSHJ	P,DSPERR	;GO PROCESS THIS ENTRY
	MOVE	T1,EPKIDX	;GET POINTER TO TABLE BACK
	MOVE	T2,ERPTSZ	;GET SIZE OF ENTRY
	ADDI	T1,-1(T2)	;INCREMENT TO NEXT BLOCK-1
	AOBJN	T1,READC1	;INCREMENT TO NEXT BLOCK AND LOOP
;HERE TO CREATE AN ENTRY OF EXTRACTED INFO FROM THE CRASH
;SUCH AS UPTIME, DISK STATS,ETC

CRSINF:	MOVSI	T1,.ESCIN_9	;CODE FOR THIS ENTRY
	PUSHJ	P,ERRINB	;CREATE HEADER AND PUSH LIST
	PUSH	P4,D.DEV	;(R0) STR NAME FOR THIS CRASH
	MOVE	T1,[%SYERR]	;SYS WIDE ERROR COUNT
	PUSHJ	P,GTBSPY	;GET IT
	 MOVE	T1,PATTERN	;LOOSER?
	PUSH	P4,T1		;(R1)
	MOVE	P1,CRSGTB	;START OF GETTAB TABLE
	MOVE	T1,P1	
	HRRI	T1,1		;PNTR FOR SYSERR
	PUSH	P4,T1		;(R2)
	PUSHJ	P,CRSDMP	;(R3-R110)DUMP GETTAB ENTRIES
	PUSH	P4,[0]		;(R111) NO LONGER PUT DISK STUFF HERE
;NOW CHECK FOR CUSTOMER DEFINED ITEMS TO DUMP
	MOVE	P1,CRSGT1	;PNTR OF ITEMS
	TLNE	P1,-1		;NULL LIST?
	PUSHJ	P,CRSDMP	;NO, DUMP THEM ALSO
	PUSHJ	P,ERRFIN	;CLOSE THE ENTRY AND WRITE IT
	PUSHJ	P,DMPDSK	;NOW DUMP ALL DISK STATS
	JRST	DMPHSB		;CONTINUE AHEAD
;ROUTINE TO EXTRACT GETTAB ITEMS FROM A CRASH.
;CALL:	MOVE	P1,AOBJN POINTER TO TABLE OF GETTABS
;	PUSHJ	P,CRSDMP
;	RETURN

CRSDMP:	MOVE	T1,0(P1)	;GET NEXT GETTAB FROM TABLE
	TLNN	T1,-1		;IF LH=0, THIS IS A SUBTABLE
	JRST	CRSDM1		;SO GO DO THAT SPECIAL
	MOVE	P3,T1		;SAVE FOR POSSIBLE SUBTABLE FOLLOWING
	PUSHJ	P,GTBSPY	;GET VALUE
	  MOVE	T1,PATTERN	;CAN'T, FLAG FOR SYSERR
	PUSH	P4,T1		;SAVE IN BUFFER
	JRST	CRSDM2		;JOIN COMMON ENDING CODE
CRSDM1:	MOVE	T3,P3		;GET BASE POINTER SET ABOVE
	MOVE	T2,T1		;MOVE SUBTABLE INDEX TO T2
	HRLI	T2,.GTC0V	;DO ONLY CPU0 FOR NOW
	PUSHJ	P,GSUBTB	;GET VALUE FROM SUBTABLE
	  MOVE	T1,PATTERN	;CAN'T, FLAG FOR SYSERR
	PUSH	P4,T1		;SAVE IN BUFFER
CRSDM2:	AOBJN	P1,CRSDMP	;LOOP FOR ENTIRE TABLE
	POPJ	P,		;RETURN
;THIS IS THE TABLE OF GETTAB ITEMS TO BE EXTRACTED FROM A CRASH.
;ADDITIONAL ITEMS SHOULD NOT BE ADDED HERE BY A SITE BECAUSE IT WILL
;CONFUSE SYSERR VERY BADLY. USE THE TABLE CRSGT1 INSTEAD.
;  ";***" INDICATES A SUBTABLE ITEM

CRSGTB:	XWD	.-CRSGTE,.+1	;PNTR FOR TABLE LENGTH
	%CNTIM		;(R3) TIME OF DAY
	%CNSIZ		;(R4) SYSTEM MEMORY SIZE
	%CNPOK		;(R5) LAST ADDR POKED
	%CNLNM		;(R6) # JOBS LOGGED IN
	%CNTIC		;(R7) #TICKS PER SECOND
	%CNVER		;(R10) MONITOR VERSION
	%CNDBG		;(R11) DEBUG STATUS WORD
	%CNHSO		;(R12) START OF MONITO HIGH SEG
	%CNNWC		;(R13) #OF WORDS OF CORE
	%NSUPT		;(R14) UPTIME IN TICKS
	%NSMMS		;(R15) MEMORY SIZE
	%NSTPE		;(R16) TOTAL MEM PAR ERRORS
	%NSSPE		;(R17) TOTAL SPURIOUS PARITY ERRORS
	%NSMPC		;(R20) MULTIPLE PARITY ERRORS
	%NSMPA		;(R21) LAST PARITY ADDR
	%NSMPW		;(R22) LAST PARITY WORD
	%NSMPP		;(R23) LAST PARITY PC
	%NSEPO		;(R24) # UNREC EXEC PDL OV
	%NSEPR		;(R25) # RECOVERED EXEC PDL OV
	%SWERC		;(R26) SWAP ERROR COUNT
	%SYDEL		;(R27) DISABLED HARDWARE ERROR COUNT
	%SYSPC		;(R30) LAST STOPCD
	%SYNDS		;(R31) # DEBUG STOPCDS
	%SYNJS		;(R32) # JOB STOPCDS
	%SYSJN		;(R33) LAST STOPCD-JOB NUMBER
	%SYSPN		;(R34) LAST STOPCD-PROGRAM NAME
	%SYSUU		;(R35) LAST STOPCD-UUO
	%SYSPP		;(R36) LAST STOPCD-P,PN
	%CCPAR		;(R37) PARITY SUBTABLE
	%CVPLA		;(R40) **HIGHEST ADDR OF PARITY ERROR
	%CVPMR		;(R41) **ADDRES IN SEGMENT OF PAR ERR
	%CVPTS		;(R42) **PAR ERRORS THIS SWEEP
	%CVPSC		;(R43) **#SWEEPS
	%CVPUE		;(R44) **USER ENABLED
	%CVPAA		;(R45) **LOGICAL AND  OF ADDR
	%CVPAC		;(R46) **LOGICAL AND OF WORDS
	%CVPOA		;(R47) **LOG OR OF ADDR
	%CVPOC		;(R50) **LOG OR OF DATA
	%CVPCS		;(R51) **COUNT OF SPUR CHANNEL ERROS
	%CCRSP		;(R52) ADDR OF RESPONSE SUBTABLE
	%CVRSO		;(R53) **SUM TTY OUT UUO RES
	%CVRNO		;(R54) **NUM TTY OUT UUO
	%CVRHO		;(R55) **HI-SUM SQ TTY OUT UUO
	%CVRLO		;(R56) **LO-SUM	"    "
	%CVRSI		;(R57) **SUM TTY INP UUO
	%CVRNI		;(R60) **NUMBER TTY INP UUO
	%CVRHI		;(R61) **HI-SUM SQ TTY INP UUO
	%CVRLI		;(R62) **LO-SUMSQ TTY INP UUO
	%CVRSR		;(R63) **SUM QUANTUM REQ RES
	%CVRNR		;(R64) **NUMBER QUANTUM REQ RES
	%CVRHR		;(R65) **HI-SUM SQ QUANTUM RES
	%CVRLR		;(R66) **LO-SUM SQ QUANTUM REQ RES
	%CVRSX		;(R67) **SUM ONE OF ABOVE
	%CVRNX		;(R70) **NUMBER ONE OF ABOVE
	%CVRHX		;(R71) ** HI-SUM SQ ONE OF ABOVE
	%CVRLX		;(R72) **LO-SUM SQ ONE OF ABOVE
	%CVRSC		;(R73) **SUM CPU RES
	%CVRNC		;(R74) **NUMBER CPU RES
	%CVRHC		;(R75) **HI-SUM CPU RES
	%CVRLC		;(R76) **LO-SUM CPU RES
	%CVUPT		;(R77) UPTIME
	%CVLST		;(R100) LOST TIME
	%CVNUL		;(R101) NULTIME
	%CVOHT		;(R102) OVERHEAD TIME IN JIFFIES
	%CVTUC		;(R103) TOTAL UUO COUNT
	%CVTJC		;(R104) TOTAL JOB CONTEXT SWITCH COUNT
	%CVTNE		;(R105) TOTAL NXM
	%CVSNE		;(R106) TOTAL SPUR NXM
	%CVNJA		;(R107) # JOBS AFFECTED LAST NXM
	%CVMNA		;(R110) FIRST ADDR LAST NXM
	CRSGTE==.-1		;END OF TABLE

CRSGT1:	XWD .-CRSGT2, .+1	;PNTR FOR TABLE TO BE DEFINED BY CUSTOMER
			;SYSERR WILL LIST TESE ITEMS IN OCTAL ONLY, IFF PRESENT

	CRSGT2==.-1

;ROUTINE TO DETERMINE IF CRASH IS A KS10 SYSTEM DUMP AND IF SO
;MAKE A HALT STATUS BLOCK ENTRY

DMPHSB:	MOVE	T1,[%FTERR]	;FEATURE SWITCH SETTINGS
	PUSHJ	P,GTBSPY	;GET IT
	 POPJ	P,		;CAN'T, THEN FORGET THIS
	TRNN	T1,F%KS10&777777;IS THIS A KS10 SYSTEM DUMP?
	 POPJ	P,		;NO--LET'S GO HOME
	MOVEI	T1,424		;ADDRESS OF FIRST WORD IN HSB
	PUSHJ	P,PEKSPY	;GET IT
	JUMPE	T1,CPOPJ	;IF IT'S ZERO, NO HSB HAS BEEN STORED
	MOVSI	T1,.ESHSB_9	;HSB ENTRY CODE
	PUSHJ	P,ERRINB	;CREATE HEADER AND PUSH POINTER
	SETZ	T1,		;GET HALT STATUS CODE (LOC 0)
	PUSHJ	P,PEKSPY
	PUSH	P4,T1		;(R0)STORE IT
	MOVEI	T1,1		;GET HALT PC (LOC 1)
	PUSHJ	P,PEKSPY
	PUSH	P4,T1		;(R1)STORE IT
	MOVE	T1,[XWD -22,4]	;HSB POINTER
	PUSH	P4,T1		;(R2)STORE IT
	PUSH	P4,[0]		;(R3)STORE IT
	MOVSI	T2,-22		;AOBJN WORD FOR SIZE OF HSB
DMPHS0:	MOVEI	T1,424(T2)	;FORM ADDRESS TO WORD IN HSB
	PUSHJ	P,PEKSPY	;GET IT
	PUSH	P4,T1		;STORE IT
	AOBJN	T2,DMPHS0	;GET'EM ALL
	PUSHJ	P,ERRFIN	;CLOSE OUT ENTRY AND WRITE IT
	POPJ	P,		;DONE
;ROUTINE TO SETUP TO SIMULATE SPYING FROM THE CRASH FILE AND
;GET ALL THE INITIAL DATA NEEDED TO PROCESS THE CRASH.
;CALL:	PUSHJ	P,SIMSPY
;	 ERROR RETURN
;	ALL OK

SIMSPY:	SETOM	DSKBLF		;CLEAR INITIAL DISK BLOCK
;CAN'T USE PEKSPY HERE BECAUSE WE WANT TO READ DIRECTORY
	MOVEI	T2,BLKSIZ	;NEED 1 BLOCK FOR THE .EXE DIRECTORY
	PUSHJ	P,GETCOR	;GET IT
	  POPJ	P,		;FAILED, GIVE UP
	MOVEM	T2,EXEADR	;STORE FOR PEKDSK
	SOS	T1,T2		;BACK UP 1 WORD AND MOVE TO T1
	HRLI	T1,-BLKSIZ	;MAKE AN IOWD
	MOVEI	T2,0		;TERMINATED BY A ZERO
	USETI	DSKX,1		;GET BLOCK 1
	IN	DSKX,T1		;READ THE FIRST BLOCK OF THE DIRECTORY
	  CAIA			;SKIP OVER FAIL RETURN
	POPJ	P,		;READ FAILED
	HLRZ	T2,1(T1)	;GET LH OF FIRST WORD
	HRRZ	T1,1(T1)	;AND RH OF SAME WORD
	CAIN	T2,.SVDIR	;MUST BE AN EXE DIRECTORY
	CAILE	T1,BLKSIZ-1	;WHICH IS LESS THAN A BLOCK LONG
	POPJ	P,		;NO
	MOVEI	T1,ABSGTB	;GET POINTER TO GETTABS
	PUSHJ	P,PEKSPY	;READ IT
	TLNE	T1,-1		;MAKE SURE ZERO LH
	POPJ	P,		;NO, GIVE UP
	CAILE	T1,ABSGTB	;MAKE SURE IT MAKES SOME SENSE
	CAML	T1,DSKFLG	; ..
	POPJ	P,		;NO, GIVE UP
	HRRZ	T2,T1		;SAVE FOR TEST LATER
	ADDI	T1,.GTSLF	;ADD OFFSET FOR GETTAB IMMEDIATE
	PUSHJ	P,PEKSPY	;READ THAT PLACE
	CAIE	T2,(T1)		;SEE IF IT MATCHES
	POPJ	P,		;NO, GIVE UP
	LSH	T1,-^D27	;KEEP JUST MAX ENTRY IN NUMTAB
	MOVEM	T1,MAXGTB	;SAVE MAX GETTAB NUMBER
	MOVNI	T3,1(T1)	;-NUMBER OF GETTABS TO T3
	HRLI	T3,(T2)		;MAKE SWAPPED AOBJN POINTER TO NUMTAB
	MOVSS	T3		;MAKE IT AOBJN POINTER
	MOVEI	T2,1(T1)	;GET LENGTH OF NUMTAB
	PUSHJ	P,GETCOR	;ALLOCATE THAT MUCH CORE
	  POPJ	P,		;CAN'T, GIVE UP
	MOVEM	T2,GTBST	;SAVE ADDRESS OF START OF NUMTAB
SIMSP2:	MOVEI	T1,(T3)		;GET ADDRESS OF NEXT ITEM IN NUMTAB
	PUSHJ	P,PEKSPY	;GET IT
	MOVEM	T1,(T2)		;SAVE IN TABLE
	ADDI	T2,1		;BUMP TABLE ADDRESS
	AOBJN	T3,SIMSP2	;BUMP NUMTAB ADDRESS AND LOOP
	MOVE	T2,GTBST	;GET ADDRESS OF START OF OUR NUMTAB
	MOVE	T1,MAXGTB	;GET LARGEST GETTAB TABLE
	CAIGE	T1,.GTIDX	;HAVE A RANGE TABLE?
	TDZA	T1,T1		;NO, USE ZERO
	HRRZ	T1,.GTIDX(T2)	;GET ADDRESS OF RNGTAB FROM NUMTAB
	MOVEM	T1,RNGTAB	;SAVE FOR GETTAB SIMULATION
	MOVE	T1,[ %CNPDB]	;SET UP PDB POINTER FOR CRASH FILE
	PUSHJ	P,GTBSPY	;SET IF IT IS THERE
	  MOVEI	T1,0		;NO, USE ZERO
	MOVEM	T1,PDBPTR	;STORE ZERO OR VALUE
	MOVE	T1,[%CNVER]	; GET CRASHED MONITORS
	PUSHJ	P,GTBSPY	; VERSION INTO A
	  MOVEI	T1,0		;CAN'T, USE ZERO
	HRRZM	T1,MONVER	; AND STORE IT AWAY
	MOVE	T1,[%CNBCP]	;GETTAB TO RETURN BOOT CPU'S
	PUSHJ	P,GTBSPY	;  CPU NUMBER
	  MOVEI	T1,0		;FAILED, ASSUME 0
	LSH	T1,1		;OFFSET FROM CPU 0 GETTAB
	ADD	T1,[%CCTOS]	;GET ADDRESS OF EPT FOR BOOT CPU
	PUSHJ	P,GTBSPY	;GET IT
	  MOVEI	T1,1000		;ASSUME PAGE 1
	SUBI	T1,220		;ADJUST FOR CALCULATIONS IN PEKDSK
	MOVEM	T1,EPTOFS	;SAVE FOR PEEK SIMULATION
	MOVE	T1,[%CNSJN]	;POINTER TO -SEGN,,JOBN
	PUSHJ	P,GTBSPY	;GET IT
	  MOVE	T1,[-^D512,,^D512] ;LET ALL REFERENCES WIN
	HLRE	T2,T1		;GET -SEGN IN 36 BITS
	MOVNI	T2,1(T2)	;MAKE IT SEGN-1
	ADDI	T2,(T1)		;COMPUTE JOBN+SEGN-1
	HRRZM	T2,JBTMXL	;SAVE FOR GETTAB SIMULATION
	JRST	CPOPJ1		;RETURN SUCCESS
;ROUTINE TO GET THE NEXT STRUCTURE FROM THE UNION OF THE SYSTEM SEARCH
;LIST AND THE SYSTEM DUMP LIST.
;CALL WITH P1=PREVIOUS NAME OR 0 IF FIRST CALL
;RETURNS CPOPJ ALWAYS WITH P1=NEW NAME OR 0 IF NO MORE

NXTSTR:	SYSSTR	P1,		;GET NEXT STR NAME
	  MOVEI	P1,0		;CAN'T DO MUCH...
	JUMPE	P1,CPOPJ	;GO IF NO MORE
	SETZM	DSKBUF+.DFGJN	;JOB 0 = SYSTEM SEARCH LIST
	MOVEM	P1,DSKBUF+.DFGNM ;STORE STR NAME
	MOVE	T1,[.DFGST+1,,DSKBUF] ;SETUP ARG POINTER
	GOBSTR	T1,		;IS THIS STR IN SYSTEM SEARCH LIST?
	  CAIA			;NO
	POPJ	P,		;YES, RETURN IT
	MOVEM	P1,DSKBUF+.DCNAM ;SETUP ARG FOR DSKCHR
	SETOM	DSKBUF+.DCPSD	;DEFAULT POSITION IN SDL FOR OLD MONITORS
	MOVE	T1,[.DCPSD+1,,DSKBUF] ;SETUP ARG
	DSKCHR	T1,		;GET POSITION IN SDL
	  JRST	NXTSTR		;SHOULDN'T HAPPEN BUT...
	SKIPGE	DSKBUF+.DCPSD	;IS THIS STR IN THE SDL?
	JRST	NXTSTR		;NO
	POPJ	P,		;YES
;ROUTINE TO OPEN THE CRASH FILE ON A SPECIFIED STRUCTURE.
;CALL:	PUSHJ	P,GETFIL
;	  ERROR RETURN
;	ALL OK

GETFIL:	MOVSI	T1,DSKX+<(FO.PRV)> ;CHANNEL IS DSKX PLUS PRIVS
	HRRI	T1,.FORED	;FUNCTION IS READ
	MOVEM	T1,D.FLOP+.FOFNC
	MOVEI	T1,.IODMP	;SET I/O MODE
	MOVEM	T1,D.FLOP+.FOIOS ; . .
	MOVE	T1,D.DEV	;GET DEVICE
	MOVEM	T1,D.FLOP+.FODEV ;AND STORE IT
	SETZM	D.FLOP+.FOBRH ;NO BUFFERS
	SETZM	D.FLOP+.FONBF ; . .
	MOVEI	T1,D.LKB	;ADDR. OF LOOKUP BLOCK
	MOVEM	T1,D.FLOP+.FOLEB ; . .
	MOVE	T1,CRASH	;GET FILENAME
	MOVEM	T1,D.LKB+.RBNAM ;STORE IT IN LOOKUP BLOCK
	MOVSI	T1,'EXE'	;ASSUME EXE
	MOVEM	T1,D.LKB+.RBEXT ;STORE IT
	MOVE	T1,CRSPPN	;GET PPN
	MOVEM	T1,D.LKB+.RBPPN ;STORE IT
	MOVEI	T1,.RBSIZ	;GET EXTENDED LOOKUP BLOCK SIZE
	MOVEM	T1,D.LKB+.RBCNT	 ;STORE IT IN LOOKUP BLOCK
	MOVE	T1,[XWD .FOLEB+1,D.FLOP] ;POINT TO FILOP. BLOCK
	FILOP.	T1,		;OPEN CRASH FILE
	  POPJ	P,		;CAN'T ACCESS FILE
FILOPN:	MOVE	T1,D.LKB+.RBSIZ ;GET FILE SIZE
	MOVEM	T1,DSKFLG	;AND SAVE IT AWAY FOR LATER
	JRST	CPOPJ1		;GIVE GOOD RETURN
;ROUTINE TO PERFORM GETTAB SIMULATION FROM AN EXE FILE ON DISK.
;DOES NOT HANDEL AN ITEM TYPE OF -2 FOR JOB ENTRIES.
;CALL:	MOVE	T1,GETTAB ITEM
;	PUSHJ	P,GTBDSK
;	  ERROR RETURN
;	NORMAL RETURN WITH VALUE IN T1

GTBDSK:	HRRZ	BP,T1		;GET TABLE NUMBER
	HLRES	T1		;KEEP JUST ITEM NUMBER IN T1
	SKIPL	MAXGTB		;DO WE HAVE ANY GETTAB POINTERS?
	CAMLE	BP,MAXGTB	;AND DO WE HAVE THIS MANY?
	POPJ	P,		;NO, RETURN ERROR
	PUSHJ	P,SAVE2		;SAVE P1-P2
	ADD	BP,GTBST	;COMPUTE ADDRESS OF THIS NUMTAB ENTRY
	MOVE	BP,(BP)		;GET THE ENTRY
	LDB	P2,[POINT 3,BP,11] ;GET TYPE OF GETTAB
	CAIE	P2,.SLIXI	;RANDOM TABLE?
	CAIN	P2,.SLIXR	;  OR RANGED GETTAB?
	JRST	GTBDS1		;YES, DO NOT MAKE -1 MY JOB
	JUMPGE	T1,GTBDS1	;IF ITEM IS -1 FOR JOB INDEXED ENTRY,
	MOVEI	T1,(J)		;  USE USER'S JOB NUMBER
GTBDS1:	CAIN	P2,.SLIXP	;DATUM IN THE PDB?
	JRST	GTBDS3		;YES, GO GET IT
	CAIN	P2,.SLIXS	;TABLE INDEXED BY JOB OR SEGMENT NUMBER?
	SKIPA	P1,JBTMXL	;YES, GET MAXIMUM
	LDB	P1,[POINT 9,BP,8] ;GET MAX ITEM IN THIS TABLE
	CAIE	P2,.SLIXR	;THIS A RANGE TABLE?
	JRST	GTBDS2		;NO, HAVE 0,,MAX IN P1
	SKIPN	P2,RNGTAB	;HAVE THE POINTER TO RNGTAB?
	POPJ	P,		;NO, GIVE ERROR RETURN
	ADDI	P1,(P2)		;ADD OFFSET INTO RNGTAB
	EXCH	T1,P1		;SAVE T1, PUT ADDRESS INTO T1
	PUSHJ	P,PEKDSK	;GET THE RNGTAB ENTRY
	EXCH	T1,P1		;PUT VALUE INTO P1, RESTORE T1
GTBDS2:	HRRE	P2,P1		;GET MAXIMUM VALUE OF TABLE
	CAMLE	T1,P2		;.LE. MAX?
	POPJ	P,		;NO, GIVE ERROR
	HLRE	P2,P1		;PUT MIN IN RH
	CAMGE	T1,P2		;.GE. MIN?
	POPJ	P,		;NO, GIVE ERROR
	ADDI	T1,(BP)		;GET ADDRESS OF WORD WE WANT
	PUSHJ	P,PEKDSK	;GET VALUE
	JRST	CPOPJ1		;GIVE GOOD RETURN

GTBDS3:	SKIPN	PDBPTR		;DO WE HAVE THE JBTPDB ADDRESS?
	POPJ	P,		;NO, RETURN
	ADD	T1,PDBPTR	;OFFSET TO THIS JOBS PDB POINTER
	PUSHJ	P,PEKDSK	;READ THE ADDRESS OF THE PDB
	JUMPE	T1,CPOPJ1	;IF NO PDB, RETURN ZERO
	ADDI	T1,(BP)		;OFFSET INTO THE PDB
	PUSHJ	P,PEKDSK	;GET THE WORD
	JRST	CPOPJ1		;GIVE GOOD RETURN
;ROUTINE TO READ A WORD FROM AN EXE FILE ON DISK.
;CALL:	MOVEI	T1,CORE ADDRESS (WILL HANDLE PER-PROCESS ADDR AND MONITOR
;				 HIGH SEG)
;	PUSHJ	P,PEKDSK
;	RETURN WITH T1=VALUE OR 0 IF ERROR

PEKDSK:	MOVEI	T1,(T1)		;CLEAR LH
	CAIGE	T1,340000	;ADDRESS IN MONITOR LOW SEG?
	JRST	REDDSK		;YES, JUST READ MONITOR LOW CORE
	PUSH	P,P1		;GET AN AC TO USE
	MOVE	P1,T1		;COPY ADDRESS TO P1
	ROT	P1,-<P2WLSH+1>	;CONVERT TO UPMP OFFSET; HALF WORD FLAG IN 1B0
	ANDI	T1,PG.BDY	;ISOLATE OFFSET IN PAGE
	PUSH	P,T1		;  AND SAVE FOR LATER
	MOVE	T1,EPTOFS	;ASSUME HIGH SEG AND GET EPT OFFSET
	TRNE	P1,400000_-^D10	;ADDRESS IN MONITOR HIGH SEG?
	JRST	PEKDS3		;YES, SKIP CHECKS
	MOVSI	T1,(J)		;JOB NUMBER TO LH
	HRRI	T1,.GTUPM	;POINT TO JBTUPM FOR THIS JOB
	PUSHJ	P,GTBSPY	;GET IT
	  JRST	PEKDS1		;CAN'T?
	HRRZS	T1		;KEEP JUST PAGE NUMBER
	JUMPN	T1,PEKDS2	;IF IN CORE, CONTINUE
PEKDS1:	POP	P,(P)		;FLUSH JUNK
	POP	P,P1		;RESTORE P1
	MOVEI	T1,0		;RETURN 0 TO INDICATE ERROR
	POPJ	P,		;AND RETURN
PEKDS2:	LSH	T1,P2WLSH	;CONVERT TO ADDRESS
PEKDS3:	ADDI	T1,220(P1)	;COMPUTE ADDRESS OF SLOT IN UPMP OF
				;MAPPING FOR THIS ADDRESS (400-417)
	PUSHJ	P,REDDSK	;GET THE MAP WORD FROM THE UPMP
	SKIPL	P1		;SKIP IF MAPPING THROUGH RH
	MOVSS	T1		;EVEN PAGES MAP THROUGH LH
	TRNN	T1,PM.ACC	;ACCESS ALLOWED FOR THIS PAGE?
	JRST	PEKDS1		;NO, RETURN ZERO
	ANDI	T1,17777	;KEEP JUST 13 BIT PAGE NUMBER
	LSH	T1,P2WLSH	;CONVERT TO ADDRESS
	ADD	T1,0(P)		;ADD IN OFFSET IN PAGE
	POP	P,(P)		;FLUSH JUNK FROM STACK
	POP	P,P1		;RESTORE P1
;;	PJRST	REDDSK		;FALL INTO REDDSK
;HERE TO ACTUALLY READ THE DISK FOR A PHYSICAL ADDRESS.  FOLLOWS
;THE .EXE DIRECTORY TO FIND THE CORRECT BLOCK.
;CALL WITH T1=PHYSICAL ADDRESS
;RETURNS WITH T1=VALUE OR 0 IF ERROR

REDDSK:	PUSHJ	P,SAVE4		;SAVE P1-P4
	PUSH	P,T2		;SAVE T2
	IDIVI	T1,PG.SIZ	;T1:=PAGE NUMBER, T2:=OFFSET IN PAGE
	EXCH	T2,0(P)		;RESTORE T2, SAVE OFFSET ON STACK
	MOVE	P2,EXEADR	;GET ADDRESS OF .EXE DIRECTORY
	HRRZ	P1,0(P2)	;GET LENGTH OF DIRECTORY
	MOVNI	P1,-1(P1)	;GET -VE LENGTH FOR AOBJN POINTER
	HRLI	P1,1(P2)	;PUT ADDRESS+1 IF LH
	MOVSS	P1		;MAKE IT RIGHT
REDDS1:	HRRZ	P2,0(P1)	;GET FILE PAGE NUMBER OF DESCRIPTOR
	HRRZ	P3,1(P1)	;GET CORE PAGE NUMBER
	LDB	P4,[POINT 9,1(P1),8] ;PLUS REPEAT COUNT
	ADD	P4,P3		;P3:=LOWER BOUND, P4:=UPPER BOUND
	CAML	T1,P3		;THIS PAGE NUMBER IN RANGE OF
	CAMLE	T1,P4		;  THIS DESCRIPTOR?
	JRST	REDDS4		;NO, TRY NEXT
	SUB	T1,P3		;COMPUTE OFFSET IN THIS DESCRIPTOR
	JUMPE	P2,REDDS2	;RETURN ZERO IF ALLOCATED BUT ZERO PAGE
	ADD	P2,T1		;COMPUTE FILE PAGE NUMBER
	LSH	P2,P2WLSH	;CONVERT TO ADDRESS
	ADD	P2,0(P)		;INCLUDE PAGE OFFSET
	CAML	P2,DSKFLG	;FILE THAT BIG?
	JRST	REDDS2		;NO, RETURN 0
	IDIVI	P2,LN.BUF	;P2:=BLOCK NUMBER, P3:=OFFSET IN BLOCK
	CAMN	P2,DSKBLF	;SEE IF BLOCK ALREADY IN CORE
	JRST	REDDS3		;YES, JUST GET FROM CORE
	MOVEM	P2,DSKBLF	;AND REMEMBER FOR NEXT TIME
IFN  LN.BUF-200,<
	IMULI	P2,LN.BUF/BLKSIZ
>
IFN	LN.BUF-<LN.BUF/200>*200,<PRINTX LN.BUF MUST BE MULT OF 200>
	USETI	DSKX,1(P2)	;NO--POSITION FILE
	IN	DSKX,DSKIOW
	JRST	REDDS3		;READ OK
REDDS2:	TDZA	T1,T1		;READ FAILED, RETURN 0
REDDS3:	MOVE	T1,DSKBUF(P3)	;GET WORD FROM BLOCK IN CORE
	POP	P,0(P)		;PRUNE STACK
	POPJ	P,		;RETURN
REDDS4:	AOBJN	P1,.+1		;INCREMENT EXE DIRECTORY
	AOBJN	P1,REDDS1	;  POINTER AND LOOP IF MORE
	JRST	REDDS2		;NOT IN CORE, RETURN 0
KLEFLG:	0			;1 BIT FOR EACH CPU SAYING THAT WE HAVE
				;  BEEN HERE ON THIS CPU BEFORE
DSKBLF:	0
SPYFLG:	BLOCK	1		;-1 IF SPYING
CRASH:	SIXBIT /CRASH/
CRSPPN:	XWD	1,4
DSKFLG:	BLOCK	1		;FLAG (AND MAX SIZE) OF DSK INPUT FILE
EXEADR:	BLOCK	1		;ADDRESS OF THE .EXE DIRECTORY FOR THIS CRASH
EPKIDX:	Z			;AOBJN POINTER TO NEXT RELATIVE ENTRY IN
				;ERPTBK TABLE IN CRASHED MONITOR
ERPTMX:	Z			;LENGTH OF TABLE
ESVIDX:	Z			;PHYSICAL ADDR OF ERROR TABLE
ERPTSZ:	BLOCK	1		;SIZE OF EACH ERPTBK ENTRY
EPTOFS:	BLOCK	1		;ADDRESS OF EPT-220 TO DO PEEK SIMULATION
				;IN PEKDSK FOR MONITOR HIGH SEG ADDRESSES
CRSHAC: BLOCK	20		;SAVE AC'S HERE ON REENTER (FOR DEBUGING)
SUBTTL	DATA AND STORAGE, BUFFERS, ETC.

ILIST:	XWD	-200,0		;DUMP MODE INPUT COMMAND LIST 
	0
OLIST:	XWD	-P2,0		;DUMP MODE OUTPUT COMMAND LIST (WORD COUNT WILL
	0 			; BE FILLED IN.)

DLIST:
BPSTRT:	IOWD	200,DAEBUF
	0
DSKIOW:
UPDLST:	IOWD	200,SECBUF
	0
PDL:	IOWD	PDLEN,PDLIST
PATTERN:XWD	252525,252525
HEADR0:	<EL.VER>B23+<EL.HED>B26	;FORMAT VERSION AND LEN FOR HEADER

JBYSUN:	POINT	3,SEGSWP,4	;SWAP UNIT POINTER
JBYLKN:	POINT	13,SEGSWP,17	;SWAP BLOCK POINTER
CFGDAT:	0			;15 BIT CREATION DATE,,TIME OF MAXCNF.SYS

QUECOD:	POINT	5,T1,14
SELPTR:	XWD	.IPCPL,.GTSID	;[602]GETTAB ARG FOR SEL PID
ACTPTR:	XWD	.IPCPA,.GTSID	;GETTAB ARG FOR [SYSTEM]ACCOUNTING PID

COMLST:	SIXBIT	.DCORE.
	SIXBIT	.DUMP.
	SIXBIT	.SAVE.
	SIXBIT	.SSAVE.
	SIXBIT	.E.
	SIXBIT	.D.
	SIXBIT	.VERSIO.
	SIXBIT	.OSAVE.
	SIXBIT	.OSSAVE.
COMLEN==.-COMLST

COMDSP:	DCORE
	DUMP
	SAVE
	SAVE
	ECOM
	DCOM
	VERCOM
	SAVE
	SAVE

JBTCLK:	Z	0(J)
QIKNAM:	ASCIZ	\@SYS:QUIKDM.CCL\
;[62]THIS CODE MUST GO HERE TO AVOID BLT OF ZEROES.
IOERR:	BLOCK	1	;[62]FLAG TO STOP IO TO ERROR FILE
IERCNT:	EXP	^D10	;[62]COUNTER FOR TIMED RETRIES
NEWEXT:	EXP	^D10	;[62]COUNT TO PREVENT TOO MANY NEW EXTS. IN ROW
ERREXT:	'SYS'	;[62]ERROR FILE EXTENSION
RELINS:	RELEAS	0,		;[535] CHANNEL # INSERTED BEFORE XCT

ZER:!
CCLFIL:	BLOCK	1	;SIXBIT JOB NUMBER IN LH FOR CCL FILES
CTYLIN:	BLOCK	1	;LINE NUMBER FOR CTY
CURBLK:	BLOCK	1
CURWRD:	BLOCK	1
C.BH:	BLOCK	3
DAQNAM:	BLOCK	1
D.FLOP:	BLOCK	.FOPPN+1 ;BLOCK FOR FILOP. FUNCTIONS
D.DEV:	BLOCK	1
D.NAM:	BLOCK	1
	BLOCK	1
D.EXT:	BLOCK	1
D.DIR:	BLOCK	1
	BLOCK	1
D.PROT:	BLOCK	1
D.DPTH:	BLOCK	.PTMAX		;LAST WORD SURE TO BE ZERO
D.LKB:	BLOCK	.RBSTS+1	;EXTENDED LOOKUP BLOCK

EBLOCK:				;BLOCK FOR EXTENDED LOOKUPS AND ENTERS
RBCNTE:	BLOCK	1
RBPPNE:	BLOCK	1
RBNAME:	BLOCK	1
RBEXTE:	BLOCK	1
RBPRVE:	BLOCK	1
RBSIZE:	BLOCK	1

LSTSTP:	BLOCK	1	;LAST SUBTABLE POINTER USED IN GSUBTB
LSTSTV:	BLOCK	1	;LAST BALUE OF SUBTABLE POINTER
GTBST:	BLOCK	1	;BEGINNING OF TABLE OF GETTAB PTRS
HGHOFF:	BLOCK	1	;BEGINNING OF HIGH SEGMENT
HGHREL:	BLOCK	1	;LENGTH OF HIGH SEGMENT
HJOB:	BLOCK	1	;HIGHEST JOB NO IN RH
LINE==HJOB			;LH LINE NO OF DUMP/DCORE COMMAND
JOBJLT:	BLOCK	1	;LOGIN TIME OF JOB REQUESTING SERVICE
INTADR:	BLOCK	1	;ADDR TO RESTART FOR ERROR INTERCEPT
INTBLK:	BLOCK	4	;ERROR INTERCEPT BLOCK
MAXGTB:	BLOCK	1	;HIGHEST LEGAL GETTAB TABLE
RNGTAB:	BLOCK	1	;ADDRESS OF RNGTAB
JBTMXL:	BLOCK	1	;JOBN+SEGN-1.  THIS IS THE MAXIMUM INDEX FOR
			;GETTAB TABLES INDEXED BY JOB OR SEGMENT NUMBER.
			;THE NUMTAB ENTRY IS NOT USED FOR THESE TABLES
			;BECAUSE THE 9 BIT FIELD OVERFLOWS ON SYSTEMS
			;WITH JOBN+SEGN-1 .GT. 511.
MFDPPN:	BLOCK	1
EVAADR:	BLOCK	1	;ADDRESS OF 1ST WORD IN EVABUF
EVABUF:	BLOCK	EVASIZ	;BUFFER FOR FUNNY SPACE DATA FROM PEKUSR
PDLIST:	BLOCK	PDLEN
PTRADR:	BLOCK	1
REMBLK:	BLOCK	1
REMWRD:	BLOCK	1
STRADR:	BLOCK	1	;SAVE .JBSA HERE DURING SAVE
DSKBUF:
SECBUF:	BLOCK	200
SEGREL:	BLOCK	1
SEGSWP:	BLOCK	1
SWPADR:	BLOCK	1
EXECT1:	BLOCK	1	;WORD FOR ADDRESS OF EXEC AC T1 IN USER'S JOBDAT
ERPTBK:	BLOCK	4	;4 WORD BLOCK FOR ERRPT. UUO
.UPJOB:	BLOCK	1	;OFFSET OF JOB NUMBER IN UPMP
.UPLST:	BLOCK	1	;OFFSET OF POINTER TO SWAPPABLE DDBS IN UPMP
LDDBSH:	BLOCK 	1	;LENGTH OF SHORT DDB
LDDBLN:	BLOCK	1	;LENGTH OF LONG DDB
LDDBDS:	BLOCK	1	;LENGTH OF DISK DDB
KONREG:	BLOCK	1	;OFFSET OF # OF DRIVE REGS IN KDB
UNISCR:	BLOCK	1	;OFFSET OF DRIVE REGISTERS IN UNIT DATA BLOCK
UNICCT:	BLOCK	1	;OFFSET TO # BAT SLOTS LEFT IN UDB [463]
CHNTCW:	BLOCK	1	;OFFSET TO EXP. TERM WD IN CDB [463]
			; (I.E. THE VALUE OF .CHTCW)
MONVER:	BLOCK	1	;[545] MONITOR VERSION
IFN FTSVSL,<
PSRCH:	BLOCK	1	;LEN,,ADDR OF OUR SEARCH LIST
SRCLST:	BLOCK	3*^D9+4	;SPACE FOR OUR SEARCH LIST>
USRLST:	BLOCK	3*^D9+4	;SPACE FOR USER SEARCH LIST
THSJOB:	BLOCK	1	;OUR JOB NUMBER
THSLIN:	BLOCK	1	;OUR LINE NUMBER
THSOFF:	BLOCK	1
THSSEG:	BLOCK	1
UPDFLG:	BLOCK	1	;-1 IF MUST DO USETO FOR NORMAL WRITE, 0 IF NOT
USRADR:	BLOCK	1
USRCOR:	BLOCK	MAXUCR+BLKSIZ
USRUPM:	BLOCK	MAXUPM
USRPPN:	BLOCK	1
WRDCNT:	BLOCK	1	;WORDS FROM LAST PATTERN
SWPUNI:	BLOCK	1	;NAME OF SWAP UNIT BEING ACCESSED
SWPSLB:	BLOCK	1	;C(UNISLB) FOR UNIT BEING ACCESSED
SWPTAB:	BLOCK	1	;ADDRESS OF SWPTAB
SWPMAX:	BLOCK	1	;LENGTH OF SWPTAB
UNISLB:	BLOCK	1	;OFFSET OF UNISLB IN UDB
$CHERR:	BLOCK	CHNN	;TOTAL ERRORS EACH CHANNEL
PDBPTR:	BLOCK	1		;ADDRESS OF JBTPDB IN MONITOR FOR SPY
NEXTUP:	BLOCK	1		;NEXT TIME TO CAUSE A WAKE
NEXTJB:	BLOCK	1		;JOB TO WAKE
QPNTR:	BLOCK	1		;POINTER TO QUEUE
OPRPPN:	BLOCK	1		;PPN OF THE OPERATOR
JIFSEC:	BLOCK	1	;JIFFIES PER SECOND
JIFDAY:	BLOCK	1	;JIFFIES PER DAY
MILJIF:	BLOCK	1	;MILLISECONDS PER JIFFY
JDPCNT:	BLOCK	1	;NUMBER OF JOBS SEEN STOPPED FOR HDW ERRORS
UUOJOB:	BLOCK	1	;JOB NUMBER OF JOB DOING LAST DAEMON UUO
UUOFNC:	BLOCK	1	;FUNCTION CODE FROM LAST DAEMON UUO
SAVXWD:	BLOCK	1	;SAVE UUO XWD (FROM EXEC AC T2)
CMDJOB:	BLOCK	1	;JOB NUMBER OF JOB DOING LAST COMMAND
CMDCMD:	BLOCK	1	;COMMAND INDEX OF LAST COMMAND
DFNJOB:	BLOCK	1	;JOB NUMBER OF LAST JOB DAEFIN'ED
UUXCOD:	BLOCK	1	;ERROR CODE RETURNED TO JOB IN UUXJOB
UUXJOB:	BLOCK	1	;JOB WHICH LAST CAME THROUGH UUEXIT
DPMJOB:	BLOCK	1	;JOB NUMBER OF LAST JOB RELEASED BECAUSE
			;JS.DPM WAS ON
DPMCNT:	BLOCK	1	;COUNT OF JOBS RELEASED DUE TO ABOVE
FNCJBS:	BLOCK	1	;DEBUG - LAST JBTSTS READ IN FINCHK
FNCJBA:	BLOCK	1	;DEBUG - LAST JBTADR READ IN FINCHK
FNCJBJ:	BLOCK	1	;DEBUG - LAST JOB OR SEG NUMBER USED IN FINCHK
PDLGUF:	BLOCK	1	;DEBUG - CONTAINS ERRONEOUS P CONTENTS
GTBGUF:	BLOCK	1	;DEBUG - COUNTS MISTAKES IN GTBSPY
ATTGUF:	BLOCK	1	;DEBUG - COUNTS ATTACH FAILURES
FRCGUF:	BLOCK	1	;DEBUG - COUNTS FRCUUO FAILURES
FINGUF:	BLOCK	1	;DEBUG - COUNTS DAEFIN ERROR RETURNS
STRGUF:	BLOCK	1	;DEBUG - COUNTS STRUUO ERROR RETURNS
WAKGUF:	BLOCK	1	;DEBUG - COUNTS ERROR RETURNS FROM WAKE UUO
CLKGUF:	BLOCK	1	;DEBUG - COUNTS CLOCK REQUESTS ON UNASSIGNED CHANNELS
INTGUF:	BLOCK	1	;DEBUG - COUNTS INTERCEPTS
OUTGUF:	BLOCK	1	;COUNTS TIMES WE WANTED TO OUTSTR BUT WERE DETACHED
SWRGUF:	BLOCK	1	;COUNTS SWAP READ ERRORS
SWWGUF:	BLOCK	1	;COUNTS SWAP WRITE ERORS
WRTGUF:	BLOCK	1	;COUNTS FAILURES IN MARKSPT
FCTGUF:	BLOCK	1	;COUNTS FACT FILE ERRORS
BSYFCT:	BLOCK	1	;COUNTS TIMES FACT FILE BEING MODIFIED TOO LONG
SPTGUF:	BLOCK	1	;DEBUG - COUNTS SWAPPING POINTER FAILURES
HSSGUF:	BLOCK	1	;DEBUG - COUNTS HIGH SEG STATUS FAILURES
UPMGUF:	BLOCK	1	;DEBUG - COUNTS UPMP FAILURES
SUOGUF:	BLOCK	1	;DEBUG - COUNTS SWAP UNIT OPEN FAILURES
SWPGUF:	BLOCK	1	;DEBUG - COUNTS SWAP POINTER INCONSISTENCIES
CURJOB:	BLOCK	1	;DEBUG - LAST JOB SERVICED
INTFLG:	BLOCK	1	;DEBUG - REASONS FOR LAST JOBINT
INTPC:	BLOCK	1	;DEBUG - PC OF LAST JOBINT
WTUERR:	BLOCK	1	;FLAG TO PREVENT RECURSIVE CALLS OF WTUCOR WHEN
			;IT GETS IO ERRORS ON THE SWAPPING DEVICE WHILE
			;ATTEMPTING TO WRITE THE EXIT VALUES FOR A UUO.
IPCPDB:	BLOCK 6		;[602]IPCF PACKET DESCRIPTOR BLK \*** KEEP
SSELBK:	BLOCK 10	;[602]IPCF MSG AREA		 /*** TOGETHER
IFN FTDEBG,<		;DON'T WASTE SPACE
PATT:	BLOCK	100	;SPACE FOR PATCHES>
SAVEP4:	BLOCK	1		;SAVE P4 HERE IN ERRFIN
FACTSZ:	BLOCK	1		;NUMBER OF WORDS IN FACT BUFFER
NXMLEN:	BLOCK	1		;LENGTH OF NXMTAB
NXMTAB:	BLOCK	1		;POINTER TO FIRST COPY OF NXMTAB
				; SUPPORT IN THIS MONITOR
ERRBUF:	BLOCK	BLKSIZ	;LAST BLOCK OF ERROR.SYS READ HERE
ERABUF:	BLOCK	ERRSIZ+EL.HED+2	;WHERE TO PUT THE NEW STUFF
ERAEND==.-1
MRVBLK:	BLOCK	ERRSIZ+EL.HED+2	;AVAIL.SYS WORKING ENTRY
MRVEND==.-1
MRVBDY==MRVBLK+EL.HED
;*****************************************************************
;SUB-BLOCK POINTERS USED IN THE ERROR ENTRIES ARE NOT CONSISTENT.
;SOMETIMES THE POINTER IS +LEN,,OFFSET WHILE OTHER TIMES IT IS
;-LEN,,OFFSET.  TO MAKE MATTERS WORSE, "OFFSET" IS SOMETIMES THE
;OFFSET FROM THE FIRST WORD OF THE HEADER AND SOMETIMES THE OFFSET
;FROM THE FIRST WORD OF THE ENTRY AFTER THE HEADER.  HOPEFULLY SOMEBODY
;WILL MAKE THEM ALL -LEN,,OFFSET FROM FIRST DATA WORD SOMEDAY.  IN
;ORDER TO MAKE THIS A LITTLE EASIER, THE FOLLOWING TWO SYMBOLS ARE
;DEFINED AND USED:
;	ERABFH - USED TO INDICATE THAT THE OFFSET IS FROM THE
;		 START OF THE HEADER.
;	ERABFS - USED TO INDICATE THAT THE OFFSET IS FROM THE
;		 FIRST WORD OF DATA AFTER THE HEADER.
ERABFH==ERABUF		;START OF THE HEADER
ERABFS==ERABUF+EL.HED	;FIRST WORD OF DATA AFTER THE HEADER
;*****************************************************************
GOBBUF:
DAEBUF:	BLOCK	BLKSIZ	;BUFFER FOR DUMP IO
IFN FTFACT!FTCHKPNT,<
FACTBF:	BLOCK	MAXFCT+TRNSIZ+1	;FACT FILE BUFFER
>;END COND ON FTFACT!FTCHKPNT
EZER==.-1
	SUBTTL	SCANER		COMMAND SCANNER FOR DEMON

	IFNDEF	LINSIZ,<LINSIZ==^D135>	;MAX CHARS/LINE
	IFNDEF	.FXLNF,<.FXLNF==6>	;MAX DIRECTORY NESTING

;FLAGS IN SF

	F%BRK==1B0		;SIGN BIT -- ON IF BREAK SEEN
	F%SOM==1B1		;ON IF SOME INPUT SEEN IN FILE SPEC COLLECTOR
	F%EXT==1B2		;EXTENSION SPECIFIED
	F%OCT==1B3		;VALID INPUT FROM OCTIN

;IMPORTANT NON-PRINTING CHARACTERS

	.CHNUL==0	;NULL
	.CHBEL==7	;BELL
	.CHTAB==11	;TAB
	.CHLFD==12	;LINE FEED
	.CHVTB==13	;VERTICAL TAB
	.CHFFD==14	;FORM FEED
	.CHCRT==15	;CARRIAGE RETURN
	.CHCNR==22	;CONTROL R
	.CHCNU==25	;CONTROL U
	.CHCNZ==32	;CONTROL Z
	.CHESC==33	;ESCAPE
	.CHDEL==177	;RUBOUT
	SUBTTL	INITIALIZE COMMAND SCANNER

;ISCAN - INITIALIZE, RESCAN, AND INPUT MONITOR COMMAND
;TSCAN - CALLED AFTER ISCAN TO INPUT A COMMAND OR KEYWORD
;CALL WITH C(T1)=IOWD TO LIST OF MONITOR COMMANDS
;RETURNS WITH C(T1)=INDEX INTO MONITOR COMMAND LIST OR -1

.ISCAN:	TLO	SF,(F%BRK)	;MARK END OF LINE SO NEW COMMAND
				; WILL BE SCANNED
	RESCAN	1		;COMMAND?
	SKPINL			;?
	  JRST	RETNEG		;NO COMMAND, RETURN -1

.TSCAN:	PUSH	P,T1		;SAVE IOWD
	PUSHJ	P,SIXIN		;READ SIXBIT COMMAND
	POP	P,T4		;RESTORE PTR TO COMMAND TABLE
	PUSHJ	P,NAME		;FIND NAME IN TABLE
RETNEG:	  SKIPA	T1,[EXP -1]	;RETURN -1 FOR NOT FOUND
	HRRZ	T1,T2		;INDEX INTO T1
	POPJ	P,		;AND RETURN
	SUBTTL	SUBROUTINES

;MAKPJN	SUBROUTINE TO MAKE CCL JOB NUMBER
;ARGS	T2=JOB NUMBER
;VALUES	T4=CCL JOB NUMBER

MAKPJN:	PUSH	P,P1		;SAVE P1
	MOVEI	P1,3		;3 DIGITS
MAKPJ1:	IDIVI	T2,^D10		;DIVIDE BY DECIMAL 10
	ADDI	T3,'0'		;MAKE SIXBIT REMAINDER
	LSHC	T3,-6		;SHIFT INTO T4
	SOJG	P1,MAKPJ1	;LOOP
	POP	P,P1		;RESTORE P1
	POPJ	P,		;RETURN

;TSIXN - TYPE C(T2) AS SIXBIT, NO TRAILING BLANKS

TSIX:	SETZ	T1,		;MAKE ROOM
	LSHC	T1,6		;GET CHAR IN T1
	MOVEI	SC,40(T1)	;MAKE ASCII IN SC
	PUSHJ	P,TYPCHR	;TYPE IT
TSIXN:	JUMPN	T2,TSIX		;LOOP IF MORE
	POPJ	P,		;DONE

;TOCT - TYPE OCTAL VALUE GIVEN IN T1

TOCT:	IDIVI	T1,^D8		;DIVIDE OUT
	JUMPE	T1,TOCT1	;EXIT IF NO MORE
	HRLM	T2,(P)		;SAVE REMAINDER
	PUSHJ	P,TOCT		;LOOP
	HLRZ	T2,(P)		;RESTORE DIGIT
TOCT1:	MOVEI	SC,"0"(T2)	;MAKE ASCII
	PUSHJ	P,TYPCHR	;TYPE
	POPJ	P,		;RETURN

;TDEC - TYPE DECIMAL VALUE GIVEN IN T1

TDEC:	IDIVI	T1,^D10		;DIVIDE OUT
	JUMPE	T1,TDEC1	;EXIT IF NO MORE
	HRLM	T2,(P)		;SAVE REMAINDER
	PUSHJ	P,TDEC		;LOOP
	HLRZ	T2,(P)		;RESTORE DIGIT
TDEC1:	MOVEI	SC,"0"(T2)	;MAKE ASCII
	PUSHJ	P,TYPCHR	;TYPE
	POPJ	P,		;RETURN
;TPPN - SUBROUTINE TO TYPE A PPN
;CALL	MOVE	T2,PPN
;	PUSHJ	P,TPPN
;USES T1,T2,T3,SC

TPPN:	MOVEI	SC,"["		;OPEN BRACKET
	PUSHJ	P,TYPCHR
	PUSHJ	P,THALF		;TYPE PPN AS HALFWORD OCTAL
	MOVEI	SC,"]"		;CLOSE BRACKET
	PJRST	TYPCHR		;TYPE IT AND RETURN


;THALF - SUBROUTINE TO TYPE A NUMBER AS HALFWORD OCTAL
;CALL	MOVE	T2,NUMBER
;	PUSHJ	P,THALF
;USES T1,T2,T3,SC

THALF:	HRLM	T2,(P)		;SAVE PROGRAMMER NO.
	HLRZ	T1,T2		;SET UP PROJECT NO.
	PUSHJ	P,TOCT		;TYPE IT
	MOVEI	SC,","		;COMMA
	PUSHJ	P,TYPCHR
	HLRZ	T1,(P)		;RESTORE PROGRAMMER NO.
	PJRST	TOCT		;TYPE IT AND RETURN
	SUBTTL	GATHER FILE SPECIFICATION

;FILSPC - INPUT A FILE SPECIFICATION OF THE FORM
;DEV:FILE.EXT[P,PN,SFD1,SFD2,...]

FILIN:	SETZM	F.ZER		;GET SET
	MOVE	T1,[F.ZER,,F.ZER+1]	;TO CLEAR DATA
	BLT	T1,F.EZER	;BLITTTTT!
	TLZA	SF,(F%SOM!F%EXT);NOTHING YET
FILSP0:	JUMPL	SF,CPOPJ1	;RETURN AT END OF LINE
	PUSHJ	P,SIXINX	;READ A SIXBIT WORD
	JUMPN	T1,FILSP5	;IF NON-NULL WORD SEEN, GO PROCESS IT
	JUMPL	SF,CPOPJ1	;RETURN IF AT END OF LINE

FILSP5:	TLO	SF,(F%SOM)	;SOME INPUT HAS BEEN SEEN
	CAIE	SC,":"		;COLON?
	  JRST	FILSP1		;NO
	SKIPE	F.DEV		;YES, DEVICE ALREADY SEEN?
	  PJRST	MULDEV		;YES, ERROR
	JUMPE	T1,NULDEV	;NULL DEVICE ILLEGAL
	MOVEM	T1,F.DEV	;STORE DEVICE NAME
	JRST	FILSP0		;GO BACK FOR MORE INPUT

FILSP1:	JUMPE	T1,FILSP2	;GO IF NO FILE NAME SEEN
	SKIPE	F.NAM		;ALREADY SEEN A FILE NAME?
	  PJRST	MULNAM		;YES, ERROR
	MOVEM	T1,F.NAM	;STORE NAME

FILSP2:	JUMPL	SF,CPOPJ1	;RETURN IF EOL
	CAIE	SC,"["		;LEFT SQUARE BRACKET?
	  JRST	FILSP3		;NO
	SKIPE	F.DIR		;DIRECTORY ALREADY SEEN?
	  PJRST	MULDIR		;YES, ERROR
	PUSHJ	P,FDIRIN	;READ A DIRECTORY SPECIFICATION
	  POPJ	P,		;ILLEGAL DIRECTORY
	JRST	FILSP0		;GOT IT.  GO BACK FOR MORE

FILSP3:	CAIE	SC,"."		;WAS TERMINATOR A PERIOD?
	  JRST	SYNERR		;NO
	TLOE	SF,(F%EXT)	;YES, EXTENSION ALREADY SEEN?
	  PJRST	MULEXT		;YES, MULTIPLE EXTENSION ILLEGAL
	PUSHJ	P,SIXINX	;READ EXTENSION
	HLLZM	T1,F.EXT	;STORE EXTENSION
	SETZ	T1,		;CLEAR NAME
	JRST	FILSP5		;AND LOOP
;FDIRIN - RETURN C(F.DIR)=DIRECTORY
;INCLUDING SFD'S (UP TO .FXLNF ALTOGETHER)
;NON-SKIP RETURN IF ERROR

FDIRIN:	MOVEI	T1,F.DIRP	;GET POINTER TO PATH BLOCK
	MOVEM	T1,F.DIR	;SAVE IN DIRECTORY POINTER
	PUSHJ	P,OCTIN		;GET PROJECT NUMBER
	CAIE	SC,","		;TERMINATED BY COMMA?
	  PJRST	ILLDIR		;NO, ERROR
	TLNN	SF,(F%OCT)	;ANYTHING?
	  HLRZ	T2,USRPPN	;NO, GRAB DEFAULT
	TLNN	T2,-1		;[605] OVERFLOW TO LH?
	TRNE	T2,400000	;[605] SIGN BIT SET?
	SKIPA			;[605]
	TRNN	T2,-1		;[605] PROJECT 0?
	  PJRST	ILLDIR		;YES, BOUNCE THIS JERK!
	HRLM	T2,F.PTH	;SAVE VALUE
	PUSHJ	P,OCTIN		;GET PROGRAMMER
	TLNN	SF,(F%OCT)	;IF NOTHING
	  HRRZ	T2,USRPPN	;GRAB DEFAULT
	TLNN	T2,-1		;CHECK AGAIN
	TRNN	T2,-1		; ..
	  PJRST	ILLDIR		;SOME PEOPLE NEVER GIVE UP
	HRRM	T2,F.PTH	;SAVE
	CAIE	SC,","		;SFD'S COMING?
	  JRST	FDIRI0		;NO, NO SFD'S
	PUSHJ	P,SAVE1		;SAVE AN AC

	MOVSI	P1,-<.FXLNF-1>	;MAX NUMBER OF SFD'S
FDIRI1:	PUSHJ	P,SIXINX	;GET SFD NAME
	MOVEM	T1,F.PTH+1(P1)	;STORE SFD NAME
	CAIE	SC,","		;MORE COMING?
	  JRST	FDIRI0		;NO, WE ARE DONE
	AOBJN	P1,FDIRI1	;GO GET NEXT
	ERROR	<Too many SFD's in file spec>
	POPJ	P,		;THAT'S TELLING HIM

FDIRI0:	CAIN	SC,"]"		;TERMINATED BY BRACKET?
	  JRST	CPOPJ1		;YES, RETURN NOW
	JUMPL	SF,CPOPJ1	;ALSO RETURN IF EOL

ILLDIR:	ERROR	<Illegal directory spec>
	POPJ	P,		;RETURN
;SUB TO GET NEXT CHAR FROM TTY INPUT BUFFER
;LOADS SC, USES NO AC'S
;IF BREAK, F%BRK (SIGN BIT) OF SF IS SET AND SC IS SET TO -1

TYIA:	JUMPGE	SF,GETB3	;JUMP IF MORE CHAR'S LEFT
	PUSHJ	P,SAVE2		;NO -- READ IN LINE
	TLZ	SF,(F%BRK)	;NO BREAK YET

	MOVE	P2,TTIBP	;LOAD PTR TO BEG OF BUF
	MOVEM	P2,TTIPTR	;STORE FOR LATER USE

	MOVEI	P1,LINSIZ	;LOAD SIZE IN BYTES
FILL1:	INCHSL	SC		;OK, GET NEXT CHAR
	  MOVEI	SC,.CHLFD	;NONE, RETURN LINE FEED
	PUSHJ	P,ISBRK		;PLACE IN BUFFER, SEE IF BREAK
	  JRST	GETB3		;WELL, THAT'S A BREAK
	SOJG	P1,FILL1	;LOOP
	CLRBFI			;LINE TOO LONG -- BUFFER FULL
	ERROR	<Input line too long>
	MOVEI	SC,.CHNUL	;SET UP NULL BYTE
	DPB	SC,P2		;AND CONCLUDE WITH EOL
;	JRST	GETB3		;PROCEED

GETB3:	ILDB	SC,TTIPTR	;GET FROM BUFFER
	JUMPN	SC,CPOPJ	;IF NOT NULL, GOOD CHAR
	TLO	SF,(F%BRK)	;ELSE FLAG BREAK
	SOJA	SC,CPOPJ	;SET ALL BITS OF SC AND RETURN
BRKTAB:	EXP .CHBEL,.CHLFD,.CHVTB,.CHFFD,.CHCNR,.CHCNU
	EXP .CHCNZ,.CHESC,.CHDEL
BRKLEN==.-BRKTAB

;ISBRK - SKIP RETURN IF NOT A BREAK CHARACTER

ISBRK:	CAIN	SC,.CHCRT	;IGNORE CARRIAGE RETURN
	  AOJA	P1,CPOPJ1	;INCREMENT CHAR COUNT FOR IGNORE
	PUSHJ	P,SAVE1		;SAVE AN AC
	MOVSI	P1,-BRKLEN	;GET LENGTH OF TABLE
	CAMN	SC,BRKTAB(P1)	;MATCH?
	  TDZA	SC,SC		;YES, REPLACE WITH NULL
	AOBJN	P1,.-2		;NO, TRY NEXT
	CAIN	SC,.CHTAB	;CONVERT TABS
	  MOVEI	SC," "		;TO SPACES
	CAIG	SC,"Z"+40	;CONVERT LC
	CAIGE	SC,"A"+40	; ..
	  JRST	.+2
	MOVEI	SC,-40(SC)	;TO UC
	IDPB	SC,P2		;SAVE CHAR AWAY
	CAIE	SC,";"		;CHECK FOR COMMENT COMING
	  JUMPN	SC,CPOPJ1	;ELSE RETURN IF NOT BREAK
	JUMPE	SC,CPOPJ	;NON-SKIP IF BREAK
	MOVEI	SC,.CHNUL	;COMMENT -- INSERT TERMINATOR
	DPB	SC,P2		;INSERT
	JRST	CPOPJ1		;AND SKIP RETURN

;ROUTINE TO IGNORE SPACES AND SCAN FOR GOOD CHAR
STYIA:	PUSHJ	P,TYIA		;GET CHAR
	CAIN	SC," "		;IGNORE SPACES
	  JRST	STYIA		;LOOP
	POPJ	P,		;GOOD CHAR, RETURN
;NAME - SCAN TABLE FOR COMMAND OR UNIQUE ABBREVIATION
;CALL WITH C(1)=SIXBIT COMMAND, C(T4)=IOWD TABLE LENGTH,TABLE ADR
;RETURNS C(T2)=INDEX INTO TABLE, ALWAYS PRESERVES T1
;CPOPJ1 IF MATCH FOUND, USES T2-T4

NAME:	PUSHJ	P,SAVE2		;SAVE P1 AND P2
	SETZB	P1,T3		;CLEAR
	SKIPN	T2,T1		;COPY COMMAND INTO T2
	  SOJA	T3,NAME2	;SET UP MASK, GO IF NULL COMMAND
	SOJA	T3,NAME1	;SET UP INITIAL MASK (-1) AND GO

NAME0:	LSH	T2,-6		;SHIFT 1 CHAR TO THE RIGHT
	LSH	T3,6		;AND ONE TO THE LEFT
NAME1:	TRNN	T2,77		;A CHAR IN RIGHTMOST POSITION?
	  JRST	NAME0		;NO, TRY SOME MORE

NAME2:	HRLI	P2,1(T4)	;REMEMBER START OF COMMAND TABLE
NAMELP:	CAMN	T1,1(T4)	;EXACT MATCH?
	  JRST	NAMEFN		;YES
	MOVE	T2,1(T4)	;CANDIDATE INTO T2
	AND	T2,T3		;MASKED TO CORRECT # OF CHARACTERS
	CAME	T1,T2		;GOT A MATCH?
	AOBJN	T4,NAMELP	;NO, TRY NEXT ONE
	JUMPGE	T4,NAMTST	;YES, YOUR FACE AND ...
	TROE	P1,1		;MARK THAT ONE WAS FOUND
	  TRO	P1,2		;TWO WERE FOUND
	HRRI	P2,1(T4)	;REMEMBER WHERE
	AOBJN	T4,NAMELP	;LOOK FOR MORE MATCHES

NAMTST:	CAIE	P1,1		;ONE MATCH FOUND?
	  POPJ	P,		;NO, COMMAND UNKNOWN OR NOT UNIQUE
	JRST	NAMDSP		;GOOD RESULT

NAMEFN:	HRRI	P2,1(T4)	;EXACT MATCH, RH(P2)=INDEX OF COMMAND
NAMDSP:	HLRZ	T4,P2		;BASE OF TABLE
	SUBI	P2,(T4)		;OFFSET INTO TABLE
	HRRZ	T2,P2		;RETURN RESULT IN T2
	JRST	CPOPJ1		;SKIP RETURN
;SIXINX - LIKE SIXIN, EXCEPT ADVANCES TTY INPUT SO NEXT CHARACTER
;WILL BE RELEVANT

SIXINX:	PUSHJ	P,SIXIN		;READ
	CAIN	SC," "		;SPACE?
	  PJRST	STYIA		;YES, READ NULLS
	POPJ	P,		;NO, RETURN

;SIXIN - RETURNS C(T1)=UP TO SIX CHARACTERS OF SIXBIT
;USES T2,SC

SIXIN:	PUSHJ	P,STYIA		;GET A CHAR
	SETZ	T1,		;CLEAR COLLECTOR
	MOVE	T2,[POINT 6,T1]	;SET UP BYTE POINTER
SIXIN1:	CAIL	SC,"0"		;SEE IF ALPHANUMERIC
	CAILE	SC,"Z"		; ..
	  POPJ	P,		;NO
	CAIGE	SC,"A"		; ..
	CAIG	SC,"9"		; ..
	  JRST	.+2		;OK
	  POPJ	P,		;BAD
	SUBI	SC,40		;MAKE SIXBIT
	TLNE	T2,770000	;SIX CHARACTERS YET?
	IDPB	SC,T2		;NO, LOAD IT IN
	PUSHJ	P,TYIA		;GET NEXT
	JRST	SIXIN1		;LOOP
	SUBTTL	NUMERIC INPUT

;OCTINW - READ OCTAL NUMBER FROM COMAND STREAM INTO SN

OCTINW:	PUSHJ	P,OCTIN		;GET OCTAL NUMBER IN T2
	MOVE	SN,T2		;MOVE
	POPJ	P,		;RETURN

;OCTIN - READ OCTAL NUMBER INTO T2

OCTIN:	PUSHJ	P,STYIA		;SKIP SPACES
	SETZB	T2,T3		;CLEAR COUNT
	TLZ	SF,(F%OCT)	;NOTHING IN YET
	CAIN	SC,"#"		;FORCING OCTAL (WHICH IS DEFAULT)?
	  PUSHJ	P,TYIA		;YES, IGNORE AND GET NEXT CHAR
OCTIN0:	CAIG	SC,"9"		;RANGE CHECK
	CAIGE	SC,"0"		; ..
	  JRST	OCTIN1		;NO, EXIT LOOP
	TLO	SF,(F%OCT)	;FLAG SOMETHING IN
	LSH	T2,3		;SHIFT OVER RESULT
	ADDI	T2,-"0"(SC)	;AND ADD OCTAL
	IMULI	T3,^D10		;AND KEEP UP DECIMAL COUNT ALSO
	ADDI	T3,-"0"(SC)	; ..
	PUSHJ	P,TYIA		;NEXT
	JRST	OCTIN0		;LOOP

OCTIN1:	CAIE	SC,"."		;FORCING DECIMAL?
	  POPJ	P,		;NO, RETURN NOW
	MOVE	T2,T3		;YES, USE DECIMAL COUNT
	PJRST	TYIA		;GET NEXT CHAR AND RETURN
	SUBTTL	ACCUMULATOR SAVERS

;ROUTINES TO SAVE P1-PX.  ALL ARE CALLED WITH PUSHJ P,SAVEX

SAVE1:	EXCH	P1,(P)		;COMMENTS SAME
	MOVEM	P1,1(P)
	MOVE	P1,(P)
	PUSHJ	P,@1(P)
	  JRST	RET1
	AOS	-1(P)
	JRST	RET1		;RESTORE P1 AND RETURN

SAVE2:	EXCH	P1,(P)		;GET RETURN, SAVE P1
	PUSH	P,P2		;SAVE P2
	MOVEM	P1,1(P)		;SAVE RETURN
	MOVE	P1,-1(P)	;RESTORE P1
	PUSHJ	P,@1(P)		;CALL CALLER
	  JRST	RET2
	AOS	-2(P)		;SKIP RET
	JRST	RET2		;RESTORE P1,P2 AND RETURN

SAVE3:	EXCH	P1,(P)		;GET RETURN, SAVE P1
	PUSH	P,P2		;SAVE P2
	PUSH	P,P3		;SAVE P3
	MOVEM	P1,1(P)		;SAVE RETURN
	MOVE	P1,-2(P)	;RESTORE P1
	PUSHJ	P,@1(P)		;CALL CALLER
	  JRST	RET3
	AOS	-3(P)		;SKIP RET
	JRST	RET3		;RESTORE P1-P3 AND RETURN

SAVE4:	EXCH	P1,(P)		;GET RETURN, SAVE P1
	PUSH	P,P2		;SAVE P2
	PUSH	P,P3		;SAVE P3
	PUSH	P,P4		;SAVE P4
	MOVEM	P1,1(P)		;SAVE RETURN
	MOVE	P1,-3(P)	;RESTORE P1
	PUSHJ	P,@1(P)		;CALL CALLER
	  JRST	RET4
	AOS	-4(P)		;SKIP RET
RET4:	POP	P,P4		;RESTORE P4
RET3:	POP	P,P3		;RESTORE P3
RET2:	POP	P,P2		;RESTORE P2
RET1:	POP	P,P1		;RESTORE P1
	POPJ	P,		;RETURN
	SUBTTL	ERROR MESSAGES

MULDEV:	ERROR	<Multiple device specs illegal>
	POPJ	P,

MULDIR:	ERROR	<Multiple directory specs illegal>
	POPJ	P,

MULEXT:	ERROR	<Multiple file extension illegal>
	POPJ	P,

MULNAM:	ERROR	<Multiple file name illegal>
	POPJ	P,

NULDEV:	ERROR	<Null device illegal>
	POPJ	P,

SYNERR:	ERROR	<Syntax error>
	POPJ	P,
;ROUTINE TO STORE A STRING IN THE MESSAGE BUFFER.
;CALL	MOVEI	T1,ADDRESS OF STRING
;	PUSHJ	P,TYPSTR
;	ALWAYS RETURN HERE

TYPSTR:	PUSH	P,SC		;SAVE SC
	HRLI	T1,(POINT 7,0)	;MAKE IT AN ASCII BYTE POINTER
TYPST1:	ILDB	SC,T1		;GET NEXT CHARACTER OF STRING
	JUMPE	SC,TYPST2	;DONE ON ZERO BYTE
	PUSHJ	P,TYPCHR	;STORE THE CHARACTER
	JRST	TYPST1		;LOOP FOR NEXT
TYPST2:	POP	P,SC		;RESTORE SC
	POPJ	P,		;  AND RETURN


;ROUTINE TO STORE ONE CHARACTER IN THE MESSAGE BUFFER AND FLUSH
;THE BUFFER WHEN A LINE FEED IS SEEN.
;CALL	MOVEI	SC,CHARACTER
;	PUSHJ	P,TYPCHR
;	ALWAYS RETURN HERE

TYPCHR:	SOSL	MSGCNT		;ROOM IN THE BUFFER?
	IDPB	SC,MSGPTR	;YES, STORE THE CHARACTER
	CAIE	SC,.CHLFD	;LINE FEED?
	POPJ	P,		;NO, RETURN NOW

DMPBUF:	PUSHJ	P,SAVE1		;SAVE P1
	MOVEI	P1,0		;STORE A ZERO BYTE AT
	IDPB	P1,MSGPTR	;  THE END OF THE STRING
	MOVE	P1,[3,,MSGARG]	;GET ARG FOR TRMOP.
	TRMOP.	P1,		;TYPE THE STRING ON THE USER'S TERMINAL
	  CAIA			;FAILED, HAVE TO USE OUTSTR
	JRST	TYPCH1		;GO RESET THE POINTERS
	PUSHJ	P,ATTCHK	;ATTACHED TO A TERMINAL?
	  JRST	TYPCH1		;NO, FORGET IT
	OUTSTR	MSGBUF		;TYPE THE STRING WITH OUTSTR
TYPCH1:	TLNE	F,L.OPR		;TELL OPERATOR ALSO?
	TLNE	F,L.INI		;  AND NOT DURING INITIALIZATION?
	JRST	TYPCH2		;NO
	MOVE	P1,[SIXBIT/OPR0/] ;GET NAME OF CENTRAL STATION OPR
	IONDX.	P1,		;GET THE TTY NUMBER (MAY HAVE CHANGED)
	  CAIA			;USE LAST ONE WE KNEW ABOUT
	MOVEM	P1,OPRLIN	;STORE IT
	MOVE	P1,[3,,OPRARG]	;GET ARG FOR TRMOP.
	TRMOP.	P1,		;TELL THE OPERATOR
	  JFCL			;WE TRIED
TYPCH2:	MOVE	P1,MSGPT1	;GET VIRGIN BYTE POINTER
	MOVEM	P1,MSGPTR	;AND STORE IT IN WORKING POINTER
	MOVEI	P1,LINSIZ	;GET MAX CHARS IN STRING
	MOVEM	P1,MSGCNT	;AND SAVE NEW COUNT
	POPJ	P,		;RETURN
;ROUTINE TO FIND THE TTY TO WHICH WE ARE TO WRITE OUR MESSAGES.
;THIS TTY IS, IN ORDER:  OPR0, CTY, OPR.
;CALL	PUSHJ	P,FNDOPR
;	RETURN HERE IF COULDN'T FIND ONE
;	RETURN HERE IF FOUND ONE WITH TTY UDX IN T1

FNDOPR:	MOVE	T1,[SIXBIT/OPR0/] ;FIRST TRY WITH OPR0
	IONDX.	T1,		;GET IT
	  CAIA			;FAILED
	JRST	CPOPJ1		;RETURN
	MOVSI	T1,'CTY'	;SECOND TRY IS CTY
	IONDX.	T1,		;GET IT
	  CAIA			;FAILED
	JRST	CPOPJ1		;RETURN
	MOVSI	T1,'OPR'	;THIRD TRY IS OPR
	IONDX.	T1,		;GET IT
	  POPJ	P,		;FAILED, RETURN
	JRST	CPOPJ1		;RETURN
	SUBTTL	STORAGE

;CONSTANTS

TTIBP:	POINT	7,TTIBUF
MSGCNT:	EXP	LINSIZ		;COUNTER FOR MESSAGE BUFFER
MSGPT1:	POINT	7,MSGBUF	;INITIAL POINTER FOR MESSAGE BUFFER
MSGPTR:	POINT	7,MSGBUF	;WORKING POINTER FOR MESSAGE BUFFER
MSGARG:	EXP	.TODSP		;TRMOP. ARG BLOCK TO TYPE MESSAGE
MSGLIN:	BLOCK	1		; ON USER'S TERMINAL
	EXP	MSGBUF
OPRARG:	EXP	.TODSP		;TRMOP. ARG BLOCK TO TYPE MESSAGE
OPRLIN:	BLOCK	1		;  ON DEVICE OPR
	EXP	MSGERR

;VARIABLES

TTIPTR:	BLOCK	1
TTIBUF:	BLOCK	<LINSIZ+4>/5

;***** KEEP THE FOLLOWING TOGETHER
MSGERR:	ASCII/DAEMON error - /
MSGBUF:	BLOCK	<<LINSIZ+4>/5>+1
;***** END OF KEEP TOGETHER

;FILE SPECIFICATION AREA

F.ZER:!
F.DEV:	BLOCK	1
F.NAM:	BLOCK	1
F.EXT:	BLOCK	1
F.DIR:	BLOCK	1	;PTR TO DIRECTORY
F.DIRP:	BLOCK	2
F.PTH:	BLOCK	.FXLNF	;ROOM FOR DIRECTORY
F.EZER==.-1

	END	DAEMON