; ADIT - Alpha Micro compatible version of DMA ADIT interface
; Version 1.25b
; Disclaimer
; Macrotech makes no representations or warranties with respect to the
; contents hereof and specifically disclaims any implied warranties of
; merchantibility or fitness for any purpose, useful or otherwise.
;
;
;
;This interface driver supports an Adit serial i/o board up to 16 channels.
;All ports have full modem (and therefore printer) control.
;
;Ports are addressed in the TRMDEF statement as 0 through 17 octal.
; This driver IS DMA driven. This driver can support multiple 16
; channels ADITs. Tested with AMOS 1.1A(68), AMOS 1.2., AMOS 1.3
; last update 26JUL84 Ver 1.20
; 25SEP84 Ver 1.21
; 17OCT84 Ver 1.22 FLIP compatible
; 07NOV84 Ver 1.23 Carrier detect enabled for DYALOG
; 04MAR85 VER 1.24 fixed bug in INIT routine
; 04JUN85 ver 1.25 made compatible with BAUD & WELCOM
; 27JUN85 ver 1.25a modified for 2 board operation (See CBITBL)
; Added tables for CONFIG macro. (blh)
; 06FEB86 ver 1.25b Added comments, set for 1 board
; operation to conserve dvr size (hjo)
; IDV hash as released 072-240-505-651
; uses standard TRMDEF baud rate, 8 data, 1 stop bit, no xon-xoff as default.
; Ports requiring special rates can be accomodated by using CONFIG macro in
; the OVRIDE table.
; Standard release configuration:
; port = E0h
; interrupt level = 7
; To change the port address/interrupt or configure for use with
; multiple boards; make changes to the table "CBITBL:", each ADIT
; uses 5 consecutive ports and one interrupt level. Each additional
; ADIT board defined in CBITBL will enlarge the driver by approx 2k
; for DMA buffer space.
SEARCH SYS
SEARCH SYSSYM
SEARCH TRM
OBJNAM 0,0,[IDV]
; Adit I/O port address offsets from base address.
;
AIC = 0 ;command register
AIR1 = 1 ;interface register 1
AIR2 = 2 ;interface register 2
AIR3 = 3 ;interface register 3
ASEMA4 = 4 ;semaphore register
AIACK = 5 ;interrupt acknowledge register
;
ABUSY = 0 ;semaphore busy bit = bit 0
;
; immediate command definitions issued thru aic.
;
ASTAT = 0 ;request io status
ARSET = ^H10 ;io channel reset
AERSET = ^H20 ;io channel error reset
ARECN = ^H30 ;io channel reconfiguration
ASDI = ^H40 ;single data in
AISDA = ^H50 ;interrupt on single data in
ASDO = ^H60 ;single data out
AISDOB = ^H70 ;interrupt on single out buffer space
AEXT = ^H80 ;io extended command
AEXTI = ^H90 ;aext with interrupt on completion
ARES1 = ^H0A0 ;reserved for future use
ASPCL = ^H0B0 ;special conditions command
AFRSET = ^H0C0 ;full board reset
AMTST = ^H0C1 ;nondestructive ram test
ANONE = ^H0F0 ;illegal command
;
;
; extended command definitions
;
SYNRCN = 1 ;synchronous line reconfiguration
SETECB = 2 ;set/clr ecb host address
OUTWBC = ^H10 ;dma out with byte count
OUTWEM = ^H12 ;dma out with eom character search
INWBC = ^H30 ;dma input with byte count
INWEOM = ^H32 ;dma input with eom character search
;
; subcommand definitions for special condition command
;
TOGCON = ^H10 ;toggle control lines
INTCON = ^H20 ;interrupt on external int
CANDMA = ^H31 ;cancel extended command
CANINT = ^H32 ;cancel interrupt attention requests
;
; special conditions bit definitions in AIR2
;
RTSBIT = 2 ;to toggle rts
DTRBIT = ^H80 ;to toggle dtr
BRKBIT = ^H10 ;start/stop reverse break condition
;
; bit definitions for request status returned values
;
INSTAT = 1 ;input buffer has data
OTSTAT = 2 ;output data will be accepted
CDSTAT = 4 ;channel had active command
OBSTAT = 8. ;out buffer still has data to send
DCDSTA = ^H10 ;non-latched dcd flag
BRKSTA = ^H20 ;latched break flag
PARSTA = ^H40 ;latched parity error flag
OVRSTA = ^H80 ;latched overrun (lost data) flag
;
;
; reconfiguration command parameters
;
B81N = ^H0C4 ;8 bits, 1 stop, no parity
BXONOF = ^H10 ;set xon xoff onboard protocol
BMULT = ^H20 ;use multiple output buffers
ONDTR = ^H80 ;dtr active - include with hi time constant
ONRTS = ^H40 ;rts active - include with hi time constant
ONBOTH = ONDTR + ONRTS ;both dtr and rts active - hi time constant
;
; macro to wait on interface busy. A3 must = baseport
;
DEFINE WAITBZY
10$$: BTST #ABUSY,ASEMA4(A3) ;test busy bit of semaphore port
BNE 10$$ ;continue testing til not busy
ENDM
; define storage for each TRMDEF.
=0
A.TDEF: BLKL 1 ; pointer to TRMDEF
A.STAT: BLKB 1 ; last status obtained
A.CMD: BLKB 1 ; extended comand byte
A.CNT: ; word format buffer count
A.LOWC: BLKB 1 ; buffer count low byte
A.HIC: BLKB 1 ; buffer count high byte
A.DMA: ; low word format DMA address
A.ADLO: BLKB 1 ; DMA address low
A.ADMI: BLKB 1 ; adresss middle
A.ADHI: BLKB 1 ; adresss high
A.BUFF: BLKB 117. ; DMA buffer area
A.SIZ=.
=0
TOTBUF=0
; This macro defines the board parms and interrupt header code.
DEFINE BOARD BRDADD,ILEVEL,INITED
10$$: WORD BRDADD!^H0FF00
BYTE ILEVEL*4,INITED
; this vector entry routine is duplicated for each board for speed.
SVLOK
SAVE A0-A6,D0-D7
MOV #TOTBUF,D7 ; get base port #
MOVW 10$$,A3 ; A3 gets base address of board
JMP INTCOM ; continue interrupt processing
TOTBUF=TOTBUF+16.
CBISIZ=.-10$$
ENDM
PSECT
BR CHROUT ;output init routine
BR INADIT ;interface init routine
JMP GETSTA ;get channel status
JMP ICMND ;issue immediate command
JMP XCMND ;issue extended command
;
;
; This routine initilizes output by arming transmit interrupts.
CHROUT: SAVE A3,D2,D0
MOV T.IHW(A5),A3 ;get board base address
MOV T.IHM(A5),D2 ;get channel number
AND #17,D2 ; mask to 0-17
SSTS D0
SVLOK
WAITBZY ; handshake
ORB #AISDOB,D2
MOVB D2,AIC(A3) ;issue command
LSTS D0
REST A3,D2,D0
RTN
;
; INADIT initilizes ADIT card, interrupt vector for card and ADIT channel.
; The standard TRMDEF parameters can be bypassed by adding a OVRIDE entry.
INADIT:
; get the board address and interrupt level from channel/board/interrupt table
MOVW D0,T.BAU(A5) ; save baud rate in TRMDEF [1.25]
SSTS D0 ; save current processor status bits
MOV T.IHM(A5),D2 ; D2 gets channel number
LEA A6,MAXPRT ; index maximum port
CMPW D2,@A6 ; legal
JHIS NOTDEF ; board not defined
MOV D2,D3 ; D3 as well
AND #17,D2 ; D2 gets channel number mod 16.
ASR D3,#4. ; D3 gets board number.
MUL D3,#CBISIZ ; then multiply by CBI entry size
LEA A0,CBITBL ; index the table
ADD D3,A0 ; add offset to proper entry in table
MOVW (A0)+,A3 ; A3 gets board base address
MOV A3,T.IHW(A5) ; set board address in TRMDEF
CLR D5 ; PRECLEAR [1.24] (was D7!)
MOVB (A0)+,D5 ; D5 gets interrupt level * 4
SUPVR
SVLOK
TSTB @A0 ; test for board already inited.
BNE OLDINT ; interrupt already done
; init interrupt vector and ADIT
SETB (A0)+ ; flag we have inited this board
MOVW #434,A6 ; get address of interrupt vectors
SUB D5,A6
MOV A0,@A6 ; install interrupt vector
WAITBZY
MOVB #AFRSET,AIC(A3) ;issue full board reset command
OLDINT:
; clear the channel of any pending commands
WAITBZY ; wait for board
ORB #ARSET,D2 ; form io channel reset command
MOVB D2,AIC(A3) ; issue command
ANDB #^H0F,D2 ; clear command portion of register
; determine if this channel overrides regular TRMDEF.
LEA A6,OVRIDE ; index configuration overrride table
MOV T.IHM(A5),D7 ; D7 gets channel #
10$: MOVW (A6)+,D6 ; get 1st word of entry
BMI 20$ ; end of table-use default
ADD #OVRSIZ-2,A6 ; bump to next entry
CMP D6,D7 ; matching channel #?
BNE 10$ ; no-keep looping
SUB #OVRSIZ-2,A6 ; back up to matching entry
MOVB (A6)+,D3 ; get AIR1
MOVB (A6)+,D4 ; get AIR2
MOVB (A6)+,D5 ; get AIR3
SVUNLK
TYPE <PRE-CONFIGED IN ADIT.IDV>
SLEEP #10000.
SVLOK
BR 30$ ; load em up.
; Use TRMDEF baud rate and standard 8 data, 1 stop, no XON-XOFF, full handshake.
20$:
; 8 data, 1 stop, no parity or XON/XOFF, single output buffer (DMA uses only 1)
MOVB #304, D3 ; set AIR1 parms
; set up baud rate
MOVW T.BAU(A5), D6 ; get system rate
LEA A6, BTABLE-2 ; index baud rate table -4
22$: ADDW #2, A6 ; pre-increment
MOVB (A6)+, D7 ; compare to possible
JEQ BBAUD ; end of list
CMPB D6, D7 ; match ?
BNE 22$ ; no-try next
MOVB (A6)+, D4 ; set AIR2
MOVB (A6)+, D5 ; set AIR3
30$: WAITBZY
MOVB D3,AIR1(A3)
MOVB D4,AIR2(A3)
MOVB D5,AIR3(A3)
ORB #ARECN,D2 ;form reconfigure command
MOVB D2,AIC(A3) ;issue command
WAITBZY
ANDB #^H0F,D2
ORB #AISDA,D2
MOVB D2,AIC(A3) ;issue int on input command
WAITBZY
; index DMA command/buffer area
LEA A4,ADTBL ; index table
MOV T.IHM(A5),D7 ; get channel #
ASL D7,#7. ; multiply by 128.
ADD D7,A4 ; A4 indexs the right entry
MOV A5,A.TDEF(A4) ; set TRMDEF pointer
MOVB #SETECB,A.CMD(A4) ; set extended command byte
MOV #A.BUFF,D7
ADD A4,D7 ; D7 gets address of buffer
MOVW D7,A.DMA(A4) ; set DMA buffer address for low 16
SWAP D7
MOVB D7,A.ADHI(A4) ; set high byte of 24 bit address
MOV A4,D3
ADD #A.CMD,D3 ; D3 indexs extended command byte
WAITBZY ; moved waitbzy to here from end 8/28
MOVB D3,AIR1(A3)
ASR D3,#8.
MOVB D3,AIR2(A3)
ASR D3,#8.
MOVB D3,AIR3(A3) ;adit parms loaded with ecb adr
ANDB #^H0F,D2
ORB #AEXT,D2
MOVB D2,AIC(A3) ;set permanent ecb adr in adit
INITXT:
LSTS D0 ;restore original status bits.
RTN
BBAUD: TYPECR <?ILLEGAL BAUD RATE FOR ADIT?>
BR INITXT
; general interrupt processor
;Note: Will only process single out, in and dma out ints.
; At entry, A3 indexs base port of interrupting board.
; D7 contains lowest port on the board (e.g. ^O20)
INTCOM: CLR D0
MOVB AIACK(A3),D0 ;acknowledge int, get chan/cmnd
MOV D0,D2
ANDB #^H0F,D0 ;d0 = channel number mod 16.
ANDB #^H0F0,D2 ;d2 = original command
; find TRMDEF entry for this channel
LEA A4,ADTBL
ADD D0,D7 ; D7 gets full channel #
ASL D7,#7. ; D7 gets offset to port's entry
ADD D7,A4 ; A4 now indexs the port entry
MOV A.TDEF(A4),D7 ; get TRMDEF ptr & set flags
BEQ SPUR ; no TRMDEF defined
MOV D7,A5 ; A5 gets TRMDEF address
; check command byte to see why card interrupted host
CMPB D2,#AEXTI
BEQ IOTDMA ;its dma out completion
CMPB D2,#AISDOB ; treat single out as DMA out
BEQ IOTDMA ; do output
CMPB D2,#AISDA ; input avail?
BNE SPUR ; no- unknown command
; process single input interrupt
MOREIN:
ORB #ASDI,D0 ; d0 forms input command
WAITBZY
MOVB D0,AIC(A3) ;issue single data in command
ANDB #^H0F,D0
WAITBZY
MOVB AIR2(A3),D1 ;get data byte
SAVE D0,A3,A4 ; save em
TRMICP ;give data to terminal driver
REST D0,A3,A4 ; restore em
MOVB AIR1(A3),D1 ;get new status byte
MOVB D1,A.STAT(A4) ;update in uentry
ANDB #INSTAT,D1
BNE MOREIN ;more data available
ORB #AISDA,D0
MOVB D0,AIC(A3) ;issue input int rearm command
REST A0-A6,D0-D7
RTE
SPUR: ORB D0,D2
MOVB D2,^H0FFFFFE00
REST A0-A6,D0-D7
RTE
;
; process dma out completion interrupts
IOTDMA: LEA A2,A.BUFF(A4) ; index output buffer
SAVE D0, A3,A4 ; save some regs
PUSH A2 ; and save for later
CLR D2 ; D2 counts bytes
10$: TRMOCP ;get data byte
TST D1 ; check for no more data
BMI 20$ ; no (more) output
MOVB D1,(A2)+ ; move to DMA buffer in ADTBL
ADD #1,D2 ; bump count
CMPB D2,#117. ; room for more
BLO 10$
20$: POP D7 ; get buffer base address
REST D0, A3,A4 ; restore regs that get trashed
TST D2 ; anything to output ?
BEQ OIPLOW ; no-clear OIP bit
; do extended DMA output, even for single char output.
MOVW D7,A.DMA(A4) ; yes set low 16 bits
SWAP D7 ; swap 16 bit words
MOVB D7,A.ADHI(A4) ; set high 8 bits
MOVB #OUTWBC,A.CMD(A4) ; set extended command in ecb
MOVW D2,A.CNT(A4) ; set output count word
ANDB #^H0F,D0
ORB #AEXTI,D0 ; form extended out command
WAITBZY
MOVB D0,AIC(A3) ; issue start of extended command
REST A0-A6,D0-D7
RTE ; do not clear OIP in status til all
; data has been output.
OIPLOW:
BCLR #7,@A5 ; clear oip in status byte
REST A0-A6,D0-D7
RTE
;
; allows obtaining current status from adit
; getsta entry: A5=TRMDEF address
; changes D4,D5,D6
GETSTA: SAVE A3-A4
CALL FINDC ; find the channel
BNE 10$
SUPVR
SVLOK
ORB #ASTAT,D5 ; make it command
WAITBZY
MOVB D5,AIC(A3) ;issue request status command
WAITBZY
MOVB AIR1(A3),D4 ;get status byte in d4
MOVB AIR2(A3),D5 ;get 8530 status
MOVB AIR3(A3),D6 ; bits.
MOVB D4,A.STAT(A4) ;also save in uentry
LSTS #0
10$: REST A3-A4
RTN ;with d4 = status
;
; icmnd allows output of an immediate command
; icmnd entry: A5=TRMDEF adr;d1,d2,d3=air1,air2,air3; d4=command
; returns new channel status in d4 if the command issued was one
; of the adit commands that returns status.
; also returns AIR2 and AIR3 bits in D2,D3
ICMND:
SAVE A3-A4,D5
CALL FINDC
BNE 10$
ORB D5,D4 ; add channel to command
SUPVR
SVLOK
WAITBZY
MOVB D1,AIR1(A3)
MOVB D2,AIR2(A3)
MOVB D3,AIR3(A3)
MOVB D4,AIC(A3) ;issue immediate command
WAITBZY
MOVB AIR1(A3),D4
MOVB AIR2(A3),D2
MOVB AIR3(A3),D3 ; give statuses back to regs
LSTS #0
10$: REST A3-A4,D5
RTN
;
; allows output of an extended command
; xcmnd entry: A5=TRMDEF address, A2=address of extended command.
XCMND:
SAVE A3-A4,D5
CALL FINDC
BNE 10$
SUPVR
SVLOK
WAITBZY
MOV A2,D7
MOVB D7,AIR1(A3)
ASR D7,#8.
MOVB D7,AIR2(A3)
ASR D7,#8.
MOVB D7,AIR3(A3)
ORB #AEXT,D5 ;DONT use interrupt completion cmnd
MOVB D5,AIC(A3) ;issue start of extended command
WAITBZY
LSTS #0
10$: REST A3-A4,D5
RTN
; findc finds the ADTBL entry for a specified channel
; At entry:
; A5 indexs the system TRMDEF for that ADIT channel
; At exit,
; Z set indicates valid ADIT channel found.
; D5 contains the port number mod 16.
; A3 index hardware base port.
; A4 indexs the ADTBL entry
FINDC: LEA A4,ADTBL
10$: MOV @A4,D7
BMI 100$ ; not found
ADD #128.,A4 ; pre-add
CMP D7,A5 ; compare
BNE 10$ ; keep looking
SUB #128.,A4 ; index the match
MOV T.IHM(A5),D5
AND #17,D5 ; D2 gets port number mod 16
MOV T.IHW(A5),A3 ; index hardware
LCC #4 ; flag we found it
100$: RTN
; This table defines all ADIT boards in the system, up to a maximum of 8.
; The first entry defines ports 0-17 octal, the second defines 20-37, etc.
; Each entry must use a unique and otherwise unused interrupt.
; No table termination is needed.
CBITBL: BOARD ^H0E0,7 ; port E0H, interrupt 7
; BOARD ^H0E8,3 ; port E8H, interrupt 3 (example second board)
MAXPRT: WORD TOTBUF ; total ports defined
; This table contains the extended DMA command and data buffers for each
; channel and the TRMDEF address of each defined channel. Each board defined
; requires 16.*128. bytes, even if all ports are not defined.
; The board entries are mapped in the same order as the CBITBL; entry points
; are calculated by the board offset in each interrupt header (DEFINE CBITBL)
; and by the port number stored in T.IHM(A5). At interrupt level, the ADIT
; card itself defines the port number mod 16. This table terminates with a
; -1 longword to allow searching the table for a matching TRMDEF.
ADTBL: BLKB TOTBUF*128.
LWORD -1 ; termination of table for FINDC.
DEFINE CONFIG PORT,AIR1,AIR2,AIR3
WORD PORT
BYTE AIR1,AIR2,AIR3,0
ENDM
OVRSIZ=6
OVRIDE:
; OVRIDE is the configuration override table. This allows the more arcane
; features of the ADIT board to be easily invoked. Each entry in the
; OVRIDE table consists of five elements:
; 1.) The CONFIG macro command.
; 2.) The I/O channel number to be re-configured.
; 3.) AIR1 byte containing information about word length,
; stop bits, parity & flow control.
; 4.) AIR2 byte containing baud rate information.
; 5.) AIR3 byte containing additional baud rate & flow
; control information.
; The bit tables below define the function of the AIR1, AIR2 & AIR3 arguements.
; The OVRIDE table must end with a short word -1.
; ===========================================================================
; BIT TABLE for defining the AIR1 argument.
; 7 6 5 4 3 2 1 0 Function
; --- --- --- --- --- --- --- --- ---
-----------------------------------
; 0 0 5 Data bits
; 1 0 6 Data bits
; 0 1 7 Data bits
; 1 1 8 Dtat bits
; 0 Single output buffer
; 1 Multiple output buffers (not supported with Alpha Micro).
; 0 Onboard XON/XOFF disabled
; 1 Onboard XON/XOFF enabled
; 0 0 Reserved for future use
; 0 1 1 stop bit
; 1 0 1 1/2 stop bits
; 1 1 2 stop bits
; 0 Odd parity
; 1 Even parity
; 0 Disable parity
; 1 Enable parity
; ===========================================================================
; BIT TABLE for defining AIR2 & AIR3 arguements.
; -----AIR2------ -----AIR3------ Function 1 = on
; 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 (bit numbers) 0 = off
; x x x x x x x x 1 x x x x x x x DTR set active x = don't care
; x x x x x x x x x 1 x x x x x x RTS set active
; 0 0 0 0 0 0 1 0 x x 0 0 0 0 0 0 38400 bps
; 0 0 0 0 0 1 1 0 x x 0 0 0 0 0 0 19200 bps
; 0 0 0 0 1 1 1 0 x x 0 0 0 0 0 0 9600 bps
; 0 0 0 1 1 1 1 0 x x 0 0 0 0 0 0 4800 bps
; 0 0 1 1 1 1 1 0 x x 0 0 0 0 0 0 2400 bps
; 0 1 1 1 1 1 1 0 x x 0 0 0 0 0 0 1200 bps
; 1 1 1 1 1 1 1 0 x x 0 0 0 0 0 0 600 bps
; 1 1 1 1 1 1 1 0 x x 0 0 0 0 0 1 300 bps
; 1 1 1 1 1 1 1 0 x x 0 0 0 0 1 1 150 bps
; 1 1 1 1 1 1 1 0 x x 0 0 0 1 0 1 110 bps
; ===========================================================================
; Example to reconfigure channel 12 (decimal) for 5 data bits,
; 1 1/2 stop bits, odd parity, 150 baud.
;
; arguement binary octal
; AIR1 00001001 011
; AIR2 11111110 376
; AIR3 00000011 003
; ===========================================================================
;
;example CONFIG 12.,AIR1,AIR2,AIR3
; CONFIG 12.,011,376,003 ; Chan # in decimal, AIR1-3 in octal
WORD -1 ; OVRIDE terminator