;[101] 27 May 1992 12:14 Edited by InterLink Systems, Inc
; Fix problem when using flow control
;[102] 30 NOV 1993 MP WSOL, Alpha Microsystems
; Update for RoadRunner Support
; This driver is for non-intelligent boards, (ie. no-Z80).
; Have tested with 16-port Revision B artwork.
VMAJOR = 2
VMINOR = 0
VWHO = 0
VSUB = 0
VEDIT = 102.
RADIX 16.
;[102] Updated for 32 bit addressing
INTADD = ^H0FFFFFF90 ; Interrupt address
AVLPIN = RS%RTS
DEFINE CCC LABEL
BCS 10$$
CALL LABEL
10$$:
ENDM
START: PHDR -1,0,0
BR CHROUT ; Character output routine
BR INIT ; Initialize port
BR 10$ ; Get the PIN status
BR 20$ ; Set the PIN status
WORD ^H0A5A5 ; Magic word for new driver
LWORD AVLPIN ; Available pin numbers
;--------- Start of Driver ------------
10$: JMP GETPIN
20$: JMP SETPIN
CHROUT: SAVE D2,A3 ; Save used registers
MOV T.IHM(A5),D0 ; Get interface port number
LEA A3,PORTS ; Index initialized flag
MOVW @A3,D2 ; Get the flag
BTST D0,D2 ; Test initilazed bit
BEQ IGNXIT ; Branch if not
MOV T.IHW(A5),A3 ; Get hardware address
MOVB #5,2(A3) ; Enable Interupt on port
IGNXIT: REST A3,D2 ; Restore used register
RTN
INIT: CMP D0,#18. ; Max baud rate (38400 baud)
JHIS BAUDER ; Above max
LEA A0,INTRPT ; Index interupt routine
MOV A0,064 ; Save in vector
LEA A0,PORTS ; Port inited indicator
MOVW @A0,D2 ; Get previous inited port
MOV T.IHM(A5),D1 ; Get port number
XORB #1,D1 ; Get other channel
BTST D1,D2 ; Has the other chanel been inited?
JEQ NEWINI ; Nope
LEA A0,BVAL ; Get baud value used on other port
CLR D3
MOVB 0(A0)[D1],D3
BTST #7,D3 ; Acr=1?
JEQ TRYB0
LEA A0,BAUD1 ; Index the baud rate table ACR=1
MOVB 0(A0)[D0],D4 ; Is it a valid baud rate?
CMPB D4,#-1
BEQ CHGB0 ; no - invalid baud rate
BCLR #7,D3
MOVB 0(A0)[D3],D4 ; Other channel also supported
CMPB D4,#-1
BEQ CHGB0
BSET #7,D0 ; Use ACR=1
JMP SBAUD
; Try to change to ACR=0
CHGB0: LEA A0,BAUD0
MOVB 0(A0)[D0],D4 ; Both baud rates defined
CMPB D4,#-1
JEQ BAUDER
BCLR #7,D3
MOVB 0(A0)[D3],D4
CMPB D4,#-1
JEQ BAUDER
SAVE D0,A5 ; Reset baud rate on other channel
MOV D3,D0 ; Old baud rate
LEA A0,TCB0
LSL D1,#2 ; Port NUM * $ for LWORD offset
MOV 0(A0)[D1],A5 ; Pntr to other chan trmdef block
BCLR #7,D0 ; Use ACR=0
CALL PINIT ; Init other chanel
REST A5,D0
JMP SBAUD
TRYB0: LEA A0,BAUD0 ; Index baud rate table ACR=0
MOVB 0(A0)[D0],D4
CMPB D4,#-1
BEQ CHGB1
BCLR #7,D3
MOVB 0(A0)[D3],D4
CMPB D4,#-1
JNE SBAUD ; Set baud rate to ACR=0
; Try to change ACR=1
CHGB1: LEA A0,BAUD1
MOVB 0(A0)[D0],D4 ; Both baud rate defined
CMPB D4,#-1
JEQ BAUDER
BCLR #7,D3
MOVB 0(A0)[D3],D4
CMPB D4,#-1
JEQ BAUDER
SAVE D0,A5 ; Reset baud rate on other channel
MOV D3,D0 ; Old baud rate
BSET #7,D0 ; Indicate that port has ACR=1
LEA A0,TCB0
LSL D1,#2 ; Port NUM * 4 for LWORD offset
MOV 0(A0)[D1],A5 ; Pntr to other chan trmdef block
CALL PINIT ; Init other channel
REST A5,D0
BSET #7,D0 ; Use ACR=1 on ther port
JMP SBAUD
BAUDER: TYPECR <Invalid BAUD RATE for 16 port>
ERRXIT: RTN
NEWINI: LEA A0,BAUD1 ; Index the baud rate table ACR=1
MOVB 0(A0)[D0],D4 ; Is it a valid baud rate?
CMPB D4,#-1
BEQ NOTB0
BSET #7,D0 ; ACR=1
JMP SBAUD
SBAUD:
; Get port number and base address of DUART and channel
PINIT: LEA A0,BAUD0
MOV D0,D3
CLR D6
BCLR #7,D0 ; Baud1?
BEQ ACR0
LEA A0,BAUD1
MOVB #^H80,D6 ; ACR Value
ACR0: ADD D0,A0 ; Offset to baud rate init value
MOV T.IHM(A5),D2 ; Use port number displacement
LEA A1,BVAL ; Save baud rate value on cur port
MOVB D3,0(A1)[D2]
LEA A1,ADDTBL ; Index port address table
MOV D2,D3
SUB A3,A3 ; Clear A3
BCLR #0,D2 ; Even or odd port
BEQ EADDR
MOV #8,A3 ; Base address of second channel
EADDR: LSL D2,#1
ADD D2,A1
MOV @A1,A2
ADD A2,A3
MOVB D6,4(A2) ; Set Aux control register
MOVB @A0,D1
ROLB D1,#4
ORB @A0,D1
MOVB D1,1(A3) ; Clock select
MOVB #010,2(A3) ; Reset MR Pointer
MOVB #020,2(A3) ; Reset receiver
MOVB #030,2(A3) ; Reset transmitter
MOVB #040,2(A3) ; Reset error status
MOVB 1(A3),D1 ; Read status register A
INCB D1
BNE 5$
TYPECR <16 Port not detected>
JMP ERRXIT
5$: MOVB #013,@A3 ; Setup Register 1
MOVB #017,D1 ; One stop bit
CMPB D0,#4 ; Did we want 110 baud
BNE 10$ ; No, Branch
MOVB #01F,D1 ; Set 2 stop bits
10$: MOVB D1,@A3 ; Output control bits for Register 2
MOVB #0A,2(A3) ; Disable RCV and XMIT
CLR D1 ; Init enabled on uarts
MOVB #3,D1
BTST #0,D3 ; Channel A?
BEQ 40$ ; Go if true
ROLB D1,#4 ; Shift up for Channel B
40$: LEA A0,IMASK1 ; Base address of IMR byte table
MOV D3,D2 ; Save channel number
LSR D2,#1 ; Index correct mask register
ADD D2,A0
ORB D1,@A0 ; Add to existing mask value
MOVB @A0,D1 ; D1 Reflects both channels
MOVB D1,5(A2) ; Program DUART
; Enable RTS
MOVB #5,D1 ; Setup channel A
BTST #0,D3 ; Test if channel B
BEQ 50$
MOVB #012,D1 ; Setup channel B
50$: LEA A0,OPBIT1 ; Base of output byte table
ADD D2,A0
ORB D1,@A0 ; Add to existing bit pattern
MOVB @A0,D1 ; D1 reflects both channels
MOVB D1,0E(A2) ; Set output port bits
MOVB #0,0D(A2) ; Output port configuration
; Set local memory flag and pointers
LEA A0,PORTS ; Port inited indicator
MOVW @A0,D2 ; Get previous inited ports
BSET D3,D2 ; Mark current port as inited
MOVW D2,@A0 ; Save indicator
LSL D3,#2 ; Index long words
LEA A0,TCB0
ADD D3,A0
MOV A5,@A0 ; Trmdef block address
MOV A3,T.IHW(A5) ; Save duart address in trmdef block
MOVB #1,2(A3) ; Enable receiver interupt
RTN
GETPIN: CLR D6
MOV #AVLPIN,D7
RTN
SETPIN: RTN
INTRPT: SAVE D0-D7,A0-A6 ; Save used registers
MOV #INTADD,A0 ;[102] Index interupt regsiter
MOVB @A0,D0 ; Get the port mask
CLR D2 ; Set port number
MOVW #3,D3 ; Set mask byte
RORB D0,#1 ; Shift into CC register
CCC DOIO ; Branch if needs work
LSLW D3,#2 ; Shift mask
ADD #2,D2 ; Index port
RORB D0,#1 ; Shift in next bit
CCC DOIO
LSLW D3,#2
ADD #2,D2
RORB D0,#1
CCC DOIO
LSLW D3,#2
ADD #2,D2
RORB D0,#1
CCC DOIO
LSLW D3,#2
ADD #2,D2
RORB D0,#1
CCC DOIO
LSLW D3,#2
ADD #2,D2
RORB D0,#1
CCC DOIO
LSLW D3,#2
ADD #2,D2
RORB D0,#1
CCC DOIO
LSLW D3,#2
ADD #2,D2
RORB D0,#1
CCC DOIO
REST D0-D7,A0-A6
RTE
DOIO: SAVE D0,D2,D3
ANDW PORTS,D3 ; Get Mask port initialized
BEQ DONE ; Branch if not initialized
LEA A2,ADDTBL ; Index address table
ADDW D2,D2 ; Double port number
MOV 0(A2)[D2],A2 ; Get address of port
LEA A5,TCB0 ; Index baud rate table
ADDW D2,D2 ;
MOVB 5(A2),D7 ; Get status register B
ANDB #3,D7 ; Mask off status bits
BNE 10$ ; Branch
ADDW #4,D2
10$: MOV 0(A5)[D2],A5 ; Get TCB
MOV T.IHW(A5),A4 ; Index hardware address
MOVB 1(A4),D5 ; Get uart status
BTST #0,D5 ; Test data in available
BEQ 30$ ; Branch if no data
MOVB 3(A4),D1 ; Get data character
MOV T.INC(A5),D7 ; Input char routine?
BNE 20$ ; Branch one
TRMICP ; Put into input buffer
BR 30$ ; Try output
30$: BTST #2,D5 ; Test data out possible
BEQ DONE ; Exit if not [101]
MOV T.OTC(A5),D7 ; Get output character link
BNE DONE ; Branch if ALT input
TRMOCP
40$: TST D1 ; Any character available?
BMI 60$ ; Yes, branch
50$: MOVB D1,3(A4) ; Output data to port
BR DONE
60$: ANDW #^C80,@A5 ; Clear the OIP bit
MOVB #8,2(A4) ; Disable Interupt on port
BR DONE
70$: MOV D7,A6 ; Get into register
CALL @A6 ; Call alt output routine
BR 40$ ; Back to routine