PAGE 56,132 ; ; ASYNC PORT DRIVER FOR KISS OR NETROM LINKS ; ; USES WIN32 COMn DRIVER ; ; ; Feb 2007 Fix ACKMODE processing .386 ; ; SEGMENT definitions and order ; ;* 32 Bit code _TEXT SEGMENT DWORD USE32 PUBLIC 'CODE' _TEXT ENDS ;* Contains 32 Bit data _BPQDATA SEGMENT DWORD PUBLIC 'DATA' _BPQDATA ENDS ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:FLAT OFFSET32 EQU _BPQDATA SEGMENT TICKS EQU 10 ; TICKS PER SECOND SETARVEC MACRO A ; MACRO TO CHANGE THE RX INT VECTOR MOV IORXCA[EBX],OFFSET32 A ENDM SETATVEC MACRO A ; MACRO TO CHANGE THE TX INT VECTOR MOV IOTXCA[EBX],OFFSET32 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 INCLUDE STRUCS.INC KISSDATA STRUC DB HARDWAREDATA DUP (0) ; REMAP HARDWARE INFO LINKSTS DB 0 ; CURRENT STATE CURALP DD 0 ; CURRENT BUFFER NEXTCHR DD 0 ASYNCMSG_Q DD 0 ; RECEIVED MESSAGES KISSTX_Q DD 0 ; MESSAGES TO SEND FRAMELEN DW 0 ; LENGTH OF CURRENT MSG TXCHAR DD 0 ; POINTER TO NEXT BYTE TO SEND TXTADDR DD 0 ; BASE ADDR OF FRAME BEING SENT TXCOUNT DW 0 ; SEND FRAME LENGTH IORXCA DD 0 IORXEA DD 0 IOTXCA DD 0 ESCFLAG DB 0 ; SET IF LAST RX CHAR WAS DLE ESCTXCHAR DB 0 ; CHAR TO SEND FOLLOWING DLE IF NZ FIRSTPORT DD 0 ; FIRST PORT DEFINED FOR THIS IO ADDR SUBCHAIN DD 0 ; NEXT SUBCHANNEL FOR SAME PHYSICAL PORT 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 TXACTIVE DW 0 ; TIMER TO DETECT 'HUNG' SENDS POLLFLAG DB 0 ; POLL OUTSTANDING FOR MULTIKISS POLLPOINTER DD 0 ; LAST GROUP POLLED POLLED DB 0 ; SET WHEN POLL RECEIVED WIN32INFO DB 16 DUP (0); FOR WINDOWS DRIVER KISSDATA ENDS IF TYPE KISSDATA GT TYPE PORTCONTROL .ERR2 TOO MUCH PORT DATA ENDIF public ENCBUFF ENCBUFF DB 600 DUP (0); KISSPARAMS DB 24 DUP (0); CHECKSUM EQU 1 POLLINGKISS EQU 2 ; KISSFLAGS BITS ACKMODE EQU 4 ; CAN USE ACK REQURED FRAMES POLLEDKISS EQU 8 ; OTHER END IS POLLING US D700 EQU 16 ; D700 Mode (Escape "C" chars EXTRN PORTTABLE:DWORD,LINKS:DWORD,NUMBEROFPORTS:WORD ; EXTRN INTERRUPTS:WORD,CHARS:WORD EXTRN TRACE_Q:DWORD PUBLIC _CRCTAB _CRCTAB DW 0,1189H,2312H,329BH,4624H DW 57ADH,6536H,74BFH,8C48H,9DC1H DW 0AF5AH,0BED3H,0CA6CH,0DBE5H,0E97EH DW 0F8F7H,1081H,0108H,3393H,221AH DW 56A5H,472CH,75B7H,643EH,9CC9H DW 8D40H,0BFDBH,0AE52H,0DAEDH,0CB64H DW 0F9FFH,0E876H,2102H,308BH,210H DW 1399H,6726H,76AFH,4434H,55BDH DW 0AD4AH,0BCC3H,8E58H,9FD1H,0EB6EH DW 0FAE7H,0C87CH,0D9F5H,3183H,200AH DW 1291H,318H,77A7H,662EH,54B5H DW 453CH,0BDCBH,0AC42H,9ED9H,8F50H DW 0FBEFH,0EA66H,0D8FDH,0C974H,4204H DW 538DH,6116H,709FH,420H,15A9H DW 2732H,36BBH,0CE4CH,0DFC5H,0ED5EH DW 0FCD7H,8868H DW 99E1H,0AB7AH,0BAF3H,5285H,430CH DW 7197H,601EH,14A1H,528H,37B3H DW 263AH,0DECDH,0CF44H,0FDDFH,0EC56H DW 98E9H,8960H,0BBFBH,0AA72H,6306H DW 728FH,4014H,519DH,2522H,34ABH DW 630H,17B9H,0EF4EH,0FEC7H,0CC5CH DW 0DDD5H,0A96AH,0B8E3H,8A78H,9BF1H DW 7387H,620EH,5095H,411CH,35A3H DW 242AH,16B1H,738H,0FFCFH,0EE46H DW 0DCDDH,0CD54H,0B9EBH,0A862H,9AF9H DW 8B70H,8408H,9581H,0A71AH,0B693H DW 0C22CH,0D3A5H,0E13EH,0F0B7H,840H DW 19C9H,2B52H,3ADBH,4E64H,5FEDH DW 6D76H,7CFFH,9489H,8500H,0B79BH DW 0A612H,0D2ADH,0C324H,0F1BFH,0E036H DW 18C1H,948H,3BD3H,2A5AH,5EE5H DW 4F6CH,7DF7H,6C7EH,0A50AH,0B483H DW 8618H,9791H,0E32EH,0F2A7H,0C03CH DW 0D1B5H,2942H,38CBH,0A50H,1BD9H DW 6F66H,7EEFH,4C74H,5DFDH,0B58BH DW 0A402H,9699H,8710H,0F3AFH,0E226H DW 0D0BDH,0C134H,39C3H,284AH,1AD1H DW 0B58H,7FE7H,6E6EH,5CF5H,4D7CH DW 0C60CH,0D785H,0E51EH,0F497H,8028H DW 91A1H,0A33AH,0B2B3H,4A44H,5BCDH DW 6956H,78DFH,0C60H,1DE9H,2F72H DW 3EFBH,0D68DH,0C704H,0F59FH,0E416H DW 90A9H,8120H,0B3BBH,0A232H,5AC5H DW 4B4CH,79D7H,685EH,1CE1H,0D68H DW 3FF3H,2E7AH,0E70EH,0F687H,0C41CH DW 0D595H,0A12AH,0B0A3H,8238H,93B1H DW 6B46H,7ACFH,4854H,59DDH,2D62H DW 03CEBH,0E70H,1FF9H,0F78FH,0E606H DW 0D49DH,0C514H,0B1ABH,0A022H,92B9H DW 8330H,7BC7H,6A4EH,58D5H,495CH DW 3DE3H,2C6AH,1EF1H,0F78H _BPQDATA ENDS _TEXT SEGMENT ; EXTRN NEEDKISS:BYTE extrn _time:near EXTRN _ASYINIT:NEAR,_ASYDISP:NEAR,_ASYSEND:NEAR,_POLLKISS:NEAR PUBLIC KISSINIT KISSINIT: ; INTERRUPT INITIALISATION CODE MOV PORTINTERLOCK[EBX],0 ; CANT USE INTERLOCK ON KISS MOV NEEDKISS,1 ; NEED TO KEEP KISS CODE CALL CHECKIOADDR ; SEE IF ANOTHER ENTRY FOR THIS ADDR MOV FIRSTPORT[EBX],EBX ; MAY BE CHANGED IN ANOTHER CHANNEL USED ; MOV AL,CHANNELNUM[EBX] SUB AL,'A' MOV CL,4 SAL AL,CL ; TO UPPER NIBBLE MOV OURCTRL[EBX],AL ; KISS CONTROL CMP EDI,0 ; FIRST ENTRY FOR THIS ADDRESS JE SHORT 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[EBX],EDI ; QUEUE TX FRAMES ON FIRST ; ; SET UP SUBCHANNEL CHAIN - ALL PORTS FOR THIS IO ADDR ARE CHAINED ; SUBLOOP: CMP SUBCHAIN[EDI],0 JE SHORT ENDOFCHAIN MOV EDI,SUBCHAIN[EDI] ; FOLLOW CHAIN JMP SHORT SUBLOOP ENDOFCHAIN: MOV SUBCHAIN[EDI],EBX ; PUT OURS ON END CALL INITCOMMON ; Display to Console MOVZX EAX,CHANNELNUM[EBX] PUSH EAX MOVZX EAX,IOBASE[EBX] PUSH EAX ; Port No CALL _ASYDISP ADD ESP,8 RET RET ; INT ALREADY HOOKED INITCOM: ; ; FIRST PORT USING THIS IO ADDRESS ; MOV POLLPOINTER[EBX],EBX ; SET FIRST PORT TO POLL CALL INITCOMMON ; SET UP THE PORT ; ATTACH WIN32 ASYNC DRIVER ; MOVZX EAX,CHANNELNUM[EBX] PUSH EAX LEA EAX,IORXCA[EBX] PUSH EAX ; Char Handler PUSH EBX ; Vector MOVZX EAX,BAUDRATE[EBX] PUSH EAX ; SPEED MOVZX EAX,IOBASE[EBX] PUSH EAX ; Port No CALL _ASYINIT ADD ESP,20 RET CHECKIOADDR: ; ; SEE IF ANOTHER PORT IS ALREADY DEFINED ON THIS CARD ; MOV EDI,PORTTABLE MOV CX,NUMBEROFPORTS INIT100: CMP EDI,EBX JE SHORT INIT110 ; NONE BEFORE OURS CMP PORTTYPE[EDI],10H ; EXTERNAL? JE @F ; YES, SO IGNORE MOV AX,IOBASE[EBX] CMP AX,IOBASE[EDI] JE SHORT INIT120 ; ANOTHER FOR SAME ADDRESS @@: MOV EDI,PORTPOINTER[EDI] LOOP INIT100 INIT110: MOV EDI,0 ; FLAG NOT FOUND INIT120: RET INITCOMMON: CMP PROTOCOL[EBX],2 ; NETROM? JNE SHORT NEEDRTS ; ; NETROM - CLEAR KISS OPTIONS, JUST IN CASE! ; MOV KISSFLAGS[EBX],0 ; CMP FULLDUPLEX[EBX],1 ; NETROM DROPS RTS TO INHIBIT! ; JE SHORT NEEDRTS ; ; MOV AL,9 ; OUT2 DTR ; NEEDRTS: SETARVEC RXASTX ; INITIAL INTERRUPT ENTRY SETATVEC IGNORE ; IF KISS, SET TIMER TO SEND KISS PARAMS ; CMP PROTOCOL[EBX],2 ; NETROM? JE SHORT NOPARAMS MOV PARAMTIMER[EBX],TICKS*30 ; 30 SECS FOR TESTING NOPARAMS: RET ; PUBLIC KISSTX,KISSRX,KISSTIMER ; EXTRN _Q_ADD:NEAR,Q_REM:NEAR,RELBUFF:NEAR,GETBUFF:NEAR KISSRX: ; ; Poll Async Driver ; pushad MOVZX EAX,IOBASE[EBX] PUSH EAX ; Port No CALL _POLLKISS ADD ESP,4 popad CMP POLLED[EBX],1 ; ZERO = NOT POLLED, 1 = POLL RECOGNISED JBE SHORT NOPOLL ; ; POLL OR POLL RESPONSE HAS BEEN RECEIVED ; TEST KISSFLAGS[EBX],POLLINGKISS JZ SHORT POLLRXED ; ; POLL RESPONSE RECEIVED - CLEAR POLL OUTSTANDING ; MOV POLLED[EBX],0 MOV POLLFLAG[EBX],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[EBX] MOV POLLED[EBX],0 AND AL,0F0H ; PORT PFINDLOOP: CMP OURCTRL[EBX],AL JE SHORT OURPOLL MOV EBX,SUBCHAIN[EBX] OR EBX,EBX JZ SHORT NOPOLL ; NOT FOR US JMP PFINDLOOP OURPOLL: ; ; SEE IF ANYTHING QUEUED ; CMP KISSTX_Q[EBX],0 JE SHORT SENDACK ; MOV POLLED[EBX],1 ; LET TIMER DO THE SEND JMP NOPOLL SENDACK: MOV ESI,EBX CALL SENDPOLL ; OTHER END DOESNT CARE ABOUT ADDR NOPOLL: LEA ESI,ASYNCMSG_Q[EBX] CALL Q_REM JNZ SHORT GOTAFRAME RET ; NOTHING RECEIVED GOTAFRAME: ; ; IF NETROM, CAN PASS ON NOW ; CMP PROTOCOL[EBX],2 JE SHORT FOUNDIT ; NETROM PROTOCOL ; ; MESSAGE MAY BE DATA OR DATA ACK. IT HAS NOT YET BEEN CHECKSUMMED ; MOV AL,MSGPORT[EDI] TEST AL,0FH JZ SHORT CHECK_CHECKSUM ; NORMAL DATA ; ; SPECIAL FRAME - IS IT AN ACK? ; AND AL,0FH CMP AL,0CH ; ACK JE SHORT 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[EBX],POLLEDKISS JNZ SHORT ACKREQFRAME ; FRAME REQUIRING AN ACK ; ; THIS IS AN ACK OF A DATA FRAME ; MOVZX EBX,BYTE PTR 7[EDI] MOV BH,8[EDI] ADD EBX,LINKS CMP L2TIMER[EBX],0 JE SHORT NOTIMER ; ALREADY EXPIRED MOV AL,L2TIME[EBX] XOR AH,AH MOV L2TIMER[EBX],AX NOTIMER: JMP SHORT NOTFOUND ; RETURN IT ACKREQFRAME: ; ; NOT ALLOWED - DISCARD ; JMP DISCARDFRAME CHECK_CHECKSUM: MOVZX ECX,WORD PTR 5[EDI] ; LENGTH, INCLUDING SUM CMP ECX,13H JB SHORT DISCARDFRAME ; TOO SHORT FOR VALID AX25 TEST KISSFLAGS[EBX],CHECKSUM JZ SHORT KISSRX00 ; ; SUM MESSAGE, AND IF DUFF DISCARD. IF OK DECREMENT COUNT TO REMOVE SUM ; DEC WORD PTR 5[EDI] ; MOV AH,MSGPORT[EDI] ; IS INCLUDED IN SUM LEA ESI,7[EDI] ; TO DATA SUB ECX,7 jz @F SUMLOOP: LODSB XOR AH,AL LOOP SUMLOOP OR AH,AH JZ SHORT KISSRX00 ; SUM OK @@: ADD RXERRORS[EBX],1 JMP SHORT DISCARDFRAME FOUNDIT: LEA ESI,PORTRX_Q[EBX] CALL _Q_ADD ; PUT ON PORT RX QUEUE RET KISSRX00: ; ; AT THIS STAGE, KISS CONTROL BYTE IS IN PORT FIELD - FIND CORRECT ; SUBPORT RECORD TO ADD IT TO ; MOV AL,MSGPORT[EDI] ; ; SHOULD ONLY HAVE NORMAL DATA NOW ; FINDLOOP: CMP OURCTRL[EBX],AL JE SHORT FOUNDIT MOV EBX,SUBCHAIN[EBX] OR EBX,EBX JZ SHORT NOTFOUND JMP FINDLOOP NOTFOUND: DISCARDFRAME: ; ; INVALID CONTROL BYTE - DISCARD IT (MAYBE SHOULD COUNT ??) ; CALL RELBUFF RET KISSTX: ; ; START TRANSMISSION - EDI = ADDR OF MESSAGE ; PUSH EBX MOV EBX,FIRSTPORT[EBX] ; ALL FRAMES GO ON SAME Q TEST KISSFLAGS[EBX],POLLEDKISS JNZ SHORT QUEUEIT ; MUST QUEUE - CANT SEND TILL POLLED CMP KISSTX_Q[EBX],0 JNE SHORT QUEUEIT ; ALREADY SOMETHING QUEUED CMP POLLFLAG[EBX],0 JNE SHORT QUEUEIT ; POLL OUTSTANDING, SO QUEUE FRAME CMP TXTADDR[EBX],0 JE SHORT OKTOSEND ; ; ALREADY SENDING - QUEUE FRAME ; QUEUEIT: LEA ESI,KISSTX_Q[EBX] CALL _Q_ADD POP EBX RET OKTOSEND: ; ; IF NETROM PROTOCOL AND NOT FULL DUPLEX AND BUSY, QUEUE IT ; CMP PROTOCOL[EBX],2 ; NETROM? JNE SHORT DONTCHECKDCD ; NO CMP FULLDUPLEX[EBX],1 JE SHORT DONTCHECKDCD ; FULLDUP - NO CHECK ; ; NETROM USES RTS, CROSS-CONNECTED TO CTS AT OTHER END, TO MEAN ; NOT BUSY ; ; MOV DX,MSR[EBX] ; IN AL,DX ; ; TEST AL,CTSBIT ; CTS HIGH? ; JZ SHORT QUEUEIT ; NO, SO QUEUE FRAME ; ; GOING TO SEND - DROP RTS TO INTERLOCK OTHERS ; ; MOV DX,MCR[EBX] ; 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[EBX] ; IN AL,DX ; TEST AL,CTSBIT ; JNZ SHORT DONTCHECKDCD ; STILL HIGH, SO CAN SEND ; ; RAISE RTS AGAIN, AND QUEUE FRAME ; ; DELAY ; MOV DX,MCR[EBX] ; MOV AL,0BH ; RTS DTR OUT2 ; ; OUT DX,AL ; JMP QUEUEIT DONTCHECKDCD: MOV TXTADDR[EBX],1 ; ENSURE POLL ISNT SENT CALL SENDFRAME POP EBX RET SENDFRAME: ; ; GET REAL PORT TABLE ENTRY - IF MULTIPORT, FRAME IS QUEUED ON ; FIRST ; CMP PROTOCOL[EBX],2 ; NETROM JE NRTX00 PUSH EBX MOV AL,4[EDI] ; PORT NUMBER TXPORTLOOP: CMP PORTNUMBER[EBX],AL JE SHORT OURPORT MOV EBX,SUBCHAIN[EBX] CMP EBX,0 JNE SHORT TXPORTLOOP POP EBX MOV TXTADDR[EBX],0 ; ALLOW OTHER ACTIONS CALL RELBUFF RET OURPORT: MOV AL,OURCTRL[EBX] ; CORRECT CONTROL BYTE MOV AH,KISSFLAGS[EBX] ; CORRECT KISSFLAGS POP EBX MOV TXCTRL[EBX],AL ; FOR TX ROUTINE MOV REALKISSFLAGS[EBX],AH ; SETATVEC TXKISS ; SEND FRAME DELIMITER FIRST ; MOV ESCTXCHAR[EBX],0 JMP SHORT TXCOMMON NRTX00: SETATVEC TXTEXT ; SEND FRAME DELIMITER FIRST MOV ESCTXCHAR[EBX],STX ; SEND STX FIRST MOV TXCCC[EBX],0 ; TXCOMMON: MOV TXTADDR[EBX],EDI ; SAVE ADDR OF LAST MESSAGE ; MOVZX ECX,WORD PTR 5[EDI] ; MSG LENGTH SUB ECX,7 ; HEADER LENGTH ADD EDI,7 MOV AX,WORD PTR [EDI] ; KISS CONTROL FRAME? AND AH,0FH ; MASK OUT PORT BITS CMP AX,1C0H ; KISS CONTROL FRAME? JNE SHORT TXNORM ; DATA FRAME ; ; KISS CONTROL FRAME ; SETATVEC TXKISSCTRL TXNORM: MOV TXCHAR[EBX],EDI ; SAVE MOV TXCOUNT[EBX],CX ; ; encode message, then send to driver ; MOV EDI,OFFSET ENCBUFF PUSH EDI ENCLOOP: CALL IOTXCA[EBX] ; DO FIRST SEND CMP TXTADDR[EBX],0 JNE ENCLOOP MOV ECX,EDI POP EDI SUB ECX,EDI push ecx push edi MOVZX EAX,IOBASE[EBX] PUSH EAX ; Port No CALL _ASYSEND add esp,12 RET ; KISSTIMER: ; ; IF FRAMES QUEUED, AND NOT SENDING, START ; CMP EBX,FIRSTPORT[EBX] ; ALL FRAMES GO ON SAME Q JNE NOTMAINPORT ; ; SEE IF POLL HAS TIMED OUT ; TEST KISSFLAGS[EBX],POLLINGKISS JZ SHORT NOTPOLLED CMP POLLFLAG[EBX],0 JE SHORT NOTPOLLED DEC POLLFLAG[EBX] JNZ NOTMAINPORT ; TIMING OUT OR RECEIVING ; ; POLL HAS TIMED OUT - MAY NEED TO DO SOMETHING ; PUSH EBX MOV EBX,POLLPOINTER[EBX] ADD L2URUNC[EBX],1 ; PUT IN UNDERRUNS FIELD POP EBX NOTPOLLED: CMP TXTADDR[EBX],0 JE SHORT NOTSENDING ; JMP NOTCTSWAIT ; IFNDEF KANT ; ; CMP TXTADDR[EBX],0FFFFH ; JNE SHORT NOTCTSWAIT ; ; WAITING FOR CTS ; ; MOV DX,MSR[EBX] ; IN AL,DX ; TEST AL,CTSBIT ; JNZ SHORT TIMERSEND ; OK TO SEND NOW ; ; ENDIF BUSY_J: JMP BUSY ; WAIT FOR CTS NOTCTSWAIT: ; ; SEE IF BEEN SENDING TOO LONG ; DEC TXACTIVE[EBX] JNZ SHORT BUSY_J ; ; SEEM TO HAVE LOST A TX INTERRUPT - TRY CALLING TX ROUTINE ; ADD L1DISCARD[EBX],1 ; FOR STATS MOV TXACTIVE[EBX],2 CALL IOTXCA[EBX] JMP BUSY NOTSENDING: ; ; SEE IF ANYTHING TO SEND ; CMP POLLED[EBX],1 JE SHORT BEENPOLLED ; OK EVEN IF SLAVE MODE TEST KISSFLAGS[EBX],POLLEDKISS JNZ NOTMAINPORT ; CANT SEND TILL WE GET POLL BEENPOLLED: CMP KISSTX_Q[EBX],0 JE SHORT NOTHINGTOSEND ; ; IF NETROM MODE AND NOT FULL DUP, CHECK DCD ; MOV POLLED[EBX],0 CMP PROTOCOL[EBX],2 ; NETROM? JNE SHORT DONTCHECKDCD_1 CMP FULLDUPLEX[EBX],1 JE SHORT DONTCHECKDCD_1 ; MOV DX,MSR[EBX] ; IN AL,DX ; ; TEST AL,CTSBIT ; DCD HIGH? ; JZ SHORT NOTHINGTOSEND ; NO, SO WAIT ; ; DROP RTS TO LOCK OUT OTHERS ; ; MOV DX,MCR[EBX] ; 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[EBX] ; IN AL,DX ; TEST AL,CTSBIT ; JNZ SHORT TIMERSEND ; STILL HIGH, SO CAN SEND ; ; RAISE RTS AGAIN, AND WAIT A BIT MORE ; ; DELAY ; ; MOV DX,MCR[EBX] ; MOV AL,0BH ; RTS DTR OUT2 ; ; OUT DX,AL JMP SHORT NOTHINGTOSEND DONTCHECKDCD_1: TIMERSEND: PUSH ESI PUSH EDI PUSH EDX LEA ESI,KISSTX_Q[EBX] CALL Q_REM CALL SENDFRAME POP EDX POP EDI POP ESI JMP SHORT NOTMAINPORT NOTHINGTOSEND: ; ; IF POLLED MODE, SEND A POLL TO NEXT PORT ; TEST KISSFLAGS[EBX],POLLINGKISS JZ SHORT NOTMAINPORT ; ; FIND WHICH CHANNEL TO POLL NEXT ; PUSH ESI MOV ESI,POLLPOINTER[EBX] MOV ESI,SUBCHAIN[ESI] CMP ESI,0 JNE SHORT POLLTHISONE MOV ESI,EBX ; BACK TO FIRST POLLTHISONE: MOV POLLPOINTER[EBX],ESI ; FOR NEXT TIME CALL SENDPOLL POP ESI BUSY: NOTMAINPORT: KISSSLOWTIMER: ; ; SEE IF TIME TO REFRESH KISS PARAMS ; TEST KISSFLAGS[EBX],POLLEDKISS JNZ SHORT KTIMERRET ; WE ARE THE SLAVE CMP PROTOCOL[EBX],2 ; NETROM? JNE SHORT KISSXX KTIMERRET: RET ; NOT ON NETROM KISSXX: DEC PARAMTIMER[EBX] JNZ SHORT KTIMERRET ; ; QUEUE A 'SET PARAMS' FRAME ; PUSH ESI PUSH EDI CMP PORTDISABLED[EBX],0 JNE SHORT NOBUFFERS ; PORT DISABLED MOV EDI,OFFSET KISSPARAMS PUSH EDI MOV AL,FEND STOSB MOV AH,OURCTRL[EBX] MOV AL,1 OR AL,AH ; PUT IN CHANNEL BITS STOSB MOV AL,BYTE PTR PORTTXDELAY[EBX] STOSB MOV AL,FEND STOSB STOSB MOV AL,2 OR AL,AH ; PUT IN CHANNEL BITS STOSB MOV AL,PORTPERSISTANCE[EBX] STOSB MOV AL,FEND STOSB STOSB MOV AL,3 OR AL,AH ; PUT IN CHANNEL BITS STOSB MOV AL,PORTSLOTTIME[EBX] STOSB MOV AL,FEND STOSB STOSB MOV AL,4 OR AL,AH ; PUT IN CHANNEL BITS STOSB MOV AL,PORTTAILTIME[EBX] STOSB MOV AL,FEND STOSB STOSB MOV AL,5 OR AL,AH ; PUT IN CHANNEL BITS STOSB MOV AL,FULLDUPLEX[EBX] STOSB MOV AL,FEND STOSB MOV ECX,EDI POP EDI SUB ECX,EDI PUSH EBX MOV EBX,FIRSTPORT[EBX] ; ALL FRAMES GO ON SAME Q ; ; QUEUE FRAME ; push ecx push edi MOVZX EAX,IOBASE[EBX] PUSH EAX ; Port No CALL _ASYSEND add esp,12 POP EBX NOBUFFERS: MOV PARAMTIMER[EBX],TICKS*60*5 ; 5 MINS POP EDI POP ESI RET SENDPOLL: ; ; SEND POLL TO PORT IN ESI ; MOV POLLFLAG[EBX],TICKS/3 ; ALLOW 1/3 SEC MOV AL,OURCTRL[ESI] ; CORRECT CONTROL BYTE OR AL,0EH ; POLL BITS MOV TXCTRL[EBX],AL ; FOR TX ROUTINE ; ; encode message, then send to driver ; MOV EDI,OFFSET ENCBUFF MOV AL,FEND STOSB MOV AL,TXCTRL[EBX] STOSB MOV AL,FEND STOSB push 3 ; LEN push OFFSET ENCBUFF MOVZX EAX,IOBASE[EBX] PUSH EAX ; Port No CALL _ASYSEND add esp,12 RET RXASTX: AND LINKSTS[EBX],0FFH-10H ; CLEAR PARITY ERROR ; ; ADD CHARS,1 ; ADC CHARS+2,0 CMP PROTOCOL[EBX],2 JE SHORT RXNR00 ; NETROM PROTOCOL CMP AL,FEND ; FRAME DELIMITER? JNE RXA010 ; NO - IGNORE ; ; GET BUFFER ; CALL GETBUFF JNZ SHORT GETB00 JMP RXA010 GETB00: MOV CURALP[EBX],EDI ; SAVE IT ; MOV DWORD PTR [EDI],OFFSET32 RXA005 RXA005: ADD EDI,7 ; SKIP CHAIN, PORT, LENGTH MOV NEXTCHR[EBX],EDI ; SAVE BUFFER ADDRESS ; MOV FRAMELEN[EBX],7 ; INITIAL LENGTH SETARVEC RXACTL RET RXA010: RET RXNR00: CMP ESCFLAG[EBX],1 JE SHORT RXA011 ; DONT ACCEPT DLE/STX CMP AL,STX JE SHORT RXA002 CMP AL,DLE JNE SHORT RXA010 ; IGNORE MOV ESCFLAG[EBX],1 RET RXA002: ; ; GET BUFFER ; CALL GETBUFF JNZ SHORT GETBNR JMP RXA011 ; IGNORE (? WAIT FOR ETX OR TIMEOUT) GETBNR: ; MOV DWORD PTR [EDI],OFFSET32 GETBNR MOV CURALP[EBX],EDI ; SAVE IT ADD EDI,7 ; SKIP CHAIN, PORT, LENGTH MOV NEXTCHR[EBX],EDI ; SAVE BUFFER ADDRESS ; MOV FRAMELEN[EBX],7 ; INITIAL LENGTH MOV RXCCC[EBX],0 SETARVEC RXAMSGNR RXA011: MOV ESCFLAG[EBX],0 RET RXACTL: ; ADD CHARS,1 ; ADC CHARS+2,0 ; ; SHOULD BE PORT NUMBER - IF FEND WE HAVE GOT OUT OF STEP ; MOV EDI,CURALP[EBX] ; GET BUFFER ADDR CMP AL,FEND JE RXA005 ; TRY AGAIN ; MOV MSGPORT[EDI],AL ; PUT CONTROL BYTE IN PORT FIELD XOR RXCCC[EBX],AL ; MAINTAIN CCC AND AL,0FH CMP AL,0EH ; POLL OR POLL REPLY? JNZ SHORT NOTPOLLREPLY ; ; POLL OR REPLY TO POLL ; MOV AL,MSGPORT[EDI] MOV POLLED[EBX],AL ; FOR BG TO PROCESS RET ; ACCEPT FEND OR CONTROL NEXT NOTPOLLREPLY: SETARVEC RXAMSG TEST KISSFLAGS[EBX],POLLINGKISS JZ SHORT NOTPOLL00 ; ; POLLED MODE - EXTEND TIMEOUT FOR DATA FRAME ; MOV POLLFLAG[EBX],5*TICKS ; 5 SECS - SHOULD BE PLENTY NOTPOLL00: RET RXAMSG: ; ADD CHARS,1 ; ADC CHARS+2,0 CMP AL,FEND JE SHORT MSGEND ; END OF FRAME CMP AL,FESC JNE SHORT NOTESC ; ; ESC - SET FLAG ; MOV ESCFLAG[EBX],1 ; SET FESC RECEIVED RET NOTESC: CMP ESCFLAG[EBX],1 JNE SHORT RXNORM CMP AL,TFESC ; ESC'ED FESC? JNE SHORT NOTTFESC MOV AL,FESC ; REAL FESC JMP SHORT RXNORM NOTTFESC: CMP AL,TFEND ; ESC'ED FEND? JNE SHORT RXNORM MOV AL,FEND RXNORM: MOV EDI,NEXTCHR[EBX] ; GET POINTER STOSB ; PUT IN BUFFER MOV NEXTCHR[EBX],EDI ; SAVE POINTER RXA500: MOV ESCFLAG[EBX],0 INC FRAMELEN[EBX] CMP FRAMELEN[EBX],MAXDATA JB SHORT RXARET ; OK DEC NEXTCHR[EBX] ; PREVENT OVERRUN OR LINKSTS[EBX],10H ; SET ERROR RXARET: RET ; MSGEND: MOV EDI,NEXTCHR[EBX] ; GET POINTER STOSB ; PUT FEND ON END MOV EDI,CURALP[EBX] MOV POLLFLAG[EBX],0 ; LINK NOW IDLE QMSG: TEST LINKSTS[EBX],10H JNZ SHORT RXAERROR ; OVERRUN, ETC MOV CX,FRAMELEN[EBX] MOV 5[EDI],CX ; LENGTH LEA ESI,ASYNCMSG_Q[EBX] ; PUT ON RX QUEUE - SUBPORT DETAILS ARE ; SORTED OUT LATER CALL _Q_ADD JMP RXAEXIT RXAERROR: MOV EDI,CURALP[EBX] CALL RELBUFF RXAEXIT: MOV IORXCA[EBX],OFFSET32 RXASTX ; FOR NEXT MESSAGE RET ; RXAMSGNR: ; ADD CHARS,1 ; ADC CHARS+2,0 CMP AL,DLE JNE SHORT NOTDLE ; ; DLE - SET FLAG UNLESS ALREADY SET ; CMP ESCFLAG[EBX],1 JE SHORT NOTDLE ; MUST BE DLE/DLE - MEANS REAL 10H! MOV ESCFLAG[EBX],1 ; SET DLE RECEIVED RET NOTDLE: MOV EDI,NEXTCHR[EBX] ; GET POINTER STOSB ; PUT IN BUFFER MOV NEXTCHR[EBX],EDI ; SAVE POINTER CMP AL,ETX ; END? JNE SHORT RXA500NR ; NO ; CMP ESCFLAG[EBX],1 JE SHORT RXA500NR ; DLE/ETX SETARVEC RXACCC ; RET ; RXA500NR: ADD RXCCC[EBX],AL ; UPDATE LRC JMP RXA500 ; CHECK FOR BUFFER OVERFLOW, ETC RXACCC: ; ADD CHARS,1 ; ADC CHARS+2,0 CMP AL,RXCCC[EBX] ; ACCUMULATED VALUE JE SHORT OK_CRC ADD RXERRORS[EBX],1 JMP RXAERROR ; DUFF OK_CRC: MOV EDI,CURALP[EBX] JMP QMSG ; QUEUE FOR BG TO PROCESS ; RXAPTY: RET ; TXKISS: SETATVEC TXNULL MOV AL,FEND JMP TXA100 ; SEND FEND TXNULL: ; ; SEND CONTROL BYTE ; SETATVEC TXTEXT MOV AL,TXCTRL[EBX] ; ; SEE IF ACK MODE IN USE ; TEST REALKISSFLAGS[EBX],ACKMODE JZ SHORT NOACKMODE ; ; SEE IF FRAME NEEDS AN ACK ; MOV ESI,TXTADDR[EBX] CMP DWORD PTR BUFFLEN-4[ESI],0 JE SHORT NOACKMODE MOV EDX,LINKS SUB DWORD PTR BUFFLEN-4[ESI],EDX ; CAN ONLY SEND 2 BOTES TO TNC SETATVEC TXHDDR1 OR AL,0CH ; RESPONSE MODE NOACKMODE: MOV TXCCC[EBX],FEND ; INITIALISE CRC - HAVE ALREADY SEND FEND XOR TXCCC[EBX],AL JMP TXA100 ; SEND KISS CONTROL TXHDDR1: ; ; SEND FIRST ACK BYTE ; MOV ESI,TXTADDR[EBX] MOV AL,BUFFLEN-4[ESI] SETATVEC TXHDDR2 JMP TXA100 ; SEND IT TXHDDR2: ; ; SEND SECOND ACK BYTE ; MOV ESI,TXTADDR[EBX] MOV AL,BUFFLEN-3[ESI] MOV DWORD PTR BUFFLEN-4[ESI],0; CLEAR INDICATOR SETATVEC TXTEXT JMP TXA100 ; SEND IT TXTEXT: MOV AL,ESCTXCHAR[EBX] OR AL,AL JZ SHORT TXA000 ; NORMAL MOV ESCTXCHAR[EBX],0 JMP TXA100 ; SEND CHAR FOLLOWING ESC TXA000: CMP TXCOUNT[EBX],0 JZ SHORT TXETX DEC TXCOUNT[EBX] MOV ESI,TXCHAR[EBX] LODSB ; NEXT CHAR MOV TXCHAR[EBX],ESI CMP PROTOCOL[EBX],2 JE SHORT CHECKDLE ; NETROM MODE XOR TXCCC[EBX],AL CMP AL,FEND JNE SHORT NOTTXFEND MOV ESCTXCHAR[EBX],TFEND ; ESC'ED FEND MOV AL,FESC JMP SHORT TXA100 NOTTXFEND: ; If D700 Mode, Escape all C chars to break up TC 0 string CMP AL,'C' JNE SHORT NOTTXD700 TEST KISSFLAGS[EBX],D700 JZ SHORT NOTTXD700 MOV ESCTXCHAR[EBX],'C' ; C Escaped is C MOV AL,FESC JMP SHORT TXA100 NOTTXD700: CMP AL,FESC JNE SHORT TXA100 MOV ESCTXCHAR[EBX],TFESC ; ESC'ED ESC JMP SHORT TXA100 CHECKDLE: ; ; CHECK FOR NETROM CHARS TO PREFIX ; ADD TXCCC[EBX],AL CMP AL,DLE JE SHORT TXDLE00 CMP AL,STX JE SHORT TXDLE00 CMP AL,ETX JNE SHORT TXA100 TXDLE00: MOV ESCTXCHAR[EBX],AL MOV AL,DLE JMP SHORT TXA100 TXETX: CMP PROTOCOL[EBX],2 JE SHORT TXETXNR TEST KISSFLAGS[EBX],CHECKSUM JNZ SHORT TXETXP SETATVEC NEXTFRAME MOV AL,FEND ; ETX TXA100: stosb 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[EBX] XOR AL,FEND ; HAVNT INCLUDED FEND YET CMP AL,FEND JNE SHORT NOTCHKFEND MOV ESCTXCHAR[EBX],TFEND ; ESC'ED FEND MOV AL,FESC JMP SHORT TXA100 NOTCHKFEND: CMP AL,FESC JNE SHORT TXA100 MOV ESCTXCHAR[EBX],TFESC ; ESC'ED ESC JMP SHORT TXA100 ASENDCC: ; ; NETROM END OF FRAME ; MOV AL,TXCCC[EBX] 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[EBX] OR AL,AL JZ SHORT SENDFEND00 ; NORMAL MOV ESCTXCHAR[EBX],0 JMP SHORT TXA100 ; SEND CHAR FOLLOWING ESC SENDFEND00: MOV AL,FEND SETATVEC NEXTFRAME JMP SHORT TXA100 NEXTFRAMENR: ; ; IF NOT FULL DUP, RAISE RTS ; CMP FULLDUPLEX[EBX],1 JE SHORT NEXTFRAME ; MOV DX,MCR[EBX] ; MOV AL,0BH ; DTR OUT2 ; ; OUT DX,AL NEXTFRAME: PUSH EDI MOV EDI,TXTADDR[EBX] MOV ESI,OFFSET32 TRACE_Q CALL _Q_ADD ; FEED TO TRACE CODE POP EDI TEST KISSFLAGS[EBX],POLLINGKISS JZ SHORT ENDFRAME ; ; SEND A POLL AFTER MSG ; MOV AL,OURCTRL[ESI] ; CORRECT CONTROL BYTE OR AL,0EH ; POLL BITS TEST KISSFLAGS[EBX],POLLINGKISS JZ SHORT 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[EBX],0 ; CLEAR SENDING INDICATOR MOV TXACTIVE[EBX],0 ; SETATVEC IGNORE RET IGNORE: RET ; TXKISSCTRL: ; ; SEND KISS CONTROL FRAME ; CMP TXCOUNT[EBX],0 JZ SHORT TXETXC DEC TXCOUNT[EBX] MOV ESI,TXCHAR[EBX] LODSB ; NEXT CHAR MOV TXCHAR[EBX],ESI JMP SHORT TXA100C TXETXC: MOV EDI,TXTADDR[EBX] CALL RELBUFF SETATVEC ENDFRAME MOV AL,FEND ; ETX TXA100C: ; MOV DX,IOADDR[EBX] ; OUT DX,AL ; SEND CHAR ; ; ADD CHARS,1 ; ADC CHARS+2,0 RET CALC_CRC: ; XOR DL,AL ; OLD FCS .XOR. CHAR MOVZX EBX,DL ; CALC INDEX INTO TABLE FROM BOTTOM 8 BITS ADD EBX,EBX MOV DL,DH ; SHIFT DOWN 8 BITS XOR DH,DH ; AND CLEAR TOP BITS XOR DX,[EBX+_CRCTAB] ; XOR WITH TABLE ENTRY RET ; ; _TEXT ENDS END