Google
 

Trailing-Edge - PDP-10 Archives - bb-bt99m-bb - cnftab.x19
There are no other files named cnftab.x19 in the archive.
	TITLE	CNFTAB - CONFIG commands module
	SUBTTL	Nick Tamburri/RJF		10-Mar-88

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


	SALL
	SEARCH	GLXMAC, ORNMAC
	PROLOG	(CNFTAB)

	.DIRECTIVE FLBLST

	.TEXT	"/LOCALS"
	SUBTTL	CSTAB - Macro to define command symbols

DEFINE CSTAB(VALUE,PREFIX)<
    .....B==VALUE
    DEFINE	X(SYMBOL)<
	PREFIX''SYMBOL==:.....B
	.....B==.....B+1
    >
    DEFINE	C(SYMBOL)<
	PREFIX''SYMBOL==:.....B
	.....B==.....B+7
    >
>
	SUBTTL	Function symbol definitions

;Here we define all the message types that will be used by the
;CONFIG module, as well as all the command codes, which should
;always be identical for simplicity.

	CSTAB(0,.CF)			;Main command table
	X (ILL)				;Zero message illegal
	X (ADD)				;ADD command
	X (AUT)				;Auto-configure
	X (HLP)				;Help
	X (LOD)				;Load microcode
	X (REM)				;Remove
	X (SET)				;Set
	X (SHO)				;Show
	X (SHT)				;Shutdown
	X (SNP)				;Snapshot
	X (SUS)				;Suspend

	CSTAB(0,.AR)			;Add/Remove
	X (ILL)				;As always, 0 illegal
	X (MEM)				;Memory
	C (CPU)				;CPU0, CPU1, ... CPU5, ALL
	C (CI)				;CI-0, CI-1, ... CI-5, ALL
	C (NI)				;NI-0, NI-1, ... NI-5, ALL
	X (FRC)				;Forced switch

	CSTAB(0,.ST)			;Set command
	X (BOT)				;Boot-text
	X (ULD)				;Microcode
	X (KLI)				;KLINIK
	X (NOT)				;Negator
	X (AUT)				;Auto-reload
	X (DMP)				;Dump
	X (RLD)				;Reload
	X (CPN)				;CPU
	X (DBG)				;DEBUG
	X (JOB)				;JOB
	X (PLC)				;POLICY-CPU
	X (IGN)				;IGNORE

	CSTAB(0,.KL)			;Set KLINIK command
	X (OFF)				;Set KLINIK OFF
	X (REM)				;Set KLINIK REMOTE
	X (USR)				;Set KLINIK USER
	X (MNT)				;Console mode MAINTENANCE
	X (OPR)				;Console mode OPERATOR
	X (PRG)				;Console mode PROGRAMMER

	CSTAB(0,.SH)			;Show command
	X (KLI)				;SHOW KLINIK
	X (STP)				;SHOW STOPCODE-FLAGS
	X (BTX)				;SHOW BOOTXT
	X (HDW)				;SHOW HARDWARE-CONFIGURATION
	SUBTTL	Application table header

	INTERN	CNFTAB			;Make available to others

CNFTAB:	EXP	2			;Length of the table
	EXP	INICNF			;Address of initial PDB
	EXP	CNFFDB			;Top level keyword PDB
SUBTTL	Dynamic device definitions


; DEVICES
	CPUMAX==7			;MAXIMUM NUMBER OF CPUS + 1 FOR "ALL"
	DEVMAX==6			;TOTAL NUMBER OF DEVICE TYPES

; MAXIUMUM NUMBER OF CHANNELS
	ND	RH10D,2			;RH10 DISK CHANNELS PER CPU
	ND	RH20D,2			;RH20 DISK CHANNELS PER CPU
	ND	CI20D,1			;CI20 DISK CHANNELS PER CPU
	ND	DX10T,1			;DX10 TAPE CHANNELS PER CPU
	ND	RH10T,2			;RH10 TAPE CHANNELS PER CPU
	ND	RH20T,2			;RH20 TAPE CHANNELS PER CPU
	ND	CI20T,0			;CI20 TAPE CHANNELS PER CPU
	ND	NI20E,1			;TOTAL NI20 ENET CHANNELS

; MAXIMUM NUMBER OF CHANNELS IN SYSTEM
	RH10DM==RH10D*CPUMAX		;TOTAL RH10 DISK CHANNELS
	RH20DM==RH20D*CPUMAX		;TOTAL RH20 DISK CHANNELS
	CI20DM==CI20D*CPUMAX		;TOTAL CI20 DISK CHANNELS
	DX10TM==DX10T*CPUMAX		;TOTAL DX10 TAPE CHANNELS
	RH10TM==RH10T*CPUMAX		;TOTAL RH10 TAPE CHANNELS
	RH20TM==RH20T*CPUMAX		;TOTAL RH20 TAPE CHANNELS
	CI20TM==CI20T*CPUMAX		;TOTAL CI20 TAPE CHANNELS
	NI20EM==NI20E*CPUMAX		;TOTAL NI20 ENET CHANNELS

	DSKMAX==RH10DM+RH20DM+CI20DM	;TOTAL DISK CHANNELS
	TAPMAX==DX10TM+RH10TM+RH20TM+CI20TM ;TOTAL TAPE CHANNELS
	DTAMAX==2*CPUMAX		;TOTAL DECTAPE CONTROLLERS
	CIPMAX==CPUMAX			;TOTAL CI20 PORTS
	NIPMAX==CPUMAX			;TOTAL NI PORTS

DSKLST::BLOCK	1			;LIST HANDLE FOR DISK DATABASE
Z.DEVB:!				;START OF DATA TO ZERO
CPUTAB:	BLOCK	1+CPUMAX		;CPU KEYWORD TABLE
DSKTAB:	BLOCK	1+<DSKMAX*2>		;DISK KONTROLLER KEYWORD TABLE
TAPTAB:	BLOCK	1+<TAPMAX*2>		;TAPE KONTROLLER KEYWORD TABLE
DTATAB:	BLOCK	1+<DTAMAX*2>		;DECTAPE KONTROLLER KEYWORD TABLE
CIPTAB:	BLOCK	1+<CIPMAX*2>		;CI20 PORT KEYWORD TABLE
NIPTAB:	BLOCK	1+<NIPMAX*2>		;NI PORT KEYWORD TABLE
PDBPTR:	BLOCK	1			;FIRST FREE DYNAMIC PDB ADDRESS
DEVPDB:	BLOCK	1+<PB%SIZ*DEVMAX>	;DYNAMIC PDB STORAGE
Z.DEVE:!				;END OF DATA TO ZERO
DSKKON:	BLOCK	1			;POINTER TO DESIRED DISK KONTROLLERS
TAPKON:	BLOCK	1			;POINTER TO DESIRED TAPE KONTROLLERS
DTKON:	BLOCK	1			;POINTER TO DESIRED DECTAPE KONTROLLERS
DEVARF:	BLOCK	1			;ADD/REMOVE FLAG (0=ADD, 1=REMOVE)
CPUFLG:	BLOCK	1			;ALL CPU FLAG (0 IF NOT, 1 IF ALL)
DEVFLG:	BLOCK	1			;ALL-DEV FLAG
DCHBLK:	BLOCK	.DCMAX+1		;DSKCHR UUO BLOCK
DIABLK:	BLOCK	5			;DIAG. UUO BLOCK
HDWPDB:	BLOCK	1+^D18			;SWITCHES FOR SHOW HARDWARE-CONFIGURATION
	SUBTTL	CNFTAB - The actual tables

;This is the macro which will be expanded by the two module dependent
;support macros.

	INTERN	INICNF			;Make tables address available
	INTERN	CNFFDB

INICNF:	$INIT	(CNFFDB)
CNFFDB:	$KEYDSP	(CNFFD1,<$ERROR(BADCOM##)>)
CNFFD1:	$STAB
	DSPTAB	(ADDFDB,.CFADD,ADD)
	DSPTAB	(AUTFDB,.CFAUT,AUTO-CONFIGURE)
	DSPTAB	(HLPFDB,.CFHLP,HELP)
	DSPTAB	(LODFDB,.CFLOD,LOAD)
	DSPTAB	(REMFDB,.CFREM,REMOVE)
	DSPTAB	(SETFDB,.CFSET,SET)
	DSPTAB	(SHOFDB,.CFSHO,SHOW)
	DSPTAB	(SHTFDB,.CFSHT,SHUTDOW,CM%NOR)
	DSPTAB	(SHTFDB,.CFSHT,SHUTDOWN)
	DSPTAB	(SNPFDB,.CFSNP,SNAPSHO,CM%NOR)
	DSPTAB	(SNPFDB,.CFSNP,SNAPSHOT)
	DSPTAB	(SUSFDB,.CFSUS,SUSPEN,CM%NOR)
	DSPTAB	(SUSFDB,.CFSUS,SUSPEND)
	DSPTAB	(SHOFDB,.CFSHO,WHAT,CM%INV)
	$ETAB
	SUBTTL	ADD/REMOVE commands

REMFDB:	$NOISE	(DEVPDB,<hardware>,<$PREFILL (REMPRE)>)
REMF04:	$SWITCH	(CONFRM##,REMF05,<$ALTER(CONFRM##)>)
REMF05:	$STAB
	DSPTAB	(CONFRM##,.ARFRC,<FORCE>)
	$ETAB

ADDFDB:	$NOISE	(DEVPDB,<hardware>,<$PREFILL (ADDPRE)>)
ADD000:	$KEYDSP	(ADDF01,$ALTER(ADDF20))
ADDF01:	$STAB
	DSPTAB	(ADDF05,.ARMEM,MEMORY)
	$ETAB

ADDF05:	$NOISE	(ADDF09,<from>)
ADDF09:	$TOKEN	(ADDF10,<#>,<$ALTER(ADDF10)>)
ADDF10:	$FIELD	(ADDF11,<first address>)
ADDF11:	$NOISE	(ADDF12,<to>)
ADDF12:	$TOKEN	(ADDF13,<#>,<$ALTER(ADDF13)>)
ADDF13:	$FIELD	(CONFRM##,<last address>)

ADDF20:	$DEV	(CONFRM##,<$ACTION(CHKDEV),$HELP(device name),$FLAGS(CM%NSF!CM%PO)>)

ADDPRE:	TDZA	S1,S1
REMPRE:	MOVEI	S1,1
	MOVEM	S1,DEVARF
	MOVEI	S1,ADD000
	SETZM	CPUFLG
	SETOM	DEVFLG
	SETZM	DSKKON
	SETZM	TAPKON
	SETZM	DTKON
	PUSHJ	P,DEVINI
	$RETT

ND	CR.ADR,4		;ADDRESS OF CURRENT ARGUMENT

CHKDEV:	MOVE	T1,S2		;COPY ADDRESS OF COMMAND BLOCK
	MOVE	S1,CR.ADR(S2)	;GET ADDRESS OF CURRENT ARGUMENT
	HRROI	S1,ARG.DA(S1)	;POINT AT DEVICE STRING
	PUSHJ	P,S%SIXB	;CONVERT TO SIXBIT
	EXCH	T1,S2		;SAVE DEVICE IN T1, RESTORE COMMAND BLOCK POINTER
	MOVE	S1,T1		;GET A COPY OF DEVICE NAME
	DEVTYP	S1,UU.PHY	;ASK ABOUT IT
	  JRST	CHKE.1		;ERROR
	JUMPE	S1,.RETT	;DEVICE NOT KNOWN YET IS OK
	TXNE	S1,TY.GEN	;GENERIC?
	JRST	CHKE.2		;YES
	LOAD	S1,S1,TY.DEV	;GET TYPE OF DEVICE (COUNT ON ZERO=DISK)
	CAXE	S1,.TYDSK	;IS IT A DISK?
	$RETT			;NO, THEN PROBABLY OK
	MOVE	S1,[1,,T1]	;MIGHT BE A DETACHED DISK
	DSKCHR	S1,		;ASK ABOUT IT
	  JRST	CHKE.1		;NOPE
	LOAD	S1,S1,DC.TYP	;GET TYPE OF ARGUMENT
	CAXE	S1,.DCTPU	;MUST BE A PHYSICAL UNIT
	JRST	CHKE.1		;NO
	$RETT			;GOOD

CHKE.1:	SKIPA	S1,[[ASCIZ /Illegal device specified/]]
CHKE.2:	MOVEI	S1,[ASCIZ /Generic device illegal/]
	PUSH	P,S1		;SAVE THE ERROR
	PUSHJ	P,P$FIXP##	;FIXUP POINTERS
	POP	P,S2		;RESTORE TEXT ADDRESS
	$RETF			;GIVE THEM AN ERROR
	SUBTTL	AUTO-CONFIGURE, EXIT, and HELP commands

AUTFDB:	$NOISE	(DEVPDB,<hardware>,<$ACTION (AUTCPU)>)
AUTCPU:	MOVEI	S1,CONFRM##		;COMMAND TREE REENTRY POINT
	PJRST	ALLCPU			;ALLOW ALL CPUS

EXTFDB:	$NOISE	(CONFRM##,<to OPR command level>)

HLPFDB:	$NOISE	(HLPF01,<with>)
HLPF01:	$KEY	(HLPF02,CNFFD1,<$DEFAULT (<HELP>)>)
HLPF02:	$CRLF	(<$ACTION (CNFHLP)>)
	SUBTTL	LOAD/SET [NO] MICROCODE tables


LODFDB:	$NOISE	(ULD000,<microcode on>,<$ACTION (ULDDEV)>)
SETULD:	$NOISE	(ULD000,<loading on>,<$ACTION (ULDDEV)>)

ULD000:	$KEY	(ULD020,CPUTAB,<$ALTER (DEVPDB)>)
ULD010:	$KEY	(ULD020,CPUTAB)
ULD020:	$NOISE	(ULD030,<device>)

ULD030:	$NUMBER	(ULD040,^D8,<device code>)
ULD040:	$NOISE	(ULD050,<unit>)
ULD050:	$NUMBER	(CONFRM##,^D8,<unit number>,<$DEFAULT (<0>)>)

ULD060:	$NUMBER	(ULD070,^D8,<device code>,<$ALTER (DEVPDB)>)
ULD070:	$NOISE	(ULD080,<unit>)
ULD080:	$NUMBER	(CONFRM##,^D8,<unit number>,<$DEFAULT (<0>)>)


; Action routine to build the device tables if necessary
ULDDEV:	PUSHJ	P,.SAVE3		;SAVE SOME ACS
	PUSH	P,S2			;SAVE POINTER
	SETOM	CPUFLG			;DON'T INSERT ANY CPUS
	SETZM	DEVFLG			;DON'T ALLOW ALL-XXX
	MOVE	S1,DSKUCD		;DISK KONTS WITH LOADABLE UCODE
	MOVEM	S1,DSKKON		;SAVE
	MOVE	S1,TAPUCD		;TAPE KONTS WITH LOADABLE UCODE
	MOVEM	S1,TAPKON		;SAVE
	SETOM	DTKON			;DECTAPES NEVER HAVE UCODE
	MOVNI	S1,1			;NO COMMAND TREE REENTRY POINT
	PUSHJ	P,DEVINI		;INIT DYNAMIC TABLES
	POP	P,S2			;GET POINTER BACK
	LOAD	S1,CR.PDB(S2),LHMASK	;GET GIVEN PDB
	PUSHJ	P,P$GPDB##		;GET ADDR WORKING COPY
	HLRZ	S2,CPUTAB		;GET NUMBER OF CPUS
	CAIN	S2,1			;ONLY ONE CPU?
	SKIPA	S2,[ULD060,,ULD030]	;YES
	MOVE	S2,[ULD000,,ULD010]	;FDBS
	SKIPE	DEVPDB			;LOADABLE KONTROLLERS PRESENT?
	MOVSS	S2			;YES
	HRRZM	S2,PB%NXT(S1)		;SET POINTER TO NEXT PARSE BLOCK
	$RETT				;RETURN
	SUBTTL	SET command

SETFDB:	$KEYDSP	(SETF01)
SETF01:	$STAB
	DSPTAB	(SETF05,.STAUT,AUTO-RELOAD)
	DSPTAB	(SETF02,.STBOT,BOOT-TEXT)
	DSPTAB	(SETF06,.STDMP,DUMP)
	DSPTAB	(SETIGN,.STIGN,IGNORE)
	DSPTAB	(KLIFDB,.STKLI,KLINIK)
	DSPTAB	(SETULD,.STULD,MICROCODE)
	DSPTAB	(SETF04,.STNOT,NO)
	DSPTAB	(SETF07,.STPLC,POLICY-CPU)
	DSPTAB	(SETF06,.STRLD,RELOAD)
	$ETAB

SETF02:	$NOISE	(SETF21,<for system start up>)
SETF21:	$CTEXT	(CONFRM##,<a single line text string>,<$DEFAULT(<DSKA:SYSTEM.EXE[1,4]>)>)
SETF04:	$KEYDSP	(SETF40)
SETF40:	$STAB
	DSPTAB	(STNF42,.STAUT,AUTO-RELOAD)
	DSPTAB	(SETF06,.STDMP,DUMP)
	DSPTAB	(SETIGN,.STIGN,IGNORE)
	DSPTAB	(SETULD,.STULD,MICROCODE)
	DSPTAB	(SETF06,.STRLD,RELOAD)
	$ETAB

SETF05:
STNF42:	$NOISE	(CONFRM##,<upon system crashes>)

SETF06:	$NOISE	(SETF60,<on>)
SETF60:	$KEYDSP	(SETF61)
SETF61:	$STAB
	DSPTAB	(SETF62,.STCPU,CPU-STOPCODES)
	DSPTAB	(SETF62,.STDBG,DEBUG-STOPCODES)
	DSPTAB	(SETF62,.STJOB,JOB-STOPCODES)
	$ETAB
SETF62:	$COMMA	(SETF60,<$ALTER(CONFRM##),$HELP(comma to specify another stopcode type)>)

SETF07:	$NOISE	(SETF70,<to be>,<$ACTION(PCPINI)>)
SETF70:	$KEY	(CONFRM##,CPUTAB)

SETIGN:	$NOISE	(SETI10,<unit>)
SETI10:	$DEV	(CONFRM##,<$HELP(name of unit),$FLAGS(CM%NSF!CM%PO)>)

;Action routine to build the CPU tables
PCPINI:	SETOM	CPUFLG			;DON'T LINK CPU TABLES TO DEVPDB
	PJRST	CPUINI			;INITIALIZE CPU TABLES AND RETURN
	SUBTTL	Miscellaneous commands
SUSFDB:
SNPFDB:
SHTFDB:	$NOISE	(SHTF01,<system>)
SHTF01:	$CTEXT	(CONFRM##,<single line reason>)
	SUBTTL	SHOW command

SHOFDB:	$KEYDSP	(SHOF01)
SHOF01:	$STAB
	DSPTAB	(CONFRM##,.SHBTX,BOOT-TEXT)
	DSPTAB	(SHOH01,.SHHDW,HARDWARE-CONFIGURATION)
	DSPTAB	(CONFRM##,.SHKLI,KLINIK)
	DSPTAB	(CONFRM##,.SHSTP,STOPCODE-FLAGS)
	$ETAB

SHOH01:	$NOISE	(SHOH02,<of system>,$PREFIL(HDWPRE))
SHOH02:	$SWITCH	(NEXT(SHOH02),HDWPDB,<$ACTION(SHRSWT),$ALTER(CONFRM##)>)

HDWPRE:	MOVEI	S1,1+^D18	;SIZE OF SWITCH TABLE
	MOVEI	S2,HDWPDB	;ADDRESS OF IT
	$CALL	.ZCHNK		;CLEAR OUT SWITCH TABLE
	MOVEI	S1,^D18		;GET TABLE SIZE
	MOVEM	S1,HDWPDB	;SAVE IT FOR S%TBAD
	$CALL	.SAVE2		;FREE UP A FEW AC'S
	MOVSI	P1,-HDWTBL	;-VE NUMBER OF COMMON ITEMS
HDWPR1:	MOVEI	S1,HDWPDB	;ADDRESS OF SWITCH TABLE
	MOVE	S2,HDWTAB(P1)	;GET AN ENTRY
	$CALL	S%TBAD		;ADD THE ENTRY
	JUMPF	HDWERR		;SHOULDN'T FAIL
	AOBJN	P1,HDWPR1	;LOOP FOR ALL COMMON ITEMS
	SETZ	P1,		;START WITH A ZERO
	$CALL	.CPUTY		;GET CPU TYPE
	CAXN	S1,%KL10	;KL10?
	MOVE	P1,[-KLOTBL,,KLOTAB] ;POINT AT OPTIONAL STUFF
	CAXN	S1,%KS10	;KS10?
	MOVE	P1,[-KSOTBL,,KSOTAB] ;POINT AT OPTIONAL STUFF
	SKIPE	P1		;ANY OPTIONS?
	PUSHJ	P,HDWOPT	;YES, FILL THEM IN
	$RETT			;DONE

HDWERR:	HALT	.		;OOPS

HDWOPT:	PUSHJ	P,@0(P1)	;CALL THE CHECK ROUTINE
	JUMPF	HDWOP1		;JUMP IF THIS OPTION IS NOT NEEDED
	MOVEI	S1,HDWPDB	;POINT AT SWITCH TABLE
	MOVE	S2,1(P1)	;GET THE ENTRY
	$CALL	S%TBAD		;ADD IT TO THE TABLE
	JUMPF	HDWERR		;SHOULDN'T FAIL
HDWOP1:	AOBJN	P1,.+1		;ACCOUNT FOR TWO-WORD ENTRIES
	AOBJN	P1,HDWOPT	;LOOP FOR ALL OF THEM
	POPJ	P,		;SUCCESS

HDWTAB:	ORNSWI	(<CONTROLLER-MICROCODES>,HCM)
	ORNSWI	(<CPU>,HCP)
	ORNSWI	(<DISK>,HDI)
;	ORNSWI	(<LOG>,HLG)
	ORNSWI	(<MONITOR-MEMORY>,HMM)
	ORNSWI	(<TAPE>,HTA)
	ORNSWI	(<UNIT-RECORD>,HUR)
HDWTBL==.-HDWTAB		;NUMBER OF COMMON ITEMS

KLOTAB:	IFIW	.RETT		;ALWAYS HAVE CFE
	ORNSWI	(<CFE>,HCF)
	IFIW	CHKCIP		;CHECK FOR CI PORT
	ORNSWI	(<CI>,HCI)
	IFIW	CHKNIP		;CHECK FOR NI PORT
	ORNSWI	(<NI>,HNI)
KLOTBL==.-KLOTAB		;NUMBER OF KL OPTIONS

KSOTAB:	IFIW	.RETT		;ALWAYS HAVE UBAS
	ORNSWI	(<UBA>,HUB)

KSOTBL==.-KSOTAB		;NUMBER OF KS OPTIONS

CHKCIP::MOVX	S1,%CCCIP	;GETTAB TO USE
	JRST	CHKPRT		;SAVE SOME CODE
CHKNIP::MOVX	S1,%CCNIP	;GETTAB TO USE
CHKPRT:	$SAVE	<T1>		;FREE UP AN AC
	MOVE	T1,S1		;COPY GETTAB INDEX
	MOVX	S1,%CNCPU	;GET NUMBER OF CPUS IN SYSTEM
	GETTAB	S1,		;ASK MONITOR
	  MOVEI	S1,1		;WON'T TELL US, HUH?
	LSH	S1,1		;DOUBLE IT FOR CDB GETTABING
	MOVNS	S1		;NEGATE
	HRLZS	S1		;AND MAKE AN AOBJN WORD
CHKPR1:	MOVE	S2,T1		;COPY THE GETTAB WE'LL USE
	ADDI	S2,(S1)		;MAKE IT CPU-SPECIFIC
	GETTAB	S2,		;ASK MONITOR
	  SETZ	S2,		;WON'T TELL US, HUH?
	JUMPN	S2,.RETT	;OK IF ANYONE HAS A PORT
	AOBJN	S1,.+1		;ACCOUNT FOR TWO TABLES/CPU
	AOBJN	S1,CHKPR1	;KEEP LOOKING
	$RETF			;NO GOOD
	SUBTTL	SETKLI - Set KLINIK parameters


KLIFDB:	$NOISE	(DEVPDB,<parameters>,<$ACTION (KLICPU)>)
KLI015:	$CRLF	(<$NEXT (KLI020),$HELP (<return to enter KLINIK mode>)>)
KLI020:	$SUBCM	(KLI025,KLIPMT,)
KLI025:	$KEYDSP	(KLI030,)
KLI030:	$STAB
	 DSPTAB	(KLI999,.KLOFF,<OFF>)
	 DSPTAB	(KLI100,.KLREM,<REMOTE>)
	 DSPTAB (KLI200,.KLUSR,<USER>)
	$ETAB


; Here for SET KLINK REMOTE
KLI100:	$CRLF	(<$NEXT (KLI105)>)
KLI105:	$SUBCM	(KLI110,PSWPMT,)
KLI110:	$FIELD	(KLI115,<Password>,<$PREFILL (NOECHO),$ERROR (ECHO)>)
KLI115:	$CRLF	(<$NEXT (KLI120),$PREFIL (ECHO)>)
KLI120:	$SUBCM	(KLI125,OPNPMT,)
KLI125:	$TAD	(KLI130,<$PREFILL (DTNOW0),$PDEFAULT (DEFDTM)>)
KLI130:	$CRLF	(<$NEXT (KLI135)>)
KLI135:	$SUBCM	(KLI140,CLSPMT,)
KLI140:	$TAD	(KLI145,<$PREFILL (DTNOW1),$PDEFAULT (DEFDTM)>)
KLI145:	$CRLF	(<$NEXT	(KLI150)>)
KLI150:	$SUBCM	(KLI155,CONPMT,)
KLI155:	$KEY	(KLI999,KLI160,<$DEFAULT (<OPERATOR>)>)
KLI160:	$STAB
	 KEYTAB	(.KLMNT,<MAINTENANCE>)
	 KEYTAB	(.KLOPR,<OPERATOR>)
	 KEYTAB	(.KLPRG,<PROGRAMMER>)
	$ETAB

; Here for SET KLINIK USER
KLI200:	$CRLF	(<$NEXT (KLI205)>)
KLI205:	$SUBCM	(KLI210,OPNPMT,)
KLI210:	$TAD	(KLI215,<$PREFILL (DTNOW0),$PDEFAULT (DEFDTM)>)
KLI215:	$CRLF	(<$NEXT (KLI220)>)
KLI220:	$SUBCM	(KLI225,CLSPMT,)
KLI225:	$TAD	(KLI999,<$PREFILL (DTNOW1),$PDEFAULT (DEFDTM)>)

; Here to exit SET KLINIK command
KLI999:	$CRLF	(<$ACTION (P$XSBC##)>)
; KLINIK prompts
KLIPMT:	ASCIZ	/KLINIK mode: /
PSWPMT:	ASCIZ	/Password: /
OPNPMT:	ASCIZ	/Access window OPEN date-time: /
CLSPMT:	ASCIZ	/Access window CLOSED date-time: /
CONPMT:	ASCIZ	/Highest console mode: /


; Action routine to build the CPU table if necessary
KLICPU:	MOVEI	S1,KLI015		;COMMAND TREE REENTRY POINT
	PJRST	ALLCPU			;ALLOW ALL CPUS

; Action routine to enable/disable echoing
NOECHO:	TDZA	S1,S1			;SET TTY NO ECHO
ECHO:	MOVEI	S1,1			;SET TTY ECHO
	$CALL	K%ECHO			;TOGGLE ECHO STATUS
	$RETT				;RETURN

; Action routine to set the default date-time
DTNOW0:	TDZA	S2,S2			;SET TO NOW
DTNOW1:	MOVSI	S2,1			;SET TO NOW + 1 DAY
	$CALL	I%NOW			;GET CURRENT UDT
	ADD	S1,S2			;PLUS THE INCREMENT
	$TEXT	(<-1,,DEFDTM>,<^H/S1/^0>)
	MOVE	S1,[POINT 7,DEFDTM]	;BYTE POINTER TO DEFAULT TEXT
	ILDB	S2,S1			;GET FIRST CHAR
	CAIE	S2," "			;IF SMALL DATE
	 JRST	DTNOW2			;BIG DATE, NO PROBLEM
	MOVEI	S2,"0"			;MAKE INTO 02-FEB
	DPB	S2,S1			;SIGH
DTNOW2:	ILDB	S2,S1			;GET A CHARACTER
	CAIE	S2," "			;START OF TIME COMPONENT?
	JRST	DTNOW2			;NO
	MOVEI	S2,":"			;MAKE PROPER FOR SCAN-STYLE PARSING
	DPB	S2,S1			;OVERWRITE SPACE
	ILDB	S2,S1			;GET NEXT CHARACTER
	CAIN	S2," "			;ANOTHER SPACE?
	MOVEI	S2,"0"			;IMBEDDED SPACES ARE ILLEGAL
	DPB	S2,S1			;OVERWRITE CHARACTER
	$RETT				;RETURN

DEFDTM:	BLOCK	6			;STORAGE FOR DEFAULT DATE-TIME TEXT
SUBTTL	Dynamic device routines -- DEVINI - Action routine for command parsing


; THIS ROUTINE WILL CAUSE THE DEVICE TABLES TO BE BUILT, MOVE THE
; APPROPRIATE PDBS AND FDBS INTO WORKING STORAGE, AND LINK THEM INTO
; THE COMMAND TREE.  ALTHOUGH DEVINI MAY BE CALLED AT ANY TIME, IT
; IS USUALLY CALLED AS AN ACTION ROUTINE ON THE ADD AND REMOVE COMMANDS.

DEVINI:	PUSH	P,S1			;SAVE COMMAND TREE REENTRY POINT
	MOVE	S1,[Z.DEVB,,Z.DEVB+1]	;SET UP BLT
	SETZM	Z.DEVB			;CLEAR FIRST WORD
	BLT	S1,Z.DEVE-1		;CLEAR ENTIRE BLOCK
	MOVEI	S1,DEVPDB		;GET ADDRESS OF FIRST PDB STORAGE
	MOVEM	S1,PDBPTR		;SAVE
	MOVSI	S1,-DEVMAX		;-NUMBER OF DEVICE TYPES
	PUSH	P,S1			;SAVE
DEVI.1:	PUSHJ	P,@DEVTAB(S1)		;INITIALIZE
	MOVE	S1,(P)			;GET COUNTER AGAIN
	AOBJP	S1,DEVI.2		;DONE?
	MOVEM	S1,(P)			;UPDATE
	JRST	DEVI.1			;LOOP
DEVI.2:	POP	P,(P)			;PHASE STACK
	MOVEI	TF,DEVMAX		;NUMBER OF DEVICE TYPES (AND PDBS)
	MOVEI	S1,DEVPDB		;POINT TO THE FIRST DYNAMIC PDB
DEVI.3:	SKIPN	0(S1)			;END?
	JRST	DEVI.4			;YES
	MOVEI	S2,PB%SIZ+1(S1)		;POINT TO THE NEXT DYNAMIC PDB
	MOVEM	S2,1(S1)		;LINK CURRENT TO NEXT
	MOVEI	S1,-1(S2)		;ADVANCE POINTER
	SOJG	TF,DEVI.3		;COUNT DOWN AND LOOP
DEVI.4:	POP	P,S2			;GET COMMAND TREE REENTRY POINT
	AOS	S2			;OFFSET
	MOVEM	S2,-PB%SIZ+1(S1)	;LINK LAST BACK TO TREE
	$RETT				;RETURN


; TABLE OF DEVICE TYPE INITIALIZATION ROUTINES
DEVTAB:	EXP	CPUINI			;CPUS
	EXP	DSKINI			;DISKS
	EXP	TAPINI			;TAPES
	EXP	DTAINI			;DECTAPES
	EXP	CIPINI			;CI20 PORTS
	EXP	NIPINI			;NI PORTS
DEVTBZ==.-DEVTAB		;NUMBER OF DEVICE TIPES WE KNOW ABOUT
IFG <DEVTBZ-DEVMAX>,<PRINTX ?Too many devices in DEVTAB. Adjust DEVMAX.>
SUBTTL	Dynamic device routines -- CPUINI - CPUs


CPUINI:	MOVE	S1,[CPUKEY,,CPUTAB]	;SET UP BLT
	BLT 	S1,CPUTAB+5		;COPY TABLE
	MOVE	S1,[%CNCPU]		;GETTAB ARGUMENT TO RETURN
	GETTAB	S1,			;THE NUMBER OF CPUS THE MONITOR
	  MOVEI	S1,1			;WAS BUILT FOR
	CAIN	S1,1			;JUST ONE?
	$RETT				;YES--CAN'T ADD OR REMOVE IT
	HRLM	S1,CPUTAB		;ADJUST KEYWORD TABLE
	SKIPGE	CPUFLG			;SKIP IF CALLER WANTS CPU TABLE LINKED
	$RETT				;ELSE RETURN
	MOVEI	S1,CPUTAB		;POINT TO WORKING COPY OF TABLE
	MOVSI	S2,[ASCIZ /ALL-CPUS/]	;POSSIBLE TEXT TO ADD
	HRRI	S2,.ARCPU+6		;CODE FOR ALL CPUS
	SKIPE	CPUFLG			;IS ALL LEGAL?
	$CALL	S%TBAD			;YES--ADD TO TABLE
	PUSH	P,PDBPTR		;SAVE PDB POINTER
	MOVEI	S1,CPUPDB		;POINT TO OUR PDB
	PUSHJ	P,COPPDB		;COPY TO WORKING STORAGE
	POP	P,S1			;GET POINTER BACK
	MOVEI	S2,REMF04		;ASSUME REMOVE
	SKIPLE	DEVARF			;IS IT?
	MOVEM	S2,3(S1)		;YES--LINK IN /FORCE
	$RETT				;DONE


; CPU PARSER DATA BLOCK
CPUPDB:	$KEY	(CONFRM##,CPUTAB,<$ALTER (.-.)>)
	BLOCK	PB%SIZ-<.-CPUPDB>


; STATIC CPU KEYWORD TABLE
CPUKEY:	$STAB
	KEYTAB	(.ARCPU+0,<CPU0>)
	KEYTAB	(.ARCPU+1,<CPU1>)
	KEYTAB	(.ARCPU+2,<CPU2>)
	KEYTAB	(.ARCPU+3,<CPU3>)
	KEYTAB	(.ARCPU+4,<CPU4>)
	KEYTAB	(.ARCPU+5,<CPU5>)
	$ETAB
SUBTTL	Dynamic device routines -- DSKINI - Disk kontrollers


DSKINI:	$SAVE	<P1,P2>			;SAVE SOME ACS
	PUSHJ	P,SETDSK		;SET UP DISK DATABASE
	MOVEI	P1,0			;START WITH FIRST UNIT
	MOVE	P2,[-DSKMAX,,DSKTAB]	;POINTER TO STORAGE
	PUSHJ	P,KONSET		;SET UP STORAGE
	MOVE	S1,DSKLST		;GET DISK DATABASE LIST HANDLE
	$CALL	L%FIRST			;POSITION TO FIRST ENTRY

DSKI.1:	JUMPF	DSKI.3			;JUMP IF END OF LIST
	MOVE	P1,.DDNAM(S2)		;GET UNIT NAME
	LOAD	S2,.DDSTS(S2),DC.CNT	;GET KONTROLLER TYPE
	MOVE	S1,DSKKON		;GET POINTER TO LEGAL KONTROLLER TYPES
	PUSHJ	P,KONCHK		;CHECK THIS ONE OUT
	JUMPF	DSKI.2			;NO GOOD
	PUSHJ	P,KONNAM		;CONVERT TO ASCII
	JUMPF	DSKI.3			;FAILED?
DSKI.2:	MOVE	S1,DSKLST		;GET LIST HANDLE AGAIN
	$CALL	L%NEXT			;POSITION TO NEXT ENTRY
	JRST	DSKI.1			;TRY FOR MORE

DSKI.3:	HLRZ	S1,DSKTAB		;GET NUMBER OF ENTRIES IN TABLE
	JUMPE	S1,.RETT		;RETURN IF EMPTY
	MOVEI	S1,DSKPDB		;POINT TO OUR PDB
	PUSHJ	P,COPPDB		;COPY TO WORKING STORAGE
	$RETT				;GIVE UP


; DISK PARSER DATA BLOCK
DSKPDB:	$KEY	(CONFRM##,DSKTAB,<$ALTER (.-.)>)
	BLOCK	PB%SIZ-<.-DSKPDB>


; DISK KONTROLLERS WITH LOADABLE MICROCODE
DSKUCD:	-DSKULN+1,,.+1			;POINTER
	EXP	.DCCRN			;RP20
DSKULN==.-DSKUCD			;LENGTH OF TABLE
SUBTTL	Dynamic device routines -- TAPINI - Tape kontrollers


TAPINI:	$SAVE	<P1,P2>			;SAVE SOME ACS
	MOVEI	P1,0			;START WITH FIRST KONTROLLER OR UNIT
	MOVE	P2,[-TAPMAX,,TAPTAB]	;POINTER TO STORAGE
	PUSHJ	P,KONSET		;SET UP STORAGE

TAPI.1:	MOVE	TF,[2,,S1]		;SET UP UUO AC
	MOVE	S1,[-1,,.TYMTA]		;MAGTAPE KONTROLLERS
	MOVE	S2,P1			;GET PREVIOUS KONTROLLER
	DVPHY.	TF,			;GET A KONTROLLER
	 JRST	TAPI.O			;OLD MONITOR
	SKIPN	P1,S2			;KONTROLLER NAME IN P1
	JRST	TAPI.3			;DONE IF ZERO
;		NOTE: WITH DI.CLM WE COULD CHECK THE KONTROLLERS FOR BEING
;		ABLE TO LOAD UCONE AND AVOID THE CALL TO KONCHK, BUT THIS
;		WILL DO FOR NOW.
	MOVEI	S2,.DIOKI		;WANT KONTROLLER INFO
	MOVEM	S2,DIABLK		;STORE FOR DIAG.
	MOVEM	P1,DIABLK+1		;STORE KONTROLLER NAME
	MOVE	S2,[-5,,DIABLK]		;POINT TO ARG BLOCK
	DIAG.	S2,			;GET CONTROLLER INFO
	 JRST	TAPI.2			;* CAN'T HAPPEN - BUT ADD ANYWAY
	LOAD	S2,DIABLK+2,DI.KTY	;GET KONTROLLER TYPE
	JRST	TAPI.K			;GO CHECK IT OUT

;HERE FOR OLD MONITORS THAT CAN'T DVPHY. KONTROLLER NAMES
TAPI.O:	MOVE	TF,[2,,S1]		;SET UP UUO AC
	MOVEI	S1,.TYMTA		;DEVICE TYPE = MAGTAPE
	MOVE	S2,P1			;GET PREVIOUS DEVICE
	DVPHY.	TF,			;GET A DEVICE
	  JRST	TAPI.3			;SAY NO MORE
	SKIPN	P1,S2			;GET DEVICE NAME
	JRST	TAPI.3			;DONE
	JUMPG	P1,TAPI.1		;SKIP LABEL DDBS
	MOVE	S2,[2,,TF]		;SET UP UUO AC
	MOVEI	TF,.TFKTP		;FUNCTION CODE
	HLLZ	S1,P1			;GET KONTROLLER NAME
	TAPOP.	S2,			;READ KONTROLLER TYPE
	  JRST	TAPI.2			;ASSUME OK TO INSERT

TAPI.K:	MOVE	S1,TAPKON		;GET POINTER TO LEGAL KONTROLLER TYPES
	PUSHJ	P,KONCHK		;CHECK THIS ONE OUT
	JUMPF	TAPI.1			;NO GOOD

TAPI.2:	PUSHJ	P,KONNAM		;CONVERT TO ASCII
	JUMPT	TAPI.1			;LOOP IF OK

TAPI.3:	HLRZ	S1,TAPTAB		;GET NUMBER OF ENTRIES IN TABLE
	JUMPE	S1,.RETT		;RETURN IF EMPTY
	MOVEI	S1,TAPPDB		;POINT TO OUR PDB
	PUSHJ	P,COPPDB		;COPY TO WORKING STORAGE
	$RETT				;GIVE UP


; TAPE PARSER DATA BLOCK
TAPPDB:	$KEY	(CONFRM##,TAPTAB,<$ALTER (.-.)>)
	BLOCK	PB%SIZ-<.-TAPPDB>


; TAPE KONTROLLERS WITH LOADABLE MICROCODE
TAPUCD:	-TAPULN+1,,.+1			;POINTER
	EXP	.TFKTX			;DX10/TX01
	EXP	.TFKD2			;DX20/TX02
TAPULN==.-TAPUCD			;LENGTH OF TABLE
SUBTTL	Dynamic device routines -- DTAINI - DecTape kontrollers

DTAINI:	$SAVE	<P1,P2>			;SAVE SOME ACS
	MOVEI	P1,0			;START WITH FIRST KONTROLLER
	MOVE	P2,[-DTAMAX,,DTATAB]	;POINTER TO STORAGE
	PUSHJ	P,KONSET		;SET UP STORAGE
	SKIPGE	DTKON			;CALLED FROM "LOAD" COMMAND?
	JRST	DTAI.3			;YES - RETURN EMPTY

DTAI.1:	MOVE	TF,[2,,S1]		;SET UP UUO AC
	MOVE	S1,[-1,,.TYDTA]		;DECTAPE KONTROLLERS
	MOVE	S2,P1			;GET PREVIOUS KONTROLLER
	DVPHY.	TF,			;GET A KONTROLLER
	 SETZ	S2,			;OLD MONITOR
	SKIPN	P1,S2			;KONTROLLER NAME IN P1
	JRST	DTAI.3			;DONE IF ZERO
DTAI.2:	PUSHJ	P,KONNAM		;CONVERT TO ASCII
	JUMPT	DTAI.1			;LOOP IF OK

DTAI.3:	HLRZ	S1,DTATAB		;GET NUMBER OF ENTRIES IN TABLE
	JUMPE	S1,.RETT		;RETURN IF EMPTY
	MOVEI	S1,DTAPDB		;POINT TO OUR PDB
	PUSHJ	P,COPPDB		;COPY TO WORKING STORAGE
	$RETT				;GIVE UP

; DECTAPE PARSER DATA BLOCK
DTAPDB:	$KEY	(CONFRM##,DTATAB,<$ALTER (.-.)>)
	BLOCK	PB%SIZ-<.-DTAPDB>

SUBTTL	Dynamic device routines -- CIPINI - CI20 ports


CIPINI:	$SAVE	<P1,P2>			;SAVE SOME ACS
	MOVEI	P1,0			;START WITH FIRST UNIT
	MOVE	P2,[-CIPMAX,,CIPTAB]	;POINTER TO STORAGE
	PUSHJ	P,KONSET		;SET UP STORAGE

CIPI.1:	MOVE	S1,P1			;GET CPU NUMBER
	LSH	S1,1			;OFFSET TO MAKE THE RIGHT GETTAB TABLE
	ADD	S1,[%CCCIP]		;FORM GETTAB FOR APPROPRIATE CPU
	GETTAB	S1,			;SEE IF THIS CPU HAS A CI20 PORT
	  SETZ	S1,			;NOPE
	JUMPE	S1,CIPI.2		;JUMP IF NONE
	AOBJN	P2,.+1			;ADVANCE POINTER
	MOVE	S1,CIPKEY(P1)		;GET KEYWORD TABLE ENTRY FOR THIS CPU
	MOVEM	S1,0(P2)		;STORE FOR PARSER
	MOVSI	S1,1			;MUST COUNT UP
	ADDM	S1,CIPTAB		; THE HEADER WORD

CIPI.2:	CAIGE	P1,CPUMAX-1		;CHECKED ALL CPUS?
	AOJA	P1,CIPI.1		;LOOP FOR ANOTHER
	MOVEI	S1,CIPTAB		;POINT TO TABLE
	MOVSI	S2,[ASCIZ /ALL-CI/]	;POSSIBLE TEXT TO ADD
	HRRI	S2,.ARCI+6		;CODE FOR ALL CI PORTS
	PUSHJ	P,ALLDEV		;ADD IF MULTIPLE CPUS

CIPI.3:	HLRZ	S1,CIPTAB		;GET NUMBER OF ENTRIES IN TABLE
	JUMPE	S1,.RETT		;RETURN IF EMPTY
	MOVEI	S1,CIPPDB		;POINT TO OUR PDB
	PUSHJ	P,COPPDB		;COPY TO WORKING STORAGE
	$RETT				;GIVE UP


; CI20 PORT PARSER DATA BLOCK
CIPPDB:	$KEY	(CONFRM##,CIPTAB,<$ALTER (.-.)>)
	BLOCK	PB%SIZ-<.-CIPPDB>


; CI20 PORT KEYWORD TABLE
CIPKEY:	KEYTAB	(.ARCI+0,<CI-0>)
	KEYTAB	(.ARCI+1,<CI-1>)
	KEYTAB	(.ARCI+2,<CI-2>)
	KEYTAB	(.ARCI+3,<CI-3>)
	KEYTAB	(.ARCI+4,<CI-4>)
	KEYTAB	(.ARCI+5,<CI-5>)
SUBTTL	Dynamic device routines -- NIPINI - CI20 ports


NIPINI:	$SAVE	<P1,P2>			;SAVE SOME ACS
	MOVEI	P1,0			;START WITH FIRST UNIT
	MOVE	P2,[-NIPMAX,,NIPTAB]	;POINTER TO STORAGE
	PUSHJ	P,KONSET		;SET UP STORAGE

NIPI.1:	MOVE	S1,P1			;GET CPU NUMBER
	LSH	S1,1			;OFFSET TO MAKE THE RIGHT GETTAB TABLE
	ADD	S1,[%CCNIP]		;FORM GETTAB FOR APPROPRIATE CPU
	GETTAB	S1,			;SEE IF THIS CPU HAS A NIA20 PORT
	  SETZ	S1,			;NOPE
	JUMPE	S1,NIPI.2		;JUMP IF NONE
	AOBJN	P2,.+1			;ADVANCE POINTER
	MOVE	S1,NIPKEY(P1)		;GET KEYWORD TABLE ENTRY FOR THIS CPU
	MOVEM	S1,0(P2)		;STORE FOR PARSER
	MOVSI	S1,1			;MUST COUNT UP
	ADDM	S1,NIPTAB		; THE HEADER WORD

NIPI.2:	CAIGE	P1,CPUMAX-1		;CHECKED ALL CPUS?
	AOJA	P1,NIPI.1		;LOOP FOR ANOTHER
	MOVEI	S1,NIPTAB		;POINT TO TABLE
	MOVSI	S2,[ASCIZ /ALL-NI/]	;POSSIBLE TEXT TO ADD
	HRRI	S2,.ARNI+6		;CODE FOR ALL NI PORTS
	PUSHJ	P,ALLDEV		;ADD IF MULTIPLE CPUS

NIPI.3:	HLRZ	S1,NIPTAB		;GET NUMBER OF ENTRIES IN TABLE
	JUMPE	S1,.RETT		;RETURN IF EMPTY
	MOVEI	S1,NIPPDB		;POINT TO OUR PDB
	PUSHJ	P,COPPDB		;COPY TO WORKING STORAGE
	$RETT				;GIVE UP


; NI PORT PARSER DATA BLOCK
NIPPDB:	$KEY	(CONFRM##,NIPTAB,<$ALTER (.-.)>)
	BLOCK	PB%SIZ-<.-NIPPDB>


; NI PORT KEYWORD TABLE
NIPKEY:	KEYTAB	(.ARNI+0,<NI-0>)
	KEYTAB	(.ARNI+1,<NI-1>)
	KEYTAB	(.ARNI+2,<NI-2>)
	KEYTAB	(.ARNI+3,<NI-3>)
	KEYTAB	(.ARNI+4,<NI-4>)
	KEYTAB	(.ARNI+5,<NI-5>)
SUBTTL	Dynamic device routines -- ALLDEV - Add "ALL" keyword


; ROUTINE TO CHECK IF "ALL" MAY BE USED AND ADD THE "ALL" ENTRY TO
; THE DYNAMICALLY BUILT TABLE
; CALL:	MOVE	S1, KEYWORD TABLE ADDRESS
;	MOVE	S2, ADDRESS OF "ALL" KEYWORD TEXTR

ALLDEV:	MOVE	TF,[%CNCPU]		;GETTAB ARGUMENT
	SKIPE	DEVFLG			;SKIP IF DISALLOWING ALL-XXX
	GETTAB	TF,			;FIND OUT HOW MANY CPUS
	  MOVEI	TF,1			; THE MONITOR IS BUILT FOR
	CAILE	TF,1			;MORE THAN ONE?
	$CALL	S%TBAD			;ADD THE "ALL" KEYWORD TO THE TABLE
	POPJ	P,			;PROPAGATE TRUE/FALSE RETURN BACK
SUBTTL	Dynamic device routines -- ALLCPU - Add "ALL-CPUS" keyword


; ACTION/PREFILL ROUTINE TO ADD "ALL-CPUS" TO THE CPU KEYWORD LIST
; CALL:	MOVE	S1, COMMAND TREE REENTRY ADDRESS
;	PUSHJ	P,ALLCPU

ONECPU:	TDZA	S2,S2			;ONE CPU
ALLCPU:	MOVEI	S2,1			;ALL CPUS
	PUSH	P,S1			;SAVE COMMAND TREE REENTRY POINT
	MOVE	S1,[Z.DEVB,,Z.DEVB+1]	;SET UP BLT
	SETZM	Z.DEVB			;CLEAR FIRST WORD
	BLT	S1,Z.DEVE-1		;CLEAR ENTIRE BLOCK
	MOVEM	S2,CPUFLG		;SET FLAG
	MOVEI	S1,DEVPDB		;GET ADDRESS OF FIRST PDB STORAGE
	MOVEM	S1,PDBPTR		;SAVE
	PUSHJ	P,CPUINI		;INIT DYNAMIC TABLE
	MOVE	S1,PDBPTR		;POINT TO PDB FOR CPU NAMES
	CAIN	S1,DEVPDB		;MORE THAN ONE CPU?
	JRST	NOCPUK			;NO CPU KEYWORDS
	POP	P,S2			;GET COMMAND TREE REENTRY POINT
	MOVEM	S2,-PB%SIZ+1+PB%ERR(S1)	;LINK LAST BACK TO NEXT PDB
	AOS	S2			;OFFSET
	MOVEM	S2,-PB%SIZ+1(S1)	;LINK LAST BACK TO TREE
	$RETT				;YES--DONE
NOCPUK:	POP	P,S1			;GET COMMAND TREE REENTRY POINT
	HRLZ	S2,S1			;STARTING ADDRESS
	HRRI	S2,DEVPDB		;WHERE TO STORE
	HLRZ	S1,(S1)			;GET LENGTH OF PDB
	ADDI	S1,DEVPDB		;CPMPUTE END OF BLT
	BLT	S2,-1(S1)		;COPY THE PDB
	$RETT				;RETURN
SUBTTL	Dynamic device routines -- COPPDB - Copy PDBs


; ROUTINE TO COPY A STATIC PDB TO WORKING STORAGE
; CALL:	MOVE	S1, ADDRESS OF STATIC PDB
;	PUSHJ	P,COPPDB

COPPDB:	PUSH	P,S1			;SAVE STATIC PDB ADDRESS
	MOVE	S1,PDBPTR		;GET FIRST FREE PDB ADDRESS
	MOVEI	S2,PB%SIZ(S1)		;COMPUTE END OF BLT
	HRL	S1,(P)			;MAKE A BLT POINTER
	BLT	S1,-1(S2)		;COPY PDB INTO THE PARSE TABLES
	MOVEM	S2,PDBPTR		;UPDATE
	POP	P,S1			;PHASE STACK
	POPJ	P,			;RETURN
SUBTTL	Dynamic device routines -- KONSET - Set up a kontroller table


KONSET:	HLRE	S2,P2			;GET -NUMBER OF KONTROLLERS
	MOVMM	S2,(P2)			;SAVE AT HEAD OF TABLE
	MOVSI	S1,1(P2)		;POINT TO FIRST DATA WORD IN TABLE
	HRRI	S1,2(P2)		;MAKE A BLT POINTER
	MOVMS	S2			;MAKE WORD COUNT POSITIVE
	LSH	S2,1			;TIMES TWO
	ADDI	S2,1(P2)		;COMPUTE END OF BLT
	BLT	S1,-1(S2)		;CLEAR STORAGE
	POPJ	P,			;RETURN
SUBTTL	Dynamic device routines -- KONCHK - Check for valid kontollers


; CHECK KONTROLLER AGAINST THE LIST OF LEGAL TYPES POINTED TO BY S1
KONCHK:	JUMPE	S1,.RETT		;RETURN IF NONE TO CHECK AGAINST
	CAME	S2,(S1)			;MATCH?
	AOBJN	S1,.-1			;LOOP
	JUMPGE	S1,.RETF		;JUMP IF POINTER RAN OUT
	$RETT				;RETURN
SUBTTL	Dynamic device routines -- KONNAM - Build kontroller names


; CONVERT KONTROLLER NAME TO ASCII AND INSERT INTO TABLE
KONNAM:	HLLZ	S2,P1			;COPY SIXBIT WORD

KONN.1:	LSHC	S1,6			;SHIFT IN A CHARACTER
	ANDI	S1,77			;STRIP OFF JUNK
	ADDI	S1," "			;CONVERT TO ASCII
	LSH	S1,35			;LEFT JUSTIFY
	LSHC	TF,7			;APPEND
	JUMPN	S2,KONN.1		;LOOP
	LSH	TF,7+7+1		;LEFT JUSTIFY
	MOVE	S2,P2			;POINT TO STORAGE
	HRRZ	S1,(S2)			;GET NUMBER OF ENTRIES
	ADDI	S2,1(S1)		;OFFSET TO NAME STORAGE

KONN.2:	SKIPN	(S2)			;ENTRY IN USE?
	JRST	KONN.3			;NO--GO ADD
	CAME	TF,(S2)			;ALREADY THERE?
	AOBJN	S2,KONN.2		;KEEP SEARCHING
	$RETT				;DON'T ADD DUPLICATE ENTRIES

KONN.3:	MOVEM	TF,(S2)			;SAVE KONTROLLER NAME
	HRRZ	S1,P2			;GET KEYWORD TABLE ADDRESS
	HRLZS	S2			;LH = THE ASCII STRING ADDRESS
	HLR	S2,P1			;RH = 3 CHARACTER SIXBIT KONT NAME
	$CALL	S%TBAD			;ADD THIS ENTRY
	POPJ	P,			;PROPAGATE TRUE/FALSE RETURN BACK
	SUBTTL	CNFHLP - Help action routine

CNFHLP:	MOVEI	S1,HELPFD		;POINT TO HELP FILE FD
	HLRO	S2,@CR.RES(S2)		;GET ADDRESS OF KEYWORD TEXT
	PUSHJ	P,P$HELP##		;READ AND TYPE HELP FILE
	PUSHJ	P,P$NPRO##		;NO PROCESSING NEEDED
	$RETT				;RETURN

HELPFD:	$BUILD	(FDMSIZ)		;SIZE OF BLOCK
	  $SET	(.FDLEN,FD.LEN,FDMSIZ)	;LENGTH OF FD
	  $SET	(.FDLEN,FD.TYP,.FDNAT)	;FILE SPEC TYPE (NATIVE)
	  $SET	(.FDSTR,,<'HLP   '>)	;ERSATZ DEVICE HLP:
	  $SET	(.FDNAM,,<'CONFIG'>)	;FILE NAME
	  $SET	(.FDEXT,,<'HLP   '>)	;EXTENSION
	$EOB				;END OF BLOCK
	SUBTTL	Set up Disk Database

SETDSK::SKIPE	S1,DSKLST	;IS THERE A LIST HANDLE?
	$CALL	L%DLST		;YES, DELETE THE LIST
	$CALL	L%CLST		;CREATE A NEW LIST
	MOVEM	S1,DSKLST	;SAVE THE HANDLE

	SETZ	T1,		;START WITH FIRST UNIT
SDSK.1:	SYSPHY	T1,		;GET NEXT PHYSICAL UNIT
	STOPCD	(SUE,HALT,,<SYSPHY UUO error>)
	JUMPE	T1,.RETT	;DONE IF ZERO RETURNED
	MOVE	S1,T1		;COPY UNIT NAME
	$CALL	BLDENT		;BUILD ENTRY FOR THIS GUY
	SKIPE	S1,DCHBLK+.DCALT ;SECOND PORT?
	$CALL	BLDENT		;YES, BUILD AN ENTRY FOR THAT ALSO
	JRST	SDSK.1		;LOOP FOR OTHERS
;Routine to build entries in the disk database
;(Entry format is in ORNMAC)

BLDENT:	MOVEM	S1,DCHBLK+.DCNAM ;FOR DSKCHR
	MOVE	S1,DSKLST	;GET LIST HANDLE
	MOVEI	S2,.DDLEN	;LENGTH OF DISK DATABASE ENTRY
	$CALL	L%CENT		;CREATE A NEW ENTRY
	SKIPT			;MAKE SURE IT WORKED
	STOPCD	(CCD,HALT,,<Can't create entry for disk database>)
	MOVE	S1,[.DCMAX,,DCHBLK] ;POINT AT ARGUMENTS
	DSKCHR	S1,		;ASK MONITOR ABOUT IT
	STOPCD	(DUE,HALT,,<DSKCHR UUO error for unit found in DCHBLK+.DCNAM>)
	MOVEM	S1,.DDSTS(S2)	;SAVE STATUS FLAGS
	MOVE	S1,DCHBLK+.DCUPN ;UNIT PHYSICAL NAME
	MOVEM	S1,.DDNAM(S2)	;SAVE IT
	MOVE	S1,DCHBLK+.DCSNM ;GET STRUCTURE NAME UNIT BELONGS TO
	MOVEM	S1,.DDSNM(S2)	;SAVE IT
	MOVE	S1,DCHBLK+.DCULN ;UNIT LOGICAL NAME
	MOVEM	S1,.DDULN(S2)	;SAVE IT
	MOVE	S1,DCHBLK+.DCALT ;GET SECOND PORT
	MOVEM	S1,.DDALT(S2)	;SAVE IT
	MOVE	S1,DCHBLK+.DCXCH ;GET EXTENDED UNIT CHARACTERISTICS
	MOVEM	S1,.DDXCH(S2)	;SAVE THEM
	MOVX	S1,.DIAKU	;DIAG. UUO FUNCTION
	MOVEM	S1,DIABLK+0	;SAVE IT
	MOVE	S1,.DDNAM(S2)	;GET UNIT PHYSICAL NAME
	MOVEM	S1,DIABLK+1	;SAVE IT
	MOVE	S1,[-2,,DIABLK]	;POINT AT ARGUMENTS
	DIAG.	S1,		;ASK FOR INFO
	  SETZ	S1,		;ERROR
	MOVEM	S1,.DDCTL(S2)	;SAVE IT
	$RETT			;ALL WE NEED FOR NOW
;Helpful debugging routine to print all known disk units

LSTDSK:	MOVE	S1,DSKLST	;GET LIST HANDLE
	$CALL	L%FIRST		;GET FIRST ENTRY
LDSK.1:	$RETIF			;RETURN IF AT END
	$TEXT	(K%BOUT,<Unit ^W/.DDNAM(S2)/ CPU mask ^O2/.DDXCH(S2),DC.XCA/>)
	$CALL	L%NEXT		;GET NEXT UNIT
	JRST	LDSK.1		;TRY FOR MORE
	SUBTTL	End of CNFCMD

	END