PAGE 62,132 ; ; HDLC driver for SCC-Based cards ; INCLUDE ENVIRON.ASM IFDEF KANT .186 NEEDSLOT EQU 1 INCLUDE KANTEQU.ASM ENDIF IFDEF MSC .186 NEEDSLOT EQU 1 INCLUDE MSCEQU.ASM ENDIF IFDEF SWITCH NEEDSLOT EQU 1 ENDIF DATA SEGMENT PUBLIC 'DATA' SETRVEC MACRO A ;MACRO TO CHANGE THE RX INT VECTOR MOV IORXCA[BX],OFFSET A ENDM SETTVEC MACRO A ;MACRO TO CHANGE THE TX INT VECTOR MOV IOTXCA[BX],OFFSET A ENDM SIOR MACRO MOV DX,SIO[BX] IN AL,DX ENDM ; SIOW MACRO ; OUT (SIO),A MOV DX,SIO[BX] OUT DX,AL ENDM ; SIOCR MACRO ; IN A,(SIOCMD) MOV DX,SIOC[BX] IN AL,DX ENDM ; SIOCW MACRO ; OUT (SIOCMD),A MOV DX,SIOC[BX] OUT DX,AL ENDM ; SIOCAD MACRO ; LD C,(SIOCMD) MOV DX,SIOC[BX] ENDM ; DELAY MACRO JMP $+2 JMP $+2 JMP $+2 JMP $+2 ENDM INCLUDE STRUCS.ASM HWDATA STRUC DB HARDWAREDATA DUP (0) ; REMAP HARDWARE INFO ASIOC DW 0 ; A CHAN ADDRESSES SIO DW 0 ; OUR ADDRESSES (COULD BE A OR B) SIOC DW 0 BSIOC DW 0 ; B CHAN CONTROL A_PTR DW 0 ; PORT ENTEY FOR A CHAN B_PTR DW 0 ; PORT ENTRY FOR B CHAN IOTXCA DW 0 ; INTERRUPT VECTORS IOTXEA DW 0 IORXCA DW 0 IORXEA DW 0 ; LINKSTS DB 0 ; SDRNEXT DW 0 SDRXCNT DW 0 CURALP DW 0 OLOADS DB 0 ; LOCAL COUNT OF BUFFERS SHORTAGES FRAMELEN DW 0 SDTNEXT DW 0 ; POINTER to NEXT BYTE to TRANSMIT SDTXCNT DW 0 ; CHARS LEFT TO SEND RR0 DB 0 ; CURRENT RR0 TXFRAME DW 0 ; ADDRESS OF FRAME BEING SENT ; SDFLAGS DB 0 ; GENERAL FLAGS PCTX_Q DW 0 ; HDLC HOLDING QUEUE RXMSG_Q DW 0 ; RX INTERRUPT TO SDLC BG ; ;SOFTDCD DB 0 ; RX ACTIVE FLAG FOR 'SOFT DC TXDELAY DB 0 ; TX KEYUP DELAY TIMER SLOTTIME DB 0 ; TIME TO WAIT IF WE DONT SEND FIRSTCHAR DB 0 ; CHAR TO SEND FOLLOWING TXDELAY L1TIMEOUT DW 0 ; UNABLE TO TX TIMEOUT PORTSLOTIMER DB 0 HOLDINIT DW 0 ; START VALUE FOR HOLD TIMER HOLDTIMER DW 0 ; HOLD RTS TIMER (PSEUDO FULL-DUP) ; IFDEF KANT DCDON DW 0 DCDOFF DW 0 ; LED CONTROLS RXON DW 0 RXOFF DW 0 ELSE TXBRG DW 0 ; FOR CARDS WITHOUT /32 DIVIDER RXBRG DW 0 ENDIF WR10 DB 0 ; NRZ/NRZI FLAG HWDATA ENDS ; SDFLAGS ; SDTINP EQU 10B ; 1 = TRANSMISSION in PROGRESS SDRINP EQU 1000000B ; 1 = RX IN PROGRESS ABSENT EQU 1B ; 1 = ABORT SENT VECTORS EQU IOTXCA IF TYPE HWDATA GT TYPE PORTCONTROL .ERR2 TOO MUCH PORT DATA ENDIF ERRORMSG DB 0DH,0AH,'PORT DEFINITION ERROR$' D14 DB 14 ; FOR RANDOM NUMBER GENERATOR ;SCC DB 0 IFDEF KANT TICKSPERSEC DB 100 ENDIF IFDEF PCSWITCH TICKSPERSEC DB 18 ENDIF extrn porttable:word,numberofports:word EXTRN QCOUNT:BYTE,FREE_Q:WORD,BUFFLEN:ABS IFDEF KANT EXTRN HDLCPORT1:WORD,RAN4:BYTE ENDIF IFDEF NEEDSLOT EXTRN RANDOM:BYTE ENDIF EXTRN TRACE_Q:WORD DATA ENDS IFDEF KANT PUBLIC KANTINIT CODE SEGMENT PUBLIC 'CODE' ASSUME CS:CODE,DS:DATA,ES:DATA ENDIF IFDEF MSC PUBLIC MSCINIT CODE SEGMENT PUBLIC 'CODE' ASSUME CS:CODE,DS:DATA,ES:DATA ENDIF IFDEF PCSWITCH IFDEF OS2 CODE SEGMENT PUBLIC 'CODE' ASSUME CS:CODE,DS:DATA,ES:DATA ELSE INITSEG SEGMENT PUBLIC 'INITSEG' ASSUME CS:INITSEG,DS:DATA,ES:DATA ENDIF PUBLIC DRSIINIT,PC120INIT,TOSHINIT,INITPART1,RLC100INIT,BAYCOMINIT PUBLIC PA0INIT ; EXTRN HOOKINT:NEAR ENDIF IFDEF KANT CLOCKFREQ DD 153600 ; 9,830,400 HZ /(32*2) ENDIF IFDEF MSC EXTRN HOOKINT:NEAR CLOCKFREQ DD 115200 ; 7,372,800 HZ /(32*2) ENDIF IFDEF PCSWITCH CLOCKFREQ DD 76800 ; 4,915,200 HZ /(32*2) TOSHCLOCKFREQ DD 57600 ENDIF SDLCCMD DB 0,0 DB 9,0C0H ; FORCE RESET (BOTH CHANNELS) DB 0,0 DB 2,00000000B ; BASE VECTOR DB 4,00100000B ; SDLC MODE DB 3,11001000B ; 8BIT, CRC ENABLE, RX DISABLED DB 7,01111110B ; STANDARD FLAGS DB 1,00010011B ; INT ON ALL RX, TX INT EN, EXT INT EN DB 5,11100001B ; DTR, 8BIT, SDLC CRC,TX CRC EN ; DB 10,10100000B ; CRC PRESET TO 1 DB 9,00001001B ; ENABLE INTS DB 11,01100110B ; NO XTAL, RXC = DPLL, TXC = RTXC, TRXC = BRG (NEEDS /32 BETWEEN TRXC AND RTXC) DB 14,10000011B DB 14,00100011B DB 15,11000000B ; EXT INT ONLY ON TX UND AND ABORT RX SDLCLEN EQU $-SDLCCMD ; IFDEF PCSWITCH TOSHR11 DB 01111000B ; NO XTAL, RXC = DPLL, TXC = DPLL, NO CLK OUTPUT CIOPARAMS LABEL BYTE DB 2BH,0FFH ; B DIRECTION - ALL IN DB 23H,0FFH ; A DIRECTION - ALL IN DB 1DH,0E2H ; C/T 2 MODE - CONT, EXT IN, EXT O, SQUARE DB 1CH,0E2H ; C/T 1 MODE "" DB 19H,10H ; C/T 2 LSB - 16 = /32 FOR SQUARE WAVE DB 18H,0 ; MSB DB 17H,10H ; C/T 1 LSB DB 16H,0 ; MSB DB 0BH,04H ; CT2 "" - GATE DB 0AH,04H ; CT1 "" - GATE DB 06H,0FH ; PORT C DIRECTION - INPUTS DB 1,84H ; ENABLE PORTS A AND B DB 0,0 ; INTERRUPT CONTROL CIOLEN EQU $-CIOPARAMS DRSIINIT: ; INTERRUPT INITIALISATION CODE MOV DX,IOBASE[BX] ; SCC ORIGIN CALL INITPART1 PUSH DX CALL INITCIO ; SET UP CIO FOR /32 POP DX CALL INITPART2 ; ; SET UP COUNTER UNLESS EXTERNAL CLOCK ; CMP BAUDRATE[BX],0 JNE STARTCOUNTER JMP EXTCLOCK STARTCOUNTER: ; MOV DX,IOBASE[BX] ADD DX,7 ; TO CIO PORT ; ; B CHANNEL ; ; SET COUNTER OUTPUT BIT ACTIVE ; MOV AL,2BH ; PORT B DIRECTION OUT DX,AL DELAY IN AL,DX ; GET IT CMP CHANNELNUM[BX],'A' JE INITACOUNTER ; AND AL,0EFH ; SET BIT 4 AS OUTPUT PUSH AX DELAY MOV AL,2BH OUT DX,AL DELAY POP AX DELAY OUT DX,AL ; UPDATE PORT B DIRECTION DELAY ; ; ENABLE COUNTER ; MOV AL,1 ; MASTER CONFIG OUT DX,AL DELAY IN AL,DX ; GET IT OR AL,40H ; ENABLE CT1 PUSH AX DELAY MOV AL,1 OUT DX,AL DELAY POP AX DELAY OUT DX,AL ; UPDATE MASTER CONFIG DELAY ; ; START COUNTER ; MOV AL,0AH ; CT1 CONTROL OUT DX,AL DELAY MOV AL,6 OUT DX,AL ; START CT1 DELAY ; JMP SHORT EXTCLOCK INITACOUNTER: AND AL,0FEH ; SET BIT 0 AS OUTPUT PUSH AX DELAY MOV AL,2BH OUT DX,AL DELAY POP AX DELAY OUT DX,AL ; UPDATE PORT B DIRECTION DELAY ; ; ENABLE COUNTER ; MOV AL,1 ; MASTER CONFIG OUT DX,AL DELAY IN AL,DX ; GET IT OR AL,20H ; ENABLE CT2 PUSH AX DELAY MOV AL,1 OUT DX,AL DELAY POP AX DELAY OUT DX,AL ; UPDATE MASTER CONFIG DELAY ; ; START COUNTER ; MOV AL,0BH ; CT2 CONTROL OUT DX,AL DELAY MOV AL,6 OUT DX,AL ; START CT2 DELAY EXTCLOCK: CALL INITREST RET RLC100INIT: MOV AX,4 ; BASE ADJUST CALL CHECKCHAN ; SEE IF C OR D MOV DX,IOBASE[BX] ; SCC ORIGIN CALL INITPART1 CALL INITPART2 CALL INITREST RET PC120INIT: MOV DX,IOBASE[BX] ADD DX,4 ; TO SCC ADDRESS CALL INITPART1 CALL INITPART2 CALL INITMODEM CALL INITREST RET TOSHINIT: ; INTERRUPT INITIALISATION CODE MOV DX,IOBASE[BX] ; SCC ORIGIN CALL INITPART1 ; ; SET UP ADDRESS LIST ; MOV AX,IOBASE[BX] MOV BSIOC[BX],AX ; B CHAN ADDR INC AX MOV ASIOC[BX],AX ; A ADDR ; ; SEE WHICH CHANNEL TO USE ; CMP CHANNELNUM[BX],'A' JE INITACHANT ; ; B CHANNEL ; DEC AX ; BACK TO B ADDRESSES MOV B_PTR[BX],BX ; POINT TO OUR ENTRY CMP DI,0 JE INITCOMT ; NO OTHER CHANNEL TO LINK MOV A_PTR[BX],DI ; CROSSLINK CHANNELS MOV B_PTR[DI],BX JMP SHORT INITCOMT INITACHANT: MOV A_PTR[BX],BX ; POINT TO OUR ENTRY CMP DI,0 JE INITCOMT ; NO OTHER CHANNEL TO LINK MOV B_PTR[BX],DI ; CROSSLINK CHANNELS MOV A_PTR[DI],BX INITCOMT: MOV SIOC[BX],AX INC AX INC AX MOV SIO[BX],AX ; ; SET UP VECTORS ; MOV IOTXCA[BX],OFFSET IGNORE ; TX CHANNEL A MOV IOTXEA[BX],OFFSET EXTINT MOV IORXCA[BX],OFFSET SDADRX ; RX CHANNEL A MOV IORXEA[BX],OFFSET SPCLINT ; ; ; INITIALISE COMMS CHIP ; MOV DX,SIOC[BX] MOV SI,OFFSET SDLCCMD ; PARAMS MOV CX,SDLCLEN CMP DI,0 ; OTHER CHAN ALREADY SET UP? JE SIOLOOPT ; NO ADD SI,4 SUB CX,4 ; SKIP RESET SIOLOOPT: LODS SDLCCMD OUT DX,AL DELAY LOOP SIOLOOPT ; ; SET UP BRG FOR REQUIRED SPEED ; MOV DX,WORD PTR TOSHCLOCKFREQ+2 MOV AX,WORD PTR TOSHCLOCKFREQ DIV BAUDRATE[BX] SUB AX,2 ; GIVES BRG PARAM MOV CX,AX ; SAVE MOV DX,SIOC[BX] MOV AL,12 OUT DX,AL DELAY MOV AL,CL OUT DX,AL ; SET LSB DELAY MOV AL,13 OUT DX,AL DELAY MOV AL,CH OUT DX,AL ; SET MSB MOV AL,11 OUT DX,AL MOV AL,TOSHR11 ; REDEFINE TX CLOCK FROM BRG OUT DX,AL CALL INITREST RET ELSE ; ; DATA ENGINE OR MSC800 ; MSCINIT: KANTINIT: ; INTERRUPT INITIALISATION CODE ; ; CLEAR HWDATA IN CASE WARM START ; MOV CX,TYPE HWDATA - HARDWAREDATA LEA DI,ASIOC[BX] XOR AL,AL REP STOSB MOV DX,IOBASE[BX] ; SCC ORIGIN CALL INITPART1 CALL INITPART2 CALL INITREST RET ENDIF INITPART1: ; ; SET UP HOLD TIMER OF NEEDED ; CMP FULLDUPLEX[BX],1 JNE NO_HOLD ; ONLY UED IN FULL DUP MODE MOV AL,PORTTAILTIME[BX] MUL TICKSPERSEC MOV HOLDINIT[BX],AX NO_HOLD: ; ; SEE IF ANOTHER PORT IS ALREADY USING THE OTHER CHANNEL ON THIS CARD ; MOV DI,PORTTABLE MOV CX,NUMBEROFPORTS INIT00: CMP DI,BX JE INIT10 ; NONE BEFORE OURS MOV AX,IOBASE[BX] CMP AX,IOBASE[DI] JE INIT20 ; ANOTHER FOR SAME ADDRESS MOV DI,PORTPOINTER[DI] LOOP INIT00 INIT10: MOV DI,0 ; FLAG NOT FOUND JMP SHORT INIT30 INIT20: ; ; ENSURE ENTRIES ARE FOR DIFFERENT CHANNELS ; MOV AL,CHANNELNUM[BX] CMP AL,CHANNELNUM[DI] JNE INIT30 INIT25: ; ; CHANNEL DEFINITION ERROR ; IFDEF PCSWITCH MOV DX,OFFSET ERRORMSG MOV AH,9 INT 21H ENDIF RET INIT30: ; ; MAKE SURE ONLY A OR B ; CMP CHANNELNUM[BX],'A' JE INIT31 CMP CHANNELNUM[BX],'B' JNE INIT25 INIT31: RET INITPART2: ; ; SET UP ADDRESS LIST - THIS PATH FOR CARDS WITH 'NORMAL' ; ADDRESSING - C/D=A0, A/B=A1, SO ORDER IS BCTRL BDATA ACTRL ADATA ; OR DE, WHICH USES WORD ADDRESSES C/D=A1, A/B=A2 ; MOV AX,DX IFDEF KANT MOV BSIOC[BX],AX ; B CHAN ADDR ADD AX,4 MOV ASIOC[BX],AX ; A CHAN ADDR ELSE MOV BSIOC[BX],AX ; B CHAN ADDR INC AX INC AX MOV ASIOC[BX],AX ; A CHAN ADDR ENDIF ; ; SEE WHICH CHANNEL TO USE ; CMP CHANNELNUM[BX],'A' JE INITACHAN ; ; MUST BE B - CHECKED EARLIER ; IFDEF KANT SUB AX,4 ELSE DEC AX DEC AX ; BACK TO B ADDRESSES ENDIF MOV B_PTR[BX],BX ; POINT TO OUR ENTRY IFDEF KANT MOV DCDON[BX],LED4+1 MOV DCDOFF[BX],LED4 MOV RXON[BX],LED5+1 MOV RXOFF[BX],LED5 ENDIF CMP DI,0 JE INITCOM ; NO OTHER CHANNEL TO LINK MOV A_PTR[BX],DI ; CROSSLINK CHANNELS MOV B_PTR[DI],BX JMP SHORT INITCOM INITACHAN: MOV A_PTR[BX],BX ; POINT TO OUR ENTRY IFDEF KANT MOV DCDON[BX],LED1+1 MOV DCDOFF[BX],LED1 MOV RXON[BX],LED2+1 MOV RXOFF[BX],LED2 ENDIF CMP DI,0 JE INITCOM ; NO OTHER CHANNEL TO LINK MOV B_PTR[BX],DI ; CROSSLINK CHANNELS MOV A_PTR[DI],BX INITCOM: PINITREST: MOV SIOC[BX],AX IFDEF KANT INC AX INC AX ; DATA 2 ABOVE CONTROL ELSE INC AX ; DATA 1 ABOVE CONTROL ENDIF MOV SIO[BX],AX ; ; SET UP VECTORS ; MOV IOTXCA[BX],OFFSET IGNORE ; TX CHANNEL A MOV IOTXEA[BX],OFFSET EXTINT MOV IORXCA[BX],OFFSET SDADRX ; RX CHANNEL A MOV IORXEA[BX],OFFSET SPCLINT ; ; ; INITIALISE COMMS CHIP ; MOV DX,SIOC[BX] MOV SI,OFFSET SDLCCMD ; PARAMS MOV CX,SDLCLEN CMP DI,0 ; OTHER CHAN ALREADY SET UP? JE SIOLOOP ; NO ADD SI,4 SUB CX,4 ; SKIP RESET SIOLOOP: LODS SDLCCMD OUT DX,AL DELAY LOOP SIOLOOP ; MOV WR10[BX],00100000B ; NRZI ; ; SET UP BRG FOR REQUIRED SPEED ; CMP BAUDRATE[BX],0 JNE NORMCLOCK ; ; SET EXTERNAL CLOCK ; MOV DX,SIOC[BX] MOV AL,11 OUT DX,AL DELAY IFDEF KANT MOV AL,00001000B ; RX = RTXC TX = TRXC ELSE MOV AL,00100000B ; RX = TRXC TX = RTXC ENDIF OUT DX,AL ; SET WR11 RET NORMCLOCK: MOV DX,WORD PTR CLOCKFREQ+2 MOV AX,WORD PTR CLOCKFREQ IFDEF PCSWITCH CMP PORTTYPE[BX],12 ; RLC400 JNE NOTRLC400 ; NORMAL CLOCK SYSTEM ; ; RLC 400 USES SAME CLOCK AS TOSH ; MOV DX,WORD PTR TOSHCLOCKFREQ+2 MOV AX,WORD PTR TOSHCLOCKFREQ NOTRLC400: ENDIF DIV BAUDRATE[BX] SUB AX,2 ; GIVES BRG PARAM MOV CX,AX ; SAVE MOV DX,SIOC[BX] MOV AL,12 OUT DX,AL DELAY MOV AL,CL OUT DX,AL ; SET LSB DELAY MOV AL,13 OUT DX,AL DELAY MOV AL,CH OUT DX,AL ; SET MSB IFDEF MSC ; THERE IS NO /32 ON THE MSC800 BOARD, SO WILL USE BRG ; FOR TRANSMIT. THIS REQUIRES IT TO BE REPROGRAMMED BETWEEN TX AND RX, ; AND SO PREVENTS LOOPBACK OR FULLDUP OPERATION ; MOV DX,WORD PTR CLOCKFREQ+2 MOV AX,WORD PTR CLOCKFREQ DIV BAUDRATE[BX] SUB AX,2 ; GIVES BRG PARAM MOV CX,AX ; SAVE MOV RXBRG[BX],AX ; ; CALC TX RATE ; ADD AX,2 SHL AX,1 SHL AX,1 SHL AX,1 SHL AX,1 SHL AX,1 ; *32 SUB AX,2 MOV TXBRG[BX],AX MOV DX,SIOC[BX] MOV AL,12 OUT DX,AL DELAY MOV AL,CL OUT DX,AL ; SET LSB DELAY MOV AL,13 OUT DX,AL DELAY MOV AL,CH OUT DX,AL ; SET MSB ; ; SET TXC=BRG, RXC=DPLL ; MOV DX,SIOC[BX] MOV AL,11 OUT DX,AL DELAY ; MOV AL,01110000B ; RXC=DPLL, TXC=BRG OUT DX,AL ENDIF RET IFDEF PCSWITCH INITCIO: ; ; INITIALISE CIO - DRSI ONLY ; CMP DI,0 JNE CIODONE ; ALREADY SET UP MOV DX,IOBASE[BX] ADD DX,7 ; TO CIO PORT IN AL,DX MOV AL,0 DELAY OUT DX,AL DELAY IN AL,DX MOV AL,0 DELAY OUT DX,AL DELAY MOV AL,1 OUT DX,AL ; FORCE RESET DELAY MOV AL,0 OUT DX,AL ; CLEAR RESET DELAY ; MOV SI,OFFSET CIOPARAMS ; PARAMS MOV CX,CIOLEN CIOLOOP: LODS CIOPARAMS OUT DX,AL DELAY LOOP CIOLOOP ; CIODONE: RET INITMODEM: ; ; SETUP MODEM - PC120 ONLY ; CMP DI,0 JNE MODDONE ; ALREADY SET UP MOV DX,IOBASE[BX] ; BASE ADDR OF CARD MOV AL,0AH OUT DX,AL ; SET MODEM CONTROL LATCH MODDONE: RET ; CHECKCHAN: ; ; ENTERED WITH AX=DIFFERENCE BETWEEN FIRST AND 2ND SCC BASE ADDR ; ; IF CHANNEL = C OR D SET TO SECOND SCC ADDRESS, AND CHANGE TO A OR B ; CMP CHANNELNUM[BX],'B' JBE CHANOK ; ; SECOND SCC ; SUB CHANNELNUM[BX],2 ADD IOBASE[BX],AX CHANOK: RET BAYCOMINIT: MOV AX,2 ; BASE ADJUST CALL CHECKCHAN ; SEE IF C OR D MOV DX,IOBASE[BX] ; SCC ORIGIN CALL INITPART1 CALL BINITPART2 CALL INITREST RET BINITPART2: ; ; SET UP ADDRESS LIST ; MOV AX,DX ADD AX,4 ; OFFSET CONTROL FROM DATA MOV ASIOC[BX],AX ; A CHAN ADDR INC AX MOV BSIOC[BX],AX ; B CHAN ADDR ; ; SEE WHICH CHANNEL TO USE ; MOV AX,DX ; A CHAN DATA CMP CHANNELNUM[BX],'A' JE BINITACHAN ; ; MUST BE B - CHECKED EARLIER ; INC AX ; TO B DATA MOV B_PTR[BX],BX ; POINT TO OUR ENTRY CMP DI,0 JE BINITCOM ; NO OTHER CHANNEL TO LINK MOV A_PTR[BX],DI ; CROSSLINK CHANNELS MOV B_PTR[DI],BX JMP SHORT BINITCOM BINITACHAN: MOV A_PTR[BX],BX ; POINT TO OUR ENTRY CMP DI,0 JE BINITCOM ; NO OTHER CHANNEL TO LINK MOV B_PTR[BX],DI ; CROSSLINK CHANNELS MOV A_PTR[DI],BX BINITCOM: MOV SIO[BX],AX ADD AX,4 ; TO CONTROL MOV SIOC[BX],AX ; ; SET UP VECTORS ; MOV IOTXCA[BX],OFFSET IGNORE ; TX CHANNEL A MOV IOTXEA[BX],OFFSET EXTINT MOV IORXCA[BX],OFFSET SDADRX ; RX CHANNEL A MOV IORXEA[BX],OFFSET SPCLINT ; ; INITIALISE COMMS CHIP ; MOV DX,SIOC[BX] MOV SI,OFFSET SDLCCMD ; PARAMS MOV CX,SDLCLEN CMP DI,0 ; OTHER CHAN ALREADY SET UP? JE BSIOLOOP ; NO ADD SI,4 SUB CX,4 ; SKIP RESET BSIOLOOP: LODS SDLCCMD OUT DX,AL DELAY LOOP BSIOLOOP ; ; SET UP BRG FOR REQUIRED SPEED ; CMP BAUDRATE[BX],0 JNE BNORMCLOCK ; ; SET EXTERNAL CLOCK ; MOV DX,SIOC[BX] MOV AL,11 OUT DX,AL DELAY MOV AL,00100000B ; RX = TRXC TX = RTXC OUT DX,AL ; SET WR11 ; ; BAYCOM RUH PORT USES NRZ ; MOV WR10[BX],00000000B ; NRZ RET BNORMCLOCK: ; MOV WR10[BX],00100000B ; NRZI ; ; THERE IS NO /32 ON THE BAYCOM BOARD, SO FOR THE MOMENT WILL USE BRG ; FOR TRANSMIT. THIS REQUIRES IT TO BE REPROGRAMMED BETWEEN TX AND RX, ; AND SO PREVENTS LOOPBACK OR FULLDUP OPERATION ; MOV DX,WORD PTR CLOCKFREQ+2 MOV AX,WORD PTR CLOCKFREQ DIV BAUDRATE[BX] SUB AX,2 ; GIVES BRG PARAM MOV CX,AX ; SAVE MOV RXBRG[BX],AX ; ; CALC TX RATE ; ADD AX,2 SHL AX,1 SHL AX,1 SHL AX,1 SHL AX,1 SHL AX,1 ; *32 SUB AX,2 MOV TXBRG[BX],AX MOV DX,SIOC[BX] MOV AL,12 OUT DX,AL DELAY MOV AL,CL OUT DX,AL ; SET LSB DELAY MOV AL,13 OUT DX,AL DELAY MOV AL,CH OUT DX,AL ; SET MSB ; ; SET TXC=BRG, RXC=DPLL ; MOV DX,SIOC[BX] MOV AL,11 OUT DX,AL DELAY ; MOV AL,01110000B ; RXC=DPLL, TXC=BRG OUT DX,AL RET PA0INIT: MOV AX,4 ; BASE ADJUST CALL CHECKCHAN ; SEE IF C OR D MOV DX,IOBASE[BX] ; SCC ORIGIN CALL INITPART1 CALL INITPART2 CALL INITREST RET IF 0 ; THIS DOESNT SEEM TO BE USED PINITPART2: ; ; SET UP ADDRESS LIST ; MOV AX,DX MOV ASIOC[BX],AX ; A CHAN ADDR ADD AX,2 MOV BSIOC[BX],AX ; B CHAN ADDR ; ; SEE WHICH CHANNEL TO USE ; MOV AX,DX ; A CHAN CONTROL CMP CHANNELNUM[BX],'A' JE PINITACHAN ; ; MUST BE B - CHECKED EARLIER ; ADD BX,2 ; TO B CTRL MOV B_PTR[BX],BX ; POINT TO OUR ENTRY CMP DI,0 JE PINITCOM ; NO OTHER CHANNEL TO LINK MOV A_PTR[BX],DI ; CROSSLINK CHANNELS MOV B_PTR[DI],BX JMP SHORT PINITCOM PINITACHAN: MOV A_PTR[BX],BX ; POINT TO OUR ENTRY CMP DI,0 JE PINITCOM ; NO OTHER CHANNEL TO LINK MOV B_PTR[BX],DI ; CROSSLINK CHANNELS MOV A_PTR[DI],BX PINITCOM: JMP PINITREST ENDIF ; OF UNUSED BIT ENDIF ; OF PC BITS INITREST: IFNDEF KANT MOV PORTINTERRUPT[BX],OFFSET SIOINT CMP DI,0 JNE INTDONE ; ALREADY SET UP CALL HOOKINT ; INTERRUPT ENDIF INTDONE: CALL RXAINIT SIOCR MOV RR0[BX],AL ; GET INITIAL RR0 RET RXAINIT: SETRVEC SDADRX MOV AL,33H SIOCW ; ERROR RESET WR3 DELAY MOV AL,11011001B ; 8BIT, CRC EN, RX EN SIOCW ; RET IFDEF PCSWITCH IFDEF OS2 CODE ENDS ELSE INITSEG ENDS ENDIF CODE SEGMENT PUBLIC 'CODE' ASSUME CS:CODE,DS:DATA,ES:DATA ENDIF PUBLIC HDLCTX,HDLCRX,HDLCTIMER,HDLCSTART,HDLCEND ; EXTRN Q_ADD:NEAR,Q_REM:NEAR,Q_ADDF:NEAR,NOBUFFERCHECK:NEAR HDLCSTART LABEL BYTE HDLCTIMER: ; ; RECORD CHANNEL ACTIVITY ; CMP LINKSTS[BX],0 JE NOTSENDING INC SENDING[BX] JMP SHORT NOTDCD NOTSENDING: SIOCR ; GET RR0 CMP SOFTDCDFLAG[BX],0 JE CHECKRR0_X TEST AL,10H ; SYNC BIT JZ DCDHIGH_X JMP SHORT NOTDCD CHECKRR0_X: TEST AL,08H ; HARD DCD JZ NOTDCD DCDHIGH_X: INC ACTIVE[BX] IFDEF KANT MOV DX,DCDON[BX] OUT DX,AL JMP SHORT NOTDCD1 ENDIF NOTDCD: IFDEF KANT MOV DX,DCDOFF[BX] OUT DX,AL NOTDCD1: ENDIF ; CMP SOFTDCD[BX],0 ; SOFT DCD TIMER ACTIVE? ; JE NOSOFTTIMER ; ; DEC SOFTDCD[BX] ; ;NOSOFTTIMER: IFDEF NEEDSLOT CMP SLOTTIME[BX],0 ; SLOT TIMER ACTIVE? JE NOSLOTTIMER DEC SLOTTIME[BX] NOSLOTTIMER: ENDIF CMP HOLDTIMER[BX],0 JE NOHOLD DEC HOLDTIMER[BX] JZ HOLDDONE JMP TIMERRET ; CANT HAVE TXDELAY OR STUCK TX ; IF HOLD RUNNING HOLDDONE: ; ; HOLD EXPIRED - DROP RTS ; CLI CALL DROPRTS STI JMP TIMERRET NOHOLD: CMP TXDELAY[BX],0 JE NOTTXDELAY DEC TXDELAY[BX] JNZ NOTTXDELAY ; ; TXDELAY HAS EXPIRED - START SENDING ; MOV AL,SDTXCRC SIOCW ; RESET TX CRC GENERATOR ; DELAY MOV AL,FIRSTCHAR[BX] SIOW CLI DELAY MOV AL,SDTXUND SIOCW ; RESET TX UNDERRUN LATCH OR SDFLAGS[BX],SDTINP AND RR0[BX],NOT SDUNDER STI NOTTXDELAY: CMP L1TIMEOUT[BX],0 JE TIMERRET DEC L1TIMEOUT[BX] JNZ TIMERRET ; ; WE HAVE BEEN UNABLE TO TRANSMIT FOR 60 SECS - CLEAR TX Q ; PUSH SI PUSH DI CLEARLOOP: LEA SI,PCTX_Q[BX] CLI CALL Q_REM STI JZ DISCARDEND ADD L1DISCARD[BX],1 ; FOR STATS ADC L1DISCARD+2[BX],0 ; MOV SI,OFFSET TRACE_Q CLI CALL Q_ADD STI JMP CLEARLOOP DISCARDEND: ; ; IF IN TX STATE, RESET SCC - INDICATES STUCK IN SEND MODE ; CMP LINKSTS[BX],0 JE NOTSTUCK ; ; IF A FRAME IS BEING SENT, RELEASE IT ; MOV DI,TXFRAME[BX] MOV TXFRAME[BX],0 CMP DI,0 JE NO_STUCK_FRAME MOV SI,OFFSET TRACE_Q ; TRACE IT CALL Q_ADD NO_STUCK_FRAME: CLI CALL DROPRTS ; CLEAR DOWN SCC STI NOTSTUCK: POP DI POP SI TIMERRET: ; ; DO CWID BITS ; IFNDEF PCSWITCH DEC PORTSLOTIMER[BX] JZ DOSLOWTIMER RET DOSLOWTIMER: MOV PORTSLOTIMER[BX],5 ; TO 20HZ ENDIF dec CWIDTIMER[BX] jnz CWIDTIMRET ; ; CHANGE TO NEXT STATE ; test CWSTATE[BX],dot + dash jnz senddotspace test CWSTATE[BX],letterspace jnz sendnextletter test CWSTATE[BX],dotspace jnz sendnextelement ; ; NEED A NEW ID ; cmp cwid[bx],0 je CWIDTIMRET ; NO ID DEFINED CMP PORTDISABLED[BX],0 JNE DISABLED ; MOV CWSTATE[BX],IDPENDING CWIDTIMRET: ret DISABLED: MOV CWIDTIMER[BX],18*60 ; TRY AGAIN IN A MINUTE RET senddotspace: mov CWIDTIMER[BX],1 mov CWSTATE[BX],dotspace jmp HIGHTONE sendnextelement: mov ax,ELEMENT[BX] mov cl,2 shr ELEMENT[BX],cl and al,3 jz sendletspace ; ; 1 = dot, 3 = dash ; CBW mov CWIDTIMER[BX],ax mov CWSTATE[BX],dot jmp LOWTONE sendletspace: mov CWSTATE[BX],letterspace mov CWIDTIMER[BX],2 jmp HIGHTONE sendnextletter: PUSH SI mov si,CWPOINTER[BX] lodsw mov CWPOINTER[BX],si POP SI mov ELEMENT[BX],ax or ax,ax jnz sendnextelement ; ; finished - set to repeat later ; lea ax,CWID[BX] mov CWPOINTER[BX],AX mov CWIDTIMER[BX],18*29*60 MOV CWSTATE[BX],0 CLI MOV AL,5 SIOCW DELAY MOV AL,11100001B ; DROP RTS SIOCW ; MOV LINKSTS[BX],0 STI ret senddotdash: cbw mov CWIDTIMER[BX],ax mov CWSTATE[BX],dot jmp LOWTONE HDLCRX: LEA SI,RXMSG_Q[BX] CLI CALL Q_REM STI JZ RXRET LEA SI,PORTRX_Q[BX] CALL Q_ADD ; PUT ON PORT RX QUEUE JMP SHORT HDLCRX ; SEE IF MORE RXRET: ; ; SEE IF WAITING FOR DCD TO DROP BEFORE SENDING ; CMP FULLDUPLEX[BX],1 JE DCDLOW ; DONT CHECK IF FULL DUPLEX SIOCR ; GET RR0 CMP SOFTDCDFLAG[BX],0 JE CHECKRR0 TEST AL,10H ; SYNC BIT JZ DCDHIGH_J JMP SHORT DCDLOW CHECKRR0: TEST AL,08H ; HARD DCD JNZ DCDHIGH DCDLOW: ; ; IF ANYTHING QUEUED, AND NOT TRANSMITTING, START TX ; TEST CWSTATE[BX],IDPENDING JNZ NEED_ID CMP PCTX_Q[BX],0 JE DCDHIGH ; NOTHING QUEUED NEED_ID: CMP HOLDTIMER[BX],0 JNE SENDNOW ; HOLD TIMER IS RUNNING, SO TX IS ; KEYED - WE CAN SEND IMMEDIATELY CMP LINKSTS[BX],0 JNE DCDHIGH ; RETURN ; ; ON A PC THIS CODE IS CALLED EVERY 2 TICKS - THIS IS NEAR ENOUGH TO SLOTTIME!! ; IFDEF NEEDSLOT CMP SLOTTIME[BX],0 JNE DCDHIGH ; WAIT TILL TIME TO TRY AGAIN ; ; SEE IF OUR TURN! ; MOV AL,RANDOM ADD AL,AL ADD AL,AL ADD AL,AL ELSE IN AL,41H MUL D14 ENDIF CMP PORTPERSISTANCE[BX],AL JNC OURTURNTOSEND IFDEF NEEDSLOT MOV AL,PORTSLOTTIME[BX] MOV SLOTTIME[BX],AL ENDIF IFDEF KANT LED 6,ON ENDIF DCDHIGH_J: JMP SHORT DCDHIGH SENDNOW: OURTURNTOSEND: IFDEF KANT LED 6,OFF ENDIF ; ; CHECK FOR PORT INTERLOCK ; CMP PORTINTERLOCK[BX],0 JE NO_INTERLOCK ; NOT SET MOV AL,PORTINTERLOCK[BX] MOV DI,PORTTABLE MOV CX,NUMBEROFPORTS LOCK00: CMP PORTINTERLOCK[DI],AL JNE LOCK40 ; NOT SAME SET CMP LINKSTS[DI],0 JNE DCDHIGH ; ANOTHER PORT IN SAME SET IS ACTIVE LOCK40: MOV DI,PORTPOINTER[DI] LOOP LOCK00 ; ; NO OTHER PORT IN SAME SET IS ACTIVE - OK TO SEND ; NO_INTERLOCK: ; MOV L1TIMEOUT[BX],0 ; STOP DCD TIMEOUT TEST CWSTATE[BX],IDPENDING JNZ STARTID CLI LEA SI,PCTX_Q[BX] CALL Q_REM JZ DCDHIGH ; NOTHING THERE?? STI JMP SENDFRAME DCDHIGH: STI RET STARTID: ; ; KICK OFF CW ID SEQUENCE ; MOV LINKSTS[BX],1 ; SET ACTIVE MOV HOLDTIMER[BX],0 ; IN CASE RUNNING CALL HIGHTONE MOV CWIDTIMER[BX],7 ; KEYUP TIME MOV CWSTATE[BX],LETTERSPACE ; START NEW LETTER ON TIMEOUT RET ; ; TONE CONTROL ROUTINES ; LOWTONE: ; USED AS MARK ON FSK SYSTEMS CLI MOV AL,5 SIOCW DELAY MOV AL,11110011B ; RAISE RTS, SEND BREAK, DROP TXENABLE SIOCW ; STI ret HIGHTONE: CLI MOV AL,5 SIOCW DELAY CMP CWTYPE[BX],'O' ; IF ONOFF KEYING, DROP RTS JE KEYUP MOV AL,11100011B ; TXEN OFF BREAK OFF RTS SIOCW ; STI RET KEYUP: MOV AL,11100001B ; DROP RTS SIOCW ; STI RET HDLCTX: ; ; START TRANSMISSION - DI = ADDR OF MESSAGE - UNLESS DCD HIGH ; ; CMP PCTX_Q[BX],0 ; JNE QUEUEFORTX ; ALREADY ONE WAITING ; ; CMP SOFTDCDFLAG[BX],0 ; JE CHECKRR0_1 ; ; CMP SOFTDCD[BX],0 ; JNE QUEUEFORTX ; ; JMP SHORT DCDLOW_1 ; ;CHECKRR0_1: ; ; TEST RR0[BX],08H ; JNZ QUEUEFORTX ; ;DCDLOW_1: ; ; CLI ; CMP LINKSTS[BX],0 ; JE OKTOSEND QUEUEFORTX: ; ; CANNOT SEND IT YET - QUEUE FRAME ; CLI LEA SI,PCTX_Q[BX] CALL Q_ADD STI CMP L1TIMEOUT[BX],0 JNE QTXRET ; TIMER ALREADY RUNNING IFDEF PCSWITCH MOV L1TIMEOUT[BX],18*55 ELSE MOV L1TIMEOUT[BX],100*55 ; GIVE IT NEARLY A MINUTE ENDIF QTXRET: RET OKTOSEND: STI SENDFRAME: ; MOV TXFRAME[BX],DI ; SAVE ADDRESS OF FRAME MOV AX,3[DI] SUB AX,6 MOV SDTXCNT[BX],AX ; GET MESSAGE LENGTH FROM BUFFER LEA DI,6[DI] MOV SDTNEXT[BX],DI ; SET NEXT BYTE POINTER ; OR LINKSTS[BX],1 ; SET LINK ACTIVE SETTVEC SDDTTX ; SET VECTOR TO 'TX DATA' IFNDEF KANT CMP TXBRG[BX],0 JE DONTCHANGE ; ; NEED TO RESET BRG FOR TRANSMIT ; MOV CX,TXBRG[BX] MOV DX,SIOC[BX] MOV AL,12 CLI OUT DX,AL DELAY MOV AL,CL OUT DX,AL ; SET LSB DELAY MOV AL,13 OUT DX,AL DELAY MOV AL,CH OUT DX,AL ; SET MSB ; STI NOP DONTCHANGE: ENDIF CMP HOLDTIMER[BX],0 JNE RTSUP CLI MOV AL,5 SIOCW DELAY MOV AL,11101011B ; RAISE RTS TO START SENDING FLAGS SIOCW ; MOV AL,PORTTXDELAY[BX] MOV TXDELAY[BX],AL MOV AL,-1[DI] ; FIRST BYTE MOV FIRSTCHAR[BX],AL ; SAVE MOV AL,10 DELAY SIOCW DELAY MOV AL,10000100B ; SET TO ABORT ON UNDERRUN OR AL,WR10[BX] SIOCW STI RET RTSUP: MOV HOLDTIMER[BX],0 MOV AL,-1[DI] ; FIRST BYTE MOV FIRSTCHAR[BX],AL ; SAVE MOV AL,10 DELAY CLI SIOCW DELAY MOV AL,10000100B ; SET TO ABORT ON UNDERRUN OR AL,WR10[BX] SIOCW MOV AL,SDTXCRC SIOCW ; RESET TX CRC GENERATOR ; DELAY MOV AL,FIRSTCHAR[BX] SIOW DELAY MOV AL,SDTXUND SIOCW ; RESET TX UNDERRUN LATCH OR SDFLAGS[BX],SDTINP AND RR0[BX],NOT SDUNDER STI RET ; ; *** F1 - RX ADDRESS ; *** ; READ CHAR FROM SIO AND DISCARD ; SET VECTOR TO 'RX CONTROL BYTE' - F2 ; RETURN ; ; SDADRX: IFDEF KANT SIOCR ; GET RR0 TEST AL,08H ; HARD DCD JZ NODCD ENDIF ; MOV SOFTDCD[BX],4 ; SET RX ACTIVE MOV SI,OFFSET FREE_Q CALL Q_REM JNZ GETB00 CALL NOBUFFERCHECK ; CHECK IF POOL IS CORRUPT JMP NOBUFFERS GETB00: DEC QCOUNT MOV [DI],OFFSET GETB00 ; FLAG FOR DUMP ANALYSER SIOR ; GET FIRST BYTE OF ADDRESS MOV CURALP[BX],DI ; SAVE ADDR ADD DI,5 MOV [DI],AL ; ADDR TO BUFFER INC DI MOV SDRNEXT[BX],DI ; AND NEXT BYTE POINTER ; MOV FRAMELEN[BX],5 OR SDFLAGS[BX],SDRINP ; SET RX IN PROGRESS SETRVEC SDIDRX ; SET VECTOR TO 'GET DATA' IFDEF KANT MOV DX,RXON[BX] OUT DX,AL ENDIF RET ; IFDEF KANT NODCD: SIOR ; CLEAR INT PENDING MOV AL,33H SIOCW ; ERROR RESET WR3 DELAY MOV AL,11011001B ; 8BIT, CRC EN, RX EN SIOCW ; RET ENDIF NOBUFFERS: ; ; NO BUFFER FOR RECEIVE - SET TO DISCARD ; INC OLOADS[BX] SETRVEC SDOVRX SIOR ; CLEAR INT PENDING RET SDIDRX: ; ; NOW READ CHARACTER FROM SIO AND STORE ; ; MOV SOFTDCD[BX],4 ; SET RX ACTIVE INC FRAMELEN[BX] ; SIOR SIO1 ; GET CHAR ; CMP FRAMELEN[BX],BUFFLEN-10 JNE SDID00 ; SIZE OK SETRVEC SDOVRX ; CANT TAKE ANY MORE SDID00: MOV DI,SDRNEXT[BX] ; GET NEXT BYTE POINTER STOSB MOV SDRNEXT[BX],DI ; STORE UPDATED BYTE POINTER RET ; SDOVRX: ; ; DISCARD REST OF MESSAGE ; ; MOV SOFTDCD[BX],4 ; SET RX ACTIVE SIOR SIO1 ; READ CHAR AND DISCARD RET ;*** RX SPECIAL CHARACTER INTERRUPT ; SPCLINT: SIOR ; READ CHAR AND DISCARD MOV AL,1 DELAY SIOCW ; SELECT RR1 DELAY SIOCR ; INPUT RR1 MOV AH,AL SIOCAD MOV AL,30H OUT DX,AL ; RESET SIO ERROR LATCHES TEST AH,10000000B ; END OF FRAME? JNZ SDEOF ; YES ; ; NOT END OF FRAME - SHOULD BE OVERRUN - DISCARD FRAME ; ADD L2ORUNC[BX],1 ; FOR STATS ADC L2ORUNC+2[BX],0 ; TEST SDFLAGS[BX],SDRINP JZ SDSP07 ; IF NOT SET, NO BUFFER IS ALLOCATED AND SDFLAGS[BX],NOT SDRINP MOV SI,OFFSET FREE_Q MOV DI,CURALP[BX] CALL Q_ADDF SDSP07: SETRVEC SDOVRX ; DISCARD REST OF MESSAGE JMP SPCLINTEXIT SDEOF: ; ; IF RESIDUE IS NONZERO, IGNORE FRAME ; MOV AL,AH AND AL,1110B ; GET RESIDUE BITS CMP AL,0110B JNE DONTCOUNT ; NOT MULTIPLE OF 8 BITS ; ; END OF FRAME - SEE IF FCS OK ; TEST AH,01000000B JZ SDSP10 ; J IF GOOD END-OF-FRAME ; ; FCS ERROR ; CMP FRAMELEN[BX],14H JB DONTCOUNT ; TOO SHORT ADD RXERRORS[BX],1 ADC RXERRORS+2[BX],0 ; FOR STATS DONTCOUNT: TEST SDFLAGS[BX],SDRINP JZ SDSP09 ; IF NOT SET, NO BUFFER IS ALLOCATED AND SDFLAGS[BX],NOT SDRINP DISCARDFRAME: MOV SI,OFFSET FREE_Q MOV DI,CURALP[BX] CALL Q_ADDF SDSP09: SETRVEC SDADRX IFDEF KANT MOV DX,RXOFF[BX] OUT DX,AL ENDIF JMP SPCLINTEXIT ; ; GOOD FRAME RECEIVED ; SDSP10: TEST SDFLAGS[BX],SDRINP JZ SDSP11 ; IF NOT SET, NO BUFFER IS ALLOCATED AND SDFLAGS[BX],NOT SDRINP MOV DI,SDRNEXT[BX] ; GET NEXT BYTE POINTER DEC DI MOV BYTE PTR [DI],0FEH ; OVERWRITE FIRSTS FCS BYTE WITH MARKER MOV AX,FRAMELEN[BX] ; GET LENGTH CMP AX,14H JB DISCARDFRAME ; TOO SHORT MOV DI,CURALP[BX] ; BUFFER ADDR MOV 3[DI],AX ; PUT IN LENGTH LEA SI,RXMSG_Q[BX] CALL Q_ADD ; QUEUE MSG FOR B/G SDSP11: SETRVEC SDADRX ; READY FOR NEXT FRAME IFDEF KANT MOV DX,RXOFF[BX] OUT DX,AL ENDIF SPCLINTEXIT: RET ; EXTERNAL/STATUS INTERRUPT ; ; - TRANSMIT UNDERRUN/EOM - IF AT END OF FRAME IGNORE ; ELSE SEND ABORT ; - ABORT START/END - IF RECEIVING, CANCEL MESSAGE ; ; EXTINT: MOV AH,RR0[BX] ; GET OLD RR0 SIOCR MOV RR0[BX],AL ; SAVE XOR AH,AL ; GET CHANGES AND AH,0C0H JZ SDST40 ; NO INTERESTING CHANGES SDST00: TEST SDFLAGS[BX],SDTINP JZ SDST10 ; J IF 'TX IN PROGRESS' NOT SET ; ; WE ARE TRANSMITTING - CHECK FOR UNDERRUN ; TEST AL,SDUNDER ; TX UNDERRUN? JZ SDST10 ; ONLY INTERESTING ONE TEST SDTXCNT[BX],8000H ; IS IDP CHAR COUNT -VE? JNZ SDST10 ; J IF YES (NORMAL END-OF-FRAME) ; ; UNDERRUN IN MID-FRAME ; ABORT THE TRANSMISSION ; MOV AL,SDABTX SIOCW ; SEND ABORT SEQUENCE SETTVEC SDCMTX ; SET VECTOR TO 'TX COMPLETE' OR SDFLAGS[BX],ABSENT ; SET ABORT SENT ADD L2URUNC[BX],1 ; UNDERRUNS ADC L2URUNC+2[BX],0 JMP SHORT SDST10 ; SEE IF ANY RX ERROR BITS ALSO SET ; ; IS RX IN PROGRESS? ; SDST10: TEST SDFLAGS[BX],SDRINP JZ SDST40 ; NO, SO PROBABLY ABORT FOLLOWING MSG TEST RR0[BX],SDABORT ; IS ABORT STATUS BIT SET? JZ SDST40 ; J IF NOT - ? ABORT TERMINATON MOV DI,CURALP[BX] ; BUFFER ADDR MOV SI,OFFSET FREE_Q CALL Q_ADDF ; RELEASE BUFFER AND SDFLAGS[BX],NOT SDRINP ; CLEAR RX IN PROGRESS SETRVEC SDADRX ; READY FOR NEXT FRAME IFDEF KANT MOV DX,RXOFF[BX] OUT DX,AL ENDIF SDST40: MOV AL,SDEXTR SIOCW ; RESET EXTERNAL/STATUS INTERRUPT RET ; ;*** TX DATA ; SDDTTX: DEC SDTXCNT[BX] ; DECREMENT CURRENT IDP COUNT ; JNS SDDT40 ; J IF IDP NOT YET EMPTY ; ; NO MORE DATA TO TRANSMIT ; MOV AL,10 SIOCW DELAY MOV AL,10000000B ; SET TO SEND CRC ON UNDERRUN OR AL,WR10[BX] SIOCW MOV AL,SDRPEND ; RESET TX UNDERRUN/EOM LATCH + DELAY SIOCW ; TX INTERRUPT PENDING SETTVEC SDCMTX ; SET TX VECTOR TO 'TX COMPLETION' RET ; ; TRANSMIT NEXT BYTE OF DATA ; SDDT40: MOV SI,SDTNEXT[BX] ; GET NEXT BYTE POINTER LODSB SIOW ; TRANSMIT NEXT BYTE MOV SDTNEXT[BX],SI ; STORE UPDATED BYTE POINTER RET ; ; *** F11 - TX COMPLETION ; SDCMTX: MOV AL,28H SIOCW ; RESET TX INT PENDING TEST SDFLAGS[BX],ABSENT JZ NOABORT ; ; FRAME WAS ABORTED - SEND AGAIN ; ; AND SDFLAGS[BX],NOT ABSENT ; MOV DI,TXFRAME[BX] ; JMP SHORT SENDAGAIN NOABORT: MOV DI,TXFRAME[BX] MOV TXFRAME[BX],0 MOV SI,OFFSET TRACE_Q ; TRACE IT CALL Q_ADD AND SDFLAGS[BX],NOT SDTINP ; ; SEE IF MORE TO SEND ; LEA SI,PCTX_Q[BX] CALL Q_REM JZ NOMORETOSEND ; J IF QUEUE EMPTY MOV TXFRAME[BX],DI ; SAVE ADDRESS OF FRAME SENDAGAIN: MOV AX,3[DI] SUB AX,6 MOV SDTXCNT[BX],AX ; GET MESSAGE LENGTH FROM BUFFER LEA DI,6[DI] MOV SDTNEXT[BX],DI ; SET NEXT BYTE POINTER ; OR SDFLAGS[BX],SDTINP SETTVEC SDDTTX ; SET VECTOR TO 'TX DATA' MOV AL,SDTXCRC SIOCW ; RESET TX CRC GENERATOR ; DELAY MOV AL,-1[DI] ; FIRST BYTE SIOW ; TRANSMIT IT DELAY MOV AL,SDTXUND SIOCW ; RESET TX UNDERRUN LATCH AND RR0[BX],NOT SDUNDER ; KEEP STORE COPY DELAY MOV AL,10 SIOCW DELAY MOV AL,10000100B ; SET TO ABORT ON UNDERRUN OR AL,WR10[BX] SIOCW RET NOMORETOSEND: ; ; IF RUNNING IN CARRIER HOLD MODE, (RE)START TIMER ; CMP HOLDINIT[BX],0 JE SENDPAD MOV AX,HOLDINIT[BX] MOV HOLDTIMER[BX],AX RET SENDPAD: ; ; SEND A FEW PADDING CHARS TO ENSURE FLAG IS CLEAR OF SCC ; SETTVEC SENDDUMMY1 XOR AL,AL ; FIRST DUMMY BYTE SIOW SIO1 ; TRANSMIT IT RET SENDDUMMY1: XOR AL,AL SIOW ; SECOND DUMMY SETTVEC SENDDUMMY2 RET SENDDUMMY2: XOR AL,AL SIOW ; SECOND DUMMY SETTVEC SENDDUMMY3 RET SENDDUMMY3: XOR AL,AL SIOW ; SECOND DUMMY SETTVEC DROPRTS RET DROPRTS: AND LINKSTS[BX],NOT 1 ; SET NOT TRANSMITTING MOV AL,5 SIOCW DELAY MOV AL,11100001B ; DROP RTS AND TXEN SIOCW SETTVEC IGNORE IFNDEF KANT CMP RXBRG[BX],0 JE DONTCHANGERX ; ; NEED TO RESET BRG FOR RECEIVE ; MOV CX,RXBRG[BX] MOV DX,SIOC[BX] MOV AL,12 OUT DX,AL DELAY MOV AL,CL OUT DX,AL ; SET LSB DELAY MOV AL,13 OUT DX,AL DELAY MOV AL,CH OUT DX,AL ; SET MSB ; DONTCHANGERX: ENDIF RET ; ;*** TX INTERRUPT IGNORE ; IGNORE: MOV AL,SDRPEND SIOCW ; RESET TX INTERRUPT PENDING RET ; SDTXUND EQU 0C0H ; RESET TX UNDERRUN/EOM LATCH SDABTX EQU 18H SDUNDER EQU 40H SDTXCRC EQU 80H ; RESET TX CRC GEN SDABORT EQU 80H ; ABORT DETECTED SDEXTR EQU 10H ; RESET EXT/STATUS INTS SDRPEND EQU 28H ; RESET TX INT PENDING EVEN ; IFDEF KANT PUBLIC SCCINT SCCINT: ; ; SERIAL COMMS INTERRUPT HANDLER ; PUSHA CLD MOV AL,63H ; SPECIFIC EOI TO LEV 1 OUT (IPFW),AL MOV BX,HDLCPORT1 INC RAN4 ENDIF SIOINT: ; ENTERED FROM HARDWARE INTERRUPT ; ; BX HAS PORT DATA FOR ONE OF THE TWO CHANNELS, AND CONTAINS POINTERS ; TO THE PORT DATA FOR EACH CHANNEL. ; SIOI10: MOV DX,ASIOC[BX] MOV AL,3 OUT DX,AL ; SELECT RR3 DELAY IN AL,DX ; GET PENDING INTS OR AL,AL JZ NOINTS ; NONE MOV DX,BSIOC[BX] MOV AL,2 OUT DX,AL ; SELECT RR2 DELAY IN AL,DX ; GET VECTOR CBW CMP AL,8 JAE ACHAN MOV BX,B_PTR[BX] ; GET DATA FOR B CHANNEL JMP SHORT INT_COMMON ACHAN: SUB AL,8 MOV BX,A_PTR[BX] INT_COMMON: LEA SI,VECTORS[BX] ADD SI,AX CALL [SI] MOV DX,ASIOC[BX] MOV AL,00111000B ; RESET IUS OUT DX,AL JMP SIOI10 ; SEE IF ANY MORE NOINTS: IFDEF KANT POPA IRET ELSE RET ; ENDIF HDLCEND LABEL BYTE ; CODE ENDS END