 lib ../environment
 sttl Terminal Drivers
 pag
 name ttydrvr
 global ttopn,ttcls,ttrd,ttwr,tintr,ttspc,findBRG

*
* The routines in this file make up the main system
* terminal drivers.  Most of the work is actually
* performed by other internal routines.
*

*
* Equates
*

OPNBTS equ TOPEN|HOLD|TIMOUT open bits
HLDBTS equ ESCOFF|XONXOF|XANY hold bits


*
* ttopn
*
* Open a terminal for use.  On entry, D has
* the device number.
*

ttopn pshs d save device number
 cmpb strm invalid number?
 bhs ttopn9
 pshs d save device
 lbsr ttftab
 ldd taddr,x get device address
 puls d
 bne ttopn5
 bsr ttfdev find the device address
 ldd 0,s get device number
 std tdevic,x save device number
ttopn5 ldy utask get task pointer
 ldd tstty,y get control terminal
 bne ttopn6 if set, skip this part
 stx tstty,y set the control terminal
ttopn6 lda tstate,x get states
 bita #TOPEN is it already open?
 beq ttopn7 branch if not yet open
 lda tstat2,x get special open bit
 bita #TOPWOC previously opened w/o carrier?
 beq ttopn8 skip open if not
ttopn7 bsr ttdopn do actual open
 tst uerror errors?
 bne ttopn9
ttopn8 ldy taddr,x point to device
 jsr ttenr enable rcv interrupts
 puls d,pc return
ttopn9 lda #EBDEV bad device
 sta uerror set error
 puls d,pc return


 pag

*
* ttfdev
*
* Find the device address associated with
* minor device number in B.
*

ttfdev
 pshs d,x,y save registers
 ldy #inttab search interrupt table
 ldb ,y+ get number of devices
 pshs b
 ldd 1,s restore device #
0 cmpd indev,y device # match?
 beq 1f yes
 leay INTSIZ,y no - bump to next entry
 dec 0,s end of table?
 bne 0b no
 ldx #99f
 jsr blowup
*
1 leas 1,s clean up stack
 ldd instat,y pick up device address
 std taddr,x
 lda inspcl,y get baud rate pattern
 sta tbaud2,x
 bsr clropn clear open state
 puls d,x,y,pc return
*
99 fcc $d,$a,'No TTY',0

*
* findBRG
*
* Determine the addresses of the baud rate generators
* for a given ACIA port (if any).
*    (X) - ACIA address
*    jsr findBRG
*    (Y) - Transmit BRG
*    (U) - Receive BRG
*
findBRG pshs d,x save registers
 ldx #inttab search interrupt table
 ldb ,x+ get length of table
 pshs b
10 ldd instat,x check address
 cmpd 3,s match ACIA address?
 beq 20f yes - exit
 leax INTSIZ,x move to next entry
 dec 0,s
 bne 10b
20 ldy intbrg,x get transmit BRG
 ldu inrbrg,x get receive BRG
 leas 1,s clean up stack
 puls d,x,pc return

*
* clear open state bits
*

clropn lda tstate,x
 anda #!OPNBTS clear open state bits
 sta tstate,x
 lda tstat2,x
 anda #!TOPWOC clear special open bit
 sta tstat2,x
 rts


*
* ttdopn
*
* Do actual terminal open.  X points to tty entry.
*

ttdopn bsr clropn clear open state
 ldy taddr,x get device address
 lda tbaud2,x baud rate need setting up?
 beq 10f no
 pshs x,y,u save registers
 ldx taddr,x get ACIA address
 bsr findBRG get baud rate generator addresses
 ldx 0,s restore tty structure address
 jsr ttsbrg set baud rates
 puls x,y,u restore registers
10 jsr ttconf configure the port
* response of NE implies open OK
* if EQ then blocked by CTS if Carry is 0
 bne ttdop6 is it ready?
 bcs ttdop5 branch if blocked by DCD
 pshs cc,x,y save regs
 sei mask ints
 jsr ttwcts wait for CTS
 puls cc,x,y reset regs
 bra ttdopn repeat open
ttdop5 pshs cc,x,y save regs
 sei mask ints
 jsr ttwdcd wait for DCD
 puls cc,x,y reset regs
 bra ttdopn repeat open
ttdop6 lda #ECHO|XTABS|CRMOD|BSECH
 sta tflags,x setup initial mode
 lda #BSPCH get backspace char
 sta tbksp,x save in table
 lda #CNCLC get cancel character
 sta tcncl,x save in table
 lda tstate,x
 ora #TOPEN set open status
 sta tstate,x save in table
 rts return

 pag

*
* ttcls
*
* Close the terminal whose device number is in D.
*

ttcls bsr ttftab find table entry
 lda tstate,x was the port actually open?
 bita #TOPEN
 beq 10f no - get out
 anda #!TOPEN yes - clear open state
 sta tstate,x ... so we don't get hung up here ...
 lbsr flusho flush out buffers
 ldy taddr,x get device address
 jsr ttenno close down the port
10 bsr clropn clear open state
 rts

*
* ttrd
*
* Do a terminal read operation.  Device number in D.
*

ttrd bsr ttftab find tty table entry
 lbra ttyrd go do read

*
* ttwr
*
* Do a terminal write operation.  Device number in D.
*

ttwr bsr ttftab find table entry
 lbra ttywrt go do write

*
* ttftab
*
* Find tty table entry associated with device in D.
* Exit with entry pointed at by X.
*

ttftab ldx ttytab point to table
 lda #TTYSIZ set size up
 mul calculate offset
 leax d,x point to entry
 rts return


 pag

*
* tintr
*
* TTY interrupt handler.  Determine if the interrupt
* is a receive or transmit one and take appropriate
* actions.
*

tintr bsr ttftab point to tty table
 ldy taddr,x get device address
tintr0 pshs y save port address
 jsr tttstx test for xmit int
 bne tintr3
 jsr tttstr test for rcv int
 bne tintr2
 jsr tttstb test for break interrupt
 bne tintr5
 jsr tttsts test for Clear to Send interrupt
 bne tintr9
 jsr tttstc test drop carrier int
 bne tintr6
 jsr tttste test error int
 bne tintr7 ** should be 7? **
 bra tintr9
tintr2 jsr ttgetc get character from port
 jsr ttyin go buffer char
 bra tintr9
tintr3 jsr ttyst go output another char
 lda [tqout,x] check queue count
 beq tintr4
 cmpa #OQLO low water mark?
 bne tintr9
tintr4 ldy tqout,x get output queue
 jsr wakeup
 bra tintr9
tintr5 ldd #INTS set INT interrupt
 bra tint65
tintr6 ldd #HANGS set hangup unt
tint65 jsr ttyi27
 bra tintr9
tintr7 ldb #$07 set bell char
 jsr ttyin go buffer it
tintr9 puls y restore port address
 jmp ttend clean up the port & return


*
* ttspc
*
* TTY special handler.
*

ttspc tfr x,y put arg into y
 bsr ttftab find table entry
* -- Fall through to "ttysg"
 pag

*
* ttysg
*
* Handle the actual get or put of data for ttyset
* and ttyget.  On entry, X is pointing to the terminal
* table entry and Y is; 0 if doing ttyset, or an
* address if doing ttyget and tells where the data
* should be placed.
*

ttysg cmpy #0 is pointer null?
 bne ttysg4 if not, go do 'get'
 ldd usarg1 get next word
 sta tcncl,x set cancel char
 stb tbksp,x set back space char
 ldd usarg2 get last byte
 anda #$1c mask low 4 bits **
 sta tbaud,x set bauds
 andb #HLDBTS mask off lower bits
 pshs b
 ldb tstate,x
 andb #(!HLDBTS)&$ff clear hold processing bits
 orb 0,s+ add in new ones
 stb tstate,x
 ldd usarg0 get status word
 stb tdelay,x set delays
 ldb tflags,x get old flags
 sta tflags,x set new flags
 bitb #RAW|SCHR were we in RAW or SCHR?
 bne ttysg3
 bita #RAW|SCHR going into RAW or SCHR?
 beq ttysg3
 tst [tqin,x] any characters in q?
 beq ttysg2
 tst tdel,x any delimiters yet?
 bne ttysg2 skip if so
 inc tdel,x bump delimiter count
ttysg2 bita #RAW going into RAW?
 beq ttysg3
 lda tstate,x
 bita #HOLD were we holding?
 beq ttysg3
 anda #!HOLD turn off hold
 sta tstate,x
 jsr ttyren reenable output
ttysg3 rts return
ttysg4 lda tflags,x get flags byte
 ldb tdelay,x get delays
 std 0,y++ save in buffer
 lda tcncl,x get cancel char
 ldb tbksp,x get b.s. char
 std 0,y++ save in buffer
 lda tbaud,x get bauds
 anda #$1c mask low 4 bits **
 tst tdel,x check delimiter count
 bne ttys45
 tst [tqproc,x] any chars in processed queue?
 beq ttysg5
ttys45 ora #%10000000 set del bit
ttysg5 ldb tstate,x
 andb #HLDBTS keep hold processing bits
 std 0,y save in buffer
 rts return
