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 *