Google
 

Trailing-Edge - PDP-10 Archives - cuspmar86binsrc_2of2_bb-fp63a-sb - 10,7/galaxy/operat/cnforn.mac
There are 3 other files named cnforn.mac in the archive. Click here to see a list.
	TITLE	CNFORN - CONFIG module for ORION
	SUBTTL	Nick Tamburri		10-OCT-85

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


	SALL
	SEARCH	GLXMAC
	SEARCH	ORNMAC
	PROLOG(CNFORN)

	.TEXT	"/LOCALS"

	EXTERN	WTORTN

	CNFEDT==17			;EDIT LEVEL

	.DIRECTIVE FLBLST
SUBTTL	Table of Contents
SUBTTL	Revision History

COMMENT	\
1	Create this module.
	9-Sep-84 GCO 10094/NT
2	Don't type "Structures must be removed" if adding a controller.
	28-Nov-84 GCO 10125/NT
3	Add ADD/REMOVE commands for CI and NI.
	29-Jan-85 GCO 10141/JAD
4	Add KLINIK line routines.
	6-Feb-85 GCO 10146/DPM/TL
5	Rework most of CONFIG to provide ACKing and clean it up.
	12-Mar-85 GCO 10163 /JAD
6	Make add/remove CPU and remove NI work.  Make SYSPHY errors report
	device name in sixbit, not octal.  Include new error codes in RECON
	UUO error reporting.
	29-Mar-85  GCO 10182  /DPM
7	New DIAG. functions to add/remove CI/NI.
	22-Apr-85  GCO 10194  /JAD
10	Add SET [NO] MICROCODE (loading) and LOAD (microcode) commands.
	Remove SET [NO] DX20 command.
	26-Apr-85  GCO 10199  /DPM
11	Expand list of DIAG. UUO error codes.
12	Fix loop in LSTDEV routine.  Fix bad CPU argument to GETTAB UUO
	when removing a CPU.  Fix undeserved error messages when adding
	or removing ALL-CI or ALL-NI ports on non-existant or down CPUs.
	20-May-85  GCO 10210  /DPM
13	Add SET DUMP/RELOAD commands to diddle bits in DEBUGF.  Add SHOW
	STOPCODE-FLAGS command.
	30-Jul-85  GCO 10264  /JAD
14	Do copyright statements. 12-SEP-85 /LEO
15	Don't process SUSPEND command if operator does not specify a
	reason text.
	18-Sep-85 /NT
16	Add/remove CPU loops if complex disk configuration. 
	21-Oct-85 GCO 10306 /JMF
17	Fix numerous errors when using a DSKCHR block that's too short
	28-Jan-86  GCO 10371  /DPM
\
	SUBTTL	Macros and other stuff

	F==.A13			;Dedicated flag AC

	FL.ADD==1B0		;Various bit flags
	FL.CHK==1B1
	FL.ALT==1B2
	FL.DMN==1B3
	FL.HEA==1B4
	FL.NCD==1B5
	FL.WAC==1B6
	FL.UN1==1B7
	FL.NO==1B8

;CPU STATUS FLAGS

	CS.DWN==1B0		;DOWN
	CS.NEX==1B1		;NON-EXISTANT
	CS.DET==1B2		;DETACHED
	CS.NOK==1B3		;OK WORD NOT COUNTING UP
	CS.BOT==1B4		;THIS IS THE BOOT CPU

	DEFINE	GTTAB(AC,ENTRY,DEFAULT),<
		MOVE	AC,[ENTRY]
		XLIST
		GETTAB	AC,
		  IFB  <DEFAULT>,<HALT .>
		  IFNB <DEFAULT>,<MOVE AC,[DEFAULT]>
		LIST
		SALL
	>

	DEFINE	MSYM(NAME,VALUE),<NAME==VALUE>
;STORAGE

;*** KEEP THE NEXT TWO SYMBOLS CONTIGUOUS
RCNARG:	BLOCK	1		;RECON. .RCBTX FUNCTION WORD COUNT
RSNTXT:	BLOCK	<<.TXTSZ==16>/5>+1 ;BUFFER FOR SNAPSHOT/SHUTDOWN REASON
RSNEND==.-1
RSNADR:	BLOCK	1		;Address of reason text
CTYBLK:	BLOCK	3		;Arg block for CTY typeout TRMOP.
DCHARG:	BLOCK	.DCMAX		;DSKCHR UUO BLOCK
INIDON:	BLOCK	1		;Initialization done flag
ULDTXT:	BLOCK	10		;DEVICE STORAGE FOR MICROCODE ACKS AND ERRORS
PHYNAM:	BLOCK	1		;SIXBIT UNIT NAME (USED BY NXTKON)
PHYUNI:	BLOCK	1		;SIXBIT UNIT NAME (USED BY NXTUNI)
SYSSIZ:	BLOCK	1		;SIZE OF THE MONITOR
NWCORE:	BLOCK	1		;NUMBER OF WORDS OF MEMORY ON THE SYSTEM
MONVER:	BLOCK	1		;MONITOR VERSION (%CNVER)
CPUN:	BLOCK	1		;NUMBER OF RUNNING CPU'S IN SYSTEM
CPUOK:	BLOCK	1		;NUMBER OF CPUS WITH OK WORDS RUNNING
CPURUN:	BLOCK	1		;MASK WHICH ARE RUNNING 
CPUSTS:	BLOCK	6		;ONE PER CPU (EVEN IF NOT THERE)
				;LH = CPU STATUS FLAGS (CS.XXX)
				;RH = CDB ADDRESS
CHRCNT:	BLOCK	1		;COUNT OF CHARACTERS IN ACK MESSAGE
ADDREM:	BLOCK	1		;ADDRESS OF "ADD" OR "REMOVE" TEXT
TXTPTR:	BLOCK	1		;BYTE POINTER TO DEPOSIT MESSAGE CHARACTERS

;GET-DATA-FROM-MONITOR STUFF
SAVEP1:	BLOCK	2
SAVEP3:	BLOCK	2
INST:	0
DATA:	0
CNPNTR:	0,,DATA


; SET KLINIK
Z.KLIB:!				;Start of data to zero
KLICPU:	BLOCK	1			;CPU number or 7 for ALL
KLIDTD:	BLOCK	<26+3>/4		;Data for DTE. UUO
Z.KLIE:!				;End of data to zero
	SUBTTL	Dispatch Table -- Main commands

CNFDSP:	$STAB
	.CFADD##,,C$ADD			;Add command
	.CFAUT##,,C$AUTO		;Autoconfigure
	.CFREM##,,C$REMV		;Remove
	.CFLOD##,,C$LOAD		;Load microcode
	.CFSET##,,C$SET			;Set
	.CFSHO##,,C$SHOW		;Show
	.CFSHT##,,C$SHUT		;Shutdown
	.CFSNP##,,C$SNAP		;Snapshot
	.CFSUS##,,C$SUSP		;Suspend
	$ETAB

	SUBTTL	Dispatch Tables -- ADD/REMOVE commands

ADDDSP:	$STAB
	.ARMEM##,,ADDMEM		;Memory
	$ETAB

ADDCPX:	$STAB
	.ARCPU##,,ADDCPU		;CPU
	.ARCI##,,ADDCI			;CI
	.ARNI##,,ADDNI			;NI
	$ETAB

	SUBTTL	Dispatch Tables -- SET commands

SETDSP:	$STAB
	.STBOT##,,SETBOT		;Boot text
	.STULD##,,SETULD		;Set [no] microcode loading
	.STNOT##,,SETNOT		;Negator
	.STAUT##,,SETAUT		;Auto-reload
	.STKLI##,,KLINIK		;Set KLINIK
	.STDMP##,,SETDMP		;Set DUMP (on)
	.STRLD##,,SETRLD		;Set RELOAD (on)
	$ETAB

	SUBTTL	Dispatch Tables -- SET NO commands

STNDSP:	$STAB
	.STBOT##,,SETBOT		;Boot text
	.STULD##,,SETULD		;Set [no] microcode loading
	.STAUT##,,SETAUT		;Auto-reload
	.STDMP##,,SETDMP		;Set DUMP (on)
	.STRLD##,,SETRLD		;Set RELOAD (on)
	$ETAB

SHODSP:	$STAB
	.SHKLI##,,KLISHW		;SHOW KLINIK
	.SHSTP##,,SHWSTP		;SHOW STOPCODE-FLAGS
	$ETAB

	SUBTTL	CPUNAM - SIXBIT CPU names

	DEFINE	CPUNMS(NUMBER)<IRP <NUMBER>,<SIXBIT |CPU'NUMBER|>>

CPUNAM::CPUNMS<0,1,2,3,4,5>
	SUBTTL	CNFORN - Main dispatch routine.

;	Here from ORION's application dispatch, to dispatch to the
; various CONFIG command routines.

;	INTERN	CNFORN			;MAKE AVAILABLE TO ORION

CNFORN::SKIPE	INIDON			;Have we initialized ourselves
	  JRST	CNF.1			;Yes, don't do it again
	GTTAB	S1,%CNNWC		;Get the number of words of memory
	MOVEM	S1,NWCORE		;Save it
	GTTAB	S1,%CNSIZ		;Get maximum core size
	MOVEM	S1,SYSSIZ		;Store it
	GTTAB	S1,%CNVER		;Get the monitor version
	MOVEM	S1,MONVER		;Save it for later
	SETOM	INIDON			;Remember we've come through here

CNF.1:	MOVE	S2,COM.PB(MI)		;Was parser block filled in
	ADDI	S2,(MI)			;POINT PB AT THE BLOCK
	MOVE	S1,S2			;GET THE BLOCK POINTER
	$CALL	P$SETU##		;SETUP THE POINTER
	$CALL	P$KEYW##		;GET THE FIRST KEYWORD
	 $RETIF				;ERROR
	MOVEI	S2,CNFDSP		;Get the address of the table
	$CALL	TABSRC##		;Search the command table for dispatch
	 $RETIF				;Illegal command?
	$CALL	.SAVET			;Give workers room
	SETZB	F,TXTPTR		;Clear all flags, and message address
	PJRST	(S2)			;Go process the command
	SUBTTL	Command processors -- ADD/REMOVE commands

C$REMV:	TLZA	F,(FL.ADD)		;Clear the adding flag
C$ADD:	TLO	F,(FL.ADD)		;Set flag to add
	MOVEI	S1,[ASCIZ |ADD|]	;Assume ADD command
	TLNN	F,(FL.ADD)		;Good guess?
	MOVEI	S1,[ASCIZ |REMOVE|]	;No
	MOVEM	S1,ADDREM		;Save for $IACK
	$CALL	P$KEYW##		;Get the object of the verb
	 $RETIF
	HRLZ	S2,S1			;Copy keyword index
	MOVEM	S2,DCHARG+.DCNAM	;Store in DSKCHR argument block
	MOVE	T1,[.DCMAX,,DCHARG]	;Point at argument block
	DSKCHR	T1,			;Is it a DSK controller?
	  CAIA				;No
	PJRST	ADDKON			;Yes, go do that
	DEVNAM	S2,			;Perhaps a device?
	  SKIPA	S2,[ADDDSP]		;Point to the dispatch table
	PJRST	RADMTK			;Go add/remove a kontroller
	$CALL	TABSRC##		;Search the table
	JUMPT	(S2)			;Dispatch if found a match
	MOVEI	S2,ADDCPX		;Point to per-CPU table
	PUSHJ	P,CPUSRC		;Search the table
	JUMPT	(S2)			;Dispatch if found a match
	$RETF				;Else error
	SUBTTL	ADD/REMOVE MEMORY

ADDMEM:	$IACK	(^T/@ADDREM/ MEMORY)
	$CALL	GETADR			;Get the beginning address
	  $RETIF
	MOVE	T2,S1			;Save it
	$CALL	GETADR			;Get the end address
	  $RETIF
	MOVE	T3,S1			;Save it
	MOVEI	T1,3			;Get the lenght of the arg block
	MOVE	S1,[XWD .RCMON,T1]	;Assume adding
	TLNN	F,(FL.ADD)		;Are we adding?
	 MOVE	S1,[XWD .RCMOF,T1]	; Not, so we're removing
	RECON.	S1,			;Tell the monitor what we want
	 JRST	RCNERR			;Go type the code and reason
	MOVEI	S1,[ASCIZ |online|]	;Assume he removed memory
	TLNN	F,(FL.ADD)		;Did he really add
	 MOVEI	S1,[ASCIZ |offline|]	;Yes, get real message
	LSH	T2,-1			;Convert to kilos
	LSH	T3,-1			;Both addresses
	$TEXT	(WTORTN,<Memory from address ^D/T2/K to ^D/T3/K is now ^T/(S1)/>)
	LSH	T2,^D10			;Convert to words now
	LSH	T3,^D10			; .  .  .
	$TEXT	(WTORTN,<(Words from ^O/T2/ to ^O/T3/)>)
	$RETT				;Return true
	SUBTTL	ADD/REMOVE KONTROLLER

ADDKON:	$IACK	(^T/@ADDREM/ CONTROLLER)
	$SAVE	<P1,P2,P3>		;Make room
	HRLZS	S1			;Put kontroller name in LH
	PUSHJ	P,FNDKON		;Get the next disk kontroller
	  $RETIF			;Message already given
	DMOVE	P1,S1			;Save controller and unit
	PUSHJ	P,SETCPU		;SET UP NEEDED CPU DATA BASE
	MOVEM	P1,DCHARG+.DCNAM	;For DSKCHR
	MOVE	T1,[.DCMAX,,DCHARG]	;Point at DSKCHR argument list
	DSKCHR	T1,			;Get info
	  JRST	FNDK.E			;But we already found it?
	LOAD	S1,DCHARG+.DCXCH,DC.XCA	;Get CPU mask
	TDNE	S1,CPURUN		;Any of the CPUs up?
	JRST	CONT.3			;Yes, remove kontroller and return
	$TEXT	(WTORTN,<CPU owning controller is down>)
	$RETF				;END MESSAGE AND RETURN
CONT.3:	MOVE	P3,S1			;Save bit mask
	MOVE	P2,P1			;Shuffle first unit on the controller
	MOVEI	P1,2			;And set up lenght of RECON. arg block
	JRST	DKONCM			;Go remove it
	SUBTTL	ADD/REMOVE CPU

ADDCPU:	SUBI	S1,.ARCPU##		;Translate to CPU number
	CAIL	S1,0			;Range check
	CAILE	S1,5			; (ALL is illegal)
	$RETF				;Give up if not valid
	$SAVE	<P1>			;Make room for the CPU number
	MOVE	P1,S1			;Save it
	PUSHJ	P,SETCPU		;Set up the CPU database
	$IACK	(^T/@ADDREM/ CPU)
	MOVSI	S1,(CS.NEX)		;NON-EXISTANT BIT
	CAIGE	P1,6			;RANGE CHECK CPU NUMBER
	 TDNE	S1,CPUSTS(P1)		;IN RANGE, IS IT REAL
	  TRNA				;Error
	   JRST	ADDCP1			;Yep try to do it
	$TEXT	(WTORTN,<Illegal CPU specified - CPU^O/P1/ does not exist>)
	$RETF
ADDCP1:	TLNE	F,(FL.ADD)		;Adding?
	 JRST	R%CPUA			;Go to that routine

;HERE TO REMOVE A CPU

	SKIPGE	CPUSTS(P1)		;CPU ALREADY DOWN
	$RETT				;YES, JUST RETURN NOW
	MOVE	T3,CPUN			;GET NUMBER OF RUNNING CPUS
	CAIE	T3,1			;TRYING TO REMOVE THE LAST REMAINING CPU
	 JRST	ADDCP2			;NO, ONWARD
	$TEXT	(WTORTN,<Use SHUTDOWN to remove last CPU>)
	$RETF				;END OUTPUT AND RETURN
ADDCP2:	MOVE	T3,CPUOK		;NUMBER OF ACTUALLY RUNNING CPUS
	CAIE	T3,1			;ONLY ONE OF THOSE LEFT
	 JRST	CPU.1			;NO
	MOVSI	T3,(CS.NOK)		;YES, CHECK IF CPU NOT RUNNING ANYWAY
	TDNE	T3,CPUSTS(P1)	 	;WELL?
	 JRST	CPU.1			;CPU IS DEAD, OK TO REMOVE IT
	$TEXT	(WTORTN,<No running CPUs will be left>)
	$RETF				;IF OPERATOR REALLY WANTS THIS, USE "SHUT"
CPU.1:	$CALL	P$SWITCH##		;See if he typed the force switch
	JUMPF	CPU.10			;No, check before doing
	CAIN	S1,.ARFRC##		;Force switch?
	 JRST	CPU.2			;Yes, so bypass
CPU.10:	TLO	F,(FL.WAC!FL.CHK) 	;SET "WORRY ABOUT CPU",ONLY CHECKING
	MOVE	S1,P1			;Get the CPU number
	PUSHJ	P,RADKON		;CHECK ALL DISK KONTROLLERS
	TLNE	F,(FL.NCD)		;DID SOME CHECK FAIL
	$RETF				;YES, CANNOT REMOVE THE CPU
	MOVE	S1,P1			;Get the CPU number
	PUSHJ	P,LSTDEV		;LOOK FOR LOST DEVICES, GIVE WARNING
	TLZ	F,(FL.CHK)		;NOT CHECKING ANY MORE
	MOVE	S1,P1			;Get the CPU we're removing
	PUSHJ	P,DETJBS		;DETACH JOBS AS APPROPRIATE
	TRNA				;WE HAVE DONE CHECKS
CPU.2:	$TEXT	(WTORTN,<%Bypassing lots of checking>)
	MOVSI	S1,(CS.DWN)		;GET CPU IS DOWN BIT
	IORB	S1,CPUSTS(P1)		;LIGHT IN STATUS BLOCK
	SOS	CPUN			;ONE LESS CPU IN SYSTEM
	TLNN	S1,(CS.NOK)		;WAS CPU'S OK WORD COUNTING BEFORE
	SOS	CPUOK			;YES, BUT IT WILL STOP SOON
	MOVSI	S1,(CS.NOK)		;IN CASE IT WASN'T
	IORM	S1,CPUSTS(P1)		;LIGHT THE BIT NOW
	MOVEI	S1,1			;GET BIT FOR CPU0
	LSH	S1,(P1)			;POSITION FOR CORRECT CPU
	ANDCAB	S1,CPURUN		;CLEAR/GET NEW RUNNING CPU MASK
	HRLI	S1,.STCRN		;SET RUN CPUN
	SETUUO	S1,			;SET NEW SPECIFICATION
	 $TEXT	(WTORTN,<SETUUO to set CPU^D/S1/ runnability failed>)
	MOVEI	S1,(P1)			;GET CPU NUMBER
	LSH	S1,1			;*2 FOR SUBTABLE GETTABS
	ADD	S1,[%CCOKP]		;GET THE OK WORD FOR CPUN
	GETTAB	S1,			;GET IT
	 $TEXT	(WTORTN,<%Unable to determine status of CPU^D/P1/ - continuing>)
	JUMPG	S1,CPU.5		;AVOID LOOP, SHUT IT DOWN IF ALREADY DEAD
CPU.3:	MOVEI	S1,(P1)			;GET CPU NUMBER
	LSH	S1,1			;*2 FOR SUBTABLE GETTABS
	ADD	S1,[%CVJOB]		;JOB CURRENTLY RUNNING ON CPU
	GETTAB	S1,			;GET IT
	 $TEXT	(WTORTN,<%Unable to determine job running on CPU^D/P1/ - continuing>)
	JUMPN	S1,CPU.3		;WAIT FOR CPU TO ONLY RUN NULL JOB
CPU.4:	TLZ	F,(FL.HEA)		;MAKE SURE HEADER GETS PRINTED
	MOVE	S1,P1			;GET THE CPU NUMBER
	TLNN	F,(FL.DMN)		;DONT DETACH IF FORCED REMOVAL
	PUSHJ	P,RADKON		;GO AND DETACH ALL THE UNITS NOW
CPU.5:	MOVEI	S1,ST.URE(P1)		;GET CPU NUMBER, FLAG AS REMOVE
	HRLI	S1,.STCDN		;SET "DOWN" CPUN
	SETUUO	S1,			;SHUT IT DOWN
	  $TEXT	(WTORTN,<%Can't shut down CPU^D/P1/>)
CPU.6:	MOVEI	S1,(P1)			;GET CPU NUMBER
	LSH	S1,1			;*2 FOR SUBTABLE GETTABS
	ADD	S1,[%CCOKP]		;GET THE OK WORD FOR CPUN
	GETTAB	S1,			;GET IT
	  SKIPA				;ASSUME DOWN
	JUMPLE	S1,CPU.6		;WAIT FOR IT TO STICK ITS HEAD IN THE SAND
	MOVE	S1,CPUN			;HOW MANY CPU'S ARE LEFT
	CAIE	S1,1			;ONLY 1 REMAINING
	JRST	CPU.7			;NO, JUST MAKE THE CPU GO AWAY
	MOVSI	S1,.STCSB		;OK TO CACHE MONITOR DATA BASE NOW
	HRRI	S1,1B35			;LIGHT BIT TO TURN ON CACHE
	SETUUO	S1,			;SINCE ONLY 1 PROCESSOR LEFT
	  JFCL				;OK, MUST BE A KI
CPU.7:	MOVSI	S1,(CS.DET)		;"CPU DETACHED" BIT
	TDNE	S1,CPUSTS(P1)		;IS THE CPU ALREADY DETACHED
	$RETT				;YES, RETURN NOW
	IORM	S1,CPUSTS(P1)		;SAY DETACHED NOW
	MOVE	S1,[XWD .RCDET,T1]	;GET THE DETACH CPU FUNCTION
	MOVEI	T1,2			;Get the lenght of the arge block
	MOVE	T2,CPUNAM(P1)		;And get the SIXBIT CPU name
	RECON.	S1,			;Do the request
	 JRST	RCNERR
	$RETT
;HERE TO ADD A CPU

R%CPUA:	SKIPL	CPUSTS(P1)		;IS IT ALREADY UP
	JRST	CPUA.2			;YES, GO LET IT IN (UNDO OPSER'S ":SET RUN")
	MOVSI	S1,(CS.DWN!CS.NOK)	;CPU IS DOWN BIT
	ANDCAM	S1,CPUSTS(P1)		;NOT ANY MORE
	AOS	CPUN			;ONE MORE CPU RUNNING
	AOS	CPUOK			;ONE MORE COUNTING
	MOVSI	S1,.STCSB		;MUST UNCACHE MONITOR DATA BASE
	SETUUO	S1,			;DO IT (1B35 = 0)
	  JFCL				;OK, MUST BE A KI
	MOVSI	S1,(CS.DET)		;CPU DETACHED BIT
	TDNN	S1,CPUSTS(P1)		;IS IT
	JRST	CPUA.1			;NO, LET IT IN
	ANDCAM	S1,CPUSTS(P1)		;CLEAR DETACHED CPU BIT
	MOVEI	S1,2			;TWO WORD ARGUMENT
	MOVE	S2,CPUNAM(P1)		;GET CPU NAME
	DMOVEM	S1,RCNARG		;SAVE
	MOVE	S1,[.RCATT,,RCNARG]	;SET UP UUO AC
	RECON.	S1,			;Go it
	 JRST	RCNERR
	TLNE	F,(FL.NCD)		;DID IT WORK
	$RETT				;NO, RETURN NOW
CPUA.1:	MOVE	S1,P1			;GET CPU NUMBER (ST.URE OFF = ADD THIS ONE)
	HRLI	S1,.STCDN		;SET CPU UP ( OR ALLOWED TO BE UP )
	SETUUO	S1,			;i.e. LET THIS CPU IN
	  $TEXT	(WTORTN,<Can't set CPU^D/T2/ to up status>)
CPUA.2:	MOVEI	S1,1B35			;GET A BIT FOR CPU0
	LSH	S1,(P1)			;POSITION FOR CPUN
	IORB	S1,CPURUN		;ADD/GET NEW RUNNING CPU MASK
	HRLI	S1,.STCRN		;NOW ALLOW IT TO RUN JOBS
	SETUUO	S1,			;OTHERWISE WHY BOTHER ADDING IT
	  $TEXT	(WTORTN,<Can't set CPU^D/P1/ to run jobs>)
	$RETT				;ADDING IS A LOT EASIER THAN REMOVING
	SUBTTL	ENABLE/DISABLE CI

ADDCI:	SUBI	S1,.ARCI##		;TRANSLATE TO CI NUMBER
	CAIL	S1,0			;RANGE
	CAILE	S1,6			; CHECK
	$RETF				;GIVE UP IF NOT VALID
	$SAVE	<P1>			;SAVE AN AC
	MOVSI	P1,-6			;ASSUME ALL CPUS
	CAIE	S1,6			;WAS IS?
	HRRO	P1,S1			;NO
	PUSHJ	P,P$CFM##		;NEED A CRLF
	$RETIF				;ERROR
	$IACK	(^T/@ADDREM/ CI)

ADCI.1:	HRLZ	T1,P1			;GET CPU NUMBER
	HRRI	T1,.DIISM		;DIAG. FUNCTION TO SET MAINT MODE
	TLNE	F,(FL.ADD)		;"ADD CI"?
	HRRI	T1,.DIICM		;YES, THAT MEANS CLEAR MAINT MODE
	MOVX	T2,<574B8>		;LOAD DEVICE CODE
	MOVEI	S1,[ASCIZ |dis|]	;ASSUME REMOVING
	TLNE	F,(FL.ADD)		;GOOD GUESS?
	MOVEI	S1,[ASCIZ |en|]		;NOPE
	MOVE	S2,[XWD -2,T1]		;POINT AT THE ARGUMENTS
	DIAG.	S2,			;DO THE UUO
	  JRST	ADCI.2			;ERROR
	$TEXT	(WTORTN,<CI port on CPU^O/T1,LHMASK/ ^T/0(S1)/abled>)
	JRST	ADCI.3			;ONWARD

ADCI.2:	CAIN	S2,DIANR%		;CPU DOWN?
	JRST	ADCI.3			;YES
	CAIL	S2,DIAETL		;KNOWN ERROR CODE?
	MOVEI	S2,DIAETL		;NO, USE CATCH-ALL
	$TEXT	(WTORTN,<DIAG. UUO error attempting to ^T/0(S1)/able CI port on CPU^O/T1,LHMASK/^M^J(Error (^O/S2/) ^T/@DIAETX(S2)/)>)

ADCI.3:	AOBJN	P1,ADCI.1		;LOOP FOR ANOTHER CPU
	$RETT				;RETURN
	SUBTTL	ENABLE/DISABLE NI

	.DIANI==114			;NI MISCELLANEOUS FUNCTIONS
	.DINEN==1			;ENABLE/DISABLE SUB-FUNCTION

ADDNI:	SUBI	S1,.ARNI##		;TRANSLATE TO CI NUMBER
	CAIL	S1,0			;RANGE
	CAILE	S1,6			; CHECK
	$RETF				;GIVE UP IF NOT VALID
	$SAVE	<P1>			;SAVE AN AC
	MOVSI	P1,-6			;ASSUME ALL CPUS
	CAIE	S1,6			;WAS IS?
	HRRO	P1,S1			;NO
	PUSHJ	P,P$CFM##		;NEED A CRLF
	$RETIF				;ERROR
	$IACK	(^T/@ADDREM/ NI)

ADNI.1:	HRLZ	T1,P1			;GET CPU NUMBER
	HRRI	T1,.DIISM		;DIAG. FUNCTION TO SET MAINT MODE
	TLNE	F,(FL.ADD)		;"ADD NI"?
	HRRI	T1,.DIICM		;YES, THAT MEANS CLEAR MAINT MODE
	MOVX	T2,<564B8>		;LOAD DEVICE CODE
	MOVEI	S1,[ASCIZ |dis|]	;ASSUME REMOVING
	TLNE	F,(FL.ADD)		;GOOD GUESS?
	MOVEI	S1,[ASCIZ |en|]		;NOPE
	MOVE	S2,[XWD -2,T1]		;POINT AT THE ARGUMENTS
	DIAG.	S2,			;DO THE UUO
	  JRST	ADNI.2			;ERROR
	$TEXT	(WTORTN,<NI port on CPU^O/T1,LHMASK/ ^T/0(S1)/abled>)
	JRST	ADNI.3			;ONWARD

ADNI.2:	CAIN	S2,DIANR%		;CPU DOWN?
	JRST	ADNI.3			;YES
	CAIL	S2,DIAETL		;KNOWN ERROR CODE?
	MOVEI	S2,DIAETL		;NO, USE CATCH-ALL
	$TEXT	(WTORTN,<DIAG. UUO error attempting to ^T/0(S1)/able NI port on CPU^O/T1,LHMASK/^M^J(Error (^O/S2/) ^T/@DIAETX(S2)/)>)

ADNI.3:	AOBJN	P1,ADNI.1		;LOOP
	$RETT				;RETURN
	SUBTTL	"LOAD microcode"


C$LOAD:	$IACK	(LOAD microcode)
	PUSHJ	P,ULDARG		;GET DIAG ARGUMENTS
	$RETIF				;CHECK FOR ERRORS
	HRRI	T1,.DILOD		;FUNCTION CODE
	MOVE	S1,[-2,,T1]		;SET UP UUO AC
	DIAG.	S1,			;LOAD MICROCODE
	  JRST	LOAD.E			;FAILED
	$TEXT	(WTORTN,<Microcode loaded on ^T/ULDTXT/>)
	$RETT				;RETURN
LOAD.E:	$TEXT	(WTORTN,<Microcode load failed; ^A>)
	PJRST	DIAERR			;REPORT DIAG ERROR AND RETURN
; RETURN DIAG. UUO ARGUMENTS FOR LOAD AND SET [NO] MICROCODE COMMANDS
ULDARG:	SETZ	T1,			;ASSUME CPU0
	PUSHJ	P,P$KEYW##		;GET A KEYWORD
	JUMPF	ULDDEV			;TRY FOR A DEVICE CODE

; CPU NUMBER
ULDCPU:	MOVEI	S2,-.ARCPU##(S1)	;GET POSSIBLE CPU INDEX
	CAIL	S2,0			;RANGE
	CAILE	S2,5			; CHECK
	JRST	ULDKON			;PERHAPS A KONTROLLER
	MOVE	T1,S2			;SAVE

; DEVICE CODE
ULDDEV:	PUSHJ	P,P$NUM##		;GET A DEVICE CODE
	JUMPF	ULDOPE			;OPR CMD ERROR
	CAIL	S1,000			;RANGE
	CAILE	S1,776			; CHECK
	JRST	ULDDCE			;ILLEGAL DEVICE CODE
	TRNE	S1,3			;ONE MORE
	JRST	ULDDCE			;ILLEGAL DEVICE CODE
	HRLZ	T2,S1			;SAVE
	PUSHJ	P,P$NUM##		;ELSE GET A UNIT NUMBER
	JUMPF	ULDOPE			;OPR CMD ERROR
	CAIL	S1,0			;RANGE
	CAILE	S1,7			; CHECK
	JRST	ULDUNE			;ILLEGAL UNIT NUMBER
	LSH	S1,3			;POSITION
	HRR	T2,S1			;SAVE
	JRST	ULDXIT			;DONE
; KONTROLLER NAME
ULDKON:	HRLZ	S2,S1			;COPY KEYWORD INDEX
	MOVEM	S2,DCHARG		;INCASE IT'S A DISK KONT
	MOVE	S2,[.DCMAX,,DCHARG]	;SET UP UUO AC
	DSKCHR	S2,			;A DISK?
	  JRST	ULDKO1			;NO--TRY FOR A NON-DISK KONT
	MOVE	S2,DCHARG+.DCUPN	;GET UNIT NAME
	LOAD	TF,DCHARG+.DCXCH,DC.XCA	;GET CPU MASK
	JRST	ULDKO2			;ONWARD
ULDKO1:	HRLZ	S2,S1			;COPY KEYWORD INDEX
	DEVNAM	S2,			;A NON-DISK KONTROLLER?
	  JRST	ULDCIP			;CHECK CI PORT
	MOVE	TF,[.RCCPU,,S1]		;SET UP UUO AC
	MOVEI	S1,2			;TWO WORD ARG BLOCK
	RECON.	TF,			;GET CPU MASK
	  JRST	ULDNCP			;CAN'T GET CPU NUMBER
ULDKO2:	JFFO	TF,.+1			;FIND FIRST BIT
	MOVEI	T1,43			;OFFSET FROM CPU0
	SUB	T1,S1			;GET CPU NUMBER
	MOVE	T2,[-2,,S1]		;SET UP UUO AC
	MOVEI	S1,.DIAKU		;FUNCTION CODE
	DIAG.	T2,			;TRANSLATE KONT NAME INTO DIAG ARGS
	  JRST	ULDNDC			;CAN'T GET DEVICE CODE
	JRST	ULDXIT			;DONE

; CI20 PORT
ULDCIP:	MOVEI	S2,-.ARCI##(S1)		;GET POSSIBLE CI PORT INDEX
	CAIL	S2,0			;RANGE
	CAILE	S2,5			; CHECK
	JRST	ULDNIP			;CHECK NI PORT
	MOVE	T1,S2			;PUT CPU NUMBER IN LH
	MOVSI	T2,574			;DEVICE CODE
	JRST	ULDXIT			;DONE

; NIA20 PORT
ULDNIP:	MOVEI	S2,-.ARNI##(S1)		;GET POSSIBLE NI PORT INDEX
	CAIL	S2,0			;RANGE
	CAILE	S2,5			; CHECK
	JRST	ULDDCE			;SAY CAN'T DETERMINE DEVICE CODE
	MOVE	T1,S2			;PUT CPU NUMBER IN LH
	MOVSI	T2,564			;DEVICE CODE
;	JRST	ULDXIT			;DONE

; EXIT
ULDXIT:	HLRZ	S1,T2			;GET DEVICE CODE
	LDB	S2,[POINT 3,T2,32]	;GET UNIT NUMBER
	$TEXT	(<-1,,ULDTXT>,<^I/ULDITX/^0>) ;GENERATE ACK TEXT
	HRLZS	T1			;POSITION CPU NUMBER
	MOVE	S1,T2			;COPY DEVICE,,UNIT
	TRZ	S1,7			;CLEAR SLAVE NUMBER
	TRZ	T2,70			;CLEAR UNIT NUMBER
	LSH	S1,3			;POSITION UNIT FIELD
	IOR	T2,S1			;MERGE CORRECT UNIT/SLAVE
	LSH	S1,6			;POSITION DEVICE CODE
	HLL	T2,S1			;REPLACE
	$RETT				;RETURN

ULDITX:	ITEXT	(<CPU^O/T1/, device ^O3/S1/, unit ^O/S2/>)
ULDOPE:	MOVEI	S2,[ASCIZ /Operator command parsing error/]
	JRST	ULDERR
ULDDCE:	MOVEI	S2,[ASCIZ /Illegal device code/]
	JRST	ULDERR
ULDUNE:	MOVEI	S2,[ASCIZ /Illegal unit number/]
	JRST	ULDERR
ULDNDC:	MOVEI	S2,[ASCIZ /Cannot determine device code for controller/]
	JRST	ULDERR
ULDNCP:	MOVEI	S2,[ASCIZ /Cannot determine CPU number for controller/]
;	JRST	ULDERR
ULDERR:	$TEXT	(WTORTN,<^T/(S2)/>)
	$RETF
	SUBTTL	The "SUSPEND" Command

	MBTPGS==10			;NUMBER OF PAGES FOR MONBTS

C$SUSP:	$IACK	(SUSPEND)
	$CALL	P$TEXT			;Get the text string
	SKIPF				;Failed?
	 SKIPN	1(S1)			;String null?
	  JRST	REAS.1			;No reason given is an error
	MOVEM	S1,RSNADR		;Store its address
	MOVE	S1,[.RCROM,,T1]		;SET TO RUN ONLY 1 JOB
	MOVEI	T1,2			;2 WORD ARGUMENT BLOCK
	SETZ	T2,			;JOB NUMBER 0 = ALLOW ALL USERS
	RECON.	S1,			;DO THE UUO
	  JRST	RCNERR			;FAILED, TELL WHY
	MOVEI	S1,[ASCIZ /SEND ALL Expect an interruption of service/]
	PUSHJ	P,SNDALL		;OUTPUT THE MESSAGE
	MOVEI	S1,^D5			;GIVE IT TIME TO TYPE OUT
	SLEEP	S1,			;WAIT
	HRRZ	S1,MONVER		;Get the monitor version
	CAILE	S1,70200		;Pre-7.03?
	JRST	SUSP.5			;No, 7.03 doesn't need this
	MOVE	S1,[XWD .RCMOF,T1]	;Point to the rem mem arg block
	MOVEI	T1,3			;Get the lenght of the argument block
	MOVE	T2,SYSSIZ		;FIRST WORD OUTSIDE THE MONITOR
SUSP.3:	MOVE	T3,T2			;COPY ADDRESS
	ADDI	T3,<MBTPGS*PAGSIZ>-1	;LAST LOCATION NEEDED FOR MONBTS
	CAMLE	T3,NWCORE		;OFF THE TOP OF MEMORY
	JRST	SUSP.6			;No room at all
	RECON.	S1,			;Tell the monitor what we want
	 TRNA				;Failed? Try again
	JRST	SUSP.5			;It worked, continue
	ADDI	T2,PAGSIZ		;TRY A DIFFERENT PLACE
	JRST	SUSP.3			;TRY AGAIN
SUSP.5:	DMOVEM	T2,SAVEP3		;Save the addresses for later
	MOVE	S1,[.RCROM,,T1]		;SET TO RUN ONLY ME NOW
	MOVEI	T1,2			;2 WORD ARGUMENT BLOCK
	MOVE	T2,G$MJOB##		;ONLY ME
	RECON.	S1,			;DO IT
	 JRST	RCNERR
	MOVSI	S1,.RCIOW		;Get wait for I/O to finish function
	RECON.	S1,			;Wait
	 JRST	RCNERR
	PUSHJ	P,SETCPU		;SET UP CPU DATA BASE
	MOVSI	T1,-6			;NUMBER OF CPUS
SUSP.1:	SKIPL	T2,CPUSTS(T1)		;IS THE CPU DOWN
	TLNE	T2,(CS.BOT)		;OR THE BOOT CPU
	JRST	SUSP.2			;IGNORE THIS ONE
	MOVEI	T2,ST.USU(T1)		;GET CPU NUMBER AND FLAG = SUSPEND THYSELF
	HRLI	T2,.STCDN		;SET "DOWN" CPU FUNCTION
	SETUUO	T2,			;MAKE IT GO AWAY
	 $TEXT	(WTORTN,<Can't set CPU^D/(T1),RHMASK/ offline>)
SUSP.2:	AOBJN	T1,SUSP.1		;DO ALL CPUS THAT WILL REMAIN AFTER SUSPEND
	MOVSI	S1,.RCIOW		;Get wait for I/O to finish function
	RECON.	S1,			;Wait
	 JRST	RCNERR
	MOVE	S1,SAVEP3		;Get the address of MONBTS
	ADR2PG	S1			;Make it into a page number
	HRLI	S1,.RCSPN		;FUNCTION SUSPEND
	MOVE	0,RSNADR		;Get the address of the reason
	ADDI	0,1			; so it can be found in the dump
	RECON.	S1,			;Do the suspend
	 TRNA				;Failed? Get everything back
	JRST	SUSP.4			;Monitor already welcomed users
	MOVEI	S1,[ASCIZ /SEND ALL System resumed/]
	PUSHJ	P,SNDALL		;TELL WORLD THE SYSTEM IS BACK
SUSP.4:	MOVE	S1,[.RCROM,,T1]		;SET TO RUN ONLY 1 JOB
	MOVEI	T1,2			;2 WORD ARGUMENT BLOCK
	SETZ	T2,			;JOB NUMBER 0 = ALLOW ALL USERS
	RECON.	S1,			;DO THE UUO
	  JRST	AUTO.E			;Something really wrong here
	HRRZ	S1,MONVER		;Get the monitor version
	CAILE	S1,70200		;Pre-7.03?
	$RETT				;No, 7.03 doesn't need this
	MOVE	S1,[XWD .RCMON,T1]	;Get back the memory
	MOVEI	T2,3			; MONBTS used
	DMOVE	T3,SAVEP3		;Get the addresses
	RECON.	S1,			;Tell the monitor what we want
	 JFCL				;Failed? Non-fatal for now
	$RETT

SUSP.6:	$TEXT	(WTORTN,<Cannot reorganize memory to make room for MONBTS reload>)
	$RETT
	SUBTTL	The "SNAPSHOT" and "SHUTDOWN" commands


C$SNAP:	$IACK	(SNAPSHOT)
	MOVSI	T1,.RCCI7		;WANT A CI7 CONTINUABLE STOPCD
	JRST	REASON			;ASK FOR REASON, DO COMMAND


C$SHUT:	$IACK	(SHUTDOWN)
	MOVSI	T1,.RCRLD		;WANT TO RELOAD THE MONITOR
	JRST	REASON			;ASK FOR REASON, DO COMMAND


REASON:	$CALL	P$TEXT##		;Get the reason
	 JUMPF	REAS.1			;Need a reason
	MOVEI	0,1(S1)			;POINT TO IT WITH AC 0 FOR THE DUMP
	SKIPN	@0			;Null reason illegal also
	 JRST	REAS.1
	MOVE	S1,T1			;Get function to perform (for RCNERR)
	RECON.	S1,			;DO THE FUNCTION
	 JRST	RCNERR			;GIVE ERROR
	$RETT				;RETURN

REAS.1:	$TEXT	(WTORTN,<A reason must be specified>)
	$RET
	SUBTTL	The "AUTOCONFIGURE" command


C$AUTO:	$SAVE	<P1>			;SAVE P1
	PUSHJ	P,P$KEYW##		;TRY FOR A KEYWORD
	JUMPF	AUTO.A			;NO GOOD
	SUBI	S1,.ARCPU##		;OFFSET
	CAIL	S1,0			;RANGE
	CAILE	S1,6			; CHECK
	$RETF				;BAD CPU NUMBER
	CAIN	S1,6			;ALL CPUS?
AUTO.A:	MOVNI	S1,1			;YES--SET TO -1
	MOVE	P1,S1			;PRESERVE CPU ARGUMENT
	PUSHJ	P,P$CFM##		;TIME FOR A CRLF
	$RETIF				;JUNK INPUT
	$IACK	(AUTOCONFIGURE)
	TLZ	F,(FL.ADD)		;SET TO SEIZE MAGTAPE CONTROLLERS
	PUSHJ	P,RADMTK		;DO IT
	 JUMPF	AUTO.9			;Not supported
	MOVE	S1,[.RCROM,,T1]		;SET TO RUN ONLY ME NOW
	MOVEI	T1,2			;2 WORD ARGUMENT BLOCK
	MOVE	T2,G$MJOB##		;ONLY ME
	RECON.	S1,			;DO IT
	 JRST RCNERR			;PROBABLY NOT PRIVLEGED
	MOVSI	S1,.RCIOW		;Get wait for I/O to finish function
	RECON.	S1,			;Wait
	 JRST	RCNERR
	MOVE	S1,[.RCRAC,,T1]		;AUTOCONFIGURE
	MOVEI	T1,2			;ARGUMENT LIST IS 2 WORDS LONG
	MOVE	T2,P1			;GET CPU ARGUMENT
	RECON.	S1,			;DO IT
	 TRNA
	JRST	AUTO.0			;Done, continue onward
	PUSHJ	P,AUTO.9		;Type this is not supported
	MOVE	S1,[.RCROM,,T1]		;SET TO TURN TIMESHARING BACK ON
	MOVEI	T1,2			;2 WORD ARGUMENT LIST
	SETZ	T2,			;ALLOW USERS AGAIN
	RECON.	S1,			;DO IT
	 JRST	AUTO.E			;System very sick
	TLO	F,(FL.ADD)		;ALSO FREE UP MAGTAPES
	PUSHJ	P,RADMTK		;RELEASE MTA KONTROLLERS
	$RETT				;FINISH THE LINE AND EXIT
AUTO.0:	MOVE	S1,[.RCROM,,T1]		;SET TO RUN ALL JOBS
	MOVEI	T1,2			;2 WORD ARGUMENT BLOCK
	SETZ	T2,			;JOB NUMBER 0 = ALLOW ALL USERS
	RECON.	S1,			;DO THE UUO
	 JRST	AUTO.E			;Nasty trouble
	PUSHJ	P,SETCPU		;SET UP CPU DATA BASE
	TLO	F,(FL.ADD)		;WANT TO ADD CONTROLLERS
	PUSHJ	P,RADMTK		;FREE UP MAGTAPE KONTROLLERS
	MOVSI	T1,-6			;NUMBER OF CPUS
AUTO.1:	SKIPGE	CPUSTS(T1)		;CPU UP?
	JRST	AUTO.2			;NO, DON'T WORRY ABOUT IT
	HRRZ	S1,T1			;CPU TO RADKON
	PUSHJ	P,RADKON		;ADD ALL CHANNELS ON THIS CPU
AUTO.2:	AOBJN	T1,AUTO.1		;DO IT FOR ALL CPUS
	$RETT				;ALL DONE, SO JUST EXIT

AUTO.9:	$TEXT	(WTORTN,<Monitor does not support auto-configuration>)
	$RETF

;Here when we try to set system to run all and fail. The system is
;totally useless, and we might as well just reload.
AUTO.E:	$TEXT	(CTYTYP,<^G^G?Error trying to set all users to run>)
	$TEXT	(CTYTYP,<Error code from RECON. UUO is ^O/S1/>)
	$TEXT	(CTYTYP,<System shutting down with RLD stopcode>)
	MOVEI	0,[ASCIZ |ORION CONFIG error trying to set all users to run|]
	MOVSI	S1,.RCRLD	;Get the reload function
	RECON.	S1,		;Reload the system please
	 TRNA			;Now we really can't do much more
	$RETT			;Just for consistency's sake
	$TEXT	(CTYTYP,<^G^G?Error attempting reload function>)
	$TEXT	(CTYTYP,<Error code from RECON. UUO is ^O/S1/>)
	$TEXT	(CTYTYP,<Please reload system manually - ORION halting>)
	$STOP(ESS,<Error shutting down system>)
;SUBROUTINE TO SEIZE OR RELEASE MAGTAPE CONTROLLERS
; RETURNS TRUE NORMALLY, FALSE IF NOT-IMPLEMENTED OR ALREADY SEIZED

RADMTK:	$SAVE	<P1,P2>			;Get some save acs
	MOVE	S1,[-2,,P1]		;DIAG. ARGUMENT LIST
	MOVEI	P1,.DIARM		;ASSUME RELEASING MAGTAPE KONTROLLERS
	TLNN	F,(FL.ADD)		;ACTUALLY SEIZING KONTROLLERS?
	MOVEI	P1,.DIASM		;YES, SET TO SEIZE KONTROLLER
	MOVEI	P2,0			;ALL KONTROLLERS
	DIAG.	S1,			;DO IT
	  JRST	DIAERR			;REPORT ERROR
	$RETT
	SUBTTL	The "SET" command

C$SET:	$CALL	P$KEYW##		;Get the set keyword
	 $RETIF
	MOVEI	S2,SETDSP		;Get the address of the table
	$CALL	TABSRC##		;FIND ARGUMENT
	 $RETIF
	JRST	(S2)			;DISPATCH TO PROCESS ARGUMENT

;"NO"

SETNOT:	TLO	F,(FL.NO)		;Set no flag
	$CALL	P$KEYW##		;Get the next keyword
	 $RETIF
	MOVEI	S2,STNDSP		;GEt the address of the table to search
	$CALL	TABSRC##		;Fidn it
	 $RETIF
	JRST	(S2)			;Call the routine

;"MICROCODE (loading)"

SETULD:	$IACK	(SET MICROCODE)
	PUSHJ	P,ULDARG		;GET DIAG ARGUMENTS
	$RETIF				;CHECK FOR ERRORS
	MOVEI	S2,[ASCIZ /enabled/]	;ASSUME ENABLE
	TLNE	F,(FL.NO)		;NO?
	MOVEI	S2,[ASCIZ /disabled/]	;DISABLE
	HRRI	T1,.DIELD		;ASSUME ENABLE
	TLNE	F,(FL.NO)		;NO?
	HRRI	T1,.DIDLD		;DISABLE
	MOVE	S1,[-2,,T1]		;SET UP UUO AC
	DIAG.	S1,			;LOAD MICROCODE
	  JRST	ULDX.E			;FAILED
	$TEXT	(WTORTN,<Microcode loading is ^T/(S2)/ on ^T/ULDTXT/>)
	$RETT
ULDX.E:	$TEXT	(WTORTN,<Set microcode loading ^T/(S2)/ failed; ^A>)
	PJRST	DIAERR			;REPORT DIAG ERROR AND RETURN

;"RELOAD"

SETAUT:	$IACK	(SET AUTO-RELOAD)
	MOVE	S1,[.RCNAR,,T1]		;GET FUNCTION CODE,,ADDRESS
	MOVEI	T1,2			;LENGTH OF BLOCK IS 2
	MOVE	T2,F			;GET FLAG WORD
	ANDX	T2,<FL.NO>		;Set no if no bit on
	RECON.	S1,			;DO FUNCTION
	  JRST	RCNERR			;FAILED, TELL WHY
	MOVEI	S1,[ASCIZ |enabled|]	;Assume he's enabling
	TLNE	F,(FL.NO)		;Is he really disabling
	 MOVEI	S1,[ASCIZ |disabled|]	;Yes, get the real message
	$TEXT	(WTORTN,<Automatic system reload is ^T/(S1)/>)
	$RETT
;"BOOTXT"

SETBOT:	$CALL	P$TEXT##		;Get the boot text
	 $RETIF
	DMOVE	T1,S1			;Save the temporary ACs
	$IACK	(SET BOOTXT)
	DMOVE	S1,T1			;Restore the temporaries
	CAIG	S2,.TXTSZ		;Less than eighty characters?
	 JRST	SBOT.1			;Yes, onward
	$TEXT	(WTORTN,<Maximum of ^D/[.TXTSZ]/ characters allowed for boot message>)
	$RETF
SBOT.1:	MOVEI	T3,1(S1)		;Get the address of the text
	HRLI	T3,(POINT 7,)		;Build a byte pointer
	MOVE	T4,[POINT 7,RSNTXT]	;And get the destination pointer
	SETZ	T2,			;Zero character counter
SBOT.2:	ILDB	T1,T3			;Get a character
	JUMPE	T1,SBOT.3		;If the end, go finish things up
	IDPB	T1,T4			;Store into the arg block
	AOJA	T2,SBOT.2		;Count the character and loop
SBOT.3:	SETZ	T1,
	IDPB	T1,T4
	MOVEI	S1,2(T2)		;INCLUDE CR/NULL IN COUNT, MOVE TO P1
	IDIVI	S1,5			;COMPUTE WORD COUNT
	SKIPE	S2			;ANY RESIDUAL BYTES IN NEXT WORD?
	ADDI	S1,1			;YES, ACCOUNT FOR THAT
	ADDI	S1,1			;INCLUDE THE WORD COUNT WORD
	MOVEM	S1,RCNARG		;STORE WORD COUNT
	MOVE	S1,[.RCBTX,,RCNARG]	;POINT TO BLOCK
	RECON.	S1,			;REPLACE THE BOOTXT STRING
	  JRST	RCNERR			;FAILED, TELL WHY
	MOVEI	S1,RSNTXT		;Get address of string
	SKIPN	T2			;Null string?
	 MOVEI	S1,[ASCIZ |[Null]|]	;Otherwise get null indicator
	$TEXT	(WTORTN,<Boot-text setting accepted.  New boot string is:>)
	$TEXT	(WTORTN,<	^T/(S1)/>)
	$RETT
;"DUMP" OR "RELOAD"

SETDMP:	TDZA	S1,S1			;NOTE "DUMP" ENTRY AND SKIP
SETRLD:	MOVEI	S1,1			;NOTE "RELOAD" ENTRY
	$SAVE	<P1,P2>			;SAVE AN AC OR TWO
	MOVE	P1,S1			;SAVE ENTRY FLAG IN P1
	SETZ	P2,			;START WITH NOTHING
SDMP.1:	$CALL	P$KEYW##		;GET NEXT KEYWORD
	 $RETIF
	MOVEI	S2,DMPTAB		;ASSUME DUMP
	SKIPE	P1			;GOOD GUESS?
	MOVEI	S2,RLDTAB		;NO
	$CALL	TABSRC##		;TRANSLATE THE KEYWORD
	 $RETIF				;SHOULDN'T HAPPEN
	IOR	P2,(S2)			;ADD IN THE BIT
	$CALL	P$COMMA##		;SEE IF COMMA
	JUMPT	SDMP.1			;IF SO, KEEP LOOKING
	$CALL	P$CFM##			;SEE IF CONFIRM
	 $RETIF

	$IACK	(SET ^T/@DMPRLD(P1)/)
	JUMPN	P1,SRLD.1		;JUMP IF SET [NO] RELOAD
	MOVSI	S1,.RCSDF		;ASSUME SET
	TLNN	F,(FL.NO)		;DID THEY SAY NO?
	MOVSI	S1,.RCCDF		;NO, THAT MEANS CLEAR THE BITS
	JRST	SDMP.2			;JOIN COMMON CODE

SRLD.1:	MOVSI	S1,.RCSDF		;ASSUME SET
	TLNE	F,(FL.NO)		;DID THEY SAY NO?
	MOVSI	S1,.RCCDF		;YES, THAT MEANS CLEAR THE BITS
SDMP.2:	HRRI	S1,T1			;ADDRESS OF ARGUMENT LIST
	MOVEI	T1,2			;NUMBER OF WORDS
	MOVE	T2,P2			;COPY FLAGS HERE
	RECON.	S1,			;DO IT
	  JRST	RCNERR			;ERROR
	PJRST	SHST.1			;FINISH UP VIA SHOW STOPCODE-FLAGS

DMPRLD:	[ASCIZ	/DUMP/]
	[ASCIZ	/RELOAD/]

DMPTAB:	$STAB
	.STCPN##,,[ST%DCP]
	.STDBG##,,[ST%DDC]
	.STJOB##,,[ST%DJE]
	$ETAB

RLDTAB:	$STAB
	.STCPN##,,[ST%CP1]
	.STDBG##,,[ST%RDC]
	.STJOB##,,[ST%RJE]
	$ETAB
	SUBTTL	The "SHOW STOPCODE-FLAGS" command

SHWSTP:	$SAVE	<P1>			;SAVE AN AC
	$IACK	(SHOW STOPCODE-FLAGS)
	MOVX	S1,%CNDBG		;DEBUG FLAGS WORD
	GETTAB	S1,			;ASK THE MONITOR
	  SETZ	S1,			;DUH?
SHST.1:	MOVE	P1,S1			;COPY FLAGS WORD TO A SAFE AC
	$TEXT	(WTORTN,<System will ^A>) ;START TEXT
	TXC	P1,ST%DCP!ST%DDC!ST%DJE	;FLIP THE BITS
	TXNN	P1,ST%DCP!ST%DDC!ST%DJE	;ALL BITS ON? (LEAVE FLIPPED)
	JRST	[$TEXT	(WTORTN,<not do continuable stopcode dumps>)
		 JRST	SHST.R]		;SEE ABOUT RELOADS
	$TEXT	(WTORTN,<do continuable dumps on ^A>) ;MORE NOISE
	MOVEI	S1,DMPBTS		;POINT AT TABLE
	PUSHJ	P,PRTBIT		;PRINT PRETTY BITS
	$TEXT	(WTORTN,< stopcodes>)	;ADD CRLF
SHST.R:	$TEXT	(WTORTN,<System will reload on ^A>) ;START TEXT
	TXO	P1,ST%NAR		;SET THE "STOP" BIT FOR PRTBIT
	MOVEI	S1,RLDBTS		;POINT AT TABLE
	PUSHJ	P,PRTBIT		;PRINT PRETTY BITS
	$TEXT	(WTORTN,< stopcodes>)	;ADD CRLF
	$RETT

DMPBTS:	$STAB
	[ST%DCP],,[ASCIZ /CPU/]
	[ST%DDC],,[ASCIZ /DEBUG/]
	[ST%DJE],,[ASCIZ /JOB/]
	$ETAB

RLDBTS:	$STAB
	[ST%CP1],,[ASCIZ /CPU/]
	[ST%RDC],,[ASCIZ /DEBUG/]
	[ST%RJE],,[ASCIZ /JOB/]
	[ST%NAR],,[ASCIZ /STOP/]	;FAKE TO INCLUDE THIS
	$ETAB
;ROUTINE TO HELP SHOW STOPCODE-FLAGS COMMAND PRINT PRETTY TEXT.
;COULD BE MADE MORE GENERAL IF THE NEED ARISES.  CALL WITH THE
;CONTROL TABLE ADDRESS IN S1, AND THE BITS TO TEST IN P1.  THIS
;ROUTINE WILL ADD COMMAS AND/OR "and" AS APPROPRIATE.

PRTBIT:	$SAVE	<P2,P3>			;SAVE AN AC OR TWO
	MOVE	P2,S1			;COPY TABLE ADDRESS
	HLLZ	S1,(P2)			;GET LENGTH OF TABLE
	MOVNS	S1			;MAKE IT -VE
	HRRI	S1,1(P2)		;POINT AT REAL ENTRIES
	MOVE	P2,S1			;BACK WHERE ITS SAFE

;FIRST COUNT HOW MANY BITS ARE SET

	SETZ	P3,			;INIT COUNT OF BITS TO ZERO
	MOVE	T1,P2			;COPY THE AOBJN POINTER
PBIT.1:	HLRZ	S1,(T1)			;GET A BIT ADDRESS
	TDNE	P1,(S1)			;BIT SET?
	AOS	P3			;YES, COUNT IT
	AOBJN	T1,PBIT.1		;LOOP

;NOW PRINT THE TEXT FOR EACH BIT WITH PROPER PUNCTUATION.

	PUSH	P,[0]			;INIT A FLAG
	CAIL	P3,3			;3 OR MORE ITEMS?
	SETOM	(P)			;YES, REMEMBER THAT
PBIT.2:	HLRZ	S1,(P2)			;GET A BIT ADDRESS
	TDNN	P1,(S1)			;BIT SET?
	JRST	PBIT.4			;NO
	HRRZ	S1,(P2)			;GET TEXT ADDRESS
	$TEXT	(WTORTN,<^T/0(S1)/^A>)	;ADD NAME
	SUBI	P3,1			;ONE LESS ITEM LEFT
	SKIPN	(P)			;NEED ANY COMMAS?
	JRST	PBIT.3			;NO
	SKIPE	P3			;ANY MORE ITEMS?
	$TEXT	(WTORTN,<,^A>)		;YES, PRINT ","
	CAILE	P3,1			;MORE THAN ONE ITEM LEFT?
	$TEXT	(WTORTN,< ^A>)		;YES, PRINT " "
PBIT.3:	CAIN	P3,1			;ONE MORE ITEM LEFT?
	$TEXT	(WTORTN,< and ^A>)	;YES, NEED THE "and" NOW
PBIT.4:	AOBJN	P2,PBIT.2		;DO ALL BITS
	POP	P,(P)			;TOSS JUNK
	$RETT				;RETURN
	SUBTTL	KLINIK routines


	;The SHOW KLINIK command

	BYTMSK==377

KLISHW:	$SAVE	<P1,P2>			;Preserve AC
	MOVE	S1,[Z.KLIB,,Z.KLIB+1]	;Set up BLT
	SETZM	Z.KLIB			;Clear first word
	BLT	S1,Z.KLIE-1		;Clear KLINIK data storage
	PUSHJ	P,P$CFM##		;Confirm this
	$RETIF
	PUSHJ	P,SETCPU		;Set up CPU database
	$IACK	(KLINIK Status)
	MOVSI	P1,-6			;For all CPUs
	SETO	P2,			;Flag for first time
KLIS.1:	MOVSI	S1,(CS.DWN!CS.NEX!CS.DET) ;Down, non-ex, or DET?
	TDNE	S1,CPUSTS(P1)		;??
	 JRST	KLIS.X			;Yes, don't even try
	AOSE	P2			;First time?
	$TEXT	(WTORTN,<>)		;No, add a blank line
	HRLOM	P1,T1			;CPU,,Master DTE
	MOVE	T2,[XWD ^D16,KLIDTD]	;Point to string block
	MOVE	S1,[XWD .DTKPR,T1]	;Read parameters
	MOVE	S2,S1			;Save original C(AC)
	DTE.	S1,			;Read current setting
	 JRST	[PUSHJ	P,KLIDTE	;Report error
		  HALT	.		;Always skips
		 JRST	KLIS.X]		;Go try next CPU
	$TEXT	(WTORTN,<	-- CPU^O1/T1,LHMASK/ KLINIK Status -->)
	MOVEI	T4,KLIDTD		;Point to returned data
	HRLI	T4,(POINT 16,,)		;Thus
	ILDB	T1,T4			;Get byte count
	LDB	T3,[POINT 16,KLIDTD+3,32];Console,,KLINIK
	TRNE	T3,BYTMSK		;Open?
	 JRST	KLS.OW			;Yes
	$TEXT	(WTORTN,<Access window closed>)
	JRST	KLIS.X			;Output string
KLS.OW:	$TEXT	(WTORTN,<Access window open
Window opened on ^A>)
	PUSHJ	P,KLS.DT		;Type date
	$TEXT	(WTORTN,<^M^JWindow closes on ^A>)
	PUSHJ	P,KLS.DT		;Type date
	$TEXT	(WTORTN,<^M^JKLINIK mode: ^A>)
	ILDB	T1,T4			;Fetch CSL,,KLINIK
	MOVE	T3,T1			;Save CSL
	ANDI	T1,BYTMSK		;Get KLINIK
	CAIN	T1,BYTMSK		;USER mode?
	 JRST	[$TEXT	(WTORTN,<USER>)
		 JRST	KLIS.X]		;Yes, done
	MOVE	T1,T3			;Get CSL mode
	LSH	T1,-8			;only CSL mode
	IDIVI	T1,3			;Xlate (1,3,7) to (0,1,2)
	$TEXT	(WTORTN,<REMOTE	Console mode: ^T/@MODTAB(T1)/>)
KLIS.X:	AOBJN	P1,KLIS.1		;Next
	$RETT

MODTAB:	[ASCIZ .OPERATOR.]
	[ASCIZ .PROGRAMMER.]
	[ASCIZ .MAINTENANCE.]

KLS.DT:	ILDB	T1,T4			;Fetch the time(sec/2)
	PUSH	P,T1			;Save time
	ILDB	T1,T4			;Get mon,,yr
	ILDB	T2,T4			;Get 0,,day
	MOVE	T3,T1			;Month,,yr
	LSH	T3,-8			;Month
	CAILE	T3,^D12			;Better be legal
	 SETZ	T3,			;Glad we checked
	$TEXT	(WTORTN,<^D2R0/T2,BYTMSK/^T/MONTAB(T3)/-^D2R0/T1,BYTMSK/ at ^A>)
	POP	P,T1			;Restore time
	LSH	T1,1			;Make seconds
	IDIVI	T1,^D60			;Min:sec
	MOVE	T3,T2			;Sec
	IDIVI	T1,^D60			;Hr:min
	$TEXT	(WTORTN,<^D2R0/T1/:^D2R0/T2/:^D2R0/T3/^A>)
	POPJ	P,

MONTAB:	0
	ASCIZ .-Jan.
	ASCIZ .-Feb.
	ASCIZ .-Mar.
	ASCIZ .-Apr.
	ASCIZ .-May.
	ASCIZ .-Jun.
	ASCIZ .-Jul.
	ASCIZ .-Aug.
	ASCIZ .-Sep.
	ASCIZ .-Oct.
	ASCIZ .-Nov.
	ASCIZ .-Dec.
	;The SET KLINIK Command
KLINIK:	$SAVE	<P1>			;Save P1
	MOVE	S1,[Z.KLIB,,Z.KLIB+1]	;Set up BLT
	SETZM	Z.KLIB			;Clear first word
	BLT	S1,Z.KLIE-1		;Clear KLINIK data storage
	PUSHJ	P,P$CFM##		;Try for a CRLF
	JUMPT	KLIN.1			;Go default to "ALL-CPUS"
	PUSHJ	P,P$KEYW##		;Get a keyword instead
	$RETIF				;Give up
	SUBI	S1,.ARCPU##		;Translate to CPU number
	CAIL	S1,0			;Range
	CAILE	S1,6			; Check
	$RETF				;Loser
	CAIN	S1,6			;"ALL-CPUS"?
	MOVEI	S1,7			;Yes
	HRLOM	S1,KLICPU		;Save CPU number (DTE=MASTER)
	PUSHJ	P,P$CFM##		;Must have a CRLF now
	$RETIF				;We don't
	JRST	KLIN.2			;Onward
KLIN.1:	MOVEI	S1,7			;All CPUs
	HRLOM	S1,KLICPU		;Save CPU number (DTE=MASTER)
KLIN.2:	PUSHJ	P,P$KEYW##		;Pick up a keyword
	$RETIF				;Need one of these too
	MOVNI	P1,1			;Init temp storage
	CAIN	S1,.KLOFF##		;Off?
	MOVEI	P1,0			;Yes
	CAIN	S1,.KLREM##		;Remote?
	MOVEI	P1,1			;Yes
	CAIN	S1,.KLUSR##		;User?
	MOVEI	P1,377			;Yes
	JUMPL	P1,.RETF		;Give up if we're fed junk
	DPB	P1,[POINT 8,KLIDTD+3,31];Save KLINIK mode
	PUSHJ	P,P$CFM##		;Want a CRLF
	$RETIF				;Didn't get one
	JUMPE	P1,KLIN.4		;If SET KLINIK OFF, go do it now
	CAIE	P1,1			;Remote?
	JRST	KLIN.3			;No
	PUSHJ	P,P$SIXF##		;Get a sixbit quantity
	$RETIF				;No such animal
	SETZ	T1,			;Keep track of where we are
	MOVE	S2,S1			;Grab password
KLI.2A:	JUMPE	S2,KLI.2B		;If end, quit
	SETZ	S1,			;Clear junk
	LSHC	S1,6			;Get next char
	ADDI	S1," "-' '		;Make UC ASCII
	DPB	S1,[POINT 8,KLIDTD+4,15
		    POINT 8,KLIDTD+4,7
		    POINT 8,KLIDTD+4,31
		    POINT 8,KLIDTD+4,23
		    POINT 8,KLIDTD+5,15
		    POINT 8,KLIDTD+5,7](T1)
	AOJA	T1,KLI.2A		;Loop for all 6 chars of password

KLI.2B:	PUSHJ	P,P$CFM##		;Time for a CRLF
	$RETIF				;OPR gave us garbage
KLIN.3:	PUSHJ	P,P$TIME##		;Get date-time
	$RETIF				;Must have one of these
	MOVE	P2,S1			;Save OPEN UDT
	MOVE	T4,[POINT 8,KLIDTD+0,15];Point to OPEN time
	PUSHJ	P,KLIN.T		;Convert and store
	PUSHJ	P,P$CFM##		;CRLF again
	$RETIF				;Trashed.
	PUSHJ	P,P$TIME##		;Get date-time
	$RETIF				;Not there
	CAMG	S1,P2			;Closing beyond opening date-time?
	$RETF				;Nope
	MOVE	T4,[POINT 8,KLIDTD+2]	;Point to CLOSE time
	PUSHJ	P,KLIN.T		;Convert and store
	PUSHJ	P,P$CFM##		;Get a CRLF
	$RETIF				;Can't
	CAIE	P1,1			;Remote?
	JRST	KLIN.4			;No
	PUSHJ	P,P$KEYW##		;Get a keyword
	$RETIF				;Must have one
	MOVNI	P1,1			;Init temp storage
	CAIN	S1,.KLMNT##		;Console mode MAINTENANCE?
	MOVEI	P1,7			;Yes
	CAIN	S1,.KLOPR##		;Console mode OPERATOR?
	MOVEI	P1,1			;Yes
	CAIN	S1,.KLPRG##		;Console mode PROGRAMMER?
	MOVEI	P1,3			;Yes
	JUMPL	P1,.RETF		;Have a known quantity?
	DPB	P1,[POINT 8,KLIDTD+3,23];Store for -20F
	PUSHJ	P,P$CFM##		;Parse a CRLF
	$RETIF
KLIN.4:	$IACK	(SET KLINIK)
	MOVE	T1,KLICPU		;CPU#,,DTE#
	MOVE	T2,[XWD 26,KLIDTD]	;String len,,addr
	MOVEI	S1,24			;Data length
	DPB	S1,[POINT 16,KLIDTD,15]	;Goes in arg block
	HLRZ	S1,T1			;CPU#
	CAIN	S1,7			;ALL?
	 JRST	KLIN.A			;YES
	MOVE	S1,[XWD	.DTKPS,T1]	;Set KLINIK
	MOVE	S2,S1			;Keep a copy in case of error
	DTE.	S1,			;AHoooom
	 PUSHJ	P,KLIDTE		;Report error
	$TEXT	(WTORTN,<CPU^O/T1,LHMASK/ SET KLINIK succeeded>)
	$RETT				;Exit

KLIN.A:	PUSHJ	P,SETCPU		;See what's about
	MOVSI	P1,-6			;TRY EACH CPU
KLIA.1:	MOVSI	S1,(CS.DWN!CS.NEX!CS.DET) ;Down, non-ex, or DET?
	TDNE	S1,CPUSTS(P1)		;??
	 JRST	KLIA.2			;Yes, don't even try
	HRLM	P1,T1			;Try this CPU
	MOVE	S1,[XWD .DTKPS,T1]	;UUO pointer
	MOVE	S2,S1			;Save in case of error
	DTE.	S1,			;AHoooom
	 PUSHJ	P,KLIDTE		;Report error
	$TEXT	(WTORTN,<CPU^O/T1,LHMASK/ SET KLINIK succeeded>)
KLIA.2:	AOBJN	P1,KLIA.1		;Next
	$RETT				;Done
	;DTE. UUO error handler

KLIDTE:	PUSH	P,T4			;Save AC
	HLRZ	T4,S2			;Get function that failed
	CAIN	T4,.DTKPR		;Read?
	 SKIPA	T4,[SIXBIT /SHOW/]	;Yes
	MOVE	T4,[SIXBIT /SET/]	;No, must be a SET command
	PUSH	P,T4			;Save command name for later
	MOVSI	T4,-ERRTBL		;Length of error table
	CAMN	S1,S2			;No UUO?
	 JRST	DTEERE			;If no UUO, no KLINIK
DTEERL:	MOVS	S2,ERRTAB(T4)		;Get error
	CAIE	S1,(S2)			;Match?
	AOBJN	T4,DTEERL		;No
DTEERE:	HRRZ	T4,ERRTAB(T4)		;Get ITEXT address
	POP	P,S2			;Restore command that failed
	$TEXT	(WTORTN,<CPU^O/T1,LHMASK/ ^W/S2/ KLINIK failed>)
	$TEXT	(WTORTN,<DTE. UUO  error - ^I/@T4,RHMASK/>)
	POP	P,T4
	AOS	(P)
	POPJ	P,

ERRTAB:	XWD	DTEUF%,[ITEXT <KLINIK functions not present>]
	XWD	DTEDC%,[ITEXT <CPU illegal or down>]
	XWD	DTEAP%,[ITEXT <Primary protocol not running>]
	XWD	DTENC%,[ITEXT <Inusfficient monitor free core>]
	XWD	DTEIB%,[ITEXT <CONFIG/Monitor version skew>]
ERRTBL==.-ERRTAB
	XWD	0,[ITEXT <Unexpected DTE. error (^O/S1/)>]

KLIN.T:	$CALL	S%U2DT			;Get time and date
	PUSH	P,S2			;Save date
	ADDI	S1,^D1K			;Round to nearest 2-sec clunk
	IDIVI	S1,^D2K			;And convert
	ROT	S1,-^D8			;Get high byte first
	IDPB	S1,T4			;Store
	ROT	S1,^D8			;Now low byte
	IDPB	S1,T4			;Finish time
	MOVE	S1,(P)			;Get date
	IDIVI	S1,^D31			;Get days
	AOJ	S2,			;1-31
	MOVEM	S2,(P)			;Save daze
	IDIVI	S1,^D12			;Get months
	AOJ	S2,			;1-12
	IDPB	S2,T4			;Month comes next
	ADDI	S1,^D64			;Year
	IDPB	S1,T4			;Store year
	SETZ	S1,			;Required zero
	IDPB	S1,T4			;Store that
	POP	P,S1			;Day of month
	IDPB	S1,T4			;Store that
	POPJ	P,			;Done
	SUBTTL	SHOW Command

C$SHOW:	$CALL	P$KEYW##		;Get the show keyword
	 $RETIF
	MOVEI	S2,SHODSP		;Get the address of the table
	$CALL	TABSRC##		;Find argument
	 $RETIF
	JRST	(S2)			;Dispatch to process argument
	SUBTTL	Some Random Subroutines -- DETJBS - Detach jobs lost from CPU

;SUBROUTINE TO DETACH JOBS WHOSE TERMINAL WILL BE LOST BY REMOVING A CPU
;CALL:	S1 = CPU BEING REMOVED

DETJBS:	$CALL	.SAVE4			;Get some save ACs
	TLZ	F,(FL.HEA)		;New heading required
	MOVEI	P4,1			;Get a bit for CPU0
	LSH	P4,(S1)			;Set it for CPU being checked
	GTTAB	P1,%CNSJN		;Number of jobs in the system
	MOVNI	P1,-1(P1)		;Form AOBJN for jobs
	HRLZS	P1
	MOVEI	P2,2			;Get the argblock lenght for RECON.
DETJ.1:	HRRZ	P3,P1			;Get the job number to check
	TRMNO.	P3,			;Get its terminal number
	 JRST	DETJ.3			;ISN'T ANY, TRY NEXT
	MOVE	S2,P3			;Save possible line number
	DEVNAM	P3,			;Get the SIXBIT terminal name
	 JRST	DETJ.3			;Shouldn't happen
	MOVE	S1,[XWD .RCCPU,P2]	;Get the argument pointer
	RECON.	S1,			;Get the CPU accessibility for terminal
	 JRST	DETJ.3			;Shouldn't happen
	TRZN	S1,P4			;Accesible from us?
	 JRST	DETJ.3			;No, continue
	JUMPN	S1,DETJ.3		;If others can access it, continue
	ANDI	S2,777			;Isolate line number for job
	HRLZS	S2			;In left half for detach
	HRR	S2,P1			;Get the job number
	ATTACH	S2,			;DETACH THE JOB
	 JRST	DETJ.3			;Shouldn't happen
DETJ.2:	TLON	F,(FL.HEA)		;HEADING GIVEN
	$TEXT	(WTORTN,<% Detaching Jobs:>)
	$TEXT	(WTORTN,< ^D/P1/^A>)
DETJ.3:	AOBJN	P1,DETJ.1		;CONTINUE FOR ALL JOBS IN THE SYSTEM
	TLNE	F,(FL.HEA)		;HAVE TO CLEAN UP
	$TEXT	(WTORTN,<>)		;Carriage return
	$RETT
	SUBTTL	LSTDEV - Report any devices that will be lost

;CALL:	S1 = CPU BEING REMOVED

LSTDEV:	$SAVE	<P1>			;Make room
	MOVEI	P1,1			;Get a bit for CPU0
	LSH	P1,(S1)			;Move to the position CPU being checked
	TLZ	F,(FL.HEA)		;New heading for this loop
LSTD.0:	SETO	T1,			;Init DVPHY. arg block for all devices
	SETZ	T2,			;Start at first device
	MOVEI	T3,2			;Init a place for RECON.
LSTD.1:	MOVE	S1,[XWD 2,T1]		;Get pointer to DVPHY. arg block
	DVPHY.	S1,			;Get a device name
	  JRST	LSTD.0			;Perhaps a network device disconnected
	JUMPE	T2,.RETT		;All done, return
	MOVE	T4,T2			;Move to find CPU that owns it
	MOVE	S1,[XWD .RCCPU,P3]	;Get the pointer for a RECON.
	RECON.	S1,			;Get the mask of CPUs that own this
	 JRST	RCNERR			;Strange
	TDZN	S1,P1			;One of them the one we're looking for?
	 JRST	LSTD.1			;No, loop
	JUMPN	S1,LSTD.1		;Continue if others can access it
	MOVE	S1,T4			;Get the device name
	DEVCHR	S1,			;Get status bits
	TXNN	S1,<DV.ASC!DV.ASP>	;Is it inited or assigned?
	 JRST	LSTD.1			;No, loop
	TXON	F,FL.HEA		;Did we already print the header?
	 $TEXT	(WTORTN,<The following active devices will be lost:>)
	$TEXT	(WTORTN,<	^W/T4/>)
	JRST	LSTD.1			;AND LOOK AT ANOTHER DEVICE
	SUBTTL	Remove all disk kontrollers on a cpu

;CALL:	S1 = CPU TO WORRY ABOUT (FL.WAC ALREADY ON)

RADKON:	$SAVE	<P1,P2,P3>		;Get scratch AC
	MOVEI	P3,1			;Get a bit for CPU0
	LSH	P3,(S1)			;Make into a bit
	MOVEI	P1,2			;Lenght of arg block for RECON.
	SETZB	P2,PHYNAM		;Indicate first call
RADK.1:	MOVE	S1,P2			;Get previous kontroller address
	PUSHJ	P,NXTKON		;Find next disk kontroller
	JUMPF	RADK.E			;Strange
	JUMPE	S1,.POPJ		;Done with disk kontrollers
	MOVE	P2,S1			;Save the address
	MOVEM	S1,DCHARG+.DCNAM	;Store name for DSKCHR
	MOVE	S2,[.DCMAX,,DCHARG]	;Argument for DSKCHR
	DSKCHR	S2,			;Get CPU this Kon is on
	  JRST	RADK.E			;Shouldn't fail
	LOAD	S1,DCHARG+.DCXCH,DC.XCA	;Get CPU descriptors
	TDZN	S1,P3			;Kon on this CPU?
	 JRST	RADK.1			;No, next Kon
	JUMPN	S1,RADK.1		;Also go if Kon also on some other CPU
	PUSHJ	P,RADK.2		;Remove or check the controller
	JRST	RADK.1			;Loop for all
RADK.2:	TXNE	F,FL.CHK		;Checking or doing?
	 JRST	DKONCM			;Checking
	JRST	DKONRM			;Removing

RADK.E:	$TEXT	(WTORTN,<Error trying to step through controllers - DSKCHR or SYSPHY error on unit ^W/S1/>)
	$RETF
	SUBTTL	FNDKON - Find given controller name

;CALL:	S1/	Controller name
;
;RTNS:	TRUE	S1/	First unit name on controller
;		S2/	Alternate port name

FNDKON:	$SAVE	<P1>			;Make a scratch reg
	HLLZ	P1,S1			;Get the controller name
FNDK.0:	SETZ	S1,			;Start at beginning of controller list
FNDK.1:	PUSHJ	P,NXTKON		;Get the next controller
	JUMPF	FNDK.E			;??
	JUMPE	S1,FNDK.N		;Non-exitent
	CAME	S2,P1			;What we're looking for?
	JRST	FNDK.1			;No, keep trying
	$RETT				;Yes, return now

FNDK.E:	$TEXT	(WTORTN,<Error trying to find controller name - DSKCHR or SYSPHY error on unit ^W/S1/>)
	$RETF
FNDK.N:	$TEXT	(WTORTN,<Non-existent controller ^W/P1/>)
	$RETF
	SUBTTL	NXTKON - Step through the disk kontroller data blocks

;CALL:	S1 = Previous unit or 0 for first time
;
;RTNS::S1 = SIXBIT name of unit

NXTKON:	$SAVE	<P1>			;Save a reg
	HLLZ	P1,S1			;Save this controller
	TXNN	F,FL.ALT		;Already looking a alternate kontrollers?
	MOVEM	S1,PHYNAM		;Store for later
NXTK.1:	MOVE	S1,PHYNAM		;Get unit we're on
	SYSPHY	S1,			;Get the next kontroller on the system
	 $RETF				;??
	MOVEM	S1,PHYNAM		;Store for next time
	JUMPE	S1,NXTK.3		;No more,,Go see if done
	TXNN	F,FL.ALT		;Looking for auxilliary?
	 JRST	NXTK.2			;No, go return this name
	MOVEM	S1,DCHARG+.DCNAM	;Store name for DSKCHR
	MOVE	S1,[.DCMAX,,DCHARG]	;Get the pointer to the arg list
	DSKCHR	S1,			;We're interested in the aux port
	 JRST	FNDK.E			;Shouldn't happen
	MOVEI	S1,DCHARG+.DCALT	;Set to get second port name
	TXNE	F,FL.ADD		;Adding the controller?
	MOVEI	S1,DCHARG+.DCDET	;Yes, get detached port name
	SKIPN	S1,(S1)			;Get the alternate port name
	 JRST	NXTK.1			;None, so try for next
NXTK.2:	HLLZ	S2,S1			;Get controller name
	JUMPE	P1,.RETT		;On the first one, return now
	CAMN	S2,P1			;Same as what we have?
	 JRST	NXTK.1			;No, try the next
	$RETT				;No, return it
NXTK.3:	TXON	F,FL.ALT		;Already checked alternate?
	 JRST	NXTK.1			;No, try it again now
	TXZ	F,FL.ALT		;Clear flag for next time
	$RETT
	SUBTTL	NXTUNI - Return next unit on controller

;CALL:	S1/	Kontroller name
;
;RTNS:	TRUE	S1/	Unit name
;		S2/	Kontroller name

NXTUNI:	$SAVE	<P1>			;Get a scratch reg
	TXNN	F,FL.ALT		;Looking for alternate ports?
	MOVEM	S1,PHYUNI		;No, store kontroller in question
	HLLZ	P1,S1			;Save the name to look for
NXTU.1:	MOVE	S1,PHYUNI		;Get the last name we wanted
	SYSPHY	S1,			;Get the next
	 JRST	FNDK.E			;??
	MOVEM	S1,PHYUNI		;Store for next time
	JUMPE	S1,NXTU.3		;All done, check aux port
	TXNN	F,FL.ALT		;Looking for auxilliary?
	 JRST	NXTU.2			;No, go return this name
	MOVEM	S1,DCHARG+.DCNAM	;Store name for DSKCHR
	MOVE	S1,[.DCMAX,,DCHARG]	;Get the pointer to the arg list
	DSKCHR	S1,			;We're interested in the aux port
	 JRST	FNDK.E			;Shouldn't happen
	MOVEI	S1,DCHARG+.DCALT	;Set to get second port name
	TXNE	F,FL.ADD		;Adding the controller?
	MOVEI	S1,DCHARG+.DCDET	;Yes, get detached port name
	SKIPN	S1,(S1)			;Get the alternate port name
	 JRST	NXTU.1			;None, so try for next
NXTU.2:	HLLZ	S2,S1			;Get controller name
	CAME	S2,P1			;What we want?
	 JRST	[SETZ S1,		;Not on this controller
		 $RETT]			;Return signifying that
	$RETT				;Else return the names now
NXTU.3:	TXNN	F,FL.ALT		;Already checked alternate port
	 JRST	NXTU.1			;No, try it again now
	$RETT
	SUBTTL	DKONCM - Check if disk controller may be removed

;CALL:	P1 = 2 (FOR RECON. ARG COUNT)
;	P2 = SIXBIT UNIT OR KONTROLLER NAME
;	P3 = CPU BIT MASK # IF FL.WAC IS ON
;RTNS::FL.NCD ON IF CANNOT REMOVE THE KONTROLLER

DKONCM:	$SAVE	<P2>			;Callers want P2 preserved
	MOVE	S1,PHYNAM		;First unit on prime port
	MOVEM	S1,PHYUNI		;Where to start the search
	MOVE	S1,P2			;First unit on kontroller
	HLLZS	P2			;Kontroller name
	MOVEM	S1,DCHARG+.DCNAM	;Store for DSKCHR
	JRST	DKON.0			;And go check if mounted
DKON.1:	MOVE	S1,DCHARG+.DCNAM	;Else, yes, get the first unit
	PUSHJ	P,NXTUNI		;Get the next
	JUMPE	S1,DKON.4		;Zero means we're done
	JUMPF	RADK.E			;Strange error otherwise
	MOVEM	S1,DCHARG+.DCNAM	;Store the unit name for the DSKCHR
	CAME	S2,P2			;Still on the one we want
	 JRST	DKON.4			;No, all done
DKON.0:	MOVE	S1,[XWD .DCMAX,DCHARG] ;Point to the argument block
	DSKCHR	S1,			;Get info about unit (just want STR)
	 JRST	DKON.E			;Shouldn't happen
	SKIPN	T2,DCHARG+.DCSNM	;Get name of structure mounted
	JRST	DKON.1			;Ok to remove unit if nothing spinning
	MOVEI	T1,2			;Get lenght of arg block for RECON.
	MOVE	S1,[.RCCPU,,T1]		;Get the pointer to args
	RECON.	S1,			;Get CPU mask for acceptabity
	 JRST	RCNERR
	TDZE	S1,P3			;Is it on CPU being tested?
	 JUMPE	S1,DKON.2		;Yes, don't remove if only port
	TLNE	F,(FL.WAC)		;Worrying about removing a cpu
	TDNE	S1,CPURUN		;Are any other CPUs running?
	 JRST	DKON.1			;Yes, ok to remove it then
DKON.2:	TLNE	F,(FL.ADD)		;Adding?
	 JRST	DKON.1			;Yes, loop
	TLON	F,(FL.NCD!FL.HEA)	;Already give header, and flag error
	$TEXT	(WTORTN,<Following structures must be dismounted:>)
	$TEXT	(WTORTN,<	^W/DCHARG+.DCSNM/ on ^W/DCHARG+.DCNAM/>)
	JRST	DKON.1			;Loop for all units
DKON.4:	TLNE	F,(FL.NCD!FL.CHK)	;Ok to really remove the units
	$RETT				;No, return now
	MOVE	P2,-1(P)		;Restore first unit on controller
	JRST	DKOR.0			;Go remove
	SUBTTL	DKONRM -- Add/Remove disk controller

DKONRM:	$SAVE	<P2>			;Callers want P2 to return intact
DKOR.0:	MOVE	S1,PHYNAM		;First unit on prime port
	MOVEM	S1,PHYUNI		;Where to start the search
	MOVE	S1,P2			;First unit on kontroller
	HLLZS	P2			;Kontroller name
	MOVEM	S1,DCHARG+.DCNAM	;Store for DSKCHR
	JRST	DKOR.4			;And go check if mounted
DKOR.1:	MOVE	S1,DCHARG+.DCNAM	;Else, yes, get the first unit
	PUSHJ	P,NXTUNI		;Get the next
	JUMPF	RADK.E			;Strange error otherwise
	JUMPE	S1,.RETT		;Zero means we're done
	MOVEM	S1,DCHARG+.DCNAM	;Store the unit name for the DSKCHR
	CAME	S2,P2			;Still on the one we want
	 JRST	.RETT			;No, all done
DKOR.4:	MOVE	S1,[XWD .DCMAX,DCHARG] ;Point to the argument block
	DSKCHR	S1,			;Get info about unit (just want STR)
	  JRST	DKON.E			;Shouldn't happen
	LOAD	S2,S1,DC.STS		;Get the status of the unit
	TLNN	F,(FL.ADD)		;Add or remove command
	 JRST	DKOR.8			;Remove
	CAIE	S2,.DCSTD		;Is the unit down
	 JRST	DKOR.1			;No, already usable
	MOVE	S1,[XWD .RCATT,T1]	;Add function
	SKIPN	T1,DCHARG+.DCDET	;Alternate port?
	JRST	DKOR.6			;Go attach the unit
	MOVEM	T1,PHYNAM		;Yes, after the attach is done, won't
	MOVEM	T1,PHYUNI		; be able to find this unit in SYSPHY
	TXO	F,FL.ALT		; chain
	JRST	DKOR.6			;Now go attach the unit
DKOR.8:	CAIN	S2,.DCSTD		;Is unit already detached
	 JRST	DKOR.1			;Yes, don't do it again
	TXNE	S1,DC.ALT		;This dual ported?
	 TXNN	F,FL.WAC		;Removing a cpu?
	  JRST	DKOR.5			;No, don't report anything
	MOVEI	T1,2			;Get lenght of arg block for RECON.
	MOVE	T2,DCHARG+.DCNAM	;Get the name of the unit
	MOVE	S1,[.RCCPU,,T1]		;Get the pointer to args
	RECON.	S1,			;Get CPU mask for acceptabity
	 JRST	RCNERR			; ??
	TDNN	S1,P1			;Unit on the CPU being removed
	 JRST	DKOR.5			;No, nothing to report
	TLON	F,(FL.HEA)		;Printed the header yet?
	 $TEXT	(WTORTN,<%Following drive(s) are dual ported with the CPU being removed:>)
	$TEXT	(WTORTN,<	^W/DCHARG+.DCNAM/>)
DKOR.5:	MOVE	S1,[XWD .RCDET,T1]	;Remove function
DKOR.6:	MOVEI	T1,2			;Lenght of arg block
	MOVE	T2,DCHARG+.DCNAM	;Get unit to attach/detach
	RECON.	S1,			;Do the function
	 PUSHJ	P,RCNERR		;??
	JRST	DKOR.1			;Loop for all units

DKON.E:	$TEXT	(WTORTN,<Error trying to get structure name mounted on drive ^W/DCHARG+.DCSNM/>)
	$RETF
	SUBTTL	Subroutine to set up CPU status table

SETCPU:	$SAVE	<P1>			;Get a safe AC
	MOVE	S1,[.STCPU,,SP.CR0!SP.CR1!SP.CR2!SP.CR3!SP.CR4!SP.CR5]
	SETUUO	S1,			;Set this job to run anywhere
	  JFCL				;Ok, must be a single processor
	SETZM	CPUN			;Clear count of running cpus
	SETZM	CPUOK			;Clear count of cpus with ok words counting
	SETZM	CPURUN			;And mask for running ones
	MOVSI	S1,-6			;Max cpus
SETC.1:	MOVSI	S2,(S1)			;Cpun to lh
	LSH	S2,1			;*2 for gettab
	ADD	S2,[%CCPTR&777777,,.GTSLF]
	GETTAB	S2,			;Get base of cdb constants = cdb address
	 $STOP(CDB,<Can't determine CDB base address for CPU^D/S1,RHMASK/>)
	TLNN	S2,(SL.MAX)		;Is max for gettab = 0
	JRST	[MOVSI S2,(CS.DWN!CS.NEX) ;Yes, mark it non-existant
		JRST SETC.2]		;And store data
	MOVEI	P1,(S1)			;Copy cpu number
	LSH	P1,1			;*2 for gettab
	ADD	P1,[%CVRUN]		;Get .CPRUN
	GETTAB	P1,			;Get it
	 $STOP(CDS,<Can't determine run status for CPU^D/S1,RHMASK/>)
	TLNE	P1,(CV%DET)		;Is it detached
	JRST	[HRLI S2,(CS.DWN!CS.DET) ;Yes, mark it
		JRST SETC.2]		;Store data
	TLNE	P1,(CV%RMV)		;Is cpu already stopped
	JRST	[HRLI S2,(CS.DWN)	;Yes, mark it down
		JRST SETC.2]		;Store data
	TLZ	S2,-1			;CPU is up, clear status bits
	AOS	CPUN			;Count a running CPU
	GTTAB	P1,%CNBCP		;Find the boot cpu
	CAIN	P1,(S1)			;This it
	TLO	S2,(CS.BOT)		;Yes, remember that
	MOVEI	P1,1B35			;Get a bit for cpu0
	LSH	P1,(S1)			;Position it correctly
	IORM	P1,CPURUN		;Light a running cpu bit
	MOVEI	P1,(S1)			;Copy cpu number
	LSH	P1,1			;*2 for gettab
	ADD	P1,[%CCOKP]		;Get the ok word
	GETTAB	P1,			;Get it
	 $STOP(CDU,<Can't determine up status for CPU^D/S1,RHMASK/>)
	SKIPG	P1			;Is the cpu really running
	AOSA	CPUOK			;Yes, count the cpu
	TLO	S2,(CS.NOK)		;No, remember this one isn't
SETC.2:	MOVEM	S2,CPUSTS(S1)		;Update status
	AOBJN	S1,SETC.1		;And try another cpu
	$RETT				;Return
	SUBTTL	CPUSRC - CPU-driven table searching


CPUSRC:	HLLZ	T1,(S2)			;GET THE NUMBER OF ENTRIES
	MOVN	T1,T1			;MAKE IT NEGATIVE
	HRRI	T1,1(S2)		;ADDRESS OF THE TABLE
CPUS.1:	HLRZ	T2,(T1)			;MINIMUM OFFSET IS CPU0
	MOVEI	T3,6(T2)		;MAXIMUM OFFSET IS CPU5 + 1 (ALL CPUS)
	CAIL	S1,(T2)			;RANGE
	CAILE	S1,(T3)			; CHECK
	SKIPA				;NO MATCH
	JRST	CPUS.2			;YES..
	AOBJN	T1,CPUS.1		;TRY NEXT ONE
	$RETF				;ERROR..RETURN
CPUS.2:	HRRZ	S2,(T1)			;GET THE DATA
	$RETT				;RETURN TRUE
	SUBTTL	GETADR - Input an address from a token

; This routine will return a number based on the string a user types.
;If the string begins with a # character, the number will be assumed
;octal else it will be decimal, if the number is followed by a "P"
;then it will be assumed to mean page number, else it will be in units
;if 1024 words.

GETADR:	$SAVE	<P1,P2,P3>		;Make some room
	MOVEI	P3,^D10			;Assume decimal radix
	$CALL	P$TOK##			;See if he specified octal
	 SKIPF				;Didn't see if number
	MOVEI	P3,^O10			;He did, get real radix
GETAD1:	PUSHJ	P,P$FLD##		;Get the next token
	 JUMPF	GETA.6			; ??
	MOVEI	P1,1(S1)		;Save the string address
	MOVE	S2,P1			;Make a working copy
	HRLI	S2,(POINT 7,)		;Make it a byte pointer
	SETO	P2,			;Clear the place for the number
GETA.1:	ILDB	S1,S2			;Get the next character
	CAIL	S1,"0"			;Numeric?
	 CAILE	S1,"9"			; .  .  .
	  JRST	GETA.3			;No, go see if done
	SKIPGE	P2			;First time through?
	 SETZ	P2,			;Yes, start with a null
	IMUL	P2,P3			;Shift current total by radix
	ADDI	P2,-"0"(S1)		;Add this character into it
	JRST	GETA.1			;Loop for all

;When we get here, we have a number in P2 which will default to
;representing pages. We'll see if we have to convert it to kilo-words.
GETA.3:	JUMPE	S1,GETA.8		;All done?
	CAIE	S1,"K"			;No, did he specify kilo?
	 CAIN	S1,"k"			;Both ways
	  TRNA				;Yes
	JRST	GETA30			;No, try for pages
	LSH	P2,1			;Convert to right number of pages
	JRST	GETA.9			;Go return the value
GETA30:	CAIE	S1,"P"			;Did he specify pages
	 CAIN	S1,"p"			; .  .  .
	  JRST	GETA.9			;All set, go return the number
	JRST	GETA40			;Illegal format
GETA.4:	ILDB	S1,S2			;Make sure he didn't type more
	JUMPE	S1,GETA.5		;If he didn't, go finish up
GETA40:	$TEXT	(WTORTN,<Illegally formatted address>)
	$RETF				;Return bad
GETA.5:	JUMPGE	P2,.RETT		;Did he type any digits?
	$TEXT	(WTORTN,<Illegal address specified - at least one digit must be specified>)
	$RETF
GETA.6:	$TEXT	(WTORTN,<Error parsing address field>)
	$RETF

;Here with a number of words.
GETA.8:	ADR2PG	P2			;Convert to pages
GETA.9:	MOVE	S1,P2			;Get the number to be returned
	$RETT				;Return it
	SUBTTL	SNDALL - Routine to send a message to all terminals

SNDALL:	$SAVE	<S2+1>			;Save possible data reg
	PUSHJ	P,SEND.1		;Send the message
	MOVEI	S1,[BYTE (7).CHCRT,.CHLFD] ;Append a CRLF to it
SEND.1:	MOVE	S2+1,S1			;Point to text
	MOVX	S1,.TOTYP		;TRMOP. to stuff text down TTY's throat
	MOVE	S2,FRCLIN##		;Send text to FRCLIN
	MOVX	TF,<3,,S1>		;Set up for CALLI
	TRMOP.	TF,			;Do SEND ALL command
	  $RETF				;Can't
	$RETT				;Return sucessful
	SUBTTL	CTYTYP - Type messages on the CTY

CTYTYP:	SKIPN	CTYBLK+1		;Did we already set-up TRMOP. block
	 PUSHJ	P,SETCTY		;No, do so now
	MOVEM	S1,CTYBLK+2		;Store the character
	MOVE	S1,[3,,CTYBLK]		;Point to the argument block
	TRMOP.	S1,			;Type the character
	 $STOP(CTC,<Can't type to CTY>)
	$RETT

SETCTY:	MOVSI	S2,'CTY'		;Get the name of the CTY
	IONDX.	S2,			;And get it's UDX
	 $STOP	(CGU,<Can't get universal device index of CTY>)
	MOVEM	S2,CTYBLK+1		;Store it
	MOVEI	S2,.TOOUC		;Get the output a character functionn
	MOVEM	S2,CTYBLK		;Store it
	$RET
	SUBTTL	Error subroutines

RCNERR:	$TEXT	(WTORTN,<RECON. UUO error (^O/S1/)^A >)
	CAIL	S1,RCNETL		;Error number in range?
	MOVEI	S1,RCNETL		;No, something really wrong
	$TEXT	(WTORTN,< ^T/@RCNETX(S1)/>)
	JRST	ERRXIT			;Join common error exit

DIAERR:	$TEXT	(WTORTN,<DIAG. UUO error (^O/S1/)^A >)
	CAIL	S1,DIAETL		;Error number in range?
	MOVEI	S1,DIAETL		;No, something really wrong
	$TEXT	(WTORTN,< ^T/@DIAETX(S1)/>)
ERRXIT:	MOVE	S1,[EXP MF.FAT!<INSVL.(<'CNF'>,MF.SUF)>] ;Get error flags
	MOVEM	S1,G$APFG##		;Set them for typeout
	$RETF

RCNETX:	[ASCIZ	/No such error code/]
	[ASCIZ	/Illegal argument list/]
	[ASCIZ	/Not privileged/]
	[ASCIZ	/Timesharing has already stopped on some CPU/]
	[ASCIZ	/Illegal job number/]
	[ASCIZ	/System cannot be snapshotted/]
	[ASCIZ	/Address check/]
	[ASCIZ	/Illegal string/]
	[ASCIZ	/Illegal CPU number/]
	[ASCIZ	/CPU still running/]
	[ASCIZ	/Can't attach disk/]
	[ASCIZ	/Device is spooled/]
	[ASCIZ	/Device is already attached/]
	[ASCIZ	/Illegal device/]
	[ASCIZ	/Device in use/]
	[ASCIZ	/Can not detach disk/]
	[ASCIZ	/LOKCON not loaded (can't set memory off-line)/]
	[ASCIZ	/Removing monitor memory/]
	[ASCIZ	/Job(s) too big/]
	[ASCIZ	/Moving locked job(s)/]
RCNETL==.-RCNETX
	[ASCIZ	|Unknown error code|]

DIAETX:	[ASCIZ	/No such error code/]
	[ASCIZ	/Not privileged/]
	[ASCIZ	/Illegal number of arguments/]
	[ASCIZ	/Illegal controller/]
	[ASCIZ	/Illegal unit/]
	[ASCIZ	/Some units already assigned/]
	[ASCIZ	/Unit not in diagnostic mode/]
	[ASCIZ	/Unit assigned to another job/]
	[ASCIZ	/No free core/]
	[ASCIZ	/No assigned units/]
	[ASCIZ	\I/O word crosses a page boundary\]
	[ASCIZ	/Illegal function/]
	[ASCIZ	/Job can't be virtual/]
	[ASCIZ	/No such CPU/]
	[ASCIZ	/CPU not running/]
	[ASCIZ	/Bad argument list/]
	[ASCIZ	/No CI port on CPU/]
	[ASCIZ	/Read CI port counters timed out/]
	[ASCIZ	/No NI port on CPU/]
	[ASCIZ	/Microcode reload failed/]
	[ASCIZ	/Microcode not available/]
DIAETL==.-DIAETX
	[ASCIZ	/Unknown error code/]
	SUBTTL	End of CNFORN

	END