;*; Updated on 25-Nov-91 at 8:29 AM by Michele Tonti; edit time: 0:00:39
;*************************** AMUS Program Label ******************************
; Filename: PI6P.M68                                        Date: 11/25/91
; Category: TDV          Hash Code: 771-613-663-463      Version:
; Initials: GR/AM        Name: James A. Jarboe IV
; Company: Educational Video Network, Inc.         Telephone #: 4092955767
; Related Files:
; Min. Op. Sys.:                               Expertise Level:
; Special:
; Description: Modified driver for Piiceon 6 port serial I/O board.  Modified
; to work under AMOS 1.4 and 2.x
;
;*****************************************************************************
;*; Updated on 23-Nov-91 at 4:52 AM by James A. Jarboe I V; edit time: 1:10:49
;***************************************************************************
;                                                                          *
;                P I I C E O N   6   P O R T   D R I V E R                 *
;                                                                          *
;***************************************************************************
;
; This driver, for the Piiceon 6 port I/O board, can be assembled 2 ways.
; /V:0 - For AMOS 1.3C and earlier versions.
; /V:1 - For AMOS 1.3D and greater versions which include AMOS 2.x
;
; Modifications for 1.3D and greater versions were made by
; James A. Jarboe IV. In addition to making modifications so that
; this driver will work on AMOS 2.x, Minor modifications where also
; made to existing code.

       SEARCH  SYS
       SEARCH  SYSSYM
       SEARCH  TRM

       OBJNAM  PI6P.IDV

; Get Assembly options
; /V:0 - AMOS 1.3C or <  (Assembles to original hash)  245-560-543-501
; /V:1 - AMOS 1.3D or >  (Assembles with changes) 655-571-436-333 2.0(100)


       NVALU   OPTION


       PAGE
;***************************************************************************
;                                                                          *
;                              V E R S I O N                               *
;                                                                          *
;***************************************************************************
; Edit history:
;
; 2.0 [100] 23-Nov-91 by James A. Jarboe I V
;           Added COMSER Stuff for 2.x
;           Modified some message text.
;

       VMAJOR  =       2.              ; Current 1.3D - 2.x version.
       VMINOR  =       0.
       VEDIT   =       100.            ; James A. Jarboe I V

       PAGE
;***************************************************************************
;                                                                          *
;                      D R I V E R   C O N S T A N T S                     *
;                                                                          *
;***************************************************************************
;

INTVEC  =       ^H064                   ; Interrupt port address.

INTAD1  =       ^H0FFFF60               ; Address of interrupt vector.
INTAD2  =       ^H0FFFF40
INTAD3  =       ^H0FFFF20

; Define 2681 Command register bits.

CM$RMRP =       20              ; Reset mode register pointer
CM$RRCV =       40              ; Reset receiver
CM$RTXM =       60              ; Reset transmitter
CM$REST =       100             ; Reset error status
CM$RXEN =       1               ; Receiver enable
CM$RXDI =       2               ; Receiver disable
CM$TXEN =       4               ; Transmitter enable
CM$TXDI =       10              ; Transmitter disable

; Define 2681 Mode Register 1 bits

M1$8B   =       3                       ; 8 bits per character.
M1$NP   =       20                      ; No parity

; Define 2681 Mode Register 2 bits

M2$1SB  =       7                       ; 1 stop bit.
M2$2SB  =       17                      ; 2 stop bits.
M2$NM   =       0                       ; Normal channel mode.
M2$CET  =       20                      ; CTS enables transmitter.

;
RS$RTS  =       ^H10                    ; Request to send.
RS$CTS  =       ^H20                    ; Clear to send.
RS$DCD  =       ^H100                   ; Recieve line signal or DCD.

AVLPIN  =       RS$DCD!RS$CTS!RS$RTS    ; Available pins.
                                       ;

       PAGE
;***************************************************************************
;                                                                          *
;                          P I 6 P   D R I V E R                           *
;                                                                          *
;***************************************************************************
;
;
       ASMMSG  " "

PI6P:
       IF      NE,OPTION               ; AMOS/L 1.3D or greater.

       ASMMSG "Assembling PI6P for AMOS/L 1.3D or greater "
        PHDR   -1,0,0
        BR     CHROUT                  ; Character output.
        BR     INIT                    ; Initialize ports.
        BR     20$                     ; GETPIN
        BR     30$                     ; SETPIN
        LWORD  ^H0A5A5                 ; Flag word.
        LWORD  AVLPIN                  ; Available flags.
20$:     JMP    GETPIN                  ; Vector to GETPIN.
30$:     JMP    SETPIN                  ; Vector to SETPIN.

       IFF                             ; AMOS/L 1.3C or less.

       ASMMSG "Assembling PI6P for AMOS/L 1.3C or less    "
        BR     CHROUT                  ; Character output.
        BR     INIT                    ; Initialize ports.
        NOP                            ;
        JMP    CHROUT                  ;
       ENDC
       ASMMSG " "


;***************************************************************************
;                                                                          *
;                               C H R O U T                                *
;                                                                          *
;***************************************************************************
; Character output routine.
;
CHROUT: SAVE    D2,A3
       MOV     T.IHM(A5), D0           ; Get port number.
       LEA     A3,PORTS                ; Port inited indicator.
       MOVW    @A3,D2                  ; Get previous inited ports
       BTST    D0,D2                   ; Has channel been inited
       JEQ     IGNXIT                  ; Nope.
       MOV     T.IHW(A5), A3           ; Get base address of I/O port.
       MOVB    #5,4(A3)                ; Xmit enable = ff,,port num
IGNXIT: REST    A3,D2                   ; Restore registers.
       RTN                             ; Return to caller.


       PAGE
;***************************************************************************
;                                                                          *
;                               I N I T                                    *
;                                                                          *
;***************************************************************************
; Initialize the board.
;
INIT:
       CMP     D0, #18.                ; Test baud rate.
       JCC     BAUDER                  ; Is greater than 0-17.
       LEA     A0,INTRPT               ; Get address of interrupt routine.
       MOV     A0,INTVEC               ; Save in autovector.
NOTFST:
       LEA     A0,PORTS                ; If first call, init all ports
       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 other channel been inited?
       JEQ     NEWINI                  ; Nope.

       LEA     A0,BVAL                 ; Get baud value used on other port.
       CLR     D3
       MOVB    0(A0)[D1],D3            ; Offset to port
       BTST    #7.,D3
       JEQ     TRYB0                   ;

       LEA     A0,BAUD1                ; Index baud rate table.
       MOVB    0(A0)[D0],D4            ; Is it a valid 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
       JMP     SBAUD

CHGB0:
       LEA     A0,BAUD0
       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.
       LEA     A0,TCB0
       LSL     D1,#2                   ; Port num * 4 for lword offset.
       MOV     0(A0)[D1],A5            ; Pointer to other chn trmdef blk.
       BCLR    #7.,D0                  ; Use ACR=0
       CALL    SBAUD
       REST    A5,D0
       JMP     SBAUD

TRYB0:
       LEA     A0, BAUD0
       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

CHGB1:  LEA     A0,BAUD1
       MOVB    0(A0)[D0],D4
       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            ; Pointer to other chan trmdef blk
       CALL    SBAUD                   ; Init other channel
       REST    A5,D0                   ;
       BSET    #7.,D0                  ; Use ACR=1 on new port
       JMP     SBAUD

; Yes, the message for the earlier version is wrong but this keeps the
; hash right and the correction is in the new version.
;
BAUDER:
       IF      NE, OPTION
       TYPECR  <Invalid BAUD RATE for PIICEON 6 Port Board>
       IFF
       TYPECR  <Invalid BAUD RATE for 16 port>
       ENDC
ERRXIT: RTN

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

       IF      NE,OPTION
GETPIN:
       CLR     D6                      ; Clear port status bits.
       BSET    #RS.DCD, D6             ; Say we have DCD
       BSET    #RS.CTS, D6             ; Say we have CTS
       CLR     D7
       MOV     #AVLPIN, D7             ; Say we have these pins.
       RTN

;
SETPIN:
       RTN                             ; Return nothing.

       ENDC

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


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
       JEQ     NOTB0
       BSET    #7.,D0
       JMP     SBAUD

NOTB0:  LEA     A0, BAUD0
       MOVB    0(A0)[D0],D4            ;
       CMPB    D4,#-1
       JEQ     BAUDER

SBAUD:
       LEA     A0, BAUD0
       MOV     D0,D3
       CLR     D6
       BCLR    #7.,D0                  ; Baud 1?
       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 # as displacement.
       LEA     A1,BVAL                 ; Save baud rate value on curr port.
       MOVB    D3,0(A1)[D2]
       LEA     A1,BPADR
       MOV     D2,D3                   ; Save a copy.
       SUB     A3,A3
       BCLR    #0,D2                   ; Even or odd port.
       BNE     EADDR
       MOV     #16., A3                ; Base address of channel.

EADDR:  LSL     D2,#1                   ; Base address of uart.
       ADD     D2,A1                   ;
       MOV     @A1,A2
       ADD     A2,A3
       MOVB    D6,10(A2)
       MOVB    @A0,D1                  ; Get baud rate code.
       ROLB    D1,#4                   ; Shift to receiver select bits.
       ORB     @A0,D1                  ; Or int transmit clock select bits.
       MOVB    D1,2(A3)                ;
       MOVB    #CM$RMRP,4(A3)          ; Reset mode register pointer.
       MOVB    #CM$RRCV,4(A3)          ; Reset receiver.
       MOVB    #CM$RTXM,4(A3)          ; Reset transmitter.
       MOVB    #CM$REST,4(A3)          ; Reset error status.

       MOVB    2(A3),D1
       INCB    D1
       BNE     20$

; Yes, the message for the earlier version is wrong but this keeps the
; hash right and the correction is in the new version.
;
       IF      NE, OPTION
        TYPECR <Piiceon 6 Port not detected>
       IFF
        TYPECR <16 Port not detected>
       ENDC
       JMP     ERRXIT

20$:
       MOVB    #<M1$8B!M1$NP>, @A3     ; Set up for mode register 1
       MOVB    #<M2$1SB!M2$NM!M2$CET>, D1      ; Set 1 stop bit.
       CMPB    D0,#4                   ; Did we want 110 baud?
       BNE     30$                     ; No..
       MOVB    #<M2$2SB!M2$NM!M2$CET>, D1      ; Set two stop bits.

30$:    MOVB    D1,@A3
       MOVB    #12,4(A3)
       CLR     D1
       MOVB    #3,D1                   ;
       BTST    #0,D3                   ; Channel A?
       BNE     40$                     ;  Yes..
       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                  ;
       MOVB    D1,12(A2)               ; Save
       MOVB    #5,D1
       BTST    #0,D3
       BNE     50$
       MOVB    #22,D1

50$:    LEA     A0,OBIT1                ; Base address of output byte table.
       ADD     D2,A0                   ;
       ORB     D1,@A0                  ; Add to existing bit pattern.
       MOVB    @A0,D1                  ; D5 reflexts both channels.
       MOVB    D1,34(A2)               ; Set bits on
       MOVB    #0,32(A2)


       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                  ; Save TRMDEF block address.
       MOV     A3,6(A5)                ; Save duart address in trmdef block.
       LEA     A0,INTRPT
       MOV     A0,INTVEC
       MOVB    #1,4(A3)
       RTN

INTRPT: LSTS    #23400
       SAVE    D0,D1,D2,D3,D4,D5,D6,D7,A0,A1,A2,A3,A4,A5,A6
       CLR     D2
       MOV     #INTAD1, A0             ; Check first board.
       MOVB    12(A0),D0
       ANDB    #63,D0
       JNE     SERVB0
       MOVB    #10,D2                  ; Check second board
       MOV     #INTAD2, A0
       MOVB    12(A0),D0
       ANDB    #63,D0
       JNE     SERVB0
       MOVB    #20,D2                  ; Check third board
       MOV     #INTAD3, A0
       MOVB    12(A0),D0
       ANDB    #63,D0
       JNE     SERVB0
       REST    A6,A5,A4,A3,A2,A1,A0,D7,D6,D5,D4,D3,D2,D1,D0
       RTE

SERVB0: LEA     A5,TCB0
       ANDB    #60,D0
       BNE     10$
       ADDW    #4,D2
10$:    MOV     0(A5)[D2],A5
       MOV     12(A5),D0
       LEA     A3,PORTS
       MOVW    @A3,D2
       BTST    D0,D2
       JEQ     FLSINT
       MOV     6(A5),A4
       MOVB    2(A4),D1
       BTST    #0,D1
       BNE     20$
       BTST    #2,D1
       BNE     30$
       BR      FLSINT
20$:    MOVB    6(A4),D1
       TRMICP
       REST    A6,A5,A4,A3,A2,A1,A0,D7,D6,D5,D4,D3,D2,D1,D0
       RTE
30$:    TRMOCP                          ; Get Next output char from TRMSER.
       TST     D1                      ; Data available?
       BPL     OPRG7                   ; Yes.
       ANDW    #^C<OIP>,@A5            ; No..Clear the OIP flag.
       MOVB    #10,4(A4)               ; Disable transmitter.
       BR      L1454
OPRG7:  MOVB    D1,6(A4)
L1454:  REST    A6,A5,A4,A3,A2,A1,A0,D7,D6,D5,D4,D3,D2,D1,D0
       RTE
FLSINT: REST    A6,A5,A4,A3,A2,A1,A0,D7,D6,D5,D4,D3,D2,D1,D0
       RTE


       PAGE
;***************************************************************************
;                                                                          *
;                     B A U D   R A T E   T A B L E S                      *
;                                                                          *
;***************************************************************************
;
;
BAUD1:          ; ACR BIT 7 = 1
       BYTE    -1                              ; 50 baud
       BYTE    0                               ; 75 baud
       BYTE    1                               ; 110 baud
       BYTE    2                               ; 134.5 baud
       BYTE    3                               ; 150 baud
       BYTE    -1                              ; 200 baud
       BYTE    4                               ; 300 baud
       BYTE    5                               ; 600 baud
       BYTE    6                               ; 1200 baud
       BYTE    12                              ; 1800 baud
       BYTE    7                               ; 2000 baud
       BYTE    10                              ; 2400 baud
       BYTE    -1                              ; 3600 baud
       BYTE    11                              ; 4800 baud
       BYTE    -1                              ; 7200 baud
       BYTE    13                              ; 9600 baud
       BYTE    14                              ; 19200 baud
       BYTE    -1                              ; 38400 baud
       BYTE    0
BAUD0:                  ; ACR = 0
       BYTE    0                               ; 0 = 50 baud
       BYTE    -1                              ; 1 = 75 baud
       BYTE    1                               ; 2 = 110 baud
       BYTE    2                               ; 3 = 134.5 baud
       BYTE    -1                              ; 4 = 150 baud
       BYTE    3                               ; 5 = 200 baud
       BYTE    4                               ; 6 = 300 baud
       BYTE    5                               ; 7 = 600 baud
       BYTE    6                               ; 8 = 1200 baud
       BYTE    -1                              ; 9 = 1800 baud
       BYTE    -1                              ; 10 = 2000 baud
       BYTE    10                              ; 11 = 2400 baud
       BYTE    -1                              ; 12 = 3600 baud
       BYTE    11                              ; 13 = 4800 baud
       BYTE    12                              ; 14 = 7200 baud
       BYTE    13                              ; 15 = 9600 baud
       BYTE    -1                              ; 16 = 19200 baud
       BYTE    14                              ; 17 = 38400 baud
       BYTE    0                               ; 18 USED FOR UN-INITED PORTS

       EVEN


BVAL:   BYTE    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

BPADR:  LWORD   INTAD1
       LWORD   INTAD2
       LWORD   INTAD3


TCB0:   LWORD   0
TCB1:   LWORD   0
TCB2:   LWORD   0
TCB3:   LWORD   0
TCB4:   LWORD   0
TCB5:   LWORD   0

PORTS:  WORD    0

IMASK1: BYTE    0
IMASK2: BYTE    0
IMASK3: BYTE    0
IMASK4: BYTE    0
IMASK5: BYTE    0
IMASK6: BYTE    0

OBIT1:  BYTE    0
OBIT2:  BYTE    0
OBIT3:  BYTE    0
OBIT4:  BYTE    0
OBIT5:  BYTE    0
OBIT6:  BYTE    0

       END