;AM1006         Serial Port Interface Driver for the AM-1006
;
;                                                               ASL-xxxxx-xx
;                                 NOTICE
;
;All  rights  reserved.  This software is the property of Alpha Microsystems
;and the material contained herein is the  proprietary  property  and  trade
;secrets  of  Alpha Microsystems, embodying substantial creative efforts and
;confidential information, ideas and expressions, no part of  which  may  be
;reproduced  or  transmitted  in  any  form  or  by  any  means, electronic,
;mechanical,  or  otherwise,  including  photocopying  or  input  into   any
;information  storage  or  retrieval  system  without  the  express  written
;permission of Alpha Microsystems.
;
;CAUTION: Unauthorized distribution or reproduction  of  this  material  may
;subject you to legal action.
;
;
;This interface driver supports the 4/8 serial ports contained on the
;AM-1006 CPU board.  Unlike the AM-100t ports, they have full modem
;(and therefore printer) control.
;
;Ports are addressed in the TRMDEF statement as 0 thru 7.
;
;Edit History:
;

; modify September 1985 by Tan Nguyen at the House of Reps. to have full
; individual port programable.


       SEARCH  SYS
       SEARCH  SYSSYM
       SEARCH  TRM

OBJNAM  AM1006.IDV


       PAGE

;Define Miscellaneous Parameters and Constants
;
;Define 2681 Status Register Bits
ST$RDRF =       0                       ; 1 = Receive Data Register Full
ST$FFUL =       1                       ; 1 = FIFO full
ST$TRDY =       2                       ; 1 = Transmit holding register empty
ST$EMT  =       3                       ; 0 = Transmit shift register empty
ST$OVRN =       4                       ; 1 = Overrun error
ST$PRER =       5                       ; 1 = Parity error
ST$FRER =       6                       ; 1 = Framing error
ST$RCBR =       7                       ; 1 = Received break

;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$RBCI =       120                     ; Reset break change interrupt
CM$STBR =       140                     ; Start break
CM$SPBR =       160                     ; Stop break
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$5B   =       0                       ; 5 bits per character
M1$6B   =       1                       ; 6 bits per character
M1$7B   =       2                       ; 7 bits per character
M1$8B   =       3                       ; 8 bits per character
M1$PO   =       4                       ; Parity Odd
M1$PE   =       0                       ; Parity Enable
M1$FP   =       10                      ; Force parity
M1$NP   =       20                      ; No parity
M1$SM   =       30                      ; Special parity mode
M1$IF   =       100                     ; Interrupt on FIFO full

; 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
M2$RTS  =       40                      ; Transmitter RTS control
M2$AE   =       100                     ; Auto echo mode
M2$LL   =       200                     ; Local loop mode
M2$RL   =       300                     ; Remote loop mode

PAGE

; Define 2681 Interrupt Mask Register bits
IM$TXRD =       1                       ; Interrupt on transmitter ready
IM$RXRD =       2                       ; Interrupt on receiver ready

; Define 2681 Interrupt Status Register bits
IS$TRA  =       1                       ; Transmitter ready A
IS$RRA  =       2                       ; Receiver ready A
IS$TRB  =       20                      ; Transmitter ready B
IS$RRB  =       40                      ; Receiver ready B

;Define I/O Port Offsets
;
;These are defined as offset to the base of the serial port block.
P.MDR   =       0                       ; Mode Register (Input & Output)
P.SR    =       1                       ; Status Register (Input)
P.CLK   =       1                       ; Clock Select Register (Output)
P.CMR   =       2                       ; Command Register (Output)
P.RCV   =       3                       ; Receiver Holding Register (Input)
P.TXM   =       3                       ; Tranmitter Holding Register (Output)
P.ACR   =       4                       ; Auxiliary Control Register (Output)
P.ISR   =       5                       ; Interrupt Status Register (Input)
P.IMR   =       5                       ; Interrupt Mask Register (Output)
P.OCR   =       15                      ; Output port configuration register(Output)
P.SOB   =       16                      ; Set output port bits register(Output)
P.ROB   =       17                      ; Reset output port bits register(Output)

       PAGE

;Driver Commumnications Area
;
;This is the standard branch table used by TRMDEF and TRMSER.  Only TRMDEF
;is allowed to call the initialization routine.
AM1:
       BR      CHROUT                  ; character output routine
       BR      INIT                    ; initialization routine
       NOP
CHROUT:
       JMP     CHROT

;CHROT          Output Character Initiation Routine
;
;Enable the 2681 transmitter which generates an initial interrupt which
;will be dispatched to the transmitter routine, starting the output
;process.  This routine is called by clock routine set up by TRMSER.
;
;Inputs:        A5      Pointer to terminal definition block
;
;Outputs:       None
;
;Modifies:      A6

CHROT:
       SAVE    A6
       MOV     T.IHW(A5),A6            ; Get base address of DUART
       MOVB    #CM$RXEN!CM$TXEN,P.CMR(A6); Enable transmitter
       REST    A6
       RTN

       PAGE

;INIT           Initialize the AM-1006 Port
;
;This routine is called by TRMDEF each time a port on the AM-1006 is defined.
;The routine must intialize the proper port to the specified configuration,
;or, if the default is specified, it must set the 1006 up for async 19200 baud
;operation.
;
;Inputs:        D0      Specified baud rate code.
;               A5      Points to terminal definition block.
;
;Outputs:       Outputs to 1006 board only.
;
;Modifies:      D1, A2, A3, A4; 1006 command register;

; Get baud rate code
INIT:   LEA     A6,BAUDTB               ; index the baud rate table
       ROLB    D0,#1                   ; Shift to word offset
       MOVB    0(A6)[D0],D1            ; Get first byte of baud rate code
       CMPB    D1,#-1                  ; Is it a valid baud rate ?
       JEQ     BDBAUD                  ;   no - invalid baud rate
; Get port number and base addresses of DUART and channel
       LEA     A3,DUART1               ; get base of DUART address table
       MOV     T.IHM(A5),D2            ; use port # as displacement
       MOV     D2,D3                   ; keep a copy
       ANDB    #06,D2                  ; Reset bit 0, dont care channl A or B
       ASL     D2,#1                   ; double for long word increments
       MOV     0(A3)[D2],A2            ; Set A2 to base of DUART
       MOV     A2,A4                   ; set A4 to base of specific channel
       BTST    #0,D3                   ; port # indicates channel A or B
       BEQ     10$                     ; channel A
       ADD     #10,A4                  ; channel B
; Set up baud rate
10$:
       MOVB    D1,P.ACR(A2)            ; Send table select code
       INC     A6                      ;  Bump pointer
       MOVB    0(A6)[D0],D1            ; Get baud rate code
       ROLB    D1,#4                   ; Shift to receiver select bits
       ORB     0(A6)[D0],D1            ;  or int transmit clock select bits
       MOVB    D1,P.CLK(A4)            ; Send to proper channel
; Reset everything
       MOVB    #CM$RMRP,P.CMR(A4)
       MOVB    #CM$RRCV,P.CMR(A4)
       MOVB    #CM$RTXM,P.CMR(A4)
       MOVB    #CM$REST,P.CMR(A4)

       MOVB    P.SR(A4),D1             ; Look at status reg
       CMPB    D1,#^H0FF               ; If not there, should read FF
       JEQ     NOPORT                  ; If there, should be cleared


;***************************************************************************
; removed the section below  (comments out)                  (TNN) tannguyen

;       MOVB    #M1$8B!M1$NP,P.MDR(A4)  ; Set up mode register 1     (TNN)
;       MOVB    #M2$1SB!M2$NM!M2$CET,D1 ; Set up for mode register 2 (TNN)
;       CMPB    D0,#4                   ; Did we want 110 baud       (TNN)
;       BNE     30$                                                  (TNN)
;       MOVB    #M2$2SB!M2$NM!M2$CET,D1 ; Set to two stop bits       (TNN)
;30$:                                                                (TNN)
;       MOVB    D1,P.MDR(A4)            ; Set up mode register 2     (TNN)
;***************************************************************************

;***************************************************************************
; added this section below     (TNN)
;
;*****************MODIFICATION FOR AM1006 STARTS HERE** (TNN) ***************
;  INSERT THIS SECTION AND DELETE THE PREVIOUS SET MODE STATEMENTS
;  PLEASE ALSO REFER TO THE PROGRAM ATTACHED ON [100,53] ON AMUS -
;                      BLKINP.M68    PASWOR.BAS
;
;This gets the mode registers from the tables. all you want to do when
;you assign different mode to any port (e.g, port 0=8bit,none parity
;port 7 7 bit odd parity,etc.) is set the table accordingly
;
SETMOD: LEA     A6,MR1TAB               ;get mode reg. 1 table
       MOVB    0(A6)[D3],D1            ;get the mode for this port
       MOVB    D1,P.MDR(A4)            ;SET IT
       LEA     A6,MR2TAB               ;same thing for reg 2
       MOVB    0(A6)[D3],D1            ;get mode for this port
       MOVB    D1,P.MDR(A4)            ;set it
;done
;******************END OF MOD FOR AM1006 ENDS HERE (TNN)**********************


       MOVB    #CM$RXDI!CM$TXDI,P.CMR(A4) ; Temporarily disable interupts
       CLR     D1
       MOVB    #IM$TXRD!IM$RXRD,D1
       CLR     D1
       MOVB    #IM$TXRD!IM$RXRD,D1     ; Allow interrupts
       BTST    #0,D3                   ; channel A ?
       BEQ     40$                     ; yes
       ROLB    D1,#4                   ; Shift for channel B
40$:
       LEA     A6,IMASK1               ; Base address of IMR byte table
       MOV     D3,D2                   ; Get another copy
       ASR     D2,#1                   ; Index OPBIT table
       ORB     D1,0(A6)[D2]            ; Set new bit pattern for given DUART
       MOVB    0(A6)[D2],D1            ; Make sure D1 reflects both channels
       MOVB    D1,P.IMR(A2)            ; Send to DUART
; Now enable DTR & RTS
       MOVB    #5,D1                   ; Set up for channel A
       BTST    #0,D3                   ; See if channel B
       BEQ     50$                     ; Nope
       MOVB    #22,D1                  ; Set to channel B
50$:
       LEA     A6,OPBIT1               ; Base address of output byte table
       ORB     D1,0(A6)[D2]            ; Set new pattern for given DUART
       MOVB    0(A6)[D2],D1            ; Make sure D1 reflects both channels
       MOVB    D1,P.SOB(A2)            ; Set bits on
       MOVB    #0,P.OCR(A2)            ; Send to the DUART
; SET LOCAL MEMORY FLAGS AND POINTERS
       LEA     A0,PORTS                ; index port initialization indicator
       BSET    D3,@A0                  ; mark this port as initialized
       ASL     D3,#2                   ; times 4 to index long words
       LEA     A3,TRMDF0               ; get beginning of TRMDEF table
       MOV     A5,0(A3)[D3]            ; store pointer to TRMDEF block in tbl
       MOV     A4,T.IHW(A5)            ; Save I/O address in terminal def blk
       LEA     A0,INTRPT               ; Get addr of interrupt dispatch
       MOV     A0,INTVEC               ; Save in autovector
       MOVB    #CM$RXEN,P.CMR(A4)      ; Enable receiver interupts
       RTN


BDBAUD:
       TYPECR  <?Invalid baud rate for specified interface>
       RTN                             ; just ignore initialization


NOPORT: TYPECR  <? Port does not exist !!>
       RTN

PAGE

; INTRPT
; Come here via INTERRUPT vector to process all AM-1006 INTERRUPTs.
;
; Inputs:       None
;
; Outputs:      None
;
; Modifies:     A0,A2,A5,D1

INTRPT:
       SVLOK                           ; Lock all interrupts
       SAVE    A0-A6,D0-D7             ; Save all registers
       MOV     #INTADD,A0              ; Index the interrupt port
       MOVB    @A0,D1                  ; read INTERRUPT byte
       BTST    #IOINT1,D1             ; Duart 1 I/O (receive/trans) INTERRUPT?
       BEQ     IOSRV1                 ; yes, go service it
       BTST    #IOINT2,D1             ; Duart 2 ?
       BEQ     IOSRV2                 ;
       BTST    #IOINT3,D1             ; Duart 3 ?
       JEQ     IOSRV3                 ;
       BTST    #IOINT4,D1             ; Duart 4 ?
       JEQ     IOSRV4                 ;
       BTST    #TIMR1I,D1             ; accidental timer INTERRUPT DUART 1 ?
       JEQ     TIMR1S                 ; yes, go turn it off
       BTST    #TIMR2I,D1             ; DUART 2 ?
       JEQ     TIMR2S                 ;
       BTST    #TIMR3I,D1             ; DUART 3 ?
       JEQ     TIMR3S                 ;
       BTST    #TIMR4I,D1             ; DUART 4 ?
       JEQ     TIMR4S                 ;

BADINT: REST    A0-A6,D0-D7             ; Restore registers
       RTE                             ; Return from exception

IOSRV1: MOVB    #PORT01,D1              ; bit pattern indicates ports 0,1 initd
       ANDB    PORTS,D1                ; is either port of this DUART inited?
       BEQ     BADINT                  ; no, invalid INTERRUPT, ignore it
       MOV     DUART1,A2               ; get base of DUART
       MOVB    P.ISR(A2),D1            ; read INTERRUPT status reg
       ANDB    #IS$TRA!IS$RRA,D1       ; recv or transmit intrt. from ch A?
       BEQ     IOSR1B                  ; must be channel B
       MOV     TRMDF0,A5               ; get pointer to port 0's TRMDEF block
       JMP     GINTRP                  ; go to general processing routine

IOSR1B: MOV     TRMDF1,A5               ; get pointer to port 1's TRMDEF block
       JMP     GINTRP                  ; go to general processing routine

IOSRV2: MOVB    #PORT23,D1              ; bit pattern indicates ports 2,3 initd
       ANDB    PORTS,D1                ; is either port of this DUART inited?
       BEQ     BADINT                  ; no, invalid INTERRUPT, ignore it
       MOV     DUART2,A2               ; get base of DUART
       MOVB    P.ISR(A2),D1            ; read INTERRUPT status reg
       ANDB    #IS$TRA!IS$RRA,D1       ; recv or transmit intrt. from ch A?
       BEQ     IOSR2B                  ; must be channel B
       MOV     TRMDF2,A5               ; get pointer to port 2's TRMDEF block
       JMP     GINTRP                  ; go to general processing routine

IOSR2B: MOV     TRMDF3,A5               ; get pointer to port 3's TRMDEF block
       JMP     GINTRP                  ; go to general processing routine

IOSRV3: MOVB    #PORT45,D1              ; bit pattern indicates ports 4,5 initd
       ANDB    PORTS,D1                ; is either port of this DUART inited?
       BEQ     BADINT                  ; no, invalid INTERRUPT, ignore it
       MOV     DUART3,A2               ; get base of DUART
       MOVB    P.ISR(A2),D1            ; read INTERRUPT status reg
       ANDB    #IS$TRA!IS$RRA,D1       ; recv or transmit intrt. from ch A?
       BEQ     IOSR3B                  ; must be channel B
       MOV     TRMDF4,A5               ; get pointer to port 4's TRMDEF block
       BR      GINTRP                  ; go to general processing routine

IOSR3B: MOV     TRMDF5,A5               ; get pointer to port 5's TRMDEF block
       BR      GINTRP                  ; go to general processing routine

IOSRV4: MOVB    #PORT67,D1              ; bit pattern indicates ports 6,7 initd
       ANDB    PORTS,D1                ; is either port of this DUART inited?
       JEQ     BADINT                  ; no, invalid INTERRUPT, ignore it
       MOV     DUART4,A2               ; get base of DUART
       MOVB    P.ISR(A2),D1            ; read INTERRUPT status reg
       ANDB    #IS$TRA!IS$RRA,D1       ; recv or transmit intrt. from ch A?
       BEQ     IOSR4B                  ; must be channel B
       MOV     TRMDF6,A5               ; get pointer to port 6's TRMDEF block
       BR      GINTRP                  ; go to general processing routine

IOSR4B: MOV     TRMDF7,A5               ; get pointer to port 7's TRMDEF block
       BR      GINTRP                  ; go to general processing routine

TIMR1S: MOVB    #PORT01,D1              ; port init mask for this DUART
       MOV     DUART1,A2               ; get base of DUART
       BR      SHUTOF

TIMR2S: MOVB    #PORT23,D1              ; port init mask for this DUART
       MOV     DUART2,A2               ; get base of DUART
       BR      SHUTOF

TIMR3S: MOVB    #PORT45,D1              ; port init mask for this DUART
       MOV     DUART3,A2               ; get base of DUART
       BR      SHUTOF

TIMR4S: MOVB    #PORT67,D1              ; port init mask for this DUART
       MOV     DUART4,A2               ; get base of DUART
       BR      SHUTOF

SHUTOF: ANDB    PORTS,D1                ; either port on this DUART inited?
       JEQ     BADINT                  ; no, invalid INTERRUPT ignore it
       MOVB    #^H08,P.ROB(A2)          ; shut off timer
       REST    A0-A6,D0-D7             ; restore registers
       RTE

PAGE

;GINTRP         General Serial Port Interrupt Processing Routine
;
; Come here to determine which channel (A or B) of given DUART generated the
; INTERRUPT.
;
;Inputs:        A5      Terminal definition index
;               All registers SAVEd on stack
;
;Outputs:       D1      2681 Status Register
;               A4      Pointer to base of I/O ports
;
;Modifies:      D1, A4

GINTRP:
       MOV     T.IHW(A5),A4            ; get I/O register base into A4
       MOVB    P.SR(A4),D1             ; read the 2681 status register
       BTST    #ST$RDRF,D1             ; check receiver data register full flag
       BNE     INPR                    ;   and go process if set
       BTST    #ST$TRDY,D1             ; check transmitter empty flag
       BNE     OUTPR                   ;   and go process if set
       BR      FLSINT                  ; handle false interrupt
       PAGE

;INPR           Input Character Interrupt Routine
;
;Come here whenever we get a receiver interrupt.  Read the character from
;the AM-1006 and pass on to TRMSER.
;
;Inputs:        A2      DUART base
;               A4      Port register base
;               All registers SAVEd on stack
;
;Outputs:       None
;
;Modifies:      Restores registers


INPR:   MOVB    P.RCV(A4),D1            ; read the data character
       TRMICP                          ; go process the character
       REST    A0-A6,D0-D7             ; restore registers
       RTE

       PAGE

;OUTPR          Transmitter Interrupt Routine
;
;Come here on a transmitter interrupt.  If another character is available
;for output, grab it and send it to the 2681.
;Otherwise, clear the OIP flag and dismiss interrupt.
;
;Inputs:        D1      2681 Status Register
;               A2      DUART base
;               A4      I/O register base address
;               A5      Terminal definition index
;               All registers SAVEd on the stack
;
;Outputs:       Only to AM-1006
;
;Modifies:      Registers restored

OUTPR:  TRMOCP                          ; get next output character from TRMSER
       TST     D1                      ; data available?
       BPL     OUTREG                  ;   yes -
       ANDW    #^C<OIP>,@A5            ;   no - clear the OIP flag
       MOVB    #CM$TXDI,P.CMR(A4)
       BR      OUTRTN                  ; return

;Send character to transmitter

OUTREG: MOVB    D1,P.TXM(A4)            ; s
end character to 2681
OUTRTN: REST    A0-A6,D0-D7             ; return
       RTE

       PAGE

;FLSINT         False Interrupt Routine
;
;Come here when interrupt was caused by neither transmitter or receiver.
;The interrupt is either DCD change or spurious.  In either case, we just
;ignore the interrupt.
;
;Inputs:        D1      2681 Status Register
;               A2      DUART base
;               A4      I/O register base address
;               All registers SAVEd on stack
;
;Outputs:       None
;
;Modifies:      Restores registers

FLSINT: REST    A0-A6,D0-D7             ; restore register
       RTE                             ; return

PAGE

;Define baud rate table

BAUDTB:
       BYTE    0,0                     ; 50 baud
       BYTE    200,0                   ; 75 baud
       BYTE    0,1                     ; 110 baud
       BYTE    0,2                     ; 134.5 baud
       BYTE    200,3                   ; 150 baud
       BYTE    0,3                     ; 200 baud
       BYTE    0,4                     ; 300 baud
       BYTE    0,5                     ; 600 baud
       BYTE    0,6                     ; 1200 baud
       BYTE    200,12                  ; 1800 baud
       BYTE    200,7                   ; 2000 baud
       BYTE    0,10                    ; 2400 baud
       BYTE    -1,-1                   ; 3600 baud
       BYTE    0,11                    ; 4800 baud
       BYTE    0,12                    ; 7200 baud
       BYTE    0,13                    ; 9600 baud
       BYTE    200,14                  ; 19200 baud
       BYTE    0,14                    ; 38400 baud

       EVEN

DUART1:  LWORD   ^H0FFFF10             ; I/O base for DUART 1 ( ports 0&1 )
DUART2:  LWORD   ^H0FFFF20             ; I/O base for DUART 2 ( ports 2&3 )
DUART3:  LWORD   ^H0FFFF70             ; I/O base for DUART 3 ( ports 4&5 )
DUART4:  LWORD   ^H0FFFF90             ; I/O base for DUART 4 ( ports 6&7 )

TRMDF0: LWORD 0                        ; pointer to TRMDEF block for port 0
TRMDF1: LWORD 0                        ;   "     "     "     "    "   "   1
TRMDF2: LWORD 0                        ;   "     "     "     "    "   "   2
TRMDF3: LWORD 0                        ;   "     "     "     "    "   "   3
TRMDF4: LWORD 0                        ;   "     "     "     "    "   "   4
TRMDF5: LWORD 0                        ;   "     "     "     "    "   "   5
TRMDF6: LWORD 0                        ;   "     "     "     "    "   "   6
TRMDF7: LWORD 0                        ;   "     "     "     "    "   "   7

PORTS:  BYTE  0                        ;  port initialization indicator
PORT01  =  ^H03                        ;  bit pattern indcating ports 0,1 initd
PORT23  =  ^H0C                        ;  bit pattern indcating ports 2,3 initd
PORT45  =  ^H30                        ;  bit pattern indcating ports 4,5 initd
PORT67  =  ^H0C0                       ;  bit pattern indcating ports 6,7 initd


IMASK1: BYTE    0                       ; DUART 1 interrupt mask reg byte
IMASK2: BYTE    0                       ; DUART 2 interrupt mask reg byte
IMASK3: BYTE    0                       ; DUART 3 interrupt mask reg byte
IMASK4: BYTE    0                       ; DUART 4 interrupt mask reg byte

OPBIT1: BYTE    0                       ; DUART 1 output port bits
OPBIT2: BYTE    0                       ; DUART 2 output port bits
OPBIT3: BYTE    0                       ; DUART 3 output port bits
OPBIT4: BYTE    0                       ; DUART 4 output port bits

INTADD  =       ^H0FFFF89               ; Interrupt port address
INTVEC  =       ^H064                   ; Address of interrupt vector

IOINT1  =       0                       ; Duart 1 I/O interrupt bit
IOINT2  =       1                       ; Duart 2 I/O interrupt bit
IOINT3  =       2                       ; Duart 3 I/O interrupt bit
IOINT4  =       3                       ; Duart 4 I/O interrupt bit
TIMR1I  =       4                       ; Duart 1 timer interrupt bit
TIMR2I  =       5                       ; Duart 2 timer interrupt bit
TIMR3I  =       6                       ; Duart 3 timer interrupt bit
TIMR4I  =       7                       ; Duart 4 timer interrupt bit
;
; EACH PORT HAS ITS OWN MODE REGISTER 1 AND 2 VALUE
; this method helps to invidually set up different mode to different
; port. There are two tables: MR1TAB and MR2TAB for mode registers 1 and 2
;

; mode register 1 table

MR1TAB:
       BYTE    M1$7B+M1$PE+M1$PO       ;Port 0,7-bits,odd parity(teleray)
       BYTE    M1$7B+M1$PE+M1$PO       ;Port 1,7-bits,odd parity(teleray)
       BYTE    M1$7B+M1$PE+M1$PO       ;Port 2,7-bits,odd parity(teleray)
       BYTE    M1$8B+M1$NP             ;port 3,8-bits,no parity(votestation)
       BYTE    M1$8B+M1$NP             ;port 4,8-bits,no parity(votestation)
       BYTE    M1$8B+M1$NP             ;port 5,8-bits,no parity(votestation)
       BYTE    M1$8B+M1$NP             ;port 6,8-bits,no parity(votestation)
       BYTE    M1$7B+M1$NP             ;port 7,8-bits,no parity(XEROX1730)

; mode register 2 table

MR2TAB:
       BYTE    M2$1SB+M2$NM+M2$CET     ;everybody 1stopbit,rts,normal
       BYTE    M2$1SB+M2$NM+M2$CET     ;everybody 1stopbit,rts,normal
       BYTE    M2$1SB+M2$NM+M2$CET     ;everybody 1stopbit,rts,normal
       BYTE    M2$1SB+M2$NM+M2$CET     ;everybody 1stopbit,rts,normal
       BYTE    M2$1SB+M2$NM+M2$CET     ;everybody 1stopbit,rts,normal
       BYTE    M2$1SB+M2$NM+M2$CET     ;everybody 1stopbit,rts,normal
       BYTE    M2$1SB+M2$NM+M2$CET     ;everybody 1stopbit,rts,normal
       BYTE    M2$1SB+M2$NM+M2$CET     ;everybody 1stopbit,rts,normal

       EVEN

       END