ACIA module for Motorola 6850
The ACIA module is responsible for communication with serial (RS-232) devices.
nam ACIA
ttl Interrupt-Driven Acia driver
* Copyright 1982 by Microware Systems Corporation
* Reproduced Under License
* This source code is the proprietary confidential property of
* Microware Systems Corporation, and is provided to licensee
* solely for documentation and educational purposes. Reproduction,
* publication, or distribution in any form to any party other than
* the licensee is strictly prohibited!
use defsfile
***************
* Edition History
* # date Comments
* -- -------- ----------------------------------------------------
* 3 83/02/11 Add X-ON/X-OFF generation code
* 4 83/03/10 Getstat Ready returns (B)=bytecount
Edition equ 4 Current Edition
***************
* Interrupt-driven Acia Device Driver
INPSIZ set 80 input buffer size (<=256)
OUTSIZ set 140 output buffer size (<=256)
IRQReq set %10000000 Interrupt Request
PARITY set %01000000 parity error bit
OVERUN set %00100000 overrun error bit
FRAME set %00010000 framing error bit
NOTCTS set %00001000 not clear to send
DCDLST set %00000100 data carrier lost
IRQIN equ %10000000 input IRQ enable
IRQOUT equ %00100000 output IRQ enable
INPERR set PARITY+OVERUN+FRAME+NOTCTS+DCDLST
**********
* Static storage offsets
*
org V.SCF room for scf variables
INXTI rmb 1 input buffer next-in ptr
INXTO rmb 1 input buffer next-out ptr
INCNT rmb 1 input char count
ONXTI rmb 1 output buffer next-in ptr
ONXTO rmb 1 output buffer next-out ptr
HALTED rmb 1 output IRQ's disabled when non-zero
INHALT rmb 1 input halted
INPBUF rmb INPSIZ input buffer
OUTBUF rmb OUTSIZ output buffer
ACIMEM equ . Total static storage requirement
* HALTED state conditions
H.XOFF equ 1 V.XOFF char has been received; awaiting V.XON
H.EMPTY equ 2 Output buffer is empty
***************
* Module Header
mod ACIEND,ACINAM,DRIVR+OBJCT,REENT+1,ACIENT,ACIMEM
fcb UPDAT.
ACINAM fcs "ACIA"
fcb Edition Current Revision
ACIENT lbra INIT
lbra READ
lbra WRITE
lbra GETSTA
lbra PUTSTA
lbra TRMNAT
ACMASK fcb 0 no flip bits
fcb IRQReq Irq polling mask
fcb 10 (higher) priority
ttl INTERRUPT-DRIVEN Acia device routines
pag
***************
* Init
* Initialize (Terminal) Acia
*
INIT ldx V.PORT,U I/o port address
ldb #$03 master reset signal
stb 0,X reset acia
ldb #H.EMPTY
stb HALTED,U output IRQ's disabled; buffer empty
lda M$OPT,Y option byte count
INIT05 cmpa #PD.PAR-PD.OPT acia control value given?
blo INIT10 ..no; default $15
ldb PD.PAR-PD.OPT+M$DTYP,Y
bne INIT20
INIT10 ldb #$15 default acia control
INIT20 stb V.TYPE,U save device type
stb 0,X init acia
lda 1,X
lda 1,X remove any interrupts
tst 0,X interrupt gone?
bmi ErrNtRdy ..No; abort
clra
clrb
std INXTI,U Initialize buffer ptrs
std ONXTI,U
sta INHALT,U flag input not halted
sta INCNT,U clear in char count
ldd V.PORT,U
leax ACMASK,PCR
leay ACIRQ,PCR address of interrupt service routine
OS9 F$IRQ Add to IRQ polling table
bcs INIT9 Error - return it
ldx V.PORT,U
ldb V.TYPE,U
orb #IRQIN enable acia input interrupts
stb 0,X initialize acia for input interrupts
clrb
INIT9 rts
***************
* Read
* return One Byte of input from the Acia
*
* Passed: (Y)=Path Descriptor
* (U)=Static Storage address
* returns: (A)=input Byte (carry clear)
* or CC=Set, B=Error code if error
*
READ00 bsr ACSLEP
READ lda INHALT,U is input halted?
ble Read.a branch if not
ldb INCNT,U get input character count
cmpb #10 less than 10 chars in buffer?
bhi Read.a branch if not
ldb V.XON,U get X-ON char
orb #Sign set sign bit
stb INHALT,U flag input resume
ldb V.TYPE,U get control value
orb #IRQIN!IRQOUT enable input & output IRQs
stb [V.PORT,U] set control register
Read.a ldb INXTO,U (input buffer) next-out ptr
leax INPBUF,U address of input buffer
orcc #IntMasks calm interrupts
cmpb INXTI,U any data available?
beq READ00
abx
lda 0,X the char
dec INCNT,U decrement char count
incb ADVANCE Next-out ptr
cmpb #INPSIZ-1 end of circular buffer?
bls READ10 ..no
clrb reset ptr to start of buffer
READ10 stb INXTO,U save updated buffer ptr
clrb
ldb V.ERR,U Transmission error?
beq READ90 ..no; return
stb PD.ERR,Y return error bits in pd
clr V.ERR,U
comb return carry set
ldb #E$Read signal read error
READ90 andcc #^IntMasks enable IRQ requests
rts
ErrNtRdy comb
ldb #E$NotRdy
rts
**********
* Acslep - Sleep for I/O activity
* This version Hogs Cpu if signal pending
*
* Passed: (cc)=Irq's Must be disabled
* (U)=Global Storage
* V.Busy,U=current proc id
* Destroys: possibly Pc
ACSLEP pshs D,X
lda V.BUSY,U get current process id
sta V.Wake,U arrange wake up signal
andcc #^IntMasks interrupts ok now
ldx #0
OS9 F$Sleep wait for input data
ldx D.Proc
ldb P$Signal,X signal present?
beq ACSL90 ..no; return
cmpb #S$Intrpt Deadly signal?
bls ACSLER ..yes; return error
ACSL90 clra clear carry
lda P$State,X check process state flags
bita #Condem has process died?
bne ACSLER ..Yes; return error
puls D,X,PC return
ACSLER leas 6,S Exit to caller's caller
coma return carry set
rts
***************
* Write
* Write char Through Acia
*
* Passed: (A)=char to write
* (Y)=Path Descriptor
* (U)=Static Storage address
* returns: CC=Set If Busy (output buffer Full)
*
WRIT00 bsr ACSLEP sleep a bit
WRITE leax OUTBUF,U output buffer address
ldb ONXTI,U (output) next-out ptr
abx
sta 0,X Put char in buffer
incb ADVANCE the ptr
cmpb #OUTSIZ-1 end of circular buffer?
bls WRIT10 ..no
clrb reset ptr to start of buffer
WRIT10 orcc #IntMasks disable interrupts
cmpb ONXTO,U buffer full?
beq WRIT00 ..yes; sleep and retry
stb ONXTI,U save updated next-in ptr
lda HALTED,U output already enabled?
beq Write80 ..yes; don't re-enable
anda #^H.EMPTY no longer halted due to empty
sta HALTED,U
bne Write80 ..Still HALTED; don't enable IRQ
lda V.TYPE,U Parity control
ora #IRQIN!IRQOUT enable input & output IRQs
sta [V.PORT,U] Enable output interrupts
Write80 andcc #^IntMasks enable IRQs
Write90 clrb (return carry clear)
rts
***************
* Getsta/Putsta
* Get/Put Acia Status
*
* Passed: (A)=Status Code
* (Y)=Path Descriptor
* (U)=Static Storage address
* returns: varies
GETSTA cmpa #SS.Ready Ready status?
bne GETS10 ..no
ldb INCNT,U get input character count
beq ErrNtRdy ..No; return not ready error
ldx PD.RGS,Y
stb R$B,X return bytecount to caller (!)
STATUS99 clrb
rts
GETS10 cmpa #SS.EOF End of file?
beq Write90 ..yes; return carry clear
PUTSTA comb return carry set
ldb #E$UnkSvc Unknown service code
rts
***************
* Subroutine TRMNAT
* Terminate Acia processing
*
* Passed: (U)=Static Storage
* returns: Nothing
*
TRMN00 lbsr ACSLEP wait for I/O activity
TRMNAT ldx D.Proc
lda P$ID,X
sta V.BUSY,U
sta V.LPRC,U
ldb ONXTI,U
orcc #IntMasks disable interrupts
cmpb ONXTO,U output done?
bne TRMN00 ..no; sleep a bit
lda V.TYPE,U
sta [V.PORT,U] disable acia interrupts
andcc #^IntMasks enable interrupts
ldx #0
OS9 F$IRQ remove acia from polling tbl
rts
***************
* AcIRQ
* process Interrupt (input or output) from Acia
*
* Passed: (U)=Static Storage addr
* (X)=Port address
* (A)=polled status
* Returns: Nothing
*
ACIRQ ldx V.PORT,U get port address
tfr A,B copy status
andb #INPERR mask status error bits
orb V.ERR,U
stb V.ERR,U update cumulative errors
bita #5 input ready (or carrier lost)?
bne InIRQ ..yes; go get it
* Fall Through to Do output
****************
* OutIRQ
* output to Acia Interrupt Routine
*
* Passed: (A)=Acia Status Register Contents
* (X)=Acia port address
* (U)=Static Storage address
OutIRQ lda INHALT,U send X-ON or X-OFF?
bpl OutI.a branch if not
anda #^Sign clear sign bit
sta 1,X send character
eora V.XON,U get zero if X-ON
sta INHALT,U mark it sent
lda HALTED,U is output halted?
bne OutIRQ3 branch if so
clrb clear carry
rts
OutI.a leay OUTBUF,U output buffer ptr
ldb ONXTO,U (output) next-out ptr
cmpb ONXTI,U output buffer already empty?
beq OutIRQ2 ..yes; disable output IRQ, return
clra
lda D,Y next output char
incb ADVANCE Next-out ptr
cmpb #OUTSIZ-1 end of circular buffer?
bls OutIRQ1 ..no
clrb
OutIRQ1 stb ONXTO,U save updated next-out ptr
sta 1,X Write the char
cmpb ONXTI,U last char in output buffer?
bne WAKEUP ..no
OutIRQ2 lda HALTED,U
ora #H.EMPTY
sta HALTED,U
OutIRQ3 ldb V.TYPE,U
orb #IRQIN disable output IRQs
stb 0,X
WAKEUP ldb #S$Wake Wake up signal
lda V.Wake,U Owner waiting?
Wake10 beq Wake90 ..no; return
clr V.Wake,U
SendSig OS9 F$Send send signal
Wake90 clrb return carry clear
rts
***************
* Inacia
* process Acia input Interrupt
*
* Passed: (A)=Acia Status Register data
* (X)=Acia port address
* (U)=Static Storage address
*
* Notice the Absence of Error Checking Here
*
InIRQ lda 1,X Read input char
beq InIRQ1 ..NULL, impossible Ctl Chr
cmpa V.INTR,U keyboard Interrupt?
beq InAbort ..Yes
cmpa V.QUIT,U keyboard Quit?
beq InQuit ..Yes
cmpa V.PCHR,U keyboard Pause?
beq InPause ..Yes
cmpa V.XON,U X-ON continue?
beq InXON ..Yes
cmpa V.XOFF,U X-OFF Immediate Pause request?
beq InXOFF ..Yes
InIRQ1 leax INPBUF,U input buffer
ldb INXTI,U (input) next-in ptr
abx
sta 0,X save char in buffer
incb update Next-in ptr
cmpb #INPSIZ-1 end of circular buffer?
bls InIRQ2 ..no
clrb
InIRQ2 cmpb INXTO,U input overrun?
bne InIRQ30 ..no; good
ldb #OVERUN mark overrun error
orb V.ERR,U
stb V.ERR,U
bra WAKEUP throw away character
InIRQ30 stb INXTI,U update next-in ptr
inc INCNT,U
InIRQ4 lda V.XOFF,U get X-OFF char
beq WAKEUP branch if not enabled
ldb INCNT,U get input count
cmpb #INPSIZ-10 is buffer almost full?
blo WAKEUP bra if not
ldb INHALT,U have we sent XOFF?
bne WAKEUP yes then don't send it again
anda #^Sign insure sign clear
sta V.XOFF,U
ora #Sign set sign bit
sta INHALT,U flag input halt
ldb V.TYPE,U get control value
orb #IRQIN!IRQOUT enable input & output IRQs
stb [V.PORT,U]
bra WAKEUP
***************
* Control character routines
InPause ldx V.DEV2,U get echo device static ptr
beq InIRQ1 ..None; buffer char, exit
sta V.PAUS,X request pause
bra InIRQ1 buffer char, exit
InAbort ldb #S$Intrpt keyboard INTERRUPT signal
bra InQuit10
InQuit ldb #S$Abort Abort signal
InQuit10 pshs A save input char
lda V.LPRC,U last process id
lbsr Wake10 Send error signal
puls A restore input char
bra InIRQ1 buffer char, exit
InXON lda HALTED,U
anda #^H.XOFF
sta HALTED,U enable output
bne InXON99 ..exit if otherwise disabled
lda V.TYPE,U parity control
ora #IRQIN!IRQOUT enable input & output IRQs
sta 0,X
InXON99 clrb
rts
InXOFF lda HALTED,U
bne InXOFF10 ..already halted, continue
ldb V.TYPE,U get acia control code
orb #IRQIN enable only input IRQs
stb 0,X
InXOFF10 ora #H.XOFF
sta HALTED,U restrict output
clrb
rts
emod Module Crc
ACIEND equ *