Google
 

Trailing-Edge - PDP-10 Archives - BB-J724A-SM_1980 - sources/kmc11.p11
There is 1 other file named kmc11.p11 in the archive. Click here to see a list.
.SBTTL	KMC11/DUP11 DRIVER
;
; THIS SECTION CONTAINS SUBROUTINES TO DRIVE THE KMC11/DUP11.
;  THESE ARE:
;
;	DQINIT		INITIALIZE THE KMC11/DUP11
;	DQREAD		CONDITION THE KMC11/DUP11 FOR INPUT
;	DQWRIT		CONDITION THE KMC11/DUP11 TO OUTPUT A DATA MESSAGE
;	DQCNTL		CONDITION THE KMC11/DUP11 TO OUTPUT A CONTROL MESSAGE
;	DQKILL		CEASE ANY KMC11/DUP11 OPERATIONS
;
; THIS SECTION ALSO CONTAINS THE INTERRUPT CODE FOR THE KMC11/DUP11,
;  AND A "ONCE-PER-CLOCK-TICK" SUBROUTINE
;  TO PROVIDE DELAYED MODEM CONTROL SINCE A MODEM INTERRUPT
;  CANNOT BE CAUSED BY THE PROGRAM.
;  IT ALSO MAINTAINS THE KEEP-ALIVE COUNTERS.
;
.REPT 0


                          COPYRIGHT (c) 1980, 1979
            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.

.ENDR
;
;
;
;		REVISION HISTORY
;
;
; 4(001) BS	ADDED EDIT NUMBERS
;
;
;
VKMC11=001
;
VEDIT=VEDIT+VKMC11
;
;
;
; SPECIFY THE NUMBER OF TRAILING PADS REQUIRED ON
;  DATA MESSAGES.
;
DQTRLP=1		;TO BE SURE THE LAST CHAR MAKES IT
;
; SPECIFY THE TYPE OF LINE INTERFACE, WHICH IS REPORTED TO THE -10
;
DQTYPE=2		;1 = DQ11, 2 = KMC11/DUP11, 3 = DUP11 ALONE
;
;
; INITIALIZATION
;
; R4 = POINTER TO LINE CONTROL BLOCK FOR THE KMC11/DUP11 TO BE
;	INITIALIZED.
;
DQINIT:	TRACE	TRCDQF,R4	;TRACE "DUP11 INITIALIZATION"
	MOV	LB.SLA(R4),R3	;GET DUP11 LINE HARDWARE ADDRESS
	MOV	#UP.INI,UP.XSR(R3) ;INITIALIZE THE DUP11
11$:	BIT	#UP.INI,UP.XSR(R3) ;HAS IT FINISHED INITIALIZATION?
	BNE	11$		;NO, WAIT FOR IT.
	MOV	#UP.CCI!UP.DMD!EBCSYN,UP.PAR(R3) ;SET UP PARMS
				; FOR BISYNC
	MOV	#UP.HDX,UP.XSR(R3) ;BLIND RECEIVER DURING TRANSMISSIONS
	MOV	#UP.SSY,UP.RSR(R3) ;STRIP LEADING SYNC FROM MESSAGES
	MOV	LB.LNU(R4),R0	;LINE NUMBER
	ASR	R0		;LINE NUMBER/4 = KMC11 NUMBER
	BIC	#1,R0		;KMC11 NUMBER * 2
	MOV	R0,R2		;SAVE KMC11 NUMBER * 2
	ASR	R2		;COMPUTE KMC11 NUMBER
	MOV	#MDTBL,R1	;COMPUTE KMC11 TABLE ADDRESS
	TST	R2		; USING NO MULTIPLY INSTRUCTION
	BEQ	13$		;WE HAVE IT
12$:	ADD	#MDTLN,R1	;POINT TO NEXT TABLE
	SOB	R2,12$		;DECREMENT COUNTER AND TRY AGAIN.
;
;			; CONTINUED ON NEXT PAGE
;
;
; HERE TO INITIALIZE THE KMC11 WHICH OWNS THIS DUP11.
;  IF THE KMC11 HAS ALREADY BEEN INITIALIZED (BY STARTING ONE
;  OF ITS OTHER LINES FIRST, FOR EXAMPLE) THEN WE NEED DO NOTHING.
;  OTHERWISE WE STORE THE KMC11 CONTROL BLOCK ADDRESS INTO SEL 2
;  TO SIGNAL IT TO START PROCESSING AND WAIT FOR ITS "RUN" BIT.
;
; R1 = ADDRESS OF KMC11 CONTROL BLOCK
; R0 = KMC11 NUMBER * 2
; R4 = LCB POINTER
;
13$:	BIT	#MDFER,MDFGE(R1) ;IS PDP-11 ALREADY RUNNING?
	BNE	15$		;YES, DON'T INIT AGAIN.
	MOV	MDVEC(R0),R2	;NO, POINT TO KMC11 VECTOR
	BNE	14$		;THERE IS SUCH A KMC11
	STOPCD	KMM		;KMC11 IS MISSING
;
14$:	MOV	#MDAINT,(R2)+	;STORE POINTER TO INT. HANDLER
	MOV	#MD.LVL*40,(R2)+ ;STORE PRIORITY LEVEL
	MOV	#MDBINT,(R2)+	;STORE OTHER INT. HANDLER POINTER
	MOV	#MD.LVL*40,(R2)+ ;STORE PRIORITY LEVEL
	MOV	#MDFER,MDFGE(R1) ;MARK PDP-11 RUNNING
	MOV	MDCSR(R0),R3	;POINT TO KMC11 CSR
	MOV	R1,2(R3)	;POINT MICROCODE TO KMC11 TABLE
15$:	MOV	R1,LB.MD(R4)	;STORE POINTER TO KMC11 TABLE IN LCB
	MOV	LB.LNU(R4),R0	;GET LINE NUMBER
	BIC	#^C3,R0		;LINE WITHIN KMC11
	ASL	R0		; *2
	ADD	R1,R0		;POINT INTO KMC11 TABLE
	MOV	R4,MDLCB(R0)	;STORE POINTER TO LCB IN KMC11 TABLE
;
;			; CONTINUED ON NEXT PAGE
;
;
; NOW WAIT FOR THE KMC11 TO START.  WE WAIT UP TO THREE SECONDS.
;
	MOV	R4,-(SP)	;SAVE R4
	MOV	#JIFSEC*3,-(SP)	;NUMBER OF JIFFIES TO WAIT
	MOV	#EBTIME!EBWAIT,(R5) ;WAIT ONLY FOR TIME TO PASS
	MOV	#1,TCTIM(R5)	;CHECK FOR "RUN" EVERY JIFFY
;
; HERE BEGINS THE LOOP THAT WAITS FOR THE KMC11 TO BEGIN RUNNING.
;
16$:	MOV	2(SP),R4	;POINT R4 TO LCB
	MOV	LB.MD(R4),R3	;POINT R3 TO KMC11 CONTROL BLOCK
	BIT	#MDFKR,MDFGK(R3) ;IS THE KMC11 RUNNING NOW?
	BNE	17$		;YES.
	JSR	PC,WAIT		;NO, WAIT ONE JIFFY
	DEC	(SP)		;WAITED LONG ENOUGH?
	BNE	16$		;NO, CHECK AGAIN.
	STOPCD	KNR		;KMC11 NOT RUNNING (WAITED 3 SEC)
;
; HERE WHEN THE KMC11 HAS SET ITS "RUN" BIT.
;
17$:	MOV	(SP)+,R4	;DISCARD DEPLETED COUNTER
	MOV	(SP)+,R4	;GET BACK LCB POINTER
;
; EXERCISE THE KMC11 TO BE SURE IT IS WORKING
;
	MOV	#21,R0		;COUNT OF TIMES TO EXERCISE
18$:	JSR	PC,MDACTV	;PULL ITS CHAIN
	SOB	R0,18$		;DO THIS FOR A WHILE
	RTS	PC		;RETURN.
;
;
; START RECEIVER
;
; R4 = POINTER TO LINE CONTROL BLOCK
;
; RETURNS C BIT SET IF ERROR, CLEAR IF OK.
;  (ONLY ERROR IS CHUNKS DEPLETED)
;
DQREAD:	TRACE	TRCDQF,R4	;TRACE ENTRY TO "DQ READ"
	MOV	LB.SLA(R4),R3	;GET HARDWARE ADDRESS
.IF NE,FT.CHK
	BIT	#LS.RGO!LS.RRN,(R4) ;IS DUP11 ALREADY READING?
	BEQ	11$		;NO, GOOD.
	STOPCD	QRN		;DUP11 SUBR WITH DUP11 RUNNING
11$:	MOV	LB.TC1(R4),R0	;POINT TO BSC TASK
	TST	TCCHK1(R0)	;DOES IT HAVE ANY CHUNKS?
	BEQ	12$		;NO, OK
	STOPCD	QRN		;YES, SOMETHING'S WRONG.
12$:	TST	LB.CCH(R4)	;IS THERE A "CURRENT CHUNK"?
	BEQ	13$		;NO, ALL IS WELL.
	STOPCD	QRN		;YES, THERE SHOULD NOT BE.
13$:
.ENDC ;.IF NE,FT.CHK
	MOV	CHLST,R0	;GET A CHUNK
	JSR	PC,GETCHK
	BCS	15$		;NO MORE CHUNKS
	CLR	LB.CRD(R4)	;CLEAR COUNT OF CHARACTERS READ
	MOV	R4,R2		;POINT R2 TO LCB
	ADD	#LB.SO1,R2	;BUILD POINTER TO FIRST SILO
	JSR	PC,MDSLOI	;INITIALIZE THE SILO
;
;			; CONTINUED ON NEXT PAGE
;
;
; HERE WHEN EVERYTHING IS READY.
;  UNLESS WE ARE WAITING TO START A WRITE,
;  WE MUST START THE RECEIVER NOW, SINCE SOME DUP11'S
;  DON'T INTERRUPT ON CARRIER, AND IF WE WAIT UP TO
;  16 MILLISECONDS BEFORE STARTING THE RECEIVER AFTER
;  GETTING CARRIER, WE WILL FREQUENTLY LOSE THE FIRST
;  CHARACTER OF THE MESSAGE.
;
	MFPS	-(SP)		;SAVE CPU PRIORITY LEVEL
	MTPS	#BR7		;DISABLE CPU INTERRUPTS
	BIS	#UP.DIE,UP.RSR(R3) ;ENABLE MODEM INTERRUPTS
	BIS	#LS.RGO,(R4)	;WAITING TO START RECEIVER
	BIT	#LS.XGO,(R4)	;IS A WRITE PENDING?
	BNE	14$		;YES, WAIT FOR IT TO START.
	BIC	#LS.RGO!LS.CAR,(R4) ;NO, NO READ PENDING.
	BIC	#UP.CAR,LB.DIP(R4) ;PROCESS CARRIER NEXT TIME WE SEE IT
	BIS	#LS.RRN,(R4)	;START THE READ NOW.
	JSR	PC,MDACTV	;ACTIVATE THE KMC11
	BIS	#UP.REN,UP.RSR(R3) ;ENABLE  THE DUP11 FOR READING
14$:	MTPS	(SP)+		;RESTORE CPU PRIORITY
	CLC			;FLAG NO ERROR
	RTS	PC		;AND RETURN.
;
;
; HERE IF WE CANNOT GET A CHUNK TO READ INTO.  THIS IS A FATAL
;  READ ERROR.
;
15$:	INC	LB.CHD(R4)	;COUNT TIMES CHUNKS DEPLETED
;	SEC			;FLAG ERROR (C ALREADY SET)
	RTS	PC		;GIVE ERROR RETURN.
;
;
; SUBROUTINE TO START TRANSMITTING A DATA MESSAGE FROM LB.MSG
;
; R4 = POINTER TO LINE CONTROL BLOCK
;
; RETURNS WITH C BIT SET IF ERROR, CLEAR IF NOT.
;
DQWRIT:	TRACE	TRCDQF,R4	;TRACE ENTRY TO "DQ WRITE DATA"
	BIC	#LS.CTL,(R4)	;THIS IS A DATA, NOT A CONTROL MESSAGE
	MOV	LB.SLA(R4),R3	;GET DUP11 HARDWARE ADDRESS
.IF NE,FT.CHK
	BIT	#LS.ACT,(R4)	;IS DUP11 STILL ACTIVE?
	BEQ	11$		;NO.
	STOPCD	QRN		;YES, THIS IS NOT PROPER.
11$:
.ENDC ;.IF NE,FT.CHK
	MOV	LB.MSG(R4),R0	;POINT TO MESSAGE
	MOV	(R0),R1		;POINT TO FIRST DATA CHUNK
	MOV	R1,MSGLCH(R0)	;START WITH FIRST CHUNK
	ADD	#CHDAT,R1	;POINT TO DATA AREA
	MOV	R1,MSGPTR(R0)	;STORE POINTER TO START OF DATA
	JSR	PC,XMTSTR	;ARRANGE TO START TRANSMITTER
	RTS	PC		;RETURN.
;
;
; SUBROUTINE TO ARRANGE TO START THE TRANSMITTER
;
XMTSTR:	BIS	#LS.XGO,(R4)	;XMITTER WAITING FOR CTS
	BIC	#LS.XND,(R4)	;NOT ENDING TRANSMISSION
	MFPS	-(SP)		;SAVE INTERRUPT LEVEL
	MTPS	#BR7		;DISABLE INTERRUPTS
	BIS	#UP.RTS!UP.DIE,UP.RSR(R3) ;RAISE REQUEST TO SEND
				; AND ENABLE FOR CTS INTERRUPT
	MOV	LB.CSD(R4),LB.DEW(R4) ;WAIT A WHILE, THEN CHECK FOR CTS
				; NOTE THAT MODEM INTERRUPTS ARE IGNORED
				; UNTIL TIME IS UP.
	BNE	11$		;TIME IS NOT YET UP.
;
; HERE IF CLEAR-TO-SEND DELAY SPECIFIED IS ZERO.
;  IF CTS IS UP, START THE TRANSMITTER.  NOTE THAT
;  A ZERO CLEAR-TO-SEND DELAY SHOULD BE USED ONLY WITH MODEMS
;  THAT HAVE A CLEAR-TO-SEND DELAY OF LESS THAN 16 MILLISECONDS,
;  SINCE A LARGER DELAY CAN BE TIMED WITHOUT LOSS OF EFFICIENCY
;  AND TOO SHORT A DELAY (LESS THAN ABOUT 8 MILLISECONDS)
;  DOES NOT WORK WITH SOME IBM HOSTS.
;
	BIT	#UP.CTS,UP.RSR(R3) ;IS CTS UP?
	BEQ	11$		;NO, WAIT FOR MODEM INTERRUPT
	BIC	#LS.XGO,(R4)	;NOT WAITING FOR CTS
	BIS	#LS.XRN,(R4)	;NOW RUNNING
	BIS	#UP.SND,UP.XSR(R3) ;ENABLE FOR SENDING
	MOV	#UP.XSM!EBCPAD,UP.XBF(R3) ;FIRST CHAR IS PAD
	JSR	PC,MDACTV	;ACTIVATE THE KMC11
	BR	12$		;ENABLE INTERRUPTS, CLEAR C AND RETURN.
;
; HERE IF CTS DELAY IS NON-ZERO, OR IF IT IS ZERO AND CTS IS NOT UP.
;
11$:	BIC	#UP.CTS,LB.DIP(R4) ;PROCESS CTS RAISING NEXT TIME WE SEE IT
12$:	MTPS	(SP)+		;ENABLE INTERRUPTS
	CLC			;CLEAR 'C' FLAG
	RTS	PC		;RETURN.
;
;
; SUBROUTINE TO START TRANSMITTING A CONTROL MESSAGE (E.G., ACK)
;
; R4 = POINTER TO LINE CONTROL BLOCK
; R0 = POINTER TO MESSAGE TO SEND
; R1 = LENGTH OF MESSAGE TO SEND
;
; ON RETURN:
;
;	C SET IF ERROR, CLEAR IF NOT.
;
DQCNTL:	TRACE	TRCDQF,R4	;TRACE ENTRY TO "DQ WRITE CONTROL"
	MOV	R0,LB.CMA(R4)	;REMEMBER CONTROL MESSAGE ADDRESS
	MOV	R1,LB.CMC(R4)	; AND LENGTH
	BIS	#LS.CTL,(R4)	;WE ARE WORKING ON A CONTROL MESSAGE
	TRACE	TRCDQF,R0	; AND NOTE MESSAGE
	MOV	LB.SLA(R4),R3	;GET DUP11 HARDWARE ADDRESS
.IF NE,FT.CHK
	BIT	#LS.ACT,(R4)	;IS DUP11 STILL ACTIVE?
	BEQ	11$		;NO.
	STOPCD	QRN		;YES, ERROR.
11$:	TST	LB.CCH(R4)	;HAS RECEIVER STILL GOT A CHUNK?
	BEQ	12$		;NO, THAT'S GOOD.
	STOPCD	QRN		;YES, MUST SOMEHOW BE RUNNING.
12$:
.ENDC ;.IF NE,FT.CHK
	JSR	PC,XMTSTR	;ARRANGE TO START TRANSMITTER
	RTS	PC		;RETURN.
;
;
; THIS IS THE COMMON INTERRUPT CODE FOR DUP11 RECEIVER INTERRUPTS.
;  IT IS CALLED WITH PS CONTAINING THE LINE NUMBER.
;  MODEM INTERRUPTS ALSO COME HERE.
;
DQAINT:	JSR	R4,(PC)		;SAVE R4 WITHOUT CHANGING PS
	MFPS	R4		;GET PS
	BIC	#177760,R4	;REMOVE ALL BUT LINE NUMBER
	ASL	R4		;LINE NUMBER * 2
	MOV	DQLCB(R4),R4	;GET POINTER TO LCB
	MOV	R3,-(SP)	;SAVE R3
	MOV	R1,-(SP)	;SAVE R1
	MOV	R0,-(SP)	;SAVE R0
.IF NE,FT.CHK
	TST	R4		;HAVE WE A LINE BLOCK?
	BNE	11$		;YES.
	STOPCD	UQR		;UNKNOWN DUP11 RECEIVER INTERRUPT
11$:
.ENDC ;.IF NE,FT.CHK
	MOV	LB.SLA(R4),R3	;GET HARDWARE ADDRESS OF DUP11
	INC	LB.RCT(R4)	;ONE MORE RECEIVER INTERRUPT
	TRACE	TRCDQF,R4	;TRACE DUP11 "A" INTERRUPT
;
;
; HERE TO CHECK FOR A DUP11 RECEIVER INTERRUPT BIT
;
RCVTST:	MOV	UP.RSR(R3),R0	;GET RECEIVER STATUS REGISTER
	MOV	R0,LB.RST(R4)	;STORE LAST RECEIVER STATUS
	TRACE	TRCDQF,R0	;TRACE INTERRUPT STATUS
;
; HERE TO CHECK FOR DATASET INTERRUPT FLAGS, SINCE THE KMC11 TAKES
;  CARE OF DATA SIGNALS.
;
11$:	BIT	#UP.DCA!UP.DCB,R0 ;ANY DATASET FLAGS?
	BEQ	12$		;NO, EXIT THE INTERRUPT.
	JSR	PC,RCVDSF	;YES, PROCESS DATASET FLAGS
;
; HERE ON NORMAL EXIT.  WAKE THE BSC TASK IF REQUESTED.
;
12$:	BIT	#LS.CIE,(R4)	;DOES BSC TASK WANT TO BE AWAKENED?
	BEQ	13$		;NO.
	BIC	#LS.CIE,(R4)	;YES, CLEAR FLAG
	MOV	LB.TC1(R4),R0	;POINT TO BSC TASK'S TCB
	BIT	#EBQCHK,(R0)	;IS BSC TASK WAITING FOR CHUNK DATA?
	BEQ	13$		;NO (UNLIKELY)
	BIC	#EBQCHK!EBWAIT,(R0) ;YES, UNWAIT IT.
13$:
;
; HERE TO RESTORE REGISTERS AND RETURN.
;
14$:	MOV	(SP)+,R0	;RESTORE R0
	MOV	(SP)+,R1	; AND R1
	MOV	(SP)+,R3	; AND R3
	MOV	(SP)+,R4	; AND R4
	RTI			;EXIT INTERRUPT
;
;
; SUBROUTINE TO RECORD A DUP11 ERROR.
;  CALLER INCREMENTS LB.SE4, LB.SE5 OR LB.SE6 BEFORE CALLING.
;
DQERRR:	INC	LB.SE1(R4)	;COUNT MASTER ERROR COUNTER
	MOV	LB.SLA(R4),R3	;POINT TO DUP11 CSR
	MOV	UP.RSR(R3),LB.SE2(R4) ;RECORD STATUS REG 1
	MOV	UP.XSR(R3),LB.SE3(R4) ; AND STATUS REG 2
	BIS	#LS.ERR,(R4)	;FLAG AN ERROR
	RTS	PC		;RETURN TO CALLER.
;
;
; SUBROUTINE TO STOP THE RECEIVER
;
;   R4 POINTS TO LCB, R3 TO CSR.
;
RCVSTP:	TRACE	TRCDQF,R4	;TRACE DUP11 RECEIVER STOP
.IF NE,DEBUG
	BIT	#LS.RGO!LS.RRN,(R4) ;IS RECEIVER RUNNING?
	BNE	11$		;YES.
	STOPCD	DBG		;NO, SHOULDN'T BE HERE.
11$:
.ENDC ;.IF NE,DEBUG
	BIC	#UP.DIE,UP.RSR(R3) ;DISABLE MODEM INTERRUPTS
	BIS	#LS.KIL,(R4)	;KILL CURRENT OPERATION
	JSR	PC,MDACTV	;AWAKEN THE KMC11
	RTS	PC		;RETURN.
;
;
; HERE ON A SILO INTERRUPT FROM THE KMC11.
;  DRAIN ANY NON-EMPTY SILOS WHICH HAVE THEIR "INTERRUPT ON
;  NEXT CHARACTER" FLAG CLEAR, WHICH MEANS THAT THE KMC11
;  MIGHT HAVE INTERRUPTED BECAUSE OF THEM.  THE KMC11 WILL
;  GIVE FULL AND WARNING INTERRUPTS REGARDLESS OF THE
;  STATE OF THIS FLAG.
;
MDAINT:	MOV	R2,-(SP)	;SAVE R2
	MOV	R3,-(SP)	;SAVE R3
	MOV	R4,-(SP)	;SAVE R4
	MOV	R5,-(SP)	;SAVE R5
;
; HERE TO CHECK ALL LCB'S FOR A NON-EMPTY SILO
;
	CLR	R5		;LINE NUMBER * 2
;
; HERE TO CHECK THE NEXT LCB
;
11$:	MOV	DQLCB(R5),R4	;POINT TO LCB
	BEQ	13$		;NO LCB FOR THIS LINE
	BIT	#LS.XGO!LS.XRN!LS.KIL!LS.KLC,(R4)
				;IS THIS LINE WRITING OR KILLED?
	BNE	13$		;YES, IGNORE ITS SILO
	BIT	#LS.RRN,(R4)	;NO, IS LINE DOING INPUT?
	BEQ	13$		;NO, IGNORE ITS SILO.
	TRACE	TRCMDF,R4	;KMC11 INPUT INTERRUPT FOR THIS LCB
	MOV	LB.SLO(R4),R3	;POINT TO SILO
	BIT	#MDSLFE,MDSLFG(R3) ;WILL THIS SILO INT. ON NEXT CHAR?
	BNE	12$		;YES, IGNORE IT UNTIL IT INTERRUPTS.
	MOV	MDSLPT(R3),R2	;NO, GET CURRENT ADDRESS FROM SILO
	SUB	LB.CCD(R4),R2	;SUBTRACT INITIAL ADDRESS
	CMP	R2,@LB.CCR(R4)	;HAS COUNT CHANGED?
	BEQ	12$		;NO, IGNORE THIS EMPTY SILO.
	JSR	PC,MDSLEM	;YES, EMPTY THE SILO
	BIS	#LS.RSE,(R4)	;MARK THAT THE RECEIVE SILO
				; WAS EMPTIED.
.IF NE,DEBUG
	BR	13$		;DONE WITH THIS LCB
.ENDC ;.IF NE,DEBUG (NO CODE BETWEEN FINISH AND REJECT UNLESS DEBUG)
;
;			; CONTINUED ON NEXT PAGE (UNLESS DEBUG)
;
;
; HERE TO REJECT THIS LCB (R3 IS SET UP)
;
12$:
.IF NE,DEBUG
	TRACE	TRCMDF,R3	;RECORD SILO POINTER
	TRACE	TRCMDF,(R3)	; AND ITS STATUS BITS
.ENDC ;.IF NE,DEBUG
;
; HERE WHEN WE ARE DONE WITH THIS LCB
;
13$:	ADD	#2,R5		;INCREMENT LINE NUMBER * 2
	CMP	#<NLINES*2>,R5	;DONE ALL THE LINES?
	BNE	11$		;NO, DO THE REST.
;
; HERE WHEN ALL THE SILOS HAVE BEEN EMPTIED.
;
	MOV	(SP)+,R5	;RESTORE R5
	MOV	(SP)+,R4	; AND R4
	MOV	(SP)+,R3	; AND R3
	MOV	(SP)+,R2	; AND R2
	RTI			;EXIT THE INTERRUPT
;
;
; DUP11 TRANSMIT INTERRUPTS.  SHOULD NOT HAPPEN SINCE THE KMC11
;  PROCESSES ALL DATA FLAGS.
;
DQBINT:	STOPCD	UQX		;UNKNOWN DUP11 TRANSMIT INTERRUPT
;
;
; INTERRUPT CODE FOR KMC11 "FUNCTION DONE" AND "ERROR".
;
MDBINT:	MOV	R0,-(SP)	;SAVE R0
	MOV	R1,-(SP)	; AND R1
	MOV	R2,-(SP)	; AND R2
	MOV	R3,-(SP)	; AND R3
	MOV	R4,-(SP)	; AND R4
	MOV	R5,-(SP)	; AND R5
;
; HERE TO CHECK ALL LCB'S FOR COMPLETION OR ERROR.
;
	CLR	R5		;LINE NUMBER * 2
;
; HERE TO CHECK THE NEXT LCB
;
11$:	MOV	DQLCB(R5),R4	;POINT TO LCB
	BEQ	18$		;NO LCB, DO NOTHING.
	TRACE	TRCMDF,R4	;NOTE OUTPUT INTERRUPT FOR THIS LCB
	MOV	LB.SLA(R4),R3	;POINT TO DUP11 CSR
	BIT	#LS.CMP!LS.KLC,(R4) ;FUNCTION COMPLETE?
	BEQ	18$		;NO, CHECK NEXT LCB
	TRACE	TRCMDF,(R4)	;RECORD LCB STATUS ON INTERRUPT
	BIT	#LS.KLC,(R4)	;COMPLETION OF KILL REQUEST?
	BEQ	12$		;NO.  CHECK FOR WRITE AND READ.
	BIT	#LS.MDE,(R4)	;YES, HAVE WE HAD AN ERROR?
	BEQ	16$		;NO.  AWAKEN BSC TASK IF REQ.
	BIC	#LS.MDE,(R4)	;YES, CLEAR KMC11 ERROR FLAG
	BIS	#LS.ERR,(R4)	;SET SUMMARY ERROR FLAG
	BR	16$		;AWAKEN BSC TASK IF REQ.
;
;
; HERE IF NOT COMPLETION OF A KILL REQUEST
;
12$:	BIT	#LS.XGO!LS.XRN,(R4) ;COMPLETION OF A WRITE?
	BEQ	14$		;NO.
	BIC	#UP.DIE,UP.RSR(R3) ;YES, DISABLE MODEM INTERRUPTS
	BIC	#UP.RTS,UP.RSR(R3) ;DROP RTS
	CLR	LB.DEW(R4)	;NOT WAITING FOR MODEM SIGNALS
	BIT	#LS.MDE,(R4)	;HAVE WE HAD AN ERROR?
	BEQ	13$		;NO.
	INC	LB.SE5(R4)	;YES, "TRANSMITTER NOT FAST ENOUGH"
	JSR	PC,DQERRR	;RECORD DUP11 REGISTERS
	BIC	#LS.ACT!LS.MDE,(R4) ;DONT START A READ FOLLOWING WRITE
	CLR	LB.CCH(R4)	;THERE IS NO CURRENT CHUNK
13$:	BIC	#LS.XGO!LS.XRN!LS.CMP,(R4) ;CLEAR COMPLETED WRITE FLAGS
	BIT	#LS.ACT,(R4)	;IS DUP11 STILL ACTIVE?
	BEQ	16$		;NO, LEAVE MODEM INTS DISABLED.
	BIS	#UP.DIE,UP.RSR(R3) ;YES, ENABLE MODEM INTS
	BR	16$		;AWAKEN BSC TASK IF REQUESTED.
;
; HERE IF NOT COMPLETION OF KILL OR WRITE
;
14$:	BIT	#LS.RGO!LS.RRN,(R4) ;RECEIVER RUNNING?
	BEQ	15$		;NO.
	BIC	#LS.RGO!LS.RRN!LS.CMP!LS.MDE,(R4) ;YES, CLEAR THE FLAGS
	BIC	#UP.DIE,UP.RSR(R3) ;CLEAR MODEM INTERRUPT ENABLE
	CLR	LB.CCH(R4)	;THERE IS NO CURRENT CHUNK
	MOV	LB.SLO(R4),R0	;POINT TO CURRENT SILO
	BIT	#MDSLFO,MDSLFG(R0) ;HAS IT OVERFLOWED?
	BEQ	20$		;NO.
	INC	LB.SE7(R4)	;YES, COUNT SILO OVERFLOWS.
20$:	INC	LB.SE4(R4)	;MUST BE AN ERROR...
	JSR	PC,DQERRR	; SINCE THAT IS ONLY REASON FOR STOPPING
	BR	16$		;AWAKEN BSC TASK IF REQUESTED
;
; HERE IF NOT COMPLETION OF KILL, WRITE OR READ.
;
15$:	STOPCD	KCQ		;KMC11 COMPLETE ON AN IDLE LCB
;
;
; HERE WHEN LINE HAS MADE A TRANSITION.
;
16$:	MOV	LB.TC1(R4),R0	;POINT TO TCB OF BSC TASK
	BIT	#EBINTR,(R0)	;DOES IT WANT TO BE AWAKENED?
	BEQ	17$		;NO.
	BIC	#EBINTR!EBWAIT,(R0) ;YES, AWAKEN IT.
17$:
;
; HERE WHEN WE ARE DONE WITH THIS LCB.
;
18$:
.IF NE,DEBUG
	TST	R4		;HAVE WE AN LCB?
	BEQ	19$		;NO, DONT TRACE
	TRACE	TRCMDF,(R4)	;YES, TRACE NEW STATE OF LCB
19$:
.ENDC ;.IF NE,DEBUG
	ADD	#2,R5		;INCREMENT LINE NUMBER * 2
	CMP	#<NLINES*2>,R5	;DONE LAST LINE?
	BNE	11$		;NO, DO THE REST.
;
; HERE WHEN WE HAVE DONE A PASS AND ALL LINES HAVE NO ACTION.
;
	MOV	(SP)+,R5	;RESTORE R5
	MOV	(SP)+,R4	; AND R4
	MOV	(SP)+,R3	; AND R3
	MOV	(SP)+,R2	; AND R2
	MOV	(SP)+,R1	; AND R1
	MOV	(SP)+,R0	; AND R0
	RTI			;EXIT THE INTERRUPT.
;
;
; SUBROUTINE TO STOP THE TRANSMITTER
;
; R4 POINTS TO THE LCB
; R3 POINTS TO THE DUP11 CSR
;
XMTSTP:	TRACE	TRCDQF,R4	;TRACE DUP11 TRANSMITTER STOP
	BIC	#UP.RTS,UP.RSR(R3) ;DROP REQUEST TO SEND
	BIS	#LS.KIL,(R4)	;TELL KMC11 TO STOP
	JSR	PC,MDACTV	;AWAKEN KMC11
	CLR	LB.DEW(R4)	;NOT WAITING TO ENABLE MODEM
	CLC			;INDICATE NO ERROR
	RTS	PC		;RETURN.
;
;
; SUBROUTINE TO PROCESS A DATA SET FLAG.
;
;  R0 = DATASET FLAGS
;  R3 = DUP11 CSR
;
; ON RETURN, R3 IS DESTROYED.
;
RCVDSF:	INC	LB.DIC(R4)	;COUNT DATASET INTERRUPTS
	MOV	R0,LB.DIS(R4)	;RECORD LAST MODEM INTERRUPT STATUS
	TST	LB.DEW(R4)	;WAITING FOR DATASET ENABLE?
	BNE	13$		;YES, IGNORE MODEM SIGNAL.
	BIT	#LS.ACT,(R4)	;IS THE DUP11 ACTIVE?
	BEQ	13$		;NO, IGNORE THE MODEM SIGNALS
	MOV	R0,LB.DIP(R4)	;YES, RECORD LAST MODEM SIGNALS PROCESSED
	BIT	#LS.XGO,(R4)	;WAITING TO START XMITTER?
	BEQ	11$		;NO.
	JSR	PC,14$		;YES, CHECK FOR CLEAR-TO-SEND.
11$:	BIT	#LS.XRN,(R4)	;RUNNING THE TRANSMITTER?
	BEQ	12$		;NO.
	JSR	PC,18$		;YES, BE SURE CTS STILL UP
12$:	BIT	#LS.RRN,(R4)	;RUNNING RECEIVER?
	BEQ	13$		;NO.
	JSR	PC,20$		;YES, WORRY ABOUT CARRIER FAILURE.
13$:	RTS	PC		;RETURN TO CALLER.
;
;
; THREE SUBROUTINES TO PROCESS DATA SET FLAGS.  THEY ARE CALLED
;  BASED ON THE CURRENT STATE OF THE DUP11.
;
; R0 = MODEM STATUS FLAGS, FROM THE DUP11.
; R3 = POINTER TO DUP11 CSR
;
; HERE IF WE ARE WAITING TO START THE TRANSMITTER
;
14$:	BIT	#UP.CTS,R0	;HAVE WE CLEAR-TO-SEND?
	BEQ	17$		;NO, WAIT FOR IT.
	BIC	#LS.XGO,(R4)	;NO LONGER WAITING TO START TRANSMITTER
	BIT	#LS.RGO,(R4)	;WAITING TO START RECEIVER?
	BEQ	15$		;NO.
	BIC	#LS.RGO!LS.CAR,(R4) ;YES, WAITING NO LONGER.
	BIC	#UP.CAR,LB.DIP(R4) ;PROCESS CARRIER NEXT TIME WE SEE IT
	BIS	#LS.XRN!LS.RRN,(R4) ;START XMIT, FOLLOW WITH RCV
	BR	16$		;INFORM THE KMC11
;
; HERE IF THE WRITE IS NOT TO BE FOLLOWED BY A READ
;
15$:	BIS	#LS.XRN,(R4)	;NOW RUNNING TRANSMITTER
16$:	BIS	#UP.SND,UP.XSR(R3) ;ENABLE THE DUP11 FOR SENDING
	MOV	#UP.XSM!EBCPAD,UP.XBF(R3) ;FIRST CHAR IS PAD
	JSR	PC,MDACTV	;INFORM THE KMC11
17$:	RTS	PC		;ALL DONE.
;
; HERE IF WE ARE RUNNING THE TRANSMITTER
;
18$:	BIT	#UP.CTS,R0	;IS CLEAR-TO-SEND STILL UP?
	BNE	19$		;YES, ALL OK.
	INC	LB.SE6(R4)	;NO, NOTE CLEAR-TO-SEND FAILURE
	JSR	PC,DQERRR	;NOTE ERROR
	JSR	PC,XMTSTP	;STOP THE TRANSMITTER
19$:	RTS	PC		;ALL DONE.
;
; HERE IF THE RECEIVER IS RUNNING.
;
20$:	BIT	#UP.CAR,R0	;IS CARRIER UP?
	BNE	21$		;YES.
	BIT	#LS.CAR,(R4)	;NO, HAVE WE SEEN CARRIER YET?
	BEQ	22$		;NO, DONT WORRY ABOUT IT.
	JSR	PC,RCVSTP	;YES, STOP THE RECEIVER
	BR	22$		;ALL DONE.
;
; HERE IF CARRIER IS UP
;
21$:	BIS	#LS.CAR,(R4)	;MARK WE HAVE SEEN CARRIER
22$:	RTS	PC		;RETURN.
;
;
; SUBROUTINE TO SEE IF THE KMC11 HAS READ ANY CHARACTERS
;  RECENTLY.  ALL CHARACTERS UP TO CHLEN HAVE BEEN PROCESSED.
;
; R5 POINTS TO THE TCB, WHICH MUST HAVE EBWAIT SET.
; R4 POINTS TO THE CURRENT CHUNK.  
;
; ON RETURN:
;
;	C SET: SOME CHARACTERS WERE FOUND IN THE SILO.
;		IF R4 UNDISTURBED, THEY ARE IN CURRENT CHUNK
;		  (THE LENGTH FIELD HAS BEEN UPDATED)
;		IF R4 CLEAR, GET A NEW CHUNK TO PROCESS.
;
;	C CLEAR: THE SILO IS EMPTY.  IT IS NOW
;		SET TO RESTART THE BSC TASK ON THE NEXT CHARACTER.
;
DQINWQ:	MOV	R0,-(SP)	;SAVE R0
	MOV	R3,-(SP)	; AND R3
	MOV	R2,-(SP)	; AND R2
	MOV	R4,R0		;POINT R0 TO CURRENT CHUNK
	MOV	TCLCB(R5),R4	;POINT TO LCB
11$:	MFPS	-(SP)		;SAVE INTERRUPT LEVEL
	MTPS	#MD.LVL*40	;DISABLE KMC11 INTERRUPTS
	BIT	#LS.RSE,(R4)	;HAS THE RECEIVE SILO BEEN
				; EMPTIED SINCE LAST CALL?
	BNE	13$		;YES, BE SURE PROCESSING IS DONE.
	CMP	R0,LB.CCH(R4)	;NO, IS THIS STILL THE CURRENT CHUNK?
	BNE	12$		;NO.  DISCARD IT AND GET ANOTHER.
	MOV	DSPCLK,R3	;YES, GET DISPATCHER CLOCK
	MOV	JIFCLK,R2	; AND JIFFIE CLOCK
	XOR	R3,R2		;FORM LOGICAL DIFFERENCE
	BIT	#177774,R2	;HAVE MORE THAN THREE TICKS PASSED?
	BNE	17$		;YES, MAKE BSC TASK WAIT.
	MOV	LB.SLO(R4),R3	;NO, POINT R3 TO SILO
	MOV	MDSLPT(R3),R2	;GET CURRENT ADDRESS FROM SILO
	SUB	LB.CCD(R4),R2	;SUBTRACT INITIAL ADDRESS
	CMP	R2,@LB.CCR(R4)	;HAS COUNT CHANGED?
	BNE	14$		;YES, PROCESS CHARACTERS
	BR	16$		;NO, TELL CALLER TO WAIT
;
;
; HERE TO ABANDON THIS CHUNK BECAUSE IT IS NO LONGER
;  BEING FILLED.
;
12$:	MTPS	(SP)+		;ENABLE INTERRUPTS
	TRACE	TRCMDF,R4	;TRACE DECISION TO ABANDON OLD CHUNK
	MOV	R1,-(SP)	;SAVE R1 
	MOV	TCIDLE,R1	;GIVE CURRENT CHUNK TO IDLE TASK
	JSR	PC,QUECHK	; TO FREE.
	MOV	(SP)+,R1	;RESTORE R1
	CLR	R0		;NO MORE OLD CHUNK
	BR	15$		;TELL CALLER TO RECYCLE
;
; HERE TO TELL CALLER TO RECYCLE BECAUSE THE SILO HAS BEEN
;  DRAINED SINCE THE LAST TIME WE CAME THROUGH HERE.  IF WE
;  DO NOT DO THIS, THE SILO MIGHT HAVE BEEN DRAINED BETWEEN
;  THE CALLER'S LAST TEST AND OUR TESTS, SO MAKE CALLER
;  DO HIS TESTS ONE MORE TIME.
;
13$:	BIC	#LS.RSE,(R4)	;CLEAR INTERRUPT FLAG
	MTPS	(SP)+		;RESTORE INTERRUPTS
	BR	15$		;TELL CALLER TO RECYCLE
;
;
; HERE TO EMPTY THE SILO AND TELL CALLER TO PROCESS CHARS
;
14$:	TRACE	TRCMDF,R4	;TRACE DECISION TO EMPTY SILO
	JSR	PC,MDSLEM	;EMPTY THE SILO
	MTPS	(SP)+		;ENABLE INTERRUPTS
;
; HERE TO RETURN, TELLING CALLER NOT TO WAIT.
;
15$:	MOV	(SP)+,R2	;RESTORE R2
	MOV	(SP)+,R3	; AND R3
	MOV	R0,R4		;RESTORE R4
	MOV	(SP)+,R0	; AND R0
	SEC			;FLAG MORE PROCESSING REQUIRED
	RTS	PC		;RETURN.
;
;
; HERE IF THE SILO IS STILL EMPTY.  ARRANGE TO AWAKEN THIS TASK
;  WHEN THE NEXT CHARACTER IS STORED.
;
16$:	BIS	#LS.CIE,(R4)	;SET WAKEUP FLAG
	BIS	#MDSLFE,MDSLFG(R3) ;MAKE THIS SILO INTERRUPT
				; ON NEXT CHARACTER
;
; COME HERE TO WAIT THE TASK.  FROM ABOVE, WE WILL AWAKEN
;  ON THE NEXT CHARACTER.  IF THE LINE IS RUNNING FAST,
;  WE BYPASS THE ABOVE CODE AND JUST REQUIRE THE BSC TASK
;  TO WAIT UNTIL EITHER THE CHUNK FILLS OR ITS TIMER
;  EXPIRES.
;
17$:	TRACE	TRCMDF,R4	;TRACE DECISION TO WAIT THE TASK.
	MTPS	(SP)+		;RESTORE INTERRUPT LEVEL
	MOV	(SP)+,R2	;RESTORE R2
	MOV	(SP)+,R3	;RESTORE R3
	MOV	R0,R4		;RESTORE R4
	MOV	(SP)+,R0	;RESTORE R0
	CLC			;FLAG NO CHARACTERS
	RTS	PC		;RETURN.
;
;
; SUBROUTINE TO EMPTY THE KMC11'S SILO.
;
; THIS SUBROUTINE IS CALLED FROM INPUT INTERRUPT
;  AND IF THE BSC TASK NEEDS MORE CHARACTERS TO
;  AVOID GOING IDLE.
;
; INTERRUPTS ARE MASKED OFF BY THE CALLER OF THIS SUBROUTINE.
;
; R4 = LCB POINTER
; R3 = SILO POINTER (FROM LB.SLO(R4)).
;  DESTROYS R2
;
MDSLEM:	TRACE	TRCMDF,MDSLFG(R3) ;TRACE SILO FLAG BITS
.IF NE,DEBUG
	BIT	#MDSLFE,MDSLFG(R3) ;IS THIS SILO INTERRUPTABLE?
	BEQ	11$		;NO.
	STOPCD	DBG		;YES, WE SHOULD NOT BE PROCESSING IT.
11$:	BIT	#LS.RRN,(R4)	;IS LINE DOING INPUT?
	BNE	12$		;YES.
	STOPCD	DBG		;NO, SHOULDN'T BE HERE.
12$:
.ENDC ;.IF NE,DEBUG
	MOV	R0,-(SP)	;SAVE R0
	MOV	R1,-(SP)	; AND R1
	BIT	#MDSLFW,MDSLFG(R3) ;REACHED WARNING LEVEL YET?
	BEQ	MDSLE1		;NO, DONT SWITCH SILOS
	TRACE	TRCMDF,MDSLCC(R3) ;YES, TRACE DEPARTURE OF CHUNK
	MOV	R4,R2		;BUILD POINTER TO OTHER SILO
	ADD	#LB.SO1,R2
	CMP	R2,R3		;IS THIS SILO 1?
	BNE	13$		;NO.
	ADD	#LB.SO2-LB.SO1,R2 ;YES, MAKE R2 POINT TO SILO 2
13$:
;
; 			; CONTINUED ON NEXT PAGE
;
;
; GET A CHUNK TO HOLD NEW SILO DATA
;
	MOV	CHFST,R0	;GET ANOTHER CHUNK.
	CMP	R0,CHLST	;IS THERE ONLY ONE CHUNK LEFT?
	BEQ	14$		;YES, WE ARE OUT OF CHUNKS
	MOV	(R0),R1		;NO, GET NEXT CHUNK
	BIC	#1,R1		;CLEAR "FREE" FLAG
	MOV	R1,CHFST	;NEXT IS NOW FIRST CHUNK
	CLR	(R0)		;CLEAR "FREE" BIT
	CLR	2(R1)		;CLEAR NEW FIRST CHUNK'S BACK POINTER
	DEC	CHFREC		;ONE FEWER FREE CHUNK
	TRACE	TRCCNK,R0	;TRACE CHUNK MANIPULATION
.IF NE,CHOWNR
	MOV	PC,R1		;CHUNK OWNER IS HERE
	JSR	PC,CHOWNG	;RECORD CHUNK OWNER
.ENDC ;.IF NE,CHOWNR
	JSR	PC,MDSLOI	;INITIALIZE THE NEW SILO
	BR	MDSLE1		;PROCESS DATA IN OLD SILO
;
; HERE IF WE RUN OUT OF CHUNKS.  THIS IS NOT A FATAL ERROR IF
;  THE BSC TASK SEES THE END OF THE BISYNC MESSAGE BEFORE
;  NEEDING THE DATA THAT WAS LOST.
;
14$:	INC	LB.CHD(R4)	;RECORD EXHAUSTION OF CHUNKS
	MOV	LB.SLA(R4),R3	;POINT TO DUP11 CSR
	JSR	PC,RCVSTP	;STOP THE RECEIVER
	BR	MDSLEX		;EXIT THE SUBROUTINE
;
;
; HERE TO GIVE THE CHARACTERS IN THE SILO TO THE TASK.
;  THIS IS DONE BY UPDATING THE LENGTH FIELD OF THE CURRENT
;  CHUNK.
;
; R3 = POINTER TO SILO.  LB.SLO(R4) MAY POINT TO THE OTHER SILO.
;
MDSLE1:	MOV	MDSLCC(R3),R2	;POINT TO THIS SILO'S CHUNK
	MOV	R2,R0		;COPY POINTER
	ADD	#CHDAT,R0	;MAKE POINTER TO DATA AREA
	SUB	MDSLPT(R3),R0	;COMPUTE NEW FILL LEVEL
	NEG	R0		;IN POSITIVE FORM
	MOV	R0,CHLEN(R2)	;STORE NEW LENGTH
	TRACE	TRCMDF,R0	;TRACE NEW LENGTH
	BIT	#MDSLFW,MDSLFG(R3) ;ARE WE AT WARNING POINT?
	BEQ	12$		;NO, DONT RECORD STATISTIC.
	MOV	MDSLPT(R3),R0	;YES, GET CURRENT FILL POINT
				; (NOTE THAT THIS MAY STILL
				;   BE THE CURRENT SILO, BUT
				;   THIS IS UNLIKELY)
	SUB	MDSLPW(R3),R0	;SUBTRACT WARNING POINT
	CMP	R0,LB.MDU(R4)	;GREATER THAN MAX NEEDED BEFORE?
	BLO	12$		;NO.
	MOV	R0,LB.MDU(R4)	;YES, STORE NEW MAX DEPTH
12$:	CMP	R3,LB.SLO(R4)	;ARE WE CHANGING SILOS?
	BEQ	MDSLEX		;NO.
	ADD	CHLEN(R2),LB.CRD(R4) ;YES, ACCUMULATE CHARS READ
	CMP	LB.CRD(R4),#DQRLMT ;TOO MANY CHARACTERS IN MESSAGE?
	BLE	MDSLEX		;NO, LOOK FOR ANOTHER CHARACTER.
	MOV	LB.SLA(R4),R3	;YES, POINT TO DUP11 CSR
	JSR	PC,RCVSTP	;STOP THE RECEIVER
;
; CONTINUED ON NEXT PAGE
;
;
; HERE WHEN THE SILO HAS BEEN EMPTIED, OR ON AN ERROR.
;
MDSLEX:	BIT	#LS.CIE,(R4)	;DOES THE TASK WANT TO BE RESTARTED?
	BEQ	11$		;NO.
	BIC	#LS.CIE,(R4)	;YES, CLEAR FLAG
	MOV	LB.TC1(R4),R0	;POINT TO BSC TCB
	BIT	#EBQCHK,(R0)	;WAITING FOR A CHUNK?
	BEQ	11$		;NO (UNLIKELY)
	BIC	#EBQCHK!EBWAIT,(R0) ;YES, UNWAIT THE TASK
11$:	MOV	(SP)+,R1	;RESTORE R1
	MOV	(SP)+,R0	; AND R0
	RTS	PC		;RETURN.
;
;
; SUBROUTINE TO INTIIALIZE A SILO.
;
; R0 = POINTER TO CHUNK TO HOLD DATA
; R2 = POINTER TO SILO.
; R4 = LCB POINTER
;
MDSLOI:	MOV	R0,LB.CCH(R4)	;SILO CHUNK IS NOW CURRENT
	MOV	LB.TC1(R4),R1	;GET TCB OF RECEIVE CHUNK HANDLER
	JSR	PC,QUECHK	;SEND HIM THE CHUNK
	ADD	#CHLEN,R0	;POINT TO LENGTH FIELD
	MOV	R0,LB.CCR(R4)	;STORE FOR NEXT INPUT INTERRUPT
	ADD	#CHDAT-CHLEN,R0	;POINT TO DATA FIELD
	MOV	R0,LB.CCD(R4)	;STORE FOR NEXT INPUT INTERRUPT
	MOV	R0,MDSLPT(R2)	;STORE NEW INITIAL DATA POINTER
	ADD	#CHDATL,R0	;POINT TO END OF DATA AREA
	MOV	R0,MDSLPL(R2)	;STORE FOR OVERFLOW CHECKING
	SUB	LB.MDS(R4),R0	;BACK UP FOR LATENCY
	MOV	R0,MDSLPW(R2)	;STORE AS WARNING LEVEL
	MOV	LB.CCH(R4),MDSLCC(R2) ;COPY POINTER TO CURRENT CHUNK
	CLR	MDSLFG(R2)	;CLEAR SILO FLAGS
	MOV	R2,LB.SLO(R4)	;WE HAVE A NEW SILO
	TRACE	TRCMDF,LB.CCH(R4) ;TRACE NEW "CURRENT CHUNK"
	RTS	PC		;RETURN TO CALLER
;
;
; SUBROUTINE TO KILL ANY KMC11/DUP11 OPERATIONS.  
;
; R4 = LCB POINTER
; R5 = POINTER TO BSC TCB
;
; DESTROYS R0, R1 AND R3
;
DQKILL:	TRACE	TRCDQF,R4	;TRACE ENTRY TO DQKILL
	MOV	LB.SLA(R4),R3	;POINT TO CSR
;
; CONSIDER STOPPING THE TRANSMITTER
;
	BIT	#LS.XGO!LS.XRN,(R4) ;TRANSMITTER RUNNING?
	BEQ	12$		;NO.
	JSR	PC,XMTSTP	;YES, BEGIN STOPPING THE TRANSMITTER
	MOV	#MDMXTT,R0	;WAIT A SHORT WHILE FOR KILL
11$:	BIT	#LS.KLC,(R4)	;HAS THE KILL COMPLETED?
	BNE	12$		;YES.
	SOB	R0,11$		;NO, WAIT A WHILE FOR IT
;
; HERE WHEN THE TRANSMITTER HAS BEEN KILLED, OR IF IT IS
;  NOT RUNNING.
; CONSIDER STOPPING THE RECEIVER
;
12$:	BIT	#LS.RGO!LS.RRN,(R4) ;IS RECEIVER RUNNING?
	BEQ	15$		;NO.
	JSR	PC,RCVSTP	;MAYBE, BEGIN STOPPING THE RECEIVER
	MOV	#MDMXTT,R0	;TIME TO WAIT FOR KILL
13$:	BIT	#LS.KLC,(R4)	;IS THE RECEIVER KILL COMPLETE?
	BNE	14$		;YES, DONT WAIT FOR IT.
	SOB	R0,13$		;NO, WAIT FOR IT.
;
; HERE WHEN THE RECEIVER HAS BEEN KILLED.
;
14$:	CLR	LB.CCH(R4)	;THERE IS NO CURRENT CHUNK
.IF NE,DEBUG
	MOV	#-1,LB.SLO(R4)	;THE SILO IS GONE
.ENDC ;.IF NE,DEBUG
;
;			; CONTINUED ON NEXT PAGE
;
;
; HERE WHEN THE LINE HAS BEEN KILLED, OR WAS NOT RUNNING AT ALL.
;
15$:	MFPS	-(SP)		;SAVE INTERRUPT LEVEL
	MTPS	#BR7		;DISABLE INTERRUPTS
	BIC	#UP.DIE,UP.RSR(R3) ;DISABLE DATASET INTERRUPTS
				; (AVOID HARDWARE RACE CONDITION
				; IN 11/34 BY DISABLING INTS)
	MTPS	(SP)+		;RESTORE INTERRUPTS
16$:	JSR	PC,DEQCHK	;ANY CHUNKS IN RECEIVER QUEUE?
	BCS	17$		;NO.
	MOV	TCIDLE,R1	;YES, FREE THEM
	JSR	PC,QUECHK	; BY SENDING TO BACKGROUND TASK
	BR	16$		;BE SURE WE'VE GOT THEM ALL.
;
; HERE WHEN THE KMC11/DUP11 HAS BEEN KILLED.
;
17$:	BIT	#LS.ACT!LS.CMP,(R4) ;WAS THE KMC11 ACTIVE?
	BEQ	19$		;NO, THIS WAS ALL FOR NOTHING.
	BIT	#LS.KLC,(R4)	;YES, HAS THE KILL COMPLETED?
	BNE	18$		;YES.
	STOPCD	KKF		;NO, KMC11 KILL FAILED.
;
; HERE WHEN THE KILL IS COMPLETE.  CLEAR ALL RELEVENT LCB
;  STATUS BITS.
;
18$:	BIC	#LS.ACT!LS.CMP!LS.KIL!LS.KLC,(R4)
				;THE KMC11/DUP11 IS NO LONGER ACTIVE
19$:	TRACE	TRCDQF,R4	;TRACE COMPLETION OF DQKILL
	RTS	PC		;RETURN.
;
;
; SUBROUTINE TO SIGNAL THE KMC11 THAT THERE IS SOME LCB
;  ACTIVITY WHICH IT SHOULD NOTICE.
;
MDACTV:	TRACE	TRCMDF,R4	;TRACE ENTRY TO MDACTV
	TRACE	TRCMDF,(R4)	;NOTE LCB STATUS
	MOV	R3,-(SP)	;SAVE R3
	MOV	LB.MD(R4),R3	;POINT TO KMC11 TABLE
	MOV	R0,-(SP)	;SAVE R0
	MOV	R1,-(SP)	; AND R1
	MOV	R2,-(SP)	; AND R2
	MOV	#MDMXTT,R2	;WAIT THIS LONG FOR KMC11 TO RESPOND
11$:	MOV	MDFGE(R3),R0	;GET 11-FLAGS
	MOV	MDFGK(R3),R1	; AND KMC FLAGS
	XOR	R1,R0		;XOR 11-FLAGS WITH KMC-FLAGS
	BIT	#MDFEA,R0	;IS OLD ACTIVE FLAG STILL ON?
	BEQ	12$		;NO.
	SOB	R2,11$		;YES, WAIT FOR KMC11 TO FOLLOW
	STOPCD	KNA		;KMC11 NOT FOLLOWING ACTIVE FLAG
;
12$:
.IF NE,DEBUG
	SUB	#MDMXTT,R2	;COMPUTE NUMBER OF TIMES
	NEG	R2		; THROUGH THE LOOP
	CMP	R2,MDMUTT	;MORE THAN PREVIOUS MAX?
	BLE	13$		;NO.
	MOV	R2,MDMUTT	;YES, STORE NEW MAX
13$:
.ENDC ;.IF NE,DEBUG
	BIT	#MDFKR,MDFGK(R3) ;IS KMC11 STILL RUNNING?
	BNE	14$		;YES.
	STOPCD	KNR		;NO, KMC11 NOT RUNNING.
;
; HERE WHEN THE KMC11 HAS COMPLETED THE LAST OPERATION AND IS
;  RUNNING.
;
14$:	MOV	(SP)+,R2	;RESTORE R2
	MOV	(SP)+,R1	;RESTORE R1
	MOV	#MDFEA,R0	;GET BIT TO XOR
	XOR	R0,MDFGE(R3)	;COMPLEMENT ACTIVE FLAG
	MOV	(SP)+,R0	;RESTORE R0
	MOV	(SP)+,R3	; AND R3
	RTS	PC		;DONE.
;
;
; THREE SUBROUTINES TO INTERFACE TO THE DL10 TASK.  THESE SENSE
;  SET AND CLEAR THE MODEM SIGNALS DTR AND DSR.
;
; SUBROUTINE TO CLEAR DTR
;
; R0 = LCB ADDRESS
;
DQDTR0:	MOV	LB.SLA(R0),R0	;POINT TO CSR
	BIC	#UP.DTR,UP.RSR(R0) ;CLEAR DTR
	RTS	PC		;RETURN.
;
; SUBROUTINE TO SET DTR
;
DQDTR1:	MOV	LB.SLA(R0),R0	;POINT TO CSR
	BIS	#UP.DTR,UP.RSR(R0) ;SET DTR
	RTS	PC		;RETURN.
;
; SUBROUTINE TO RETURN VALUES OF DTR AND DSR.
;
; R0 = LCB ADDRESS
; R1 BITS 1 AND 2 ARE 0.
;
; ON RETURN:
;
;	BIT 1 OF R1 = DTR
;	BIT 2 OF R1 = DSR
;	 R1 IS OTHERWISE UNDISTURBED.
;
DQMDMS:	MOV	LB.SLA(R0),R0	;POINT TO CSR
	BIT	#UP.DTR,UP.RSR(R0) ;IS DTR SET?
	BEQ	11$		;NO.
	BIS	#B1,R1		;YES, SET FLAG IN R1
11$:	BIT	#UP.DSR,UP.RSR(R0) ;IS DSR SET?
	BEQ	12$		;NO.
	BIS	#B2,R1		;YES, SET FLAG IN R1
12$:	RTS	PC		;RETURN.
;
;
; SUBROUTINE TO INTERFACE WITH THE TRAP HANDLER.  ON A STOP CODE
;  THIS SUBROUTINE IS CALLED TO STORE THE STATUS OF THE DUP11
;  IN THE LCB FOR POST-MORTUM DEBUGGING.
;
;  R5 DOES NOT POINT TO A TCB, BUT IT MUST NOT BE DESTROYED.
;
; R4 = LCB ADDRESS
;
.IF NE,DEBUG
TRAPDQ:	MOV	LB.SLA(R4),R3	;GET HARDWARE ADDRESS
	MOV	UP.RSR(R3),LB.RG0(R4) ;STORE RECEIVER STATUS REGISTER
	MOV	UP.RBF(R3),LB.RG1(R4) ;STORE RECEIVER BUFFER
	MOV	UP.XSR(R3),LB.RG2(R4) ;STORE TRANSMIT STATUS REGISTER
	MOV	UP.XBF(R3),LB.RG3(R4) ;STORE TRANSMIT BUFFER
	RTS	PC		;RETURN.
;
.ENDC ;.IF NE,DEBUG
;
; SUBROUTINE TO STOP THE KMC11S ON A FATAL ERROR.
;
TRAPMD:	CLR	R1		;KMC11 NUMBER
	MOV	#MDTBL,R3	;POINTER TO KMC11 TABLE
11$:	BIC	#MDFER,MDFGE(R3) ;CLEAR "11-RUNNING"
	ADD	#MDTLN,R3	;POINT TO NEXT KMC11 TABLE
	INC	R1		;INCREMENT KMC11 NUMBER
	CMP	#<NLINES/4>,R1	;DONE ALL KMC11S?
	BNE	11$		;NO, DO THE REST.
	RTS	PC		;RETURN TO TRAP HANDLER.
;
;
; SUBROUTINE TO CHECK ON THE DUP11S ONCE A JIFFIE
;  WE MUST COUNT THE CLEAR-TO-SEND DELAY AND
;  COMPENSATE FOR IMPROPER DUP11 JUMPERS WHICH
;  WILL PREVENT THE CARRIER SIGNAL FROM CAUSING
;  AN INTERRUPT.
;
DSPDQT:	MOV	R0,-(SP)	;SAVE R0
	MOV	R1,-(SP)	; AND R1
	MOV	R2,-(SP)	; AND R2
	MOV	R3,-(SP)	; AND R3
	MOV	R4,-(SP)	; AND R4
	CLR	R1		;R1 IS DUP11 NUMBER
11$:	MOV	DQLCB(R1),R4	;POINT TO LCB
	BEQ	15$		;NO LCB FOR THIS LINE
	MFPS	-(SP)		;YES, SAVE INTERRUPT LEVEL
	MTPS	#BR7		;DISABLE INTERRUPTS
	TST	LB.DEW(R4)	;WAITING TO SET MODEM ENABLE?
	BEQ	12$		;NO.
	DEC	LB.DEW(R4)	;YES, WAITED LONG ENOUGH?
	BNE	14$		;NO, WAIT UNTIL NEXT TIME
12$:	MOV	LB.SLA(R4),R3	;POINT TO CSR
	MOV	UP.RSR(R3),R0	;GET MODEM STATUS BITS
	BIT	#UP.DIE,R0	;ARE MODEM INTERRUPTS ENABLED?
	BEQ	14$		;NO, DONT CALL SUBROUTINE.
	BIT	#UP.DCA!UP.DCB,R0 ;ARE DATASET CHANGE FLAGS SET?
	BNE	13$		;YES, PROCESS ANY POSSIBLE CHANGES
	MOV	LB.DIP(R4),R2	;GET LAST MODEM SIGNALS PROCESSED
	XOR	R0,R2		;CHECK FOR ANY CHANGES IN SIGNALS
	BIT	#UP.CTS!UP.CAR,R2 ;ANY IMPORTANT MODEM SIGNALS CHANGED?
	BEQ	14$		;NO.
13$:	JSR	PC,RCVDSF	;YES, PROCESS ANY MODEM SIGNAL CHANGES
14$:	MTPS	(SP)+		;RESTORE INTERRUPT LEVEL
15$:	ADD	#2,R1		;INCREMENT TO NEXT LINE
	CMP	#NLINES*2,R1	;DONE ALL THE LINES?
	BNE	11$		;NO, DO THE REST
;
;			; CONTINUED ON NEXT PAGE
;
;
; NOW GO THROUGH ALL THE KMC11'S.
;
	CLR	R1		;KMC11 NUMBER
	MOV	#MDTBL,R3	;POINT TO KMC11 TABLE
16$:	BIT	#MDFER,MDFGE(R3) ;IS PDP-11 RUNNING?
	BEQ	18$		;NO, THIS KMC11 NOT IN USE.
	BIT	#MDFKR,MDFGK(R3) ;YES, IS KMC11 RUNNING?
	BEQ	18$		;NO, NO TIMEING YET.
;
; HERE WHEN WE HAVE A RUNNING KMC11.
;
	INC	MDTIC(R3)	;COUNT TOWARDS ONE SECOND
	CMP	#JIFSEC,MDTIC(R3) ;REACHED A SECOND YET?
	BNE	18$		;NO, WAIT UNTIL NEXT TIME
	CLR	MDTIC(R3)	;YES, REINITIALIZE TICK COUNTER
	INC	MDALE(R3)	;COUNT PDP-11 ALIVE COUNTER
	BIT	#7,MDALE(R3)	;HAS IT BEEN EIGHT SECONDS? [2(755)]
	BNE	18$		;NO, CHECK NEXT KMC11
	MOV	MDALK(R3),R0	;YES, GET KMC11 ALIVE COUNTER
	CMP	R0,MDALKS(R3)	;SAME AS LAST TIME?
	BNE	17$		;NO, KMC11 STILL ALIVE.
	STOPCD	KKS		;KMC11 KEEP-ALIVE STOPPED.
;
17$:	MOV	R0,MDALKS(R3)	;SAVE OLD VALUE OF KEEP-ALIVE
;
; HERE WHEN WE ARE DONE WITH THIS KMC11
;
18$:	ADD	#MDTLN,R3	;POINT TO NEXT KMC11 TABLE
	INC	R1		;NUMBER OF KMC11
	CMP	#<NLINES/4>,R1	;DONE LAST KMC11?
	BNE	16$		;NO, DO THE REST.
;
; HERE WHEN WE ARE DONE WITH THIS "TICK".
;
	MOV	(SP)+,R4	;RESTORE R4
	MOV	(SP)+,R3	; AND R3
	MOV	(SP)+,R2	; AND R2
	MOV	(SP)+,R1	; AND R1
	MOV	(SP)+,R0	; AND R0
	RTS	PC		;RETURN TO DISPATCHER.
;
.SBTTL	CONTROL MESSAGES
;
; CONTROL MESSAGES
;
;
; ENQ MESSAGE, FOR BIDDING FOR THE LINE AND ASKING FOR A
;  REPEAT OF THE LAST RESPONSE.
;
ENQMSG:	.BYTE	EBCLPD,EBCSYN,EBCSYN
	.BYTE	EBCSYN,EBCENQ,EBCPAD
ENQLEN=.-ENQMSG
;
; ACK-0 MESSAGE, USED FOR POSITIVE ACKNOWLEDGMENT TO BID AND
;  FOR POSITIVE ACKNOWLEDGE OF EVEN DATA BLOCKS
;
AK0MSG:	.BYTE	EBCLPD,EBCSYN,EBCSYN
	.BYTE	EBCSYN,EBCDLE,EBCAK0
	.BYTE	EBCPAD
AK0LEN=.-AK0MSG
;
; ACK-1 MESSAGE, USED FOR POSITIVE ACKNOWLEDGMENT OF ODD DATA
;  BLOCKS
;
AK1MSG:	.BYTE	EBCLPD,EBCSYN,EBCSYN
	.BYTE	EBCSYN,EBCDLE,EBCAK1
	.BYTE	EBCPAD
AK1LEN=.-AK1MSG
;
; TTD MESSAGE, FOR SOLICITING A NAK BECAUSE DATA IS NOT
;  YET READY.
;
TTDMSG:	.BYTE	EBCLPD,EBCSYN,EBCSYN
	.BYTE	EBCSYN,EBCSTX,EBCENQ
	.BYTE	EBCPAD
TTDLEN=.-TTDMSG
;
; HASP BID SEQUENCE SOH-ENQ FOR BIDDING FOR A LINE.
;
BIDMSG:	.BYTE	EBCLPD,EBCSYN,EBCSYN
	.BYTE	EBCSYN,EBCSOH,EBCENQ
	.BYTE	EBCPAD
BIDLEN=.-BIDMSG
;
;
; EOT MESSAGE, USED TO TERMINATE A MESSAGE SEQUENCE.
;
EOTMSG:	.BYTE	EBCLPD,EBCSYN,EBCSYN
	.BYTE	EBCSYN,EBCSYN,EBCEOT
	.BYTE	EBCPAD,EBCPAD
EOTLEN=.-EOTMSG
;
; NAK MESSAGE, USED TO REQUEST THE RETRANSMISSION OF THE LAST
;  DATA MESSAGE AND TO REFUSE A BID.
;
NAKMSG:	.BYTE	EBCLPD,EBCSYN,EBCSYN
	.BYTE	EBCSYN,EBCNAK,EBCPAD
NAKLEN=.-NAKMSG
;
; WACK MESSAGE, USED TO ACKNOWLEDGE A DATA BLOCK BUT FORCE A WAIT
;  BEFORE THE NEXT DATA BLOCK IS SENT.
;
WAKMSG:	.BYTE	EBCLPD,EBCSYN,EBCSYN
	.BYTE	EBCSYN,EBCDLE,EBCWAK
	.BYTE	EBCPAD
WAKLEN=.-WAKMSG
;
	.EVEN		;BE SURE NEXT SECTION STARTS ON
			; A WORD BOUNDRY.
;