view level1/modules/sc6850.asm @ 3277:33d539c123cf

d64: Add mb.ddisk script for making Dragon boot floppy At least it works in XRoar when running off a 80d floppy and preparing a new 40d boot floppy in the second drive. The "format" must be run manually for now since there is not enough memory to run it from inside the script...
author Tormod Volden <debian.tormod@gmail.com>
date Sat, 07 Mar 2020 23:15:05 +0100
parents b1efa6891f4e
children
line wrap: on
line source

********************************************************************
* sc6850 - Motorola 6850 UART Driver
*
* $Id$
*
* Data sheet for 6850 is here:
*     http://www.classiccmp.org/dunfield/r/6850.pdf
*
* Edt/Rev  YYYY/MM/DD  Modified by
* Comment
* ------------------------------------------------------------------
*   1      2017/05/08  Boisy G. Pitre
* Created for Corsham 6809
*

           nam   sc6850
           ttl   Motorola 6850 UART Driver

           ifp1
           use   defsfile
           endc

* miscellaneous definitions
DCDStBit   equ   %00100000      DCD status bit for SS.CDSta call
DSRStBit   equ   %01000000      DSR status bit for SS.CDSta call
SlpBreak   set   TkPerSec/2+1   line Break duration
SlpHngUp   set   TkPerSec/2+1   hang up (drop DTR) duration

* 
* 6850 Register Definitions
*
           org   0
StatReg    rmb   1
CtlReg     equ   StatReg
DataReg    rmb   1

* 6850 Status Register Bit Definitions
Stat.IRQ   equ   %10000000      IRQ occurred
Stat.Par   equ   %01000000      Rx data Parity error
Stat.Ovr   equ   %00100000      Rx data Overrun error
Stat.Frm   equ   %00010000      Rx data Framing error
Stat.CTS   equ   %00001000      Rx data Framing error
Stat.DCD   equ   %00000100      Rx data Framing error
Stat.TxE   equ   %00000010      Tx data register Empty
Stat.RxF   equ   %00000001      Rx data register Full
Stat.Err   equ   Stat.Ovr!Stat.Frm!Stat.Par Status error bits
Stat.Flp   equ   $00            all Status bits active when set
Stat.Msk   equ   Stat.IRQ!Stat.RxF active IRQs

* 6850 Control Register Bit Definitions
Ctl.RxIEn  equ   %10000000      Rx interrupt enable
Ctl.tc1    equ   %01000000      Transmitter control 1
Ctl.tc0    equ   %00100000      Transmitter control 0
Ctl.ws2    equ   %00010000
Ctl.ws1    equ   %00001000
Ctl.ws0    equ   %00000100
Ctl.cds0   equ   %00000001
Ctl.cds1   equ   %00000010
Ctl.BauMsk equ   Ctl.cds0!Ctl.cds1
Ctl.WrdMsk equ   Ctl.ws2!Ctl.ws1|Ctl.ws0
Ctl.TCMsk  equ   Ctl.tc1!Ctl.tc0
Ctl.Reset  equ   Ctl.cds1|Ctl.cds0

* 6850 Bit/Parity/Stop definitions
Ctl.8O1     equ   Ctl.ws2!Ctl.ws1|Ctl.ws0
Ctl.8E1     equ   Ctl.ws2!Ctl.ws1
Ctl.8N1     equ   Ctl.ws2!Ctl.ws0
Ctl.8N2     equ   Ctl.ws2
Ctl.7O1     equ   Ctl.ws1|Ctl.ws0
Ctl.7E1     equ   Ctl.ws1
Ctl.7O2     equ   Ctl.ws0
Ctl.7E2     equ   0

* Command bit definitions
Cmd.TIRB   equ   %00001100      see Tx IRQ/RTS/Break table below
Cmd.DTR    equ   %00000001      DTR output (set=enabled)

* Tx IRQ/RTS/Break table
TIRB.Off   equ   %00000000      RTS & Tx IRQs disabled
TIRB.On    equ   %00000100      RTS & Tx IRQs enabled
TIRB.RTS   equ   %00001000      RTS enabled, Tx IRQs disabled
TIRB.Brk   equ   %00001100      RTS enabled, Tx IRQs disabled, Tx line Break

* V.ERR bit definitions
DCDLstEr   equ   %00100000      DCD lost error
OvrFloEr   equ   %00000100      Rx data overrun or Rx buffer overflow error
FrmingEr   equ   %00000010      Rx data framing error
ParityEr   equ   %00000001      Rx data parity error

* FloCtlRx bit definitions
FCRxSend   equ   %10000000      send flow control character
FCRxSent   equ   %00010000      Rx disabled due to XOFF sent
FCRxDTR    equ   %00000010      Rx disabled due to DTR
FCRxRTS    equ   %00000001      Rx disabled due to RTS

* FloCtlTx bit definitions
FCTxXOff   equ   %10000000      due to XOFF received
FCTxBrk    equ   %00000010      due to currently transmitting Break

* Wrk.Type bit definitions
Parity     equ   %11100000      parity bits
MdmKill    equ   %00010000      modem kill option
RxSwFlow   equ   %00001000      Rx data software (XON/XOFF) flow control
TxSwFlow   equ   %00000100      Tx data software (XON/XOFF) flow control
RTSFlow    equ   %00000010      CTS/RTS hardware flow control
DSRFlow    equ   %00000001      DSR/DTR hardware flow control

* Wrk.XTyp bit definitions
SwpDCDSR   equ   %10000000      swap DCD+DSR bits (valid for 6551 only)
ForceDTR   equ   %01000000      don't drop DTR in term routine
RxBufPag   equ   %00001111      input buffer page count

* static data area definitions
           org   V.SCF          allow for SCF manager data area
Cpy.Stat   rmb   1              Status register copy
CpyDCDSR   rmb   1              DSR+DCD status copy
Mask.DCD   rmb   1              DCD status bit mask (MUST immediately precede Mask.DSR)
Mask.DSR   rmb   1              DSR status bit mask (MUST immediately follow Mask.DCD)
CDSigPID   rmb   1              process ID for CD signal
CDSigSig   rmb   1              CD signal code
FloCtlRx   rmb   1              Rx flow control flags
FloCtlTx   rmb   1              Tx flow control flags
RxBufEnd   rmb   2              end of Rx buffer
RxBufGet   rmb   2              Rx buffer output pointer
RxBufMax   rmb   2              Send XOFF (if enabled) at this point
RxBufMin   rmb   2              Send XON (if XOFF sent) at this point
RxBufPtr   rmb   2              pointer to Rx buffer
RxBufPut   rmb   2              Rx buffer input pointer
RxBufSiz   rmb   2              Rx buffer size
RxDatLen   rmb   2              current length of data in Rx buffer
SigSent    rmb   1              keyboard abort/interrupt signal already sent
SSigPID    rmb   1              SS.SSig process ID
SSigSig    rmb   1              SS.SSig signal code
WritFlag   rmb   1              initial write attempt flag
Wrk.Type   rmb   1              type work byte (MUST immediately precede Wrk.Baud)
Wrk.Baud   rmb   1              baud work byte (MUST immediately follow Wrk.Type)
Wrk.XTyp   rmb   1              extended type work byte

regWbuf    rmb   2              substitute for regW
RxBufDSz   equ   256-.          default Rx buffer gets remainder of page...
RxBuff     rmb   RxBufDSz       default Rx buffer
MemSize    equ   .

rev        set   0
edition    set   1

           mod   ModSize,ModName,Drivr+Objct,ReEnt+rev,ModEntry,MemSize

           fcb   UPDAT.         access mode(s)

ModName    fcs   "sc6850"
           fcb   edition


* These 3 bytes control how the IRQ ISR processes interrupts from this
* device
IRQPckt    equ   *
Pkt.Flip   fcb   Stat.Flp       flip byte
Pkt.Mask   fcb   Stat.Msk       mask byte
           fcb   $0A            priority

* NOTE:  SCFMan has already cleared all device memory except for V.PAGE and
*        V.PORT.  Zero-default variables are:  CDSigPID, CDSigSig, Wrk.XTyp.
* Entry:
* Y = address of the device descriptor
* U = address of the device memory area
*
* Exit:
* CC = carry set on error
* B  = error code
Init 
           pshs  cc,dp          save IRQ/Carry status, system DP 
           IFNE  H6309
           tfr   u,w
           tfr   e,dp
           tfr   y,w            save descriptor pointer
           ELSE
           tfr   u,d            get device memory area
           tfr   a,dp           and make it the direct page
           pshs  y              save descriptor pointer
           ENDC

* Register the ISR
* D address of the device status register
* X address of the "packet" containing the flip/mask/priority
* Y address of the device IRQ service routine
* U address of the device IRQ service routine memory
           ldd   <V.PORT        base hardware address (=status register)

           leax  IRQPckt,pc
           leay  IRQSvc,pc
           os9   F$IRQ

           IFNE  H6309
           tfr   w,y            recover descriptor pointer
           ELSE
           puls  y
           ENDC

           lbcs  ErrExit        failed to register interrupt

DfltInfo   ldd   #RxBufDSz      default Rx buffer size
           leax  RxBuff,u       default Rx buffer address
           std   <RxBufSiz      save Rx buffer size
           stx   <RxBufPtr      save Rx buffer address
           stx   <RxBufGet      set initial Rx buffer input address
           stx   <RxBufPut      set initial Rx buffer output address
           IFNE  H6309
           addr  d,x            point to end of Rx buffer
           ELSE
           leax  d,x
           ENDC
           stx   <RxBufEnd      save Rx buffer end address
           subd  #80            characters available in Rx buffer
           std   <RxBufMax      set auto-XOFF threshold
           ldd   #10            characters remaining in Rx buffer
           std   <RxBufMin      set auto-XON threshold after auto-XOFF
           ldb   #TIRB.RTS      default command register

 * setup 6850
           ldx   <V.PORT        get port address
           orcc  #IntMasks      disable IRQs while setting up hardware
           lda   #Ctl.Reset
           sta   CtlReg,x       master reset the 6850
           lda   #Ctl.RxIEn!Ctl.8N2!Ctl.cds0  turn on Rx interrupts, default to 8N2, divide-by-1 mode
           sta   CtlReg,x

           sta   <Cpy.Stat      save Status copy
*           tfr   a,b            copy it...
*           eora  Pkt.Flip,pc    flip bits per D.Poll
*           anda  Pkt.Mask,pc    any IRQ(s) still pending?

* [NAC HACK 2015Sep13] the UART model in exec09 cannot flag rx char available
* so this test will always fail. Even if I could get the i/o there to be non-
* blocking I still can't work out how I could get the UART status register to
* behave correctly.. it would need to support type-ahead.
*           lbne  NRdyErr        yes, go report error... (device not plugged in?)

           puls  cc,dp,pc       recover IRQ/Carry status, system DP, return

*
*
Term       clrb                 default to no error...
           pshs  cc,dp          save IRQ/Carry status, dummy B, system DP
           IFNE  H6309
           tfr   u,w            setup our DP
           tfr   e,dp
           ELSE
           tfr   u,d
           tfr   a,dp
           ENDC
           IFEQ  Level-1
           ldx   >D.Proc
           lda   P$ID,x
           sta   <V.BUSY
           sta   <V.LPRC
           ENDC
           ldx   <V.PORT
           lda   0,x            get current status

           ldd   <RxBufSiz      get Rx buffer size
           tsta                 less than 256 bytes?
           beq   TermExit       yes, no system memory to return...
           pshs  u              save data pointer
           ldu   <RxBufPtr      get address of system memory
           os9   F$SRtMem
           puls  u              recover data pointer
TermExit
           ldd   <V.PORT        base hardware address is status register

           ldx   #$0000         remove IRQ table entry
           leay  IRQSvc,pc
           puls  cc             recover IRQ/Carry status
           os9   F$IRQ
           puls  dp,pc          restore dummy A, system DP, return

ReadSlp
           IFEQ  Level-1
           lda   <V.BUSY
           sta   <V.WAKE
           lbsr  Sleep0         go suspend process...
           ELSE
           ldd   >D.Proc        process descriptor address
           sta   <V.WAKE        save MSB for IRQ service routine
           tfr   d,x            copy process descriptor address
           IFNE  H6309
           oim   #Suspend,P$State,x
           ELSE
           ldb   P$State,x
           orb   #Suspend
           stb   P$State,x
           ENDC
           lbsr  Sleep1         go suspend process...
           ENDC
           ldx   >D.Proc        process descriptor address
           ldb   P$Signal,x     pending signal for this process?
           beq   ChkState       no, go check process state...
           cmpb  #S$Intrpt      do we honor signal?
           lbls  ErrExit        yes, go do it...
ChkState   equ   *
           IFNE  H6309
           tim   #Condem,P$State,x
           ELSE
           ldb   P$State,x
           bitb  #Condem
           ENDC
           bne   PrAbtErr       yes, go do it...
           ldb   <V.WAKE        true interrupt?
           beq   ReadChk        yes, go read the char.
           bra   ReadSlp        no, go suspend the process

*
* Input	U = Address of device static data storage
*	Y = Address of path descriptor module
*
* Output
*	A = Character read
*	CC = carry set on error, clear on none
*	B = error code if CC.C set.
*
Read       clrb                 default to no errors...
           pshs  cc,dp          save IRQ/Carry status, system DP
           IFNE  H6309
           tfr   u,w            setup our DP
           tfr   e,dp
           ELSE
           tfr   u,d
           tfr   a,dp
           ENDC
ReadLoop   orcc  #IntMasks      disable IRQs while checking Rx flow control
ReadChk    lda   <FloCtlRx      get Rx flow control flags
           beq   ReadChar       none, go get Rx character...
           ldx   <RxDatLen      get Rx data count again
           cmpx  <RxBufMin      at or below XON level?
           bhi   ReadChar       no, go get Rx character...
           ldx   <V.PORT
           bita  #FCRxSent      Rx disabled due to XOFF sent?
           beq   ChkHWHS        no, go check hardware handshake(s)...
           ldb   <FloCtlTx      get Tx flow control flags
           bitb  #FCTxBrk       currently transmitting line Break?
           beq   NotTxBrk       yes, go skip XON this time...
ReadLp2    andcc #^IntMasks     turn interupts back on
           bra   ReadLoop
NotTxBrk   equ   *
           IFNE  H6309
           tim   #Stat.TxE,StatReg,x
           ELSE
           pshs  a
           lda   StatReg,x
           bita  #Stat.TxE
           puls  a
           ENDC
           beq   ReadLp2        no, go skip XON this time...
           ldb   <V.XON
           stb   DataReg,x      write XON character
ChkHWHS    bita  #FCRxDTR!FCRxRTS Rx disabled due to DTR or RTS?
           beq   RxFloClr       no, go clear Rx flow control flag(s)...
RxFloClr   clr   <FloCtlRx      clear Rx flow control flags
ReadChar   ldb   <V.ERR         get accumulated errors, if any
           stb   PD.ERR,y       set/clear error(s) in path descriptor
           bne   ReprtErr       error(s), go report it/them...
           ldd   <RxDatLen      get Rx buffer count
           beq   ReadSlp        none, go sleep while waiting for new Rx data...
           IFNE  H6309
           decd                 less character we're about to grab
           ELSE
           subd  #$0001
           ENDC
           std   <RxDatLen      save new Rx data count
           orcc  #IntMasks  see if this fixes the problem
           ldx   <RxBufGet      current Rx buffer pickup position
           lda   ,x+            get Rx character, set up next pickup position
           cmpx  <RxBufEnd      end of Rx buffer?
           blo   SetPckUp       no, go keep pickup pointer
           ldx   <RxBufPtr      get Rx buffer start address
SetPckUp   stx   <RxBufGet      set new Rx data pickup pointer
           puls  cc,dp,pc       recover IRQ/Carry status, dummy B, system DP, return

*
* Module jump table
*
ModEntry   lbra  Init
           bra   Read
           nop
           bra   Write
           nop
           IFNE  H6309
           bra   GStt
           nop
           ELSE
           lbra  GStt
           ENDC
           lbra  SStt
           lbra  Term

PrAbtErr   ldb   #E$PrcAbt
           bra   ErrExit

ReprtErr   clr   <V.ERR         clear error status
           bitb  #DCDLstEr      DCD lost error?
           bne   HngUpErr       yes, go report it...
           ldb   #E$Read

* come here with cc, dp, pc stacked.
* set carry in the stacked copy of cc and return.
ErrExit    equ  *
           IFNE  H6309
           oim   #Carry,,s      set carry
           ELSE
           lda   ,s
           ora   #Carry
           sta   ,s
           ENDC
           puls  cc,dp,pc       restore CC, system DP, return

HngUpErr   ldb   #E$HangUp
           lda   #PST.DCD       DCD lost flag
           sta   PD.PST,y       set path status flag
           bra   ErrExit

NRdyErr    ldb   #E$NotRdy
           bra   ErrExit

UnSvcErr   ldb   #E$UnkSvc
           bra   ErrExit

*
*
Write
           pshs  cc,dp          save IRQ/Carry status, Tx character, system DP
           IFNE  H6309
           tfr   u,w            setup our DP
           tfr   e,dp
           tfr   a,e
           ELSE
           pshs  a
           tfr   u,d
           tfr   a,dp
           puls  a
           sta   <regWbuf
           ENDC
           orcc  #IntMasks      disable IRQs during error and Tx disable checks
           bra   WritChr
WritLoop   lda   <WritFlag
           beq   WritFast
           lbsr  Sleep1
WritFast   inc   <WritFlag
WritChr    ldx   <V.PORT
           ldb   <V.ERR         get accumulated errors, if any
           andb  #DCDLstEr      DCD lost error? (ignore other errors, if any)
           stb   PD.ERR,y       set/clear error(s) in path descriptor
           bne   ReprtErr       DCD lost error, go report it...
ChkTxFlo   ldb   <FloCtlTx      get Tx flow control flags
           bitb  #FCTxBrk       currently transmitting line Break?
           bne   WritLoop       yes, go sleep a while...
           lda   <Wrk.Type      get software/hardware handshake enables
           bita  #DSRFlow       DSR/DTR handshake enabled?
* Changed below - BGP
*           beq   ChkTxFlo       no, go check Tx flow control
           beq   ChkRxFlo       no, go check Rx flow control
           ldb   <Cpy.Stat      get copy of status register
           bitb  <Mask.DSR      Tx disabled due to DSR?
           bne   WritLoop       yes, go sleep a while...
           bita  #TxSwFlow      Tx software flow control enabled?
           beq   ChkRxFlo       no, go check pending Rx flow control
           bitb  #FCTxXOff      Tx disabled due to received XOFF?
           bne   WritLoop       yes, go sleep a while...
ChkRxFlo   bita  #RxSwFlow      Rx software flow control enabled?
           beq   ChkTxE         no, go check Tx register empty
           ldb   <FloCtlRx      get Rx flow control flags
           bitb  #FCRxSend      XON/XOFF Rx flow control pending?
           bne   WritLoop       yes, go sleep a while...
ChkTxE     equ   *
           IFNE  H6309
           tim   #Stat.TxE,StatReg,x
           ELSE
           pshs  a
           lda   StatReg,x
           bita  #Stat.TxE
           puls  a
           ENDC
           beq   WritLoop       no, go sleep a while...
           IFNE  H6309
           ste   DataReg,x      write Tx character
           ELSE
           ldb   <regWbuf
           stb   DataReg,x
           ENDC
           clr   <WritFlag      clear "initial write attempt" flag
           puls  cc,dp,pc       recover IRQ/Carry status, Tx character, system DP, return


GStt       clrb                 default to no error...
           pshs  cc,dp          save IRQ/Carry status, dummy B, system DP
           IFNE  H6309
           tfr   u,w            setup our DP
           tfr   e,dp
           ELSE
           pshs  a
           tfr   u,d
           tfr   a,dp
           puls  a
           ENDC
           ldx   PD.RGS,y       caller's register stack pointer
           cmpa  #SS.EOF
           beq   GSExitOK       yes, SCF devices never return EOF
           cmpa  #SS.Ready
           bne   GetScSiz
           ldd   <RxDatLen      get Rx data length
           lbeq   NRdyErr        none, go report error
           tsta                 more than 255 bytes?
           beq   SaveLen        no, keep Rx data available
           ldb   #255           yes, just use 255
SaveLen    stb   R$B,x          set Rx data available in caller's [B]
GSExitOK   puls  cc,dp,pc       restore Carry status, dummy B, system DP, return

GetScSiz   cmpa  #SS.ScSiz
           bne   GetComSt
           ldu   PD.DEV,y
           ldu   V$DESC,u
           clra
           ldb   IT.COL,u
           std   R$X,x
           ldb   IT.ROW,u
           std   R$Y,x
           puls  cc,dp,pc       restore Carry status, dummy B, system DP, return

GetComSt   cmpa  #SS.ComSt
           lbne  UnSvcErr       no, go report error
           ldd   <Wrk.Type
           std   R$Y,x
           clra                 default to DCD and DSR enabled
           ldb   <CpyDCDSR
           bitb  #Mask.DCD
           beq   CheckDSR       no, go check DSR status
           ora   #DCDStBit
CheckDSR   bitb  <Mask.DSR      DSR bit set (disabled)?
           beq   SaveCDSt       no, go set DCD/DSR status
           ora   #DSRStBit
SaveCDSt   sta   R$B,x          set 6551 ACIA style DCD/DSR status in caller's [B]
           puls  cc,dp,pc       restore Carry status, dummy B, system DP, return

BreakSlp   ldx   #SlpBreak      SS.Break duration
           bra   TimedSlp

HngUpSlp   ldx   #SlpHngUp      SS.HngUp duration
           bra   TimedSlp

           IFEQ  Level-1
Sleep0     ldx   #$0000
           bra   TimedSlp
           ENDC
Sleep1     ldx   #1             give up balance of tick
TimedSlp   pshs  cc             save IRQ enable status
           andcc #^Intmasks     enable IRQs
           os9   F$Sleep
           puls  cc,pc          restore IRQ enable status, return

SStt       clrb                 default to no error...
           pshs  cc,dp          save IRQ/Carry status, dummy B, system DP
           IFNE  H6309
           tfr   u,w            setup our DP
           tfr   e,dp
           ELSE
           pshs  a
           tfr   u,d
           tfr   a,dp
           puls  a
           ENDC
           ldx   PD.RGS,y
           cmpa  #SS.HngUp
           bne   SetBreak
           puls  cc,dp,pc       restore IRQ/Carry status, dummy B, system DP, return

SetBreak   cmpa  #SS.Break      Tx line break?
           bne   SetSSig
           puls  cc,dp,pc       restore IRQ/Carry status, dummy B, system DP, return

SetSSig    cmpa  #SS.SSig
           bne   SetRelea
           lda   PD.CPR,y       current process ID
           ldb   R$X+1,x        LSB of [X] is signal code
           orcc  #IntMasks      disable IRQs while checking Rx data length
           ldx   <RxDatLen
           bne   RSendSig
           std   <SSigPID
           puls  cc,dp,pc       restore IRQ/Carry status, dummy B, system DP, return
RSendSig   puls  cc             restore IRQ/Carry status
           os9   F$Send
           puls  dp,pc          restore system DP, return

SetRelea   cmpa  #SS.Relea
           bne   SetCDSig
           leax  SSigPID,u      point to Rx data signal process ID
           bsr   ReleaSig       go release signal...
           puls  cc,dp,pc       restore Carry status, dummy B, system DP, return

SetCDSig   cmpa  #SS.CDSig      set DCD signal?
           bne   SetCDRel
           lda   PD.CPR,y       current process ID
           ldb   R$X+1,x        LSB of [X] is signal code
           std   <CDSigPID
           puls  cc,dp,pc       restore Carry status, dummy B, system DP, return

SetCDRel   cmpa  #SS.CDRel      release DCD signal?
           bne   SetComSt
CDRelSig   leax  CDSigPID,u     point to DCD signal process ID
           bsr   ReleaSig       go release signal...
           puls  cc,dp,pc       restore Carry status, dummy B, system DP, return

SetComSt   cmpa  #SS.ComSt
           bne   SetOpen
           ldd   R$Y,x          caller's [Y] contains ACIAPAK format type/baud info
           bsr   SetPort        go save it and set up control/format registers
ReturnOK   puls  cc,dp,pc       restore Carry status, dummy B, system DP, return

SetPort    pshs  cc             save IRQ enable and Carry status
           orcc  #IntMasks      disable IRQs while setting up ACIA registers
           std   <Wrk.Type      save type/baud in data area
	anda	#PARMASK
	
*           leax  BaudTabl,pc
*           andb  #BaudRate      clear all but baud rate bits
*           ldb   b,x            get baud rate setting
*           IFNE  H6309
*           tfr   b,e            save it temporarily
*           ELSE
*           stb   <regWbuf
*           ENDC
*           ldb   <Wrk.Baud      get baud info again
*           andb  #^(Ctl.RxCS!Ctl.Baud) clear clock source + baud rate code bits
*           IFNE  H6309
*           orr   e,b            mask in clock source + baud rate and clean up stack
*           ELSE
*           orb   <regWbuf
*           ENDC
*           ldx   <V.PORT        get port address
*           anda  #Cmd.Par       clear all except parity bits
*           IFNE  H6309
*           tfr   a,e            save new command register contents temporarily
*           ELSE
*           sta   <regWbuf
*           ENDC
*           lda   CmdReg,x       get current command register contents
*           anda  #^Cmd.Par      clear parity control bits
*           IFNE  H6309
*           orr   e,a            mask in new parity
*           ELSE
*           ora   <regWbuf
*           ENDC
*           std   CmdReg,x       set command+control registers
           puls  cc,pc          recover IRQ enable and Carry status, return...

SetOpen    cmpa  #SS.Open
           bne   SetClose
           lda   R$Y+1,x        get LSB of caller's [Y]
           deca                 real SS.Open from SCF? (SCF sets LSB of [Y] = 1)
           bne   ReturnOK       no, go do nothing but return OK...
           puls  cc,dp,pc 

SetClose   cmpa  #SS.Close
           lbne  UnSvcErr       no, go report error...
           lda   R$Y+1,x        real SS.Close from SCF? (SCF sets LSB of [Y] = 0)
           bne   ReturnOK       no, go do nothing but return OK...
           leax  SSigPID,u      point to Rx data signal process ID
           bsr   ReleaSig       go release signal...
           bra   CDRelSig       go release DCD signal, return from there...

ReleaSig   pshs  cc             save IRQ enable status
           orcc  #IntMasks      disable IRQs while releasing signal
           lda   PD.CPR,y       get current process ID
           suba  ,x             same as signal process ID?
           bne   NoReleas       no, go return...
           sta   ,x             clear this signal's process ID
NoReleas   puls  cc,pc          restore IRQ enable status, return


* Interrupt service routine
IRQSvc
           pshs  dp             save system DP
           IFNE  H6309
           tfr   u,w            setup our DP
           tfr   e,dp
           ELSE
           tfr   u,d            setup our DP
           tfr   a,dp
           ENDC

           ldx   <V.PORT
           ldb   StatReg,x      get current Status register contents
           stb   <Cpy.Stat      save Status register copy
           bitb  #Stat.Err      error(s)?
           beq   ChkRDRF        no, go check Rx data
* Error-handling
           tst   DataReg,x      read Rx data register to clear ACIA error flags
           bitb  #Stat.Frm      framing error (assume Rx line Break)?
           beq   ChkParty       no, go check if parity error...
           lda   <V.QUIT        default to keyboard quit ("Break") code
           bra   RxBreak        go pretend we've received V.QUIT character...

ChkParty   bitb  #Stat.Par      parity error?
           beq   ChkOvRun       no, go check overrun error...
           lda   #ParityEr      mark parity error
ChkOvRun   bita  #Stat.Ovr      overrun error?
           beq   SaveErrs       no, go save errors...
           ora   #OvrFloEr      mark overrun error
SaveErrs   ora   <V.ERR
           sta   <V.ERR
           lbra  ChkTrDCD       go check if DCD transition...

* Read data?
ChkRDRF    bitb  #Stat.RxF      Rx data?
           lbeq  ChkTrDCD       no, go check DCD transition
           lda   DataReg,x      get Rx data
RxBreak    beq   SavRxDat       its a null, go save it...
           clr   <SigSent
           cmpa  <V.INTR        interrupt?
           bne   Chk.Quit       no, go on...
           ldb   #S$Intrpt
           bra   SendSig

Chk.Quit   cmpa  <V.QUIT        abort?
           bne   Chk.PChr       no, go on...
           ldb   #S$Abort
SendSig    pshs  a              save Rx data
           lda   <V.LPRC        get last process' ID
           os9   F$Send
           puls  a              recover Rx data
           stb   <SigSent       set signal sent flag
           bra   SavRxDat       go save Rx data...

Chk.PChr   cmpa  <V.PCHR        pause?
           bne   Chk.Flow       no, go on...
           ldx   <V.DEV2        attached device defined?
           beq   SavRxDat       no, go save Rx data...
           sta   V.PAUS,x       yes, pause attached device
           bra   SavRxDat       go save Rx data...

Chk.Flow   equ   *
           IFNE  H6309
           tim   #TxSwFlow,<Wrk.Type Tx data software flow control enabled?
           ELSE
           pshs  a
           lda   #TxSwFlow
           bita  <Wrk.Type
           puls  a
           ENDC
           beq   SavRxDat       no, go save Rx data...
           cmpa  <V.XON         XON?
           bne   Chk.XOff       no, go on...
           IFNE  H6309
           aim   #^FCTxXOff,<FloCtlTx clear XOFF received bit
           ELSE
           pshs  a
           lda   #^FCTxXOff
           anda  <FloCtlTx
           sta   <FloCtlTx
           puls  a
           ENDC
           bra   SetTxFlo       go save new Tx flow control flags...

Chk.XOff   cmpa  <V.XOFF        XOFF?
           bne   SavRxDat       no, go save Rx data...
           ldb   #FCTxXOff      set XOFF received bit
           orb   <FloCtlTx      set software Tx flow control flag
SetTxFlo   stb   <FloCtlTx      save new Tx flow control flags
           lbra  ChkTrDCD       go check DCD transition...
SavRxDat   equ   *
           IFNE  H6309
           aim   #^FCRxSend,<FloCtlRx clear possible pending XOFF flag
           ELSE
           pshs  a
           lda   #^FCRxSend
           anda  <FloCtlRx
           sta   <FloCtlRx
           puls  a
           ENDC
           ldx   <RxBufPut      get Rx buffer input pointer
           IFNE  H6309
           ldw   <RxDatLen      Rx get Rx buffer data length
           cmpw  <RxBufSiz      Rx buffer already full?
           ELSE
           pshs  d
           ldd   <RxDatLen
           std   <regWbuf
           cmpd  <RxBufSiz
           puls  d
           ENDC
           blo   NotOvFlo       no, go skip overflow error...
           IFNE  H6309
           oim   #OvrFloEr,<V.ERR mark RX buffer overflow error
           ELSE
           ldb   #OvrFloEr
           orb   <V.ERR
           stb   <V.ERR
           ENDC
           bra   DisRxFlo       go ensure Rx is disabled (if possible)

NotOvFlo   sta   ,x+            save Rx data
           cmpx  <RxBufEnd      end of Rx buffer?
           blo   SetLayDn       no, go keep laydown pointer
           ldx   <RxBufPtr      get Rx buffer start address
SetLayDn   stx   <RxBufPut      set new Rx data laydown pointer
           IFNE  H6309
           incw                 one more byte in Rx buffer
           stw   <RxDatLen      save new Rx data length
           cmpw  <RxBufMax      at or past maximum fill point?
           ELSE
           pshs  d
           ldd   <regWbuf
           addd  #1
           std   <regWbuf
           std   <RxDatLen
           cmpd  <RxBufMax
           puls  d
           ENDC
           blo   SgnlRxD        no, go check Rx data signal...
DisRxFlo   ldx   <V.PORT
*           ldb   CmdReg,x       get current Command register contents
           IFNE  H6309
           tim   #ForceDTR,<Wrk.XTyp forced DTR?
           ELSE
           lda   #ForceDTR
           bita  <Wrk.XTyp
           ENDC
           bne   DisRxRTS       yes, go check RTS disable...
           IFNE  H6309
           tim   #DSRFlow,<Wrk.Type DSR/DTR Flow control?
           ELSE
           lda   #DSRFlow
           bita  <Wrk.Type
           ENDC
           beq   DisRxRTS       no, go check RTS disable
           IFNE  H6309
           oim   #FCRxDTR,<Wrk.Type mark RX disabled due to DTR
           ELSE
           lda   #FCRxDTR
           ora   <Wrk.Type
           sta   <Wrk.Type
           ENDC
           andb  #^Cmd.DTR      clear (disable) DTR bit
DisRxRTS   equ   *
           IFNE  H6309
           tim   #RTSFlow,<Wrk.Type
           ELSE
           lda   #RTSFlow
           bita  <Wrk.Type
           ENDC
           beq   NewRxFlo       no, go set new Rx flow control...
           IFNE  H6309
           tim   #DSRFlow,<Wrk.Type line break?
           ELSE
           lda   #DSRFlow
           bita  <Wrk.Type
           ENDC
           bne   NewRxFlo       yes, go set new Rx flow control...
           IFNE  H6309
           oim   #FCRxRTS,<FloCtlRx
           ELSE
           lda   #FCRxRTS
           ora   <FloCtlRx
           sta   <FloCtlRx
           ENDC
           andb  #^Cmd.TIRB     clear Tx IRQ/RTS/Break control bits (disable RTS)
NewRxFlo
*           stb   CmdReg,x       set/clear DTR and RTS in Command register
           IFNE  H6309
           tim   #RxSwFlow,<Wrk.Type Rx software flow control?
           ELSE
           ldb   <Wrk.Type
           bitb  #RxSwFlow
           ENDC
           beq   SgnlRxD        no, go check Rx data signal...
           lda   <V.XOFF        XOFF character defined?
           beq   SgnlRxD        no, go check Rx data signal...
           ldb   <FloCtlRx      get Rx flow control flags
           bitb  #FCRxSent      XOFF already sent?
           bne   SgnlRxD        yes, go check Rx data signal...
           orb   #FCRxSend      set send XOFF flag
           stb   <FloCtlRx      set new Rx flow control flags
           IFNE  H6309
           tim   #Stat.TxE,StatReg,x
           ELSE
           ldb   StatReg,x
           bitb  #Stat.TxE
           ENDC
           beq   SgnlRxD        no, go skip XOFF this time...
           sta   DataReg,x      write XOFF character
           ldb   #FCRxSent      set XOFF sent flag
           orb   <FloCtlRx      mask in current Rx flow control flags
           andb  #^FCRxSend     clear send XOFF flag
           stb   <FloCtlRx      save new flow control flags
SgnlRxD    ldb   <SigSent       already sent abort/interrupt signal?
           bne   ChkTrDCD       yes, go check DCD transition...
           lda   <SSigPID       Rx data signal process ID?
           beq   ChkTrDCD       none, go check DCD transition...
           stb   <SSigPID       clear Rx data signal
           ldb   <SSigSig       Rx data signal code
           os9   F$Send
ChkTrDCD   ldx   <V.PORT
           lda   <Cpy.Stat      get Status register copy
           tfr   a,b            copy it...
           eora  <CpyDCDSR      mark changes from old DSR+DCD status copy
*           andb  #Stat.DSR!Stat.DCD clear all but DSR+DCD status
           stb   <CpyDCDSR      save new DSR+DCD status copy
           bita  <Mask.DCD      DCD transition?
           beq   CkSuspnd       no, go check for suspended process...
           bitb  <Mask.DCD      DCD disabled now?
           beq   SgnlDCD        no, go check DCD signal...
           lda   <Wrk.Type
           bita  #MdmKill       modem kill enabled?
           beq   SgnlDCD        no, go on...
           ldx   <V.PDLHd       path descriptor list header
           beq   StCDLost       no list, go set DCD lost error...
           lda   #PST.DCD       DCD lost flag
PDListLp   sta   PD.PST,x       set path status flag
           ldx   PD.PLP,x       get next path descriptor in list
           bne   PDListLp       not end of list, go do another...
StCDLost   lda   #DCDLstEr      DCD lost error flag
           ora   <V.ERR
           sta   <V.ERR
SgnlDCD    lda   <CDSigPID      get process ID, send a DCD signal?
           beq   CkSuspnd       no, go check for suspended process...
           ldb   <CDSigSig      get DCD signal code
           clr   <CDSigPID      clear DCD signal
           os9   F$Send

CkSuspnd   clrb                 clear Carry (for exit) and LSB of process descriptor address
           lda   <V.WAKE        anybody waiting? ([D]=process descriptor address)
           beq   IRQExit        no, go return...
           IFEQ  Level-1
           clr   <V.WAKE
           ldb   #S$Wake
           os9   F$Send
           ELSE
           stb   <V.WAKE        mark I/O done
           tfr   d,x            copy process descriptor pointer
           lda   P$State,x      get state flags
           anda  #^Suspend      clear suspend state
           sta   P$State,x      save state flags
           ENDC
IRQExit    puls  dp,pc          recover system DP, return...

           emod
ModSize    equ   *
           end