Google
 

Trailing-Edge - PDP-10 Archives - dec-10-omona-u-mc9 - dpxkon.mac
There are 11 other files named dpxkon.mac in the archive. Click here to see a list.
TITLE DPXKON - DEVICE DEPENDENT RP10/RP01(RP02) DRIVER V110
SUBTTL  T WACHS/TH  15 JUN 76
	SEARCH	F,S
	$RELOC
	$HIGH
;***COPYRIGHT 1973,1974,1975,1976,1977 DIGITAL EQUIPMENT CORP., MAYNARD, MASS.***
XP VDPKON,110		;DEFINE VERSION FOR GLOB AND MAP

;ASSEMBLY INSTRUCTIONS:  DPXKON,DPXKON/C_S,KONPAR,DPXKON

;ALL INTERN AND EXTERN DECLARATIONS:

ENTRY	DPXKON
INTERN	DPXPOS,DPXRED,DPXWRT,DPXRDS,DPXWTS,DPXINT,DPXSTS,DPXRCL,DPXSTP
INTERN	DPCLR,DPATTN,DPDONE,DPXWTF,DPXRDF,DPXWTC,DPXRDC
EXTERN	DPXCO1,DPXCIT,DPXDI1,DPXDO1,DPXDOT,DPXFNC,DPXIWD,UNIPCT
EXTERN	CPOPJ1,TPOPJ1,CPOPJ,TPOPJ

BSYBIT==20		;DP KONTROL BUSY
STPBIT==20		;STOP DP(CLEAR BUSY, SET DONE
			; CAUSE INTERRUPT)
ALLERR==177720
DPCLR==177710
DPATTN==776
STATBT==176		;READY, ONLINE, UNSAFE,NO SUCH DEV, RD ONLY
STATB2==174		;ALL EXECPT READ ONLY
UNSAFE==10		;FILE UNSAFE
SEKINC==100
ENDCYL==200000
SRCHER==40000
CORPAR==12	;CHAN-DETECTED CORE PARITY ERROR BITS
NXMERR==10000	;CHAN-DETECTED NXM
DLERR==20000	;DATA LATE (OVER RUN)
DPDONE==10

PARDIS==5000		;DISABLE STOP ON PAR ERROR

;THESE LOCATIONS ARE DEFINED IN COMMON FOR EACH KONTROL
;THEY ARE INDEXED BY J:

REPEAT	0,<
DPXCO1:	CONO	DP'N,(T2)
DPXDOT:	DATAO	DP'N,T1
DPXDO1:	DATAO	DP'N,T2
DPXDI1:	DATAI	DP'N,T2
DPXCIT:	CONI	DP'N,T1
DPXCI2:	CONI	DP'N,T2
DPXDI3:	DATAI	DP'N,T3
DPXFNC:	0
DPXIWD:	0
>


DPXKON:		;CAUSE LOADING ON LIBRARY SEARCH
IFN FTDSUP,<
DPXWTF:	MOVEI	T4,OPWTF	;WRITE FORMAT (HEADERS)
	JRST	DPXGO
>
IFE FTDSUP,<
DPXWTF==CPOPJ			;CAN'T WRITE HEADERS IF NO SUPER-USETO
>
DPXRDC::
DPXRDF::
DPXRED:	TDZA	T4,T4		;OP=0(READ)
DPXWTC::
DPXWRT:	MOVEI	T4,OPWRT
	JRST	DPXGO		;START MOVING DATA
DPXRDS:	TDZA	T4,T4		;OP=0(READ)
DPXWTS:	MOVEI	T4,OPWRT
	HRLI	T4,1		;LH=1 - STOP ON ERR
DPXGO:	PUSHJ	P,KONECT	;CONNECT RP10 TO DRIVE, SET UP T1
	  JRST	DPXDWN		;ERROR - UNIT NOT READY
	MOVE	T2,@KONIOC(J)	;LOC OF FIRST IOWD
	MOVE	T2,(T2)		;INITIAL IOWD ITSELF
	MOVEM	T2,DPXIWD(J)	;SAVE IN CONTROL DATA BLOCK

DPXGO1:	LDB	T4,UNYBPT	;T3 HAS SURFACE*SECTOR
	IDIV	T3,T4		;T3=SURF T4=SECTOR
	DPB	T3,[POINT 5,T1,18]	;STORE SURFACE
	DPB	T4,[POINT 4,T1,23]	;STORE SECTOR
	OR	T1,KONIOC(J)	;INITIAL KON WD ADDR
DPXGO2:	TRZE	T1,1		;SEEK INC?
	JRST	RECAL2		;YES
	SETZM	T2		;TURN OFF RP10 PI CHANNEL
	XCT	DPXCO1(J)	;CONO DPN,(T2)
	POP	P,DPXFNC(J)	;SAVE FUNCTION (CAN'T GET INTERRUPTED
				; NOW TILL DATA TRANSFER IS DONE)
	XCT	DPXDOT(J)	;START THE OPERATION
	LDB	T2,KOYPI	;TURN PI CHANNEL BACK ON
	XCT	DPXCO1(J)
	JRST	CPOPJ1		;GIVE GOOD (SKIP) RETURN TO FILSER


DPXPOS:	HRROI	T4,OPPOS	;FUNCTION=POSITION, DISABLE PARITY STOP
	JRST	DPXRC1		;CONNECT TO UNIT AND DO POSITIONING

DPXRCL:	MOVEI	T4,OPCAL	;FUNCTION=RECALIBRATE
DPXRC1:	PUSHJ	P,KONECT	;CONECT TO DRIVE, SET UP T1
	  JRST	DPXDWN		;ERROR - UNIT NOT READY
	JRST	DPXGO2		;START RP10 GOING (FUNCTION ON END OF PD LIST)

IFN FTRP04,<
DPXUNL::
DPXERR::
DPXECC::STOPCD	CPOPJ1##,DEBUG,RIF,	;++RP10 ISNT FANCY
DPXREG::POPJ	P,		;NO MASSBUS REGS TO READ
>
;HERE WHEN A UNIT IS NOT READY. (ERROR BITS FOR T1 IN T3)
;SINCE IT MAY BECOME READY BEFORE THE CONTROLLER IS USED AGAIN, AND IF IT
; DOES WE WILL GET A FREE INTERRUPT, DPXFNC MUST BE RESET SO THAT WE WONT
; TELL FILSER ABOUT A SPURIOUS DATA INTERRUPT
DPXDWN:	MOVEI	T1,OPPOS	;SET UP A "POSITION" FUNCTION
	MOVEM	T1,DPXFNC(J)	;IN THE KONTROLLER DATA DBLOCK
	IOR	T1,T3		;ADD ERROR BITS
	LDB	T2,KOYPI	;ENSURE THAT RP10 HAS A PIA
	XCT	DPXCO1(J)	; (IN CASE OF POWER FAIL RECOVERY)
	XCT	DPXCI2##(J)	;COMI BITS INTO T2
	XCT	DPXDI3##(J)	;DATAI BITS INTO T3
	POPJ	P,		;GIVE NON-SKIP RETURN TO FILSER
;SUBROUTINE TO CONNECT RP10 TO A UNIT, FUNCTION IN T4
;RETURNS CPOPJ IF CANT CONNECT OR WRITE-PROTECTED ON A WRITE REQUEST
;   WITH HARDWARE FUNCTION (DATAO) IN T1 ERROR BITS IN T3
;CPOPJ1 NORMALLY, FUNCTION ON END OF PD LIST, FUNCTION STILL IN T4
KONECT:	XCT	DPXCIT(J)	;CONI DPN,T1
	TRNN	T1,BSYBIT	;BUSY?
	JRST	KONEC1		;NO
	MOVEI	T2,STPBIT	;YES. CLEAR BUSY, SET DONE
	XCT	DPXCO1(J)
	AOS	UNIHNG##(U)	;COUNT THE ERROR IN UNIHNG
	JRST	KONECT		;TRY, TRY AGAIN
KONEC1:
	PUSHJ	P,CLRSET	;CONNECT TO DRIVE, DATAI T2 (SIM ERROR)
IFN FTDSUP,<
	CAIN	T4,OPWTF	;IF TRYING TO FORMAT,
	TLNN	T2,1		;WRITE-HEADER LOCKOUT MUST BE OFF
>
	TLNE	T2,STATBT	;UNIT OK?
	JRST	KONERR		;NO - CHECK WRITE LOCK
KONEC2:	DPB	T4,[POINT 3,T1,2];YES. SET OPERATION IN T1
	TLNN	T4,1		;STOP ON ERROR?
	TRO	T1,PARDIS	;NO, DISABLE STOP ON ERROR
	EXCH	T4,(P)		;SAVE FUNCTION ON PD LIST
;(CAN'T DO A MOVEM DPXFNC SINCE
;WE MIGHT GET A POSITION INTERRUPT
;BEFORE THE DATA-TRANSFER STARTS)
	MOVE	T2,UNIBLK(U)	;DESIRED BLOCK
	LDB	T3,UNYBPY	;NUMBER OF BLOCKS/CYLINDER
	IDIV	T2,T3		;CYLINDER IN T2
	DPB	T2,[POINT 8,T1,13]	;SAVE IN T1
	TRNE	T2,400		;EXTRA BIT IN CYLINDER NUMBER (RP03)?
	TRO	T1,200000	;YES SET BIT IN DATAO WORD
	MOVEM	T2,UNICYL(U)	;SAVE CYLINDER IN UNIT DB
	PJRST	1(T4)

KONERR:	TLNN	T2,STATB2	;WAS THE STATUS "ERROR" WRITE LOCK?
	TRNE	T4,1		;YES. IS THE OPERATION A WRITE?
	TDZA	T3,T3		;NO-CLEAR POPJ ERROR BITS
	JRST	KONEC2		;READ-ONLY IS OK
	TLNE	T2,SEKINC
	JRST	KONER2
	TLNE	T2,70		;NOT-READY, FILE UNSAFE, OR OFF-LINE?
	TRO	T3,KOPOFL	;YES-LIGHT BIT FOR FILSER
	TLNE	T2,UNSAFE	;FILE UNSAFE
	TRO	T3,KOPFUS	;YES, LIGHT BIT FOR FILSER
KONXIT:	POPJ	P,		;ERROR STATUS

;HERE ON SEEK INCOMPLETE
KONER2:	TRO	T1,1		;IDICATE SEEK INCOMPLETE
	JRST	KONEC2		;AND CONTINUE
IFN FTDOPT,<			;DISK OPTIMIZATION?
;ROUTINE TO COMPUTE LATENCY TIME FOR A UNIT LESS A SAFETY FACTOR
; TO INSURE THAT A COMPLETE REVOLUTION WILL NOT BE MISSED
; 0 FOR AN ANSWER MEANS CLOSEST POSSIBLE NEXT BLOCK

REPEAT 0,<
TABLE SHOWING INSTANEOUS TIME RELATION BETWEEN SECTOR COUNTER
AND ACTUAL SECTOR POSITION FOR RPO2 AND RP01 UNITS:

SECTOR COUNTER:
	20
!19!! 0! 1! 2! 3! 4! 5! 6! 7! 8! 9!10!11!12!13!14!15!16!17!18!19!
RP02:
	!  9  !  0  !  1  !  2  !  3  !  4  !  5  !  6  !  7  !  8  !
RP01:
	!     4     !     0     !     1     !     2     !     3     !
>


	INTERN	DPXLTM

DPXLTM:	LDB	T2,UNYPUN	;PHYSICAL UNIT NO. ON THIS CONTROLLER
	ROT	T2,-6		;SHIFT TO UNITS POSITION FOR DATAO
	TLO	T2,<OPSEL>B20	;SET OPERATION TO SELECT
	XCT	DPXDO1(J)	;DO A DATAO DPX,T2 TO SELECT UNIT
	XCT	DPXDI1(J)	;DO A DATAI DPX,T2 TO READ SECTOR COUNTER
	XCT	DPXDI1(J)	;READ A SECOND TIME SINCE COUNTER IS
				; STROBBED INTO BUFFER ON TRAILING EDGE OF DATAI
	TLC	T2,60		;COMPLEMENT ON-LINE,ON-CYL
	TLNE	T2,60		;ON-LINE AND ON-CYL?
	POPJ	P,		;NO, ERROR RETURN, T1=UNSPECIFIED
	LDB	T4,[POINT 4,T2,22]	;GET ACTUAL HALF SECTOR COUNTER
	LDB	T3,UNYBPT	;NO. OF BLOCKS PER TRACK(REVOLUTION)
	IDIVI	T1,(T3)		;T2 GETS DESIRED SECTOR NO.(RP02=0-9;RP01=0-4)
	LSH	T2,1		;CONVERT TO HALF SECTOR LIKE HARDWARE
	CAIE	T3,^D10		;IS THIS AN RP02?
	ADDI	T2,2(T2)	;NO, MUST BE RP01, CONVERT TO QUARTER SECTOR
				; PLUS 2
	SUB	T2,T4		;DESIRED HALF SECTOR - MOD20(ACTUAL HALF SECT+2)
				; GIVES NO. OF HALF(QUART) SECTORS TO WAIT
				; TO GET TO DESIRED HALF(QUART) SECTOR(-20 THRU +20)
	HRREI	T1,0(T2)	;MOVE NO. OF HALF SECTORS TO WAIT
				; SINCE HARDWARE CONVENIENTLY HAS A BUILT
				; IN SAFETY FACTOR, NO NEED TO SUBTRACT
				; ANYTHING HERE.
	JUMPGE	T1,DPXLT1	;IF DISTANCE IS NEGATIVE
	ADDI	T1,^D20		;ADD NO. OF HALF SECTORS IN ONE REVOLUTION
				; SINCE DISK SPINS IN ONE DIRECTION
DPXLT1:	IMULI	T1,^D1250	;CONVERT HALF SECTORS TO MICROSECONDS
	JRST	CPOPJ1		;AND GIVE GOOD RETURN
>	;END CONDITIONAL ON FTDOPT
;HERE WHEN A UNIT HANGS DURING A TRANSFER (IE DOES NOT INTERRUPT)
;ATTEMPT TO CLEAR CONTROL AND CAUSE AN INTERRUPT

DPXSTP:	XCT	DPXDI1(J)	;READ IN UNIT STATUS OF LAST UNIT CONTROLLER
				; CONNECTED TO, THE ONE TRANSFERRING (DATAI DPX,T2)
	MOVE	T3,T2		;SAVE IN T3 FOR RETURN
	XCT	DPXCIT(J)	;READ CONTROL STATUS (CONI DPX,T1)
	PUSH	P,T1		;SAVE ON STACK
	MOVEI	T2,STPBIT	;STOP THE UNIT BIT
	XCT	DPXCO1(J)	;STOP UNIT AND CLEAR PI (SO NO INT.)
	XCT	DPXCIT(J)	;READ STATUS (CONI DPX,T1)
	TRNN	T1,BSYBIT	;IS BUSY FLAG NOW OFF?
	AOS	-1(P)		;YES; SET SUCCESSFUL RETURN
	MOVEI	T2,FNCHNG	;INDICATE HUNG-RECOVERY
	IORM	T2,DPXFNC(J)	; INTERRUPT
	LDB	T2,KOYPI	;PI FOR THIS KONTROLLER
	XCT	DPXCO1(J)	;RESTORE PI AND GET INTERRUPT (CONO DPX,T2)
	PJRST	T2POPJ##	;RETURN PREVIOUS CONI STATUS IN T2
				;OK OR ERROR RETURN

;HERE FROM COMMON ON AN INTERRUPT
;ACS HAVE BEEN SAVED, J AND P SET UP
DPXINT:	XCT	DPXCIT(J)	;CONI DPN,T1
	PUSH	P,T1		;SAVE CONI BITS
	MOVE	U,KONCUA(J)	;UNIT DATA BLOC LOC
	HRRZ	S,DPXFNC(J)	;S=FUNCTION
	TRZE	S,FNCHNG	;HUNG RECOVERY?
	JRST	DEVERR		;YES, RETURN AN ERROR
	TRNE	S,74		;POSITIONING INTERRUPT?
	JRST	POSINT		;YES
IFN FTDETS,<
	CAMN	U,ETSUNI	;IS ANY FORCED ERROR TESTING IN EFFECT?
	PUSHJ	P,ETSCN		;YES, SEE IF FOR THIS UNIT - BOTH T1 AND 0(P) MAYBE
				; CHANGED TO SIMULATE A HARDWARE ERROR
>
	TRNE	T1,ALLERR	;ERROR?
	JRST	ERROR		;TOO BAD
	TRNN	T1,ENDCYL	;DATA INTERRUPT. END OF CYLINDER?
	JRST	DATAIN		;NO


;HERE ON END-OF-CYLINDER
	MOVE	F,KONIOC(J)	;INITIAL KONTROL WORD ADDRESS
	HLRZ	R,1(F)		;LOC(LAST IOWD)+1
	SUBI	R,1		;R=LOC OF LAST IOWD
	HRRZ	T2,(R)		;INITIAL ADDR. OF LAST IOWD
	HRRZ	T3,1(F)		;NO - LOC. OF LAST DATA WORD
	SUBI	T3,1(T2)	;# OF WORDS TRANSFERRED
	CAIG	T3,2		;WAS THIS IOWD STARTED?
	JRST	ERROR		;NO - END CYLINDER WAS FROM PREVIOUS IOWD
	TRNE	S,1		;OP = WRITE?
	SUBI	T3,2		;YES. CHAN STORE IS 2 TOO HIGH 
	TRNN	T3,177		;EVEN NUMBER OF BLOCKS MOVED?
	JRST	ERROR		;NO. POSSIBLE CHANNEL ERROR
;HERE ON A POSSIBLE CHANNEL ERROR.  THE WORDCOUNT COMPUTATION GAVE A "FUNNY" COUNT,
; WITH END OF CYLINDER. THIS IS POSSIBLE IF IT IS THE LAST IOWD,
; AND END OF CYLINDER CAME UP ON THE LAST WORD XFERRED
ENDTST:	TRNE	S,1		;WRITING?
	ADDI	T3,2		;YES. ADD BACK THE 2 WORDS
	HLRE	T4,(R)		;-WDCNT OF LAST IOWD
	TRNE	T4,177		;NOT EVEN MULTIPLE OF 200 WORDS?
	TRNE	T3,176		;YES, 200 OR 201 WORDS COMPUTED?
	JRST	ENDTS1		;NO
	JRST	ERROR		;YES, REAL END OF CYLINDER
ENDTS1:
	ADD	T3,T4		;+NO OF WORDS XFERRED (-1?)
	SKIPN	1(R)		;LAST IOWD?
	AOJE	T3,DATAIN	;YES. OK IF T3=-1
	JRST	DEVERR		;NO. CHANNEL ERROR (WRONG WORDCOUNT)


;HERE WHEN ALL DATA IS IN CORE
DATAIN:
	XCT	DPXDI1(J)	;DATAI DPN,T2
	LSH	T2,-^D15	;SHIFT DRIVE NUMBER
	HLLM	T2,S		;SAVE DRIVE IN LH(S)
DATIN1:
	MOVEI	T3,OPPOS	;SET FUNCTION=POSITION, SO ON NEXT
	MOVEM	T3,DPXFNC(J)	; INTERRUPT WE DONT TELL FILSER ABOUT THIS DATA
CLRAT0:	XCT	DPXDI1(J)	;DATAI DPN,T2
IFN FTDETS,<			;DISK ERROR TESTING
	CAMN	U,ETSUNI	;IS SOMEONE SIMULATING ERROR ON THIS UNIT?
	PUSHJ	P,ETSDTI	;YES, GO MODIFY DATA1 BITS IN T2 AS A TEST
>
CLRATN:	MOVE	T3,T2		;SAVE DATAI WORD
	ANDI	T2,DPATTN	;GET ATTENTION BITS
	JUMPE	T2,INTXIT	;THROUGH IF NONE
	HRLI	T2,<OPCLR>B20	;SET TO CLEAR ATTENTIONS
	XCT	DPXDO1(J)	;DATAO DPN,T2 - CLEAR ATTNS
	LSH	T2,^D27		;POSITION ATTNS IN LH
	ORM	T2,S		;SAVE IN S
INTXIT:	LDB	T2,KOYPI	;DPN PI CHANNEL
	TRO	T2,DPCLR	;SET TO CLEAR THE RP10
	XCT	DPXCO1(J)	;CLEAR ALL BUT PI ASSIGNMENTS
	MOVE	T1,S		;RETURN TO FILSER WITH T1 =
				;BITS 0-7 = ATTENTIONS
				;BITS 15-17 = DRIVE NUMBER(IF DATA INTERRUPT)
				;BITS 18-23 = ERROR INDICATION
				;BITS 33-35 = FUNCTION
	POP	P,T2		;T2 = CONI BITS
	PJRST	FILINT		;RETURN TO FILSER
;HERE ON A POSITIONING INTERRUPT
POSINT:	XCT	DPXDI1(J)	;DATAI DPN,T2
IFN FTDETS,<		;DISK ERROR TESTING
	CAMN	U,ETSUNI	;IS SOMEONE SIMULATING ERROR ON THIS UNIT?
	PUSHJ	P,ETSDTI	;YES, GO MODIFY DATA1 BITS IN T2 AS A TEST
>
	TRNN	S,70		;SPECIAL INTERRUPT?
				;(RECALIBRATE OR FREE POSITIONING)
	JRST	CLRATN		;NO. SET ATTNS IN LH AND GO TO FILSER
	LDB	T1,UNYPUN	;YES. U=SPECIAL UNIT #
	MOVNS	T1		;SET TO COMPUTE RIGHT ATTN BIT
	MOVEI	T3,400
	LSH	T3,(T1)		;T3= ATTN BIT WHICH SHOULD BE ON
	TDNN	T2,T3		;IS IT FOR "SPECIAL" UNIT?
	JRST	POSIN3		;NO. DON'T WORRY ABOUT IT
	MOVE	T4,DPXFNC(J)
	TRNN	T4,OPPOS
	JRST	POSIN1
	TLNE	T2,SEKINC
	JRST	DEVERR
	JRST	POSIN3
POSIN1:	TLO	T3,<OPCLR>B20	;YES. CLEAR THIS ATTN
	MOVE	T1,T3		;(LEAVE THE OTHER ATTNS FOR LATER)
	XCT	DPXDOT(J)	;DATAO DPN,T1
	TRZN	T4,10		;FREE POSITION?
	JRST	POSIN2		;NO. MUST BE FROM RECALIBRATE
	TLNE	T2,SEKINC
	JRST	POSIN4
	LDB	T1,UNYPUN	;YES. GET UNIT NUMBER
	ROT	T1,-6		;POSITION TO DRIVE FIELD
	POP	P,T2		;PD LIST HAS CONI BITS - REMOVE IT
	SOS	(P)		;DPXGO1 WILL EXIT CPOPJ1
	PUSHJ	P,KONEC2	;SET UP FOR DATA IO COMMAND
	  STOPCD .+1,DEBUG,KDS,	;++KONEC2 DIDN'T SKIP

	PJRST	DPXGO1		;START NEW DATA COMMAND AND EXIT THE INTERRUPT


;WAS A RECALIBRATE INTERRUPT FOR SELECTED DRIVE
POSIN2:	TRZ	T4,20		;RESET RECALIBRATE BIT
	MOVEM	T4,DPXFNC(J)	;SAVE IN FUNCTION
	MOVE	T1,UNICYL(U)	;GET DESIRED CYLINDER
	LDB	T2,UNYPUN	;T2=DRIVE
	LSH	T1,^D22		;POSITION NEW CYLINDER ADDRESS
	TLZE	T1,10000	;EXTENDED CYLINDER NUMBER (RP03)?
	TRO	T1,200000	;YES, SET EXTENDED BIT
	DPB	T2,[POINT 3,T1,5]	;SET UP DRIVE NUMBER
	TLO	T1,<OPPOS>B20	;POSITION TO IT
	MOVEI	T2,10		;INDICATE "FREE" POSITIONING
	ORM	T2,DPXFNC(J)
	XCT	DPXDOT(J)	;DATAO DPN,T1
	JRST	TPOPJ		;AND EXIT THE INTERRUPT



;HERE WHEN "WRONG" ATTENTION BIT IS UP
POSIN3:	MOVEI	S,OPPOS		;JUST A POSITIONING INTERRUPT
	JRST	CLRATN		;GO CLEAR THE ATTENTION AND TELL FILSER
;HERE ON SEEK INCOMPLETE AFTER FREE POSITION
POSIN4:	TRC	S,IODERR+10	;TURN ON IODERR, TURN OFF 10
	LDB	T2,UNYPUN	;UNIT (DATAI MAY RETURN 0
	HRLZS	T2		;INSTEAD OF RIGHT DRIVE AFTER SEEK INCOMPLETE
	JRST	DATIN1		;GO TELL FILSER
ERROR:	TLNN	T1,CORPAR	;NO, CORE PARITY ERROR?
	TRNE	T1,NXMERR!DLERR	;NO. NXM OR DATA LATE?
	JRST	REF		;YES. REFRENCE THE LOC
CHANER:	TLNE	T1,DATBTS	;DATA ERROR (PARITY)?
	TROA	S,IODTER	;DATA ERROR
DEVERR:	TRO	S,IODERR	;YES
	TRNE	T1,SRCHER	;SEARCH ERROR (HEADERS)?
	TRO	S,IOHDER	;YES
	JRST	DATAIN		;LOOK AT ATTNS AND GO TO FILSER

;HERE ON SEEK-INCOMPLETE
RECAL2:	TLO	T1,<OPCAL>B20	;RECALIBRATE TO BRING DRIVE TO LIFE
	XCT	DPXDOT(J)
	POP	P,T1		;FUNCTION
	TRO	T1,20		;INDICATE RECALIBRATE
	MOVEM	T1,DPXFNC(J)
	PJRST	CPOPJ1		;AND TELL FILSER ALL'S OK

DATBTS=5
ERRBTS=143720

REF:	TRNN	T1,NXMERR!DLERR	;CHAN - DETECTED ERROR
	TROA	S,IOCHMP!IODERR	;CORE PARITY ERR
	TRO	S,IOCHNX!IODERR	;NXM OR DATA LATE
	TRNE	T1,DLERR	;DATA LATE (=OVERRUN)?
	TRO	S,IOVRUN	;YES
	JRST	CHANER		;SET IODERR AND CONTINUE
IFN FTDETS,<
;ROUTINE TO FORCE AN ERROR ON DATAI ON CONNECT TO UNIT
; AFTER SPECIFIED NUMBER OF GOOD TRANSFER INTERRUPTS
;CALL:	MOVE	T2,DATAI BITS
;	CAMN	U,ETSUNI
;	PUSHJ	P,ETSDTI
;	RETURN

ETSDTI:	SKIPL	ETSGTI		;NO. OF GOOD TRANSFER INT FINISHED?
	POPJ	P,		;NO, DO NOT FAKE AN ERROR YET?
	OR	T2,ETSDCO	;YES, SET SELECTED BITS
	ANDCM	T2,ETSDCA	;CLEAR SELECTED BITS
	SOSG	ETSBDT		;HAD ENOUGH BAD DATAI'S YET?
	SETZM	ETSUNI		;YES, STOP ALL FURTHER FAKE ERRORS
	POPJ	P,		;RETURN
;ROUTINE TO FORCE A HARDWARE ERROR ON CONI AFTER TRANSFER INTERRUPT
;CALL:	MOVE	T1,CONI BITS AFTER DATA TRANSFER INTERRUPT
;	PUSH	P,T1		;PUT ON STACK TOO
;	CAMN	U,ETSUNI	;IS THIS UNIT BEING ERROR TESTED?
;	PUSHJ	P,ETSCN		;YES
;	RETURN WITH T1 MODIFIED

ETSCN:	SOSL	ETSGTI		;NO. OF GOOD TRANSFER INT FINISHED?
	POPJ	P,		;NO, DO NOT FAKE AN ERROR YET
	OR	T1,ETSCCO	;YES, SET SPECIFIED ERROR BITS
	ANDCM	T1,ETSCCA	;CLEAR OTHERS
	MOVEM	T1,-1(P)	;STORE ON STACK TOO
	SOSG	ETSBCN		;HAD ENOUGH BAD CONI'S YET?
	SETZM	ETSUNI		;YES, STOP ALL FURTHER FAKE ERRORS
	POPJ	P,		;RETURN
>	;END CONDITIONAL ON FTDETS
;SUBROUTINE TO GET STATUS OF A UNIT
; ENTER WITH U=UNIT DATA BLOCK ADR. J=KONTROLLER DATA BLOCK ADR.
; RETURN WITH T2=UNIT STATUS FROM DATAI, GOOD-BITS ARE COMPLEMENTED
; SO ERRORS CAN BE CHECKED EASILY

DPXSTS:	MOVEI	T2,DPCLR	;ENTRY TO CLEAR CONO
	XCT	DPXCO1(J)	;DO THE CONO TO RP10
CLRSET:	LDB	T1,UNYPUN	;UNIT NUMBER
	ROT	T1,-6		;POSITION TO DRIVE FIELD
	TLO	T1,<OPSEL>B20	;SET OPERATION = NOP
	TLC	T1,10000	;FIRST CONNECT TO ANOTHER DRIVE
	XCT	DPXDOT(J)	;SO THAT RECONNECTING TO RIGHT
	TLC	T1,10000	;DRIVE WILL GIVE GOOD STATUS INFORMATION
	XCT	DPXDOT(J)	;DATAO DPN,T1
	XCT	DPXDI1(J)	;DATAI DPN,T2
IFN FTDETS,<			;DISK ERROR TESTING SIMULATION?
	CAMN	U,ETSUNI	;ERROR TESTING ON THIS UNIT?
	PUSHJ	P,ETSDTI	; SET, CLEAR T2 BITS
>
	TLC	T2,60		;INVERT BITS WHICH SHOULD BE 1
	POPJ	P,		;AND EXIT
IFN FTDHIA,<

;HERE TO CHECK CAPACITY & STATUS OF A UNIT

DPXCPY::PUSHJ	P,DPXSTS	;GET STATUS OF OF THIS UNIT IN T2
	PUSH	P,T2		;SAVE STATUS
	MOVSI	T4,KOPUHE##	;ASSUME ERRORS
	TLO	T4,KOPNSU##	;ALSO SUCH UNIT
	TLNE	T2,4		;DOES NOT EXIST
	JRST	DPXCP3		;NO, GIVE DON'T ASK QUESTION RETURN
	SETZ	T4,		;ASSUME UNIT IS UP
	SKIPN	DINITF##	;IN ONCE-ONLY?
	JRST	DPXCP3		;NO, ASSUME CONTROLLER IS UP
	TLCN	T2,60		;UNIT ON CYLINDER & ON-LINE?
	TLNE	T2,110		;YES - SEEK INCOMPLETE,FILE UNSAFE
	TLO	T4,KOPUHE##	;YES - INDICATE UNIT HAD ERROR
	LDB	T2,[POINT 11,T2,10]	;GET DRIVE & CYLINDER # FOR DATAO
	TLO	T2,417400	;(10,,370000)_^D14 - SELECT AN ILLEGAL SECTOR
	ROT	T2,-^D14	;SHIFT INTO CORRECT POSITION FOR DATAO
	OR	T2,KONIOC##(J)
	XCT	DPXDO1##(J)	;DO A DATAO DPX,T2
	MOVEI	T2,^D1000	;LOOP 1000 TIMES
DPXCP1:	XCT	DPXCIT##(J)	;DO A CONI DPX,T1
	TRNE	T1,DPDONE	;DONE YET?
	JRST	DPXCP2		;YES
	SOJG	T2,DPXCP1	;NO, LOOP
	JRST	DPXCP3		;CONTROLLER IS DEAD
DPXCP2:	TRNN	T1,200		;ILLEGAL SECTOR?
	TLO	T4,KOPUHE##	;NO - SOMETHING'S AMISS!
DPXCP3:
	LDB	T2,KOYPI##
	XCT	DPXCO1##(J)	;GIVE RP10 A PI
	XCT	DPXCIT##(J)	;CONI DP'N,T1
	SKIPN	DINITF##	;IF ATTACH COMMAND,
	TRNE	T1,7		;IF THE CONTROLLER ISN'T THERE,
	CAIA
	JRST	T2POPJ##	;NEITHER IS THE UNIT
	POP	P,T2		;RESTORE UNIT STATUS TO T2
IFN FT22BIT,<
	TLNE	T1,20		;22-BIT CHAN?
	TLO	T4,KOP22B##	;YES
>
	TRNE	T2,2000		;SKIP IF UNIT NOT RP03
	JRST	DPXCP4		;IS RP03, SET UP
	MOVEI	T1,^D40000	;# BLOCKS ON UNIT (RP02)
	MOVEI	T2,^D40600	;# BLOCKS INCLUDING MAINT CYLS
	HRRI	T4,1		;RETURN RP02 TYPE CODE
	JRST	DPXCP5		;TEST IF UNIT UP AND RETURN
;HERE IF UNIT IS RP03
DPXCP4:	MOVEI	T1,^D80000	;# BLOCKS (RP03)
	MOVEI	T2,^D81200	;# BLOCKS INCLUDING MAINT CYLS
	HRRI	T4,2		;RETURN RP03 TYPE CODE
DPXCP5:	SETZ	T3,		;NO 10/11 COMPATABILITY MODE
	MOVE	W,[^D10,,^D200]	;BLKS PER TRK,,BLKS PER CYL
	TLNN	T4,KOPUHE##	;UNIT UP?
	AOS	(P)		;YES, SKIP-RETURN
IFN FTDUAL,<
	HRRZS	J		;NO SERIAL NUMBER
>
	POPJ	P,		;RETURN TO CALLER

>	;END FTDHIA


	LIT

DPXEND:	END