
 lib environment
 lib sptab
 lib macdefs
 data
 sttl Serial Printer Driver
 pag
 name sprdrvr
 global spopn,spcls,spwrt,spntr,spspc

*
* This file contains serial printer driver
* routines provided with the standard configuration.
*

XONXOF equ %01000000 XON/XOFF processing
SPLOC equ 35 low water count
data equ 0
cont equ 2

*
* spopn
*
* Open the serial port.
*

spopn cmpb #SPMAX legal device number?
 bhi spopn6 if not - error
 pshs b save dev number
 bsr spsel select printer structure
 tst spstat,x is it open?
 puls b reset dev number
 bne spopn4 if open - exit
 aslb
 aslb
 ldy #sptabl point to table
 leay b,y point to this guys data
 ldd 0,y get buffer address
 std spiptr,x set up info in structure
 std spoptr,x
 std spbfst,x
 addd #SPBFSZ calc buffer end
 std spbfen,x set end
 ldd 2,y get acia address
 std spacia,x
 clr spxoff,x clear holding flagg
 ldy spacia,x get address
*** Configure the port ***
spconf lda #$10 reset status
 sta cont,y
 lda cont,y get status
 ldb #1 turn on interrupts
 stb cont,y
 ldb #$1f enable ints
 stb cont,y
**************************
 inc spstat,x set open status
spopn4 rts return
spopn6 lda #EBDEV set error
 sta uerror
 rts return

*
* select printer structure - return in X.
*

spsel ldx #spstrc point to structures
 lda #SPSZ
 mul calc offset
 leax d,x adjust ptr
 rts return

*
* spcls
*
* Close the acia - no operation now.
*

spcls bsr spsel select printer
 clr spstat,x zero status
 rts return

*
* spwrt
*
* Write to serial printer.
*

spwrt bsr spsel select printer
spwrt1 jsr cpass get a character from user
 bmi spwrt6 none left?
 pshs b save character
spwrt2 lda spcntr,x get char count
 ldb #SPBFSZ get buffer size
 subb #2
 pshs b
 cmpa 0,s+ upper limit?
 blo spwrt4
 pshs cc save cpu status
 seti mask interrupts
 jsr spstrt start output
 puls cc reset status
 pshs x
 ldy spbfst,x point to queue
 ldb #TTYOPR set priority
 jsr sleep sleep on queue
 puls x
 bra spwrt2 repeat
spwrt4 puls b get character
 bsr spout output it
 bra spwrt1 repeat loop
spwrt6 pshs cc save status
 seti mask interrupts
 bsr spstrt kick port
 puls cc,pc return

*
* spntr
*
* Serial port interrupt handler
*

spntr bsr spsel select printer
 ldy spacia,x get port address
 ldd 2,s get status
 tsta -- cmpa #0 xmit int?
 beq 2f branch if an xmit
 cmpa #2 receive interrupt?
 beq spntr6 branch if rcv int
* unknown interrupt at this point
 lda #1 reset external int
 sta cont,y
 lda cont,y
 lda #$10
 sta cont,y
 bra spntr9 go clean up int

* it was a transmit interrupt
2 bsr spstr1 start output
 lda spcntr,x get char count
 beq 4f
 cmpa #SPLOC low water mark?
 bne spntr9
4 pshs y save port address
 ldy spbfst,x point to queue
 jsr wakeup
 puls y
 bra spntr9

* it was a receive interrupt
spntr6 ldb data,y read the character
 tst spspcl,x doing XON/XOFF?
 beq spntr9 exit if not
 cmpb #XOFFC is char an XOFF?
 bne spntr7
 stb spxoff,x start holding
 bra spntr9
spntr7 cmpb #XONC is char an XON?
 bne spntr9
 tst spxoff,x are we currently holding?
 beq spntr9 skip if not
 clr spxoff,x restart output
* in ACIA version, interrupts are enabled here *
 bsr spntr9 clean up
 bra spstrt kick output

* clean up after interrupt
spntr9 pshs d,y
 ldd 2,s
 andb #$fe find low port address
 tfr d,y point to it
 lda #$38 reset ints
 sta cont,y
 puls d,y,pc return

*
* spout
*
* Output char to serial printer queue.
*

spout ldy spiptr,x get queue pointer
 stb 0,y+ place in q
 cmpy spbfen,x end of q?
 bne spout2
 ldy spbfst,x reset q pointer
spout2 sty spiptr,x save pointer
 cmpb #$d is it cr?
 bne spout4
 inc spcntr,x bump count
 ldb #$a set up line feed
 bra spout repeat
spout4 inc spcntr,x bump char counter
* in ACIA version, interrupts would be enabled here, but
* only if spxoff,x were equal to zero (not holding)
 rts

*
* spstrt
*
* Start output on the serial port.
*

spstrt ldy spacia,x point to acia
*** Check for xmit busy ***
sptbsy lda #1 select reg 1
 sta cont,y
 lda cont,y get status
 bita #1 xmit done?
***************************
 beq spstr4 if so - exit
spstr1 tst spxoff,x are we holding?
 bne spstr6 skip if so
 tst spcntr,x any characters?
 beq spstr6
 ldy spoptr,x get q pointer
 ldb 0,y+ get character
 cmpy spbfen,x end of q?
 bne spstr2
 ldy spbfst,x reset to beginning
spstr2 sty spoptr,x save pointer
 ldy spacia,x get acia
 stb data,y output the character
 dec spcntr,x dec char count
spstr4 rts return
spstr6 ldy spacia,x get port address
spdisx lda #$28 show finished transmitting
 sta cont,y
 rts


*
* spspc
*
* special routine (like ttyset/ttyget)
*

spspc pshs x save argument
 lbsr spsel point to printer structure
 puls y restore argument
 cmpy #0 doing put or get?
 bne spspc4 branch if get
* put
 ldd usarg2 get hold processing byte in b
 andb #XONXOF clear unnecessary bits
 stb spspcl,x put in proper place
 rts
* get
spspc4 clra -- ldd #0 fake data
 clrb
 std 0,y++
 std 0,y++
 ldb spspcl,x get XON/XOFF flag
 std 0,y
 rts
