 sttl TTY Handlers
 pag

*
* All code in this section is the common tty handler
* code.  The device dependent code resides with the
* drivers.  This handler package requires an ACIA be used
* for all character type devices.
*


*
* ttyren
*
* Re-enable the tty output after a timeout operation.
* Upon entry, x should point to the tty structure.
*

ttyren
 lda tstate,x check state
 bita #HOLD
 lbne ttyst9
 anda #!TIMOUT clear time out
 sta tstate,x reset state
 ldy taddr,x
 lbeq ttys55
 jsr [D_ttenxr,u] enable xmit interrupts


 pag

*
* ttyst
*
* TTY start will output a character to the terminal.
* Upon entry, x should point to the tty structure in
* use.  Getc is called for the character.
*

ttyst lda tstate2,x is it ok to transmit?
 bita #DSR_OK
 lbeq ttyst9 no - wait until it is
 ldy taddr,x get device address
 beq ttys55
 jsr [D_ttxbsy,u] test xmit busy?
 beq ttys55
ttyst1 lda tstate,x
 bita #TIMOUT
 lbne ttyst9
 if DO_IXON
 lda tstate2,x need to send PROTOCOL?
 bita #SEND_XOF
 beq 12f
 anda #!SEND_XOF
 ora #XOF_SENT
 ldb #XOFFC
 bra 16f
12 bita #SEND_XON
 beq 14f
 anda #!SEND_XON
 ldb #XONC
 bra 16f
14 bita #SEND_DLE
 beq ttyst15
 anda #!SEND_DLE
16 pshs a
 lda tstate,x transparent mode?
 bita #TRANSPNT
 puls a
 beq 19f no - continue
 bita #DLE_SENT has the DLE been sent?
 beq 18f no
 anda #!DLE_SENT
 bra 19f
18 lda tstate2,x don't change output flags
 ora #DLE_SENT
 ldb #DLE
19 sta tstate2,x remember state
 bra ttyst2 go send character
 endif
ttyst15
 ldy tqout,x get out q
 lbsr get_oq get character
 bne ttyst9 exit if queue empty
 if DO_IXON
 cmpb #DLE special case?
 bne ttyst17
 lda tstate,x in transparent mode?
 bita #TRANSPNT
 beq ttyst17 no - send normally
 lda tstate2,x fix it up
 ora #SEND_DLE
 sta tstate2,x
 bra ttyst1
ttyst17
 endif
 lda tflags,x
 bita #RAW test raw mode
 bne ttyst2
 tstb char negative?
 bmi ttyst6
ttyst2 ldy taddr,x get device address
 jmp [D_ttputc,u] write characetr
ttys55 rts
ttyst6 lda tstate,x
 bita #XANY|XONXOF HOLD processing enabled?
 bne ttyst65 yes
 bita #ESCOFF ESCape HOLD disabled?
 bne ttys55 yes - ignore HOLD character
ttyst65 lda tstate,x get states
 ora #TIMOUT|HOLD set hold mode
 sta tstate,x reset states
ttyst9 ldy taddr,x get port
 jmp [D_ttdisx,u] disable xmit interrupts

 pag

*
* ttyout
*
* Put the character in b into the output q.  Upon
* entry, x should point to the tty structure.  Tab
* expansions, upper case mapping, and special character
* handling are all done here.
*

ttyout lda tflags,x get flags
 bita #RAW raw mode?
 beq ttyo12
 lda tstate,x no hold in RAW mode
 anda #!HOLD
 sta tstate,x
 ldy tqout,x point to out q
 lbsr put_oq put char in q
 lbra ttyoue go finish
ttyo12 cmpb #$ff special hold char?
 beq ttyou6
 andb #$7f mask parity bit
 cmpb #TABCH
 bne ttyou2
 lda tflags,x check mode
 bita #XTABS expand tabs?
 beq ttyou2
ttyo14 ldb #SPACE
 bsr ttyout output it
 lda tcolm,x check column
 bita #7
 bne ttyo14
 rts
ttyou2 lda tflags,x check mode
 bita #LCASE lower case mode?
 beq ttyou4
 cmpb #'a lower case letter?
 blo ttyo22
 cmpb #'z
 bhi ttyo22
 subb #$20 make upper
 bra ttyou4
ttyo22 ldy #lcht point to map
ttyo23 cmpb 0,y++
 bne ttyo24
 ldb -1,y get mapped char
 pshs b
 ldb #'\ output escape
 lbsr ttyout
 puls b
 bra ttyou6
ttyo24 tst 0,y end of list?
 bne ttyo23
ttyou4 cmpb #CR
 bne ttyou6
 lda tflags,x check mode
 bita #CRMOD
 beq ttyou6
 ldb #NL convert to NL
 lbsr ttyout output it
 ldb #CR reset CR
ttyou6 ldy tqout,x point to out q
 lbsr put_oq
 cmpb #CR
 bhi ttyou8
 bne ttyo75 is it cr?
 clr tcolm,x clear out column count!
ttyo75 cmpb #9 is it tab character?
 bne ttyo77
 lda tcolm,x get column count
 anda #!7 mask low 3 bits
 adda #8 add in tab
 sta tcolm,x save new column
 bra ttyoue
ttyo77 cmpb #$08 hardware backspace?
 blo ttyoue
 bne ttyou8
 tst tcolm,x column zero?
 beq ttyoue
 dec tcolm,x
 bra ttyoue
ttyou8 cmpb #SPACE is it control char?
 blo ttyoue
 inc tcolm,x bump column count
ttyoue lda tstate,x ** kludge for ACIA **
 bita #HOLD
 bne ttyoe1
 ldy taddr,x get device address
 jmp [D_ttenxr,u] enable xmit interrupts
ttyoe1 rts return

lcht fcc "~^|!{(})`'"
 fcb 0
 pag

*
* ttyin
*
* Place the character in b on the input q.
* Upon entry, x should point to the tty structure.
* Signal processing and character mapping are
* performed in this roiutine.
*

ttyin
 if DO_IXON
 lda tstate,x transparent mode?
 bita #TRANSPNT
 beq 10f no - continue
 lda tstate2,x processing DLE sequence?
 bita #DLE_GOT
 bne 05f yes - go handle character
 cmpb #DLE is this the start of a DLE sequence?
 bne 10f no - normal input processing
 ora #DLE_GOT remember DLE seen
 sta tstate2,x
 rts all done
05 anda #!DLE_GOT consumed DLE character
 sta tstate2,x
10
 endif
 lda tflags,x raw mode?
 bita #RAW
 bne ttyi44
 andb #$7f mask par bit
ttyin0 cmpb #SPACE control char?
 bhs ttyi44 skip junk if so
ttyin2 cmpb #QUITC
 beq ttyi25
 cmpb #INTRC
 bne ttyin3
 ldd #INTS set signal
 bra ttyi27
ttyi25 ldd #QUITS set signal
ttyi27 jmp send_TI send interrupt & get out
ttyin3 lda tstate,x get state
 cmpb #HOLDC Escape?
 bne ttyi34
 bita #ESCOFF escape processing disabled?
 bne ttyin4 yes - ignore ESC as special character
 bita #HOLD holding??
 bne ttyi36
ttyi33 ora #TIMOUT|HOLD set HOLDing
 sta tstate,x
 jmp ttyren
ttyi34 bita #XONXOF doing XON/XOFF processing?
 beq ttyin4 no - don't bother
 cmpb #XOFFC XOFF character?
 bne ttyi35 no
 bita #HOLD already stopped?
 beq ttyi33 no - stop output
 lbra ttyin9 ignore XOFF if already stopped!
ttyi35 cmpb #XONC XON character
 bne ttyin4 no - continue
* -- HOLD off
ttyi36 anda #!HOLD clear hold mode
 sta tstate,x
 jmp ttyren
ttyin4 cmpb #CR new line?
 bne ttyi44
 clr tcolm,x clear out column
ttyi44 lda tstate,x get current state
 bita #XANY allow any character to restart?
 beq ttyi46 no - continue on
 bita #HOLD currently stopped?
 bne ttyi36 yes - go restart it
ttyi46 ldy tqin,x input Q pointer
 lda 0,y check q count
 if DO_IXON
 cmpa #XOF_POINT need to send XOFF?
 bne 47f no - continue
 pshs a save count
 lda tstate,x XON/XOF protocol enabled?
 bita #IXONXOF
 puls a
 beq 47f no - can't do it
 lda tstate2,x go send XOFF when possible
 anda #!XOF_SENT not sent yet...
 ora #SEND_XOF
 sta tstate2,x
 pshs b,x,y save registers
 jsr ttyst send XOF if possible
 puls b,x,y
 jsr wakeup kick anybody waiting on input
 bra 49f
47
 endif
 cmpa #CHRLIM hit limit?
 lbhs flusht flush this guy!
 lda cbufct check buffer count
 cmpa lcbuf
 lbhi flusht if overflow, flush!
49 lda tflags,x check mode
 bita #RAW raw mode?
 beq ttyin5
 lbsr putc put char in q
 ldy tqin,x get in q
 pshs b save char
 lbsr wakeup awaken those waiting
 puls b get character
 inc tdel,x bump delimiter count
 rts return
ttyin5 bita #LCASE
 beq ttyin6
 cmpb #'A capital letter?
 blo ttyin6
 cmpb #'Z
 bhi ttyin6
 addb #$20 make lower case
ttyin6 ldy tqin,x point to input q
 lbsr putc
 lda tflags,x check mode
 bita #SCHR single char mode?
 bne ttyi65
 cmpb #CR
 bhi ttyin7
 beq ttyi65
 cmpb #EOTCH
 bne ttyin7
ttyi65 ldy tqin,x point to input q
 pshs b
 lbsr wakeup wake up waiting
 inc tdel,x bump count
ttyi67 puls b reset char
ttyin7 cmpb tcncl,x kill character?
 bne ttyin8
 lda tflags,x check mode
 bita #SCHR single character?
 bne ttyin8
 ldb #'^ output '^x\n'
 lbsr ttyout
 ldb #'x
 lbsr ttyout
 ldb #CR
 lbsr ttyout
 jmp ttyst
ttyin8 lda tflags,x check mode
 bita #ECHO
 beq ttyin9
 cmpb tbksp,x back space?
 bne ttyi85
 bita #BSECH echo bs?
 beq ttyi85
 ldb #$08 set bs
 lbsr ttyout
 ldb #SPACE set space
 lbsr ttyout
 ldb #$08 reset char
ttyi85 lbsr ttyout echo character
 jmp ttyst start output
ttyin9 rts return

 pag

*
* flusht
*
* Flush all queues belonging to this terminal.
*

flusht
 lbsr flushi flush Input queues
 ldy tqout,x point to out q
10 lbsr get_oq flush out q
 bpl 10b
 ldy tqin,x get input q
 lbsr wakeup wakeup input q waiters
 ldy tqout,x wake up out q waiters
 lbsr wakeup
 lda tstate,x get states
 anda #!(HOLD|TIMOUT) clear hold mode
 sta tstate,x
 ldd #0 no pre-sold output
 std tsold,x
 jmp ttyst

*
* flusho
*
* Flush all this guys queues after waiting for the
* output q to empty.
*

flusho lda tstate,x check state
 bita #HOLD holding?
 beq fluso1
fluso0 anda #!(HOLD|TIMOUT)
 sta tstate,x clear hold
 lbsr ttyren kick output
fluso1 ldd [tqout,x] check char count
 lbeq flusht
 lda tstate,x check for hold
 bita #HOLD
 bne fluso0

 if 0 *** I don't think this can work - GDT 4/1/85 ***
 pshs x save ptr
 ldx taddr,x get device address
 jsr [D_ttiscts,u] check for CTS
 puls x reset tty ptr
 lbeq flusht if not - just flush the guy
 endif

 ldy tqout,x point to out q
 ldb #TTYOPR set priority
 pshs x save x
 lbsr sleep
 puls x
 bra fluso1

*
* flushi - Flush input Queues only
*
flushi
 ldy tqproc,x get procd q
10 lbsr getc get character
 bpl 10b
 ldy tqin,x flush input q
20 lbsr getc
 bpl 20b
 clr tdel,x clear delim count
 if DO_IXON
 lbsr chk_xon see if need to send XON
 endif
 rts



*
* xtprcq
*
* Transfer characters from input q to procd q.  If not
* in raw mode, do escape, backspace, and cancel
* processing.  Enter with x pointing to tty structure.
*

xtprcq pshs cc save cc
 seti mask ints
 tst tdel,x delimiters yet?
 bne xtprc0
 if DO_IXON
 bsr chk_xon allow chars in if we shut them off
 endif
 ldy tqin,x sleep on input q
 ldb #TTYIPR
 pshs x save x
 lbsr sleep
 puls x
 puls cc reset cc
 bra xtprcq
xtprc0 puls cc reset cc
 tst [tqin,x] input q empty?
 bne xtprc1
 dec tdel,x dec the del count
 bra xtprcq repeat test
xtprc1 ldy #prcbuf+2 point to buffer
 clrb
 pshs b,y delimiter flag
xtprc2 tst 0,s delimiter?
 beq xtpr22
 clr 0,s clear del flag
 tst tdel,x check del count
 beq xtpr21 if 0 - skip
 dec tdel,x dec the del count
xtpr21 lda tflags,x get flags
 bita #RAW|SCHR in raw mode?
 lbeq xtprc5
xtpr22 ldy tqin,x point to in q
 lbsr getc get a character
 bmi xtprc5 none left?
 cmpb #CR check for delim
 beq xtpr25
 cmpb #EOTCH
 bne xtprc3
 inc 0,s set del flag
 lda tflags,x get flags
 bita #SCHR single char mode?
 bne xtprc2
xtpr25 inc 0,s set del flag
xtprc3 lda tflags,x check mode
 bita #RAW|SCHR
 beq xtpr31
 inc 0,s set del flag for each raw char
 bra xtpr45
xtpr31 ldy 1,s point to buffer
 lda -1,y check previous
 cmpa #'\ escape?
 bne xtca32
 cmpb #EOTCH is it eot?
 beq xtp315
 cmpb tbksp,x backspace char?
 beq xtp315
 cmpb tcncl,x cancel char?
 bne xtca32
xtp315 leay -1,y backup over slash
 sty 1,s save new ptr
 bra xtpr45
xtca32 cmpb tbksp,x backspace char?
 bne xtca33
 cmpy #prcbuf+2 buffer begin?
 beq xtprc2
 leay -1,y backup pointer
 sty 1,s
 bra xtprc2
xtca33 cmpb #EOTCH eot char?
 beq xtprc2
 cmpb tcncl,x cancel char?
 bne xtprc4
 puls b,y -- caution (order)
 bra xtprc1 repeat all
xtprc4 cmpb #$20 check for control char
 bhs xtpr45
 cmpb #CR is it cr?
 beq xtpr45
 cmpb #9 is it tab char?
 beq xtpr45
 lda tflags,x get flags
 bita #CNTRL control char ignore?
 lbne xtprc2
xtpr45 ldy 1,s get pointer
 stb 0,y+ transfer char
 sty 1,s save pointer
 cmpy #prcbuf+PRCSIZ overflow??
 lblo xtprc2
xtprc5 puls b remove del flag from stack
 ldy tqproc,x get procd q
 pshs x
 ldx #prcbuf+2 point to processed buf
xtprc6 cmpx 2,s end of buffer?
 bhs xtprc7
 ldb 0,x+ get character
 lbsr putc
 bra xtprc6
xtprc7
 if DO_IXON
 bsr chk_xon see if need to send XON
 endif
 ldd #-1 set good
 puls x,y,pc return

 if DO_IXON
chk_xon lda tstate2,x did we shut the other guy down?
 bita #XOF_SENT
 beq 10f no - continue
 anda #!XOF_SENT kill flag
 ora #SEND_XON try to restart him
 sta tstate2,x
 jsr ttyst kick output to get XON out
10 rts
 endif
 pag

*
* req_read - CPU has informed us he wants to read
* Tell him when some data is available.
*
req_read lbsr ttftab get TTY table address
 lda [tqproc,x] anything available?
 bne 00f yes - go use it
 lbsr xtprcq go process input (wait if none there)
00 lda [tqproc,x] get input processed count
 beq 05f jump for EOF detected
 cmpa #1 special case for single character
 beq 10f
 ldb tflags,x single character & RAW always return 1 char
 bitb #RAW|SCHR
 bne 10f
05 ldb #R_RDOK inform CPU data now available
 rts
10 ldy tqproc,x go fetch character
 lbsr getc
 lda #R_RD1C inform CPU single character returned
 exg a,b
 rts

*
* read_data - CPU wants IOP to send data
*  Max # chars to move in transaction speicific value
*
read_data lbsr ttftab get TTY table address
 ldu utask see how many chars to send
 ldy tqproc,x input queue pointer
 clr ,-s set FIFO counter
10 lda 0,y any more characters?
 beq 20f no - done
 lbsr getc fetch character
 lbsr FIFO_put put into FIFO
 inc 0,s bump FIFO count
 dec tstval,u does the guy want more?
 bne 10b
20 lda ,s+ get # chars in FIFO
 ldb #R_SNDNC data now available in FIFO
 tst 0,y any more data in case guy wants it?
 beq 30f
 ldb #R_SNDMC yes - special response
30 rts
 pag

*
* ttywrt
*
* The main terminal write routine.  Control is passed
* to here from the device driver routine which calculates
* the ttys structure location and passes it in x.
*

ttywrt ldb fifo_cnt get FIFO input length
 cmpb #0 anything in FIFO?
 beq 90f no - exit
 pshs b save input length
10 lbsr FIFO_get fetch character
 lbsr ttyout output it
 dec 0,s decrement count
 bne 10b repeat
 puls a clean up stack
90 pshs cc save cc
 seti mask ints
 lbsr ttyst give output a kick
 puls cc,pc return

*
* open_tty - Perform device open
*
open_tty
 jsr ttopn perform tty open
 if DBG_IO&DEBUG_CONTROL
 jsr DB_msg
 fdb DBG_IO,10f
 lbsr dmp_TTY
 endif
10 ldb #R_OPEN
 rts

*
* close_tty - Perform device close
*
close_tty
 jsr ttcls perform tty close
 if DBG_IO&DEBUG_CONTROL
 jsr DB_msg
 fdb DBG_IO,10f
 lbsr dmp_TTY
 endif
10 ldb #R_CLOSE
 rts

*
* req_write - Request permission to write data
*
req_write
 jsr ttftab get TTY table
 if DBG_IO&DEBUG_CONTROL
 jsr DB_msg
 fdb DBG_IO,05f
 lbsr dmp_TTY
 endif
05 pshs cc mask interrupts while fiddling
10 seti
 ldy tqout,x get output queue pointer
 ldd oq_count,y get queue length
 addd tsold,x include any space already sold
 addd #FIFO_SIZE and assume the CPU will send this many more
 cmpd OQHI space available?
 ble 20f yes - OK
 lda tdelay,x special flush bit?
 bita #$40
 beq 15f no - go to sleep
 jsr flusho yes - flush output
 bra 10b try again
15 pshs d,x,y,u no - save registers
 ldb #TTYSPR
 jsr sleep
 puls d,x,y,u restore registers
 bra 10b try again
20 ldy utask am I supposed to be dead?
 tst tssgnl,y
 bne 30f yes - abort
 ldd tsold,x update amount pre-sold
 addd #FIFO_SIZE -- assume entire FIFO load
 std tsold,x
 ldb #R_REQOK request granted code
 puls cc,pc return
*
30 puls cc clean up stack
 leas 2,s -- pop normal return
 rts abnormal I/O completion (no response)

*
* write_data - Write data to a terminal
*
write_data
 jsr ttftab get tty table pointer
 jsr ttywrt go consume data
 pshs cc save interrupt state
 seti mask interrupts
 ldd tsold,x
 subd #FIFO_SIZE
 bpl 00f
 ldd #0 don't screw up!
00 std tsold,x update count
 ldy tqout,x wake up anybody waiting for space
 if DBG_IO&DEBUG_CONTROL
 jsr DB_msg
 fdb DBG_IO,10f
 pshs d,x,y,u
 ldx #00f
 jsr DB_pdata
 tfr y,d
 jsr DB_phex2
 puls d,x,y,u
 endif
10 jsr wakeup
 ldb #R_WRITE
 puls cc,pc return
00 fcc $d,'FIFO consumed, wakeup at $',0

*
* Write single character
*  -- Character passed via transaction message
*
wrt_sc pshs cc save interrupt state
 jsr ttftab compute tty table address
00 ldy tqout,x output Q pointer
 ldd oq_count,y check for overrun
 cmpd OQHI
 bls 10f jump if space
 lda tdelay,x special flush bit?
 bita #$40
 beq 05f no - wait for space
 jsr flusho yes - make space!
 bra 00b
05 ldb #TTYOPR wait a while
 jsr sleep
 bra 00b try again
10 ldy utask fetch character
 ldb tstval,y
 jsr ttyout send to output queue
 seti mask interrupts
 jsr ttyst kick output - make sure it starts
 ldb #R_WRITE
 puls cc,pc return

*
* send_int - Interrupt all tasks associated with a terminal
*
send_int pshs d,x,y,u
 jsr ttftab get TTY table address
 jsr flusht flush terminal buffers
 lda 1,s get terminal #
 jsr int_all interrupt all associated tasks
 ldx utask also interrupt current task if appropriate
 lda 1,s
 cmpa tsdev,x
 bne 10f
 jsr xmtint
10 puls d,x,y,u,pc clean up stack & return

 if DBG_IO&DEBUG_CONTROL
*
* dmp_TTY - dump TTY table
*    X - TTY Table address
*
dmp_TTY pshs d,x,y,u
 tfr x,y
 ldx #00f
 jsr DB_pdata
 ldd 2,s
 jsr DB_phex2
 ldx #01f
 jsr DB_pdata
 lda [tqin,y]
 jsr DB_phex
 ldx #02f
 jsr DB_pdata
 lda [tqout,y]
 jsr DB_phex
 ldx #03f
 jsr DB_pdata
 ldd tstate,y
 jsr DB_phex2
99 puls d,x,y,u,pc
*
00 fcc $d,'TTY Table $',0
01 fcc ', In Q = ',0
02 fcc ', Out Q = ',0
03 fcc ', State = ',0
 endif
