/* Copyright 2001-2015 John Wiseman G8BPQ This file is part of LinBPQ/BPQ32. LinBPQ/BPQ32 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. LinBPQ/BPQ32 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses */ // // Implements the DOS register based API. // Called via an assmbler glue that puts registers into C variables. #define _CRT_SECURE_NO_DEPRECATE #pragma data_seg("_BPQDATA") #include "time.h" #include "stdio.h" #include #include "compatbits.h" #include "CHeaders.h" extern QCOUNT; extern BPQVECSTRUC BPQHOSTVECTOR[]; extern int MAJORVERSION; extern int MINORVERSION; extern char pgm[256]; // Uninitialised so per process VOID PostDataAvailable(TRANSPORTENTRY * Session); DllExport int APIENTRY SendMsg(int stream, char * msg, int len); DllExport int APIENTRY AllocateStream(int stream); DllExport int APIENTRY SendRaw(int port, char * msg, int len); DllExport time_t APIENTRY GetRaw(int stream, char * msg, int * len, int * count); VOID SENDNODESMSG(); int BTLENGTH; char BTEXTFLD[256]; int REALTIMETICKS; VOID CHOSTAPI(ULONG * pEAX, ULONG * pEBX, ULONG * pECX, ULONG * pEDX, VOID ** pESI, VOID ** pEDI) { ULONG EAX = *pEAX; ULONG EBX = *pEBX; ULONG ECX = *pECX; ULONG EDX = *pEDX; VOID * ESI = *pESI; VOID * EDI = *pEDI; int Command; int Stream; int n; int Temp; PBPQVECSTRUC HostVec; TRANSPORTENTRY * Session; /* ; COMMANDS SUPPORTED ARE ; ; AH = 0 Get node/switch version number and description. On return ; AH = major version number and AL = minor version number, ; and user's buffer pointed to by ES:ESI is set to the text ; string normally output by the USERS command, eg: ; "G8BPQ Packet Switch Version 4.01 Dev". CX is set to the ; length of the text string. ; ; ; 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:ESI (length CX) ; ; ; AH = 3 Receive frame into buffer at ES:ESI, 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:EDI = 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:ESI length CX. For example: ; ; "WORCS:G8TIC" or "TICPMS:G8TIC-10". ; ; ; AH = 10 Unproto transmit frame. Data pointed to by ES:ESI, 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:EDI, ; 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:ESI, Len CX = Text ; 2=kick off nodes broadcast ; ; 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 ; */ Command = (EAX & 0xFFFF) >> 8; Stream = (EAX & 0xFF); n = Stream - 1; // API Numbers Streams 1-64 if (n < 0 || n > 63) n = 64; HostVec = &BPQHOSTVECTOR[n]; Session = HostVec->HOSTSESSION; switch (Command) { case 0: // Check Loaded/Get Version EAX = ('P' << 8) | 'B'; EBX = ('Q' << 8) | ' '; EDX = (MAJORVERSION << 8) | MINORVERSION; break; case 1: // Set Appl mAsk HostVec->HOSTAPPLMASK = EDX; // APPL MASK HostVec->HOSTAPPLFLAGS = (UCHAR)ECX; // APPL FLAGS // If either is non-zero, set allocated and Process. This gets round problem with // stations that don't call allocate stream if (ECX || EBX) { HostVec->HOSTFLAGS |= 0x80; // SET ALLOCATED BIT HostVec->STREAMOWNER = GetCurrentProcessId(); // Set Program Name memcpy(&HostVec->PgmName, pgm, 31); } break; case 2: // Send Frame // ES:ESI = MESSAGE, CX = LENGTH, BX = VECTOR EAX = SendMsg(Stream, ESI, ECX); break; case 3: // AH = 3 Receive frame into buffer at ES:EDI, 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). EAX = GetMsg(Stream, EDI, &ECX, &EBX); break; case 4: // 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). ECX = EDX = 0; if (HostVec->HOSTFLAGS & 3) //STATE CHANGE BITS EDX = 1; if (Session) ECX = 1; break; case 5: // AH = 5 Ack stream status change HostVec->HOSTFLAGS &= 0xFC; // Clear Chnage Bits break; case 6: // AH = 6 Session control. // CX = 0 Conneect - APPLMASK in DL // CX = 1 connect // CX = 2 disconnect // CX = 3 return user to node SessionControl(Stream, ECX, EDX); break; case 7: // 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 ECX = 0; // unacked frames EDX = QCOUNT; ESI = (void *)MONCount(Stream); EBX = RXCount(Stream); ECX = TXCount(Stream); EAX = 0; // Is this right ??? break; case 8: // 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:EDI = CALLSIGN GetConnectionInfo(Stream, EDI, &EAX, &Temp, &EBX, &ECX, &EDX); // Return the Secure Session Flag rather than not connected EAX |= Temp <<8; break; case 9: // Not Implemented break; case 10: // AH = 10 Unproto transmit frame. Data pointed to by ES:ESI, of // length CX, is transmitted as a HDLC frame on the radio // port (not stream) in AL. EAX = SendRaw(EAX, ESI, ECX); return; case 11: // AH = 11 Get Trace (RAW Data) Frame into ES:EDI, // Length to CX, Timestamp to AX EAX = GetRaw(Stream, EDI, &ECX, &EBX); break; case 12: // Update Switch if (EDX == 2) { SENDNODESMSG(); break; } if (EDX == 2) { // UPDATE BT BTLENGTH = ECX; memcpy(BTEXTFLD, ESI, ECX + 7); } break; case 13: // BPQALLOC // AL = 0 = Find Free // AL != 0 Alloc or Release if (EAX == 0) { EAX = FindFreeStream(); break; } if (ECX == 1) // Allocate { EAX = AllocateStream(Stream); break; } DeallocateStream(Stream); break; case 14: // AH = 14 Internal Interface for IP Router // Send frame - to NETROM L3 if DL=0 // to L2 Session if DL<>0 break; // Shouldn't be needed case 15: // GETTIME EAX = REALTIMETICKS; EBX = 0; #ifdef EXCLUDEBITS EBX = (ULONG)ExcludeList; #endif break; } *pEAX = EAX; *pEBX = EBX; *pECX = ECX; *pEDX = EDX; *pESI = ESI; *pEDI = EDI; return; }