Google
 

Trailing-Edge - PDP-10 Archives - BB-PBDEB-BB_1990 - 10,7/unsmon/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 V137
SUBTTL  T WACHS/TH  25 APR 89
	SEARCH	F,S,DEVPRM
	$RELOC
	$HIGH


;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
;  OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.

.CPYRT<1973,1988>


XP VDPKON,137		;DEFINE VERSION FOR GLOB AND MAP

DPXKON::ENTRY	DPXKON
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

;EXTRA BITS IN DPXFNC
FNCRCL==20		;FREE RECALIBRATE
FNCPOS==10		;FREE POSITION
FNCHNG==100		;HUNG RECOVERY
SUBTTL	AUTOCONFIGURATION


DPFIX==0			;NOT A FIXED HEAD DEVICE (IF 0)
DPOFS==400000			;NO OFFSET CAPABILITY
DPRDC==400000			;NO 10/11 COMPATABILITY MODE
DPUNL==400000			;NO UNLOAD CAPABILITY
DPCPY==KOPIDL			;KONTROLLER MUST BE IDLE TO DETERMINE UNIT TYPE
DPMX==0				;CANNOT DO MULTIPLE TRANSFERS
DPDRB==0			;DOESN'T USE DISK I/O REQUEST BLOCKS
DPBMX==0			;NOT A BLOCK MULTIPLEX KONTROLLER
DPECA==0			;TRY OFFSET/RECAL BEFORE TRYING ECC
DPERNO==0			;NO DRIVE REGISTERS TO SAVE ON ERROR
DPXELG==DPEELG##		;ERROR LOG ROUTINE IS IN COMMOD

DPXDMX==10			;MAXIMUM DRIVES PER KONTROLLER
DPXHDN==DPXDMX-1		;HIGHEST DRIVE NUMBER ON KONTROLLER

;DRIVER CHARACTERISTICS
;	DPX	= DPXCNF
;	DSK	= DISK
;	0	= MAXIMUM DEVICES IN SYSTEM (NO LIMIT)
;	TYPDP	= KONTROLLER TYPE
;	DPXDMX	= MAXIMUM DRIVES PER KONTROLLER
;	DPXHDN	= HIGHEST DRIVE NUMBER ON KONTROLLER
;	MDSEC0	= SECTION FOR KDB/UDB
;	MDSEC0	= SECTION FOR DDB
DRVCHR	(DPX,DSK,0,TYPDP,DPXDMX,DPXHDN,MDSEC0,MDSEC0,<DR.MCD>)

	.ORG	KONUDB		;START OF KONTROLLER SPECIFIC DATA
DPXUTB:!BLOCK	DPXDMX		;UDB TABLE
DPXEBK:!BLOCK	1		;DUMMY WORD FOR REGISTER STORAGE
DPXIOB:!			;START OF SPECIAL I/O INSTRUCTIONS
DPXCO1:!BLOCK	1
DPXDOT:!BLOCK	1
DPXDO1:!BLOCK	1
DPXDI1:!BLOCK	1
DPXCIT:!BLOCK	1
DPXCI2:!BLOCK	1
DPXDI3:!BLOCK	1
DPXIOE:!			;END OF SPECIAL I/O INSTRUCTIONS
DPXFNC:!BLOCK	1		;INITIAL FUNCTION CODE (SET TO BE POSITION
				; IN CASE THE OPERATOR CAUSES INTERRUPT
				; BEFORE DISK PACKS ARE EVER USED BY SYSTEM
DPXIWD:!BLOCK	1
DPXIUM:! BLOCK	DPXDMW		;IGNORE DRIVE MASK
DPXNUM:! BLOCK	DPXDMW		;NEW DRIVE MASK
DPXKLN:!			;LENGTH OF KDB
	.ORG

;PROTOTYPE KDB
DPXKDB:	XXKON	(DP)
	SETWRD	(DPXCO1,<CONO	000,(T2)>)
	SETWRD	(DPXDOT,<DATAO	000,T1>)
	SETWRD	(DPXDO1,<DATAO	000,T2>)
	SETWRD	(DPXDI1,<DATAI	000,T2>)
	SETWRD	(DPXCIT,<CONI	000,T1>)
	SETWRD	(DPXCI2,<CONI	000,T2>)
	SETWRD	(DPXDI3,<DATAI	000,T3>)
	SETWRD	(DPXFNC,<EXP	OPPOS>)		;INITIAL FUNCTION CODE
	KDBEND

EQUATE	(LOCAL,0,<DPXULP,DPXULB>)
EQUATE	(LOCAL,CPOPJ##,<DPXEDL,DPXINI,DPXRLD>)

	DPXCCM==CYLCM##
	DPXICD==DSKICD##	;PROTOTYPE INTERRUPT CODE
	DPXICL==DSKICL##

	DPXUDB==0		;NO PROTOTYPE UDB
	DPXULN==UNIEBK+DPERNO	;LENGTH OF UDB

DPXDSP:	DRVDSP	(DPX,DSKCHN##,DSKDDB##,DDBLEN##,DSKDIA##)

;DEFAULT MONGEN'ED DEVICE TABLE

DEFMDT:	MDKL10	(7,250,0,0,<MD.KON>)	;DEVICE CODE 250
	MDKL10	(7,254,0,0,<MD.KON>)	;DEVICE CODE 254
	MDKL10	(7,260,0,0,<MD.KON>)	;DEVICE CODE 260
	MDTERM				;TERMINATE TABLE

DPXCKT:	EXP	0			;COMPATIBLE KONTROLLER TABLE
DPXCFG:	XMOVEI	T1,DPXMDT##	;MONGEN'ED DEVICE TABLE
	XMOVEI	T2,DEFMDT	;DEFAULT TABLE
	MOVNI	T3,1		;NO MASSBUS UNIT OR DRIVE INFORMATION
	MOVEI	T4,MD.KON	;MATCH ON KONTROLLER DEFINITION
	PUSHJ	P,AUTMDT##	;SCAN THE TABLES
	  JRST	CPOPJ1##	;NO MATCHES
	PUSHJ	P,SAVE1##	;SAVE P1
	MOVSI	T1,0		;I/O BUS-STYLE CHANNEL
	PUSHJ	P,AUTCHN##	;BUILD A CHANNEL DATA BLOCK
	  POPJ	P,		;NO CORE
	MOVNI	T1,1		;NO MASSBUS UNIT NUMBER
	MOVEI	T2,TYPDP	;KONTROLLER TYPE
	PUSHJ	P,DSKKON##	;BUILD A KDB
	  POPJ	P,		;GIVE UP IF NO CORE
	MOVSI	T1,-<DPXIOE-DPXIOB> ;NUMBER OF WORDS TO CHECK
	XMOVEI	T2,DPXIOB(J)	;STARTING WORD
	HRRZ	T3,.CPDVC##	;<DEVICE CODE>/4
	PUSHJ	P,AUTDVC##	;SET DEVICE CODES
	MOVE	T1,KDBCSO(J)	;GET CONSO SKIP CHAIN ADDRESS
				;***NEED SYMBOL (DONE)
	MOVEI	T2,10		;AND INTERRUPT FLAGS
	HRRM	T2,DICDIF##(T1)	;SET THEM
	MOVSI	P1,-1		;NO MASSBUS UNIT,,DRIVE 0

DPXCF1:	PUSHJ	P,DPXDRV	;AUTOCONFIGURE A SINGLE DRIVE
	  JFCL			;IGNORE ERRORS
	HRRZ	T1,P1		;GET DRIVE NUMBER
	CAIGE	T1,DPXDMX-1	;DONE ALL DRIVES?
	AOJA	P1,DPXCF1	;LOOP BACK FOR MORE
	JRST	CPOPJ1##	;TRY ANOTHER DEVICE ON CHANNEL

;CONFIGURE A SINGLE DRIVE
DPXDRV:	HRRZ	T1,P1		;GET UNIT
	MOVE	T1,BITTBL##(T1)	;AND IT'S BIT
	TDNE	T1,DPXIUM(J)	;WANT TO IGNORE THIS DRIVE?
	POPJ	P,		;SAY IT DOESN'T EXIST
	XMOVEI	T1,DPXMDT##	;MONGEN'ED DEVICE TABLE
	XMOVEI	T2,DEFMDT	;AND THE DEFAULT TABLE
	MOVE	T3,P1		;DRIVE INFORMATION
	PUSHJ	P,AUTMDT##	;FOUND A DRIVE MATCH?
	  POPJ	P,		;NO
	HRLZ	T1,P1		;PHYSICAL DRIVE NUMBER
	HRR	T1,P1		;UDB TABLE INDEX
	MOVEI	T2,TYPDP	;FLAGS,,UNIT TYPE
	PUSHJ	P,DSKDRV##	;BUILD A UDB
	  JFCL			;FAILED
	JRST	CPOPJ1##	;RETURN
;ONCE A SECOND CODE
DPXSEC:	SKIPL	@KDBCHN(J)	;CHANNEL BUSY?
	POPJ	P,		;LEAVE IT ALONE
	SKIPE	T1,DPXNUM(J)	;GET BIT MASK
	JFFO	T1,DPXSE1	;FIND FIRST UNIT NUMBER
	HRRZS	KDBNUM(J)	;INDICATE NO DRIVES TO CONFIGURE
	POPJ	P,		;DONE
DPXSE1:	PUSHJ	P,AUTLOK##	;GET AUTCON INTERLOCK
	  POPJ	P,		;TRY AGAIN NEXT TIME
	PUSHJ	P,SAVW##	;PRESERVE W
	MOVE	W,J		;COPY KDB ADDRESS TO W FOR AUTCON
	PUSH	P,T2		;SAVE PHYSICAL DRIVE NUMBER
	MOVE	T1,KDBDVC(J)	;DEVICE CODE
	XMOVEI	T2,DPXDSP	;DISPATCH
	MOVE	T3,KDBCHN(J)	;CHANNEL DATA BLOCK
	PUSHJ	P,AUTSET##	;SET UP CPU VARIABLES
	EXCH	P1,(P)		;SAVE P1, PHYSICAL DRIVE NUMBER
	TLO	P1,-1		;NO MASSBUS UNIT
	PUSH	P,KDBUNI(J)	;SAVE KDBUNI
	MOVEM	P1,KDBUNI(J)	;SET FOR THIS MASSBUS UNIT NUMBER (FOR RDMBR)
	PUSHJ	P,DPXDRV	;CONFIGURE A NEW UNIT
	  JFCL			;IGNORE ERRORS
	PUSHJ	P,AUTULK##	;RELEASE AUTCON INTERLOCK
	POP	P,KDBUNI(J)	;RESTORE KDBUNI
	PJRST	P1POPJ##	;RESTORE P1 AND RETURN
DPXWTF:	MOVEI	T4,OPWTF	;WRITE FORMAT (HEADERS)
	JRST	DPXGO

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,@KDBICP(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,KDBICP(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
	MOVEI	T2,DSKCHN##	;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)

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
	MOVEI	T2,DSKCHN##	;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)
	CAIN	T4,OPWTF	;IF TRYING TO FORMAT,
	TLNN	T2,1		;WRITE-HEADER LOCKOUT MUST BE OFF

	TLNE	T2,STATBT	;UNIT OK?
	JRST	KONERX		;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)

KONERX:	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
	POPJ	P,		;ERROR STATUS

;HERE ON SEEK INCOMPLETE
KONER2:	TRO	T1,1		;IDICATE SEEK INCOMPLETE
	JRST	KONEC2		;AND CONTINUE
;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     !
>



DPXLTM:	MOVE	T2,UDBPDN(U)	;PHYSICAL DRIVE NUMBER
	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
;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
	MOVEI	T2,DSKCHN##	;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

;CHECK IF KONTROL IS ALIVE
DPXALV:	XCT	DPXCIT(J)	;CONI
	TRNE	T1,7		;IS IT ALIVE?
	POPJ	P,
	MOVEI	T2,DSKCHN##	;NO. GIVE IT A PI
	XCT	DPXCO1(J)	
	POPJ	P,		;AND 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
	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,KDBICP(J)	;INITIAL KONTROL WORD ADDRESS
	HLRZ	T1,1(F)		;LOC(LAST IOWD)+1
	SUBI	T1,1		;R=LOC OF LAST IOWD
	HRRZ	T2,(T1)		;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
	TRNE	S,1		;WRITING?
	ADDI	T3,2		;YES. ADD BACK THE 2 WORDS
	HLRE	T4,(T1)		;-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(T1)		;LAST IOWD?
	AOJE	T3,DATAIN	;YES. OK IF T3=-1
	MOVE	T1,(P)		;RESTORE CONI BITS FOR DEVERR
	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
	XCT	DPXDI1(J)	;DATAI DPN,T2
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:	MOVEI	T2,DSKCHN##+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
	TRNN	S,70		;SPECIAL INTERRUPT?
				;(RECALIBRATE OR FREE POSITIONING)
	JRST	CLRATN		;NO. SET ATTNS IN LH AND GO TO FILSER
	MOVN	T1,UDBPDN(U)	;U=SPECIAL NUMBER
				;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
	MOVE	T1,UDBPDN(U)	;GET PHYSICAL DRIVE 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
	MOVE	T2,UDBPDN(U)	;GET PHYSICAL DRIVE NUMBER
	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
	MOVS	T2,UDBPDN(U)	;PHYSICAL DRIVE NUMBER IN LH (T2)
	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
;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:	MOVE	T1,UDBPDN(U)	;PHYSICAL DRIVE 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
	TLC	T2,60		;INVERT BITS WHICH SHOULD BE 1
	POPJ	P,		;AND EXIT
;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,KDBICP(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
	MOVSI	T4,KOPNSU	;UNIT DOESN'T EXIST
	JRST	DPXCP3		;CONTROLLER IS DEAD
DPXCP2:	TRNN	T1,200		;ILLEGAL SECTOR?
	TLO	T4,KOPUHE	;NO - SOMETHING'S AMISS!
DPXCP3:	MOVEI	T2,DSKCHN##
	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
	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
	$INIT

;CHECK FOR KONTROLLER UP
DPXUPA:	PUSHJ	P,SAVE2##	;SAVE P1-P2
	MOVEI	T2,DPCLR+DSKCHN## ;CLEAR ALL ERROR FLAGS
	XCT	DPXCO1(J)	;DO THE CONO
	MOVE	T1,[XWD 500000,DPATTN]
	XCT	DPXDOT(J)
	XCT	DPXCIT(J)
	TRNE	T1,7		;CONTROLLER ON-LINE?
	TRNE	T1,175770	;YES. TEST ALL BUT DISK NRDY
	POPJ	P,
	XCT	DPXDI1(J)	;DATAI DP'N, T2
	TLNN	T2,1		;WRITE-HEADER LOCKOUT ON?
	SETZ	T1,		;NO, SO INDICATE
	JRST	CPOPJ1##

;CHECK HARDWARE WRITE PROTECT
DPXHWP:	PUSHJ	P,DPXSTS	;GET STATUS FOR THIS UNIT IN T2
	TLNE	T2,2		;WRITE PROTECT ON?
	AOS	(P)		;YES -SKIP
	POPJ	P,		;RETURN

	$HIGH
	LIT

DPXEND:	END