1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-05-01 06:09:11 +00:00
Files
PDP-10.stacken/files/stacken-tape-backup/dskb:10_7/anf10/dncomm.p11
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

1269 lines
33 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
.SBTTL DNCOMM - MAIN LOOP AND CLOCK ROUTINES 23-OCT-87
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1976,1979,1980,1981,1984,1987,1988.
;ALL RIGHTS RESERVED.
;
;
;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 THAT IS NOT SUPPLIED BY DIGITAL.
VRCOMM=066 ;FILE EDIT NUMBER
.SBTTL PARITY INTERRUPT, EMT, TRAP, ETC.
.IF GE <PDP11-34>
;HERE ON A PARITY CONTROL INTERRUPT
MP.INT: MOV MP.REG,#0 ;SAVE FOR INTERESTED PARTIES
.IF NE FT.HLP
RESET
SAVE <R0,R1>
JSR R0,CKTCRL
.ASCIZ \MEMORY PARITY ERROR MP.REG=\
.EVEN
MOV MP.INT+4,R0
JSR PC,CKTOCT
JSR PC,CM.INT
.ENDC;.IF NE FT.HLP
STOPCD MEM
.ENDC;.IF GE <PDP11-34>
;HERE ON A BUS TIMEOUT
NXMINT: TST TRPPC ;SOMEBODY REQUESTING TRAP INTERCEPT?
BEQ 100$ ;NO, GO DIE IN PEACE
MOV (P)+,TRPDPC ;YES, REMEMBER TRAP PC AND
MOV (P)+,TRPDPS ; PS WORDS IN CASE ANYONE CARES
MOV TRPSP,P ;RESET THE STACK TO KNOWN STATE
MOV 4(P),6(P) ;CONCOCT AN RTI BLOCK
MOV TRPPC,4(P) ; TO RESTORE PI ET AL ON INTERCEPT
MOV (P)+,TRPSP ;POP A LEVEL OF NXM INTERCEPTING
MOV (P)+,TRPPC ; . . .
RTI ;INTERCEPT TRAP, RESETTING PI LEVELS ETC.
100$:
.IF NE FT.HLP
SAVE <R0,R1>
JSR R0,CKTCRL
.ASCIZ \BUS TRAP\
.EVEN
JSR PC,CM.INT
.ENDC;.IF NE FT.HLP
STOPCD NXM ;DIE IN USUAL WAY
;HERE ON A ILLEGAL INSTRUCTION
ILSINT:
.IF NE FT.HLP
SAVE <R0,R1>
JSR R0,CKTCRL
.ASCIZ \ILL\
.EVEN
BR ILSCOM
.ENDC;.IF NE FT.HLP
;HERE ON A BPT
BPTINT: ;DIE IN USUAL WAY
.IF NE FT.HLP
SAVE <R0,R1>
JSR R0,CKTCRL
.ASCIZ \BREAK POINT\
.EVEN
BR ILSCOM
.ENDC;.IF NE FT.HLP
.IF EQ FT.TSK
;HERE ON A IOT INSTRUCTION
IOTINT: ;DIE IN USUAL WAY
.IF NE FT.HLP
SAVE <R0,R1>
JSR R0,CKTCRL
.ASCIZ /IOT/
.EVEN
BR ILSCOM
.ENDC;.IF NE FT.HLP
.ENDC;.IF EQ FT.TSK
;HERE ON A EMT INSTRUCTION
EMTINT: ;DIE IN USUAL WAY
.IF NE FT.HLP
SAVE <R0,R1>
JSR R0,CKTCRL
.ASCIZ /EMT/
.EVEN
BR ILSCOM
.ENDC;.IF NE FT.HLP
;HERE ON RANDOM INTERRUPT
ERRINT: ;DIE IN USUAL WAY
.IF NE FT.HLP
SAVE <R0,R1>
JSR R0,CKTCRL
.ASCIZ /FATAL ERROR/
.EVEN
BR ILSCM0
ILSCOM: JSR R0,CKTSTR
.ASCIZ \ INSTRUCTION\
.EVEN
ILSCM0: JSR PC,CM.INT
.ENDC;.IF NE FT.HLP
STOPCD ILS
.IF NE FT.HLP
CM.INT: MOV 6(P),R0
JSR PC,CKTYPC ;TYPE " @PC=<VALUE><CR><LF>"
RESTORE <R0,R1>
RTS R0
.ENDC ;.IF NE FT.HLP
.IF NE FT.HLP
CKTYPC: ;TYPE " @PC=<VALUE><CR><LF>
JSR R0,CKTSTR
.ASCIZ \ @PC=\
.EVEN
JSR PC,CKTOCT
JSR PC,CKCRLF
RTS PC
.ENDC
;HERE ON A TRAP INSTRUCTION
Q=0 ;OFFSET FOR PC ON STACK
TRPINT: SUB #2,(P) ;BACKUP TO TRAP INSTRUCTION
.IIF NE FTDL10, MOV @DL10AD,#0 ;SAVE DL10 STATUS HERE
; TWIDDLE SW ;PUT SWICHES HERE
MOV %5,-(P) ;SAVE REGISTERS
MOV %4,-(P)
MOV %3,-(P)
MOV %2,-(P)
MOV %1,-(P)
MOV %0,-(P)
CRSPDL: MOV P,#0 ;FOR THOSE WHO READ DUMPS
Q=14 ;OFFSET FOR PC HAS CHANGED
.IF NE DEBUG
.IF EQ FT.SLB
.IF NE NLINES
MOV #FRSTLB,J ;GET LINE BLOCK ADR FOR FIRST LINE
BR 21$
20$: MOV LB.SLA(J),DQ ;GET SYNCHRONOUS LINE HDW ADR
MOV DQ,R0 ;COPY ADDRESS OF DEVICE
MOV J,R1 ;COPY LINE BLOCK ADDRESS
ADD #LB.CRS,R1 ;POINT TO SAVE AREA
MOV (R0)+,(R1)+ ;SAVE SYNCHRONOUS LINE HDW STATE
MOV (R0)+,(R1)+ ;SAVE TRANSMITTER STATUS
MOV (R0)+,(R1)+
MOV (R0)+,(R1)+
.IF NE FTDQ11
DQREGS PRA
MOV 6(DQ),(R1)+
DQREGS SRA
MOV 6(DQ),(R1)+
DQREGS PTA
MOV 6(DQ),(R1)+
DQREGS STA
MOV 6(DQ),(R1)+
.ENDC;.IF NE FTDQ11
21$: MOV LB.LNK(J),J ;GET ADR OF NEXT LINE BLOCK
BNE 20$
.ENDC;.IF NE NLINES
.ENDC;.IF EQ FT.SLB
.ENDC;.IF NE DEBUG
CLR R0 ;HESITATE
27$: SOB R0,27$
RESET
.IF NE FT.HLP
JSR R0,CKTCRL
.ASCIZ \TRAP\
.EVEN
MOVB @Q(P),R0 ;GET CODE IF ANY
BEQ 30$
JSR PC,CKTBOC ;TYPE CODE AND BLANK
30$:
MOV Q(P),R0
JSR PC,CKTYPC ;TYPE " @PC=<VALUE><CR><LF>
.ENDC
.IIF NE FT.DTE, JSR PC,DTERLD ;ASK -10 TO RELOAD US
;THE PROGRAM ENTRY INTO THE M9301 ROM TAKES IN R0 THE ADDRESS
; OF A FOUR WORD ARGUMENT BLOCK. THE ARGUMENTS IN THIS BLOCK ARE
; AS FOLLOWS.
; 1) THIS IS THE SERIAL NUMBER OF THIS 11 (DEFAULT'S TO OUR
; NODE NUMBER FOR CONVENIENCE)
; 2) THIS IS THE NODE NUMBER OF THE TEN THAT WE WANT TO BOOT
; US. (ZERO MEANS ANY TEN)
; 3) THIS IS THE NUMBER OF THE DQ-11 TO USE WHEN BOOTING
; 4) THIS IS THE ADDRESS OF AN ASCIZ STRING TO PASS AS A
; COMMAND STRING TO NETLDR. ZERO IMPLIES NO COMMAND STRING
;THE FOLLOWING MACRO BUILDS THE PARAMETER BLOCK FOR THE ROM.
.MACRO NETLDR S,N,L,TEXT
.WORD S
.WORD N
.WORD L
.IF NB <TEXT>
.WORD .+2
.ASCIZ \TEXT\
.EVEN
.IFF
.WORD 0
.ENDC
.ENDM ;NETLDR
.IF NE FT.ROM
GO.ROM: JSR R0,ROMADR ;GO BOOT FROM THE PROM
.IF NE FTNTLD ;IF THE USER SPECIFIED THE PARMS,
LDCNFG ;THEN USE HIS CONFIG.
.IFF ;OTHERWISE USE THE DEFAULT
NETLDR OURNNM,0,0 ;SERIAL=OURNNM,NODE=0,DQ=0,NO TEXT.
.ENDC
.ENDC; FT.ROM
.IIF NE FT.MOP,JMP MOPDMP ;IF A DN22, GO USE MOP HACK
.IF EQ FT.MOP!FT.ROM ;IF NEITHER ROM OR MOP
MOVB @Q(P),R0 ;GET STOPCD(IF ANY)
BEQ 97$
.IF NE FTDL10
BIT #DL.PEN,@DL10AD ;IS PORT ENABLED ?
BEQ 95$
MOV DL10AD,R1 ;POINT INTO WINDOW
MOV R0,DL.STP(R1) ;SAVE STOP CODE FOR LOSER
.ENDC;.IF NE FTDL10
95$: HALT
97$: MOV Q(P),R0 ;GET TRAP ADR
HALT
JMP BEGIN ;RESTART
.ENDC; FT.ROM!FT.MOP
;JMP HERE ON SOME IMPOSSIBLE ERRORS
SYSERR: TRAP
.CKTTS
.SBTTL TRAP INTERCEPT SET/CLEAR
;TRPST -- SET UP FOR INTERCEPTION OF NXM ERRORS (ANYTHING THROUGH TRAP 4)
;CALL IS:
;
; JSR R0,TRPST
; .WORD ADR
;
;WHERE ADR IS THE INTERCEPT TRAP ADDRESS WHICH SHOULD GAIN CONTROL SHOULD
;A TRAP THROUGH 4 OCCUR.
;
;THE CALLER MUST NOT HAVE ANY DATA PUSHED ONTO THE STACK (HE MUST BE
;READY TO "RTS PC" TO HIS CALLER!!!
;
;YOU MAY NEST AS MANY CALLS TO TRPST AS THERE IS STACK SPACE (I.E., YOU
;DON'T HAVE TO WORRY ABOUT THE "TRAP" RESOURCE, IT IS RECURSIVE).
;
;THE TRAP INTERCEPT WILL BE AUTOMATICALLY CLEARED WHEN THE CALLER EXECUTES
;HIS "RTS PC".
;
;ON A TRAP, THE TRAP SERVICE ROUTINE IS ENTERED WITH THE STACK AND PI AT
;THE SAME LEVEL AS AT THE CALL TO TRPST (E.G., YOU MAY POINT THE TRAP
;ADDRESS AT THE ROUTINE'S "RTS PC", SEE DTEINI FOR AN EXAMPLE).
;
;THE CARRY BIT IS PRESERVED, ALL OTHER CONDITION CODE BITS ARE LOST.
TRPST: MOV @#PS,-(P) ;SAVE THE CURRENT PI/PROCESSOR STATUS
MOV TRPSP,-(P) ;SAVE THE OLD (CURRENT) STACK
MOV TRPPC,-(P) ; AND PC WORDS
MOV P,TRPSP ;SET THE NEW TRAP STACK
MOV (R0)+,TRPPC ; AND PC WORDS.
MOV R0,-(P) ;ADDRESS OF CALLER TO BE CALLED
MOV 10(P),R0 ;RESTORE R0 FOR CALLER
JSR PC,@(P)+ ;AND CALL OUR CALLER
;HERE WHEN OUR CALLER HAS FINISHED AND "RTS PC"'ED BACK TO US TO CLEAR
;THE TRAP INTERCEPT
MOV (P)+,TRPPC ;RESTORE PREVIOUS LEVEL'S PC
MOV (P)+,TRPSP ; AND STACK WORDS
BIT (P)+,(P)+ ;POP OFF TWO MORE JUNK WORDS
RTS PC ;RETURN TO CALLER'S CALLER
;TRPCL -- UNDO A CALL TO TRPST
;CALL IS:
;
; JSR PC,TRPCL
;
;MUST BE CALLED AT SAME STACK LEVEL AS TRPST CALL.
TRPCL: MOV (P)+,10(P) ;FINAL RETURN ADDRESS
BIT (P)+,P ;POP OFF JUNK (TRPST JSR) WORD
MOV (P)+,TRPPC ;RESTORE PREVIOUS LEVEL'S PC
MOV (P)+,TRPSP ; AND STACK WORDS.
BIT (P)+,P ;POP OFF ANOTHER JUNK WORD
RTS PC ;AND RETURN
.SBTTL POWER FAIL INTERRUPT
PWFINT: TWIDDLE ;COUNT POWER FAIL TRAPS
MOV #PWFINU,PWFVEC ;ON POWER RESTART, RESTART US
CLR R0 ;INITIALIZE SOB
SOB R0,. ;WAIT FOR POWER RESTART
;IF THE SOB FALLS THROUGH TO HERE (SEVERAL CLOCK TICKS LATER) THEN WE
;HAVE A SPURIOUS POWER FAIL CONDITION.
TWIDDLE ;AN INTERESTING EVENT IN ITSELF
; BR PWFINU ;ASSUME POWER FAIL RESTART
.SBTTL NORMAL STARTUP AND POWER FAIL RESTART
;HERE ON EITHER POWER FAIL RESTART, OR SUPRIOUS POWER FAIL INTERRUPT
PWFINU: TWIDDLE ;COUNT POWER FAIL RESTARTS
CLR R0 ;INIT FOR SOB LOOP
SOB R0,. ;WAIT FOR THINGS TO SETTLE DOWN
;NORMAL NODE STARTUP
BEGIN: RESET ;CLEAR THE WORLD
MOV #PDL,P ;GET A GOOD STACK
CLR TRPPC ;NO TRAP INTERCEPT IN EFFECT
MOV #PWFINT,PWFVEC ;RESET POWER FAIL IN CASE POWER RESTART
.IF NE FT.87S+FT.D20
;THE FIRST TIME THROUGH HERE THE ROM HAS LEFT R1 POINTING TO THE
;STATUS REGISTER FOR THE DTE THAT LOADED US. SAVE THAT INFO FOR USE
;LATER ON. ON A POWER-FAIL RESTART, R1 WILL BE JUNK SO WE ASSUME
;THAT .PRDTE WILL STILL BE THE CORRECT DTE. IF NOT, THEN TENSEC (OR
;SOMEONE) WILL NOTICE AND CLEAR IT, FORCING TENSEC TO START SCANNING
;FOR AN EXTANT DTE. SIMILARLY, IF BOOTED VIA A SYNC LINE TENSEC WILL
;EVENTUALLY FIND A WORKING DTE (IF ANY EXIST). THE ONLY REAL REASON
;THIS CODE EXISTS IS TO FORCE THE -11 TO USE THE DTE FROM WHICH IT
;WAS LOADED ON THE OFF CHANCE THE -11 HAS MORE THAN ONE DTE.
BIC #TE.BNX-1,R1 ;ADJUST TO START OF REGISTERS
CMP R1,#TE.BAS ;IS R1 POINTING TO A DTE?
BLO 5$ ;BELOW FIRST DTE, FORGET IT
CMP R1,#TE.BAS+<TE.NNN*TE.BNX> ;IS R1 POINTING TO A DTE?
BHIS 5$ ;ABOVE LAST DTE, FORGET IT
MOV R1,.PRDTE ;VALID DTE, SAVE OUR LOADING DTE
ADD #TE.STW,R1 ;OFFSET TO DTE STATUS REGISTER
MOV R1,.PRSTA ;SAVE DTE STATUS REG ADR ALSO
5$:
.ENDC;.IF NE FT.87S+FT.D20
JSR PC,CHK.11 ;BE SURE HDW ALL HERE
.WORD MYNAME
RCOUNT: TWIDDLE ;COUNT RESTARTS
MOV #NXMINT,NXMVEC ;SET BUS TRAP LOCATION
.SBTTL INITIALIZATION CODE
;ENABLE THE MEMORY PARITY OPTION
.IF GE <PDP11-34>
MP.ARM: MOV #MP.ENB,MP.REG ;ARM PARITY OPTION
.ENDC;.IF GE <PDP11-34>
.IF NE FTDL10
09$: BIT #DL.PEN,@DL10AD ;IS DL10 PORT ENABLED ?
BNE 09$ ;IF SO WAIT FOR 10
.ENDC
Z=ROMLOW&160000
.IF NE Z-160000 ;IF ROM PROG IN READ/WRITE MEMORY - BETTER BE CAREFUL
MOV #ROMLOW,PHYLIM
.ENDC
;THE FOLLOWING ZEROES HIGH CORE FOR DUMPS
.IF NE FTCLEAR
MOV PRGEND,R0 ;FIRST LOCATION TO ZERO
10$: CLR (R0)+ ;CLEAR HIGH CORE
CMP R0,PHYLIM
BNE 10$
.ENDC;.IF NE FTCLEAR
;INITIALIZE CHUNKS
CLR FRECNT ;NO CHUNKS YET
CLR LSTFRE ;NO CHUNKS YET
MOV PRGEND,R2 ;ADR OF CHUNK
15$: MOV R2,R0 ;COPY ADR OF CHUNK
ADD #CNKSIZ,R2 ;MAKE ADR OF NEXT CHUNK
CMP R2,PHYLIM
BHI 20$ ;EXIT IF WE'RE AT THE END OF MEMORY
JSR PC,FRECNK ;FREE CHUNK
BR 15$
20$:
MOV FRECNT,FREMAX
;INITIALIZE THE QUEUES
.MACRO X Q
MOV #Q'.QUE,Q'.PTR
MOV #Q'.QUE,Q'.TKR
.ENDM X
X QI
X QO
X NC
.IIF NE,FT.DCP, X NS ;NSP QUEUE
.IIF NE DEVN, X DV
.IIF NE FTDL10, CLR T10QUE ;CLEAR TO-10 QUEUE POINTER
.IIF NE FT.DTE, JSR PC,DTEINI ;INIT DTE DATA BASE IF WE HAVE ONE
.IIF NE DMCN, JSR PC,DMCONC ;SET UP THE DMC-11 MESSAGE BUFFER POOL
;HERE TO INITIALIZE THE DDCMP LINES
INI.10:
.IF NE NTLINE
.IF NE,FT.DCP
.IIF NE FTDCP3!FTDCP4, JSR PC,NSPINI ; CLEAR DCP DATABASE
.ENDC
MOV #FRSTLB,J ;ADR OF FIRST BLOCK
BR 13$
10$: MOV #<LB.SIZ-LB.ZER>/2,R0 ;ESTABLISH COUNTER
MOV J,R1 ;MAKE ADDR OF WORD TO ZERO
ADD #LB.ZER,R1
12$: CLR (R1)+
SOB R0,12$
BIC #^C<LS.MPT>,(J) ;VIRGIN LINE STATUS
JSR PC,DDCINI ;DO DDCMP INITIALIZATION
13$: MOV LB.LNK(J),J ;GET ADR OF NEXT BLOCK
BNE 10$
.ENDC;.IF NE NTLINE
;INITIALIZE THE STATION CONTROL BLOCKS
MOV #<SEQLIM*2>,R0
20$: CLRB SQNTAB-1(R0)
SOB R0,20$
MOV #OURSCB,SB ;GET STATION BLOCK
30$: JSR PC,CLRSCB ;CLEAR REST OF BLOCK
SB.ADV 30$ ;CLEAR NEXT BLOCK ALSO
.IF NE FTDL10!FT.DTE
CLR TENSCB ;NO PATH TO THE TEN
.ENDC ;END .IF NE FTDL10!FT.DTE
MOV #OURSCB,SB ;OUR SCB ADR AGAIN
BIS #SBF.SQ!SBF.IC!SBF.IU!SF.HID,@SB ;FLAG BLOCK IN USE
MOV SB,SQNTAB ;1ST NONSEQUENTIAL NODE IS US
;INITIALIZE THE DEVICES
.IF NE DEVN
DDBINI: MOV FIRDDB,J ;GET FIRST DEVICE BLOCK
10$: BIC #DS.QUE!DS.ACT,@J ;CLRDDB WON'T HIT THESE BITS
.IF NE FT.TSK
MOV J,R0
ADD #DB.TSK,R0
CLR (R0)+ ;AND WON'T GET THESE
CLR (R0)+
CLR (R0)+
CLR (R0)
.ENDC;.IF NE FT.TSK
JSR PC,CLRDDB ;CLEAN OUT DEVICE BLOCK
.IF NE FT.CTY!TTYN!RDAN
BIT #DS.TTY,@J ;WAS THIS A TTY ?
.IF NE FT.RDA
BNE 14$ ; YES
BIT #RDEASC,DB.RDT(J) ;ASCII RDX ?
.ENDC
BEQ 90$ ; NO
;INITIALIZE ASCII TTY AND RDA DEVICES
14$: MOV J,R0 ;POINT TO BYTES TO CLEAR
ADD #DB.TZR,R0
MOV #DB.TSZ-DB.TZR,R1 ;AND GET THERE NUMBER
11$: CLRB (R0)+ ;AND CLEAR THEM
SOB R1,11$
CLR DB.TOB(J) ;NO TTY OUTPUT YET
CLR DB.TOB+2(J)
.IF NE FT.TSK
MOV #DB.KQU,DB.KPT(J) ;INITIALIZE KEYBOARD PUTER
MOV #DB.KQU,DB.KTK(J) ;INITIALIZE KEYBOARD TAKER
.ENDC;.IF NE FT.TSK
.IF NE FT.RDA
BIT #RDEASC,DB.RDT(J) ;ASCII RDX ?
BNE 15$ ; YES, DONT DO IT
.ENDC
MOV #RSTMSG,DB.STR(J) ;START UP MESSAGE
15$:
.IF NE FT.CTY
CMP J,#CTYDDB ;IS THIS CTY ?
BEQ 44$ ;IF SO DON'T INITIALIZE DL11
.ENDC;.IF NE FT.CTY
MOV DB.DHB(J),R3 ;GET ADR OF DH/DZ11 BLOCK FOR LINE
MOV DB..LN(J),R2 ;SET UP LINE # FOR DH/DZ.INI
.IF NE FT.RDA
BIT #DS.TTY,@J ;IS IT TTY?
BEQ 67$ ; NO
.ENDC
;ASCII TTY ONLY
.IF NE TTYN
JINDEX JMP,DB.TYP(J),R0,29$
29$: .WORD 30$ ; DH-11
.WORD 31$ ; DZ-11
30$:
.IF EQ TTYDHN
TRAP ; NO DH TTYS!
.IFF
SAVE <#TTDHOU,#TTDHIN,DB.LCB(J)>
JSR PC,DH.INI ; INITIALIZE THE DH11 AND LCB
BR 40$ ; CONTINUE
.ENDC ;.IF EQ TTYDHN
31$:
.IF EQ TTYDZN
TRAP ; DO DZ TTYS!
.IFF
SAVE <#TTDZOU,#TTDZIN,DB.LCB(J)>
JSR PC,DZ.INI
.ENDC ;.IF EQ TTYDZN
.ENDC ; TTYN
40$: ADD #6,P ; POP THE ARGS TO DH/DZ.INI
.IF NE FTDN11
BITB #40,DB.DVT(J) ;IS IT AUTO-DIAL LINE?
BEQ 44$ ;NO, CONTINUE
BIC #^CDNDISP,DB.DNS(J) ;CLEAR DIAL BIT & TIMER
JSR PC,DNADDR ;R1=DNTAB,R2=HDW
BIC #7,R2 ;INITIALIZE
MOV #DN..ME,(R2)+ ;SET MASTER ENABLE IN FIRST UNIT
CLR (R2)+ ;CLR 2ND UNIT
CLR (R2)+ ;CLR 3RD UNIT
CLR (R2)+ ;CLR 4TH UNIT
MOV J,2(R1) ;PUT DDB ADDRESS INTO DNBLK
.ENDC;.IF NE FTDN11
44$: JSR PC,BEGXMT ;START LINE TYPING
BR 90$ ;THE TTY LINE IS INITIALIZED
.ENDC;.IF NE FT.CTY!TTYN!RDAN
;ASCII RDA
.IF NE FT.RDA
67$: JINDEX JMP,DB.TYP(J),R0,69$
69$: .WORD 70$ ; DH-11 RDA
.WORD 71$ ; DZ-11 RDA
70$:
.IF EQ RDADHN
TRAP ; NO DH-11 RDAS!
.IFF
SAVE <#RDDHOU,#RDDHIN,DB.LCB(J)>
JSR PC,DH.INI ; SET UP DH AND LINE BLOCK
BR 40$
.ENDC ;.IF EQ RDADHN
71$:
.IF EQ RDADZN
TRAP ; NO DZ-11 RDAS!
.IFF
SAVE <#RDDZOU,#RDDZIN,DB.LCB(J)>
JSR PC,DZ.INI
BR 40$
.ENDC ;.IF EQ RDADZN
.ENDC ;.IF NE FT.RDA
;STEP TO NEXT DDB
90$: MOV DB.LNK(J),J ;GET NEXT DEVICE BLOCK
BEQ 99$
JMP 10$ ;CLEAR IT OUT
99$:
.ENDC;.IF NE DEVN
;INITIALIZE THE TTY'S
.IF NE <FT.CTY+TTYN+RDAN>
MOV #TI.QUE,TI.PTR ;POINTER TO TTY INPUT SILO
MOV #TI.QUE,TI.TKR
.IIF NE FT.CTY, BIS #100,CTISTS ;ENABLE CTY KEYBOARD
.ENDC;.IF NE <FT.CTY+TTYN+RDAN>
.IF NE FT.TSK
TSKINI: MOV #RUNQUE,R0 ;POINT TO 1ST RUN QUEUE
MOV #TKPMAX,R1 ;GET THE NUMBER OF QUEUES
12$: CLR (R0)+ ;AND CLEAR THEM
SOB R1,12$
CLR TASK ;FLAG NO CURRENT JOB
CLR L.TASK
MOV #FIRTSK,J ;GET FIRST TASK BLOCK ADR
20$: BEQ 30$
MOV TK.JSA(J),R0 ; START ADDR
CMP #1,RCOUNT+2 ; RESTARTING ?
BEQ 25$ ; YES, WE ARE
MOV TK.RSA(J),R0 ; NO, USE RESTART ADDR
25$: JSR PC,TSKBEG ; START TASK
MOV TK.LNK(J),J ; NEXT TASK, PLEASE
BR 20$
30$:
.ENDC;.IF NE FT.TSK
CLR PS ;ENABLE INTERRUPTS
.IIF NE FT.87S+FT.D20,JSR PC,RINIDB ;RING THE -10'S CHIMES (KEEP DTELDR HAPPY)
;START THE CLOCK
MOV #CLKENB,CLKWRD
.SBTTL MAIN PROGRAM LOOP
LOOP:
;COMMON BUG IS TO CLEAR THIS
ASSERT 0 EQ #ERRINT
ASSERT #NXMINT EQ NXMVEC ;AND CHECK BUS TRAP LOCATION ALSO
ASSERT #7*40 CLEAR IN PS ;CHECK TO SEE PION
ASSERT #PDL EQ P ;DID SOMEONE GARBAGE STACK ?
MOV #2$,NXMVEC ;RESET BUS TRAP VECTOR
MOV @SW,SW ;DISPLAY IN THE LIGHTS
2$: MOV #NXMINT,NXMVEC ;RESET BUS TRAP VECTOR
MOV #PDL,P ;IN CASE WE TRAPPED
SPL 0 ;REENABLE INTERRUPTS
TST JIFFLG ;HAS CLOCK TICKED ?
BEQ 4$
JSR PC,JIFSCN ;YES SO DO ONCE PER TICK CODE
CLR JIFFLG ;RESET FLAG FOR NEXT TIME
4$:
.IF NE <FT.CTY+TTYN+RDAN>
QUEGET TI,5$ ;GET NEXT ENTRY ON TTY INPUT QUEUE
JSR PC,RECINT ;GO HANDLE INPUT
BR 4$ ;NOW GO BACK FOR MORE
5$:
.ENDC;.IF NE <FT.CTY+TTYN+RDAN>
;HERE TO CHECK DDCMP
.IF NE NTLINE
QUEGET QI,20$ ;GET ENTRY FROM QUEUE
JMP DDCINP ;CHECK DDCMP INPUT
20$: ;CHECK OUTPUT QUEUE
QUEGET QO,30$ ;GET ENTRY FROM QUEUE
; ASSERT J BETWEEN #LBLK0 #<LBLK0+<NTLINE*LB.SIZ>>
TRACE DD
JMP DDCXMT ;TRY TO SEND SOMETHING
.ENDC;.IF NE NTLINE
30$: ;CHECK NCL QUEUE
.IF NE,FT.DCP
JSR PC,NSPCHK ;CHECK TO SEE WHAT IS TO BE DONE
.ENDC; NE,FT.DCP
QUEGET NC,40$ ;GET STATION WHICH WANTS ATTENTION
BIT #SBF.IU,@SB ;IS BLOCK STILL IN USE ?
BEQ 30$ ;WHERE TO GO WHEN NONE
TRACE NC
.IIF NE FT.SNK, CLR J
JSR PC,NCLCHK ;GO CHECK STATION
40$:
.IF NE DEVN
QUEGET DV,50$ ;GET ENTRY FROM QUEUE
TRACE DV ;KEEP TRACKS
JSR PC,@DB.OPC(J) ;DISPATCH TO ROUTINE
50$:
.ENDC;.IF NE DEVN
.IIF NE FTDL10, JSR PC,LOOPDL ;CHECK ON 10'S ACTIVITIES
.IIF NE FT.DTE, JSR PC,LOOPDT ;DITTO
.IIF NE FT.TSK, JSR PC,LOOPTK ;SEE WHAT CAN BE DONE FOR TASKS
JMP LOOP ;NOW REPEAT ALL THIS UNTILL
;YOU GET IT WRONG
.SBTTL QUEUE PUT,GET ROUTINES
;
;HERE TO QUEUE INPUT AND OUTPUT (DDCMP)
;
.IF NE NTLINE
QUEPUT QO CODE ;PROCEDURE FOR INSERTING IN THE QO QUEUE
QUEPUT QI CODE ;PROCEDURE FOR INSERTING IN THE QI QUEUE
.ENDC ; .IF NE NTLINE
;
.SBTTL CHUNK HANDLING ROUTINES
;CHUNK CONVENTIONS
; CHUNK SIZE IS A POWER OF TWO
; ADR OF CHUNK IS A MULTIPLE OF CHUNK SIZE
; FIRST WORD OF CHUNK IS A LINK TO THE NEXT CHUNK ADR OR 0
; 2ND WORD OF CHUNK IS A POINTER TO NEXT BYTE IN CHUNK TO FILL
;CABLTB -- "BLT" A BYTE STREAM, ALLOCATING NEW CHUNK (ERSGET)
;CGBLTB -- "BLT" A BYTE STREAM, ALLOCATING NEW CHUNK (GETCNK)
;CALL: MOV <SRC>,R1
; MOV <CNT>,R2
; JSR PC,CABLTB
; RETURN
;
;WHERE <SRC> IS SOURCE BYTE ADDRESS, AND <CNT> IS THE COUNT OF BYTES TO BE
;COPIED.
;
;CABLTB AND CGBLTB WILL MAKE A COPY OF THE BYTE STREAM POINTED TO BY R1/R2,
;STARTING WITH A NEW FRESH CHUNK. FOR CGBLTB, IF A NEW STREAM COULDN'T BE
;STARTED, RETURN IS "BEQ".
;
;ON RETURN, R0 POINTS TO FIRST CHUNK IN RESULTANT COPY, R1/R2 UPDATED.
CABLTB: JSR PC,ERSGET ;GET A CHUNK OR ELSE
BNE CMBLTB ;WE GOT IT
TRAP ;"OR ELSE" GOT US INSTEAD
CGBLTB: JSR PC,GETCNK ;GET A CHUNK IF CONVENIENT
BNE CMBLTB ;WE GOT IT
RTS PC ;WE DIDN'T GET IT, SO IT GOES
CMBLTB: MOV R2,CN.LEN(R0) ;PRESET FINAL COPYED LENGTH
MOV R0,-(P) ;SAVE START OF COPYED BYTE STREAM
ADD #CN.NCT,R0 ;FIRST DATA BYTE WITHIN NEW BYTE STREAM
JSR PC,CNBLTB ;COPY THE DATA, ALLOCATING AS NEEDED
MOV (P)+,R0 ;RESTORE ORIGINAL NEW COPY ADDRESS
RTS PC ;RETURN WITH COPYED BYTE STREAM
;CNBLTB -- "BLT" A BYTE STREAM, ALLOCATING NEW CHUNKS AS NEEDED
;CALL: MOV <DST>,R0
; MOV <SRC>,R1
; MOV <CNT>,R2
; JSR PC,CNBLTB
; RETURN
;
;WHERE <DST> IS THE DESTINATION BYTE ADDRESS TO START STORING THE COPIED BYTE
;STREAM; <SRC> IS THE SOURCE BYTE ADDRESS TO COPY FROM; AND <CNT> IS THE NUMBER
;OF BYTES TO BE COPIED.
;
;ON RETURN, R0/R1/R2 UPDATED.
.REPT 0
CNBLTB: MOVB (R1)+,(R0)+ ;COPY ANOTHER BYTE
ADVCNK R0 EXTEND ;ALLOCATE NEW CHUNK IF NEEDED
ADVCNK R1 FREE ;FREE UP STALE CHUNK IF FINISHED
SOB R2,CNBLTB ;LOOP FOR ENTIRE BYTE STREAM
RTS PC ;RETURN WITH COPYED BYTES
.ENDR ;.REPT 0
CNBLTB: MOV R3,-(P) ;SAVE A REGISTER
1$: MOV #CNKSIZ-1,R3 ;PROTOTYPE CHUNK BOUNDRY TESTER
;LOOP COPYING BYTES
10$: MOVB (R1)+,(R0)+ ;COPY ANOTHER BYTE
BIT R3,R0 ;ADVCNK R0 EXTEND
BNE 14$ ;CONTINUE
JSR PC,GTCKR0 ; EXTEND
14$: BIT R3,R1 ;ADVCNK R1 FREE
BNE 16$ ;CONTINUE
JSR PC,FRCKR1 ; FREE
16$: SOB R2,10$ ;LOOP FOR ENTIRE BYTE STREAM
17$: MOV (P)+,R3 ;RESTORE SCRATCH REGISTER
RTS PC ;RETURN WITH COPYED BYTES
;AVCKRN -- ADVANCE TO NEXT CHUNK IN CHAIN, NEITHER FREEING NOR ALLOCATING
;ACVKR0 - R0 CHUNK ADDRESS
AVCKR0: BIT #CNKSIZ-1,R0 ;IF NOT AT A CHUNK BOUNDARY
BNE 10$ ;EXIT ITS OK
MOV -CNKSIZ(R0),R0 ;ELSE ADVANCE TO THE NEXT CHUNK
BEQ 10$ ;AND EXIT IF NONE
ADD #2,R0 ;ELSE SKIP THE LINK WORD
10$: RTS PC
;AVCKR3 - R3 CHUNK ADDRESS
AVCKR3: BIT #CNKSIZ-1,R3 ;IF NOT AT A CHUNK BOUNDARY
BNE 10$ ;EXIT ITS OK
MOV -CNKSIZ(R3),R3 ;ELSE ADVANCE TO THE NEXT CHUNK
BEQ 10$ ;AND EXIT IF NONE
ADD #2,R3 ;ELSE SKIP THE LINK WORD
10$: RTS PC
;GTCKRN -- ADVANCE TO NEXT CHUNK IN CHAIN, ALLOCATING NEW CHUNK IF REQUIRED
;GTCKR0 - R0 CHUNK ADDRESS
GTCKR0: BIT #CNKSIZ-1,R0 ;IF NOT END OF CHUNK, EXIT
BNE 10$
SAVE <R2>
MOV R0,R2
MOV -CNKSIZ(R0),R0 ;IS THERE A NEXT CHUNK ALREADY?
BNE 5$ ;YES, DON'T HAVE TO ALLOCATE A NEW ONE
JSR PC,ERSGET ;ALLOCATE A NEW CHUNK
MOV R0,-CNKSIZ(R2) ;AND LINK IT IN
5$: RESTORE <R2>
TST (R0)+ ;AND BE SURE TO POINT TO THE DATA
10$: RTS PC
;GTCKR1 - R1 CHUNK ADDRESS
GTCKR1: BIT #CNKSIZ-1,R1 ;IF NOT AT END OF CHUNK,EXIT
BNE 10$
SAVE <R0>
MOV -CNKSIZ(R1),R0 ;IS THERE A NEXT CHUNK ALREADY?
BNE 5$ ;YES, USE IT
JSR PC,ERSGET ;GET NEXT CHUNK
MOV R0,-CNKSIZ(R1) ;LINK NEW CHUNK TO PREVIOUS
5$: MOV R0,R1 ;COPY CHUNK ADR
TST (R1)+ ;SKIP LINK SLOT
RESTORE <R0>
10$: RTS PC
;GTCKR2 - R2 CHUNK ADDRESS
GTCKR2: BIT #CNKSIZ-1,R2 ;IF NOT AT END OF CHUNK,EXIT
BNE 10$
SAVE <R0>
MOV -CNKSIZ(R2),R0 ;IS THERE A NEXT CHUNK ALREADY?
BNE 5$ ;YES, USE IT
JSR PC,ERSGET ;GET NEXT CHUNK
MOV R0,-CNKSIZ(R2) ;LINK NEW CHUNK TO PREVIOUS
5$: MOV R0,R2 ;COPY CHUNK ADR
TST (R2)+ ;SKIP LINK SLOT
RESTORE <R0>
10$: RTS PC
;GTCKR3 - R3 CHUNK ADDRESS
GTCKR3: BIT #CNKSIZ-1,R3 ;IF NOT AT END OF CHUNK,EXIT
BNE 10$
SAVE <R0>
MOV -CNKSIZ(R3),R0 ;IS THERE A NEXT CHUNK ALREADY?
BNE 5$ ;YES, USE IT
JSR PC,ERSGET ;GET NEXT CHUNK
MOV R0,-CNKSIZ(R3) ;LINK NEW CHUNK TO PREVIOUS
5$: MOV R0,R3 ;COPY CHUNK ADR
TST (R3)+ ;SKIP LINK SLOT
RESTORE <R0>
10$: RTS PC
;GTCKR4 - R4 CHUNK ADDRESS
GTCKR4: BIT #CNKSIZ-1,R4 ;IF NOT AT END OF CHUNK,EXIT
BNE 10$
SAVE <R0>
MOV -CNKSIZ(R4),R0 ;IS THERE A NEXT CHUNK ALREADY?
BNE 5$ ;YES, USE IT
JSR PC,ERSGET ;GET NEXT CHUNK
MOV R0,-CNKSIZ(R4) ;LINK NEW CHUNK TO PREVIOUS
5$: MOV R0,R4 ;COPY CHUNK ADR
TST (R4)+ ;SKIP LINK SLOT
RESTORE <R0>
10$: RTS PC
;FRCKRN -- ADVANCE TO NEXT CHUNK, FREEING OLD STALE CHUNK
;FRCKR0 - R0 CHUNK ADDRESS
FRCKR0: BIT #CNKSIZ-1,R0 ;WAS THAT LAST CHAR IN CHUNK ?
BNE 10$
SUB #CNKSIZ,R0 ;MAKE ADR OF CHUNK
MOV (R0),-(P) ;SAVE ADR OF NEXT CHUNK
JSR PC,FRECNK ;RELEASE DEAD CHUNK
MOV (P)+,R0 ;GET ADR OF NEXT CHUNK
BEQ 10$
TST (R0)+ ;SKIP LINK WORD
10$: RTS PC
;FRCKR1 - R1 CHUNK ADDRESS
FRCKR1: BIT #CNKSIZ-1,R1 ;WAS THAT LAST CHAR IN CHUNK ?
BNE 10$
SAVE <R0>
MOV R1,R0
SUB #CNKSIZ,R0 ;MAKE ADR OF CHUNK
MOV (R0),R1 ;SAVE ADR OF NEXT CHUNK
BEQ .+4
TST (R1)+ ;SKIP LINK WORD
JSR PC,FRECNK ;RELEASE DEAD CHUNK
RESTORE <R0>
10$: RTS PC
;GETCNK -- GET A FREE CHUNK IF LOTS AVAILABLE
;ERSGET -- GET A FREE CHUNK IF ANY AVAILABLE
; CALL JSR PC,GETCNK
; RETURN WITH CHUNK ADR IN R0
;
;ON RETURN, "BEQ" IS ERROR, "BNE" IS SUCCESS
GETCNK: CMP #ERSCNT,FRECNT ;DO WE HAVE ENOUGH ?
BMI ERSGET ;IF WE DO GIVE HIM ONE
TWIDDLE ;MORE CORE MIGHT HELP
NOCNKS: CLR R0 ;CAN'T AFFORD TO GIVE HIM ONE
RTS PC
ERSGET: PIOFF ;SET LEVEL 7
DEC FRECNT ;COUNT CHUNK OUT OF LIST
.IF EQ DGUTS
ASSERT PL ;BE SURE SOME STILL LEFT
.IFF
BPL ERSGT0
CTYMSG LSW ;REPORT FAILURE, AND RETURN VALUE =0
INC FRECNT
PION
BR NOCNKS
ERSGT0:
.ENDC ; .IF EQ DGUTS
MOV FIRFRE,R0 ;GET ADR OF FIRST FREE CHUNK
ASSERT NE ;HOPE WE GOT ONE
ASSERT CHUNK R0 ;IS CHUNK ADDRESS REASONABLE
TST @R0
ASSERT NE
ASSERT CHUNK @R0 ;CHECK ALSO ON HIS FRIEND
MOV @R0,FIRFRE ;RESET ADR OF FIRST FREE CHUNK
PION ;RESTORE PROCESSOR LEVEL
CLRCNK R0 ;ZERO THE WHOLE THING, OR JUST THE LINKAGES
TRACE CN
CLZ ;SET PS SO CALLER KNOWS HE WON A CHUNK
RTS PC ;DISMISS CALL
;FRECNL -- FREE UP A CHAIN OF LINKED CHUNKS
;CALL: MOV <ADR>,R0
; JSR PC,FRECNL
; RETURN
FRECNL: MOV CN.MLK(R0),-(P) ;SAVE NEXT LINKED LIST OF CHUNKS
JSR PC,FRECKS ;FREE UP THIS LINKED LIST OF CHUNKS
MOV (P)+,R0 ;RESTORE ADDRESS OF NEXT LINKED LIST
BNE FRECNL ;AND FREE IT UP TOO
RTS PC ;ALL DONE
;FRECKS -- FREE UP LINKED LIST OF CHUNKS
; CALL: MOV R0,<ADR OF 1ST CHUNK>
; JSR PC,FRECKS
FRECKS: TST R0
10$: BEQ FCNK99 ;IF NO CHUNKS LEFT DISMISS
TRACE CN
MOV @R0,-(P) ;SAVE ADR OF NEXT CHUNK
JSR PC,FRECNK ;FREE FIRST CHUNK
MOV (P)+,R0 ;GET ADR OF NEXT CHUNK
BR 10$
;FRECNK -- FREE UP (DEALLOCATE) USED CHUNK
; CALL: MOV R0,<ADR OF CHUNK>
; JSR PC,FRECNK
; RETURN
FRECNK:
SET.CD CNK
ASSERT FRECNT LO FREMAX;HAVE WE FREED ONE TOO MANY CHUNKS ?
ASSERT CHUNK R0 ;CHECK ADDRESS IS REASONABLE
ASSERT NE R0
BIC #CNKSIZ-1,R0 ;BE SURE IT POINTS TO START OF CHUNK
CMP R0,PRGEND
BLO FCNK99
CMP R0,PHYLIM
BHIS FCNK99
PIOFF ;SET LEVEL 7
CLR @R0 ;CLEAR LINK WORD IN NEW FREE CHUNK
TST LSTFRE ;IS THERE ALREADY AN OLDEST CHUNK ?
BNE 5$
MOV R0,FIRFRE ;NEW FIRST CHUNK
BR 7$
5$: MOV R0,@LSTFRE ;SET LINK WORD IN PREVIOUS OLDEST CHUNK
7$: MOV R0,LSTFRE ;SAVE ADDRESS OF OLDEST CHUNK
PION ;RESTORE PROCESSOR LEVEL
INC FRECNT
FCNK99: RTS PC
.SBTTL CLOCK (KW11) ROUTINES
;HERE BECAUSE CLOCK INTERRUPTED
CLKINT: ASSERT #<15.*60.> GE JIFFLG ;MAKE SURE LOW LEVEL IS RUNNING
INC JIFFLG ;ONE MORE JIFFY
ADD #1,LOWUP ; UP TIME OF NODE GOES UP
ADC HIGHUP
DEC SECTIC ;COUNT DOWN TO THE NEXT SECOND
BNE 10$ ;SKIP IF NOT AN EVEN SECOND
INC SECFLG ;INDICATE A SECOND HAS PASSED
MOV #JIFSEC,SECTIC ;RESTART SECOND TIMER
10$: ;
PROFILE ;JUST INCASE SOMEONE IS INTERESTED
RTI ;AND THAT'S ALL
;HERE AT LOW LEVEL WHEN CLOCK HAS GONE OFF
JIFSCN:
;THIS CODE ENABLES ONE TO CHANGE THE SPEED OF A DH LINE ON THE FLY
;WITH DDT11
.IF DF DIDLLS
MOV #0,J
DHHLC=.-2
BEQ $10$
PIOFF
CLR DHHLC
BIC #17,(J)
BIS #0,(J)
DHHLN=.-2
MOV #0,4(J)
DHHLO=.-4
PION
$10$:
.ENDC ; .IF DF DIDLLS
;HERE TO CHECK ALL DDB'S ONCE EACH TICK
.IF NE DEVN
MOV FIRDDB,J ;GET FIRST DEVICE BLOCK
10$: SPL 7 ;INHIBIT INTERRUPTS
TSTB DB.TIM(J) ;IS TIMER RUNNING FOR DEVICE ?
BLE 20$
DECB DB.TIM(J)
BNE 20$
MOVB DB.TIM+1(J),R0 ;GET TIMER TYPE CODE
CLR DB.TIM(J)
SPL 0 ;ENABLE INTERRUPTS
JSR PC,@DB.TPC(J) ;DISPATCH TO DEVICE DEPENDENT ROUTINE
20$: SPL 0 ;ENABLE INTERRUPTS
MOV DB.LNK(J),J ;GET NEXT DEVICE BLOCK ADR
BNE 10$
.ENDC;.IF NE DEVN
;HERE TO CHECK TASKS ONCE EACH TICK
.IF NE FT.TSK
MOV #FIRTSK,J ;GET ADR OF FIRST TASK BLOCK
30$: TST TK.TIM(J) ;ARE WE TIMING ?
BEQ 36$ ;IF NOT DONE
DEC TK.TIM(J) ;COUNT TIMER
BNE 36$
BIC #TK.SLP,@J ;CLEAR SLEEP BIT
JSR PC,TSKWAK ;WAKE THE TASK
36$: MOV TK.LNK(J),J ;GET NEXT TASK BLOCK
BNE 30$
.ENDC;.IF NE FT.TSK
;HERE TO CHECK DM11-BB'S EVERY 167 MS (EVERY 10 TICKS)
.IF NE FTDM11!NDZ11
SUB JIFFLG,DSCLCK ;COUNT DOWN THE DATA-SET TIMER
BGT 40$ ;DON'T CHECK MODEMS TILL NEGATIVE
.IIF NE FTDM11,JSR PC,DMSCN ;CALL DM11 CLOCK ROUTINE IN DNDM11
.IIF NE NDZ11,JSR PC,DZSCN
MOV #DSCSPD,DSCLCK ;RESET TIMER FOR NEXT TIME
40$:
.ENDC
;HERE TO CALL NCL SO IT CAN RE-ROUTE ANY MESSAGES IT MAY NEED TO
JSR PC,NCLJIF ;DO NCL JIFFY PROCESSING
;HERE TO SEE IF IT'S TIME TO DO DDCMP REP CHECKING. THIS IS DONE
;EVERY "REPSPD" TICKS
.IF NE NTLINE
SUB JIFFLG,RPCLCK ;COUNT OFF THE JIFFYS
BGT 50$ ;IF STILL POS THEN DON'T CHECK YET
JSR PC,REPCHK ;CHECK FOR DDCMP TIMEOUTS
MOV #REPSPD,RPCLCK ;RESET TIMER FOR NEXT CHECK
50$:
.ENDC ;.IF NE NTLINE
;HERE TO SEE IF A SECOND HAS PASSED, AND IF SO CALL THE ROUTINE
;THAT PROCESSES ONCE / SECOND STUFF
TST SECFLG ;HAS A SECOND PASSED ?
BEQ 90$ ;IF NOT, DON'T CALL SECOND SCAN
JSR PC,SECSCN ;A SECOND HAS PASSED, CALL SECSCN
CLR SECFLG ;RESET IT FOR NEXT TIME
90$: RTS PC ;RETURN BACK TO THE MAIN LOOP
;HERE ONCE PER SECOND
SECSCN:
.IF NE FTDL10!FT.DTE
JSR PC,TENSEC ;DO DL10/DTE SECOND SCAN
.ENDC
;HERE ONCE A SECOND TO CHECK EACH LINE
SEC.10:
.IF NE NTLINE
MOV #FRSTLB,J ;SCAN LINE BLOCK STARTING WITH FIRST
BR 90$
05$:
; JSR PC,SL.SEC ;DRIVER ONCE PER SEC CHECK
.IF NE FT.MPT
BIT #LS.MPT,(J) ;IF MULTIPOINT
BEQ 10$
BITB #MP.SEL,LB.MPS(J) ;AND IF SELECTED
BEQ 90$
TSTB LB.MPT(J) ;AND IF SELECTION TIMER RUNNING
BEQ 10$
DECB LB.MPT(J) ; DECREMENT TIME LEFT
;IF TIME RAN OUT
BNE 10$
JSR PC,SELNXT ;MUST FORCE SELECT TO BE SENT
.IF NE FTTRIB
TST LB.MPL(J) ;IF YOU'RE A TRIBUTARY
BNE 9$
BISB #MP.SNM,LB.MPS(J) ;YOU MUST SEND A SELECT
CLRB LB.MPT(J) ;AND STOP THE TIMER
BR 10$
9$:
.ENDC
BITB #MP.SFF,LB.MPS(J) ;IF COUNTER RAN OUT
BNE 07$
.IF NE FT.RDM!FT.RDP
JSR R0,RDESST ;IF A RDE DEV, REPORT THE STATE
.BYTE 0,240
.ENDC
JSR PC,L.DOWN ;PUT THE STATION OFFLINE
BR 90$
07$: DECB LB.MPS(J) ;DECREMENT THE FAILURE COUNTER
.ENDC
10$:
40$: TSTB LB.BNN+1(J) ;IF BOOT MODE, ITS TIMER IS RUNNING
BEQ 90$ ;IF NOT WE ARE DONE
INCB LB.BNN+1(J)
BNE 90$
CLR LB.BNN(J) ;REVOKE EXCLUSIVE LICENSE
90$: MOV LB.LNK(J),J ;NOW TRY THE NEXT LINE BLOCK
BNE 05$ ;IF THERE IS ONE
.ENDC;.IF NE NTLINE
.IF NE FTDCP3!FTDCP4 ;NSP CODE HAS CLOCK STUFF TOO
JSR PC,NSPSEC ;CALL IT
.ENDC
;HERE ONCE A SECOND TO CHECK EACH SCB
SECNCL: MOV #OURSCB,SB ;GET 1ST STATION BLOCK
BR 82$
10$: BIT #SBF.IU,@SB ;IS BLOCK IN USE ?
BEQ 82$ ;IF NOT DON'T CHECK IT
MOV SB,DNA ;SAVE DESTINATION ADR
JSR PC,NCLQRQ
MOV #SQNTAB,SQNODE
20$: MOV @SQNODE,SNA ;IS THERE A SOURCE FOR THIS SLOT ?
BEQ 80$ ;BRANCH IF DONE WITH SEQUENTIAL NODES
MOV SB,R0 ;COPY SCB POINTER
ADD #SB.IMQ-CN.MLK,R0 ;POINT TO INPUT MSG QUEUE
JSR PC,TIMQUE ;CHECK FOR ANTIQUE ENTRIES
.WORD FRECKS
TSTB SB.TIM(SB) ;ARE WE TIMING ?
BEQ 50$
DECB SB.TIM(SB) ;DECREMENT TIMER
BNE 50$ ;BRANCH IF TIMER HASN'T GONE OFF
JSR PC,NCLSEC ;GO DO ONCE A SECOND NCL STUFF
50$: ADD #2,SQNODE ;ADVANCE TO NEXT SEQUENTIAL NODE
ADD #SQNSIZ,SB ;ADVANCE TO NEXT SNA
BR 20$
80$: MOV DNA,SB ;GET SCB ADR AGAIN
82$: SB.ADV 10$ ;GET NEXT STATION BLOCK
;HERE ONCE A SECOND TO CHECK DEVICES
.IF NE DEVN
SECDEV: MOV FIRDDB,J ;GET FIRST DEVICE BLOCK
Z=DS.COR
.IIF NE FT.TSK,Z=Z!DS.PAU
10$: BIT #Z,@J ;DOES DEVICE WANT TO RUN AGAIN ?
BEQ 20$
TWIDDLE ;COUNT TIMES THIS HAPPENS
BIC #Z,@J ;CLEAR REQUEST
JSR PC,QUEDEV ;REQUEST EXECUTION
20$: SPL 7 ;INHIBIT INTERRUPTS
TSTB DB.TIM(J) ;IS SECONDS TIMER RUNNING
BPL 22$
INCB DB.TIM(J) ;IF SO INCREMENT IT
BNE 22$
MOVB DB.TIM+1(J),R0 ;IF TIMER RAN OUT, GET FUNCTION CODE
CLR DB.TIM(J)
SPL 0 ; ENABLE INTERRUPTS
JSR PC,@DB.TPC(J) ;AND SERVICE THE TIMER
22$: SPL 0 ;ENABLE INTERRUPTS
.IF NE FTDN11
.IF NE FT.RDA
BIT #RDEASC,DB.RDT(J)
BNE 23$
.ENDC
BIT #DS.TTY,@J ;IS THIS A TTY ?
BEQ 30$
.IF NE FT.CTY
CMP J,#CTYDDB
BEQ 30$
.ENDC;.IF NE FT.CTY
23$: BITB #DNTIME,DB.DNT(J) ;DN11 TIMER GOING?
BEQ 30$ ;NO, CHECK DATASET STATUS
.IF NE FT.CHK
BITB #40,DB.DVT(J) ;AUTO DIAL LINE?
ASSERT NE ;IT HAD BETTER BE!
BITB #DNDIAL,DB.DNS(J) ;UNDER CONTROL OF DN11/801?
ASSERT NE ;IT HAD BETTER BE!
.ENDC;.IF NE FT.CHK
DECB DB.DNT(J) ;DECREMENT TIMER
MOVB DB.DNT(J),R0 ;AND GET NEW VALUE
BITB #DNTIME,R0 ;TIMER EXPIRED?
BNE 30$ ;NO, DONE
BIC #177477,R0 ;CLEAR UNWANTED BITS
ASL R0 ;PUT CODE
ASL R0 ;INTO RIGHT
ASL R0 ;PLACE
SWAB R0
JSR PC,@DNTDSP(R0) ;EXECUTE TIMER ROUTINE
BR 30$ ;DO NEXT DDB
.ENDC;.IF NE FTDN11
30$: MOV DB.LNK(J),J ;GET NEXT DEVICE BLOCK
BNE 10$
.ENDC;.IF NE DEVN
;HERE IS THE ONCE / SECOND STUFF FOR TASKS.
.IF NE FT.TSK
MOV TASK,J ;GET ADDR OF RUNNING TASK
BEQ 40$ ;SKIP IF NONE
SUB SECFLG,TK.QTM(J) ;COUNT DOWN HIS QUANTUM
40$:
.ENDC
;HERE IS SOME CODE THAT SUPPORTS THE SINK MACRO
ND LPTSNK,0 ;USE THE LPT FOR SINK ONLY IF REQUESTED
.IF NE LPTSNK
SINK LP0DDB
.IFF
SINK CTYDDB
.ENDC ;.IF NE LPTSNK
CTYMSG ;CTY LOGGING
;
;******** here is a convenient place for source macro calls ******
;
;HERE TO CHECK IF A MINUTE HAS PASSED, AND IF SO CALL ONCE/MINUTE CODE
SUB SECFLG,MINTIC ;COUNT DOWN TO NEXT MINUTE
BGT 90$ ;BRANCH IF HASN'T PASSES
JSR PC,MINSCN ;BRANCH TO ONCE/MINUTE ROUTINE
MOV #60.,MINTIC ;RESET MINUTE TICKER
90$: RTS PC ;POP BACK TO MAIN LOOP
;HERE IS THE ONCE / MINUTE CODE (A GOOD PLACE FOR DEBUGING CHECKS)
MINSCN:
RTS PC ;POP BACK TO MAIN LOOP
;HERE TO CHECK FOR DDCMP REP TIMEOUTS
.IF NE NTLINE
REPCHK: MOV #FRSTLB,J ;SCAN LINE BLOCKS STARTING WITH THE FIRST
BR 10$
15$:
.IIF NE FTDUP11,JSR PC,DUPJIF ;KISS THE DUP'S A ONCE IN A WHILE
.IF NE FT.MPT
BIT #LS.MPT,(J) ;IF NOT MULTIPOINT, GO AHEAD AND CHECK IT
BEQ 12$
BITB #MP.SEL,LB.MPS(J) ;ELSE IF NOT SELECTED,SKIP THE LINE
BEQ 10$
.ENDC
12$: DEC LB.REP(J) ;POKE THE TIMER
BGT 10$
JSR PC,DDCSEC ;IF TIMER RAN OUT, DO SOMETHING
10$: MOV LB.LNK(J),J ;STEP TO NEXT BLOCK, AND LOOP
BNE 15$
RTS PC ;EXIT IF NO BLOCK
.ENDC ;.IF NE NTLINE
;HERE TO TIME ENTRIES IN A QUEUE
; CALL MOV #FOO,R0 ;POINTER TO FIRST ENTRY IN QUEUE
; JSR TIMQUE
; .WORD WHERE ;TO GO WHEN ENTRY HAS EXPIRED
; RETURN
TIMQUE: BR 20$
10$: MOV R1,R0
20$: MOV CN.MLK(R0),R1 ;GET POINTER TO NEXT MSG
BEQ 90$ ;IF NO MORE WE ARE DONE
DEC CN.TIM(R1) ;DECREMENT TIMER
BNE 10$
TWIDDLE ;COUNT DEAD MSGS
MOV CN.MLK(R1),CN.MLK(R0) ;DELINK OBSOLETE MSG
MOV R0,-(P) ;SAVE GOOD POINTER
MOV R1,R0 ;POINT TO DEAD MSG
MOV @2(P),R1 ;GET ADR OF WHERE TO GO
JSR PC,@R1 ;DISPOSE OF MESSAGE
MOV (P)+,R0 ;GET GOOD POINTER BACK
BR 20$
90$: ADD #2,@P
RTS PC