Google
 

Trailing-Edge - PDP-10 Archives - BB-FP64A-SB_1986 - 10,7/rdreg/rdreg.mac
There are 5 other files named rdreg.mac in the archive. Click here to see a list.
	TITLE	RDREG -- Read and interpret Massbus registers
	SUBTTL	G.M. Uhler/GMU


;This program asks the user for an RH20 device code, an optional drive
;select unit number, and a CPU number if on a multi-CPU (TOPS-10) system and
;reads and interprets the massbus registers of the specified device.
;The program is assembled with a separate universal file, DEFS, that
;defines macros that give the massbus registers to interpret and the
;definitions of bits and fields in each register.  In this manner,
;only the UNIVERSAL file need be changed to change the type of device
;being interpreted.  The program is assembled for either TOPS-10 or TOPS-20
;by changing the definition of the parameter TOPS in the universal file
;RDRMAC.  This need be done only once when the program is moved to a new
;operating system.



;Copyright (C) 1980,1981,1982,1983 by
;Digital Equipment Corporation, Maynard, Mass.
;
;
;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.
	SUBTTL	Assembly directives


	SEARCH	RDRMAC		;Get the monitor specific definitions
	SEARCH	DEFS		;Get the Massbus register definitions

IF TOPS-10,<
	SEARCH	JOBDAT,MACTEN,UUOSYM
	.REQUIRE REL:SCAN
>
IF TOPS-20,<
	SEARCH	MONSYM,MACSYM
>
	.DIRECTIVE .XTABM,FLBLST
	SALL



	RDRVER==1		;Major version
	RDRMIN==0		;Minor version
	RDREDT==6		;Edit number
	RDRWHO==0		;Who edited


;Define the version number information for TOPS-10 and setup the program
;so that it's running as a sharable high segment.

IF TOPS-10,<
	LOC	.JBVER
	VRSN.	(RDR)
	RELOC
	TWOSEG
	RELOC	400000
>

;Define the entry vector for TOPS-20

IF TOPS-20,<
ENTVEC:	JRST	RDREG		;Start instruction
	JRST	RDREG		;Restart instruction
	FLD(RDRVER,VI%MAJ)!FLD(RDRMIN,VI%MIN)!FLD(RDREDT,VI%EDN)!FLD(RDRWHO,VI%WHO)
				;Version number
ENTLEN==.-ENTVEC		;Length of the entry vector
> ;End IF TOPS-20
	SUBTTL	Parameter definitions


;Miscelaneous definitions

PDLLEN==50			;Length of stack
DRAES==1B9			;Disable register access error interrupt
.DXDTR==06B5			;Drive type register
.FTBIT==1			;Field type is bit
.FTVAL==2			;Field type is value
.FTNVL==3			;Field type is value (negative number)
OPDEF XCONI[700240,,0]		;Because CONI is a macro also
	SUBTTL	Program initialization


RDREG:	JFCL			;No CCL entry
	RESET			;Clear the world
	MOVE	P,[IOWD PDLLEN,PDL] ;Setup a PDL
IF TOPS-10,<
	MOVEI	T1,0		;Force .TCHAR in SCAN to
	CALL	.TYOCH##	;  do an OUTCHR
> ;End IF TOPS-10
	CALL	ASKDVC		;Get the device code
	  JRST	BADDVC		;Bad device code
	CAIL	N,540		;Range check the
	CAILE	N,574		;  RH20 device code for legality
	CAIA			;Illegal
	TRNE	N,3		;And must be only 7 bits
	JRST	BADDVC		;Bad device code
	LSH	N,-2		;Convert to 7 bit form
	DPB	N,[POINT 7,DODATO,9] ;Store device code in DATAO
	DPB	N,[POINT 7,DODATI,9] ;Store device code in DATAI
	DPB	N,[POINT 7,DOCONI,9] ;Store device code in CONI
	MOVEI	N,0		;Assume no unit number required
IFN FTDSEL,<
	CALL	ASKUNI		;Ask for unit number
	  JRST	BADUNI		;Bad unit number
	JUMPL	N,BADUNI	;Range check the
	CAILE	N,7		;  drive select value
	JRST	BADUNI		;Go if error
> ;End IFN FTDSEL
	HRLZM	N,DRVSEL	;Save the drive select value
IF TOPS-10,<
	MOVX	T1,%CNST2	;GETTAB arg to get CNFST2
	GETTAB	T1,		;Get it
	  HALT	.		;Can't happen
	TXNE	T1,ST%LSC	;Low seg cached (i.e. only 1 CPU)?
	JRST	RDREG0		;Yes, don't ask about CPU number
	MOVEI	T1,0		;No arg for .QSCAN
	CALL	.QSCAN##	;Initialize input line
	HRROI	T1,[ASCIZ/CPU number: /]
	CALL	TSTRG		;Prompt the user
	CALL	OCTNW		;Get the number
	CAIL	N,0		;Range check the CPU number
	CAILE	N,5		;...
	JRST	BADCPU		;If illegal
	MOVX	T1,SP.CR0	;Get bit for CPU0
	LSH	T1,(N)		;Shift by value of CPU
	HRLI	T1,.STCPU	;Function for SET CPU ONLY CPUn
	SETUUO	T1,		;Restrict execution to that CPU
	  JRST	NOSCPU		;Failed
RDREG0:
> ;End IF TOPS-10
	USRIOT			;Get USRIOT privs from monitor
	  JRST	NOTRPS		;Request failed
	CALL	CHKDTR		;See if drive type is one we know about
	  JRST	BADDTR		;No, tell him
	HRROI	T1,[ASCIZ/

Rg Name      Contents        Text
-- ----   -------------- ----------------------------------------
/]
	CALL	TSTRG		;Type the header
	SUBTTL	Register read and print logic


	MOVSI	P1,-REGTBL	;Get AOBJN pointer to register table
	XCT	DOCONI		;Get the CONI
	JRST	RDREG2		;Skip the rest for the CONI
RDREG1:	MOVE	T1,DRVSEL	;Get drive select
	TXO	T1,DRAES	;Set DRAES
	HLRZ	T2,REGTAB(P1)	;Get register to read from table
	DPB	T2,[POINT 6,T1,5] ;Store in DATAO word
	XCT	DODATO		;Setup the preparation register
	IMULI	T1,1		;Stall
	IMULI	T1,1		;...
	XCT	DODATI		;Read the value
	LDB	T3,[POINT 6,T1,5] ;Get register select back
	CAIE	T3,(T2)		;Same as what we asked for?
	JRST	RDREG1		;No, took an interrupt at the wrong time
RDREG2:	MOVEM	T1,MBRTAB(P1)	;Store in the table
	AOBJN	P1,RDREG1	;Loop for all elements in the table
	MOVSI	P1,-REGTBL	;Build the AOBJN pointer again
	HRROI	T1,[ASCIZ/  /]	;No register number to print for CONI
	CALL	TSTRG		;  so don't try
	JRST	RDREG4		;Join common processing
RDREG3:	HLRZ	T1,REGTAB(P1)	;Get register back
	CALL	.TOCT2		;Type as 2 digit octal number
RDREG4:	CALL	TSPAC		;Add a space separator
	HRRZ	P3,REGTAB(P1)	;Get address of block for this register
	MOVE	T2,0(P3)	;Get SIXBIT name of register
	CALL	.T6ALL		;Type as full SIXBIT name
	CALL	TSPAC		;Add a space separator
	MOVE	T2,MBRTAB(P1)	;Get the octal value
	CALL	.T12DG		;Type as 12 octal digits
	MOVEI	C," "		;Make the separator a space
RDREG5:	SKIPN	T1,1(P3)	;Any more fields left to do?
	JRST	RDREG9		;No
	SKIPL	2(P3)		;This field valid for all types?
	CAMN	DTR,2(P3)	;No, is it legal for this one?
	CAIA			;Yes, continue
	JRST	RDREG8		;No, skip it
	LDB	T1,T1		;Get the field from P2
	HLRZ	T2,3(P3)	;Get the type of field
	CAIN	T2,.FTBIT	;Is it a bit?
	JUMPE	T1,RDREG8	;Yes, don't print if it's off
	PUSH	P,T1		;Save the value
	MOVE	T1,C		;Move the separator to T1
	CALL	TCHAR		;Type the separator
	HRRO	T1,3(P3)	;Get the string for this field
	CALL	TSTRG		;Type it
	CAIE	T2,.FTVAL	;This a value field?
	CAIN	T2,.FTNVL	;  or a negative value field?
	SKIPA	T1,["="]	;Yes, get the separator
	JRST	RDREG7		;No, continue
	CALL	TCHAR		;Print it
	SKIPE	T1,0(P)		;Get the value back but don't negate if 0
	CAIE	T2,.FTNVL	;Is it a negative value field?
	JRST	RDREG6		;No, just print as-is
	SETOM	T2		;Get a full mask of ones
	LDB	T3,[POINT 6,1(P3),11] ;Get the size of the field
	LSH	T2,(T3)		;Shift the ones mask that much
	IOR	T1,T2		;Make it a full 36 bit negative number
	MOVNS	T1		;Negate it
RDREG6:	CALL	TOCTW		;Type in octal
RDREG7:	POP	P,(P)		;Flush the stack
	MOVEI	C,","		;Change the separator
RDREG8:	ADDI	P3,3		;Step block pointer by length of field
	JRST	RDREG5		;  and loop for next field
RDREG9:	HRROI	T1,[ASCIZ/
/]				;Get a CRLF
	CALL	TSTRG		;End the line
	AOBJN	P1,RDREG3	;Loop for all registers
	RESET			;Clear the world
	MONRT.			;Exit quietly
	JRST	RDREG		;Resart if CONTINUE
	SUBTTL	Error processing



BADDVC:	SKIPA	T1,[-1,,[ASCIZ/
?Illegal RH20 device code
/]]
NOTRPS:	HRROI	T1,[ASCIZ/
?Failed to get USRIOT privilegs
/]
	CALL	TSTRG
	EXIT

IF TOPS-10,<
BADCPU:	SKIPA	T1,[-1,,[ASCIZ/
?Illegal CPU number
/]]
NOSCPU:	HRROI	T1,[ASCIZ/
?Unable to restrict execution to specified CPU
/]
	CALL	TSTRG
	EXIT
> ;End IF TOPS-10

IFN FTDSEL,<
BADUNI:	SKIPA	T1,[-1,,[ASCIZ/
?Illegal unit number
/]]
> ;End IFN FTDSEL

BADDTR:	HRROI	T1,[ASCIZ/
?Drive type register does not match known values
/]
	CALL	TSTRG
	EXIT
	SUBTTL	Subroutines


;Routine to print a number left-padded to a least size two with spaces.
;Call:
;	T1/Number
;	CALL	.TOCT2
;Return CPOPJ always

.TOCT2:	CAILE	T1,7		;One digit?
	PJRST	TOCTW		;No, print as-is
	PUSH	P,T1		;Save the number
	CALL	TSPAC		;Type a space
	POP	P,T1		;Restore the number
	PJRST	TOCTW		;Type it


;Routine to print all 6 characters of a SIXBIT name.
;Call:
;	T2/SIXBIT word
;	CALL	.T6ALL
;Return CPOPJ always

.T6ALL:	MOVEI	T3,6		;Setup loop count
.T6AL1:	LSHC	T1,^D36		;Move to T1, clear T2
	LSHC	T1,-^D30	;Keep just one character in T1
	ADDI	T1,"A"-'A'	;Convert to ASCII
	CALL	TCHAR		;Type it
	SOJG	T3,.T6AL1	;Loop for all six
.HELPR::RET			;Return


;Routine to print a number as six octal digits separated by commas.
;Call:
;	T2/Number
;	CALL	.T12DG
;Return CPOPJ always

.T12DG:	PUSH	P,T2		;Save the number
	CALL	.T12D1		;Type the left half
	HRROI	T1,[ASCIZ/,,/]	;Separate the two halves
	CALL	TSTRG		;  by commas
	POP	P,T2		;Restore the number
	HRLZS	T2		;Keep only right half
.T12D1:	MOVEI	T3,6		;Get a loop count
.T12D2:	LSHC	T1,^D36		;Move number to T1, clear T2
	LSHC	T1,-^D33	;Keep only 3 bits
	ADDI	T1,"0"		;Convert to ASCII
	CALL	TCHAR		;Type it
	SOJG	T3,.T12D2	;Loop for all
	RET			;Return
;Routine to read the drive type register from the specified drive
;and check it against the table of the ones we know about.
;Call:
;	CALL	CHKDTR
;Return CPOPJ if no match
;	CPOPJ1 if match with DTR set to the index

CHKDTR:	MOVX	T1,.DXDTR!DRAES ;Get drive type register
	IOR	T1,DRVSEL	;Include drive select field
	XCT	DODATO		;Setup the preparation register
	IMULI	T1,1		;Stall
	IMULI	T1,1		;...
	XCT	DODATI		;Read the value
	LDB	DTR,[POINT 6,T1,5] ;Get the register select field
	CAIE	DTR,<.DXDTR_-^D30> ;Was it the register we wanted?
	JRST	CHKDTR		;No, try again
	ANDI	T1,77		;Isolate just the drive type
	MOVSI	DTR,-DTRTBL	;Build AOBJN pointer to table
CHKDT1:	CAME	T1,DTRTAB(DTR)	;Find a match?
	AOBJN	DTR,CHKDT1	;No, loop for all
	JUMPGE	DTR,.POPJ	;Return error if no match
	TLZ	DTR,-1		;Clear the LH
.POPJ1:	AOS	0(P)		;Give skip return
.POPJ:	RET			;Return

;Define the table of drive types that we know about.

DEFINE DTRTYP(A,B),<
	EXP	A
.DT'B==.-DTRTAB-1
>

DTRTAB:	DRVTYP
DTRTBL==.-DTRTAB
	SUBTTL	TOPS-10 specific support routines


;The following equivalences define the local routines in terms of routines
;in SCAN for TOPS-10.

IF TOPS-10,<
TCHAR==.TCHAR##			;Type a character
TSTRG==.TSTRG##			;Type a string
OCTNW==.OCTNW##			;Input an octal number
TSPAC==.TSPAC##			;Type a space
TOCTW==.TOCTW##			;Type an octal number


;Routine to ask the user for the RH20 device code.
;Call:
;	CALL	ASKDVC
;Return CPOPJ if error
;	CPOPJ1 with number in N

ASKDVC:	MOVEI	T1,0		;No arg for .QSCAN
	CALL	.QSCAN##	;Initialize input line
	HRROI	T1,[ASCIZ/
RH20 device code: /]
	CALL	TSTRG		;Prompt the user
	CALL	OCTNW		;Get the number
	RETSKP			;Give skip return


IFN FTDSEL,<
;Routine to ask the user for the massbus unit number.
;Call:
;	CALL	ASKUNI
;Return CPOPJ if error
	CPOPJ1 with number in N

ASKUNI:	MOVEI	T1,0		;No arg for .QSCAN
	CALL	.QSCAN##	;Initialize input line
	HRROI	T1,[ASCIZ/Unit number (drive select): /]
	CALL	TSTRG		;Prompt the user
	CALL	OCTNW		;Get the number
	RETSKP			;Give skip return
> ;End IFN FTDSEL
> ;End IF TOPS-10
	SUBTTL	TOPS-20 specific support routines


IF TOPS-20,<
;Routine to print a space character.
;Call:
;	CALL	TSPAC
;Return CPOPJ always

TSPAC:	HRROI	T1,[ASCIZ/ /]	;Get the space
;;	PJRST	TSTRG		;Fall into TSTRG


;Routine to print a string.
;Call:
;	T1/Byte pointer to string
;	CALL	TSTRG
;Return CPOPJ always

TSTRG:	PSOUT			;Output the string
	RET			;Return


;Routine to print a character.
;Call:
;	T1/Character to print
;	CALL	TCHAR
;Return CPOPJ always
;Preserves all but T1

TCHAR:	PUSH	P,T2		;Save T2
	LSHC	T1,-^D36	;Move character to T2, clear rest of word
	LSHC	T1,^D36-^D7	;Left justify character in T2
	HRROI	T1,T2		;Get a byte pointer to the character
	PSOUT			;Output it
	POP	P,T2		;Restore T2
	RET			;Return


;Routine to print an octal number.
;Call:
;	T1/number to print
;	CALL	TOCTW
;Return CPOPJ always
;Destroys T1, T2, T3

TOCTW:	MOVE	T2,T1		;Copy number to T2
	MOVX	T1,.PRIOU	;Destination is primary output device
	MOVX	T3,FLD(^D8,NO%RDX) ;Radix is octal
	NOUT			;Output the number
	  HALT	.		;Shouldn't happen
	RET			;Return
;Routine to ask the user for the RH20 device code.
;Call:
;	CALL	ASKDVC
;Return CPOPJ if error
;	CPOPJ1 with number in N

ASKDVC:	HRROI	T1,[ASCIZ/
RH20 device code: /]
	PJRST	ASKNUM


IFN FTDSEL,<
;Routine to ask the user for the massbus unit number.
;Call:
;	CALL	ASKUNI
;Return CPOPJ if error
	CPOPJ1 with number in N

ASKUNI:	HRROI	T1,[ASCIZ/Unit number (drive select): /]
	PJRST	ASKNUM
> ;End IFN FTDSEL


;Routine to ask the user for an octal number.
;Call:
;	T1/Byte pointer to prompt string
;	CALL	ASKNUM
;Return CPOPJ if error
;	CPOPJ1 with number in N

ASKNUM:	MOVE	T3,T1		;Copy byte pointer to T3 for RDTTY
	PSOUT			;Prompt the user
	SETZM	NUMBUF		;Clear first word of NUMBUF
	MOVE	T1,[NUMBUF,,NUMBUF+1] ;Setup to clear it all
	BLT	T1,NUMBUF+NUMBLN-1 ;Clear it all
	HRROI	T1,NUMBUF	;Get byte pointer to NUMBUF
	MOVEI	T2,NUMBLN*5	;Get length of buffer in bytes
	RDTTY			;Read the string from the user
	  RET			;Failed
	HRROI	T1,NUMBUF	;Get byte pointer to NUMBUF again
	MOVEI	T3,^D8		;Radix is octal
	NIN			;Read the number
	  RET			;Failed
	MOVE	N,T2		;Return the number in N
	ILDB	T2,T1		;Get next byte
	JUMPE	T2,.POPJ1	;Give skip return if end of line
	RET			;Else error
> ;End IF TOPS-20
	SUBTTL	Generate the tables from the macros


;Define a macro to generate byte pointers from the mask in the
;FIELDS macro definition.  Stupid MACRO chokes on the one in MACTEN
;unless the argument to the POS macro is symbolic.

DEFINE	POINTR(LOC,MASK),<
	POSN==POS(<MASK>)
	SIZ==WID(<MASK>)
	POINT	SIZ,LOC,POSN
>


;Define the first-level table that gives the registers that we want to
;read and the address of the block describing the fields in that register.

DEFINE XX(A,B),<
	XWD	A,.'B
>

REGTAB:	REGS
REGTBL==.-REGTAB


;Now, for each register defined in the REGTAB table, define another
;table giving its SIXBIT mnemonic and the fields that we want to
;interpret in the register.

DEFINE XX(A,B),<
.'B:	SIXBIT/B/
	B
	EXP	0
>

DEFINE FIELDS(A,B,C,D),<
IFIDN <C>,<BIT>,<..XX==.FTBIT>
IFIDN <C>,<VAL>,<..XX==.FTVAL>
IFIDN <C>,<NVAL>,<..XX==.FTNVL>
IFIDN <D>,<ALL>,<..YY==-1>
IFDIF <D>,<ALL>,<..YY==.DT'D>
	POINTR	MBRTAB(P1),A
	EXP	..YY
	XWD	..XX,[ASCIZ\B\]
>
	REGS
	SUBTTL	Low segment data locations


	XLIST			;Literals under XLIST
	LIT
	LIST

IF TOPS-10,<
	RELOC
>


DODATO:	DATAO	0,T1		;Device code patched in
DODATI:	DATAI	0,T1		;Ditto
DOCONI:	XCONI	0,T1		;Ditto
DRVSEL:	BLOCK	1		;Drive select value in bits 15-17
MBRTAB:	BLOCK	REGTBL		;Registers stored here
PDL:	BLOCK	PDLLEN		;Push down list
IF TOPS-20,<
NUMBUF:	BLOCK	2		;Storage for numbers read in
NUMBLN==.-NUMBUF		;Length of buffer
> ;End IF TOPS-20


IF TOPS-10,<
	END	RDREG
> ;End IF TOPS-10

IF TOPS-20,<
	END	<ENTLEN,,ENTVEC>
> ;End IF TOPS-20