nam z8530
ttl Interrupt-Driven SCC-driver (one channel)
***************
* Edition History
* # date Comments by
* -- -------- ------------------------------------------------- ------
* 01 97/09/01 Initial version based on sampledriver
* of P.J. Kramer PE1JPD
* 02 97/10/01 SCC handling based on SuperVozelj by
* Matjaz Vitmar, S53MV PE1JPD
* 03 97/10/10 Based on new developed file-manager SMP PE1JPD
Edition equ 03 current Edition number
Typ_Lang set (Drivr<<8)+Objct
Attr_Rev set (ReEnt<<8)+0
psect z8530,Typ_Lang,Attr_Rev,Edition,0,Entry
use /dd/defs/defsfile
********************************
* Definitions
*
Carry equ %00000001
BUFSIZE set 350
MAXBUF set 8
clock equ 4915200
chana equ 4
data equ 2
********************************
* Static storage requirements
*
vsect
RxINr ds.w 1
RxONr ds.w 1
RxInx ds.l 1
RxBuf ds.l 1
RxCount ds.w 1
TxBuf ds.l 1
TxCount ds.w 1
TxStat ds.w 1
SigPID ds.w 1
SigPNm ds.w 1
SigSCd ds.w 1
IRQMask ds.w 1
RxBuffer ds.b MAXBUF*BUFSIZE
TxBuffer ds.b MAXBUF*BUFSIZE
RxIndex ds.l MAXBUF
ends
***************
* Module Header
Entry dc.w Init
dc.w Read
dc.w Write
dc.w GetStat
dc.w SetStat
dc.w Term
Init move.l a1,-(sp)
lea.l RxBuffer(a2),a0 get address of storage
move.l a0,RxBuf(a2) first buffer is current buffer RxBuf
lea.l RxIndex(a2),a1 get address of address-index
move.l a1,RxInx(a2) store it
move #MAXBUF-1,d1 for MAXBUF buffers
ILp move.l a0,(a1)+ store address of buffer in index
clr (a0) and clear length of rxdata
lea.l BUFSIZE(a0),a0 load address of next buffer
dbra d1,ILp and continue
move #2,RxCount(a2) data starts at offset 2, after length
lea.l TxBuffer(a2),a0
move.l a0,TxBuf(a2)
move.l (sp)+,a1
move.b M$IRQLvl(a1),d0
lsl #8,d0
ori #%0010000000000000,d0
move d0,IRQMask(a2)
move.b M$Vector(a1),d0
move.b M$Prior(a1),d1
lea.l IRQSrv(pc),a0
movea.l V_PORT(a2),a3
os9 F$IRQ
bcs init9
movea.l V_PORT(a2),a3
bsr RstScc
move.l #38400,d0
bsr IniScc
init9 rts
RstScc move.b (a3),d0
lea.l RstSccTbl(pc),a1
moveq #5,d0
RstSccLp move.b (a1)+,(a3)
tst.l (a1)
dbf d0,RstSccLp
rts
RstSccTbl dc.b $09,$c0
dc.b $02,$00
dc.b $09,$08
IniScc lea.l IniSccTbl(pc),a1
moveq #15,d1
IniSccLp1 move.b (a1)+,(a3)
tst.l (a1)
dbf d1,IniSccLp1
move.l #clock,d1
lsr.l #6,d1
divu d0,d1
move.b #$0c,(a3)
tst.l (a1)
subq.w #2,d1
move.b d1,(a3)
tst.l (a1)
move.b #$0d,(a3)
tst.l (a1)
lsr.w #8,d1
move.b d1,(a3)
tst.l (a1)
moveq #15,d1
IniSccLp2 move.b (a1)+,(a3)
tst.l (a1)
dbf d1,IniSccLp2
rts
IniSccTbl dc.b $04,$e0 WR4 SDLC mode
dc.b $01,$00 WR1 INT disable
dc.b $0a,$a0 WR10 CRC preset 1, NRZI, flag idle
dc.b $07,$7e WR7 flag
dc.b $03,$c8 WR3 RX 8bits/character
dc.b $05,$61 WR5 TX 8bits/character, SDLC CRC
dc.b $0e,$60 WR14 disable DPLL & BRG
dc.b $0b,$7f WR11 NOXTAL, RXclk=TXclk=TRxC=DPLL
dc.b $0e,$e0 WR14 set NRZI mode
dc.b $0e,$80 WR14 set source = BR generator, RTxC
dc.b $0e,$20 WR14 enter search mode
dc.b $0e,$01 WR14 enable BRG
dc.b $03,$c9 WR3 RX enable
dc.b $05,$69 WR5 TX enable
dc.b $0f,$50 WR15 TX Underrun/EOM IE, sync/hunt IE
dc.b $01,$13 WR1 RX INT all chr, TX int & spec cond.
********************
* Read block of data
*
Read move sr,-(sp)
move IRQMask(a2),sr
move RxONr(a2),d1
cmp RxINr(a2),d1
bne.s ReadBuf
move V_BUSY(a2),V_WAKE(a2)
move (sp)+,sr
moveq #0,d0
os9 F$Sleep
move P$Signal(a4),d1
beq.s RdWake
cmpi #S$Deadly,d1
blo.s RdWErr
RdWake btst.b #Condemn,P$State(a4)
beq.s Read
RdWErr ori #Carry,ccr
rts
ReadBuf move (sp)+,sr
move.l RxInx(a2),a1
move.l (a1,d1.w),a1
addq #4,d1
cmpi #(4*MAXBUF),d1
bcs.s upobuf
clr d1
upobuf move d1,RxONr(a2)
move (a1)+,d1
move d1,d0
subq #1,d1
RdLp move.b (a1)+,(a0)+
dbra d1,RdLp
moveq #0,d1
rts
********************
* Write block of data
*
Write tst d0
beq.s WritEx
move d0,d1
subq #1,d1
move d1,TxCount(a2)
movea.l TxBuf(a2),a1
WrLp move.b (a0)+,(a1)+
dbra d1,WrLp
move.l V_PORT(a2),a3
movea.l TxBuf(a2),a1
move.b #$80,(a3) reset CRC-generator
tst.l (a2)
move.b (a1)+,data(a3) put first byte in tx register
move.l a1,TxBuf(a2)
move #4,TxStat(a2) status is tx-data
WritEx rts
********************
* Getstat
*
GetStat cmpi #SS_Ready,d0
bne.s GetOpt
clr.l R$d1(a5)
move RxONr(a2),d1
cmp RxINr(a2),d1
beq.s NotRdy
move.l RxInx(a2),a0
move.l (a0,d1.w),a0
move (a0),R$d1+2(a5)
bne.s GetEx
NotRdy move #E$NotRdy,d1
bra.s GetEx
GetOpt cmpi #SS_Opt,d0
bne.s GetEOF
nop
bra.s GetEx
GetEOF cmpi.b #SS_EOF,d0
beq.s GetEx
GetUnk move #E$UnkSvc,d1
GetEEx ori #Carry,ccr
GetEx rts
********************
* Setstat
*
SetStat cmpi #SS_DsRTS,d0
bne.s SetEnR
movea.l V_PORT(a2),a3
move.b #5,(a3) WR5
tst.l (a2)
move.b #$69,(a3) tx 8 bits, tx enable, tx crc enable, rts=0
bra SetEx
SetEnR cmpi #SS_EnRTS,d0
bne.s SetOpn
movea.l V_PORT(a2),a3
move.b #5,(a3) WR5
tst.l (a2)
move.b #$6b,(a3) tx 8 bits, tx enable, tx crc enable, rts=1
bra SetEx
SetOpn cmpi #SS_Open,d0
beq.s SetOps
cmpi #SS_Opt,d0
bne.s SetSig
SetOps nop
bra.s SetEx
SetSig cmpi #SS_SSig,d0
bne.s SetRel
tst SigPID(a2)
beq.s SetSDA
move #E$NotRdy,d1
bra.s SetEEx
SetSDA move PD_CPR(a1),d0
move R$d2+2(a5),d1
move sr,-(sp)
move IRQMask(a2),sr
move RxONr(a2),d2
cmp RxINr(a2),d2
beq.s SetSSi
move (sp)+,sr
os9 F$Send
bra.s SetEx
SetSSi move d0,SigPID(a2)
move d1,SigSCd(a2)
move PD_PD(a1),SigPNm(a2)
move (sp)+,sr
moveq #0,d1
bra.s SetEx
SetRel cmpi #SS_Relea,d0
bne.s SetUnk
move PD_CPR(a1),d0
cmp SigPID(a2),d0
beq.s SetRPN
SetREx moveq #0,d1
bra.s SetEx
SetRPN move PD_PD(a1),d0
cmp SigPNm(a2),d0
bne.s SetREx
clr SigPID(a2)
bra.s SetEx
SetUnk move #E$UnkSvc,d1
SetEEx ori #Carry,ccr
SetEx rts
********************
* Terminate
*
Term move P$ID(a4),d0
move d0,V_LPRC(a2)
move d0,V_BUSY(a2)
movea.l V_PORT(a2),a3
move.l a1,-(sp)
bsr RstScc
move.l (sp)+,a1
move.b M$Vector(a1),d0
suba.l a0,a0
os9 F$IRQ
rts
IRQSrv movea.l V_PORT(a2),a3 channel B
move.b #2,(a3) read RR2
tst.l (a2) delay
btst #3,(a3)
beq.s IRQScc branch if channel B
addq.l #chana,a3 else, set up channel A
IRQScc move.b (a3),d2 RR0 in d2
tst.l (a2)
swap d2 and swap in high word
move.b #1,(a3)
tst.l (a2)
move.b (a3),d2 RR1 in d2 low word
tst.l (a2)
cmpi #4,TxStat(a2) status = tx-data?
beq.s Tx branch if so
move.b #$28,(a3) else, reset tx interrupt
bra.s Rx and check receiver
Tx btst #18,d2 tx buffer empty?
beq.s Rx branch if so
subi #1,TxCount(a2) not empty: send data
bmi.s TxEom
movea.l TxBuf(a2),a0
move.b (a0)+,data(a3)
move.l a0,TxBuf(a2)
bra.s Rx and leave
TxEom move.b #$e8,(a3) res txint pending, underrun/eom latch
move #5,TxStat(a2)
Rx btst #16,d2 rx char available?
beq.s ExtSt branch if not
movea.l RxBuf(a2),a0
move RxCount(a2),d1
move.b data(a3),d0
cmpi #BUFSIZE-2,d1
bcc.s ExtSt
move.b d0,(a0,d1.w)
addq #1,RxCount(a2)
bra.s RxEof
ExtSt move.b #$10,(a3) reset ext/status interrupt
RxEof move.l d2,d0
andi.l #$00900000,d0 abort? sync/hunt?
bne Err branch if not
btst #7,d2 end of frame?
beq IRQExit branch if not
eori.b #$07,d2
andi.b #$6e,d2 crc-error? overrun?
bne.s Err branch if so
movea.l RxBuf(a2),a0
move RxCount(a2),d1
subq #4,d1
move d1,(a0)
move RxINr(a2),d1
addq #4,d1
cmpi #(4*MAXBUF),d1
bcs.s updind
clr d1
updind cmp RxONr(a2),d1
beq.s Err
move d1,RxINr(a2)
move.l RxInx(a2),a0 get index in a0
move.l (a0,d1.w),a0 get address of next buffer
move.l a0,RxBuf(a2) and make it current buffer
move SigPID(a2),d0
beq.s NoSigReq
move SigSCd(a2),d1
clr SigPID(a2)
bra.s SendSig
NoSigReq move V_WAKE(a2),d0
beq.s Wake
clr V_WAKE(a2)
moveq #S$Wake,d1
SendSig os9 F$Send
Wake moveq #0,d1
Err move #2,RxCount(a2) reset inputptr
move.b #$30,(a3) error reset command
IRQExit rts
ends