/*++ 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);