Mercurial > hg > Members > kono > nitros9-code
changeset 1966:4de571b41659
Added lots of comments should now compile and work.
author | afra |
---|---|
date | Wed, 04 Jan 2006 14:25:28 +0000 |
parents | 7d14b2ce38c4 |
children | 1cb1a5c389cc |
files | level1/modules/sc6551dragon.asm |
diffstat | 1 files changed, 657 insertions(+), 371 deletions(-) [+] |
line wrap: on
line diff
--- a/level1/modules/sc6551dragon.asm Wed Jan 04 14:24:43 2006 +0000 +++ b/level1/modules/sc6551dragon.asm Wed Jan 04 14:25:28 2006 +0000 @@ -1,384 +1,670 @@ -******************************************************************** -* ACIA51 - Serial port device driver +* +* Dragon 64/Alpha 6551 serial port driver +* +* Disassembled 2005/04/25 00:12:02 by Disasm v1.5 (C) 1988 by RML +* +* The Dragon 64 and Dragon Alpha have a hardware serial port driven +* by a Rockwell 6551, mapped from $FF04-$FF07. * -* $Id$ +* Communication between the read/write routines and the ACIA, is buffered +* using a pair of ring buffers, when disassembling labels have been assigned +* so that bytes are placed into the Rx/Tx queue Tail, and removed from the +* head. When the queues become full the calling process is put to sleep +* while it awiaits Rx/Tx from the remote device. +* +* 2005-05-01, P.Harvey-Smith. +* Initial disassembly. +* +* 2005-10-24, P.Harvey-Smith. +* Code clean up/commenting. * -* Edt/Rev YYYY/MM/DD Modified by -* Comment -* ------------------------------------------------------------------ -* 4 1985/??/?? -* From Dragon OS-9 Level One VR 02.00.00 + + nam ACIA51 + ttl os9 device driver + + ifp1 + use defsfile.dragon + endc + +* Following definitions borrowed from sc6551.asm + +* Status bit definitions +Stat.IRQ equ %10000000 IRQ occurred +Stat.DSR equ %01000000 DSR level (clear = active) +Stat.DCD equ %00100000 DCD level (clear = active) +Stat.TxE equ %00010000 Tx data register Empty +Stat.RxF equ %00001000 Rx data register Full +Stat.Ovr equ %00000100 Rx data Overrun error +Stat.Frm equ %00000010 Rx data Framing error +Stat.Par equ %00000001 Rx data Parity error + +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 + +* Control bit definitions +Ctl.Stop equ %10000000 stop bits (set=two, clear=one) +Ctl.DBit equ %01100000 see data bit table below +Ctl.RxCS equ %00010000 Rx clock source (set=baud rate, clear=external) +Ctl.Baud equ %00001111 see baud rate table below + +* data bit table +DB.8 equ %00000000 eight data bits per character +DB.7 equ %00100000 seven data bits per character +DB.6 equ %01000000 six data bits per character +DB.5 equ %01100000 five data bits per character + +* baud rate table + org $00 +BR.ExClk rmb 1 16x external clock (not supported) + org $11 +BR.00050 rmb 1 50 baud (not supported) +BR.00075 rmb 1 75 baud (not supported) +BR.00110 rmb 1 109.92 baud +BR.00135 rmb 1 134.58 baud (not supported) +BR.00150 rmb 1 150 baud (not supported) +BR.00300 rmb 1 300 baud +BR.00600 rmb 1 600 baud +BR.01200 rmb 1 1200 baud +BR.01800 rmb 1 1800 baud (not supported) +BR.02400 rmb 1 2400 baud +BR.03600 rmb 1 3600 baud (not supported) +BR.04800 rmb 1 4800 baud +BR.07200 rmb 1 7200 baud (not supported) +BR.09600 rmb 1 9600 baud +BR.19200 rmb 1 19200 baud - nam ACIA51 - ttl Serial port device driver +* Command bit definitions +Cmd.Par equ %11100000 see parity table below +Cmd.Echo equ %00010000 local echo (set=activated) +Cmd.TIRB equ %00001100 see Tx IRQ/RTS/Break table below +Cmd.RxI equ %00000010 Rx IRQ (set=disabled) +Cmd.DTR equ %00000001 DTR output (set=enabled) + +* parity table +Par.None equ %00000000 +Par.Odd equ %00100000 +Par.Even equ %01100000 +Par.Mark equ %10100000 +Par.Spac equ %11100000 -* Disassembled 02/04/21 22:37:41 by Disasm v1.6 (C) 1988 by RML +* 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 - IFP1 - use defsfile - ENDC +* 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.Baud bit definitions +StopBits equ %10000000 number of stop bits code +WordLen equ %01100000 word length code +BaudRate equ %00001111 baud rate code + +* 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 + +* End of borrowed stuff :) + +tylg set Drivr+Objct +atrv set ReEnt+rev +rev set $01 + mod eom,name,tylg,atrv,start,size -tylg set Drivr+Objct -atrv set ReEnt+rev -rev set $00 -edition set $04 +RxQueueTailOffset rmb 1 ; Tail of Rx queue, Rx inturrupt inserts here +RxQueueHeadOffset rmb 1 ; Head of Rx queue, read call fetches from here +u001F rmb 1 +TxQueueTailOffset rmb 1 ; Tail of Tx queue, write call inserts here +TxQueueHeadOffset rmb 1 ; Head of Tx queue, Tx inturrupt fetches here +u0022 rmb 1 +u0023 rmb 1 ; something to do with XON/XOFF +u0024 rmb 2 +SavedDSRDCD rmb 1 ; Saved DSR and DCD ststus +RxQueue rmb 80 ; Rx Queue +RxQueueLen EQU *-RxQueue ; Rx queue length + +TxQueue rmb 140 ; Tx Queue +TxQueueLen EQU *-TxQueue ; Tx Queue length - mod eom,name,tylg,atrv,start,size +size equ . + + fcb $03 + +name equ * + fcs /ACIA51/ + fcb $04 + +start equ * -u0000 rmb 1 -u0001 rmb 2 -u0003 rmb 1 -u0004 rmb 1 -u0005 rmb 1 -u0006 rmb 3 -u0009 rmb 2 -u000B rmb 1 -u000C rmb 1 -u000D rmb 1 -u000E rmb 1 -u000F rmb 1 -u0010 rmb 13 -u001D rmb 1 -u001E rmb 1 -u001F rmb 1 -u0020 rmb 1 -u0021 rmb 1 -u0022 rmb 1 -u0023 rmb 1 -u0024 rmb 2 -u0026 rmb 1 -u0027 rmb 36 -u004B rmb 44 -u0077 rmb 9 -u0080 rmb 46 -u00AE rmb 85 -size equ . + lbra Init + lbra Read + lbra Write + lbra GetSta + lbra SetSta + lbra Term + +IRQPkt + FCB $00 ; Normal bits (flip byte) + FCB $80 ; Bit 1 is interrupt request flag (Mask byte) + FCB $0A ; Priority byte + + +* Init +* +* Entry: +* Y = address of device descriptor +* U = address of device memory area +* +* Exit: +* CC = carry set on error +* B = error code +* + +Init LDX V.PORT,U ; 1,U Get port address $FF04 + stb AciaStat,x ; Write to status reg, this resets ACIA + ldb #$02 + stb <u0022,u + ldd <IT.PAR,y ; Get parity & baud rate <$26,y + + andb #$0F + leax <BaudRateTable,pcr ; Calculate baud rate values for Acia + ldb b,x + + anda #$F0 + sta V.TYPE,u ; Save parity bits for later use + ldx V.PORT,u ; Get port address $FF04 + std AciaCmd,x ; Setup Command (A), Control (B,Baud rates). + lda ,x + lda ,x + tst AciaStat,x ; Get status + lbmi ErrorExit ; Error if int occoured + + clra ; Init some static storage + clrb + std <RxQueueTailOffset,u ; Init Rx queue + std <TxQueueTailOffset,u ; Init Tx queue + sta <u0023,u + sta <u001F,u + std <u0024,u + + ldd V.PORT,u ; Get port address $FF04 + addd #$0001 ; Setup V$IRQ on status reg changes + leax >IRQPkt,pcr ; Point to packet + leay >IRQService,pcr ; Point to handler + os9 F$IRQ ; Install it ! + bcs InitExit ; Error : Exit + + ldx V.PORT,u ; Get port address $FF04 + ldb V.TYPE,u ; Get device parity settings + orb #Cmd.DTR ; SET DTR, flag us as ready + stb AciaCmd,x + clrb ; Flag no error +InitExit + rts + +; +; Baud rate table, all baud rates use external clock. +; + +BaudRateTable + fcb Ctl.RxCS+BR.00110 + fcb Ctl.RxCS+BR.00300 + fcb Ctl.RxCS+BR.00600 + fcb Ctl.RxCS+BR.01200 + fcb Ctl.RxCS+BR.02400 + fcb Ctl.RxCS+BR.04800 + fcb Ctl.RxCS+BR.09600 + fcb Ctl.RxCS+BR.19200 - fcb UPDAT. +PutProcToSleep + bsr DoPutProcToSleep + +* +* 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 lda <u0023,u + ble L00A1 + + ldb <u001F,u + cmpb #$0A + bhi L00A1 + + ldb V.XON,u + orb #$80 + stb <u0023,u + + ldb V.TYPE,u ; Get prity settings + orb #TIRB.On+Cmd.DTR ; Enable tranmitter inturrupt & DTR ($05) + ldx V.PORT,u ; Get port address $FF04 + stb AciaCmd,x ; Write to ACIA + +L00A1 tst <u0024,u + bne ErrorExit + + ldb <RxQueueHeadOffset,u ; Get queue head ptr + leax <RxQueue,u ; Get Rx Queue address -name fcs /ACIA51/ - fcb edition + orcc #$50 ; Disable Inturrupts + cmpb <RxQueueTailOffset,u ; Is Head=Tail, and therefore queue empty ? + beq PutProcToSleep ; Yes : sleep and await input from remote device + + abx ; Calculate pos in queue for next char + lda ,x ; Get byte from read queue + dec <u001F,u + incb + cmpb #RxQueueLen-1 ; Reached end of queue area ? + bls L00BF ; no : continue + + clrb ; Wrap tail pointer to the beginning of queue space +L00BF stb <RxQueueHeadOffset,u ; save new queue pointer + clrb + ldb V.ERR,u + beq L00CF ; No error : exit + + stb <$3A,y + clr V.ERR,u + comb ; Flag and return error + ldb #$F4 +L00CF andcc #$AF ; Enable inturrupts + rts + +ErrorExit + comb ; Flag error & return + ldb #$F6 + rts + +; +; Put calling process to sleep while we await input or output from remote device. +; + +DoPutProcToSleep + pshs x,b,a + lda V.BUSY,u ; Get busy process + sta V.WAKE,u ; Store in proc to wake + andcc #$AF ; Enable inturrupts + ldx #$0000 ; Sleep indefinatly + os9 F$Sleep ; Put caller to sleep + + ldx <D.Proc ; Get current proces descriptor addr + ldb <P$Signal,x ; Get signal code of proc + beq L00EF + + cmpb #$03 + bls L00F8 -start equ * - lbra L002A - lbra L0086 - lbra L00FE - lbra L012F - lbra L0146 - lbra L0173 -L0027 neg <u0080 - dec <u00AE - fcb $41 A - stb $01,x - ldb #$02 - stb <u0022,u - ldd <$26,y - andb #$0F - leax <L007C,pcr - ldb b,x - anda #$F0 - sta u0006,u - ldx u0001,u - std $02,x - lda ,x - lda ,x - tst $01,x - lbmi L00D2 - clra - clrb - std <u001D,u - std <u0020,u - sta <u0023,u - sta <u001F,u - std <u0024,u - ldd u0001,u - addd #$0001 - leax >L0027,pcr - leay >L0194,pcr - os9 F$IRQ - bcs L007B - ldx u0001,u - ldb u0006,u - orb #$01 - stb $02,x - clrb -L007B rts -L007C sync - lbra L1798 - orcc #$1C - exg x,f -L0084 bsr L00D6 -L0086 lda <u0023,u - ble L00A1 - ldb <u001F,u - cmpb #$0A - bhi L00A1 - ldb u000F,u - orb #$80 - stb <u0023,u - ldb u0006,u - orb #$05 - ldx u0001,u - stb $02,x -L00A1 tst <u0024,u - bne L00D2 - ldb <u001E,u - leax <u0027,u - orcc #$50 - cmpb <u001D,u - beq L0084 - abx - lda ,x - dec <u001F,u - incb - cmpb #$4F - bls L00BF - clrb -L00BF stb <u001E,u - clrb - ldb u000E,u - beq L00CF - stb <$3A,y - clr u000E,u - comb - ldb #$F4 -L00CF andcc #$AF - rts -L00D2 comb - ldb #$F6 - rts -L00D6 pshs x,b,a - lda u0004,u - sta u0005,u - andcc #$AF - ldx #$0000 - os9 F$Sleep - ldx <u004B - ldb <$36,x - beq L00EF - cmpb #$03 - bls L00F8 -L00EF clra - lda $0D,x - bita #$02 - bne L00F8 - puls pc,x,b,a -L00F8 leas $06,s - coma - rts -L00FC bsr L00D6 -L00FE leax <u0077,u - ldb <u0020,u - abx - sta ,x - incb - cmpb #$8B - bls L010D - clrb -L010D orcc #$50 - cmpb <u0021,u - beq L00FC - stb <u0020,u - lda <u0022,u - beq L012B - anda #$FD - sta <u0022,u - bne L012B - lda u0006,u - ora #$05 - ldx u0001,u - sta $02,x -L012B andcc #$AF -L012D clrb - rts -L012F cmpa #$01 - bne L013E - ldb <u001F,u - beq L00D2 - ldx $06,y - stb $02,x -L013C clrb - rts -L013E cmpa #$06 - beq L012D -L0142 comb - ldb #$D0 - rts -L0146 cmpa #$1A - bne L0161 - lda $05,y - ldx $06,y - ldb $05,x - orcc #$50 - tst <u001F,u - bne L015C - std <u0024,u - bra L012B -L015C andcc #$AF - lbra L01F8 -L0161 cmpa #$1B - bne L0142 - lda $05,y - cmpa <u0024,u - bne L013C - clr <u0024,u - rts -L0170 lbsr L00D6 -L0173 ldx <u004B - lda ,x - sta u0004,u - sta u0003,u - ldb <u0020,u - orcc #$50 - cmpb <u0021,u - bne L0170 - lda u0006,u - ldx u0001,u - sta $02,x - andcc #$AF - ldx #$0000 - os9 F$IRQ - rts -L0194 ldx u0001,u - tfr a,b - andb #$60 - cmpb <u0026,u - beq L01AB - stb <u0026,u - bitb #$60 - lbne L02AE - lbra L029C -L01AB bita #$08 - bne L01FD - lda <u0023,u - bpl L01C4 - anda #$7F - sta ,x - eora u000F,u - sta <u0023,u - lda <u0022,u - bne L01EA - clrb - rts -L01C4 leay <u0077,u - ldb <u0021,u - cmpb <u0020,u - beq L01E2 - clra - lda d,y - incb - cmpb #$8B - bls L01D8 - clrb -L01D8 stb <u0021,u - sta ,x - cmpb <u0020,u - bne L01F0 -L01E2 lda <u0022,u - ora #$02 - sta <u0022,u -L01EA ldb u0006,u - orb #$01 - stb $02,x -L01F0 ldb #$01 - lda u0005,u -L01F4 beq L01FB - clr u0005,u -L01F8 os9 F$Send -L01FB clrb - rts -L01FD bita #$07 - beq L0213 - tfr a,b - tst ,x - anda #$07 - ora u000E,u - sta u000E,u - lda $02,x - sta $01,x - sta $02,x - bra L01FB -L0213 lda ,x - beq L022E - cmpa u000B,u - beq L028B - cmpa u000C,u - beq L028F - cmpa u000D,u - beq L0283 - cmpa u000F,u - beq L029C - cmpa <u0010,u - lbeq L02AE -L022E leax <u0027,u - ldb <u001D,u - abx - sta ,x - incb - cmpb #$4F - bls L023D - clrb -L023D cmpb <u001E,u - bne L024A - ldb #$04 - orb u000E,u - stb u000E,u - bra L01F0 -L024A stb <u001D,u - inc <u001F,u - tst <u0024,u - beq L025D - ldd <u0024,u - clr <u0024,u - bra L01F8 -L025D lda <u0010,u - beq L01F0 - ldb <u001F,u - cmpb #$46 - bcs L01F0 - ldb <u0023,u - bne L01F0 - anda #$7F - sta <u0010,u - ora #$80 - sta <u0023,u - ldb u0006,u - orb #$05 - ldx u0001,u - stb $02,x - lbra L01F0 -L0283 ldx u0009,u - beq L022E - sta $08,x - bra L022E -L028B ldb #$03 - bra L0291 -L028F ldb #$02 -L0291 pshs a - lda u0003,u - lbsr L01F4 - puls a - bra L022E -L029C lda <u0022,u - anda #$FE - sta <u0022,u - bne L02AC - lda u0006,u - ora #$05 - sta $02,x -L02AC clrb - rts -L02AE lda <u0022,u - bne L02B9 - ldb u0006,u - orb #$01 - stb $02,x -L02B9 ora #$01 - sta <u0022,u - clrb - rts +L00EF clra + lda P$State,x ; Get process state + bita #Condem ; Process condemed ? (being killed ?) + bne L00F8 ; yes : error, exit + + puls pc,x,b,a ; Return + +L00F8 leas $06,s + coma + rts + +L00FC bsr DoPutProcToSleep + +* +* Input U = Address of device static data storage +* Y = Address of path descriptor module +* A = Character to write +* +* Output +* CC = carry set on error, clear on none +* B = error code if CC.C set. +* + +Write leax <TxQueue,u ; Get pointer to transmit queue + ldb <TxQueueTailOffset,u ; Get offset of end of TX queue + abx ; Calculate next free queue slot + sta ,x ; Put byte to transmit in queue + incb ; Increment queue tail ptr + cmpb #TxQueueLen-1 ; End of Queue area ? + bls L010D ; no, continue + clrb ; Point at begining of queue area + +L010D orcc #$50 ; Disable inturrupts + cmpb <TxQueueHeadOffset,u ; is Head=Tail therefore queue full ? + beq L00FC ; Yes : sleep process until room in queue + + stb <TxQueueTailOffset,u ; Re-save tail pointer + lda <u0022,u + beq L012B + + anda #$FD + sta <u0022,u + bne L012B + + lda V.TYPE,u ; Get parity bits + ora #TIRB.On+Cmd.DTR ; Enable tranmitter inturrupt & DTR ($05) + ldx V.PORT,u ; Get port address $FF04 + sta AciaCmd,x ; Write to ACIA + +L012B andcc #$AF ; Enable Inturrupts +L012D clrb ; Flag no error + rts + +* +* Input U = Address of device static data storage +* Y = Address of path descriptor module +* A = Status code +* +* Output +* Depends on status code. +* + +GetSta cmpa #SS.Ready ; Device ready ? ($01) + bne L013E + + ldb <u001F,u + beq ErrorExit + + ldx $06,y + stb $02,x +L013C clrb + rts + +L013E cmpa #SS.EOF ; EOF ? ($06) + beq L012D + +L0142 comb ; Flag error + ldb #$D0 + rts + +* +* Input U = Address of device static data storage +* Y = Address of path descriptor module +* A = Status code +* +* Output +* Depends on status code. +* + +SetSta cmpa #SS.SSig ; Send signal on data ready ? ($1A) + bne L0161 + + lda PD.CPR,y ; Get caller's process id + ldx PD.RGS,y ; Get caller's Regs + ldb $05,x ; Get lower half of X ???? + + orcc #$50 ; Disable inturrupts + tst <u001F,u + bne L015C + + std <u0024,u + bra L012B + +L015C andcc #$AF + lbra L01F8 + +L0161 cmpa #SS.Relea ; Release device ? ($1B) + bne L0142 + + lda PD.CPR,y ; Get calling process ID + cmpa <u0024,u ; Same process ? + bne L013C ; no ! + + clr <u0024,u ; Yes : release + rts + +L0170 lbsr DoPutProcToSleep + +* +* Input U = Address of device static data storage +* +* Output +* CC = carry set on error, clear on none +* B = error code if CC.C set. +* + +Term ldx <D.Proc ; Get current process descriptor addr + lda P$ID,x ; Get process ID + sta V.BUSY,u ; Save it in busy and last processs + sta V.LPRC,u + + ldb <TxQueueTailOffset,u ; Check we have sent all bytes ? + orcc #$50 + cmpb <TxQueueHeadOffset,u + bne L0170 ; Still bytes left to send, wait to send them + + lda V.TYPE,u ; Get Parity settings + ldx V.PORT,u ; Get port address $FF04 + sta AciaCmd,x ; Set parity in ACIA + andcc #$AF ; Enable inturrupts + + ldx #$0000 ; Remove IRQ handler + os9 F$IRQ + rts + +* +* F$IRQ handler, +* +* Input : +* A = Status byte XOR flip +* U = our data area +* +* In this case, since flip byte is zero, and any value XOR zero +* remains uncahanged, A contains the contents of the ACIA status +* register ($FF05) +* + +IRQService + ldx V.PORT,u ; Get port address $FF04 + tfr a,b ; Take a copy of status + andb #Stat.DSR+Stat.DCD ; Mask all but DSR & DCD ($60) + cmpb <SavedDSRDCD,u ; Compare to saved + beq L01AB ; not changed, check other bits + + stb <SavedDSRDCD,u ; Save DSR & DCD values + bitb #$60 ; Was either set ??? + lbne L02AE ; yes + lbra L029C - emod -eom equ * - end +L01AB bita #Stat.RxF ; Rx register full ? ($08) + bne L01FD ; yes + + lda <u0023,u + bpl L01C4 + + anda #$7F + sta ,x + eora V.XON,u + sta <u0023,u + lda <u0022,u + bne L01EA + + clrb + rts + +L01C4 leay <TxQueue,u ; Point to transmit queue + ldb <TxQueueHeadOffset,u ; Check that there are bytes to transmit + cmpb <TxQueueTailOffset,u + beq L01E2 ; no : skip + + clra + lda d,y ; Get byte to transmit + incb ; Increment head offset ptr + cmpb #TxQueueLen-1 ; Head at end of Queue area ? + bls L01D8 + + clrb ; Yes : point it at beginning +L01D8 stb <TxQueueHeadOffset,u ; Save it + sta AciaData,x ; Transmit byte + cmpb <TxQueueTailOffset,u ; Head=Tail therefore Tx queue empty ? + bne L01F0 ; no : skip ahead + +L01E2 lda <u0022,u + ora #$02 + sta <u0022,u + +L01EA ldb V.TYPE,u ; Get parity settings + orb #Cmd.DTR ; Enable DTR, ready + stb AciaCmd,x ; Write to ACIA + +L01F0 ldb #S$Wake ; Wake up calling process + lda V.WAKE,u ; Get proc ID to wake +L01F4 beq L01FB + + clr V.WAKE,u ; Clear saved wake proc ID +L01F8 os9 F$Send ; send wakeup signal +L01FB clrb ; Flag no error + rts + +L01FD bita #Stat.Par+Stat.Frm+Stat.Ovr ; Check for Parity/Framing/Overrun errors ($07) + beq L0213 ; No Error detected, do read + + tfr a,b ; Copy status + tst ,x + anda #$07 + ora V.ERR,u + sta V.ERR,u + lda $02,x + sta $01,x + sta $02,x + bra L01FB + +L0213 lda ,x ; Read byte from ACIA + beq L022E ; zero, branch ahead + + cmpa V.INTR,u ; Inturrupt char ? + beq L028B + + cmpa V.QUIT,u ; Quit char ? + beq L028F + + cmpa V.PCHR,u ; Pause char ? + beq L0283 + + cmpa V.XON,u ; Xon char ? + beq L029C + + cmpa <V.XOFF,u ; Xoff char ? + lbeq L02AE + +; +; If we reach here, char is nothing special, so just put it in queue +; +L022E leax <RxQueue,u ; Point to receive queue + ldb <RxQueueTailOffset,u ; Get tail offset + abx ; Calculate address + sta ,x ; Put char in queue + incb ; increment tail ptr + cmpb #RxQueueLen-1 ; End of queue area ? + bls L023D ; no : continue + + clrb ; point to begining of Rx queue area +L023D cmpb <RxQueueHeadOffset,u ; Same as head of queue ? + bne L024A ; no : + + ldb #$04 + orb V.ERR,u ; accumulated errors + stb V.ERR,u + bra L01F0 + +L024A stb <RxQueueTailOffset,u ; Save tail ptr + inc <u001F,u + tst <u0024,u + beq L025D + + ldd <u0024,u + clr <u0024,u + bra L01F8 + +L025D lda <V.XOFF,u + beq L01F0 + + ldb <u001F,u + cmpb #$46 + bcs L01F0 + + ldb <u0023,u + bne L01F0 + + anda #$7F + sta <V.XOFF,u + ora #$80 + sta <u0023,u + + ldb V.TYPE,u ; Get parity settings + orb #TIRB.On+Cmd.DTR ; Enable tranmitter inturrupt & DTR ($05) + ldx V.PORT,u ; Get port address $FF04 + stb AciaCmd,x ; Write to acia + + lbra L01F0 +L0283 ldx V.DEV2,u + beq L022E + + sta $08,x + bra L022E + +L028B ldb #$03 + bra L0291 + +L028F ldb #$02 +L0291 pshs a + + lda V.LPRC,u ; Get last active proc ID + lbsr L01F4 ; Wake process + puls a + bra L022E + +L029C lda <u0022,u + anda #$FE + sta <u0022,u + bne L02AC + + lda V.TYPE,u ; Get parity settings + ora #TIRB.On+Cmd.DTR ; Enable tranmitter inturrupt & DTR ($05) + sta AciaCmd,x ; Write to ACIA +L02AC clrb ; Flag no error + rts + +L02AE lda <u0022,u + bne L02B9 + + ldb V.TYPE,u ; Get parity settings + orb #Cmd.DTR ; Enable DTR + stb AciaCmd,x ; Write to ACIA + +L02B9 ora #$01 + sta <u0022,u + clrb + rts + + emod +eom equ * + end