PAGE 56,132 ; ; ASYNC PORT INTERRUPT ROUTINES FOR KISS OR NETROM LINKS ; ; SUPPORTS 'STANDARD' ASYNC CARDS, OR ONE QUADPORT CARD ; ; SUPPORTS 2 PORT KISS TNCs ; INCLUDE ENVIRON.ASM IFDEF KANT .186 TICKS EQU 100 ; TIMER TICKS PER SECOND INCLUDE KANTEQU.ASM ENDIF IFDEF MSC .186 TICKS EQU 100 ; TIMER TICKS PER SECOND INCLUDE MSCEQU.ASM EXTRN ASYNCMODE:BYTE ENDIF IFDEF KANT INCLUDE KANTEQU.ASM EXTRN ASYNCMODE:BYTE ENDIF IFDEF PCSWITCH IFDEF OS2 TICKS EQU 32 ELSE TICKS EQU 18 ENDIF ENDIF SETARVEC MACRO A ; MACRO TO CHANGE THE RX INT VECTOR MOV IORXCA[BX],OFFSET A ENDM SETATVEC MACRO A ; MACRO TO CHANGE THE TX INT VECTOR MOV IOTXCA[BX],OFFSET A ENDM ; DELAY MACRO JMP $+2 JMP $+2 JMP $+2 JMP $+2 ENDM FEND EQU 0C0H ; KISS CONTROL CODES FESC EQU 0DBH TFEND EQU 0DCH TFESC EQU 0DDH STX EQU 2 ; NETROM CONTROL CODES ETX EQU 3 DLE EQU 10H CTSBIT EQU 10H ; BIT IN MSR DATA SEGMENT PUBLIC 'DATA' INCLUDE STRUCS.ASM KISSDATA STRUC DB HARDWAREDATA DUP (0) ; REMAP HARDWARE INFO IFDEF PCSWITCH IOADDR DW 0 ; TX/RX DATA; BRG LO IER DW 0 ; INTERRUPT ENABLE IIR DW 0 ; INTERRUPT IDENT LCR DW 0 ; LINE CONTROL MCR DW 0 ; MODEM CONTROL LSR DW 0 ; LINE STATUS MSR DW 0 ; MODEM STATUS ENDIF IFDEF MSC IOADDR DW 0 ENDIF LINKSTS DB 0 ; CURRENT STATE CURALP DW 0 ; CURRENT BUFFER NEXTCHR DW 0 ASYNCMSG_Q DW 0 ; RECEIVED MESSAGES KISSTX_Q DW 0 ; MESSAGES TO SEND FRAMELEN DW 0 ; LENGTH OF CURRENT MSG TXCHAR DW 0 ; POINTER TO NEXT BYTE TO SEND TXTADDR DW 0 ; BASE ADDR OF FRAME BEING SENT TXCOUNT DW 0 ; SEND FRAME LENGTH IORXCA DW 0 IORXEA DW 0 IOTXCA DW 0 ESCFLAG DB 0 ; SET IF LAST RX CHAR WAS DLE ESCTXCHAR DB 0 ; CHAR TO SEND FOLLOWING DLE IF NZ INTFLAG DB 0 ; SET WHEN INTERRUPT OUTSTANDING FIRSTPORT DW 0 ; FIRST PORT DEFINED FOR THIS IO ADDR SUBCHAIN DW 0 ; NEXT SUBCHANNEL FOR SAME PHYSICAL PORT QUADCHAIN DW 0 ; NEXT PORT ON THIS QUADRAM CARD OURCTRL DB 0 ; CONTROL BYTE FOR THIS PORT TXCTRL DB 0 ; CONTROL BYTE TO SEND REALKISSFLAGS DB 0 ; KISS FLAGS FOR ACTIVE SUBPORT TXCCC DB 0 ; NETROM/BPQKISS CHECKSUMS RXCCC DB 0 ;PARAMTIMER DW 0 ; TIMER FOR SENDING KISS PARAMS - MOVED TO MAIN TABLE TXACTIVE DW 0 ; TIMER TO DETECT 'HUNG' SENDS IFDEF PCSWITCH POLLFLAG DB 0 ; POLL OUTSTANDING FOR MULTIKISS ELSE POLLFLAG DW 0 ; POLL OUTSTANDING FOR MULTIKISS ENDIF POLLPOINTER DW 0 ; LAST GROUP POLLED FIFO DB 0 ; SET IF FIFO AVAILABLE (16550) POLLED DB 0 ; SET WHEN POLL RECEIVED KISSDATA ENDS IF TYPE KISSDATA GT TYPE PORTCONTROL .ERR2 TOO MUCH PORT DATA ENDIF IFDEF KANT EXTRN ASYNCPORT:WORD EXTRN RAN5:BYTE CLOCKFREQ DD BD9600*9600 ENDIF IFDEF PCSWITCH INTPORT EQU 2D3H ; FIRST CARD ONLY FOR NOW INTNUMBER DB 0 ; 1 FOR LEVEL 3, 2 FOR LEV 4 QUADFIRST DW 0 ENDIF CHECKSUM EQU 1 POLLINGKISS EQU 2 ; KISSFLAGS BITS ACKMODE EQU 4 ; CAN USE ACK REQURED FRAMES POLLEDKISS EQU 8 ; OTHER END IS POLLING US QUADFLAG DB 0 FIRSTQUAD DW 0 ; PORT TABLE ENTRY OF FIRST QUADRAM PORT EXTRN QCOUNT:BYTE,FREE_Q:WORD,BUFFLEN:ABS IFDEF PCSWITCH EXTRN NEEDKISS:BYTE ENDIF EXTRN PORTTABLE:WORD,NUMBEROFPORTS:WORD ; EXTRN INTERRUPTS:WORD,CHARS:WORD IFDEF PCSWITCH EXTRN TRACE_Q:WORD ENDIF DATA ENDS IFNDEF PCSWITCH CODE SEGMENT PUBLIC 'CODE' ASSUME CS:CODE,DS:DATA,ES:DATA ELSE 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 QUADINIT ; EXTRN HOOKINT:NEAR QUADINIT: MOV QUADFLAG,1 ; THIS IS A QUADRAM QUADPORT CARD ENDIF PUBLIC KISSINIT KISSINIT: ; INTERRUPT INITIALISATION CODE IFNDEF PCSWITCH ; ; CLEAR HWDATA IN CASE WARM START ; MOV CX,TYPE KISSDATA - HARDWAREDATA LEA DI,LINKSTS[BX] XOR AL,AL REP STOSB ENDIF MOV PORTINTERLOCK[BX],0 ; CANT USE INTERLOCK ON KISS IFDEF PCSWITCH MOV NEEDKISS,1 ; NEED TO KEEP KISS CODE ENDIF CALL CHECKIOADDR ; SEE IF ANOTHER ENTRY FOR THIS ADDR MOV FIRSTPORT[BX],BX ; MAY BE CHANGED IN ANOTHER CHANNEL USED ; MOV AL,CHANNELNUM[BX] SUB AL,'A' MOV CL,4 SAL AL,CL ; TO UPPER NIBBLE MOV OURCTRL[BX],AL ; KISS CONTROL CMP DI,0 ; FIRST ENTRY FOR THIS ADDRESS JE INITCOM ; NO OTHER CHANNEL TO LINK ; ; THIS IS NOT THE FIRST PORT ON THIS I/O ADDR - WE MUST BE USING ; AN ADDRESSABLE PROTOCOL - IE KISS AS DEFINED FOR KPC4 ETC ; MOV FIRSTPORT[BX],DI ; QUEUE TX FRAMES ON FIRST ; ; SET UP SUBCHANNEL CHAIN - ALL PORTS FOR THIS IO ADDR ARE CHAINED ; SUBLOOP: CMP SUBCHAIN[DI],0 JE ENDOFCHAIN MOV DI,SUBCHAIN[DI] ; FOLLOW CHAIN JMP SUBLOOP ENDOFCHAIN: MOV SUBCHAIN[DI],BX ; PUT OURS ON END CALL INITCOMMON RET ; INT ALREADY HOOKED INITCOM: ; ; FIRST PORT USING THIS IO ADDRESS ; MOV POLLPOINTER[BX],BX ; SET FIRST PORT TO POLL CALL INITCOMMON ; SET UP THE PORT IFDEF PCSWITCH CMP QUADFLAG,1 JE INITQUAD MOV PORTINTERRUPT[BX],OFFSET SIOINT CALL HOOKINT ; ATTACH INTERRUPT ENDIF RET IFDEF PCSWITCH INITQUAD: ; ; SET UP INTERRUPT SYSTEM ; CMP INTNUMBER,0 JNE QUADOK ; ALREADY HAVE FIRST MOV INTNUMBER,1 ; FOR LEVEL 3 CMP INTLEVEL[BX],3 JE INTOK MOV INTNUMBER,2 ; ONLY SUPPORT 3 OR 4 INTOK: MOV PORTINTERRUPT[BX],OFFSET QUADINT MOV QUADFIRST,BX ; SAVE PORT NO QUADOK: MOV QUADFLAG,0 ; ; BUILD CHAIN OF PORTS ; MOV DI,FIRSTQUAD CMP DI,0 JNE NOTFIRST MOV FIRSTQUAD,BX RET PUBLIC CHECKQUAD CHECKQUAD: ; ; CALLED WHEN ALL PORTS SET UP TO INITIALISE QUADPORT INT SYSTEM ; CMP QUADFIRST,0 JE NOTQUAD ; NO QUADPORT CARD IN SYSTEM MOV BX,QUADFIRST CALL HOOKINT MOV DX,INTPORT MOV AL,INTNUMBER OUT DX,AL ; SET BOARD INT CONTROL NOTQUAD: RET NOTFIRST: ; ; ADD TO END OF CHAIN ; CMP QUADCHAIN[DI],0 JE ENDOFQCHAIN MOV DI,QUADCHAIN[DI] JMP NOTFIRST ; ENDOFQCHAIN: MOV QUADCHAIN[DI],BX RET ENDIF CHECKIOADDR: ; ; SEE IF ANOTHER PORT IS ALREADY DEFINED ON THIS CARD ; MOV DI,PORTTABLE MOV CX,NUMBEROFPORTS INIT100: CMP DI,BX JE INIT110 ; NONE BEFORE OURS MOV AX,IOBASE[BX] CMP AX,IOBASE[DI] JE INIT120 ; ANOTHER FOR SAME ADDRESS MOV DI,PORTPOINTER[DI] LOOP INIT100 INIT110: MOV DI,0 ; FLAG NOT FOUND INIT120: RET INITCOMMON: IFDEF KANT MOV AL,01110110B ; TIMER 1, LOW/HI, MODE3, BINARY OUT (TMD),AL MOV DX,WORD PTR CLOCKFREQ+2 MOV AX,WORD PTR CLOCKFREQ DIV BAUDRATE[BX] OUT (TCT1),AL MOV AL,AH OUT (TCT1),AL ; ; GET SERIAL I/O UNIT GOING ; MOV AL,11001110B ; 2 STOP NO PARITY 8 BIT 16X OUT (SMD),AL MOV AL,25H ; SRDY + RXEN +TXEN OUT (SCM),AL ; MOV AL,0 OUT (SIMK),AL ; UNMASK TX AND RX INTS ; ENDIF IFDEF PCSWITCH PUSH BX ; ; SET UP ADDRESS LIST ; MOV CX,7 MOV AX,IOBASE[BX] INIT00: MOV IOADDR[BX],AX INC AX ADD BX,2 LOOP INIT00 POP BX MOV DX,IER[BX] ; INTERRUPT CONTROL REG MOV AL,5 OUT DX,AL ; ALLOW RX AND RX ERROR ONLY INC DX DELAY IN AL,DX ; CLEAR ANY INTERRUPT ; ; SET SPEED ; INC DX MOV AL,80H ; DLAB DELAY OUT DX,AL MOV DX,1 MOV AX,49664 ; 115200 DIV BAUDRATE[BX] MOV DX,IOADDR[BX] OUT DX,AL ; SET LSB DELAY INC DX MOV AL,AH OUT DX,AL ; SET MSB MOV DX,LCR[BX] MOV AL,03H ; 8 BIT NO PARITY OUT DX,AL INC DX ; TO MCR MOV AL,0BH ; DTR RTS OUT2 CMP PROTOCOL[BX],2 ; NETROM? JNE NEEDRTS ; ; NETROM - CLEAR KISS OPTIONS, JUST IN CASE! ; MOV KISSFLAGS[BX],0 ; CMP FULLDUPLEX[BX],1 ; NETROM DROPS RTS TO INHIBIT! ; JE NEEDRTS ; ; MOV AL,9 ; OUT2 DTR ; NEEDRTS: DELAY OUT DX,AL ; ; CHECK FOR 16550 - IF PRESENT ENABLE FIFOS ; MOV DX,IIR[BX] MOV AL,10000001B ; 8 BYTE TRIGGER OUT DX,AL DELAY IN AL,DX AND AL,11000000B CMP AL,11000000B JE FIFOOK XOR AL,AL OUT DX,AL ; DISABLE FIFO AGAIN JMP FIFO_DONE FIFOMSG DB '16550 Detected and FIFO enabled $' FIFOOK: MOV FIFO[BX],1 ; INDICATE FIFO ACTIVE MOV DX,OFFSET FIFOMSG ; TELL USER IFDEF OS2 EXTRN OS2MSG:NEAR MOV AX,CS CALL OS2MSG ELSE PUSH DS MOV AH,9 PUSH CS POP DS INT 21H POP DS ENDIF FIFO_DONE: MOV DX,LSR[BX] ; CLEAR LINE STATUS INTS IN AL,DX DELAY MOV DX,IOADDR[BX] IN AL,DX ; CLEAR ANY PENDING RX INTERRUPT ; MOV IORXEA[BX],OFFSET RXAPTY ENDIF SETARVEC RXASTX ; INITIAL INTERRUPT ENTRY SETATVEC IGNORE ; IF KISS, SET TIMER TO SEND KISS PARAMS ; CMP PROTOCOL[BX],2 ; NETROM? JE NOPARAMS MOV PARAMTIMER[BX],TICKS*30 ; 30 SECS FOR TESTING NOPARAMS: RET ; IFDEF PCSWITCH IFDEF OS2 ELSE INITSEG ENDS CODE SEGMENT PUBLIC 'CODE' ENDIF ELSE ; NOT PC - IE DATA ENGINE, ETC ENDIF ASSUME CS:CODE,DS:DATA,ES:DATA PUBLIC KISSTX,KISSRX,KISSTIMER ; EXTRN Q_ADD:NEAR,Q_REM:NEAR,Q_ADDF:NEAR,RELBUFF:NEAR,GETBUFF:NEAR EXTRN HEXOUT:NEAR,NOBUFFERCHECK:NEAR KISSRX: CMP POLLED[BX],1 ; ZERO = NOT POLLED, 1 = POLL RECOGNISED JBE NOPOLL ; ; POLL OR POLL RESPONSE HAS BEEN RECEIVED ; TEST KISSFLAGS[BX],POLLINGKISS JZ POLLRXED ; ; POLL RESPONSE RECEIVED - CLEAR POLL OUTSTANDING ; MOV POLLED[BX],0 MOV POLLFLAG[BX],0 ; CLEAR POLL OUTSTANDING JMP SHORT NOPOLL ; SEE IF ANYTHING ELSE POLLRXED: ; ; WE ARE A SLAVE, AND THIS IS A POLL. SEE IF FOR US, AND IF SO, REPLY ; MOV AL,POLLED[BX] MOV POLLED[BX],0 AND AL,0F0H ; PORT CMP AL,OURCTRL[BX] JE OURPOLL JMP SHORT NOPOLL ; NOT FOR US OURPOLL: ; ; SEE IF ANYTHING QUEUED ; CMP KISSTX_Q[BX],0 JE SENDACK ; MOV POLLED[BX],1 ; LET TIMER DO THE SEND JMP NOPOLL SENDACK: MOV SI,BX CALL SENDPOLL ; OTHER END DOESNT CARE ABOUT ADDR NOPOLL: CHKRX: LEA SI,ASYNCMSG_Q[BX] CLI CALL Q_REM STI JNZ GOTAFRAME RET ; NOTHING RECEIVED GOTAFRAME: ; ; IF NETROM, CAN PASS ON NOW ; CMP PROTOCOL[BX],2 JE FOUNDIT ; NETROM PROTOCOL ; ; MESSAGE MAY BE DATA OR DATA ACK. IT HAS NOT YET BEEN CHECKSUMMED ; MOV AL,MSGPORT[DI] TEST AL,0FH JZ CHECK_CHECKSUM ; NORMAL DATA ; ; SPECIAL FRAME - IS IT AN ACK? ; AND AL,0FH CMP AL,0CH ; ACK JE ACKFRAME JMP NOTFOUND ; DONT RECOGNISE TYPE ACKFRAME: ; ; ACK FRAME. WE DONT SUPPORT ACK REQUIRED FRAMES AS A SLAVE - THEY ARE ; ONLY ACCEPTED BY TNCS ; TEST KISSFLAGS[BX],POLLEDKISS JNZ ACKREQFRAME ; FRAME REQUIRING AN ACK ; ; THIS IS AN ACK OF A DATA FRAME ; MOV BL,5[DI] MOV BH,6[DI] CMP L2TIMER[BX],0 JE NOTIMER ; ALREADY EXPIRED MOV AL,L2TIME[BX] XOR AH,AH MOV L2TIMER[BX],AX NOTIMER: JMP SHORT NOTFOUND ; RETURN IT ACKREQFRAME: ; ; NOT ALLOWED - DISCARD ; JMP DISCARDFRAME CHECK_CHECKSUM: TEST KISSFLAGS[BX],CHECKSUM JZ KISSRX00 ; ; SUM MESSAGE, AND IF DUFF DISCARD. IF OK DECREMENT COUNT TO REMOVE SUM ; MOV CX,3[DI] ; LENGTH, INCLUDING SUM CMP CX,14H JB DISCARDFRAME ; TOO SHORT FOR VALID AX25 DEC WORD PTR 3[DI] ; MOV AH,MSGPORT[DI] ; IS INCLUDED IN SUM LEA SI,5[DI] ; TO DATA SUB CX,5 SUMLOOP: LODSB XOR AH,AL LOOP SUMLOOP OR AH,AH JZ KISSRX00 ; SUM OK ADD RXERRORS[BX],1 ADC RXERRORS+2[BX],0 JMP SHORT DISCARDFRAME FOUNDIT: LEA SI,PORTRX_Q[BX] CALL Q_ADD ; PUT ON PORT RX QUEUE JMP SHORT CHKRX ; SEE IF MORE KISSRX00: ; ; AT THIS STAGE, KISS CONTROL BYTE IS IN PORT FIELD - FIND CORRECT ; SUBPORT RECORD TO ADD IT TO ; MOV AL,MSGPORT[DI] ; ; SHOULD ONLY HAVE NORMAL DATA NOW ; FINDLOOP: CMP OURCTRL[BX],AL JE FOUNDIT MOV BX,SUBCHAIN[BX] OR BX,BX JZ NOTFOUND JMP FINDLOOP NOTFOUND: DISCARDFRAME: ; ; INVALID CONTROL BYTE - DISCARD IT (MAYBE SHOULD COUNT ??) ; CALL RELBUFF RET KISSTX: ; ; START TRANSMISSION - DI = ADDR OF MESSAGE ; PUSH BX MOV BX,FIRSTPORT[BX] ; ALL FRAMES GO ON SAME Q CLI TEST KISSFLAGS[BX],POLLEDKISS JNZ QUEUEIT ; MUST QUEUE - CANT SEND TILL POLLED CMP KISSTX_Q[BX],0 JNE QUEUEIT ; ALREADY SOMETHING QUEUED CMP POLLFLAG[BX],0 JNE QUEUEIT ; POLL OUTSTANDING, SO QUEUE FRAME CMP TXTADDR[BX],0 JE OKTOSEND ; ; ALREADY SENDING - QUEUE FRAME ; QUEUEIT: LEA SI,KISSTX_Q[BX] CALL Q_ADD STI POP BX RET OKTOSEND: ; ; IF NETROM PROTOCOL AND NOT FULL DUPLEX AND BUSY, QUEUE IT ; IFDEF PCSWITCH CMP PROTOCOL[BX],2 ; NETROM? JNE DONTCHECKDCD ; NO CMP FULLDUPLEX[BX],1 JE DONTCHECKDCD ; FULLDUP - NO CHECK ; ; NETROM USES RTS, CROSS-CONNECTED TO CTS AT OTHER END, TO MEAN ; NOT BUSY ; MOV DX,MSR[BX] IN AL,DX TEST AL,CTSBIT ; CTS HIGH? JZ QUEUEIT ; NO, SO QUEUE FRAME ; ; GOING TO SEND - DROP RTS TO INTERLOCK OTHERS ; MOV DX,MCR[BX] MOV AL,09H ; DTR OUT2 OUT DX,AL ; ; MAKE SURE CTS IS STILL ACTIVE - IF NOT, WE HAVE A COLLISION, ; SO RELEASE RTS AND WAIT ; DELAY MOV DX,MSR[BX] IN AL,DX TEST AL,CTSBIT JNZ DONTCHECKDCD ; STILL HIGH, SO CAN SEND ; ; RAISE RTS AGAIN, AND QUEUE FRAME ; DELAY MOV DX,MCR[BX] MOV AL,0BH ; RTS DTR OUT2 OUT DX,AL ; JMP QUEUEIT DONTCHECKDCD: ENDIF MOV TXTADDR[BX],1 ; ENSURE POLL ISNT SENT STI CALL SENDFRAME POP BX RET SENDFRAME: ; ; GET REAL PORT TABLE ENTRY - IF MULTIPORT, FRAME IS QUEUED ON ; FIRST ; CMP PROTOCOL[BX],2 ; NETROM JE NRTX00 PUSH BX MOV AL,2[DI] ; PORT NUMBER TXPORTLOOP: CMP PORTNUMBER[BX],AL JE OURPORT MOV BX,SUBCHAIN[BX] CMP BX,0 JNE TXPORTLOOP POP BX MOV TXTADDR[BX],0 ; ALLOW OTHER ACTIONS CALL RELBUFF RET OURPORT: MOV AL,OURCTRL[BX] ; CORRECT CONTROL BYTE MOV AH,KISSFLAGS[BX] ; CORRECT KISSFLAGS POP BX MOV TXCTRL[BX],AL ; FOR TX ROUTINE MOV REALKISSFLAGS[BX],AH SETATVEC TXKISS ; SEND FRAME DELIMITER FIRST ; MOV ESCTXCHAR[BX],0 JMP SHORT TXCOMMON NRTX00: SETATVEC TXTEXT ; SEND FRAME DELIMITER FIRST MOV ESCTXCHAR[BX],STX ; SEND STX FIRST MOV TXCCC[BX],0 ; TXCOMMON: MOV TXTADDR[BX],DI ; SAVE ADDR OF LAST MESSAGE ; MOV CX,3[DI] ; MSG LENGTH SUB CX,5 ; HEADER LENGTH ADD DI,5 MOV AX,WORD PTR [DI] ; KISS CONTROL FRAME? AND AH,0FH ; MASK OUT PORT BITS CMP AX,1C0H ; KISS CONTROL FRAME? JNE TXNORM ; DATA FRAME ; ; KISS CONTROL FRAME ; SETATVEC TXKISSCTRL TXNORM: MOV TXCHAR[BX],DI ; SAVE MOV TXCOUNT[BX],CX ; ; MOST HARDWARE SEEMS TO INTERRUPT WHEN TX INT IS ENABLED, CAUSING ; THE FIRST CHAR TO BE SENT. HOWEVER SOME SEEM NOT TO, SO THE CODE ; CHECKS THAT THE INTERRUPT OCCURS IN A REASONABLE TIME, AND IF IT ; DOESNT, IT SENDS THE FIRST CHAR DIRECTLY. ; MOV INTFLAG[BX],1 ; INT EXPECTED ; IFDEF KANT MOV AL,0 OUT SIMK,AL ENDIF IFDEF PCSWITCH MOV DX,IER[BX] MOV AL,7 ; ENABLE TX INT OUT DX,AL ENDIF MOV CX,15 WAITLOOP: CMP INTFLAG[BX],0 JE SENDRET ; INT HAS OCCURED LOOP WAITLOOP ; ; INT FAILED ; CALL IOTXCA[BX] ; DO FIRST SEND SENDRET: MOV TXACTIVE[BX],TICKS*30 ; ALLOW 30 SECS TO SEND RET ; KISSTIMER: ; ; IF FRAMES QUEUED, AND NOT SENDING, START ; CMP BX,FIRSTPORT[BX] ; ALL FRAMES GO ON SAME Q JNE NOTMAINPORT_J1 ; ; SEE IF POLL HAS TIMED OUT ; TEST KISSFLAGS[BX],POLLINGKISS JZ NOTPOLLED CLI CMP POLLFLAG[BX],0 JE NOTPOLLED DEC POLLFLAG[BX] STI JNZ NOTMAINPORT_J1 ; TIMING OUT OR RECEIVING ; ; POLL HAS TIMED OUT - MAY NEED TO DO SOMETHING ; IFNDEF PCSWITCH CMP ASYNCMODE,'K' ; TERMINAL OR KISS MODE? JNE NOTPOLLED ; TERMINAL MODE ENDIF PUSH BX MOV BX,POLLPOINTER[BX] ADD L2URUNC[BX],1 ; PUT IN UNDERRUNS FIELD ADC L2URUNC+2[BX],0 POP BX NOTPOLLED: CLI CMP TXTADDR[BX],0 JE NOTSENDING ; JMP NOTCTSWAIT ; IFNDEF KANT ; ; CMP TXTADDR[BX],0FFFFH ; JNE NOTCTSWAIT ; ; WAITING FOR CTS ; ; MOV DX,MSR[BX] ; IN AL,DX ; TEST AL,CTSBIT ; JNZ TIMERSEND ; OK TO SEND NOW ; ; ENDIF BUSY_J: JMP BUSY ; WAIT FOR CTS NOTMAINPORT_J1: JMP NOTMAINPORT NOTCTSWAIT: ; ; SEE IF BEEN SENDING TOO LONG ; DEC TXACTIVE[BX] JNZ BUSY_J ; ; SEEM TO HAVE LOST A TX INTERRUPT - TRY CALLING TX ROUTINE ; ADD L1DISCARD[BX],1 ; FOR STATS ADC L1DISCARD+2[BX],0 MOV TXACTIVE[BX],2 CALL IOTXCA[BX] JMP BUSY NOTSENDING: ; ; SEE IF ANYTHING TO SEND ; STI CMP POLLED[BX],1 JE BEENPOLLED ; OK EVEN IF SLAVE MODE TEST KISSFLAGS[BX],POLLEDKISS JNZ NOTMAINPORT_J ; CANT SEND TILL WE GET POLL BEENPOLLED: ; ; IF IN FIFO MODE, ENSURE FIFO IS EMPTY ; IFDEF PCSWITCH TEST FIFO[BX],1 JZ KTIM50 ; NOT USING FIFO MOV DX,LSR[BX] IN AL,DX TEST AL,40H JZ NOTMAINPORT ; DONT SEND ANYTHING YET KTIM50: ENDIF CMP KISSTX_Q[BX],0 JE NOTHINGTOSEND ; ; IF NETROM MODE AND NOT FULL DUP, CHECK DCD ; MOV POLLED[BX],0 IFDEF PCSWITCH CMP PROTOCOL[BX],2 ; NETROM? JNE DONTCHECKDCD_1 CMP FULLDUPLEX[BX],1 JE DONTCHECKDCD_1 MOV DX,MSR[BX] IN AL,DX TEST AL,CTSBIT ; DCD HIGH? JZ NOTHINGTOSEND ; NO, SO WAIT ; ; DROP RTS TO LOCK OUT OTHERS ; MOV DX,MCR[BX] MOV AL,09H ; DTR OUT2 OUT DX,AL ; ; ; MAKE SURE CTS IS STILL ACTIVE - IF NOT, WE HAVE A COLLISION, ; SO RELEASE RTS AND WAIT ; DELAY MOV DX,MSR[BX] IN AL,DX TEST AL,CTSBIT JNZ TIMERSEND ; STILL HIGH, SO CAN SEND ; ; RAISE RTS AGAIN, AND WAIT A BIT MORE ; ; DELAY ; MOV DX,MCR[BX] MOV AL,0BH ; RTS DTR OUT2 OUT DX,AL JMP SHORT NOTHINGTOSEND DONTCHECKDCD_1: TIMERSEND: ENDIF PUSH SI PUSH DI PUSH DX LEA SI,KISSTX_Q[BX] CALL Q_REM CALL SENDFRAME POP DX POP DI POP SI NOTMAINPORT_J: JMP SHORT NOTMAINPORT NOTHINGTOSEND: ; ; IF POLLED MODE, SEND A POLL TO NEXT PORT ; TEST KISSFLAGS[BX],POLLINGKISS JZ NOTMAINPORT ; ; FIND WHICH CHANNEL TO POLL NEXT ; PUSH SI MOV SI,POLLPOINTER[BX] MOV SI,SUBCHAIN[SI] CMP SI,0 JNE POLLTHISONE MOV SI,BX ; BACK TO FIRST POLLTHISONE: MOV POLLPOINTER[BX],SI ; FOR NEXT TIME CALL SENDPOLL POP SI BUSY: STI NOTMAINPORT: KISSSLOWTIMER: ; ; SEE IF TIME TO REFRESH KISS PARAMS ; TEST KISSFLAGS[BX],POLLEDKISS JNZ KTIMERRET ; WE ARE THE SLAVE CMP PROTOCOL[BX],2 ; NETROM? JNE KISSXX KTIMERRET: RET ; NOT ON NETROM KISSXX: DEC PARAMTIMER[BX] JNZ KTIMERRET ; ; QUEUE A 'SET PARAMS' FRAME ; PUSH SI PUSH DI CMP PORTDISABLED[BX],0 JNE NOBUFFERS ; PORT DISABLED CALL GETBUFF JZ NOBUFFERS ; PUSH DI ADD DI,5 MOV AL,FEND STOSB MOV AH,OURCTRL[BX] MOV AL,1 OR AL,AH ; PUT IN CHANNEL BITS STOSB MOV AL,PORTTXDELAY[BX] STOSB MOV AL,FEND STOSB STOSB MOV AL,2 OR AL,AH ; PUT IN CHANNEL BITS STOSB MOV AL,PORTPERSISTANCE[BX] STOSB MOV AL,FEND STOSB STOSB MOV AL,3 OR AL,AH ; PUT IN CHANNEL BITS STOSB MOV AL,PORTSLOTTIME[BX] STOSB MOV AL,FEND STOSB STOSB MOV AL,4 OR AL,AH ; PUT IN CHANNEL BITS STOSB MOV AL,PORTTAILTIME[BX] STOSB MOV AL,FEND STOSB STOSB MOV AL,5 OR AL,AH ; PUT IN CHANNEL BITS STOSB MOV AL,FULLDUPLEX[BX] STOSB MOV CX,DI POP DI SUB CX,DI MOV 3[DI],CX ; SET LENGTH PUSH BX MOV BX,FIRSTPORT[BX] ; ALL FRAMES GO ON SAME Q ; ; QUEUE FRAME ; LEA SI,KISSTX_Q[BX] CLI CALL Q_ADD STI POP BX NOBUFFERS: MOV PARAMTIMER[BX],TICKS*60*5 ; 5 MINS POP DI POP SI RET SENDPOLL: ; ; SEND POLL TO PORT IN SI ; MOV POLLFLAG[BX],TICKS/3 ; ALLOW 1/3 SEC MOV AL,OURCTRL[SI] ; CORRECT CONTROL BYTE OR AL,0EH ; POLL BITS MOV TXCTRL[BX],AL ; FOR TX ROUTINE SETATVEC TXKISSPOLL ; SEND FRAME DELIMITER FIRST ; ; MOST HARDWARE SEEMS TO INTERRUPT WHEN TX INT IS ENABLED, CAUSING ; THE FIRST CHAR TO BE SENT. HOWEVER SOME SEEM NOT TO, SO THE CODE ; CHECKS THAT THE INTERRUPT OCCURS IN A REASONABLE TIME, AND IF IT ; DOESNT, IT SENDS THE FIRST CHAR DIRECTLY. ; MOV INTFLAG[BX],1 ; INT EXPECTED ; IFDEF PCSWITCH MOV DX,IER[BX] MOV AL,7 ; ENABLE TX INT OUT DX,AL ELSE CMP ASYNCMODE,'K' ; TERMINAL OR KISS MODE? JNE PSENDRET ; TERMINAL MODE ENDIF IFDEF KANT MOV AL,0 OUT SIMK,AL ENDIF IFDEF MSC ; !!!!!!!! ENDIF MOV CX,15 PWAITLOOP: CMP INTFLAG[BX],0 JE PSENDRET ; INT HAS OCCURED LOOP PWAITLOOP ; ; INT FAILED ; CALL IOTXCA[BX] ; DO FIRST SEND PSENDRET: MOV TXACTIVE[BX],TICKS*30 ; ALLOW 30 SECS TO SEND RET ; TXKISSPOLL: MOV INTFLAG[BX],0 ; INTERRUPT HAS OCCURED SETATVEC SENDPOLLCTRL MOV AL,FEND JMP TXA100 ; SEND FEND RXASTX: AND LINKSTS[BX],0FFH-10H ; CLEAR PARITY ERROR ; IFDEF KANT LED 0,OFF IN AL,SRB ELSE MOV DX,IOADDR[BX] IN AL,DX ; READ A CHAR ; ; ADD CHARS,1 ; ADC CHARS+2,0 ENDIF CMP PROTOCOL[BX],2 JE RXNR00 ; NETROM PROTOCOL CMP AL,FEND ; FRAME DELIMITER? JNE RXA010 ; NO - IGNORE ; ; GET BUFFER ; MOV SI,OFFSET FREE_Q CALL Q_REM JNZ GETB00 CALL NOBUFFERCHECK ; CHECK IF POOL IS CORRUPT JMP RXA010 GETB00: DEC QCOUNT MOV CURALP[BX],DI ; SAVE IT MOV WORD PTR [DI],OFFSET RXA005 RXA005: ADD DI,5 ; SKIP CHAIN, PORT, LENGTH MOV NEXTCHR[BX],DI ; SAVE BUFFER ADDRESS ; MOV FRAMELEN[BX],5 ; INITIAL LENGTH SETARVEC RXACTL IFDEF KANT LED 0,ON ENDIF RET RXA010: RET RXNR00: CMP ESCFLAG[BX],1 JE RXA011 ; DONT ACCEPT DLE/STX CMP AL,STX JE RXA002 CMP AL,DLE JNE RXA010 ; IGNORE MOV ESCFLAG[BX],1 RET RXA002: ; ; GET BUFFER ; MOV SI,OFFSET FREE_Q CALL Q_REM JNZ GETBNR CALL NOBUFFERCHECK ; CHECK IF POOL IS CORRUPT JMP RXA011 ; IGNORE (? WAIT FOR ETX OR TIMEOUT) GETBNR: MOV WORD PTR [DI],OFFSET GETBNR DEC QCOUNT MOV CURALP[BX],DI ; SAVE IT ADD DI,5 ; SKIP CHAIN, PORT, LENGTH MOV NEXTCHR[BX],DI ; SAVE BUFFER ADDRESS ; MOV FRAMELEN[BX],5 ; INITIAL LENGTH MOV RXCCC[BX],0 SETARVEC RXAMSGNR IFDEF KANT LED 0,ON ENDIF RXA011: MOV ESCFLAG[BX],0 RET RXACTL: IFDEF KANT IN AL,SRB ELSE MOV DX,IOADDR[BX] IN AL,DX ; READ A CHAR ; ; ADD CHARS,1 ; ADC CHARS+2,0 ENDIF ; ; SHOULD BE PORT NUMBER - IF FEND WE HAVE GOT OUT OF STEP ; MOV DI,CURALP[BX] ; GET BUFFER ADDR CMP AL,FEND JE RXA005 ; TRY AGAIN ; MOV MSGPORT[DI],AL ; PUT CONTROL BYTE IN PORT FIELD XOR RXCCC[BX],AL ; MAINTAIN CCC AND AL,0FH CMP AL,0EH ; POLL OR POLL REPLY? JNZ NOTPOLLREPLY ; ; POLL OR REPLY TO POLL ; MOV AL,MSGPORT[DI] MOV POLLED[BX],AL ; FOR BG TO PROCESS IFDEF KANT LED 0,OFF ENDIF RET ; ACCEPT FEND OR CONTROL NEXT NOTPOLLREPLY: SETARVEC RXAMSG TEST KISSFLAGS[BX],POLLINGKISS JZ NOTPOLL00 ; ; POLLED MODE - EXTEND TIMEOUT FOR DATA FRAME ; MOV POLLFLAG[BX],5*TICKS ; 5 SECS - SHOULD BE PLENTY NOTPOLL00: RET RXAMSG: IFDEF KANT IN AL,SRB ELSE MOV DX,IOADDR[BX] IN AL,DX ; READ A CHAR ; ; ADD CHARS,1 ; ADC CHARS+2,0 ENDIF CMP AL,FEND JE MSGEND ; END OF FRAME CMP AL,FESC JNE NOTESC ; ; ESC - SET FLAG ; MOV ESCFLAG[BX],1 ; SET FESC RECEIVED RET NOTESC: CMP ESCFLAG[BX],1 JNE RXNORM CMP AL,TFESC ; ESC'ED FESC? JNE NOTTFESC MOV AL,FESC ; REAL FESC JMP SHORT RXNORM NOTTFESC: CMP AL,TFEND ; ESC'ED FEND? JNE RXNORM MOV AL,FEND RXNORM: MOV DI,NEXTCHR[BX] ; GET POINTER STOSB ; PUT IN BUFFER MOV NEXTCHR[BX],DI ; SAVE POINTER RXA500: MOV ESCFLAG[BX],0 INC FRAMELEN[BX] CMP FRAMELEN[BX],BUFFLEN-10 JB RXARET ; OK DEC NEXTCHR[BX] ; PREVENT OVERRUN OR LINKSTS[BX],10H ; SET ERROR RXARET: RET ; MSGEND: MOV DI,NEXTCHR[BX] ; GET POINTER STOSB ; PUT FEND ON END MOV DI,CURALP[BX] MOV POLLFLAG[BX],0 ; LINK NOW IDLE QMSG: TEST LINKSTS[BX],10H JNZ RXAERROR ; OVERRUN, ETC MOV CX,FRAMELEN[BX] MOV 3[DI],CX ; LENGTH LEA SI,ASYNCMSG_Q[BX] ; PUT ON RX QUEUE - SUBPORT DETAILS ARE ; SORTED OUT LATER CALL Q_ADD JMP RXAEXIT RXAERROR: MOV DI,CURALP[BX] MOV SI,OFFSET FREE_Q CALL Q_ADDF RXAEXIT: MOV IORXCA[BX],OFFSET RXASTX ; FOR NEXT MESSAGE IFDEF KANT LED 0,OFF ENDIF RET ; RXAMSGNR: IFDEF KANT IN AL,SRB ELSE MOV DX,IOADDR[BX] IN AL,DX ; READ A CHAR ; ; ADD CHARS,1 ; ADC CHARS+2,0 ENDIF CMP AL,DLE JNE NOTDLE ; ; DLE - SET FLAG UNLESS ALREADY SET ; CMP ESCFLAG[BX],1 JE NOTDLE ; MUST BE DLE/DLE - MEANS REAL 10H! MOV ESCFLAG[BX],1 ; SET DLE RECEIVED RET NOTDLE: MOV DI,NEXTCHR[BX] ; GET POINTER STOSB ; PUT IN BUFFER MOV NEXTCHR[BX],DI ; SAVE POINTER CMP AL,ETX ; END? JNE RXA500NR ; NO ; CMP ESCFLAG[BX],1 JE RXA500NR ; DLE/ETX SETARVEC RXACCC ; RET ; RXA500NR: ADD RXCCC[BX],AL ; UPDATE LRC JMP RXA500 ; CHECK FOR BUFFER OVERFLOW, ETC RXACCC: IFDEF KANT IN AL,SRB ELSE MOV DX,IOADDR[BX] IN AL,DX ; READ A CHAR ; ; ADD CHARS,1 ; ADC CHARS+2,0 ENDIF ; CMP AL,RXCCC[BX] ; ACCUMULATED VALUE JE OK_CRC ADD RXERRORS[BX],1 ADC RXERRORS+2[BX],0 ; JMP RXAERROR ; DUFF OK_CRC: MOV DI,CURALP[BX] JMP QMSG ; QUEUE FOR BG TO PROCESS ; IFDEF PCSWITCH RXAPTY: ; ; ERROR INTERRUPT (FRAMING/OVERRUN) ; MOV DX,LSR[BX] IN AL,DX ; READ LINE STATUS TO CLEAR INTERRUPT ; ADD L2ORUNC[BX],1 ; FOR STATS ADC L2ORUNC+2[BX],0 OR LINKSTS[BX],10H ; SET ERROR FLAG RET ; ENDIF TXKISS: MOV INTFLAG[BX],0 ; INTERRUPT HAS OCCURED SETATVEC TXNULL MOV AL,FEND JMP TXA100 ; SEND FEND TXNULL: ; ; SEND CONTROL BYTE ; SETATVEC TXTEXT MOV AL,TXCTRL[BX] ; ; SEE IF ACK MODE IN USE ; TEST REALKISSFLAGS[BX],ACKMODE JZ NOACKMODE ; ; SEE IF FRAME NEEDS AN ACK ; MOV SI,TXTADDR[BX] CMP WORD PTR BUFFLEN-2[SI],0 JE NOACKMODE SETATVEC TXHDDR1 OR AL,0CH ; RESPONSE MODE NOACKMODE: MOV TXCCC[BX],FEND ; INITIALISE CRC - HAVE ALREADY SEND FEND XOR TXCCC[BX],AL JMP TXA100 ; SEND KISS CONTROL TXHDDR1: ; ; SEND FIRST ACK BYTE ; MOV SI,TXTADDR[BX] MOV AL,BUFFLEN-2[SI] SETATVEC TXHDDR2 JMP TXA100 ; SEND IT TXHDDR2: ; ; SEND SECOND ACK BYTE ; MOV SI,TXTADDR[BX] MOV AL,BUFFLEN-1[SI] MOV WORD PTR BUFFLEN-2[SI],0; CLEAR INDICATOR SETATVEC TXTEXT JMP TXA100 ; SEND IT TXTEXT: MOV INTFLAG[BX],0 ; INTERRUPT HAS OCCURED MOV AL,ESCTXCHAR[BX] OR AL,AL JZ TXA000 ; NORMAL MOV ESCTXCHAR[BX],0 JMP SHORT TXA100 ; SEND CHAR FOLLOWING ESC TXA000: CMP TXCOUNT[BX],0 JZ TXETX DEC TXCOUNT[BX] MOV SI,TXCHAR[BX] LODSB ; NEXT CHAR MOV TXCHAR[BX],SI CMP PROTOCOL[BX],2 JE CHECKDLE ; NETROM MODE XOR TXCCC[BX],AL CMP AL,FEND JNE NOTTXFEND MOV ESCTXCHAR[BX],TFEND ; ESC'ED FEND MOV AL,FESC JMP SHORT TXA100 NOTTXFEND: CMP AL,FESC JNE TXA100 MOV ESCTXCHAR[BX],TFESC ; ESC'ED ESC JMP SHORT TXA100 CHECKDLE: ; ; CHECK FOR NETROM CHARS TO PREFIX ; ADD TXCCC[BX],AL CMP AL,DLE JE TXDLE00 CMP AL,STX JE TXDLE00 CMP AL,ETX JNE TXA100 TXDLE00: MOV ESCTXCHAR[BX],AL MOV AL,DLE JMP SHORT TXA100 TXETX: CMP PROTOCOL[BX],2 JE TXETXNR TEST KISSFLAGS[BX],CHECKSUM JNZ TXETXP SETATVEC NEXTFRAME MOV AL,FEND ; ETX TXA100: IFDEF KANT OUT STB,AL ELSE MOV DX,IOADDR[BX] OUT DX,AL ; SEND CHAR ; ; ADD CHARS,1 ; ADC CHARS+2,0 ENDIF RET TXETXNR: SETATVEC ASENDCC MOV AL,03H JMP SHORT TXA100 TXETXP: SETATVEC ASENDFEND ; ; SEND CHECKSUM - BEWARE! - IT MAY BE FEND OR FESC ; MOV AL,TXCCC[BX] XOR AL,FEND ; HAVNT INCLUDED FEND YET CMP AL,FEND JNE NOTCHKFEND MOV ESCTXCHAR[BX],TFEND ; ESC'ED FEND MOV AL,FESC JMP SHORT TXA100 NOTCHKFEND: CMP AL,FESC JNE TXA100 MOV ESCTXCHAR[BX],TFESC ; ESC'ED ESC JMP SHORT TXA100 ASENDCC: ; ; NETROM END OF FRAME ; MOV AL,TXCCC[BX] SETATVEC NEXTFRAMENR JMP SHORT TXA100 ASENDFEND: ; ; USED TO SEND FINAL CHAR OF CHECKSUMMED FRAME ; ; IF THE CHECKSUM WAS FEND OR FESC, WE HAVE TO SEND THE 'ESC'ED VALUE ; FIRST ; MOV AL,ESCTXCHAR[BX] OR AL,AL JZ SENDFEND00 ; NORMAL MOV ESCTXCHAR[BX],0 JMP SHORT TXA100 ; SEND CHAR FOLLOWING ESC SENDFEND00: MOV AL,FEND SETATVEC NEXTFRAME JMP SHORT TXA100 NEXTFRAMENR: ; ; IF NOT FULL DUP, RAISE RTS ; IFDEF PCSWITCH CMP FULLDUPLEX[BX],1 JE NEXTFRAME MOV DX,MCR[BX] MOV AL,0BH ; DTR OUT2 OUT DX,AL ENDIF NEXTFRAME: MOV DI,TXTADDR[BX] IFDEF PCSWITCH MOV SI,OFFSET TRACE_Q CALL Q_ADD ; FEED TO TRACE CODE ELSE MOV SI,OFFSET FREE_Q CALL Q_ADDF ENDIF JMP ENDFRAME ; TEST KISSFLAGS[BX],POLLINGKISS ; JZ ENDFRAME ; ; SEND A POLL ; SENDPOLLCTRL: MOV AL,TXCTRL[BX] ; CHANNEL BITS TEST KISSFLAGS[BX],POLLINGKISS JZ POLLRESP ; MUST BE SENDING POLL RESPONSE SETATVEC SENDPOLLFEND JMP TXA100 ; SEND IT SENDPOLLFEND: MOV AL,FEND POLLRESP: SETATVEC ENDFRAME JMP TXA100 ; SEND IT ENDFRAME: MOV TXTADDR[BX],0 ; CLEAR SENDING INDICATOR MOV TXACTIVE[BX],0 ; IFDEF KANT MOV AL,10B OUT SIMK,AL ; MASK TX INT ENDIF IFDEF PCSWITCH MOV DX,IER[BX] MOV AL,5 OUT DX,AL ; MASK TX, ENABLE RX & RX ERROR ENDIF SETATVEC IGNORE RET IGNORE: IFDEF KANT MOV AL,10B OUT SIMK,AL ; MASK TX INT ENDIF RET ; TXKISSCTRL: ; ; SEND KISS CONTROL FRAME ; MOV INTFLAG[BX],0 ; INTERRUPT HAS OCCURED CMP TXCOUNT[BX],0 JZ TXETXC DEC TXCOUNT[BX] MOV SI,TXCHAR[BX] LODSB ; NEXT CHAR MOV TXCHAR[BX],SI JMP SHORT TXA100C TXETXC: MOV DI,TXTADDR[BX] MOV SI,OFFSET FREE_Q CALL Q_ADDF SETATVEC ENDFRAME MOV AL,FEND ; ETX TXA100C: IFDEF KANT OUT STB,AL ELSE MOV DX,IOADDR[BX] OUT DX,AL ; SEND CHAR ; ; ADD CHARS,1 ; ADC CHARS+2,0 ENDIF RET IFDEF PCSWITCH QUADINT: ; ; SEE WHICH PORT THE INTERRUPT IS FOR ; ; BX POINTS TO FIRST, AND PORTS MUST BE IN ORDER ; MOV DX,INTPORT ; ONLY ALLOW ONE FOR NOW IN AL,DX AND AL,1FH JZ QUADEXIT ; NO INTS ?? FINDPORT: SHR AL,1 JB PORTFOUND MOV BX,QUADCHAIN[BX] ; NEXT ON LEVEL JMP FINDPORT PORTFOUND: CALL SIOINT ; DEAL WITH IT QUADEXIT: MOV DX,INTPORT XOR AL,AL OUT DX,AL ; RESET COMMON INT LOGIC DELAY MOV AL,INTNUMBER OUT DX,AL ; REPRIME ?? RET ENDIF if 0 QUADINT: ; ; DIGIBOARD DRIVER ; ; SEE WHICH PORT THE INTERRUPT IS FOR ; ; BX POINTS TO FIRST, AND PORTS MUST BE IN ORDER ; MOV DX,INTPORT ; ONLY ALLOW ONE CARD FOR NOW IN AL,DX CMP AL,0FFH JZ QUADEXIT ; NO INTS ?? AND AL,3 INC AL FINDPORT: DEC AL JZ PORTFOUND MOV BX,PORTPOINTER[BX] JMP FINDPORT PORTFOUND: CALL SIOINT ; DEAL WITH IT QUADEXIT: RET endif IFDEF KANT PUBLIC SCUINT SCUINT: ; ; SERIAL COMMS INTERRUPT HANDLER ; PUSHA CLD INC RAN5 MOV AL,61H ; SPECIFIC EOI TO LEV 1 OUT (IPFW),AL MOV BX,ASYNCPORT ; ASYNC PORT IN AL,SST ; ASYNC STATUS TEST AL,RXRDY JZ NORX AND AL,00111000B ; ERROR BITS? JZ NOERRORS OR LINKSTS[BX],10H ; SET ERROR RXED MOV AL,35H ; SRDY + ECL +RXEN +TXEN OUT (SCM),AL ; RESET ERROR BITS NOERRORS: CALL IORXCA[BX] POPA IRET NORX: CALL IOTXCA[BX] POPA IRET ENDIF SIOINT: ; ; ENTERED FROM HARDWARE INTERRUPT ; ; ADD INTERRUPTS,1 ; ADC INTERRUPTS+2,0 IFDEF PCSWITCH SIOI10: MOV DX,IIR[BX] ; INTERRUPT IDENT IN AL,DX AND AL,1111B CMP AL,6 JE INTRXEA CMP AL,4 JE INTRXCA CMP AL,2 JE INTTXCA CMP AL,0CH ; FIFO TIMEOUT FOR 16550 JE INTRXCA CMP AL,0 JNE NOINT ; NOTHING PENDING ; ; MODEM INT NOT USED - JUST READ TO CLEAR IT ; MOV DX,MSR[BX] IN AL,DX JMP SHORT SIOI10 INTRXEA: CALL IORXEA[BX] JMP SIOI10 INTRXCA: CALL IORXCA[BX] ; ; MUST CLEAR FIFO IF 16550 ; TEST FIFO[BX],1 JZ SIOI10 ; NOT USING FIFO ; ; SEE IF STILL MORE DATA IN FIFO ; MOV DX,LSR[BX] IN AL,DX TEST AL,1 JNZ INTRXCA ; MORE CHARS STILL AVAILABLE JMP SIOI10 INTTXCA: CALL IOTXCA[BX] ; ; LOOP TO FILL FIFO IF 16550 ; TEST FIFO[BX],1 JZ SIOI10 ; NO FIFO ; ; WE HAVE A TX FIFO - LOAD IT UP ; MOV CX,15 ; MAX WRITES - 1 FIFOTXLOOP: CMP IOTXCA[BX],OFFSET IGNORE JE SIOI10 ; ALL MESSAGE IS NOW IN FIFO PUSH CX CALL IOTXCA[BX] POP CX LOOP FIFOTXLOOP JMP SIOI10 ; SEE IF ANOTHER NOINT: RET ; ENDIF CODE ENDS END