; 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 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 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 DEFINE BBITS RATE, AIR2, AIR3 BYTE RATE, AIR2, AIR3 ENDM ; This table defines the standard systembaud rates supported by ADIT. BTABLE: BBITS 21, 002,0!ONBOTH ; 38400 BBITS 20, 006,0!ONBOTH ; 19200 BBITS 17, 016,0!ONBOTH ; 9600 BBITS 15, 036,0!ONBOTH ; 4800 BBITS 13, 076,0!ONBOTH ; 2400 BBITS 10, 176,0!ONBOTH ; 1200 BBITS 07, 376,0!ONBOTH ; 600 BBITS 06, 376,1!ONBOTH ; 300 BBITS 04, 376,3!ONBOTH ; 150 BBITS 02, 162,5!ONBOTH ; 110 BYTE 0 EVEN NOTDEF: TYPECR EXIT END .