; ; 13/9/99 ; ; Validate callsings in Nodes message ; PAGE 56,132 ; DATA SEGMENT PUBLIC 'DATA' INCLUDE ENVIRON.ASM INCLUDE STRUCS.ASM IFDEF KANT INCLUDE KANTEQU.ASM ENDIF TEMPFIELD DB 7 DUP (0) ; TEMP STORAGE FOR CALL NODEMSGLEN DW 0 ; LENGTH OF RECEIVED NODES MSG SAVEPTR DW 0 ; TEMP SAVE FIELD NODEQUAL DB 0 ; QUALITY OF ABOVE PORT ROUTEQUAL DB 0 ; QUALITY OF CURRENT ROUTE SAVENBOUR DW 0 ; POINTER TO NEIGHBOUR LIST WHEN ; PROCESSING NODES MSG L3TIMER DW 1 ; TIMER FOR 'NODES' MESSAGE IDTIMER DW 0 ; TIMER FOR ID MESSAGE BTTIMER DW 0 ; TIMER FOR BT MESSAGE NODECALL DB 9CH,9EH,88H,8AH,0A6H,40H,0E0H ; 'NODES' IN AX25 FORMAT SAVEBX DW 0 ; TEMP STORAGE DESTHEADER DW 0 ; HEAD OF SORTED NODES CHAIN LASTPOINTER DW 0 ; ; FIELDS TO CONTROL INCREMENTAL NODERS BROADCASTS ; NODESINPROGRESS DB 0 L3_10SECS DB 10 ; 1 SEC TO 10 SECS COUNTER CURRENTNODE DW 0 ; NEXT NODE TO SEND CURRENTPORT DW 0 ; PORT WE ARE SENDING NODES ON CURRENTPORTNO DB 0 ; NUMBER OF CURRENT PORT PORTSLEFT DB 0 ; PORTS STILL TO SEND ON B100 DB 100 B10 DB 10 B21 DB 21 IDMSG_Q DW 0 ; ID/BEACONS WAITING TO BE SENT TXMINQUAL DB 0 ; MINIMUM TO SEND ON CURRENT PORT PUBLIC ROUTEQUAL,SAVENBOUR,NODECALL,BTTIMER,IDTIMER,L3TIMER PUBLIC DESTHEADER,IDMSG_Q IFDEF PCSWITCH EXTRN HH:BYTE,MM:BYTE,SSECS:BYTE ENDIF EXTRN MYCALL:BYTE,BBSCALL:BYTE,AX25CALL:BYTE,NORMCALL:BYTE,QCOUNT:BYTE EXTRN BUFFER:WORD,SAVELINK:WORD,SAVEPORT:BYTE EXTRN BBSCALL:BYTE,IDINTERVAL:WORD EXTRN MINQUAL:WORD,L3INTERVAL:WORD,NEIGHBOURS:WORD EXTRN MAXNEIGHBOURS:WORD,DESTS:WORD,MAXDESTS:WORD EXTRN OBSINIT:BYTE,PORTTABLE:WORD,NUMBEROFPORTS:WORD EXTRN ENDDESTLIST:WORD,OBSMIN:BYTE,NODE:BYTE,NUMBEROFNODES:WORD EXTRN TNCTABLE:WORD,BTINTERVAL:WORD,LINKS:WORD,MAXLINKS:WORD IFDEF MSC EXTRN HOURS:BYTE,MINS:BYTE,SECS:BYTE ENDIF DATA ENDS CODE SEGMENT PUBLIC 'CODE' ASSUME CS:CODE,DS:DATA,ES:DATA,SS:DATA ; PUBLIC PROCESSNODEMESSAGE,L3SWAPADDRESSES,CHECKL3TABLES PUBLIC FINDDESTALIAS,FINDDESTINATION,FINDNEIGHBOUR PUBLIC L3CONNECTFAILED,L3LINKFAILED,L3LINKCLOSED,L3TIMERPROC,L3BG PUBLIC CHECKNEIGHBOUR,SENDNODESMSG,REFRESHROUTE PUBLIC FINDNEIGHBOURF,FINDDESTINATIONF,PROCROUTESF,L3FASTTIMER PUBLIC PROCROUTES,CHAINNODE,UNCHAINNODE EXTRN Q_ADD:NEAR,GETBUFF:NEAR,RELBUFF:NEAR,COMPARECALLS:NEAR EXTRN L2SETUPCROSSLINK:NEAR,GETPORTQUALITY:NEAR EXTRN CONVFROMAX25:NEAR,CONVTOAX25:NEAR,GETPORTTABLEENTRY:NEAR EXTRN Q_REM:NEAR,SENDIDMSG:NEAR,COUNTNODES:NEAR,CLEAROUTLINK:NEAR EXTRN SENDBTMSG:NEAR,PUT_ON_PORT_Q:NEAR,COUNT_AT_L2:NEAR IF BLACKBITS EXTRN CHECKBLACKLIST:NEAR ENDIF L3TIMERPROC: ; ; CHECK FOR EXCESSIVE BUFFERS QUEUED AT LINK LEVEL ; CMP QCOUNT,30 JA COUNT_OK MOV SI,LINKS MOV CX,MAXLINKS CHKLINK00: CMP LINKTYPE[SI],3 JNE CHKLINK10 ; NOT INTERNODE MOV BX,SI ; MOV AH,0 CALL COUNT_AT_L2 ; SEE HOW MANY QUEUED CMP AH,50 JB CHKLINK10 ; OK ; ; DESTROY THE SESSION ; MOV BX,SI CALL L3LINKCLOSED ; REPORT TO LEVEL 3 CALL CLEAROUTLINK JMP COUNT_OK ; CANT BE ANY MORE OVERLOADED LINKS CHKLINK10: ADD SI,TYPE LINKTABLE LOOP CHKLINK00 ; COUNT_OK: CMP IDTIMER,0 JE NOIDMSG ; SUPPRESSED DEC IDTIMER JNZ NOIDMSG MOV AX,IDINTERVAL MOV IDTIMER,AX CALL SENDIDMSG NOIDMSG: ; ; CHECK FOR BEACON ; CMP BTTIMER,0 JE NOBTMSG ; SUPPRESSED DEC BTTIMER JNZ NOBTMSG MOV AX,BTINTERVAL MOV BTTIMER,AX MOV BX,TNCTABLE ; IN CASE SENDING MAIL BEACON CALL SENDBTMSG NOBTMSG: ; ; CHECK FOR NODES BROADCAST ; CMP L3TIMER,0 JE L3TIMRET ; TIMER UPDATE AND BROADCAST SUPPRESSED DEC L3TIMER JNZ L3TIMRET ; ; UPDATE DEST LIST AND SEND 'NODES' MESSAGE ; MOV AX,L3INTERVAL MOV L3TIMER,AX CALL UPDATEDESTLIST CALL SENDNODESMSG ; ; TIDY ROUTES ; MOV SI,NEIGHBOURS MOV CX,MAXNEIGHBOURS CMDR10: PUSH CX TEST NEIGHBOUR_FLAG[SI],1 JNZ CMDR88 ; LOCKED CMP NEIGHBOUR_LINK[SI],0 JNE CMDR88 ; HAS AN ACTIVE SESSION CALL COUNTNODES ; NODES USING THIS DESTINATION ; ; IF NUMBER USING ROUTE IS ZERO, DELETE IT ; OR AL,AL JNZ CMDR88 PUSH DI MOV DI,SI MOV CX,TYPE NEIGHBOUR_LIST REP STOSB POP DI CMDR88: POP CX ADD SI,TYPE NEIGHBOUR_LIST LOOP CMDR10 L3TIMRET: RET L3FASTTIMER: ; ; CALLED ONCE PER SECOND - USED ONLY TO SEND NEXT PART OF A NODES OR ; ID MESSAGE SEQUENCE ; DEC L3_10SECS JNZ L3TIMRET MOV L3_10SECS,10 CMP IDMSG_Q,0 ; ID/BEACON TO SEND? JE L3FT00 ; NO MOV SI,OFFSET IDMSG_Q CALL Q_REM JZ L3FT00 ; ?? MOV AL,MSGPORT[DI] CALL GETPORTTABLEENTRY CMP TXPORT[BX],0 JNE SKIPTX ; DONT SEND IF SHARED TX CALL PUT_ON_PORT_Q JMP L3TIMRET SKIPTX: CALL RELBUFF JMP L3TIMRET L3FT00: CMP NODESINPROGRESS,0 JE L3TIMRET CALL SENDNEXTNODESFRAGMENT RET L3BG: ; ; TRANSFER MESSAGES FROM DEST TO LINK ; MOV BX,DESTS MOV CX,MAXDESTS L3BG60: CMP DEST_CALL[BX],0 JE L3BG90 ; SPARE L3BG61: LEA SI,DEST_Q[BX] ; FRAMES TO SEND? CMP WORD PTR [SI],0 JE L3BG90 ; NO PUSH BX PUSH CX ; MOV AL,DEST_ROUTE[BX] OR AL,AL JZ L3BG80 DEC AL MOV AH,0 ADD AX,AX ; * 2 ADD AX,AX ; * 4 ADD BX,AX ; TO ROUTE ENTRY MOV BX,ROUT1_NEIGHBOUR[BX] ; GET NEIGHBOUR ENTRY OR BX,BX JZ L3BG80 ; NO NEIGHBOUR? MOV AX,BX ; SAVE NEIGHBOUR ADDR MOV BX,NEIGHBOUR_LINK[BX] ; GET LINK TABLE ENTRY OR BX,BX JZ L3BG80 ; ???? INACTIVE ???? CMP L2STATE[BX],0 JA L3BG70 ; ; LINK ENTRY IS INVALID - IT PROBABLY HAS BEEN 'ZAPPED', SO CANCEL IT ; MOV BX,AX MOV NEIGHBOUR_LINK[BX],0 JMP SHORT L3BG80 L3BG70: CMP L2STATE[BX],5 ; LINK UP? JL L3BG85 ; NO, SO WAIT FOR IT PUSH BX ; SAVE LINK MOV BX,AX ; NEIGHBOUR ; ; COUNT FRAMES TO NEIGHBOUR ; ADD WORD PTR NBOUR_IFRAMES[BX],1 ADC WORD PTR NBOUR_IFRAMES+2[BX],0 POP BX CALL Q_REM ; GET THE FRAME LEA SI,TX_Q[BX] CALL Q_ADD ; QUEUE ON LINK POP CX POP BX JMP L3BG61 ; SEE IF MORE L3BG80: POP CX POP BX ; RECOVER DEST TABLE ADDR PUSH BX PUSH CX CALL ACTIVATE_DEST L3BG85: POP CX POP BX L3BG90: ADD BX,TYPE DEST_LIST LOOP L3BG60 L3BG95: RET ACTIVATE_DEST: PUSH BX MOV AL,DEST_ROUTE[BX] OR AL,AL JNZ DESTISOK ; ALREADY HAVE A SELECTED ROUTE ; MOV DEST_ROUTE[BX],1 ; TRY TO ACTIVATE FIRST DESTISOK: MOV AL,DEST_ROUTE[BX] DEC AL MOV AH,0 ADD AX,AX ; * 2 ADD AX,AX ; * 4 ADD BX,AX ; TO ROUTE ENTRY MOV BX,ROUT1_NEIGHBOUR[BX] ; GET NEIGHBOUR ENTRY OR BX,BX JZ NOROUTETODEST MOV AX,NEIGHBOUR_LINK[BX] ; GET LINK TABLE ENTRY OR AX,AX JZ ACTIVATENEIGHBOUR ; NEED TO SET UP L2 SESSION TO NEIGHBOUR POP BX ; ? MUST BE WAITING FOR LINK TO COME UP RET ACTIVATENEIGHBOUR: ; ; SET UP LINK TABLE ENTRY ; CALL L2SETUPCROSSLINK ; START SESSION TO NODE IN [BX] POP BX RET NOROUTETODEST: ; ; CURRENT NEIGHBOUR NOT DEFINED - RESET TO USE FIRST ; POP BX MOV DEST_ROUTE[BX],0 RET L3CONNECTFAILED: ; ; L2 LINK SETUP HAS FAILED - SEE IF ANOTHER NEIGHBOUR CAN BE USED ; MOV SI,NEIGHBOUR[BX] ; TO NEIGHBOUR CMP SI,0 JE L3CFRET ; NOTHING ??? MOV NEIGHBOUR_LINK[SI],0 ; CLEAR IT PUSH BX CALL L3TRYNEXTDEST ; RESET ASSOCIATED DEST ENTRIES POP BX L3CFRET: RET L3TRYNEXTDEST: ; ; FIND ANY DESINATIONS WITH [SI] AS ACTIVE NEIGHBOUR, AND ; SET NEXT BEST NEIGHBOUR (IF ANY) ACTIVE ; MOV BX,DESTS MOV CX,MAXDESTS ; L3CFR010: CMP DEST_ROUTE[BX],0 JE L3CFR090 ; NO ACTIVE ROUTE ; PUSH BX MOV AL,DEST_ROUTE[BX] DEC AL MOV AH,0 ADD AX,AX ; * 2 ADD AX,AX ; * 4 ADD BX,AX ; TO ACTIVE ROUTE ENTRY CMP ROUT1_NEIGHBOUR[BX],SI ; GET NEIGHBOUR ENTRY JNE L3CFR080 ; NOT THIS DEST ; ; NEIGHBOUR HAS FAILED - DECREMENT OBSCOUNT ; AND TRY TO ACTIVATE ANOTHER (IF ANY) ; CMP ROUT1_OBSCOUNT[BX],0 JE L3CFR020 ; ALREADY ZERO - WILL BE DELETED BY NEXT NODES UPDATE TEST ROUT1_OBSCOUNT[BX],80H JNZ L3CFR020 ; LOCKED DEC ROUT1_OBSCOUNT[BX] JNZ L3CFR020 ; STILL OK ; ; (ROUTE HAS EXPIRED - WE SHOULD CLEAR IT, AND MOVE OTHERS (IF ANY) UP) ; L3CFR020: POP BX ; ; REMOVE FIRST MESSAGE FROM DEST_Q. L4 WILL RETRY - IF IT IS LEFT HERE ; WE WILL TRY TO ACTIVATE THE DESTINATION FOR EVER ; PUSH SI LEA SI,DEST_Q[BX] CALL Q_REM JZ L3CFR025 ; NONE?? CALL RELBUFF L3CFR025: POP SI INC DEST_ROUTE[BX] ; TO NEXT CMP DEST_ROUTE[BX],4 JNE L3CFR040 ; MOV DEST_ROUTE[BX],1 ; TRY TO ACTIVATE FIRST L3CFR040: JMP SHORT L3CFR090 L3CFR080: POP BX L3CFR090: ADD BX,TYPE DEST_LIST LOOP L3CFR010 RET CHECKNEIGHBOUR: ; ; MESSAGE RECEIVED ON LINK WITH NO DESTINATION - SET ONE UP ; LEA SI,LINKCALL[BX] CALL FINDNEIGHBOUR JZ L3CONN07 ; IN LIST - OK CMP BX,0 JE L3CONN08 ; TABLE FULL?? ; ; FIRST MAKE SURE WE ARE ALLOWING NETWORK ACTIVITY ON THIS PORT ; MOV AL,SAVEPORT CALL GETPORTQUALITY CMP AL,0 JNE QUALOK ; ; NOT A NETWORKING PORT ; RET QUALOK: MOV NEIGHBOUR_QUAL[BX],AL ; QUALITY MOV CX,7 MOV DI,BX REP MOVSB ; PUT IN CALL MOV AL,SAVEPORT MOV NEIGHBOUR_PORT[BX],AL L3CONN07: ; ; SET THIS AS ACTIVE LINK IF NONE PRESENT ; CMP NEIGHBOUR_LINK[BX],0 JNE L3CONN08 MOV AX,SAVELINK MOV NEIGHBOUR_LINK[BX],AX MOV AL,SAVEPORT MOV NEIGHBOUR_PORT[BX],AL L3CONN08: MOV AX,BX MOV BX,SAVELINK MOV NEIGHBOUR[BX],AX ; SET LINK - NEIGHBOUR RET CHECKL3TABLES: ; ; CHECK THAT FAR NODE IS IN 'NODES'. ; BX POINTS TO L4 TABLE ENTRY ; RETURNS POINTER TO NEIGHBOUR ENTRY IN AX ; PUSH BX MOV BX,SAVELINK MOV BX,NEIGHBOUR[BX] ; NEIGHBOUR ENTRY MOV SAVENBOUR,BX MOV SI,BUFFER LEA SI,L3SRCE[SI] CALL FINDDESTINATION JZ L3CONN09 ; OK ; CMP BX,0 JNE CAN_ADD DONT_ADD: MOV AX,0 POP BX RET ; TABLES FULL CAN_ADD: ; ; ADD DESTINATION VIA NEIGHBOUR, UNLESS ON BLACK LIST ; IF BLACKBITS PUSH SI CALL CHECKBLACKLIST POP SI JZ DONT_ADD ; ENDIF MOV CX,7 LEA DI,DEST_CALL[BX] REP MOVSB ; PUT IN CALL CALL CHAINNODE ; PUT ON SORTED CHAIN L3CONN09: ; ; MAKE SURE NEIGHBOUR IS DEFINED FOR DESTINATION ; ; IF NODE - NEIGHBOUR, THEN CAN USE NEIGHBOUR QUALITY, ; OTHERWISE WE DONT KNOW ROUTE, SO MUST SET QUAL TO 0 ; MOV ROUTEQUAL,0 ; DONT KNOW ROUTING, SO SET QUALITY TO ZERO MOV AX,SAVENBOUR CALL PROCROUTES ; ADD NEIGHBOUR IF NOT PRESENT ; CMP DEST_ROUTE[BX],0 ; IS THERE AN ACTIVE ROUTE? JNE L3CONN20 ; DEST IS ACTIVE ; ; MAKE CURRENT NEIGHBOUR ACTIVE ; MOV AX,SAVENBOUR INC DEST_ROUTE[BX] CMP ROUT1_NEIGHBOUR[BX],AX JE L3CONN20 ; FOUND REQUIRED ENTRY ; INC DEST_ROUTE[BX] CMP ROUT2_NEIGHBOUR[BX],AX JE L3CONN20 ; FOUND REQUIRED ENTRY ; INC DEST_ROUTE[BX] CMP ROUT3_NEIGHBOUR[BX],AX JE L3CONN20 ; FOUND REQUIRED ENTRY ; ; CURRENT NEIGHBOUR ISNT IN DEST LIST - SET TO USE BEST ; MOV DEST_ROUTE[BX],1 L3CONN20: ; ; REFRESH OBS COUNT ; PUSH BX ; SAVE DEST TABLE ENTRY MOV AL,DEST_ROUTE[BX] OR AL,AL JZ REFROUTY ; NONE ACTIVE??? DEC AL MOV AH,0 ADD AX,AX ; * 2 ADD AX,AX ; * 4 ADD BX,AX ; TO ROUTE ENTRY TEST ROUT1_OBSCOUNT[BX],80H JNZ REFROUTY ; LOCKED MOV AL,OBSINIT MOV ROUT1_OBSCOUNT[BX],AL ; SET OBSOLESCENCE COUNT REFROUTY: POP AX ; DEST TABLE ENTRY POP BX RET PROCESSNODEMESSAGE: ; ; PROCESS A NET/ROM 'NODES' MESSAGE ; ; UPDATE NEIGHBOURS LIST WITH ORIGINATING CALL, AND ; DESTINATION LIST WITH ANY PRACTICAL ROUTES ; ; ; INCOMING MESSAGE IS IN [DI] ; ; MOV AL,SAVEPORT ; PORT MESSAGE CAME IN ON CALL GETPORTQUALITY OR AL,AL JZ PROCNODE02 ; PORT QUALITY=0, SO IGNORE MOV AX,MSGLENGTH[DI] ; GET MESSAGE LENGTH MOV NODEMSGLEN,AX ; SAVE MOV AL,MSGPORT[DI] MOV SAVEPORT,AL MOV SAVEPTR,DI ; SAVE POINTER ; ; SEE IF OUR CALL - DONT WANT TO PUT IT IN LIST! ; LEA SI,MSGORIGIN[DI] ; SET TO ADDR OF ORIGINATING STATION MOV DI,OFFSET MYCALL PUSH SI CALL COMPARECALLS POP SI JZ PROCNODE02 MOV DI,OFFSET BBSCALL CALL COMPARECALLS JNZ PROCNODE03 ; OK PROCNODE02: RET PROCNODE03: ; MOV DI,SAVEPTR LEA SI,MSGORIGIN[DI] ; SET TO ADDR OF ORIGINATING STATION AND BYTE PTR 6[SI],01EH ; MASK OFF LAST ADDR BIT ; ; SEE IF ORIGINATING CALL IS IN NEIGHBOUR LIST - IF NOT ADD IT ; CALL FINDNEIGHBOUR ; RETURNS ZF AND BX ALIGNED TO ENTRY ; OR FIRST FREE ENTRY JZ PROCNODE10 ; ENTRY FOUND ; CMP BX,0 JE TABLESFULL_JMP ; NO ROOM ; ; CREATE NEIGHBOUR RECORD ; PUSH SI LEA DI,NEIGHBOUR_CALL[BX] MOV CX,7 REP MOVSB AND BYTE PTR -1[DI],01EH ; MASK END OF ADDR BIT MOV AL,SAVEPORT ; PORT MESSAGE CAME IN ON MOV NEIGHBOUR_PORT[BX],AL ; SAVE CALL GETPORTQUALITY MOV NEIGHBOUR_QUAL[BX],AL ; QUALITY MOV NEIGHBOUR_LINK[BX],0 ; CANT HAVE A LINK IF NEW NODE POP SI PROCNODE10: MOV SAVENBOUR,BX ; SAVE POINTER TO NEIGHBOUR FOR DEST ; LIST UPDATES ; ; GET TIME FROM BIOS DATA AREA OR RTC ; IFDEF KANT MOV AL,1 OUT CLOCK_D,AL GETTIMELOOP: IN AL,CLOCK_D ; WAIT FOR NOT BUSY TEST AL,2 JZ OKTOREAD MOV AL,0 OUT CLOCK_D,AL MOV AL,1 OUT CLOCK_D,AL JMP GETTIMELOOP OKTOREAD: IN AL,CLOCK_MINUTE+1 AND AL,0FH MUL B10 MOV CL,AL IN AL,CLOCK_MINUTE AND AL,0FH ADD CL,AL ; MINS TO CL IN AL,CLOCK_HOUR+1 AND AL,0FH MUL B10 MOV CH,AL IN AL,CLOCK_HOUR AND AL,0FH ADD CH,AL ; HOURS TO CH MOV NEIGHBOUR_TIME[BX],CX ; SAVE MOV AL,0 OUT CLOCK_D,AL ENDIF IFDEF MSC MOV AH,HOURS MOV AL,MINS MOV NEIGHBOUR_TIME[BX],AX ; SAVE ; ENDIF IFDEF PCSWITCH MOV AH,HH MOV AL,MM MOV NEIGHBOUR_TIME[BX],AX ; SAVE ; ENDIF ; GET QUALITY ; MOV AL,NEIGHBOUR_QUAL[BX] MOV ROUTEQUAL,AL ; FOR INITIAL ROUTE TABLE UPDATE MOV NODEQUAL,AL ; ; CHECK LINK IS IN DEST LIST ; CALL FINDDESTINATION ; RETURNS ZF AND BX ALIGNED TO ENTRY ; OR FIRST FREE ENTRY JZ PROCNODE20 ; ENTRY FOUND ; CMP BX,0 JNE PROCNODE11 ; OK TABLESFULL_JMP: RET PROCNODE11: ; ; CREATE DESTINATION RECORD ; PUSH SI MOV DI,BX MOV CX,TYPE DEST_LIST MOV AL,0 REP STOSB ; CLEAR ENTRY LEA DI,DEST_CALL[BX] MOV CX,7 REP MOVSB AND BYTE PTR -1[DI],01EH ; MASK END OF ADDR BIT POP SI JMP SHORT PROCNODE21 PROCNODE20: ; ; ALWAYS UPDATE ALIAS IN CASE NOT PRESENT IN ORIGINAL TABLE ; CALL UNCHAINNODE ; REMOVE FROM CHAIN PROCNODE21: PUSH SI ADD SI,10 ; SKIP CONTROL, PID AND SIG BYTES LEA DI,DEST_ALIAS[BX] MOV CX,6 REP MOVSB ; PUT IN ALIAS POP SI CALL CHAINNODE ; PUT BACK ON SORTED LIST ; ; UPDATE QUALITY AND OBS COUNT ; MOV AX,SAVENBOUR ; POINTER TO NEIGHBOUR CALL PROCROUTES ; SUB NODEMSGLEN,23 ; LEVEL 2 HEADER + NODE MNEMONIC ; ; PROCESS KNOWN DESTINATIONS ; ADD SI,16 ; TO DESTINATIONS PROCNODE30: CMP NODEMSGLEN,21 JAE PROCNODE31 ; STILL AT LEAST 1 ENTRY LEFT RET PROCNODE31: IF BLACKBITS PUSH SI CALL CHECKBLACKLIST POP SI JZ PROCNODE50_J ; ENDIF ; ; SEE IF OUR CALL - DONT WANT TO PUT IT IN LIST! ; MOV DI,OFFSET MYCALL PUSH SI CALL COMPARECALLS POP SI JZ PROCNODE50_J MOV DI,OFFSET BBSCALL PUSH SI CALL COMPARECALLS POP SI JZ PROCNODE50_J ; ; MAKE SURE ITS NOT CORRUPTED ; PUSH SI MOV CX,6 ; OLY CHECK FIRST 6 CALLLOOP: CMP BYTE PTR [SI],40H ; DUFF CALLSIGN? JB SHORT DUFFNODE INC SI LOOP CALLLOOP INC SI MOV CX,6 ALIASLOOP: LODSB CMP AL,7AH JA DUFFNODE CMP AL,20H JAE NODEOK CMP AL,0 JE NODEOK DUFFNODE: POP SI PROCNODE50_J: JMP PROCNODE50 NODEOK: LOOP ALIASLOOP ; POP SI ; ; CALCULATE ROUTE QUALITY ; MOV AL,NODEQUAL ; LINK QUALITY MUL BYTE PTR 20[SI] ; REPORTED QUALITY ADD AX,128 MOV ROUTEQUAL,AH ; ; SEE IF BELOW MIN QUAL FOR AUTO UPDATES ; CMP AH,BYTE PTR MINQUAL JB TOO_POOR ; IGNORE IT ; ; CHECK LINK IS IN DEST LIST ; CALL FINDDESTINATION ; RETURNS ZF AND BX ALIGNED TO ENTRY ; OR FIRST FREE ENTRY JZ PROCNODE33 ; ENTRY FOUND ; CMP BX,0 JNE PROCNODE32 TOO_POOR: JMP PROCNODE50 ; NO ROOM TO ADD - SHOULD WE DROP POORER DESTS?? PROCNODE32: ; ; CREATE DESTINATION RECORD ; PUSH SI MOV DI,BX MOV CX,TYPE DEST_LIST MOV AL,0 REP STOSB ; CLEAR ENTRY LEA DI,DEST_CALL[BX] MOV CX,7 REP MOVSB POP SI JMP SHORT PROCNODE34 PROCNODE33: CALL UNCHAINNODE ; REMOVE FROM LIST ; PROCNODE34: ; ; UPDATE ALIAS ; PUSH SI ADD SI,7 LEA DI,DEST_ALIAS[BX] MOV CX,6 REP MOVSB ; PUT IN ALIAS ; POP SI ; CALL CHAINNODE ; PUT BACK ; ; PROCESS ROUTE QUALITY INFO ; PUSH SI ADD SI,13 ; TO BEST NEIGHBOUR ; ; NOW POINTING AT BEST NEIGHBOUR - IF THIS IS US, THEN ROUTE IS A LOOP ; MOV DI,OFFSET MYCALL CALL COMPARECALLS JNE PROCNODE35 ; NOT US MOV ROUTEQUAL,0 ; ZERO QUALITY PROCNODE35: POP SI ; ; DEST IS NOW IN TABLE - ; 1. SEE IF THIS ROUTE IS IN TABLE - IF SO UPDATE QUALITY, ; IF NOT, ADD THIS ONE IF IT HAS HIGHER QUALITY THAN EXISTING ONES ; MOV AX,SAVENBOUR ; POINTER TO NEIGHBOUR CALL PROCROUTES PROCNODE50: ADD SI,21 SUB NODEMSGLEN,21 JMP PROCNODE30 RET PROCROUTESF: MOV SAVENBOUR,AX CALL PROCROUTES RETF PROCROUTES: ; ; ADD NEIGHBOUR ADDRESS IN AX TO ROUTE TABLE IF BETTER QUALITY ; THAN THOSE PRESENT ; TEST DEST_STATE[BX],80H ; BBS ENTRY JZ OKTOPROC RET ; LEAVE WELL ALONE! OKTOPROC: PUSH BX ; SAVE CMP ROUT1_NEIGHBOUR[BX],AX JE PROCNODE44 ; FOUND (ROUTE 1) ADD BX,4 CMP ROUT1_NEIGHBOUR[BX],AX JE PROCNODE45 ; FOUND (ROUTE 2) ADD BX,4 CMP ROUT1_NEIGHBOUR[BX],AX JE PROCNODE45 ; FOUND (ROUTE 3) ; ; NOT IN ANY ROUTE ; POP BX PUSH BX CMP ROUT1_NEIGHBOUR[BX],0 JE PROCNODE45 ; SPARE ENTRY, SO USE IT MOV AL,ROUTEQUAL CMP AL,ROUT1_QUALITY[BX] JB PROCNODE41 ; WORSE ; ; MOVE NEXT 2 ENTRIES DOWN 1 ; MOV AL,ROUT2_QUALITY[BX] MOV ROUT3_QUALITY[BX],AL MOV AL,ROUT2_OBSCOUNT[BX] MOV ROUT3_OBSCOUNT[BX],AL MOV AX,ROUT2_NEIGHBOUR[BX] MOV ROUT3_NEIGHBOUR[BX],AX ; MOV AL,ROUT1_QUALITY[BX] MOV ROUT2_QUALITY[BX],AL MOV AL,ROUT1_OBSCOUNT[BX] MOV ROUT2_OBSCOUNT[BX],AL MOV AX,ROUT1_NEIGHBOUR[BX] MOV ROUT2_NEIGHBOUR[BX],AX MOV DEST_ROUTE[BX],0 ; CANCEL ACTIVE ROUTE, SO WILL USE NEW ONE JMP SHORT PROCNODE45 ; PUT IN NEW ENTRY PROCNODE41: ADD BX,4 CMP ROUT1_NEIGHBOUR[BX],0 JE PROCNODE45 ; SPARE ENTRY, SO USE IT CMP AL,ROUT1_QUALITY[BX] JB PROCNODE42 ; WORSE MOV AL,ROUT1_QUALITY[BX] ; REALLY MOVING 2 TO 3 - BX IS OFFSET BY 4 MOV ROUT2_QUALITY[BX],AL MOV AL,ROUT1_OBSCOUNT[BX] MOV ROUT2_OBSCOUNT[BX],AL MOV AX,ROUT1_NEIGHBOUR[BX] MOV ROUT2_NEIGHBOUR[BX],AX JMP SHORT PROCNODE45 ; SPARE ENTRY, SO USE IT PROCNODE42: ADD BX,4 CMP ROUT1_NEIGHBOUR[BX],0 ; 3RD JE PROCNODE45 ; SPARE ENTRY, SO USE IT CMP AL,ROUT1_QUALITY[BX] JA PROCNODE45 ; WE ARE BETTER THAN WORSE, SO OVERWRITE ; ; THIS ROUTE IS WORSE THAN ANY OF THE CURRENT 3 - IGNORE IT ; JMP SHORT PROCNODE49 PROCNODE44: ; ; THIS IS A REFRESH OF BEST - IF THIS ISNT ACTIVE ROUTE, MAKE IT ACTIVE ; CMP DEST_ROUTE[BX],1 JBE PROCNODE45 ; LEAVE IT IF NOT SELECTED OR ALREADY USING BEST MOV DEST_ROUTE[BX],1 ; PROCNODE45: MOV AX,SAVENBOUR ; POINTER TO NEIGHBOUR MOV ROUT1_NEIGHBOUR[BX],AX ; ; I DONT KNOW WHY I DID THIS, BUT IT CAUSES REFLECTED ROUTES ; TO BE SET UP WITH OBS = 0. THIS MAY PREVENT A VALID ALTERNATE ; VIA THE SAME NODE TO FAIL TO BE FOUND. SO I'LL TAKE OUT THE ; TEST AND SEE IF ANYTHING NASTY HAPPENS ; IT DID - THIS IS ALSO CALLED BY CHECKL3TABLES. TRY RESETING ; OBS, BUT NOT QUALITY TEST ROUT1_OBSCOUNT[BX],80H JNZ PROCNODE49X ; LOCKED MOV AL,OBSINIT MOV ROUT1_OBSCOUNT[BX],AL ; SET OBSOLESCENCE COUNT PROCNODE49X: MOV AL,ROUTEQUAL CMP AL,0 JE PROCNODE49 ; IF ZERO, SKIP UPDATE MOV ROUT1_QUALITY[BX],AL PROCNODE49: POP BX ; ; IT IS POSSIBLE ROUTES ARE NOW OUT OF ORDER ; SORTROUTES: MOV AL,ROUT1_QUALITY[BX] CMP AL,ROUT2_QUALITY[BX] JAE ROUT1_OK ; ; SWAP 1 AND 2 ; CALL SWAP1_2 MOV DEST_ROUTE[BX],0 ; FORCE A RE-ASSESSMENT ROUT1_OK: MOV AL,ROUT2_QUALITY[BX] CMP AL,ROUT3_QUALITY[BX] JAE ROUTESOK ; ; SWAP 2 AND 3 ; ADD BX,4 ; SO SWAP1_2 REALLY SWAPS 2-3 CALL SWAP1_2 SUB BX,4 MOV DEST_ROUTE[BX],0 ; FORCE A RE-ASSESSMENT JMP SORTROUTES ; 1 AND 2 MAY NOW BE WRONG! ROUTESOK: RET SWAP1_2: MOV AL,ROUT1_QUALITY[BX] MOV AH,ROUT2_QUALITY[BX] MOV ROUT1_QUALITY[BX],AH MOV ROUT2_QUALITY[BX],AL MOV AL,ROUT1_OBSCOUNT[BX] MOV AH,ROUT2_OBSCOUNT[BX] MOV ROUT1_OBSCOUNT[BX],AH MOV ROUT2_OBSCOUNT[BX],AL PUSH CX MOV AX,ROUT1_NEIGHBOUR[BX] MOV CX,ROUT2_NEIGHBOUR[BX] MOV ROUT1_NEIGHBOUR[BX],CX MOV ROUT2_NEIGHBOUR[BX],AX POP CX RET FINDNEIGHBOURF: CALL FINDNEIGHBOUR RETF FINDNEIGHBOUR: ; MOV BX,0 MOV DI,NEIGHBOURS MOV CX,MAXNEIGHBOURS FINDNE00: CMP BYTE PTR [DI],0 JNE FINDNE05 ; NOT A SPARE ENTRY CMP BX,0 JNE FINDNE10 ; ALREADY FOUND A SPARE MOV BX,DI ; POINTER TO FIRST FREE JMP SHORT FINDNE10 ; TRY NEXT ENTRY FINDNE05: MOV AL,SAVEPORT CMP NEIGHBOUR_PORT[DI],AL ; CORRECT PORT? JNE FINDNE10 ; NO PUSH SI PUSH DI PUSH CX CALL COMPARECALLS ; CORRECT ENTRY? POP CX POP DI POP SI JE FINDNE99 ; YES FINDNE10: ADD DI,TYPE NEIGHBOUR_LIST LOOP FINDNE00 ; ; ENTRY NOT FOUND - BX HAS FIRST FREE ENTRY, OR ZERO IF TABLE FULL ; OR AL,1 RET FINDNE99: MOV BX,DI XOR AL,AL RET FINDDESTINATIONF: CALL FINDDESTINATION RETF ; FINDDESTINATION: MOV BX,0 MOV DI,DESTS MOV CX,MAXDESTS FINDDE00: CMP DEST_CALL[DI],0 JNE FINDDE05 ; NOT A SPARE ENTRY CMP BX,0 JNE FINDDE10 ; ALREADY FOUND A SPARE MOV BX,DI ; POINTER TO FIRST FREE JMP SHORT FINDDE10 ; TRY NEXT ENTRY FINDDE05: PUSH SI PUSH DI PUSH CX LEA DI,DEST_CALL[DI] CALL COMPARECALLS ; CORRECT ENTRY? POP CX POP DI POP SI JE FINDDE99 ; YES FINDDE10: ADD DI,TYPE DEST_LIST LOOP FINDDE00 ; ; ENTRY NOT FOUND - BX HAS FIRST FREE ENTRY, OR ZERO IF TABLE FULL ; OR AL,1 RET FINDDE99: MOV BX,DI XOR AL,AL RET ; FINDDESTALIAS: ; ; FIND DEST ENTRY USING ALIAS MOV BX,DESTS MOV CX,MAXDESTS FINDDA00: PUSH SI PUSH DI PUSH CX LEA DI,DEST_ALIAS[BX] MOV CX,6 REP CMPSB ; CORRECT ENTRY? POP CX POP DI POP SI JE FINDDA99 ; YES ADD BX,TYPE DEST_LIST LOOP FINDDA00 ; ; ENTRY NOT FOUND ; OR AL,1 RET FINDDA99: XOR AL,AL RET L3SWAPADDRESSES: ; ; EXCHANGE ORIGIN AND DEST ; MOV DI,BUFFER LEA SI,L3SRCE[DI] LEA DI,TEMPFIELD MOV CX,7 REP MOVSB ; SAVE ORIGIN MOV DI,BUFFER LEA SI,L3DEST[DI] LEA DI,L3SRCE[DI] MOV CX,7 REP MOVSB ; AND BYTE PTR -1[DI],00011110B ; MASK SSID OR BYTE PTR -1[DI],00000001B ; SET LAST CALL MOV DI,BUFFER LEA SI,TEMPFIELD LEA DI,L3DEST[DI] MOV CX,7 REP MOVSB ; AND BYTE PTR -1[DI],00011110B ; MASK SSID RET L3LINKFAILED: ; ; LINK IN BX HAS FAILED - REMOVE IT FROM L3 TABLES ; MOV SI,NEIGHBOUR[BX] ; TO NEIGHBOUR CMP SI,0 JE L3LFRET ; NOTHING ??? MOV NEIGHBOUR[BX],0 MOV NEIGHBOUR_LINK[SI],0 ; CLEAR IT PUSH BX CALL L3TRYNEXTDEST ; RESET ASSOCIATED DEST ENTRIES POP BX L3LFRET: RET L3LINKCLOSED: ; ; L2 SESSION HAS SHUT DOWN (PROBABLY DUE TO INACTIVITY) ; CLEAR NEIGHBOUR ; MOV SI,NEIGHBOUR[BX] ; TO NEIGHBOUR CMP SI,0 JE L3LCRET ; NOTHING ??? MOV NEIGHBOUR[BX],0 MOV NEIGHBOUR_LINK[SI],0 ; CLEAR IT PUSH BX CALL CLEARACTIVEROUTE POP BX ; CLEAR ASSOCIATED DEST ENTRIES L3LCRET: RET CLEARACTIVEROUTE: ; ; FIND ANY DESINATIONS WITH [SI] AS ACTIVE NEIGHBOUR, AND ; SET INACTIVE ; MOV BX,DESTS MOV CX,MAXDESTS ; L3CAR010: CMP DEST_ROUTE[BX],0 JE L3CAR090 ; NO ACTIVE ROUTE ; PUSH BX MOV AL,DEST_ROUTE[BX] DEC AL MOV AH,0 ADD AX,AX ; * 2 ADD AX,AX ; * 4 ADD BX,AX ; TO ACTIVE ROUTE ENTRY CMP ROUT1_NEIGHBOUR[BX],SI ; GET NEIGHBOUR ENTRY POP BX JNE L3CAR090 ; NOT THIS DEST ; MOV DEST_ROUTE[BX],0 ; SET NO ACTIVE ROUTE L3CAR090: ADD BX,TYPE DEST_LIST LOOP L3CAR010 RET REFRESHROUTE: ; ; RESET OBS COUNT ON CURRENT ROUTE TO DEST FOR SESSION IN [BX] ; CALLED WHEN INFO ACK RECEIVED, INDICATING ROUTE IS STILL OK ; PUSH BX MOV BX,L4TARGET[BX] ; DEST MOV AL,DEST_ROUTE[BX] OR AL,AL JZ REFROUTX ; NONE ACTIVE??? DEC AL MOV AH,0 ADD AX,AX ; * 2 ADD AX,AX ; * 4 ADD BX,AX ; TO ROUTE ENTRY TEST ROUT1_OBSCOUNT[BX],80H JNZ REFROUTX ; LOCKED MOV AL,OBSINIT MOV ROUT1_OBSCOUNT[BX],AL ; SET OBSOLESCENCE COUNT REFROUTX: POP BX RET UPDATEDESTLIST: ; ; DECREMENT OBS COUNTERS ON EACH ROUTE, AND REMOVE 'DEAD' ENTRIES ; MOV BX,DESTS MOV CX,MAXDESTS ; UPDEST000: CMP DEST_CALL[BX],0 JE UPDEST050 ; SPARE ENTRY TEST DEST_STATE[BX],80H JNZ UPDEST050 ; LOCKED DESTINATION CMP ROUT1_NEIGHBOUR[BX],0 JE UPDEST060 ; NO DESTINATIONS - DELETE ENTRY CMP ROUT1_OBSCOUNT[BX],0 JE UPDEST005 ; FAILED IN USE - DELETE TEST ROUT1_OBSCOUNT[BX],80H JNZ UPDEST010 ; LOCKED DEC ROUT1_OBSCOUNT[BX] JNZ UPDEST010 ; STILL OK ; ; REMOVE ENTRY ; UPDEST005: CALL MOVEALL JMP UPDEST000 ; LOOP BACK TO PROCESS MOVED ENTRIES UPDEST010: CMP ROUT2_NEIGHBOUR[BX],0 JE UPDEST050 ; NO MORE DESTINATIONS CMP ROUT2_OBSCOUNT[BX],0 JE UPDEST015 ; FAILED IN USE - DELETE TEST ROUT2_OBSCOUNT[BX],80H JNZ UPDEST020 ; LOCKED DEC ROUT2_OBSCOUNT[BX] JNZ UPDEST020 ; STILL OK ; ; REMOVE ENTRY ; UPDEST015: CALL MOVE3TO2 JMP UPDEST010 ; LOOP BACK UPDEST020: CMP ROUT3_NEIGHBOUR[BX],0 JE UPDEST050 ; NO MORE CMP ROUT3_OBSCOUNT[BX],0 JE UPDEST025 ; FAILED IN USE - DELETE TEST ROUT3_OBSCOUNT[BX],80H JNZ UPDEST050 ; LOCKED DEC ROUT3_OBSCOUNT[BX] JNZ UPDEST050 ; STILL OK ; ; REMOVE ENTRY ; UPDEST025: CALL CLEARTHIRD UPDEST050: ADD BX,TYPE DEST_LIST LOOP UPDEST000 RET UPDEST060: ; ; NO ROUTES LEFT TO DEST - REMOVE IT ; LEA SI,DEST_Q[BX] CALL Q_REM JZ UPDEST070 ; NO BUFFERS QUEUED CALL RELBUFF JMP UPDEST060 UPDEST070: PUSH CX ; SAVE COUNT ; ; MAY NEED TO CHECK FOR L4 CIRCUITS USING DEST, BUT PROBABLY NOT, ; AS THEY SHOULD HAVE TIMED OUT LONG AGO ; CALL UNCHAINNODE ; REMOVE FROM SORTED LIST MOV CX,TYPE DEST_LIST MOV DI,BX XOR AL,AL REP STOSB POP CX JMP UPDEST050 ; LOOP BACK MOVEALL: MOV AL,ROUT2_QUALITY[BX] MOV ROUT1_QUALITY[BX],AL MOV AL,ROUT2_OBSCOUNT[BX] MOV ROUT1_OBSCOUNT[BX],AL MOV AX,ROUT2_NEIGHBOUR[BX] MOV ROUT1_NEIGHBOUR[BX],AX MOVE3TO2: ; MOV AL,ROUT3_QUALITY[BX] MOV ROUT2_QUALITY[BX],AL MOV AL,ROUT3_OBSCOUNT[BX] MOV ROUT2_OBSCOUNT[BX],AL MOV AX,ROUT3_NEIGHBOUR[BX] MOV ROUT2_NEIGHBOUR[BX],AX CLEARTHIRD: MOV ROUT3_QUALITY[BX],0 MOV ROUT3_OBSCOUNT[BX],0 MOV ROUT3_NEIGHBOUR[BX],0 MOV DEST_ROUTE[BX],0 ; CANCEL ACTIVE ROUTE, SO WILL RE-ASSESS BEST RET SENDNODESMSG: CMP NODESINPROGRESS,0 ; STILL GOING? JE SENDNODE00 ; NO RET SENDNODE00: ; ; SEND NODES MESSAGES TO ALL PORTS ; MOV BX,PORTTABLE MOV CURRENTPORT,BX MOV CX,NUMBEROFPORTS MOV PORTSLEFT,CL SENDNEXTNODESFRAGMENT: ; ; SEND NEXT FRAGMENT OF A NODES BROADCAST ; ; FRAGMENTS ARE SENT AT 10 SECONDS INTERVALS - PARTLY TO REDUCE ; QRM, PARTLY TO REDUCE LOAD ON BUFFERS (AND TX POWER SUPPLIES!) ; ; ; SEND TO PORT IN CURRENTPORT, STARTING AT CURRENTNODE ; ; MOV BX,CURRENTPORT MOV AL,PORTNUMBER[BX] MOV CURRENTPORTNO,AL CMP CURRENTNODE,0 JNE NOTFIRST ; ; FIRST FRAGMENT TO A PORT ; CMP PORTQUALITY[BX],0 JNE SENDNODE30 JMP SENDNODEXX ; NO NODES MSG IF QUAL = 0 SENDNODE30: MOV AX,DESTS MOV CURRENTNODE,AX ; START OF LIST NOTFIRST: MOV AL,PORTMINQUAL[BX] MOV TXMINQUAL,AL CALL GETBUFF JNZ SENDNODE32 JMP STILLMORE ; WAIT A BIT SENDNODE32: ; PUSH BX PUSH DI ; SAVE BUFFER CALL SETUPNODESMSG ; ; ADD DESTINATION INFO (UNLESS BBS ONLY) ; CMP NODE,0 JE SENDNODEAA ; BBS ONLY - DONT SEND FULL NODES LIST MOV AH,0 MOV AL,NODESPACLEN[BX] OR AL,AL JNZ PAC_OK MOV AH,1 ; 0 = 256 PAC_OK: CMP AX,50 ; STUPIDLY SMALL? JA PAC_OK2 MOV AX,50 ; EVEN THIS IS RATHER SILLY! PAC_OK2: SUB AX,22 ; FIXED PART DIV B21 ; 21 BYTES PER ENTRY MOV AH,0 MOV CX,AX ; MAX DESTS IN ONE MESSAGE MOV BX,CURRENTNODE SENDNODE42: CMP BX,ENDDESTLIST JNE SENDNODE43 ; ; END OF TABLE ; SENDNODEAA: MOV CURRENTNODE,0 JMP SENDNODE48 ; FINISHED SENDNODE43: MOV AL,ROUT1_QUALITY[BX] CMP AL,0 JE IGNORENODE ; IGNORE IT ; CMP AL,TXMINQUAL JB IGNORENODE MOV AL,OBSMIN ; MINIMUM TO BROADCAST CMP ROUT1_OBSCOUNT[BX],AL JAE SENDNODE44 ; SEND ; TEST DEST_STATE[BX],80H ; JNZ SENDNODE44 ; LOCKED DESTINATION - INCLUDE IT IGNORENODE: ; ; IGNORE IT ; ADD BX,TYPE DEST_LIST JMP SENDNODE42 SENDNODE44: LEA SI,DEST_CALL[BX] IF BLACKBITS CALL CHECKBLACKLIST ; RETURN Z IF NODE IS IN LIST JZ IGNORENODE ; DONT BROADCAST ENDIF PUSH CX MOV CX,13 REP MOVSB ; CALL AND ALIAS MOV SI,ROUT1_NEIGHBOUR[BX] CMP SI,0 JNE SENDNODE45 ; VALID POINTER ; ; DUMMY POINTER IN BBS ENTRY - PUT IN OUR CALL ; MOV SI,OFFSET MYCALL SENDNODE45: MOV AH,NEIGHBOUR_PORT[SI] ; GET PORT OF BEST NEIGHBOUR MOV CX,7 REP MOVSB ; PUT IN CALL MOV AL,100 CMP AH,CURRENTPORTNO JNE NOTSAMEPORT ; ; BEST NEIGHBOUR IS ON CURRENT PORT - REDUCE QUALITY BY QUAL_ADJUST ; MOV SI,CURRENTPORT SUB AL,QUAL_ADJUST[SI] ; PERCENTAGE REDUCTION NOTSAMEPORT: MUL ROUT1_QUALITY[BX] DIV B100 STOSB POP CX ADD BX,TYPE DEST_LIST LOOP SENDNODE42 ; ; CURRENT MESSAGE FULL, SEND IT AND START ANOTHER ; MOV CURRENTNODE,BX SENDNODE48: MOV CX,DI POP DI SUB CX,DI MOV MSGLENGTH[DI],CX POP BX CMP TXPORT[BX],0 JNE SKIPTX1 ; DONT SEND IF SHARED TX CALL PUT_ON_PORT_Q JMP SHORT SENDNODE48A SKIPTX1: CALL RELBUFF SENDNODE48A: ; ; SEE IF MORE TO GO ; CMP CURRENTNODE,0 JNE STILLMORE SENDNODEXX: ; ; FINISHED THIS PORT - SEE IF MORE ; DEC PORTSLEFT JNZ ANOTHERPORT ; MOV NODESINPROGRESS,0 ; FINISHED RET ANOTHERPORT: MOV BX,CURRENTPORT MOV BX,PORTPOINTER[BX] MOV CURRENTPORT,BX STILLMORE: MOV NODESINPROGRESS,1 ; RESTART TIMER RET SETUPNODESMSG: MOV AL,PORTNUMBER[BX] MOV MSGPORT[DI],AL LEA DI,MSGDEST[DI] MOV SI,OFFSET NODECALL MOV CX,7 REP MOVSB MOV SI,OFFSET MYCALL MOV CX,7 REP MOVSB OR BYTE PTR -1[DI],01100001B ; SET CMD END AND RESERVED BITS MOV AL,UI STOSB ; CONTROL MOV AL,0CFH STOSB ; PID MOV AL,0FFH STOSB ; FLAG MOV CX,6 REP MOVSB ; ALIAS FOLLOWS CALL RET CHAINNODE: ; ; PUT NODE IN BX ON SORTED NODES CHAIN ; INC NUMBEROFNODES PUSH SI PUSH DI MOV SI,DESTHEADER CMP SI,0 JNE NOTEMPTY ; ; LIST IS EMPTY - THIS MUST BE FIRST ; MOV DESTHEADER,BX JMP SHORT CHAINRET NOTEMPTY: MOV LASTPOINTER,OFFSET DESTHEADER SCANLOOP: PUSH SI LEA SI,DEST_ALIAS[SI] LEA DI,DEST_ALIAS[BX] MOV CX,6 REP CMPSB POP SI JB CARRYON ; ; ADD IT HERE ; MOV SI,LASTPOINTER MOV AX,DEST_CHAIN[SI] ; NEXT MOV DEST_CHAIN[SI],BX MOV DEST_CHAIN[BX],AX JMP SHORT CHAINRET CARRYON: CMP DEST_CHAIN[SI],0 JE SCANEND MOV LASTPOINTER,SI MOV SI,DEST_CHAIN[SI] JMP SCANLOOP SCANEND: ; ; ADD ON END ; MOV DEST_CHAIN[SI],BX MOV DEST_CHAIN[BX],0 ; END CHAINRET: POP DI POP SI RET UNCHAINNODE: ; ; REMOVE NODE IN BX FROM SORTED NODES CHAIN ; DEC NUMBEROFNODES ; PUSH SI MOV SI,OFFSET DESTHEADER ; MAINLOOP: CMP SI,0 JE UNLINKRET ; NOT THERE!! CMP DEST_CHAIN[SI],BX JE FOUNDOURS MOV SI,DEST_CHAIN[SI] JMP MAINLOOP FOUNDOURS: MOV AX,DEST_CHAIN[BX] ; NEXT MOV DEST_CHAIN[SI],AX ; REMOVE OURS FROM CHAIN UNLINKRET: MOV DEST_CHAIN[BX],0 POP SI RET CODE ENDS END