Google
 

Trailing-Edge - PDP-10 Archives - bb-d549g-sb - config.mac
There are 2 other files named config.mac in the archive. Click here to see a list.
	TITLE	CONFIG  --  Congifuration Program for 7.01
	SUBTTL	C.D.O'Toole/CDO   18-Apr-80


;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.

;COPYRIGHT (C) 1978,1979,1980 BY DIGITAL EQUIPMENT CORPORATION


	SEARCH	UUOSYM

	CFGWHO==0
	CFGVER==1
	CFGMIN==0
	CFGEDT==6

	CFGVER==BYTE(3)CFGWHO(9)CFGVER(6)CFGMIN(18)CFGEDT

	LOC	<.JBVER==137>
	EXP	CFGVER
	RELOC

;Revision History

;1	Create CONFIG.MAC and implement original features
;2	Correct bug which allowed the removal of the last running CPU
;3	Begin implementation of System Sleep
;4	Dont DETACH disk units if forced removal of a CPU
;5	KONCPU moved in load 70037
;6	DETACH the CPU after REMOVE so that unit record gear comes out right
;AC DEFINITIONS

	F==0			;A FLAG REG
		FL.EOL==1B0	;END OF LINE SEEN
		FL.ETX==1B1	;END OF PHYSICAL LINE SEEN
		FL.RSC==1B2	;HAVE GETONE USE RESCAN LAST CHARACTER
		FL.WAC==1B3	;WORRY ABOUT CPU NUMBER IN REMOVE
		FL.NCD==1B4	;"NO CAN DO" THIS COMMAND
		FL.HEA==1B5	;HEADING ALREADY GIVEN
		FL.CHK==1B6	;CHECKING ONLY
		FL.ADD==1B7	;"ADD" RATHER THAN "REMOVE"
		FL.UPZ==1B8	;^Z TYPED, EXIT AFTER COMMAND
		FL.DMN==1B9	;OPERATOR REALLY WANTS COMMAND DONE
		FL.POK==1B10	;"P" OR "K" SEEN IN "GETNUM"
		FL.DME==1B11	;"DETJBS" FOUND ME IN ITS SCAN
		FL.NIN==1B12	;DISALLOW ^C INTERRUPTS

	T1==1			;TEMPORARY ACS FOR ANY SUBROUTINE
	T2==2
	T3==3
	T4==4
	T5==5

	CH==6			;CHARACTER HOLDER

	P1==12			;PRESERVED ACS FOR ANY COMMAND PROCESSOR
	P2==13
	P3==14
	P4==15
	P5==16

	P==17


;I/O CHANNELS

	PTY==0			;FOR "SET MEMORY" UNTIL JIM WRITES THE UUO

;DEBUGGING SWITCHES

	IFNDEF	FTPTYDEBUG,<FTPTYDEBUG==0>

;TEMPORARY DEFINITIONS

OPDEF	RECON.	[CALLI 202]	;RE-CONFIGURE UUO
		.RCROJ==0	;FUNCTION 0 - RUN ONLY SPECIFIED JOB
		.RCSLP==1	;FUNCTION 1 - SUSPEND THE SYSTEM NOW
	SUBTTL	Macros and other stuff

	SALL			;CLEAN UP LISTING

	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==400000+VALUE>

	MSYM	MONITR,0	;SYMBOLIZE LOCATION 0 OF THE MONITOR

;DISK DATA BASE

	MSYM	UNINAM,0	;UDB: SIXBIT/kon/,,SIXBIT/unit/
	MSYM	UNILOG,1	;UDB: SIXBIT/str/ IF STRUCTURE MOUNTED
	MSYM	UNISYS,3	;UDB: NEXT SYSTEM UNIT,,xxx
	MSYM	UNIKON,6	;UDB: xxx,,KONTROLLER FOR UNIT
	MSYM	UNIDES,55	;UDB: UNIT STATUS IS BITS 7-8
		UNVDWN==3	;CODE INDICATING UNIT IS DOWN (DETACHED)

	MSYM	UNI2ND,72	;UDB: bits,,2ND PORT IF DUAL
	MSYM	KONTAB,0	;KDB: 8 WORD TABLE OF UNITS ON KONTROLLER
	MSYM	KONCPU,32	;KDB: CPU OWNING KONTROLLER IS BITS 0-2

;DDB'S IN GENERAL

	MSYM	DEVNAM,0	;SIXBIT/device/
	MSYM	DEVCHR,1	;DEVICE CHARACTERISTICS
		DCVNET==20000,,0 ;"NETWORK DEVICE"

	MSYM	DEVIOS,2	;IO STATUS
		IOACT==10000	;IO IN PROGESS

	MSYM	DEVSER,3	;LH = LINK TO NEXT DDB
	MSYM	DEVTYP,12	;BITS 4-9 ARE DEVICE TYPE
	MSYM	DEVCPU,20	;BITS 0-2 IS CPU OWNING DEVICE
	MSYM	DEVJOB,21	;BITS 27-35 ARE JOB NUMBER
	MSYM	DDBLDB,22	;RH LINK TO LDB FOR TTY'S

;LINE DATA BLOCKS

	LDBDCH==22		;LINE BITS, (27-35 ARE LINE NUMBER)
				; ( 22 IS THE 7.00 VALUE, GETTAB'ABLE IN 7.01 )
		LDRPTY==400000	;LINE IS REALLY A PTY
		LDRREM==2000	;LINE IS A REMOTE (NETWORK) LINE
	LDBBYT==LDBDCH+1	;BITS 22-24 ARE CPU OWNING TERMINAL

;MONBTS COMMUNICATION DATA

	MSYM	MBTCOM,411	;ADDRESS OF COMMUNICATION REGION
		MBTPGS==10	;NUMBER OF PAGES MIKE WANTS FOR MONBTS
;PSI INTERRUPT BLOCKS

PSIBAS:				;BASE OF INTERRUPT SYSTEM
CCINT:	EXP	CCTRAP		;NEW PC AT INTERRUPT
	BLOCK	3		;OTHER 3 WORDS

;BUFFER STUFF

PTYOBF:	BLOCK	3		;PTY OUTPUT RING HEADER
PTYIBF:	BLOCK	3		; "  INPUT    "    "
PTYOPN:	EXP	.IOASC		;ASCII MODE
	SIXBIT	/PTY/		;GET A PTY
	XWD	PTYOBF,PTYIBF	;FOR I/O

;TRMOP. BLOCKS

FRCTYP:	EXP	.TOTYP		;STICK STRING INTO INPUT BUFFER
FRCLIN:	BLOCK	1		;LINE NUMBER FILLED IN
FRCSTR:	EXP	0		;ASSRESS OF THE STRING

;STORAGE

PDL:	BLOCK	50		;A STACK
DOPTR:	BLOCK	1		;POINTER TO PROCEDURE COMMAND STRING
DONAM:	BLOCK	1		;NAME OF PROCEDURE IN PROGRESS
DOFLG:	BLOCK	1		;SAVED "F" DURING PROCEDURE (REALLY FL.UPZ)
SAVCHR:	BLOCK	1		;SAVED CHARACTER FROM GETONE
TTYTAB:	BLOCK	1		;ADDRESS OF TTYTAB (INDEXED BY T1)
FIRDSK:	BLOCK	1		;ADDRESS OF FIRST DISK UNIT IN SYSTEM
ACTDEV:	BLOCK	1		;COUNT OF IOACT DDB'S
DEVLST:	BLOCK	1		;ADDRESS OF FIRST DDB IN SYSTEM
MYJOBN:	BLOCK	1		;MY JOB NUMBER
MYLINE:	BLOCK	1		;AND MY LINE NUMBER
DCHOFS:	BLOCK	1		;OFFSET INTO LDB FOR LDBDCH
BYTOFS:	BLOCK	1		;OFFSET FOR LDBBYT ( LDBDCH+1 )
SYSSIZ:	BLOCK	1		;SIZE OF THE MONITOR
NWCORE:	BLOCK	1		;NUMBER OF WORDS OF MEMORY ON THE SYSTEM
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)
				;1B0 = CPU IS DOWN
				;1B1 = CPU IS NON-EXISTANT
				;1B2 = CPU HAS BEEN DETACHED
				;1B3 = CPU'S OK WORD IS NOT COUNTING
				;1B4 = THIS IS THE CURRENT POLICY CPU
				;RH = CDB ADDRESS
	SUBTTL	Entry Point and Main Command Dispatch

CONFIG:	JFCL			;NO CCL ENTRY
	RESET			;START FRESH
	MOVE	P,[IOWD 50,PDL]	;GET A STACK
	OPEN	PTY,PTYOPN	;GRAB A PTY
	  HALT	.		;WHAT
	INBUF	PTY,1		;ONLY NEED 1 BUFFER
	OUTBUF	PTY,1		;IN EITHER DIRECTION
	MOVEI	T1,[EXP <PS.SON+5>,PSIBAS
		EXP .PCSTP,<<CCINT-PSIBAS>,,0>,0]
	PIRST.	T1,		;BUILD THE PSI SYSTEM IN ONE SWELL FOOP
	  HALT	.		;WHAT
	GTTAB	T1,%CNSIZ	;SIZE OF THE MONITOR
	HRRZM	T1,SYSSIZ	;SAVE FOR LATER
	MOVEI	T1,-1(T1)	;WANT HIGHEST ADDRESS
	SPY	T1,		;SPY ON THE MONITOR
	  HALT	.		;WHAT
	MOVSI	T1,1		;;; GET 256K FOR NOW
;;;	GTTAB	T1,%CNNWC	;GET NUMBER OF WORDS OF MEMORY
	MOVEM	T1,NWCORE	;SAVE FOR LATER
	GTTAB	T1,%LDUNI	;GET ADDRESS OF FIRST UNIT IN SYSTEM
	HLRZM	T1,FIRDSK	;SAVE FOR LATER USE
	GTTAB	T1,%CNDEV	;GET HEADER OF DEVICES
	HLRZM	T1,DEVLST	;SAVE FOR LATER
	GTTAB	T1,<.GTTTY,,.GTSLF> ;GET ADDRESS OF TTYTAB
	TLZ	T1,-1		;CLEAR GETTAB BITS
	TDO	T1,[Z MONITR(T1)] ;INDEX BY TI FOR INDIRECT ADDRESSING
	MOVEM	T1,TTYTAB	;STORE FOR LATER USE
	GTTAB	T1,%CNDCH,LDBDCH ;GET OFFSET FOR LDBDCH
	HRRZM	T1,DCHOFS	;STORE FOR DETJBS
	ADDI	T1,LDBBYT-LDBDCH ;GET OFFSET FOR LDBBYT
	HRRZM	T1,BYTOFS	;STORE THAT TOO
	GTTAB	T1,%CNFLN	;FIND MONITORS SPECIAL TTY
	TRO	T1,.UXTRM	;ADD TERMINAL IONDX FOR TRMOP.
	HRRZM	T1,FRCLIN	;REMEMBER FOR LATER
	PJOB	T1,		;GET MY JOB NUMBER
	MOVEM	T1,MYJOBN	;FOR "DETJBS"
	TRMNO.	T1,		;GET LINE NUMBER FOR MY JOB
	  HALT	.		;WHAT
	ANDI	T1,777		;JUST THE NUMBER
	MOVEM	T1,MYLINE	;FOR "DETJBS"
	SETZM	DOPTR		;NO PROCEDURES IN PROGRESS
	SUBTTL	Main Command Loop

NXTCOM:	OUTSTR	[ASCIZ/CONFIG>/] ;PROMPT THE OPERATOR
	SETZB	F,SAVCHR	;CLEAR FLAGS, NO SAVED CHARACTER NOW
MAIN.0:	PUSHJ	P,GETSIX	;GET COMMAND AND MASK
	JUMPE	T1,NULCMD	;NULL COMMAND
	MOVE	T3,[-NUMCMD,,CMDTBL] ;GET AOBJN TO COMMAND TABLE
	PUSHJ	P,TABSRC	;LOOK IT UP IN THE TABLE
	  SKIPA T2,[NUMCMD]	;ILLEGAL COMMAND
	  MOVEI	T2,NUMCMD+1	;AMBIGUOUS COMMAND
	PUSHJ	P,@CMDDSP(T2)	;EXECUTE IT
MAIN.1:	PUSHJ	P,FLUSH		;EAT UP REST OF INPUT LINE
	SKIPN	P1,DOPTR	;DOING A PROCEDURE
	JRST	MAIN.2		;NO
	TLNE	F,(FL.NCD)	;ERROR DURING PROCEDURE
	PUSHJ	P,[OUTSTR [ASCIZ/?Procedure "/]
		MOVE T1,DONAM	;GET PROCEDURE WE WERE DOING
		PUSHJ P,SIXOUT	;OUTPUT IT
		OUTSTR [ASCIZ/" terminated due to above error/]
		SETZ P1,	;SHUT DOWN PROCEDURE
		JRST CRPOPJ]	;END MESSAGE AND RETURN
	ILDB	P1,P1		;GET NEXT CHARACTER IN PROCEDURE
	JUMPN	P1,MAIN.2	;STILL MORE, CONTINUE
	SETZM	DOPTR		;END OF PROCEDURE
	MOVE	F,DOFLG		;RESTORE OLD FLAGS ( FL.UPZ )
MAIN.2:	TLNN	F,(FL.UPZ)	;YES, WAS END A CONTROL-Z
	JRST	NXTCOM		;NO, GET ANOTHER COMMAND
	JRST	%EXIT		;YES, EXIT NOW
NULCMD:	TLNN	F,(FL.EOL)	;JUST AN EMPTY LINE
	PUSHJ	P,BADFMT	;NO, COMPLAIN
	JRST	MAIN.1		;THEN FLUSH INPUT LINE
	DEFINE	COMNDS,<
	XLIST
		X	ADD,<put a piece of hardware back on-line>
		X	EXIT,<exit this program>
		X	DO,<canned procedure>
		X	HELP,<types out this text>
		X	REMOVE,<disconnect a piece of hardware>
;;; "SUSPEND" command not available yet
;;;		X	SUSPEND,<put the system to sleep>
	LIST
	SALL
	>

	DEFINE	X(CMD,STR),<<SIXBIT/CMD     />>
CMDTBL:	COMNDS			;GENERATE THE COMMAND TABLE
NUMCMD==<.-CMDTBL>		;NUMBER OF COMMANDS

	DEFINE	X(CMD,STR),<EXP %'CMD>
CMDDSP:	COMNDS			;GENERATE THE DISPATCH TABLE
	EXP	[CAME T1,[SIXBIT/DAMNIT/] ;FORCE THE COMMAND
		 JRST ILLCMD	;NO, TYPE OUT ILLEGAL COMMAND
		 TLO F,(FL.DMN)	;LIGHT THE BIT
		 POP P,(P)	;REMOVE THE CALL
		 JRST MAIN.0]	;GET THE COMMAND FORCED
	EXP	AMBIGC		;TYPE OUT AMBIGUOUS COMMAND

	DEFINE	X(CMD,STR),<EXP [ASCIZ\STR\]>
CMDHLP:	COMNDS			;GENERATE THE HELP DESCRIPTORS
	SUBTTL	Random Error Message Printers for Command Scanner

AMBIGA:	OUTSTR	[ASCIZ/?Ambiguous Argument - "/]
	JRST	ILSXIT		;FINISH ERROR MESSAGE
ILLARG:	OUTSTR	[ASCIZ/?Unknown Argument - "/]
	JRST	ILSXIT		;FINISH ERROR MESSAGE
ILLCPU:	OUTSTR	[ASCIZ/?Illegal CPU/]
	JRST	ERRXIT		;FINISH UP AND RETURN
NOARGS:	TLNN	F,(FL.EOL)	;END OF INPUT
	JRST	BADFMT		;NO, GIVE DIFFERENT ERROR
	OUTSTR	[ASCIZ/?Missing Argument/]
	JRST	ERRXIT		;END LINE AND RETURN
JUNK:	OUTSTR	[ASCIZ/?Junk after end of command - "/]
	SKIPA			;OUTPUT OFFENDING CHARACTER
BADFMT:	OUTSTR	[ASCIZ/?Command Error - "/]
	CAIGE	CH,40		;A REGULAR CHARACTER
	JRST	[OUTCHR ["^"]	;NO, OUTPUT UP-ARROW
		ADDI CH,100	;MAKE A REAL LETTER
		JRST .+1]	;RETURN INLINE
	OUTCHR	CH		;OUTPUT OFFENDING CHARACTER
	JRST	ILLXIT		;FINISH UP AND RETURN
AMBIGC:	OUTSTR	[ASCIZ/?Ambiguous Command - "/]
	SKIPA			;SKIP OVER OTHER MESSAGE
ILLCMD:	OUTSTR	[ASCIZ/?Unknown Command - "/]
ILSXIT:	PUSHJ	P,SIXOUT	;APPEND COMMAND TYPED
ILLXIT:	OUTCHR	[""""]		;CLOSE QUOTES
ERRXIT:	TLO	F,(FL.NCD)	;MARK COMMAND ERROR
CRPOPJ:	OUTSTR	[BYTE (7)15,12,0]
	POPJ	P,
	SUBTTL	The "DO" Command

%DO:	PUSHJ	P,GETSIX	;GET PROCEDURE NAME
	JUMPE	T1,NOARGS	;ERROR IF NONE (MAYBE TRY MIC:MIC.MIC)
	MOVE	T3,[-NUMPRC,,PRCTBL] ;KNOWN PROCEDURES
	PUSHJ	P,TABSRC	;LOOK IT UP
	  JRST	ILLARG		;ILLEGAL
	  JRST	AMBIGA		;AMBIGUOUS
	MOVE	P1,T2		;SAVE OFFSET TO PROCEDURE
	SKIPE	DOPTR		;ONLY 1 LEVEL
	JRST	[OUTSTR [ASCIZ/?Cannot nest procedures/]
		JRST ERRXIT]	;TERMINATE
	MOVE	T1,PRCPTR(P1)	;GET POINTER TO COMMAND STRING
	JUMPG	T1,(T1)		;ROUTINE TO USE IF NOT A BYTE POINTER
	PUSHJ	P,CMDEND	;MUST BE END OF COMMAND STRING
	  JRST	JUNK		;ISN'T, ERROR
	PUSHJ	P,FLUSH		;EAT UP REST OF THIS LINE
	MOVEM	T1,DOPTR	;STORE FOR "GETONE"
	MOVE	P1,PRCTBL(P1)	;GET NAME OF PROCEDURE
	MOVEM	P1,DONAM	;STORE FOR ANY ERROR MESSAGES
	MOVEM	F,DOFLG		;SAVE OLD FLAGS ( FL.UPZ )
	TLZ	F,(FL.UPZ)	;CLEAR ^Z TYPED FLAG
	POPJ	P,		;RETURN TO START PROCEDURE

	DEFINE	COMNDS,<
	XLIST

	X	DUALIZ,<put 1026/1042 back together>,<ADD CPU1@ADD MEMORY 512K TO 1024K@>
	X	HELP,<types out this text>
	X	SPLIT,<10AM split of 1026/1042>,<REMOVE CPU1@REMOVE MEMORY 512K TO 1024K@>
	X	BUG,<BUG>,<DO SPLIT@>

	LIST
	SALL
	>

	DEFINE	X(CMD,STR,TEXT),<<SIXBIT/CMD     />>
PRCTBL:	COMNDS			;GENERATE THE PROCEDURE TABLE
NUMPRC==<.-PRCTBL>		;NUMBER OF PROCEDURES

	DEFINE	X(CMD,STR,TEXT),<EXP [ASCIZ\STR\]>
PRCHLP:	COMNDS			;GENERATE THE HELP DESCRIPTORS

	DEFINE	X(CMD,STR,TEXT),<
		IFNB <TEXT>,<POINT 7,[ASCIZ\TEXT\]>
		IFB <TEXT>,<EXP D%'CMD>
	>
PRCPTR:	COMNDS			;GENERATE BYTE POINTERS TO TEXT
	SUBTTL	The "HELP" Command

%HELP:	OUTSTR	[ASCIZ/Commands are:/]
	MOVEI	P2,CMDHLP	;FIRST HELP TEXT
	SKIPA	P1,[-NUMCMD,,CMDTBL] ;AOBJN FOR MAIN COMMAND TABLE
HLPCOM:	OUTSTR	[ASCIZ/Arguments are:/]

;COMMON PART OF HELP TEXT FOR OTHER COMMAND PROCESSORS
;	P1 = AOBJN TO COMMAND TABLE
;	P2 = ADDRESS OF PARALLEL HELP TEXT TABLE

HELP.1:	OUTSTR	[BYTE (7)15,12,11,0] ;CR,LF,TAB
	MOVE	T1,(P1)		;GET A COMMAND FROM THE TABLE
	PUSHJ	P,SIXOUT	;OUTPUT IT
	OUTCHR	[11]		;ALIGN WITH A TAB
	OUTSTR	@(P2)		;TEXT FOR IT
	AOS	P2		;STEP TO NEXT HELP TEXT
	AOBJN	P1,HELP.1	;AND TRY ANOTHER
	JRST	CRPOPJ		;END LINE AND RETURN

;"DO HELP"

D%HELP:	MOVEI	P2,PRCHLP	;POINT TO HELP TEXT TABLE
	MOVE	P1,[-NUMPRC,,PRCTBL] ;AOBJN TO COMMAND TABLE
	JRST	HLPCOM		;DO HELP COMMAND

;"ADD/REMOVE HELP"

R%HELP:	MOVE	P1,[-NUMRMV,,RMVTBL] ;AOBJN TO COMMAND TABLE
	MOVEI	P2,RMVHLP	;HELP TEXTS
	JRST	HLPCOM		;ENTER COMMON PART OF HELP
	SUBTTL	The "ADD" and "REMOVE" Commands

%ADD:	TLO	F,(FL.ADD)	;REALLY THE ADD COMMAND
%REMOV:	PUSHJ	P,GETSIX	;GET THING TO REMOVE
	JUMPE	T1,NOARGS	;NONE SUPPLIED
	MOVE	T3,[-NUMRMV,,RMVTBL] ;KNOWN ARGUMENTS
	PUSHJ	P,TABSRC	;FIND ARGUMENT
	  JRST	%REM.1		;ILLEGAL, LOOK FURTHER
	  JRST	AMBIGA		;AMBIGUOUS
	PUSHJ	P,@RMVDSP(T2)	;DISPATCH TO IT
	JRST	%REM.2		;AND CHECK IF WE SHOULD BE DETACHED
%REM.1:	SETZ	T2,		;EXACT MATCH REQUIRED
	MOVE	T3,[-6,,[SIXBIT/CPU0  CPU1  CPU2  CPU3  CPU4  CPU5  /]]
	PUSHJ	P,TABSRC	;MAKE TONY HAPPY, TAKE "CPU 1" OR "CPU1"
	  JFCL			;STILL ILLEGAL
	  JRST	ILLARG		;TYPE OUT ILLEGAL ARGUMENT
	MOVE	P2,T2		;PUT OFFSET = CPU NUMBER IN P2
	PUSHJ	P,R%CPU1	;AND GO REMOVE IT
%REM.2:	TLNN	F,(FL.DME)	;IS MY JOB SUPPOSED TO GET DETACHED TOO
	POPJ	P,		;NO, ALL DONE
	HRLZ	T2,MYLINE	;GET LINE NUMBER FOR DETACH
	ATTACH	T2,		;DETACH ME NOW
	  HALT	.		;WHAT
	JRST	%EXIT		;AND GO AWAY


	DEFINE	COMNDS,<
	XLIST
		X	CONTRO,<controller id>
		X	CPU,<CPU number>
		X	HELP,<types out this text>
		X	MEMORY,<addr TO addr>
	LIST
	SALL
	>

	DEFINE	X(CMD,STR),<<SIXBIT/CMD     />>
RMVTBL:	COMNDS			;GENERATE THE ARGUMENT TABLE
NUMRMV==<.-RMVTBL>		;NUMBER OF ARGUMENTS

	DEFINE	X(CMD,STR),<EXP R%'CMD>
RMVDSP:	COMNDS			;GENERATE THE DISPATCH TABLE

	DEFINE	X(CMD,STR),<EXP [ASCIZ\STR\]>
RMVHLP:	COMNDS			;GENERATE THE HELP DESCRIPTORS
;"MEMORY addr1 TO addr2"

R%MEMO:	PUSHJ	P,GETNUM	;GET FIRST ADDRESS
	JUMPL	T1,NOARGS	;MISSING
	MOVE	P1,T1		;REMEMBER FIRST ADDRESS
	PUSHJ	P,GETSIX	;GET GUIDE WORD
	TLNN	F,(FL.EOL)	;IF NOT AT END OF LINE
	JUMPE	T1,NOARGS	;SAY INVALID CHARACTER IF NO COMMAND
	CAME	T1,[SIXBIT/TO/]	;IS IT THERE
	JRST	[OUTSTR [ASCIZ/?Keyword "TO" Missing/]
		JRST ERRXIT]	;GIVE ERROR AND RETURN
	PUSHJ	P,GETNUM	;GET LAST ADDRESS
	JUMPL	T1,NOARGS	;MISSING
	TLNE	F,(FL.POK)	;ADDRESS END WITH "P" OR "K"
	SOSA	P2,T1		;YES, BACK OFF BY ONE LOCATION
	MOVE	P2,T1		;REMEMBER LAST ADDRESS
	PUSHJ	P,CMDEND	;MUST BE THE END OF THE COMMAND
	  JRST	JUNK		;ISN'T, GIVE AN ERROR MESSAGE
RMEMCM:	TLZ	F,(FL.NCD)	;CLEAR "NO CAN DO" ERROR FLAG
	MOVEI	T1,[ASCIZ/SET MEMORY /]
	PUSHJ	P,PTYSTR	;FIRST PART OF COMMAND
	TLNN	F,(FL.ADD)	;ADDING OR REMOVING
	SKIPA	T1,[[ASCIZ/OFF/]]
	MOVEI	T1,[ASCIZ/ON/]
	PUSHJ	P,PTYSTR	;OUTPUT DIRECTION
	MOVEI	T1,[ASCIZ/ FROM #/]
	PUSHJ	P,PTYSTR	;OUTPUT REST
	MOVE	T1,P1		;WHERE TO START
	PUSHJ	P,PTYOCT	;OUTPUT IT
	MOVEI	T1,[ASCIZ/ TO #/]
	PUSHJ	P,PTYSTR	;SOME MORE
	MOVE	T1,P2		;WHERE IT ENDS
	PUSHJ	P,PTYOCT	;IN OCTAL
	JRST	PTYCLF		;END LINE AND WAIT FOR COMPLETION

;"CONTROLLER xxx"

R%CONT:	PUSHJ	P,GETSIX	;GET KONTROLLER TYPE
	JUMPE	T1,NOARGS	;NONE GIVEN
	MOVE	P1,T1		;COPY KONTROLLER WANTED
	PUSHJ	P,CMDEND	;MUST BE THE END OF THE COMMAND
	  JRST	JUNK		;ISN'T, GIVE AN ERROR MESSAGE
	SETZ	T1,		;INDICATE FIRST CALL
CONT.1:	PUSHJ	P,FNDKON	;GET A DISK KONTROLLER
	JUMPE	T1,[MOVE T1,P1	;COPY ONE WE COULDN'T FIND
		JRST ILLARG]	;AND GIVE A MESSAGE
	CAME	T2,P1		;THIS THE ONE WE'RE LOOKING FOR
	JRST	CONT.1		;NO, LOOK FOR ANOTHER
	MOVE	P1,T1		;COPY KONTROLLER ADDRESS
	PUSHJ	P,SETCPU	;SET UP NEEDED CPU DATA BASE
	LDB	T1,[POINT 3,KONCPU(P1),2] ;GET CPU OWNING KONTROLLER
	SKIPL	CPUSTS(T1)	;IS THE CPU OWNING THE KONTROLLER DOWN
	JRST	DKONCM		;REMOVE KONTROLLER AND RETURN
	OUTSTR	[ASCIZ/?CPU owning Controller is down/]
	JRST	ERRXIT		;END MESSAGE AND RETURN

;"CPU n"

R%CPU:	PUSHJ	P,GETNUM	;GET CPU NUMBER
	JUMPL	T1,NOARGS	;ILLEGAL CPU NUMBER
	MOVE	P2,T1		;COPY CPU NUMBER
R%CPU1:	PUSHJ	P,CMDEND	;MUST BE THE END OF THE COMMAND
	  JRST	JUNK		;ISN'T, GIVE AN ERROR MESSAGE
	PUSHJ	P,SETCPU	;SET UP NEEDED CPU DATA BASE
	MOVSI	T1,(1B1)	;NON-EXISTANT BIT
	CAIGE	P2,6		;RANGE CHECK CPU NUMBER
	TDNE	T1,CPUSTS(P2)	;IN RANGE, IS IT REAL
	JRST	ILLCPU		;NOPE
	TLNE	F,(FL.ADD)	;TRYING TO ADD A CPU
	JRST	R%CPUA		;YES, GO DO THAT

;HERE TO REMOVE A CPU

	SKIPGE	CPUSTS(P2)	;CPU ALREADY DOWN
	POPJ	P,		;YES, JUST RETURN NOW
	MOVE	T1,CPUN		;GET NUMBER OF RUNNING CPUS
	CAIN	T1,1		;TRYING TO REMOVE THE LAST REMAINING CPU
	JRST	[OUTSTR [ASCIZ/?You really DON'T want to remove the last one/]
		JRST ERRXIT]	;END OUTPUT AND RETURN
	MOVE	T1,CPUOK	;NUMBER OF ACTUALLY RUNNING CPUS
	CAIN	T1,1		;ONLY ONE OF THOSE LEFT
	JRST	[MOVSI T1,(1B3)	;YES, REMOVING A CPU THAT ISN'T RUNNING IS OK
		TDNE T1,CPUSTS(P2) ;WELL?
		JRST CPU.1	;CPU IS DEAD, OK TO REMOVE IT
		OUTSTR [ASCIZ/?No running CPUs will be left/]
		JRST ERRXIT]	;IF OPERATOR REALLY WANTS THIS, USE "SHUT"
CPU.1:	TLNE	F,(FL.DMN)	;FORCED REMOVE
	JRST	[OUTSTR [ASCIZ/%Bypassing lots of checking/]
		PUSHJ P,CRPOPJ	;PRETTY UP OUTPUT
		JRST CPU.2]	;YES, SKIP CHECKS
	TLO	F,(FL.WAC!FL.CHK) ;SET "WORRY ABOUT CPU",ONLY CHECKING
	PUSHJ	P,RADKON	;CHECK ALL DISK KONTROLLERS
	TLNE	F,(FL.NCD)	;DID SOME CHECK FAIL
	POPJ	P,		;YES, CANNOT REMOVE THE CPU
	PUSHJ	P,LSTDEV	;LOOK FOR LOST DEVICES, GIVE WARNING
	TLZ	F,(FL.CHK)	;NOT CHECKING ANY MORE
	PUSHJ	P,DETJBS	;DETACH JOBS AS APPROPRIATE
CPU.2:	MOVSI	T1,(1B0)	;GET CPU IS DOWN BIT
	IORB	T1,CPUSTS(P2)	;LIGHT IN STATUS BLOCK
	SOS	CPUN		;ONE LESS CPU IN SYSTEM
	TLNN	T1,(1B3)	;WAS CPU'S OK WORD COUNTING BEFORE
	SOS	CPUOK		;YES, BUT IT WILL STOP SOON
	MOVSI	T1,(1B3)	;IN CASE IT WASN'T
	IORM	T1,CPUSTS(P2)	;LIGHT THE BIT NOW
	MOVEI	T1,1B35		;GET BIT FOR CPU0
	LSH	T1,(P2)		;POSITION FOR CORRECT CPU
	ANDCAB	T1,CPURUN	;CLEAR/GET NEW RUNNING CPU MASK
	HRLI	T1,.STCRN	;SET RUN CPUN
	SETUUO	T1,		;SET NEW SPECIFICATION
	  HALT	.		;WHAT
	MOVEI	P3,(P2)		;GET CPU NUMBER
	LSH	P3,1		;*2 FOR GETTABS
	MOVE	T2,[%CCOKP]	;GET THE OK WORD FOR CPU
	ADD	T2,P3		;FOR CPUN
	GETTAB	T2,		;GET IT
	  HALT	.		;WHAT
	JUMPG	T2,CPU.5	;AVOID LOOP, SHUT IT DOWN IF ALREADY DEAD
CPU.3:	MOVE	T2,[%CVJOB]	;JOB CURRENTLY RUNNING ON CPU
	ADD	T2,P3		;FOR CPUN
	GETTAB	T2,		;GET IT
	  HALT	.		;WHAT
	JUMPN	T2,CPU.3	;WAIT FOR CPU TO ONLY RUN NULL JOB
CPU.4:	PUSHJ	P,LSTDEV	;COUNT IOACT DDB'S (FL.CHK IS OFF)
	SKIPE	ACTDEV		;ANY IOACTIVE
	JRST	CPU.4		;YES, WAIT FOR THEM TO STOP
	TLNN	F,(FL.DMN)	;DONT DETACH IF FORCED REMOVAL
	PUSHJ	P,RADKON	;GO AND DETACH ALL THE UNITS NOW
CPU.5:	MOVEI	T2,1B18(P2)	;GET CPU NUMBER, FLAG AS REMOVE
	HRLI	T2,.STCDN	;SET "DOWN" CPUN
	SETUUO	T2,		;SHUT IT DOWN
	  HALT	.		;WHAT
CPU.6:	MOVE	T2,[%CCOKP]	;GET THE OK WORD FOR CPU
	ADD	T2,P3		;FOR CPUN
	GETTAB	T2,		;GET IT
	  HALT	.		;WHAT
	JUMPLE	T2,CPU.6	;WAIT FOR IT TO STICK ITS HEAD IN THE SAND
	MOVE	T1,CPUN		;HOW MANY CPU'S ARE LEFT
	CAIE	T1,1		;ONLY 1 REMAINING
	JRST	CPU.7		;NO, JUST MAKE THE CPU GO AWAY
	MOVSI	T1,.STCSB	;OK TO CACHE MONITOR DATA BASE NOW
	HRRI	T1,1B35		;LIGHT BIT TO TURN ON CACHE
	SETUUO	T1,		;SINCE ONLY 1 PROCESSOR LEFT
	  JFCL			;OK, MUST BE A KI
CPU.7:	MOVSI	T1,(1B2)	;"CPU DETACHED" BIT
	TDNE	T1,CPUSTS(P2)	;IS THE CPU ALREADY DETACHED
	POPJ	P,		;YES, RETURN NOW
	IORM	T1,CPUSTS(P2)	;SAY DETACHED NOW
	MOVEI	T1,[ASCIZ/DETACH CPU/]
	PUSHJ	P,PTYSTR	;OUTPUT DETACH COMMAND
	MOVE	T1,P2		;THE CPU NUMBER
	PUSHJ	P,PTYOCT	;OUTPUT THAT TOO
	JRST	PTYCLF		;END THE LINE AND RETURN

;HERE TO ADD A CPU

R%CPUA:	SKIPL	CPUSTS(P2)	;IS IT ALREADY UP
	JRST	CPUA.2		;YES, GO LET IT IN (UNDO OPSER'S ":SET RUN")
	MOVSI	T1,(1B0!1B3)	;CPU IS DOWN BIT
	ANDCAM	T1,CPUSTS(P2)	;NOT ANY MORE
	AOS	CPUN		;ONE MORE CPU RUNNING
	AOS	CPUOK		;ONE MORE COUNTING
	MOVSI	T1,.STCSB	;MUST UNCACHE MONITOR DATA BASE
	SETUUO	T1,		;DO IT (1B35 = 0)
	  JFCL			;OK, MUST BE A KI
	MOVSI	T1,(1B2)	;CPU DETACHED BIT
	TDNN	T1,CPUSTS(P2)	;IS IT
	JRST	CPUA.1		;NO, LET IT IN
	ANDCAM	T1,CPUSTS(P2)	;CLEAR DETACHED CPU BIT
	MOVEI	T1,[ASCIZ/ATTACH CPU/]
	PUSHJ	P,PTYSTR	;OUTPUT ATTACH COMMAND
	MOVE	T1,P2		;COPY CPU NUMBER
	PUSHJ	P,PTYOCT	;WHICH ONE TO ATTACH
	PUSHJ	P,PTYCLF	;END THE COMMAND
	TLNE	F,(FL.NCD)	;DID IT WORK
	POPJ	P,		;NO, RETURN NOW
CPUA.1:	MOVE	T1,P2		;GET CPU NUMBER ( 1B18 OFF = ADD THIS ONE )
	HRLI	T1,.STCDN	;SET CPU UP ( OR ALLOWED TO BE UP )
	SETUUO	T1,		;i.e. LET THIS CPU IN
	  HALT	.		;WHAT
CPUA.2:	MOVEI	T1,1B35		;GET A BIT FOR CPU0
	LSH	T1,(P2)		;POSITION FOR CPUN
	IORB	T1,CPURUN	;ADD/GET NEW RUNNING CPU MASK
	HRLI	T1,.STCRN	;NOW ALLOW IT TO RUN JOBS
	SETUUO	T1,		;OTHERWISE WHY BOTHER ADDING IT
	  HALT	.		;WHAT
	POPJ	P,		;ADDING IS A LOT EASIER THAN REMOVING
	SUBTTL	The "SUSPEND" Command

%SUSPE:	TLNE	F,(FL.DMN)	;ONLY WORKS IF YOU MEAN IT
	PUSHJ	P,CMDEND	;NO ARGUMENTS
	  JRST	JUNK		;COMPLAIN
	MOVE	T1,[.RCROJ,,T2]	;SET TO RUN ONLY 1 JOB
	MOVEI	T2,2		;2 WORD ARGUMENT BLOCK
	SETZ	T3,		;JOB NUMBER 0 = ALLOW ALL USERS
	RECON.	T1,		;DO THE UUO
	  JRST	[OUTSTR [ASCIZ/?No System Sleep support in the monitor/]
		JRST ERRXIT]	;END MESSAGE AND RETURN
	MOVEI	T1,[ASCIZ/SEND ALL Expect an interruption of service/]
	PUSHJ	P,FRCOLF	;OUTPUT THE MESSAGE, END STRING
	MOVEI	T1,^D5		;GIVE IT TIME TO TYPE OUT
	SLEEP	T1,		;WAIT
	MOVE	P1,SYSSIZ	;FIRST WORD OUTSIDE THE MONITOR
SUSP.3:	MOVE	P2,P1		;COPY ADDRESS
	ADDI	P2,<MBTPGS*1000>-1 ;LAST LOCATION NEEDED FOR MONBTS
	CAMLE	P2,NWCORE	;OFF THE TOP OF MEMORY
	HALT	.		;WHAT
	PUSHJ	P,RMEMCM	;SET SOME MEMORY OFF-LINE
	TLNE	F,(FL.NCD)	;DID IT WORK
	JRST	[ADDI P1,1000	;NO, TRY A DIFFERENT PLACE
		JRST SUSP.3]	;TRY AGAIN
	MOVE	T1,[3,,T2]	;SET UP FOR POKE
	MOVEI	T2,MBTCOM-MONITR ;WHERE TO POKE ADDRESS OF COMM REGION
	MOVE	T3,MBTCOM	;GET OLD VALUE
	MOVE	T4,P1		;NEW VALUE = WHERE COMM REGION IS
	LSH	T4,-^D9		;AS A PAGE NUMBER
	POKE.	T1,		;STORE FOR MONBTS
	  HALT	.		;WHAT
	TLO	F,(FL.NIN)	;DON'T LET THE OPERATOR ^C OUT OF THIS
	MOVE	T1,[.RCROJ,,T2]	;SET TO RUN ONLY ME NOW
	MOVEI	T2,2		;2 WORD ARGUMENT BLOCK
	MOVE	T3,MYJOBN	;ONLY ME
	RECON.	T1,		;DO IT
	  HALT	.		;WHAT
	MOVEI	T1,^D5		;ALLOW SYSTEM TO SETTLE DOWN
	SLEEP	T1,		;WAIT
	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,(1B4)	;OR THE BOOT CPU
	JRST	SUSP.2		;IGNORE THIS ONE
	MOVEI	T2,1B19(T1)	;GET CPU NUMBER AND FLAG = SUSPEND THYSELF
	HRLI	T2,.STCDN	;SET "DOWN" CPU FUNCTION
	SETUUO	T2,		;MAKE IT GO AWAY
	  HALT	.		;WHAT
SUSP.2:	AOBJN	T1,SUSP.1	;DO ALL CPUS THAT WILL REMAIN AFTER SUSPEND
	MOVEI	T1,^D5		;ALLOW SYSTEM TO SETTLE DOWN
	SLEEP	T1,		;WAIT
	MOVE	T1,[.RCSLP,,0]	;FUNCTION SUSPEND
	RECON.	T1,		;"COMPUTUS INTERRUPTUS"
	  CAIA			;DUMP MUST HAVE FAILED, LET THE WORLD BACK IN
	JRST	SUSP.4		;JIM ALREADY TOLD EVERYBODY THAT WE ARE BACK
	MOVEI	T1,[ASCIZ/SEND ALL System resumed/]
	PUSHJ	P,FRCOLF	;TELL WORLD THE SYSTEM IS BACK
SUSP.4:	MOVE	T1,[.RCROJ,,T2]	;SET TO RUN ONLY 1 JOB
	MOVEI	T2,2		;2 WORD ARGUMENT BLOCK
	SETZ	T3,		;JOB NUMBER 0 = ALLOW ALL USERS
	RECON.	T1,		;DO THE UUO
	  HALT	.		;WHAT
	TLO	F,(FL.ADD)	;MUST RETURN THE MEMORY WE STOLE FOR MONBTS
	JRST	RMEMCM		;PUT BACK ON-LINE AND RETURN TO COMMAND LEVEL
	SUBTTL	Some Input Subroutines

;SUBROUTINE TO INPUT A SINGLE CHARACTER INTO CH
;	PUSHJ	P,GETONE
;	  RETURN HERE IF A SPECIAL CHARACTER
;	  RETURN HERE IF A NUMBER
;	  RETURN HERE IF A LETTER
;IF FL.RSC IS ON, THIS GETS THE LAST CHARACTER (TERMINATOR OF PREVIOUS)

GETONE:	TLNE	F,(FL.EOL)	;END OF LINE SEEN
	JRST	GETO.2		;YES, RETURN LINE FEED
	TLZE	F,(FL.RSC)	;WANT OLD CHARACTER AGAIN
	JRST	[MOVE CH,SAVCHR	;YES, GET SAVED CHARACTER
		JRST GETO.B]	;AND PROCESS IT
	SKIPE	DOPTR		;DOING A PROCEDURE
	JRST	[ILDB CH,DOPTR	;GET A CHARACTER
		CAIN CH,"@"	;CRLF REQUESTED
		JRST GETO.3	;YES, GET ONE
		OUTCHR CH	;ECHO IT SINCE OPERATOR DIDN'T TYPE IT
		JUMPN CH,GETO.A	;RETURN IN LINE IF A REAL CHARACTER
		HALT .]		;SOME BODY DIDN'T ADD PROCEDURE CORRECTLY
	INCHWL	CH		;NO, GET A CHARACTER
GETO.A:	MOVEM	CH,SAVCHR	;SAVE FOR RESCAN
GETO.B:	JUMPE	CH,GETONE	;IGNORE NULLS
	CAIN	CH,15		;CARRIAGE RETURN ??
	JRST	GETONE		;YES, PITCH THOSE
	CAIE	CH,7		;^G ??
	CAIN	CH,13		;^K ??
	JRST	GETO.1		;YES, MARK END OF TEXT AND RETURN LINE FEED
	CAIN	CH,14		;^L ??
	JRST	GETO.1		;YES, MARK END OF TEXT AND RETURN LINE FEED
	CAIE	CH,12		;LINE FEED ??
	CAIN	CH,33		;ALTMODE ??
	JRST	GETO.1		;YES, MARK END OF TEXT AND RETURN LINE FEED
	CAIN	CH,32		;^Z ??
	JRST	GETO.0		;YES, LIGHT LOTS OF BITS FOR ^Z
	CAIN	CH,11		;A TAB
	SKIPA	CH,[" "]	;YES, CONVERT TO SPACE
	CAIN	CH," "		;A SPACE
	POPJ	P,		;YES, TAKE "SPECIAL" RETURN
	CAIE	CH,"!"		;LOOK FOR COMMENTS
	CAIN	CH,";"		;...
	JRST	GETO.2		;FAKE AN END OF LINE
	CAIG	CH,"9"		;LOOK FOR DIGITS
	CAIGE	CH,"0"		;...
	SKIPA			;NOT A DIGIT
	JRST	CPOPJ1		;TAKE "DIGIT" EXIT
	CAIG	CH,"Z"+40	;LOWER CASE LETTER
	CAIGE	CH,"A"+40	;...
	SKIPA			;NOT LOWER CASE
	SUBI	CH," "		;CONVERT TO UPPER CASE
	CAIG	CH,"Z"		;NOW DO LETTER CHECK
	CAIGE	CH,"A"		;...
	POPJ	P,		;MUST BE A SPECIAL
CPOPJ2:	AOS	(P)		;TAKE "LETTER" EXIT
CPOPJ1:	AOS	(P)		;LOTS OF SKIP RETURNS
CPOPJ:	POPJ	P,		;RETURN

GETO.0:	TLO	F,(FL.UPZ)	;MARK ^Z FOR JMF
GETO.1:	TLO	F,(FL.ETX)	;MARK REAL END OF TEXT
GETO.2:	TLO	F,(FL.EOL)	;LIGHT FAKE END OF LINE
	MOVEI	CH,12		;RETURN LINE FEED
	POPJ	P,		;TAKE "SPECIAL" RETURN
GETO.3:	PUSHJ	P,CRPOPJ	;END ECHOING WITH CR,LF
	JRST	GETO.1		;AND MARK LINE AS COMPLETE


;SUBROUTINE TO SEARCH A TABLE FOR A COMMAND OR ARGUMENT
;CALL:	T1 = ITEM IN SIXBIT
;	T2 = MASK FOR CHARACTERS TYPED
;	T3 = AOBJN POINTER FOR TABLE TO SEARCH
;RTNS:	CPOPJ  = NOT IN THE TABLE
;	CPOPJ1 = AMBIGUOUS
;	CPOPJ2 = FOUND IT
;RETURNS T1 INTACT, T2 = RELATIVE INDEX FOR COMMAND, CLOBBERS T3,T4,T5

TABSRC:	MOVEI	T4,(T3)		;SAVE TABLE START ADDRESS
	PUSH	P,T2		;SAVE MASK TO USE
	SETZ	T2,		;CLEAR FOUND INDICATOR
TABS.1:	MOVE	T5,(T3)		;GET AN ITEM
	CAMN	T1,T5		;EXACT MATCH
	JRST	[MOVEI T2,(T3)	;YES, MARK WHERE WE FOUND IT
		JRST TABS.3]	;AND EXIT
	ANDCM	T5,(P)		;MASK TO AS MANY CHARS AS IN T1
	CAME	T1,T5		;NOW DO WE HAVE A MATCH
	JRST	TABS.2		;NO, TRY NEXT ENTRY IN TABLE
	JUMPN	T2,[POP P,(P)	;IF ALREADY HAVE 1 MATCH
		JRST CPOPJ1]	;GIVE AMBIGUOUS RETURN
	MOVEI	T2,(T3)		;SAVE ADDRESS OF THIS MATCH
TABS.2:	AOBJN	T3,TABS.1	;AND LOOK SOME MORE
TABS.3:	POP	P,(P)		;CLEAN STACK NOW
	JUMPE	T2,CPOPJ	;RETURN IF NEVER FOUND ONE
	SUBI	T2,(T4)		;COMPUTE RELATIVE OFFSET OF COMMAND
	JRST	CPOPJ2		;AND GIVE LOTS OF SKIP RETURNS
;SUBROUTINE TO EAT UP THE REST OF THE INPUT LINE

FLUSH:	TLZ	F,(FL.EOL!FL.RSC) ;CLEAR SCANNER FLAGS
	TLNE	F,(FL.ETX)	;REACHED END OF LINE YET
	POPJ	P,		;YES, RETURN
	PUSHJ	P,GETONE	;GET A CHARACTER
	  JFCL			;IGNORE VARIOUS RETURNS
	  JFCL			;...
	JRST	FLUSH		;NOW LOOK FOR END OF LINE

;HERE WHEN OPERATOR TYPES ^C AT US, IGNORE IT IF FL.NIN IS ON, ELSE EXIT

CCTRAP:	TLNE	F,(FL.NIN)	;DO WE HAVE THE SYSTEM LOCKED UP
	DEBRK.			;YES, IGNORE ^C^C
%EXIT:	MONRT.			;OK TO STOP, STOP
	JRST	CONFIG		;RESTART PROGRAM ON CONTINUE

;SUBROUTINE TO ENSURE THAT NO GARBAGE FOLLOWS LAST ARGUMENT OF A COMMAND
;CALLED BY VARIOUS COMMAND PROCESSORS AFTER READING LAST ARGUMENT BUT BEFORE
;	EXECUTING THE COMMAND ITSELF.
;RTNS:	CPOPJ	JUNK AFTER COMMAND
;	CPOPJ1	NOTHING BUT END OF LINE

CMDEND:	TLO	F,(FL.RSC)	;GET LAST ARGUMENT TERMINATOR
CMDE.1:	PUSHJ	P,GETONE	;GET A CHARACTER
	  JRST	CMDE.2		;SPECIAL, CHECK IT OUT
	  POPJ	P,		;NUMBER, JUNK
	  POPJ	P,		;SPECIAL, JUNK
CMDE.2:	CAIN	CH," "		;SPACE AFTER COMMAND
	JRST	CMDE.1		;ALLOW SPACES BEFORE ANY COMMENTS
	TLNE	F,(FL.EOL)	;END OF LINE
	AOS	(P)		;YES, NO JUNK
	POPJ	P,		;RETURN

;SUBROUTINE TO GET A SIXBIT WORD FROM THE INPUT STREAM INTO "T1"
;	ALSO RETURNS MASK FOR POSSIBLE COMMAND IN "T2"
;CLOBBERS T3

GETSIX:	MOVE	T3,[POINT 6,T1]	;PRIME THE BYTE POINTER
	SETZ	T1,		;AND THE RECEIVING WORD
	SETO	T2,		;AND THE EVENTUAL COMMAND MASK
	TLO	F,(FL.RSC)	;START WITH LAST TERMINATOR
GETS.1:	PUSHJ	P,GETONE	;GET A CHARACTER
	  JRST	GETS.2		;SPECIAL, GO LOOK
	  JRST	[JUMPE T1,CPOPJ	;NUMBERS CANNOT BE THE FIRST IN A COMMAND
		JRST .+1]	;BUT CAN BE PARTS OF IT (e.g. CPU0, RPE4)
	SUBI	CH,40		;TO SIXBIT
	TLNE	T3,770000	;GOT THEM ALL YET
	IDPB	CH,T3		;NO, INSERT NEW CHARACTER
	LSH	T2,-6		;ADJUST MASK FOR NEW CHARACTER
	JRST	GETS.1		;AND GET ANOTHER
GETS.2:	CAIN	CH," "		;STOP ON A BLANK
	JUMPE	T1,GETS.1	;YES, IGNORE LEADING BLANKS
	POPJ	P,		;RETURN WITH T1,T2 SET UP
;SUBROUTINE TO GET A NUMERIC ARGUMENT FROM THE INPUT STREAM INTO "T1"
;RTNS:	T1 .LT. 0 IF NO DIGITS FOUND
;CLOBBERS T2,T3

GETNUM:	SETO	T1,		;NO DIGITS SEEN YET
	MOVEI	T2,^D10		;DEFAULT RADIX
	TLO	F,(FL.RSC)	;START WITH LAST TERMINATOR
	TLZ	F,(FL.POK)	;CLEAR "P" OR "K" SEEN
GETN.1:	PUSHJ	P,GETONE	;GET A CHARACTER
	  JRST	GETN.2		;A SPECIAL, CHECK IT OUT
	  SKIPA			;A NUMBER, INCLUDE IT
	  JRST	GETN.3		;A LETTER, CHECK FOR K OR P
	MOVEI	T3,-"0"(CH)	;CONVERT TO ASCII
	CAIL	T3,(T2)		;RADIX CHECK
	JRST	GETN.4		;ILLEGAL ( NO 8'S OR 9'S IN OCTAL )
	SKIPGE	T1		;ANY DIGITS SO FAR
	TDZA	T1,T1		;NO, THIS IS THE FIRST
	IMULI	T1,(T2)		;"SHIFT" PREVIOUS SUM
	ADDI	T1,(T3)		;AND INCLUDE THE NEW DIGIT
	JRST	GETN.1		;GET MORE
GETN.2:	CAIN	CH,"#"		;INPUTTING OCTAL
	JRST	[JUMPGE T1,GETN.4 ;CAN'T CHANGE RADIX IN THE MIDDLE OF THE STREAM
		CAIN T2,^D8	;ALREADY DONE THIS ONCE
		POPJ P,		;YES, CAN'T TYPE TWO OF THEM
		MOVEI T2,^D8	;NEW RADIX
		JRST GETN.1]	;AND GET ANOTHER DIGIT
	CAIN	CH," "		;A BLANK
	JUMPL	T1,GETN.1	;YES, IGNORE LEADING BLANKS ALWAYS
	POPJ	P,		;STOP ON A SPECIAL OR OTHER BLANKS
GETN.3:	JUMPL	T1,CPOPJ	;ERROR IF NO DIGITS YET
	SETO	T3,		;FLAG INVALID LETTER
	CAIN	CH,"K"		;ALLOW "K"
	MOVEI	T3,^D10		;*1024 IF "K"
	CAIN	CH,"P"		;ALLOW "P"
	MOVEI	T3,^D9		;*512 IF "P"
	JUMPL	T3,GETN.4	;ILLEGAL IF NEITHER
	TLO	F,(FL.POK)	;LIGHT "P" OR "K" SEEN
	LSH	T1,(T3)		;ADJUST APPROPRIATELY
	SETZM	SAVCHR		;EAT UP THE "P" OR "K"
	POPJ	P,		;RETURN WITH NUMBER IN T1

GETN.4:	SETO	T1,		;ANYTHING ILLEGAL, RETURN -1
	POPJ	P,		;RETURN
	SUBTTL	Some Output Subroutines

;SUBROUTINE TO OUTPUT SIXBIT VALUE IN AC "T1"

SIXOUT:	MOVE	T2,T1		;COPY SIXBIT OVER
SIXOU1:	JUMPE	T2,CPOPJ	;ALL DONE AT END OF SIXBIT WORD
	SETZ	T1,		;CLEAR RECEIVING AC
	LSHC	T1,6		;BRING IN A CHARACTER
	MOVEI	T1," "(T1)	;TO ASCII
	OUTCHR	T1		;OUTPUT IT
	JRST	SIXOU1		;AND GET THEM ALL

;SUBROUTINE TO OUTPUT "T1" IN CORRECT RADIX

DECOUT:	SKIPA	T3,[^D10]	;GET RADIX
OCTOUT:	MOVEI	T3,10		;GET RADIX
OCTOU1:	IDIVI	T1,(T3)		;STRIP DIGIT
	PUSH	P,T2		;SAVE IT
	SKIPE	T1		;WAS THAT ALL
	PUSHJ	P,OCTOU1	;NO, GET ANOTHER
	POP	P,T1		;RESTORE CHARACTER
	MOVEI	T1,"0"(T1)	;TO ASCII
	OUTCHR	T1		;OUTPUT IT
	POPJ	P,		;AND RETURN

;SUBROUTINE TO OUTPUT THE ASCIZ STRING POINTED TO BY "T1" ON THE SYSTEM TTY

FRCOLF:	PUSHJ	P,FRCOUT	;OUTPUT STRING AND THEN <CR><LF>
FRCCLF:	MOVEI	T1,[BYTE (7)15,12,0] ;A <CR><LF> PAIR
FRCOUT:	HRRM	T1,FRCSTR	;STORE IN TRMOP. BLOCK
	MOVE	T1,[3,,FRCTYP]	;FOR TRMOP.
	TRMOP.	T1,		;OUTPUT THE STRING
	  HALT	.		;WHAT
	POPJ	P,		;AND RETURN
	SUBTTL	Some PTY Subroutines

;SUBROUTINE TO OUTPUT AN ASCIZ STRING TO THE PTY

PTYSTR:	MOVE	T2,T1		;MOVE STRING ADDRESS
	TLO	T2,(POINT 7,0)	;MAKE A BYTE POINTER
PTYST1:	ILDB	T1,T2		;GET A CHARACTER
	JUMPE	T1,CPOPJ	;DONE ON A NULL
	PUSHJ	P,PTYPUT	;OUTPUT IT
	JRST	PTYST1		;AND LOOP

;SUBROUTINE TO STICK 1 CHARACTER INTO THE PTY OUTPUT BUFFER

	OUTPUT	PTY,		;HERE WHEN FULL
PTYPUT:	SOSGE	PTYOBF+.BFCTR	;MAKE ROOM - MAKE ROOM
	JRST	.-2		;HACK, DUMP THE BUFFER
	IDPB	T1,PTYOBF+.BFPTR ;STICK THE NEW CHARACTER
IFE FTPTYDEBUG,<TLNE F,(FL.NCD)> ;ERROR SEEN?
	OUTCHR	T1		;SHOW THE CHARACTER
	POPJ	P,		;ALL DONE

;SUBROUTINE TO STUFF "T1" DOWN THE PTY IN CORRECT RADIX

PTYDEC:	SKIPA	T3,[^D10]	;GET RADIX
PTYOCT:	MOVEI	T3,10		;GET RADIX
PTYOC1:	IDIVI	T1,(T3)		;STRIP A DIGIT
	PUSH	P,T2		;SAVE IT
	SKIPE	T1		;DONE YET
	PUSHJ	P,PTYOC1	;NO, GET ANOTHER
	POP	P,T1		;GET DIGIT
	MOVEI	T1,"0"(T1)	;TO ASCII
	JRST	PTYPUT		;OUTPUT IT AND RETURN (MAYBE)

;SUBROUTINE TO OUTPUT "T1" IN SIXBIT TO THE PTY

PTYSIX:	MOVE	T2,T1		;COPY VALUE
PTYSI1:	JUMPE	T2,CPOPJ	;DONE AT END OF SIXBIT WORD
	SETZ	T1,		;CLEAR RECEIVING AC
	LSHC	T1,6		;SHIFT IN A CHARACTER
	MOVEI	T1," "(T1)	;CONVERT TO ASCII
	PUSHJ	P,PTYPUT	;STUFF INTO PTY BUFFER
	JRST	PTYSI1		;AND GET ANOTHER
;SUBROUTINE TO END THE CURRENT LINE AND WAIT FOR PTY TO GO HUNGRY AGAIN

PTYOLF:	PUSHJ	P,PTYSTR	;STRING FIRST, THEN <CR><LF>, THEN WAIT
PTYCLF:	MOVEI	T1,[BYTE (7)15,12,0] ;A CRLF
	PUSHJ	P,PTYSTR	;ADD THAT TO THE BUFFER
	OUTPUT	PTY,		;DUMP THE BUFFER
PTYCL1:	MOVEI	T1,PTY		;CHANNEL USED
	JOBSTS	T1,		;GET ITS STATUS
	  HALT	.		;WHAT
	TLNN	T1,(JB.UOA)	;SOMETHING TO READ
	JRST	[TLNE T1,(JB.UDI) ;NO, PTY READY FOR MORE
		 POPJ P,	  ;YES, FINALLY RETURN
		 MOVE T1,[HB.RPT+^D500] ;NO 1/2 SECOND NAP
		 HIBER T1,	  ;GIVE IT A CHANGE TO MAKE SOME OUTPUT
		   HALT .	  ;WHAT
		 JRST PTYCL1]	  ;GO BACK AND WAIT
	INPUT	PTY,		;FILL ONE BUFFER
PTYCL2:	PUSHJ	P,PTYGET	;SNARF UP A CHARACTER
	  JRST	PTYCL1		;NO MORE, GO BACK AND WAIT
	CAIN	T1,"?"		;AN ERROR MESSAGE COMING AT US
	TLO	F,(FL.NCD)	;YES, LIGHT BIT
IFE FTPTYDEBUG,<TLNE F,(FL.NCD)> ;ERROR SEEN?
	OUTCHR	T1		;SHOW THE CHARACTER
	JRST	PTYCL2		;GO BACK AND GET ANOTHER CHARACTER

;SUBROUTINE TO GET 1 CHARACTER FROM THE PTY (CALLER MUST FILL BUFFER)
;RTNS:	CPOPJ	BUFFER IS EMPTY
;	CPOPJ1	GOT ONE IN "T1"

PTYGET:	SOSGE	PTYIBF+.BFCTR	;ANYTHING THERE
	POPJ	P,		;NO, RETURN NOW
	ILDB	T1,PTYIBF+.BFPTR ;GET ONE
	JUMPN	T1,CPOPJ1	;RETURN WITH IT
	JRST	PTYGET		;PITCH NULLS
	SUBTTL	Some Random Subroutines

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

DETJBS:	TLZ	F,(FL.HEA)	;NEW HEADING REQUIRED
	GTTAB	T1,%CNSJN	;NUMBER OF JOBS IN THE SYSTEM
	MOVNI	T1,-1(T1)	;FORM AOBJN FOR JOBS
	HRLZS	T1		;...
DETJ.1:	SKIPN	T2,@TTYTAB	;GET TTY DDB FOR JOB
	JRST	DETJ.3		;ISN'T ANY, TRY NEXT
	MOVE	T3,DEVNAM(T2)	;SIXBIT TTY NAME
	TLNN	T3,-1		;IS IT ALREADY DETACHED
	JRST	DETJ.3		;YES, DON'T OVERKILL
	HRRZ	T2,DDBLDB(T2)	;STEP TO LDB FOR LINE
	MOVE	T3,T2		;COPY LDB ADDRESS
	ADD	T3,BYTOFS	;WORD CONTAINING CPU NUMBER
	PEEK	T3,		;GET IT
	LDB	T3,[POINT 3,T3,24] ;GET CPU OWNING TERMINAL
	CAME	T3,P2		;ON THE CPU BEING REMOVED
	JRST	DETJ.3		;NO, LEAVE IT ALONE
	ADD	T2,DCHOFS	;GET LINE CHARACTERISTICS WORD
	PEEK	T2,		;LDB'S ARE NOT IN THE SPY SEG
	TRNE	T2,LDRPTY!LDRREM ;IGNORE PTY AND NETWORK LINES
	JRST	DETJ.3		;TRY ANOTHER LINE
	ANDI	T2,777		;ISOLATE LINE NUMBER FOR JOB
	CAMN	T2,MYLINE	;IS THIS ME
	JRST	[TLO F,(FL.DME)	;YES, MARK TO DO THIS ONE LATER
		JRST DETJ.2]	;AND RESUME
	HRLZS	T2		;IN LEFT HALF FOR DETACH
	ATTACH	T2,		;DETACH THE JOB
	  HALT	.		;WHAT
DETJ.2:	TLON	F,(FL.HEA)	;NEED A HEADING
	OUTSTR	[ASCIZ/% Detaching Jobs:/]
	OUTCHR	[" "]		;SPACE BETWEEN JOB NUMBERS
	PUSH	P,T1		;SAVE AOJBN
	HRRZS	T1		;ISOLATE JOB NUMBER
	PUSHJ	P,DECOUT	;OUTPUT IT
	POP	P,T1		;RESTORE
DETJ.3:	AOBJN	T1,DETJ.1	;CONTINUE FOR ALL JOBS IN THE SYSTEM
	TLNE	F,(FL.HEA)	;HAVE TO CLEAN UP
	JRST	CRPOPJ		;YES
	POPJ	P,		;NO, RETURN
;SUBROUTINE TO LOOK FOR AND REPORT ANY DEVICES THAT WILL BE LOST
;CALL:	P2 = CPU BEING REMOVED
;RTNS:	P1 = CLOBBERED
;	COUNTS ACTDEV FOR EACH IOACT DDB

LSTDEV:	TLZ	F,(FL.HEA)	;NEW HEADING FOR THIS LOOP
	SETZM	ACTDEV		;CLEAR COUNT OF ACTIVE DEVICES
	SKIPA	P1,DEVLST	;POINT TO FIRST DDB
LSTD.1:	HLRZ	P1,DEVSER(P1)	;STEP TO NEXT DDB
LSTD.2:	JUMPE	P1,CPOPJ	;DONE WITH OTHER DDBS
	CAIL	P1,MONITR	;THIS DDB IN THE MONITORS HIGH SEGMENT
	JRST	[MOVEI P1,DEVSER-MONITR(P1) ;YES, MUST BE "DSKDDB"
		PEEK P1,	;SO JUST GET ADDRESS OF NEXT DDB
		HLRZ P1,P1	;SINCE NOBODY CAN OWN THIS ONE (NOT WRITTABLE)
		JRST LSTD.2]	;AND LOOK SOME MORE
	LDB	T2,[POINT 6,DEVTYP(P1),9] ;GET DEVICE TYPE
	CAIE	T2,.TYPTY	;DON'T CARE ABOUT PTY'S
	CAIN	T2,.TYDSK	;OR DSK'S
	JRST	LSTD.1		;TRY NEXT DDB
	CAIN	T2,.TYMPX	;OR MPX'S
	JRST	LSTD.1		;TRY NEXT DDB
	LDB	T1,[POINT 3,DEVCPU(P1),2] ;GET CPU OWNING THE DEVICE
	CAME	T1,P2		;SAME AS CPU BEING REMOVED
	JRST	LSTD.1		;TRY NEXT DDB
	LDB	T1,[POINT 9,DEVJOB(P1),35] ;GET JOB NUMBER USING DEVICE
	JUMPE	T1,LSTD.1	;OK, NOBODY USING IT
	CAIN	T2,.TYTTY	;IS THIS SOMEBODYS TTY
	JRST	[CAMN P1,@TTYTAB ;CHECK IT CONTROLLS A JOB OR JUST INITED
		JRST LSTD.1	;CONTROLLING, WILL DETACH JOB IN ANOTHER ROUTINE
		JRST LSTD.3]	;GIVE WARNING
	MOVSI	T2,(DCVNET)	;GET "NETWORK" BIT
	TDNE	T2,DEVCHR(P1)	;IS THIS A NETWORK DEVICE
	JRST	LSTD.1		;TRY NEXT DDB
	MOVEI	T2,IOACT	;"IO IN PROGRESS" BIT
	TDNE	T2,DEVIOS(P1)	;IS IT
	AOS	ACTDEV		;YES, COUNT NUMBER OF ACTIVES DEVICES
LSTD.3:	TLNN	F,(FL.CHK)	;WANT OUTPUT OR JUST ADDING UP ACTDEV
	JRST	LSTD.1		;JUST ADDING, GET NEXT DDB
	TLON	F,(FL.HEA)	;HEADING GIVEN
	PUSHJ	P,[OUTSTR [ASCIZ/% Following Jobs will lose devices:/]
		JRST CRPOPJ]	;OUTPUT HEADING
	OUTCHR	[11]		;ALIGN OUTPUT
	PUSHJ	P,DECOUT	;OUTPUT JOB NUMBER
	OUTSTR	[ASCIZ/ has /]	;PRETTY IT UP
	MOVE	T1,DEVNAM(P1)	;GET DEVICE OWNED
	PUSHJ	P,SIXOUT	;OUTPUT IT
	PUSHJ	P,CRPOPJ	;ADD CRLF
	JRST	LSTD.1		;AND LOOK AT ANOTHER DEVICE
;SUBROUTINE TO REMOVE ALL DISK KONTROLLERS ON A CPU
;CALL:	P2 = CPU TO WORRY ABOUT (FL.WAC ALREADY ON)
;RTNS:	P1 = CLOBBERED
;	CALLS DKONCM SO FL.NCD MAY BE LIT

RADKON:	SETZ	P1,		;INDICATE FIRST CALL
RADK.1:	MOVE	T1,P1		;GET PREVIOUS KONTROLLER ADDRESS
	PUSHJ	P,FNDKON	;FIND NEXT DISK KONTROLLER
	JUMPE	T1,CPOPJ	;DONE WITH DISK KONTROLLERS
	MOVE	P1,T1		;COPY KONTROLLER ADDRESS
	LDB	T1,[POINT 3,KONCPU(P1),2] ;GET CPU OWNING KONTROLLER
	CAMN	T1,P2		;THIS ON THE CPU BEING REMOVED
	PUSHJ	P,[TLNE F,(FL.CHK) ;CHECKING OR DOING
		   JRST DKONCM	;CHECKING
		   JRST DKONRM]	;REMOVING
	JRST	RADK.1		;DO NEXT KONTROLLER

;SUBROUTINE TO STEP THROUGH THE DISK KONTROLLER DATA BLOCKS
;CALL:	T1 = PREVIOUS KONTROLLER OR 0 FOR FIRST TIME
;RTNS:	T1 = NEXT KONTROLLER OR 0 IF NO MORE
;	T2 = SIXBIT NAME OF KONTROLLER

FNDKON:	JUMPE	T1,[MOVE T1,FIRDSK ;GET FIRST UNIT IN SYSTEM
		JRST FNDK.2]	;AND STEP TO ITS KONTROLLER
	MOVSI	T2,-10		;NUMBER OF POSSIBLE UNITS ON KONTROLLER
	HRRI	T2,KONTAB(T1)	;AND WHERE THEY ARE
	SETZ	T1,		;COMPUTE LAST UNIT
FNDK.1:	HRRZ	T3,0(T2)	;ADDRESS OF UNIT
	CAILE	T3,(T1)		;SINCE "XCHANGE" COULD RE-ORDER THE TABLE
	MOVE	T1,T3		;FIND HIGHEST ADDRESS AS LAST UNIT BY SYSINI
	AOBJN	T2,FNDK.1	;LOOK AT ALL POSSIBLE UNITS
	HLRZ	T1,UNISYS(T1)	;POINTER TO NEXT UNIT IN SYSTEM
	JUMPE	T1,CPOPJ	;LAST UNIT IN SYSTEM
FNDK.2:	HLLZ	T2,UNINAM(T1)	;NAME OF UNIT
	HRRZ	T1,UNIKON(T1)	;LINK BACK TO KONTROLLER
	POPJ	P,		;AND RETURN
;SUBROUTINE TO REMOVE A DISK KONTROLLER
;CALL:	P1 = KONTROLLER ADDRESS
;	P2 = CPU # IF FL.WAC IS ON
;RTNS:	FL.NCD ON IF CANNOT REMOVE THE KONTROLLER

DKONCM:	MOVSI	T2,-10		;MAX NUMBER OF UNITS ON KONTROLLER
	HRRI	T2,KONTAB(P1)	;THE START OF THE UNIT TABLE
DKON.1:	SKIPN	T3,0(T2)	;NEXT UNIT ON KONTROLLER
	JRST	DKON.3		;NONE, ALL DONE
	SKIPN	UNILOG(T3)	;THE LOGICAL NAME OF STRUCTURE MOUNTED
	JRST	DKON.3		;OK TO REMOVE UNIT IF NOTHING SPINNING
	HRRZ	T1,UNI2ND(T3)	;SOMETHING THERE, SEE IF DUAL PORTED
	JUMPE	T1,DKON.2	;CANNOT REMOVE IF NO OTHER PATH
	TLNN	F,(FL.WAC)	;WORRYING ABOUT REMOVING A CPU
	JRST	DKON.3		;NO, OK TO REMOVE IT
	MOVE	T1,UNIKON(T1)	;GET KONTROLLER FOR 2ND PATH
	LDB	T1,[POINT 3,KONCPU(T1),2] ;GET CPU OF 2ND KONTROLLER
	SKIPGE	CPUSTS(T1)	;IS THE CPU OF 2ND KONTROLLER DOWN
	JRST	DKON.2		;YES, TELL OPERATOR TO DISMOUNT PACK
	CAME	T1,P2		;ON SAME CPU AS ONE BEING REMOVED
	JRST	DKON.3		;NO, OK TO REMOVE IT
DKON.2:	PUSH	P,T2		;SAVE AOBJN FOR UNITS
	TLON	F,(FL.HEA)	;ALREADY GIVE HEADER
	PUSHJ	P,[OUTSTR [ASCIZ/? Following Packs MUST be dismounted:/]
		JRST CRPOPJ]	;NO, GIVE HEADER NOW
	OUTCHR	[11]		;OUTPUT A TAB TO ALIGN
	MOVE	T1,UNILOG(T3)	;POINT TO STRUCTURE NAME
	PUSHJ	P,SIXOUT	;OUTPUT STR NAME
	OUTSTR	[ASCIZ/ on /]
	MOVE	T1,UNINAM(T3)	;GET DRIVE NAME
	PUSHJ	P,SIXOUT	;OUTPUT THAT
	PUSHJ	P,ERRXIT	;END LINE, LIGHT ERROR BIT
	POP	P,T2		;RESTORE AOBJN TO KONTROLLER
DKON.3:	AOBJN	T2,DKON.1	;DO NEXT UNIT
	TLNE	F,(FL.NCD!FL.CHK) ;OK TO REALLY REMOVE THE UNITS
	POPJ	P,		;NO, RETURN NOW
DKONRM:	MOVSI	T5,-10		;NUMBER OF UNITS POSSIBLE
	HRRI	T5,KONTAB(P1)	;AND WHERE THEY ARE
DKON.4:	SKIPN	T4,0(T5)	;NEXT UNIT ON THE KONTROLLER
	JRST	DKON.6		;NONE, ALL DONE
	LDB	T1,[POINT 2,UNIDES(T4),8] ;GET UNIT STATUS CODE
	TLNE	F,(FL.ADD)	;ADD OR REMOVE COMMAND
	JRST	[CAIE T1,UNVDWN	;ADD, IS UNIT DOWN (DETACHED)
		 JRST DKON.6	;NO, ALREADY USABLE
		 MOVEI T1,[ASCIZ/ATTACH /] ;ADD
		 JRST DKON.5]	;GO ATTACH THE UNIT
	CAIN	T1,UNVDWN	;IS UNIT ALREADY DETACHED
	JRST	DKON.6		;YES, DON'T DO IT AGAIN
	MOVEI	T1,[ASCIZ/DETACH /] ;REMOVE
DKON.5:	PUSHJ	P,PTYSTR	;OUTPUT THAT
	MOVE	T1,UNINAM(T4)	;GET UNIT TO ATTACH/DETACH
	PUSHJ	P,PTYSIX	;OUTPUT THAT
	PUSHJ	P,PTYCLF	;END THE COMMAND LINE
DKON.6:	AOBJN	T5,DKON.4	;AND GET THE REST
	POPJ	P,		;ALL DONE
;SUBROUTINE TO SET UP CPU STATUS TABLE

SETCPU:	MOVE	T1,[.STCPU,,SP.CR0!SP.CR1!SP.CR2!SP.CR3!SP.CR4!SP.CR5]
	SETUUO	T1,		;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	T1,-6		;MAX CPUS
SETC.1:	MOVSI	T2,(T1)		;CPUN TO LH
	LSH	T2,1		;*2 FOR GETTAB
	ADD	T2,[%CCPTR&777777,,.GTSLF]
	GETTAB	T2,		;GET BASE OF CDB CONSTANTS = CDB ADDRESS
	  HALT	.		;WHAT
	TLNN	T2,(SL.MAX)	;IS MAX FOR GETTAB = 0
	JRST	[MOVSI T2,(1B0!1B1) ;YES, MARK IT NON-EXISTANT
		JRST SETC.2]	;AND STORE DATA
	MOVEI	T3,(T1)		;COPY CPU NUMBER
	LSH	T3,1		;*2 FOR GETTAB
	ADD	T3,[%CVRUN]	;GET .CPRUN
	GETTAB	T3,		;GET IT
	  HALT	.		;WHAT
	TLNE	T3,(1B2)	;IS IT DETACHED
	JRST	[HRLI T2,(1B0!1B2) ;YES, MARK IT
		JRST SETC.2]	;STORE DATA
	TLNE	T3,(1B1)	;IS CPU ALREADY STOPPED
	JRST	[HRLI T2,(1B0)	;YES, MARK IT DOWN
		JRST SETC.2]	;STORE DATA
	TLZ	T2,-1		;CPU IS UP, CLEAR STATUS BITS
	AOS	CPUN		;COUNT A RUNNING CPU
	GTTAB	T3,%CNBCP	;FIND THE BOOT CPU
	CAIN	T3,(T1)		;THIS IT
	TLO	T2,(1B4)	;YES, REMEMBER THAT
	MOVEI	T3,1B35		;GET A BIT FOR CPU0
	LSH	T3,(T1)		;POSITION IT CORRECTLY
	IORM	T3,CPURUN	;LIGHT A RUNNING CPU BIT
	MOVEI	T3,(T1)		;COPY CPU NUMBER
	LSH	T3,1		;*2 FOR GETTAB
	ADD	T3,[%CCOKP]	;GET THE OK WORD
	GETTAB	T3,		;GET IT
	  HALT	.		;WHAT
	SKIPG	T3		;IS THE CPU REALLY RUNNING
	AOSA	CPUOK		;YES, COUNT THE CPU
	TLO	T2,(1B3)	;NO, REMEMBER THIS ONE ISN'T
SETC.2:	MOVEM	T2,CPUSTS(T1)	;UPDATE STATUS
	AOBJN	T1,SETC.1	;AND TRY ANOTHER CPU
	POPJ	P,		;RETURN
	END	CONFIG		;END OF THIS PROGRAM