; ; BPQ HOST MODE SUPPORT CODE ; ; 22/11/95 ; ; MOVED FROM TNCODE.ASM COS CONITIONALS WERE GETTING TOO COMPLICATED ; (OS2 VERSION HAD UPSET KANT VERISON ; ; 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] ;