Trailing-Edge
-
PDP-10 Archives
-
tops10_704_monitoranf_bb-x140c-sb
-
10,7/anf10/dntsk.p11
There are 3 other files named dntsk.p11 in the archive. Click here to see a list.
.SBTTL DNTSK - TASK ROUTINES 28 MAR 79
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1976,1977,1978,1979,1980,1981,1984,1988.
;ALL RIGHTS RESERVED.
VRTSK=013 ;FILE EDIT NUMBER
.SBTTL TASK BLOCK DEFINITIONS
.IF NE FT.TSK
BLOCK TK ;DEFINE X & XX MACROS
X STS,1 ;STATUS WORD
TK.RUN=100000 ;TASK IS RUNNABLE
TK.LGI=040000 ;JOB IS LOGGED IN - I.E. HASN'T EXITED YET
TK.TRG=020000 ;TASK HAS BEEN TRIGERRED BY ANOTHER TASK
TK.WAK=010000 ;SOMETHING HAS OCCURED TO WAKE TASK
TK.NOP=004000 ;DEVICE ON THIS CALL WAS NOT OPENED
TK.SLP=002000 ;SLEEP BIT WILL NOT WAKE UNTIL SPECIFIED NO OF
;COUNTS (IN JIFFIES) HAS OCCURRED OR HOST DIES
X LNK,1 ;LINK TO NEXT TASK BLOCK
X RQL,1 ;RUN QUEUE LINK
X PRI,1 ;POINT TO PRIORITY QUEUE
X JSA,1 ;ADDRESS TO CONTINUE TASK
X RSA,1 ;ADDRESS TO USE ON A RESTART
X PDL,2 ;1ST WORD IS ADR OF PDL, 2ND WORD IS CURRENT PDL POINTER
X ZER,0 ;START CLEARING HERE ON A RESTART
X TIM,1 ;SECOND TIMER
XX QTM,1 ;QUANTUM TIME - COUNTS TICKS WITHOUT INTERRUPTION
X TPC,1 ;ROUTINE TO GO TO WHEN CLOCK GOES OFF
X DTK,1 ;DB.TSK FOR CURRENT SVC
X SPT,1 ;SEND QUEUE PUTTER
X STK,1 ;SEND TAKER
X SQU,TKSQSZ ;SEND QUEUE
X ARG,1 ;SAVE VALUE TO RETURN TO CALLER
X SIZ,0 ;SIZE OF TASK BLOCK
;MACRO TO DEFINE TASKS FOR THE SYSTEM
; 1ST ARGUMENT IS 3 CHAR TASK NAME
; 2ND ARGUMENT IS TASK STARTING ADDRESS
; 3RD ARGUMENT IS THE RESTART ADDRESS
; 4TH ARGUMENT IS THE TASK PRIORITY
; 5TH ARGUMENT IS THE STACK SPACE THE TASK WILL USE
.MACRO TSKGEN JOBNAM,JBSA,JBRSA,PRIOR,PDLSIZ
TSKNUM=TSKNUM+1
.EVEN
FIRTSK=.
JOBNAM'TKB:
.WORD 0 ;TK.STS
.WORD TSKLNK ;TK.LNK
TSKLNK=FIRTSK
.WORD 0 ;TK.RQL
Z=RUNQUE+<2*PRIOR>-TK.RQL
.WORD Z ;TK.PRI
.WORD JBSA ;TK.JSA
.WORD JBRSA ;TK.RSA
.WORD .-TK.PDL+TK.SIZ+<2*PDLSIZ>+60 ;INITIAL PDL POINTER
.BLKW 1 ;TK.PDL+2(CURRENT PDL POINTER)
.BLKB TK.SIZ-TK.ZER
.BLKW PDLSIZ+30
.ENDM TSKGEN
TSKNUM=0
TSKLNK=0
;MACRO TO GET A CHUNK OF FREE CORE
.MACRO CNKGET DATA
.NTYPE Z,DATA
;.IF EQ <R0-Z>
; JSR PC,GETCNK ;JUST GET A CHUNK
;.IFF
CLR -(P) ;WE WILL PUT CHUNK ADR HERE LATER
MOV R0,-(P) ;SAVE REGISTER
CLR R0 ;ASSUME NO CHUNKS
CMP #ERSCNT*2,FRECNT ;WANT TASK TO FAIL BEFORE SYSTEM
BGE .+6 ;OK TO CONTINUE
JSR PC,GETCNK ;TRY TO GET SOME FREE CORE
MOV R0,2(P) ;SAVE ADR OF CHUNK
MOV (P)+,R0 ;GET ADR OF CHUNK BACK
MOV (P)+,DATA ;GIVE USER ADR OF CHUNK
;.ENDC;.IF EQ <R0-Z>
.ENDM CNKGET
;MACRO TO RETURN A CHUNK OF FREE CORE
.MACRO CNKFRE DATA
MOV R0,-(P) ;SAVE REGISTER
MOV DATA,R0 ;GET ADDRESS OF CHUNK
JSR PC,FRECNK ;RELEASE CHUNK
MOV (P)+,R0 ;RESTORE REGISTER
.ENDM CNKFRE
;MACRO TO GET 32 BIT UPTIME
.MACRO TIMER DATA
MOV LOWUP,DATA ;GET UPTIME
.NTYPE Z,DATA
.IF EQ <Z&70>
MOV HIGHUP,DATA+1 ;PUT HIGH BITS IN NEXT REG
.IFF
MOV HIGHUP,DATA+2 ;GET HIGH ORDER BITS
.ENDC;.IF EQ <Z&70>
.ENDM TIMER
;MACROS WHICH GENERATE SUPERVISOR CALLS
; FORMAT OF CALL IS:
; IOT
; .BYTE CODE,FLAGS
; TTY # (-1 = CTY) OR TSK BLOCK ADR
; ARG1 (OR 0)
; ARG2 (OR 0)
; FLAGS ARE:
IO.NBK=001 ;CALL DOESN'T WANT TO BLOCK
IO.KYB=002 ;CALL IS FOR KEYBOARD
IO.PUT=004 ;CALL IS FOR PUTS
IO.IDX=006 ;IO INDEX IS OR OF IO.KYB & IO.PUT
IO.ARG=010 ;ARGUMENT IS REG
IO.AR2=020 ;ARG2 IS IN A REG
IO.AR1=040 ;ARG1 IS IN A REG
; CODES WHICH HAVE BEEN ASSIGNED ARE:
; 0 ;OPEN
; 2 ;GET
; 4 ;PUT
; 6 ;RELEASE
; 10 ;IMGPUT (ONLY FOR DH11 OUTPUT)
; 12 ;GET BIT
; 14 ;SET BIT
; 16 ;CLEAR BITS
; 20 ;DIAL
; 200 ;WAKE
; 202 ;TRIGGER
; 204 ;SEND
; 206 ;RECEIVE
; 210 ;HIBER
; 212 ;EXIT
; 214 ;SLEEP
;MACRO TO PUT CALLS INTO RIGHT FORMAT
.MACRO UUOARG ARG
.IF NB <ARG>
FOOEY=FOOEY&077777
.IF IDN <ARG><PUT>
Z=Z!IO.PUT
FOOEY=FOOEY!100001 ;HAVE SET PUT/GET
.ENDC;.IF IDN <ARG><PUT>
.IF IDN <ARG><GET>
FOOEY=FOOEY!100002 ;HAVE SET PUT/GET
.ENDC;.IF IDN <ARG><GET>
.IF IDN <ARG><NONBLOCKING>
Z=Z!IO.NBK
FOOEY=FOOEY!100004 ;HAVE SET BLOCKING/NONBLOCKING
.ENDC;.IF IDN <ARG><NONBLOCKING>
.IF IDN <ARG><BLOCKING>
FOOEY=FOOEY!100010 ;HAVE SET BLOCKING/NONBLOCKING
.ENDC;.IF IDN <ARG><BLOCKING>
.IF IDN <ARG><KEYBOARD>
Z=Z!IO.KYB
FOOEY=FOOEY!100020 ;HAVE SET PRINTER/KEYBOARD
.ENDC;.IF IDN <ARG><KEYBOARD>
.IF IDN <ARG><PRINTER>
FOOEY=FOOEY!100040 ;HAVE SET PRINTER/KEYBOARD
.ENDC;.IF IDN <ARG><PRINTER>
.IF EQ <FOOEY&100000>
.ERROR ARG ;CAN'T RECOGNIZE MACRO ARGUMENT
.ENDC;.IF EQ <FOOEY&100000>.ENDC;.IF NB <ARG>
.ENDC;.IF NB <ARG>
.ENDM UUOARG
.MACRO UUO CODE,RDWRT,IO,MODE,DEV,ARG1,ARG2
FOOEY=0 ;COLLECT INFORMATION ABOUT ARGUMENTS HERE
IOT ;THIS IS SUPERVISOR CALL INSTRUCTION
Z=0
UUOARG RDWRT
UUOARG IO
UUOARG MODE
.IF NB <DEV>
.NTYPE ZZ,DEV
.IIF EQ <ZZ&70>,Z=Z!IO.ARG
.ENDC;.IF NB <DEV>
.IF NB <ARG1>
.NTYPE ZZ,ARG1
.IIF EQ <ZZ&70>,Z=Z!IO.AR1 ;ARG1 IN A REGISTER ?
.ENDC;.IF NB <ARG1>
.IF NB <ARG2>
.NTYPE ZZ,ARG2
.IIF EQ <ZZ&70>,Z=Z!IO.AR2 ;ARG2 IN A REGISTER ?
.ENDC;.IF NB <ARG2>
.BYTE CODE,Z
.WORD DEV ;TSK BLOCK ADR OR TTY #
.IF NB ARG1
.WORD ARG1 ;ARG1
.IFF
.WORD ZERO ;DEFAULT ZERO
.ENDC;.IF NB ARG1
.IF NB ARG2
.WORD ARG2 ;ARG2
.IFF
.WORD ZERO ;DEFAULT IS ZERO
.ENDC;.IF NB ARG2
.ENDM UUO
;MACRO FOR A TASK TO KILL ITSELF
.MACRO EXIT
UUO 212,,,,0,0,0
.ENDM EXIT
;MACRO TO PAUSE IN EXECUTION
.MACRO HIBER ARG1
UUO 210,,,,0,ARG1,0
.ENDM HIBER
;MACRO TO WAKE ANOTHER TASK
.MACRO WAKE JOBNAM
UUO 200,,,,JOBNAM'TKB,0,0
.ENDM WAKE
;MACRO TO BEGIN ANOTHER TASK
.MACRO TRIGER JOBNAM
UUO 202,,,,JOBNAM'TKB,0,0
.ENDM TRIGER
;MACRO TO SEND A MESSAGE TO A TASK
.MACRO SEND JOBNAM,ARG1,MODE
UUO 204,,,MODE,JOBNAM'TKB,ARG1,0
.ENDM SEND
;MACRO TO PICK UP ENTRIES FROM SEND QUEUE
.MACRO RECEIVE ARG1,MODE
UUO 206,,,MODE,0,ARG1,0
.ENDM RECEIVE
;IO MACROS
;MACRO TO REQUEST EXCLUSIVE USE OF A TTY
.MACRO OPEN DEV,IO,RDWRT
UUO 0,RDWRT,IO,,DEV,0,0
.ENDM OPEN
;MACRO TO GET INPUT FROM A TTY
.MACRO GET DEV,IO,MODE,ARG1
UUO 2,GET,IO,MODE,DEV,ARG1,0
.ENDM GET
;MACRO TO WRITE ON A TTY
.MACRO PUT DEV,IO,MODE,ARG1
UUO 4,PUT,IO,MODE,DEV,ARG1,0
.ENDM PUT
;MACRO TO FREE UP A TTY
.MACRO RELEASE DEV,IO,RDWRT
UUO 6,RDWRT,IO,,DEV,0,0
.ENDM RELEASE
;MACRO TO TRANSMIT A STRING ON DH11 LINE(NO FILLERS ETC.)
; ARG1 IS LENGTH
; ARG2 IS ADR OF STRING
.MACRO IMGPUT DEV,IO,MODE,ARG1,ARG2
UUO 10,PUT,IO,MODE,DEV,ARG1,ARG2
.ENDM IMGPUT
;MACRO TO PUT TASK TO SLEEP
.MACRO SLEEP ARG1
UUO 214,,,,0,ARG1,0
.ENDM SLEEP
;MACRO TO GET STATUS BITS FROM RDA OR TTY DEVICE BLOCK
.MACRO GETBIT DEV,ARG1
UUO 12,,,,DEV,ARG1,0
.ENDM GETBIT
;MACRO TO SET STATUS BITS IN RDA OR TTY DEVICE BLOCK
.MACRO SETBIT DEV,ARG2,ARG1
UUO 14,,,,DEV,ARG1,ARG2
.ENDM SETBIT
;MACRO TO CLEAR STATUS BITS IN RDA OR TTY DDB
.MACRO CLRBIT DEV,ARG2,ARG1
UUO 16,,,,DEV,ARG1,ARG2
.ENDM CLRBIT
;MACRO TO ALLOW TASK TO DIAL OUT
;INITIATE A STATUS REQUEST OR TERMINATE A CALL
;
;
; THE FORMAT OF THE CALL:
; DIAL LINE#,BLOCKING,TYPE,ADR
; TYPE IS ONE OF THE FOLLOWING
; 0 - TERMINATE PREVIOUS CALL
; 1 - SEND DIAL STATUS TO WORD POINTED TO BY ADR
; 2 - INITIATE A DIAL REQUEST. THE NUMBER TO DIAL
; IS POINTED TO BY ADR
;
; AUTO DIAL STATUS
DNRREQ=000200 ;AUTO DIAL REQ OUTSTANDING SET BY MACRO CLEARED IN RDXSER
DNRERR=100000 ;ERROR ON PREVIOUS CALL
DNREAD=000010 ;AUTO DIAL FAILURE
DNRANS=000020 ;CALL ANSWERED
DNRENC=000040 ;NO CARRIER SET FOR NO ANSWER, BUSY, OR DROPPED CARRIER IN MIDDLE OF CALL
DNREBY=000100 ;ALREADY DIALING NUMBER
;
;
.MACRO DIAL DEV,MODE,ARG1,ARG2
UUO 20,,,MODE,DEV,ARG1,ARG2
.ENDM DIAL
.ENDC;.IF NE FT.TSK
.SBTTL SCHEDULE BACKGROUND TASKS
;HERE TO SCHEDULE A TASK TO EXECUTE
;CALL (FROM LOOP)
; JSR PC,LOOPTK
.IF NE FT.TSK
LOOPTK: MOV #RUNQUE,R0 ;LOCATE THE RUN QUEUES
10$: MOV (R0)+,J ;GET THE TASK ON THIS QUEUE
BNE 60$ ;IF THERE IS ONE RUN IT
CMP R0,#RUNQUE+<TKPMAX*2> ;IF THERE IS ANOTHER QUEUE,
;BETTER TRY THAT ONE
BLO 10$
RTS PC ;EXIT
60$:
;CHECK THINGS ARE STILL OK
.IF NE FT.CHK
BIT #TK.SLP,@J ;TASK SLEEPING
CHK EQ ;TROUBLE IF IT IS!
.ENDC ;END IF NE FT.CHK
MOV SP,LPTKSP ;SAVE SYSTEM PDL
MOV J,TASK ;REMEMBER WHO WAS RUNNING
MOV TK.PDL+2(J),P ;GET NEW STACK POINTER
RESTORE <R5,R4,R3,R2,R1,R0>
RTS PC ;DISPATCH TO TASK
;HERE WHEN TASK DONE EXECUTING
LOPTK7: SAVE <R0,R1,R2,R3,R4,R5> ;SAVE REGISTERS FOR TASK
MOV TASK,J ;GET POINTER TO TASK BLOCK
MOV P,TK.PDL+2(J) ;SAVE STACK POINTER
MOV (PC)+,SP ;RESTORE SYSTEM PDL
LPTKSP: 0 ;SP AT ENTRY TO LOOPTK
CLR TASK ;FLAG NOT RUNNING USER
RTS PC ;EXIT
.ENDC;.IF NE FT.TSK
.SBTTL TASK HANDLING
.IF NE FT.TSK
IOTINT: BIC #17,2(P) ;CLEAR BITS IN USERS PS
MOV 2(P),PS ;SET PROCESSOR LEVEL
SAVE <R5,R4,R3,R2,R1,R0> ;SAVE ALL REG'S ON STACK
MOV 14(P),R3 ;GET CALLING PC
MOV (R3)+,R0 ;GET DISPATCH AND FLAGS
MOV R0,R1 ;COPY FLAGS
SWAB R1
MOVB R1,@TASK ;SAVE FLAGS
MOV (R3)+,J ;GET DEVICE NUMBER
MOV (R3)+,R2 ;GET DATA ADR
MOV (R3)+,R1 ;GET ARG2
BIT #IO.AR1*400,R0 ;IS ARG1 IN A REG ?
BEQ 12$
ASL R2 ;CONVERT TO WORD OFFSET
ADD P,R2 ;POINT TO PLACE ON STACK
12$:
BIT #IO.AR2*400,R0 ;IS ARG2 IN A REG?
BEQ 11$ ;NO
ASL R1 ;POINT TO REG ON STACK
ADD P,R1
11$:
SAVE <J>
MOV TASK,J
TSTB TK.QTM(J) ;CHECK QUANTUM TIME
BNE 17$ ;SKIP IF TIME STILL LEFT
PIOFF
BIS #TK.SLP,@J ;PUT TASK TO SLEEP
MOV #4*TKQTIM,TK.TIM(J) ;FOR 4 QUANTUM TIMES
JSR PC,STPTSK
PION
JSR PC,LOPTK7 ;GO TO MAIN SCHEDULAR
17$:
MOV R2,TK.ARG(J) ;SAVE VALUE TO RETURN TO CALLER
RESTORE <J>
MOV R3,14(P) ;SO WE RETURN TO RIGHT PLACE
MOV R0,R3 ;COPY FLAGS AND DISPATCH
BIC #^C77,R0 ;STRIP FLAG BITS
TSTB R3 ;IS THIS AN IO CALL ?
BMI 20$
BIT #IO.ARG*400,R3 ;WAS ARGUMENT IN A REG ?
BEQ 14$
ASL J ;CONVERT REG ADR TO WORD
ADD P,J ;POINT TO RIGHT POINT ON STACK
14$: MOV @J,J ;GET ARGUMENT
.IIF NE FT.CTY, CMP J,#-1 ;CHECK FOR CTY OR GREATER
BMI IOTBUM ;IF TOO SMALL REJECT
CMP J,#TTYN+RDAN ;RANGE CHECK
BPL IOTBUM ;AND FLUSH LOSING CALLS
ASL J ;SO WE CAN INDEX INTO TABLE
MOV TTYTAB(J),J ;CONVERT TO DEVICE BLOCK ADDRESS
JMP @IOTDSP(R0) ;DISPATCH ON TYPE
20$: JMP @SVCDSP(R0) ;DISPATCH ON TYPE
IOTBUM: BIS #10,16(P) ;SET N BIT FOR LOSER
BR IOTFIN
;HERE TO RETURN DATA TO USER, DATA IN R0
IOTRET:
MOV TASK,J
MOV R0,@TK.ARG(J) ;RETURN RESULT TO USER
CLR ZERO
IOTFIN: MOV TASK,J ;POINT TO CURRENT TASK BLOCK
BIT #TK.NOP,@J ;WAS DEVICE OPENED OR NOT USED ?
BEQ 10$ ;CAUZ THAT'S SIMPLE
CLR @TK.DTK(J) ;FORGET WHO USED DEVICE LAST
BIC #TK.NOP,@J ;ASSUME NEXT DEVICE IS OPENED
10$: RESTORE <R0,R1,R2,R3,R4,R5> ;RESTORE ALL REG'S
.IF NE NLINES
CMP QI.PTR,QI.TKR ;DDCMP WAITING ?
BNE 80$
.ENDC;.IF NE NLINES
TSTB JIFFLG ;SHOULD WE PAUSE ?
BEQ 90$
80$: JSR PC,LOPTK7 ;YES
90$: RTI
SVCDSP: WAKTSK ;CODE (200) WAKE TASK
TRGTSK ;CODE (202) TRIGER TASK
SNDTSK ;CODE (204) SEND TO TASK
RCVTSK ;CODE (206) RECEIVE FROM TASK
HIBER. ;CODE (210) HIBER
TSKEND ;CODE (212) EXIT
SLEEP. ;CODE (214) SLEEP
IOTDSP: IOTOPN ;CODE (0) OPEN
IOTGET ;CODE (2) GET
IOTPUT ;CODE (4) PUT
IOTREL ;CODE (6) RELEASE
IOTIMP ;CODE (10) IMGPUT
IOTGTB ;CODE (12) GET BIT
IOTSET ;CODE (14) SET BIT
IOTCLR ;CODE (16) CLEAR BITS
IOTDNL ;CODE (20) DIAL
;HERE FOR AN OPEN MACRO
IOTOPN: JSR PC,IOCOWN ;SEE IF HE CAN HAVE IT
BIC #TK.NOP,@TASK ;DEVICE WAS OPENED
BR IOTFIN ;RETURN
;HERE FOR A GET MACRO
IOTGET: JSR PC,IOCOWN ;CHECK USER OWNS DEVICE
BEQ 50$ ;BRANCH IF GETTING PRINTER
;HERE IF GETTING A CHAR FROM KEYBOARD
10$: MOV DB.KTK(J),R1 ;GET KEYBOARD TAKER
CMP R1,DB.KPT(J) ;IS THE KEYBOARD DATA IN QUEUE ?
BNE 20$ ;IF SO GET IT
JSR PC,IOTIOW ;WAIT A WHILE
BR 10$ ;AND CHECK AGAIN
20$: ADD J,R1 ;RELOCATE ADDRESS
MOV (R1)+,R0 ;GET DATA
SUB J,R1 ;MAKE ADDRESS RELATIVE AGAIN
CMP R1,#DB.KQU+TQS+TQS ;IS THAT END OF QUEUE ?
BNE 24$
MOV #DB.KQU,R1 ;YES SO RESET POINTER
24$: MOV R1,DB.KTK(J) ;SAVE POINTER
BR IOTRET ;RETURN DATA TO USER
;HERE IF GETTING CHAR FROM PRINTER (=NCL)
50$: TST DB.TOC(J) ;ANY CHARS IN QUEUE ?
BNE 52$ ;IF SO HE WINS ONE
JSR PC,IOTIOW ;WAIT FOR ONE
BR 50$
52$: MOV DB.TOB(J),R0 ;GET PRINTER TAKER
MOVB (R0)+,R1 ;GET NEXT CHARACTER
ADVCNK R0 FREE
54$: MOV R0,DB.TOB(J) ;SAVE TAKER
DEC DB.TOC(J) ;COUNT CHAR OUT
BNE 60$
TST R0
BEQ 55$
BIC #CNKSIZ-1,R0 ;POINT TO ADR OF CHUNK
JSR PC,FRECNK ;RELEASE CHUNK
55$: CLR DB.TOB+2(J) ;NO MORE PUTTER
CLR DB.TOB(J) ;AND NO MORE TAKER
60$: MOV R1,R0 ;PUT DATA IN RIGHT REG FOR RETURN
MOV R1,#0
66$: JMP IOTRET ;RETURN DATA TO USER
;HERE FOR A PUT MACRO
IOTPUT: JSR PC,IOCOWN ;CHECK USER OWNS DEVICE
BNE 20$ ;IN CASE PUTTING TO KEYBOARD=NCL
;HERE FOR A PUT TO PRINTER
10$: CMP #ERSCNT,FRECNT ;ANY ROOM LEFT ?
BMI 14$ ;IF SO PROCEDE
BIT #DS.ACT,@J ;IS PRINTER RUNNING ?
BEQ 14$ ;IF NOT LET HER RIP
JSR PC,IOTIOW ;WAIT FOR CORE TO BE AVAILABLE
BR 10$
14$: PIOFF
MOV DB.PPT(J),R0 ;GET PRINTER PUTTER
BNE 16$
JSR PC,ERSGET ;GET A CHUNK FOR CHAR
TST (R0)+ ;SKIP LINK WORD
MOV R0,DB.PTK(J) ;INITIALIZE THE TAKER
16$: ADVCNK R0 EXTEND
18$: MOVB @R2,(R0)+ ;PUT CHAR INTO QUEUE
MOV R0,DB.PPT(J) ;SAVE UPDATED PUTTER
INC DB.PCN(J) ;COUNT CHAR
PION
JSR PC,BEGXMT ;BEGIN TYPING
JMP IOTFIN
;HERE FOR A PUT TO KEYBOARD (=NCL)
20$:
BIT #DS.DIE!DS.DSC,@J ;IS HOST DOWN
BNE 30$
BIT #DS.CON,@J ;ARE WE STILL CONNECTED
BEQ 30$
CMPB #TTYMIC,DB.ICC(J) ;IS MSG ALREADY FULL ?
BPL 26$
23$: JSR PC,IOTIOW ;WAIT OR GIVE ERROR RETURN
BR 20$
26$: MOVB @R2,R0 ;GET DATA
BIC #^C377,R0 ;MASK OUT GARBAGE
BIS #DS.PAU,@J ;SET PAUSE FOR LINE EFFICIENCY
JSR PC,RECINT ;GO HANDLE INPUT CHARACTER
BIS #DS.Q10,@J ;FLAG WE SENT KYBD DATA
JMP IOTFIN
30$: JMP IOTBUM ;ERROR RETURN
;HERE FOR AN IMGPUT MACRO
IOTIMP: JSR PC,IOCOWN ;SEE IF WE CAN HAVE DEVICE
BEQ 10$ ;BRANCH IF PUTTING TO PRINTER
7$: JMP IOTBUM ;ONLY DO THIS FOR PRINTER
10$:
.IF NE FT.CTY
CMP J,#CTYDDB
BEQ 7$
.ENDC;.IF NE FT.CTY
.IF NE TTYDHN+RDADHN
11$: PIOFF
BIT #DS.ACT,@J ;IS PRINTER ACTIVE ?
BEQ 12$
PION
JSR PC,IOTIOW ;WAIT FOR PRINTER TO STOP
BR 11$
12$: BIS #DS.ACT,@J ;FLAG IS ACTIVE NOW
;MOV R1,R1 ;PUT ADR OF STRING IN RIGHT REG
MOV @R2,R0 ;PUT COUNT IN RIGHT REG
BMI 14$ ;CHECK COUNT IS NEGATIVE
NEG R0 ;MAKE IT NEGATIVE
14$: JSR PC,DHIMTY ;TYPE STRING
PION
80$: BIT #DS.ACT,(J) ; ACTIVE (I.E. TYPING)
BEQ 90$
JSR PC,IOTIOW ; IO WAIT
BR 80$ ; TILL DONE
90$: JMP IOTFIN
.IFF
BR 7$ ;NOOP IF NO DH11 LINES
.ENDC ; .IF NE TTYDHN+RDADHN
;HERE FOR A RELEASE MACRO
IOTREL: JSR PC,IOCOWN ;CHECK USER OWNS DEVICE
CLR @R0 ;CLEAR OUT DB.TSK
JMP IOTFIN
;HERE TO CHECK IF TASK OWNS (OR CAN HAVE) A DEVICE
; CALL: JSR PC,IOCOWN
; IF CAN'T HAVE WILL GO TO IOTBUM
; RETURNS WITH Z BIT SET IF PRINTER REQ; ELSE Z BIT CLEAR
; AND R0 POINTS TO RIGHT DB.TSK SLOT
IOCOWN: MOV R3,R0 ;GET FLAGS
SWAB R0 ;PUT FLAGS IN RH
BIC #^CIO.IDX,R0 ;LEAVE ONLY IO INDEX
ADD J,R0 ;WE WANT IO.IDX+J+DB.TSK
ADD #DB.TSK,R0 ; SO FINISH DOUBLE INDEX
TST @R0 ;ANYONE ALREADY USING FACILITY ?
BEQ 20$ ;CAUZ IF FREE U WIN
CMP TASK,@R0 ;OR MAYBE WE ALREADY OWN IT ?
BEQ 22$ ;CAUZ THAT COOL ALSO
TST (P)+ ;CLEAN OFF STACK
JMP IOTBUM ;AND EXIT SVC
20$: BIS #TK.NOP,@TASK ;DEVICE HAS NOT BEEN OPENED
22$: MOV TASK,-(P) ;SAVE TASK BLOCK ADR ON STACK
MOV @P,@R0 ;STUFF TASK BLOCK ADR IN DDB
ADD #TK.DTK,@P ;POINT TO DEVICE SLOT
MOV R0,@(P)+ ;SAVE <DEVICE BLOCK ADR>+DB.TSK+IO.IDX
BIT #IO.KYB*400,R3 ;SET/CLEAR Z BI
RTS PC
IOTIOW: BIT #IO.NBK,@TASK ;IS THIS A NONBLOCKING REQUEST ?
BEQ 10$
TST (P)+ ;POP RETURN OFF STACK
JMP IOTBUM ;GIVE ERROR RETURN
10$: MOV J,-(P) ;SAVE DDB POINTER
MOV TASK,J ;POINT TO RIGHT TASK
JSR PC,STPTSK ;STOP TASK
MOV (P)+,J ;RESTORE DDB POINTER
JSR PC,LOPTK7 ;WAIT FOR A WHILE
RTS PC ;AND BACK TO CALLER
;HERE TO REMOVE A TASK FROM A RUN QUEUE
STPTSK: MOV R0,-(P) ;SAVE REG
PIOFF ;DISABLE INTERRUPTS
MOV TK.PRI(J),R0 ;POINT TO RUN QUEUE
CMP TK.RQL(R0),J ;DID WE FIND OURSELVES YET ?
BEQ 20$
TRAP
20$: MOV TK.RQL(J),TK.RQL(R0) ;DELINK US
BIC #TK.RUN,@J ;CLEAR RUNNING FLAG
BIT #TK.WAK,(J) ;WAKE TASK ?
BEQ 90$
JSR PC,TSKWAK ; WAKE HIM UP
90$: PION
MOV (P)+,R0 ;RESTORE REGISTER
RTS PC
.IF NE FTDM11
;
;MACROS TO GET SET AND CLEAR BITS
; BIT0 IF ONE SET IS A DATASET LINE (READ ONLY)
; BIT1 DATA TERMINAL READY (READ ONLY)
; BIT2 REQUEST TO SEND
; BIT3 SECONDARY TRANSMIT
; BIT4 SECONDARY RECEIVE
; BIT5 CLEAR TO SEND
; BIT6 CARRIER
; BIT7 RING
; BIT8 =0 IF LINE CONNECTED
; BIT9 =0 IF HOST IS THERE
; BIT15 =1 IF EITHER BIT8 OR BIT9 SET
;
;CODE (12) GETBIT
IOTGTB: JSR PC,DMSETU ;POINT DM11BB TO LINE
BEQ IOTGTX ;IN CASE OF ERROR
BIC #^C376,R0 ;CLEAR GARBAGE
BIT #LCB.DS,R2 ;IS THIS A DATA SET LINE
BEQ 05$ ;SKIP IF NOT
INC R0 ;SET DSL BIT
05$: BIT #DS.CON,@J ;IS DEVICE CONNECTED?
BNE 10$ ;SKIP IF OK
BIS #B8+B15,R0 ;SET ERROR STATUS
10$: BIT #DS.DIE!DS.DSC,@J ;IS HOST THERE
BEQ 20$ ;SKIP IF OK
BIS #B9+B15,R0 ;SET ERROR STATUS
20$: JMP IOTRET ;RETURN BITS
;CODE (14) SET BITS
IOTSET: MOV @R1,R4 ;PICK UP MASK
BIC #177761,R4 ;STRIP EXTRANEOUS BITS
JSR PC,DMSETU ;POINT TO DM11BB LINE
BEQ IOTGTX ;IN CASE OF ERROR
BIS R4,@R1 ;SET BITS
BR IOTGTB ;GET NEW BITS AND RETURN
;CODE (16) CLEAR BITS
;
IOTCLR: MOV @R1,R4 ;GET MASK
BIC #177761,R4 ;STRIP EXTRANEOUS BITS
JSR PC,DMSETU ;POINT DM11BB TO LINE
BEQ IOTGTX ;IN CASE OF ERROR
BIC R4,@R1 ;CLEAR BITS
BR IOTGTB ;GET NEW BITS AND RETURN
IOTGTX: JMP IOTBUM ;ERROR RETURN TO USER
;HERE TO POINT DM11BB TO A PARTICULAR LINE
;
;CALL JSR PC,DMSETU ;J POINT TO DDB
; Z BIT SET IF FAIL
; Z BIT CLEARED IF OK
; CONTENTS OF DB.LCB IN R2
; AND CONTENTS OF DM11BB REG ON R0
DMSETU:
MOV @DB.LCB(J),R2
BIT #LCB.DS,R2 ;IS LINE A DATA SET?
BEQ 90$ ;NO SO RET WITH ERROR
MOV DB.HDW(J),R3 ;POINTER TO DH11 BLOCK
MOV DHB.DM(R3),R3 ;DM11BB HARDWARE ADDRESS
BEQ 90$ ;DONE
MOV #140,R0 ;COUNTER TO BE SURE DM11BB WORKS
MOV #DM.SCN,@R3 ;CLEAR SCANNER
20$: MOV R3,R1 ;COPY ADDRESS OF DM11BB
BIT #DM.BSY,(R1)+ ;TEST FOR STILL BUSY
BEQ 21$
SOB R0,20$
TWIDDLE R3 ;COUNT BUSTED DM11BB'S
SEZ ;FLAG WE LOST
BR 90$
21$: MOVB DB..LN(J),R0 ;GET LINE NO
MOV R0,@R3 ;POINT TO LINE
BIS #1,@R1 ;WANT TO LOOK AT LINE
.IF NE FT.CHK
MOV @R3,R0 ;GET DM11BB REGISTER
BIC #^C17,R0 ;STRIP ALL BUT LINE SELECT
CMPB DB..LN(J),R0 ;IS THIS LINE DESIRED
CHK EQ
.ENDC ;IF NE FT.CHK
MOV @R1,R0 ;GET STATUS FOR LINE
CLZ ;CLEAR Z BIT
90$: RTS PC
.IFF
IOTGTB:
IOTSET:
IOTCLR:
CLR R0
JMP IOTRET
.ENDC ;.IF NE FTDM11
.IF NE DN11N
;
;CODE (20) DIAL MACRO
;
;SUBROUTINE TO START AN AUTO DIAL SEQUENCE
;CALLED BY TTYSER FOR AN RDX DEVICE
;ROUTINE DESTROYS REGS 0,1,2
;
;
DNSTTJ:
BIT #DNRREQ,DB.DNR(J) ;NEED TO DIAL
BEQ 20$ ;NO
BIC #DNRREQ,DB.DNR(J) ;CLEAR REQUEST
BIC #TS.DTR+TS.RNG,DB.DCS(J) ;IN CASE LOSE
JSR PC,DNADDR ;R1=DNTAB,R2=HDW
BIT #DN.PWI+DN.ACR,@R2 ;POWER ON AND HEALTHY?
BNE 40$ ;NO
MOV DB.LCB(J),R0 ;SET STATE TO DIAL
MOVB #LCS.DL,LC.STA(R0) ;GET DTR UP
BISB #DNDIAL,DB.DNS(J) ;FLAG WE ARE DIALING
BIT #DN..CR+DN.DLO,@R2 ;CALL REQUEST UP?
BNE 10$
JMP DNBEGN
10$: BIC #^CDN..ME,@R2 ;CLEAR CALL
MOVB #<100*TMDLO+DN.TDL>,DB.DNT(J) ;SET TIMER
20$: RTS PC
40$: BIS #DNRERR+DNREAD,DB.DNR(J) ;AUTO DIALER FAILER
; JSR PC,WAKEPP ;WAKE PRINTER TASK
; RTS PC
;
WAKEPP:
SAVE <J>
MOV DB.TSK+4(J),J
BEQ 50$ ;NO TASK ATTACHED
JSR PC,TSKWAK ;WAKE THE TASK
50$: RESTORE <J>
RTS PC
;
IOTDNL: JSR PC,IOCOWN ;ERROR RETURN IF SOMEONE ELSE OWNS TTY
BIT #40,DB.DVT(J) ;IS THIS AN AUTODIAL LINE?
BEQ 12$ ;NO, TAKE ERROR RETURN
TSTB (R2) ;TERMINATE REQUEST?
BEQ 70$ ;YES
CMPB #1,(R2) ;STATUS REQUEST?
BEQ 50$ ;YES
;NO, MUST BE A DIAL REQUEST
BITB #DNDIAL,DB.DNS(J) ;ARE WE ALREADY DIALING
BEQ 20$ ;NO
10$: BIS #DNREBY+DNRERR,DB.DNR(J) ;SET ERROR CONDITIONS
12$: JMP IOTBUM ;FAILURE RETURN
20$:
BIT #TS.DTR,DB.DCS(J) ;CALL UP ON LINE?
BNE 10$ ;YES, ERROR RETURN
BIC #DNRERR+DNREAD+DNRANS+DNRENC+DNREBY,DB.DNR(J) ;CLEAR FLAGS
BITB #IO.AR2,@TASK ;CHECK IF IN A REG
BEQ 25$ ;SKIP IF NO
MOV @R1,R1 ;GET ADR OFF STACK
25$: MOV R1,R3 ;MOVE ADDRESS OF CHARACTERS
JSR PC,DNADDR ;GET DNTAB ADDRESS IN R1
;DN STATUS REG IN R2. R0 DESTROYED
MOV #6,R4 ;DISPLACEMENT INTO DNTAB
ADD R1,R4 ;OF FIRST DIGIT
MOV R4,4(R1) ;INITIALIZE POINTER
CLRB (R4)+ ;FIRST BYTE IS 0
MOV #16.,R2 ;MAXIMUM # OF CHARACTERS
30$: MOVB (R3)+,R0 ;GET NEXT CHARACTERS
BIC #177600,R0 ;KEEP 7 BITS
CMP #60,R0 ;IS IT LESS THAN 0?
BGT 35$ ;YES, INSERT A 17
CMP #71,R0 ;IS IT GREATER THAN 9?
BLT 35$ ;YES, INSERT A 17
BIC #177760,R0 ;STRIP EXTRA BITS
MOVB R0,(R4)+ ;INSERT IT
DEC R2 ;ALL DONE?
BNE 30$ ;NO
35$: MOVB #17,(R4) ;YES INSERT TERMINATOR
40$: BIS #DNRREQ,DB.DNR(J) ;DIAL REQUEST
JSR PC,QUEDEV ;WAKE SERVICE ROUTINE
45$: JSR PC,IOTIOW ;WAIT UNTIL ALL DONE
BIT #DNRERR,DB.DNR(J) ;ERROR?
BNE 12$ ;YES, TAKE ERROR RETURN
BIT #DNRANS,DB.DNR(J) ;CALL ANSWERED?
BEQ 45$ ;NO, WAIT
JMP IOTFIN ;ALL DONE
50$: MOV DB.DNR(J),(R1) ;RETURN STATUS
JMP IOTFIN ;ALL DONE
70$: JSR PC,DNADDR ;DIALER SHOULD DISCONNECT
JSR PC,DNCLR
.IFF
IOTDNL:
.ENDC ;IF NE DN11N
JMP IOTFIN
;CODE (200) WAKE TASK
WAKTSK: JSR PC,TSKWAK
JMP IOTFIN
;CODE (202) TRIGGER TASK
TRGTSK: BIS #TK.TRG,@J ;RESTART WHEN REASONABLE
BIT #TK.LGI,@J ;HAS TASK BEEN EXITED ?
BNE 90$ ;IF NOT WE ARE DONE
MOV TK.JSA(J),R0 ;GET STARTING ADDRESS
JSR PC,TSKBEG ;SETUP TO RUN
90$: JMP IOTFIN
;HERE TO LOG A TASK IN, I.E. EITHER START OR RESTART IT
; CALL MOV #<TSK BLK ADR>,J
; MOV #<STARTING ADR>,R0
; JSR PC,TSKBEG
TSKBEG: MOV J,R1 ;COPY BLOCK ADR
ADD #TK.ZER,R1 ;MAKE ADR OF 1ST LOCATION TO CLEAR
MOV #<TK.SIZ-TK.ZER>/2,R2
22$: CLR (R1)+ ;CLEAR NEXT LOCATION IN BLOCK
SOB R2,22$
MOV TK.PDL(J),R1 ;GET STACK POINTER
MOV R0,-(R1) ;SAVE STARTING ADR
SUB #14,R1 ;SKIP REGS
MOV R1,TK.PDL+2(J) ;SAVE CURRENT PDL POINTER
PIOFF
MOV #TK.LGI,@J ;INITIALIZE THE STATUS WORD
JSR PC,TSKRUN ;SET TASK RUNNABLE
PION
RTS PC
;CODE (204) SEND TO TASK
SNDTSK: MOV TK.SPT(J),R0 ;GET QUEUE PUTTER
TST (R0)+ ;ADVANCE PUTTER
CMP #TKSQSZ*2,R0 ;HIT END OF QUEUE ?
BNE 10$
CLR R0 ;RESET TO BEGINING OF QUEUE
10$: CMP R0,TK.STK(J) ;WOULD THAT HIT TAKER ?
BEQ SNDT69 ;IF SO REJECT REQUEST
ADD J,R0 ;MAKE ABSOLUTE
MOV @R2,TK.SQU(R0) ;PUT DATA INTO QUEUE
SUB J,R0
MOV R0,TK.SPT(J) ;SAVE UPDATE PUTTER
BR WAKTSK ;NOW WAKE RECEIVING TASK
SNDT69: JMP IOTBUM
;CODE (206) RECEIVE FROM TASK
RCVTSK: MOV TASK,J ;GET OUR TASK BLOCK
MOV TK.STK(J),R0 ;GET QUEUE TAKER
CMP R0,TK.SPT(J) ;IS IT SAME AS PUTTER ?
BNE 20$
JSR PC,IOTIOW ;WAIT
BR RCVTSK ;THEN TRY SAME SILLY TEST
20$: TST (R0)+ ;ADVANCE TAKER
CMP #TKSQSZ*2,R0 ;TIME TO WRAP ?
BNE 24$
CLR R0
24$: MOV R0,TK.STK(J) ;SAVE TAKER
ADD J,R0 ;MAKE ABSOLUTE
MOV TK.SQU(R0),R0 ;GET NEXT ENTRY FROM QUEUE
JMP IOTRET ;RETURN DATA
;CODE (210) HIBER
HIBER.: MOV TASK,J ;GET OUR TASK BLOCK
PIOFF
HIBSLP: MOV @R2,TK.TIM(J) ;SET TIMER
JSR PC,STPTSK ;STOP THE TASK
; BIT #TK.WAK,@J ;HAS A WAKE HAPPENED ?
; BEQ 20$ ;IF NOT JUST CALL SCHEDULER
; JSR PC,TSKRUN ;SET TASK RUNNABLE AGAIN
20$: PION ;REENABLE INTERRUPTS
JSR PC,LOPTK7 ;BACK TO SCHEDULER
JMP IOTFIN ;THEN EXIT UUO
;CODE (214) SLEEP
SLEEP.: MOV TASK,J ;GET TASK BLOCK
TST @R2 ;CHECK SLEEP TIME
BEQ 20$ ;FINISHED IF ZERO
PIOFF
BIS #TK.SLP,@J ;SET SLEEP BIT
BR HIBSLP ;PUT TO SLEEP
20$: JMP IOTFIN ;DONE
;CODE (212) EXIT
TSKEND: MOV TASK,J ;POINT TO OUR TASK BLOCK
MOV FIRDDB,R0 ;POINT TO FIRST DEVICE BLOCK
BR 28$ ;IN CASE NONE
20$:
.IF NE FT.RDA
TST DB.RDT(R0) ;RDA?
BNE 23$ ;YES, SKIP IT
.ENDC;IF NE FT.RDA
BIT #DS.TTY,@R0 ;IS IT A TTY ?
BEQ 26$
23$: MOV R0,R1 ;COPY DDB ADR
ADD #DB.TSK,R1 ;POINT TO TASK WORDS
MOV #4,R2 ;COUNTER
22$: CMP J,@R1 ;IS THIS ONE US ?
BNE 24$
CLR @R1 ;THIS NO LONGER TRUE
24$: TST (R1)+ ;ADVANCE TO NEXT SLOT
SOB R2,22$
26$: MOV DB.LNK(R0),R0 ;GET NEXT DEVICE BLOCK
28$: BNE 20$
CLR TK.TIM(J) ;STOP TIMER
PIOFF ;WHILE WE STOP THE TASK
BIC #Tk.WAK,(J) ;KILL IT IN ALL CASES
JSR PC,STPTSK ;STOP THE TASK
BIC #TK.LGI,@J ;KILL TASK
PION
BIT #TK.TRG,@J ;WAS TASK TRIGERED ?
BEQ 90$
MOV TK.JSA(J),R0 ;GET STARTING ADDRESS
JSR PC,TSKBEG
90$: JSR PC,LOPTK7 ;AND OUT
;HERE TO SET A TASK RUNNABLE
; CALL MOV #<TSK BLOCK ADR>,J
; JSR PC,TSKRUN
TSKRUN: SAVE <R0,R1>
MOV TK.PRI(J),R1 ;POINT TO RUN QUEUE HEADER
32$: MOV R1,R0
MOV TK.RQL(R0),R1 ;GET ADR OF NEXT TASK
BNE 32$
CLR TK.RQL(J) ;CLEAR OUR RUN-QUEUE LINK
MOV J,TK.RQL(R0) ;PUT NEW TASK AT END OF QUEUE
BIS #TK.RUN,@J
BIC #TK.WAK,@J
MOVB #TKQTIM,TK.QTM(J) ;RESET QUANTUM RUN TIME
RESTORE <R1,R0>
RTS PC
;HERE TO WAKE A TASK
; CALL MOV #<TSK BLK ADR>,J
; JSR PC,TSKWAK
TSKWAK: PIOFF ;DISABLE INTERRUPTS FOR A WHILE
BIT #TK.LGI,@J ;DID TASK EXIT ?
BEQ 90$ ;IF SO WE ARE DONE
BIT #TK.SLP,@J ;IS TASK SLEEPING
BNE 90$ ;DONT WAKE IF IT IS
BIS #TK.WAK,@J ;SET WAKEUP FLAG
BIT #TK.RUN,@J ;TASK ALREADY RUNNING ?
BNE 90$ ;IF SO WE ARE DONE
JSR PC,TSKRUN ;SET TASK RUNNABLE
90$: PION
RTS PC
;HERE TO WAKE A TASK ASSOCIATED WITH 'PRINTER GETS'
; CALL MOV <DDB ADR>,J
; JSR PC,TK0WAK
; RETURN WITH Z BIT SET IF NO TASK
; ELSE Z BIT CLEARED
TK0WAK: TST DB.TSK(J) ;IS THERE A TASK
BEQ 90$ ;IF NOT JUST RETURN
MOV J,-(P) ;SAVE DDB ADR
MOV DB.TSK(J),J ;POINT TO TASK BLOCK
JSR PC,TSKWAK ;GO WAKE THE TASK
MOV (P)+,J ;RESTORE DDB POINTER & CLR Z BIT
90$: RTS PC
;HERE TO WAKE A TASK ASSOCIATED WITH 'CONNECTION BROKEN"
;CALL MOV <DDB ADR>,J
; JSR PC,HSTWAK
; RETURN WITH Z BIT SET IF NO TASK
; ELSE Z BIT CLEARED
HSTWAK: MOV J,-(P) ;SAVE DDB ADR
MOV DB.TSK(J),J ;POINT TO TASK BLOCK
BEQ 90$ ;EXIT IF NO TASK
BIC #TK.SLP,@J ;CLEAR SLEEP BIT
CLR TK.TIM(J) ;AND SLEEPING TASKS
JSR PC,TSKWAK ;WAKE TASK
90$: MOV (P)+,J ;RESTORE DDB POINTER AND CLEAR Z BIT
RTS PC
.ENDC;.IF NE FT.TSK