
 lib hardware
 lib ../environment
 sttl Terminal Drivers
 data
 pag
 name ttydrvr
 global ttopn,ttcls,ttrd,ttwr,tintr,ttspc,findBRG
 global in1,in2,incomp,out1,out2,outstat,viaintr
 global TIMCNT
 global figpoint


*
*   temporary storage and buffer locations for parallel
*   terminal i/o

in1 fcb 0 first half input buffer
in2 fcb 0 second half input buffer
incomp fcb 0 non-zero if input complete
out1 fcb 0 first half output buffer
out2 fcb 0 second half output buffer
outstat fcb 0 status of output

TIMCNT fcb 0 extended timeout counter for via

*
* 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 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
 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 lbsr ttftab find table entry
 lbsr flusho flush out buffers
 bsr clropn clear open state
 ldy taddr,x get device address
 jmp ttenno close down the port

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

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

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

ttwr lbsr 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


figpoint ldx ttytab
 lda #TTYSIZ
 mul
 leax d,x
 ldy taddr,x
 rts
*
*   VIA (parallel terminal I/O) interrupt handler
*
viaintr
 lda IFR08
 bita #CA1
 lbne rcvintr
 bita #CB1
 bne xmtintr
*
*   check for transmit timeout
*

 bita #$40
 beq nopto
 lda #$40
 sta IFR08
 dec TIMCNT
 beq pto
 ldd #0
 std T1CNTR
 rts
pto ldb #20
 stb TIMCNT
 ldd #0
 std T1CNTR
 ldb PCR08
 pshs b
 andb #$1F
 orb #$E0
 lda ORB08
 anda #%10111111
 stb PCR08
 puls b
 stb PCR08
 sta ORB08
nopto rts
*
*   handle `data received by X-12' interrupt
*
xmtintr
 lda outstat
 bmi send2
*
*   completed whole character, go set next one up
*
xmfin
 ldb #$40
 stb IER08
 stb IFR08
 ldb #CB1
 stb IFR08
 anda #$3F
 sta outstat say nothing going on noww
*   handle next transmit character
vintrn
 tst waiters anybody else waiting?
 beq vintr7
 lbsr fndng find who is waiting
 clr b,x he's no longer waiting
 dec waiters
 lda nowtty get previous
 stb nowtty set new
 ldx #waitlst now make previous wait
 tst a,x already waiting?
 bne vintr7
 inc a,x show waiting
 inc waiters
vintr7 ldb nowtty
 lbsr figpoint
 pshs y
 jsr ttyst
 lda [tqout,x]
 beq vintr8
 cmpa #OQLO
 bne vintr9
vintr8 ldy tqout,x
 jsr wakeup
vintr9 puls y
*   fill with selector later
vend rts
*
*   send second half of data character
*
send2 anda #$7F strip bit 7
 ora #$40 indicate busy on second half
 sta outstat leave business around for later
 ldb #$40
 stb IER08
 stb IFR08
 lda out2
 sta ORB08
 ldb #20
 stb TIMCNT
 ldd #0
 std T1CNTR
 rts
*
*   handle X-12 data ready interrupts
*
rcvintr lda ORA08
 tsta  is it the first or second half
 bpl rcrv2 second half if positive
*
 sta in1
 rts
*
*   got both halves, now must interrogate
*   the control bits for special cases
*
rcrv2 sta in2 store the second half
 ldb #0
 lbsr figpoint
 lda in1
 lsra
 lsra
 anda #$0F
 lbeq rcrv3 X-12 receive
*
*   check out the weird combinations of bytes coming through
*   here from the X-12
 cmpa #TTYOFF Xoff TTY
 bne ttgx00
 lda #%00000001 say no more for tty
 ora incomp
 sta incomp
 lbra ttgxit
ttgx00 cmpa #TTYON XON tty
 bne ttgx01
 lda #%11111110 say go ahead for tty
 anda incomp
 sta incomp
 pshs y
 lbra tintr3
ttgx01 cmpa #TTYBRK check for break on tty
 bne ttgx02
 lda #%00000010 found break on tty00
 ora incomp
 sta incomp
 pshs y
 lbra tintr5 INT!!!
ttgx02 cmpa #PPROFF XOFF PPR
 bne ttgx03
 lda #%00000100 say no more for ppr
 ora incomp
 lbra ttgxit
ttgx03 cmpa #PPRON
 bne ttgx04
 lda #%11111011 say go ahead for ppr
 anda incomp
 sta incomp
 ldb #8 point to ppr device
 lbsr figpoint
 pshs y
 lbra tintr3
ttgx04     cmpa    #SPROFF             XOFF spr
           bne     ttgx05
           lda     #%00001000          say no more for spr
           ora     incomp
           bra     ttgxit
ttgx05     cmpa    #SPRON              XON spr
           bne     ttgx06
           lda     #%11110111          say more for spr
           anda    incomp
           sta     incomp
           ldb     #9            point to spr device
           lbsr    figpoint
           pshs    y
           lbra    tintr3
ttgx06     cmpa    #TTYCBRK            clear break
           bne     ttgx07              unknown??
           lda     #%11111101          say no more break
           anda    incomp
           bra     ttgxit
ttgx07     cmpa    #COMON
           bne     ttgx08
           lda     #%11101111          say more for comm line
           anda    incomp
           sta     incomp
           ldb     #3
           lbsr    figpoint
           pshs    y
           lbra    tintr3
ttgx08     cmpa    #COMOFF
           bne     ttgx09
           lda     #%00010000          com off
           ora     incomp
           bra     ttgxit
ttgx09     cmpa    #COMBRK             SPECIAL MULTI-MODE INTERRUPT
           bne     ttgx10              no
*   this is an extended control stream, low two bits show
*   type of interrupt
*
*    00 - BREAK
*    01 - HANGUP
*    10 - PARITY
*    11 -
           lda     in1                 get original input byte
           anda    #%00000011          save two bits
           beq     combrk              standard BREAK when low two clear
combrk     lda     #%00000010          found break on tty
           ora     incomp              include in status
           sta     incomp
           ldb     #3
           lbsr    figpoint            go point at this device
           pshs    y                   INT!!!!
           lbra    tintr5
ttgx10     cmpa    #COMCBRK            clear break from comm line
           bne     ttgx11
           lda     incomp              ** dummy
           bra     ttgxit
ttgx11     ldb     #3
           lbsr    figpoint
           bra     rcrv3
ttgclr     lda     incomp
ttgxit     sta     incomp
           ldb     #0                  .
           lbsr    figpoint             .. dummy to make stack work
           pshs    y                   .
           jmp     tintr9
*
*   normal data byte from X-12
*
rcrv3      pshs    y
           lbra    tintr2              then go handle the character

*
* ttspc
*
* TTY special handler.
*

ttspc tfr x,y put arg into y
 lbsr 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
 tfr b,a
 anda #$0f get just the baud rate
 cmpa #$0a was it 2400 or higher?
 bhs ttysg1
 cmpa #$04 was it 150 or lower?
 bls ttysg1
 deca correct baud rate
 cmpa #$04 was baud rate 200?
 bne ttysg1
 clra set no baud rate
ttysg1 sta tbaud2,x save it
 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
 pshs b save hold bits
 ldb tbaud2,x get baud rate bits
 cmpb #$0a is it 2400 baud or higher?
 bhs ttysg6 skip if so
 cmpb #$04 is it 150 baud or lower?
 bls ttysg6 skip if so
 incb correct baud rate
ttysg6 orb 0,s+ add in hold bits
 std 0,y save in buffer
 rts return

