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