home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
archives
/
decpro300.zip
/
procon.mac
< prev
next >
Wrap
Text File
|
1988-08-16
|
40KB
|
1,468 lines
.TITLE KERCON - KERMIT connect module
.SBTTL S Hecht/D Stevens/R McQueen
;++
; This module contains the terminal emulation code for Pro/Kermit.
;--
; Version number
.IDENT /1.0.05/
; Directives
.ENABLE LC ; Enable lower case in ASCIx
.NLIST BEX
.LIBRARY /KERMLB/ ; Kermit macro library file
.SBTTL Revision History
;++
; Version 1.0.00
;
; 1.0.00 By: Authors On: Many days
; Create this module
;
; 1.0.01 By: Robert C McQueen On: 28-Feb-1984
; Rewrite lost of the console terminal processing so that
; Ctl-O, Ctl-C, etc get to the -10 a lot faster.
;
; 1.0.02 By: Robert C. McQueen On: 27-March-1984
; Try once again to fix the ^C problem.
;
; 1.0.03 By: Robert C. McQueen On: 6-April-1984
; Send RIS character sequence to the terminal after we exit
; the connect processing.
;
; 1.0.04 By: Robert C. McQueen On: 16-April-1984
; Make this a seperate task. Solves some of the problem
; of needing a DTE equiv for Tool kit and also get lots of
; address space for logging.
;
; 1.0.05 By: Robert C. McQueen On: 11-May-1984
; Fix local echo for the F11 to F13 keys (ESC, BS, LF).
;--
.SBTTL External symbols
; Get the KERMLB definitions
.MCALL KERDEF
KERDEF ; Get the general symbol definitions
.MCALL CHRDEF ; Get the character definition macro
CHRDEF ; Define the special characters
.MCALL IOSBDF ; IOSB definitions
IOSBDF ; Define the offsets
.MCALL BLSRTN ; Allow use of BLISS macros from
.MCALL BLSCAL ; library
.MCALL TABLE ; Macro to generate tables
.MCALL MSG ; Macro to define text literals.
.MCALL PJMP ; Jump and return from routine
.MCALL ND ; If not defined, define symbol macro
;
; System routines used in Kercon
;
.MCALL QIO$S ; QIO on the stack
.MCALL QIOW$S ; QIOW using the stack
.MCALL QIOW$C ; QIOW
.MCALL ASTX$S ; Exit from an AST routine
.MCALL CLEF$S ; Clear event flag
.MCALL MRKT$S ; Mark time
.MCALL SETF$S ; Set event flag
.MCALL WTSE$S ; Wait for single EFN using stack
.MCALL ALUN$C ; Assign a LUN
.MCALL EXIT$S ; Exit from the routines
.SBTTL Macro definitions -- Escape commands
;++
; This macro contains the valid commands that can follow an escape character
;--
.MACRO ESCCMD
$TABA 'C,C$EXIT ;; Close communications port
$TABA 'B,C$BREAK ;; Send a break
$TABA 'S,C$STAT ;; Issue the status
$TABA '?,C$HELP ;; Issue the help text
.ENDM
;
; Now expand the table.
;
TABLE ESC,ESCCMD
.SBTTL Macro definitions -- Function keys allowed
;++
; The following macro will generate the possible function keys that we
; can handle.
;--
.MACRO FNCKEY
KY '13~',C$BREAK, ; F3 - Break key
KY '20~',C$EXIT, ; F9 - Main Screen
KY '21~',C$EXIT, ; F10 - Exit key
KY '23~',C$CHAR,.CHESC ; F11 - Generate an escape character
KY '24~',C$CHAR,.CHCNH ; F12 - Generate a backspace character
KY '25~',C$CHAR,.CHLFD ; F13 - Generate a line feed character
KY '28~',C$HELP, ; F15 - Call help routine
.ENDM
;
; Now generate the tables
;
.MACRO KY TEXT,ROUTIN,ADDTNL,?TXTADR
;;
;; Save the current state of the psects
;;
.SAVE ;; Save the current PSECT
.ENABL LSB ;; Start local symbol block
;;
;; First generate the text
;;
.PSECT $TEXT$, RO, D ;; $TEXT$ psect
;;
TXTADR: .ASCIZ TEXT
.EVEN
;;
;; Now store the address in the table
;;
.RESTORE ;; Restore the PSECT
;;
;; Generate the address of the item
;;
.WORD TXTADR
.DSABL LSB ;; End of local symbol block
;;
.ENDM
;
; Now generate the table of text
;
.PSECT $TABL$, RO, D
T$KEY: FNCKEY ; Generate the function keys
KEY$L=.-T$KEY ; Length of the table
;
; Now generate the routines that get called.
;
.MACRO KY TEXT,ROUTINE,ADDTNL,?TXTADR
.WORD ROUTINE
.ENDM
FNCKEY ; Generate the routine addresses
;
; Now generate the addition information
;
.MACRO KY TEXT,ROUTINE,ADDTNL,?TXTADR
.IF NB <ADDTNL>
.WORD ADDTNL
.IFF
.WORD 0
.ENDC
.ENDM
FNCKEY
.SBTTL Symbol definitions
;++
; The following are local symbol definitiosn for the KERCON module.
;--
; \/ \/ MUST BE A POWER OF 2.
ND NM.TIC, 64. ; Allow 64 characters input buffer
ND NM.QIO, 4. ; Up to four output QIO's pending at once
; /\ /\ MUST BE A POWER OF 2.
.SBTTL State definitions for Console Terminal Input
;++
; The following define the various states of the Console Terminal Input
; routines. These input routines are all at AST level and the states
; describe what happens there.
;--
$CSINI= 0 ; Initial state
$CSESC= 1*2 ; Saw an <Escape>
$CSCSI= 2*2 ; Saw a CSI
$CSSQB= 3*2 ; Saw a [
$CSDG1= 4*2 ; Saw first digit
$CSDG2= 5*2 ; Saw second digit
$CSCEC= 6*2 ; Saw connect escape character (ESCCHR)
.SBTTL General storage locations
.PSECT $OWN$, RW, D
INPCHR: .BLKW 1 ; Place to read characters into
CONXIT: .BLKW 1 ; Exit connect processing
FNCPTR: .BLKW 1 ; Pointer into FNCTXT
FNCTXT: .BLKW 3 ; Function key text
NOBIT8: .BLKW 1 ; No bit 8
;
; Terminal input data
;
TILOCK: .BLKW 1 ; Interlock for the terminal data base
TTIBUF: .BLKB NM.TIC ; Number of terminal characters allowed
TTINCH: .BLKW 1 ; Number of characters in TRMBUF
TTIIDX: .BLKW 1 ; Index into TTIBUF
TTISTO: .BLKW 1 ; Index to store characters into TTIBUF
TIIOSB: .BLKB IB.MSZ ; IOSB for QIO
TIQIO: .BLKW 1 ; QIO pending for the console input
STATE: .BLKW 1 ; State of the AST routine
TBC: .BLKB 2 ; Type ahead buffer count
QIOIDX: .BLKB 1 ; Current output QIO number
.EVEN
;
; Terminal output data
;
TOIOSB: .BLKB IB.MSZ ; IOSB for non-AST level outputs
TOIOS0: .BLKB <IB.SIZ*NM.QIO> ; IOSB's for QIO
TOLOCK: .BLKW 1 ; Interlock for console type out
OUTCHR: .BLKW 1 ; Character to be output
.SBTTL CONNECT processing
;++
; The following is the main processing for the terminal emulation.
;--
.PSECT $CODE$, RO, I
MAIN: ALUN$C XKLUN,XK,0,$CODE$ ; Assign XK LUN
ALUN$C TERLUN,TI,0,$CODE$ ; Assign the terminal LUN
JSR PC,INILIB ; Initialize the library routines
JSR PC,CRECON ; Make the connect character ascii
BLSCAL TT.INIT ; Initialize terminal processing
JSR PC,CONECT ; Do the connect processing
JSR PC,S$CLEAR ; Clear the screen
EXIT$S ; Exit the task
.SBTTL Main connect routine (entry point)
;++
; This routine will handle the processing of the CONNECT command. It is
; called directly from the command dispatch processing.
;
; Usage:
; JSR PC,CONNECT
; (Return)
;
;--
.PSECT $CODE$, RO, I
CONECT::
;
; First initialize some local parameters, so we don't have to do this
; every time
;
MOV #FALSE,NOBIT8 ; Assume we are not removing bit 8
CMP #PR.MARK,PARITY ; Using mark parity?
BEQ 5$ ; Yes, must remove the bit
BIT #TRUE,TRM7BT ; Only passing 7 bit codes?
BNE 10$ ; Don't have to remove the bit
5$: MOV #TRUE,NOBIT8 ; Flag we must remove bit 8
;
; Initialize the two different ports
;
10$: CLR CONXIT ; Clear the exit flag
JSR PC,CT.INI ; Initialize the CT port
BCS 90$ ; Failed, print an error message
CLR R0 ; Use the default
13$: MOV #DUMPXK,R1 ; Routine to do direct XK dumps
JSR PC,XK.INI ; Open the XK port
BCS 100$ ; Could not get XK
;
; At this point we have the two ports attached, so we just clear the
; screen and output the banner for terminal emulation.
;
JSR PC,S$CLEAR ; Clear screen
JSR PC,C$BANR ; Output the connect banner
;
; The following is commented out since most systems will screw up when getting
; the leading CSI's from the function keys. Everything at this point
; expects <ESC>[ rather than <CSI>.
;
; Set up terminal subsystem so that we get correct type of codes from
; the keys.
;
MOV #RTN7BT,R0 ; Assume we want 7 bit codes
; CMP #PR.NONE,PARITY.TYPE ; No parity?
; BNE 15$ ; If not, we can't pass 8 bit codes anyway
; BIT #TRUE,TRM7BT ; 7-bit desired?
; BNE 15$ ; Yes, do that
; MOV #RTN8BT,R0 ; No, use 8-bit data
15$: BLSCAL TT.TEXT,R0 ; Send the string
BLSCAL TT.OUTPUT ; And force it out
JSR PC,CT.QIO ; Post the initial QIO for the terminal
; CMP DUPLEX,#DP.HAL ; Check for half duplex
; BNE 20$ ; If not skip
;
; MOV IBM.CHAR,R0 ; If half then send turn around char.
; JSR PC,CT.PAR ; Generate the parity
; JSR PC,XK.OUT ; Write the character with parity
;
;
; Here to start the terminal emulation
;
20$: JSR PC,DUMPXK ; Dump XK input to console screen
JSR PC,DUMPCT ; Dump the console input to the XK
JSR PC,XK.QIO ; Make sure a QIO is posted for the XK
JSR PC,CT.QIO ; Make sure there is a QIO posted
TST CONXIT ; Must we exit?
BNE 40$ ; Yes, just exit
;
; Here to wait for the EFNs to be set by somebody
;
WTSE$S #CONEFN ; Wait until we have input
CLEF$S #CONEFN ; Clear so we know when none.
MRKT$S #CONEFN,#1.,#2. ; Make sure we run at least once a second
BR 20$ ; Loop for more input
;
; Here to exit from the connect processing
;
40$: JSR PC,XK.SHT ; Shut down the XK
JSR PC,CT.SHT ; Shut this down too
BLSCAL TT.TEXT,#M$RIS ; Send the reset string
BLSCAL TT.OUTPUT ; Force it out
RTS PC ; Return to the caller
;
; Here if we can not get the console terminal
;
90$: BLSCAL BL$MOV,<#CTBS$L,#M$CTBS,#MSG1> ; Console is busy
JSR PC,S$CLEAR ; Clear the screen
BLSCAL TT.TEXT,#M$CTBS,+ ; Port is busy
BLSCAL TT.TEXT,#RESTXT,+ ; Say he should type resume
BLSCAL TT.OUTPUT,,- ; Force the output
CALL WTRES ; Wait for resume key
RTS PC ; And return
;
; Here if we can not get the XK port
;
100$: JSR PC,CT.SHT ; Release the console terminal
BLSCAL BL$MOV,<#XKBS$L,#M$XKBS,#MSG1> ; XK is busy
JSR PC,S$CLEAR ; Clear the screen
BLSCAL TT.TEXT,#M$XKBS,+ ; Port is busy
BLSCAL TT.TEXT,#RESTXT,+ ; Say he should type resume
BLSCAL TT.OUTPUT,,- ; Force the output
CALL WTRES ; Wait for resume key
RTS PC ; And return
; Text for various items above
.PSECT $PLIT$, RO, D ; This is data
M$RIS: .ASCIZ <.CHESC>/c/ ; Reset to initial state
MSG XKBS,<Communications port in use by another task - try again when free>
MSG CTBS,<Console terminal in use by another task>
RESTXT: .ASCIZ <.CHCRT><.CHLFD>/Press RESUME to continue/<.CHCRT><.CHLFD>
;RTN8BT: .ASCIZ <.CHESC>/ G/ ; Want 8-bit codes from function keys
RTN7BT: .ASCIZ <.CHESC>/ F/ ; Want 7-bit codes from function keys
.EVEN ; Make sure we are on a word boundary
.SBTTL C$BANR - Connect banner type out
;++
; This routine will type the banner for the connect. This is displayed when
; terminal emulation is entered.
;--
.PSECT $PLIT$, RO, D
CONMG1: .ASCII <.CHCR><.CHLF><.CHLF>\PRO/Kermit - \
.ASCII \Terminal Emulation version 1.0\
.ASCII <.CHCR><.CHLF><.CHLF><.CHLF>
.ASCII \Now entering Terminal Emulation mode\<.CHCR><.CHLF><.CHLF>
.ASCIZ \Type \
CONMG2: .ASCIZ \C \
CONMG3: .ASCIZ \or press MAIN SCREEN or EXIT \
CONMG4: .ASCII \to return to PRO/Kermit, \
.ASCIZ <.CHCR><.CHLF>/Type /
CONMG5: .ASCIZ \? \
CONMG6: .ASCIZ \or press HELP \
CONMG7: .ASCIZ \for help.\<.CHCR><.CHLF>
.EVEN
.PSECT $CODE$, RO, I
C$BANR: BLSCAL TT.TEXT,#CONMG1,+ ; Output the first part
BLSCAL TT.TEXT,#CONCHR,+ ; And the connect character
BLSCAL TT.TEXT,#CONMG2,+ ; Second part
BIT #TRUE,TRMTRN ; Terminal in transparent mode?
BNE 10$ ; Yes, don't output the following
BLSCAL TT.TEXT,#CONMG3,+ ; Output some more
10$: BLSCAL TT.TEXT,#CONMG4,+ ; Output the rest of the line
BLSCAL TT.TEXT,#CONCHR,+ ; And the connect character
BLSCAL TT.TEXT,#CONMG5,+ ; And the last part
BIT #TRUE,TRMTRN ; Transparent mode?
BNE 20$ ; Yes, skip this about HELP key
BLSCAL TT.TEXT,#CONMG6,+ ; Output about HELP
20$: BLSCAL TT.TEXT,#CONMG7,+ ; Finish message off
BLSCAL TT.OUTPUT,,- ; Output the rest of the characters
RTS PC ; Return to the caller
.SBTTL C$CHAR - Send a special character to the remote
;++
; This routine will send a special character to the remote.
;
; Usage:
; R1/ Information from table
; JSR PC,C$CHAR
; (Return)
;--
.PSECT $CODE$, RO, I
C$CHAR: PJMP XKOUT ; Send it
.SBTTL C$EXIT - Exit from terminal emulation
;++
; This routine will be called to exit from the terminal emulation. It
; will cause the flag to be set so that the loop level notices that we
; have to exit.
;
; Usage:
; JSR PC,C$EXIT
; (Return)
;
;--
.PSECT $CODE$, RO, I
C$EXIT: MOV #1,CONXIT ; Set the flag
RTS PC ; Return to the caller
.SBTTL C$BREAK - Send a break to the remote
;++
; This routine will send a break character to the remote connection.
;
; Usage:
; JSR PC,C$BREAK
; (Return)
;
;--
.PSECT $CODE$, RO, I
C$BREAK:
JSR PC,XK.BRK ; Send the break
RTS PC ; Return to the caller
.SBTTL C$STAT - Output the connection status
;++
; This routine will output the connection status. This routine is called
; after the escape character has been typed followed by an 'S'.
;--
.PSECT $PLIT$, RO, D
STAMG1: .ASCIZ <.CHCRT><.CHLFD><.CHLFD>/[The baud rate is /
STAMG2: .ASCIZ \ (T)/\
STAMG3: .ASCIZ / (R) bits per second.]/<.CHCRT><.CHLFD>/[Local echo /
STAMG4: .ASCIZ /]/<.CHCRT><.CHLFD><.CHLFD>
MSG ON,<on>
MSG OFF,<off>
.MACRO SPD
$TAB S.50,<50>
$TAB S.75,<75>
$TAB S.100,<100>
$TAB S.110,<110>
$TAB S.134,<134>
$TAB S.150,<150>
$TAB S.200,<200>
$TAB S.300,<300>
$TAB S.600,<600>
$TAB S.1200,<1200>
$TAB S.1800,<1800>
$TAB S.2000,<2000>
$TAB S.2400,<2400>
$TAB S.3600,<3600>
$TAB S.4800,<4800>
$TAB S.7200,<7200>
$TAB S.9600,<9600>
$TAB S.19.2,<19200>
; $TAB S.38.4,<38400>
.ENDM
; Now define the item in the table
TABLE SPD,SPD ; Define the speed table
.PSECT $CODE$, RO, I
C$STAT: BLSCAL TT.TEXT,#STAMG1,+ ; Output the message.
MOV #TC.XSP,R0 ; Get the transmit speed parameter
MOV #CURXKP,R1 ; Use the current parameters
JSR PC,FNDXKP ; Find the parameter in the block
JSR PC,C$SBAU ; Output the baud rate
BLSCAL TT.TEXT,#STAMG2,+ ; Output the message.
MOV #TC.RSP,R0 ; Get the receive speed parameter
MOV #CURXKP,R1 ; Use the current parameters
JSR PC,FNDXKP ; Find the parameter in the block
JSR PC,C$SBAU ; Output the baud rate
BLSCAL TT.TEXT,#STAMG3,+ ; Output the message.
MOV #M$ON,R2 ; Assume local echo
BIT #TRUE,LCLECH ; Local echo?
BNE 10$ ; If non-zero we are using local echo
MOV #M$OFF,R2 ; If zero, we aren't
10$: BLSCAL TT.TEXT,R2,+ ; Output the message.
BLSCAL TT.TEXT,#STAMG4,+ ; Output the message.
BLSCAL TT.OUTPUT,,- ; Output the rest of the mess
RTS PC ; Return to the caller
;
; Subroutine to output the baud rate given the index.
;
C$SBAU: MOVB (R0),R2 ; Get the index
MOV #T$SPD,R0 ; Get the table
MOV #SPD$L/2,R1 ; Get the length
JSR PC,FNDOFS ; Find the offset
TST R0 ; Is this zero?
BEQ 99$ ; Yes, just return
ADD #SPD$L,R0 ; Point to the entry
MOV (R0),R2 ; Get the item
MOVB (R2)+,R3 ; Get the length
TST -(SP) ; Allocate one word
10$: MOVB (R2)+,(SP) ; Get the character
JSR PC,TT.CHAR ; Output the character
SOB R3,10$ ; Loop for all character
TST (SP)+ ; Clear up the stack
99$: RTS PC ; Return to the caller
.SBTTL C$HELP - Help command for the connect processing
;++
; This routine will issue the help message to the user's terminal. It will
; then return to the calling routine.
;
; Usage:
; JSR PC,C$HELP
; (Return)
;
;--
.PSECT $PLIT$, RO, D
CNHLP1: .ASCII <.CHCRT><.CHLFD>/CONNECT escape commands:/<.CHCRT><.CHLFD>
.ASCII <.CHLFD>
.ASCII / B Send a break/<.CHCRT><.CHLFD>
.ASCII \ C Close connect and return to PRO/Kermit\<.CHCRT><.CHLFD>
.ASCII / S Type Status/<.CHCRT><.CHLFD>
.ASCII / ? Help (this message)/<.CHCRT><.CHLFD>
.ASCIZ / /
CNHLP2: .ASCIZ / Send the escape character/<.CHCRT><.CHLFD>
CNHLP3: .ASCII \Press MAIN SCREEN or EXIT to return to PRO/Kermit\<.CHCRT><.CHLFD>
.ASCIZ \Press HELP for this message\<.CHCRT><.CHLFD>
.EVEN
.PSECT $CODE$, RO, I
C$HELP: BLSCAL TT.TEXT,#CNHLP1,+ ; Output the first part of the help message
BLSCAL TT.TEXT,#CONCHR,+ ; Output the escape character
BLSCAL TT.TEXT,#CNHLP2,+ ; Last part of the text
BIT #TRUE,TRMTRN ; Transparent mode?
BNE 10$ ; Yes, don't say anything about function keys
BLSCAL TT.TEXT,#CNHLP3,+ ; No, tell him about other keys
10$: BLSCAL TT.OUTPUT,,- ; Output the rest of the mess
RTS PC ; Return to the caller
.SBTTL CT.INI - Initialize the terminal processing
;++
; This routine will initialize the terminal connect processing.
;
; Usage:
; JSR PC,CT.INI
; (Return - Status in R0)
;
;--
.PSECT $CODE$, RO, I
CT.INI: CLR TTIIDX ; Clear the pointers
CLR TTISTO ; . . .
CLR TTINCH ; . . .
CLR STATE ; Clear the character processing state
MOV #1,TILOCK ; Clear the interlock
MOV #1,TOLOCK ; Clear the interlock
MOV #-1,TIQIO ; And the QIO pending flag
QIOW$C IO.ATT,TERLUN,TTAEFN, , , , ,$CODE$ ; Grab the device
;
; Now get the directive status and determine if we really did it correctly
;
MOV $DSW,R0 ; Get the status
BGE 10$ ; Branch if no error
SEC ; Mark the failure
RTS PC ; Return to the caller
;
; Set the terminal for binary input. This keeps control-C's from
;killing us.
;
10$: QIOW$C SF.SMC,TERLUN,TTAEFN, , , ,<SMCBIN,SMCBNL>,$CODE$
;
; Clear out the flag bytes in the output IOSB's so that they can be used.
;
MOV #NM.QIO,R0 ; Get the count
MOV #TOIOS0-IB.SIZ,R1 ; Point before first block
20$: ADD #IB.SIZ,R1 ; Point to next IOSB
CLRB IB.FLG(R1) ; Clear the flag
SOB R0,20$ ; And loop for all IOSB's
;
; Give a good return
;
CLC ; Clear the carry for the caller
RTS PC ; Return to the caller
; Parameter list for SF.SMC function. Sets the terminal for binary
;I/O.
.PSECT $TEXT$, RO, D
SMCBIN: .BYTE TC.BIN,1 ; Turn binary on
SMCBNL=.-SMCBIN ; Length of block
.SBTTL CT.SHT - Shut down the terminal processing
;++
; This routine will shut down the connect terminal processing.
;
; Usage:
; JSR PC,CT.SHT
; (Return - Status in R0)
;
;--
.PSECT $CODE$, RO, I
CT.SHT: QIOW$C IO.KIL,TERLUN,TTAEFN, , , , ,$CODE$ ; Kill QIO's
QIOW$C SF.SMC,TERLUN,TTAEFN, , , ,<SMCCBN,SMCCBL>,$CODE$ ; Clear binary
QIOW$C IO.DET,TERLUN,TTAEFN, , , , ,$CODE$ ; Detach the device
MOV #-1,TIQIO ; No QIO pending any more
RTS PC ; And return
.PSECT $TEXT$, RO, D
SMCCBN: .BYTE TC.BIN, 0 ; Clear binary input
SMCCBL=.-SMCCBN ; Length of block
.SBTTL CT.INP - Read a character from the CT buffer
;++
; This routine will read a character from the CT buffer. It will then
; return the character to the calling routine
;
; Usage:
; JSR PC,CT.INP
; (Return)
;
; On return:
; Carry - Clear if no characters, set if there was one
; R1/ Character if any there
;--
.PSECT $CODE$, RO, I
CT.INP: DEC TILOCK ; Do I have the interlock?
BNE 90$ ; No, skip this
;
; Here with the interlock, see if there are characters to process
;
MOV TTINCH,R0 ; Get the number of characters
BEQ 10$ ; Branch if none
;
; Here if we have characters that can be passed back to the caller
;
MOV TTIIDX,R1 ; Get the index
MOVB TTIBUF(R1),R1 ; Get the character
DEC TTINCH ; Decrement the number of characters
INC TTIIDX ; Increment
BIC #^C<NM.TIC-1>,TTIIDX ; Make sure we don't go over the end
; of the buffer
CLC ; Clear the carry
MOV #1,TILOCK ; Clear the interlock
RTS PC ; Return to the caller
;
; Here if there were no characters, set the carry and return
;
10$: SEC ; Set the carry
MOV #1,TILOCK ; Clear the interlock
RTS PC ; Return to the caller
;
; Here if we could not get the interlock. Just return as if there were no
; characters.
;
90$: SEC ; Set the carry
RTS PC ; Return to the caller
.SBTTL CT.QIO - Post initial QIO for console terminal
;++
; This routine will post the initial QIO for the console terminal.
;
; Usage:
; JSR PC,CT.QIO
; (Return)
;
;--
.PSECT $CODE$, RO, I
CT.QIO: INC TIQIO ; Need a QIO?
BNE 99$ ; No, just return
CMP TTINCH,#NM.TIC ; Buffer full?
BEQ 10$ ; Branch if so
MOV R1,-(SP) ; Save R1
MOV TTISTO,R1 ; Get the index
ADD #TTIBUF,R1 ; Get the address to output
CLR TIQIO ; Flag QIO is posted
QIO$S #IO.RAL!IO.RNE,#TERLUN,#TTREFN,,#TIIOSB,#CTIAST,<R1,#1>
MOV (SP)+,R1 ; Restore R1
99$: RTS PC ; Return to the caller
; Here if there is no room to read into. Remember we don't have a QIO
;outstanding.
10$: MOV #-1,TIQIO ; No QIO
RTS PC ; Return
.SBTTL CTIAST - Handle ASTs for incoming characters
;++
; This routine will handle console terminal input ASTs. This routine
; will normally be called because there was a single character QIO
; outstanding for the console terminal.
;
; Usage:
; AST level call.
;
;--
.PSECT $CODE$, RO, I
CTIAST::MOV R0,-(SP) ; Save this register
MOV 2(SP),R0 ; Get the current IOSB
JSR PC,1$ ; Call the processing routine
MOV (SP)+,R0 ; Restore the register
TST (SP)+ ; Remove the IOSB from the stack
ASTX$S ; Exit from the AST level routine
;
; The following is the main routine for the AST level processing.
;
1$: MOV #-1,TIQIO ; No QIO pending now
;
; Now determine if there is an error from the QIO.
;
TSTB IB.STS(R0) ; Was there any errors?
BGE 10$ ; Branch if there were no errors
RTS PC ; Just return if errors
;
; Here if we have input some characters, determine the number and update
; the counts
;
10$: MOV IB.CNT(R0),R0 ; Get the count of characters
BEQ 20$ ; No characters, just exit
;
; Here if we have read some characters from the console terminal
;
SETF$S #CONEFN ; Set the event flag
ADD R0,TTISTO ; Point the index to the end
BIC #^C<NM.TIC-1>,TTISTO ; Make sure queue works correctly
ADD R0,TTINCH ; Count up number of characters available
20$: JSR PC,DUMPCT ; Dump console to the XK
PJMP CT.QIO ; Issue the QIO
.SBTTL CTDUMP - Dump the console input
;++
; This routine will dump the console input to the communications line. It
; will return when all of the characters have been processed.
;
; Usage:
; JSR PC,DUMPCT ; Call the routine
; (Return)
;
;--
DUMPCT: JSR R1,$SAVE4 ; Save some registers
10$: JSR PC,CT.INP ; Get a character
BCS 99$ ; Branch if no more characters
;
; Now branch to the correct state.
;
MOV STATE,R0 ; Get the state
MOV CTIDSP(R0),R0 ; Get the routine address
JSR PC,@R0 ; Dispatch to the routine
BR 10$ ; Loop for the next character
;
; Here to return to the caller
;
99$: RTS PC ; Return
;++
; The following is the dispatch table for the various routines. These
; routines will process the character that we received from the console
; terminal.
;--
.PSECT $PLIT$, RO, D
CTIDSP: .WORD ASTINI ; Initial state
.WORD ASTESC ; Saw an <Escape>
.WORD ASTCSI ; Saw a CSI
.WORD ASTSQB ; Saw a [
.WORD ASTDG1 ; Saw first digit
.WORD ASTDG2 ; Saw second digit
.WORD ASTCEC ; Saw connect escape character (ESCCHR)
.SBTTL CTDUMP - ASTINI - Initial state
;++
; This routine will handle the initial state for the AST processing.
;
; Usage:
; R1/ Character
; JSR PC,@R0
; (Return)
;
;--
.PSECT $CODE$, RO, I
.ENABL LSB ; Start local symbol block
; (QIOW$C causes problems)
ASTINI: CMP R1,ESCCHR ; Is this the escape character?
BEQ 30$ ; Yes, handle differently
CMP R1,#.CHCSI ; Is this a CSI?
BEQ 40$ ; Check if allowed
CMP R1,#.CHESC ; Start of an escape sequence?
BEQ 40$ ; Yes, handle it differently
10$: JSR PC,XKOUT ; Output the character
RTS PC ; Return to the caller
;
; Here after we have gotten an escape character in the initial state
;
30$: MOV #$CSCEC,STATE ; Set the new state
RTS PC ; Return to the caller
;
; Here after we have gotten an Escape (33 octal) or a CSI
;
40$: BIT #TRUE,TRMTRN ; Terminal transparent mode?
BNE 10$ ; Branch if so
;
; Now determine if we have enough character coming from the keyboard for this
; to possibly be a function key.
;
MOVB #TC.TBF,TBC ; Store the function
QIOW$C SF.GMC,TERLUN,TTREFN,,TIIOSB,,<TBC,2>,$CODE$
CMPB #4,TBC+1 ; Do we have enough characters?
; BLE 50$ ; Skip if enough
; JMP 10$ ; Else output the character
BGT 10$ ; No, output the escape/CSI
;
; Here if we may have the start of an escape sequence.
;
50$: CLR FNCTXT ; Clear this
CLR FNCTXT+2 ; block
CLR FNCTXT+4 ; of characters
MOV #FNCTXT,R2 ; Get a pointer to the block
MOVB R1,(R2)+ ; Store the characters
MOV R2,FNCPTR ; Store the pointer
MOV #$CSESC,STATE ; Assume we got an escape
CMP #.CHESC,R1 ; Correct?
BEQ 99$ ; Yes, just return
MOV #$CSCSI,R1 ; No, return CSI state
99$: RTS PC ; Return to the caller
.DSABL LSB ; End of local symbol block
.SBTTL CTDUMP - ASTESC - Process after an <Esc>
;++
; This routine will handle the processing after an .CHESC character
; has been input. It will determine if the next character is a square
; bracket and change state to handle it if it is.
;
; Usage:
; R1/ Character
; JSR PC,@R0
; (Return)
;
;--
.PSECT $CODE$, RO, I
ASTESC: MOVB R1,@FNCPTR ; Store the character
INC FNCPTR ; Point to the next position
CMPB #'[,R1 ; Is this a square bracket?
BEQ 10$ ; Yes, process it
MOV #$CSINI,STATE ; Store the new state
PJMP CT.DFK ; Dump the function key
;
; Here to get the new state
;
10$: MOV #$CSSQB,STATE ; Set the new state
RTS PC ; Return to the caller
.SBTTL CTDUMP - ASTCSI - Process after a CSI
;++
; This routine will handle the processing after a CSI character has
; been input. It will determine if the next character is a digit and
; change state, so that the ASTDG1 routine is called if it is.
;
; Usage:
; R1/ Character
; JSR PC,@R0
; (Return)
;
;--
.PSECT $CODE$, RO, I
ASTCSI: MOVB R1,@FNCPTR ; Store the character
INC FNCPTR ; Point to the next position
JSR PC,CHKDIG ; Is this character a digit?
BCS 10$ ; Branch if that was a digit
JSR PC,CT.DFK ; Dump the function key text
MOV #$CSINI,STATE ; Back to the initial state
RTS PC ; Return to the caller
;
; Here if the information was a digit, change to the next possible state
; ($CSDG1)
;
10$: MOV #$CSDG1,STATE ; Set the state
RTS PC ; Return to the caller
.SBTTL CTDUMP - ASTSQB - Process after a square bracket.
;++
; This routine will handle the processing after an escape [ has been seen.
; It will determine if the next character is a digit and then proceed to
; process them.
;
; Usage:
; R1/ Character
; JSR PC,@R0
; (Return)
;
;--
.PSECT $CODE$, RO, I
ASTSQB= ASTCSI
.SBTTL CTDUMP - ASTDG1 - Here after the first digit of a function key
;++
; This routine will handle the processing after the first digit of a function
; key. It is assumed that either another digit or a tilda will follow the
; function key that was input. If the function key is followed by a tilda
; then we will attempt to find the function key in the table. If it is not
; in the table then the information will be output to the user's terminal.
;
; Usage:
; R1/ Character
; JSR PC,@R0
; (Return)
;
;--
.PSECT $CODE$, RO, I
ASTDG1: MOVB R1,@FNCPTR ; Store the character
INC FNCPTR ; Point to the next position
CMPB #'~,R1 ; Is this a tilda?
BEQ 20$ ; Yes, process it
JSR PC,CHKDIG ; Is this character a digit?
BCS 10$ ; Branch if that was a digit
JSR PC,CT.DFK ; Dump the function key text
BR 30$ ; Output the function key
;
; Here if the information was a digit, change to the next possible state
; ($CSDG1)
;
10$: MOV #$CSDG2,STATE ; Set the state
RTS PC ; Return to the caller
;
; Here if we have gotten the last character of the function key. Attempt
; to find it in the table. If it is in the table then we will process
; the function, else we will output the function key to the XK port
;
20$: JSR PC,CT.FFK ; Find the function key
BCC 30$ ; Branch if we did the function
JSR PC,CT.DFK ; Didn't, so dump the function key
30$: MOV #$CSINI,STATE ; Set the new state
RTS PC ; Return to the caller
.SBTTL CTDUMP - ASTDG2 - Here after the second digit of a function key
;++
; This routine will be called after the second digit of a function key. It
; wants a tilda to be the character that was input in this state. If the
; character is not a tilda, then the function key is output to the XK port.
;
; Usage:
; R1/ Character
; JSR PC,@R0
; (Return)
;
;--
.PSECT $CODE$, RO, I
ASTDG2: MOVB R1,@FNCPTR ; Store the character
INC FNCPTR ; Point to the next position
CMPB #'~,R1 ; Is this a tilda?
BEQ 20$ ; Yes, process it
JSR PC,CT.DFK ; Dump the function key text
BR 30$ ; Exit the routine
;
; Here if we have gotten the last character of the function key. Attempt
; to find it in the table. If it is in the table then we will process
; the function, else we will output the function key to the XK port
;
20$: JSR PC,CT.FFK ; Find the function key
BCC 30$ ; Branch if we did the function
JSR PC,CT.DFK ; Didn't, so dump the function key
30$: MOV #$CSINI,STATE ; Set the new state
RTS PC ; Return to the caller
.SBTTL CTDUMP - ASTCEC - Saw connect escape character
;++
; Here after we have seen a connect escape character. This routine will
; determine if the character following it is a valid command character. If
; it is then it will dispatch to the correct routine, else it will send a bell
; to the console.
;
; Usage:
; R1/ Character
; JSR PC,@R0
; (Return)
;
;--
.PSECT $CODE$, RO, I
ASTCEC: MOV R1,R2 ; Copy the character
CMPB #'a,R2 ; Is this a lower case character?
BGT 10$ ; Branch if it is
SUB #'a-'A,R2 ; Convert to upper case
10$: CMPB R2,ESCCHR ; Is this the escape character?
BNE 30$ ; No, go find it in the table
JSR PC,XKOUT ; Output the character
BR 99$ ; Finish up
;
; Here if we have to find the character in the table.
;
30$: MOV #T$ESC,R0 ; Get the escape character table
MOV #<ESC$L/2>,R1 ; And the length
JSR PC,FNDOFS ; Find the item
TST R0 ; Find it?
BNE 20$ ; Branch if we did
JSR PC,CT.BEL ; Output a bell and then the characters
BR 99$ ; Finish up
;
; Here if we have found the entry in the table
;
20$: ADD #ESC$L,R0 ; Point to the other entry
MOV (R0),R0 ; Get the address of the routine
JSR PC,@R0 ; Jump to the routine
;
; Here to reset the state
;
99$: MOV #$CSINI,STATE ; Store the new state
RTS PC ; Return to the caller
.SBTTL CT.FFK - Find a function key
;++
; This routine will find a function key. It is assume that the function
; key text has been accumulated in the FNCTXT locations.
;
; Usage:
; JSR PC,CT.FFK
; (Return)
;
; On return:
; If carry set - Not found
; If carry clear - Found and processed.
;--
CT.FFK: MOV #<KEY$L/2>,R0 ; Get the number of function keys
MOV #T$KEY,R1 ; Get the address of the table
;
; Now loop to find the function key
;
10$: MOV (R1)+,R2 ; Get the address of the text
MOV #4,R3 ; Number of characters to check
MOV #FNCTXT+2,R4 ; First character
CMPB FNCTXT,#.CHCSI ; First character of string a CSI?
BNE 20$ ; No, just enter loop
DEC R4 ; Yes, start one character earlier
20$: CMPB (R4)+,(R2)+ ; Is this the same?
BNE 30$ ; Jump if not
SOB R3,20$ ; Loop for all characters
BR 40$ ; Found what we need, go handle it
30$: SOB R0,10$ ; Loop for all function keys possible
SEC ; Set the carry
RTS PC ; And return to the caller
40$: ADD #KEY$L-2,R1 ; Point to the entry
MOV (R1),R0 ; Get the routine address
ADD #KEY$L,R1 ; Point to the addition information
MOV (R1),R1 ; Get it
JSR PC,(R0) ; Call the routine and return
CLC ; Clear the carry
RTS PC ; Return to the caller
.SBTTL CT.DFK - Dump a function key
;++
; This routine will unwind a function key we have be accumlating in the
; FNCTXT locations. The text will be output to the XK port and then
; the routine will return.
;
; Usage:
; JSR PC,CT.DFK
; (Return)
;
;--
.PSECT $CODE$, RO, I
CT.DFK: MOV #5,R3 ; Maximum number of characters
MOV #FNCTXT,R2 ; Address of the text
10$: MOVB (R2)+,R1 ; Get a character
BEQ 20$ ; Branch if finished
JSR PC,XKOUT ; Output it
SOB R3,10$ ; Loop for all keys read
20$: RTS PC ; Return to the caller
;
; SUBROUTINE - CHKDIG - Check to see if R1 contains a digit
;
CHKDIG: CMPB #'0,R1 ; Compare against zero
BGT 10$ ; If less than zero not a digit
CMPB #'9,R1 ; Compare against nine
BLT 10$ ; If greater than nine not a digit
SEC ; Set the carry bit
RTS PC ; Return to the caller
;
; Here if not a digit, clear the carry
;
10$: CLC ; Clear the carry
RTS PC ; Return to the caller
.SBTTL CT.BEL - Output a bell to the user
;++
; This routine will output a bell to the console terminal. This is done
; for the internal buffers being full, or the fact that the user has
; given a bad escape command.
;
; Usage:
; JSR PC,CT.BEL
; (Return)
;
;--
.PSECT $CODE$, RO, I
CT.BEL: QIO$S #IO.WVB,#TERLUN,#TTWEFN,,#TOIOSB,,<#M$BELL,#1>
RTS PC
.PSECT $PLIT$, RO, I
M$BELL: .ASCIZ <.CHCNG>
.SBTTL CT.PAR - Add parity to a character
;++
; This routine will append the parity bit to the character given it.
;
; Usage:
; R0/ Character
; JSR PC,CT.PAR
; (Return - R0 with character + parity)
;
;--
.PSECT $CODE$, RO, I
CT.PAR: ; FROM BLISS-16 code of GEN.PARITY
BIT #TRUE,DEV.PARITY.FLAG ; Have hardware doing the parity?
BEQ 99$ ; Yes, just return
JSR R1,$SAVE2 ;
BIT #1,IBM.FLAG ;
BEQ 1$
BR 9$
1$: MOV R1,R2 ; CHARACTER,*
MOV PARITY.TYPE,R0 ;
ASL R0
ADD P.AAQ(R0),PC ; Case dispatch
3$: MOV R2,R1 ;
RTS PC
4$: MOV R2,R1 ;
BR 9$
5$: MOV R2,R1 ; *,TEMP.CHAR
BIC #177600,R1 ; *,TEMP.CHAR
BIS #200,R1 ; *,TEMP.CHAR
BR 7$ ;
6$: MOV R2,R1 ; *,TEMP.CHAR
BIC #177600,R1 ; *,TEMP.CHAR
7$: MOV R1,R0 ; TEMP.CHAR,*
ASH #-4,R0
XOR R0,R1 ; *,TEMP.CHAR
MOV R1,R0 ; TEMP.CHAR,*
ASR R0
ASR R0
XOR R0,R1 ; *,TEMP.CHAR
MOV R1,R0 ; TEMP.CHAR,*
BIC #177774,R0
CMP R0,#1
BEQ 8$
BIC #177774,R1
CMP R1,#2
BNE 10$
8$: MOV R2,R1 ;
BIC #177600,R1
9$: BIS #200,R1
RTS PC
10$: MOV R2,R1
BIC #177600,R1
99$: RTS PC ;
.PSECT $PLIT$, RO , D
P.AAQ: ; CASE Table for GEN.PARITY
2$: .WORD 0 ; [3$]
.WORD 4 ; [4$]
.WORD 24 ; [6$]
.WORD 10 ; [5$]
.WORD 114 ; [10$]
.SBTTL Create escape character
; Create the ascii for the escape character
.PSECT $CODE$, RO, I
CRECONCHR::
MOV ESCCHR,R1 ; Get the escape character
MOV #CONCHR,R0 ; Point to the place to store info
CMPB R1,#40 ; Compare against 40
BLT 10$ ; Branch if less than
CMPB R1,#177 ; Is this a delete?
BEQ 30$ ; Jump if it is
JMP 20$ ; Jump to the right routine.
; Here if we have a control character
10$: MOVB #'^,(R0)+ ; Store it
ADD #'A-1,R1 ; Make this a real character
20$: MOVB R1,(R0)+ ; Store it
CLRB (R0)+ ; Clear the last character location
RTS PC ; Return to sender
; Here if we have a delete, store the <del>
30$: MOVB #'<,(R0)+ ; Store the opening bracket
MOVB #'d,(R0)+ ; Store the d
MOVB #'e,(R0)+ ; Store the e
MOVB #'l,(R0)+ ; Store the l
MOVB #'>,(R0)+ ; Store the closing bracket
CLRB (R0)+ ; Clear the last byte
RTS PC ; Return to sender
.SBTTL CT.OUT - Output a single character to the screen
;++
; This routine will output a single character to the screen.
; It is used for the local echo processing.
;
; Usage:
;
; R1/ Character
; JSR PC,CT.OUT
; return here always
;
;--
.PSECT $CODE$, RO, I
CT.OUT: MOV R1,OUTCHR ; Save the character
QIOW$C IO.WVB,TERLUN,TTWEFN,,TOIOSB,,<OUTCHR,1>, $CODE$
RTS PC ; And return
.SBTTL DUMPXK - Dump directly from the XK buffer
;++
; This routine will be called directly from the XK ast input routine. This
; routine will do a QIO to directly output the characters so that there
; can be no delay in processing the input from the XK. The only way we will
; delay is if there is input from the console terminal pending.
;--
DUMPXK: DEC TOLOCK ; Do I have the interlock?
BNE 99$ ; No, just exit
JSR R1,$SAVE3 ; Save R1-3
;
; Here if we can queue the XK output directly to the user terminal.
;
10$: CMP XKNXTC,XKFREC ; Is the buffer empty?
BEQ 90$ ; Yes, just exit
;
; Here if we have something in the buffer
;
MOVB QIOIDX,R2 ; And set up the pointer
ASL R2 ; Mul by two
MOV R2,R0 ; Get a copy
ASL R2 ; So we have address offset
ADD R0,R2 ; For correct IOSB
ADD #TOIOS0,R2 ; Point at correct IOSB
TSTB IB.FLG(R2) ; Is this IOSB free?
BNE 90$ ; No, we must wait
INCB IB.FLG(R2) ; Flag this IOSB is in use
INCB QIOIDX ; Count up to next IOSB
BICB #^C<NM.QIO-1>,QIOIDX ; Make sure it stays in range
;
; Determine how big a QIO we can post to output the information to the
; console
;
MOV #XKBUFLEN,R0 ; Get the length of the buffer
SUB XKNXTC,R0 ; Compute the pointer to end of buffer
CMP XKNXTC,XKFREC ; Determine if in the right order
BGT 20$ ; If free is before next then just
; output to the end of the buffer
MOV XKFREC,R0 ; Get the address of the next free
SUB XKNXTC,R0 ; Subtract the next character pointer
;
; Here after we have determine the amount of characters to output to the
; terminal
;
20$: MOV XKNXTC,R1 ; Get the pointer to the next character
ADD #XKBUFF,R1 ; Point to the buffer
;
; At this point we must determine if we must strip the 8th bit from the
; characters that we just read or can leave them on.
;
BIT #TRUE,NOBIT8 ; Must strip the 8th bit?
BNE 40$ ; No, just do the QIO
;
; Here to loop removing the 8th bit from the input (bit number 7)
;
MOV R0,-(SP) ; Save the length
MOV R1,-(SP) ; Save the address
30$: BICB #200,(R1)+ ; Clear the bit
SOB R0,30$ ; Loop for all characters
MOV (SP)+,R1 ; Restore R1
MOV (SP)+,R0 ; And R0
;
; Now do the QIO to output the information to the user's screen
;
40$: QIO$S #IO.WVB,#TERLUN,#TTWEFN,,R2,#CTOAST,<R1,R0>
ADD R0,XKNXTC ; Update the pointer to the next
BIC #^C<XKBUFLEN-1>,XKNXTC ; Make sure we are a circular buffer
BR 10$ ; Loop and see if anything more
;
; Now clear the interlock, restore R1 and return
;
90$: MOV #1,TOLOCK ; Release the interlock
99$: RTS PC ; Return to the caller
.SBTTL CTOAST - AST routine XK to CT dump routine
;++
; This routine will handle the ASTs that are generated by the dumping of
; data directly from the XK (Comm port) to the CT (Console Terminal)
; It will update the counters that the XK port uses to store information
; into its buffer. It will also light the CONEFN so that if we are
; waiting we will start up again.
;--
CTOAST: SETF$S #CONEFN ; Light the event flag
ADD #IB.CNT,(SP) ; Point to count word in IOSB
ADD @(SP),XKFREE ; Update the number of free characters
SUB @(SP),XKUSED ; Decrease the amount used
ADD #IB.FLG-IB.CNT,(SP) ; Point to flag byte
CLRB @(SP) ; Clear the flag - IOSB is free
TST (SP)+ ; Remove the IOSB from the stack
ASTX$S ; Return from the AST routine
.SBTTL XKOUT - Support local echo
;++
; This routine will support the local echo processing and add any parity
; character before sending the character to the XK port.
;
; Usage:
; R0/ Character
; JSR PC,XKOUT
; (Return via XK.OUT)
;
;--
XKOUT: BIT #TRUE,LCLECH ; Local echo?
BEQ 10$ ; No, just send it to XK
JSR PC,CT.OUT ; Yes, write on screen also
10$: JSR PC,CT.PAR ; Generate the parity
PJMP XK.OUT ; Write the character
.SBTTL End of KERCON
.END MAIN