Trailing-Edge
-
PDP-10 Archives
-
BB-J845A-SM
-
source/dup11.p11
There are 2 other files named dup11.p11 in the archive. Click here to see a list.
.SBTTL DUP11 DRIVER
;
; THIS SECTION CONTAINS SUBROUTINES TO DRIVE THE DUP11.
; THESE ARE:
;
; DQINIT INITIALIZE THE DUP11
; DQREAD CONDITION THE DUP11 FOR INPUT
; DQWRIT CONDITION THE DUP11 TO OUTPUT A DATA MESSAGE
; DQCNTL CONDITION THE DUP11 TO OUTPUT A CONTROL MESSAGE
; DQKILL CEASE ANY DUP11 OPERATIONS
;
; THIS SECTION ALSO CONTAINS THE INTERRUPT CODE FOR THE DUP11,
; AND A "ONCE-PER-CLOCK-TICK" SUBROUTINE
; TO PROVIDE DELAYED MODEM CONTROL SINCE A MODEM INTERRUPT
; CANNOT BE CAUSED BY THE PROGRAM.
;
.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
; 4(002) Remove chunk ownership trace in DUP receiver interrupt code
;
;
;
VDUP11=002
;
VEDIT=VEDIT+VDUP11
;
;
;
; 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=3 ;1 = DQ11, 2 = KMC11/DUP11, 3 = DUP11 ALONE
;
;
; INITIALIZATION
;
; R4 = POINTER TO LINE CONTROL BLOCK FOR 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
RTS PC ; AND 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 14$ ;NO MORE CHUNKS
MOV R0,LB.CCH(R4) ;STORE CHUNK ADDRESS
ADD #CHLEN,R0 ;POINT TO LENGTH FIELD
MOV R0,LB.CCR(R4) ;STORE FOR INPUT INTERRUPT ROUTINES
ADD #CHDAT-CHLEN,R0 ;POINT TO DATA FIELD
MOV R0,LB.CCD(R4) ;STORE FOR INPUT INTERRUPT ROUTINES
CLR LB.CRD(R4) ;CLEAR COUNT OF CHARACTERS READ
;
; ; CONTINUED ON NEXT PAGE
;
;
; HERE WHEN EVERYTHING IS READY.
; 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.
;
MOV LB.TC1(R4),R1 ;GET TCB OF BSC TASK
MOV LB.CCH(R4),R0 ;GET CURRENT CHUNK
JSR PC,QUECHK ;SEND CHUNK TO DRIVER WHILE WE FILL IT
MFPS -(SP) ;SAVE CPU PRIORITY LEVEL
MTPS #BR7 ;DISABLE CPU INTERRUPTS
BIS #UP.DIE!UP.RIE!UP.REN,UP.RSR(R3) ;START THE DUP11 NOW
BIS #LS.RRN,(R4) ;RECEIVER IS NOW RUNNING
BIC #UP.CAR,LB.DIP(R4) ;PROCESS CARRIER NEXT TIME WE SEE IT
BIC #LS.CAR,(R4) ;WE HAVE NOT YET SEEN CARRIER
MTPS (SP)+ ;RESTORE CPU PRIORITY
CLC ;FLAG NO ERROR
14$: RTS PC ;AND 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
BIS #UP.SND!UP.XIE,UP.XSR(R3) ;YES, START XMT
MOV #UP.XSM!EBCPAD,UP.XBF(R3)
BIC #LS.XGO,(R4) ;NOT WAITING FOR CTS
BIS #LS.XRN,(R4) ;NOW RUNNING
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 (ANOTHER) 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
BIT #UP.RDN,R0 ;IS RECEIVER DONE?
BEQ 11$ ;NO, CHECK FOR DATASET FLAG
MOV UP.RBF(R3),R1 ;YES, GET CHARACTER
BLT 12$ ;ERROR.
MOVB R1,@LB.CCD(R4) ;STORE BYTE IN CURRENT CHUNK
INC LB.CCD(R4) ;ADVANCE POINTER
INC @LB.CCR(R4) ;INCREMENT LENGTH FIELD OF CHUNK
CMP @LB.CCR(R4),#CHDATL ;IS CHUNK FULL?
BNE 11$ ;NO.
;
;
; WE HAVE FILLED THE CURRENT CHUNK. GET ANOTHER ONE SO WE CAN FILL IT.
;
MOV CHFST,R0 ;GET ANOTHER CHUNK.
CMP R0,CHLST ;IS THERE ONLY ONE CHUNK LEFT?
BEQ 13$ ;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
;[4(002)] MOV PC,R1 ;CHUNK OWNER IS HERE
;[4(002)] JSR PC,CHOWNG ;RECORD CHUNK OWNER
.ENDC ;.IF NE,CHOWNR
MOV R0,LB.CCH(R4) ;IT IS NOW CURRENT
BIC #UP.RIE,UP.RSR(R3) ;DISABLE RECEIVER INTERRUPTS FOR THIS LINE
MTPS #BR4 ;ALLOW XMT AND RCV INTS FROM OTHER LINES
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
ADD #CHDATL,LB.CRD(R4) ;INCREMENT COUNT OF CHARACTERS READ
MTPS #BR7 ;DISABLE INTERRUPTS
BIS #UP.RIE,UP.RSR(R3) ;ALLOW NEW RECEIVER INTERRUPTS ON THIS LINE
CMP LB.CRD(R4),#DQRLMT ;TOO MANY CHARACTERS IN MESSAGE?
BGT 14$ ;YES, SHUT DOWN RECEIVER.
BR RCVTST ;NO, LOOK FOR ANOTHER DONE INTERRUPT
;
;
; HERE IF NOT RECEIVER DONE, OR AFTER PROCESSING RECEIVER DONE.
; (EXCEPT IN LONG RECEIVER DONE PROCESSING, WHICH CHECKS FOR ANOTHER
; DONE FLAG.)
;
11$: BIT #UP.DCA!UP.DCB,LB.RST(R4) ;ANY DATASET FLAGS?
BEQ 15$ ;NO, EXIT THE INTERRUPT.
JSR PC,RCVDSF ;YES, PROCESS DATASET FLAGS
BR RCVTST ;CHECK FOR MORE FLAGS
;
; HERE ON ERROR IN RECEIVER
;
12$: INC LB.SE4(R4) ;RECEIVER OVERRUN
JSR PC,DQERRR ;RECORD AN ERROR
BR 14$ ;TERMINATE THE INTERRUPT.
;
; COME HERE IF WE ARE OUT OF CHUNKS. WE DO NOT SET LS.ERR BECAUSE
; WE MAY BE FILLING CORE WITH PADS IF THE BSC TASK IS SLOWER THAN
; THE LINE. IF WE RUN OUT OF CORE BEFORE THE MESSAGE IS ACTUALLY
; IN THEN THE BSC TASK WILL MISS THE ETX.
;
13$: INC LB.CHD(R4) ;NOTE CHUNKS DEPLETED
;
; COME HERE IF WE HAVE TOO LONG A MESSAGE. IF THIS IS ACTUALLY
; AN ERROR AND NOT JUST READING PADS IT WILL BE CAUGHT BY
; THE BSC TASK, AS ABOVE.
;
14$: JSR PC,RCVSTP ;KILL THE RECEIVER
;
; HERE ON NORMAL EXIT. WAKE THE BSC TASK IF REQUESTED.
;
15$: BIT #LS.CIE,(R4) ;DOES BSC TASK WANT TO BE AWAKENED?
BEQ 16$ ;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 16$ ;NO (UNLIKELY)
BIC #EBQCHK!EBWAIT,(R0) ;YES, UNWAIT IT.
16$:
;
; HERE TO RESTORE REGISTERS AND RETURN.
;
17$: 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.
;
DQERRR: INC LB.SE1(R4) ;COUNT MASTER ERROR COUNTER
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.REN!UP.RIE!UP.DIE,UP.RSR(R3) ;STOP THE RECEIVER
CLR LB.CCH(R4) ;NO CURRENT CHUNK
BIC #LS.RGO!LS.RRN,(R4) ;NOT RUNNING
BIT #EBQCHK,@LB.TC1(R4) ;IS BSC TASK WAITING FOR A CHUNK?
BEQ 12$ ;NO.
BIC #EBQCHK!EBWAIT,@LB.TC1(R4) ;YES, UNWAIT IT.
12$: RTS PC ;RETURN.
;
;
; COMMON CODE FOR DUP11 INTERRUPTS
;
DQBINT: JSR R4,(PC) ;SAVE R4
MFPS R4 ;PUT PS IN R4
BIC #177760,R4 ;REMOVE ALL BUT LINE NUMBER
ASL R4 ;LINE NUMBER * 2
MOV DQLCB(R4),R4 ;GET LCB POINTER
MOV R3,-(SP) ;SAVE R3
MOV R0,-(SP) ;SAVE R0
MOV R1,-(SP) ;SAVE R1
.IF NE,FT.CHK
TST R4 ;IS THERE A LINE BLOCK?
BNE 11$ ;YES.
STOPCD UQX ;UNKNOWN DUP11 XMIT INTERRUPT
11$:
.ENDC ;.IF NE,FT.CHK
MOV LB.SLA(R4),R3 ;GET HARDWARE ADDRESS
INC LB.XCT(R4) ;ONE MORE TRANSMIT INTERRUPT
TRACE TRCDQF,R4 ;TRACE DUP11 "B" INTERRUPT
;
;
; HERE TO CHECK FOR (ANOTHER) DUP11 TRANSMITTER
; INTERRUPT BIT.
;
XMTTST: MOV UP.XSR(R3),R1 ;GET TRANSMITTER STATUS BITS
MOV R1,LB.XST(R4) ;RECORD LAST TRANSMIT STATUS
BMI 17$ ;BRANCH IF ANY ERRORS.
TRACE TRCDQF,R1 ;TRACE DUP11 STATUS
BIT #UP.XDN,R1 ;IS THE INTERRUPT TRANSMIT DONE?
BEQ 19$ ;NO, TIME TO EXIT.
BIT #LS.XND,(R4) ;IS THIS THE EXTRA DONE INTERRUPT
; THAT WE GET AS THE XMITTER STOPS?
BEQ 11$ ;NO, MUST BE REAL DATA.
JSR PC,XMTST1 ;YES, DO SECOND HALF OF XMIT STOP
BR 19$ ;WE ARE DONE.
;
; HERE WHEN WE HAVE A REAL TRANSMIT DONE INTERRUPT.
;
11$: BIT #LS.CTL,(R4) ;ARE WE SENDING A CONTROL MESSAGE?
BNE 14$ ;YES.
MOV LB.MSG(R4),R1 ;NO, POINT TO DATA MESSAGE
MOVB @MSGPTR(R1),R0 ;GET NEXT CHARACTER
BIC #^C<377>,R0 ;REMOVE POSSIBLE SPREAD SIGN
MOV R0,UP.XBF(R3) ;SEND CHARACTER, CLEARING SOM
BIC #UP.XIE,UP.XSR(R3) ;DISABLE XMT INTERRUPTS FROM THIS LINE
MTPS #BR4 ;ALLOW INTERRUPTS FROM OTHER LINES
INC MSGPTR(R1) ;POINT TO NEXT CHARACTER
MOV MSGPTR(R1),R0 ;COMPUTE POSITION IN BUFFER
SUB MSGLCH(R1),R0
SUB #CHDAT,R0
MOV MSGLCH(R1),R1 ;POINT TO CURRENT CHUNK
CMP CHLEN(R1),R0 ;HAVE WE EXHAUSTED THIS CHUNK?
BNE 12$ ;NO.
;
; ; CONTINUED ON NEXT PAGE
;
;
; HERE WHEN WE HAVE SENT ALL OF THIS CHUNK. GO ON TO NEXT.
;
MOV LB.MSG(R4),R1 ;POINT TO MESSAGE AGAIN.
MOV @MSGLCH(R1),R0 ;POINT TO NEXT CHUNK OF MESSAGE
BEQ 13$ ;END OF MESSAGE
MOV R0,MSGLCH(R1) ;STORE POINTER TO NEXT CHUNK
ADD #CHDAT,R0 ;COMPUTE DATA ADDRESS
MOV R0,MSGPTR(R1) ;STORE IT FOR NEXT INTERRUPT
; BR 12$ ;DONE WITH THIS CHARACTER.
;
; HERE ON END OF CHARACTER PROCESSING. DISABLE PROCESSOR INTERRUPTS
; AND RE-ENABLE THIS LINE.
;
12$: MTPS #BR7 ;DISABLE PROCESSOR INTERRUPTS
BIS #UP.XIE,UP.XSR(R3) ;ENABLE XMT INTS FROM THIS LINE
BR 16$ ;LOOK FOR ANOTHER DONE BIT
;
; HERE ON END OF CHUNKS FOR DATA MESSAGE
;
13$: MTPS #BR7 ;DISABLE PROCESSOR INTERRUPTS
BIS #UP.XIE,UP.XSR(R3) ;WE WILL GET ONE MORE DONE INTERRUPTT
BR 15$ ;SHUT DOWN TRANSMITTER
;
; HERE IF WE ARE SENDING A CONTROL MESSAGE
;
14$: MOVB @LB.CMA(R4),R0 ;GET NEXT CHARACTER
BIC #^C<377>,R0 ;REMOVE POSSIBLE SPREAD SIGN
MOV R0,UP.XBF(R3) ;SEND CHARACTER, CLEARING SOM
INC LB.CMA(R4) ;ADVANCE TO NEXT CHARACTER
DEC LB.CMC(R4) ;DECREMENT COUNTER
BNE 19$ ;NOT END OF MESSAGE,
; EXIT THE INTERRUPT
;
; HERE ON END OF MESSAGE
;
15$: BIS #UP.XEM,UP.XBF(R3) ;TELL THE DUP11 END OF MESSAGE
JSR PC,XMTSTP ;ARRANGE TO STOP THE TRANSMITTER
;
; HERE WHEN WE ARE DONE WITH THE TRANSMIT INTERRUPT.
;
16$: BR XMTTST ;BACK TO TOP OF LOOP.
;
;
; HERE ON TRANSMIT ERROR INTERRUPT
; (THE ONLY ERROR DETECTED HERE IS TRANSMITTER DATA LATE.)
;
17$: MOV R1,LB.ERS(R4) ;SAVE ERROR STATUS
TRACE TRCDQF,R1 ;TRACE ERROR INTERRUPT
BIS #LS.ERR,(R4) ;FLAG AN ERROR
BIT #LS.XND,(R4) ;IS THIS THE EXTRA DONE AFTER STOPPING?
BEQ 18$ ;NO, DO NORMAL TRANSMITTER STOP
JSR PC,XMTST1 ;YES, DO SECOND HALF OF TRANSMITTER STOP
BR 19$ ; AND DISMISS THE INTERRUPT
;
; HERE IF THIS IS NOT THE EXTRA DONE INTERRUPT AFTER
; STOPPING THE TRANSMITTER.
;
18$: INC LB.SE5(R4) ;COUNT TRANSMITTER NOT FAST ENOUGH
JSR PC,DQERRR ;RECORD THE ERROR
JSR PC,XMTSTP ;STOP THE TRANSMITTER
; BR 15$ ;DISMISS THE INTERRUPT
;
; HERE WHEN NO MORE FLAGS ARE FOUND.
; (ALSO FROM CONTROL MESSAGE, SINCE IT DOESN'T ENABLE INTERRUPTS.
; THIS IS TO IMPROVE BUS LATENCY.)
;
19$: MOV (SP)+,R1 ;RESTORE R1
MOV (SP)+,R0 ;RESTORE R0
MOV (SP)+,R3 ;RESTORE R3
MOV (SP)+,R4 ;RESTORE R4
RTI ;EXIT THE INTERRUPT.
;
;
; SUBROUTINE TO STOP THE TRANSMITTER
;
; R4 POINTS TO THE LCB
; R3 POINTS TO THE CSR
;
XMTSTP: TRACE TRCDQF,R4 ;TRACE DUP11 TRANSMITTER STOP
BIC #UP.SND,UP.XSR(R3) ;TELL DUP11 WE HAVE STOPPED SENDING
BIT #UP.XIE,UP.XSR(R3) ;ARE TRANSMIT INTERRUPTS ENABLED?
BEQ XMTST1 ;NO, DO SECOND HALF RIGHT AWAY.
BIS #LS.XND,(R4) ;YES, WAIT FOR NEXT TRANSMIT
; INTERRUPT WHEN SENDING COMPLETE
CLC ;FLAG SUCCESS
RTS PC ;WAIT FOR NEXT TRANSMIT INTERRUPT
;
; SUBROUTINE CALLED ON NEXT TRANSMIT DONE INTERRUPT
; OR BRANCHED TO FROM ABOVE WHEN TRANSMIT INTERRUPTS NOT ENABLED.
; ALSO CALLED DIRECTLY FROM TRANSMIT ERROR, SINCE IN THAT CASE
; WE DO NOT GET ANOTHER DONE INTERRUPT.
;
XMTST1: TRACE TRCDQF,R4 ;TRACE SECOND HALF OF TRANSMIT STOP
BIC #LS.XND,(R4) ;CLEAR FLAG THAT GOT US HERE
BIC #UP.RTS,UP.RSR(R3) ;DROP REQUEST TO SEND
BIC #UP.XIE,UP.XSR(R3) ;DISABLE TRANSMIT DONE INTERRUPTS
BIC #LS.XGO!LS.XRN,(R4) ;DUP11 TRANSMITTER NOT RUNNING
CLR LB.DEW(R4) ;NOT WAITING TO ENABLE MODEM
MOV LB.TC1(R4),R1 ;GET TCB OF BSC TASK
BIT #EBINTR,(R1) ;IS IT WAITING?
BEQ 11$ ;NO.
BIC #EBINTR!EBWAIT,(R1) ;MAYBE, RESTART IT.
11$: CLC ;MARK OK
RTS PC ; AND RETURN.
;
;
; SUBROUTINE TO PROCESS A DATA SET FLAG.
;
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 14$ ;YES, IGNORE MODEM SIGNAL.
BIT #LS.ACT,(R4) ;IS THE DUP11 ACTIVE?
BEQ 14$ ;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,15$ ;YES, CHECK FOR CLEAR-TO-SEND.
11$: BIT #LS.XRN,(R4) ;RUNNING THE TRANSMITTER?
BEQ 12$ ;NO.
JSR PC,17$ ;YES, BE SURE CTS STILL UP
12$: BIT #LS.RGO,(R4) ;WAITING TO START RECEIVER?
BEQ 13$ ;NO.
JSR PC,19$ ;YES, SEE IF CARRIER UP YET
13$: BIT #LS.RRN,(R4) ;RUNNING RECEIVER?
BEQ 14$ ;NO.
JSR PC,21$ ;YES, WORRY ABOUT CARRIER FAILURE.
14$: RTS PC ;RETURN TO CALLER.
;
;
; FOUR SUBROUTINES TO PROCESS DATA SET FLAGS. THEY ARE CALLED
; BASED ON THE CURRENT STATE OF THE DUP11.
;
; R0 = MODEM STATUS FLAGS, FROM THE DUP11.
;
; HERE IF WE ARE WAITING TO START THE TRANSMITTER
;
15$: BIT #UP.CTS,R0 ;HAVE WE CLEAR-TO-SEND?
BEQ 16$ ;NO, WAIT FOR IT.
BIC #LS.XGO,(R4) ;NO LONGER WAITING TO START TRANSMITTER
BIS #LS.XRN,(R4) ;NOW RUNNING TRANSMITTER
BIS #UP.SND!UP.XIE,UP.XSR(R3) ;START THE TRANSMITTER
MOV #UP.XSM!EBCPAD,UP.XBF(R3) ;START OF MESSAGE
16$: RTS PC ;ALL DONE.
;
; HERE IF WE ARE RUNNING THE TRANSMITTER
;
17$: BIT #UP.CTS,R0 ;IS CLEAR-TO-SEND STILL UP?
BNE 18$ ;YES, ALL OK.
INC LB.SE6(R4) ;NO, NOTE CLEAR-TO-SEND FAILURE
JSR PC,DQERRR ;NOTE ERROR
JSR PC,XMTSTP ;STOP THE TRANSMITTER
18$: RTS PC ;ALL DONE.
;
; HERE IF WE ARE WAITING TO START THE RECEIVER
;
19$: BIT #UP.CAR,R0 ;IS CARRIER UP YET?
BEQ 20$ ;NO, KEEP WAITING FOR IT.
BIS #UP.RIE!UP.REN,UP.RSR(R3) ;YES, START THE RECEIVER
BIC #LS.RGO,(R4) ;NO LONGER WAITING TO START RECEIVER
BIS #LS.RRN,(R4) ;NOW RUNNING RECEIVER
20$: RTS PC ;ALL DONE.
;
; HERE IF THE RECEIVER IS RUNNING.
;
21$: BIT #UP.CAR,R0 ;IS CARRIER UP?
BNE 22$ ;YES.
BIT #LS.CAR,(R4) ;NO, HAVE WE SEEN CARRIER YET?
BEQ 23$ ;NO, DONT WORRY ABOUT IT.
JSR PC,RCVSTP ;YES, STOP THE RECEIVER
BR 23$ ;ALL DONE.
;
; HERE IF CARRIER IS UP
;
22$: BIS #LS.CAR,(R4) ;MARK WE HAVE SEEN CARRIER
23$: RTS PC ;RETURN.
;
;
; SUBROUTINE TO SEE IF THE DUP11 HAS READ ANY CHARACTERS
; RECENTLY.
;
; R5 POINTS TO THE TCB, WHICH MUST HAVE EBWAIT SET.
; R4 AND R3 ARE NOT SET UP AND MUST BE PRESERVED.
;
; ON RETURN:
;
; C SET: RCVSCC HAS FOUND CHARACTERS IN THE DUP11
; (NOT POSSIBLE IN THIS VERSION)
; C CLEAR: THE DUP11 HAS NO CHARACTERS. IT IS NOW
; SET TO RESTART THE BSC TASK ON THE NEXT CHARACTER.
;
DQINWQ: MOV R4,-(SP) ;SAVE R4
MOV R3,-(SP) ; AND R3
MOV TCLCB(R5),R4 ;POINT TO LCB
MOV LB.SLA(R4),R3 ;POINT TO DUP11 CSR
MFPS -(SP) ;SAVE INTERRUPT LEVEL
MTPS #BR7 ;DISABLE INTERRUPTS
BIS #LS.CIE,(R4) ;FLAG AWAKEN THE BSC TASK ON NEXT CHAR
MTPS (SP)+ ;RESTORE INTERRUPT LEVEL
MOV (SP)+,R3 ;RESTORE R3
MOV (SP)+,R4 ;RESTORE R4
CLC ;FLAG NO CHARACTERS
RTS PC ;RETURN.
;
;
; SUBROUTINE TO KILL ANY 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
MFPS -(SP) ;SAVE INTERRUPT LEVEL
MTPS #BR7 ;DISABLE INTERRUPTS
BIT #LS.ACT,(R4) ;IS THE DUP11 DOING ANYTHING?
BEQ 12$ ;NO.
;
; CONSIDER STOPPING THE TRANSMITTER
;
BIT #LS.XGO!LS.XRN,(R4) ;YES, TRANSMITTER RUNNING?
BEQ 11$ ;NO.
MOV #EBINTR!EBTIME!EBWAIT,(R5) ;YES, SET UP FOR XMIT STOP
ADD #JIFSEC,TCTIM(R5) ;BE SURE TO WAIT AT LEASE ONE SEC
JSR PC,XMTSTP ;BEGIN STOPPING THE TRANSMITTER
MTPS (SP)+ ;ENABLE INTERRUPTS
MOV R2,-(SP) ;SAVE R2
MOV R4,-(SP) ; AND R4 [1(717)]
JSR PC,WAIT ;WAIT FOR TRANSMITTER TO STOP
; (OR FOR SOME TIME TO PASS)
MOV (SP)+,R4 ;RESTORE R4 [1(717)]
MOV (SP)+,R2 ;RESTORE R2
MOV LB.SLA(R4),R3 ;RESTORE R3 [1(717)]
MFPS -(SP) ;SAVE INTERRUPT LEVEL
MTPS #BR7 ;DISABLE INTERRUPTS
;
; ; CONTINUED ON NEXT PAGE
;
;
; CONSIDER STOPPING THE RECEIVER
;
11$: BIT #LS.RGO!LS.RRN,(R4) ;IS RECEIVER RUNNING?
BEQ 12$ ;NO.
JSR PC,RCVSTP ;YES, STOP THE RECEIVER
12$: BIC #UP.DIE,UP.RSR(R3) ;CLEAR DATASET INTERRUPT ENBALE
MTPS (SP)+ ;RESTORE INTERRUPTS
13$: JSR PC,DEQCHK ;ANY CHUNKS IN RECEIVER QUEUE?
BCS 14$ ;NO.
MOV TCIDLE,R1 ;YES, FREE THEM
JSR PC,QUECHK ; BY SENDING TO BACKGROUND TASK
BR 13$ ;BE SURE WE'VE GOT THEM ALL.
;
; HERE WHEN THE DUP11 HAS BEEN KILLED.
;
14$: BIT #LS.ACT,(R4) ;IS THE DUP11 REALLY DEAD?
BEQ 15$ ;YES.
MOV UP.RSR(R3),R1 ;NO, GET DATASET BITS
JSR PC,DQINIT ;REALLY ZAP THE DUP11
BIC #^C<UP.DTR>,R1 ;SAVE ONLY DTR
BIS R1,UP.RSR(R3) ;PUT BACK DTR
BIC #LS.ACT,(R4) ;THE DUP11 IS NO LONGER ACTIVE
15$: RTS PC ;RETURN.
;
;
; 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 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
MOV (SP)+,R4 ;YES, 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.
;