Google
 

Trailing-Edge - PDP-10 Archives - tops10_703a_sys_atpch16_bb-fr67f-bb - 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		21-Nov-86


	SEARCH	GLXMAC, ORNMAC
	SALL
	PROLOG	(CNFHDW)

	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)


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

	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


;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
	SUBTTL	Data segment


	$DATA	TMPSTG,10	;TEMPORARY BLOCK FOR CONVERTING TEXT STRINGS

	$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

				;*** 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,3	;DIAG. UUO BLOCK

	$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
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
	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.CFE!HW.UBA!HW.CPU	;CFE OR CPU INFO?
	PUSHJ	P,CPU		;LIST CPU CONFIGURATION
	TXNE	F,HW.MME	;MEMORY INFO?
	PUSHJ	P,MEMORY	;LIST MEMORY CONFIGURATION
	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.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
	SETZM	KLFLAG		;DON'T KNOW CPU TYPE YET
	MOVX	T1,%CCTYP	;GET CPU TYPE
	PUSHJ	P,CPUGTB	;DO CPU-SPECIFIC GETTAB
	HRRZS	T1		;KEEP JUST DIGITAL CPU TYPE
	CAXN	T1,.CCKLX	;CPU A KL10?
	SETOM	KLFLAG		;YES
	CAXN	T1,.CCKLX	;CPU A KL10?
	MOVEI	T2,[ASCIZ /KL10/]
	CAXN	T1,.CCKSX	;CPU A KS10?
	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
	$TEXT	(WTIRTN,< serial number ^D/T1/, 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.7		;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?
	HRRZ	T2,DTETYP	;GET SOFTWARE TYPE
	CAIE	T2,.C1MCB	;MCB?
	SKIPA	T2,[[ITEXT (<^O/DTETYP,LHMASK/>)]]
	MOVEI	T2,[ITEXT (<^D/DTETYP,RHMASK/.>)]
	$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
	PUSHJ	P,OPENFE	;OPEN UP AN "FE" DEVICE
	  JRST	CPL.13		;NONE AVAILABLE?
	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,<
	PUSHJ	P,CFEDEV	;PRINT CFE DEVICE CONFIGURATION
>; END IFN FTLCFE
	JRST	CPU.N		;NEXT CPU
CPUS.1:				;KS10 HARDWARE STUFF GOES HERE
IFN FTLUBA,<
	PUSHJ	P,UBACNF	;PRINT UBA CONFIGURATION
>; END IFN FTLUBA
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 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
	HALT	.		;NO, REAL ERROR
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
	  HALT	.		;ERROR
	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
	  HALT	.		;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
	;$TEXT	(WTIRTN,<^M^JNI Configuration^M^J^J      Node       S/W type  S/W vers  H/W type^M^J  -------------  --------  --------  -------->)
	POPJ	P,		;FOR NOW
	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>)
	$TEXT	(WTIRTN,<  ---------->)
	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
	$TEXT	(WTIRTN,<  ^W6L/.DDNAM(P1)/  ^A>)
	SKIPN	KLFLAG		;KL SYSTEM?
	JRST	DISK.2		;NO, SKIP THIS STUFF
	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>)
	MOVE	S1,.DDXCH(P1)	;GET ACCESSIBILITY MASK
	SKIPE	MLTCPU		;IF SMP SYSTEM,
	PUSHJ	P,CPUMSK	; PRINT CPU ACCESSIBILITY MASK
	LOAD	S1,.DDSTS(P1),DC.CNT ;GET CONTROLLER TYPE
	HLRZ	S2,.DDCTL(P1)	;GET CONTROLLER DEVICE CODE
	PUSHJ	P,DSKCTL	;COBBLE UP A NAME
	$TEXT	(WTIRTN,<^T/0(S2)/^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:	$TEXT	(WTIRTN,<^M^JTape Configuration^M^J^J  Drive    Type   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>)
	$TEXT	(WTIRTN,<  ---------->)
	MOVX	T1,.TYMTA	;DEVICE TYPE
	MOVEM	T1,DVPBLK+0	;SALT IT AWAY
	SETZM	DVPBLK+1	;WE WANT FIRST DEVICE

TAPE.1:	MOVE	T1,[2,,DVPBLK]	;POINT AT ARGUMENTS
	DVPHY.	T1,		;ASK FOR NEXT DEVICE
	  POPJ	P,		;DONE?
	SKIPN	T1,DVPBLK+1	;ANYTHING THERE?
	POPJ	P,		;NO, MUST BE DONE
	LDB	T2,[POINT 12,T1,11] ;GET FIRST 2 CHARACTERS OF DEVICE NAME
	CAIN	T2,' ''L'	;LABEL DDB?
	JRST	TAPE.1		;YES, SKIP IT
	MOVEM	T1,TOPBLK+1	;SAVE FOR LOTS OF TAPOP. FUNCTIONS
	$TEXT	(WTIRTN,<  ^W6/T1/  ^A>) ;START WITH NAME
	MOVX	T1,.TFKTP	;READ CONTROLLER TYPE
	MOVEM	T1,TOPBLK+0
	MOVE	T1,[2,,TOPBLK]	;POINT AT ARGUMENTS
	TAPOP.	T1,		;ASK MONITOR
	  SETZ	T1,		;ASSUME SOMETHING WORTHLESS
	MOVE	P1,T1		;PRESERVE IT
	$TEXT	(WTIRTN,<^T6L/@TAPTYP(T1)/  ^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>)
	MOVE	S1,[.RCCPU,,T2]	;POINT AT ARGUMENTS
	MOVEI	T2,2		;JUST 2 WORDS
	MOVE	T3,DVPBLK+1	;GET DEVICE NAME
	RECON.	S1,		;ASK MONITOR FOR CPU MASK
	  SETZ	S1,		;DUH?
	SKIPE	MLTCPU		;IF SMP SYSTEM,
	PUSHJ	P,CPUMSK	; PRINT CPU MASK
	SKIPN	KLFLAG		;KL SYSTEM?
	JRST	TAPE.2		;NO
	MOVE	S1,[-2,,T1]	;ASK FOR DEVICE CODE
	MOVX	T1,.DIAKU	;DIAG. FUNCTION
	MOVE	T2,DVPBLK+1	;GET DEVICE NAME
	DIAG.	S1,		;ASK MONITOR
	  SETZ	S1,		;DUH?
	HLRZ	S2,S1		;KEEP JUST THE PERTINENT INFO
	MOVE	S1,P1		;COPY CONTROLLER TYPE
	PUSHJ	P,TAPCTL	;COBBLE UP A NAME FOR THE CONTROLLER
	$TEXT	(WTIRTN,<^T/0(S2)/^A>)
TAPE.2:	$TEXT	(WTIRTN,<>)	;END THE LINE
	JRST	TAPE.1		;ON TO NEXT UNIT
	SUBTTL	Generate Disk/Tape Controller Name

TAPCTL:	CAIN	S1,.TFKD2	;DX20 TAPE CONTROLLER?
	JRST	TAPC.1		;YES
	JRST	COMCTL		;NO
DSKCTL:	CAIN	S1,.DCCRA	;CI DISK CONTROLLER?
	JRST	DSKC.1		;YES
	CAIN	S1,.DCCRN	;RP20 DISK CONTROLLER?
	JRST	DSKC.2		;YES
COMCTL:	MOVE	S1,S2		;COPY CONTROLLER DEVICE CODE
	MOVEI	S2,CTLTAB	;POINT AT TABLE
	PUSHJ	P,TABSRC##	;LOOK FOR A MATCH
	$RETIT			;GOODNESS IF TABSRC FOUND AN ENTRY
	$TEXT	(<-1,,TMPSTG>,<Device code ^O3/S1/^0>) ;SAY SOMETHING
	MOVEI	S2,TMPSTG	;POINT AT RESULT
	POPJ	P,		;BEST WE COULD DO

DSKC.1:	LDB	S1,[POINT 6,.DDNAM(P1),17] ;$$$ GET CONTROLLER NUMBER
	SUBI	S1,'A'		;$$$ ENCODED AS 'A' - 'Z'
	$TEXT	(<-1,,TMPSTG>,<HSC50-^D/S1/^0>)
	MOVEI	S2,TMPSTG	;POINT AT RESULT
	POPJ	P,		;GOOD STUFF HERE

TAPC.1:!			;DX20 TAPES COME HERE TOO
DSKC.2:	MOVE	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
	SETZ	S2,		;$$$ FOR NOW
	$TEXT	(<-1,,TMPSTG>,<RH20-^O/S1,RHMASK/ (^O3/S1,LHMASK/), DX20-^O/S2/^0>)
	MOVEI	S2,TMPSTG	;COP OUT
	POPJ	P,		;BUT IT SUFFICES
	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	DTA,0,DECtape
DEV	LPT,URCLPT,Line printer
DEV	PTR,0,Paper tape reader
DEV	PTP,0,Paper tape punch
>; 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),<
	EXP	HDR'TYPE
>; END DEFINE DEV

URCHDR:	DEVS

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

URCDEV:	DEVS
HDRCDR:	ASCIZ	/    Device  CPU
    ------  ---/
HDRCDP:	ASCIZ	/    Device  CPU
    ------  ---/
HDRDTA:	ASCIZ	/    Device  CPU
    ------  ---/
HDRLPT:	ASCIZ	/    Device  CPU  Type   Status
    ------  ---  -----  ------/
HDRPTR:	ASCIZ	/    Device  CPU
    ------  ---/
HDRPTP:	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/  ^T20L/(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  ******  ^T20/(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 8 line group>,170500,<DM11-BB #0 Modem Ctl>
	DEV	160040,<DH11 #1 8 line group>,170510,<DM11-BB #1 Modem Ctl>
	DEV	160060,<DH11 #2 8 line group>,170520,<DM11-BB #2 Modem Ctl>
	DEV	160100,<DH11 #3 8 line group>,170530,<DM11-BB #3 Modem Ctl>
	DEV	160120,<DH11 #4 8 line group>,170540,<DM11-BB #4 Modem Ctl>
	DEV	160140,<DH11 #5 8 line group>,170550,<DM11-BB #5 Modem Ctl>
	DEV	160160,<DH11 #6 8 line group>,170560,<DM11-BB #6 Modem Ctl>
	DEV	160200,<DH11 #7 8 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
	SETZM	DTEBLK+1	;START WITH FE NUMBER 0

OPFE.1:	MOVE	T1,[.DTEGF,,DTEBLK] ;POINT AT ARGUMENTS
	DTE.	T1,		;TRY TO GET AN FED
	  SKIPA			;ERROR
	JRST	.POPJ1##	;SUCCESS
	CAIE	T1,DTEFB%	;FED BUSY?
	CAIN	T1,DTENF%	;OR NON-EXISTANT?
	AOSA	DTEBLK+1	;YES, TRY NEXT FE
	POPJ	P,		;NO, WE'RE CONFUSED, GIVE UP
	JRST	OPFE.1		;MAYBE THAT WILL SUCCEED


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)
	$ETAB

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

TAPTYP:	[ASCIZ	/TM10A/]
	[ASCIZ	/TM10B/]
	[ASCIZ	/TM10C/]
	[ASCIZ	/TU70/]
	[ASCIZ	|TM02/3|]
	[ASCIZ	|TM02/3|]
	[ASCIZ	/TU70/]
	[ASCIZ	/TU78/]
	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.

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?
	JRST	.POPJ1##	;SKIP RETURN


;Convert DECnet node number to name.
;Returns name for node in DTETYP in T1.

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
	JRST	.POPJ1##	;SKIP RETURN
;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.

CPUMSK:	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
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
;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:	HALT	.		;OOPS
	SUBTTL	The End


	END