Google
 

Trailing-Edge - PDP-10 Archives - BB-F492Z-DD_1986 - 10,7/703mon/dx2com.mac
There are 2 other files named dx2com.mac in the archive. Click here to see a list.
TITLE	DX2COM -- COMMON CODE FOR ALL DEVICES DRIVEN THROUGH DX20'S V012
SUBTTL	G.M. UHLER/GMU	10 SEP 85
	SEARCH	F,S,ICHPRM
	$RELOC
	$HIGH



;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1981,1986>
;COPYRIGHT (C) 1981,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.


;

XP VDX2CM,012
SALL


;ASSEMBLY INSTRUCTIONS:
;	.R MACRO
;	*DX2COM,DX2COM/C=DX2COM

DX2COM::ENTRY	DX2COM


;TECHNICAL INFORMATION AND TECHNIQUES FOR PROGRAMMING THE
;RH20/DX20 ARE AVAILABLE IN THE FOLLOWING DOCUMENTS:
;
;  DX20 PROGRAMMED DEVICE ADAPTER TECHNICAL MANUAL,
;	DOCUMENT NUMBER EK-0DX20-TM-001, FEB 78
;  RH20 MASSBUS CONTROLLER UNIT DESCRIPTION,
;	DOCUMENT NUMBER EK-RH20-UD-001, AUG 76
	SUBTTL	MACRO DEFINITIONS


;MACRO TO COMPUTE THE WIDTH OF A MASK
;	"WID" RETURNS THE LENGTH OF THE LEFTMOST STRING OF
;	CONSECUTIVE ONES IN THE WORD.

DEFINE	WID(MASK),<<^L<-<<MASK>_<^L<MASK>>>-1>>>

;MACRO TO COMPUTE THE POSITION OF A MASK

DEFINE	POS(MASK),<<^L<MASK>+^L<-<<MASK>_<^L<MASK>>>-1>-1>>

;MACRO TO BUILD A POINTER TO A MASKED QUANTITY
;	POINTR	LOCATION,MASK

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

;MACRO TO INSERT A VALUE IN A MASKED FIELD
;	INSVL.(VALUE,MASK)

DEFINE INSVL.(VALUE,MASK),<<<<VALUE>B<POS(<MASK>)>>&<MASK>>>

;MACRO TO WAIT AWHILE. USED IN RDREG TO GIVE THE MASSBUS TIME TO
;ACCEPT THE DATAO TO SETUP THE PREPARATION REGISTER BEFORE
;DOING THE DATAI TO READ THE REGISTER

DEFINE	STALL, <
	IMULI	P,1
	XLIST
	IMULI	P,1
	LIST
>
	SUBTTL	DX20 DEVICE DEPENDENT REGISTER/BIT DEFINITIONS


.DXMTR==03B5			;MAINTENANCE REGISTER
	MR.SCY==1B31		;MICROPROCESSOR SINGLE CYCLE
	MR.STR==1B33		;MICROPROCESSOR START
	MR.RES==1B34		;MICROPROCESSOR RESET

.DXDTR==06B5			;DRIVE TYPE REGISTER

.DXMIR==30B5			;MICROCONTROLLER INSTRUCTION REGISTER

.DXPCR==31B5			;MICROPROCESSOR PC REGISTER
	PC.IRE==1B20		;INSTRUCTION REGISTER ENABLE
	PC.MSE==1B21		;MICROSTORE ENABLE
	PC.PCE==1B22		;PC ENABLE
	PC.PCI==1B23		;PC AUTO INCREMENT
	PC.MPC==7777B35		;MICROPROCESSOR PC

.DXIBR==36B5			;DIAGNOSTIC REGISTER 7
	DX.IBR==377		;CONTENTS OF THE BR REGISTER

.DXIPE==37B5			;DIAGNOSTIC REGISTER 7
	DX.IPE==1B22		;INSTRUCTION REGISTER PARITY ERROR

.CRM10==10			;LOCATION IN THE CRAM CONTAINING A CODE
				;  CHECKED BY THE DRIVERS TO SEE IF THE
				;  MICROCODE IS VALID

.DXSAD==1			;FULL START ADDRESS FOR ALL VERSIONS
				;  OF THE DX20 MICROCODE
	SUBTTL	DX20 MICROCODE LOADING SUBROUTINES


;ROUTINE TO CLEAR, LOAD, AND VERIFY, AND START THE MICROCODE FOR A DX20.
;CALL:
;	T1/ADDRESS OF MICROCODE LOADER BLOCK
;	PUSHJ	P,DXLOAD
;RETURN CPOPJ IF UNSUCCESSFUL
;	CPOPJ1 WITH MICROCODE LOADED BUT NOT STARTED

DXLOAD::PUSHJ	P,SAVE4##	;SAVE SOME ACS
	MOVE	P1,T1		;COPY MICROCODE LOADER BLOCK ADDRESS
	PUSHJ	P,BTUCOD##	;FIND ADDRESS
	  JRST	DXLOA1		;NOT AVAILABLE
	PUSHJ	P,MPRES		;RESET THE MICROPROCESSOR
	PUSHJ	P,DXCLR		;CLEAR THE CRAM AND WORKING MEMORY
	PUSHJ	P,LOAD		;LOAD THE MICROCODE
	  JRST	DXLOA1		;FAILED
	PUSHJ	P,VERIFY	;VERIFY THE MICROCODE THAT WE JUST LOADED
	  JRST	DXLOA1		;FAILED
	PUSHJ	P,MPCHK		;DO A FINAL CHECK ON THE MICROSTORE
	  JRST	DXLOA1		;FAILED
	PUSHJ	P,RDCRM0	;READ THE VERSION NUMBER FROM CRAM LOC 0
	LDB	T1,[POINT 6,T2,25] ;GET MAJOR VERSION
	LSH	T1,30		;POSITION
	TRZ	T2,777600	;ISOLATE EDIT LEVEL
	IOR	T2,T1		;FORM STANDARD DEC-10 VERSION NUMBER
	PUSH	P,T2		;SAVE IT
	PUSHJ	P,DXSTRT	;START THE DX20
	POP	P,.ULVER(P1)	;SET VERSION IN MICROCODE LOADER BLOCK
	MOVE	T1,P1		;POINT TO THE MICROCODE LOADER BLOCK ADDRESS
	PUSHJ	P,BTURPT##	;REPORT A SUCESSFUL LOAD
	JRST	CPOPJ1##	;GIVE SKIP RETURN
DXLOA1:	MOVEI	T2,.CRM10	;WRITE A 0 INTO CRAM LOCATION 10
	MOVEI	T3,0		;  SO THAT ATTEMPTS TO START THIS DX20
	PUSHJ	P,WRCRAM	;  WILL FAIL
	MOVE	T1,P1		;COPY MICROCODE LOADER BLOCK ADDRESS
	PJRST	BTURPT##	;REPORT LOAD ERROR AND RETURN


;It might occur to someone to call BTURPT before DXSTRT to save the
;PUSH and POP of the microcode version number.  It is done that way
;to waste enough KL CPU time to give the DX20 microprocessor enough
;time to get through its full initialization and get to the idle
;loop before a massbus init or a call to the reset routine stops
;it again.  If the DX20 doesn't finish its initialization, the
;restart of the microprocessor (at a different start address than
;that used by DXSTRT) will cause strange things to happen.
;ROUTINE TO LOAD OR VERIFY THE MICROCODE IN A DX20.
;CALL:
;	P1/ADDRESS OF MICROCODE LOADER BLOCK
;	PUSHJ	P,LOAD/VERIFY
;RETURN CPOPJ IF ERROR
;	CPOPJ1 WITH FUNCTION PERFORMED SUCCESSFULLY

LOAD:	PUSH	P,[.DXPCR!PC.MSE!PC.PCE] ;DATAO BITS TO WRITE CRAM
	PUSH	P,[IFIW LDCRAM]	;ROUTINE TO LOAD CRAM
	PUSH	P,[IFIW LDWM]	;ROUTINE TO LOAD DRAM
	PUSH	P,[.UEDRL,,.UECRL] ;DRAM,,CRAM ERROR CODES
	JRST	FUNC		;ENTER COMMON CODE

VERIFY:	PUSH	P,[.DXPCR!PC.IRE!PC.PCE] ;DATAO BITS TO READ CRAM
	PUSH	P,[IFIW VFCRAM]	;ROUTINE TO VERIFY CRAM
	PUSH	P,[IFIW VFWM]	;ROUTINE TO VERIFY DRAM
	PUSH	P,[.UEDRV,,.UECRV] ;DRAM,,CRAM ERROR CODES

FUNC:	PUSH	P,[EXP 0]	;RESERVE SPACE FOR CRAM LOCATION 0
	MOVSI	P2,-3777	;AOBJN POINTER
	MOVSI	P3,(<POINT 18,,>!1B12) ;MAKE A TWO WORD BYTE POINTER
	MOVE	P4,.ULADR(P1)	;GET UCODE ADDRESS
FUNC1:	ILDB	T1,P3		;GET A BYTE OF DATA
	HRRZ	T2,P2		;GET CRAM ADDRESS
	SKIPE	T3,.ULMAG(P1)	;HAVE A MAGIC NUMBER TRANSLATION TABLE?
	PUSHJ	P,MAGIC		;YES--SEE IF A SUBSTITUTION IS NECESSARY
	IOR	T2,-4(P)	;INCLUDE DATAO BITS TO READ/WRITE CRAM
	PUSHJ	P,WTREG		;INITIALIZE ADDRESS OF CRAM LOCATIONS
	PUSHJ	P,@-3(P)	;DISPATCH TO CRAM FUNCTION ROUTINE
	  JRST	FUNC3		;ERROR
	AOBJN	P2,FUNC1	;LOOP
	PUSHJ	P,RDCRM0	;READ THE CONTENTS OF CRAM LOCATION 0
	HRRZM	T2,(P)		;SAVE ON STACK
	MOVSI	P2,-1777	;AOBJN POINTER
	MOVSI	P3,(<POINT 8,,>!1B12) ;MAKE A TWO WORD BYTE POINTER
	MOVE	P4,.ULADR(P1)	;GET ADDRESS OF UCODE STORAGE
	ADDI	P4,2000		;OFFSET TO THE DRAM DATA
FUNC2:	HRRZ	T2,P2		;GET WORKING MEMORY ADDRESS
	PUSHJ	P,LDMAR		;SET MAR/MARX TO THAT VALUE
	ILDB	T1,P3		;GET A BYTE OF DATA
	ANDI	T1,377		;KEEP ONLY 8 BITS
	PUSHJ	P,@-2(P)	;DISPATCH TO WORKING MEMORY FUNCTION ROUTINE
	  JRST	FUNC4		;ERROR
	AOBJN	P2,FUNC2	;LOOP
	MOVEI	T2,0		;RESTORE THE VALUE THAT WAS IN CRAM LOCATION
	POP	P,T3		;GET PREVIOUS CONTENTS OF CRAM LOCATION 0
	PUSHJ	P,WRCRAM	;  LOADING WORKING MEMORY
	ADJSP	P,-4		;PHASE STACK
	JRST	CPOPJ1##	;RETURN
FUNC3:	SKIPA	T1,-1(P)	;CRAM LOAD/VERIFY ERROR
FUNC4:	HLRZ	T1,-1(P)	;DRAM LOAD/VERIFY ERROR
	DPB	T1,ULBEBP##	;STORE
	ADJSP	P,-5		;PHASE STACK
	POPJ	P,		;RETURN
;ROUTINE TO CLEAR THE CRAM AND WORKING MEMORY OF A DX20.
;CALL:
;	P1/ADDRESS OF MICROCODE LOADER BLOCK
;	PUSHJ	P,DXCLR
;RETURN CPOPJ ALWAYS

DXCLR:	PUSH	P,F		;SAVE F
	MOVSI	F,-4000		;4000 LOCATIONS TO CLEAR IN THE CRAM
DXCLR1:	HRRZ	T2,F		;GET THE ADDRESS TO WRITE
	MOVEI	T3,0		;PUT A ZERO IN IT
	PUSHJ	P,WRCRAM	;WRITE THE CRAM LOCATION
	AOBJN	F,DXCLR1	;WRITE THEM ALL

	MOVEI	T2,0		;SET THE MAR/MAR EXTENSION
	PUSHJ	P,LDMAR		;  TO 0
	MOVEI	F,2000		;2000 LOCATIONS IN THE WORKING MEMORY
DXCLR2:	MOVEI	T2,11400	;LDMEM 0,I MICROINSTRUCTION
	PUSHJ	P,DXXCT		;CLEAR NEXT LOCATION IN WORKING MEMORY
	SOJG	F,DXCLR2	;DO THEM ALL
	JRST	FPOPJ##		;RESTORE F AND RETURN


;ROUTINE TO START THE DX20 MICROPROCESSOR AT THE FULL START ENTRY
;POINT.
;CALL:
;	P1/ADDRESS OF MICROCODE LOADER BLOCK
;	PUSHJ	P,DXSTRT
;RETURN CPOPJ ALWAYS

DXSTRT:	PUSHJ	P,MPRES		;MAKE SURE THE PROCESSOR IS RESET
	MOVE	T2,[.DXPCR!PC.IRE!PC.PCE!PC.PCI!INSVL.(.DXSAD,PC.MPC)]
	PUSHJ	P,WTREG		;SET THE PC TO THE FULL START ADDRESS
	MOVE	T2,[.DXMTR!MR.STR] ;MAINTENANCE REGISTER+START BIT
	PJRST	WTREG		;START THE MICROPROCESSOR AND RETURN
;ROUTINE TO READ THE CONTENTS OF CRAM LOCATION 0.
;CALL:
;	P1/ADDRESS OF MICROCODE LOADER BLOCK
;	PUSHJ	P,RDCRM0
;RETURN CPOPJ ALWAYS WITH:
;	T2/CONTENTS OF CRAM LOCATION 0

RDCRM0:	MOVE	T2,[.DXPCR!PC.IRE!PC.PCE!INSVL.(0,PC.MPC)] ;SET TO READ
	PUSHJ	P,WTREG		;  CRAM LOCATION 0
	MOVSI	T2,(.DXMIR)	;READING THIS REGISTER RETURNS THE VALUE
	PJRST	RDREG		;  THAT IS ADDRESSED BY THE PC REGISTER


;ROUTINE TO WRITE A WORD INTO A DX20 CRAM LOCATION.
;CALL:
;	T2/ADDRESS OF LOCATION TO WRITE
;	T3/DATA TO BE WRITTEN
;	P1/ADDRESS OF MICROCODE LOADER BLOCK
;	PUSHJ	P,WRCRAM
;RETURN CPOPJ ALWAYS

WRCRAM:	PUSH	P,T3		;SAVE THE DATA TO BE WRITTEN
	TDO	T2,[.DXPCR!PC.MSE!PC.PCE] ;PC REGISTER+BITS TO ENABLE
	PUSHJ	P,WTREG		;  MICROSTORE AND PC WRITES
	POP	P,T2		;RESTORE THE DATA TO BE WRITTEN
	HRLI	T2,(.DXMIR)	;WRITES INTO THE IR GO INTO THE CRAM LOCATION
	PJRST	WTREG		;  ADDRESSED BY THE PC REGISTER


;ROUTINE TO LOAD THE DX20 MEMORY ADDRESS AND ADDRESS EXTENSION REGISTERS
;(MAR AND MARX) WITH A VALUE.
;CALL:
;	T2/ADDRESS TO LOAD
;	P1/ADDRESS OF MICROCODE LOADER BLOCK
;	PUSHJ	P,LDMAR
;RETURN CPOPJ ALWAYS

LDMAR:	PUSH	P,T2		;SAVE THE ADDRESS TO LOAD
	ANDI	T2,377		;KEEP LOW 8 BITS
	TRO	T2,1000		;ADD A LDMAR MICROINSTRUCTION
	PUSHJ	P,DXXCT		;EXECUTE IT
	POP	P,T2		;RESTORE THE ADDRESS TO LOAD
	LSH	T2,-^D8		;GET 2 HIGH ORDER BITS
	TRO	T2,400		;ADD A LDMARX MICROINSTRUCTION
	PJRST	DXXCT		;EXECUTE THAT AND RETURN
;ROUTINE TO CAUSE THE DX20 TO EXECUTE AN INSTRUCTION.
;CALL:
;	T2/MICROINSTRUCTION TO EXECUTE
;	P1/ADDRESS OF MICROCODE LOADER BLOCK
;	PUSHJ	P,DXXCT
;RETURN CPOPJ ALWAYS

DXXCT:	PUSH	P,T2		;SAVE THE INSTRUCTION TO EXECUTE
	MOVE	T2,[.DXMTR!MR.SCY] ;GET MAINTENANCE REGISTER AND SINGLE CYLCLE
	PUSHJ	P,WTREG		;FORCE THE DX20 INTO SINGLE CYCLE MODE
	MOVEI	T2,0		;STORE THE INSTRUCTIN TO EXECTUTE IN CRAM LOC 0
	POP	P,T3		;RESTORE THE INSTRUCTION TO EXECUTE
	PUSHJ	P,WRCRAM	;WRITE IT INTO THE CRAM
	MOVE	T2,[.DXPCR!PC.IRE!PC.PCI] ;PC REG+IR ENABLE+PC AUTO INCR
	PUSHJ	P,WTREG		;SETUP TO EXECUTE THE INSTRUCTION
	MOVE	T2,[.DXMTR!MR.SCY!MR.STR] ;MAINT REG+SINGLE CYCLE+START
	PUSHJ	P,WTREG		;EXECUTE THE INSTRUCTION
	MOVSI	T2,(.DXMTR)	;CLEAR SINGLE CYCLE AND LEAVE START OFF
	PJRST	WTREG		;CLEAR START AND RETURN
;ROUTINE TO LOAD DATA INTO A CRAM LOCATION.
;CALL:
;	T1/16 BITS OF DATA TO WRITE
;	P1/ADDRESS OF MICROCODE LOADER BLOCK
;	PUSHJ	P,LDCRAM
;RETURN CPOPJ1 ALWAYS

LDCRAM:	HRRZ	T2,T1		;MOVE DATA TO THE RIGHT AC
	HRLI	T2,(.DXMIR)	;ADD THE REGISTER THAT WE WANT
	PUSHJ	P,WTREG		;DO THE DATAO THAT CAUSES THE WRITE
	JRST	CPOPJ1##	;GIVE SKIP RETURN


;ROUTINE TO LOAD DATA INTO A WORKING MEMORY LOCATION.
;CALL:
;	T1/8 BITS OF DATA TO WRITE
;	P1/ADDRESS OF MICROCODE LOADER BLOCK
;	PUSHJ	P,LDWM
;RETURN CPOPJ1 ALWAYS

LDWM:	HRRZ	T2,T1		;GET DATA INTO THE WRITE AC
	TRO	T2,11400	;ADD A LDMEM N,I MICROINSTRUCTION
	PUSHJ	P,DXXCT		;EXECUTE THE INSTRUCTION
	JRST	CPOPJ1##	;GIVE SKIP RETURN
;ROUTINE TO VERIFY THE DATA IN A CRAM LOCATION.
;CALL:
;	T1/16 BITS OF CRAM DATA
;	P1/ADDRESS OF MICROCODE LOADER BLOCK
;	PUSHJ	P,VFCRAM
;RETURN CPOPJ IF NO MATCH
;	CPOPJ1 IF MATCH

VFCRAM:	MOVSI	T2,(.DXMIR)	;READ THIS REGISTER TO GET THE DATA
	PUSHJ	P,RDREG		;READ THE DATA
	CAIN	T2,(T1)		;MATCH WITH WHAT IT SHOULD BE?
	AOS	(P)		;YES--SKIP
	POPJ	P,		;RETURN


;ROUTINE TO VERIFY THE DATA IN A WORKING MEMORY LOCATION
;CALL:
;	T1/8 BITS OF DATA
;	P1/ADDRESS OF MICROCODE LOADER BLOCK
;	PUSHJ	P,VFWM
;RETURN CPOPJ IF NO MATCH
;	CPOPJ1 IF MATCH

VFWM:	MOVEI	T2,043411	;GET A MOVMEM BR,I MICROINSTRUCTION
	PUSHJ	P,DXXCT		;EXECUTE IT
	MOVSI	T2,(.DXIBR)	;REGISTER TO READ THE BR
	PUSHJ	P,RDREG		;READ THE REGISTER
	ANDI	T2,DX.IBR	;KEEP ONLY THE BR OUTPUT
	CAIE	T2,(T1)		;MATCH?
	POPJ	P,		;NO
	JRST	CPOPJ1##	;YES, GIVE SKIP RETURN


;ROUTINE TO SUBSTITUTE A MAGIC NUMBER
;CALL:
;	T2/LOAD ADDRESS
;	T3/MAGIC TRANSLATION TABLE
;	PUSHJ	P,MAGIC
;RETURN	CPOPJ ALWAYS WITH T1 CONTAINING POSSIBLY UPDATED DATA

MAGIC:	MOVE	T4,(T3)		;GET A WORD
	AOJE	T4,CPOPJ##	;RETURN IF END OF TABLE
	HRRZ	T4,(T3)		;GET AN ADDRESS
	CAIE	T4,(T2)		;MATCH?
	AOJA	T3,MAGIC	;LOOP
	HLRZ	T1,(T3)		;GET ASSOCIATED MAGIC VALUE
	POPJ	P,		;AND RETURN
;ROUTINE TO RESET THE DX20 MICROPROCESSOR
;CALL:
;	P1/ MICROCODE LOADER BLOCK ADDRESS
;	PUSHJ	P,MPRES
;RETURN CPOPJ ALWAYS

MPRES:	MOVE	T2,[.DXMTR!MR.RES] ;SET RESET BIT IN MAINT REG
	PJRST	WTREG		;RESET THE DX20


;ROUTINE TO CHECK THE STATUS OF THE MICROPROCESSOR
;CALL:
;	P1/ADDRESS OF MICROCODE LOADER BLOCK
;RETURNS CPOPJ IF CONSISTANCY CHECKS FAIL OR CPOPJ1 IF OK

MPCHK:	MOVE	T2,[.DXPCR!PC.IRE!PC.PCE!PC.PCI!7] ;REGISTER TO WRITE+
				;  IR ENABLE+PC ENABLE+PC AUTO INCR+PC TO READ
	PUSHJ	P,WTREG		;WRITE THE REGISTER
	MOVSI	T2,(.DXMIR)	;POINT AT DIAGNOSTIC REGISTER 0
	PUSHJ	P,RDREG		;READ THE CONTENTS
	PUSH	P,T2		;SAVE FOR COMPARE
	MOVSI	T2,(.DXDTR)	;POINT AT DRIVE TYPE REGISTER
	PUSHJ	P,RDREG		;READ THAT
	POP	P,T3		;RESTORE CRAM LOCATION 7
	CAME	T2,T3		;HAVE TO BE THE SAME
	POPJ	P,		;ERROR IF NOT
	MOVSI	T2,(.DXIPE)	;POINT AT DIAGNOSTIC REGISTER 7
	PUSHJ	P,RDREG		;READ IT
	TRNN	T2,DX.IPE	;IR PARITY ERROR ON LAST READ?
	AOS	(P)		;NO, GIVE SKIP RETURN
	POPJ	P,		;   AND RETURN
;ROUTINE TO READ A DRIVE OR CONTROLLER REGISTER.
;CALL:
;	T2/DATAO ARGUMENT TO LOAD PREPARATION REGISTER
;	W/KDB ADDRESS
;	PUSHJ	P,RDREG
;RETURN CPOPJ ALWAYS WITH:
;	T2/16 BITS OF RETURNED DATAI
;DESTROYS T3

RDREG:	HRRZ	T3,.ULDEV(P1)	;GET DX20 NUMBER FOR DS
	TLO	T2,<(DO.DRE)>(T3) ;SET DS AND DISABLE RAE
	XCT	.ULDTO(P1)	;TELL MBC WHICH REGISTER WE WANT TO READ
	PUSH	P,T2		;SAVE THE ARGUMENT
	STALL			;WAIT FOR THINGS TO SETTLE
	XCT	.ULDTI(P1)	;READ THE VALUE
	MOVE	T3,T2		;SAVE RESULT
	XCT	.ULCNI(P1)	;CONI
	EXCH	T2,T3		;SWAP
	TRNE	T3,CI.RAE	;REGISTER ACCESS ERROR?
	JRST	RDREG2		;YES, TRY TO RECOVER
RDREG1:	POP	P,(P)		;BRING STACK INTO PHASE
	ANDI	T2,177777	;RETURN ONLY DATA BITS
	POPJ	P,		;RETURN
RDREG2:	PUSH	P,T4		;SAVE T4
	MOVEI	T3,^D10		;RETRY OPERATION 10 TIMES
RDREG3:	MOVEI	T2,CO.MBE!CO.RAE ;MASSBUS ENABLE PLUS CLEAR RAE
	XCT	.ULCNO(P1)	;CLEAR THE ERROR
	MOVE	T2,-1(P)	;GET DATAO ARGUMENT BACK
	XCT	.ULDTO(P1)	;SETUP THE PREPARATION REGISTER AGAIN
	STALL			;WAIT FOR THINGS TO SETTLE
	XCT	.ULDTI(P1)	;READ THE VALUE
	MOVE	T4,T2		;SAVE RESULT
	XCT	.ULCNI(P1)	;CONI
	EXCH	T2,T4		;SWAP
	TRNE	T4,CI.RAE	;REGISTER ACCESS ERROR?
	SOJG	T3,RDREG3	;YES, LOOP
	MOVEI	T4,CO.MBE!CO.RAE ;MASSBUS ENABLE PLUS CLEAR RAE
	EXCH	T2,T4		;SWAP
	XCT	.ULCNO(P1)	;MAKE SURE RAE IS CLEARED
	MOVE	T2,T4		;RESTORE
	POP	P,T4		;RESTORE T4
	JRST	RDREG1		;RETURN TO THE CALLER
;ROUTINE TO WRITE ONE MASSBUS REGISTER.
;CALL:
;	T2/DATAO ARGUMENT
;	W/KDB ADDRESS
;	PUSHJ	P,WTREG
;RETURN CPOPJ ALWAYS
;DESTROYS T3

WTREG:	HRRZ	T3,.ULDEV(P1)	;GET DX20 NUMBER FOR DS
	TLO	T2,<(DO.LDR!DO.DRE)>(T3) ;DRIVE NUMBER, LOAD REG, DISABLE RAE
	MOVE	T3,T2		;COPY ARGUMENTS
	XCT	.ULDTO(P1)	;DATAO
	XCT	.ULCNI(P1)	;CONI
	TRNN	T2,CI.RAE	;REGISTER ACCESS ERROR?
	POPJ	P,		;NO--RETURN
	PUSH	P,T3		;SAVE ARGUMENTS
	MOVEI	T3,^D10		;RETRY OPERATION 10 TIMES
WTREG1:	MOVEI	T2,CO.MBE!CO.RAE ;MASSBUS ENABLE PLUS CLEAR RAE
	XCT	.ULCNO(P1)	;CLEAR THE ERROR
	MOVE	T2,(P)		;GET ARGUMENTS BACK
	XCT	.ULDTO(P1)	;RETRY THE OPERATION
	XCT	.ULCNI(P1)	;CONI
	TRNE	T2,CI.RAE	;STILL HAVE AN ERROR
	SOJG	T3,WTREG1	;YES, LOOP BUT NOT TOO MANY TIMES
	MOVEI	T2,CO.MBE!CO.RAE ;MASSBUS ENABLE PLUS CLEAR RAE
	XCT	.ULCNO(P1)	;INSURE THAT RAE IS CLEARED
	POP	P,T2		;RESTORE T2
	POPJ	P,		;RETURN
SUBTTL	END

DX2END::!END