PAGE 56,132 ; ; 22/11/95 ; ; FIX CONDITIONALS SO WE CAN ASSEMBLE KANT VERSION ; DATA SEGMENT PUBLIC 'DATA' INCLUDE ENVIRON.ASM INCLUDE STRUCS.ASM IFDEF KANT INCLUDE KANTEQU.ASM ENDIF IFDEF MSC INCLUDE MSCEQU.ASM ENDIF IF TNC2 TABLELEN DW TYPE TNCDATA ; LNKSTATEMSG DB 'Link state is: ' CONNECTEDMSG DB 'CONNECTED to ' WHATMSG DB 'Eh?',0DH CMDMSG DB 'cmd:' DISCONNMSG DB CR,'*** DISCONNECTED',CR CONMSG DB CR,'*** CONNECTED to ' SWITCH DB 'SWITCH',CR WAS DB ' was ' VIA DB ' via ' OFF DB 'OFF',0DH ON DB 'ON ',0DH CMDX STRUC DB ' ' ; COMMAND STRING CMDLEN DB ? ; SIGNIFICANT LENGTH CMDPROC DW ? ; COMMAND PROCESSOR CMDFLAG DW ? ; FLAG/VALUE ADDRESS CMDX ENDS COMMANDLIST LABEL BYTE CMDX <'BBSMON',6,ONOFF,BBSMON> ; BBS (SHORT FORM ) MONITOR BTCMD CMDX <'BTEXT',2,BTEXT> CMDX <'CONOK',4,ONOFF,CONOK> CMDX <'C SWITCH',8,CSWITCH> CMDX <'CBELL',2,ONOFF,CBELL> CMDX <'CONMODE',4,CONMODE> CMDX <'CPACTIME',2,ONOFF,CPACTIME> CMDX <'CR',2,ONOFF,CRFLAG> CMDX <'APPLFLAG',5,VALHEX,APPLFLAGS> CMDX <'APPL',4,VALHEX,APPLICATION> CMDX <'CONVERS',4,TNCCONV> CMDX <'CONNECT',1,TNCCONNECT> CMDX <'DISCONNE',1,TNCDISC> CMDX <'ECHO',1,ONOFF,ECHOFLAG> CMDX <'FLOW',4,ONOFF,FLOWFLAG> CMDX <'HEADERLN',2,ONOFF,HEADERLN> CMDX <'K',1,TNCNODE> ; CONNECT TO NODE CMDX <'MTXFORCE',4,ONOFF,MTXFORCE> ; MONITOR TXED FRAMES WHEN M OFF CMDX <'LFIGNORE',3,ONOFF,LFIGNORE> ; IGNORE LF IN DATA FROM USER CMDX <'MTX',3,ONOFF,MTX> ; MONITOR TRANSMITTED FRAMES CMDX <'MALL',2,ONOFF,MALL> CMDX <'MCOM',4,ONOFF,MCOM> CMDX <'MCON',2,ONOFF,MCON> CMDX <'MMASK',2,VALHEX,MMASK> ; MONITOR PORT MASK CMDX <'MONITOR',1,ONOFF,TRACEFLAG> CMDX <'NEWMODE',2,ONOFF,NEWMODE> CMDX <'NODE',3,TNCNODE> ; CONNECT TO NODE CMDX <'NOMODE',2,ONOFF,NOMODE> CMDX <'SENDPAC',2,VALHEX,SENDPAC> CMDX <'PACLEN',1,VALUE,TPACLEN> CMDX <'RELEASE',3,TNCRELEASE> CMDX <'TRANS',1,TNCTRANS> UNPROT CMDX <'UNPROTO',1,UNPROTOCMD> NUMBEROFCOMMANDS EQU ($-COMMANDLIST)/TYPE CMDX LASTCH DB 0 ; ESC FLAG FOR HOST READ BUFFER HEXFLAG DB 0 NUMBER DB 4 DUP (0),CR BADMSG DB '?bad parameter',CR,0 ENDIF BTHDDR DW 0 ; CHAIN DB 0 ; PORT BTLENGTH DW 7 ; LENGTH DB 0F0H ; PID BTEXTFLD DB 0DH,256 DUP (0) IF TNC2 CMDENDADDR DW 0 ; POINTER TO END OF COMMAND MBOPTIONBYTE DB 0 ENDIF D10 DB 10 D16 DB 16 NEWVALUE DB 0 SWITCHSP DB 'SWITCH ' DISCFLAG DB 0 ; HOST MODE DISCONNECT PARAM (FOR STAY CHECK) IFNDEF PCSWITCH BREAKING DB 0 ; IN BREAK STATE FLAG ENDIF EVEN IF TNC2 EXTRN TNCTABLE:WORD,NUMBEROFSTREAMS:WORD EXTRN PACLEN:BYTE,TRANSDELAY:BYTE ENDIF EXTRN PORTTABLE:WORD,NUMBEROFPORTS:WORD,BUFFLEN:ABS IF BLACKBITS EXTRN BLACKLIST:BYTE ENDIF EXTRN BBSCALL:BYTE,IDMSG:WORD,NORMCALL:BYTE EXTRN QCOUNT:BYTE,UNPROTOCALL:BYTE,IDMSG_Q:WORD EXTRN SESSIONHDDR:BYTE,SESSHDDRLEN:ABS EXTRN COMPAREFIELD:BYTE,COMPAREPORT:BYTE IFDEF PCSWITCH EXTRN DESQVIEW:BYTE,VECTORLENGTH:ABS EXTRN BPQHOSTVECTOR:BYTE,BPQVECLENGTH:BYTE,BPQHOSTSTREAMS:ABS ELSE EXTRN ASYNCMODE:BYTE ENDIF IFNDEF KANT EXTRN REALTIMETICKS:WORD ENDIF IF TNC2 PUBLIC SWITCH ENDIF PUBLIC DISCFLAG,B2HEX DATA ENDS CODE SEGMENT PUBLIC 'CODE' ASSUME CS:CODE,DS:DATA,ES:DATA ; PUBLIC TNCTIMERPROC IF TNC2 PUBLIC CONSOLESEND,SENDSTARDISC PUBLIC PUTCHARINBUFFER,DOCONMODECHANGE EXTRN SETUPCONSOLESESSION:NEAR,DECODECALLSTRING:NEAR EXTRN CHECKIFBUSY:NEAR,NORMSTR:NEAR EXTRN CONV_DIGITS:NEAR,CLEARSESSIONENTRY:NEAR ENDIF EXTRN PUT_ON_PORT_Q:NEAR,SENDNODESMSG:NEAR,FINDDESTINATION:NEAR PUBLIC COUNT_QUEUED_FRAMES,SCAN,SENDIDMSG,SENDBTMSG,COUNT_Q PUBLIC COUNT_AT_L2 EXTRN CLOSESESSIONPARTNER:NEAR,CONVFROMAX25:NEAR EXTRN GETBUFF:NEAR,RELBUFF:NEAR,Q_ADDF:NEAR,Q_ADD:NEAR,Q_REM:NEAR EXTRN SETUPBPQCONSOLESESSION:NEAR EXTRN FINDLINKXX:NEAR,GETPORTWINDOW:NEAR,SENDSABM:NEAR IFDEF PCSWITCH EXTRN DATASEG:WORD ENDIF EXTRN RETURNEDTONODE:NEAR,GETPORTTABLEENTRY:NEAR CR EQU 0DH LF EQU 0AH IFDEF KANT ; ; INTERRUPT HANDLERS FOR ASYNC PORT ; PUBLIC GOTTNCCHAR,TNCSENDCHAR,KANTTNCBG ; GOTTNCCHAR: ; ; CHARACTER AVAILABLE INTERRUPT ; IN AL,(SST) TEST AL,40H JZ NOBREAK ; MOV BREAKING,1 ; BREAK DETECTED RET NOBREAK: CMP BREAKING,1 JNE NOTBREAKEND ; ; END OF BREAK ; MOV BREAKING,0 CALL SETCOMMANDMODE IN AL,SRB ; DISCARD NULL RET NOTBREAKEND: TEST AL,01110000B ; ERROR BITS JZ NOERROR MOV AL,00110101B OUT (SCM),AL ; RESET ERROR RET NOERROR: IN AL,(SRB) CALL SENDCHARSUPPORT RET TNCSENDCHAR: ; ; CHARACTER SEND INTERRUPT - JUST TURN OFF FOR NOW ; MOV AL,10B OUT SIMK,AL ; MASK TX INT RET KANTTNCBG: ; ; SEND ON ASYNC IF ANYTHING AVAILABLE ; CMP RXCOUNT[BX],0 JE KANTTNCRET ; NOWT THERE CMP ASYNCMODE,'T' JNE DISCARDIT ; NOT IN TERMINAL MODE IN AL,SST TEST AL,TXRDY JZ KANTTNCRET ; CANT SEND ; ; CHECK CTS TO SEE IF TERMINAL WANTS US TO STOP SENDING ; IN AL,IPFW TEST AL,80H JNZ KANTTNCRET ; CTS LOW CALL GETONECHAR OUT STB,AL KANTTNCRET: ; ; LOOK FOR TRANSPARENT MODE SEND ; CMP AUTOSENDFLAG[BX],1 JNE KNOSEND MOV AUTOSENDFLAG[BX],0 CMP KBBUFFER[BX],0 JE KNOSEND ; MESSAGE ALREADY SENT CALL SENDPACKET KNOSEND: ; ; IF CTS HAS BEEN DROPPED, SEE IF OK TO RAISE AGAIN ; TEST VMSR[BX],10H JNZ KCTSOK CALL CHECKCTS KCTSOK: RET DISCARDIT: CALL GETONECHAR JMP KNOSEND ; CHECK FOR CTS CHANGE KDROPCTS: CTRL CTS,OFF RET KRAISECTS: CTRL CTS,ON RET ENDIF IFDEF MSC ; ; INTERRUPT HANDLERS FOR MSC ASYNC PORT ; PUBLIC MSCTNCBG ; IF 0 GOTTNCCHAR: ; ; CHARACTER AVAILABLE INTERRUPT ; IN AL,(SST) TEST AL,40H JZ NOBREAK ; MOV BREAKING,1 ; BREAK DETECTED RET NOBREAK: CMP BREAKING,1 JNE NOTBREAKEND ; ; END OF BREAK ; MOV BREAKING,0 CALL SETCOMMANDMODE IN AL,SRB ; DISCARD NULL RET NOTBREAKEND: TEST AL,01110000B ; ERROR BITS JZ NOERROR MOV AL,00110101B OUT (SCM),AL ; RESET ERROR RET NOERROR: IN AL,(SRB) CALL SENDCHARSUPPORT RET TNCSENDCHAR: ; ; CHARACTER SEND INTERRUPT - JUST TURN OFF FOR NOW ; MOV AL,10B OUT SIMK,AL ; MASK TX INT RET ENDIF MSCTNCBG: ; ; SEE IF ANYTHING RECEIVED ; IN AL,(SCC0CMD) TEST AL,RXRDY JZ MSCNORX IN AL,(SCC0) CALL SENDCHARSUPPORT MSCNORX: ; ; ; SEND ON ASYNC IF ANYTHING AVAILABLE ; CMP RXCOUNT[BX],0 JE KANTTNCRET ; NOWT THERE CMP ASYNCMODE,'T' JNE DISCARDIT ; NOT IN TERMINAL MODE IN AL,(SCC0CMD) TEST AL,TXRDY ; JZ KANTTNCRET ; ; CHECK CTS TO SEE IF TERMINAL WANTS US TO STOP SENDING ; ; TEST AL,20H ; JZ KANTTNCRET ; CTS LOW CALL GETONECHAR OUT (SCC0),AL KANTTNCRET: ; ; LOOK FOR TRANSPARENT MODE SEND ; CMP AUTOSENDFLAG[BX],1 JNE KNOSEND MOV AUTOSENDFLAG[BX],0 CMP KBBUFFER[BX],0 JE KNOSEND ; MESSAGE ALREADY SENT CALL SENDPACKET KNOSEND: ; ; IF CTS HAS BEEN DROPPED, SEE IF OK TO RAISE AGAIN ; TEST VMSR[BX],10H JNZ KCTSOK CALL CHECKCTS KCTSOK: RET DISCARDIT: CALL GETONECHAR JMP KNOSEND ; CHECK FOR CTS CHANGE KDROPCTS: ; CTRL CTS,OFF RET KRAISECTS: ; CTRL CTS,ON RET ENDIF TNCTIMERPROC: ; ; CALLED AT 3HZ ; IF TNC2 ; CHECK FOR TRANSPARENT MODE SEND TIMOUT ; MOV BX,TNCTABLE MOV CX,NUMBEROFSTREAMS JCXZ TIMRET TIM000: ; TEST MODEFLAG[BX],TRANS ; JZ TIM100 ; NOT TRANS MODE CMP TRANSTIMER[BX],0 JE TIM100 ; NOTHING DOING DEC TRANSTIMER[BX] JNZ TIM100 ; STILL OK ; CMP KBBUFFER[BX],0 JE TIM100 ; NO MESSAGE TO SEND ; MOV AUTOSENDFLAG[BX],1 ; CANT DO IT HERE - WAIT TILL NEXT INT 14 TIM100: ADD BX,TYPE TNCDATA LOOP TIM000 TIMRET: ENDIF IFDEF PCSWITCH ; ; CHECK LENGTH OF HOST MODE RAW DATA QUEUES ; MOV CX,BPQHOSTSTREAMS MOV BX,OFFSET BPQHOSTVECTOR ; ; VECTOR FORMAT IS: ; ; 0-1 2 BYTES - ADDRESS OF SESSION ENTRY ; 2 1 BYTE - STATE CHANGE FLAGS ; 3 1 BYTE - APPLICATION MASK ; 4 1 BYTE - APPLICATION FLAGS - TOP BIT ENABLES MONITORING ; 5-6 2 BYTES - RAW FRAME QUEUE ; BPQTRACELOOP: TEST BYTE PTR 4[BX],80H JZ NOTRACE ; NOT ENABLED ; CMP WORD PTR 5[BX],0 JE NOTRACE ; NONE QUEUED PUSH BX ADD BX,5 ; TO HEADER CALL COUNT_Q POP BX CMP AL,10 ; MAX LENGTH JB NOTRACE LEA SI,5[BX] CALL Q_REM JZ NOTRACE ; WOT? CALL RELBUFF NOTRACE: ADD BX,VECTORLENGTH LOOP BPQTRACELOOP ENDIF RET IF TNC2 CONSOLESEND: PUSH DI MOV CX,MSGLENGTH[DI] LEA SI,L3PID+1[DI] SUB CX,6 ; HEADER LENGTH JZ SENDCONSEND ; ZERO LENGTH TEXT CMP CX,257 JB HOSTTEST MOV CX,256 ; PROTECTION HOSTTEST: SENDCONS00: LODSB CALL PUTCHARINBUFFER LOOP SENDCONS00 SENDCONSEND: POP DI CALL RELBUFF RET KEYSUPPORT: CMP KBBUFFER[BX],0 JNE KEYB05 ; BUFFER ALREADY ALLOCATED ; ; GET A BUFFER ; WAITFORBUFFER: CMP QCOUNT,20 ; PLENTY FREE? JAE ENOUGH ; YES PUSH AX CALL RELEASE_TIMESLICE ; WAIT FOR MORE TO BE RELEASED POP AX JMP WAITFORBUFFER ENOUGH: PUSH AX CALL GETBUFF POP AX JNZ KEYSUPP00 RET ; WOT NO BUFFERS!! KEYSUPP00: MOV KBBUFFER[BX],DI ; SAVE ADDR MOV L3PID[DI],0F0H LEA DI,L3PID+1[DI] MOV CURSOR[BX],DI ; SET MESSAGE START MOV MSGLEN[BX],0 KEYB05: TEST MODEFLAG[BX],COMMAND JNZ KEYB06C ; COMMAND MODE - SKIP TRANS TEST TEST MODEFLAG[BX],TRANS JNZ KEYB06T ; TRANS MODE ; ; CONV MODE - SEE IF CPACTIME ON ; CMP CPACTIME[BX],0 JE KEYB06 ; NOT CPACTIME MOV AH,TRANSDELAY MOV TRANSTIMER[BX],AH ; REPRIME SEND TIMER JMP SHORT KEYB06 ; PROCESS CHAR KEYB06T: MOV AH,TRANSDELAY MOV TRANSTIMER[BX],AH JMP SHORT KBNORM ; TRANSPARENT MODE KEYB06: ; ; STILL JUST CONV MODE ; CMP AL,SENDPAC[BX] JNE NOTSENDPAC ; ; SEND PACKET CHAR - SHOUD WE SEND IT? ; MOV TRANSTIMER[BX],0 CMP CRFLAG[BX],1 JE KBCR_JMP ; SEND IT JMP SENDPACKET KBCR_JMP: JMP KBCR NOTSENDPAC: KEYB06C: ; ; COMMAND OR CONV MODE ; CMP AL,20H JB KBCTRL KBNORM: CMP MSGLEN[BX],256 JA TOOLONG ; PROTECT BUFFER ; INC MSGLEN[BX] MOV DI,CURSOR[BX] STOSB MOV CURSOR[BX],DI TOOLONG: TEST ECHOFLAG[BX],0FFH JZ NOECHO CALL KBECHO NOECHO: MOV AL,TPACLEN[BX] CMP BYTE PTR MSGLEN[BX],AL JNE NOSEND ; ; DONT APPLY PACLEN IN COMMAND MODE ; TEST MODEFLAG[BX],COMMAND JNZ NOSEND JMP SENDPACKET NOSEND: RET KBCTRL: CMP LFIGNORE[BX],0 JE KBCTRL00 ; ; IF LF, IGNORE IT ; CMP AL,0AH JE NOSEND ; IGNORE RET KBCTRL00: CMP AL,8 JE KBBSPACE CMP AL,1AH ; CTRL/Z JE KBNORM ; FOR MBX TERMINATOR TEST MODEFLAG[BX],CONV JNZ CTRLREST ; ; COMMAND MODE ; CMP AL,2 JNE NOTID JMP SENDIDMSG NOTID: CMP AL,5 JNE NOTNODES JMP SENDNODES NOTNODES: CMP AL,0DH JE KBCR JMP SHORT CTRLREST ; ; CONV MODE ; CTRLREST: CMP AL,3 JE KBESCAPE ; RETURN TO COMMAND MODE ; CMP AL,14H ; CTRL/T JNE IGNORECTRL XOR TRACEFLAG[BX],1 RET IGNORECTRL: JMP KBNORM KBESCAPE: CALL SETCOMMANDMODE JMP KBRET ; EXIT SETCOMMANDMODE: CMP MSGLEN[BX],0 JE SETCOMM00 CALL SENDPACKET ; PROCESS WAITING DATA SETCOMM00: OR MODEFLAG[BX],COMMAND ; BACK TO COMMAND MODE AND MODEFLAG[BX],NOT (CONV+TRANS) MOV TRANSTIMER[BX],0 ; CANCEL TRANS MODE SEND TIMER MOV AUTOSENDFLAG[BX],0 ; IN CASE ALREADY SET MOV SI,OFFSET CMDMSG MOV CX,4 CALL SENDREPLY CALL KBRET RET KBBSPACE: CMP MSGLEN[BX],0 JE KBBS00 DEC MSGLEN[BX] DEC CURSOR[BX] TEST ECHOFLAG[BX],0FFH JZ KBBS00 CALL KBECHO KBBS00: RET KBCR: CALL KBNORM ; PUT CR IN BUFFER SENDPACKET: MOV DI,KBBUFFER[BX] MOV CX,CURSOR[BX] SUB CX,DI ; MESSAGE LENGTH MOV MSGLENGTH[DI],CX ; ; SEE IF COMMAND STATE ; TEST MODEFLAG[BX],COMMAND JZ NOTCOMMAND JMP TNCCOMMAND ; COMMAND TO TNC NOTCOMMAND: ; ; IF CONNECTED, SEND TO L4 (COMMAND HANDLER OR DATA), ; OTHERWISE SEND AS AN UNPROTO FRAME (TO ALL PORTS??) ; TEST VMSR[BX],80H ; CONNECTED? JNZ SENDTOL4 ; ; SEND BUFFER AS AN UNPROTO FRAME ; MOV SI,DI ; MESSAGE TO SI CALL SENDUIMESSAGE JMP KBRET ; RESET MESSAGE BUFFER POINTERS SENDTOL4: MOV DI,KBBUFFER[BX] MOV KBBUFFER[BX],0 ; CLEAR BUFFER ALLOCATED MOV MSGLEN[BX],0 ; ; SEE IF SESSION ; CALL CHECKSESSION ; GET SESSION IN SI CMP SI,0 JE KBCR10 ; NO SESSION?? ; ; SEE IF FAR SESSION BUSY ; PUSH SI ; SAVE SESSION TESTFORBUSY: ; TEST VMSR[BX],00010000B ; CHECK CTS JNZ NOTBUSY IFDEF PCSWITCH ; MUSTNT STOP IN DE VERSION CALL RELEASE_TIMESLICE CALL CHECKCTS JMP TESTFORBUSY ENDIF ; NOTBUSY: POP SI LEA SI,L4RX_Q[SI] CALL Q_ADD ; PUT ON PORT RX QUEUE CALL CHECKCTS ; SEE IF NOW BUSY RET KBCR10: ; ; NO FREE SESSIONS - ?? ERROR MSG ; CALL RELBUFF MOV KBBUFFER[BX],0 RET CHECKSESSION: MOV SI,KBSESSION[BX] CMP SI,0 JNE KBCR00 ; OK ; ; SET UP A SESSION FOR THE CONSOLE ; PUSH BX PUSH DI CALL SETUPCONSOLESESSION POP DI ; MOV SI,BX POP BX ; ; SI=SESSION, BX=TNC ; CMP SI,0 JE KBCR00 ; NO SESSION?? MOV KBSESSION[BX],SI MOV AL,TPACLEN[BX] MOV SESSPACLEN[SI],AL ; COPY PACLEN TO SESSION LEVEL KBCR00: RET KBECHO: CALL PUTCHARINBUFFER ; RET TNCCOMMAND: ; ; PROCESS COMMAND TO TNC CODE ; LEA SI,L3PID+1[DI] MOV DI,SI PUSH SI ; ; CONVERT TO UPPER CASE ; MOV CX,200 ; IN CASE GARBAGE!! TNCUCLOOP: LODSB CMP AL,0DH JE TNCUCEND CMP AL,61H JB TNCUCOK CMP AL,7AH JA TNCUCOK SUB AL,20H TNCUCOK: STOSB LOOP TNCUCLOOP ; TNCUCEND: MOV CMDENDADDR,SI ; SAVE REAL END OF COMMAND MOV AL,20H MOV CX,40 REP STOSB ; PUT A FEW SPACES ON END FOR DECODE ROUTINES POP SI CALL SCAN CMP BYTE PTR [SI],20H JE NULLCMD ; BLANK LINE MOV DI,OFFSET COMMANDLIST MOV CX,NUMBEROFCOMMANDS COMMANDLOOP: PUSH SI PUSH DI PUSH CX MOV CL,8[DI] ; MIN LENGTH REP CMPSB JE COMMANDFOUND POP CX POP DI POP SI ADD DI,TYPE CMDX LOOP COMMANDLOOP TNCDUFF: MOV SI,OFFSET WHATMSG MOV CX,4 CALL SENDREPLY NULLCMD: JMP SENDOK COMMANDFOUND: CMP BYTE PTR [SI],0DH JE ENDOFCOMMAND CMP BYTE PTR [SI],' ' JE ENDOFCOMMAND CMPSB JE COMMANDFOUND ; LOOP TILL ALL COMPARED OR END ; ; END OF STRING WRONG ; POP CX POP DI POP SI JMP TNCDUFF ENDOFCOMMAND: POP CX POP DI POP AX ; TO CLEAR STACK CALL SCAN JMP WORD PTR 9[DI] ; ENTER COMMAND PROCESSOR - ; SI POINTS TO CHAR FOLLOWING COMMAND ENDIF SCAN: MOV CX,10 ; DONT LOOK TOO FAR! SCAN1: CMP BYTE PTR [SI],20H JNE SCANRET INC SI LOOP SCAN1 XOR AL,AL ; RETURN Z SCANRET: RET ; IF TNC2 UNPROTOCMD: ; ; EXTRACT CALLSIGN STRING ; CMP BYTE PTR [SI],20H JE UNPROTODIS CMP BYTE PTR [SI],'*' JE CLEARUNPROTO CALL DECODECALLSTRING ; CONVERT TO AX25 FORMAT JZ UNPROTOOK JMP TNCDUFF CLEARUNPROTO: LEA DI,UNPROTO[BX] MOV AL,0 MOV CX,63 REP STOSB ; COPY IN UNPROTODIS: MOV AL,1 CALL DISPLAYUNPROTO ; DISPLAY CURRENT SETTING JMP SENDOK UNPROTOOK: PUSH SI MOV AL,0 CALL DISPLAYUNPROTO ; DISPLAY OLD STRRING POP SI LEA DI,UNPROTO[BX] MOV CX,63 REP MOVSB ; COPY IN JMP SENDOK CONMODE: JMP KBRET DISPLAYUNPROTO: ; PUSH AX MOV SI,OFFSET UNPROT MOV CX,8 CALL PUTSTRINGINBUFFER MOV SI,OFFSET WAS ; DISPLAY 'was' MOV CX,5 POP AX OR AL,AL JZ DISPU00 ; NO MOV CX,1 ; LEAVE OUT 'WAS' DISPU00: CALL PUTSTRINGINBUFFER LEA SI,UNPROTO[BX] CMP BYTE PTR [SI],40H JBE DISPUPRET CALL CONVFROMAX25 PUSH SI MOV SI,OFFSET NORMCALL CALL PUTSTRINGINBUFFER POP SI CMP BYTE PTR [SI],0 JE DISPUPRET PUSH SI MOV SI,OFFSET VIA MOV CX,5 CALL PUTSTRINGINBUFFER POP SI DISPUPLOOP: CALL CONVFROMAX25 PUSH SI MOV SI,OFFSET NORMCALL INC CX CALL PUTSTRINGINBUFFER POP SI CMP BYTE PTR [SI],0 JNE DISPUPLOOP DISPUPRET: MOV AL,0DH CALL PUTCHARINBUFFER RET TNCCONV: OR MODEFLAG[BX],CONV AND MODEFLAG[BX],NOT (COMMAND+TRANS) JMP KBRET TNCTRANS: ; ; MAKE PRETTY SURE THIS ISNT A BIT OF STRAY DATA ; CALL SCAN JZ TRANSOK JMP TNCDUFF TRANSOK: OR MODEFLAG[BX],TRANS AND MODEFLAG[BX],NOT (COMMAND+CONV) JMP KBRET TNCNODE: ; ; CONNECT TO NODE ; OR MODEFLAG[BX],CONV ; INTO CONVERSE MODE AND MODEFLAG[BX],NOT (COMMAND+TRANS) OR VMSR[BX],88H ; SET CONNECTED JMP KBRET BTEXT: ; CMP BYTE PTR [SI],20H JE BTDIS ; PUSH SI MOV AL,0 CALL DISPLAYBT ; DISPLAY OLD STRING POP SI MOV DI,OFFSET BTEXTFLD MOV CX,255 BTLOOP: LODSB STOSB CMP SI,CMDENDADDR ; END? JE BTEND LOOP BTLOOP BTEND: XOR AL,AL STOSB ; NULL ON END ; ; SET UP TO SEND IT AS A UI ; MOV CX,DI MOV SI,OFFSET BTHDDR SUB CX,SI MOV MSGLENGTH[SI],CX JMP SENDOK BTDIS: MOV AL,1 CALL DISPLAYBT ; DISPLAY CURRENT SETTING JMP SENDOK DISPLAYBT: ; PUSH AX MOV SI,OFFSET BTCMD MOV CX,8 CALL PUTSTRINGINBUFFER MOV SI,OFFSET WAS ; DISPLAY 'was' MOV CX,5 POP AX OR AL,AL JZ DISPBT00 ; NO MOV CX,1 ; LEAVE OUT 'WAS' DISPBT00: CALL PUTSTRINGINBUFFER MOV SI,OFFSET BTEXTFLD DISPBT10: LODSB OR AL,AL JZ DISPBT20 CALL PUTCHARINBUFFER JMP DISPBT10 DISPBT20: MOV AL,0DH CALL PUTCHARINBUFFER RET VALHEX: MOV HEXFLAG,1 ; DISPLAY IN HEX VALUE: ; ; PROCESS COMMANDS WITH VALUE PARAMS ; CMP BYTE PTR [SI],20H JBE DISPVAL ; DISPLAY ONLY CALL GETVALUE ; GET NUMBER, UP TO SPACE , CR OR OFFH JC BADVALUE ; INVALID DIGITS VALOK: MOV CL,0 CALL KEYDISP ; DISPLAY KEYWORD WAS MOV SI,CMDFLAG[DI] ; ADDR OF FLAG MOV AH,[SI][BX] ; GET OLD VALUE MOV AL,NEWVALUE MOV [SI][BX],AL ; SET FLAG MOV AL,AH ; DISPLAY OLD JMP VALDISP BADVALUE: MOV SI,OFFSET BADMSG ERRCOM: CALL NORMSTR JMP SENDOK DISPVAL: MOV CX,1 CALL KEYDISP DISPV00: MOV SI,CMDFLAG[DI] ; ADDR OF FLAG MOV AL,[SI][BX] ; GET VALUE VALDISP: MOV WORD PTR NUMBER+1,2020H ; CLEAR OUT IN CASE LESS THAN 3 DIGITS MOV NUMBER+3,20H MOV DI,OFFSET NUMBER CMP HEXFLAG,1 JE DISPHEX CALL CONV_DIGITS JMP SHORT DISPCOM DISPHEX: CALL CONVHEX DISPCOM: MOV SI,OFFSET NUMBER MOV CX,5 CALL PUTSTRINGINBUFFER JMP SENDOK KEYDISP: PUSH CX MOV SI,DI MOV CX,8 ; MAX LENGTH CALL PUTSTRINGINBUFFER MOV SI,OFFSET WAS ; DISPLAY 'was' POP CX OR CL,CL MOV CX,5 JZ KEYDISP12 ; NO MOV CX,1 ; LEAVE OUT 'WAS' KEYDISP12: CALL PUTSTRINGINBUFFER RET CONVHEX: MOV BYTE PTR NUMBER,'$' INC DI ENDIF B2HEX: PUSH AX SHR AL,1 SHR AL,1 SHR AL,1 SHR AL,1 CALL B1HEX POP AX B1HEX: AND AL,0FH CMP AL,10 JB B1HEX2 ADD AL,7 B1HEX2: ADD AL,30H STOSB RET PUBLIC GETVALUEF GETVALUEF: CALL SCAN CALL GETVALUE MOV AL,NEWVALUE RETF GETVALUE: ; ; EXTRACT NUMBER (HEX OR DECIMAL) FROM INPUT STRING ; MOV NEWVALUE,0 LODSB CMP AL,'$' ; HEX? JE DECODEHEX DEC SI VALLOOP: LODSB CMP AL,' ' JE ENDVALUE CMP AL,0FFH JE ENDVALUE CMP AL,',' JE ENDVALUE ; ; ANOTHER DIGIT - MULTIPLY BY 10 ; MOV AL,NEWVALUE CMP AL,26 JNC DUFFVALUE ; WILL OVERFLOW IF MULTIPLIED MUL D10 MOV NEWVALUE,AL MOV AL,-1[SI] SUB al,'0' JC DUFFVALUE CMP AL,10 JNC DUFFVALUE ADD NEWVALUE,AL JC DUFFVALUE JMP VALLOOP DECODEHEX: HEXLOOP: LODSB CMP AL,' ' JE ENDVALUE CMP AL,0FFH JE ENDVALUE CMP AL,',' JE ENDVALUE ; ; ANOTHER DIGIT - MULTIPLY BY 16 ; MOV AL,NEWVALUE MUL D16 MOV NEWVALUE,AL MOV AL,-1[SI] SUB al,'0' JC DUFFVALUE CMP AL,10 JC HEXOK SUB AL,7 CMP AL,10 JC DUFFVALUE CMP AL,16 JNC DUFFVALUE HEXOK: ADD NEWVALUE,AL JMP HEXLOOP ENDVALUE: CLC RET DUFFVALUE: STC RET IF TNC2 ONOFF: ; ; PROCESS COMMANDS WITH ON/OFF PARAM ; CMP BYTE PTR [SI],20H JBE CMDDISP LODSB CMP AL,'Y' JE CMDON CMP AL,'N' JE CMDOFF ; TO HANDLE YES/NO LODSB CMP AL,'N' JE CMDON CMP AL,'F' JE CMDOFF CMP AL,' ' JE CMDDISP ; DISPLAY CURRENT VALUE JMP TNCDUFF CMDON: MOV AL,1 JMP SHORT ONOFF00 CMDOFF: MOV AL,0 ONOFF00: MOV SI,CMDFLAG[DI] ; ADDR OF FLAG MOV AH,[SI][BX] ; GET OLD VALUE MOV [SI][BX],AL ; SET FLAG MOV AL,0 JMP CMDDISP00 ; DISPLAY CMDDISP: MOV SI,CMDFLAG[DI] ; ADDR OF FLAG MOV AH,[SI][BX] ; GET OLD VALUE MOV AL,1 ; DISPLAY FLAG CMDDISP00: PUSH AX MOV SI,DI MOV CX,8 ; MAX LENGTH CALL PUTSTRINGINBUFFER MOV SI,OFFSET WAS ; DISPLAY 'was' MOV CX,5 POP AX PUSH AX ; DISPLAY ONLY? OR AL,AL JZ CMDDISP12 ; NO MOV CX,1 ; LEAVE OUT 'WAS' CMDDISP12: CALL PUTSTRINGINBUFFER POP AX MOV SI,OFFSET OFF CMP AH,0 JE WASOFF MOV SI,OFFSET ON WASOFF: MOV CX,4 CALL PUTSTRINGINBUFFER JMP SENDOK TNCCONNECT: CMP BYTE PTR [SI],20H ; ANY PARAM? JBE TNCCSTATE ; NO, SO REQUEST FOR CURRENT STATE ; ; CONNECT, BUT NOT TO SWITCH - CONNECT TO NODE, THAN PASS TO IT FOR ; PROCESSING ; OR MODEFLAG[BX],CONV ; INTO CONVERSE MODE AND MODEFLAG[BX],NOT (COMMAND+TRANS) OR VMSR[BX],88H ; SET CONNECTED JMP SENDPACKET ; LOOP BACK - WILL NOW GO TO NODE TNCCSTATE: MOV SI,OFFSET LNKSTATEMSG ; LINK STATE IS MOV CX,15 CALL SENDREPLY TEST VMSR[BX],80H JZ TNCST10 ; NOT CONNECTED MOV SI,KBSESSION[BX] CMP SI,0 JE TNCST10 ; NO SESSION?? PUSH SI MOV SI,OFFSET CONNECTEDMSG MOV CX,13 CALL SENDREPLY POP SI MOV SI,L4CROSSLINK[SI] CMP SI,0 JNE TNCST05 ; CONNECTED PAST SWITCH ; ; CONNECTED TO SWITCH ; MOV SI,OFFSET SWITCH MOV CX,6 JMP SHORT TNCST06 TNCST05: CALL CONVFROMAX25 ; CONVERT CALL TO NORMAL MOV SI,OFFSET NORMCALL TNCST06: CALL SENDREPLY MOV AL,0DH CALL PUTCHARINBUFFER JMP KBRET TNCST10: MOV SI,OFFSET DISCONNMSG+5 MOV CX,13 CALL SENDREPLY JMP KBRET CSWITCH: ; ; CONNECT TO NODE (SPECIAL FOR BBS FORWARDING SYSTEM) ; MOV SI,OFFSET CMDMSG MOV CX,4 CALL SENDREPLY MOV SI,OFFSET CONMSG MOV CX,25 CALL SENDREPLY ; CALL DOCONMODECHANGE ; SET CONNECTED AND CHANGE MODE IF NEEDED JMP KBRET DOCONMODECHANGE: OR VMSR[BX],88H ; SET CONNECTED ; ; IF NOMODE IS ON LEAVE IN TNC COMMAND MODE, ELSE PUT INTO CONV MODE ; (MAY NEED TO IMPLEMENT CONMODE SOMETIME) ; CMP NOMODE[BX],0 JNE CSWITCH00 ; OR MODEFLAG[BX],CONV ; INTO CONVERSE MODE AND MODEFLAG[BX],NOT (COMMAND+TRANS) CSWITCH00: RET TNCDISC: PUSH BX MOV BX,KBSESSION[BX] CMP BX,0 JE KBD00 ; NO SESSION CALL CLOSESESSIONPARTNER KBD00: POP BX ; MOV KBSESSION[BX],0 AND VMSR[BX],7FH ; DROP DCD OR VMSR[BX],08H ; DELTA DCD CALL SENDOK ; SEND CMD: SENDSTARDISC: MOV SI,OFFSET DISCONNMSG MOV CX,18 CALL SENDREPLY RET SENDOK: MOV SI,OFFSET CMDMSG MOV CX,4 CALL SENDREPLY KBRET: MOV DI,KBBUFFER[BX] LEA DI,L3PID+1[DI] MOV CURSOR[BX],DI ; RESET MESSAGE START MOV MSGLEN[BX],0 RET SENDREPLY: LODSB CALL PUTCHARINBUFFER LOOP SENDREPLY RET TNCRELEASE: ; ; DISCONNECT TNC, BUT LEAVE SESSION WITH NODE ; CALL DORELEASE CALL SENDOK RET DORELEASE: PUSH BX MOV BX,KBSESSION[BX] CMP BX,0 JE KBDX00 ; NO SESSION PUSH BX ; KB SESSION MOV BX,L4CROSSLINK[BX] ; TO USERS SESSION CMP BX,0 JE NOXLINK ; ?? MOV L4CROSSLINK[BX],0 ; RETURN TO COMMAND HANDER CALL RETURNEDTONODE ; TELL USER NOXLINK: POP BX CALL CLEARSESSIONENTRY ; RELEASE KB SESSION KBDX00: POP BX ; MOV KBSESSION[BX],0 AND VMSR[BX],7FH ; DROP DCD OR VMSR[BX],08H ; DELTA DCD RET PUTSTRINGINBUFFER: LODSB CALL PUTCHARINBUFFER LOOP PUTSTRINGINBUFFER RET PUBLIC SEND_CONNECTED SEND_CONNECTED: ; ; SEND TAPR-STYLE *** CONNECTED TO CURRENT PORT ; ; TEST MODEFLAG[BX],TRANS JNZ SENDCON10 ; NOT IF TRANSPARENT MOV SI,KBSESSION[BX] CMP SI,0 JE SENDCON10 ; NO SESSION?? MOV SI,L4CROSSLINK[SI] CMP SI,0 JE SENDCON10 ; NO TARGET?? ; CALL CONVFROMAX25 ; CONVERT CALL TO NORMAL PUSH CX MOV SI,OFFSET CONMSG MOV CX,18 CALL PUTSTRINGINBUFFER MOV SI,OFFSET NORMCALL POP CX CALL PUTSTRINGINBUFFER MOV AL,0DH CALL PUTCHARINBUFFER SENDCON10: RET ; DONT BOTHER! ENDIF SENDIDMSG: PUSH BX MOV BX,PORTTABLE MOV CX,NUMBEROFPORTS SENDID10: MOV SI,IDMSG PUSH CX CALL SENDIDMSG00 POP CX MOV BX,PORTPOINTER[BX] LOOP SENDID10 POP BX RET IF TNC2 SENDNODES: PUSH BX CALL SENDNODESMSG POP BX RET ENDIF SENDIDMSG00: PUSH SI ; SAVE MESSAGE ADDR CALL GETBUFF POP SI JZ SENDIDRET PUSH DI MOV CX,3[SI] REP MOVSB POP DI MOV AL,PORTNUMBER[BX] MOV MSGPORT[DI],AL ; ; IF PORT HAS A CALLSIGN DEFINED, SEND THAT INSTEAD ; CMP PORTCALL[BX],20H JBE NOPORTCALL PUSH SI PUSH DI LEA SI,PORTCALL[BX] LEA DI,12[DI] ; COPY TO ID MESSAGE MOV CX,7 REP MOVSB OR BYTE PTR -1[DI],1 ; SET END OF CALL BIT POP DI POP SI NOPORTCALL: MOV SI,OFFSET IDMSG_Q ; Q FOR SENDING LATER (AT INTERVALS) CALL Q_ADD SENDIDRET: RET SENDBTMSG: MOV SI,OFFSET BTHDDR SENDUIMESSAGE: MOV DX,PORTTABLE ; FIRST HDLC LINK MOV CX,NUMBEROFPORTS SENDUI10: PUSH SI ; MESSAGE PUSH CX CALL SENDUIMSG00 POP CX MOV SI,DX MOV DX,PORTPOINTER[SI] POP SI LOOP SENDUI10 RET SENDUIMSG00: PUSH SI ; SAVE MESSAGE ; IF TNC2 ; IF TNC HAS A DEFINED UNPROTO STRING, THEN USE IT, ELSE IF PORT HAS A ; DEFINED STRING USE THAT, ELSE IGNORE ; LEA SI,UNPROTO[BX] CMP BYTE PTR [SI],40H JA UNPROT_OK ; ; NO TNC STRING - TRY PORT ; ENDIF MOV SI,DX MOV SI,PORTUNPROTO[SI] CMP SI,0 JE SKIP_UI ; IGNORE UNPROT_OK: PUSH SI ; SAVE UNPROTO ADDR CALL GETBUFF POP SI JZ SKIP_UI ; NO BUFFERS MOV AX,DI ; BUFFER LEA DI,MSGDEST[DI] MOV CX,7 REP MOVSB OR BYTE PTR -1[DI],0C0H ; SET COMMAND BITS PUSH SI ; SAVE POSSIBLE DIGIS MOV SI,OFFSET BBSCALL MOV CX,7 REP MOVSB POP SI SENDUILOOP: CMP BYTE PTR [SI],0 JE SENDUIEND ; END OF DIGIS MOV CX,7 REP MOVSB JMP SENDUILOOP SENDUIEND: OR BYTE PTR -1[DI],1 ; SET LAST CALL MOV BYTE PTR [DI],3 ; UI INC DI POP SI ; MESSAGE MOV CX,MSGLENGTH[SI] ADD SI,5 SUB CX,5 REP MOVSB ; COPY IN MESSAGE MOV CX,DI MOV DI,AX ; BUFFER SUB CX,DI MOV MSGLENGTH[DI],CX PUSH BX MOV BX,DX ; PORT TABLE ENTRY MOV AL,PORTNUMBER[BX] MOV MSGPORT[DI],AL MOV SI,OFFSET IDMSG_Q ; Q FOR SENDING LATER (AT INTERVALS) CALL Q_ADD POP BX RET SKIP_UI: POP SI RET RELEASE_TIMESLICE: ; ; CALLED WHEN WAITING FOR SOMETHING TO HAPPEN - RELEASE REST OF ; TIME SLICE ; IFDEF PCSWITCH CMP DESQVIEW,0 JE NO_DV MOV AX,1000H ; DV RELEASE TIMESLOT INT 15H STI ; XT BIOS BUG ENDIF NO_DV: RET ; IF TNC2 ; IFDEF PCSWITCH ; ; COMBIOS EMULATION CODE ; ; THE SYSTEM MAINTAINS VIRTUAL MSR AND LSR REGS FOR EACH PORT ; ; THE MSR BITS SUPPORTED ARE DCD=CONNECTED ; CTS=NOT BUSY ; ; AN ATTEMPT IS ALSO MADE TO MAINTAIN DELTA BITS ; ; BIT 7 - Receive Line Signal Detect (DCD) ; 6 - Ring Indicator ; 5 - Data Set Ready ; 4 - Clear To Send ; 3 - Delta RLSD ( ie state has changed since last ; access) ; 2 - Trailing Edge Ring Detect ; 1 - Delta DSR ; 0 - Delta CTS EVEN ; OLDINT14 DD 0 INT14: CLI ; DESQVIEW BUG PUSH DS PUSH BX PUSH CX MOV DS,CS:DATASEG MOV BX,TNCTABLE MOV CX,NUMBEROFSTREAMS JCXZ NO_STREAMS INT14LP1: CMP DL,BIOSPORT[BX] JE PORTFOUND ADD BX,TYPE TNCDATA LOOP INT14LP1 NO_STREAMS: POP CX POP BX POP DS JMP DWORD PTR CS:OLDINT14 RETURNLOADEDFLAG: ; ; RETURN 'LOADED' FLAG ; POP BX POP DS ; CLEAR STACK MOV AX,0AA55H MOV BX,AX ; FOR YFB IRET NODECOMMANDS: ; ; INT 14 WITH AH = 1F ; ; NODE-SPECIFIC COMBIOS EXTENTIONS ; ; AL = 0 - RETURN VERSION AND NODE DS ; AL = 1 - RETURN ES:SI = CONNECTED CALL (IN AX25 FORM), OR SI=0 ZERO ; IF NOT CONNECTED. ALSO PORT IN AL IF L2 ; ; AL = 2 = RETURN UNACKED PACKETS ON CONNECTION (IN AH) ; ; AL = 10H RECONNECT USER TO NODE (SAME AS TNC RELEASE) ; ; ONLY DS,BX SAVED AT THIS POINT ; ; BX = TNC DATA ; CMP AL,0 JE GETVERSION CMP AL,1 JE GETCONNECTEDCALL CMP AL,2 JE GETUNACKED CMP AL,10H JE RELUSER JMP SHORT NODERET RELUSER: PUSH ES PUSH DS POP ES CALL DORELEASE POP ES JMP SHORT NODERET GETVERSION: MOV DH,MAJORVERSION MOV DL,MINORVERSION MOV AX,DS JMP SHORT NODERET GETUNACKED: PUSH ES PUSH DS POP ES ; ; SEE IF CROSS-SESION STILL BUSY ; MOV AH,0 MOV SI,KBSESSION[BX] ; GET SESSION IN SI CMP SI,0 JE UNACKRET ; NO SESSION ; ; SEE IF FAR SESSION BUSY ; PUSH BX MOV BX,SI ; CALL CHECKIFBUSY ; RETURNS FRAMES QUEUED IN AH ; POP BX ; TNC DATA ; ; AH IS FRAMES QUEUED ; UNACKRET: POP ES ; JMP SHORT NODERET GETCONNECTEDCALL: PUSH DS POP ES MOV SI,0 MOV AX,0 ; PORT NUMBER TEST VMSR[BX],80H JZ RETCALL10 ; NOT CONNECTED MOV SI,KBSESSION[BX] CMP SI,0 JE RETCALL10 MOV SI,L4CROSSLINK[SI] MOV AH,L4CIRCUITTYPE[SI] TEST AH,L2LINK ; NOT L2 JZ RETCALL10 ; ; L2 - GET PORT ; MOV BX,L4TARGET[SI] ; LINK ENTRY MOV AL,LINKPORT[BX] RETCALL10: NODERET: POP BX POP DS ; CLEAR STACK IRET PORTFOUND: ; POP CX AND AH,7FH ; MASK TO ALLOW TOP BIT TO BE SET CMP AH,1FH JE NODECOMMANDS ; CMP AH,4 JE RETURNLOADEDFLAG CLD ; ; BX POINTS TO TNC DATA AREA DS TO DATA, DS, BX ON STACK ; STI PUSH CX PUSH SI PUSH DI PUSH BP PUSH DX PUSH ES ; SAVE LAST IN CASE WE NEED TO RETURN NEW VALUE PUSH AX ; MOV ES,CS:DATASEG ; ; IF A TIMER SEND IS REQUIRED, DO IT HERE ; CMP AUTOSENDFLAG[BX],1 JNE INT14_00 MOV AUTOSENDFLAG[BX],0 CMP KBBUFFER[BX],0 JE INT14_00 ; MESSAGE ALREADY SENT PUSH CX PUSH DI CALL SENDPACKET POP DI POP CX INT14_00: POP AX OR AH,AH JNZ NOTINIT JMP RETURNSTATUS ; INIT NOTINIT: DEC AH JNZ NOTSEND JMP SENDCHAR ; SEND NOTSEND: DEC AH JZ GETCHAR ; RECEIVE DEC AH JZ L14A3 ; STATUS DEC AH ; INSTALLED CHECK TRAPPED ABOVE DEC AH JZ L14A9 ; DROP RTS DEC AH JZ L14AC ; RAISE RTS DEC AH JZ L14AF ; SEND BREAK DEC AH JZ NDREAD DEC AH JZ MBOPTIONS ; GET/SET OPTIONS DEC AH JNZ NOTWRITEBUFFER JMP WRITEBUFFER NOTWRITEBUFFER: DEC AH JZ READBUFFER_JMP JMP INT14EXIT READBUFFER_JMP: JMP READBUFFER GETCHAR: JMP GETCHARSUPPORT NDREAD: ; ; NON - DESTRUCTIVE READ ; MOV SI,GETPTR[BX] MOV AL,[SI] MOV AH,VLSR[BX] AND AH,0FEH ; MASK DAV BIT CMP RXCOUNT[BX],0 JZ NDNODATA OR AH,1 ; SET DAV IF BUFFER NOT EMPTY NDNODATA: JMP INT14EXIT MBOPTIONS: MOV AH,MBOPTIONBYTE MOV MBOPTIONBYTE,AL MOV AL,AH JMP INT14EXIT L14A3: JMP RETURNSTATUS L14A9: JMP DROPRTS L14AC: JMP RAISERTS L14AF: JMP SENDBREAK INT14EXIT: POP ES POP DX POP BP POP DI POP SI POP CX POP BX POP DS IRET ; SENDCHAR: CALL SENDCHARSUPPORT JMP SHORT RETURNSTATUS ENDIF SENDCHARSUPPORT: ; ; CALLED FROM SEND CHAR OR SEND BLOCK ; CALL KEYSUPPORT ; CHAR KEYED - BX IS SESSION RET IFDEF PCSWITCH WAITFORCHAR: CALL RELEASE_TIMESLICE GETCHARSUPPORT: CMP RXCOUNT[BX],0 JE WAITFORCHAR ; WAIT FOR CHAR CALL GETONECHAR GETAH: MOV AH,VLSR[BX] AND AH,0FEH ; MASK DAV BIT CMP RXCOUNT[BX],0 JZ L1579 OR AH,1 ; SET DAV IF BUFFER NOT EMPTY L1579: JMP INT14EXIT ENDIF GETONECHAR: MOV SI,GETPTR[BX] LODSB ; GET CHAR DEC RXCOUNT[BX] MOV DX,TNCBUFFLEN ADD DX,BX CMP SI,DX ; BUFFER WRAP? JB L153C ; NO MOV SI,BX ; RESET TO START L153C: CMP RXCOUNT[BX],128 ; GETTING LOW? JNB L1560 ; NO TEST RTSFLAG[BX],1 ; RTS UP? JZ L1560 ; YES ; ; RTS HAD BEEN DROPPED TO STOP OTHER END SENDING - RAISE IT AGAIN ; AND RTSFLAG[BX],0FEH L1560: MOV GETPTR[BX],SI RET IFDEF PCSWITCH RETURNSTATUS: ; ; GET STATUS - AH = LSR, AL = MODEM STATUS ; ; IF CTS IS LOW (MEANING CROSS SESSION IS BUSY) ; CHECK IF STILL BUSY ; TEST VMSR[BX],10H JNZ CTSOK CALL CHECKCTS CTSOK: CALL GETSTATUS JMP INT14EXIT GETSTATUS: ; ; GET STATUS - AH = LSR, AL = MODEM STATUS ; MOV AL,VLSR[BX] AND AL,0FEH CMP RXCOUNT[BX],0 JZ L1599 ; ; IF FLOW ON, AND CHARS IN KB BUFFER, DONT REPORT DATA AVAIL ; TEST FLOWFLAG[BX],1 JZ DATAAVAIL ; FLOW OFF CMP MSGLEN[BX],0 JNE L1599 ; SOMETHING KEYED DATAAVAIL: OR AL,1 ; SET DATA AVAIL L1599: MOV AH,AL MOV AL,VMSR[BX] AND VMSR[BX],0F0H ; CLEAR DELTA BITS ; PUSH AX ; MOV AL,AH ; CALL HEXOUT ; POP AX RET DROPRTS: ; ; DROP DTR/RTS ; OR RTSFLAG[BX],1 JMP INT14EXIT RAISERTS: ; ; RAISE DTR/RTS ; AND RTSFLAG[BX],0FEH JMP INT14EXIT SENDBREAK: ; ; SET COMMAND MODE FLAG TO TNC CODE ; CALL SETCOMMANDMODE JMP INT14EXIT ENDIF PUTCHARINBUFFER: ; ; CALLED BY L4 CODE TO PASS DATA TO VIRTUAL TNC ; CMP RXCOUNT[BX],TNCBUFFLEN JB STILLOK ; ; OVERRUN - LOSE IT ; OR VLSR[BX],2 ; SET OVERRUN ERROR RET STILLOK: PUSH DI AND VLSR[BX],NOT 2 ; CLEAR OVERRRUN CLI MOV DI,PUTPTR[BX] MOV [DI],AL INC DI INC WORD PTR RXCOUNT[BX] MOV AX,TNCBUFFLEN ; BUFFER LENGTH ADD AX,BX ; END ADDR CMP DI,AX ; END OF BUFFER ADDR JB L1648 ; OK ; ; BUFFER WRAPAROUND ; MOV DI,BX ; POINT BACK TO START L1648: MOV PUTPTR[BX],DI STI CMP RXCOUNT[BX],TNCBUFFLEN-300 ; ALLOW FOR FULL PACKET JB L1667 ; ; BUFFER GETTING FULL - DROP RTS/DTR ; OR RTSFLAG[BX],1 ; SET BUSY L1667: POP DI RET CHECKCTS: ; ; SEE IF CROSS-SESION STILL BUSY ; MOV SI,KBSESSION[BX] ; GET SESSION IN SI CMP SI,0 JE CLEARCTS ; NO SESSION ; ; SEE IF FAR SESSION BUSY ; PUSH BX MOV BX,SI ; CALL CHECKIFBUSY ; RETURNS FRAMES QUEUED IN AH ; POP BX ; TNC DATA ; ; AH IS FRAMES QUEUED - SEE IF STILL TOO NEAR WINDOW ; INC AH CMP AH,L4WINDOW[SI] JB CLEARCTS TEST VMSR[BX],00010000B ; ALREADY OFF? JZ CTSNOCHANGE AND VMSR[BX],11101111B ; DROP CTS? OR VMSR[BX],00000001B ; DELTA BIT IFNDEF PCSWITCH CALL KDROPCTS ; STOP TERMINAL SENDING ENDIF CTSNOCHANGE: RET CLEARCTS: OR VMSR[BX],11H ; CTS AND DELTA CTS IFNDEF PCSWITCH CALL KRAISECTS ; ALLOW TERMINAL TO SEND ENDIF RET IFDEF PCSWITCH READBUFFER: MOV DX,0 ; CHARS RETURNED POP ES ; USERS SEG MOV AH,0DH ; END CHAR GETBLOOP: CMP RXCOUNT[BX],0 JE GETBEND ; NOTHING DOING PUSH DX CALL GETONECHAR POP DX STOSB INC DX ; CHARS RETURNED CMP AL,AH ; TERMINATOR JE GETBRET SKIPXX: MOV LASTCH,AL ; PREVIOUS LOOP GETBLOOP ; SEE IF MORE ; ; COUNT EXCEEDED ; GETBRET: GETBEND: MOV CX,DX ; CHARS RETURNED CALL GETSTATUS ; POP DX POP BP ADD SP,2 ; LEAVE DI POP SI ADD SP,2 ; LEAVE CX ; POP BX POP DS IRET ; WRITEBUFFER: POP ES PUSH ES WBLOOP: MOV AL,ES:[DI] INC DI PUSH ES PUSH DI PUSH CX MOV ES,CS:DATASEG CALL SENDCHARSUPPORT POP CX POP DI POP ES LOOP WBLOOP MOV DX,0 ; CHARS NOT SENT POP ES JMP GETBEND ENDIF ENDIF COUNT_QUEUED_FRAMES: ; ; COUNT NUMBER OF FRAMES QUEUED ON A SESSION (IN SI) ; RETURN TOTAL IN AL, NUMBER QUEUED ABOVE LINK IN AH (FOR HOST MODE TESTS) ; PUSH BX IF TNC2 TEST L4CIRCUITTYPE[SI],HOST+BPQHOST ELSE TEST L4CIRCUITTYPE[SI],BPQHOST ENDIF JZ CQF00 LEA BX,L4TX_Q[SI] CALL COUNT_Q MOV AH,AL POP BX RET CQF00: TEST L4CIRCUITTYPE[SI],SESSION JZ CQF10 ; MUST BE L2 SESSION ; ; L4 SESSION - GET NUMBER UNACKED, AND ADD NUMBER ON TX QUEUE ; LEA BX,L4TX_Q[SI] CALL COUNT_Q MOV AH,AL MOV AL,TXSEQNO[SI] SUB AL,L4WS[SI] ; LAST FRAME ACKED - GIVES NUMBER OUTSTANING ; ADD AL,AH POP BX RET CQF10: ; ; L2 CIRCUIT ; LEA BX,L4TX_Q[SI] CALL COUNT_Q MOV AH,AL ; NUMBER ON SESSION MOV BX,L4TARGET[SI] ; TO LINK CALL COUNT_AT_L2 POP BX RET COUNT_AT_L2: ; ; COUNTS FRAMES QUEUED ON AN L2 SESSION (IN BX) ; PUSH BX LEA BX,TX_Q[BX] CALL COUNT_Q ADD AH,AL ; NUMBER ON L2 TX QUEUE POP BX ; LINK ; ; COUNT FRAMES IN TSLOTS ; PUSH CX MOV AL,0 MOV CX,8 TSLOOP: CMP FRAMES[BX],0 ; FRAME THERE? JE TSLOOP2 ; NO INC AL TSLOOP2: ADD BX,2 LOOP TSLOOP POP CX ADD AL,AH ; TOTAL IN AL, NUMBER ABOVE LINK IN AH RET COUNT_Q: ; ; SEE HOW MANY BUFFERS ATTACHED TO Q HEADER IN BX ; XOR AL,AL COUNT_Q_LOOP: CMP WORD PTR [BX],0 JE COUNT_RET INC AL MOV BX,[BX] ; FOLLOW CHAIN JNZ COUNT_Q_LOOP ; JUST IN CASE! COUNT_RET: RET IFDEF PCSWITCH ; JUMPVECTOR LABEL WORD DW CHECKLOADED ; 0 DW SETAPPLFLAGS ; 1 DW SENDBPQFRAME ; 2 DW GETBPQFRAME ; 3 DW GETSTREAMSTATUS ; 4 DW CLEARSTREAMSTATUS ; 5 DW BPQCONDIS ; 6 DW GETBUFFERSTATUS ; 7 DW GETCONNECTIONINFO ; 8 DW BPQRETURN ; 9 - GETCALLS DW RAWTX ; 10 IE KISS TYPE DATA DW GETRAWFRAME ; 11 DW UPDATESWITCH ; 12 DW BPQALLOC ; 13 DW SENDNETFRAME ; 14 DW GETTIME ; 15 PUBLIC BPQHOSTPORT MARKER DB 'G8BPQ' ; MUST BE JUST BEFORE INT 7F ENTRY DB MAJORVERSION DB MINORVERSION BPQHOSTPORT: ; ; SPECIAL INTERFACE, MAINLY FOR EXTERNAL HOST MODE SUPPORT PROGS ; ; COMMANDS SUPPORTED ARE ; ; AH = 0 Get node/switch version number and description. On return ; AH='B',AL='P',BH='Q',BL=' ' ; DH = major version number and DL = minor version number. ; ; ; AH = 1 Set application mask to value in DL (or even DX if 16 ; applications are ever to be supported). ; ; Set application flag(s) to value in CL (or CX). ; whether user gets connected/disconnected messages issued ; by the node etc. ; ; ; AH = 2 Send frame in ES:SI (length CX) ; ; ; AH = 3 Receive frame into buffer at ES:DI, length of frame returned ; in CX. BX returns the number of outstanding frames still to ; be received (ie. after this one) or zero if no more frames ; (ie. this is last one). ; ; ; ; AH = 4 Get stream status. Returns: ; ; CX = 0 if stream disconnected or CX = 1 if stream connected ; DX = 0 if no change of state since last read, or DX = 1 if ; the connected/disconnected state has changed since ; last read (ie. delta-stream status). ; ; ; ; AH = 6 Session control. ; ; CX = 0 Conneect - APPLMASK in DL ; CX = 1 connect ; CX = 2 disconnect ; CX = 3 return user to node ; ; ; AH = 7 Get buffer counts for stream. Returns: ; ; AX = number of status change messages to be received ; BX = number of frames queued for receive ; CX = number of un-acked frames to be sent ; DX = number of buffers left in node ; SI = number of trace frames queued for receive ; ;AH = 8 Port control/information. Called with a stream number ; in AL returns: ; ; AL = Radio port on which channel is connected (or zero) ; AH = SESSION TYPE BITS ; BX = L2 paclen for the radio port ; CX = L2 maxframe for the radio port ; DX = L4 window size (if L4 circuit, or zero) ; ES:DI = CALLSIGN ;AH = 9 Fetch node/application callsign & alias. AL = application ; number: ; ; 0 = node ; 1 = BBS ; 2 = HOST ; 3 = SYSOP etc. etc. ; ; Returns string with alias & callsign or application name in ; user's buffer pointed to by ES:SI length CX. For example: ; ; "WORCS:G8TIC" or "TICPMS:G8TIC-10". ; ; ; AH = 10 Unproto transmit frame. Data pointed to by ES:SI, of ; length CX, is transmitted as a HDLC frame on the radio ; port (not stream) in AL. ; ; ; AH = 11 Get Trace (RAW Data) Frame into ES:DI, ; Length to CX, Timestamp to AX ; ; ; AH = 12 Update Switch. At the moment only Beacon Text may be updated ; DX = Function ; 1=update BT. ES:SI, Len CX = Text ; 2=kick off nodes broadcast ; ; AH = 13 Allocate/deallocate stream ; If AL=0, return first free stream ; If AL>0, CL=1, Allocate stream. If aleady allocated, ; return CX nonzero, else allocate, and return CX=0 ; If AL>0, CL=2, Release stream ; ; ; AH = 14 Internal Interface for IP Router ; ; Send frame - to NETROM L3 if DL=0 ; to L2 Session if DL<>0 ; ; ; AH = 15 Get interval timer IFDEF OS2 BPQHOSTAPI: PUBLIC BPQHOSTAPI ELSE PUSH DS MOV DS,CS:DATASEG STI ; ENDIF ; CALCULATE AND STACK ROUTINE ADDRESS ; MOV BL,AH AND BL,0FH ADD BL,BL ; COMMAND * 2 XOR BH,BH ADD BX,OFFSET JUMPVECTOR PUSH CS:[BX] ; ROUTINE TO STACK ; ; FUNCTIONS 11 AND 13 NEED A PORT. OTHERS ABOVE 9 DONT ; CMP AH,11 JE NEEDHOSTPORT CMP AH,13 JE NEEDHOSTPORT CMP AH,10 JAE HOSTNOPORT ; OR AL,AL JZ HOSTNOPORT ; BROADCAST STREAM NEEDHOSTPORT: ; ; CALCULATE PORT VECTOR ADDDRESS ; PUSH AX DEC AL CMP AL,64 JBE ALOK MOV AL,63 ; PROTECT US! ALOK: MUL BPQVECLENGTH ADD AX,OFFSET BPQHOSTVECTOR ; POINT TO VECTOR FOR STREAM IN AL XCHG AX,BX ; VECTOR TO BX GOTPORT: POP AX HOSTNOPORT: RET ; ENTER STACKED ROUTINE ; SENDNETFRAME: ; ; ATTACH FRAME TO OUTBOUND L3 QUEUES (ONLY USED FOR IP ROUTER) ; ; SI, CX INCLUDE THE L2 SESSION INFO (15 BYTES) ; CMP QCOUNT,20 ; PLENTY FREE? JNB NETOK JMP NETEXIT ; NO NETOK: PUSH SI ; USERS BUFFER CALL GETBUFF POP SI JZ NETEXIT ; WOT? PUSH ES ; SAVE PUSH ES POP DS ; MSG SEG TO DS MOV ES,CS:DATASEG PUSH DI ADD DI,5 PUSH SI ADD SI,15 ; REMOVE HEADER INFO SUB CX,15 IFDEF OS2 .386 AND EDI,0FFFFH AND ECX,0FFFFH DB 67H ; USE ESI/EDI .286 ENDIF REP MOVSB POP SI PUSH DI MOV DI,OFFSET COMPAREFIELD+7; IN CASE L2 MOV CX,7 IFDEF OS2 .386 AND EDI,0FFFFH AND ECX,0FFFFH DB 67H ; USE ESI/EDI .286 ENDIF REP MOVSB ; GET L2 INFO MOV DI,OFFSET COMPAREFIELD ; IN CASE L2 MOV CX,7 IFDEF OS2 .386 AND EDI,0FFFFH AND ECX,0FFFFH DB 67H ; USE ESI/EDI .286 ENDIF REP MOVSB ; GET L2 INFO POP CX ; END OF DATA POP DI ; START OF DATA SUB CX,DI ; LENGTH MOV DS,CS:DATASEG MOV MSGLENGTH[DI],CX ; ; SEE IF L2 OR L3 ; CMP DL,0 JNE NETSENDL2 PUSH DI LEA SI,L3DEST[DI] CALL FINDDESTINATION POP DI JZ L3OK NETCANTSEND: CALL RELBUFF JMP NETEXIT1 L3OK: LEA SI,DEST_Q[BX] CALL Q_ADD NETEXIT1: POP ES NETEXIT: IFDEF OS2 RET ELSE POP DS IRET ENDIF NETSENDL2: ; ; SEND FRAME TO L2 DEST, CREATING A LINK ENTRY IF NECESSARY ; PUSH DI ; SAVE BUFFER MOV COMPAREPORT,DL CALL GETPORTTABLEENTRY MOV BP,BX MOV DI,OFFSET COMPAREFIELD CALL FINDLINKXX ; GET LINK FOR THIS ADDRESS PAIR (IN BX) ; ; SET UP NEW SESSION (OR RESET EXISTING ONE) ; JZ GOTLINK CMP BX,0 JNE SENDL2_10 JMP NETCANTSEND ; TABLES FULL SENDL2_10: ; ; COPY ADDRESS INFO TO LINK TABLE ; LEA SI,COMPAREFIELD+7 LEA DI,LINKCALL[BX] MOV CX,7 REP MOVSB LEA SI,COMPAREFIELD LEA DI,OURCALL[BX] MOV CX,7 REP MOVSB ; MOV LINKPORT[BX],DL ; PUT IN PORT MOV AL,DS:PORTT1[BP] MOV L2TIME[BX],AL ; SET STANDARD TIMER VALUE MOV LINKTYPE[BX],2 ; DOWNLINK CALL GETPORTWINDOW MOV LINKWINDOW[BX],AL MOV L2STATE[BX],2 ; CONNECTING CALL SENDSABM ; KICK IT OFF GOTLINK: POP DI LEA SI,TX_Q[BX] CALL Q_ADD ; QUEUE ON LINK JMP NETEXIT1 SETAPPLFLAGS: OR BYTE PTR 2[BX],80H ; SET STREAM IN USE MOV 3[BX],DL ; APPL MASK MOV 4[BX],CL ; APPL FLAGS BPQRETURN: IFDEF OS2 RET ELSE POP DS IRET ENDIF BPQALLOC: CMP AL,0 JE SHORT ALLOC_FIND ; ; ALLOC OR RELEASE ; CMP CL,1 JE SHORT ALLOC CMP CL,2 JNE SHORT BPQRETURN ; ; RELEASE STREAM ; AND BYTE PTR 2[BX],7FH ; CLEAR ALLOCATED BIT JMP SHORT BPQRETURN ALLOC: TEST BYTE PTR 2[BX],80H JZ SHORT ALLOC_OK MOV CX,1 JMP SHORT BPQRETURN ALLOC_OK: OR BYTE PTR 2[BX],80H ; SET ALLOCATED BIT MOV CX,0 JMP SHORT BPQRETURN ALLOC_FIND: ; ; LOOK FOR FIRST FREE SESSION ; MOV BX,OFFSET BPQHOSTVECTOR MOV AL,1 ALLOC_LOOP: TEST BYTE PTR 2[BX],80H JZ SHORT OK_TO_ALLOC ADD BX,VECTORLENGTH INC AL CMP AL,65 JNE SHORT ALLOC_LOOP MOV AL,0FFH JMP SHORT BPQRETURN OK_TO_ALLOC: OR BYTE PTR 2[BX],80H ; SET ALLOCATED BIT JMP SHORT BPQRETURN CHECKLOADED: MOV AX,'PB' MOV BX,' Q' MOV DH,MAJORVERSION MOV DL,MINORVERSION ; MOV SI,OFFSET SESSIONHDDR ; MOV CX,SESSHDDRLEN-2 ; PUSH CX ; REP MOVSB ; POP CX IFDEF OS2 RET ELSE POP DS IRET ENDIF GETTIME: MOV AX,REALTIMETICKS IF BLACKBITS MOV BX,OFFSET BLACKLIST ENDIF JMP BPQRETURN GETSTREAMSTATUS: ; ; AH = 4 Get stream status. Returns: ; ; CX = 0 if stream disconnected or CX = 1 if stream connected ; DX = 0 if no change of state since last read, or DX = 1 if ; the connected/disconnected state has changed since ; last read (ie. delta-stream status). ; ; MOV DL,2[BX] ; STATE CHANGE BITS AND DL,3 ; ISOLATE MOV DH,0 JZ BPQSSTATE00 MOV DL,1 BPQSSTATE00: MOV CX,[BX] ; LOCAL SESSION OR CX,CX JZ BPQSTATE10 ; NO SESSION MOV CX,1 BPQSTATE10: IFDEF OS2 RET ELSE POP DS IRET ENDIF CLEARSTREAMSTATUS: ; ; AH = 5 Ack stream status change ; ; AND BYTE PTR 2[BX],0FCH ; CLEAR IT IFDEF OS2 RET ELSE POP DS IRET ENDIF GETBUFFERSTATUS: ; ; AH = 7 Get buffer counts for stream. Returns: ; ; BX = number of frames queued for receive ; CX = number of un-acked frames to be sent ; DX = number of buffers left in node ; SI = number of monitor frames queued for receive XOR CX,CX ; unacked frames ; PUSH BX ADD BX,5 ; TO TRACE QUEUE CALL COUNT_Q XOR AH,AH POP BX PUSH AX ; SAVE MOV SI,[BX] ; LOCAL SESSION CMP SI,0 JNE BPQSTATE01 ; CONNECTED ; ; NOT CONNECTED - JUST RETURN FREE Q COUNT AND CHANGE BITS ; MOV BX,0 ; NOTHING QUEUED JMP SHORT BPQSTATUSEND BPQSTATE01: ; ; CONNECTED ; LEA BX,L4TX_Q[SI] CALL COUNT_Q XOR AH,AH MOV BX,AX ; QUEUED RX FRAMES BPQSTATE02: CMP L4CROSSLINK[SI],0 JE BPQSTATUSEND ; NOT CONNECTED BEYOND SWITCH MOV SI,L4CROSSLINK[SI] CALL COUNT_QUEUED_FRAMES XOR AH,AH MOV CX,AX ; QUEUED TO SEND BPQSTATUSEND: XOR DH,DH MOV DL,QCOUNT ; FREE BUFFERS POP SI IFDEF OS2 RET ELSE POP DS IRET ENDIF GETCONNECTIONINFO: ; ; PACLEN IN BX ; PUSH BP MOV AX,0 ; PORT MOV BP,AX ; PACLEN MOV CX,AX ; MAXFRAME MOV DX,AX ; L4 WINDOW MOV BX,[BX] ; SESSION CMP BX,0 JE NO_INFO ; NOT CONNECTED MOV BP,WORD PTR SESSPACLEN[BX] MOV SI,OFFSET SWITCHSP CMP L4CROSSLINK[BX],0 JE CALLCOPY ; ; CONNECTED OUT - GET TARGET SESSION ; MOV SI,L4CROSSLINK[BX] MOV DL,L4WINDOW[SI] MOV AH,L4CIRCUITTYPE[SI] ; UPLINK SESSION TYPE TEST AH,BPQHOST JNZ HOST_ENTRY TEST AH,L2LINK JNZ L2_ENTRY ; ; ANOTHER NODE ; ; IF THE HOST IS THE UPLINKING STATION, WE NEED THE TARGET CALL ; TEST L4CIRCUITTYPE[BX],UPLINK; GET SESSION TYPE JZ RETURNCALL ; MOV SI,L4TARGET[SI] ; NODE LEA SI,DEST_CALL[SI] ; NODE CALLSIGN JMP SHORT RETURNCALL L2_ENTRY: PUSH SI ; SAVE SESSION MOV SI,L4TARGET[SI] ; ; SI IS LINK ENTRY - EXTRACT PORT AND MAXFRAME ; MOV AL,LINKPORT[SI] MOV CL,LINKWINDOW[SI] MOV DL,0 ; NO L4 WINDOW ; LEA SI,LINKCALL[SI] TEST AH,UPLINK JZ L2_DOWN ; DOWNLINK, SO WE HAVE THE RIGHT CALL ; ; IF UPLINK, SHOULD USE SEESION CALL, IN CASE *** LINKED HAS BEEN USED ; POP SI ; BACK TO SESSION JMP SHORT HOST_ENTRY L2_DOWN: ADD SP,2 ; LOOSE SAVES SI JMP SHORT RETURNCALL HOST_ENTRY: LEA SI,L4USER[SI] RETURNCALL: PUSH DI ; USERS BUFFER PUSH ES PUSH AX PUSH CX MOV ES,CS:DATASEG CALL CONVFROMAX25 ; CONVERT CALL TO NORMAL POP CX POP AX POP ES POP DI MOV SI,OFFSET NORMCALL CALLCOPY: PUSH CX MOV CX,10 IFDEF OS2 .386 ; ; NEED TO USE 32 BIT MOVE, SO ENSURE TOP WORD OF ESI IS ZERO ; AND ESI,0FFFFH AND ECX,0FFFFH DB 67H .286 ENDIF REP MOVSB ; RETURN CALL POP CX NO_INFO: MOV BX,BP MOV BH,0 POP BP IFDEF OS2 RET ELSE POP DS IRET ENDIF BPQCONDIS: ; ; CL=0 CONNECT USING APPL MASK IN DL ; CL=1, CONNECT. CL=2 - DISCONNECT. CL=3 RETURN TO NODE ; PUSH ES MOV ES,CS:DATASEG CMP CL,1 JA BPQDIS OR BYTE PTR 2[BX],80H ; SET STREAM IN USE CMP WORD PTR [BX],0 JNE BPQCONRET ; ALREADY CONNECTED?? ; ; SET UP A SESSION FOR THE CONSOLE ; PUSH BX MOV AL,DL CMP CL,0 JE GOTMASK MOV AL,3[BX] ; SO WE GET CORRECT CALLSIGN GOTMASK: CALL SETUPBPQCONSOLESESSION ; MOV SI,BX POP BX ; ; SI=SESSION, BX=VECTOR ; CMP SI,0 JE BPQDIS00 ; RETURN DISCONNECTED?? MOV [BX],SI MOV L4CIRCUITTYPE[SI],BPQHOST+UPLINK BPQCONRET: OR BYTE PTR 2[BX],1 ; STATE CHANGE POP ES JMP BPQRETURN ; BPQDIS: CMP WORD PTR [BX],0 JE BPQCONRET ; NOT CONNECTED?? CMP CL,3 JNE DO_DISC MOV DISCFLAG,'S' ; SET 'STAY' FLAG DO_DISC: PUSH BX MOV BX,[BX] ; TO SESSION CALL CLOSESESSIONPARTNER POP BX MOV DISCFLAG,0 ; CLEAR STAY FLAG BPQDIS00: MOV WORD PTR [BX],0 OR BYTE PTR 2[BX],3 ; STATE CHANGE ; JMP SHORT BPQCONRET SENDBPQFRAME: ; ; ES:(E)SI = MESSAGE, CX = LENGTH, BX = VECTOR ; CMP AL,0 JE BPQHOSTUNPROTO MOV BX,[BX] CMP BX,0 JE SENDHOSTRET ; NO SESSION ; ; GET A BUFFER ; BWAITFORBUFFER: CMP QCOUNT,20 ; PLENTY FREE? JAE BENOUGH ; YES PUSH AX CALL RELEASE_TIMESLICE ; WAIT FOR MORE TO BE RELEASED POP AX JMP BWAITFORBUFFER BENOUGH: PUSH SI ; USERS BUFFER CALL GETBUFF POP SI JZ SENDHOSTRET ; ?? PUSH ES ; SAVE PUSH ES POP DS ; MSG SEG TO DS MOV ES,CS:DATASEG PUSH DI ; SAVE BUFFER ADD DI,5 MOV AL,0F0H ; PID STOSB IFDEF OS2 .386 AND EDI,0FFFFH AND ECX,0FFFFH DB 67H ; USE ESI/EDI .286 ENDIF REP MOVSB MOV CX,DI POP DI SUB CX,DI ; LENGTH MOV DS,CS:DATASEG MOV MSGLENGTH[DI],CX ; ; IF CONNECTED, PASS MESSAGE TO TARGET CIRCUIT - FLOW CONTROL AND ; DELAYED DISC ONLY WORK ON ONE SIDE ; LEA SI,L4RX_Q[BX] MOV L4KILLTIMER[BX],0 ; RESET SESSION TIMEOUT CMP L4CROSSLINK[BX],0 ; CONNECTED? JE SENDF50 ; NO, SO QUEUE NORMALLY MOV BX,L4CROSSLINK[BX] ; TO SESSION PARTNER CMP L4STATE[BX],5 JNE SENDF50 ; NOT UP YET - AGAIN QUEUE NORAMLLY LEA SI,L4TX_Q[BX] SENDF50: CALL Q_ADD ; PUT ON QUEUE ; POP ES SENDHOSTRET: JMP BPQRETURN BPQHOSTUNPROTO: CMP AH,2 JNE UNPROTORET ; ONLY USED FOR SEND DATA ; ; SEND FRAME TO ALL RADIO PORTS ; ; COPY DATA TO A BUFFER IN OUR SEGMENTS - SIMPLFIES THINGS LATER ; CMP QCOUNT,20 ; PLENTY FREE? JB UNPROTORET ; DONT BOTHER IF VERY LOW PUSH SI ; USERS BUFFER CALL GETBUFF POP SI JZ UNPROTORET ; ?? PUSH ES ; SAVE USERS ES PUSH ES POP DS ; MSG SEG TO DS MOV ES,CS:DATASEG PUSH DI ; SAVE BUFFER ADD DI,5 MOV AL,0F0H ; PID STOSB REP MOVSB MOV CX,DI POP DI SUB CX,DI ; LENGTH MOV DS,CS:DATASEG MOV MSGLENGTH[DI],CX ; PUSH DI ; SAVE FOR RELEASE MOV SI,DI CALL SENDUIMESSAGE POP DI CALL RELBUFF POP ES ; USER'S ES UNPROTORET: MOV CX,0 MOV DX,0 IFDEF OS2 RET ELSE POP DS IRET ENDIF GETBPQFRAME: MOV CX,0 ; FRAME LENGTH MOV BX,[BX] ; SESSION OR BX,BX JZ GETF10 ; NO SESSION LEA SI,L4TX_Q[BX] CMP WORD PTR [SI],0 JNE GETF20 GETF10: XOR BX,BX ; NO MORE IFDEF OS2 RET ELSE POP DS IRET ENDIF GETF20: MOV L4KILLTIMER[BX],0 ; RESET SESSION TIMEOUT MOV DX,DI ; SAVE USERS BUFFER CALL Q_REM MOV CX,MSGLENGTH[DI] LEA SI,L3PID+1[DI] SUB CX,6 ; HEADER LENGTH JZ GETBPQEND ; ZERO LENGTH TEXT CMP CX,257 JB BPQLENOK MOV CX,256 ; PROTECTION BPQLENOK: PUSH DI ; SAVE BUFFER MOV DI,DX ; RESTORE USERS BUFFER PUSH CX IFDEF OS2 .386 ; ; NEED TO USE 32 BIT MOVE, SO ENSURE TOP WORD OF ESI IS ZERO ; AND ESI,0FFFFH AND ECX,0FFFFH DB 67H .286 ENDIF REP MOVSB ; COPY TO SUPPLIED BUFFER POP CX POP DI GETBPQEND: CALL RELBUFF LEA BX,L4TX_Q[BX] CALL COUNT_Q XOR AH,AH ; FRAMES WAITING MOV BX,AX MOV DI,DX IFDEF OS2 RET ELSE POP DS IRET ENDIF GETRAWFRAME: MOV CX,0 ; FRAME LENGTH LEA SI,5[BX] CMP WORD PTR [SI],0 JNE GETRF20 XOR BX,BX ; NO MORE IFDEF OS2 RET ELSE POP DS IRET ENDIF GETRF20: MOV DX,DI ; SAVE USERS BUFFER CALL Q_REM MOV CX,MSGLENGTH[DI] JCXZ GETRAWEND ; ZERO LENGTH TEXT PUSH DI ; SAVE BUFFER MOV SI,DI MOV DI,DX ; RESTORE USERS BUFFER PUSH CX MOV AX,BUFFLEN-4[SI] ; GET TIMESTAMP IFDEF OS2 .386 ; ; NEED TO USE 32 BIT MOVE, SO ENSURE TOP WORD OF ESI IS ZERO ; AND ESI,0FFFFH AND ECX,0FFFFH DB 67H .286 ENDIF REP MOVSB ; COPY TO SUPPLIED BUFFER POP CX POP DI GETRAWEND: PUSH AX ; SAVE TIMESTAMP CALL RELBUFF ; ; COUNT THOSE LEFT ON QUEUE ; LEA BX,5[BX] CALL COUNT_Q XOR AH,AH ; FRAMES WAITING MOV BX,AX MOV DI,DX POP AX IFDEF OS2 RET ELSE POP DS IRET ENDIF RAWTX: ; ; ES:SI = MESSAGE, CX = LENGTH, AL = PORT ; ; GET A BUFFER ; CMP QCOUNT,20 ; PLENTY FREE? JB RAWEXIT ; no CALL GETPORTTABLEENTRY PUSH SI ; USERS BUFFER CALL GETBUFF POP SI JZ RAWEXIT PUSH ES ; SAVE PUSH ES POP DS ; MSG SEG TO DS MOV ES,CS:DATASEG PUSH DI ; SAVE BUFFER ADD DI,5 IFDEF OS2 .386 AND EDI,0FFFFH AND ECX,0FFFFH DB 67H ; USE ESI/EDI .286 ENDIF REP MOVSB MOV CX,DI POP DI SUB CX,DI ; LENGTH MOV DS,CS:DATASEG MOV MSGLENGTH[DI],CX ; MOV AL,PORTNUMBER[BX] MOV MSGPORT[DI],AL CALL PUT_ON_PORT_Q POP ES RAWEXIT: IFDEF OS2 RET ELSE POP DS IRET ENDIF UPDATESWITCH: CMP DX,2 JNE NOTNODES PUSH ES MOV AX,DATA MOV ES,AX CALL SENDNODESMSG POP ES JMP RAWEXIT NOTNODES: CMP DX,1 JNE RAWEXIT ; ; UPDATE BT ; PUSH ES ; SAVE USERS ES PUSH ES POP DS ; MSG SEG TO DS MOV ES,CS:DATASEG MOV ES:BTLENGTH,CX ADD ES:BTLENGTH,6 MOV DI,OFFSET BTEXTFLD REP MOVSB POP ES ; USER'S ES JMP RAWEXIT ; ; INT 2F ENTRY - USED TO TELL WINDOWS TO LOAD BPQCODE VxD ; ; Structure for real mode device initialization API. ; Win386_Startup_Info_Struc STRUC SIS_Version db 3, 0 ; Structure version SIS_Next_Ptr dd ? ; Seg:Off of next dev in list SIS_Virt_Dev_File_Ptr dd 0 ; Ptr to ASCIZ file name to load SIS_Reference_Data dd ? ; Data to be passed to device SIS_Instance_Data_Ptr dd 0 ; Ptr to instance data list Win386_Startup_Info_Struc ENDS ; ; Structure for instance data list. (List terminated with 0 dword). ; Instance_Item_Struc STRUC IIS_Ptr dd ? ; Seg:Off of instance item IIS_Size dw ? ; Size of instance item in bytes Instance_Item_Struc ENDS InstData LABEL BYTE DB 3,0 ; VERSION DD 0 ; NEXT POINTER VXDOFFSET DW OFFSET VXDNAME DW CODE VXDINFO DD 0 ; REFERENCE DATA DD 0 ; INSTANCE DATA POINTER VXDNAME DB '\WINDOWS\SYSTEM\BPQCODE.386',0 OLDINT2F DD 0 INT2F: cmp ax,1605h ; WINDOWS LOADING? jnz @f ; ; HOOK IN OUR INSTANCE DATA ; push di lea di,InstData mov word ptr cs:[di].SIS_Next_Ptr,bx mov word ptr cs:[di][2].SIS_Next_Ptr,es pop di push cs pop es lea bx,InstData @@: jmp CS:[OLDINT2F] ; ENDIF ; OF PCSWITCH (FOR API STUFF) HEXOUT: IFDEF DOS PUSH AX PUSH AX sar al,1 sar al,1 sar al,1 sar al,1 call hexout1 pop ax call hexout1 mov al,20h call printit POP AX ret hexout1: and al,0fh cmp al,10 jl hexout5 add al,7 hexout5: add al,30h call printit ; ret ; printit: PUSH BX mov AH,14 int 10h POP BX ENDIF ret ; IFDEF DOS ; HAVE AN INITSEG CODE ENDS INITSEG SEGMENT PUBLIC 'INITSEG' ASSUME CS:INITSEG,DS:CODE,ES:NOTHING,SS:DATA ENDIF IF TNC2 PUBLIC INITIALISETNCPORT ENDIF EXTRN DECODECALLSTRINGF:FAR IFDEF DOS EXTRN HOSTINTERRUPT:BYTE ENDIF PUBLIC INSTALLINT14 INSTALLINT14: ; ; INSTALL INT 14 TRAP AND INT 7F TRAPS ; PUSH ES PUSH DS MOV AX,CODE MOV DS,AX IF TNC2 IF 0 ; INT14 ONLY USED FOR KANT/MSC ; ; HOOK INT 14 ; MOV AL,14H MOV AH,35H INT 21H ; GET VECTOR MOV WORD PTR OLDINT14,BX MOV WORD PTR OLDINT14+2,ES ; SAVE MOV DX,OFFSET INT14 MOV AL,14H MOV AH,25H ; SET NEW VECTOR INT 21H ENDIF ENDIF IFDEF DOS ; ; HOOK INT 2F (FOR WINDOWS) AND API VECTOR ; MOV AL,2FH MOV AH,35H INT 21H ; GET VECTOR MOV WORD PTR OLDINT2F,BX MOV WORD PTR OLDINT2F+2,ES ; SAVE MOV DX,OFFSET INT2F MOV AL,2FH MOV AH,25H ; SET NEW VECTOR INT 21H MOV DX,OFFSET BPQHOSTPORT MOV AL,SS:HOSTINTERRUPT MOV BYTE PTR VXDINFO,AL MOV AH,25H ; SET NEW VECTOR INT 21H ENDIF POP DS POP ES ; RET IF TNC2 INITIALISETNCPORT: ; ; INITIALISE PORT CONTROL TABLE ENTRY ; ; BX = PORT ENTRY, AL = INT14 PORT NUMBER ; ASSUME DS:DATA MOV BIOSPORT[BX],AL MOV AX,0 ; START OF BUFFER ADD AX,BX MOV PUTPTR[BX],AX MOV GETPTR[BX],AX MOV VLSR[BX],20H MOV VMSR[BX],30H MOV MODEFLAG[BX],COMMAND MOV SENDPAC[BX],0DH MOV CRFLAG[BX],1 MOV MALL[BX],1 MOV MMASK[BX],0FFH ; MONITOR MASK FOR PORTS MOV AL,PACLEN MOV TPACLEN[BX],AL ; TNC PACLEN MOV APPLICATION[BX],BBSAPPL ; FOR COMPATIBILITY MOV KBBUFFER[BX],0 MOV KBSESSION[BX],0 MOV RXCOUNT[BX],0 PUSH SI PUSH CX MOV SI,OFFSET UNPROTOCALL IFDEF PCSWITCH CALL DECODECALLSTRINGF ELSE CALL DECODECALLSTRING ENDIF LEA DI,UNPROTO[BX] MOV CX,56 REP MOVSB ; UNPROTO ADDR POP CX POP SI RET ENDIF IFDEF DOS INITSEG ENDS ELSE CODE ENDS ENDIF END