home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
EFFO
/
forum3.lzh
/
EXAMPL
/
sc68681.a
< prev
next >
Wrap
Text File
|
1987-11-05
|
25KB
|
1,099 lines
ttl SC68681 DUART Device Driver
nam SC68681
*******************************************************************************
* Edition History
*
* # Date Comments by
* -- -------- --------------------------------------------------------- ----
* 0 87/07/20 Initial Version from GMX SC68681 disassembled mst
* 1 87/10/01 Adapted to SCN68681-Hardware on mc68'000 mst
*
Edition equ 1
Typ_Lang equ (Drivr<<8)+Objct
Attr_Rev equ (ReEnt<<8)+0
psect SC68681,Typ_Lang,Attr_Rev,Edition,0,SC681ENT
use <defsfile>
*********************************************
* Device Driver Variables
*
vsect
V_RBufWrt DS.L 1 writepointer to Readbuffer
V_RBufRd DS.L 1 readpointer to Readbuffer
V_RBufEnd DS.L 1 pointer to end of Readbuffer
V_InCnt DS.W 1 number of chars in Inputbuffer
V_WBufWrt DS.L 1 writepointer of Writebuffer
V_WBufRd DS.L 1 readpointer to Writebuffer (next character)
V_WBufEnd DS.L 1 pointer to end of Writebuffer
V_OutCnt DS.W 1 number of chars in Outputbuffer
V_BaseAd DS.L 1 baseaddress of SCN68681
* V_IBase DS.B 1 offset to interrupt area in D_DuImr (always 0)
align
V_Chanel DS.B 1 Flag: Channel A = 0, B = 1
V_XOnFlg DS.B 1 XOn/XOff-Flag: Bit 7=1:XOn/XOff to send, Code in bit 0-7
* Bit 7=0:Nothing to send
V_Flag DS.W 1 Bit 0: 0=XOn, 1=XOff; Bit 1: 0=new writechar, 1=no char
V_ProcID DS.W 1 Store Caller's Process ID of Signal to be sent
V_SigCod DS.W 1 Store Signal Code to be sent
V_PathNr DS.W 1 Store Pathnumber (Only once used !?!)
V_SigBf1 DS.W 1 Requesters Process ID
DS.W 1 Signal Code
DS.B 1 Path Number
align
V_SigBf2 DS.W 1 Requesters Process ID
DS.W 1 Signal Code
DS.B 1 Path Number
align
V_IRQMsk DS.W 1 IRQ-Mask for SCN68681
V_IRQEn DS.B 1 IRQ Enable pattern Rx & Tx
V_Mask DS.B 1 IRQ Mask, IRQ Sources allowed
V_RTSLine DS.B 1 RTS-Line on OP0(A), OP1(B)
V_DTRLine DS.B 1 DTR-Line on OP3(B), OP4(A)
V_RBuf DS.B 80 Readbuffer
RBufEnd
V_WBuf DS.B 140 Writebuffer
WBufEnd
ends
*********************************************
* SCN68681 Register Definitions
*
* Registers for both Channels are accessed via Chip-Baseaddress
* Registers for each Channel are accessed via Port-Address
*
* Write Registers:
CSR equ $3 Clock Select Reg.
CR equ $5 Command Register
THR equ $7 TX Holding Register
ACR equ $9 Aux. Control Register
IMR equ $B Interrupt Mask Register
CTUR equ $D C/T Upper Register
CTLR equ $F C/T Lower Register
* CSRB equ $13 Clock Select Reg. B
* CRB equ $15 Command Register B
* THRB equ $17 TX Holding Register B
OPCR equ $1B Output Port Conf. Reg.
OPRSet equ $1D Set Output Port Bits Command
OPRRes equ $1F Reset Output Port Bits Command
* Read/Write Registers
MR equ $1 Mode Register, 1 & 2
* MRB equ $11 Mode Register B, 1 & 2
IVR equ $19 Interrupt Vector Register
* Read Registers:
SRAB equ $3 Status Register A,B
RHR equ $7 RX Holding Register
IPCR equ $9 Input Port Change Reg.
ISR equ $B Interrupt Status Reg.
CTU equ $D Counter/Timer Upper
CTL equ $F Counter/Timer Lower
* SRB equ $13 Status Register B
* RHRB equ $17 RX Holding Register B
* Input equ $1B Input Port
StartCnt equ $1D Start Counter Command
StopCnt equ $1F Stop Counter Command
*********************************************
* SCN68681 Commands
*
C_No equ $0 No Command
C_ResMR equ $10 Reset MR Pointer
C_ResRec equ $20 Reset Receiver
C_ResTrs equ $30 Reset transmitter
C_ResErr equ $40 Reset Error Status
C_ResBrk equ $50 Reset break change IRQ
C_StrBrk equ $60 Start break
C_StpBrk equ $70 Stop break
*********************************************
* SCN68681 Ststus Register Bit Definitions
*
S_Break equ 7 received break
S_FramEr equ 6 framing error
S_Parity equ 5 parity error
S_Overun equ 4 overrun error
S_TxEMT equ 3 Transmitter empty
S_TxRDY equ 2 Transmitter ready
S_FFULL equ 1 Read FIFO full
S_RxRDY equ 0 Receiver ready
E_FramEr equ $40
E_Parity equ $20
E_Overun equ $10
*********************************************
* SCN68681 Interrupt Mask- and Statusregister
*
I_InpPrt equ $80 Input Port Change
I_CgBrkB equ $40 Change in Break Channel B
I_RxRDYB equ $20 Receiver ready or FIFO full Channel B
I_TxRDYB equ $10 Transmitter Ready Channel B
I_CntRdy equ $08 Counter ready
I_CgBrkA equ $04 Change in Break Channel A
I_RxRDYA equ $02 Receiver ready of FIFO full Channel A
I_TxRDYA equ $01 Transmitter ready Channel A
*********************************************
* SCN68681 Auxiliary Control Register
*
A_IP3Int equ $08 IP3 change of state IRQ-enable
A_IP2Int equ $04
A_IP1Int equ $02
A_IP0Int equ $01
*********************************************
* Input/Output Port Bits Usage
*
RTSxN equ $80 Set MR to use OP(0),OP(1) as RTS
CTSxN equ $10 set MR to use IP(0),IP(1) as CTS
IP0 equ $01 Channel A CTS-Line
IP1 equ $02 Channel B CTS-Line
IP2 equ $03 Channel B DCD-Line
IP3 equ $04
IP4 equ $05
IP5 equ $06
OP0 equ $01 Channel A RTS-Line
OP1 equ $02 Channel B RTS-Line
OP2 equ $04
OP3 equ $08 Channel B DTR-Line
OP4 equ $10 Channel A DTR-Line
OP5 equ $20
OP6 equ $40
OP7 equ $80
*********************************************
* Default Settings of sc68681-Parameters
*
BrgClk equ $E0 Baudrateset 2 & Clock on X1/CLK
*********************************************
* Global Variables defined in 'IOGLOB.A'
*
* D_DuImr ds.b 2 IRQ-Mask for two SCN68681
*********************************************
* Drivers Jumptable
*
SC681ENT DC.W Init
DC.W Read
DC.W Write
DC.W GetStat
DC.W SetStat
DC.W Term
*********************************************
* Initialize device and its static storage
*
* INPUT: (a1) device descriptor module
* (a2) device static storage
* (a6) system global data
*
* USAGE (a3) device portaddress
* (a5) device portaddress with 4 LSB's zero
*
* OUTPUT none
*
* ERROR cc Carry set
* d1.w Error Code
*
AdDec equ $FF7948
Init:
move.w M$DevCon(a1),d0
move.b 2(a1,d0.w),d0 Slotno. aus Dev-Descr
clr.l d2
move.b d0,d2
mulu #16,d2 Offset berechnen
movea.l #SlotTab,a3 ptr auf Slottab
cmpi.l #DUART_K,0(a3,d2.w) already initialized ?
beq.s InitPORT
addi.b #$f8,d0 f. AdrDecod. aufbereiten
move.l ROMBOT,a0 ROMBOT holen
jsr AdDec Slot programmieren
move.l #DUART_K,0(a3,d2.w) Kennung in Slottab
move.l a0,4(a3,d2.w) Addresse in Slottab.
suba.l #$4000,a0 ROMBOT korrigieren
move.l a0,ROMBOT
InitPORT: move.l 4(a3,d2.w),d0
add.l d0,V_PORT(a2) add cardadr and channeladr
MOVEA.L V_PORT(A2),A3 get device portaddress
MOVE.L A3,D0
BTST #3,D0 test which channel
BNE.S InitB
CLR.B V_Chanel(A2) Init Channel A
MOVE.B #OP0,V_RTSLine(A2) prepare so set OP0 to Low
MOVE.B #OP4,V_DTRLine(A2)
MOVE.B #I_RxRDYA+I_TxRDYA,V_IRQEn(A2) Enable Rx & Tx IRQ's
MOVE.B #$FE,V_Mask(A2) Tx IRQ not allowd
BRA.S Init01
InitB: MOVE.B #1,V_Chanel(A2) Init Channel B
MOVE.B #OP1,V_RTSLine(A2) prepare to set OP1 to Low
MOVE.B #OP3,V_DTRLine(A2)
MOVE.B #I_RxRDYB+I_TxRDYB,V_IRQEn(A2) Enable Rx & Tx IRQ's
MOVE.B #$EF,V_Mask(A2) Tx IRQ not allowed
Init01: ANDI.B #$F0,D0 get baseaddress of port
MOVEA.L D0,A5
MOVE.L D0,V_BaseAd(A2)
* Setup IRQ-Mask
MOVE.B M$IRQLvl(A1),D2 get hardware IRQ Level
ASL.W #8,D2 shift into priority
BSET #13,D2 set systemstate bit
MOVE.W D2,V_IRQMsk(A2)
* Initialize SCN68681 Hardware
MOVE SR,-(A7)
MOVE D2,SR
BSR InitDev Initialize SCN68681
MOVE (A7)+,SR
TST.B D1
BNE InitErr
* Initialize Bufferpointers and Flags
BSET #1,V_Flag(A2) no char in writebuffer
LEA V_RBuf(A2),A0
MOVE.L A0,V_RBufWrt(A2)
MOVE.L A0,V_RBufRd(A2)
LEA RBufEnd-V_RBuf(A0),A0 end of readbuffer
MOVE.L A0,V_RBufEnd(A2)
LEA V_WBuf(A2),A0
MOVE.L A0,V_WBufWrt(A2)
MOVE.L A0,V_WBufRd(A2)
LEA WBufEnd-V_WBuf(A0),A0
MOVE.L A0,V_WBufEnd(A2)
* Setup IRQ-Handler and D_DuImr
MOVE.B M$Vector(A1),D0
MOVE.B M$Prior(A1),D1
LEA IRQEnt(PC),A0
OS9 F$IRQ
BCS.S InitRts
MOVEA.L V_PORT(A2),A3
move.b M$Vector(a1),IVR(a3) set up Interrupt vector
MOVE SR,-(A7)
MOVE V_IRQMsk(A2),SR
MOVE.B #$05,CR(A3) enable Tx and Rx
LEA D_DuImr(A6),A4 interrupt mask register base
* ADDA.W V_IBase(A2),A4 always 0
MOVE.B V_IRQEn(A2),D3
OR.B D3,(A4) two channels/one byte
MOVE.B V_Mask(A2),D3
AND.B D3,(A4)
MOVEA.L V_BaseAd(A2),A5
MOVE.B (A4),IMR(A5)
MOVE (A7)+,SR
MOVE.B V_RTSLine(A2),OPRSet(A5)
MOVEQ #0,D1
InitRts: RTS
*********************************************
* Initialize Device
* Resets Port A/B depending on (a3)
*
* INPUT (a3) port address (A or B)
* (a5) device baseaddr
*
InitDev: MOVE.B #C_ResRec,CR(A3) Reset Channel Receiver
NOP
MOVE.B #C_ResTrs,CR(A3) Reset Channel Transmitter
NOP
MOVE.B #C_ResErr,CR(A3) Reset Error Status
NOP
MOVE.B #C_ResBrk,CR(A3) Reset break change IRQ
NOP
MOVE.B #BrgClk,ACR(A5) Baudrateset and Clocksource
NOP
MOVE.B #$00,CTUR(A5) Set Timer
NOP
MOVE.B #$03,CTLR(A5)
*********************************************
* Select Baudrate
*
* Set Clock Select Register CSR
move.b $5D(a1),d0
* MOVE.B PD_BAU(A1),D0 Adjustable Baud Rate
CMPI.B #$FF,D0 External not allowed
BEQ.S InitErr
ANDI.W #$001F,D0
CMP.B #$10,D0 19'000 Baud
BHI.S InitErr
MOVE.B BaudTab(PC,D0.W),D0
CMP.B #$FF,D0 not allowed with Set choosen
BEQ.S InitErr
MOVE.B D0,CSR(A3) Clock Select
* set Mode Register 1
move.b $5C(a1),d0
* MOVE.B PD_PAR(A1),D0 Parity Code
MOVE.B D0,D2
MOVE.B #C_ResMR,CR(A3) Reset MR Pointer
ANDI.W #3,D0 mask parity
MOVE.B ParTab(PC,D0.W),D0
BMI.S InitErr
MOVE.B D2,D1
ANDI.W #$C,D1 mask number of bits/char
ASR.W #2,D1
OR.B BitsTab(PC,D1.W),D0
ORI.B #RTSxN,D0 control by RxRTS Signal
MOVE.B D0,MR(A3) Set Mode Register 1
* set Mode Register 2
MOVE.B D2,D1
ANDI.W #$30,D1 mask number of stop bits
ASR.W #4,D1
MOVE.B StopTab(PC,D1.W),D0
BMI.S InitErr
ANDI.B #$0C,D2 mask number of bits/char
CMP.B #$0C,D2 5 Bits/char
BEQ.S InitDev1
CMPI.B #$01,D1 1 1/2 stop bits
BNE.S InitDev1
ADDQ.B #1,D0 add 0.5 to stop bit length for 5 bits/char
InitDev1: ORI.B #CTSxN,D0 CTS enable
MOVE.B D0,MR(A3) Set Mode Register 2
CLR.W D1
RTS
InitErr: MOVE.W #E$BMode,D1 Error, bad I/O Mode
ORI #Carry,ccr
RTS
*********************************************
* Initializationtable for SCN68681
*
BaudTab: DC.B $FF,$00,$11,$22,$33,$44,$55,$66,$AA
DC.B $77,$88,$FF,$99,$FF,$BB,$CC,$DD
ParTab: DC.B $10,$04,$FF,$00
BitsTab: DC.B $03,$02,$01,$00
StopTab: DC.B $07,$07,$0F,$FF
DC.B $00
*********************************************
* Get next character
*
* INPUT (a1) path descriptor
* (a2) device static storage
* (a4) process descriptor
* (a6) system global data
*
* OUTPUT d0.b input character
*
* ERROR cc Carry set
* d1.w Error Code
*
Read00: MOVE.W V_BUSY(A2),V_WAKE(A2)
MOVE (A7)+,SR
BSR Sleep
Read: TST.B V_XOnFlg(A2) XOn/XOff to send ?
BLE.S ReadChar
* if XOn/XOff to send or if XOff sent by RxIRQ (bit7=0)
CMPI.W #10,V_InCnt(A2)
BHI.S ReadChar
* less than 10 char in buffer and RxIRQ sent XOff --> send XOn
MOVE.B V_XON(A2),D1
MOVEA.L V_PORT(A2),A3
MOVE SR,-(A7)
MOVE V_IRQMsk(A2),SR
BTST #S_TxRDY,SRAB(A3) Transmitter Ready ?
BEQ.S RTrNRdy no-->
CLR.B V_XOnFlg(A2) XOn/XOff sent
MOVE.B D1,THR(A3) TX Holding Register
BRA.S Read01
* mark XOn to be sent if transmitter goes ready
RTrNRdy: ORI.B #$80,D1 set XOn/XOff to send bit
MOVE.B D1,V_XOnFlg(A2)
MOVEA.L V_BaseAd(A2),A0
MOVE.B V_IRQEn(A2),D3
*@ LEA D_DuImr(A6),A5
* ADDA.W V_IBase(A2),A5
*@ OR.B D3,(A5)
*@ MOVE.B (A5),IMR(A0) Interrupt Mask Register
Read01: MOVE (A7)+,SR
*********************************************
* Read character from readbuffer
*
ReadChar: TST.W V_ProcID(A2) ID of signal to be sent
BNE.S NotRdyErr
MOVE SR,-(A7)
MOVE V_IRQMsk(A2),SR
TST.W V_InCnt(A2)
BEQ.S Read00
MOVE (A7)+,SR
MOVEA.L V_RBufRd(A2),A0
MOVE.B (A0)+,D0
SUBQ.W #1,V_InCnt(A2)
CMPA.L V_RBufEnd(A2),A0
BCC.S RdChar00
LEA V_RBuf(A2),A0
RdChar00: MOVE.L A0,V_RBufRd(A2)
MOVE.B V_ERR(A2),PD_ERR(A1)
BEQ.S ReadEnd no error
CLR.B V_ERR(A2)
MOVE.W #E$Read,D1
BRA.S Err
NotRdyErr: MOVE.W #E$NotRdy,D1
Err ORI #Carry,ccr
ReadEnd: RTS
*********************************************
* Sleep until awakened by IRQ
*
Sleep: MOVEM.L D0/A0,-(A7)
MOVEQ #0,D0 sleep until awakened by signal
OS9 F$Sleep
MOVE.W P$Signal(A4),D1 get signal sent
BNE.S SigKind
State: BTST #Condemn,P$State(A4) process died ?
BNE.S SigErr
MOVEM.L (A7)+,D0/A0
RTS
SigKind: CMPI.W #S$Intrpt,D1 non user signals 0-3
BHI.S State
SigErr: LEA $C(A7),A7
BRA.S Err
*********************************************
* Output a character
*
* INPUT d0.b char to write
* (a1) path descriptor
* (a2) device static storage
* (a4) process descriptor pointer
* (a6) system global data
*
* OUTPUT none
*
* ERROR cc Carry set
* d1.w Error Code
*
Write00: MOVE.W V_BUSY(A2),V_WAKE(A2)
MOVE (A7)+,SR
BSR.S Sleep
Write: MOVE SR,-(A7)
MOVE V_IRQMsk(A2),SR
MOVE.W V_OutCnt(A2),D2
CMPI.W #WBufEnd-V_WBuf,D2
BCC.S Write00
ADDQ.W #1,V_OutCnt(A2)
MOVEA.L V_WBufWrt(A2),A0
MOVE.B D0,(A0)+ store char in writebuffer
CMPA.L V_WBufEnd(A2),A0
BCC.S Write1
LEA V_WBuf(A2),A0 reset bufferpointer
Write1: MOVE.L A0,V_WBufWrt(A2) update pointer
BCLR #1,V_Flag(A2) set Flag: new char in buffer
MOVEA.L V_BaseAd(A2),A0
MOVE.B V_IRQEn(A2),D3
*@ LEA D_DuImr(A6),A5
* ADDA.W V_IBase(A2),A5
*@ OR.B D3,(A5)
*@ MOVE.B (A5),IMR(A0)
MOVE (A7)+,SR
CLR.L D1
RTS
*********************************************
* GETSTAT/SETSTAT device status
*
* INPUT d0.w function code
* (a1) path descriptor
* (a2) device static storage
* (a6) system global data
*
* OUTPUT depends upon function code
*
* ERROR cc Carry set
* d1.w Error Code
*
GetStat: CMPI.W #SS_Ready,D0
BNE.S GStat00
*********************************************
* Test for data available
*
* INPUT none
*
* OUTPUT d1.l Nr of input chars available
*
MOVEA.L PD_RGS(A1),A0 SS_Ready returns number of chars available
CLR.W R$d1(A0)
MOVE.W V_InCnt(A2),R$d1+2(A0)
BEQ NotRdyErr no char available
RTS
GStat00: CMPI.W #SS_EOF,D0 test for EOF
BEQ.S GStatEnd
StatErr: MOVE.W #E$UnkSvc,D1
ORI #Carry,ccr
GStatEnd: RTS
*********************************************
* SETSTAT Device Status
*
* USAGE (a5) addr to D_DuImr+Offset
*
SetStat: MOVEA.L V_BaseAd(A2),A0
*@ LEA D_DuImr(A6),A5
* ADDA.W V_IBase(A2),A5
CMPI.W #SS_SSig,D0
BNE.S SetStat1
*********************************************
* Send Signal on data ready
*
* INPUT d2.w user defined signal code
* OUTPUT none
*
TST.W V_ProcID(A2)
BNE NotRdyErr
MOVE.W PD_CPR(A1),D0 Requesters Process ID
MOVEA.L PD_RGS(A1),A4 Addr of caller's MPU Register Stack
MOVE.W R$d2+2(A4),D1 get signal code
MOVE SR,-(A7)
MOVE V_IRQMsk(A2),SR
TST.W V_InCnt(A2)
BNE.S Rel00 data ready --> go to send signal
* prepare Signal to be sent if char arrives
MOVE.W D0,V_ProcID(A2)
MOVE.W D1,V_SigCod(A2)
MOVE.W PD_PD(A1),V_PathNr(A2) nowhere else used !?!
MOVE.B V_IRQEn(A2),D3
*@ OR.B D3,(A5)
*@ MOVE.B (A5),IMR(A0) IRQ Mask Register
SSig01: MOVE (A7)+,SR
SSig02: CLR.W D1
RTS
SetStat1: CMPI.W #SS_Relea,D0 Release Device
BNE.S SetStat2
*********************************************
* Release device
*
* INPUT none
* OUTPUT none
*
MOVE.W PD_CPR(A1),D2 Requesters Process ID
LEA V_ProcID(A2),A3
BSR.S PrcIdTst test for correct proc. ID and path Nr.
TST.B V_Chanel(A2)
BEQ.S SSig02 Chanel A: return, no error
LEA V_SigBf2(A2),A3
BSR.S PrcIdTst
LEA V_SigBf1(A2),A3
BSR.S PrcIdTst
TST.W V_SigBf2(A2)
BNE.S SSig02
TST.W V_SigBf1(A2)
BNE.S SSig02
MOVE.B #BrgClk,ACR(A0) baudrateset and clocksource
MOVE SR,-(A7)
MOVE V_IRQMsk(A2),SR
*@ BCLR #7,(A5)
*@ BEQ.S SSig01
*@ MOVE.B (A5),IMR(A0)
BRA.S SSig01
Rel00: MOVE (A7)+,SR
BRA SendSig
*********************************************
* Test if current Process ID and Path Number matches
* values stored in SigBfx
*
* INPUT (a3) address of SigBfx
* d2.w current process ID
*
* OUTPUT Signal sent on match and SigBfx cleared,
* otherwhise nothing
*
PrcIdTst: CMP.W (A3),D2 test process ID
BNE.S PrcTst00
MOVE.W PD_PD(A1),D0 Path number
CMP.W $4(A3),D0 test Path Number
BNE.S PrcTst00
CLR.W (A3) clear process ID in SigBfx
PrcTst00: RTS
*
SetStat2: TST.B V_Chanel(A2)
BEQ.S SetStat4
CMPI.W #SS_DCOn,D0
BNE.S SetStat3
*********************************************
* Sends Signal when Data Carrier Detect line goes true
* (only Channel B)
*
* INPUT d2.w Signal Code to be sent
* OUTPUT none
*
LEA V_SigBf1(A2),A3
BRA.S Signal
SetStat3: CMPI.W #SS_DCOff,D0
BNE.S SetStat4
*********************************************
* Sends Signal when data detect carrier line goes false
* (only Channel B)
*
* INPUT d2.w Signal Code to be sent
* OUTPUT none
*
LEA V_SigBf2(A2),A3
Signal: MOVE.W PD_CPR(A1),(A3) Requesters process ID
MOVEA.L PD_RGS(A1),A4
MOVE.W R$d2+2(A4),2(A3) store Signal Code to SigBf2
MOVE.B PD_PD(A1),4(A3) store Path Number
MOVE.B #BrgClk+A_IP2Int,ACR(A0) enable IP2 change of state IRQ
MOVE SR,-(A7)
MOVE V_IRQMsk(A2),SR
*@ ORI.B #I_InpPrt,(A5) Inputport-change IRQ-Enable in IMR
* BSET #7,(A5) inputport-change IRQ enable in IMR
*@ BNE SSig01
TST.B IPCR(A0)
*@ MOVE.B (A5),IMR(A0)
BRA SSig01
SetStat4: CMPI.W #SS_EnRTS,D0
BNE.S SetStat5
*********************************************
* Enable RTS line (DTR-Line)
*
* INPUT none
* OUTPUT none
*
LEA OPRSet(A0),A0 set Output Port Bits
BRA.S SetOutput
SetStat5: CMPI.W #SS_DsRTS,D0
BNE.S SetStat6
*********************************************
* Disable RTS line (DTR-Line)
*
* INPUT none
* OUTPUT none
*
LEA OPRRes(A0),A0 reset Output Port Bits
SetOutput: MOVE.B V_DTRLine(A2),(A0)
BRA.S StatEnd
SetStat6: CMPI.W #SS_Break,D0
BNE StatErr
*********************************************
* Send Break
*
* INPUT none
* OUTPUT none
*
MOVEA.L V_PORT(A2),A3
MOVE.B #C_StrBrk,CR(A3)
MOVEQ #30,D0
OS9 F$Sleep
MOVE.B #C_StpBrk,CR(A3)
StatEnd: CLR.B D1
RTS
*********************************************
* Terminate device
*
* INPUT (a1) device descriptor pointer
* (a2) device static storage
* (a6) system global data
*
* OUTPUT none
*
* ERROR cc Carry set
* d1.w Error Code
*
Term00: MOVE.W V_BUSY(A2),V_WAKE(A2)
MOVE (A7)+,SR
PEA Term(PC)
BSR Sleep
ADDQ.L #4,A7
Term: MOVE.W P$ID(A4),V_BUSY(A2)
MOVE.W P$ID(A4),V_LPRC(A2)
MOVE SR,-(A7)
MOVE V_IRQMsk(A2),SR
TST.W V_OutCnt(A2)
BNE.S Term00 not all char sent
MOVEQ #50,D0
OS9 F$Sleep
MOVE.B V_IRQEn(A2),D0
NOT.B D0
MOVEA.L V_BaseAd(A2),A0
*@ LEA D_DuImr(A6),A5
* ADDA.W V_IBase(A2),A5
*@ AND.B D0,(A5)
*@ MOVE.B (A5),IMR(A0) disable all IRQ's for that channel
MOVE (A7)+,SR
MOVEA.L V_PORT(A2),A3
MOVE.B #$0A,CR(A3) disable Tx, Rx
MOVE.B V_RTSLine(A2),D0
OR.B V_DTRLine(A2),D0
MOVE.B D0,OPRRes(A0)
MOVE.B M$Vector(A1),D0
SUBA.L A0,A0
OS9 F$IRQ
RTS
*********************************************
* IRQ Service Routine
*
* INPUT (a2) static storage
* (a3) port address
* (a6) system global data
*
* USAGE d0 IRQ Status Register
* (a0) Baseaddress
*
IRQEnt: MOVEA.L V_BaseAd(A2),A0
MOVE.B ISR(A0),D0 get IRQ-Status
LEA D_DuImr(A6),A3
* ADDA.W V_IBase(A2),A3
AND.B (A3),D0
BNE.S IRQSvc
IRQErr: ORI #Carry,ccr
RTS
IRQSvc: TST.B V_Chanel(A2)
BEQ.S ChA_IRQ
* Channel B IRQ servicing
ANDI.B #$B0,D0 mask Input Port Change, RxRDY, TxRDY
BEQ.S IRQErr
MOVEA.L V_PORT(A2),A3
BTST #5,D0 RxRDY ?
BNE.S RxIRQ yes -->
BTST #7,D0 Input Port Change ?
BEQ TxIRQ no -->
* IRQ caused by Input Port Change
MOVE.B IPCR(A0),D1
BTST #6,D1 Delta IP2 ?
BEQ.S IRQRet
BTST #2,D1 IP2 ?
BNE.S IP2On
TST.W V_SigBf1(A2) any process waiting on signal ?
BEQ.S IRQRet no -->
MOVEM.W V_SigBf1(A2),D0-D1 send signal to waiting process
BSR SendSig
CLR.W V_SigBf1(A2)
TST.W V_SigBf2(A2) any process waiting on signal ?
BNE.S IRQRet
BRA.S DisIP2
IP2On: TST.W V_SigBf2(A2)
BEQ.S IRQRet
MOVEM.W V_SigBf2(A2),D0-D1
BSR SendSig
CLR.W V_SigBf2(A2)
TST.W V_SigBf1(A2)
BNE.S IRQRet
DisIP2: MOVE.L A5,-(A7)
MOVE.B #BrgClk,ACR(A0) disable IP2 IRQ
*@ LEA D_DuImr(A6),A5
* ADDA.W V_IBase(A2),A5
*@ BCLR #7,(A5)
*@ MOVE.B (A5),IMR(A0)
MOVEA.L (A7)+,A5
IRQRet: RTS
* Channel A IRQ servicing
ChA_IRQ: ANDI.B #$03,D0 mask TxRDY, RxRDY
BEQ IRQErr
MOVEA.L V_PORT(A2),A3
BTST #1,D0 RxRDY ?
BEQ.S TxIRQ no -->
* Receiver Rx Interrupt
RxIRQ: MOVE.B V_XOnFlg(A2),D1 XOn/XOff to send ?
BPL GetChar
BTST #S_TxRDY,SRAB(A3)
BEQ GetChar no -->
BCLR #7,D1 mask out XOn/XOff Code
MOVE.B D1,THR(A3) send XOn/XOff
MOVE.B V_XON(A2),D0
EOR.B D0,D1 d1=0 if XON sent
MOVE.B D1,V_XOnFlg(A2) d1<>0 (bit7=0) if XOff sent
BRA GetChar
* Transmitter Tx Interrupt
TxIRQ: MOVE.B V_XOnFlg(A2),D0
BPL.S SendDat
BCLR #7,D0
MOVE.B D0,THR(A3) send XOn/XOff
MOVE.B V_XON(A2),D1
EOR.B D1,D0
MOVE.B D0,V_XOnFlg(A2) mark if it was XOff
TST.B V_Flag(A2)
BNE.S SigIRQ no more data in buffer -> wakeup process
RTS
SendDat: MOVE.W V_OutCnt(A2),D0
BEQ.S TxEnd buffer empty -->
TST.B V_Flag(A2)
BNE.S SigIRQ no more data in buffer -> wakeup process
SUBQ.W #1,D0
MOVE.L A1,-(A7)
MOVEA.L V_WBufRd(A2),A1
MOVE.B (A1)+,THR(A3) send data
CMPA.L V_WBufEnd(A2),A1
BCS.S TxNorm00
LEA V_WBuf(A2),A1 reset buffer pointer
TxNorm00: MOVE.L A1,V_WBufRd(A2)
MOVEA.L (A7)+,A1
MOVE.W D0,V_OutCnt(A2)
CMPI.W #10,D0
BHI.S SdSigEnd --> return
TST.W D0
BNE.S WakeUp
TxEnd: BSET #1,V_Flag(A2) no char available
* Wakeup process gone to sleep due to writebuffer full
SigIRQ: MOVE.B V_Mask(A2),D0
MOVE.L A5,-(A7)
*@ LEA D_DuImr(A6),A5
* ADDA.W V_IBase(A2),A5
*@ AND.B D0,(A5)
*@ MOVE.B (A5),IMR(A0)
MOVEA.L (A7)+,A5
WakeUp: MOVEQ #S$Wake,D1
MOVE.W V_WAKE(A2),D0
SendS00: BEQ.S SdSigEnd no process waiting
CLR.W V_WAKE(A2)
*********************************************
* Subroutine to send a signal
*
SendSig: MOVEA.L D_SysDis(A6),A0
OS9call F$Send,A0
CLR.W D1
SdSigEnd: RTS
*********************************************
* test error condition and get char read
*
GetChar: MOVE.B SRAB(A3),D1
ANDI.B #E_FramEr+E_Parity+E_Overun,D1 mask errors
BEQ.S CtrlSeq no error -->
OR.B D1,V_ERR(A2)
MOVE.B #C_ResTrs,CR(A3)
NOP
* test for Controlsequences handled by the IRQ Server
CtrlSeq: MOVE.B RHR(A3),D0 get character
BEQ.S InsertCH
CMP.B V_INTR(A2),D0
BEQ CtrlC
CMP.B V_QUIT(A2),D0
BEQ CtrlE
CMP.B V_PCHR(A2),D0
BEQ Pause
CMP.B V_XON(A2),D0
BEQ XOn
CMP.B V_XOFF(A2),D0
BEQ XOff
*********************************************
* Insert Character in buffer
*
InsertCH: MOVE.L A1,-(A7)
MOVEA.L V_RBufWrt(A2),A1
MOVE.B D0,(A1)+ store char into buffer
ADDQ.W #1,V_InCnt(A2)
CMPI.W #RBufEnd-V_RBuf,V_InCnt(A2)
BLS.S BfNtFull
* Readbuffer full
SUBQ.W #1,V_InCnt(A2) Buffer full
MOVEA.L (A7)+,A1
BSET #4,V_ERR(A2)
BRA WakeUp
* Insert char in readbuffer
BfNtFull: CMPA.L V_RBufEnd(A2),A1
BCS.S Ins00
LEA V_RBuf(A2),A1 reset buffer pointer
Ins00: MOVE.L A1,V_RBufWrt(A2) update pointer
MOVEA.L (A7)+,A1 get data
MOVE.W V_ProcID(A2),D0 process to receive signal
BEQ.S Ins01
MOVE.W V_SigCod(A2),D1
CLR.W V_ProcID(A2)
BRA SendSig
Ins01: MOVE.B V_XOFF(A2),D0
BEQ.S Ins02 XOff disabled -->
CMPI.W #70,V_InCnt(A2)
BCS.S Ins02
MOVE.B V_XOnFlg(A2),D1
BNE.S Ins02
BCLR #7,V_XOFF(A2)
BSET #7,D0
MOVE.B D0,V_XOnFlg(A2)
MOVE.B V_IRQEn(A2),D0
MOVE.L A5,-(A7)
*@ LEA D_DuImr(A6),A5
* ADDA.W V_IBase(A2),A5
*@ OR.B D0,(A5)
*@ MOVE.B (A5),IMR(A0)
MOVEA.L (A7)+,A5
NOP
Ins02: BTST #S_RxRDY,SRAB(A3)
BEQ WakeUp
BRA GetChar get next char already available
*********************************************
* Routines to perform Control Sequence Commands
*
Pause: TST.L V_DEV2(A2) address of attached device
BEQ InsertCH
move.l a0,-(a7)
lea V_DEV2(A2),A0
move.b d0,V_PAUS(A0)
move.l (a7)+,a0
* MOVE.B D0,([V_DEV2,A2],V_PAUS)
BRA InsertCH
CtrlC: MOVEQ #S$Intrpt,D1
BRA.S CtrlCE
CtrlE: MOVEQ #S$Abort,D1
CtrlCE: MOVE.B D0,-(A7)
MOVE.W V_LPRC(A2),D0 last active process ID
BSR SendS00
MOVE.B (A7)+,D0
BRA InsertCH
XOn: BCLR #0,V_Flag(A2)
TST.B V_Flag(A2)
BNE.S XEnd --> char to write in buffer
MOVE.B V_IRQEn(A2),D0
MOVE.L A5,-(A7)
*@ LEA D_DuImr(A6),A5
* ADDA.W V_IBase(A2),A5
*@ OR.B D0,(A5)
*@ MOVE.B (A5),IMR(A0)
MOVEA.L (A7)+,A5
NOP
BTST #S_TxRDY,SRAB(A3)
BEQ.S XEnd no -->
BRA TxIRQ
XOff: BSET #0,V_Flag(A2)
XEnd: MOVEQ #0,D1
RTS
ends
* E O F *