File: DT.TK of Disk: Disks/MyPDP/m8-blue-rka1-rkb1
(Source file text) 

/DT.TK 26-JAN-86
/DECTAPE BLOCK DRIVER FOR PDP8/PDP11 TAPES

IFDEF TC08 <
/NAME:	"D^100+"T&3777   DT
/LENGTH: TWO PAGES
/FUNCTION:TO HANDLE DECTAPE TRANSFERS. IT CAN DO A 
/	SEARCH-ONLY AND A SEARCH-AND-TRANSFER.
/	THE DECTAPE DATATRANSFER VECTOR RESEMBLES
/	THAT OF OS8 EXCEPT FOR THE UNIT NUMBER
/	A BLOCKNUMBER WITH BIT0=1 MEANS THAT THE BLOCK
/	HAS TO BE READ FROM A PDP11-FORMATTED TAPE.
/	THE ONLY DIFFERENCE WITH SUCH A TAPE IS THAT
/	THE WORD COUNT FOR ONE BLOCK IS 600 
/	FOR SUCH TRANSFERS THE LENGTH MUST BE SUFFICIENT !
/CONCEPT: BLOCK TRANSFERS TO AND FROM DECTAPE ARE
/	PRESUMABLY VERY COMMON IN BOTH FOREGROUND AND
/	BACKGROUND. THE MASS-STORAGE HANDLER HAS TO RE-
/	SEMBLE OTHER MASS-STORAGE HANDLERS FOR COMPATI-
/	BILITY, AND THIS IS TRUE FOR THE SYSTEM BLOCKDRIVER
/	THERE IS ONE DISTINCT EXCEPTION: WHEN A TRANSFER
/	LENGTH IS SPECIFIED OF 00 BLOCKS THEN THE DISK
/	WILL DO A FULL 20, BUT THIS MODULE USES THIS
/	SIGNAL TO DO A SEARCH-ONLY. THUS MAX TRANSFERLENGTH
/	IS 37 PAGES OR 17 AND A HALF BLOCKS.
/	THE MODULE WORKS 'CONNECTED' TO THE INTERRUPT:
/	AN INTERRUPT JUMPS INTO 'DTINT' WITH A VERY SHORT
/	DELAY IN BETWEEN. HERE IT STARTS DOING A SEARCH, AND
/	WHEN THE PAGECOUNTER (NEG.) OVERFLOWS, THE TRANSFER
/	IS READY. WHEN IT FLOWS OVER THE VERY FIRST TIME
/	THEN THE MODULE HAS DONE A SEARCH-ONLY.
/ERRORS:WHEN AC UNEQ 0 THERE CAN BE A NUMBER OF DECTAPE ERRORS
/	HAVING CAUSED IT.
/THIS TASK TRIES THE TRANSFER 3 TIMES  MAX. IF
/AN ERROR OCCURS.
/NOTE THAT THE DECTAPE IS A LITTLE BIT TROUBLESOME
/WITH ITS ERRORFLAG: THIS FLAG CAN COME UP
/SPONTANEOUSLY  WHEN A SELECT ERROR OCCURS AND
/ONE OF THE UNITS IS SELECTED. THE SKIPCHAIN WOULD
/THEN RUN INTO A FLAG THAT COULD NOT BE CLEARED.
/SO ITS DTSF INSTRUCTION MUST BE REMOVED FROM THE SKIPCHAIN.
/
/DECTAPE IOT DEFINITIONS:
DTSF=6771
DTRA=6761
DTXA=6764
DTCA=6762
DTLA=6766
DTRB=6772
DTLB=6774
			/END IFDEF TC08 >
	"D^100+"T&3777	/NAME DT
IFDEF TC08 <400+1		/TWO PAGES , ONE CONNECT
	DTA		/CONNECT DEVICE DTA IN THE SKIPCHAIN
	DTINT		/SO IT JUMPS TO 'DTINT' AFTER INTERRUPT >
IFDEF TD8E <1000	/FOUR PAGES >
XDTNUM,	DTNUM
IFDEF TC08 <
IFNZRO CDTOIF-6200 <
XDTRFLD,DTRFLD >>
XDTWC,	DTWC
XDTUN,	DTUN
XDTBL,	DTBL
XDTBU,	DTBU
XDTFL,	DTFL
XDTSUB,	DTSUB
DTFLD,	0

DT,	SNA		/CLOSE ?
	 JMP CLOSE
	JMS DEFER	/GET FUNCTION WORD
	DCA DTFLD	/SAVE BUFFERFIELD
	ISZ X
	ACM1
	TAD I X		/GET BUFFER ADDRESS
	DCA DTBUF
	ISZ X
	TAD I X		/GET OS/8 BLOCK
IFDEF TC08 <
	CLL RAL		/THIS IS THE DECTAPE BLOCK
	SZL		/L=0 IF PDP8 TAPE
	CLL IAC RAR	/ROTATE BACK IF PDP11 TAPE,SET LINK
	DCA DTBLK
	SZL
	TAD M400	/SET WC=600 IF PDP11-TAPE
	TAD M200	/OR 200 IF PDP8-TAPE
	CDTOIF
	DCA I XDTWC	/ >
IFDEF TD8E <
	CLL RAL
	DCA DTBLK
	TAD DTBLK
	CMA		/MINUS STARTING TAPE BLOCK^2-1
	CDTOIF
	DCA I XDTBL	/ >
	TAD DTFLD	/COMPUTE NUMBER OF RECORDS
	AND C3700
	BSW
	DCA I XDTNUM	/TO SECOND PAGE
	TAD I XDTNUM
	TAD DTBLK	/ENDBLOCK
	DCA DTLAST	/SAVE FOR LATER
IFDEF TC08 <TAD C7	/ >
IFDEF TD8E <AC0001	/ >
	AND DTFLD	/MAKE POINTER TO TAPETABLE
	TAD (TAPETB
	DCA DTTABL
	CDF 00
	CLL
	TAD (5		/COMPUTE DISTANCE
	TAD I DTTABL	/BACKW. FOR 4 OR LESS
	CIA		/L=0
	TAD DTBLK	/L=0 IS FORWARDS
	CDTOIF
	CML CLA
	TAD DTFLD	/GET UNIT, NUMBER OF BLOCKS
IFDEF TC08 <RTR		/DIVIDE BY 16, SET MOTION REG.
	RTR		/
	DCA DTUNIT	/SAVE DTUNIT
IFNZRO CDTOIF-6200 <
	TAD MYCDF	/NOTE THAT 'CDTOIF' CANNOT BE USED
	DCA I XDTRFLD	/IN THE INTERRUPT-ENVIRONMENT >>
IFDEF TD8E <
	RTR
	DCA I XDTUN	/
	TAD DTFLD	/GET BUFFER FIELD
	AND C70
	TAD C6201	/MAKE CDF
	DCA I XDTFL	/
	TAD DTBUF
	DCA I XDTBU	/ >
	JMS MONITOR
	   RESERV RETURN CONTINUE
	DCA DTSLOT
IFDEF TC08 <
	TAD DTUNIT	/MOVE PARAMETERS TO NEXT PAGE
	DCA I XDTUN
	TAD DTBLK	/BLOCK NUMBER
	DCA I XDTBL
	TAD DTBUF
	DCA I XDTBU	/BUFFER ADDRESS
	TAD DTFLD	/BUFFER FIELD
	DCA I XDTFL	/ >
	JMS I XDTSUB	/DO THE TRANSFER
	SZA 
	 JMP DTXIT	/ERROR, DON'T UPDATE TAPETB
	TAD DTLAST	/SET LAST BLOCK IN TAPE TABLE
	CDF 00
	DCA I DTTABL
	DCA ZTEM1	/ZERO COMPLETION STATUS
	TAD DTFLD
	AND C3700	/GET TRANSFER LENGTH
	SNA CLA		/SEARCH ONLY ? THEN NO CLEAR RELEASE OPTION
	 JMP .+3
DTXIT,	DCA ZTEM1	/REMEMBER AC
	TAD (CLEAR RELEASE
	TAD (HALT SIGNAL
	DCA .+3		/SETUP PROPPER MONITOR REQUEST
	TAD ZTEM1	/GET COMPLETION STATUS
	JMS MONITOR
	   HALT SIGNAL CLEAR RELEASE
DTSLOT,	   0

CLOSE,	ACM1
	JMS MONITOR
	   EXIT SWPOUT

DTLAST,	0		/LAST READ/WRITTEN BLOCK
DTTABL,	0		/POINTER TO DECTAPE TABLE
DTBUF,	0
DTBLK,	0
DTUNIT,	0

PAGE
IFDEF TC08 <
/THIS PAGE DOESN'T NEED A PAGE HEADER.
/A "0" MUST BE THE FIRST INSTRUCTION ANYHOW.
/
DTSUB,	0		/DECTAPE XFER ROUTINE
	ACM3		/SET NUMBER OF RETRIES TO 3
	DCA DTTRY
DTST,	ACM3		/MAXIMUM NUMBER OF TURN AROUNDS
	DCA MAXTRN
	TAD DTNUM	/COMPUTE # OF BLOCKS
	CMA
	DCA DTNUMX
DTMON,	CDF 00
	ACM1		//
	TAD DRET1A	//DTRB-1=DTSF
	IOF		///NO KIDING HERE
	DCA I (DTA^4+INT ///INSERT DTSF IN SKIPCHAIN
	DCA DTJMP	///
	TAD (7754	///
	DCA I (7755	///DEPOSIT BLOCKNUMBER IN WC
	TAD DTMON	///FLD=00
	DTLB		///FOR SEARCH
	TAD DTUN	///
	AND C7400	///UNIT+MOTION
	TAD (214	///SEARCH
	ION		///
	DTCA DTXA	///
	JMS MONITOR	//
	   WAIT
CDTA,	   DTA
	SNA CLA		/ERROR ?
	 JMP I DTSUB	/N
	ISZ DTTRY	/TRIED ENOUGH ?
	JMP DTST	/N
IFNZRO HRDERR-4 <?>
	TAD C4		/Y: PASS HRDERR
	JMP I DTSUB	/RETURN AC=4

/NOW THE INTERRUPT PART OF THIS TASK
/
DTINT,	CDF 00
	DTRB		///ERRORS
	AND (2700	///DON'T MIND END OF TAPE
	SZA CLA
	 JMP DTERR	///
DTJMP,	0		///PROGRAM SWITCH
DRET1A,	DTRB		///
	SPA CLA		///END ZONE ?
	JMP DTURN1	///YES: REVERSE MOTION
	DTRA		///
	RTL		///REVERSE BIT TO LINK
	RTL		///
	CLA		///
	TAD I (7754	///
	CIA		///
	TAD DTBL	///RIGHT BLOCK ?
	SNA		///NO
	 JMP DTFIND	///YES
	CIA		///
	SNL		///
	 IAC		///
	SZL CLA		///
	JMP DTURN2	///CONTINUE IN SAME DIRECTION
DTURN,	TAD C400	///REVERSE MOTION
	ISZ MAXTRN	///TRIED ENOUGH??
	SKP		///NO
	 JMP DTERR	///Y: ERROR
DTURN2,	DTXA		///
	TAD DTWC	///SET UP WC
	DCA I (7754	///
DTEXIT,	CIF 00		///
	JMP I ZFSTEXT

DTURN1,	TAD C200	///
	JMP DTURN	///

DTWC,	0		/-200 OR -600
MAXTRN,	0

DTFIND,	SNL CLA		/RIGHT DIRECTION ?
	 JMP DTURN2	///NO
	TAD DTBU	///
	DCA I (7755	///
	TAD (JMP DRET3A	///
	DCA DTJMP	///DRET3A RETURN
	TAD DTFL	///
	DTLB		///
	TAD DTFL	///
	SPA CLA		///
	 TAD (50-30	///
	TAD (30		///
DRET3A,	ISZ DTNUMX	///LAST BLOCK ?
	JMP DTURN2	///NO: NEXT ONE
DTERR,	CLA
	DTRA		///
	AND (204	///EXTRACT MOTION AND INTERRUPT ENABLE
	DTXA		///STOP MOTION, CLEAR INT ENABLE
	DCA I (DTA^4+INT///REMOVE DTSF FROM SKIPCHAIN
	TAD CDTA	///
IFNZRO CDTOIF-6200 <
DTRFLD,	CDF		/// >
IFZERO CDTOIF-6200 <
	CDTOIF		/// >
	CIF 00		///
	JMS I ZSOFINT	///
DTNUMX,	0		///PASS -NUMBER OF BLOCKS IF ERROR

C400,	400
DTBU,	0
DTFL,	0
DTUN,	0
DTBL,	0
DTTRY,	0
DTNUM,	0

			/END IFDEF TC08 >
IFDEF TD8E <
/NAME:	"D^100+"T&3777	/DT (FOR MODULARITY)
/LENGTH: 3 PAGES
/FUNCTION: TO HANDLE TD8E-TAPE TRANSFERS. IT CAN DO A
/	SEARCH-ONLY AND A SEARCH-AND-TRANSFER.
/	THE TRANSFER CANNOT BE DONE IN A REAL-TIME ENVIRON-
/	MENT. IT NEEDS TO TURN OFF THE INTERRUPT-ENABLE FOR
/	AT LEAST 20 MS, WHICH IS TOO FAST TO SEE IT ON THE
/	TELETYPE, BUT FAR TOO SLOW FOR MOST REAL-TIME APPLI
/	CATIONS. SO USE IT WITH CARE.
/	 THE DATA TRANSFER VECTOR RESEM-
/	BLES THAT OF OS8 EXCEPT FOR THE UNIT NUMBER AND THE
/	MEANING OF THE LINK, GIVING THE INITIAL DIRECTION.
/CONCEPT: DURING A SEARCH FOR THE STARTING BLOCK OF THE
/	TRANSFER EVERYTHING CAN GO ON, INCLUDING INTER-
/	RUPTS. WHEN A TRANSFER IS DONE, INT.ENAB. IS TURNED
/	OFF AND REAL TIME WORK IS IMPOSSIBLE. HOWEVER, EVE-
/	RYTHING STAYS AS IT IS, SO YOU JUST LOOSE A COUPLE
/	OF INTERRUPTS, DEVICES  WILL "HESITATE" ETC.
/	A TRANSFER OF LENGTH 0 IS IN OS8 OFTEN INTERPRETED
/	AS A TRANSFER OF 40 PAGES, IN THIS MODULE HOWEVER
/	AS A SEARCH-ONLY.
/ERRORS: NO ERRORS KNOMN AT THE MOMENT
/
/USE:
/AGAIN,	CDF FIELD OF DTV
/	TAD (POINTER TO DTV
/	JMS MONITOR
/	   CALL
/	   "D^100+"T&3777	/DT
/	 JMP TWAIT	/BUSY;AC UNCHANGED;WAIT A FEW SEC.
/	DCA SLOT	/NORMAL RETURN;SLOT # IN AC
/	JMS MONITOR	/WAIT FOR COMPLETION OR ERROR
/	   WAIT
/SLOT,	   0
/	SZA CLA		/ERROR ?
/	 JMP TRY	/YES
/	ETC.
/
/FORMAT OF DATATRANSFERVECTOR (DTV):
/DTV,	RLL.LLL.FFF.UUU /R/W;LENGTH(PAGES);FIELD;UNIT
/	BUFFER ADDRESS IN CORE
/	BLOCK # ON TAPE

/USE OF ZTEM-REGISTERS:
DTV=X		/POINTER TO DATA-TRANSFER-VECTOR
DTCNT=ZTEM1	/COUNTER FOR TIMEOUT OF QUAD LINES
DTETMP=ZTEM2	/EFUN TEMPORARY
DTDIFB=ZTEM3	/DIFFERENCE # BLOCKS (COMPUTE STALL)
DTRWFL=ZTEM4	/R/W-FLAG
DTCNT2=ZTEM5	/COUNTER OF WORDS PER BLOCK
DTCSUM=ZTEM6	/CHECKSUM
DTCNT1=ZTEM7	/COUNTER OF LINES BETWEEN BLOCKS
DTXADR=AUTO10	/CURRENT ADDRESS REGISTER

/OTHER REGISTERS WITHIN THIS MODULE, BECAUSE THEY MUST KEEP
/THEIR VALUE THROUGHOUT MONITOR CALLS:
O=DTUN	/FUNCTION WORD (SEE NEXT PAGE)
O=DTBU	/STARTING ADDRESS OF CURR./NEXT BLOCK IN CORE
O=DTNUMX	/MINUS # OF BLOCKS TO BE TRANSFERED YET
O=DTBLK	/MINUS (STARTING) BLOCK -1 ON TAPE
O=DTFLD	/CDF BUFFER FIELD
O=DTPRCN/COUNTER OF PRECEDE'S DURING/AFTER A UTS-DELAY
O=DTRYCN/NUMBER OF TRIES ON ERROR

/PARAMETERS:
DTQDNM=100	/TIMEOUT FOR SDSQ; JMP .-1

SDSS=6771	/SKIP ON SINGLE LINE FLAG
SDST=6772	/SKIP ON TIME ERROR
SDSQ=6773	/SKIP ON QUAD LINE FLAG
SDLC=6774	/LOAD TAPE COMMAND REGISTER
SDLD=6775	/LOAD DATA REGISTER
SDRC=6776	/READ COMMAND REGISTER
SDRD=6777	/READ DATA REGISTER
CDTCLR,	DTCLR
CDTXFR,	DTXFR
CDTBL,	DTBL
DTNUMX,	0
DTNUM,	0
DTUN,	0
DTWC,	0	/(NOT USED)

DTSUB,	0		/TRANSFER ROUTINE FOR TD8E
	ACM3
	DCA DTRYCN	/RETRY COUNTER
DTRTRY,	AC6000		/ONLY UNIT- & DIRECTION-BITS, CLEAR AC!!
	AND DTUN
	IOF		///IF AN INTERRUPT COMES BETWEEN
	SDLC		///SDLC AND SDRC, IT WILL CAUSE
	ION		///A TIME-ERROR.
	SDRC		///
	AND (100	/TIME- OR SELECT-ERROR ?
	SZA CLA
	 JMS DTERR	/PROBABLY SELECT ERROR
	SDRC		/GET UNIT # & DIR.
			/STOP/GO & R/W BITS ARE ZERO
	TAD (1000	/SET GO BIT
	SDLC		/THIS STARTS THE TAPE, SETS THE
			/UTS DELAY AND CLEARS AC & FLAGS
	CLA		/
	TAD DTNUM
	CIA
	DCA DTNUMX
	AC0001		/GO WAIT SOME TIME
DTSTRT,	DCA DTSTALL
	JMS MONITOR
	   STALL
DTSTALL,   1		/# OF TICKS. (1 TICK = 100 MS)
	JMP DTUTS
DTPREC,	JMS MONITOR
	   PRECEDE	/WAIT SOME 20 MS
DTUTS,	SDSQ		/SEE IF UTS-DELAY IS OVER
	 JMP DTCNPR	/THIS MUST BE THE UTS DELAY
DTBLM,	TAD (6000	/YES, AT LEAST 4 LINES PASSED
	DCA DTPRCN	/AC =2 AFTER STALL, NO PROBLEM
	JMP I CDTCLR	/OK NOW, GO FIND BLOCK #

    /HERE IMMEDIATELY AFTER A TRANSFER OF A BLOCK.
DTRWCO,	ION		///JUST BEFORE SDST !!
	SDST	//	///TIME ERROR ?
	 SZA		/OR CHECKSUM ERROR ?
	 JMS DTERR	/YES, WHAT A PITY AFTER ALL !
    /WE DON'T NEED TO CLEAR THE WRITE-BIT, BECAUSE THE
    /TIME ERROR, WHICH WILL SOON EXIST, WILL DO THAT.
	CDTOIF		/NO NEED TO DO THIS EARLIER.
	ACM1
	TAD I CDTBL
	DCA I CDTBL	/SET TO MINUS NEXT BLOCK#
	TAD C200
	TAD DTBU	/SET ADDRESS FOR NEXT TRANSFER
	DCA DTBU
	CLA CLL	//	/CLEAR LINK IN CASE WE'RE READY
	ISZ DTNUMX	/READY NOW ?
	 JMP DTBLM	/NO, SEE IF BLOCK # IS STILL OK
	JMP DTSTOP //	/YES

DTFND,	TAD DTNUMX	/NOW THAT WE FOUND THE BLOCK,
	SNA CLA		/DOES HE REALLY WANT A(NOTHER)
			/TRANSFER ?
	 JMP DTSTOP	/NO, STOP THE TAPE AND EXIT.
			/ (LINK IS SUPPOSED TO BE ZERO)
	TAD (-12	/YES, SET LINECOUNT
	DCA DTCNT1	/MAX # OF LINES FROM NOW TO MT 42
	TAD DTBU
	DCA DTXADR	/USE AUTOINDEX FOR FAST TRANSFER
	TAD DTUN
	AND (1000	/READ OR WRITE ?
DTFL,	   HLT		//OVERLAYED BY CDF FIELD OF XFER
	JMP I CDTXFR	//TRANSFER NEXT BLOCK

DTCNPR,	ISZ DTPRCN	/NOT ALWAYS PRECEDE
	 JMP DTPREC	/TRY ONCE MORE
	JMS DTERR	/TOO LONG
DTERR,	0		///SUB FOR DEBUG
	ION	//	///ERROR RETURN, MAYBE IOF (OR HLT FOR DEBUG)
	CLA STL		///LINK = 1: ERROR
	CDTOIF		/
	ISZ DTRYCN	/TRY 3 TIMES
	 JMP DTRTRY	/TRY ONE MORE TIME
DTFATR,	STL		/FATAL ERROR RETURN
DTSTOP,	ION		///IF INTERRUPT ENABLE WAS OFF
	SDRC	//	///WE STILL HAVE TO STOP THE TAPE
	AND (6000	/READ UNIT # & DIRECTION
	SDLC		/CLEAR S/G- (& R/W-) BIT
	SZL CLA
	 AC0004		/(HRDERR
	JMP I DTSUB	/RETURN
DTPRCN,	6000
DTRYCN,	0
DTBU,	0

PAGE
CDTSTRT,DTSTRT
CDTPREC,DTPREC
CDTSLWT,DTSLWT
CDTFND,	DTFND
CDTERR, DTERR
CDRTRY,	DTRTRY
DTBL,	0
DTCLR,	SDRC		/CLEAR SL- & QL-FLAGS
	AND C7000
	IOF
	SDLC		///CLEAR TIME ERROR FLAG
	JMS I CDTSLWT	///READ COMMAND REGISTER SYNCHRONE
	AND (100	///TIME- OR SELECT-ERROR ?
	SZA CLA
	 JMS I CDTERR	/YES, MUST BE SELECT ERROR.
DTNXT,	IOF		///WE CAN'T USE INTERRUPTS NOW
	SDRD		///CLEAR FLAGS AFTER IOF
	CLA		///SHOULD BE ACM3
	TAD M4
	DCA DTCNT
	JMS I CDTSLWT	///AND WAIT FOR NEXT FLAG
	SDRC		///READ COMMAND
	AND (2077	///MARK TRACK
	CLL RTL		///DIRECTION TO LINK
	TAD (-130	///THE BLOCK # !
	SNA
	 JMP DTHOT	///YES, NOW HURRY !
	TAD C4		///MAYBE 25 ?
	SNA
	 JMP DT25	///COULD BE NEAR
	TAD (-130	///TRY 53
	SNA
	 JMP DTNEAR	///YES, VERY NEAR NOW!
	TAD C4		///OR MAYBE 52
	SNA
	 JMP DT52	///NO, SERVE SOME INTERRUPTS
	TAD (140	///OR 22 (ENDZONE) ?
	SZA CLA		/IF NOT, WE DON'T WANT TO KNOW
	 JMP DTSLOW /SLOW /NONE OF THEM ALL
			/YES, ASSUME ENDZONE BACKWARD
DTFORT,	DCA DTDIFB	/CLEAR DIFFERENCE
	SDRC		/READ COMMAND
	CLL RTL		/DIRECTION TO LINK
	SZL		/FORWARD OR REVERSE ?
	 JMP DTMOVE	/REVERSE, CHANGE DIRECTION
DTSLOW,	ION		///ION HAS A DELAY
	JMP DTNXT
DT25,	JMS I CDTSLWT	///WAIT FOR NEXT LINE
	AND C77
	TAD (-53	///IS IT 53 ?
	SNA
	 JMP DTNEAR	///YES, ONLY A FEW MICROSEC. NOW
	IAC		///ELSE IT MUST BE 52
	SZA
	JMP I CDRTRY	///SOMEPING WENT WRONG
DT52,	JMS I CDTSLWT	///READ NEXT LINE
	AND C77
	TAD (-25
	SZA
	JMP I CDRTRY	///DON'T COUNT RETRIES ON BLOCK SEARCH
	ISZ DTCNT	///TIME-OUT
	 JMP DT25	///TRY NEXT ONE
	JMP DTSLOW

DTNEAR,	JMS I CDTSLWT	///WAIT FOR NEXT LINE
	AND (2077
	CLL RTL		///DIRECTION TO LINK
	TAD (-130	///MARK TRACK MUST BE 26 !
	SZA
	JMP I CDRTRY	/// NO 26 ???
/DON'T CHANGE THE NEXT 20 LINES, THEY TOOK ME A LOT OF TIME
DTHOT,	SDRD		///READ BLOCK # WHERE WE ARE
	SPA		/IF MINUS CODE IS NOT RIGHT
	 JMS I CDTERR
	SNL
	 TAD C3		/IF IN REVERSE LOOK FOR 3 BLOCKS
	IAC		/BEFORE THE ACTUAL TARGET BLOCK.
	TAD DTBL	/ADD MINUS BLOCK # WE ARE LOOKING
	SZA		/RIGHT BLOCK # ?
	 JMP DTNOTY	/NO, GET IT
	SNL		/RIGHT DIRECTION ?
	 JMP I CDTFND	/OK, GO TRANSFER THIS PAGE
DTNOTY,	SPA SNA		/MAKE POSITIVE
	 CIA		/IF AC = 0, LINK WILL CHANGE TO 0
	SZL		/IF LINK IS 0 NOW, CHANGE DIRECTION
	 JMP DTNORT	/NO, JUST COMPUTE HOW LONG TO WAIT
DTRTRN,	DCA DTDIFB	/SAVE DIFFERENCE
	SDRC
	RTL		/DIRECTION TO LINK
DTMOVE,	CML RTR		/DIRECTION HAS CHANGED NOW
	SDLC		/GIVE COMMAND, CLEAR AC
	TAD (10		/CHANGE DIRECTION: 100 MS.
	TAD DTDIFB
DTNORT,	ION
	CLL RAR		/COMPUTE # OF TICKS TO WAIT
	CLL RAR		/WE DIVIDE # OF BLOCKS BY 8,
	CLL RAR		/8*17MS = 136 MS ON THE SAFE SIDE
	DCA DTDIFB
	TAD DTDIFB	/DELAY DANGEROUS ?
	AND (7770
	SZA CLA
	TAD (10		/NEVER TOO LARGE .8 SEC =50 BLKS (80 IN ENDZONE)
	SNA		/LESS THAN .8 SEC ?
	TAD DTDIFB	/TAKE EXACT VALUE
	SNA		/CAN WE DO A STALL ?
	 JMP I CDTPREC	/NO, MAYBE NEXT BLOCK
	JMP I CDTSTRT	/YES, WAIT A WHILE

PAGE
CDTRWCO,DTRWCO
CDTRTRN,DTRTRN
CDTER1,	DTERR
	0
DTCHCK,	ISZ DTCNT1 //	///NOT 42, ENOUGH COUNTS ?
	 JMP DT42	///NO, TRY NEXT LINE
	JMP I CDTRTRN	///RETURN TAPE AND RETRY
DTXFR,	SZA CLA	//	/READ OR WRITE ?
	 ACM1
	DCA DTRWFL	/0 IF READ, -1 IF WRITE
	TAD M200	/FOR ONE DECTAPE BLOCK
	DCA DTCNT2	/SET COUNT TO - # WORDS IN BLOCK
	TAD (-DTQDNM
	DCA DTCNT //	/SET COUNTER FOR TIME-OUT
	SDRC		///CLEAR SINGLE & QUAD-LINE FLAG
	AND C7000	///CLEAR WRITE-BIT
	SDLC	//	///CLEAR TIME-ERROR FLAG
DT42,	JMS DTSLWT	///WAIT FOR NEXT LINE
	AND C77		///MARK TRACK
	TAD (-42 //	///IS IT 42 ?
	SZA CLA
	 JMP DTCHCK	///NO, TRY ENOUGH TIMES
	ISZ DTRWFL //	///0 OR -1
	 JMP DTREAD	///0 MEANS READ, -1 MEANS WRITE
	SDRC		///BIT 1: REVERSE DIRECTION
	AND (2700	///BIT 3: WRITE; BIT 4: WRITE LOCK
	SZA	//	///BIT 5: SELECT- OR TIME-ERROR
	 JMS I CDTER1	///ERROR
	SDRC		///READ UNIT #, DIR. & GO-BITS
	TAD (400	///SET WRITE
	SDLC	//
	ACM1		///WRITE -1 TO REVERSE CHECKSUM
	JMS DTWRQD	///WRITE
	ACM1	//
	DCA DTCSUM	///PUT ALSO IN CHECKSUM

DTWRBL,	TAD I DTXADR	///READ FROM CORE
	JMS DTWRQD //
	ISZ DTCNT2	///READY ?
	 JMP DTWRBL	///NO, NEXT
	JMS DTWRQD //	///WRITE 0 IN 129TH (201TH) WORD
	JMS DTGCHK	///COMPUTE CHECKSUM
	JMS DTWRQD	///WRITE IT
	JMS DTWRQD //	///LET CHECKSUM FINISH
	JMP I CDTRWCO	///

DTWRQD,	0	//	///SUBROUTINE TO WRITE ON TAPE
	JMS DTEFUN	///WITHIN A REASONABLE TIME
DTWRLP,	ISZ DTCNT	///TIME-OUT, (MUST BE INIT. SET)
	 SKP	//
	 JMS I CDTER1	///TOO LONG
	SDSQ		///FLAG UP ?
	 JMP DTWRLP //	///NO, LOOP
DTWRFD,	SDLD		///YES, WRITE NEXT WORD
	CLA
	TAD (-DTQDNM //	///SET COUNT FOR NEXT TRANSFER
	DCA DTCNT
	JMP I DTWRQD

DTREAD,	JMS DTRDQD
	JMS DTRDQD	///WAIT FOR 8 LINES TO PASS
	AND C77	//	///REVERSE CHECKSUM
	TAD (7700
	DCA DTCSUM
DTRDBL,	JMS DTRDQD //	///WAIT FOR FOUR LINES & READ DATA
	JMS DTEFUN	///PREPARE CHECKSUM
	DCA I DTXADR	///PUT IN CORE
	ISZ DTCNT2 //	///COUNT THE NUMBER OF TRANSFERS
	 JMP DTRDBL	///NEXT
	JMS DTRDQD	///READ 129TH (201TH) WORD
	JMS DTEFUN //
	JMS DTRDQD	///READ CHECKSUM
	AND (7700	///
	JMS DTEFUN //
	CLA
	JMS DTGCHK	//COMPARE CHECKSUMS
	JMP I CDTRWCO	///GO LOOK IF TRANSFER IS OK.

DTRDQD,	0	//	///SUBROUTINE TO REPLACE THE
			///NORMAL SEQUENCE: SDSQ;JMP .-1
			///BECAUSE IF SOMEONE STOPS THE
	CLA	//	///TAPE, IT WILL NEVER SKIP.
	TAD (-DTQDNM	///TIME-OUT
DTRDLP,	IAC		///LOOP
	SMA	//
	 JMS I CDTER1	///TOO LONG
	SDSQ
	 JMP DTRDLP //	///FLAG STILL DOWN
DTRDFD,	SDRD		///UP, RETURN WITH DATA IN AC
	JMP I DTRDQD

DTSLWT,	0		///SUBR. TO REPLACE SDSS;JMP .-1
	SDSS	//	///BECAUSE THAT COULD BE TOO TIME-
	 SKP CLA	///CONSUMING. FIRST TRY IF ALR. UP
	 JMP DTSLFD	///YES, QUICK RETURN
	TAD (-100 //	///TIME-OUT, MUST BE ENOUGH
DTSLLP,	IAC
	SMA
	 JMS I CDTER1 // ///TOO LONG
	SDSS
	 JMP DTSLLP	///NOT YET UP, LOOP UNTIL...
DTSLFD,	SDRC	//	///RETURN WITH COMMAND REGISTER
	JMP I DTSLWT
DTEFUN,	0	//	///I DIDN'T THINK IT'S POSSIBLE TO
	CMA		///WRITE THESE ROUTINES BETTER THAN
	DCA DTETMP	///THE BEST DIGITAL-PEOPLE DID.
	TAD DTETMP //	///SO I DIDN'T TRY TO, AND HEREBY
	AND DTCSUM	///I THANK THEM FOR DOING THE GOOD
	CIA		///THINKING WORK.
	CLL RAL	//
	TAD DTETMP
	TAD DTCSUM
	DCA DTCSUM //
	TAD DTETMP
	CMA
	JMP I DTEFUN //

DTGCHK,	0	//
	TAD DTCSUM
	CMA BSW		///
	JMS DTEFUN
	CLA	//
	TAD DTCSUM
	AND (7700
	JMP I DTGCHK //

			/END IFDEF TD8E >
$