SEARCH  SYS
       SEARCH  SYSSYM
       SEARCH  TRM

       OBJNAM  0,0,[IDV]

;[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

NOTB0:  LEA     A0,BAUD0                ; Index baud rate table ACR=0
       MOVB    0(A0)[D0],D4
       CMPB    D4,#-1
       JEQ     BAUDER

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

20$:    MOV     D7,A6                   ; Move address into register
       CALL    @A6                     ; Call input routine

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

DONE:   REST    D0,D2,D3
       RTN

BAUD1:  BYTE    -1                      ; 50    0
       BYTE    0                       ; 75    1
       BYTE    1                       ; 110   2
       BYTE    2                       ; 134.5 3
       BYTE    3                       ; 150   4
       BYTE    -1                      ; 200   5
       BYTE    4                       ; 300   6
       BYTE    5                       ; 600   7
       BYTE    6                       ; 1200  8
       BYTE    0A                      ; 1800  9
       BYTE    07                      ; 2000  10
       BYTE    08                      ; 2400  11
       BYTE    -1                      ; 3600  12
       BYTE    9                       ; 4800  13
       BYTE    -1                      ; 7200  14
       BYTE    0B                      ; 9600  15
       BYTE    0C                      ; 19200 16
       BYTE    -1                      ; 38400 17
       BYTE    0                       ; 57600 18      (Clk/4) (Not Valid)

BAUD0:  BYTE    0                       ; 50    0
       BYTE    -1                      ; 75    1
       BYTE    1                       ; 110   2
       BYTE    2                       ; 134.5 3
       BYTE    -1                      ; 150   4
       BYTE    3                       ; 200   5
       BYTE    4                       ; 300   6
       BYTE    5                       ; 600   7
       BYTE    6                       ; 1200  8
       BYTE    -1                      ; 1800  9
       BYTE    -1                      ; 200   10
       BYTE    8                       ; 2400  11
       BYTE    -1                      ; 3600  12
       BYTE    9                       ; 4800  13
       BYTE    0A                      ; 7200  14
       BYTE    0B                      ; 9600  15
       BYTE    -1                      ; 19200 16
       BYTE    0C                      ; 38400 17
       BYTE    0                       ; 57600 18      (Clk/4) (Not Valid)
       EVEN

BVAL:   BLKB    16.
       EVEN
;[102]  Updated for 32 bit Adressing
ADDTBL: LWORD   0FFFFFF10
       LWORD   0FFFFFF20
       LWORD   0FFFFFF30
       LWORD   0FFFFFF40
       LWORD   0FFFFFF50
       LWORD   0FFFFFF60
       LWORD   0FFFFFF70
       LWORD   0FFFFFF80

TCB0:   BLKL    16.

PORTS:  WORD    0

IMASK1: BLKB    16.
OPBIT1: BLKB    16.
       EVEN


       END