PAGE 56,132 LF EQU 0AH CR EQU 0DH ; CODE SEGMENT ASSUME DS:CODE, CS:CODE ORG 0100H INCLUDE ENVIRON.ASM GO: JMP INIT ; ; 400H BYTE RECEIVE BUFFER FOR EACH PORT ; DB 2FDH DUP (0) ; ; CONTROL FIELDS FOR EACH PORT ; PORT DB ? ; PORT NUMBER RTSFLG DB 0 ; BIT 0 SET IF RTS/DTR UP VLSR DB 0 ; LAST RECEIVED LSR VALUE VMSR DB 0 RXCOUNT DW 0 ; BYTES IN RX BUFFER PUTPTR DW 0 ; POINTER FOR LOADING BUFFER GETPTR DW 0 OLDINT14 DD 0 ; SAVED INT 14 VECTOR INT14: STI CMP DL,CS:PORT JZ ITSFORUS JMP DWORD PTR CS:OLDINT14 ; NOT FOR OUR PORT - PASS DOWN CHAIN ITSFORUS: PUSH DS PUSH CS POP DS PUSH DX PUSH CX PUSH BX OR AH,AH JZ INITPORT ; INIT DEC AH JZ SENDCHAR ; SEND DEC AH JZ GETCHAR ; RECEIVE DEC AH JZ L14A3 ; STATUS DEC AH JZ L14A6 ; INSTALLED? DEC AH JZ L14A9 ; DROP RTS DEC AH JZ L14AC ; RAISE RTS DEC AH JZ L14AF ; SEND BREAK DEC AH JZ NDREAD DEC AH DEC AH JNZ INT14EXIT JMP WRITEBUFFER NDREAD: ; ; NON - DESTRUCTIVE READ ; MOV BX,[GETPTR] MOV AL,[BX] JMP INT14EXIT GETCHAR: JMP SHORT GETCHARSUPPORT NOP L14A3: ; ; GET STUFF FROM NODE IF BUFFER EMPTY ; CMP RXCOUNT,0 JNE GOTSOME PUSH ES PUSH DS POP ES PUSH SI PUSH DI CALL GETDATA POP DI POP SI POP ES GOTSOME: JMP RETURNSTATUS L14A6: JMP RETURNLOADEDFLAG L14A9: JMP DROPRTS L14AC: JMP RAISERTS L14AF: JMP SENDBREAK INT14EXIT: POP BX POP CX POP DX POP DS IRET INITPORT: JMP RETURNSTATUS SENDCHAR: ; ; SEND CHAR ; JMP SHORT RETURNSTATUS GETCHARSUPPORT: MOV BX,[GETPTR] JMP GETC00 GETCWAIT: PUSH AX MOV AX,1000H INT 15H ; RELEASE TIMESLICE POP AX GETC00: CMP [RXCOUNT],0 JE GETCWAIT ; WAIT FOR CHAR MOV AL,[BX] ; GET CHAR PUSH AX INC BX DEC WORD PTR [RXCOUNT] MOV DX,0400H CMP BX,DX ; BUFFER WRAP? JL L153C ; NO MOV BX,0 ; RESET TO START L153C: CMP WORD PTR [RXCOUNT],128 ; GETTING LOW? JNB L1560 ; NO MOV AH,[RTSFLG] TEST AH,1 ; RTS UP? JZ L1560 ; YES ; ; RTS HAD BEEN DROPPED TO STOP OTHER END SENDING - RAISE IT AGAIN ; AND AH,0FEH ; CLEAR FLAG MOV [RTSFLG],AH L1560: POP AX MOV [GETPTR],BX MOV AH,[VLSR] AND AH,0FEH ; MASK DAV BIT CMP WORD PTR [RXCOUNT],0 JZ L1579 OR AH,1 ; SET DAV IF BUFFER NOT EMPTY L1579: JMP INT14EXIT RETURNSTATUS: ; ; GET STATUS - AH = LSR, AL = MODEM STATUS ; MOV AL,VLSR AND AL,0FEH CMP WORD PTR [RXCOUNT],0 JZ L1599 OR AL,1 ; SET DATA AVAIL L1599: MOV AH,AL MOV AL,VMSR JMP INT14EXIT RETURNLOADEDFLAG: ; ; RETURN 'LOADED' FLAG ; MOV CL,80H ; REQUEST MONITORING MOV DL,0 MOV AL,STREAMBASE ; FIRST PORT MOV AH,1 ; SET APPL MASK CALL NODE MOV AX,0AA55H JMP INT14EXIT DROPRTS: ; ; DROP DTR/RTS ; MOV CL,0H ; DISABLE MONITORING MOV DL,0 MOV AL,STREAMBASE ; FIRST PORT MOV AH,1 ; SET APPL MASK CALL NODE JMP INT14EXIT RAISERTS: ; ; RAISE DTR/RTS ; MOV CL,80H ; ENABLE MONITORING MOV DL,0 MOV AL,STREAMBASE ; FIRST PORT MOV AH,1 ; SET APPL MASK CALL NODE JMP INT14EXIT SENDBREAK: JMP INT14EXIT PUTCHAR: MOV DI,[PUTPTR] MOV [DI],AL INC DI INC WORD PTR [RXCOUNT] MOV AX,400H ; BUFFER LENGTH CMP DI,AX ; END OF BUFFER ADDR JL L1648 ; OK ; ; BUFFER WRAPAROUND ; MOV DI,0 L1648: CMP DI,[GETPTR] ; BUFFER OVERRUN? JNE L167B ; NO OR BYTE PTR [VLSR],2 ; SET OVERRUN ERROR DEC WORD PTR [RXCOUNT] ; LOSE THE CHAR JMP SHORT L1680 L167B: MOV [PUTPTR],DI L1680: RET WRITEBUFFER: ; PUSH DI WBLOOP: MOV AL,ES:[DI] INC DI PUSH CX CALL KISSCHAR POP CX LOOP WBLOOP POP DI POP BX POP CX POP DX MOV AX,0 ; STATUS MOV CX,0 ; NOT SEND POP DS IRET CURSOR DW OFFSET LINEBUFFER+1 LINEBUFFER DB 350 DUP (0) ; MSG FROM PC APPL MSGLEN DW -1 STREAMBASE DB 0 MONITORDATA DB 350 DUP (0) ; RAW FRAME FROM NODE D10 DB 10 MMASK DB 02H HOSTFLAG DB 0 KISSESC EQU 1B ; ESC RECEIVED ; ; KISS CONTROL VALUES ; FEND EQU 0C0H ; KISS FRAME END FESC EQU 0DBH ; KISS ESCAPE TFEND EQU 0DCH ; ESCAPED FEND TFESC EQU 0DDH ; ESCAPED ESCAPE ; ; BASIC LINK LEVEL MESSAGE BUFFER LAYOUT ; MESSAGE STRUC MSGCHAIN DW ? ; CHAIN WORD MSGPORT DB ? ; PORT MSGLENGTH DW ? ; LENGTH MSGDEST DB ? MESSAGE ENDS ; ; KISS MODE SUPPORT CODE ; KISSCHAR: CMP AL,FEND JE KBFEND ; END OF FRAME RECEIVED CMP AL,FESC JE KBFESC ; ESCAPE TEST HOSTFLAG,KISSESC JZ NOESC ; ; IN ESCAPE SEQUENCE - CHAR SHOULD BE TFEND OR TFESC ; AND HOSTFLAG,NOT KISSESC ; CLEAR IT CMP AL,TFEND JE SND0C0 CMP AL,TFESC JE SND0C1 KISSRET: RET ; IGNORE IT SND0C1: MOV AL,FESC JMP SHORT NOESC SND0C0: MOV AL,FEND NOESC: ; MOV BX,CURSOR MOV [BX],AL INC BX INC MSGLEN CMP MSGLEN,330 JA KISSRET ; OVERFLOW MOV CURSOR,BX RET KBFESC: OR HOSTFLAG,KISSESC ; SET ESCAPE MODE RET KBFEND: ; ; FRAME DELIMITER ; ; MAY BE START OR END FRAME ; CMP MSGLEN[BX],-1 JE KISSRET ; NULL FRAME - MUST BE START OF FRAME ; ; WE HAVE AT LEAST ONE BYTE OF A FRAME ; MOV AL,LINEBUFFER ; CONTROL BYTE AND AL,0FH ; MASK OFF CHANNEL JZ KBK000 ; DATA ; ; FOR NOW WE IGNORE ALL OTHERS - DO ENQUIRE LATER ; ; CP 0EH ; ENQUIRE ; JR NZ,KBKEND ; ; ENQUIRE COMMAND - RETURN FEND END FEND ; ; LD A,FEND ; CALL OUTCH0 ; SEND DIRECT ; LD A,0EH ; CALL OUTCH0 ; LD A,FEND ; CALL OUTCH0 JMP SHORT RESETBUFFER KBK000: ; ; SEND DATA TO RADIO PORT ; MOV AL,LINEBUFFER ; CTRL BYTE AGAIN OR AL,AL JNE KBK020 ; WE HAVE A PORT NUMBER ; ; GET DEFAULT PORT ; MOV CL,MMASK ; SHOULD HAVE ONE BIT SET OR CL,CL JZ RESETBUFFER ; NO BITS DEFINED MOV AL,10H ; PORT NO IN UPPER NIBBLE KBK010: TEST CL,1 JNZ KBK020 ; FOUND IT ADD AL,10H SHR CL,1 JMP KBK010 ; LOOP BACK KBK020: ; ; PORT IN UPPER 4 BITS OF AL ; MOV CL,4 SHR AL,CL ; ; GET PORT ENTRY ; MOV CX,MSGLEN MOV AH,10 ; RAW SEND FRAME TO PORT IN AL PUSH ES PUSH CS POP ES PUSH SI MOV SI,OFFSET LINEBUFFER+1 ; AFTER CONTROL BYTE PUSH DI CALL NODE POP DI POP SI POP ES RESETBUFFER: MOV CURSOR,OFFSET LINEBUFFER+1; SET MESSAGE START MOV MSGLEN,-1 ; FOR CONTROL RET GETDATA: ; ; SEE IF ANYTHING QUEUED ; MOV AL,STREAMBASE ; FIRST PORT MOV AH,11 MOV DI,OFFSET MONITORDATA CALL NODE CMP CX,0 JE DATAPOLLRET MOV DI,OFFSET MONITORDATA ; ; ENSURE PLENTY OF SPACE ; ; CHECK PORT ; MOV CL,MSGPORT[DI] AND CL,7FH ; MASK TX BIT DEC CL MOV AL,1 SHL AL,CL ; SHIFT BIT UP TEST MMASK,AL JZ DATAPOLLRET ; DONT WANT THIS PORT ; XOR DH,DH ; CONTROL BYTE CMP MMASK,AL JE KISS_SINGLE ; SINGLE PORT MODE ; ; MULITPORT KISS MODE - PUT PORT NUMBER IN UPPER NIBBLE OF DH ; MOV DH,MSGPORT[DI] MOV CL,4 SHL DH,CL ; UP 4 BITS KISS_SINGLE: MOV CX,MSGLENGTH[DI] SUB CX,5 JC DATAPOLLRET JCXZ DATAPOLLRET LEA SI,MSGDEST[DI] MOV AL,0C0H ; FEND CALL PUTCHAR ; MOV AL,DH ; CONTROL CALL PUTCHAR ; KISSLOOP: LODSB CMP AL,FEND JE KTXFEND CMP AL,FESC JNE NOTFESC CALL PUTCHAR ; SEND ESC MOV AL,TFESC JMP SHORT NOTFESC ; SEND TFESC KTXFEND: MOV AL,FESC CALL PUTCHAR MOV AL,TFEND NOTFESC: CALL PUTCHAR LOOP KISSLOOP MOV AL,0C0H ; FEND CALL PUTCHAR ; DATAPOLLRET: RET HEXOUT: 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 AX PUSH BX mov AH,14 int 10h POP BX POP AX ret ; NODE: INTVAL LABEL BYTE INT 7FH ; PATCHED BY LOAD ROUTINE RET ENDOFCODE LABEL BYTE ; MSG DB 'KISS Host Mode Interface for G8BPQ switch version ' db VERSIONSTRING,' ',DATESTRING db 0dh,0ah,'$' ERRORMSG DB 0AH,'Parameter error:',0dh,0ah,0ah db 'Format is KISS bpqport BIOSPort Portmask' db 0dh,0AH,0ah,'Program NOT installed' DB 0dh,0ah,0AH,'$' NOTBPQERROR DB 'Switch not found$' VERSERROR DB 'Version not compatible with Node Software$' G8BPQ DB 'G8BPQ' BADCONFIGMSG DB 'Configuration file read error',0DH,0AH,'$' CONFIGFILENAME DB CONFIGNAME,0 NOCONFIGMSG DB 'Configuration file ',CONFIGNAME,' not found',0DH,0AH,'$' ; ; BPQCFG FIRST 128 BYTES ; CONFIGTABLE LABEL BYTE ; ; CONFIGURATION DATA STRUCTURE ; ; DEFINES LAYOUT OF CONFIG RECORD PRODUCED BY CONFIGURATION PROG ; ; LAYOUT MUST MATCH THAT IN CONFIG.C SOURCE ; C_NODECALL DB 10 DUP (0) ; OFFSET = 0 C_NODEALIAS DB 10 DUP (0) ; OFFSET = 10 C_BBSCALL DB 10 DUP (0) ; OFFSET = 20 C_BBSALIAS DB 10 DUP (0) ; OFFSET = 30 ; C_OBSINIT DW 0 ; OFFSET = 40 C_OBSMIN DW 0 ; OFFSET = 42 C_NODESINTERVAL DW 0 ; OFFSET = 44 C_L3TIMETOLIVE DW 0 ; OFFSET = 46 C_L4RETRIES DW 0 ; OFFSET = 48 C_L4TIMEOUT DW 0 ; OFFSET = 50 C_BUFFERS DW 0 ; OFFSET = 52 C_PACLEN DW 0 ; OFFSET = 54 C_TRANSDELAY DW 0 ; OFFSET = 56 C_T3 DW 0 ; OFFSET = 58 DW 0 ; OFFSET = 60 DW 0 ; OFFSET = 62 C_IDLETIME DW 0 ; OFFSET = 64 C_EMSFLAG DB 0 ; OFFSET = 66 DB 0 C_BBS DB 0 ; OFFSET = 68 C_NODE DB 0 ; OFFSET = 69 C_HOSTINTERRUPT DB 0 ; OFFSET = 70 C_DESQVIEW DB 0 ; OFFSET = 71 C_MAXLINKS DW 0 ; OFFSET = 72 C_MAXDESTS DW 0 C_MAXNEIGHBOURS DW 0 C_MAXCIRCUITS DW 0 ; 78 C_TNCPORTLISTO DB 16 DUP (0) ; OFFSET = 80 C_IDINTERVAL DW 0 ; 96 C_XXXXXXXX DW 0 ; 98 ; SPARE (WAS DIGIFLAG) C_MINQUAL DW 0 ; 100 C_HIDENODES DB 0 ; 102 C_L4DELAY DW 0 ; 103 C_L4WINDOW DW 0 ; 105 C_BTINTERVAL DW 0 ; 106 X_UNPROTO DB 9 DUP (0) ; 108 ; NOW SPARE C_BBSQUAL DW 0 ; 117 DB (CONFIGTABLE+128-$) DUP (0) CONFIGHANDLE DW 0 INIT: MOV DX,OFFSET MSG MOV AH,9 INT 21H ; ; GET NODE INTERRUPT NUMBER FROM CONFIG FILE ; MOV DX,OFFSET CONFIGFILENAME MOV AH,3DH MOV AL,0 ; READ ONLY INT 21H ; OPEN IT JC NOCONFIGFILE MOV CONFIGHANDLE,AX MOV BX,AX MOV DX,OFFSET CONFIGTABLE MOV CX,128 MOV AH,3FH INT 21H ; READ CMP AX,CX JNE SHORTCONFIG JMP SHORT PROCESSCONFIG NOCONFIGFILE: MOV DX,OFFSET NOCONFIGMSG JMP SHORT CONFIGERR SHORTCONFIG: MOV DX,OFFSET BADCONFIGMSG CONFIGERR: MOV AH,9 INT 21H MOV AX,4C01H INT 21H ; EXIT PROCESSCONFIG: MOV BX,CONFIGHANDLE MOV AH,3EH INT 21H ; CLOSE IT MOV AL,C_HOSTINTERRUPT ; INTERRUPT MOV BYTE PTR INTVAL+1,AL ; PATCH NODE CALL INSTRUCTION ; ; GET NODE VERSION ; MOV AH,0 ADD AX,AX ADD AX,AX MOV SI,AX PUSH DS XOR AX,AX MOV DS,AX LDS SI,DS:[SI] ; GET POINTER TO HOST SUPPORT CODE SUB SI,7 MOV DI,OFFSET G8BPQ MOV CX,5 REP CMPSB ; MAKE SURE SWITCH IS LOADED JE SWITCHOK POP DS MOV DX,OFFSET NOTBPQERROR MOV AH,9 INT 21H JMP SHORT EXIT SWITCHOK: CMP BYTE PTR DS:[SI],MAJORVERSION JNE BADVERSION CMP BYTE PTR DS:1[SI],MINORVERSION JE VERSIONOK BADVERSION: POP DS MOV DX,OFFSET VERSERROR MOV AH,9 INT 21H EXIT: MOV AX,4C00H INT 21H VERSIONOK: POP DS MOV SI,82H ; PARAM STRING CALL GETVALUE ; NUMBER OF PORTS JC BADPORTVAL MOV AL,NEWVALUE OR AL,AL JZ BADPORTVAL CMP AL,64 JA BADPORTVAL MOV AL,NEWVALUE MOV STREAMBASE,AL CALL GETVALUE ; BIOS PORT JC BADPORTVAL MOV AL,NEWVALUE DEC AL MOV PORT,AL ; CALL GETVALUE ; BIOS PORT JC BADPORTVAL MOV AL,NEWVALUE MOV MMASK,AL ; ; INSTALL INTERRUPTS ; 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 MOV AX,0 ; START OF BUFFER MOV DS:[PUTPTR],AX MOV DS:[GETPTR],AX MOV DX,OFFSET ENDOFCODE INT 27H BADPORTVAL: MOV AH,9 MOV DX,OFFSET ERRORMSG INT 21H RET 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,0DH 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,0DH 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 NEWVALUE DB 0 D16 DB 16 CODE ENDS ; END GO