Trailing-Edge
-
PDP-10 Archives
-
tops10_703_distr_bb-x140b-sb
-
10,7/703anf/dntty.p11
There are 5 other files named dntty.p11 in the archive. Click here to see a list.
.SBTTL DNTTY - TERMINAL ROUTINES 3 SEP 85
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979,1980,1981,1982,1983,1984 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
VRTTY=116 ;FILE EDIT NUMBER
.IF NE <FT.CTY+TTYN+RDAN>
;DB.DCS STATUS BITS FOR TTY SERVICE
TS.DFE=1 ;DEFERED ECHO MODE
TS..LC=2 ;TRANSLATE LOWER CASE TO UPPER
TS.FRZ=4 ;OUTPUT HAS BEEN FROZEN BY TYPEIN OF XOF
TS.IMI=10 ;IMAGE MODE INPUT
TS.IMO=20 ;IMAGE MODE OUTPUT
TS.PAG=40 ;TTY PAGE IN EFFECT
TS.TAP=100 ;TTY TAPE FEATURE(IMPLIES SUPPRESS NORMAL CR HANDLING)
TS.TAB=200 ;TTY HAS HDW TAB
TS.FRM=400 ;TTY HAS HDW FORM FEED
TS.TIW=1000 ;JOB IS IN INPUT WAIT FOR TTY
TS.LMD=2000 ;LINE INPUT MODE
TS.CRL=4000 ;NO AUTO CR/LF ON LINE OVERFLOW
TS.DTR=10000 ;DATA TERMINAL READY
TS.RNG=20000 ;RING
TS.CAR=20000 ;CARRIER
TS.DSR=40000 ;DATASET READY
TS.ADL=100000 ;AUTO DIAL LINE (DN11)
TS.RCN=TS..LC!TS.PAG!TS.TAB!TS.FRM!TS.CRL!TS.DTR!TS.RNG!TS.CAR!TS.DSR ;BITS TO PRESERVE ON A RECONNECT
.IIF NDF,ESCF,ESCF=176 ;NOTE, ESCF CANNOT BE > 177
;MACRO TO MAKE DEVICE DEPENDENT PORTION OF DEVICE BLOCK FOR TTY'S
.MACRO SETLCB QLCB
.WORD LCB'QLCB ;DB.LCB
.ENDM
.MACRO DDXGEN DEV,DV,DRQ,XBITS,XZZ
ZZZ=1
.REPT NXTDH&17
ZZZ=ZZZ*2
.ENDR
.WORD ZZZ ;DB.BIT
.BYTE 17&NXTDH ;DB..LN
Z=0
.IF NDF DV'XZZ'XS
.IIF DF DEV'XS,DV'XZZ'XS=DEV'XS
.ENDC
.IF NDF DV'XZZ'XS
Z=LCB.AB ;AUTO BAUD LINE
ZZXS=^D2400 ;SCAN AT 2400 BAUD
.IFF
ZZXS=DV'XZZ'XS
.ENDC
.IF NDF DV'XZZ'RS
.IIF DF DEV'RS,DV'XZZ'RS=DEV'RS
.ENDC
.IIF NDF DV'XZZ'RS,ZZRS=ZZXS
.IIF DF DV'XZZ'RS,ZZRS=DV'XZZ'RS
.MACRO DHSSET LINE
ZZS=0
.IIF DF DV'XZZ'XS,ZZS=1
.IIF DF DV'XZZ'RS,ZZS=1
.IF NE ZZS
SPD ZZXS,ZZRS ;CALCULATE LINE SPEED
DHS'LINE=QQ
.ENDC
.ENDM DHSSET
DHSSET \NXTDH
.IIF DF DV'XZZ'DSL, Z=Z!LCB.DS
.MACRO DHCSET LINE
DHC'LINE=Z
.ENDM DHCSET
.MACRO DHZSET LINE
DHZ'LINE=LCS.VG
.IF EQ Z&LCB.DS
DHZ'LINE=LCS.AB
.IF EQ Z&LCB.AB
DHZ'LINE=LCS.RU
.ENDC
.ENDC
.ENDM
DHCSET \NXTDH
DHZSET \NXTDH
.BYTE 12,12,20,12,12,12 ;DB.FIL
.BYTE 0 ;DB.EPL
SETLCB \NXTDH ;DB.LCB
DHINDX=DHINDX+1
.IF NE FTDN11
Z=0
.IF DF DV'XZZ'801
Z=DV'XZZ'801
.ENDC
.BYTE Z ;DB.DNS (DN11 STATUS)
.BYTE 0 ;DB.DNT (DN11 TIMER)
.ENDC;.IF NE FTDN11
.WORD 0 ;DB.TTS (TTY STATUS WORD)
.BLKB <DB.TSZ-DB.TZR>
.EVEN
.ENDM DDXGEN
NXTDZ=-1 ;
NXTDH=-1 ;LOCATE FIRST TTY LINE
DRESET=0
ASYDEV=ASY.DH ;BUILD DH LINES FIRST
DDBGEN TTY,T,TTYDHN,TTYDRQ,<DS.TTY!DS.OUT> ;MAKE DEVICE BLOCKS FOR TTYS
ASYDEV=ASY.DZ ;NOW DZ LINES
DRESET=1 ;DONT BUILD NEW SYMBOLS
.MACRO DDXGEN DEV,DV,DRQ,XBITS,XZZ
ZZZ=1
.REPT NXTDZ&7
ZZZ=ZZZ*2
.ENDR
.WORD ZZZ ;DB.BIT
.BYTE 7&NXTDZ ;DB..LN
Z=0
.IF NDF DV'XZZ'XS
.IIF DF DEV'XS,DV'XZZ'XS=DEV'XS
.ENDC
.IF NDF DV'XZZ'XS
Z=LCB.AB ;AUTO BAUD LINE
ZZXS=^D2400 ;SCAN AT 2400 BAUD
.IFF
ZZXS=DV'XZZ'XS
.ENDC
.IF NDF DV'XZZ'RS
.IIF DF DEV'RS,DV'XZZ'RS=DEV'RS
.ENDC
.IIF NDF DV'XZZ'RS,ZZRS=ZZXS
.IIF DF DV'XZZ'RS,ZZRS=DV'XZZ'RS
.MACRO DZSSET LINE
ZZS=0
.IIF DF DV'XZZ'XS,ZZS=1
.IIF DF DV'XZZ'RS,ZZS=1
.IF NE ZZS
SPD ZZXS,ZZRS ;CALCULATE LINE SPEED
DZS'LINE=QQ
.ENDC
.ENDM DZSSET
DZSSET \NXTDZ
.IIF DF DV'XZZ'DSL, Z=Z!LCB.DS
.MACRO DZCSET LINE
DZC'LINE=Z
.ENDM DZCSET
.MACRO DZZSET LINE
DZZ'LINE=LCS.VG
.IF EQ Z&LCB.DS
DZZ'LINE=LCS.AB
.IF EQ Z&LCB.AB
DZZ'LINE=LCS.RU
.ENDC
.ENDC
.ENDM
DZCSET \NXTDZ
DZZSET \NXTDZ
.BYTE 12,12,20,12,12,12 ;DB.FIL
.BYTE 0 ;DB.EPL
SETLCB \<NXTDZ+<NDH11*20>> ;DB.LCB
DZINDX=DZINDX+1
.IF NE FTDN11
Z=0
.IF DF DV'XZZ'801
Z=DV'XZZ'801
.ENDC
.BYTE Z ;DB.DNS (DN11 STATUS)
.BYTE 0 ;DB.DNT (DN11 TIMER)
.ENDC;.IF NE FTDN11
.WORD 0 ;DB.TTS (TTY STATUS WORD)
.BLKB <DB.TSZ-DB.TZR>
.EVEN
.ENDM DDXGEN
DDBGEN TTY,T,TTYDZN,TTYDRQ,<DS.TTY!DS.OUT>
.MACRO DDXGEN DEV,DV,DRQ,XBITS,XZZ
ZZZ=1
.REPT NXTDH&17
ZZZ=ZZZ*2
.ENDR
.WORD ZZZ ;DB.BIT
.BYTE 17&NXTDH ;DB..LN
Z=0
.BYTE 12,12,20,12,12,12 ;DB.FIL
.BYTE 0 ;DB.EPL
.WORD CT0LDB ;DUMMY LINE CONTROL BLOCK
.IF NE FTDN11
Z=0
.IF DF DV'XZZ'801
Z=DV'XZZ'801
.ENDC
.BYTE Z ;DB.DNS (DN11 STATUS)
.BYTE 0 ;DB.DNT (DN11 TIMER)
.WORD CT'XZZ'DDB+DB.TSZ ;CTY HAS NO DATASET FUNCTION
.ENDC
.WORD 0 ;DB.TTS (TTY STATUS WORD)
.BLKB <DB.TSZ-DB.TZR>
.EVEN
.ENDM DDXGEN
.IF NE FT.CTY
DRESET=0
NXTDH=0 ;CTY ISN'T A DH DEV SO FAKE IT
.IF NDF CTYRNN
.IIF DF TTYRNN,CTYRNN=TTYRNN ;SAME RESTRICTIONS AS TTYS
.ENDC
DDBGEN CTY,CT,1,TTYDRQ,<DS.OUT!DS.TTY> ;MAKE A DEVICE BLOCK FOR THE CTY
.ENDC
.IF NE FT.RDA ; IF WE HAVE IT, IT IS THE SAME
.MACRO DDXGEN DEV,DV,DRQ,XBITS,XZZ
ZZZ=1
.REPT NXTDH&17
ZZZ=ZZZ*2
.ENDR
.WORD ZZZ ;DB.BIT
.BYTE 17&NXTDH ;DB..LN
Z=0
.IF NDF DV'XZZ'XS
.IIF DF DEV'XS,DV'XZZ'XS=DEV'XS
.ENDC
.IF NDF DV'XZZ'XS
ZZXS=^D2400 ;SCAN AT 2400 BAUD
.IFF
ZZXS=DV'XZZ'XS
.ENDC
.IF NDF DV'XZZ'RS
.IIF DF DEV'RS,DV'XZZ'RS=DEV'RS
.ENDC
.IIF NDF DV'XZZ'RS,ZZRS=ZZXS
.IIF DF DV'XZZ'RS,ZZRS=DV'XZZ'RS
.MACRO DHSSET LINE
ZZS=0
.IIF DF DV'XZZ'XS,ZZS=1
.IIF DF DV'XZZ'RS,ZZS=1
.IF NE ZZS
SPD ZZXS,ZZRS ;CALCULATE LINE SPEED
DHS'LINE=QQ
.ENDC
.ENDM DHSSET
DHSSET \NXTDH
.IIF DF DV'XZZ'DSL, Z=Z!LCB.DS
.MACRO DHCSET LINE
DHC'LINE=Z
.ENDM DHCSET
.MACRO DHZSET LINE
DHZ'LINE=LCS.VG
.IF EQ Z&LCB.DS
DHZ'LINE=LCS.AB
.IF EQ Z&LCB.AB
DHZ'LINE=LCS.RU
.ENDC
.ENDC
.ENDM
DHCSET \NXTDH
DHZSET \NXTDH
.BYTE 0,0,0,0,0,0 ;DB.FIL
.BYTE 0 ;DB.EPL
SETLCB \NXTDH ;DB.LCB
DHINDX=DHINDX+1
.IF NE FTDN11
Z=0
.IF DF DV'XZZ'801
Z=DV'XZZ'801
.ENDC
.BYTE Z ;DB.DNS (DN11 STATUS)
.BYTE 0 ;DB.DNT (DN11 TIMER)
.ENDC
.BLKB <DB.TSZ-DB.TZR>
.EVEN
.ENDM DDXGEN
ASYDEV=ASY.DH
DRESET=0
NXTDH=-1 ; START WITH RIGHT LINE NUMBER
DDBGEN RDA,D,RDADHN,RDADRQ,<DS.OUT>
.MACRO DDXGEN DEV,DV,DRQ,XBITS,XZZ
ZZZ=1
.REPT NXTDZ&7
ZZZ=ZZZ*2
.ENDR
.WORD ZZZ ;DB.BIT
.BYTE 7&NXTDZ ;DB..LN
Z=0
.IF NDF DV'XZZ'XS
.IIF DF DEV'XS,DV'XZZ'XS=DEV'XS
.ENDC
.IF NDF DV'XZZ'XS
ZZXS=^D2400 ;SCAN AT 2400 BAUD
.IFF
ZZXS=DV'XZZ'XS
.ENDC
.IF NDF DV'XZZ'RS
.IIF DF DEV'RS,DV'XZZ'RS=DEV'RS
.ENDC
.IIF NDF DV'XZZ'RS,ZZRS=ZZXS
.IIF DF DV'XZZ'RS,ZZRS=DV'XZZ'RS
.MACRO DZSSET LINE
ZZS=0
.IIF DF DV'XZZ'XS,ZZS=1
.IIF DF DV'XZZ'RS,ZZS=1
.IF NE ZZS
SPD ZZXS,ZZRS ;CALCULATE LINE SPEED
DZS'LINE=QQ
.ENDC
.ENDM DZSSET
DZSSET \NXTDZ
.IIF DF DV'XZZ'DSL, Z=Z!LCB.DS
.MACRO DZCSET LINE
DZC'LINE=Z
.ENDM DZCSET
.MACRO DZZSET LINE
DZZ'LINE=LCS.VG
.IF EQ Z&LCB.DS
DZZ'LINE=LCS.AB
.IF EQ Z&LCB.AB
DZZ'LINE=LCS.RU
.ENDC
.ENDC
.ENDM
DZCSET \NXTDZ
DZZSET \NXTDZ
.BYTE 0,0,0,0,0,0 ;DB.FIL
.BYTE 0 ;DB.EPL
SETLCB \<NXTDZ+<NDH11*20>> ;DB.LCB
DZINDX=DZINDX+1
.IF NE FTDN11
Z=0
.IF DF DV'XZZ'801
Z=DV'XZZ'801
.ENDC
.BYTE Z ;DB.DNS (DN11 STATUS)
.BYTE 0 ;DB.DNT (DN11 TIMER)
.ENDC
.BLKB <DB.TSZ-DB.TZR>
.EVEN
.ENDM DDXGEN
ASYDEV=ASY.DZ
DRESET=1
NXTDZ=-1
DDBGEN RDA,D,RDADZN,RDADRQ,<DS.OUT>
.ENDC; .IF NE FT.RDA
.MACRO DDXGEN DEV,DV,DRQ,XBITS,XZZ ;REDEFINE FOR NEXT DEVICE
.ENDM DDXGEN
.IF NE FT.TSK
.IIF NE FT.CTY, .WORD CTYDDB ;ADDRESS OF DEVICE BLOCK FOR CTY IS ENTRY "-1"
TTYTAB:
.MACRO X ART,ARG,ARX,ARY
.IF EQ D'ART'L'ARG'-1
.WORD T'ARX'DDB
ZTTY=ZTTY+1
.IFF
.IF EQ D'ART'L'ARG'-6
.WORD D'ARY'DDB
ZRDA=ZRDA+1
.IFF
.WORD 0
.ENDC
.ENDC
.ENDM
ZTTY=0 ;START WITH TTY0 DDB
ZRDA=0 ;START WITH RDA0 DDB
Z=0 ;INITIALIZE INDEX FOR DH11
.REPT DHLINE
X H,\Z,\ZTTY,\ZRDA
Z=Z+1
.ENDR
Z=0 ;RESET DZ11 LINE INDEX
.REPT DZLINE
X Z,\Z,\ZTTY,\ZRDA
Z=Z+1
.ENDR
.ENDC ;.IF NE FT.TSK
.IF NE FT.CTY
CT0LDB: .WORD 0 ;LC.CAR DUMMY LDB FOR CTY
.BYTE LCS.RU ;LC.STA LINE IS RUNNING
.BYTE 0 ;LC.MOD
.WORD B.300 ;LC.SPD 300 BAUD
.WORD B.300 ;LC.PSP 300 BAUD
.WORD CT0DDB ;LC.BLK
.WORD CTIINT ;LC.INS
.WORD CTOINT ;LC.OUS
.IF NE NDZ11
.WORD 0 ;LC.CNT
.WORD 0 ;LC.BUF
.ENDC
.ENDC
CTYSER:
TTYSER: CMP #TTYMML,DB.MML(J) ;DID HANDLER GIVE REASONABLE SIZE MSG ?
BPL 10$ ;IF SO USE IT
MOV #TTYMML,DB.MML(J) ;USE OUR SIZE CAUZ IT'S SMALLER
10$: MOVB #DCM.AS,DB.DCM(J) ;SET DATA CODE AND MODE
MOVB DB.TYP(J),R0 ;GET ASYNC CONTROLLER TYPE
ASR R0 ;MAKE INTO DIRECT VALUE (NOT INDEX)
.IF NE FT.CTY
CMP #CT0DDB,J ;IS THIS THE CTY?
BEQ 11$ ;YES,
.ENDC ;.IF NE FT.CTY
INCB R0 ;NO,
11$: INCB R0 ;CTY = 1; DH-11 = 2; DZ-11 = 3
MOVB R0,DB.DVV(J) ;SET CONTROLLER TYPE
JSR PC,DVCCFM ;SEND CONNECT CONFIRM
BIT #DS.CON,@J ;CONNECTED ?
BNE 20$
RTS PC
20$: JSR PC,DVXDRQ ;SEND SOME DATA REQUESTS
TST DB.OBF(J) ;DID 10 SEND DATA ?
BNE TOGMSG
JMP TTYICK
;HERE TO OUTPUT THE "ESCAPE FUNCTION" CHARACTER
TOGESC: JSR PC,QTECHR ;QUEUE TWO OF 'EM SO THAT ONE
BR TOGMSG ;WILL ACTUALLY GET PRINTED
;HERE WHEN WIN A DATA CHAR
TOGCHR: CMP R0,#ESCF ;IS THIS FUNCTION FLAG?
BEQ TOGESC ;YES, SPECIAL PROCESSING
JSR PC,QTYCHR ;QUEUE CHAR TO BE TYPED
TOGMSG: JSR PC,DVGBYT ;GET NEXT BYTE FROM THE NCL MESSAGE
BR TOGCHR ;WON A DATA CHARACTER
BR TOGMS1 ;WON A MESSAGE TYPE
JMP TOGDON ;ALL OUT OF MESSAGE
;START OF SUBMESSAGE, DISPATCH BASED ON MESSAGE TYPE
TOGMS1: TST R0 ;MESSAGE TYPE CAN'T BE NEGATIVE
BLE TOGBAD ;IF IT IS, WE COMPLAIN
CMP R0,#4 ;ALSO CAN'T BE TOO BIG EITHER
BGT TOGBAD ;IF IT IS, WE COMPLAIN
ASL R0 ;WORD INDEX
JMP @10$-2(R0) ;DISPATCH ON MESSAGE TYPE
10$: TOGMSG ;01 - DATA WITHOUT EOM
TOGMSG ;02 - DATA WITH EOM
TOGSTS ;03 - STATUS
TOGCTL ;04 - CONTROL
;HERE ON BAD MESSAGE TYPE OR FORMAT
TOGBAD:
.IF EQ DGUTS
TRAP ;ILLEGAL MSG TYPE
.IFF
CTYMSG NCL
32$: JSR PC,DVGBYT ;GET NEXT BYTE OF MSG
BR 32$ ;EAT BAD MSG
BR TOGMS1 ;TRY AGAIN WITH NEXT MSG
JMP TOGDON ;ALL DONE
.ENDC
;HERE WHEN WE RECEIVE A STATUS MESSAGE
TOGSTS: JSR PC,DVGDBY ;GET CODE IN STATUS MSG
10$: MOV R0,-(P) ;SAVE CODE
JSR PC,DVGEXF ;GET BITS TO SET/CLEAR
ASSERT EQ DB.OCN(J) ;MAKE SURE NOTHING LEFT OVER
MOV (P)+,R1 ;GET CODE AGAIN
MOV DB.DCS(J),-(P) ;SAVE CURRENT STATUS
BIT #TS.DTR,R0 ;IF IT'S DTR
BEQ 40$ ; AND
CMP #2,R1 ;HE WANTS IT CLEAR
BNE 40$ ; SKIP IF NOT "CLEAR"
SAVE <R1> ;GET A TEMP FOR A BIT
BIT #TS.FRZ,R0 ;IS TEN CLEARING XOFF
BEQ 15$ ;NO,ONWARD
SAVE <R0,R2,R3,R4,R5> ;YES,SAVE SOME ACS
JSR PC,BEGXMT ;START OUTPUT
RESTORE <R5,R4,R3,R2,R0> ;RESTORE ACS
15$: MOV DB.LCB(J),R1 ;GET POINTER TO THE LCB
BEQ 35$ ;GET OUT IF NO LCB
ADD #LC.STA,R1 ;POINT TO DATASET STATE BYTE
CMPB #LCS.RC,@R1 ;RUNNING NORMALLY?
.IF NE FTDN11
BEQ 27$ ;YES, -10 WANTS US TO HANG UP
CMPB #LCS.DL,@R1 ;NO, DIALING OUT?
BEQ 27$ ;YES, -10 APPARENTLY WANTS TO ABORT
CMPB #LCS.DS,@R1 ;DIALING OUT SUCCESSFUL?
.ENDC;.IF NE FTDN11
BNE 35$ ;YES, -10 STILL WANTS TO ABORT
27$: MOVB #LCS.HA,@R1 ;FORCE DATASET TO HANG UP
35$: RESTORE <R1> ;GET SET/CLEAR BACK (IT'S CLEAR)
40$: BIC #TS.DTR!TS.CAR,R0 ;IGNORE -10'S OPINION OTHERWISE
42$: BIT #TS.IMO,R0 ;SET OR CLEAR IMAGE OUTPUT?
BEQ 60$ ;NO, ACT NORMALLY
BIC #TS.IMO,R0 ;DON'T ACTUALLY DO IT NOW
SAVE R0 ;SAVE BITS TO SET/CLEAR
MOV R1,R0 ;COPY SET/CLEAR CODE
DEC R0 ;CONVERT TO ESCAPE FUNCTION CODE
JSR PC,QTECHR ;PUT ESCAPE FUNCTION INTO DATA STREAM
RESTOR R0 ;GET BITS TO SET/CLEAR BACK
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
;DO "SET" BITS IF REQUESTED
60$: CMP #1,R1 ;DOES HE WANT A SET BITS ?
BNE 70$
BIS R0,DB.DCS(J) ;SET BITS
BR 90$ ;AND NOW DONE
;DO "CLEAR" BITS IF REQUESTED
70$: CMP #2,R1 ;WANT TO CLEAR BITS ?
BNE 80$
BIC R0,DB.DCS(J) ;CLEAR THE BITS LIKE BEFORE
BR 90$ ;NOW DONE
;NOT "SET" OR "CLEAR" BITS
80$:
.IF EQ DGUTS
TRAP
.IFF
TST (P)+ ;GET STACK BACK INTO SYNC
CTYMSG NCL ;LOG BAD NCL MSG ERROR
RTS PC ;AND EXIT
.ENDC ;.IF EQ DGUTS
;SEE IF ANYTHING CHANGED, TELL THE -10 IF NEEDED
90$: TRACE DV
MOV DB.DCS(J),R0 ;COPY OF NEW STATUS
BIC #TS.DTR!TS.CAR,(P) ;IGNORE DTR AND CAR (THIS IS TO AVOID
BIC #TS.DTR!TS.CAR,R0 ; A STATUS MESSAGE WAR WITH THE -10)
CMP R0,(P)+ ;DID DEVICE CONTROL STATUS CHANGE?
BEQ 95$ ;NO, ALL SET
BIS #DS.XDS,@J ;YES, SEND -10 OUR NEW STATUS
95$: BR TOGMSG
;HERE WHEN WE RECEIVE A CONTROL MESSAGE
TOGCTL: JSR PC,DVGDBY ;GET DCT BYTE
52$: TST R0 ;DCT CAN'T BE TOO SMALL
BLT TOGBAD ;OR WE WILL GET UPSET
CMP R0,#4 ;DCT ALSO CAN'T BE TOO BIG
BGT TOGBAD ;OR WE WILL GET UPSET
ASL R0 ;WORD INDEX
JSR PC,@54$(R0) ;DISPATCH ON DCT CODE
BR TOGMSG ;FIRE UP ANOTHER MESSAGE
54$: TOGC00 ;00 - ECHO PIPELINE MARKER
TOGC01 ;01 - CHARACTER GOBBLER
TOGC02 ;02 - TTY CHARACTERISTICS
TOGC03 ;03 - AUTO DIAL
TOGC04 ;04 - XOFF REQUEST
;HERE WHEN RECEIVE AN ECHO-PIPELINE MARKER
TOGC00: JSR PC,DVGDBY ;GO GET MARKER
TST DB.IBF(J) ;MORE STUFF PENDING ?
BNE 99$ ;IF SO CAN'T GO TO LOCAL ECHO
CMPB R0,DB.EPL(J) ;DOES IT MATCH LAST I SENT ?
BNE 99$ ;IF NOT IGNORE IT
BIC #TS.DFE,DB.DCS(J) ;BACK INTO LOCAL ECHO MODE
BIS #DS.XDS,(J) ;SEND NEW STATUS TO HOST
99$: RTS PC ;ALL DONE HERE
;HERE WHEN RECEIVE A DIAL-OUT REQUEST
TOGC03:
.IF NE FTDN11
JSR PC,DNSTRT ;START DIALING
RTS PC ;NOTHING MORE HERE
.IFF
TST (P)+ ;POP RETURN ADDRESS
BR TOGBAD ;BUMMER
.ENDC
;HERE TO SEND AN XOFF MSG ASAP
TOGC04: JSR PC,SNDXOF ;SEND XOFF RIGHT AWAY
BIC #DS.IST,@J ;LET THE -10 GENERATE THE XON
RTS PC ;AND KEEP WORKING
;HERE WHEN RECEIVE A CHARACTER GOBBLER
TOGC01: PIOFF ;DISABLE INTERRUPTS FOR A WHILE
MOV DB.TOB(J),R0 ;GET POINTER TO OUTPUT CHARS
MOV DB.TOB+2(J),R1 ;SAVE END POINTER ALSO
CLR DB.TOC(J) ;ZERO OUTPUT COUNT
CLR DB.TOB(J) ;NO OUTPUT TAKER
CLR DB.TOB+2(J) ;AND NO TAKER
PION ;REENABLE INTERRUPTS
BIC #TS.FRZ,DB.DCS(J) ;START OUTPUT IF STOPPED
MOV R1,-(SP) ;MOVE TO A MORE CONVENIENT PLACE
TST R0
BEQ 40$
10$: CMP R0,(P) ;WAS THAT LAST CHARACTER TO THROW AWAY?
BEQ 30$ ;YES, WE'RE DONE
ADVCNK R0,FREE ;ADVANCE A FREE CHUNK (IF NECESSARY)
MOVB (R0)+,R1 ;GET NEXT CHARACTER
CMP R1,#ESCF ;IS IT FUNCTION ESCAPE CHARACTER?
BNE 10$ ;NO, KEEP FLUSHING
ADVCNK R0,FREE ;ADVANCE CHUCKS, IF NEEDED
MOVB (R0)+,R1 ;GET FUNCTION CODE
JSR PC,DOESCF ;PERFORM FUNCTION
BR 10$ ;AND CONTINUE FLUSHING
30$: DEC R0 ;ENSURE WE HAVEN'T RUN OFF CHUNK
BIC #CNKSIZ-1,R0 ;FREE REST OF LIST
JSR PC,FRECKS ;FRECK IT!
40$: TSTB (P)+ ;CLEAN UP STACK
RTS PC ;BACK FOR MORE MESSAGES
;HERE WHEN RECEIVE A CHARACTERISTICS MESSAGE
TOGC02: MOV J,R2 ;COPY DEVICE BLOCK POINTER
ADD #DB.FIL,R2 ;POINT TO FILLER SECTION
MOV #6,R3 ;COUNTER
66$: JSR PC,DVGEXF ;GET AND EXTENSIBLE FIELD
CLC ;NEED LOGICAL SHIFT (DIVIDE BY 2)
ROR R0 ;GET FILL TIME AS SEC/500
BEQ 67$ ;IF 0 JUST USE IT
ASR R0 ;GET FILL TIME AS SEC/250
ADD #4,R0 ;FOR ROUND OFF
BIT #37000,R0 ;IS TIME TOO LARGE FOR TICK TIMER
BEQ 68$
NEG R0
SWAB R0 ;GET FILL TIME IN SEC
BR 67$
68$: ASR R0 ;GET FILL TIME IN SEC/125
ASR R0 ;GET FILL TIME IN SEC/62.5
67$: MOVB R0,(R2)+ ;SAVE FILLER
SOB R3,66$ ;LOOP BACK FOR REST OF FILLER
;NOW GET SPEED FROM CHARACTERISTICS MESSAGE
JSR PC,DVGEXF ;GET RECEIVE SPEED
.IF NE TTYN
JSR PC,75$ ;CONVERT RECEIVE SPEED TO A DH11 CODE
MOV DB.LCB(J),R2 ;POINT TO LINE CONTROL BLOCK
MOV LC.SPD(R2),R2 ;GET INITIAL GUESS FOR SPEED
MOV R2,-(P)
TST R1 ;CHECK SPEED TABLE INDEX FROM 75$
BLT 72$ ;IF DIDN'T FIND SPEED
BIC #^C377,R2 ;MASK OUT JUNK
SWAB R1 ;POSITION RECEIVE CODE IN "LH"
BIS R1,R2 ;SET NEW RECEIVE SPEED IN OUR COPY
.ENDC
72$: JSR PC,DVGEXF ;GET TRANSMIT SPEED
.IF NE TTYN
JSR PC,75$ ;CONVERT THAT TO A DH11 CODE
TST R1
BLT 74$ ;IF DIDN'T FIND SPEED
BIC #377,R2 ;MASK OUT JUNK
BIS R1,R2 ;PUT NEW SPEED IN OUR COPY
74$: CMP R2,(P)+ ;SAME AS LAST SPEED ?
BEQ TYSR60 ;IF SO IGNORE
PIOFF
MOV R2,-(P) ;SAVE SPEED
MOV DB.LCB(J),R2 ;POINT TO LCB
CMPB #LCS.AB,LC.STA(R2) ; AUTO BAUD ?
BNE 73$ ; NO
MOVB #LCS.RU,LC.STA(R2) ;SET TO RUN STATE
BIC #LCB.TM,LC.CAR(R2) ;CLEAR TIMER
73$: JSR PC,SETSPD ;SET NEW SPEED
TST (P)+ ;POP THE SPEED
PION
BR TYSR60
;HERE TO SEARCH SPEED TABLE FOR DH11 CODE
75$: MOV #SPDLIM-SPDTAB,R1 ;MAKE SPEED TABLE INDEX
76$: CMP R0,SPDTAB(R1) ;CHECK FOR MATCH
BEQ 78$
SUB #2,R1 ;LOWER INDEX TO SPDTAB
BPL 76$
78$: ASR R1 ; FORM TRUE INDEX
RTS PC
.ENDC
TYSR60: JSR PC,DVGEXF ;GET WIDTH
MOVB R0,DB.WID(J)
JSR PC,DVGEXF ;GET AUTO CAR RETURN POSITION
MOVB R0,DB.ACR(J)
JSR PC,DVGEXF ;GET ELEMENT NUMBER
.IF NE FT2741
MOV #BCDXIN-2-ELETAB,R1 ;FIRST INDEX TO TRY
82$: CMP ELETAB(R1),R0 ;HIT OUR BOY ?
BNE 84$ ;IF NOT RIGHT DON'T USE
SWAB R1 ;POITION BITS
ASR R1 ; DITTO
BIC #BCDCOD,DB.BCD(J) ;CLEAR OLD CODE
BPL 86$ ;BRANCH IF NOT 2741
BIS R1,DB.BCD(J) ;SET NEW CODE
84$: DECB R1 ;ON TO NEXT
DECB R1
BPL 82$
.ENDC
86$: JSR PC,DVGEXF ;GET 2741 BITS
.IF NE FT2741
BIC #<BCDTDY!BCDAPL!BCDHDB>,DB.BCD(J)
BIC #^C<BCDTDY!BCDAPL!BCDHDB>,R0
BIS R0,DB.BCD(J)
.ENDC
BIC #TT.APL,DB.TTS(J) ;CLEAR THE APL BIT INITIALLY
BIT #CHRAPL,R0 ;MAKE SURE WE GET THE APL BIT
BEQ 87$ ;NOT SET, LEAVE IT CLEAR
BIS #TT.APL,DB.TTS(J) ;YES, SET IT
87$: ASSERT EQ DB.OCN(J) ;COUNT SHOULD BE 0 NOW
RTS PC ;BACK FOR MORE [SUB]MESSAGES
TOGDON: BIT #DS.XDS,(J) ;SEND STATUS IF REQUIRED
BEQ 20$
JSR PC,DVPDCS
20$:
.IF NE FT.TSK
JSR PC,TK0WAK ;WAKE 'GET PRINTER' TASK IF ANY
MOV J,R3 ;COPY DDB ADDRESS
24$: MOV DB.TSK+6(J),J ;GET ADDRESS OF 'PUT KEYBOARD' TASK
BEQ 26$
JSR PC,TSKWAK
26$: MOV R3,J ;RESTORE DDB ADDRESS
.ENDC
JSR PC,BEGXMT ;START TYPING
;HERE TO CHECK FOR INPUT TO GO TO THE 10
TTYICK: BIT #DS.ACT,@J ;UNLESS ACTIVE
BNE 10$
BIT #DS.DIE!DS.DSC,(J) ;ARE WE DONE WITH THE CONNECTION
BEQ 10$ ;IF NOT, SEE IF THERE IS INPUT
JMP DVCCFM ;NO LONGER CONNECTED. SEND
; DISCONNECT CONFIRM AND CLEAN DDB
10$:
.IF NE DN11N
.IF NE FT.RDA&FT.TSK
TST DB.RDT(J) ; CHECK FOR RDA DEVICE
BEQ 17$ ; NO
JSR PC,DNSTTJ ; CHECK FOR AUTO DIAL ON DEVICE
JSR PC,RDXSTA ; CHECK STATUS
17$:
.ENDC
.ENDC
BIT #DS.IQU,@J ;IS NCL ALREADY SENDING OUR INPUT ?
BEQ 16$
12$:; JMP TYICK9 ;IF SO HOLD REST
RTS PC ;SAVE 2 BYTES
;NOW SHIP THE CHARACTERS
16$: BIT #DS.IST,(J) ;DID WE STOP INPUT?
BEQ 15$ ;NO, BRANCH
JSR PC,SNDXON ;YES, SEND AN XON
BIC #DS.IST,(J) ;AND CLEAR XOFF FLAG
15$:
.IF NE FT.TSK
CMP DB.ICC(J),#TTYMIC ;HOW MANY CHARS IN MSG?
BHIS 18$ ;IF FULL SEND IT
BIT #DS.PAU,(J) ;CHECK WHETHER WE SHOULD HOLD
BNE 12$
.ENDC
18$:
.IF NE FT.RDA
TST DB.RDT(J) ; RDA DEVICE ??
BEQ 19$ ; NO, KEEP GOING
TST DB.IDR(J) ; INPUT DATA REQUESTS ??
BNE 11$ ; SEND DATA
RTS PC ; NO, GO BACK
11$: JMP RDACN0
19$:
.ENDC
BIT #DS.EPL,@J ;NEED TO SEND AN ECHO PIPELINE MARKER ?
BEQ 20$ ;IF NOT DON'T BOTHER
MOV #4,R0 ;CODE THIS IS A CONTROL MSG
JSR PC,DVPBSM ;BEGIN CONTROL SUBMESSAGE
BCS TYICK3 ;IF WE CAN'T SEND MSG,
;PRETEND WE DIDN'T WANT TO
CLR R0 ;CODE IS ECHO-PIPELINE-MARKER
JSR PC,DVPDAT
BCS 20$ ;ERROR RETURN
MOVB DB.EPL(J),R0 ;SERIAL # FOR MARKER
INC R0 ;INCREMENT SERIAL NUMBER
JSR PC,DVPDAT
BCS 20$ ;ERROR RETURN
BIC #DS.EPL,@J ;FLAG WE HAVE DONE IT NOW
INCB DB.EPL(J) ;INCREMENT SERIAL NUMBER FOR REAL
;HERE TO CONSIDER SENDING CHARACTERISTICS
20$: BIT #DS.XCH,@J ;NEED TO SEND CHARACTERISTICS ?
BEQ TYICK3
MOV #4,R0 ;CHARACTERISTICS IS CONTROL SUBMSG
JSR PC,DVPBSM ;BEGIN SUBMESSAGE
BCS TYICK3 ;IF WE CAN'T SEND MSG,
;PRETEND WE DIDN'T WANT TO
MOV #2,R0 ;CODE IS 2 FOR CHARACTERISTICS
JSR PC,DVPDAT
BCS TYICK3 ;ERROR RETURN
MOV #6,R2 ;ESTABLISH COUNTER FOR FILLS
MOV J,R4 ;COPY DEVICE BLOCK ADDRESS
ADD #DB.FIL,R4 ;POINT TO FILLERS
22$: MOVB (R4)+,R0 ;GET NEXT FILLER
BIC #^C377,R0 ;STRIP EXTRA BITS
ASL R0
ASL R0
ASL R0
ASL R0
JSR PC,DVPEXD ;PUT EXTENSIBLE FIELD IN SUBMESSAGE
SOB R2,22$ ;LOOP BACK FOR REST OF FILLERS
.IF NE TTYN
MOV DB.LCB(J),R0 ;POINT TO LINE CONTROL BLOCK
MOV LC.SPD(R0),R0 ;GET SPEED
MOV R0,-(P)
SWAB R0
ASL R0 ;MAKE INTO INDEX
JSR PC,24$
MOV (P)+,R0
ASL R0
JSR PC,24$
BR 26$
24$: BIC #^C76,R0 ;STRIP EXTRA BITS
MOV SPDTAB(R0),R0 ;TRANSLATE TO BAUD
JMP DVPEXD
26$:
.IFF
MOV #^D110,R0 ;DEFAULT IS 110 BAUD
JSR PC,DVPEXD ;PUT INTO SUBMSG
MOV #^D110,R0 ;DEFAULT IS 110 BAUD
JSR PC,DVPEXD
.ENDC
MOVB DB.WID(J),R0 ;WIDTH
JSR PC,DVPEXA
MOVB DB.ACR(J),R0 ;AUTO CRLF POSITION
JSR PC,DVPEXA
.IF NE FT2741
MOV DB.BCD(J),R0 ;GET 2741 STATUS
SWAB R0
BIC #^C7,R0 ;LEAVE ONLY ELEMENT CODE
ROL R0
MOV ELETAB(R0),R0 ;GET ELEMENT NUMBER FOR TTY
.IFF
CLR R0 ;FOR NON 2741 80'S SEND ZIP
.ENDC
JSR PC,DVPEXD
.IF NE FT2741
MOV DB.BCD(J),R0 ;2741 BITS
BIC #^C<BCDTDY!BCDAPL!BCDHDB>,R0 ;STRIP EXTRA BITS
.ENDC
BIT #TT.APL,DB.TTS(J) ;MAKE SURE WE SEND THE APL BIT
BEQ 30$ ;NOT SET, LEAVE IT CLEAR
BIS #CHRAPL,R0 ;YES, SET IT
30$: JSR PC,DVPEXD
BIC #DS.XCH,@J ;HAVE SENT THEM NOW
TYICK3:
;CHECK TO SEE IF WE WANT TO TURN LINE AROUND
.IF NE FT2741
MOV DB.BCD(J),R0 ;GET 2741 STATUS
BPL 20$ ;IF NOT 2741 WE ARE DONE
BIT #BCDPRL,R0 ;IS THE PRINTER LOCKED ?
BNE 20$ ;IF SO WE ARE DDONE
BIT #DS.ACT,@J ;IS TRANSMITTER ACTIVE ?
BNE 20$ ;IF SO CAN'T GIVE IT UP
BIT #TS.TIW,DB.DCS(J) ;DEVICE IN INPUT WAIT ?
BEQ 20$ ;IF NOT WE ARE DONE
MOV #<4*400>+1,DB.TIM(J) ;START CLOCK
BIS #BCDPRL!BCDCDB,DB.BCD(J)
BIS #DS.ACT,@J
.ENDC;.IF NE FT2741
20$:
.IF NE FT.TSK
BIT #DS.Q10,(J) ;ID THERE STUFF IN THIS ?
BEQ 24$
BIC #DS.Q10,(J) ;NOT ANY LONGER
BIC #TS.TIW,DB.DCS(J) ;TEN NO LONGER HUNGRY
BR 26$
.ENDC
24$: BIT #DS.XDS,@J ;NEED TO SEND DEVICE STATUS ?
BEQ 40$
26$:
JSR PC,DVPDCS ;PUT DEVICE STATUS INTO THE MESSAGE
40$:
44$:
RDACN0: MOV DB.IBF(J),R0 ;GET MESSAGE POINTER
BEQ TYICK9 ;IF NO CORE
.IF NE FT.RDA
TST DB.RDT(J) ;RDX DEVICE ?
BEQ 45$ ; NO
BPL 39$ ;NO BREAK SEEN
BIC #RDEBRK,DB.RDT(J) ;CLEAR BREAK SEEN
38$: DECB DB.IDR(J) ;COUNT REQUEST OFF
BR 45$
39$: CMP DB.ICC(J),#TTYMIC ;DO WE HAVE TO SHIP IT ?
BHIS 38$ ; YES
BR TYICK9 ;RETURN TO USER
45$:
.ENDC
TST DB.ICN(J) ;UNFINISHED SUBMESSAGE ?
BEQ 46$
JSR PC,DVPSBM ;CLOSE OFF SUBMESSAGE
46$: MOV J,CN.DDB(R0) ;SAVE DEVICE BLOCK ADDRESS
BIS #DS.IQU,@J ;SO WE DON'T SEND MORE FOR WHILE
CLR DB.ICC(J) ;NO LONGER HOLDING TTY CHARS
JSR PC,NCLIN1 ;GET RID OF MESSAGE
CLR DB.IBF(J) ;FORGET BUFFER
CLR DB.IAD(J) ;FORGET BYTE POINTER
;
; Here after we have cleared our count of input
; characters that gets maintained at interupt level.
; NOTE that we moved the XON code from higher up to down
; here, since we want to make sure all is idle before we
; let the terminal start up again
;
.IF NE FT.RDA
TST DB.RDT(J) ;IS THIS AN RDA
BNE TYICK9 ;YES, SKIP THIS
.ENDC
BIT #DS.IST,(J) ;DID WE STOP INPUT?
BEQ TYICK9 ;NO, BRANCH
JSR PC,SNDXON ;YES, GO SEND AN XON
BIC #DS.IST,(J) ;AND CLEAR XOFF FLAG
TYICK9: RTS PC
SPDTAB: .WORD ^D0
.WORD ^D50
.WORD ^D75
.WORD ^D110
.WORD ^D134
.WORD ^D150
.WORD ^D200
.WORD ^D300
.WORD ^D600
.WORD ^D1200
.WORD ^D1800
.WORD ^D2000
.WORD ^D2400
.WORD ^D3600
.WORD ^D4800
.WORD ^D7200
.WORD ^D9600
.WORD ^D19200
.WORD ^D1
SPDLIM: .WORD ^D2
.MACRO X Q ;MACRO TO MAKE IT EASY TO DEFINE DISPATCH ENTRYS
.IF DF Q
.WORD Q
.IFF
.WORD TRPINT
.ENDC
.ENDM
DEVTYP: ;DISPATCH FOR TYPE OF DEVICE TO TYPE ON
X DHTYPE
X DZTYPE
DEVSPD: ;DISPATCH FOR TYPE OF DEVICE TO SET SPEED ON
X DHSPD
X DZSPD
DEVBKN: ;DISPATCH TO TURN ON XMIT-BREAK
X DHBKON
X DZBKON
DEVBKF: ;DISPATCH TO TURN OFF XMIT-BREAK
X DHBKOF
X DZBKOF
;DEVICE TIMER (USED FOR IRMA CATCHER)
RDATIM:
CTYTIM:
TTYTIM:
JMP @10$(R0) ;DISPATCH ON TIMER CODE
10$: TCLK00 ;(TCLK00) FILLER
.IF NE FT2741
TCLK02 ;(TCLK02)
TCLK04 ;(TCLK04)
TCLK06 ;(TCLK06)
TCLK10 ;(TCLK10)
30$ ;(TCLK12)
.IFF;.IF NE FT2741
30$ ;(TCLK02)
30$ ;(TCLK04)
30$ ;(TCLK06)
30$ ;(TCLK10)
30$ ;(TCLK12)
.ENDC;.IF NE FT2741
30$: RTS PC ;HERE TO JUST RETURN
TCLK00: PIOFF
BIT #DS.ACT,@J ;BE SURE IS ACTIVE
BEQ 90$ ;THIS IS A RACE CONDITION
JSR PC,XMTINT ;FAKE TRANSMIT DONE INTERRUPT
90$: PION
100$: RTS PC
TYPHIA: MOV #HIAMSG,R1 ; GET "HOST IS AVAILABLE"
BR TTYMSG ; AND PRINT IT ON THE TTY
TYPNHA: MOV #NHAMSG,R1 ;GET "NO HOST AVAILABLE"
BR TTYMSG ; AND GIVE IT TO THE USER
TYPWCC: MOV #WCCMSG,R1 ;GET "WAITING FOR CONNECT CONFIRM"
BR TTYMSG
TYPHSD: MOV #HSDMSG,R1 ;GET "HOST SENT DISCONNECT"
BR TTYMSG
TYPHWA: MOV #HWAMSG,R1 ;GET "HOST WENT AWAY"
BR TTYMSG
TYPIBF: MOV #IBFMSG,R1 ;GET "INPUT BUFFER FULL"
; BR TTYMSG
;TTYMSG ROUTINE TO START A TTY TYPING A FIXED STRING. (WON'T
; TYPE STRING IF AN RDA LINE, OR IF ONE IS ALREADY TYPING.)
;ENTER WITH
; R1/ ADDRESS OF STRING TO TYPE
TTYMSG: TST DB.STR(J) ;DON'T FORCE THE MSG IF
BNE 99$ ;ONE IS ALREADY TYPING OUT
.IF NE FT.RDA
TST DB.RDT(J) ;RDA ??
BNE 99$ ;YES, DON'T SEND HIM GARBAGE.
.ENDC
MOV R1,DB.STR(J)
; CLRB DB.TIM(J) ;CLEAR TIMER SO OUTPUT SURE TO START.
; ; (THIS IS NECESSARY BECAUSE IF WE
; ; ARE PRINTING A DISCONNECT MSG,
; ; CLRDDB WILL CLEAR TIMER AND STOP US)
JSR PC,BEGXMT ;START THE TTY TYPING
99$: RTS PC
TYMSG1: RTS PC
;HERE FROM LOOP WITH INPUT CHAR IN R0, DEVICE BLOCK ADR IN J
RECINT: BIT #DS.DIE!DS.DSC,@J ;DID TEN DIE ?
BNE TYMSG1 ;TOSS CHAR AND LET DISCONNECT
; CODE TELL USER WHAT'S GOING ON
.IF NE FTHOST!FT.RDA
BIT #DS.CON,@J ;IS TTY CONNECTED ?
BNE RECIN0
.ENDC
.IF NE FT.RDA
TST DB.RDT(J) ; IS THIS RDA DEV ??
BNE TYMSG1 ; YES, DUMP IT
.ENDC
.IF NE FTHOST
JSR PC,FNDPFH ;TRY TO CONNECT TO HOST
BEQ TYPNHA ;IF NO HOST AVAILABLE, TELL THE USER
JSR PC,SNDCON ;TRY TO CONNECT TO THE HOST
BR TYPWCC ;TELL THE GUY WE SENT A CONNECT FOR HIM
.ENDC
;HERE TO PROCESS THE CHARACTER
RECIN0:
.IF NE FTHOST
TST DB.RLA(J) ;ARE WE HALF WAY THERE
BEQ TYPWCC ;IF SO, SAY "WAITING FOR CONFIRM"
.ENDC
.IF NE FT.TSK
BIT #DS.PAU,(J) ;DID THIS COME FROM A TASK
BEQ 14$ ;NO, INTERUPT LEVEL CHECKS BUFFER FULL
CMP #TTYMIC,DB.ICC(J) ;HOW MANY CHARS ALREADY WAITING ?
BMI TYPIBF ;TELL USER THAT INPUT BUFFER IS FULL
.ENDC
14$: BIC #^C377,R0 ;STRIP EXTRA BITS
MOV R0,R1 ;COPY CHARACTER
BIC #^C177,R1 ;STRIP EXTRA BITS
CMPB R1,#21 ;IS THIS AN "XON"
BNE 15$ ;NO, MOVE ALONG
SAVE <R0,R1> ;SAVE CHARACTER
JSR PC,BEGXMT ;YES, START TYPING
RESTORE <R1,R0> ;GET BACK CHARACTER
15$: BIT #DS.XDS,(J) ;SEND NEW STATUS TO HOST?
BEQ 16$ ;NO, KEEP GOING
SAVE <R0,R1> ;PROTECT OUR CHAR FROM DNDEV
JSR PC,DVPDCS ;SEND STATUS TO THE -10
RESTORE <R1,R0> ;GET THE CHARACTER BACK
16$: BIT #TS.IMI,DB.DCS(J) ;CHECK FOR IMAGE INPUT MODE
BNE RECIN1 ;IN WHICH WHICH CASE NO EDITING
TST R1
BEQ RECINX ;FLUSH NULLS
CMP R1,#40 ;SPACE?
BNE 20$ ;NOPE, DON'T DO AUTO CRLF CHECK
MOVB DB.ACR(J),R2 ;GET ACR POSITION
BEQ 20$ ;0 SAYS WE DON'T DO IT
CMPB R2,DB.COL(J) ;HAVE WE REACHED THAT POINT?
BHI 20$ ;NOT YET, KEEP GOING
MOV #215,R0 ;CHANGE SPACE INTO CR
MOV #15,R1 ;IN BOTH PLACES
20$: BITB #CF..LC,CHRTAB(R1) ;IS CHARACTER LOWER CASE ?
BEQ RECIN1
BIT #TS..LC,DB.DCS(J) ;DO WE WANT TO CONVERT LC TO UPPER ?
BEQ RECIN1
ADD #140,R0 ;CONVERT TO UPPER CASE AND
; COMPLEMENT PARITY
RECIN1:
.IF NE FT.RDA
TST DB.RDT(J) ; RDA ??
BNE 99$ ; YES, CHECK FOR BREAK
.ENDC
42$: BIT #TS.DFE,DB.DCS(J) ;IN DEFERED ECHO MODE ?
BNE 55$ ;SEND IT WITH A NEW ECHOPIPELINE MARKER
BIT #DS.ACT,@J ;IS LINE ALREADY TYPING ?
BNE 50$ ;IF SO GO INTO DEFERRED ECHO MODE
.IF NE FT2741
TST DB.BCD(J) ;IS THIS A 2741 ?
BMI 50$ ;IF SO GO INTO DEFERRED ECHO MODE
.ENDC
BIT #<TS.TAP!TS.IMI>,DB.DCS(J) ;TAPE OR IMAGE MODE?
BNE 43$ ;IF SO, THEN <CR> NOT SPECIAL
CMPB #15,R1 ;IS CHAR A CARRIAGE RETURN ?
BEQ 48$ ;IF SO SPECIAL ACTION
43$: BITB #CHRDEF,CHRTAB(R1) ;DOES THIS CHAR PUT US INTO DEFERRED ECHO MODE ?
BNE 50$
MOV R0,-(P) ;SAVE CHAR
.IF NE FT.TSK
JSR PC,TK0WAK ;WAKE UP THE 'GET PRINTER' TASK
BEQ 46$ ;IF NONE, JUST ECHO
JSR PC,QTYCHR ;USE NCL ENTRY
BR 49$
.ENDC
46$: TSTB DB.HLD(J) ;IF ALREADY HOLDING A CHAR BETTER FORCE IT OUT
BEQ 44$
47$: JSR PC,BEGXMT ;ECHO IT
MOVB (P),DB.HLD(J) ;SAVE CHAR
BR 45$
44$: MOVB R0,DB.HLD(J) ;SAVE CHAR
49$: JSR PC,BEGXMT ;ECHO IT
45$: MOV (P)+,R0 ;GET CHAR BACK
.IF NE FT.HLD ;IF WE ARE HOLDING CHARACTERS
CMP #<TTYMIC/2>,DB.ICC(J) ;DO WE HAVE PLENTY OF CHARACTERS?
BMI 60$ ;YES, SEND THE MESSAGE NOW
TWIDDLE ;FOR THISE WHO WATCH
TWIDDLE DB.ICC(J) ;SEE HOW MANY CHARS IN THE MESSAGE
JSR PC,DVPDAT ;PUT BYTE INTO THE MESSAGE
BR 70$ ;GO RETURN
.IFF
BR 60$ ;PUT CHAR IN INPUT QUEUE
.ENDC;.IF NE FT.HLD ;IF WE ARE HOLDING CHARACTERS
;HERE WHEN USER TYPES A CARRIAGE RETURN WHILE IN LOCAL ECHO MODE
48$:
.IF NE FT.TSK
JSR PC,TK0WAK ;WAKE UP 'GET PRINTER' TASK
BEQ 51$
MOV R0,-(P) ;SAVE CHARACTER <CR>
JSR PC,QTYCHR ;ECHO THE <CR>
MOV #12,R0 ;AND APPEND A <LF>
JSR PC,QTYCHR
MOV (P)+,R0 ;GET THE <CR> BACK
BR 52$ ;NOW SEND THE <CR> TO THE HOST
.ENDC
51$: MOV #CRLMSG,DB.STR(J) ;TYPE A CR/LF
52$: JSR PC,55$ ;PUT CARRIAGE RETURN INTO MSG
BIS #TS.DFE,DB.DCS(J) ;SET DEFERED ECHO MODE
JSR PC,BEGXMT
JMP DVPDCS ;SEND NEW STATUS TO 10
;IF RDA, CHECK FOR BREAK
.IF NE FT.RDA
99$: CMP #RDABRK,R1 ;BREAK ??
BNE 60$ ; NO
BIS #RDEBRK,DB.RDT(J) ;SET IT SEEN
BR 60$
.ENDC
;HERE TO GO INTO DEFERRED ECHO MODE
50$: BIS #TS.DFE,DB.DCS(J) ;SET DEFERED ECHO FLAG
MOV R0,-(P) ;SAVE INPUT CHAR
JSR PC,DVPDCS ;PUT STATUS INTO MESSAGE
MOV (P)+,R0 ;GET CHAR BACK
55$: BIS #DS.EPL,@J ;NEED TO SEND A NEW ECHO PIPELINE MARKER
60$: JSR PC,DVPDAT ;PUT BYTE INTO THE MESSAGE
98$: JSR PC,QUEDEV ;WAKE SERVICE ROUTINE
70$:
.IF NE FT.RDA!FT.TSK
.IF NE FT.RDA
TST DB.RDT(J) ;IS THIS AN RDA DEVICE?
BNE 75$ ;YES, NEED TO COUNT CHAR
.ENDC
.IF NE FT.TSK
BIT #DS.PAU,(J) ;DID THIS COME FROM A TASK?
BEQ RECINX ;NO, DON'T COUNT, INTERUPT LEVEL HAS
.ENDC
75$: INC DB.ICC(J) ;COUNT CHAR INTO THE MESSAGE
.ENDC ; .IF NE FT.RDA!FT.TSK
RECINX: RTS PC
;HERE TO SEND XON
SNDXON: MOVB #21,R0 ;GET XON
BR SNDNOW ;GO SEND IT
;HERE TO SEND XOFF
SNDXOF: MOVB #223,R0 ;GET XOFF
SNDNOW: PIOFF ;INTERUPTS OFF
BIT #DS.ACT,@J ;ARE WE ALREADY OUTPUTING?
BEQ 10$ ;NO, START OUTPUT
MOVB R0,DB.ASP(J) ;YES, WE'LL CATCH IT AT NEXT XMT INT
BR 20$ ;TURN ON INTERRUPTS AND EXIT
10$: BIS #DS.ACT,@J ;SAY WE ARE TYPING
JSR PC,TYPE90 ;GO SEND IT
20$: PION ;INTERUPTS BACK ON
RTS PC ;RETURN
BEGXMT: PIOFF ;DISABLE INTERRUPTS
BIT #DS.ACT,@J ;ARE WE ALREADY TYPING ?
BNE 20$ ;IN CASE ALREAY TYPING
BIS #DS.ACT,@J ;SET ACTIVE FLAG
TSTB DB.TIM(J) ;IF TIMER IS RUNNING,EXIT
BNE 20$
JSR PC,XMTINT
20$: PION ;REENABLE INTERRUPTS
RTS PC
;HERE WHEN NO OUTPUT LEFT AND MAY WANT TO RELEASE OUTPUT CHUNK
XMT.80: TST DB.OBF(J)
BNE XMT.90
DEC R0 ;BACK UP TAKER
BIC #CNKSIZ-1,R0 ;MAKE INTO A CHUNK ADR
JSR PC,FRECNK ;RELEASE CHUNK
CLR DB.TOB(J) ;CLEAR POINTER
CLR DB.TOB+2(J) ;AND PUTTER
;HERE WHEN NOTHING MORE TO TYPE
XMT.90: JSR PC,QUEDEV ;SEND DATA REQUESTS MAYBE
.IF NE FT2741
TSTB DB.TIM+1(J) ;DOING 2741 FUNCTION ?
BNE 20$ ;IF SO DON'T STOP TIMER
.ENDC
BIC #DS.ACT,@J ;CLEAR ACTIVE FLAG
.IF NE FT.TSK
MOV J,-(P) ;SAVE DDB ADR
MOV DB.TSK+4(J),J ;GET TASK BLOCK ADR
BEQ 12$ ;IF NONE WE ARE DONE
JSR PC,TSKWAK ;WAKE UP THE TASK
12$: MOV (P)+,J ;RESTORE DDB ADR
.ENDC
20$: RTS PC
;HERE AT INTERRUPT LEVEL TO SEE IF THERE ARE MORE CHARS TO TYPE
TTDZOU:
TTDHOU:
XMTINT:
.IF NE FT2741
TST DB.BCD(J) ;2741S USE DB.ASP FOR OTHER THAN XOF/XON
BMI 1$ ;SO DON'T CHECK HERE
.ENDC
MOVB DB.ASP(J),R0 ;DO WE WANT TO SEND A CHARACTER FAST?
BEQ 1$ ;NO
CLRB DB.ASP(J) ;YES, CLEAR OUT THE CHAR
JMP TYPE90 ;AND SEND IT
1$: CMP #20,JIFFLG ;IF CLOCK LEVEL HAS RUN RECENTLY
BGE XMT.0 ; THEN IT'S OK TO RUN TERMINALS NOW
MOVB #3,DB.TIM(J) ;IF WE'VE BEEN TYING UP THE MACHINE
BIS #DS.ACT,@J ;FLAG THE LINE AS "ACTIVE"
5$: RTS PC ;BUT OTHERWISE SHUT IT DOWN
; (LETTING IRMA RESTART IT LATER)
XMT.0: CLR DB.TIM(J) ;CLEAR THE TIMER
.IF NE FT.RDA
TST DB.RDT(J) ;RDA DEVICE ??
BNE 33$ ; YES
.ENDC
MOV DB.LCB(J),R1 ;POINT TO LCB OF LINE
BIT #LCB.DS,@R1 ;IS THIS A DATA SET LINE?
BEQ 2$ ; NO, SO GO AHEAD
CMPB #LCS.CD,LC.STA(R1) ;SEE IF WE ARE AUTOBAUDING (OR BOUT TO)
BGT 2$ ; STATE < LCS.CD
CMPB #LCS.AB,LC.STA(R1) ;MAX STATE TO HOLD ON
BLT 2$ ; STATE > LCS.AB
MOVB #-6,DB.TIM(J) ;WAIT FOR LATER TO CHECK FOR OUTPUT
RTS PC
2$:
.IF NE FT2741
TST DB.BCD(J) ;GET 2741 STATUS BITS
BPL 10$ ;BRANCH IF NOT 2741
MOVB DB.ASP(J),R1 ;HOLDING A CHARACTER ?
BEQ 10$
CLRB DB.ASP(J)
BR 38$
.ENDC
10$: MOV DB.FTM(J),DB.TIM(J) ;SET IRMA TIMER WAITING IN WINGS
BEQ 20$ ;IF NONE FIND NEXT CHAR TO TYPE
CLR DB.FTM(J)
RTS PC ;WAIT FOR TIMER TO GO OFF
20$: TST DB.STR(J) ;IS THERE A MESSAGE TO TYPE ?
BEQ 30$
MOVB @DB.STR(J),R1 ;GET NEXT CHAR IN STRING
BNE 22$
CLR DB.STR(J) ;HAVE EXHAUSTED STRING
BR 30$
22$: INC DB.STR(J) ;ADVANCE STRING POINTER
BR 38$
30$: MOVB DB.HLD(J),R1 ;HOLDING A CHARACTER ?
BEQ 32$ ; FROM FREE CR/LF ?
CLRB DB.HLD(J) ;DON'T TYPE IT TWICE
BR 38$ ;BUT GO TYPE IT NOW
32$: BIT #TS.FRZ,DB.DCS(J) ;IS OUTPUT STOPPED WITH XOF ?
BNE XMT.90 ;IF SO STOP TYPING
33$:
.IF NE FT.TSK
MOV DB.PTK(J),R0 ;GET PRINTER TAKER (TASK)
BEQ 50$ ;IF NON, TRY FOR STUFF FROM NCL
DEC DB.PCN(J) ;ADJUST COUNT
ASSERT PL
JSR PC,XMTGET ;POINT TO NEXT CHARACTER IN CHUNKS
MOVB (R0)+,R1 ;GET NEXT BYTE
CMP R0,DB.PPT(J) ;WAS THAT THE LAST
BNE 46$
DEC R0
BIC #CNKSIZ-1,R0 ;RESTORE CHUNK POINTER
JSR PC,FRECNK ;RELEASE CHUNK
CLR DB.PPT(J) ;CLEAR PUTTER
CLR R0
46$: MOV R0,DB.PTK(J) ;SAVE UPDATED PUTTER
BR 38$
50$: TST DB.TSK(J) ;IS THERE A 'GET PRINTER' TASK
BNE XMT.90 ;IF SO STOP THE XMITTER
.ENDC
36$: MOV DB.TOB(J),R0 ;GET POINTER TO OUTPUT CHARS
BEQ XMT.90 ;IF NONE WE ARE DONE
CMP R0,DB.TOB+2(J) ;SAME AS PUTTER ?
BEQ XMT.80
JSR PC,XMTGET ;POINT TO NEXT BYTE
MOVB (R0)+,R1 ;GET NEXT BYTE
MOV R0,DB.TOB(J)
DEC DB.TOC(J) ;COUNT CHAR OUT OF CHUNKS
CMP R1,#ESCF ;IS IT ESCAPE FUNCTION CHARACTER?
BNE 38$ ;NO, CONTINUE NORMALLY
JSR PC,XMTGET ;POINT TO NEXT CHARACTER
MOVB (R0)+,R1 ;GET FUNCTION
MOV R0,DB.TOB(J) ;UPDATE TAKER
DEC DB.TOC(J) ;AND ACCOUNT FOR CHARACTER
CMP R1,#ESCF ;ANOTHER ESCAPE?
BEQ 38$ ;YES, PASS IT ON AS DATA
JSR PC,DOESCF ;NO, DO FUNCTION
BR 36$ ;LOOK FOR ANOTHER CHARACTER
38$: MOVB #-2,DB.TIM(J) ;RESET IRMA CATCHER
BIT #TS.IMO,DB.DCS(J) ;IMAGE MODE?
BEQ 39$ ;NO,
MOV R1,R0 ;YES, COPY CHARACTER
JMP TYPE90 ; NO EDITING
39$: CMPB #211,R1 ;IS THIS A TAB?
BEQ 40$ ; IF SO, GO DO FILL
CMPB #11,R1 ;IS THE OTHER FLAVOR OF TAB ?
BNE TYPEIT
40$: MOVB DB.COL(J),R2 ;GET CURRENT COLUMN
ADD #10,R2 ;WHERE WE WILL BE WHEN DONE
BIC #7,R2
BIT #TS.CRL,DB.DCS(J) ;EVER DO FREE CR/LF
BNE 62$
CMPB R2,DB.WID(J) ;IS THAT INSIDE BOUNDRY ?
BLOS 62$
MOV R1,R0 ;PUT CH WHERE IT IS EXPECTED
JMP TYPE85 ;IF NOT TYPE CR FIRST
62$: BIT #TS.TAB,DB.DCS(J) ;DOES TTY HAVE HARDEWARE TAB ?
BNE XMT.2
INCB DB.COL(J) ;ADVANCE COLUMN POINTER
BITB #7,DB.COL(J) ;WAS THAT LAST ?
BEQ XMT.1
MOVB R1,DB.HLD(J) ;SAVE TAB FOR LATER
XMT.1: MOV #240,R1
DECB DB.COL(J) ;SPACES WILL INC LATER
BR TYPEIT
XMT.2: MOVB R2,DB.COL(J) ;SAVE COLUMN
BR TYPEIT ;GO TYPE CHARACTER
;SUBROUTINE TO ADVANCE CHUNKS AND CAUSE DATA REG UNITS TO BE SENT
;CALL MOV <CHUNK ADDRESS<,R0
XMTGET: BIT #CNKSIZ-1,R0 ;ARE WE PAST END OF CURRENT CHUNK?
BNE 10$ ;NO, NOTHING SPECIAL
JSR PC,QUEDEV ;YES, WAKE SERVICE ROUTINE AT LOOP LEVEL
10$: ADVCNK R0,FREE ;POINT TO NEXT BYTE
RTS PC ;RETURN TO CALLER
;SUBROUTINE TO DO ESCAPE FUNCTION
; CALL MOV <FNC>,R1
; JSR PC,DOESCF ;GET FUNCTION IN REGISTER
DOESCF: CMP R1,#ESCF ;IS IT A SECOND ESCAPE CHARACTER?
BEQ 10$ ;IF SO, RETURN IMMEDIATELY
ASL R1 ;MAKE INDEX INTO ESCTAB
CMP R1,#MAXESC ;CHECK RANGE
ASSERT LE
JSR PC,@ESCTAB(R1) ;DO FUNCTION
10$: RTS PC
ESCTAB: ;ESCAPE FUNCTION TABLE
IMOON ;IMAGE OUT ON
IMOOFF ;IMAGE OUT OFF
MAXESC=.-ESCTAB-2 ;MAXIMUM LEGAL INDEX
IMOON: BIS #TS.IMO,DB.DCS(J)
RTS PC
IMOOFF: BIC #TS.IMO,DB.DCS(J)
RTS PC
;HERE TYPE A CHAR
; CALL JSR PC,TYPEIT ;WITH J SET UP AND CHAR IN R1
TYPEIT:
.IF NE FT2741
MOV DB.BCD(J),R3 ;GET 2741 STATUS BITS
BMI 10$ ;BRANCH IF 2741
JMP TYPE40 ;NOT 2741 SO NO SPECIAL HANDLING
10$: TRACE 27
BIT #BCDPRL,R3 ;TEST FOR PRINTER LOCKED
BEQ TYPE31 ;BRANCH IF NOT LOCKED
BIT #BCDBRK,R3 ;GO ON IF RCVBRK FLAG IS SET
BNE TYPE31
MOVB R1,DB.ASP(J) ;SAVE CHAR FOR LATER
BIT #BCDHDB,R3 ;TEST FOR REVERSE BREAK FEATURE
BEQ 6$ ;BRANCH IF DOESN'T HAVE IT
BIT #BCDCDB,R3 ;CHECK FOR OK TO DODEBREAK
BEQ 6$
BIT #BCDRCR,R3 ;WAS LAST CHAR IN A CR ?
BNE 6$ ;IF SO WE'LL GET CONTROL SOON ANYWAY
JINDEX JSR,DB.TYP(J),R3,DEVBKN ;CALL DRIVER TO SEND BREAK
BIS #BCDKBL!BCDXRB,DB.BCD(J);PRINTER LOCKED, XMT REV BREAK
MOV #<6*400>+^D21,DB.TIM(J) ;TIMER TO STOP BREAK
6$: RTS PC ;AND RETURN TO CALLER
TYPE31: BIC #^C177,R1 ;STRIP PARITY
;BEQ XMTINT ;FLUSH NULLS
;CMP #177,R1 ;TRANSMITTING RUBOUT ?
;BEQ XMTINT ;FLUSH RUBOUTS
;MAKE SPECIAL CHECKS FOR CARRIAGE RETURN
CMP #15,R1 ;IS THIS A CARRIAGE RETURN
BNE 10$ ;BRANCH IF NOT A CR
BIT #BCDOCR,R3 ;2ND CR IN A ROW ?
BNE 11$ ;PROBABLY FILLER - FLUSH IT
MOV #BCDCRL,R0 ;CARRIAGE RETURN CHAR
JMP TYPE37 ;GO TYPE CR
10$: BIT #BCDOCR,R3 ;DID 10 JUST SEND A CR ?
BEQ 12$ ;IF NOT DON'T CHECK FURTHER
BIC #BCDOCR,R3 ;CLEAR THE FLAG
MOV R3,DB.BCD(J) ;IN CASE FOLLOWING IS LF
CMP #12,R1 ;IS THIS A LINE FEED ?
BNE 12$ ;NO, KEEP GOING
11$: JMP XMTINT ;FLUSH LINE FEEDS
12$: MOV R3,R2 ;MAKE A COPY OF THE STATUS WORD
BIC #^CBCDCOD,R2 ;LEAVE CODE ONLY
MOV R2,R0 ;IN CASE IS NOT TIDY
ADD R1,R2
MOVB BCDXOU(R2),R1 ;TRANSLATE CHARACTER
BGE 40$ ;BRANCH IF THIS CHAR ISN'T AFFECTED BY TIDY
BIT #BCDTDY!BCDAPL,R3 ;CHECK FOR APL MODE OR TIDY
BNE 40$ ;IN WHICH CASE NOTHING SPECIAL
BIC #^C177,R2 ;STRIP EXTRA BITS
MOVB R2,DB.ASP(J) ;SAVE CHAR IN CASE WE DON'T TYPE IMMEDIATELY
BIT #BCDCON,R3 ;HAVE WE ALREADY TYPED THE TICK ?
BNE 30$ ;IF SO DONE FOR NOW
MOVB ARROW+BCDXOU(R0),R1 ;IN CASE WE WANTED A ^
TSTB TDYTAB(R2) ;DO WE WANT A ' OR A ^
BGE 23$
MOVB QUOTE+BCDXOU(R0),R1 ;WANTS A ' INSTEAD OF AN ARROW
23$: JSR PC,60$ ;BE SURE CASE SHIFT IS RIGHT
BIS #BCDCON,R3 ;SET HAVE SENT ' OR ^ FLAG
BR TYPE35 ;JUST TYPE IT
30$: MOVB TDYTAB(R2),R2 ;CONVERT THE CHAR
BIC #^C177,R2 ;STRIP EXTRA BITS
ADD R0,R2 ;ADD IN CHARACTER SET
MOVB BCDXOU(R2),R1 ;GET WHAT TO TYPE INSTEAD
JSR PC,60$ ;BE SURE CASE SHIFT IS RIGHT
CLRB DB.ASP(J) ;CLEAR SO WE DON'T TYPE AGAIN
BIC #BCDCON,R3 ;CLEAR FLAG
40$: JSR PC,60$ ;BE SURE CASE SHIFT IS RIGHT
BR TYPE35
;HERE TO BE SURE WE ARE IN RIGHT CASE SHIFT
; CALL JSR PC,60$
; RETURN IF IN RIGHT SHIFT
60$: CMP #BCDSPC,R1 ;TEST FOR CHAR IS A SPACE
BEQ 68$ ;IF SO DON'T CHECK SHIFT
BIT #10,R1 ;CHECK FOR NON-PRINTING CHARS
BEQ 61$ ; WHICH DON'T CARE ABOUT SHIFT CASE
BIT #4,R1 ;DISTINGUISHED BY 14 BITS IN CODE
BNE 68$ ;ONE OF THEM
61$: BIT #100,R1 ;TEST FOR UPPER SHIFT CHAR
BNE 64$ ;BRANCH IF NEED SHIFT
BIT #BCDUPS,R3 ;ARE WE ALREADY IN DOWN SHIFT ?
BEQ 68$ ;BRANCH IF SO
BIC #BCDUPS,R3
MOV #BCDLCS,R0 ;DOWN SHIFT CHAR
BR 66$
64$: BIT #BCDUPS,R3 ;ARE WE ALREADY IN UP SHFIT ?
BNE 68$ ;BRANCH IF SO
BIS #BCDUPS,R3 ;SET UP SHIFT
MOV #BCDUCS,R0
66$: TST (P)+ ;CLEAN OFF STACK
TSTB DB.ASP(J) ;ALREADY HOLDING A CHAR ?
BNE TYPE39 ;TYPE CHAR
MOVB R2,DB.ASP(J) ;SAVE CHAR TO TYPE LATER
BR TYPE39
68$: RTS PC
;HERE TO SET FILLER TIMES FOR 2741
TYPE35: MOV R3,DB.BCD(J) ;UPDATE STATUS
MOV R1,R0 ;COPY CHAR
CMPB #035,R0 ;IS CHAR A BACKSPACE ?
BNE 10$ ;NO
JMP TYPE81
10$: CMPB #057,R0 ;HORIZONTAL TAB?
BNE 22$
20$: MOVB DB.COL(J),R1 ;TAB USES SAME OBSTRUSE FORMULA FOR FILL
BIC #^C377,R1 ;AS LOSER HAS SET HIS TABS TO 8N FLAVOR
MOV R1,-(SP) ;SAVE CURRENT POSITION
BIS #7,R1 ;FIND NEXT MULT OF 8
INC R1
SUB (SP)+,R1 ;GET DELTA
ADD #8.+8.+1,R1 ;TWICE THE CONSTANT + ROUNDER
ASR R1 ;DELTA/2 + 8 (ROUNDED)
MOVB R1,DB.FTM(J) ;SET FILLER
BR TYPE83 ;GO CONSIDER FREE CRLF
22$: CMPB #056,R0 ;IS CHAR A LINE FEED?
BNE 23$
MOVB #5,DB.FTM(J) ;LINE FEED FILL IS ABOUT ONE CHAR TIME
BR TYPE90
23$: CMPB #055,R0 ;IS CHAR A CARRIAGE RETURN ?
BEQ TYPE37
CMPB #075,R0 ;IS CHAR AN IDLE ?
BNE TYPE82 ;NORMAL PRINTING CHAR
BR TYPE90 ;JUST TYPE IT
;HERE WHEN TYPEING CR ON A 2741
TYPE37: BIS #BCDOCR,R3 ;SET SPECIAL FLAG
JSR PC,CRF274
TYPE39: MOV R3,DB.BCD(J)
BR TYPE90
CRF274: MOV R1,-(SP) ;COMPUTE CR FILLER
MOVB DB.COL(J),R1 ;SET FILL TIME=67.5<1.5+INCHES> MS
BIC #^C377,R1 ;FLUSH SIGN EXTENSION AS COL MAY BE > 127
ASR R1 ;USE 5<1.5+COL/10.> JIFFIES
ADD #10,R1 ; =COL/2+8 JIFFIES
CMP R1,#177 ;MAKE SURE RESULT IS POSITIVE BYTE TO GET JIFFIES
BLE 1$
MOV #177,R1
1$: MOVB R1,DB.FTM(J) ;SET CR FILLER
CLRB DB.COL(J) ;NOW BACK AT COLUMN 0
MOV (SP)+,R1
RTS PC
.ENDC
TYPE40: MOV R1,R0 ;COPY CHARACTER
BIT #TS.IMO,DB.DCS(J) ;IMAGE MODE OUTPUT ?
BNE TYPE90 ;IF SO NO EDITING
BIC #^C177,R1 ;STRIP PARITY BIT
MOVB PARTAB(R1),R0 ;PUT PARITY ON CHARACTER
BITB #CHRHMO,CHRTAB(R1) ;IS THIS A NORMAL ASCII CHARACTER ?
BNE TYPE82 ;IF SO JUST ADJUST COUNT
BITB #CHRFLL,CHRTAB(R1) ;DOES CHAR REQUIRE FILLERS ?
BEQ 61$
MOV R1,R2 ;COPY 7 BIT CHAR
ADD #DB.FIL-10,R2
ADD J,R2
MOVB @R2,DB.FTM(J) ;SET FILL TIMER FOR LATER USE
61$: CMPB #10,R1 ;IS CHAR A BACKSPACE ?
BEQ TYPE81 ;BACKUP COLUMN POINTER
CMPB #11,R1 ;IS CHAR HORIZONTAL TAB ?
BEQ TYPE90 ;IF SO DB.COL ALREADY COUNTED
CMPB #15,R1 ;IS THIS A CARRIAGE RETURN ?
BNE TYPE90
CLRB DB.COL(J) ;BACK IN COLUMN 0 !
BR TYPE90
;HERE WHEN TYPING A BACKSPACE
TYPE81: DECB DB.COL(J) ;BACK UP COLUMN COUNTER
BGE TYPE90 ;IF STILL POSITIVE TYPE IT
CLRB DB.COL(J) ;ELSE BACK TO COLUMN ZERO
BR TYPE90 ;THEN TYPE IT
;HERE FOR USUAL PRINTING CHARACTERS
TYPE82: INCB DB.COL(J) ;COUNT COLUMNS
TYPE83: CMPB DB.COL(J),DB.WID(J) ;WAS THIS ALREADY ON RH MARGIN ?
BLOS TYPE90 ;IF OK CONTINUE
BIT #TS.CRL,DB.DCS(J) ;EVER DO FREE CR/LF
BNE TYPE90 ;IF NOT DON'T DO ONE NOW
.IF NE FT2741
TST DB.BCD(J) ;IF WE ARE A 2741, R0 IS BCD NOW
BPL TYPE85
MOV R2,R0 ;R2 STILL HAS ASCII - USE IT
.ENDC
TYPE85: MOVB R0,DB.HLD(J) ;SAVE CHARACTER FOR LATER
MOV #CRLMSG,DB.STR(J) ;DO A CR/LF FIRST
JMP XMTINT ;AND START OVER
;HERE WHEN HAVE SET FILLERS ETC.
TYPE90:
.IF NE TTYN+RDAN+FT.CTY
.IF NE FT.CTY
CMP J,#CTYDDB ;IS THIS FOR THE CTY ?
BNE 33$
JMP CTYTYP ;IF SO DO IT
33$:
.ENDC
MOV DB.LCB(J),R1 ;POINT TO LCB
CMPB #LCS.RU,LC.STA(R1) ;LINE OK?
BGT 95$ ; NO, DONT PRINT IT
CMPB #LCS.RC,LC.STA(R1) ;LINE OK?
BLT 95$ ; NO, DONT PRINT IT
JINDEX JMP,DB.TYP(J),R2,DEVTYP
95$: MOVB #-1,DB.TIM(J) ;SIMULATE 600 BAUD
RTS PC ;IRMA WILL CATCH THIS LATER
.ENDC
.IIF EQ TTYN, BR CTYTYP
.SBTTL TABLES FOR AUTO BAUD UP TO 9600 BAUD (LOW BIT IS MASKED OFF)
HSPMSK=376 ;MASK FOR UNWANTED BITS (HIGH SPEED AUTOBAUD)
HSPCHR=377 ;CHAR TO SWITCH TO HIGH SPEED DETECT
LSPCHR=000 ;CHAR TO SWITCH TO LOW SPEED DETECT
LSPTAB: .BYTE 174 ;110 BAUD ^C
.BYTE 214 ;110 BAUD CR
.BYTE 234 ;110 BAUD CR
.BYTE 346 ;150 BAUD CR
.BYTE 036 ;150 BAUD ^C
.BYTE 215 ;300 BAUD CR
.BYTE 015 ;300 BAUD CR, ODD
.BYTE 003 ;300 BAUD ^C
.BYTE 203 ;300 BAUD ^C, ODD
.BYTE 372 ;600 BAUD CR, EVEN (CAN'T DETECT ^C AT 600)
.BYTE 362 ;600 BAUD CR, ODD
.BYTE 376 ;1200 BAUD ^C, EVEN
LSPEND: ;END OF TABLE
;TABLE OF LOW SPEED INDEX'S
LSP.IG=200 ;THROW AWAY NEXT CHAR AFTER AB CHAR (SIGN BIT)
LSP.SP=017 ;MASK FOR SPEED INDEX
LSPSPD: .BYTE 00 ;110 BAUD ^C
.BYTE LSP.IG!00 ;110 BAUD CR
.BYTE LSP.IG!00 ;110 BAUD CR
.BYTE LSP.IG!01 ;150 BAUD CR
.BYTE 01 ;150 BAUD ^C
.BYTE 02 ;300 BAUD CR
.BYTE 02 ;300 BAUD CR, ODD
.BYTE 02 ;300 BAUD ^C
.BYTE 02 ;300 BAUD ^C, ODD
.BYTE 03 ;600 BAUD CR
.BYTE 03 ;600 BAUD CR
.BYTE 04 ;1200 BAUD ^C, EVEN
.EVEN
;HIGH SPEED TABLE (NOTE THAT HSPMSK MASKS CHARACTERS BEFORE COMPARE)
HSPTAB: .BYTE 200 ;300 BAUD CR OR ^C, ODD OR EVEN
.BYTE 036 ;1200 BAUD ^C, ODD OR EVEN
.BYTE 346 ;1200 BAUD CR, ODD OR EVEN
.BYTE 006 ;1800 BAUD ^C, ODD OR EVEN
.BYTE 072 ;1800 BAUD CR, ODD OR EVEN
.BYTE 002 ;2400 BAUD ^C, EVEN
.BYTE 202 ;2400 BAUD ^C, ODD
.BYTE 214 ;2400 BAUD CR, EVEN
.BYTE 014 ;2400 BAUD CR, ODD
.BYTE 370 ;4800 BAUD ^C, ODD
.BYTE 360 ;4800 BAUD ^C, EVEN
.BYTE 374 ;4800 BAUD ^C, EVEN
.BYTE 362 ;4800 BAUD CR, ODD
.BYTE 372 ;4800 BAUD CR, EVEN
.BYTE 376 ;9600 BAUD ^C OR CR, ODD OR EVEN
HSPEND: ;END OF TABLE
;TABLE OF HIGH SPEED INDEX'S
HSPSPD: .BYTE LSP.IG!2 ;300 BAUD CR OR ^C
.BYTE 04 ;1200 BAUD ^C
.BYTE LSP.IG!04 ;1200 BAUD CR
.BYTE 05 ;1800 BAUD ^C
.BYTE 05 ;1800 BAUD CR
.BYTE 06 ;2400 BAUD ^C
.BYTE 06 ;2400 BAUD ^C
.BYTE 06 ;2400 BAUD CR
.BYTE 06 ;2400 BAUD CR
.BYTE 07 ;4800 BAUD ^C
.BYTE 07 ;4800 BAUD ^C
.BYTE 07 ;4800 BAUD ^C
.BYTE 07 ;4800 BAUD CR
.BYTE 07 ;4800 BAUD CR
.BYTE 10 ;9600 BAUD ^C, CR
.EVEN
;DH11 HARDWARE SPEEDS
SPDPAR: .WORD B.110 ;00
.WORD B.150 ;01
.WORD B.300 ;02
.WORD B.600 ;03
.WORD B.1200 ;04
.WORD B.1800 ;05
.WORD B.2400 ;06
.WORD B.4800 ;07
.WORD B.9600 ;10
.SBTTL TTY INPUT INTERRUPT SERVICE
.IF NE TTYN
ABCHAR: .WORD 0 ;STORE THE AUTOBAUD CHARACTER HERE
;HERE ON A DH11 OR DZ11 CHARACTER INTERUPT
TTDZIN:
TTDHIN:
MOV DB.LCB(J),R2 ;POINT TO LCB
BIT #LCB.IG,LC.CAR(R2) ;ARE WE IGNORING THIS LINE FOR 1 CHAR
BEQ 10$ ;NO
BIC #LCB.IG,LC.CAR(R2) ;YES, SKIP THIS CHAR AND GRAB NEXT
BR 99$
10$: CMPB #LCS.AB,LC.STA(R2) ;AUTO BAUD?
BEQ REC.AB ; YES
CMPB #LCS.RU,LC.STA(R2) ;LINE OK?
BGT LRTS ; IF IT ISN'T, PUNT THE CHAR
CMPB #LCS.RC,LC.STA(R2) ;LINE OK?
BLT LRTS ; IF IT ISN'T, PUNT THE CHAR
BIT #DHRFER,R1 ;CHECK FOR A FRAMMING ERROR
BEQ REC.00 ;BRANCH IF NORMAL CHARACTER
;HERE TO HANDLE A FRAMING ERROR - PROBABLY A BREAK
.IF NE FT2741
TST DB.BCD(J) ;CHECK TO SEE IF LINE IS 2741
BPL 20$ ;IF IT IS SPECIAL HANDLING
JMP RCVBRK ;KROQUE
20$:
.ENDC
BIT #LCB.BK,LC.CAR(R2) ;WAS LAST CHAR A BREAK?
BNE 30$ ;YES, WE HAVE GOTTEN TWO IN A ROW
BIS #LCB.BK,LC.CAR(R2) ;NO, FLAG THIS ONE
BR 99$ ;AND IGNORE IT
30$: BIT #LCB.AB,LC.CAR(R2) ;IF THIS ISN'T AN AUTO-BAUD
BEQ 99$ ;LINE, THEN DON'T RESET SPEED
MOVB #LCS.AB,LC.STA(R2) ;RESET STATE TO AUTO-BAUD
BIS #LCB.TM,LC.CAR(R2) ;GIVE HIM FOREVER TO RESPOND
BIC #LCB.LS,LC.CAR(R2) ;USE HIGH SPEED TABLE
MOV #B.HSPD,-(P) ;PUSH A SPEED OF 2400 BAUD,
JSR PC,SETSPD ;AND SET THE LINE TO IT.
TST (P)+ ;CLEAN UP THE STACK
99$: RTS PC ;AND GO HOME
REC.AB: MOVB R1,ABCHAR ;SAVE CHAR
BIT #LCB.LS,LC.CAR(R2) ;USING LOW SPEED TABLE?
BEQ 15$ ;NO, USE HIGH SPEED
CMPB #HSPCHR,R1 ;IS THIS A HIGH SPEED CHARACTER?
BEQ 60$ ;YES, SET HIGH SPEED AND TRY AGAIN
MOV #LSPTAB,R0 ;GET START OF TABLE
10$: CMP R0,#LSPEND ;AT END OF TABLE
BEQ 60$ ;BRANCH IF END OF TABLE
CMPB R1,(R0)+ ;DOES CHAR MATCH
BNE 10$ ;LOOP IF NOT
MOVB LSPSPD-LSPTAB-1(R0),R0 ;GET CHAR STATUS
BR 30$ ;GO TO COMMON CODE
15$: MOV #HSPTAB,R0 ;GET START OF TABLE
BICB #^C<HSPMSK>,R1 ;STRIP OFF UNWANTED BITS
CMPB #LSPCHR,R1 ;IS THIS A LOW SPEED CHARACTER?
BEQ 20$ ;YES, GO SEARCH LOW SPEEDS
20$: CMP R0,#HSPEND ;AT END OF TABLE
BEQ 50$ ;BRANCH IF END OF TABLE
CMPB R1,(R0)+ ;DOES CHAR MATCH
BNE 20$ ;LOOP IF NOT
MOVB HSPSPD-HSPTAB-1(R0),R0 ;GET CHAR STATUS
30$: BPL 40$ ;BRANCH IF NOT IGNORING NEXT CHAR
BIS #LCB.IG,LC.CAR(R2) ;IGNORE THE NEXT CHAR ON THIS LINE
40$: MOV R0,R2 ;MAKE COPY
BIC #^C<LSP.SP>,R2 ;GET INDEX BITS
ASL R2 ;MAKE IT A WORD
MOV SPDPAR(R2),-(P) ;GET THE DH11 SPEED BITS
JSR PC,SETSPD ;GO SET NEW SPEED
TST (P)+ ;NOW POP OFF USED SPEED BITS
MOV DB.LCB(J),R1 ;GET POINTER TO LCB
MOVB #LCS.RU,LC.STA(R1) ;GO TO RUNNING STATE
BIC #LCB.TM,LC.CAR(R1) ;STOP ANY TIMERS
BIS #DS.XDS,@J ;ALSO TELL THE -10
MOVB #1,DB.TIM(J) ;KICK THE IRMA TIMER
MOV #215,R1 ;A CR
JMP TTYINP ;LOOKS LIKE THE USER TYPED IT
50$: BIS #LCB.IG,LC.CAR(R2) ;IGNORE THE NEXT CHARACTER
MOV #B.LSPD,-(P) ;PUSH A SPEED OF 300 BAUD
BIS #LCB.LS,LC.CAR(R2) ;USE LOW SPEED TABLE
BR 70$ ;GO TO COMMON CODE
60$: MOV #B.HSPD,-(P) ;PUSH A SPEED OF 2400 BAUD,
BIC #LCB.LS,LC.CAR(R2) ;USE HIGH SPEED TABLE
70$: JSR PC,SETSPD ;AND SET THE DETECTION SPEED
TST (P)+ ;CLEAN UP THE STACK
LRTS: RTS PC ;DON'T DO ANYTHING WITH THE CHAR
REC.00:
BIC #LCB.BK,LC.CAR(R2) ;CLEAR BREAK CHAR FLAG
.IF NE FT2741
MOV DB.BCD(J),R3 ;GET 2741 STATUS BITS
BPL REC.60 ;BRANCH IF NOT 2741
BIT #BCDRCR,R3 ;TEST FOR LAST CHAR WAS A CR
BNE RCVEOT ;IF SO TREAT THIS CHAR AS AN EOT
BIC #^C77,R1 ;CLEAR PARITY BIT
CMP #<BCDEOT&77>,R1
BEQ RCVEOT
BIT #BCDKBL,R3 ;IS THE KEYBOARD LOCKED ?
BNE RCVEOA ;IS SO THIS MUST BE AN EOA
CMP #<BCDUCS&77>,R1 ;IS THIS UP SHIFT ?
BEQ BCDRUS ;BRANCH IF WE RECEIVED AN UPSHIFT
CMP #<BCDLCS&77>,R1 ;IS THIS A DOWN SHIFT ?
BEQ BCDRDS ;BRANCH IF WE RECEIVED A DOWN SHIFT
MOV R3,R2 ;MAKE ANOTHER COPY OF DB.BCD
BIC #^C<BCDCOD+BCDUPS>,R2 ;LEAVE ONLY FIELD FOR CODE & SHIFT
ADD R2,R1 ;COMBINE CODSET WITH CHARACTER
MOVB BCDXIN(R1),R1 ;TRANSLATE CHARACTER
BEQ 99$ ;IF NULL THROW CHAR AWAY
BIC #BCDRCR,R3 ;CLEAR CARRIAGE RETURN BIT
CMP #15,R1 ;KEEP TRACK OF CARRIAGE POSITION
BNE 20$
BIS #BCDRCR!BCDKBL,R3
BR 34$
20$: CMP #40,R1 ;CHECK ALL SPACING CHARS
BGT 21$ ;BR IF CONTROL CHAR (MAYBE)
CMP #174,R1
BGE 30$ ;SPACING CHARS = SPACE (40) TO VERT. BAR (174)
21$: CMP #11,R1 ;CHECK TAB
BEQ 29$ ;BR IF SO
CMP #10,R1 ;CKECK BACKSPACE
BNE 34$ ;IF NOT THEN CARRIAGE NOT AFFECTED
DECB DB.COL(J) ;BACKSPACE
BR 34$
29$: BISB #7,DB.COL(J) ;TAB TO NEXT MULTTIPLE OF 8
30$: INCB DB.COL(J) ;ADVANCE CARRIAGE POSITION
34$: BIT #BCDAPL,R3 ;TEST FOR APL MODE
BNE REC.50 ;BRANCH IF NO TRANSLATION
BIT #BCDCON,R3 ;IS THIS THE CHARACTER FOLLOWING AN ARROR ?
BEQ 40$
BIC #BCDCON,R3 ;CLEAR FOLLOWING AN ARROW BIT
CMP R1,#10 ;WAS CHAR A BACKSPACE ?
BEQ BCD.99 ;IF IT WAS JUST STORE STATUS
CMP R1,#40 ;TEST TO SEE IF CHAR MUST BE TRANSLATED
BMI REC.50 ;BRANCH IF NO TRANSLATION
MOVB ARRTAB-40(R1),R1 ;TRANSLATE AGAIN
37$:
BR REC.50
40$: CMP R1,#ARROW ;TEST FOR THIS CHAR IS AN ARROW
BNE REC.50
BIS #BCDCON,DB.BCD(J) ;SET ARROW MODE
99$: RTS PC ;AND DONE
REC.50: MOV R3,DB.BCD(J) ;RESTORE 2741 STATUS
REC.60:
.ENDC
JMP TTYINP ;PASS INPUT TO QUEUE
.IF NE FT2741
;HERE FROM REC.00 WHEN RECEIVE AN EOA
RCVEOA: BIT #BCDPRL,R3 ;IS THE PRINTER ALREADY LOCKED ?
BEQ BCD.98 ;IF NOT THIS MUST BE JUNK
CMP #BCDEOA,R1 ;IS CHARACTER AN EOA ?
BNE BCD.98 ;IF NOT IGNORE
BIC #BCDKBL!BCDUPS,R3 ;KEYBOARD UNLOCKED & LOWER SHIFT
BR BCD.99 ;RESTORE STATUS THEN DISMISS
;HERE WHEN RECEIVE AN EOT FROM A 2741 LINE
RCVEOT: ;BIT #TS.TIW,DB.DCS(J) ;WAITING FOR INPUT ?
;BEQ 10$
BIC #TS.TIW,DB.DCS(J) ;NO LONGER WAITING
BIS #DS.XDS,@J ;NEED TO SEND STATUS TO CONTROLLER
10$: BIS #BCDKBL!BCDPRL,R3 ;SET ALL LOCKED
BIT #BCDXRB,R3 ;TEST FOR WE WERE SENDING REVERSE BREAK
BNE BCD.99 ;IF WE ARE IGNORE THIS EOT
MOV #<2*400+^D10>,DB.TIM(J) ;GIVE IT A TENTH OF A SECOND TO SETTLE
BIT #BCDRCR,R3 ;CHECK FOR CR CASE
BEQ 20$
JSR PC,CRF274 ;YES, CALC. PROPER FILLER
CLRB DB.FTM+1(J) ;MAKE SURE DB.FTM FCN IS FILLER!
20$: BIC #BCDCON!BCDUPS!BCDRCR,R3 ;CLEAR UPPERSHIFT & PRINTER LOCKED
BIS #DS.ACT,@J ;WE WILL SEND A CHARACTER LATER
BIT #BCDRCR,DB.BCD(J) ;TEST AGAINST CORE COPY CUZ CLEARED R3
BNE BCD.99 ;IF FOLLOWED CR WE ARE DONE
BIT #BCDAPL,R3 ;IS LINE IN APL-MODE ?
BEQ BCD.99 ;IF NOT WE ARE DONE
MOV #BELL,R1 ;MAKE A BELL
BR REC.50 ;GIVE THAT GUY A BELL
BCDRDS: BIC #BCDUPS,R3
BR BCD.99
BCDRUS: BIS #BCDUPS,R3 ;SET UPPER SHIFT
BCD.99: MOV R3,DB.BCD(J) ;RESTORE STATUS TO 2741 TABLE
BCD.98: RTS PC
.ENDC
.ENDC
;CTY INPUT INTERRUPT
.IF NE FT.CTY
CTIINT: SAVE <J>
MOV #CTYDDB,J ;GET DEVICE BLOCK FOR CTY
SAVE <R0,R1>
TSTB CTISTS ;CHECK IT WAS DATA INTERRUPT
BGE CTIIN9 ;TRASH INTERRUPT
SPL 7 ;LOCK OUT EVERYTHING ELSE
MOV CTICHR,R1 ;GET KEYBOARD DATA & CLEAR FLAG
.IF NE FT.DDT
CMP #204,R1 ;DID I TYPE A CTRL/D?
BNE CD1 ;NOPE, IGNORE
CD: BR CTIIN9 ;PUT BREAKPOINT HERE
CD1:
.ENDC
JSR PC,TTYINP ;HAVE TTY INPUT
CTIIN9: RESTORE <R1,R0>
RESTORE <J>
RTI ;DISMISS INTERRUPT
;CTY OUTPUT INTERRUPT
CTOINT: SAVE <R0,R1,R2,R3,J>
MOV #CTYDDB,J ;LOAD DEVICE BLOCK ADDRESS
CLR CTOSTS ;DISABLE INTERRUPTS
JSR PC,XMTINT ;GO SEE WHAT WE CAN DO NEXT
RESTORE <J,R3,R2,R1,R0>
RTI
CTYTYP: MOVB R0,CTOCHR ;TYPE NEXT CHAR
MOVB #100,CTOSTS ;ENABLE INTERUPTS
RTS PC
.ENDC
;HERE TO QUEUE A CHAR TO TYPED
; CALL: LOAD J WITH TTY DEVICE BLOCK ADDRESS
; MOV <CHR>,R0
; JSR PC,QTYCHR
QTYCHR: MOV R0,R3 ;COPY BYTE
PIOFF
JSR PC,QTYCH ;QUEUE THE CHARACTER
PION
RTS PC
;SUBROUTINE TO QUEUE ESCAPE CHARACTER + FUNCTION CODE
; CALL MOV <FNC>,R0 ;PUT FUNCTION IN R0
; JSR PC,QTECHR ;ASSUMES J CONTAINS DDB ADDRESS
QTECHR: PIOFF
MOV R0,-(P) ;SAVE FUNCTION CODE
MOV #ESCF,R3 ;GET ESCAPE CHARACTER
JSR PC,QTYCH ;QUEUE IT
MOV (P)+,R3 ;RETRIEVE FUNCTION
JSR PC,QTYCH ;QUEUE IT ALSO
PION
RTS PC
QTYCH: MOV DB.TOB+2(J),R0 ;GET POINTER TO LAST DATA CHAR
BNE 14$
JSR PC,ERSGET ;TAKE FROM EMERGENCY STORE
TST (R0)+ ;SKIP LINK WORD
MOV R0,DB.TOB+2(J) ;SET LIMIT WORD
MOV R0,DB.TOB(J) ;SET 1ST BYTE POINTER
14$: ADVCNK R0 EXTEND ;ADVANCE TO NEXT CHARACTER
; ;ALLOCATING A NEW CHUNK IF REQUIRED
16$: MOVB R3,(R0)+ ;PUT BYTE INTO CHUNK
MOV R0,DB.TOB+2(J) ;RESET LIMIT BYTE POINTER
INC DB.TOC(J) ;COUNT CHAR INTO THE CHUNKS
RTS PC
;HERE TO PASS TTY INPUT CHAR TO TASK OF NCL
; CALL WITH J POINTING TO LINE BLOCK
; AND INPUT CHAR IN R1
TTYINP:
.IF NE FT.TSK
MOV DB.TSK+2(J),R0 ;GET TASK BLOCK THAT WANTS INPUT
BEQ TYPIN0
SAVE <J>
MOV R0,J
JSR PC,TSKWAK ;WAKE THE TASK
RESTORE <J>
MOV DB.KPT(J),R0 ;GET KEYBOARD PUTTER
ADD J,R0 ;MAKE ADR ABSOLUTE
MOV R1,(R0)+ ;PUT CHAR INTO BUFFER
SUB J,R0 ;MAKE ADR RELATIVE AGAIN
CMP R0,#DB.KQU+TQS+TQS ;DID WE HIT END OF QUEUE ?
BNE 20$
MOV #DB.KQU,R0 ;YES SO POINT TO START
20$: CMP R0,DB.KTK(J) ;WOULD THIS OVERTAKE TAKER ?
BEQ 90$ ;IF SO DON'T DO IT
MOV R0,DB.KPT(J) ;NO SO FREEZE IT
90$: RTS PC
.ENDC
TYPIN0: CMP #TTYMIC,DB.ICC(J) ;HOW MANY CHARS ALREADY WAITING ?
BPL 5$ ;STILL OK
JMP TYPIBF ;TELL USER THAT INPUT BUFFER IS FULL
5$: MOV R1,R0 ;COPY THE CHARACTER,
BIC #^C177,R0 ; AND CLEAR PARITY IN THE COPY
BNE 10$ ;IF NOT A NULL, GO CHECK ^S
BIT #TS.IMI,DB.DCS(J) ;IF WE ARE IN IMAGE MODE
BNE 10$ ; THEN KEEP THE NULL
RTS PC ;IF NOT IMAGE MODE, IGNORE NULLS
10$: BIT #TS.PAG,DB.DCS(J) ;ARE WE IN PAGE MODE?
BEQ 20$ ;NO, DON'T CHECK XON/XOFF
CMPB #23,R0 ;WAS THE CHAR ^S (XOFF)?
BNE 12$ ;NO, CHECK ^Q
BIS #TS.FRZ,DB.DCS(J) ;YES, STOP OUTPUT
BR 20$ ;QUEUE THE XOFF
12$: CMPB #21,R0 ;WAS THE CHAR A ^Q (XON)?
BNE 20$ ;NO, NORMAL CHAR
BIC #TS.FRZ,DB.DCS(J) ;YES, START OUTPUT
20$: QUEPUT TI ;PUT THE CHAR IN THE INPUT QUEUE
;
; Stop input from a terminal at interupt level, thereby
; avoiding any problems with loop level begin unable
; to keep up with TTY input.
;
.IF NE FT.RDA
TST DB.RDT(J) ;Is this an RDA device?
BNE 35$ ;Yes, skip this
.ENDC
BIT #DS.IST,(J) ;Have we already sent XOFF
BNE 35$ ;Yes, don't bother with another
INC DB.ICC(J) ;Count this character
CMP #TTYMIC-^D20,DB.ICC(J) ;Are we in danger of overrunning?
BHI 35$ ;No, all is well
JSR PC,SNDXOF ;Yes, ship an XOFF now
BIS #DS.IST,(J) ;Signal that we sent an XOFF
35$: RTS PC ;Let let loop worry about the char.
PARTAB: .BYTE 000,201,202,003,204,005,006,207
.BYTE 210,011,012,213,014,215,216,017
.BYTE 220,021,022,223,024,225,226,027
.BYTE 030,231,232,033,234,035,036,237
.BYTE 240,041,042,243,044,245,246,047
.BYTE 050,251,252,053,254,055,056,257
.BYTE 060,261,262,063,264,065,066,267
.BYTE 270,071,072,273,074,275,276,077
.BYTE 300,101,102,303,104,305,306,107
.BYTE 110,311,312,113,314,115,116,317
.BYTE 120,321,322,123,324,125,126,327
.BYTE 330,131,132,333,134,335,336,137
.BYTE 140,341,342,143,344,145,146,347
.BYTE 350,151,152,353,154,355,356,157
.BYTE 360,161,162,363,164,365,366,167
.BYTE 170,371,372,173,374,175,176,377
; HERE TO SET LINE SPEED
.IF NE TTYN
; CALL: JSR PC,SETSPD ; WITH J SETUP
; RETURN ; USES R0 & R1
SETSPD:
SAVE <R2,R3>
.IF NE FT.CTY
CMP J,#CTYDDB ; IS THIS FOR THE CTY ?
BEQ 99$ ; CAUSE CTY NOT DH11
.ENDC
BIS #DS.XCH,@J ; SO WE SEND CHARACTERISTICS TO 10
MOV @DB.DHB(J),R0 ; GET DH11 HDW ADDRESS
MOV 6(P),R1 ; GET NEW LINE SPEED
.IIF NE FT2741,PIOFF
MOVB DB..LN(J),R2 ; FETCH THE DH11 LINE #
JINDEX JSR,DB.TYP(J),R3,DEVSPD
BCS 98$ ; CARRY SET IS ERROR
MOV DB.LCB(J),R2 ; SUCCESS, GET ADDRESS OF LCB
MOV R1,LC.SPD(R2) ; AND PUT NEW ACTUAL SPEED IN LCB
98$:
.IF NE FT2741
BIC #BCDB27,DB.BCD(J) ; CLEAR 2741 BITS
CMP #B.134,LC.SPD(R2) ; IS IT A 2741
BNE 20$ ; IF NOT, NOTHING SPECIAL
BIS #BCD274!BCDVRG,DB.BCD(J); VIRGIN 2741
BR 21$ ; AND EXIT
20$: CLR DB.BCD(J) ; NO LONGER 2741
21$: PION
.ENDC
99$: RESTORE <R3,R2>
RTS PC
.IFF
SETSPD: RTS PC
.ENDC
.ENDC