Trailing-Edge
-
PDP-10 Archives
-
BB-F492Z-DD_1986
-
10,7/703anf/dncomm.p11
There are 3 other files named dncomm.p11 in the archive. Click here to see a list.
.SBTTL DNCOMM - MAIN LOOP AND CLOCK ROUTINES 12 FEB 85
;COPYRIGHT (C) 1976,1979,1980,1981,1984 BY
;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.
VRCOMM=065 ;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 ?
BNE 14$ ; YES
.IF NE FT.RDA
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