;*; Updated on 25-Nov-91 at 8:34 AM by Michele Tonti; edit time: 0:00:13
; UPDATED ON 30-NOV-93 FOR ROADRUNNER BY MP.WSOL ,ALPHA MICROSYSTEMS
;*************************** AMUS Program Label ******************************
; Filename: PI16IF.M68 Date: 11/25/91
; Category: TDV Hash Code: 266-204-704-055 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 version of Piiceon's 16 port I/O board smart driver.
; It can be conditionally assembled to work with AMOS/L 1.3C or less or AMOS/L
; 1.3D or greater (including 2.x)
;*****************************************************************************
;*; Updated on 23-Nov-91 at 4:14 AM by James A. Jarboe I V; edit time: 2:12:39
;
;
; MODULE NAME: PI16IF.M68
; DATE: 12/2/85
; MODIFIED: 1/8/86 - MODIFIED BAUD RATE TABLE
; 4/15/86 - MODIFIED FOR REV F BOARD
;
; 2.0 [100] 12-Nov-91 by James A. Jarboe I V
; Added option to assemble with PHDR and COMSER stuff for
; 2.x Systems.
;[101] 06 February 1992 05:42 Edited by InterLink Systems, Inc.
; Changed to properly support Dimension-030
;[102] 12 February 1992 08:58 Edited by InterLink Systems, Inc.
; Changed WZ80 to a loop without timed exit.
;[103] 26 March 1992 08:58 Edited by InterLink Systems, Inc.
; Added delay to enhance robustness.
;[104] 14 April 1992 09:31 Edited by InterLink Systems, Inc.
; Removed unneeded delays & added needed SVLOK's
;[105] 11 May 1992 12:52 Edited by InterLink Systems, Inc.
; Added SSTS and LSTS to save Interrupt level
;******************************************************************************
;[106] 30 NOV 1993 12:00 Edited by Mike Wsol, ALPHA MICROSYSTEMS
; UPDATE FOR ROADRUNNER SUPPORT, 32 bit addressing
; Assemble with /V:0 for AMOS 2.2C(452)-3 Roadrunner Release
; will only work with Revision F and Later Revision boards, Rev B will
; trmdef but will not communicate. The board design is radically different.
;****************************************************************************\
; SMART 16 PORT DRIVER
;
; This version of the PIICEON 16 Port smart driver has been modified
; so that it can be conditionally assembled to work on AMOS/L systems
; with an OS Version of 1.3C or less or 1.3D or greater.
;
; The Additions that where made:
; Added PHDR for new style drivers.
; Added Flag word for new style drivers.
; Added GETPIN and SETPIN vector offsets
;
; !**NOTE**! 13-Nov-91 12:41 AM
;
; This current version 2.0(100) HAS BEEN tested with a PIICEON 16 port
; board with AMOS 2.2 and it works!
; The only problem, if any, would be the logic
; of setting the pins at SETPIN:. This may not be compatible with
; the PI16 port board. If not, it can be modified using the WZ80 logic
; that is used. Let me know.
;
; Conditional Assembly:
; /V:1 = AMOS/L 1.3C or less - 404-313-521-455
; /V:0 = AMOS/L 1.3D or greater - 266-056-156-034 2.0(100)
;
SEARCH SYS
SEARCH SYSSYM
SEARCH TRM
OBJNAM PI16IF.IDV
NVALU OPTION
ASMMSG " "
IF EQ,OPTION
ASMMSG "Assembling PI16IF for AMOS/L 1.3D or greater "
IFF
ASMMSG "Assembling PI16IF for AMOS/L 1.3C or less "
ENDC
ASMMSG " "
PAGE
;***************************************************************************
; *
; C U R R E N T V E R S I O N *
; *
;***************************************************************************
;
VMAJOR = 2 ;
VMINOR = 0
VWHO = 0
VSUB = 0
VEDIT = 106. ;MPWsol
PAGE
;***************************************************************************
; *
; C O N S T A N T S *
; *
;***************************************************************************
;
;Define 2681 Status Register Bits
ST$RDRF = 0 ; 1 = Receive Data Register Full
ST$TRDY = 2 ; 1 = Transmit holding register empty
;[106] Update for 32 Bit Addressing for ROADRUNNER
INTADD = ^H0FFFFFF90 ; Interrupt port address
INTVEC = ^H064 ; Address of interrupt vector
;[106] Update for 32 Bit Addressing for ROADRUNNER support
DATAPRT = ^H0FFFFFF10 ; Data & Status Port
Z80PRT = ^H0FFFFFF50 ; Z80 Interrupt Port
TRDYPRT = ^H0FFFFFF30 ; Transmit ready port
;
RS%RTS = ^H04 ; Request to send.
AVLPIN = RS%RTS ; Available pins.
PAGE
;***************************************************************************
; *
; P I 1 6 I F D R I V E R *
; *
;***************************************************************************
;
;
PI16IF:
IF EQ,OPTION ; AMOS/L 1.3D>
ASMMSG " Adding PHDR "
PHDR -1,0,0
BR CHROT ; Character output routine.
BR INIT ; Initialization routine.
BR 20$ ; GETPIN vector.
BR 30$ ; SETPIN vector.
WORD ^H0A5A5 ; Noise word for new format.
LWORD AVLPIN ; Driver Flags.
20$: JMP GETPIN ;
30$: JMP SETPIN ;
CHROT:
SAVE A6,D0,D1,D2,D6 ; [105]
SSTS D2 ; [105] Save Interrupt status
SVLOK ; [104]
MOV T.IHM(A5),D0 ; GET PORT NUM
LEA A6,PORTS ; PORT INITED INDICATOR
MOVW @A6,D6 ; GET PREVIOUS INITED PORTS
BTST D0,D6 ; HAS CHANNEL BEEN INITED
JEQ IGNXIT ; NOPE
CALL WZ80 ; WAIT FOR Z80 INT TO BE SERVICED
; JEQ IGNXIT ; [104]
MOV #DATAPRT,A6 ;[106] DATA PORT NUM
ORW #^H0FF00,D0 ; XMIT ENABLE = FF,,PORT NUM
MOVW D0,@A6
; SVUNLK ; [104]
IGNXIT: LSTS D2 ; [105] Restore interrupt status
REST A6,D0,D1,D2,D6
RTN
;--------- WAIT FOR Z80 INT TO BE SERVICED ------
WZ80:
; MOVW #^H900,D6 ; DONT WAIT FOREVER [101] [102]
MOV #Z80PRT,A6 ;[106] ; WAIT FOR INT ON Z80 TO BE SERVICED
SWAIT:
; NOP ; [103][104]
; NOP ; [103][104]
MOVW @A6,D1 ; MUST BE WORD MOVE
BTST #0,D1 ; 0->INT ACTIVE
BEQ SWAIT ; [102]
; DBNE D6,SWAIT ; [102]
; NOP ; [103][104]
RTN ; RET ZF=1 IF T/O
;Initialize the PI-1016 Port
; ENTER WITH D0 = BAUD RATE INDICATOR
; A5 -> terminal definition block.
LEA A0,INTRPT ; GET ADDDRESS OF INTERRUPT ROUTINE
MOV A0,INTVEC ; SAVE IN AUTOVECTOR
LEA A0,AMALIV ; IF FIRST CALL, THEN INIT ALL PORTS
TSTB @A0
BNE NOTFST
MOVB #-1,@A0
PUSH D0
CALL PRTOFF ; TURN OFF ALL PORTS
POP D0
NOTFST:
LEA A0,PORTS ; PORT INITED INDICATOR
MOVW @A0,D2 ; GET PREVIOUS INITED PORTS
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
BTST #7.,D3 ; ACR=1?
JEQ TRYB0
TRYB1:
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
CHGB0: ; TRY TO CHANGE TO ACR=0
LEA A0,BAUD0
MOVB 0(A0)[D0],D4 ; BOTH BAUD RATES DEFNED
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 CHANEL
MOV D3,D0 ; OLD BAUD RATE
LEA A0,TCB0
LSL D1,#2 ; PORT NUM * 4 FOR LWORD OFFSET
MOV 0(A0)[D1],A5 ; PNTR TO OTHER CHAN TRM DEF BLK
BCLR #7.,D0 ; USE ACR=0
CALL PINIT ; INIT OTHER CHANNEL
REST D0,A5
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
CHGB1: ; TRY TO CHANGE TO ACR=1
LEA A0,BAUD1
MOVB 0(A0)[D0],D4 ; BOTH BAUD RATES DEFNED
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 CHANEL
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 TRM DEF BLK
CALL PINIT ; INIT OTHER CHANNEL
REST D0,A5
BSET #7.,D0 ; USE ACR=1 ON NEW PORT
JMP SBAUD
BAUDER:
TYPECR <Invalid BAUD RATE for 16 port>
ERRXIT:
RTN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This is the Major addition to PI16IF driver to add COMSER compatability
; to this driver.
IF EQ,OPTION
ASMMSG " Adding GETPIN & SETPIN "
GETPIN:
CLR D6 ; Clear status on pins.
MOV #AVLPIN, D7 ; Set available mask.
RTN ; Return
; Note if this doesn't work, try logic at ACR0: to set port status,
; or just set to return.
;
SETPIN:
SSTS D6 ; Get processor status
PUSHW D6 ; Save on stack
SVLOK ; Disable interupts
MOV T.IHW(A5), A6 ; Read hardware address.
MOV T.IHM(A5), D7 ; Read port number.
MOVB #1, D6 ; Default to port A
BTST #0, D7 ; Is this port A?
BEQ 10$ ; Yes..use it.
MOVB #2, D6 ; Default to port B
10$: ORB #^H81, D7 ; Force 2nd half of DUART.
MOVB D7,4(A6) ; Select duart
; NOP ; [103][104]
BTST #RS%RTS, D0 ; Set or reset RTS
BEQ 20$ ; Reset it.
MOVB D6, P.SOB(A6) ; Set RTS.
BR 30$
20$: MOVB D6, P.ROB(A6) ; Reset RTS
30$: POPW D6 ; Restore processor status.
LSTS D6
RTN
;--- ENTER WITH D0 BITS 0..6=BAUD RATE CODE, D0 B7 = ACR
; A5 -> TRMDEF BLK
SBAUD:
; Get port number and base addresses 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 # as displacement
LEA A1,BVAL ; SAVE BAUD RATE VALUE ON CURR PORT
MOVB D3,0(A1)[D2]
MOV D2,D4 ; keep a copy
CLR D3
BCLR #0,D2 ; EVEN OR ODD PORT
BEQ EADDR
MOV #8.,D3 ; BASE ADDR OF CHANNEL
EADDR:
LSL D2,#3 ; BASE ADDR OF UART = 8*PORT NUM
ORB #^H80,D2
ADD D2,D3 ; Set D2 to base of DUART
; set D3 to base of specific channel
LSL D2,#8. ; PUT ADDR IN HI BYTE
LSL D3,#8.
MOV #TRDYPRT,A3 ;[106] TX RDY PORT
MOVW D3,D5
ADDW #<P.MDR_8.>,D5
MOVB #M1$8B!M1$NP,D5 ; Set up mode register 1
MOVW D5,@A2
CALL WZ80
; JEQ Z80ERR ; [104]
MOVB #M2$1SB!M2$NM!M2$CET,D5 ; Set up for mode register 2
CMPB D0,#4 ; Did we want 110 baud
BNE 30$
MOVB #M2$2SB!M2$NM!M2$CET,D5 ; Set to two stop bits
30$:
MOVW D5,@A2 ; Set up mode register 2
CALL WZ80
; JEQ Z80ERR ; [104]
CLRB D5 ; NO INTS ENABLED ON UART
BTST #11.,D3 ; CHANNEL A ?
BEQ 40$ ; GO IF TRUE
ROLB D5,#4 ; SHIFT UP FOR CHANNEL B
40$:
LEA A0,IMASK1 ; BASE ADDRESS OF IMR BYTE TABLE
MOV D4,D0 ; SAVE CHANNEL NUM
LSR D4,#1 ; INDEX CORRECT MASK REGISTER
ADD D4,A0
ORB D5,@A0 ; ADD TO EXISTING MASK VALUE
MOVB @A0,D5 ; D1 REFLECTS BOTH CHANNELS
MOVW D5,@A2 ; PROGRAM DUART
CALL WZ80
; JEQ Z80ERR ; [104]
; Now enable DTR & RTS
MOVW D2,D5
ADDW #<P.SOB_8.>,D5
MOVB #5,D5 ; SET UP CHANNEL A
BTST #11.,D3 ; TEST IF CHANNEL B
BEQ 50$
MOVB #22,D5 ; SET UP CHANNEL B
50$:
LEA A0,OPBIT1 ; BASE ADDRESS OF OUTPUT BYTE TABLE
ADD D4,A0
ORB D5,@A0 ; ADD TO EXISTING BIT PATTERN
MOVB @A0,D5 ; D1 REFLECTS BOTH CHANNELS
MOVW D5,@A2 ; SET BITS ON
CALL WZ80
; JEQ Z80ERR ; [104]
MOVW D2,D5
ADDW #<P.OCR_8.>,D5
MOVW D5,@A2 ; SET UP OPR
CALL WZ80
; JEQ Z80ERR ; [104]
; SET LOCAL MEMORY FLAGS AND POINTERS
LEA A0,PORTS ; PORT INITED INDICATOR
MOVW @A0,D2 ; GET PROVIOUS INITED PORTS
BSET D0,D2 ; MARK CURRENT PORT AS INITED
MOVW D2,@A0 ; SAVE INDICATOR
LSL D0,#2 ; INDEX LONG WORDS
LEA A0,TCB0
ADD D0,A0
MOV A5,@A0 ; SAVE TRMDEF BLOCK ADDRESS
MOV D3,T.IHW(A5) ; SAVE DUART ADDRESS IN TRMDEF BLOCK
Z80ERR:
TYPECR <No response from the 16 port.>
RTN
;-------- TURN OFF ALL PORTS -------
PRTOFF:
MOV #DATAPRT,A4 ; [106] PORT TO Z80
MOV #^H0F,D0 ; PORTS 0..F
NXTOFF:
MOVW D0,D1
ORW #^H0FC00,D1
AND
W #^H0FCFF,D1 ; FC -> DISABLE XMITTER INTERRUPT
MOVW D1,@A4 ; DISABLE XMIT INT
CALL WZ80
MOV D0,D3
LSL D3,#3 ; 8*PORT = BASE ADDR
AND #^H0FF,D3
ORB #^H80,D3 ; SET HIT BIT FOR CTRL PORT OUTPUT
LSL D3,#8. ; MOVE TO HI BYTE
ADDW #<P.CMR_8.>,D3 ; OFFSET TO CMD REG
MOVB #CM$RXDI!CM$TXDI,D3 ; disable RCV AND XMIT
MOVW D3,@A4
CALL WZ80
DBF D0,NXTOFF
RTN
;--------- INTERRUPT SERVICE ROUTINE -------
; INTRPT
; Come here via INTERRUPT vector to process all PM-1016 INTERRUPTs.
INTRPT:
SAVE A0-A6,D0-D7
SVLOK ; [105] Disable other Interrupts
LEA A3,PORTS
MOV #DATAPRT,A4 ;[106] INPUT PORT
CLR D1
MOVW @A4,D1
MOV D1,D0 ; SAVE DATA BYTE
LSR D0,#8. ; MOVE PORT NUM TO LOW BYTE
CMPB D0,#^H0FF ; XMIT INT?
JNE NOXMIT
CLR D2
AND #^H0FF,D1
BSET D1,D2
LEA A5,TCB0
LSL D1,#2 ; LONG WORD OFFSET
MOV 0(A5)[D1],D1 ; TCB PNTR, USE D0 TO SET FLAGS
MOV D1,A5
JEQ FLSINT
ANDW @A3,D2
JEQ FLSINT
TRMOCP ; get next output character from TRMSER
MOV T.IHM(A5),D0
TST D1 ; data available?
BPL OPRG7 ; yes -
ANDW #^C<OIP>,@A5 ; no - clear the OIP flag
;Send character to transmitter
OPRG7:
MOV #DATAPRT,A4 ;[106] XMIT DATA PORT
AND #^H0FF,D1 ; CLEAR PORT NUM
LSL D0,#8. ; PORT NUM INTO HI BYTE OF LOW WRD
MOVB D1,D0 ; SET PORT NUM IN WORD TO XMIT
CALL WZ80 ; MAKE SURE Z80 NOT IN INT ROUTINE
MOVW D0,@A4 ; send character to 16 PORT
; NOP ; [103][104]
JMP FLSINT
;--------- RECEIVE FROM TERMINAL ------
NOXMIT:
CLR D2
AND #^H0FF,D0 ; GET PORT NUM
BSET D0,D2
LEA A5,TCB0
LSL D0,#2 ; LONG WORD OFFSET
MOV 0(A5)[D0],D0 ; TCB PNTR, USE D0 TO SET FLAGS
MOV D0,A5
BEQ FLSINT
ANDW @A3,D2
BEQ FLSINT
;Input Character Interrupt Routine
;
;Come here whenever we get a receiver interrupt. Read the character from
;the PM-1016 and pass on to TRMSER.
;
;ENTER WITH D1 = INPUT BYTE
; A5 TRMDEF BLOCK PNTR
; All registers SAVEd on stack
INPR:
TRMICP ; go process the character
FLSINT:
REST A0-A6,D0-D7 ; restore registers
RTE ; Restore interrupts