319 lines
12 KiB
C
319 lines
12 KiB
C
/*++ BUILD Version: 0001
|
|
*
|
|
* WOW v1.0
|
|
*
|
|
* Copyright (c) 1991, Microsoft Corporation
|
|
*
|
|
* WUCOMM.H
|
|
* WOW32 16-bit User API support
|
|
*
|
|
* History:
|
|
* Created 07-Mar-1991 by Jeff Parsons (jeffpar)
|
|
* Updated Dec-1992 by Craig Jones (v-cjones)
|
|
--*/
|
|
|
|
#include "wowcomm.h"
|
|
|
|
// these limits set as doc'd in Win3.1 Prog. ref. for OpenComm()
|
|
#define NUMCOMS 9 // max avail COM's
|
|
#define NUMLPTS 3 // max available LPT's
|
|
#define NUMPORTS NUMCOMS+NUMLPTS // max # of entries in PortTab[]
|
|
|
|
// com port indicies into PortTab[]
|
|
#define COM1 0
|
|
#define COM2 1
|
|
#define COM3 2
|
|
#define COM4 3
|
|
#define COM5 4
|
|
#define COM6 5
|
|
#define COM7 6
|
|
#define COM8 7
|
|
#define COM9 8
|
|
#define LPT1 NUMCOMS
|
|
#define LPT2 LPT1+1
|
|
#define LPT3 LPT1+2
|
|
#define AUX COM1
|
|
#define PRN LPT1
|
|
|
|
// DOS comm IRQ assignments
|
|
#define IRQ3 3
|
|
#define IRQ4 4
|
|
#define IRQ5 5
|
|
#define IRQ7 7
|
|
|
|
// LPT assignments a la Win3.1
|
|
#define LPTFIRST 0x80 // 0x80 == LPT1
|
|
#define LPTLAST LPTFIRST + NUMLPTS - 1 // 0x82 == LPT3
|
|
|
|
// other useful deinitions & macros
|
|
#define COMMASK 0x00FF // strip garbage from idComDev
|
|
#define LPTMASK 0x007F // get 0-based LPT #
|
|
#define GETLPTID(id) ((id & LPTMASK) + LPT1) // 0x80 LPT to PortTab[] index
|
|
#define TABIDTOLPT(id) (id + LPTFIRST - NUMCOMS) // PortTab[] index to LPT 0x80
|
|
#define VALIDCOM(id) ((id < NUMCOMS) ? TRUE : FALSE)
|
|
#define VALIDLPT(id) (((id >= LPTFIRST) && (id <= LPTLAST)) ? TRUE : FALSE)
|
|
|
|
#define GETPWOWPTR(id) (VALIDCOM(id) ? PortTab[id].pWOWPort : (VALIDLPT(id) ? PortTab[GETLPTID(id)].pWOWPort : NULL))
|
|
|
|
#define RM_BIOS_DATA 0x00400000 // bios data real mode seg:0
|
|
|
|
// for Win3.1 compatibility in EscapeCommFunction() API thunk support
|
|
#define RESETDEV 7
|
|
#define GETMAXLPT 8
|
|
#define GETMAXCOM 9
|
|
#define GETBASEIRQ 10
|
|
|
|
// notifications for EnableCommNotification() support
|
|
#define CN_RECEIVE 0x0001
|
|
#define CN_TRANSMIT 0x0002
|
|
#define CN_EVENT 0x0004
|
|
#define CN_RECEIVEHI 0x0100
|
|
#define CN_TRANSMITHI 0x0200
|
|
#define CN_NOTIFYHI 0x0400
|
|
|
|
#define WOW_WM_COMMNOTIFY 0x0044
|
|
|
|
// set all the events that can be masked on NT (a sub-set of Win3.1)
|
|
#define EV_NTEVENTS (EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_TXEMPTY | \
|
|
EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_RING)
|
|
|
|
// constants for how Win3.1 expects to see the MSR
|
|
#define MSR_DELTAONLY 0x0000000F // strip off MSR state bits
|
|
#define MSR_STATEONLY 0x000000F0 // strip off MSR delta bits
|
|
#define MSR_DCTS 0x01 // bit for delta CTS
|
|
#define MSR_DDSR 0x02 // bit for delta DSR
|
|
#define MSR_TERI 0x04 // bit for TERI
|
|
#define MSR_DDCD 0x08 // bit for delta DCD
|
|
#define MSR_CTS 0x10 // bit for CTS
|
|
#define MSR_DSR 0x20 // bit for DSR
|
|
#define MSR_RI 0x40 // bit for RI
|
|
#define MSR_DCD 0x80 // bit for DCD
|
|
|
|
// Win3.1 constants for RLSD, CTS, and DSR timeout support
|
|
#define CE_RLSDTO 0x0080
|
|
#define CE_CTSTO 0x0020
|
|
#define CE_DSRTO 0x0040
|
|
|
|
// constants for the Event Word
|
|
#define EV_CTSS 0x00000400 // bit for Win3.1 showing CTS state
|
|
#define EV_DSRS 0x00000800 // bit for Win3.1 showing DSR state
|
|
#define EV_RLSDS 0x00001000 // bit for Win3.1 showing RLSD state
|
|
#define EV_RingTe 0x00002000 // bit for Win3.1 showing RingTe state
|
|
|
|
#define ERR_XMIT 0x4000 // can't xmit a char Win3.1
|
|
#define INFINITE_TIMEOUT 0xFFFF // infinite timeout Win3.1
|
|
#define IGNORE_TIMEOUT 0x0000 // Win3.1 ignore RLSD, CTS, & DSR timeouts
|
|
|
|
#define COMBUF 2 // max. # of bytes we'll queue for WriteComm()
|
|
|
|
#define MAXCOMNAME 4 // max length of a comm device name
|
|
#define MAXCOMNAMENULL MAXCOMNAME+1 // length of a comm device name + NULL
|
|
|
|
// for 16-bit to 32-bit comm support
|
|
typedef struct _WOWPORT {
|
|
UINT idComDev; // idComDev returned to app as handle of port
|
|
HANDLE h32; // NT file handle used instead of idComDev
|
|
HANDLE hREvent; // structure for overlapped reads
|
|
CRITICAL_SECTION csWrite; // critsect controls following 4 variables.
|
|
PUCHAR pchWriteHead; // oldest byte not yet written to port.
|
|
PUCHAR pchWriteTail; // first byte available in buffer.
|
|
WORD cbWriteFree; // number of bytes available in write buffer.
|
|
WORD cbWritePending; // number of bytes now in WriteFile()
|
|
PUCHAR pchWriteBuf; // write buffer
|
|
WORD cbWriteBuf; // size of the write buffer. One byte unused.
|
|
HANDLE hWriteThread; // thread handle for COM writer.
|
|
HANDLE hWriteEvent; // signalled by app thread when empty buffer
|
|
// made non-empty to wake up writer thread.
|
|
OVERLAPPED olWrite; // Overlapped structure used for writes.
|
|
BOOL fWriteDone; // Indicates app thread completed first write.
|
|
DWORD cbWritten; // Valid when fWriteDone == TRUE.
|
|
DWORD dwThreadID; // app's thread id for crashed/hung app support
|
|
DWORD dwErrCode; // most recent error for this idComDev
|
|
COMSTAT cs; // struct for error handling
|
|
BOOL fChEvt; // TRUE if app set fChEvt in DCB struct
|
|
// 16-bit DCB for LPT support only
|
|
PDCB16 pdcb16; // save DCB for LPT ports
|
|
// for UngetCommChar() support
|
|
BOOL fUnGet; // flag specifying an ungot char is pending
|
|
UCHAR cUnGet; // ungot char in "buffer" only if fUnGet is set
|
|
// for SetCommEventMask()/EnableCommNotification() support
|
|
HANDLE hMiThread; // thread handle for Modem interrupt support
|
|
BOOL fClose; // flag to close auxiliary threads
|
|
// for SetCommEventMask() support only
|
|
DWORD dwComDEB16; // DWORD obtained by call to GlobalDosAlloc()
|
|
PCOMDEB16 lpComDEB16; // flat address to above
|
|
// for XonLim & XoffLim checking in SetCommState
|
|
DWORD cbInQ; // Actual size of in Queue set in WU32OpenComm
|
|
// for RLSD, CTS, DSR timeout support
|
|
WORD RLSDTimeout; // max time in msec to wait for RLSD (0->ignore)
|
|
WORD CTSTimeout; // max time in msec to wait for CTS (0->ignore)
|
|
WORD DSRTimeout; // max time in msec to wait for DSR (0->ignore)
|
|
DWORD QLStackSeg; // Quicklink 1.3 hack See bug #398011
|
|
// save the seg val of COMDEB16 in low word, &
|
|
// the QuickLink stack selector in the high word
|
|
} WOWPORT, *PWOWPORT;
|
|
|
|
// Table of above structs, one entry needed for each comm port
|
|
typedef struct _PORTTAB {
|
|
CHAR szPort[MAXCOMNAMENULL]; // port name
|
|
PWOWPORT pWOWPort; // pointer to Comm Mapping struct
|
|
} PORTTAB, *PPORTTAB;
|
|
|
|
//
|
|
// Macro to calculate the size of chunk to write from the write
|
|
// to the filesystem.
|
|
//
|
|
// This is either the entire pending part of the
|
|
// buffer, or, if the buffer wraps, it is the portion
|
|
// between the head and the end of the buffer.
|
|
//
|
|
// In order to keep COMSTAT.cbOutQue moving at a reasonable
|
|
// pace, we restrict ourselves to writing at most 1024 bytes
|
|
// at a time. This is because ProComm for Windows uses the
|
|
// cbOutQue value in displaying its progress, so if we allow
|
|
// larger writes it will only update every 5-10k (assuming
|
|
// ProComm's default 16k write buffer),
|
|
//
|
|
|
|
#define CALC_COMM_WRITE_SIZE(pwp) \
|
|
min(1024, \
|
|
(pwp->pchWriteHead < pwp->pchWriteTail) \
|
|
? pwp->pchWriteTail - pwp->pchWriteHead \
|
|
: (pwp->pchWriteBuf + pwp->cbWriteBuf) - \
|
|
pwp->pchWriteHead \
|
|
);
|
|
|
|
|
|
// Win3.1 timesout Tx after approx. 65000 msec (65 sec)
|
|
#define WRITE_TIMEOUT 65000
|
|
|
|
// bitfields of the 16-bit COMSTAT.status
|
|
#define W31CS_fCtsHold 0x01
|
|
#define W31CS_fDsrHold 0x02
|
|
#define W31CS_fRlsdHold 0x04
|
|
#define W31CS_fXoffHold 0x08
|
|
#define W31CS_fSentHold 0x10
|
|
#define W31CS_fEof 0x20
|
|
#define W31CS_fTxim 0x40
|
|
|
|
// Win3.1 Baud Rate constants
|
|
#define W31CBR_110 0xFF10
|
|
#define W31CBR_300 0xFF11
|
|
#define W31CBR_600 0xFF12
|
|
#define W31CBR_1200 0xFF13
|
|
#define W31CBR_2400 0xFF14
|
|
#define W31CBR_4800 0xFF15
|
|
#define W31CBR_9600 0xFF16
|
|
#define W31CBR_14400 0xFF17
|
|
#define W31CBR_19200 0xFF18
|
|
#define W31CBR_reserved1 0xFF19
|
|
#define W31CBR_reserved2 0xFF1A
|
|
#define W31CBR_38400 0xFF1B
|
|
#define W31CBR_reserved3 0xFF1C
|
|
#define W31CBR_reserved4 0xFF1D
|
|
#define W31CBR_reserved5 0xFF1E
|
|
#define W31CBR_56000 0xFF1F
|
|
|
|
// these are defined in Win3.1 windows.h but aren't supported in comm.drv
|
|
#define W31CBR_128000 0xFF23
|
|
#define W31CBR_256000 0xFF27
|
|
|
|
// special way to say 115200
|
|
#define W31CBR_115200 0xFEFF
|
|
|
|
// constants for conversions from Win3.1 baud specifications to 32-bit baud
|
|
#define W31_DLATCH_110 1047
|
|
#define W31_DLATCH_300 384
|
|
#define W31_DLATCH_600 192
|
|
#define W31_DLATCH_1200 96
|
|
#define W31_DLATCH_2400 48
|
|
#define W31_DLATCH_4800 24
|
|
#define W31_DLATCH_9600 12
|
|
#define W31_DLATCH_14400 8
|
|
#define W31_DLATCH_19200 6
|
|
#define W31_DLATCH_38400 3
|
|
#define W31_DLATCH_56000 2
|
|
#define W31_DLATCH_115200 1
|
|
|
|
// Win3.1 flags for DCB structure
|
|
#define W31DCB_fBinary 0x0001
|
|
#define W31DCB_fRtsDisable 0x0002
|
|
#define W31DCB_fParity 0x0004
|
|
#define W31DCB_fOutxCtsFlow 0x0008
|
|
#define W31DCB_fOutxDsrFlow 0x0010
|
|
#define W31DCB_fDummy (0x0020 | 0x0040)
|
|
#define W31DCB_fDtrDisable 0x0080
|
|
#define W31DCB_fOutX 0x0100
|
|
#define W31DCB_fInX 0x0200
|
|
#define W31DCB_fPeChar 0x0400
|
|
#define W31DCB_fNull 0x0800
|
|
#define W31DCB_fChEvt 0x1000
|
|
#define W31DCB_fDtrFlow 0x2000
|
|
#define W31DCB_fRtsFlow 0x4000
|
|
#define W31DCB_fDummy2 0x8000
|
|
|
|
|
|
|
|
//+++ DEBUG SUPPORT
|
|
|
|
#ifdef DEBUG
|
|
|
|
#define COMMDEBUG(lpszformat) LOGDEBUG(1, lpszformat)
|
|
|
|
// for watching the modem events
|
|
#define DEBUGWATCHMODEMEVENTS(dwE, dwM, dwS, pcE16, pcM16) { \
|
|
if(dwS) { \
|
|
if((dwE != (DWORD)pcE16) || (dwM != (DWORD)pcM16)) { \
|
|
dwE = (DWORD)pcE16; \
|
|
dwM = (DWORD)pcM16; \
|
|
COMMDEBUG(("\nEvt:0x%4X MSR:0x%2X\n", dwE, dwM)); \
|
|
} \
|
|
else { \
|
|
COMMDEBUG((".")); \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
// prototype for real-time debug output
|
|
void CommIODebug(ULONG fhCommIO, HANDLE hCommIO, LPSZ lpsz, ULONG cb, LPSZ lpszFile);
|
|
|
|
|
|
#else // endif DEBUG
|
|
|
|
#define COMMDEBUG(lpszFormat)
|
|
#define DEBUGWATCHMODEMEVENTS(dwE, dwM, dwS, pcE16, pcM16)
|
|
#define CommIODebug(fhCommIO, hCommIO, lpsz, cb, lpszFile)
|
|
|
|
#endif // endif !DEBUG
|
|
|
|
//--- DEBUG SUPPORT
|
|
|
|
|
|
|
|
|
|
// API support function prototypes
|
|
ULONG FASTCALL WU32BuildCommDCB(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32ClearCommBreak(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32CloseComm(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32EnableCommNotification(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32EscapeCommFunction(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32FlushComm(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32GetCommError(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32GetCommEventMask(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32GetCommState(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32OpenComm(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32ReadComm(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32SetCommBreak(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32SetCommEventMask(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32SetCommState(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32TransmitCommChar(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32UngetCommChar(PVDMFRAME pFrame);
|
|
ULONG FASTCALL WU32WriteComm(PVDMFRAME pFrame);
|
|
|
|
// prototypes for functions exported to the VDM
|
|
BYTE GetCommShadowMSR(WORD idComDev);
|
|
HANDLE GetCommHandle(WORD idComDev);
|
|
|
|
// prototype for crashed/hung app cleanup support
|
|
VOID FreeCommSupportResources(DWORD dwThreadID);
|