Google
 

Trailing-Edge - PDP-10 Archives - BB-FI82B-DD_1989 - 35,1414/wtcher.mac
There is 1 other file named wtcher.mac in the archive. Click here to see a list.
TITLE	WTCHER - WATCHDOG FOR ACCEPTENCE	3 JAN 76
SUBTTL	S. MEIDELL

	SEARCH UUOSYM,MACTEN

WTCVER==1
WTCEDT==0
WTCMIN==0
WTCWHO==0
.JBVER==137
	LOC	.JBVER
	VRSN.	(WTC)
	RELOC

;I/O CHANNEL DEFINITIONS

TTY==1
DSK==2
DS1==3

;AC DEFINITIONS

F=0	;FLAG REGISTER
T1=1	;TEMPORARIES - 
T2=2	;THESE REGISTERS ARE NEVER
T3=3	;GUARANTEED TO BE RETURNED IN
T4=4	;THE SAME STATE UNLESS
T5=5	;SPECIFICALLY STATED IN SUB SPEC
P1=6	;PERMANENT REGISTERS -
P2=7	;THESE ARE PRESERVED THROUGH ALL
P3=10	;SUBROUTINE CALLS
P4=11	; - - - 
N=12	;NUMERIC I/O REG
N1=13	;TEMP FOR NUMERIC CONVERSION
R=14	;RADIX REG
M=15	;MESSAGE REGISTER
CH=16	;CHARACTER REGISTER
P=17	;PDL

;MISCELLANEOUS DEFINITIONS

PDLEN==20	;LENGTH OF PUSH-DOWN LIST
GT.PRC==1B9	;BIT IN IMMEDIATE GETTAB TO DETERMINE IF IN PDB OR NOT
;BIT DEFINITIONS FOR FLAG REGISTER
;	LEFT HALF DEFINITIANS
VMSER==400000	;THIS IS VM MONITOR
BREAK==200000	;BREAK CHARACTER ENCOUNTERED
NEWSLP==100000	;DAEMON SHOULD BE CALLED TO RESET SLEEP TIME
DSKEOF==040000	;DISK INPUT EOF FOUND
DATWRN==020000	;OVER DATA ERROR MAXIMUM WARNING
DEVWRN==010000	;OVER DEVICE ERROR MAXIMUM WARNING
TOTWRN==004000	;OVER TOTAL HARD ERROR MAXIMUM WARNING
WHTREQ==002000	;WHAT PROCESSING IS REQUESTED DO NOT UPDATE FILE
NOTNEW==001000	;CREATE ONLY OPN FAILED, SO THIS IS RESTART(OR ERROR?)
NOCALC==000400	;USE UDB VALUE, DON'T COMPUTE A DELTA (DELTA)
NOREAD==000200	;DO NOT READ DISK FILE, IMPLIES NOCALC (DELTA)
DOALL==000100	;RESET ALL UNIT DATA
DECMAL==2	;DON'T PRINT DECIMAL POINT IF ON(DECPRT)
BPAF==1		;STOP AT FIRST NULL CHARACTER IN CONVERSION
	SUBTTL	UNIT DATA BLOCK ITEMS

UNINAM==0		;UNIT NAME
UNILOG==1		;LOGICAL UNIT WITHIN STR
UNIHID==2		;PACK ID
UNISYS==3		;LH - ADDR OF NEXT UDB IN SYSTEM
			;	0 IF LAST UDB
UNISTR==4		;LH - ADDR OF NEXT UDB IN STR
			;RH - UP POINTER TO STR DATA BLOCK
UNICHN==5		;LH - ADDR OF NEXT UDB ON CHANNEL (RING)
			;RH - UP POINTER TO CDB
UNIKON==6		;POINTER TO KON BLOCK FOR THIS UNIT
UNISWP==7		;POINTER TO NEXT SWAPPING UNIT
UNIHCT==10		;HARD ERRORS ON THIS UNIT
			;LH - DEVICE AND SEARCH ERRORS
			;RH - DATA ERRORS
UNISCT==11		;SOFT ERRORS - SAME FORMAT AS UNIHCT
UNIMCT==12		;SOFTWARE DETECTED ERRORS (3 FIELDS OF 12 BITS)
			;SAT FAILS, RIB REDUNDENCY, CHECKSUM
UNIERR==13		;LAST ERROR STATUS ON DEV AFTER FIRST RECOV TRY
UNISOF==14		;ERROR STATUS BEFORE RECOV 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
UNIDWC==21		;BLOCKS WRITTEN IN DUMP MODE
UNIMRC==22		;BLOCKS READ FOR MONITOR
UNIMWC==23		;BLOCKS WRITTEN FOR MONITOR
UNIICT==24		;SWAP READS (ALSO COUNTED IN UNIMRC)
UNIOCT==25		;SWAP WRITES (ALSO COUNTED IN UNIMWC)
UNIMSC==26		;NO. OF MONITOR AND SWAPPING SEEKS
UNIUSC==27		;NO. OF USER(INCL. GET'S & SAVE'S) SEEKS
UNIPCT==30		;SEEK INCOMPLETE ERRORS
UNISDI==32		;DATAI ON LAST ERROR BEFORE RECOV TRY
UNIHDI==33		;DATAI AFTER FAILURE OF FIRST RECOV TRY
UNIECT==34		;NO. OF RETRIES+INITIAL ATTEMPT WHICH FAILED
			;	BIT 0 SET IF SUCESSFUL OPERATIONS SINCE
UNIHNG==35		;HUNG RECOVERY (4 FIELDS OF 9 BITS)
			;	# NOT RECOV BY STOP UNIT IN TRAN STATE
			;	# RECOV BY STOP UNIT IN TRANS STATE
			;	#CAUSED BY UNIT IN POS STATE AND RECOV AUTO
			;# RECOV BY RESTARTING UNIT, IDLE OR TRANS STATE
UNICDA==40		;RH - ADDR OF DDB FOR CURRENT FILE
UNIPCI==45		;#BLOCKS PAGED IN
UNIPCO==46		;#BLOCKS PAGED OUT
	SUBTTL	INITIALIZE

WTCHER:	RESET			;STOP THE WORLD
	MOVE	P,[XWD -PDLEN,PDL] ;SET UP A PUSHDOWN LIST
	SETZ	F,		;CLEAR FLAGS

;SET UP TTY

	INIT	TTY,0		;DO INIT
	SIXBIT	/TTY/
	XWD	TYOB,TYIB
	  EXIT			;CAN'T GET TTY?????
	TLO	F,BREAK		;DON'T READ UNLESS ASKED

;TELL THE USER WHO WE ARE

	MOVEI	M,[ASCIZ \
WTCHER - WATCHDOG FOR ACCEPTENCE - V\]
	PUSHJ	P,MSG
	MOVEI	N,WTCVER	;GET THE VERSION NUMBER
	PUSHJ	P,OCTPRT	;OUTPUT IT IN OCTAL
	MOVEI	CH,100+WTCMIN	;GET MINOR VERSION AS LETTER
	TRNE	CH,77		;IS THERE A MINOR VERSION?
	PUSHJ	P,TYO		;YES, OUTPUT IT
	MOVEI	CH,"("		;ALWAYS
	PUSHJ	P,TYO		;  OUTPUT
	MOVEI	N,WTCEDT	;  *
	PUSHJ	P,OCTPRT	;EDIT LEVEL
	MOVEI	CH,")"		;*
	PUSHJ	P,TYO		;AS PART OF VERSION
	MOVEI	N,WTCWHO	;GET WHO LAST MODIFIED
	JUMPE	N,ENDVER	;WAS IT DEC?
	MOVEI	CH,"-"		;NO, BETTER OUTPUT
	PUSHJ	P,TYO		; THE
	PUSHJ	P,OCTPRT	; TRAILER
ENDVER:	MOVEI	M,[ASCIZ .	FOR HELP, TYPE 'HELP'
.]
	PUSHJ	P,MSG		;AND THEN FINISH HEADER
;SET UP FOR GETTAB SIMULATIONS, IF POSSIBLE

	MOVE	T1,[EXP %CNPDB]	;FIND JBTPDB
	GETTAB	T1,		; FROM MONITOR
	  SETZ	T1,		;OH WELL...
	MOVEM	T1,PDBPTR	;SAVE FOR USE IN SIMULATOR
	SETZ	T4,		;CLEAR T4 IN CASE CAN'T SPY
	MOVE	T1,[EXP %CNSIZ]	;WE NEED SIZE OF SYSTEM
	GETTAB	T1,		;SO GET IT
	  JRST	SPYER1		;NO SIZE, NO SPY
	SUBI	T1,1		;MAKE IT ALAST ADDRESS
	SPY	T1,		;SET SPY
	  JRST	SPYER2		;AH SHUCKS
	MOVE	T1,.JBFF	;GET FIRST AVAIL LOCATION
	MOVEM	T1,GTBST	;THIS BECOMES START OF GETTAB PTRS

NXTGTB:	HRLZ	T1,T4		;NEXT TABLE POINTER
	HRRI	T1,.GTSLF	;LET'S DO IMMEDIATE
	GETTAB	T1,		;GET NEXT TABLE POINTER
	  JRST	ENDGTB		;THAT'S ALL FOLKS
	TLZE	T1,37		;CLEAR MONITOR XR AND INDIRECT
	TLO	T1,T1		;SET UP OUR AC
	TRO	T1,400000	;SET SPY BIT
	PUSHJ	P,PLACER	;STORE IN TABLE OF TABLE POINTERS
	AOJA	T4,NXTGTB	;LOOP FOR ALL POSSIBLE GETTABS

ENDGTB:	SUB	T2,GTBST	;CURRENT-START=NUMBER+1
	SOJ	T2,		;NUMBER OF LEGAL GETTAB'S
	MOVEM	T2,MAXGTB	;SAVE NUMBER OF LEGAL GETTAB'S
;SET UP UDB ADDRESS TABLE

	MOVE	T1,.JBFF	;GET FIRST AVAILABLE LOCATION
	MOVEM	T1,UDBST	;THIS BECOMES START OF UDB ADDR TABLE
	MOVE	T1,[EXP %LDUNI]	;SET UP FOR AND GET
	PUSHJ	P,GTBSPY	;  ADDRESS OF FIRST UDB IN SYSTEM
	  JRST	GTUERR		;FATAL IF WE CAN'T GET THIS INFO
	SETZ	T4,		;CLEAR T4 FOR COUNTER
NXTUDB:	HLRZS	T1		;MOVE ADDRESS TO PROPER SIDE
	JUMPE	T1,NXTUD1	;IF DONE,QUIT
	PUSHJ	P,PLACER	;ELSE, PUT INTO TABLE
	MOVEI	T1,UNISYS(T1)	;GET ADDRESS OF ADDRESS OF NEXT UNB
	PUSHJ	P,PEKSPY	;GET ADDRESS OF NEXT UDB FROM MONITOR
	SOJA	T4,NXTUDB	;SUBTRACT 1 FROM COUNT AND LOOP
NXTUD1:	HRLM	T4,UDBST	;MAKE AOBJN POINTER
;FINISH INITIALIZE WITH FLAG SETS AND OPEN DISK, CREATE FILE

	MOVE	T1,[EXP %CNTIC]	;GET NUMBER OF
	PUSHJ	P,GTBSPY	;  TICKS/SECOND
	  MOVEI	T1,^D60		;ERROR ASSUMES 60
	IMUL	T1,[EXP ^D60*^D60*^D24] ;MAKE NUMBER TICKS/DAY
	MOVEM	T1,TICDAY	;SAVE FOR LATER COMPUTATIONS
	MOVE	T1,[EXP %CNST2]
	PUSHJ	P,GTBSPY	;GET SPECIAL SOFTWARE CONFIG
	  SETZ	T1,		;OBVIOUSLY NOTHING SPECIAL
	TRNE	T1,ST%VMS	;IS THERE VIRT MEM ON THIS SYSTEM?
	TLO	F,VMSER		;YES, MARK THIS FACT
	TLO	F,NEWSLP	;MARK THAT DAEMON NEEDS TO BE CALLED
	MOVE	T1,[XWD 6,FILOPN] ;SET UP TO DO CREATE ONLY
	FILOP.	T1,		;  OPEN AND FILOP.
	  TLO	F,NOTNEW	;ERROR RETURN, ASSUME MEANS RESTART
	MOVE	T2,DKIB		;AND SAVE BUFFER ADDRESSES
	MOVEM	T2,DKIBS	; FOR LATER
	MOVE	T2,DKOB		;AS TO NOT KEEP INCREASING CORE
	MOVEM	T2,DKOBS	; *

	TLNE	F,NOTNEW	;DID WE HAVE ERROR RETURN?
	JRST	OLDRUN		;YES, ASSUME RESTART
;;	JRST	NEWRUN		;NO, DROP THRU TO NEW RUN SETUP
;THIS IS A NEW RUN, SET UP A VIRGIN DISK FILE

	MOVEI	M,[ASCIZ \INITIAL EXECUTION - NEW STATISTIC FILE IS BEING CREATED
FILE NAME IS WTCHER.STS
\]
	PUSHJ	P,MSG		;SEND ABOVE MESSAGE TO THE  USER
	MOVE	P1,UDBST	;GET UDB AOBJN POINTER


UDBOST:	MOVE	P4,(P1)		;GET ADDRESS OF UDB INTO P4
	MOVEI	T1,UNINAM(P4)	;GET UNIT NAME
	PUSHJ	P,PEKSPY
	PUSHJ	P,DKO		;OUTPUT TO DISK
	TLO	F,NOREAD	;DON'T DO DISK INPUT
	PUSHJ	P,UPDATE	;GO SET UP FILE, AND ACCUMULATE TOTALS
	TLZ	F,NOREAD	;RESET THE BIT
	MOVE	T1,T5		;GET TOTAL HARD ERRORS
	PUSHJ	P,DKO		;OUTPUT AS TOTAL HARD ERRORS SEEN
	MOVE	T1,T3		;GET ACCUMULATED READS
	PUSHJ	P,DKO		;OUTPUT AS TOTAL READS DONE
	MOVE	T1,T4		;GET ACCUMULATED WRITES
	PUSHJ	P,DKO		;OUTPUT AS TOTAL WRITES DONE
	AOBJN	P1,UDBOST	;LOOP FOR ALL UDBS SEEN


	JRST	STDFIN		;GO CLOSE OUT FILE AND DO A WHAT
;THIS IS A RE-START OF A RUN, A STS FILE ALREADY EXITS

OLDRUN:	CAIE	T1,ERAEF%	;MAKE SURE THIS IS 'ALREADY EXITS'
	  JRST	DSKERR		;NOPE, SOMETHING'S WRONG!
	MOVEI	M,[ASCIZ \RESTARTED EXECUTION - STATISTIC FILE ALREADY EXISTS
FILE NAME IS WTCHER.STS
\]
	PUSHJ	P,MSG		;SEND ABOVE MESSAGE TO THE USER

	PUSHJ	P,OPNDSK	;OPEN DISK FILES I/O
	MOVE	T1,[EXP %NSUPT]	;GET UPTAIME
	PUSHJ	P,GTBSPY	;  IN TICKS
	  SETZ	T1,		;ERROR ASSUMES NONE
	LSHC	T1,-^D18	;MULTIPLY BY 2**18 AND SET UP FOR
	DIV	T1,TICDAY	;  DIVISION BY TCKS/DAY TO GET
	MOVEM	T1,P1		;  UPTIME IN UDT UNITS, SAVE
	MOVE	T1,[EXP %CNDTM]	;NOW GET THE TIME
	PUSHJ	P,GTBSPY	;  IN UDT UNITS
	  SETZ	T1,		;ERRORS ASSUME NONE
	SUB	T1,P1		;MAKE TIME MONITOR CAME UP
	CAML	T1,LOKBLK+.RBTIM ;WAS FILE MADE SINCE MONITOR CAME UP?
	TLO	F,NOCALC	;NO, FILE IS OLDER THAN MON, DON'T CALC
OLDRU1:	PUSHJ	P,DKI		;GET UNIT NAME
	JUMPE	T1,OLDEND	;ZERO IS END OF FILE
	PUSHJ	P,DKO		;GO SAVE NAME
	MOVE	M,T1		; BOTH ON DISK AND IN AC
	MOVE	P1,UDBST	;GET UDB AOBJN POINTER
OLDRU2:	MOVE	T1,(P1)		;GET ADDRESS OF UNIT NAME IN UDB
	PUSHJ	P,PEKSPY	;GET UNIT NAME FROM MONITOR
	CAMN	T1,M		;MATCH?
	JRST	OLDRU3		;YES, DO PROCESSING
	AOBJN	P1,OLDRU2	;NO, LOOP TO NEXT UDB
	JRST	OLDER1		;FALL THROUGH, COMPLAIN-NO MATCHING UDB

OLDRU3:	MOVE	P4,(P1)		;MOVE UDB ADDR TO PROPER AC
	HRROS	(P1)		;MARK UDB AS FOUND
	PUSHJ	P,UPDATE	;DO DISK UPDATE, GET NEW R/W/E COUNTS
	PUSHJ	P,DKI		;GET ACCUMULATED HARD ERRORS
	ADD	T1,T5		;MAKE NEW TOTAL
	PUSHJ	P,DKO		;OUTPUT NEW TOTAL
	PUSHJ	P,DKI		;GET ACCUMULATED READS
	ADD	T1,T3		;MAKE NEW TOTAL
	PUSHJ	P,DKO		;OUTPUT
	PUSHJ	P,DKI		;GET ACCUMULATED WRITES
	ADD	T1,T4		;MAKE NEW TOTAL
	PUSHJ	P,DKO		;OUTPUT
	JRST	OLDRU1		;GO GET NEXT UNIT
;FINISH RESTART OF EXISTING FILE, UNUSUAL CONDITIONS CODE

OLDEND:	TLZ	F,NOCALC	;RESET NO CALC DELTAS BIT
	MOVE	P1,UDBST	;GET UDB AOBJN POINTER
OLDEN1:	SKIPL	(P1)		;WAS UDB FOUND IN DISK FILE?
	PUSHJ	P,OLDEN2	;NO, PUT IT INTO FILE
	HRRZS	(P1)		;CLEAR FLAG OF FOUND
	AOBJN	P1,OLDEN1	;LOOP TO NEXT IN TABLE
	JRST	STDFIN		;ALL DONE

OLDEN2:	MOVE	P4,(P1)		;GET ADDRESS OF UDB TO PROPER AC
	MOVEI	T1,UNINAM(P4)	;GET ADDRESS OF UNIT NAME
	PUSHJ	P,PEKSPY	;GET UNIT NAME FROM MONITOR
	PUSHJ	P,DKO		;OUTPUT IT
	MOVE	M,T1		;GET TO OUTPUT AC
	PUSHJ	P,SIXBP		;OUTPUT NAME TO USER
	MOVEI	M,[ASCIZ . UDB NOT FOUND IN FILE, IS BEING INSERTED
.]
	PUSHJ	P,MSG		;OUTPUT ABOVE MESSAGE
	TLO	F,NOREAD	;THIS IS NEW RECORD, NO READING
	PUSHJ	P,UPDATE	;MAKE NEW DISK RECORD
	TLZ	F,NOREAD	;RESET BIT
	MOVE	T1,T5		;GET ERROR COUNT
	PUSHJ	P,DKO		;OUTPUT
	MOVE	T1,T3		;GET ACCUM READS
	PUSHJ	P,DKO		;OUTPUT
	MOVE	T1,T4		;GET ACCUM WRITES
	PJRST	DKO		;OUTPUT AND RETURN TO CALLER
	SUBTTL	STDFIN - FINISH INITIALIZE, SET UP FOR AND DO WHAT

STDFIN:	OUTPUT	DS1,		;FORCE LAST BUFFER OUT
	CLOSE	DS1,		;CLOSE FILE TO MAKE SURE
	TLNE	F,NOTNEW	;DO WE NEED TO CLOSE INPUT SIDE?
	CLOSE	DSK,		;YES
	MOVE	T1,[%CNHOR]	;GET PRESENT HOUR
	PUSHJ	P,GTBSPY
	  JRST	TIMERR		;SHUCKS
	MOVE	N,T1		;SAVE FOR A SEC
	MOVE	T1,[%CNMIN]	;GET PRESENT MINUTE
	PUSHJ	P,GTBSPY
	  JRST	TIMERR		;SHUCKS AGAIN
	IMULI	N,^D100	;MOVE HOUR OVER TO PROPER PLACE
	ADDI	N,(T1)		;ADD IN MINUTE
	MOVEI	M,[ASCIZ .
INITIAL.]
	JRST	WHAT1		;GO DO WHAT PROCESSING AS INITIAL
	SUBTTL	SLEPER - PUT THE PROGRAM TO SLEEP

SLEPER:	TLZN	F,NEWSLP	;DO WE WANT TO CALL DAEMON?
	JRST	HBRRTN		;NO, JUST DO A HIBER
	MOVE	T1,[EXP %CNSEC]	;YES, GET THE PRESENT SECOND
	PUSHJ	P,GTBSPY	; FROM OUR LITTLE ROUTINE
	  JRST	TIMERR		; AW COME ON....
	ADD	T1,PERSEC	;ADD THE SECONDS OF SLEEP TIME
	IDIVI	T1,^D60		;CHECK FOR MINUTES
	MOVE	P2,T1		;MOVE ANY EXCESS MINUTES TO SAFE PLACE
	MOVE	T1,[EXP %CNMIN]	;GET THE PRESENT MINUTE
	PUSHJ	P,GTBSPY	; FROM THE SUBROUTINE
	  JRST	TIMERR		;WHY ME LORD?
	ADD	T1,PERMIN
	ADD	T1,P2		;ADD IN EXCESS AND PERIOD
	IDIVI	T1,^D60		;FIND HH:MM THAT IS MADE BY THAT
	MOVEM	T2,TODMIN	;SAVE TIME OF DAY OF NEXT WAKE IN MINS
	MOVE	P2,T1		;SAVE EXCESS HOURS
	MOVE	T1,[EXP %CNHOR]	;GET PRESENT HOUR OF THE DAY
	PUSHJ	P,GTBSPY
	  JRST	TIMERR		;I WOULDN'T BELEIVE IT IF I DIDN'T SEE IT
	ADD	T1,PERHOR	;ADD HOURS OF SLEEP
	ADD	T1,P2		;ADD IN THE EXCESS
	IDIVI	T1,^D24		;KEEP HOUR WITHIN 24 HOUR CLOCK RANGE
	MOVEM	T2,TODHOR	;AND SAVE
	MOVEI	T1,DAECLK	;SET UP FOR DAEMON SLEEP CALL
	DAEMON	T1,		;MAKE CLOCK REQUEST
	  JRST	DAEERR		;WELL, YOU CAN'T WIN 'EM ALL
HBRRTN:	MOVSI	T1,(HB.SWP!HB.RTL)	;SET UP HIBER BITS
	HIBER	T1,		;DO THE HIBER
	  JRST	HBRERR		;OH WELL
	SKPINC			;WOKE UP, WAS A CHARACTER TYPED?
	  JRST	PRDPRO		;NO, JUST DO PERIOD PROCESSING
;;	JRST	PARSE		;YES, FALL INTO PARSER
	SUBTTL	PARSER -PARSE COMMAND

PARSE:	PUSHJ	P,SIXAN		;GET COMMAND
	JUMPE	M,PARSE1	;ALL BLANK IS NO ERROR
	MOVEM	CH,TERMCH	;SAVE TERMINATOR FOR LATER PARSE
	MOVE	P1,[XWD -DISPL,COMTAB] ;SET UP AOBJN POINTER
	PUSHJ	P,CMDSRC	;GO FIND COMMAND IN USER
	  CAIA			; NO DICE, TELL THE USER HE'S STUPID
	JRST	@COMADR(T1)	;ELSE, GO DO HIS THING

;USER HAS MISTYPED - EITHER NO SUCH COMMAND OR A NON-UNIQUE ABBREVIATION

	MOVE	P1,T1		;SAVE ERROR INDICATION
	MOVEI	CH,"?"		;FIRST OUTPUT A ? AS THE
	PUSHJ	P,TYO		; STANDARD ERROR MESSAGE START
	PUSHJ	P,SIXBPA	;AND NOW THE ACTUAL COMMAND IN ERROR
	MOVEI	M,[ASCIZ . UNKNOWN COMMAND.] ;ASSUME IT'S UNKNOWN
	SKIPE	P1		;IS THAT A GOOD ASSUMPTION?
	MOVEI	M,[ASCIZ . IS NOT UNIQUE.] ;NO, USE OTHER MESSAGE
	PUSHJ	P,MSG		;SEND MIDDLE PART OF ERROR MESSAGE
	MOVEI	M,[ASCIZ . - TYPE 'HELP' FOR LIST OF COMMAND
.]
	PUSHJ	P,MSG		;FINISH ERROR MESSAGE
PARSE1:	PUSHJ	P,LINEAT	;EAT REST OF LINE, IF ANY

;;;;;	JRST	PRDPRO		;AND GO CHECK TIMER, ETC. FOR WORK
	SUBTTL	PERIOD - THE PERIOD PROCESSOR

;THIS ROUTINE WILL CHECK TO SEE IF ONCE A PERIOD PROCESSING SHOULD
;BE DONE. THIS IS CALLED AS THE LAST THING PRIOR TO SLEEPING IF A
;COMMAND HAS BEEN EXECUTED, OR AS THE ONLY THING IF AWAKENED. HOW-
;EVER, THIS ROUTINE DOES NOT KNOW NOR CARE HOW IT HAS BEEN
;CALLED.

PRDPRO:	TLZ	F,DECMAL	;CLEAR JUNK
	MOVE	T1,[EXP %CNHOR]	;SET UP FOR AND
	PUSHJ	P,GTBSPY	; GET THE PRESENT HOUR
	  JRST	TIMERR		;NO TIME AVAILABLE?
	CAMGE	T1,TODHOR	;IS THIS AT LEAST THE PROPER HOUR
	  JRST	SLEPER		;NO, GO DIRECTLY TO SLEEP, DO NOT PASS GO...
	MOVE	N,T1		;YES, SAVE HOUR
	MOVE	T1,[EXP %CNMIN]	;SET UP FOR AND
	PUSHJ	P,GTBSPY	;  GET PRESENT MINUTE
	  JRST	TIMERR		;CAN'T HAPPEN - BUT WILL NO DOUBT
	CAMGE	T1,TODMIN	;IS THIS AT LEAST THE PROPER MINUTE?
	  JRST	SLEPER		;NO, GO TO SLEEP, DO NOT PASS GO, DO...

;WE ARE NOW SURE WE SHOULD BE DOING ONCE A PERIOD PROCESSING

	IMULI	N,^D100		;MOVE HOURS FIGURE OVER
	ADDI	N,(T1)		; AND PUT IN THE MINUTES
	MOVEI	M,[ASCIZ .
SCHEDULED.]			;REPORT THAT THIS IS SCHEDULED
	TLO	F,NEWSLP	;TELL SLEEPER THAT WE WANT NEW DAEMON REQUEST
	JRST	WHAT1		;CONTINUE AT PROPER POINT



;PROCESSOR 'WHAT' - UNSCHEDULED, OPERATOR REQUESTED STATUS REPOORT.

WHATP:	MOVEI	M,[ASCIZ .
REQUESTED.]			;THIS IS REQUESTED REPORT
	MOVE	T1,[EXP %CNHOR]	;GET THE PRESENT
	PUSHJ	P,GTBSPY	;  HOUR FOR REPORTING
	  MOVEI	T1,0		;NO TIME IS NO TIME
	MOVE	N,T1		;PUT HOUR INTO OUTPUT AC
	IMULI	N,^D100		;MOVE IT OVER
	MOVE	T1,[EXP %CNMIN]	;NOW GO GET
	PUSHJ	P,GTBSPY	; PRESENT MINUTE OF THE HOUR
	  CAIA			;NO TIME, FORGET IT
	ADDI	N,(T1)		;ADD IN THE MINUTE FIGURE
WHAT1:	PUSHJ	P,MSG		;OUTPUT TYPE OF REPORT
	MOVEI	M,[ASCIZ . WATCHDOG STATUS REPORT - AT .]
	PUSHJ	P,MSG		;CONTINUE HEADING
	PUSHJ	P,DECPRT	;OUTPUT TIME WE WORKED SO HARD FOR
	MOVEI	M,[ASCIZ .

.]
	PUSHJ	P,MSG		;OUTPUT A CRLFCRLF
	SUBTTL	WHAT - ACTUAL WHAT PROCESSING WITH UPDATE

	PUSHJ	P,OPNDSK	;OPEN DISK FOR SINGLE ACCESS UPDATE
	MOVEI	M,[ASCIZ .
UNIT	!HARDWARE ERRORS	!INPUT OUTPUT STATS
	!DEVICE		DATA	!READS		WRITES
--------!-----------------------!---------------------------------------
.]
	PUSHJ	P,MSG		;OUTPUT HEADER

WHAT2:	PUSHJ	P,DKI		;GET UNIT NAME
	JUMPE	T1,WHTEND	;ZERO DEV NAME IS END OF LOOP
	TLNN	F,WHTREQ	;REQUESTED WHAT?
	PUSHJ	P,DKO		;NO,OUTPUT TO DISK
	PUSHJ	P,CRLF		;GET TO NEW LINE
	MOVE	M,T1		;PLACE NAME FOR OUTPUT
	PUSHJ	P,SIXBPA	;OUTPUT DEV NAME TO TTY
	PUSHJ	P,TABPRT	;OUTPUT TAB
	MOVE	P1,UDBST	;GET AOBJN POINTER FOR UDB SEARCH
WHAT3:	MOVE	P4,(P1)		;GET STARTING ADDRESS OF UDB
	MOVEI	T1,UNINAM(P4)	;GET ADDRESS OF NAME OF UNIT
	PUSHJ	P,PEKSPY	;AND GET UNIT'S NAME
	CAME	T1,M		;DOES IT MATCH?
	AOBJN	P1,WHAT3	;NO,KEEP LOOKING
	CAME	T1,M		;END OF UDB'S OR FOUND?
	  JRST	WHTER1		;END OF UDB'S, WE'RE SLIGHTLY UPSET
	TLZ	F,NOCALC	;MAKE SURE WE WILL GET DELTA VALUES
	PUSHJ	P,UPDATE	;DO UPDATING, GET DELTA TOTALS
	PUSHJ	P,DKI		;GET ACCUMULATED HARD ERROR COUNT
	ADD	T5,T1		;ADD IN UPDATE
	HLRZ	N,T5		;GET DEVICE ERRORS
	CAML	N,MAXDEV	;GREATER THAN MAX ALLOWED?
	TLO	F,DEVWRN	;YES, REMEMBER THAT
	PUSHJ	P,DECPRT	;OUTPUT NUMBER OF ERRORS
	PUSHJ	P,TABPRT	;AND A TAB
	PUSHJ	P,TABPRT	; ANOTHER
	HRRZ	N,T5		;GET NUMBER OF DATA ERRORS
	CAML	N,MAXDAT	;GREATER THAN ALLOWED?
	TLO	F,DATWRN	;YES, MARK IT
	PUSHJ	P,DECPRT	;OUTPUT DATA ERRORS
	PUSHJ	P,TABPRT	;AND A TAB
	ADDI	N,(T5)		;GET TOTAL NUMBER OF ERRORS
	CAML	N,MAXTOT	;GREATER THAN TOTAL ALLOWED?
	TLO	F,TOTWRN	;YES, MARK IT
	MOVE	T1,T5		;GET NEW HARD ERROR COUNT TO PROPER AC
	TLNN	F,WHTREQ	;SHOULD WE DO WRITE?
	PUSHJ	P,DKO		;YES, OUTPUT NEW TOTAL ERROR COUNTS
;CONTINUE AT TOTALS

	PUSHJ	P,DKI		;GET TOTAL # READS
	ADD	T1,T3		;MAKE NEW TOTAL
	TLNN	F,WHTREQ	;DO WRITE?
	PUSHJ	P,DKO		;YES, OUTPUT NEW TOTAL
	MOVE	N,T1		;SET UP AND OUTPUT TO TTY
	PUSHJ	P,DECPRT	;  THE TOTAL BLOCKS READ ON UNIT
	PUSHJ	P,TABPRT	;AND A TAB
	PUSHJ	P,TABPRT	;  ANOTHER
	PUSHJ	P,DKI		;GET TOTAL WRITES
	ADD	T1,T4		;ACCUMULATE NEW TOTAL
	TLNN	F,WHTREQ	;SHOULD WE UPDATE DISK?
	PUSHJ	P,DKO		;YES, UPDATE
	MOVE	N,T1		;SET UP AND PRINT
	PUSHJ	P,DECPRT	;  TOTAL BLOCK WRITTEN ON UNIT
	TLNN	F,TOTWRN!DEVWRN!DATWRN ;ANY WARNING TO BE GIVEN
	JRST	WHAT2		;NO, LOOP TO NEXT UNIT
	MOVEI	M,[ASCIZ .	**WARN**
TOO MANY .]
	PUSHJ	P,MSG		;START WARNING MESSAGE
	MOVEI	M,[ASCIZ .-DEVICE-.] ;ASSUME DEVICE ERRORS
	TLZE	F,DEVWRN	;TOO MANY DEVICE ERRORS?
	PUSHJ	P,MSG		;YES, TELL USER
	MOVEI	M,[ASCIZ .-DATA-.] ;ASSUME DATA ERRORS
	TLZE	F,DATWRN	;ARE THERE?
	PUSHJ	P,MSG		;YES, TELL USER
	MOVEI	M,[ASCIZ .-TOTAL-.] ;ALSO ASSUME TOTAL ERRORS TOO HIGH
	TLZE	F,TOTWRN	;ARE WE RIGHT?
	PUSHJ	P,MSG		;YES, OUTPUT
	MOVEI	M,[ASCIZ . ERRORS ON THIS UNIT.]
	PUSHJ	P,MSG		;AND FINISH OFF WARNING MESSAGE
	JRST	WHAT2		;THAN LOOP TO NEXT UNIT

WHTEND:	PUSHJ	P,CRLF		;OUTPUT A CRLF
	CLOSE	DSK,		;ALWAYS CLOSE INPUT SIDE
	PUSHJ	P,LINEAT	;EAT LINE AND PROMPT
	TLZE	F,WHTREQ	;REQUEST OR SCHEDULED?
	JRST	SLEPER		;REQUEST, THERE IS NO OUTPUT
	OUTPUT	DS1,		;OUTPUT LAST BUFFER
	CLOSE	DS1,		;CLOSE THE DISK
	JRST	SLEPER		;AND GO BACK TO SLEEP
	SUBTTL	SLEEP - MODIFY OR OUTPUT SLEEP TIME

SLEEPP:	TLO	F,DECMAL		;DON'T WANT DECIMAL PT PRINTED
	TLNE	F,BREAK		;ANY ARGS TO COMMAND?
	JRST	SLPWHT		;NO, MUST WANT CURRENT INFO
	SETZB	P1,P2		;ELSE, INITIALIZE COUNTER
	PUSHJ	P,DECIN		;GET A NUMBER
	CAIE	CH,":"		;DOES TERMINATOR IMPLY MINS OR HOURS?
	JRST	SLPSEC		;NO, MUST BE SECONDS
	MOVE	P2,N		;ELSE, ASSUME MINUTES
	PUSHJ	P,DECIN		;  AND GET NEXT NUMBER
	CAIE	CH,":"		;DOES TERMINATOR MEAN HH:MM?
	JRST	SLPSEC		;NO, ONLY MM:SS
	MOVE	P1,P2		;YES, GET HOURS TO RIGHT AC
	MOVE	P2,N		;  AND MINUTES
	PUSHJ	P,DECIN		;NOW GET SECONDS
SLPSEC:	MOVE	P3,N		;PUT SECONDS TO PROPER AC
	CAIGE	P3,^D60		;MORE THAN 59 SECONDS SPECIFIED?
	JRST	SLPSE1		;NO, CONTINUE CHECKING
	IDIVI	N,^D60		;YES,CONVERT TO MINUTES,SECONDS
	MOVE	P3,N1		;SAVE SECONDS
	ADD	P2,N		;ADD NEW MINUTES TO SPECIFIED MINUTES
SLPSE1:	CAIGE	P2,^D60		;MORE THAN 59 MINUTES SPECIFIED?
	JRST	SLPSE2		;NO, CONTINUE CHECKING
	MOVE	N,P2		;YES, GET MINUTES
	IDIVI	N,^D60		;MAKE HOURS,MINUTES
	MOVE	P2,N1		;SAVE MINUTES
	ADD	P1,N		;ADD NEW HOURS TO SPECIFIED HOURS
SLPSE2:	CAIL	P1,^D24		;MORE THAN A DAY OF SLEEPING SPECIFIED?
	  JRST	SLPERD		;ERROR!!
	MOVE	T1,P1		;GET # OF HOURS
	ADD	T1,P2		;PLUS # OF MINUTES
	ADD	T1,P3		;PLUS # OF SECONDS
	JUMPE	T1,SLPWH1	;IF IT'S 0, COMPLAIN AND DO SLPWHT
	MOVEM	P1,PERHOR	;SAVE HOURS OF SLEEPING
	MOVEM	P2,PERMIN	;  AND MINUTES
	MOVEM	P3,PERSEC	;  AND SECONDS
	IMULI	P1,^D60		;CONVERT HOURS TO MINUTES
	ADD	P2,P1		;AND ADD TO MINUTES
	IMULI	P2,^D60		;NOW CONVERT TOTAL MINS TO SECONDS
	ADD	P3,P2		;AND MAKE SECONDS FOR DAEMON SLEEP
	MOVEM	P3,SLPTIM	;SAVE IN DAEMON ARGUMENT BLOCK
	TLO	F,NEWSLP	;TELL SLEEPER TO RESET SLEEP TIME
	JRST	SLPWHT		;GO TELL USER NEW INFORMATION ABOUT
				;  SLEEP PERIOD
	SUBTTL	SLPWHT - GIVE CURRENT SLEEP TIME AND SCHEDULED WAKE UP

SLPWH1:	MOVEI	M,[ASCIZ .% ZERO IS NOT LEGAL SLEEP TIME PERIOD
.]				;THIS IS AN ERRORMESSAGE
	PUSHJ	P,MSG		;GIVE THE MESSAGE

SLPWHT:	MOVEI	M,[ASCIZ .SLEEP PERIOD IS .]
	PUSHJ	P,MSG
	SKIPN	N,PERHOR	;SLEEP HOURS?
	JRST	SLPWH2		;NO, CHECK FOR MINUTES
	PUSHJ	P,DECPRT	;YES, PRINT HOURS
	MOVEI	CH,":"		;AND THEN A
	PUSHJ	P,TYO		;COLON
SLPWH2:	MOVE	N,PERMIN	;MINUTES ALWAYS PRINT
	MOVEI	CH,"0"		;ASSUME LESS THAN 10
	CAIG	N,^D9		;RIGHT?
	PUSHJ	P,TYO		;YEP, OUTPUT
	PUSHJ	P,DECPRT	;ANYWAY ALWAYS PRINT THE NUMBER
	MOVEI	CH,":"		;THEN ANOTHER COLON
	PUSHJ	P,TYO
	MOVE	N,PERSEC	;NOW DO SECONDS
	MOVEI	CH,"0"		;SAME TEST AS FOR MINUTES
	CAIG	N,^D9		;
	PUSHJ	P,TYO		;
	PUSHJ	P,DECPRT	;OUT GO THE SECONDS
	TLNE	F,NEWSLP	;ARE WE ABOUT TO SET SLEEP TIME?
	JRST	SLPWH3		;YES, DON'T OUTPUT TIME AS IT'S WRONG
	MOVEI	M,[ASCIZ . - NEXT SCHEDULED WAKE-UP AT .]
	PUSHJ	P,MSG
	MOVE	N,TODHOR	;GET THE HOUR OF WAKE-UP
	IMULI	N,^D100		;MOVE OVER
	ADD	N,TODMIN	;AND PUT MINUTES IN
	PUSHJ	P,DECPRT	;AND TELL USER
SLPWH3:	PUSHJ	P,CRLF
	PUSHJ	P,LINEAT	;GOBBLE ANY UNUSED INPUT AND PROMPT
	JRST	PRDPRO		;GO CHECK FOR PERIOD PROCESSING
	SUBTTL	ERRMAX - SPECIFY/LIST MAXIMUM ERROR RATES

ERRMAP:	TLNE	F,BREAK		;ANY ARGS IN COMMAND?
	JRST	ERRWHT		;NO, MUST WANT CURRENT INFORMATION
	PUSHJ	P,ERRGET	;GET MAX NUMBER OF DEVICE ERRORS
	  JRST	ERRERR		;MUST HAVE THREE ARGUMENTS
	MOVE	P1,N		;SAVE
	PUSHJ	P,ERRGET	;GET MAX NUMBER OF DATA ERRORS
	  JRST	ERRERR		;MUST HAVE THREE ARGS
	MOVE	P2,N		;SAVE
	PUSHJ	P,DECIN		;GET TOTAL ERRORS ALLOWED
	SKIPE	N		;IS IT ZERO?
	MOVEM	N,MAXTOT	;NO, REPLACE TOTAL ERRORS ALLOWED
	SKIPE	P1		;IS DEVICE ERRORS = 0?
	MOVEM	P1,MAXDEV	;NO, REPLACE DEVICE ERRORS ALLOWED
	SKIPE	P2		;IS DATA ERRORS = 0?
	MOVEM	P2,MAXDAT	;NO, REPLACE

ERRWHT:	MOVEI	M,[ASCIZ .ERROR MAXIMUMS - DEVICE= .]
	PUSHJ	P,MSG
	MOVE	N,MAXDEV	;GET MAXIMUM DEVICE ERRORS ALLOWED
	PUSHJ	P,DECPRT	;OUTPUT
	MOVEI	M,[ASCIZ .	DATA= .]
	PUSHJ	P,MSG
	MOVE	N,MAXDAT	;GET MAXIMUM DATA ERRORS ALLOWED
	PUSHJ	P,DECPRT	;OUTPUT
	MOVEI	M,[ASCIZ .	TOTAL= .]
	PUSHJ	P,MSG
	MOVE	N,MAXTOT	;GET MAXIMUM TOTAL HARD ERRORS ALLOWED
	PUSHJ	P,DECPRT	;OUTPUT
	PUSHJ	P,CRLF		;OUPUT <CR><LF>
	PUSHJ	P,LINEAT	;EAT REST OF LINE AND PROMPT
	JRST	PRDPRO		;GO CHECK FOR PERIOD PROCESSING

ERRGET:	PUSHJ	P,DECIN		;GET DECIMAL INPUT VALUE
	TLNN	F,BREAK		;DID WE HIT END OF LINE
	AOS	(P)		;NO, SKIP RETURN
	POPJ	P,		;RETURN
	SUBTTL	EXITP - EXIT THIS PROGRAM

EXITP:	EXIT			;BYE!
	SUBTTL	HELPP - PRINT HELP TEXTS FOR EACH COMMAND

HELPP:	TLNN	F,BREAK		;DID HE JUST SAY "HELP" ?
	JRST	HELP2		;NO, WE MUST PARSE ARGUMENT
				;ELSE, GIVE GENERAL INFORMATION
	MOVE	P1,[XWD -DISPL,COMTAB] ;GET AOBJN PTR FOR COMMANDS AVAIL
	MOVEI	M,[ASCIZ .THE FOLLOWING COMMANDS ARE PRESENTLY AVAILABLE TO THE WTCHER PROGRAM:
.]
	PUSHJ	P,MSG		;OUTPUT HEADER
HELP1:	MOVE	M,(P1)		;GET ADDRESS OF COMMAND TABLE
	PUSHJ	P,SIXBPA	;OUTPUT IT
	PUSHJ	P,TABPRT		;OUTPUT A TAB
	AOBJN	P1,HELP1	;LOOP FOR ALL COMMANDS
	MOVEI	M,[ASCIZ \

TYPE 'HELP ARG' WHERE ARG IS ANY OF THE ABOVE COMMANDS FOR SPECIFIC
COMMAND HELP INFORMATION.
'HELP ALL' WILL GIVE ALL COMMAND HELP TEXTS.
\]
	PUSHJ	P,MSG		;END HELP MESSAGE
HELP1A:	PUSHJ	P,LINEAT	;SEND THE PROMPT CHARACTER
	JRST	PRDPRO		;GO CHECK FOR PERIOD PROCESSING


HELP2:	PUSHJ	P,SIXAN		;GET ARG IN SIXBIT
	CAME	M,[SIXBIT .ALL.] ;IS IT "ALL" ?
	JRST	HELP4		;NO, CONTINUE THE PARSE
	MOVE	P1,[XWD -DISPL,COMHLP] ;YES, SET UP AOBJN POINTER
HELP3:	MOVE	M,(P1)		;GET HELP TEXT ADDRESS
	PUSHJ	P,MSG		;OUTPUT IT
	AOBJN	P1,HELP3	;LOOP FOR ALL
	JRST HELP1A		;GO DO LAST OF JOB
HELP4:	MOVE	P1,[XWD -DISPL,COMTAB] ;SET UP LOOKUP TABLE ADDRESS
	PUSHJ	P,CMDSRC	;GO LOOK FOR THE COMMAND
	  JRST	HELP5		;OOPS!
	MOVE	M,COMHLP(T1)	;GET HELP TEXT ADDRESS
	PUSHJ	P,MSG		;OUTPUT THE HELP TEXT
	JRST	HELP1A		;GO FINISH UP
HELP5:	JUMPE	T1,HELPP	;IF TOTALLY UNKNOWN, GIVE HELP TEXT
	MOVEI	M,[ASCIZ .NOT UNIQUE ARGUMENT
.]
	PUSHJ	P,MSG		;GIVE MESSAGE
	JRST	HELPP		;AND GO GIVE HELP TEXT
	SUBTTL	RESETP - RESET ALL OR SPECIFIC DRIVE STATISTICS

RESETP:	TLNE	F,BREAK		;AT END OF LINE?
	JRST	RESET3		;YES, GO DO ANY WORK REQUIRED
	PUSHJ	P,SIXAN		;GET NEXT DEVICE NAME IN STRING
	JUMPE	M,RESET3	;ALL BLANK WE'RE DONE
	MOVEM	CH,TERMCH	;SAVE TERMINATOR
	CAMN	M,[SIXBIT .ALL.] ;RESET ALL?
	TLOA	F,DOALL		;YES, MARK SUCH AND SKIP NEXT
	SKIPA	P1,UDBST	;NO,GET AOBJN PTR AND SKIP NEXT
	JRST	RESET3		;IF RESET ALL, GO  DO ALL OF THEM
RESET2:	MOVE	P4,(P1)		;GET ADDRESS OF UDB
	MOVEI	T1,UNINAM(P4)	;GET ADDRESS OF UNIT NAME
	PUSHJ	P,PEKSPY	;GET NAME
	CAMN	T1,M		;MATCH REQUEST?
	JRST	RESE2A		;YES, BRANCH
	AOBJN	P1,RESET2	;ELSE, KEEP LOOKING
	  JRST	RESER1		;NOT FOUND  IS ERROR
RESE2A:	HRROS	(P1)		;MATCH, MARK TO RESET WITH "DO" BIT
	JRST	RESETP		;GO GET NEXT RESET UNIT

;DO ACTUAL RESET WORK ON DISK

RESET3:	PUSHJ	P,OPNDSK	;OPEN THE DISK FILES
RESET4:	PUSHJ	P,DKI		;GET UNIT NAME FROM DISK
	JUMPE	T1,RESEND	;END OF SEARCH IF ZERO
	MOVE	P3,T1		;SAVE NAME
	PUSHJ	P,DKO		;OUTPUT TO NEW DISK FILE
	MOVE	P1,UDBST	;GET AOBJN PTR TO UDB ADDR
RESET5:	MOVE	P4,(P1)		;GET UDB ADDRESS
	MOVEI	T1,UNINAM(P4)	;GET ADDRESS OF UNIT NAME
	PUSHJ	P,PEKSPY	;GET NAME
	CAMN	T1,P3		;MATCH?
	JRST	RESET6		;YES, CHECK FOR RESET STATUS
	AOBJN	P1,RESET5	;NO, LOOP
	JRST	RESET7		;CHECKED ALL UDB'S, SKIP RECORD
RESET6:	TLNN	F,DOALL		;IS THIS A RESET ALL?
	SKIPG	(P1)		;  OR A UNIT TO BE RESET?
	JRST	RESET8		;YES, GO DO IT
RESET7:	PUSHJ	P,SKPREC	;NO, JUST SKIP THIS DISK RECORD
	JRST	RESET4		;  AND GET NEXT DISK RECORD
;FOUND DISK RECORD AND UDB TO RESET, DO IT

RESET8:	TLO	F,NOCALC	;SET WE DON'T WANT DELTAS
	PUSHJ	P,UPDATE	;UPDATE THE FILE
	TLZ	F,NOCALC	;RETURN ORIGINAL STATE
	PUSHJ	P,DKI		;READ # HARD ERRORS
	SETZ	T1,		;ZERO IT
	PUSHJ	P,DKO		;WRITE TO FILE
	PUSHJ	P,DKI		;GET TOTAL READS
	SETZ	T1,		;ZERO IT
	PUSHJ	P,DKO		;WRITE TO FILE
	PUSHJ	P,DKI		;GET TOTAL WRITES
	SETZ	T1,		;ZERO IT
	PUSHJ	P,DKO		;WRITE TO FILE
	HRRZS	(P1)		;RESET "DO" BIT
	JRST	RESET4		;GO DO NEXT DISK RECORD

;HERE WHEN TROUGH ALL OF FILE

RESEND:	TLZ	F,DOALL		;TURN OFF RESET ALL BIT
	OUTPUT	DS1,
	CLOSE	DSK,
	CLOSE	DS1,
	PUSHJ	P,LINEAT
	JRST	PRDPRO
	SUBTTL	ERROR ROUTINES - WARNINGS

WHTER1:	PUSHJ	P,NOUDB		;OUPUT ERROR MSG, IGNORE DISK RECORD
	JRST	WHAT2		;GO ON TO NEXT UDB

OLDER1:	PUSHJ	P,NOUDB		;OUTPUT ERROR MSG, IGNORE DISK RECORD
	JRST	OLDRU1		;GO GET NEXT DISK RECORD

NOUDB:	MOVEI	M,[ASCIZ .	****NO UDB IN SYSTEM***.]
	PUSHJ	P,MSG		;OUTPUT ERROR MESSAGE
	PJRST	SKPREC		;SKIP RECORD AND RETURN TO CALLER

RESER1:	MOVEI	CH,"%"		;GET A %
	PUSHJ	P,TYO		;OUTPUT IT
	PUSHJ	P,SIXBPA	;AND THEN UNIT'S NAME
	MOVEI	M,[ASCIZ . NOT FOUND AS UNIT IN SYSTEM
.]
	PUSHJ	P,MSG		;OUTPUT REST OF WARNING
	JRST	RESETP		;AND GO CHECK NEXT ENTRY IN LINE

ERRERR:	MOVEI	M,[ASCIZ .% MUST SUPPLY THREE ARGS-DEV,DAT,TOT - NO INFO STORED
.]
	PUSHJ	P,MSG
	JRST	ERRWHT		;AFTER MESSAGE GIVE INFO TO USER

SLPERD:	MOVEI	M,[ASCIZ .% MORE THAN 23:59:59 AS SLEEP PERIOD NOT ALLOWED.]
	PUSHJ	P,MSG
	JRST	SLPWH3		;OUTPUT CRLF THEN PROMPT AND CONTINUE
	SUBTTL	ERROR ROUTINES - FATAL ERRORS WHICH HAVE ADDED INFO

DAEERR:	MOVEI	M,[ASCIZ .
?DAEMON UUO FAILED - .]
	PUSHJ	P,MSG		;START ERROR MESSAGE
	CAIN	T1,DAECLK	;HAS AC CHANGED?
	SKIPA	M,[ASCIZ .DAEMON IS NOT RUNNING.]
	MOVE	M,DAEMSG-1(T1)	;NO, GET PROPER MESSAGE
	JRST	PRTERR		;GO TELL HIM AND GET OUT

LEERR:	HRRZ	N,1(T1)	;GET ERROR CODE FROM PROPER BLOCK
	MOVEI	M,[ASCIZ .
?LOOKUP OR ENTER ERROR - .]
	PUSHJ	P,MSG		;OUTPUT FIRST PART
	MOVE	M,LEMSG(N)	;GET MESSAGE
	PUSHJ	P,OCTPRT	;OUTPUT ERROR CODE
	PUSHJ	P,MSG		;OUTPUT EXPLAINATION
	PJRST	DSKER2

DSKER1:	SKIPA	M,[ASCIZ .
?UNEXPLAINABLE DISK ERROR.]
DSKERR:	MOVEI	M,[ASCIZ .
?DISK ERROR.]
	PUSHJ	P,MSG
	MOVE	N,T1		;GET ERROR STATUS TO PROPER REGISTER
	MOVEI	M,[ASCIZ . STATUS = .]
	PUSHJ	P,MSG
	PUSHJ	P,OCTPRT	;OUTPUT STATUS OF ERROR
DSKER2:	MOVEI	M,[ASCIZ .
.]
	PJRST	PRTERR

LEMSG:	EXP	[ASCIZ .	FILE NOT FOUND.]
	EXP	[ASCIZ .	NO UFD.]
	EXP	[ASCIZ .	PROTECTION FAILURE.]
	EXP	[ASCIZ .	FILE BEING MODIFIED.]
	EXP	LEWRG		;CAN(T HAPPEN MESSAGE
	EXP	LEWRG		;CAN'T HAPPEN MESSAGE
	EXP	[ASCIZ .	ERROR DETECTED READING UFD OR RIB.]
	EXP	LEWRG		;7 CAN'T HAPPEN
	EXP	LEWRG		;10 CAN'T HAPPEN
	EXP	LEWRG		;11 CAN'T HAPPEN
	EXP	LEWRG		;12 CAN'T HAPPEN
	EXP	LEWRG		;13 CAN'T HAPPEN
	EXP	[ASCIZ .	NO ROOM OR QUOTA EXCEEDED.]
	EXP	[ASCIZ .	WRITE LOCK ERROR.]
	EXP	[ASCIZ .	NOT ENOUGH MONITOR FREE CORE.]
	EXP	LEWRG		;17 CAN'T HAPPEN
	EXP	[ASCIZ .	BLOCK NOT FREE ON ALLOCATED POSITION.]
	EXP	LEWRG		;21 CAN'T HAPPEN
	EXP	LEWRG		;22 CAN'T HAPPEN
	EXP	[ASCIZ .	SFD NOT FOUND.]
	EXP	[ASCIZ .	SEARCH LIST EMPTY.]
	EXP	LEWRG		;25 CAN'T HAPPEN
	EXP	[ASCIZ .	ALL STR'S ARE NO-CREATE AND NO-WRITE.]
	EXP	LEWRG		;27 CAN'T HAPPEN
LEWRG:	ASCIZ	.	ERROR CAN'T HAPPEN.

DAEMSG:	EXP	[ASCIZ .ILLEGAL FUNCTION.]
	EXP	[ASCIZ .ADDRESS CHECK.]
	EXP	[ASCIZ .WRONG NUMBER OF ARGUMENTS.]
	EXP	[ASCIZ .READY FOR THIS - IMPOSSIBLE ERROR.]
	EXP	[ASCIZ .CANNOT WRITE FILE - OPEN FAILED.]
	EXP	[ASCIZ .NO PRIVILEGES.]
	EXP	[ASCIZ .BAD FACT FORMAT.]
	EXP	[ASCIZ .INVALID PATH.]
	SUBTTL	ERROR ROUTINES - FATAL ERRORS, NO EXTRA INFORMATION

SPYER1:	SKIPA	M,[ASCIZ .
?GETTAB FAILED, CAN'T GET SIZE OF SYSTEM, SPYING IMPOSSIBLE
.]
SPYER2:	MOVEI	M,[ASCIZ .
?NO SPY PRIVILEGES, MUST HAVE THEM TO RUN WTCHER
.]
	JRST	PRTERR

HBRERR:	SKIPA	M,[ASCIZ .
?HIBER MONITOR CALL FAILED
.]

GTUERR:	MOVEI	M,[ASCIZ .
?CAN'T GET ADDRESS OF FIRST UDB - IMPOSSIBLE TO CONTINUE
.]
	JRST	PRTERR

TIMERR:	SKIPA	M,[ASCIZ .
?CAN'T GET TIME OF DAY FROM SYSTEM VIA GETTAB OR SPY
.]

CORER1:	MOVEI	M,[ASCIZ .
?CAN'T GET ENOUGH CORE AFTER REQUEST BY PLACER
.]


PRTERR:	PUSHJ	P,MSG		;PRINT THE GIVEN ERROR MESSAGE
	EXIT			;AND GIVE UP
	SUBTTL	TTY OUTPUT SUBROUTINES

;SUBROUTINE TABPRT - OUTPUT A TAB
;	NO ARGS USED

TABPRT:	MOVEI	CH,"	"	;GET TAB TO PROPER AC
	PJRST	TYO		;OUTPUT IT AND LET TYO RETURN TO USER

;SUBROUTINE CRLF - OUTPUT A <CR><LF> - ALSO FORCES OUTPUT UUO
;	NO ARGS USED

CRLF:	MOVEI	CH,15		;GET <CR>
	PUSHJ	P,TYO		;OUTPUT IT
	MOVEI	CH,12		;GET <LF>
	PJRST	TYO		;OUTPUT AND LET TYO DO POPJ FOR ME

;SUBROUTINE DECPRT - PRINT A DECIMAL NUMBER
;	INPUT - N HAS NUMBER TO CONVERT AND PRINT

DECPRT:	MOVEI	R,12		;SET RADIX
	TLNE	F,DECMAL	;SHOULD WE PRINT A DECIMAL POINT?
	PJRST	RDXPRT		;NO, JUST JRST TO RDXPRT
	PUSHJ	P,RDXPRT	;NO, OUTPUT WITH THIS RADIX
	MOVEI	CH,"."		;GET A DOT TO SHOW DECIMAL OUTPUT
	PJRST	TYO		;AND FINISH WITH THAT
OCTPRT:	MOVEI	R,10		;SET PROPER RADIX
RDXPRT:	IDIVI	N,(R)		;GET A DIGIT
	HRLM	N1,0(P)		; AND SAVE ON STACK
	SKIPE	N		;ARE WE DONE SEPARATING DIGITS?
	PUSHJ	P,RDXPRT	;NO, GO GET NEXT DIGIT
	HLRZ	CH,0(P)		;YES, GET HIGH ORDER DIGIT
	ADDI	CH,"0"		;TURN IT INTO ASCII
;;	JRST	TYO		;FALL THROUGH TO OUTPUT ROUTINE

;SUBROUTINE TYO - PLACE CHARACTER INTO BUFFER FOR TTY OUT
;	INPUT - CH HAS CHARACTER TO TYPE
;	OUTPUT - FULL BUFFER TO TTY/LINE FEED ALSO ENDS BUFFER

TYO:	SOSG	TYOB+2
	OUTPUT	TTY,
	IDPB	CH,TYOB+1
	CAIN	CH,12		;IS CHARACTER A LINE FEED?
	OUTPUT	TTY,		;YES, FORCE OUTPUT
	POPJ	P,
;MORE USEFUL TTY OUTPUT ROUTINES

;SUBROUTINE MSG - OUTPUT A GIVEN ASCIZ STRING
;	INPUT- M ADDRESS OF ASCIZ STRING
;		NOTE THAT A BYTE OF 0 TERMINATES STRING

MSG:	HRLI	M,440700	;MAKE M A BYTE POINTER
MSG1:	ILDB	CH,M		;GET A CHARACTER
	JUMPE	CH,CPOPJ	;IS IT A NUL? IF SO, WE'RE DONE
	PUSHJ	P,TYO		;SEND A CHAR
	JRST	MSG1		;GO GET THE NEXT

;SUBROUTINE SIXBPA - OUTPUT SIXBIT WORD IN M - STOP AT NULL
;SUBROUTINE SIXBP - OUTPUT SIXBIT WORD IN M - ALL SIX CHARACTERS
;	INPUT - M HAS SIXBIT WORD TO OUTPUT
;	NOTE:	T1 IS DESTROYED

SIXBPA:	TLOA	F,BPAF		;SET TO STOP AT FIRST NULL
SIXBP:	TLZ	F,BPAF		;SET TO OUTPUT ALL SIX CHARACTERS
	MOVE	T1,[XWD 440600,M] ;SET UP BYTE PTR FOR SIXBIT WORD
SIXBP1:	ILDB	CH,T1		;GET A CHARACTER FROM M
	TLNE	F,BPAF		;ARE WE STOPPING AT NULL'S??
	JUMPE	CH,CPOPJ	;YES, IS IT A NULL?
	ADDI	CH,40		;NO TO EITHER, MAKE AN ASCII CHAR
	PUSHJ	P,TYO		;OUTPUT
	TLNE	T1,770000	;HAVE WE PRINTED 6 CHARACTERS
	JRST	SIXBP1		;NO, LOOP
	POPJ	P,		;ELSE, RETURN
	SUBTTL	TTY INPUT SUBROUTINES

;SUBROUTINE DECIN - INPUT A DECIMAL NUMBER
;	OUTPUT - N HAS NUMBER IN DECIMAL
;		CH HAS TERMINATING CHARACTER IN ASCII

DECIN:	SETZ	N,		;START AT ZERO
	PUSHJ	P,SST		;GET FIRST NON-BLANK
DECIN1:	CAIL	CH,"0"		;IS THIS CHARACTER
	CAILE	CH,"9"		;  A NUMERIC?
	POPJ	P,		;NO, EXIT
	IMULI	N,^D10		;ELSE, MOVE RESULTANT OVER
	ADDI	N,-"0"(CH)	;  AND PUT IN NEW LOW ORDER DIGIT
	PUSHJ	P,TYI		;GET NEXT CHARACTER
	  POPJ	P,		;BREAK MEANS WE'RE DONE
	JRST	DECIN1		;GET NEXT

;SUBROUTINE SIXAN - INPUT CHARACTERS TO FIRST NON-ALPHAMERIC
;	OUTPUT - M HAS SIXBIT WORD (MORE THAN 6 CHARACTER STRING RETURNS
;		ONLY FIRST SIX CHARACTERS)
;		 CH HAS TERMINATING CHARACTER IN ASCII
;	NOTE:	T1 IS DESTROYED

SIXAN:	MOVE	T1,[XWD 440600,M] ;SET UP BYTE POINTER FOR OUTPUT
	SETZ	M,		;INITIALIZE AC
	PUSHJ	P,SST		;GET FIRST NON-BLANK CHARACTER
SIXAN1:	CAIL	CH,"0"		;IS THIS CHARACTER
	CAILE	CH,"9"		;  A NUMERIC?
	CAIA			;NO, CHECK FOR AN ALPHA
	JRST	SIXAN2		;YES, MAKE SIXBIT
	CAIL	CH,"A"		;IS THIS CHARACTER
	CAILE	CH,"Z"		;  AN ALPHA?
	POPJ	P,		;NEITHER, RETURN
SIXAN2:	SUBI	CH,40		;ELSE, MAKE SIXBIT
	TLNE	T1,770000	;HAVE WE FILLED THE AC?
	IDPB	CH,T1		;NO, PUT IN NEXT CHARACTER
	PUSHJ	P,TYI		;GET NEXT CHARACTER
	  POPJ	P,		;BREAK CHAR MEANS RETURN
	JRST	SIXAN1		;ELSE, GO PROCESS THIS CHARACTER

;SUBROUTINE SST - SKIP SPACES PRECEEDING AN ARG
;	OUTPUT - CH HAS 1ST NON-BLANK CHARACTER

SST:	PUSHJ	P,TYI		;GET A CHARACTER
	  POPJ	P,		;OBVIOUSLY NOT A BLANK OR TAB
	CAIE	CH," "		;IS THIS A SPACE?
	CAIN	CH,"	"	;  OR A TAB?
	JRST	SST		;YES, LOOP FOR NEXT
	POPJ	P,		;NO, WE'VE GOT A CHARACTER
;MORE USEFUL TTY INPUT ROUTINES

;SUBROUTINE TYI - INPUT A CHARACTER
;	OUTPUT	- CH HAS ASCII CHARACTER WITH FOLLOWING RESTRICTIONS
;		NULLS(000) AND RUBOUTS(177) ARE IGNORED
;		175 AND 176 ARE CONVERTED TO ALTMODE(033)
;		^C(003) AND ^Z(032) CAUSE EXIT
;		<CR>(015), <LF>(012), <VT>(013), <FF>(014), AND ALTMODE
;		(033) SET BREAK IN F AND CAUSE NON-SKIP RETURN
;		ALL CHARACTERS ARE CONVERTED TO UPPER CASE

TYI:	SOSG	TYIB+2		;CHECK FOR CHARACTER IN BUFFER
	INPUT	TTY,		;NO, GET NEXT BUFFER
	ILDB	CH,TYIB+1	;GET CHARACTER
	JUMPE	CH,TYI		;IS IT A NULL?
	CAIN	CH,177		;OR A RUBOUT?
	JRST	TYI		;EITHER WAY GO GET NEXT CHARACTER
	CAIL	CH,175		;IS THIS OLD ALTMODE?
	MOVEI	CH,33		;IF SO, MAKE A NEW ALTMODE
	CAIL	CH,140		;IS THIS LOWER CASE?
	TRZ	CH,40		;YES, MAKE UPPER CASE
	CAIE	CH,3		;IS IT ^C
	CAIN	CH,32		;  OR ^Z?
	EXIT			;YES, EXIT
	TLZ	F,BREAK		;ASSUME THIS ISN'T BREAK CHARACTER
	CAIN	CH,15		;IS THIS A <CR>?
	JRST	TYI		;YES, IGNORE IT THERE'LL BE A <LF>
	CAIG	CH,15		;BETWEEN <CR> AND
	CAIGE	CH,12		;  <LF>?
	CAIN	CH,33		;OR IS IT ALTMODE?
	TLOA	F,BREAK		;YES, SET BIT AND SKIP NEXT
CPOPJ1:	AOS	(P)		;INCREMENT RETURN ADDRESS FOR SKIP
CPOPJ:	POPJ	P,		;RETURN TO CALLER
	SUBTTL	DISK OPEN/INPUT/OUTPUT SUBROUTINES

;SUBROUTINE OPNDSK - OPENS DSK:WTCHER.STS IN EITHER UPDATE MODE
;	NO ARGS ARE SUPPLIED OR RETURNED, HOWEVER T1 IS DESTROYED

OPNDSK:	OPEN	DSK,DSKOPN	;OPEN INPUT SIDE
	  JRST	DSKERR		;OOPS!
	LOOKUP	DSK,LOKBLK	;READ ONLY ON THIS CHANNEL
	  JRST	LEERR		;AW SHUCKS...
	TLNE	F,WHTREQ	;DO WE WANT AN OUTPUT SIDE?
	JRST	OPNDS1		;NO, DON'T OPN IT
	OPEN	DS1,DSKOPN	;OPEN OUTPUT SIDE
	  JRST	DSKERR		;OOPS!!
	MOVEI	T1,ENTBLK	;SET UP AND THEN
	PUSHJ	P,OPNDS2	;  CLEAR ENTER BLOCK
	ENTER	DS1,ENTBLK	;CREATE ON THIS CHANNEL
	  JRST	LEERR		;AW SHUCKS...
OPNDS1:	MOVE	T1,DKIBS	;GET SAVED RING HEADER INFO
	MOVEM	T1,DKIB		;AND SETUP RING
	MOVE	T1,DKOBS	;GET SAVED RING HEADER INFO
	MOVEM 	T1,DKOB		;AND SETUP RING
	HLLZS	DKIB+1
	HLLZS	DKOB+1
	POPJ	P,		;ALL SHOULD BE WELL
OPNDS2:	SETZM	3(T1)
	SETZM	2(T1)
	HLLZS	1(T1)
	POPJ	P,

;SUBROUTINE DKO - PLACE WORD INTO DISK OUTPUT BUFFER
;	INPUT - T1 HAS WORD TO OUTPUT

DKO:	SOSG	DKOB+2
	OUTPUT	DS1,		;OUTPUT BLOCK
	IDPB	T1,DKOB+1
	POPJ	P,

;SUBROUTINE DKI - GET WORD FROM DISK
;	OUTPUT - T1 HAS WORD FROM DISK FILE

DKI:	SOSG	DKIB+2		;ANYTHING IN BUFFER?
	PUSHJ	P,DKI1		;NO, GET SOMETHING
	ILDB	T1,DKIB+1	;ELSE, LOAD NEXT WORD
	POPJ	P,		; AND RETURN
DKI1:	IN	DSK,		;ELSE,GET NEXT BLOCK
	POPJ	P,		;NO PROBLEMS, RETURN
	GETSTS	DSK,T1		;ELSE, GET STATUS
	TRNE	T1,IO.IMP!IO.DER!IO.DTE!IO.BKT ;ANY REAL ERRORS?
	  JRST	DSKERR		;YES, COMPLAIN BITTERLY
	TRNN	T1,IO.EOF	;MAKE SURE IT'S EOF
	  JRST	DSKER1		;NOT, THERE'S SOMETHING MESSED UP!
	TLO	F,DSKEOF	;ELSE SET EOF FOR TESTING
	POPJ	P,		; AND RETURN
	SUBTTL	MISCELLANEOUS DISK UPDATE SUBROUTINES

;SUBROUTINE UPDATE - DO UPDATE PROCESSING BASED ON FLAG REGISTER
;	FOR ALL BUT TOTALS AND ACTUAL UNIT NAME
;
;	INPUT - P4 CONTAINS THE MONITOR ADDRESS OF THE UDB
;		F HAS FLAGS NOCALC,WHTREQ,VMSER SET PROPERLY
;	OUTPUT - T3 WILL CAONTAIN ACCUMULATED TOTAL READS
;		 T4 WILL CONTAIN ACCUMULATED TOTAL WRITES
;		 T5 WILL CONTAIN ACCUMULATED TOTAL HARD ERRORS
;		THESE VALUES ARE DELTA (LAST-SEEN-VALUE-FROM-DISK-
;			RECORD, VALUE-FROM-UDB)
;		OR ACTUALLY COME FROM UDB VALUES ONLY DEPENDING ON
;		FLAG NOCALC - ON FOR UDB VALUES ONLY
;			    - OFF FOR DELTAS
;		DISK LAST-SEEN-VALUE IS UPDATED OR NOT DEPENDING ON
;		FLAG WHTREQ - ON DO NOT UPDATE
;			    - OFF UPDATE DISK
;		FLAG VMSER IS ON IF THIS IS A VM SYSTEM IMPLYING
;			UNIPCI AND UNIPCO EXIST

UPDATE:	SETZB	T3,T4		;ZERO READ/WRITE ACCUMULATORS
	MOVEI	T1,UNIHCT(P4)	;ADDRESS OF # HARD ERRORS
	PUSHJ	P,DELTA		;GET DELTA HARD ERRORS
	MOVE	T5,T1		;GET HARD ERRORS TO PROPER AC
	MOVEI	T1,UNIBRC(P4)	;GET BUFFERED READ DELTA
	PUSHJ	P,DELTA
	ADD	T3,T1		;AND ACCUMULATE TO TOT DELTA READS
	MOVEI	T1,UNIBWC(P4)	;GET BUFFERED WRITE DELTA
	PUSHJ	P,DELTA	
	ADD	T4,T1		;AND ACCUMULATE TO TOT DELTA WRITES
	MOVEI	T1,UNIDRC(P4)	;GET DUMP MODE READ DELTA
	PUSHJ	P,DELTA
	ADD	T3,T1		;ACCUMULATE
	MOVEI	T1,UNIDWC(P4)	;GET DUMP MODE WRITE DELTA
	PUSHJ	P,DELTA
	ADD	T4,T1		;ACCUMULATE
	MOVEI	T1,UNIMRC(P4)	;GET MONITOR READ DELTA
	PUSHJ	P,DELTA	
	ADD	T3,T1		;ACCUMULATE
	MOVEI	T1,UNIMWC(P4)	;GET MONITOR WRITE DELTA
	PUSHJ	P,DELTA
	ADD	T4,T1		;ACCUMULATE
	TLNN	F,VMSER		;IS THIS A VM SYSTEM?
	JRST	UPDAT1		;NO, NO PAGING STATS
	MOVEI	T1,UNIPCI(P4)	;ELSE, GET PAGES IN
	PUSHJ	P,DELTA
	PUSH	P,T1		;SAVE IT
	MOVEI	T1,UNIPCO(P4)	;NOW GET PAGES OUT
	PUSHJ	P,DELTA
	POP	P,T2		;GET SAVED PCI TO T2
	SKIPA			;SKIP NEXT AS IS FOR NON-VM SYSTEMS
UPDAT1:	SETZB	T1,T2		;NON-VM GET 0 PAGE COUNTS
	ADD	T3,T2		;ACCUMULATE BLOCKS IN FROM PAGING
	ADD	T4,T1		;ACCUMULTATE BLOCKS OUT FROM PAGING
	POPJ	P,		;RETURN TO USER
;MORE DISK UPDATE ROUTINES

;SUBROUTINE  DELTA - GET UDB VALUE SPECIFIED AND DISK VALUE GIVE AS
;	RETURN EITHER DELTA OF TWO, OR ACTUAL UDB VALUE, DEPENDING ON
;	FLAG BIT NOCALC.
;	UDB VALUE IS STORED TO DISK FOR NEXT PASS DEPENDING ON FLAG
;	BIT WHTREQ.
;	INPUT - T1 HAS ADDRESS OF UDB VALUE WANTED
;	OUTPUT - T1 HAS COMPUTED DELTA BETWEEN UDB AND SAVED VALUE
;		   OR ACTUAL UDB VALUE FROM MONITOR

DELTA:	PUSHJ	P,PEKSPY	;GET UDB VALUE
	TLNN	F,WHTREQ	;IS THIS A REQUEST OR SCHEDULED?
	PUSHJ	P,DKO		;SCHEDULED, OUTPUT NEW VALUE
	TLNE	F,NOREAD	;DO READ OF DISK FILE?
	POPJ	P,		;NO, WE'RE DONE
	MOVE	T2,T1		;SAVE UDB VALUE
	PUSHJ	P,DKI		;GET LAST VALUE SEEN FROM DISK
	TLNE	F,NOCALC	;DO WE WANT DELTA OR ACTUAL UDB?
	SKIPA	T1,T2		;ACTUAL, GET IT AND SKIP NEXT
	SUBM	T2,T1		;GET DIFFERENCE
	POPJ	P,		; AND RETURN


;SUBROUTINE SKPREC - SKIP A RECORD ON THE DISK FILE, OUTPUTTING IT
;	TO DISK.  THIS DOES NOT INCLUDE THE UNIT NAME AND IS ASSUMED TO
;	ALREADY BE INPUT AND OUTPUT.

SKPREC:	MOVEI	P1,^D12		;SET UP COUNTER FOR I/O LOOP
	TLNN	F,VMSER		;IS THIS VM SYSTEM?
	MOVEI	P1,^D10		;NO,ONLY 10 ENTRIES/UDB
SKPRE1:	PUSHJ	P,DKI	;GET NEXT WORD
	TLNN	F,WHTREQ	;SHOULD WE DO OUTPUT?
	PUSHJ	P,DKO		;OUTPUT IT
	SOJG	P1,SKPRE1	;LOOP THROUGH ENTIRE SAVED DATA BLOCK
	POPJ	P,		;AND CONTINUE ON TO NEXT UDB
	SUBTTL	MISCELLANEOUS SUBROUTINES

;SUBROUTINE LINEAT - EAT ANY LINE INPUT UP TO END OF LINE AND PROMPT
;	NO INPUT OR OUTPUT

LINEAT:	TLNE	F,BREAK		;AT END OF LINE?
	JRST	LINEA2		;YES, GO PROMPT
LINEA1:	PUSHJ	P,TYI		;GET A CHARACTER
	TLNN	F,BREAK		;ARE WE THROUGH?
	JRST	LINEA1		;NO, LOOP
LINEA2:	OUTSTR	[ASCIZ .
*.]
	POPJ	P,		;AND RETURN

;SUBROUTINE GETMSK - CREATE A MASK OF ONES IN T1 FOR CHARS IN M
;	INPUT - M HAS SIXBIT CHARACTERS
;	OUTPUT- T1 HAS MASK

GETMSK:	SETZ	T1,		;CLEAR MASK
	JUMPE	M,CPOPJ		;ANY CHARACTERS AT ALL?
	TLO	T1,770000	;AT LEAST 1, MAKE MASK
	PUSH	P,M		;SAVE M
GETMS1:	LSH	M,6		;GET RID OF CHARACTER WE KNOW OF
	JUMPE	M,MPOPJ		;QUIT IF DONE
	ASH	T1,-6		;NOT DONE, INCREASE MASK
	JRST	GETMS1		;  AND LOOP
MPOPJ:	POP	P,M		;RESTORE M
	POPJ	P,		;AND RETURN TO CALLER

;SUBROUTINE CMDSRC - SEARCH FOR NAME OR ABBREV IN TABLE
;	INPUT - M HAS SIXBIT COMMAND
;		P1 HAS AOBLN POINTER TO TABLE OF COMMANDS
;	OUTPUT-
;		SKIP RETURN HAS INDEX IN T1
;		NON-SKIP RETURN IF UNKNOWN(T1=0) OR NOT UNIQUE(T1 NOT 0)

CMDSRC:	PUSHJ	P,GETMSK	;GET MASK FOR ABBREVIATIONS
	MOVE	T5,T1		;SAVE MASK FOR LATER USE
	SETO	T2,		;SETUP MATCH COUNTER
	SETZ	T3,		;INITIALIZE POINTER SAVER
	MOVE	T1,P1		;COPY AOBJN POINTER
CMDSR1:	MOVE	T4,(T1)		;GET COMMAND CANDIDATE
	XOR	T4,M		;MASK WITH GIVEN COMMAND
	JUMPE	T4,CMDSR3	;EXACT MATCH ALWAYS WINS
	AND	T4,T5		;ELSE, CUT COMPARE TO ABBREV SIZE
	JUMPN	T4,CMDSR2	;DOES ABBREVIATION MATCH?
	MOVE	T3,T1		;YES, SAVE POSSIBLE WINNER
	ADDI	T2,1		;COUNT SUCCESS AND KEEP TRYING
CMDSR2:	AOBJN	T1,CMDSR1	;LOOP FOR ALL ENTRIES
	MOVE	T1,T3		;DONE, RESTORE POSSIBLE WINNER
	JUMPN	T2,CPOPJ	;ONE AND ONLY ONE WINNER?
CMDSR3:	SUB	T1,P1		;COMPUTE AN INDEX
	TLZ	T1,-1		;CLEAR THE RIGHT HALF
	JRST	CPOPJ1		;AND GIVE A GOOD RETURN
	SUBTTL	CORE MANAGEMENT SUBROUTINES

;SUBROUTINE GTBSPY - PERFORM GETTAB VIA SPY IF POSSIBLE
;	INPUT - T1 HAS GETTAB ARGUMENT
;	OUTPUT- T1 HAS GETTAB VALUE IF SKIP RETURN
;NOTE: THERE IS NO NEED TO SUPPORT -2 ITEM (JOB'S HIGH SEG)

GTBSPY:	JUMPGE	T1,GTBSP1	;ENSURE NEGATIVE ARG MEANS JOB
	PJOB	T2,		;GET JOB NUMBER IF NEEDED
	HRL	T1,T2		;PLACE IN RIGHT PLACE
GTBSP1:	HRRZI	T2,(T1)		;GET TABLE NUMBER
	CAML	T2,MAXGTB	;IS IT A LEGAL ENTRY?
	JRST	GTBGTB		;NO, TRY A GETTAB ANYWAY
	ADD	T2,GTBST	;MAKE ADDRESS OF POINTER TO TABLE
	MOVE	T3,(T2)		;GET MODIFIED NUMTAB WORD
	TLNE	T3,(GT.PRC)	;IS IT IN THE PDB?
	JRST	GTBPDB		;YES, O IT THAT WAY
	LDB	T3,[POINT 9,T3,8] ;NO, GET MAX ITEM VALUE
	MOVSS	T1		; AND ITEM NO. OF INPUT TO RIGHT
	CAIGE	T3,(T1)		;IS DESIRED IN RANGE?
	JRST	GTBGT1		;NO, TRY A GETTAB ANYWAY
	MOVE	T1,@(T2)	;YES, GET THE VALUE
	JRST	CPOPJ1		;AND GIVE GOOD RETURN

GTBPDB:	SKIPN	PDBPTR		;IS JBTPDB BASE AVAILABLE
	JRST	GTBGTB		;NO, TRY A GETTAB
	HLRZ	T3,T1		;GET THE JOB NUMBER
	ADD	T3,PDBPTR	;ADD JBTPDB ADDRESS
	MOVE	T3,400000(T3)	;GET ADDRESS OF JOB'S PDB
	ADD	T3,(T2)		;FIND PROPER ITEM ADDRESS
	MOVE	T1,(T3)		;GET THE DESIRED VALUE
	JRST	CPOPJ1		;AND RETURN HAPPY

GTBGT1:	MOVSS	T1		;RESTORE T1 TO ORIGINAL
GTBGTB:	GETTAB	T1,		;TRY THE GETTAB
	  POPJ	P,		;EXPECTED RETURN
	AOS	GTBWRG		;COUNT UNEXPECTED GOOD RETURNS
	JRST	CPOPJ1		;AND PRETEND WE AREN'T BOTHERED
;MORE CORE MANAGEMENT ROUTINES

;SUBROUTINE PEKSPY - PERFORM PEEK VIA SPY IF POSSIBLE
;	INPUT - T1 HAS ADDRESS OF LOCATION DESIRED
;	OUTPUT- T1 HAS CONTENTS OF LOCATION

PEKSPY:	SKIPE	MAXGTB		;SKIP IF SPY IS ILLEGAL
	SKIPA	T1,400000(T1)	;OK, GET CONTENTS OF LOCATION
	PEEK	T1,		;CAN'T SPY, TRY PEEK
	POPJ	P,		;EITHER WAY WE HAVE TO RETURN


;SUBROUTINE PLACER - PUT ARG INTO NEXT AVAILABLE LOCATION
;	INPUT - T1 HAS WORD TO BE PLACED IN CORE
;	T2 AND T3 ARE USED
;	T2 CONTAINS LOCATION OF NEXT FREE ON RETURN

PLACER:	AOS	T2,.JBFF	;NEW FIRST FREE
	CAMG	T2,.JBREL	;SKIP IF MUST EXPAND
	JRST	PLACE1		;NO, GO AHEAD
	MOVE	T3,T2		;SET UP FOR MORE CORE REQUEST
	CORE	T3,		;ASK FOR IT
	  JRST	CORER1		;OH WELL....
PLACE1:	MOVEM	T1,-1(T2)	;STORE ARG INTO NEXT LOCATION
	POPJ	P,		;AND RETURN
	SUBTTL	COMMANDS - DEFINE COMMANDS

;MACRO NAMES - THIS MACRO DEFINES ALL COMMANDS AS A FUNCTION OF THE
;		MACRO COM.
;	COM HAS THREE (3) ARGUMENTS -
;		COMMAND NAME - ACTUAL COMMAND USED BY OPERATOR
;				THIS SHOULD BE NO LONGER THAN SIX
;				(6) CHARACTERS, AT LEAST THAT IS ALL
;				OF THE NAME USED FOR PARSING.
;		DISPATCH ADDRESS - ACTUAL LABEL TO BRANCH TO FOR
;				PROCESSING OF THE COMMAND. IF THIS
;				ARG IS BLANK, THE COMMAND NAME IS USED
;				AS THE DISPATCH ADDRESS.
;		HELP TEXT ADDRESS - LABEL OF THE ASCIZ STRING OF THE
;				HELP TEXT FOR THIS COMMAND. IF THIS 
;				ADDRESS IS BLANK THE MESSAGE "NO HELP"
;				IS GIVEN.

DEFINE NAMES <
	COM	HELP,,HLPTXT
	COM	RESET,,RSTTXT
	COM	SLEEP,,SLPTXT
	COM	EXIT,,EXTTXT
	COM	WHAT,,WHTTXT
	COM	ERRMAX,ERRMAP,ERRTXT
>
;ACTUAL TABLE DEFINITIONS

;COMMAND TABLE - DEFINE THE SIXBIT COMMANDS

DEFINE COM(A,B,C) <
	SIXBIT	/A/
>
COMTAB:	NAMES
DISPL==.-COMTAB		;LENGTH OF TABLES


;COMMAND DISPATCH ADDRESSES

DEFINE COM(A,B,C) <
	IFB <B>,< EXP A'P >
	IFNB <B>,< EXP B >
>
COMADR:	NAMES


;HELP TEXT MESSAGES

DEFINE COM(A,B,C) <
	IFB <C>,< EXP NOHELP >
	IFNB <C>,< EXP C >
>
COMHLP:	NAMES
	SUBTTL	WORKING STORAGE,CONSTANTS

PDL:	BLOCK	PDLEN		;PUSHDOWN LIST
GTBST:	EXP	0		;STARTING ADDRESS FOR GETTAB INFO
MAXGTB:	EXP	0		;NUMBER OF GETTAB TABLES VIA SPY
PDBPTR:	EXP	0		;STARTING ADDRESS OF PDB POINTERS
GTBWRG:	EXP	0		;DEBUG LOCATION - # TIMES WE SUCCEEDED
				;  WHEN WE SHOULD HAVE FAILED A GETTAB
TERMCH:	EXP	0		;CHARACTER WHICH TERMINATED LAST SIXBIT
				;  COMMAND STRING
PERHOR:	EXP	1		;HOURS OF SLEEPING TIME
PERMIN:	EXP	0		;MINUTES OF SLEEPING TIME
PERSEC:	EXP	0		;SECONDS OF SLEEPING TIME
TODHOR:	BLOCK	1		;HOUR OF NEXT EXPECTED WAKE
TODMIN:	BLOCK	1		;MINUTE OF NEXT EXPECTED WAKE
DAECLK:	EXP	.CLOCK		;CLOCK REQUEST OF DAEMON
SLPTIM:	EXP	^D3600		;DEFAULT TIME IS 1 HOUR SLEEP
UDBST:	BLOCK	1		;START OF UDB ADDRESS TABLE
TICDAY:	BLOCK	1		;COMPUTED # OF TICKS/DAY
FILOPN:	XWD	DS1,2		;CREATE ONLY ON PUTPUT CHANNEL
	EXP	.IOIMG		;IN IMAGE MODE
	SIXBIT	.DSK.		;ON DISK
	XWD	DKOB,DKIB	;BUFFER RING ADDRESSES
	XWD	4,4		;# OF BUFFERS TO SET UP
	EXP	ENTBLK		;ADDRESS OF ENTER BLOCK
DSKOPN:	EXP	.IOIMG		;OPEN DISK IN IMAGE MODE
	SIXBIT	.DSK.		;ON DISK
	XWD	DKOB,DKIB	;BUFFER RING ADDRESSES
LOKBLK:	EXP	.RBTIM
	EXP	0
	SIXBIT	.WTCHER.	;FILNAME
	SIXBIT	.STS.		;EXTENTION
	BLOCK	.RBTIM-<.-LOKBLK>+1
ENTBLK:	SIXBIT	.WTCHER.
	SIXBIT	.STS.
	EXP	0
	EXP	0
MAXDEV:	XWD	5
MAXDAT:	XWD	5
MAXTOT:	XWD	5
DKIBS:	BLOCK	1
DKOBS:	BLOCK	1
TYIB:	BLOCK	3		;TTY INPUT BUFFER RING POINTER
TYOB:	BLOCK	3		;TTY OUPUT BUFFER RING POINTER
DKIB:	BLOCK	3		;DSK INPUT BUFFER RING POINTER
DKOB:	BLOCK	3		;DSK OUTPUT BUFFER RING POINTER
	SUBTTL	MESSAGE TEXTS

EXTTXT:	ASCIZ	\
THE EXIT COMMAND WILL MERELY CAUSE THE PROGRAM TO TELL DAEMON TO RESET
THE CLOCK REQUEST FOR THIS JOB AND THEN EXIT. THE INFORMATION ON DISK IS
NOT UPDATED TO CURRENT INFORMATION, THE LAST PERIODS INFORMATION IS THE
MOST CURRENT TO BE SAVED.

\
HLPTXT:	ASCIZ	\
THE HELP COMMAND ENABLES YOU TO UNDERSTAND HOW TO USE THIS PROGRAM
FOR THE VARIOUS DISK DEVICES ON THE SYSTEM BEING ACCEPTED.  TYPE 
'HELP' WITH NO ARGUMENTS FOR MORE INFORMATION.
\
RSTTXT:	ASCIZ	\
THE RESET COMMAND ALLOWS YOU, THE OPERATOR, TO CONTROL WHICH DRIVES ARE
TO BE RESET AT ANY GIVEN TIME.
THIS COMMAND TAKES THE ARGUMENTS: ALL, OR ANY NUMBER OF PHYSICAL DEVICE
NAMES SEPARATED BY A COMMA.
A RESET OF ANY OF THE DISK DEVICES WILL ZERO ALL INFORMATION ABOUT THAT
DEVICE( BLOCKS READ, BLOCKS WRITTEN, HARD DEVICE AND DATA ERRORS).
NOTE THAT THE RESET COMMAND WILL NOT ACCEPT CONTROLLER IDENTIFIERS ONLY,
ALL DRIVES MUST BE SPECIFIED INDIVIDUALLY.
THISCOMMAND SHOULD ONLY BE USED TO RESTART AN ACCEPTANCE OF A DRIVE
AFTER A MAJOR FAILURE.
\
SLPTXT:	ASCIZ	\
THE SLEEP COMMAND TAKES TWO (2) FORMS - 
SLEEP WITH NO ARGUMENTS WILL GIVE THE CURRENT SLEEP PERIOD AS HH:MM:SS
AND THE NEXT SCHEDULED WAKE TIME.
SLEEP HH:MM:SS CAUSES THE NEW SLEEP PERIOD TO BE TAKEN AND THE PERIOD TO
BE RESTARTED FROM THAT POINT. NOTE THAT THIS WILL OVERRIDE THE PRESENT
SLEEP REQUEST SO IF THE SCHEDULE CALLED FOR WAKE-UP IN 5 MINUTES AND
YOU REQUESTED A NEW SLEEP TIME OF 2 HOURS THE PROGRAM WILL NOT
WAKE FOR 2 HOURS.
\
WHTTXT:	ASCIZ	\
THE WHAT COMMAND ASKS FOR A WATCHDOG STATUS REPORT AT THAT MOMENT.
THE DISK FILE IS NOT UPDATED, THIS IS ONLY FOR GENERAL INFORMATION.
THE REPORT IS CURRENT AND EXACTLY LIKE THE NORMAL PERIOD STATUS REPORT.
\
ERRTXT:	ASCIZ	\
THE ERRMAX COMMAND TAKES TWO (2) FORMS -
1) ERRMAX WITH NO ARGUMENTS WILL GIVE THE WARNING LIMITS FOR EACH DEVICE
2) ERRMAX DEV,DAT,TOT CAUSES THE NEW VALUES SPECIFIED BY DEV, DAT, AND
TOT TO BE STORED AS NEW WARNING LIMITS.
	A NULL OR ZERO FIELD WILL LEAVE THE PRESENT VALUE UNTOUCHED.
	ALL THREE ARGUMENTS MUST BE SPECIFIED OR THERE WILL BE NO VALUES
	STORED.  THE ARGUMENTS ARE:
	DEV - MAXIMUM NUMBER OF HARD DEVICE ERRORS
	DAT - MAXIMUM NUMBER OF HARD DATA ERRORS
	TOT - MAXIMUM NUMBER OF TOTAL HARD ERRORS (DEVICE+DATA)
		NOTE THAT THIS NUMBER NEED NOT BE RELATED TO DAT AND DEV
\
NOHELP:	ASCIZ	\
THERE IS NO HELP AVAILABLE FOR THIS COMMAND AT THIS TIME.
SCREAM TO S. MEIDELL MR1-2/S43 EXT. 6492
\
	SUBTTL	LITERALS AND END

	LIT
	END	WTCHER