 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.
*

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

ttopn
 cmpd #IOPminor TTY or IOP device
 lbge iop_open
 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?
 bne ttopn8
 lbsr 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
 pshs d save device
 ldx #98f blowup!
 jsr sysmsg
 puls d
 clra
 jsr sysdec
 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
 lda tstate,x
 anda #$e0 clear states ???
 sta tstate,x
 puls d,x,y,pc return
*
98 fcc $d,$a,'Unable to locate TTY'
99 fcb $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


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

ttdopn 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
 bne ttdop6 is it ready?
 pshs cc,x,y save regs
 sei mask ints
 jsr ttenx enable xmit ints only
 ldb #TTYOPR set priority
 ldy tqout,x point to output q
 jsr sleep sleep on CTS
 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
 anda #$e0
 ora #TOPEN set open status
 sta tstate,x save in table
 rts return

 pag

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

ttcls
 cmpd #IOPminor TTY or IOP device
 lbge iop_close
 bsr ttftab find table entry
 lbsr flusho fluch out buffers
 lda tstate,x
 anda #$e0
 sta tstate,x
 ldy taddr,x get device address
 jmp ttenno close down the port

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

ttrd
 cmpd #IOPminor TTY or IOP device
 lbge iop_read
 bsr ttftab find tty table entry
 lbra ttyrd go do read

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

ttwr
 cmpd #IOPminor TTY or IOP device
 lbge iop_write
 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 ldx ttytab point to tty table
 lda #TTYSIZ get tty size
 mul find this guy in table
 leax d,x
 ldy taddr,x get device address
 beq 00f
01 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 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
 jsr ttyi27
 bra tintr9
tintr6 ldd #HANGS set hangup unt
 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

*
00 pshs d,x
 ldx #00f
 jsr Pdata
 tfr u,d
 jsr Phex
 tfr u,d
 exg a,b
 jsr Phex
 ldx #01f
 jsr Pdata
 lda 6,s
 jsr Phex
 lda 7,s
 jsr Phex
 tfr u,y
 puls d,x
 bra 01b
00 fcc $d,'TTY Port address 0, using (U) = ',0
01 fcc ', Status = ',0

*
* ttspc
*
* TTY special handler.
*

ttspc
 cmpd #IOPminor TTY or IOP device
 lbge iop_spcl
 pshs x save arg
 lbsr ttftab find table entry
 puls y reset arg
* -- 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 #$e0 mask off lower bits
 pshs b
 ldb tstate,x
 andb #$1f 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 #$e0 keep hold processing bits
 std 0,y save in buffer
 rts return
