Google
 

Trailing-Edge - PDP-10 Archives - BB-JR93N-BB_1990 - 10,7/galaxy/operat/cnfhdw.mac
There are 9 other files named cnfhdw.mac in the archive. Click here to see a list.
TITLE	CNFHDW - Display System Hardware Configuration for CNFORN
SUBTTL	Joseph A. Dziedzic /JAD/RJF		11-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.


	SEARCH	GLXMAC, ORNMAC, BTSPRM
	SALL
	PROLOG	(CNFHDW)

	.TEXT	"/LOCALS"

	ENTRY	CNFHDW
	EXTERN	WTIRTN		;INTERNAL APPLICATION MULTI-PART WTO ROUTINE


;Conditional assembly switches

ND	FTLMEM,0		;NON-ZERO TO LIST LOGICAL MEMORY CONFIGURATION
ND	FTLCFE,-1		;NON-ZERO TO LIST CFE DEVICE CONFIGURATION
ND	FTLUBA,0		;NON-ZERO TO LIST UBA CONFIGURATION
	SUBTTL	Parameters


;AC assignments

	F=.A13			;FLAGS (DEFINITION SHOULD MATCH CNFORN)


;Flags for call to CTLNAM

	CN.MUK==1B0		;MULTI-UNIT CONTROLLER
	CN.TAP==1B1		;TAPE IF SET, ELSE DISK

;APRID results (ID.xxx = KL/KS, LD.xxx = KL, SD.xxx = KS)

	ID.XUC==1B2		;EXOTIC (NON-STANDARD) MICROCODE
	ID.UVN==777B17		;MICROCODE VERSION
	LD.CSH==1B19		;CACHE
	LD.CHN==1B20		;INTERNAL CHANNELS
	LD.MPV==1B21		;EXTENDED KL10 (MODEL PV CPU)
	LD.MOS==1B22		;MOS MASTER OSCILLATOR
	LD.MCA==1B23		;MCA25


;RSX-20F-related

	.VERNO==1036		;-20F VERSION STRING LOCATION IN STATUS BLOCK
	.VERLN==9		;LENGTH OF VERSION STRING

	.KLRLD==1172		;-20F RELOAD FLAG
	.KLFCF==1173		;-20F FAULT-CONTINUATION FLAG
	.KACFL==1420		;-20F RETRY FLAG

	.FEMAX==40		;MAXIMUM DATA BYTES -20F ALLOWS FOR ME MESSAGE
	.IORLB==1000		;FUNCTION CODE
	.IOVER==-4		;NXM ERROR
	MSK16B==177777		;16 BIT ADDRESS MASK FOR $TEXT


;KS10 junk

	RLWORD==31		;WHERE IT IS
	    CSHENB==1B10	    ;CACHE ENABLED IF SET
	MAXUBA==10		;MAXIMUM NUMBER OF UNIBUS ADAPTERS
	UNBSTW==763100		;UNIBUS ADAPTER STATUS REGISTER
	    STWHPI==70		    ;MASK FOR HIGH PI ASSIGNMENT
	    STWLPI==7		    ;MASK FOR LOW PI ASSIGNMENT


;Logical memory configuration parameters

IFN FTLMEM,<
	.SBNMC==40		;NUMBER OF MEMORY CONTROLLERS
	.MXPCS==^D128		;MAXIMUM NUMBER OF "PIECES" OF MEMORY
	MS.DES==1B14		;SBDIAG FUNCTION 12 DESELECT FLAG
	MS.SIZ==3B11		;SBDIAG FUNCTION 2 MF/MG CHIP SIZE FIELD
	.CS16K==40000		;16K CHIP SIZE
	.CS64K==200000		;64K CHIP SIZE

;Memory controller types

	.MCCST==0		;CUSTOMER
	.MCMA2==1		;MA20 INTERNAL CORE MEMORY
	.MCDMA==2		;DMA20 EXTERNAL MEMORY
	.MCMB2==3		;MB20 INTERNAL CORE MEMORY
	.MCMF2==5		;MF20 INTERNAL MOS MEMORY
	.MCMG2==^D16		;MG20 INTERNAL MOS MEMORY (KLUDGED UP VALUE)
>; END IFN FTLMEM


;Miscellaneous

	MAXNDS==20		;MAXIMUM NUMBER OF NODES ON CI NETWORK

	.SSMAX==100		;SIZE OF SCS. UUO ARGUMENT BLOCK

	RCLBFL==5		;LENGTH OF READ CHANNEL LIST BUFFER
	RCIBFL==5		;LENGTH OF READ CHANNEL INFO BUFFER
	RKLBFL==5		;LENGTH OF READ KONTROLLER LIST BUFFER
	RKIBFL==10		;LENGTH OF READ KONTROLLER INFO BUFFER

	UCDNUM==^D20		;MAXIMUM NUMBER OF CONTROLLER MICROCODES

	STGLEN==20		;LENGTH OF TEMPORARY STRING BLOCK
	STGCHR==<STGLEN*5>-1	;DITTO, IN CHARS
	SUBTTL	Data segment


	$DATA	TMPSTG,STGLEN	;TEMPORARY BLOCK FOR CONVERTING TEXT STRINGS
	$DATA	STGBPT		;BYTE POINTER INTO ABOVE
	$DATA	STGCNT		;CHARS LEFT IN ABOVE

	$DATA	NCPUS		;NUMBER OF CPUS IN SYSTEM CONFIGURATION
	$DATA	MLTCPU		;NON-ZERO IF MORE THAN ONE CPU IN CONFIGURATION
	$DATA	CPUPTR		;AOBJN POINTER TO LOOP THROUGH CPUS
	$DATA	CPUSTS,6	;STATUS OF CPU - .LE. ZERO IF OK

	$DATA	KLFLAG		;NON-ZERO IF KL10 SYSTEM
	$DATA	APRID		;SAVED APRID

	$DATA	DTESTS		;DTE STATUS (0=DOWN, 1=UP)
	$DATA	DTETYP		;NODE TYPE AND NUMBER
	$DATA	DTENAM		;SOFTWARE NAME
	$DATA	DTE20F		;NON-ZERO IF RSX-20F ALIVE

				;*** KEEP IN ORDER ***
	$DATA	DTEBLK,2	;DTE. UUO BLOCK
	$DATA	FEBUF		;FE: DATA
	$DATA	VERBUF,<<.VERLN+4>/5> ;VERSION STRING BUFFER
				;*** END OF KEEP IN ORDER ***
	$DATA	FEMSG,<<<14+.FEMAX>+3>/4> ;MESSAGE FOR FRONT END
	$DATA	RLDFCF		;RELOAD AND FAULT-CONTINUATION WORD
	$DATA	RTYWRD		;RETRY WORD

	$DATA	NWCORE		;NUMBER OF WORDS OF CONFIGURED MEMORY
	$DATA	MEMSIZ		;NUMBER OF WORDS OF MEMORY ONLINE
	$DATA	NXMPTR		;AOBJN POINTER TO OUR COPY OF NXMTAB

	$DATA	DIABLK,7	;DIAG. UUO BLOCK

	KONBKL==5		;LENGTH OF BLOCK
	$DATA	KONBLK,KONBKL	;KONTROLLER INFO RETURNED HERE
	UNIBKL==6		;LENGTH OF BLOCK
	$DATA	UNIBLK,UNIBKL	;UNIT INFO RETURNED HERE
	MXPORT==4		;LENGTH OF BLOCK
	$DATA	KDBTBL,MXPORT	;KDB TABLE FOR UNITS

	$DATA	DCHBLK,.DCMAX	;DSKCHR UUO BLOCK

	$DATA	DVPBLK,2	;DVPHY. UUO BLOCK
	$DATA	TOPBLK,2	;TAPOP. UUO BLOCK

	$DATA	CPULNN,6	;LOCAL NODE NUMBER

	$DATA	SCSBLK,.SSMAX	;FOR DOING SCS. UUO

	$DATA	PTHSTS,MAXNDS	;PATH STATUS FOR EACH NODE AND EACH CPU

	$DATA	RCNBLK,<2+2*UCDNUM> ;FOR DOING RECON. TO READ BOOTSTRAP UCODE

	$DATA	ENTBLK,<.ETAR2+1> ;FOR DOING ETHNT. UUO
	$DATA	RCLBUF,RCLBFL	;READ CHANNELS LIST
	$DATA	RCIBUF,RCIBFL	;READ CHANNEL INFORMATION
	$DATA	RKLBUF,RKLBFL	;READ KONTROLLER LIST
	$DATA	RKIBUF,RKIBFL	;READ KONTROLLER INFORMATION
IFN FTLMEM,<
	$DATA	MEMCTP		;-VE NUMBER OF MEMORY CONTROLLERS ON CPU,,0
	$DATA	MEMCTN,.SBNMC	;MEMORY CONTROLLER NUMBER
	$DATA	STATS0		;FROM-MEMORY WORD FROM FUNCTION 0
	$DATA	STATS1		;FROM-MEMORY WORD FROM FUNCTION 1

	$DATA	PIECES		;NUMBER OF "PIECES" OF MEMORY (VS CONTROLLERS)
				;FOLLOWING DATA INDEXED BY "PIECE" NUMBER
	$DATA	CONTNO,.MXPCS	;CONTROLLER NUMBER
	$DATA	ADDRES,.MXPCS	;LOWER-BOUND ADDRESS
	$DATA	SIZE,.MXPCS	;SIZE (WORDS)
	$DATA	RQS,.MXPCS	;REQUESTORS
	$DATA	CONTYP,.MXPCS	;CONTROLLER TYPE (MEMCTN REPLICATED HERE)
	$DATA	INTRLV,.MXPCS	;INTERLEAVING
	$DATA	CHIPSZ		;MEMORY CHIP SIZE
>; END IFN FTLMEM
	SUBTTL	Here it starts

CNFHDW::MOVE	F,S1		;SAVE CONTROL FLAGS
	MOVX	T1,%CNCPU	;NUMBER OF CPU'S IN SYSTEM
	GETTAB	T1,		;ASK
	  HALT	.		;ERROR
	MOVEM	T1,NCPUS	;SAVE FOR TESTS
	SETZM	MLTCPU		;ASSUME JUST ONE CPU
	CAIE	T1,1		;THAT RIGHT?
	SETOM	MLTCPU		;NOPE
	MOVNS	T1		;MAKE AN AOBJN POINTER
	HRLZM	T1,CPUPTR	;SAVE FOR LATER USE
	$CALL	.CPUTY		;GET CPU TYPE
	CAXE	S1,%KL10	;KL-10?
	TDZA	S1,S1		;NO
	SETO	S1,		;YES
	MOVEM	S1,KLFLAG	;SAVE FOR LATER TESTS
	PUSHJ	P,DOLIST	;DO THE WORK
	PJRST	WTIFLS##	;FLUSH LAST MESSAGE AND RETURN


DOLIST:	$SAVE	<P1,P2,P3,P4>	;SAVE THE AC'S WE STOMP

	TXNE	F,HW.DTE!HW.UBA!HW.CPU	;DTE OR CPU INFO?
	PUSHJ	P,CPU		;LIST CPU CONFIGURATION
	TXNE	F,HW.MME	;MEMORY INFO?
	PUSHJ	P,MEMORY	;LIST MEMORY CONFIGURATION
	TXNE	F,HW.CTM	;CONTROLLER MICROCODES?
	PUSHJ	P,CTM		;LIST CONTROLLER MICROCODES
	TXNE	F,HW.CI		;CI INFO?
	PUSHJ	P,CI		;LIST CI CONFIGURATION
	TXNE	F,HW.NI		;NI INFO?
	PUSHJ	P,NI		;LIST NI CONFIGURATION
	TXNE	F,HW.DSK	;DISK INFO?
	PUSHJ	P,DISK		;LIST DISK CONFIGURATION
	TXNE	F,HW.TAP	;TAPE INFO?
	PUSHJ	P,TAPE		;LIST TAPE CONFIGURATION
	TXNE	F,HW.TAP	;DECTAPE INFO?
	PUSHJ	P,DECTAP	;LIST DECTAPE CONFIGURATION
	TXNE	F,HW.URC	;UNIT RECORD INFO?
	PUSHJ	P,UNTRCD	;LIST UNIT RECORD DEVICES

	POPJ	P,		;DONE
	SUBTTL	List CPU Configuration

CPU:	$TEXT	(WTIRTN,<CPU Configuration^M^J>)
	MOVE	P1,CPUPTR	;GET AOBJN POINTER
CPU.1:	SETZM	CPUSTS(P1)	;ASSUME CPU IS RUNNING
	SKIPN	MLTCPU		;SKIP IF SMP CONFIGURATION
	JRST	CPU.3		;DON'T BOTHER WITH SET RUN, ETC., IF NOT SMP
	$TEXT	(WTIRTN,<CPU^D/P1,RHMASK/^A>) ;YES, IDENTIFY WHICH CPU
	MOVX	T1,%CCOKP	;GET CPU OK WORD
	PUSHJ	P,CPUGTB	;DO CPU-SPECIFIC GETTAB
	MOVEM	T1,CPUSTS(P1)	;SAVE FOR LATER CHECKS
	MOVX	T1,%CVRUN	;GET OPR-CONTROLLED CPU STATUS
	PUSHJ	P,CPUGTB	;DO CPU-SPECIFIC GETTAB
	SKIPG	CPUSTS(P1)	;CPU APPEAR TO BE RUNNING?
	JRST	CPU.2		;YES
	$TEXT	(WTIRTN,< is not running^A>)
	MOVEI	T2,[0]		;NULL TEXT ADDRESS
	TXNE	T1,CV%DET	;DETACHED?
	MOVEI	T2,[ASCIZ / (detached)/] ;GET TEXT
	TXNE	T1,CV%RMV	;REMOVED?
	MOVEI	T2,[ASCIZ / (removed)/] ;GET TEXT
	$TEXT	(WTIRTN,<^T/0(T2)/>)	;END THE LINE
	JRST	CPU.N		;NEXT GUY

CPU.2:	TXNN	T1,CV%RUN	;CAN CPU RUN JOBS?
	TDZA	T1,T1		;YES, GET A ZERO
	MOVE	T1,[ASCIZ /not /]
	$TEXT	(WTIRTN,< is running and ^5/T1/scheduling jobs>)
CPU.3:	MOVE	T1,[-2,,T2]	;ASK CPU TO FILL IN CPU STATUS BLOCK
	MOVX	T2,.DIACS	;FUNCTION
	HRRZ	T3,P1		;CPU NUMBER
	DIAG.	T1,		;ASK MONITOR
	  JFCL			;HOPE THE INFO IS UP TO DATE
	MOVEI	T2,[ASCIZ /KL10/] ;ASSUME A KL
	SKIPN	KLFLAG		;CORRECT GUESS?
	MOVEI	T2,[ASCIZ /KS10/]
	$TEXT	(WTIRTN,<  ^T/0(T2)/^A>)
	MOVX	T1,%CCCSB	;GETTAB FOR CPU STATUS BLOCK SUB-TABLE
	MOVX	T2,%CVSAI	;OFFSET IN TABLE = APRID
	PUSHJ	P,CPUSTB	;DO CPU-SPECIFIC SUBTABLE GETTAB
	MOVEM	T1,APRID	;SAVE RESULTS
	SKIPN	KLFLAG		;KL10?
	JRST	CPU.4		;NO, KS10 DOESN'T HAVE DIFFERENT CPU TYPES
	LOAD	T1,APRID,LD.MPV	;GET PV CPU FLAG
	MOVEI	T1,"A"(T1)	;MODEL A IF ZERO, MODEL B IF ONE
	$TEXT	(WTIRTN,< model ^7/T1/^A>) ;FLAG CPU TYPE
CPU.4:	MOVX	T1,%CCSER	;GETTAB FOR CPU SERIAL NUMBER
	PUSHJ	P,CPUGTB	;DO CPU-SPECIFIC GETTAB
	MOVE	T2,APRID	;GET APRID
	TXNE	T2,ID.XUC	;EXOTIC MICROCODE?
	SKIPA	T2,[[ASCIZ /exotic /]] ;YES, GET IDENTIFIER
	MOVEI	T2,[ASCIZ //]	;NO
	$TEXT	(WTIRTN,< serial number ^D/T1/, ^T/(T2)/microcode version ^O/APRID,ID.UVN/>)
	SKIPN	KLFLAG		;KL10?
	JRST	CPUS.1		;NO, DO KS-SPECIFIC STUFF
	MOVE	P2,APRID	;GET APRID HERE FOR EASY TESTING
	TXNN	P2,LD.CSH!LD.CHN!LD.MPV!LD.MOS!LD.MCA ;ANY GOOD H/W OPTIONS?
	JRST	CPL.4		;NOPE, NON-INTERESTING CPU
	$TEXT	(WTIRTN,<  Hardware options:^A>)
	SETZ	P3,		;START A NEW LINE
	MOVSI	P4,-HWOPTL	;-VE LENGTH OF TABLE
CPL.1:	HLRZ	T1,HWOPTS(P4)	;GET OPTIONS BIT ADDRESS
	TDNN	P2,(T1)		;CHECK IF SET
	JRST	CPL.3		;NOPE
	SOJGE	P3,CPL.2	;JUMP IF STILL SOME ROOM ON LINE
	$TEXT	(WTIRTN,<^M^J  ^A>) ;WRAP THE LINE
	MOVEI	P3,2		;RESET COLUMN COUNT
CPL.2:	HRRZ	T1,HWOPTS(P4)	;GET TEXT STRING ADDRESS
	$TEXT	(WTIRTN,<  ^T/0(T1)/^A>) ;PRINT THE TEXT
CPL.3:	AOBJN	P4,CPL.1	;LOOP FOR ALL H/W OPTS
	$TEXT	(WTIRTN,<>)	;END THE LINE
CPL.4:	MOVX	T1,%CCCSB	;GETTAB FOR CPU STATUS BLOCK SUB-TABLE
	MOVX	T2,%CVSPC	;OFFSET IN TABLE = CONI PAG,
	PUSHJ	P,CPUSTB	;DO CPU-SPECIFIC SUBTABLE GETTAB
	ANDI	T1,600000	;KEEP JUST CACHE BITS
	LSH	T1,-^D16	;RIGHT-JUSTIFY THEM
	TRNE	P2,LD.CSH	;DON'T PRINT IF MACHINE WITHOUT CACHE
	$TEXT	(WTIRTN,<  Cache status:  ^T/@CSHSTS(T1)/>)
	TRNN	P2,LD.CHN	;KL10 WITH INTERNAL CHANNELS?
	JRST	CPL.8		;NOPE, DON'T BOTHER WITH THIS
	$TEXT	(WTIRTN,<  Internal channels:^M^J  ^A>)
	MOVSI	P2,-10		;SET TO LOOP THROUGH INTERNAL CHANNELS
CPL.5:	MOVX	T1,%CCCSB	;GETTAB FOR CPU STATUS BLOCK SUB-TABLE
	MOVEI	T2,%CVSRD(P2)	;OFFSET IN TABLE = CONI RHN,
	PUSHJ	P,CPUSTB	;DO CPU-SPECIFIC SUBTABLE GETTAB
	JUMPGE	T1,CPL.6	;JUMP IF RH20 OR NOTHING CONNECTED
;WISH WE COULD REALLY DISTINGUISH BETWEEN NIA AND CI, BUT WE CAN'T
;(LOUSY DESIGNERS NEVER MADE THE DISTINCTION IN THE DEVICE TYPE
;FIELD IN THE CONI).  ASSUME NIA20 ON CHANNEL 5, CI20 ON CHANNEL 7.
	TRNE	P2,2		;CHANNEL 7?
	SKIPA	T1,[[ASCIZ /CI20/]] ;YES
	MOVEI	T1,[ASCIZ /NIA20/] ;NO
	JRST	CPL.7		;FINISH UP
CPL.6:	SKIPE	T1		;ANYTHING THERE?
	SKIPA	T1,[[ASCIZ /RH20/]] ;YES
	MOVEI	T1,[ASCIZ |N/C|] ;NO
CPL.7:	$TEXT	(WTIRTN,<  ^O/P2,RHMASK/: ^T6/0(T1)/^A>)
	HRRZ	T1,P2		;GET CHANNEL NUMBER JUST LISTED
	CAIN	T1,3		;CHANNEL 3?
	$TEXT	(WTIRTN,<^M^J  ^A>) ;YES, ADVANCE TO NEW LINE
	AOBJN	P2,CPL.5	;LOOP FOR REMAINING CHANNELS
	$TEXT	(WTIRTN,<>)	;END THE FINAL LINE
CPL.8:	$TEXT	(WTIRTN,<  DTE configuration:>)
	MOVSI	P2,-4		;SET TO LOOP THROUGH DTE20S
	MOVX	P3,C1.1NF	;NEW FORMAT CAL11. ARGUMENT BLOCK
	MOVX	T1,.C11DT	;TYPE IS DTE20
	STORE	T1,P3,C1.1TY
	STORE	P1,P3,C1.1CN	;STUFF CPU NUMBER
CPL.9:	SETOM	DTESTS		;ASSUME NON-EXISTANT
	STORE	P2,P3,C1.1PN	;STUFF PORT NUMBER
	MOVX	T1,.C11UP	;RETURN UP/DOWN STATUS
	STORE	T1,P3,C1.1FC	;STUFF FUNCTION
	MOVE	T1,[1,,P3]	;POINT AT ARGUMENTS
	CAL11.	T1,		;ASK ABOUT THE DTE
	  JRST	[CAXN	T1,C11IP% ;INVALID PORT NUMBER?
		 JRST	CPL.10	;YES, MAKE DUE WITH WHAT WE HAVE
		 SETZ	T1,	;NO, GET A ZERO
		 JRST	.+1]	;CONTINUE
	MOVEM	T1,DTESTS	;SAVE STATUS
	MOVX	T1,.C11TY	;READ NODE TYPE AND NUMBER
	STORE	T1,P3,C1.1FC	;STUFF FUNCTION
	MOVE	T1,[1,,P3]	;POINT AT ARGUMENTS
	CAL11.	T1,		;ASK ABOUT THE DTE
	  SETZ	T1,		;ASSUME NONE
	MOVEM	T1,DTETYP	;SAVE TYPE STUFF
	MOVX	T1,.C11NM	;GET SOFTWARE NAME
	STORE	T1,P3,C1.1FC	;STUFF FUNCTION
	MOVE	T1,[1,,P3]	;POINT AT ARGUMENTS
	CAL11.	T1,		;ASK ABOUT THE DTE
	  SETZ	T1,		;ASSUME NONE
	MOVEM	T1,DTENAM	;SAVE SOFTWARE NAME
	SKIPE	DTESTS		;UP?
	SKIPA	T1,[[ASCIZ /up/]]
	MOVEI	T1,[ASCIZ /down/]
	SKIPA			;SKIP ENTRY
CPL.10:	MOVEI	T1,[ASCIZ /non-existant/]
	$TEXT	(WTIRTN,<    DTE^O/P2,RHMASK/:  ^T/0(T1)/^A>)
	SKIPG	DTESTS		;UP AND RUNNING?
	JRST	CPL.13		;NOPE
	HRRZ	T1,DTETYP	;GET SOFTWARE TYPE
	SKIPN	T2,DTENAM	;KNOW THE SOFTWARE?
	MOVSI	T2,'???'	;DUH?
	$TEXT	(WTIRTN,<  ^T/@DTTYTB(T1)/ running ^W/T2/^A>)
	CAXN	T1,.C1CFE	;CONSOLE FRONT END?
	JRST	CPL.11		;YES
	CAXN	T1,.C1D60	;DN60?
	JRST	CPL.13		;YES, NO ASSOCIATED NODE NUMBER
	MOVE	T1,DTETYP	;GET SOFTWARE TYPE AND NODE NUMBER
	TLZN	T1,-1		;HAVE A NODE NUMBER?
	JRST	CPL.13		;NOPE
	MOVEI	T2,ANFNOD	;ASSUME ANF10 NODE
	CAXN	T1,.C1MCB	;AN MCB?
	MOVEI	T2,DCNNOD	;YES, DECNET
	PUSHJ	P,(T2)		;GET NODE NAME
	  JRST	CPL.13		;NO INFO?
	$TEXT	(WTIRTN,< node ^W/T1/(^I/0(T2)/)^A>)
	JRST	CPL.13		;FINISH UP

CPL.11:	HRRZ	T1,DTETYP	;GET TYPE OF FRONT END
	CAIE	T1,.C1CFE	;RSX-20F?
	JRST	CPL.13		;NO
	HRLZ	T1,P1		;COPY CPU NUMBER
	HRR	T1,P2		; AND DTE NUMBER
	SETOM	DTE20F		;ASSUME -20F IS ALIVE
	PUSHJ	P,OPENFE	;OPEN UP AN "FE" DEVICE
	  JRST	[SETZM DTE20F	;LOOKS LIKE -20F ISNT RUNNING
		 JRST	CPL.13]	;DON'T TRY TO TALK TO THE FE
	PUSHJ	P,GETFED	;GET FE DATA
	  JRST	CPL.12		;NOT AVAILABLE
	$TEXT	(WTIRTN,< version ^T/VERBUF/>)
	LDB	T1,[POINT 1,RLDFCF,35] ;GET OFF(1) ON(0) FLAG
	$TEXT	(WTIRTN,<           Reload enable: ^T/ONOFF(T1)/^A>)
	LDB	T1,[POINT 1,RTYWRD,35] ;GET ON(1) OFF(0) FLAG
	TRC	T1,1		;COMPLEMENT IT
	$TEXT	(WTIRTN,<  Retry enable: ^T/ONOFF(T1)/^A>)
	LDB	T1,[POINT 1,RLDFCF,35-8] ;GET OFF(1) ON(0) FLAG
	$TEXT	(WTIRTN,<  Fault-continuation: ^T/ONOFF(T1)/^A>)
CPL.12:	PUSHJ	P,CLOSFE	;CLOSE THE "FE" DEVICE
CPL.13:	$TEXT	(WTIRTN,<>)	;END THE LINE
	AOBJN	P2,CPL.9	;LOOP FOR ALL 4 DTES

IFN FTLMEM,<
	PUSHJ	P,LOGMEM	;PRINT LOGICAL MEMORY CONFIGURATION
>; END IFN FTLMEM
IFN FTLCFE,<
	SKIPE	DTE20F		;RSX-20F ALIVE?
	PUSHJ	P,CFEDEV	;PRINT CFE DEVICE CONFIGURATION
>; END IFN FTLCFE
	JRST	CPU.N		;NEXT CPU
;KS10 HARDWARE STUFF HERE

CPUS.1:	MOVEI	T1,RLWORD	;KS10 RELOAD CONTROL WORD
	PEEK	T1,		;SNEAK A PEEK
	TXNN	T1,CSHENB	;IS CACHE ENABLED?
	TDZA	T1,T1		;NO, GET A ZERO AND SKIP
	MOVEI	T1,3		;YES, POINT AT "ENABLED" ENTRY IN CSHSTS
	$TEXT	(WTIRTN,<  Cache status:  ^T/@CSHSTS(T1)/>)
	$TEXT	(WTIRTN,<  UNIBUS adapters:>)
	MOVSI	P1,-MAXUBA	;MAXIMUM NUMBER OF UNIBUS ADAPTERS
	AOBJN	P1,.+1		;BUMP TO FIRST UNIBUS ADAPTER (1)
CPUS.2:	MOVE	T1,[-2,,T2]	;SET UP TO READ UNIBUS STATUS REGISTER
	MOVEI	T2,.DIRUR	;FUNCTION
	MOVS	T3,P1		;PICK UP UNIBUS ADAPTER NUMBER
	HRRI	T3,UNBSTW	;ADDRESS OF STATUS REGISTER
	DIAG.	T1,		;ASK THE MONITOR
	  JRST	CPUS.3		;ERROR, SKIP THIS
	JUMPE	T1,CPUS.3	;I DON'T THINK THIS CAN HAPPEN?
	$TEXT	(WTIRTN,<    UBA ^D/P1,RHMASK/:  High PIA: ^O/T1,STWHPI/ Low PIA: ^O/T1,STWLPI/>)
IFN FTLUBA,<
	PUSHJ	P,UBACNF	;PRINT UBA CONFIGURATION
>; END IFN FTLUBA
CPUS.3:	AOBJN	P1,CPUS.2	;LOOP FOR REMAINDER
CPU.N:	$TEXT	(WTIRTN,<>)	;BLANK LINE BETWEEN STUFF
	AOBJN	P1,CPU.1	;LOOP FOR ALL CPUS
	POPJ	P,		;RETURN
	SUBTTL	List Memory Configuration

MEMORY:	MOVX	P1,%CNNWC	;GET NUMBER OF WORDS OF MEMORY MONITOR SUPPORTS
	GETTAB	P1,		;ASK
	  HALT	.		;SHOULDN'T HAPPEN
	MOVEM	P1,NWCORE	;SAVE IT
	MOVX	T1,%NSMMS	;GET SIZE OF ONLINE MEMORY
	GETTAB	T1,		;ASK
	  HALT	.		;SHOULDN'T HAPPEN
	MOVEM	T1,MEMSIZ	;SAVE IT
	ADR2PG	P1		;CONVERT TO A NUMBER OF PAGES
	MOVE	T1,P1		;GET A COPY
	LSH	T1,-1		;CONVERT TO K
	$TEXT	(WTIRTN,<Monitor Memory Configuration^M^J^J  Monitor configured for ^D/P1/P (^D/T1/K) of physical memory>)
	MOVE	T1,NWCORE	;NUMBER OF WORDS OF CORE
	SUB	T1,MEMSIZ	;MINUS AMOUNT ONLINE = AMOUNT OFFLINE
	ADR2PG	T1		;CONVERT TO NUMBER OF PAGES
	MOVE	T2,T1		;GET A COPY
	LSH	T2,-1		;CONVERT TO K
	JUMPE	T1,.POPJ##	;NO SENSE IN PRINTING LAYOUT IF ALL ONLINE
	$TEXT	(WTIRTN,<    of which ^D/T1/P (^D/T2/K) is off-line>)
	$TEXT	(WTIRTN,<^M^J    Status    Range (P)    Range (K)^M^J    -------  -----------  ----------->)

	PUSHJ	P,SUNXMT	;SET UP NXMTAB

	MOVNS	P1		;NEGATE NUMBER OF PAGES
	HRLZS	P1		;MAKE AN AOBJN POINTER
	MOVE	P2,NXMPTR	;GET AOBJN POINTER TO OUR COPY OF NXMTAB
	SETZ	P3,		;FIRST PAGE OF RANGE WE'RE CHECKING
				; (KINDA EXPECTS PAGE ZERO IS NEVER OFFLINE)
MEM.1:	MOVE	T1,(P2)		;GET NXMTAB ENTRY
	MOVEI	T2,^D36		;BITS/WORD
MEM.2:	ROT	T1,1		;POSITION NEXT BIT TO RIGHT-MOST POSITION
	TRNE	T1,1		;PAGE OFFLINE?
	JRST	MEM.4		;YES
	TLNN	P3,400000	;PRIOR PAGES OFFLINE?
	JRST	MEM.3		;NO
	PUSHJ	P,MEM.R		;REPORT RANGE AND STATUS
	HRRZ	P3,P1		;START OF NEW RANGE
MEM.3:	AOBJP	P1,MEM.5	;DONE IF LAST PAGE
	SOJG	T2,MEM.2	;MORE IN THIS WORD?
	AOBJN	P2,MEM.1	;NO, GET NEXT WORD
	MOVE	P1,NWCORE	;DONE?  LAST PAGES MUST NOT BE IN NXMTAB
	ADR2PG	P1		; SO FAKE UP LIKE WE SCANNED EVERYTHING
	JRST	MEM.5		;REPORT LAST CHUNK

MEM.4:	TLNE	P3,400000	;PRIOR PAGES ONLINE?
	JRST	MEM.3		;NO
	PUSHJ	P,MEM.R		;REPORT RANGE AND STATUS
	HRRZ	P3,P1		;START OF NEW RANGE
	TLO	P3,400000	;REMEMBER IT'S OFFLINE
	JRST	MEM.3		;ONWARD

MEM.5:	PUSHJ	P,MEM.R		;REPORT FINAL RANGE
	POPJ	P,		;DONE

MEM.R:	TLNE	P3,400000	;PAGES OFFLINE?
	SKIPA	S1,[[ASCIZ /Offline/]] ;YES
	MOVEI	S1,[ASCIZ /Online /]
	MOVEI	S2,-1(P1)	;GET END OF RANGE
	$TEXT	(WTIRTN,<    ^T/0(S1)/  ^D4R/P3,RHMASK/ - ^D4R/S2/^A>)
	HRRZ	S1,P3		;GET START OF RANGE
	LSH	S1,-1		;CONVERT TO K
	LSH	S2,-1		;CONVERT END OF RANGE TO K
	$TEXT	(WTIRTN,<  ^D4R/S1/ - ^D4R/S2/>)
	POPJ	P,		;RETURN
	SUBTTL	List Controller Microcodes

CTM:	MOVEI	T1,2+2*UCDNUM	;LENGTH OF RECON. BLOCK
	MOVEM	T1,RCNBLK	;STORE IT
	MOVE	T1,[.RCRBM,,RCNBLK] ;POINT AT ARGUMENTS
	RECON.	T1,		;ASK MONITOR
	  SKIPA			;ERROR
	JRST	CTM.1		;SUCCESS
	CAXE	T1,RCIAL%	;FUNCTION NOT IMPLEMENTED?
	$TEXT	(WTIRTN,<?Can't determine controller microcodes>)
	$RETF			;RETURN

CTM.1:	SKIPN	P1,RCNBLK+1	;GET NUMBER OF MICROCODES
	$RETT			;NONE, ALL DONE
	$TEXT	(WTIRTN,<^M^JController Microcodes^M^J^J  Controller    Version
  ----------  ----------->)
	MOVNS	P1		;MAKE IT NEGATIVE
	HRLI	P1,RCNBLK+2	;POINT AT FIRST ONE
	MOVSS	P1		;MAKE AN AOBJN POINTER
CTM.2:	HLRZ	S1,(P1)		;GET UCODE INDEX
	MOVEI	S2,CTMTAB	;POINT AT TABLE
	$CALL	TABSRC##	;LOOK FOR IT
	SKIPT			;DID IT WORK?
	MOVEI	S2,[ASCIZ /????/] ;NOPE, LOOK DUMB
	$TEXT	(WTIRTN,<  ^T12L/0(S2)/^V11R/1(P1)/>) ;PRINT NAME AND VERSION
	ADDI	P1,1		;ACCOUNT FOR TWO-WORD ENTRIES
	AOBJN	P1,CTM.2	;LOOP FOR ALL
	$RETT

CTMTAB:	$STAB
	XWD	.BTTX1,[ASCIZ |DX10/TX01|]
	XWD	.BTTX2,[ASCIZ |DX20/TX02|]
	XWD	.BTRP2,[ASCIZ |DX20/RP20|]
	XWD	.BTKLP,[ASCIZ |CI20|]
	XWD	.BTKNI,[ASCIZ |NIA20|]
	$ETAB
	SUBTTL	List CI Configuration

CI:	PUSHJ	P,CHKCIP##	;SEE IF ANY CI PORTS IN CONFIGURATION
	$RETIF			;IF NOT, DON'T EVEN BOTHER
	MOVX	T1,%FTERR	;FEATURE TEST REGISTER
	GETTAB	T1,		;ASK MONITOR
	  SETZ	T1,		;ASSUME NOTHING USEFUL
	TRNN	T1,<F%SCA&RHMASK> ;SCA SUPPORTED?
	POPJ	P,		;NOPE
	PUSHJ	P,ZERSCS	;ZERO SCS. UUO BLOCK
	MOVE	T1,[.SQLNN+1,,.SSGLN] ;FUNCTION
	MOVEM	T1,SCSBLK+.SQFNC ;STORE IT
	MOVE	P1,CPUPTR	;AOBJN POINTER TO CPU DATA
	SETO	P2,		;ASSUME NO CI NETWORK OUT THERE
CIS.1:	SKIPLE	CPUSTS(P1)	;SKIP IF CPU IS RUNNING
	JRST	CIS.2		;NOPE
	STORE	P1,SCSBLK+.SQFNC,SS.CPU ;STORE CPU NUMBER
	XMOVEI	T1,SCSBLK	;POINT AT ARGUMENT BLOCK
	SCS.	T1,		;DO THE UUO
	  SKIPA			;ERROR, CHECK IT OUT
	JRST	CIS.3		;PROCEED
	CAXE	T1,SSNPC%	;NO CI PORT ON THIS CPU?
	CAXN	T1,SSNNK%	;OR NODE NUMBER NOT KNOWN?
	JRST	CIS.2		;YES, NOTHING TO WORRY ABOUT
	$TEXT	(WTIRTN,<?Error code ^O/T1/ from SCS. UUO>)
	POPJ	P,		;NOT MUCH ELSE TO DO

CIS.2:	SKIPA	T1,[-1]		;OK, JUST GET -1 (NEVER MATCHES)
CIS.3:	MOVE	T1,SCSBLK+.SQLNN ;GET LOCAL NODE NUMBER
	MOVEM	T1,CPULNN(P1)	;SAVE THAT
	SKIPL	T1		;A REAL NODE NUMBER?
	SETZ	P2,		;YES, REMEMBER THERE'S SOMETHING OUT THERE
	AOBJN	P1,CIS.1	;LOOP FOR ALL
	JUMPL	P2,.POPJ##	;NOTHING TO DO IF NO NODES

	$TEXT	(WTIRTN,<^M^JCI Configuration^M^J^J      Node       S/W type  S/W vers  H/W type^M^J  -------------  --------  --------  -------->)
	MOVX	S1,MAXNDS	;LENGTH OF BLOCK
	MOVEI	S2,PTHSTS	;POINT AT BLOCK
	$CALL	.ZCHNK		;ZERO IT

	PUSHJ	P,ZERSCS	;ZERO SCS. UUO BLOCK
	MOVE	T1,[.SQRPS+1,,.SSRPS] ;FUNCTION
	MOVEM	T1,SCSBLK+.SQFNC ;STORE IT
	MOVE	P1,CPUPTR	;GET AOBJN POINTER FOR CPU STUFF

CIS.4:	SKIPLE	CPUSTS(P1)	;THIS CPU LOOK OK?
	JRST	CIS.6		;NO
	STORE	P1,SCSBLK+.SQFNC,SS.CPU ;STORE CPU NUMBER
	MOVSI	P2,-MAXNDS	;MAXIMUM NUMBER OF NODES
CIS.5:	HRRZM	P2,SCSBLK+.SQRPN ;STORE NODE NUMBER
	XMOVEI	T1,SCSBLK	;POINT AT BLOCK
	SCS.	T1,		;ASK
	  TDZA	T1,T1		;OH WELL, SHOULD WORK ...
	MOVE	T1,SCSBLK+.SQRPS ;GET PATH STATUS
	LSH	T1,(P1)		;SHIFT BY CPU NUMBER
	IORM	T1,PTHSTS(P2)	;STORE ON A PER-NODE BASIS
	AOBJN	P2,CIS.5	;LOOP FOR ALL NODES
CIS.6:	AOBJN	P1,CIS.4	;LOOP FOR ALL CPUS

	PUSHJ	P,ZERSCS	;ZERO SCS. UUO BLOCK
	MOVE	T1,[.SQLPN+1,,.SSRCD] ;FUNCTION
	MOVEM	T1,SCSBLK+.SQFNC ;STORE IT
	MOVSI	P2,-MAXNDS	;LOOP FOR ALL NODES

CIS.7:	SKIPN	T1,PTHSTS(P2)	;ANY OPEN PATHS TO THIS NODE?
	JRST	CIS.8		;NO
	HLRZ	T2,T1		;GET PATH A STATUS TO RH OF T2
	IOR	T1,T2		;COMBINED STATUS IN RH OF T1
	TLZ	T1,-1		;CLEAR LH JUNK NOW
	JFFO	T1,.+1		;COMPUTE CPU NUMBER TO USE
	MOVEI	P1,^D35		;...
	SUB	P1,T2		;...
	STORE	P1,SCSBLK+.SQFNC,SS.CPU ;STORE CPU NUMBER
	HRRZM	P2,SCSBLK+.SQOND ;STORE NODE NUMBER
	XMOVEI	S1,SCSBLK	;POINT AT BLOCK
	SCS.	S1,		;ASK
	  JFCL			;ERROR?
	$TEXT	(WTIRTN,<  ^D2R0/SCSBLK+.SQOND/ (^A>)
	MOVEI	T1,2		;2 WORDS
	MOVEI	T2,SCSBLK+.SQNNM ;NODE NAME STRING
	PUSHJ	P,CNVASC	;CONVERT 8-BIT TO 7-BIT
	MOVEI	S1,")"		;CLOSE THE STRING
	DPB	S1,T1		;...
	$TEXT	(WTIRTN,<^T11L/TMPSTG/^A>)
	MOVEI	T1,1		;1 WORD
	MOVEI	T2,SCSBLK+.SQDST ;DESTINATION S/W TYPE STRING
	PUSHJ	P,CNVASC	;CONVERT 8-BIT TO 7-BIT
	$TEXT	(WTIRTN,<  ^T4L/TMPSTG/    ^A>)
	MOVEI	T1,1		;1 WORD
	MOVEI	T2,SCSBLK+.SQDSV ;DESTINATION S/W VERSION STRING
	PUSHJ	P,CNVASC	;CONVERT 8-BIT TO 7-BIT
	$TEXT	(WTIRTN,<  ^T4L/TMPSTG/    ^A>)
	MOVEI	T1,1		;1 WORD
	MOVEI	T2,SCSBLK+.SQDHT ;DESTINATION H/W TYPE STRING
	PUSHJ	P,CNVASC	;CONVERT 8-BIT TO 7-BIT
	$TEXT	(WTIRTN,<  ^T4L/TMPSTG/>)
CIS.8:	AOBJN	P2,CIS.7	;LOOP FOR NEXT NODE
	POPJ	P,		;RETURN
	SUBTTL	List NI Configuration

NI:	PUSHJ	P,CHKNIP##	;SEE IF ANY NI PORTS IN SYSTEM
	$RETIF			;IF NOT, DON'T EVEN BOTHER
	PUSHJ	P,ETHRCL	;READ ETHERNET CHANNEL LIST
	  POPJ	P,		;ERROR, GIVE UP
	SKIPL	P1,T1		;SAVE AOBJN POINTER TO LIST
	POPJ	P,		;EMPTY LIST, NOTHING TO LIST
	$TEXT	(WTIRTN,<^M^JNI Configuration^M^J^J  Chan/Kont   State     E-net Address^M^J  ---------  -------  ----------------->)
NI.1:	MOVE	T1,(P1)		;GET NEXT CHANNEL ID
	PUSHJ	P,ETHRCI	;READ CHANNEL INFO
	  JRST	NI.4		;ERROR, TRY NEXT
	MOVE	P2,T1		;SAVE AOBJN POINTER TO BUFFER
	LOAD	T1,ENTBLK+.ETCSW,ET.CON ;GET STATUS
	$TEXT	(WTIRTN,<  ETH-^D2L/.EICNM(P2)/     ^T7L/@ONFSTS(T1)/  ^A>)
	MOVEI	T1,.EICEA(P2)	;GET ADDRESS OF E-NET ADDRESS
	PUSHJ	P,EADPRT	;PRINT IT
	$TEXT	(WTIRTN,<>)	;END THE LINE
	MOVE	T1,(P1)		;GET CHANNEL ID
	PUSHJ	P,ETHRKL	;READ KONTROLLER LIST
	  JRST	NI.4		;ERROR
	SKIPL	P3,T1		;ANYTHING IN LIST?
	JRST	NI.4		;NO
NI.2:	MOVE	T1,(P3)		;GET KONTROLLER ID
	PUSHJ	P,ETHRKI	;READ KONTROLLER INFO
	  JRST	NI.3		;ERROR
	MOVE	P4,T1		;SAVE POINTER TO BUFFER
	MOVE	T1,.EIKTY(P4)	;GET KONTROLLER TYPE
	CAIN	T1,EI.KNI	;KLNI?
	SKIPA	T1,[[ITEXT (NI-^D2L/.EIKCP(P4)/)]] ;YES, NEED CPU NUMBER
	MOVEI	T1,[ITEXT (UNA-^D1L/.EIKNO(P4)/)] ;NO, NEED KONTROLLER NUMBER
	LOAD	T2,ENTBLK+.ETKSW,ET.KON ;GET ONLINE FLAG
	$TEXT	(WTIRTN,<    ^I/0(T1)/    ^T7L/@ONFSTS(T2)/  ^A>)
	MOVEI	T1,.EIKHA(P4)	;GET ADDRESS OF E-NET ADDRESS
	PUSHJ	P,EADPRT	;PRINT IT
	$TEXT	(WTIRTN,<>)	;END THE LINE
NI.3:	AOBJN	P3,NI.2		;LOOP FOR ALL KONTROLLERS
NI.4:	AOBJN	P1,NI.1		;LOOP FOR NEXT CHANNEL
	POPJ	P,		;RETURN
;ROUTINE TO READ ETHERNET CHANNEL LIST

ETHRCL:	MOVE	T1,[.ETRCL,,4]	;SET UP ETHNT. TO READ LIST
	MOVEM	T1,ENTBLK+.ETFCN ;...
	MOVEI	T1,RCLBFL	;SIZE OF BUFFER
	MOVEI	T2,RCLBUF	;ADDRESS OF BUFFER
	DMOVEM	T1,ENTBLK+.ETAR1 ;...
	PJRST	ETHRXL		;READ LIST AND RETURN

;ROUTINE TO READ ETHERNET CHANNEL INFORMATION

ETHRCI:	MOVEM	T1,ENTBLK+.ETCSW ;STORE CHANNEL ID
	MOVE	T1,[.ETRCI,,4]	;SET UP ETHNT. TO READ CHANNEL INFO
	MOVEM	T1,ENTBLK+.ETFCN ;...
	MOVEI	T1,RCIBFL	;SIZE OF BUFFER
	MOVEI	T2,RCIBUF	;ADDRESS OF BUFFER
	DMOVEM	T1,ENTBLK+.ETAR1 ;...
	PJRST	ETHRXL		;READ LIST AND RETURN

;ROUTINE TO READ ETHERNET KONTROLLER LIST

ETHRKL:	MOVEM	T1,ENTBLK+.ETCSW ;STORE CHANNEL ID
	MOVE	T1,[.ETRKL,,4]	;SET UP ETHNT. TO READ KONTROLLER LIST
	MOVEM	T1,ENTBLK+.ETFCN ;...
	MOVEI	T1,RKLBFL	;SIZE OF BUFFER
	MOVEI	T2,RKLBUF	;ADDRESS OF BUFFER
	DMOVEM	T1,ENTBLK+.ETAR1 ;...
	PJRST	ETHRXL		;READ LIST AND RETURN

;ROUTINE TO READ ETHERNET KONTROLLER INFORMATION

ETHRKI:	MOVEM	T1,ENTBLK+.ETCSW ;STORE KONTROLLER ID
	MOVE	T1,[.ETRKI,,4]	;SET UP ETHNT. TO READ KONTROLLER INFO
	MOVEM	T1,ENTBLK+.ETFCN ;...
	MOVEI	T1,RKIBFL	;SIZE OF BUFFER
	MOVEI	T2,RKIBUF	;ADDRESS OF BUFFER
	DMOVEM	T1,ENTBLK+.ETAR1 ;...
;	PJRST	ETHRXL		;READ LIST AND RETURN

;ROUTINE TO READ ETHERNET LIST AND RETURN AOBJN POINTER

ETHRXL:	MOVEI	T1,ENTBLK	;READ ETHERNET LIST
	ETHNT.	T1,		;...
	  POPJ	P,		;ERROR
	MOVNS	T1		;MAKE AOBJN POINTER TO BUFFER
	HRLZS	T1		;...
	HRR	T1,ENTBLK+.ETAR2 ;...
	JRST	.POPJ1##	;RETURN
;ROUTINE TO PRINT OUT AN ETHERNET ADDRESS

EADPRT:	PUSH	P,[5]		;SET LOOP ITERATION COUNT
	HRLI	T1,(POINT 8,)	;BUILD BYTE POINTER TO ADDRESS
	PUSH	P,T1		;SAVE BYTE POINTER ON STACK
EADPR1:	ILDB	S1,(P)		;GET NEXT HEX BYTE
	PUSHJ	P,HEXPRB	;PRINT OUT
	MOVEI	S1,"-"		;PRINT HYPHEN
	PUSHJ	P,WTIRTN
	SOSLE	-1(P)		;DECREMENT AND TEST ITERATION COUNT
	JRST	EADPR1		;LOOP BACK FOR FIRST 5 BYTES
	ILDB	S1,(P)		;GET LAST BYTE OF ADDRESS
	POP	P,(P)		;CLEAN STACK
	POP	P,(P)		;...
;	PJRST	HEXPRB		;OUTPUT LAST BYTE AND RETURN

;PRINT TWO HEX BYTES FROM S1

HEXPRB:	ANDI	S1,377		;MASK BYTE
	PUSH	P,S1		;SAVE VALUE
	LSH	S1,-4		;GET HIGH DIGIT
	PUSHJ	P,HEXPRT	;PRINT IT
	POP	P,S1		;GET BACK VALUE
	ANDI	S1,17		;GET LOW DIGIT
;	PJRST	HEXPRT		;PRINT OUT AND RETURN

HEXPRT:	ADDI	S1,"0"		;MAKE IT A DIGIT
	CAILE	S1,"9"		;INTO HEX RANGE?
	ADDI	S1,"A"-"9"-1	;YES, INTO ALPHABETICS
	PJRST	WTIRTN		;PRINT AND RETURN
	SUBTTL	List Disk Configuration

DISK:	$TEXT	(WTIRTN,<^M^JDisk Configuration^M^J^J  Drive   Type  Str   Volume^A>)
	SKIPE	MLTCPU		;SMP SYSTEM?
	$TEXT	(WTIRTN,<  CPU(s)^A>)
	SKIPE	KLFLAG		;KL SYSTEM?
	$TEXT	(WTIRTN,<  Controller^A>)
	$TEXT	(WTIRTN,<^M^J  ------  ----  ----  ------^A>)
	SKIPE	MLTCPU		;SMP SYSTEM?
	$TEXT	(WTIRTN,<  ------^A>)
	SKIPE	KLFLAG		;KL SYSTEM?
	$TEXT	(WTIRTN,<  ----------^A>)
	$TEXT	(WTIRTN,<>)	;END THE LINE
	PUSHJ	P,SETDSK##	;BUILD THE DATABASE
	MOVE	S1,DSKLST##	;GET LIST HANDLE
	PUSHJ	P,L%FIRST	;GET FIRST ENTRY
DISK.1:	JUMPF	.POPJ##		;DONE WHEN END OF LIST ENCOUNTERED
	MOVE	P1,S2		;SAVE ENTRY ADDRESS
	MOVE	S1,.DDNAM(P1)	;GET NAME
	PUSHJ	P,KONINF	;SET UP KONTROLLER INFO
	MOVE	S1,.DDNAM(P1)	;GET NAME
	PUSHJ	P,UNIINF	;SET UP UNIT INFO
	$TEXT	(WTIRTN,<  ^W6L/.DDNAM(P1)/  ^A>)
	LOAD	S1,.DDSTS(P1),DC.CNT ;GET CONTROLLER TYPE
	LSH	S1,^D9		;SHIFT IT OVER
	LOAD	S2,.DDSTS(P1),DC.UNT ;GET UNIT TYPE
	IOR	S1,S2		;COMBINE THEM
	MOVEI	S2,DSKUNT	;POINT AT TABLE
	PUSHJ	P,TABSRC##	;FIND IT IN THE TABLE
	SKIPT			;DID IT SUCCEED?
	MOVEI	S2,[ASCIZ /????/] ;NO, ACT DUMB
	$TEXT	(WTIRTN,<^T/0(S2)/  ^A>)
	$TEXT	(WTIRTN,<^W4L/.DDSNM(P1)/  ^W6L/.DDULN(P1)/  ^A>)
	SKIPN	KLFLAG		;KL SYSTEM?
	JRST	DISK.2		;NO, SKIP THIS STUFF
	MOVE	S1,.DDXCH(P1)	;GET ACCESSIBILITY MASK
	SKIPE	MLTCPU		;IF SMP SYSTEM,
	PUSHJ	P,CPUMSK	; PRINT CPU ACCESSIBILITY MASK
	LOAD	S1,KONBLK+2,DI.KTY ;GET KONTROLLER TYPE BACK
	CAXN	S1,.DCCRA	;HSC50?
	JRST	[LDB   S2,[POINT 4,.DDNAM(P1),17] ;GET HSC50 UNIT NUMBER
		 SUBI S2,1	;MAKE IT 0-BASED
		 JRST .+2]	;CONTINUE WITH THAT AS "DEVICE CODE"
	LOAD	S2,KONBLK+3,DI.DVC ;GET DEVICE CODE
	LOAD	T1,KONBLK+3,DI.CUN ;GET MASSBUS UNIT NUMBER
	HRL	S2,T1		;COPY IT
	LOAD	T1,KONBLK+2,DI.MUK ;GET MULTI-UNIT CONTROLLER FLAG
	STORE	T1,S1,CN.MUK	;SALT IT AWAY
	PUSHJ	P,CTLNAM	;COBBLE UP A NAME
	$TEXT	(WTIRTN,<^T/TMPSTG/^A>)
DISK.2:	$TEXT	(WTIRTN,<>)	;END THE LINE
	MOVE	S1,DSKLST##	;GET LIST HANDLE
	PUSHJ	P,L%NEXT	;GET NEXT ENTRY
	JRST	DISK.1		;LOOP
	SUBTTL	List Tape Configuration

TAPE:	$SAVE	<P1,P2,P3,P4>	;SAVE PRESERVED ACS
	$TEXT	(WTIRTN,<^M^JTape Configuration^M^J^J  Tape Controller(s):^M^J^J  Name  ^A>)
	SKIPE	MLTCPU		;SMP SYSTEM?
	$TEXT	(WTIRTN,<CPU   ^A>)
	MOVEI	S1,[ASCIZ\Channel/Device Code\] ;ASSUME KL
	SKIPN	KLFLAG		;IS IT?
	MOVEI	S1,[ASCIZ\  UNIBUS Address\] ;NO, GET DIFFERENT HEADER
	$TEXT	(WTIRTN,<^T/(S1)//Type^M^J  ----  ^A>)
	SKIPE	MLTCPU		;SMP SYSTEM?
	$TEXT	(WTIRTN,<----  ^A>)
	$TEXT	(WTIRTN,<------------------------>)
;Output Controller Information
	MOVEI	P4,^D26		;THERE'S 26 LETTERS IN THE ALPHABET
	MOVEI	P1,'MTA'	;START WITH THE OBVIOUS
TAPE.1:	HRLZ	S1,P1		;GET CONTROLLER NAME
	PUSHJ	P,KONINF	;GET CONTROLLER INFO
	JUMPF	TAPE.3		;JUMP IF ILLEGAL CONTROLLER
	$TEXT	(WTIRTN,<  ^W3/KONBLK+1/   ^A>) ;TYPE KDB NAME
	SKIPN	MLTCPU		;SMP SYSTEM?
	JRST	TAPE.2		;NO
	$TEXT	(WTIRTN,<CPU^A>);START CPU TYPE OUT
	LOAD	S1,KONBLK+2,DI.CAM ;GET CPU ACCESSIBILITY MASK
	PUSHJ	P,CPUNUM	;TYPE NUMBER
	$TEXT	(WTIRTN,<  ^A>)	;SPACERS
TAPE.2:	SKIPN	KLFLAG		;KS?
	$TEXT	(WTIRTN,<^O/KONBLK+4,DI.UBA/^A>) ;OUTPUT UNIBUSS ADDRESS
	LOAD	S1,KONBLK+2,DI.KTY ;GET KONTROLLER TYPE BACK
	LOAD	S2,KONBLK+3,DI.DVC ;GET DEVICE CODE
	LOAD	T1,KONBLK+3,DI.CUN ;GET MASSBUS UNIT NUMBER
	HRL	S2,T1		;COPY IT
	LOAD	T1,KONBLK+2,DI.MUK ;GET MULTI-UNIT CONTROLLER FLAG
	STORE	T1,S1,CN.MUK	;SALT IT AWAY
	TXO	S1,CN.TAP	;SET TAPE FLAG
	PUSHJ	P,CTLNAM	;COBBLE UP A NAME FOR THE CONTROLLER
	$TEXT	(WTIRTN,<^T/TMPSTG/>)
TAPE.3:	AOS	P1		;INCREMENT TO NEXT CONTROLLER NAME
	SOJG	P4,TAPE.1	;LOOP FOR ALL POSSIBLE CONTROLLERS
;Output Tape Drive Information
	$TEXT	(WTIRTN,<^M^J  Tape Unit(s):^M^J^J  Drive    Type   Volume  Controller(s)^A>)
	$TEXT	(WTIRTN,<^M^J  ------  ------  ------  ------------->)
	MOVX	T1,.TYMTA	;DEVICE TYPE
	MOVEM	T1,DVPBLK+0	;SALT IT AWAY
	SETZM	DVPBLK+1	;WE WANT FIRST DEVICE
TAPE.4:	MOVE	T1,[2,,DVPBLK]	;POINT AT ARGUMENTS
	DVPHY.	T1,		;ASK FOR NEXT DEVICE
	  POPJ	P,		;DONE?
	SKIPN	P1,DVPBLK+1	;ANYTHING THERE?
	POPJ	P,		;NO, MUST BE DONE
	LDB	T2,[POINT 12,P1,11] ;GET FIRST 2 CHARACTERS OF DEVICE NAME
	CAIN	T2,' ''L'	;LABEL DDB?
	JRST	TAPE.4		;YES, SKIP IT
	MOVEM	P1,TOPBLK+1	;SAVE FOR LOTS OF TAPOP. FUNCTIONS
	$TEXT	(WTIRTN,<  ^W6/P1/  ^A>) ;START WITH NAME
	MOVE	S1,P1		;COPY KONTROLLER NAME
	PUSHJ	P,KONINF	;GET KONTROLLER INFO
	MOVE	S1,P1		;GET UNIT NAME
	PUSHJ	P,UNIINF	;GET UNIT INFO
	LOAD	S1,KONBLK+2,DI.KTY ;GET KONTROLLER TYPE
	MOVEI	S2,TAPTYP	;TABLE ADDRESS
	PUSHJ	P,TABSRC##	;SEARCH FOR A MATCH
	SKIPT			;FIND IT?
	MOVEI	S2,[ASCIZ /???/]
	$TEXT	(WTIRTN,<^T6L/0(S2)/  ^A>)
	MOVX	T1,.TFRID	;GET REELID
	MOVEM	T1,TOPBLK+0
	MOVE	T1,[2,,TOPBLK]	;POINT AT ARGUMENTS
	TAPOP.	T1,		;ASK MONITOR
	  SETZ	T1,		;ERROR, ASSUME UNKNOWN
	$TEXT	(WTIRTN,<^W6/T1/  ^A>)
	SETOM	S1
	MOVE	P1,UNIBLK+2	;GET POINTER TO KDBS
TAPE.5:	SKIPN	S2,(P1)		;ONE THERE?
	JRST	TAPE.6		;NOPE
	AOSE	S1
	$TEXT	(WTIRTN,<, ^A>)
	$TEXT	(WTIRTN,<^W3/S2/^A>) ;OUTPUT CONTROLLER NAME
TAPE.6:	AOBJN	P1,TAPE.5
	$TEXT	(WTIRTN,<>)	;FINISH LINE
	JRST 	TAPE.4		;LOOP FOR NEXT TAPE UNIT

	SUBTTL	Generate Disk/Tape Controller Name

;Call with:
;	S1/ Kontroller type code + flags
;	S2/ Massbus unit number,,device code
;Returns with name string stored in TMPSTG


CTLNAM:	$SAVE	<P1,P2>		;SAVE AWAY A FEW ACS
	DMOVE	P1,S1		;COPY THE ARGUMENTS AWAY
	MOVX	S1,STGLEN	;LENGTH OF BUFFER
	MOVEI	S2,TMPSTG	;ADDRESS
	$CALL	.ZCHNK		;ZERO IT
	MOVEI	S1,STGCHR	;SET UP FOR OUTPUT
	MOVEM	S1,STGCNT
	MOVE	S1,[POINT 7, TMPSTG] ;BYTE POINTER
	MOVEM	S1,STGBPT
	HRRZ	S1,P1		;GET CONTROLLER TYPE
	TXNN	P1,CN.TAP	;IS THIS A DISK CONTROLLER?
	CAXE	S1,.DCCRA	;YES, HSC50?
	SKIPA			;NO
	JRST	CTLN.H		;YES, THAT'S A LITTLE SPECIAL
	SKIPN	KLFLAG		;KL?
	JRST	CTLN.2		;NO, KS DOESN'T HAVE A DEVICE CODE
	HRRZ	S1,P2		;COPY CONTROLLER DEVICE CODE
	MOVEI	S2,CTLTAB	;POINT AT TABLE
	PUSHJ	P,TABSRC##	;LOOK FOR A MATCH
	JUMPT	CTLN.1		;GO IF FOUND A MATCH
	$TEXT	(STGDPB,<Device code ^O/S1/^0>) ;SAY SOMETHING
	JRST	CTLN.2		;CONTINUE
CTLN.1:	PUSHJ	P,CHKSAX	;DUMP CONTROLLER INFO (CHECK FOR SA-10)
CTLN.2:	TXNN	P1,CN.MUK	;MULTI-UNIT CONTROLLER?
	POPJ	P,		;NO, DONE
	HRRZ	S1,P1		;GET CONTROLLER TYPE CODE
	MOVEI	S2,DSKMUK	;ASSUME DSK
	TXNE	P1,CN.TAP	;TAPE?
	MOVEI	S2,TAPMUK	;YES
	PUSHJ	P,TABSRC##	;LOOK FOR A MATCH
	$RETIF			;IF NOT FOUND, QUIT
	$TEXT	(STGDPB,<, ^T/0(S2)/-^O1/P2,LHMASK/^A>)
	POPJ	P,		;RETURN

;OUTPUT CONTROLLER INFO
CHKSAX:	$SAVE	<T1>		;GET A SCRATCH AC
	HRRZ	S1,P1		;GET CONTROLLER TYPE CODE
	MOVEI	T1,DECCTL	;ASSUME NOT SA10
	CAXE	S1,.TFKSX	;SA10 TAPE?
	CAXN	S1,.DCCSX	;SA10 DISK?
	MOVEI	T1,SAXCTL	;YES
	$TEXT	(STGDPB,<^I/(T1)/^A>) ;DUMP TEXT
	POPJ	P,		;RETURN

DECCTL:	ITEXT	(<^T/0(S2)/ (^O3/P2,RHMASK/)>) ;DEC CONTROLLER TEXT
SAXCTL:	ITEXT	(<SA10-^O1/P2,LHMASK/ (^O3/P2,RHMASK/)>) ;SA10 CONTROLLER TEXT

STGDPB:	SOSLE	STGCNT		;COUNT DOWN
	IDPB	S1,STGBPT	;STUFF IT
	$RETT			;RETURN

CTLN.H:	$TEXT	(<-1,,TMPSTG>,<HSC-^D/P2,RHMASK/^0>)
	POPJ	P,		;GOOD STUFF HERE

TAPC.1:!			;DX20 TAPES COME HERE TOO
DSKC.2:	HRRZ	S1,S2		;COPY DEVICE CODE
	LSH	S1,-2		;DIVIDE BY FOUR
	SUBI	S1,130		;COMPUTE RH20 NUMBER
	HRL	S1,S2		;PUT UN-HACKED DEVICE CODE IN LH
	HLRZS	S2		;GET DX20 UNIT NUMBER (MASSBUS UNIT NUMBER)
	$TEXT	(<-1,,TMPSTG>,<RH20-^O/S1,RHMASK/ (^O3R0/S1,LHMASK/):DX20-^O/S2/^0>)
	MOVEI	S2,TMPSTG	;COP OUT
	POPJ	P,		;BUT IT SUFFICES
	SUBTTL	List DECtape Configuration

DECTAP:	MOVX	T1,.TYDTA	;GET DEVICE TYPE
	MOVEM	T1,DVPBLK+0	;SALT IT AWAY
	SETZM	DVPBLK+1	;START WITH FIRST DEVICE
	SETO	P1,		;INIT HEADER FLAG

DTA.1:	MOVE	T1,[2,,DVPBLK]	;POINT AT ARGUMENTS
	DVPHY.	T1,		;ASK FOR NEXT DEVICE
	  JRST	DTA.2		;DONE?
	SKIPN	P2,DVPBLK+1	;ANYTHING THERE?
	JRST	DTA.2		;NO, MUST BE DONE
	AOSN	P1		;FIRST TIME?
	$TEXT	(WTIRTN,<^M^JDECtape configuration^M^J^J  Device  CPU^M^J  ------  --->)
	MOVE	T1,[.RCCPU,,T2]	;FIND OUT WHICH CPU OWNS IT
	MOVEI	T2,2
	MOVE	T3,P2
	RECON.	T1,		;ASK MONITOR
	  SETZ	T1,		;ASSUME THE BOOT
	JFFO	T1,.+1		;COUNT NUMBER OF LEADING ZEROES
	MOVEI	T1,^D35		;DETERMINE THE CPU NUMBER
	SUB	T1,T2		;...
	$TEXT	(WTIRTN,<  ^W6L/P2/   ^D/T1/>)
	JRST	DTA.1		;TRY NEXT DEVICE

DTA.2:	POPJ	P,		;DONE
	SUBTTL	List Unit Record Device Configuration

UNTRCD:	$TEXT	(WTIRTN,<^M^JUnit Record Device Configuration>)
	MOVSI	P1,-URCTBL	;POINTER TO TABLE OF TYPES OF DEVICES TO CHECK

UNTR.1:	MOVE	T1,URCTAB(P1)	;GET THE .TYXXX VALUE
	MOVEM	T1,DVPBLK+0	;SALT IT AWAY
	SETZM	DVPBLK+1	;NO PREVIOUS
	SETO	P2,		;INIT HEADER FLAG

UNTR.2:	MOVE	T1,[2,,DVPBLK]	;POINT AT ARGUMENTS
	DVPHY.	T1,		;ASK FOR NEXT DEVICE
	  JRST	UNTR.3		;DONE?
	SKIPN	P3,DVPBLK+1	;ANYTHING THERE?
	JRST	UNTR.3		;NO, MUST BE DONE
	AOSN	P2		;FIRST TIME?
	$TEXT	(WTIRTN,<^M^J  ^T/@URCNAM(P1)/ configuration:^M^J^T/@URCHDR(P1)/>)
	MOVE	T1,[.RCCPU,,T2]	;FIND OUT WHICH CPU OWNS IT
	MOVEI	T2,2
	MOVE	T3,P3
	RECON.	T1,		;ASK MONITOR
	  SETZ	T1,		;ASSUME THE BOOT
	JFFO	T1,.+1		;COUNT NUMBER OF LEADING ZEROES
	MOVEI	T1,^D35		;DETERMINE THE CPU NUMBER
	SUB	T1,T2		;...
	$TEXT	(WTIRTN,<    ^W6L/P3/   ^D/T1/ ^A>) ;DEVICE NAME AND CPU
	SKIPE	URCDEV(P1)	;SOMETHING SPECIFIC?
	PUSHJ	P,@URCDEV(P1)	;YES, DO THE DETAILS
	$TEXT	(WTIRTN,<>)	;END THE LINE
	JRST	UNTR.2		;NEXT OF THIS DEVICE

UNTR.3:	AOBJN	P1,UNTR.1	;LOOP FOR OTHER DEVICES
	POPJ	P,		;DONE
URCLPT:	MOVE	T1,[2,,T2]	;SET TO READ HARDWARE CHARACTERISTICS
	MOVX	T2,.DFHCW	;FUNCTION
	MOVE	T3,P3		;DEVICE NAME
	DEVOP.	T1,		;ASK ABOUT IT
	  SETZ	T1,		;SARGEANT SCHULTZ, EH?
	LOAD	T2,T1,DF.CLS	;GET CLASS
	$TEXT	(WTIRTN,<  ^T5L/@LPTCLS(T2)/^A>)
	MOVE	T1,[2,,T2]	;SET TO READ DEVICE STATUS
	MOVX	T2,.DFRDS	;FUNCTION
	DEVOP.	T1,		;ASK ABOUT IT
	  SETZ	T1,		;DUH
	TXNE	T1,DF.OFL	;OFFLINE?
	$TEXT	(WTIRTN,<  Offline^A>)
	TXNN	T1,DF.OFL	;ONLINE?
	$TEXT	(WTIRTN,<  Online ^A>)
	POPJ	P,		;RETURN

LPTCLS:	[ASCIZ	/Unknown/]
	[ASCIZ	/BA10/]
	[ASCIZ	/LP100/]
	[ASCIZ	/LP20/]
	[ASCIZ	/LP11/]
	[ASCIZ	/LP20/]
DEFINE	DEVS,<
DEV	CDR,0,Card reader
DEV	CDP,0,Card punch
DEV	LPT,URCLPT,Line printer
DEV	PTR,0,Paper tape reader
DEV	PTP,0,Paper tape punch
DEV	PLT,0,Plotter
>; END DEFINE DEVS

DEFINE	DEV(TYPE,SPEC,NAME),<
	EXP	.TY'TYPE
>; END DEFINE DEV

URCTAB:	DEVS
URCTBL==.-URCTAB		;LENGTH OF TABLE

DEFINE	DEV(TYPE,SPEC,NAME),<
	[ASCIZ	/NAME/]
>; END DEFINE DEV

URCNAM:	DEVS

DEFINE	DEV(TYPE,SPEC,NAME),<
IF2,<IFNDEF HDR'TYPE,<HDR'TYPE==HDRGNC>>
	EXP	HDR'TYPE
>; END DEFINE DEV

URCHDR:	DEVS

DEFINE	DEV(TYPE,SPEC,NAME),<
	EXP	SPEC
>; END DEFINE DEV

URCDEV:	DEVS
HDRLPT:	ASCIZ	/    Device  CPU  Type   Status
    ------  ---  -----  ------/

HDRGNC:	ASCIZ	/    Device  CPU
    ------  ---/
	SUBTTL	List CFE Device Configuration

IFN FTLCFE,<
CFEDEV:	HRLO	T1,P1		;GET CPU NUMBER,,-1 (FOR MASTER DTE)
	PUSHJ	P,OPENFE	;OPEN AN "FE" DEVICE
	  POPJ	P,		;WE TRIED
	$TEXT	(WTIRTN,<  CFE UNIBUS Configuration:>)
	$TEXT	(WTIRTN,<     CSR           Device           CSR     Associated Device>)
	$TEXT	(WTIRTN,<    ------  ---------------------  ------  -------------------->)
	MOVSI	P3,-CHKN	;DEVICES TO CHECK
	MOVE	P2,[POINT 18,CHKTAB]	;POINT TO ENTRIES
CFED.1:	ILDB	T1,P2		;FETCH PRIMARY DEVICE ADDRESS
	PUSHJ	P,REDFEW	;SEE IF PRESENT
	  JRST	CFED.2		;NOT PRESENT, SKIP ENTRY
	LDB	T1,P2		;FETCH ADDRESS
	ILDB	T2,P2		;FETCH DESCRIPTOR
	$TEXT	(WTIRTN,<    ^O6R/T1,MSK16B/  ^T21L/(T2)/^A>) ;OUTPUT DEVICE FOUND
	ILDB	T1,P2		;FETCH SECONDARY ADDRESS
	JUMPE	T1,CFED.5	;JUMP IF NONE
	PUSHJ	P,REDFEW	;SEE IF PRESENT
	  JRST	CFED.4		;NOT PRESENT, PRIMARY ONLY
	LDB	T1,P2		;FETCH ADDRESS
	ILDB	T2,P2		;PRESENT, FIND DESCRIPTOR
	$TEXT	(WTIRTN,<  ^O6R/T1,MSK16B/  ^T20L/(T2)/>) ;FINISH LINE
	JRST	CFED.7		;NEXT ENTRY

CFED.2:	CAXE	T1,.IOVER	;BUS TIMEOUT?
	JRST	CFEERR		;NO
	LDB	T1,P2		;FETCH ADDRESS
	TRNN	T1,400000	;MANDATORY DEVICE?
	JRST	CFED.3		;NO, IGNORE IT
	ILDB	T2,P2		;FETCH DESCRIPTOR
	$TEXT	(WTIRTN,<    Missing  ******  ^T21/(T2)/>)	;COMPLAIN
	SKIPA	T1,[2]		;SKIP SECONDARY
CFED.3:	MOVEI	T1,3		;SKIP REST OF ENTRY
	EXCH	P2,T1		;GET ORDER RIGHT
	ADJBP	P2,T1		;SKIP PAST IT
	JRST	CFED.7		;END LINE

CFED.4:	CAXE	T1,.IOVER	;BUS TIMEOUT?
	JRST	CFEERR		;NOPE
CFED.5:	IBP	P2		;SKIP SECONDARY DESCRIPTOR

CFED.6:	$TEXT	(WTIRTN,<>)	;FINISH LINE

CFED.7:	AOBJN	P3,CFED.1	;TRY NEXT DEVICE
	PJRST	CLOSFE		;CLOSE THE "FE" DEVICE AND RETURN

CFEERR:	$TEXT	(WTIRTN,<^M^J?Unexpected RSX-20F error ^D/T1/^M^J>)
	PJRST	CLOSFE		;GIVE UP ON THE SUCKER
	DEFINE	DEV(ADDR,NAME,RELADR<0>,RELNAM<0>),<
	XWD	'ADDR',[ASCIZ /'NAME'/]
	XWD	'RELADR',[ASCIZ /'RELNAM'/]
	>
	DEFINE	MDEV(ADDR,NAME,RELADR<0>,RELNAM<0>),<
	DEV	400000!<'ADDR'>,<'NAME'>,<'RELADR'>,<'RELNAM'>>

CHKTAB:	;CPU OPTIONS
	MDEV	172100,<MF11-UP Mem Parity>	;MEM PARITY
	DEV	160770,<TCU Time of Day clk>	;DATE/TIME BOARD
	;MAGNETIC MEDIA
	DEV	177170,<RX01 Floppy Control>	;FLOPPY
	DEV	177340,<TC11 DECtape Control>	;DECTAPE
	MDEV	176700,<RH11 Disk Control>	;DBn: CONTROLLER
	;SINGLE-LINE ASYNC INTERFACES
	MDEV	177560,<DL11-C CTY>		;CTY
	MDEV	175610,<DL11-E KLINIK>		;KLINIK
	DEV	175630,<DL11-E DTE1 Console>	;NULL MODEM TO FE1
	DEV	175640,<DL11-E DTE2 Console>	;NULL MODEM TO FE2
	DEV	175650,<DL11-E DTE3 Console>	;NULL MODEM TO FE3
	;MULTI-LINE ASYNC INTERFACES
	DEV	160020,<DH11 #0 16 line group>,170500,<DM11-BB #0 Modem Ctl>
	DEV	160040,<DH11 #1 16 line group>,170510,<DM11-BB #1 Modem Ctl>
	DEV	160060,<DH11 #2 16 line group>,170520,<DM11-BB #2 Modem Ctl>
	DEV	160100,<DH11 #3 16 line group>,170530,<DM11-BB #3 Modem Ctl>
	DEV	160120,<DH11 #4 16 line group>,170540,<DM11-BB #4 Modem Ctl>
	DEV	160140,<DH11 #5 16 line group>,170550,<DM11-BB #5 Modem Ctl>
	DEV	160160,<DH11 #6 16 line group>,170560,<DM11-BB #6 Modem Ctl>
	DEV	160200,<DH11 #7 16 line group>,170570,<DM11-BB #7 Modem Ctl>
	;UNIT-RECORD DEVICES
	DEV	177160,<CD20 Card Reader>
	DEV	175400,<LP20 #0 Line Printer>
	DEV	175420,<LP20 #1 Line Printer>
	DEV	177514,<LP11 #0 Line Printer>	;USED FOR LN01
	DEV	177524,<LP11 #1 Line Printer>	;USED FOR LN01
	;BACK-END CPUS
	MDEV	174400,<DTE20 #0 KL10 CPU>	;MOST EXPENSIVE -11 PERIPHERAL
	DEV	174440,<DTE20 #1 KL10 CPU>
	DEV	174500,<DTE20 #2 KL10 CPU>
	DEV	174540,<DTE20 #3 KL10 CPU>
	CHKN==<.-CHKTAB>/2
>; END IFN FTLCFE
	SUBTTL	List Logical Memory Configuration

IFN FTLMEM,<
LOGMEM:	$TEXT	(WTIRTN,<  Logical memory configuration:>)
	MOVX	T1,%CCSDP	;GETTAB FOR S-BUS DIAG SUB-TABLE
	SETZ	T2,		;FIRST WORD IN TABLE = -VE # OF CTLS,,1
	PUSHJ	P,CPUSTB	;DO CPU-SPECIFIC SUBTABLE GETTAB
	HRRZ	P2,T1		;SET OFFSET IN TABLE TO FIRST CONTROLLER
	HLLZ	P3,T1		;MAKE AN AOBJN POINTER TO TABLES
	MOVEM	P3,MEMCTP	;SAVE IT
LMEM.1:	MOVX	T1,%CCSDP	;GETTAB FOR S-BUS DIAG SUB-TABLE
	HRRZS	T2,P2		;OFFSET IN TABLE = -LEN,,CONTROLLER NUMBER
	PUSHJ	P,CPUSTB	;DO CPU-SPECIFIC SUBTABLE GETTAB
	HRRZM	T1,MEMCTN(P3)	;SAVE CONTROLLER NUMBER
	HLRES	T1		;NUMBER OF WORDS TO SKIP
	SUBI	P2,-1(T1)	;ADVANCE POINTER
	AOBJN	P3,LMEM.1	;LOOP FOR ALL

	MOVX	T1,.DISBD	;DIAG. UUO FUNCTION WE'LL USE
	MOVEM	T1,DIABLK	;SAVE IT AWAY
	HRLM	P1,DIABLK	;STUFF THE CPU NUMBER THERE TOO
	MOVE	P2,MEMCTP	;GET AOBJN POINTER TO CONTROLLER NUMBERS
	SETZB	P3,PIECES	;NO PIECES OF MEMORY YET
LMEM.2:	MOVE	T1,MEMCTN(P2)	;GET CONTROLLER NUMBER
	MOVEM	T1,CONTNO(P3)	;SAVE IT
	ROT	T1,-5		;POSITION FOR SBDIAG
	HRRI	T1,0		;FUNCTION CODE
	MOVEM	T1,DIABLK+1	;SAVE TO-MEMORY WORD
	MOVE	T1,[-3,,DIABLK]	;POINT AT ARGUMENTS
	DIAG.	T1,		;ASK MONITOR TO DO IT FOR US
	  HALT	.		;NOT IMPLEMENTED?
	MOVE	T1,DIABLK+2	;GET FROM-MEMORY WORD
	MOVEM	T1,STATS0	;SAVE IT
	MOVE	T1,MEMCTN(P2)	;GET CONTROLLER NUMBER
	ROT	T1,-5		;POSITION FOR SBDIAG
	HRRI	T1,1		;FUNCTION CODE
	MOVEM	T1,DIABLK+1	;SAVE TO-MEMORY WORD
	MOVE	T1,[-3,,DIABLK]	;POINT AT ARGUMENTS
	DIAG.	T1,		;ASK MONITOR TO DO IT FOR US
	  HALT	.		;NOT IMPLEMENTED?
	MOVE	T1,DIABLK+2	;GET FROM-MEMORY WORD
	MOVEM	T1,STATS1	;SAVE IT
	LDB	T1,MSYTYP	;GET CONTROLLER TYPE
	MOVEM	T1,CONTYP(P3)	;SAVE
	LDB	T1,MSYITL	;GET INTERLEAVING/BUS MODE
	MOVEM	T1,INTRLV(P3)	;SAVE INTERLEAVING/BUS MODE
	JUMPN	T1,LMEM.3	;JUMP IF ON-LINE
	SETZM	ADDRES(P3)	;ADDRESS NOT KNOWN IF OFFLINE
	SETZM	SIZE(P3)	;SIZE NOT KNOWN EITHER
	MOVEI	T1,17		;GET ALL REQUESTORS
	MOVEM	T1,RQS(P3)	;PRETEND THERE ARE SOME
	AOS	P3,PIECES	;COUNT ANOTHER "PIECE" OF MEMORY
	JRST	LMEM.9		;ONWARD

;SOMETHING OUT THERE AND ONLINE
LMEM.3:	MOVE	T1,CONTYP(P3)	;GET CONTROLLER TYPE
	CAIN	T1,.MCMF2	;MF20/MG20 MOS MEMORY?
	JRST	LMEM.5		;YES
	CAIE	T1,.MCMA2	;MA20
	CAIN	T1,.MCMB2	;OR MB20?
	SKIPA			;YES
	JRST	LMEM.4		;NO, MUST BE DMA OR UNKNOWN
	LDB	T1,MSYRQS	;GET REQUESTOR BITS
	MOVEM	T1,RQS(P3)	;SALT AWAY
	LDB	T1,MSYLBA	;GET LOWER-BOUND ADDRESS HIGH-ORDER BITS
	LDB	T2,MSYUBA	;GET UPPER-BOUND ADDRESS HIGH-ORDER BITS
	SUBI	T2,-1(T1)	;GET NUMBER OF 16K CHUNKS IN THIS BOX
	IMULI	T1,.CS16K	;LOWER-BOUND ADDRESS TIMES 16K CHUNK SIZE
	MOVEM	T1,ADDRES(P3)	;SAVE STARTING ADDRESS OF BOX
	IMULI	T2,.CS16K	;CONVERT NUMBER OF 16K CHUNKS TO NUMBER OF WDS
	MOVE	T3,RQS(P3)	;GET REQUESTOR BITS
	IMUL	T2,RQSTAB(T3)	;MULTIPLY BY CORRESPONDING NUMBER OF REQUESTORS
	IDIVI	T2,4		;SIZE IT CORRECTLY
	MOVEM	T2,SIZE(P3)	;SALT SIZE AWAY
	AOS	P3,PIECES	;COUNT ANOTHER "PIECE" OF MEMORY
	JRST	LMEM.9		;ONWARD

;DMA OR UNKNOWN
LMEM.4:	CAIE	T1,.MCDMA	;DMA20?
	JRST	LMEM.9		;NO, SKIP THIS CONTROLLER
	AOS	P3,PIECES	;COUNT ANOTHER "PIECE" OF MEMORY
	JRST	LMEM.9		;ONWARD

;MOS MEMORY
LMEM.5:	MOVE	T1,MEMCTN(P2)	;GET CONTROLLER NUMBER
	ROT	T1,-5		;POSITION FOR SBDIAG
	HRRI	T1,2		;FUNCTION CODE
	TXO	T1,3B14		;SELECT CHIP SIZE ROM WORD
	MOVEM	T1,DIABLK+1	;SAVE TO-MEMORY WORD
	MOVE	T1,[-3,,DIABLK]	;POINT AT ARGUMENTS
	DIAG.	T1,		;ASK MONITOR TO DO IT FOR US
	  HALT	.		;NOT IMPLEMENTED?
	MOVE	T1,DIABLK+2	;GET FROM-MEMORY WORD
	TXNE	T1,MS.SIZ	;CHIP SIZE BITS THERE?
	JRST	LMEM.6		;YES, THIS IS AN MG20
	MOVX	T1,.CS16K	;NO, THIS IS AN MF20 (16K MEMORY CHIPS)
	JRST	LMEM.7		;CONTINUE
LMEM.6:	MOVX	T1,.MCMG2	;GET PSEUDO TYPE CODE
	MOVEM	T1,CONTYP(P3)	;SALT IT AWAY
	MOVX	T1,.CS64K	;THIS IS AN MG20, 64K MEMORY CHIPS
LMEM.7:	MOVEM	T1,CHIPSZ	;SAVE MEMORY CHIP SIZE
	SETZ	P4,		;CLEAR STARTING ADDRESS
LMEM.8:	MOVE	T1,MEMCTN(P2)	;GET CONTROLLER NUMBER
	ROT	T1,-5		;POSITION FOR SBDIAG
	HRRI	T1,12		;FUNCTION CODE
	MOVE	T2,P4		;COPY ADDRESS
	IDIVI	T2,.CS16K	;SELECT PROPER BIT
	DPB	T2,[POINT 8,T1,27] ;SELECT ADDRESS RESPONSE RAM LOAD ADDRESS
	MOVEM	T1,DIABLK+1	;SAVE TO-MEMORY WORD
	MOVE	T1,[-3,,DIABLK]	;POINT AT ARGUMENTS
	DIAG.	T1,		;ASK MONITOR TO DO IT FOR US
	  HALT	.		;NOT IMPLEMENTED?
	MOVE	T1,DIABLK+2	;GET FROM-MEMORY WORD
	ADD	P4,CHIPSZ	;BUMP TO NEXT CHIP SET
	CAMGE	P4,[17,,740000]	;DONE ALL CHIPS POSSIBLE?
	JRST	LMEM.8		;NO, DO SOME MORE
	JFCL

LMEM.9:	AOBJN	P2,LMEM.2	;LOOP FOR ALL CONTROLLERS
;PRINT THE RESULTS, DUMMY
	POPJ	P,		;ALL DONE

MSYITL:	POINT	2, STATS0, 7	;INTERLEAVING/BUS MODE (0=OFFLINE)
MSYTYP:	POINT	4, STATS1, 11	;CONTROLLER TYPE
MSYLBA:	POINT	4, STATS1, 21	;LOWER BOUND ADDRESS (MA/MB)
MSYUBA:	POINT	4, STATS1, 25	;UPPER BOUND ADDRESS (MA/MB)
MSYRQS:	POINT	4, STATS1, 35	;REQUESTORS

RQSTAB:	EXP	0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4
>; END IFN FTLMEM
	SUBTTL	Open/Close "FE" Device


OPENFE:	MOVEM	T1,DTEBLK+0	;SAVE CPU,,DTE NUMBER
	SETOM	DTEBLK+1	;ASSIGN ANY AVAILABLE FED DEVICE
	MOVE	T1,[.DTEGF,,DTEBLK] ;POINT AT ARGUMENTS
	DTE.	T1,		;TRY TO GET AN FED
	  POPJ	P,		;ERROR, NONE AVAIL OR CPU DOWN
	MOVEM	T1,DTEBLK+1	;GOT ONE, SAVE FED NUMBER ASSIGNED
	JRST	.POPJ1##	;RETURN SUCCESS


CLOSFE:	MOVE	T1,[.DTEFR,,DTEBLK] ;POINT AT THE ARGUMENT BLOCK
	DTE.	T1,		;RELEASE THE FE: DEVICE
	  JFCL			;WE TRIED
	POPJ	P,		;RETURN
	SUBTTL	Read CFE Data


GETFED:	PUSHJ	P,.SAVE2##	;FREE UP A FEW AC'S
	MOVSI	P1,-<.VERLN+1>/2 ;BYTES WE MUST READ
	MOVE	P2,[POINT 7,VERBUF] ;WHERE TO STORE RESULT
GTFE.1:	MOVEI	T1,.VERNO(P1)	;ADDRESS OF THIS WORD
	PUSHJ	P,REDFEW	;READ THE WORD
	  POPJ	P,		;ERROR
	LDB	T2,[POINT 8,T1,35] ;FETCH FIRST BYTE
	CAIN	T2,200		;NULL (END OF STRING)?
	JRST	GTFE.2		;YES
	IDPB	T2,P2		;NO, SALT IT AWAY
	AOJ	P1,		;NEXT BYTE
	CAIN	P1,.VERLN	;AT END?
	JRST	GTFE.2		;YES
	LDB	T2,[POINT 8,T1,35-8] ;FETCH SECOND BYTE
	CAIN	T2,200		;NULL (END OF STRING)?
	JRST	GTFE.2		;YES
	IDPB	T2,P2		;NO, SALT IT AWAY
	AOBJN	P1,GTFE.1	;LOOP AWAY

GTFE.2:	SETZ	T1,		;GET A ZERO
	IDPB	T1,P2		;TERMINATE THE STRING
;	LDB	T1,[POINT 7,VERBUF,6] ;GET FIRST BYTE
;	CAIE	T1,"V"		;SHOULD BE VXNN-MM
;	POPJ	P,		;IT'S NOT, PROBABLY VERSION SKEW

	MOVEI	T1,.KLRLD	;FETCH RELOAD (AND FAULT-CONTINUATION) FLAGS
	PUSHJ	P,REDFEW	;READ THE WORD
	  POPJ	P,		;ERROR
	MOVEM	T1,RLDFCF	;SALT IT AWAY
	MOVEI	T1,.KACFL	;FETCH RETRY FLAG
	PUSHJ	P,REDFEW	;READ THE WORD
	  POPJ	P,		;ERROR
	MOVEM	T1,RTYWRD	;SALT IT AWAY
	JRST	.POPJ1##	;SKIP RETURN
;READ WORD FROM ME: DEVICE
;RETURN:
;	  <ERROR, ERROR CODE IN T1>
;	<SUCCESS, DATA IN T1>

REDFEW:	HRLI	T1,.IORLB	;SET UP HEADER FOR READ FUNCTION
	HLLZM	T1,FEMSG+0	;SET IO FUNCTION
	HRLI	T1,2		;DATA BYTES TO BE TRANSFERRED
	MOVSM	T1,FEMSG+2	;(PARAM-2,,BYTE-CNT)
	SETZM	FEMSG+1		;(UNIT,,PARAM-1)
	MOVEI	T1,(<BYTE (2)0(8)"E","M">) ;SET DEVICE NAME
	HRRM	T1,FEMSG+0	;IN HEADER
	MOVE	T1,[<14/2>,,FEMSG] ;WORD COUNT TO SEND,,ADDRESS
	MOVEM	T1,FEBUF	;FOR FEDSER
	MOVE	T1,[.DTEOF,,DTEBLK] ;POINT AT ARGUMENTS
	DTE.	T1,		;DO OUTPUT TO ME:
	  POPJ	P,		;ERROR
	MOVE	T1,[<14/2>,,FEMSG] ;READ HEADER
	MOVEM	T1,FEBUF	;FOR FEDSER
	MOVE	T1,[.DTEIF,,DTEBLK] ;POINT AT ARGUMENTS
	DTE.	T1,		;DO INPUT FROM ME:
	  POPJ	P,		;ERROR
	LDB	T1,[POINT 8,FEMSG+1,35] ;GET $DSW
	TRNE	T1,200		;NEGATIVE (IN 8 BITS)?
	TDO	T1,[-1,,777400]	;YES, EXTEND THE SIGN
	CAIE	T1,1		;SUCCESS?
	POPJ	P,		;NO
	LDB	T1,[POINT 16,FEMSG+2,35] ;GET AMOUNT OF DATA WHICH FOLLOWS
	CAILE	T1,.FEMAX	;TOO MUCH DATA?
	POPJ	P,		;YES
	ASH	T1,-1		;CONVERT BYTES TO WORDS
	HRLI	T1,FEMSG+3	;WHERE TO PUT DATA
	MOVSM	T1,FEBUF	;FOR FEDSER
	MOVE	T1,[.DTEIF,,DTEBLK] ;POINT AT ARGUMENTS
	DTE.	T1,		;DO INPUT FROM ME:
	  POPJ	P,		;ERROR
	LDB	T1,[POINT 16,FEMSG+3,17] ;GET THE WORD
	JRST	.POPJ1##	;SKIP RETURN
	SUBTTL	Miscellaneous text strings

HWOPTS:	[LD.MCA],,[ASCIZ |MCA25 cache/pager|]
	[LD.MOS],,[ASCIZ |MOS master oscillator|]
	[LD.MPV],,[ASCIZ |Extended addressing|]
	[LD.CHN],,[ASCIZ |Internal channels|]
	[LD.CSH],,[ASCIZ |Cache|]
HWOPTL==.-HWOPTS		;LENGTH OF TABLE

CSHSTS:	[ASCIZ	/Disabled/]
	[ASCIZ	/Load not look/]
	[ASCIZ	/Look not load/]
	[ASCIZ	/Enabled/]

DTTYTB:	[ASCIZ	/Unknown/]
	[ASCIZ	/DC76/]
	[ASCIZ	|DC76/DN87|]
	[ASCIZ	/DN60/]
	[ASCIZ	/DN87S/]
	[ASCIZ	/CFE/]
	[ASCIZ	/MCB/]

ONOFF:	ASCIZ	/ON/
	ASCIZ	/OFF/

DEFINE	.DISK(CNT,UNT,NAM),<
	XWD <CNT_9>+UNT,[ASCIZ /NAM/]
>; END DEFINE .DISK

DSKUNT:	$STAB
	.DISK	(.DCCFS,.DCUS4,RS04)
	.DISK	(.DCCRP,.DCUR4,RP04)
	.DISK	(.DCCRP,.DCUR6,RP06)
	.DISK	(.DCCRP,.DCUR3,RM03)
	.DISK	(.DCCRP,.DCUR7,RP07)
	.DISK	(.DCCRN,.DCUN0,RP20)
	.DISK	(.DCCRA,.DCU80,RA80)
	.DISK	(.DCCRA,.DCU81,RA81)
	.DISK	(.DCCRA,.DCU60,RA60)
	.DISK	(.DCCSX,.DCUS0,3330)
	.DISK	(.DCCSX,.DCUS1,3331)
	$ETAB

CTLTAB:	$STAB
	XWD	540,[ASCIZ /RH20-0/]
	XWD	544,[ASCIZ /RH20-1/]
	XWD	550,[ASCIZ /RH20-2/]
	XWD	554,[ASCIZ /RH20-3/]
	XWD	560,[ASCIZ /RH20-4/]
	XWD	564,[ASCIZ /RH20-5/]
	XWD	570,[ASCIZ /RH20-6/]
	XWD	574,[ASCIZ /RH20-7/]
	XWD	270,[ASCIZ /RH10-0/]
	XWD	274,[ASCIZ /RH10-1/]
	XWD	360,[ASCIZ /RH10-2/]
	XWD	220,[ASCIZ /DX10-0/]
	XWD	224,[ASCIZ /DX10-1/]
	XWD	034,[ASCIZ /DX10-2/]
	$ETAB

;DSKMUK CONTAINS ENTRIES FOR MULTI-UNIT DISK CONTROLLERS (ONLY RP20)

DSKMUK:	$STAB
	XWD	.DCCRN,[ASCIZ /DX20/]
	$ETAB

;TAPMUK CONTAINS ENTRIES FOR MULTI-UNIT TAPE CONTROLLERS

TAPMUK:	$STAB
	XWD	.TFKTM,[ASCIZ |TM02/3|] ;RH10/RH20
	XWD	.TFKRH,[ASCIZ |TM02/3|]	;RH11
	XWD	.TFKD2,[ASCIZ /DX20/]
	XWD	.TFK78,[ASCIZ /TM78/]
	XWD	.TFKSX,[ASCIZ /SA10/]	;SA10
	$ETAB

TAPTYP:	$STAB
	XWD	.TFKTA,[ASCIZ /TM10A/]
	XWD	.TFKTB,[ASCIZ /TM10B/]
	XWD	.TFKTC,[ASCIZ /TM10C/]
	XWD	.TFKTX,[ASCIZ /TU70/]	;DX10
	XWD	.TFKTM,[ASCIZ /TU77/]	;RH10/RH20
	XWD	.TFKRH,[ASCIZ /TU45/]	;RH11
	XWD	.TFKD2,[ASCIZ /TU70/]	;DX20
	XWD	.TFK78,[ASCIZ |TU78/9|]
	XWD	.TFKSX,[ASCIZ /TU70/]	;SA10
	$ETAB

ONFSTS:	[ASCIZ	/Offline/]
	[ASCIZ	/Online/]
	SUBTTL	Miscellaney


;Routine to do a GETTAB on a CPU-specific table entry.
;Call:
;	T1/ Table item
;	P1/ CPU number

CPUGTB:	HRRZ	S1,P1		;COPY CPU NUMBER
	LSH	S1,1		;TIMES TWO
	ADDB	T1,S1		;ADJUST TABLE INDEX FOR CPUN
	GETTAB	T1,		;DO THE GETTAB
	  JRST	GTBERR		;ERROR
	POPJ	P,		;SUCCESS


;Routine to do a GETTAB on a CPU-specific subtable entry.
;Call:
;	T1/ Subtable pointer
;	T2/ Subtable offset
;	P1/ CPU number

CPUSTB:	HRRZ	S1,P1		;COPY CPU NUMBER
	LSH	S1,1		;TIMES TWO
	ADDB	T1,S1		;ADJUST TABLE INDEX FOR CPUN
	GETTAB	T1,		;GET SUBTABLE POINTER
	  JRST	GTBERR		;ERROR
	LOAD	S1,T1,CC%CLN	;GET LENGTH-1 OF SUBTABLE (MAXIMUM INDEX)
	CAMLE	T2,S1		;ITEM WE WANT IN THE TABLE?
	JRST	GTBERR		;NOPE
	LOAD	S1,T1,CC%NRA	;GET OFFSET IN .GTCNV OF SUBTABLE
	ADD	S1,T2		;OFFSET BY THE DESIRED ITEM
	MOVS	T1,S1		;PLUG IT IN
	HRRI	T1,.GTC0V	;CDB VARIABLES TABLE FOR CPU0
	HRRZ	S1,P1		;COPY CPU NUMBER
	LSH	S1,1		;TIMES TWO
	ADDB	T1,S1		;ADJUST TABLE INDEX FOR CPUN
	GETTAB	T1,		;ASK THE MONITOR
	  JRST	GTBERR		;ERROR
	POPJ	P,		;RETURN
;Convert ANF10 node number to name.
;Returns name for node in DTETYP in T1.
;Returns ITEXT address for printing node number in T2.

ANFNOD:	MOVE	T1,[.NDRNN,,T2]	;SET UP ARGUMENTS
	MOVEI	T2,2		;2 WORDS
	HLRZ	T3,DTETYP	;GET NODE NUMBER
	NODE.	T1,		;ASK NETSER
	  POPJ	P,		;DOESN'T KNOW?
	MOVEI	T2,[ITEXT (<^O/DTETYP,LHMASK/>)] ;RETURN ITEXT FOR NUMBER
	JRST	.POPJ1##	;SKIP RETURN


;Convert DECnet node number to name.
;Returns name for node in DTETYP in T1.
;Returns ITEXT address for printing node number in T2.

;Masks for DECnet node addresses:
	DN%ARE==77_^D10
	DN%ADR==<1_^D10>-1

DCNNOD:	MOVE	T1,[DN.FLK+INSVL.(.DNNDI,DN.FNC)+INSVL.(2,DN.ARG)]
	HLRZ	T2,DTETYP	;GET NODE NUMBER
	MOVEI	T3,T1		;POINT AT ARGUMENTS
	DNET.	T3,		;ASK MONITOR
	  POPJ	P,		;DOESN'T KNOW
	MOVE	T1,T2		;COPY NAME
	HLRZ	T3,DTETYP	;GET NODE NUMBER AGAIN
	TRNN	T3,DN%ARE	;DOES IT HAVE AN AREA NUMBER?
	SKIPA	T2,[[ITEXT (<^D/T3/.>)]] ;NO, RETURN ITEXT FOR OLD FORMAT
	MOVEI	T2,[ITEXT (<^D/T3,DN%ARE/.^D/T3,DN%ADR/>)] ;YES, NEW FORMAT
	JRST	.POPJ1##	;SKIP RETURN WITH APPRORIATE ITEXT IN T2
;Convert 8-bit text string to 7-bit.  Strips trailing blanks.
;Call:
;	T1/ Number of words
;	T2/ Address of first word
;Converted string is returned in TMPSTG.
;Returns byte pointer to first free character in T1.

CNVASC:	MOVEI	S1,10		;NUMBER OF WORDS
	MOVEI	S2,TMPSTG	;ADDRESS OF BLOCK
	$CALL	.ZCHNK		;ZERO RESULT AREA
	IMULI	T1,4		;CONVERT WORDS TO BYTES
	HRLI	T2,(POINT 8)	;MAKE A BYTE POINTER
	MOVE	T3,[POINT 7,TMPSTG] ;POINTER TO STORE RESULT
	MOVE	T4,T3		;SAVE LAST VALID CHARACTER POINTER
CNVA.1:	ILDB	S1,T2		;GET A CHARACTER
	JUMPE	S1,CNVA.2	;DONE IF NULL
;IT'S JUST 7-BIT ASCII IN 8-BIT BYTES, SO NO CONVERSION NEEDED
	IDPB	S1,T3		;STORE IN RESULT AREA
	CAXE	S1," "		;FOUND A SPACE?
	MOVE	T4,T3		;NO, KEEP A COPY OF THE POINTER
	SOJG	T1,CNVA.1	;LOOP FOR MORE BYTES
CNVA.2:	SETZ	S1,		;GET A NULL
	IDPB	S1,T4		;END THE STRING
	MOVE	T1,T4		;RETURN BYTE POINTER IN T1
	POPJ	P,		;RETURN
;PRINT CPU ACCESSIBILITY MASK FOR DEVICE
;CALL WITH MASK IN S1.

CPUNUM:	TDZA	T4,T4		;FLAG ENTRY POINT
CPUMSK:	SETOM	T4
	MOVEI	T1,1		;GET BIT FOR CPU0
	MOVSI	T2,-6		;LOOP FOR ALL CPUS POSSIBLE
	SETZ	T3,		;NOBODY CAN ACCESS IT (YET)
CPUM.1:	TDNN	T1,S1		;ACCESSIBLE VIA THIS CPU?
	AOSA	T3		;NO, COUNT ANOTHER SPACE NEEDED AT END
	$TEXT	(WTIRTN,<^D/T2,RHMASK/^A>) ;PRINT CPU DIGIT
	LSH	T1,1		;SHIFT THE BIT FOR THE NEXT CPU
	AOBJN	T2,CPUM.1	;LOOP FOR REMAINDER
	JUMPE	T4,.POPJ	;RETURN IF ONLY NUMBERS WANTED
CPUM.2:	$TEXT	(WTIRTN,< ^A>)	;PRINT A SPACE
	SOJG	T3,CPUM.2	;LOOP FOR NUMBER REQUIRED
	$TEXT	(WTIRTN,<  ^A>)	;END WITH 2 SPACES
	POPJ	P,		;RETURN
;Set up a copy of NXMTAB.  Tries to use GETTAB .GTNXM if available,
;otherwise PEEKs the data.

SUNXMT:	HLRE	S1,NXMPTR	;GET -VE OF WORDS IN TABLE
	MOVMS	S1		;MAKE IT +VE
	HRRZ	S2,NXMPTR	;GET ADDRESS OF TABLE
	SKIPE	S1		;UNLESS VIRGIN TABLE,
	$CALL	M%RMEM		;RETURN THE SPACE
	SETZM	NXMPTR		;FORGET ABOUT IT
	MOVX	T1,%CNNXM	;GET MONITOR'S POINTER TO NXMTAB
	GETTAB	T1,		;ASK MONITOR
	  HALT	.		;OOPS
	HLRE	S1,T1		;GET -VE SIZE OF TABLE
	MOVMS	S1		;MAKE +VE
	$CALL	M%GMEM		;GET THE SPACE
	HLL	S2,T1		;PLUG IN -VE SIZE
	MOVEM	S2,NXMPTR	;SAVE OUR TABLE POINTER
	MOVE	S1,[.GTNXM,,.GTSLF] ;SEE IF GETTAB-ABLE
	GETTAB	S1,		;ASK MONITOR
	  SETZ	S1,		;GUESS NOT
	JUMPN	S1,SUNX.2	;GO IF GETTAB EXISTS
SUNX.1:	HRRZ	S1,T1		;COPY ADDRESS OF WORD
	PEEK	S1,		;SNEAK A PEEK
	MOVEM	S1,(S2)		;STUFF IT
	AOBJP	T1,.POPJ##	;RETURN IF MONITOR'S TABLE EXPIRED
	AOBJN	S2,SUNX.1	;KEEP COPYING
	POPJ	P,		;RETURN

SUNX.2:	HLLZS	T1		;KEEP JUST AOBJN INDEX IN RH
SUNX.3:	MOVS	S1,T1		;GET INDEX INTO NXMTAB
	HRRI	S1,.GTNXM	;TABLE NUMBER
	GETTAB	S1,		;ASK MONITOR
	  HALT	.		;DUH?!
	MOVEM	S1,(S2)		;STUFF IT
	AOBJP	T1,.POPJ##	;RETURN IF MONITOR'S TABLE EXPIRED
	AOBJN	S2,SUNX.3	;KEEP COPYING
	POPJ	P,		;RETURN
;Obtain kontroller information
;S1/ SIXBIT kontroller name (unit name, actually)

KONINF:	PUSH	P,S1		;SAVE THE KONTROLLER NAME
	MOVX	S1,KONBKL	;LENGTH OF BLOCK
	MOVEI	S2,KONBLK	;ADDRESS OF IT
	$CALL	.ZCHNK		;ZERO IT
	POP	P,S2		;STUFF THE KONTROLLER NAME IN BLOCK
	HLLZM	S2,KONBLK+1	;SAVE IN BLOCK
	MOVX	S1,.DIOKI	;FUNCTION
	MOVEM	S1,KONBLK+0	;SAVE IT
	MOVE	S1,[-KONBKL,,KONBLK] ;POINT AT IT
	DIAG.	S1,		;ASK MONITOR
	  JRST	KONI.1		;ASSUME OLD MONITOR
	$RETT			;RETURN

KONI.1:	TLNN	S1,-1		;IF AC UNCHANGED, NOT SUPPORTED
	$RETF			;HOPEFULLY INVALID CONTROLLER
	$SAVE	<P1,P2>		;SAVE AN AC OR TWO
	MOVE	P2,S2		;COPY DEVICE NAME
	MOVE	S1,S2		;MOVE IT HERE
	PUSHJ	P,RCNCPU	;GET THE CPU MASK
	STORE	S1,KONBLK+2,DI.CAM ;SAVE IT HERE
	MOVE	S1,[-2,,P1]	;GET DEVICE CODE
	MOVX	P1,.DIAKU	;FUNCTION
	DIAG.	S1,		;ASK
	  SETZ	S1,		;WE TRIED
	HLRZS	S1		;MOVE IT HERE
	STORE	S1,KONBLK+3,DI.DVC ;SAVE IT HERE
	LDB	S1,[POINT 12,P2,11] ;GET FIRST 2 CHARS OF DEVICE NAME
	CAXE	S1,'MT'		;SOME SORT OF MAGTAPE?
	JRST	KONI.2		;NO
	MOVE	S1,[2,,P1]	;GET KONTROLLER TYPE
	MOVX	P1,.TFKTP	;FUNCTION
	TAPOP.	S1,		;ASK
	  SETZ	S1,		;WE TRIED
	MOVX	S2,.TYMTA	;GET DEVICE TYPE
	JRST	KONI.3		;CONTINUE

KONI.2:	MOVEI	S1,P2		;JUST WANT THE BITS
	DSKCHR	S1,
	  HALT	.		;DUH?
	LOAD	S1,S1,DC.CNT	;GET CONTROLLER TYPE
	MOVX	S2,.TYDSK	;DEVICE TYPE
KONI.3:	STORE	S1,KONBLK+2,DI.KTY ;SAVE IT AWAY
	STORE	S2,KONBLK+2,DI.DTY ;SAVE IT AWAY
	LDB	S1,[POINT 12,P2,11] ;GET FIRST 2 CHARACTERS OF DEVICE NAME
	MOVEI	S2,^D8		;ASSUME GENERIC DEVICE
	CAIN	S1,'RN'		;RP20 DISK?
	MOVEI	S2,^D16		;YES, BIGGER MAX
	CAIN	S1,'RA'		;CI DISK?
	MOVEI	S2,^D24		;YES, BIGGER MAX
	STORE	S2,KONBLK+2,DI.KUX ;STORE
	CAIE	S1,'RN'		;RP20 DISK?
	JRST	KONI.4		;NOPE
	MOVX	S2,DI.CLM!DI.MUK ;LOADABLE MICROCODE/MULTI-UNIT FLAG
	IORM	S2,KONBLK+2	;SET IT
KONI.4:	CAIE	S1,'MT'		;SOME FLAVOR OF MAGTAPE?
	$RETT			;NOPE, THAT'S IT
	LOAD	S1,KONBLK+2,DI.KTY ;GET KONTROLLER TYPE
	MOVX	S2,DI.CLM	;LOADABLE MICROCODE FLAG
	CAXE	S1,.TFKTX	;TX01 (DX10)?
	CAXN	S1,.TFKD2	;TX02 (DX20)?
	IORM	S2,KONBLK+2	;YES
	MOVX	S2,DI.MUK	;MULTI-UNIT KONTROLLER FLAG
	CAXE	S1,.TFKTM	;TM02 ON RH10/20?
	CAXN	S1,.TFKRH	;DITTO ON RH11?
	IORM	S2,KONBLK+2	;YES
	CAXE	S1,.TFKD2	;DX20?
	CAXN	S1,.TFK78	;TM78?
	IORM	S2,KONBLK+2	;YES
	$RETT			;RETURN


;Obtain unit information
;S1/ SIXBIT unit name

UNIINF:	PUSH	P,S1		;SAVE THE UNIT NAME
	MOVX	S1,UNIBKL	;LENGTH OF BLOCK
	MOVEI	S2,UNIBLK	;ADDRESS OF IT
	$CALL	.ZCHNK		;ZERO IT
	MOVEI	S1,MXPORT	;LENGTH OF BLOCK
	MOVEI	S2,KDBTBL	;ADDRESS OF IT
	$CALL	.ZCHNK		;ZERO IT
	MOVX	S1,.DIOUI	;FUNCTION
	MOVEM	S1,UNIBLK+0	;SAVE IT
	POP	P,UNIBLK+1	;SAVE THE UNIT NAME IN THE BLOCK
	MOVE	S1,[-MXPORT,,KDBTBL] ;AOBJN POINTER TO KDB TABLE FOR UNIT
	MOVEM	S1,UNIBLK+2	;POINT MONITOR AT IT
	MOVE	S1,[-UNIBKL,,UNIBLK] ;POINT AT ARGUMENTS
	DIAG.	S1,		;DO IT
	  JRST	UNII.1		;ASSUME OLD MONITOR
	POPJ	P,		;RETURN

UNII.1:	MOVSI	S1,-1		;NUMBER OF KNOWN PORTS SO FAR
	HLLM	S1,UNIBLK+2	;ADJUST AOBJN POINTER
	MOVE	S1,UNIBLK+1	;GET UNIT NAME
	HLLZM	S1,KDBTBL	;SAVE KONTROLLER NAME
	PUSHJ	P,RCNCPU	;GET CPU MASK
	HRLZM	S1,UNIBLK+5	;SAVE IT
;UNIT NUMBER?
	MOVE	S1,UNIBLK+1	;GET UNIT NAME
	MOVEM	S1,DCHBLK	;SAVE IT HERE
	MOVE	S1,[.DCMAX,,DCHBLK] ;DSKCHR ARGS
	DSKCHR	S1,		;SEE IF A DISK
	  POPJ	P,		;GUESS NOT
	SKIPN	S1,DCHBLK+.DCDET ;GET ALTERNATE PORT
	POPJ	P,		;NONE THERE
	HLLZM	S1,KDBTBL+1	;SAVE IT
	MOVSI	S1,-2		;WE KNOW ABOUT TWO PORTS
	HLLM	S1,UNIBLK+2	;FIXUP POINTER
	POPJ	P,		;RETURN
;DO .RCCPU

RCNCPU:	$SAVE	<P1,P2>		;SAVE A COUPLE OF TEMPS
	MOVE	P2,S1		;COPY DEVICE
	MOVX	P1,2		;NUMBER OF ARGUMENTS
	MOVE	S1,[.RCCPU,,P1]	;POINT AT ARGUMENTS
	RECON.	S1,		;ASK
	  SETZ	S1,		;SORRY
	POPJ	P,		;RETURN
;Zero SCS. UUO argument block

ZERSCS:	MOVX	S1,.SSMAX	;LENGTH OF BLOCK
	MOVEI	S2,SCSBLK	;ADDRESS OF IT
	$CALL	.ZCHNK		;ZERO IT
	$RETT			;RETURN


GTBERR:	$TEXT	(WTIRTN,<?GETTAB UUO error>)
	SUBTTL	The End


	END