;**************************************************************
;*                                                            *
;*     INNER ACCESS 8 PORT SERIAL I/O DRIVER                  *
;*                                                            *
;**************************************************************
;
; REVISED 12/31/83 GW
; totally re-worked at Computerized Business Systems by NED 1/22/85
;     increased efficiency & reliability of interrupt routine
;     and multiple board handling.
;

       SEARCH  SYS
       SEARCH  TRM

       OBJNAM  .IDV

       RADIX   16.

IOADR   =       0FFFF20                 ; base i/o addr
NUMBRD  =       1                       ; max boards supported
AMV     =       7                       ; interrupt vector
BRTABL  =       2                       ; baud rate selection table (1 or 2)

; Terminal Driver Communications Area
IO8:
       BR      COUT
       BR      INIT
COUT:   JMP     CHROUT

;
; Initialize Port Number to Baud Rate in D0
;
INIT:   MOV     #IOADR,A4               ; get base address
       MOV     T.IHM(A5),D5            ; get port number
       CMP     D5,#<<NUMBRD*8>-1>      ; greater than configuration?
       JGT     INIX                    ; yes - its in error
       CLR     D1                      ;
       LSR     D5,#3                   ; calc board select
       BSET    D5,D1                   ;
       MOVB    D1,11(A4)               ; enable one of eight boards
       MOV     T.IHM(A5),D5            ; get port number
       AND     #7,D5                   ; mask for duart select
       LSR     D5,#1                   ; calc duart select code
       CLR     D1
       BSET    D5,D1                   ; enable duart chip
       MOVB    D1,10(A4)               ;
       MOVB    #033,5(A4)              ; enable chip interrupts
       ADD     #3,A4                   ; initially select channel a
       MOV     T.IHM(A5),D5            ; get port number
       AND     #1,D5                   ; even or odd?
       BEQ     INIT1                   ; even select channel a
       ADD     #8,A4                   ; select channel b

;Initialize Duart
INIT1:  MOV     A4,T.IHW(A5)            ; save selected data port
       MOVB    #30,-1(A4)              ; reset mr1 pointer & receiver
       MOVB    #13,-3(A4)              ; set no parity, 8 bits, no rx rts
       MOVB    #17,-3(A4)              ; set no tx rts,cts,1 stop bit
       ASL     D0,#1                   ; turn baud rate code into offset
       LEA     A0,BAUDTB               ; get base of baud rate table
       MOVB    0(A0)[D0],D5            ; get first byte of entry
       CMPB    D5,#-1                  ; is this a valid entry?
       BNE     10$                     ; no - display message
       CALL    BDBAUD
       MOVB    #0BB,D5
       MOVB    D5,-2(A4)
       BR      20$
10$:    MOVB    D5,1(A4)                ; yes - use it
       MOVB    1(A0)[D0],-2(A4)        ; send second byte of entry

; Store the Terminal Definition Table Base for this port
20$:    LEA     A6,TRMTBL
       MOV     T.IHM(A5),D5            ; get port number
       LSL     D5,#2                   ; turn into offset
       MOV     A5,0(A6)[D5]            ; store terminal def address

; Initialize the Interrupt Vector
       LEA     A1,INTRPT               ; index interrupt routine
       MOV     A1,<11C-<AMV*4>>        ; store interrupt address
       MOVB    #09,-1(A4)              ; enable rcv , disable xmit
       RTN

INIX:   CRLF
       TYPECR  ?Unsupported Port Number
       RTN

BDBAUD: TYPECR  ?Invalid baud rate will default to 9600
       RTN

;*************
;*  CHROUT   *
;*************
; Initiate Output to Port
CHROUT: MOV     #IOADR,A6               ; get base address
       MOV     T.IHM(A5),D7            ; get port #
       LSRW    D7,#3                   ; calc board number
       CLRB    D1
       BSET    D7,D1                   ; form board select code
       MOVB    D1,11(A6)               ; enable one of 8 i/o boards
       MOV     T.IHM(A5),D7            ; get port # again
       AND     #7,D7                   ; mask for duart select
       LSRW    D7,#1                   ; calc chip number
       CLRB    D1                      ;
       BSET    D7,D1                   ; form chip select code
       MOVB    D1,10(A6)               ; enable duart chip
       MOV     T.IHW(A5),A6            ; get ch data port address
       MOVB    #4,-1(A6)               ; enable channel xmit
       RTN

;***********************
;*  INTERRUPT ROUTINE  *
;***********************
INTRPT: SVLOK                           ; lock processor
       SAVE    D1-D7,A4-A6
       MOV     #IOADR,A4
       CLR     D4                      ; board number
       CLR     D5                      ; will be chip number

INLUP:  CLRB    D7
       BSET    D4,D7                   ; set up board enable code
       MOVB    D7,11(A4)               ; enable board
       MOVB    10(A4),D3               ; get interrupt status register
       COMB    D3                      ; reverse bits
       BNE     INLP1                   ; is int. coming from this board?
N.BRD:  ADDW    #1,D4                   ; no - increment board number
       CMPB    D4,#NUMBRD              ; is it greater than our configuration
       BLT     INLUP                   ; no - check next board
       REST    D1-D7,A4-A6
       RTE

; D3 contains bits indicating chips generating interrupts
INLP1:  BTST    D5,D3                   ; test for chip number in D5
       BNE     INLP2                   ; its this one - go get it
N.CHP:  ADDW    #1,D5                   ; increment to next chip
       CMPB    D5,#4                   ; have we checked all chips?
       BLT     INLP1                   ; no - do next one
       CLRW    D5
       BR      N.BRD                   ; yes - continue on

; D4 contains board number
; D5 contains chip number
INLP2:  CLRB    D7
       BSET    D5,D7                   ; form chip select code
       MOVB    D7,10(A4)               ; select chip
       MOVW    D4,D2                   ; get board number
       LSLW    D2,#5                   ; multiply by 32 to form offset
       MOVW    D5,D7                   ; save chip number
       LSLB    D7,#3                   ; chip number X 8 to form offset
       ADDW    D7,D2                   ; form port number X 4
       MOVB    5(A4),D1                ; read int. status register
       ANDB    #03,D1                  ; is it Ch. A ?
       BEQ     10$                     ; yes - process
       CALL    INTPRT
10$:    ADDW    #4,D2                   ; no - increment to CH. B
       MOVB    5(A4),D1                ; read int. status register
       LSRB    D1,#4                   ; shift down for processing
       ANDB    #03,D1                  ; is it CH. B ?
       BEQ     20$                     ; yes - process
       CALL    INTPRT
20$:    BR      INLUP                   ; go check for more interrupts

INTPRT: MOV     TRMTBL[~D2],A5          ; get address of Terminal Table
       BTST    #0,D1                   ; is it the transmitter?
       BNE     TX.INT                  ; yes - go process
;
; PROCESS RECEIVE INTERRUPT
;
       MOV     T.IHW(A5),A6            ; get hardware address of port
       MOVB    @A6,D1                  ; get character from port
       TRMICP                          ; and process it
       RTN

;
; PROCESS TRANSMIT INTERRUPT
;
TX.INT: TRMOCP                          ; get next character to output
       MOV     T.IHW(A5),A6            ; get hardware address of port
       TST     D1                      ; check for valid character
       BMI     NO.MOR                  ; yes - output it
       MOVB    D1,@A6
       RTN

NO.MOR: ANDW    #^C<OIP>,@A5            ; clear output in progress flag
       MOVB    #8.,-1(A6)              ; and disable xmitter
       RTN
;
; Table to store addresses of Terminal Definition Tables for each port
TRMTBL:
       LWORD   0                       ; port 0
       LWORD   0                       ; port 1
       LWORD   0                       ; port 2
       LWORD   0                       ; port 3
       LWORD   0                       ; port 4
       LWORD   0                       ; port 5
       LWORD   0                       ; port 6
       LWORD   0                       ; port 7

IF      GE,NUMBRD-2
       LWORD   0                       ; port 8
       LWORD   0                       ; port 9
       LWORD   0                       ; port 10
       LWORD   0                       ; port 11
       LWORD   0                       ; port 12
       LWORD   0                       ; port 13
       LWORD   0                       ; port 14
       LWORD   0                       ; port 15
ENDC

IF      GE,NUMBRD-3
INTTB3: LWORD   0                       ; port 16
       LWORD   0                       ; port 17
       LWORD   0                       ; port 18
       LWORD   0                       ; port 19
       LWORD   0                       ; port 20
       LWORD   0                       ; port 21
       LWORD   0                       ; port 22
       LWORD   0                       ; port 23
ENDC

IF      GE,NUMBRD-4
INTTB4: LWORD   0                       ; port 24
       LWORD   0                       ; port 25
       LWORD   0                       ; port 26
       LWORD   0                       ; port 27
       LWORD   0                       ; port 28
       LWORD   0                       ; port 29
       LWORD   0                       ; port 30
       LWORD   0                       ; port 31
ENDC

IF      GE,NUMBRD-5
INTTB5: LWORD   0                       ; port 32
       LWORD   0                       ; port 33
       LWORD   0                       ; port 34
       LWORD   0                       ; port 35
       LWORD   0                       ; port 36
       LWORD   0                       ; port 37
       LWORD   0                       ; port 38
       LWORD   0                       ; port 39
ENDC

IF      GE,NUMBRD-6
INTTB6: LWORD   0                       ; port 40
       LWORD   0                       ; port 41
       LWORD   0                       ; port 42
       LWORD   0                       ; port 43
       LWORD   0                       ; port 44
       LWORD   0                       ; port 45
       LWORD   0                       ; port 46
       LWORD   0                       ; port 47
ENDC

IF      GE,NUMBRD-7
INTTB7: LWORD   0                       ; port 48
       LWORD   0                       ; port 49
       LWORD   0                       ; port 50
       LWORD   0                       ; port 51
       LWORD   0                       ; port 52
       LWORD   0                       ; port 53
       LWORD   0                       ; port 54
       LWORD   0                       ; port 55
ENDC

IF      GE,NUMBRD-8.                    ;
INTTB8: LWORD   0                       ; port 56
       LWORD   0                       ; port 57
       LWORD   0                       ; port 58
       LWORD   0                       ; port 59
       LWORD   0                       ; port 60
       LWORD   0                       ; port 61
       LWORD   0                       ; port 62
       LWORD   0                       ; port 63
ENDC


;Define baud rate table

IF      EQ,BRTABL-1
BAUDTB:
       BYTE    0,00                    ; 50 baud
       BYTE    -1,00                   ; 75 baud
       BYTE    0,11                    ; 110 baud
       BYTE    0,22                    ; 134.5 baud
       BYTE    -1,33                   ; 150 baud
       BYTE    0,33                    ; 200 baud
       BYTE    0,44                    ; 300 baud
       BYTE    0,55                    ; 600 baud
       BYTE    0,66                    ; 1200 baud
       BYTE    -1,0AA                  ; 1800 baud
       BYTE    -1,77                   ; 2000 baud
       BYTE    0,088                   ; 2400 baud
       BYTE    -1,-1                   ; 3600 baud
       BYTE    0,099                   ; 4800 baud
       BYTE    0,0AA                   ; 7200 baud
       BYTE    0,0BB                   ; 9600 baud
       BYTE    -1,0CC                  ; 19200 baud
       BYTE    0,0CC                   ; 38400 baud

       EVEN
ENDC

IF      EQ,BRTABL-2
BAUDTB:
       BYTE    -1,00                   ; 50 baud
       BYTE    80,00                   ; 75 baud
       BYTE    80,11                   ; 110 baud
       BYTE    80,22                   ; 134.5 baud
       BYTE    80,33                   ; 150 baud
       BYTE    -1,33                   ; 200 baud
       BYTE    80,44                   ; 300 baud
       BYTE    80,55                   ; 600 baud
       BYTE    80,66                   ; 1200 baud
       BYTE    80,0AA                  ; 1800 baud
       BYTE    80,77                   ; 2000 baud
       BYTE    80,088                  ; 2400 baud
       BYTE    -1,-1                   ; 3600 baud
       BYTE    80,099                  ; 4800 baud
       BYTE    80,0AA                  ; 7200 baud
       BYTE    80,0BB                  ; 9600 baud
       BYTE    80,0CC                  ; 19200 baud
       BYTE    -1,0CC                  ; 38400 baud
       BYTE    -1,-1

       EVEN
ENDC

       END