;AM100L Serial Port Interface Driver for the AM-100/L
;
; ASL-02017-00
; 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 two serial ports contained on the
;AM-100/L CPU board. Unlike the AM-100/T, both ports have full modem
;(and therefore printer) control.
;
;Ports are addressed in the TRMDEF statement as 0 and 1.
;
;Edit History:
;
;[102] 27 October 1982
; Changed to turn off interrupts faster.
;[101] 22 April 1982
; Make sure our size is even.
;[100] 9 April 1982
; Fix baud rate terminal to reflect BR1941-05 baud rate generator
; since that is what is used on the new rev. L and A boards.
;
SEARCH SYS
SEARCH SYSSYM
SEARCH TRM
OBJNAM AM100L.IDV
PORT0 = ^H0FFFE20 ; I/O base for port 0
PORT1 = ^H0FFFE24 ; I/O base for port 1
PORTB = ^H0FFFE28 ; Baud rate generator port
INTV0 = ^H068 ; Interrupt vector for port 0
INTV1 = ^H06C ; Interrupt vector for port 1
FTDEBUG=0 ; set to 1 for debug features
DEFINE DEBUG ARG
IF NE, FTDEBUG
MOVB #^H0'ARG,^H0FFFE00
ENDC
ENDM
PAGE
;Define Miscellaneous Parameters and Constants
;
;Define 6850 Status Register Bits
;
ST$RDRF = 0 ; 1 = Receive Data Register Full
ST$TDRE = 1 ; 1 = Transmit Data Register Empty
ST$DCD = 2 ; 1 = DCD bar has gone high (no carrier)
ST$CTS = 3 ; 0 = CTS bar is low (OK to transmit)
ST$FE = 4 ; 1 = Framing Error
ST$OVRN = 5 ; 1 = Overrun Error
ST$PE = 6 ; 1 = Parity Error
ST$IRQ = 7 ; 1 = Interrupt has been requested
;Define 6850 Command Register Bits
;
CM$RESET = 3 ; Master Reset for ACIA
CM$16 = 1 ; Clock is divide by 16
CM$1STP = 24 ; 8 data bits, 1 stop bit, no parity
CM$2STP = 20 ; 8 data bits, 2 stop bits, no parity
CM$TXD = 0 ; RTS bar low, transmitter disabled
CM$TXE = 40 ; RTS bar low, transmitter enabled
CM$BREAK = 140 ; Force break
CM$RCE = 200 ; Receiver Enabled
;Define I/O Port Offsets
;
;These are defined as offset to the base of the serial port block (i.e., base
;of the board + 4).
;
;Driver Commumnications Area
;
;This is the standard branch table used by TRMDEF and TRMSER. Only TRMDEF
;is allowed to call the initialization routine.
;
PAGE
;INIT Initialize the AM-100/L Port
;
;This routine is called by TRMDEF each time a port on the AM-100/L is defined.
;The routine must intialize the proper port to the specified configuration,
;or, if the default is specified, it must set the 100/L up for async 19200 baud
;operation.
;
;Inputs: D0 Specified baud rate code.
; A5 Points to terminal definition block.
;
;Outputs: Outputs to 100/L board only.
;
;Modifies: D1, A3, A4; 100/L command register;
;
INIT: LEA A6,BAUDTB ; index the baud rate table
MOVB 0(A6)[D0],D0 ; is it valid?
JMI BDBAUD ; no - invalid baud rate
TST T.IHM(A5) ; are we selecting port 0?
BEQ 10$ ; yes -
;Set up port 1 baud rate load, I/O port, and interrupt vector
MOVB #40,D2 ; no - select port 1 baud rate load
MOV #PORT1,A4 ; and I/O port
LEA A3,INTR1 ; index port 1 interrupt routine
MOV A3,INTV1 ; store it
BR 20$
;Set up port 0 baud rate load, I/O port, and interrupt vector
10$: MOVB #20,D2 ; get port 0 select bit
MOV #PORT0,A4 ; index port 0
LEA A3,INTR0 ; index port 0 interrupt routine
MOV A3,INTV0 ; store it
;Send baud rate code to baud rate generator and reset ACIA
20$: ORB D0,D2 ; combine selector code with baud rate
MOVB D2,PORTB ; send to baud rate generator
MOV A4,T.IHW(A5) ; store I/O addr terminal definition blk
MOV A5,OFF(A3) ; store term def ptr in interrupt routine
MOVB #CM$RESET,@A4 ; reset the 6850 ACIA chip
;Set up the ACIA for 16X clock, correct # of stop bits, transmitter disabled,
; and receiver enabled
MOVB #CM$16!CM$1STP!CM$TXD!CM$RCE,D2
CMPB D0,#2 ; did we want 110 baud?
BNE 30$ ; no -
MOVB #CM$16!CM$2STP!CM$TXD!CM$RCE,D2
30$: MOVB D2,@A4 ; set up ACIA
DEBUG F0
RTN
PAGE
;CHROUT Output Character Initiation Routine
;
;Enable the 6850 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: None
;
CHROUT: MOVB #CM$16!CM$1STP!CM$TXD!CM$RCE!CM$TXE,D7
CMPW T.BAU(A5),#2 ; are we set to 110 baud?
BNE 10$ ; no -
MOVB #CM$16!CM$2STP!CM$TXD!CM$RCE!CM$TXE,D7
10$: MOV T.IHW(A5),A6 ; set terminal definition index
MOVB D7,@A6 ; enable transmitter
DEBUG F1
RTN
PAGE
;INTRn Define Serial Port Routines
;
;These routines contain code that is modified by the initialization routine.
;Called at interrupt level.
;
;Inputs: None
;
;Outputs: A5 Terminal definition block index
;
;Modifies: A5
INTR0: SVLOK ; turn off interrupts [102]
SAVE A0-A6,D0-D7 ; save registers
OFF=.-INTR0+2 ; define offset for modifying code
MOV #7777,A5 ; set channel 0 terminal definition index
BR GINTRP
INTR1: SVLOK ; turn off interrupts [102]
SAVE A0-A6,D0-D7 ; save registers
MOV #7777,A5 ; set channel 1 terminal definition index
;fall thru to GINTRP...
PAGE
;GINTRP Handle Serial Port Interrupt
;
;Come here whenever we get a serial port interrupt. Determine what type it
;is and dispatch to appropriate routine. Called at interrupt level.
;
;Inputs: A5 Terminal definition index
; All registers SAVEd on stack
;
;Outputs: D1 6850 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 @A4,D1 ; read the 6850 status register
BTST #ST$RDRF,D1 ; check receiver data register full flag
BNE INPR ; and go process if set
BTST #ST$TDRE,D1 ; check transmitter empty flag
BNE OUTPR ; and go process if set
BR INFI ; handle false interrupt
;INPR Input Character Interrupt Routine
;
;Come here whenever we get a receiver interrupt. Read the character from
;the AM-100/L and pass on to TRMSER.
;
;Inputs: A4 I/O register base
; All registers SAVEd on stack
;
;Outputs: None
;
;Modifies: Restores registers
;
INPR: DEBUG F2
MOVB P.RCV(A4),D1 ; read the data character
TRMICP ; go process the character
INTX: REST A0-A6,D0-D7 ; restore registers
RTE
PAGE
;INFI 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 6850 Status Register
; A4 I/O register base address
; All registers SAVEd on stack
;
;Outputs: None
;
;Modifies: Restores registers
;
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 6850.
;Otherwise, clear the OIP flag and dismiss interrupt.
;
;Inputs: D1 6850 Status Register
; A4 I/O register base address
; A5 Terminal definition index
; All registers SAVEd on the stack
;
;Outputs: Only to AM-100/L
;
;Modifies: Registers restored
;
OUTPR: DEBUG F4
TRMOCP ; get next output character from TRMSER
TST D1 ; data available?
BPL OPRG ; yes -
ANDW #^C<OIP>,@A5 ; no - clear the OIP flag
MOVB #CM$16!CM$1STP!CM$TXD!CM$RCE,D7
CMPW T.BAU(A5),#2 ; is terminal set for 110 baud?
BNE 10$ ; no -
MOVB #CM$16!CM$2STP!CM$TXD!CM$RCE,D7
10$: MOVB D7,@A4 ; set mode bits
OPRD: BR INTX ; return
;Send character to transmitter
OPRG: MOVB D1,P.TXM(A4) ; send character to 6850
BR INTX ; return
PAGE
;Come here if an invalid baud rate was specified
BDBAUD: TYPECR <?Invalid baud rate for specified interface>
RTN ; just ignore initialization