mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
473 lines
9.4 KiB
473 lines
9.4 KiB
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
api.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the all apis that simulate their
|
|
WIN32 counterparts.
|
|
|
|
Author:
|
|
|
|
Wesley Witt (wesw) 8-Mar-1992
|
|
|
|
Environment:
|
|
|
|
NT 3.1
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#ifdef min
|
|
#undef min
|
|
#undef max
|
|
#endif
|
|
|
|
#define COM_PORT_NAME "_NT_DEBUG_PORT"
|
|
#define COM_PORT_BAUD "_NT_DEBUG_BAUD_RATE"
|
|
#define OUT_NORMAL 0
|
|
#define OUT_TERMINAL 1
|
|
|
|
ULONG KdPollThreadMode = 0;
|
|
|
|
//
|
|
// Global Data
|
|
//
|
|
HANDLE DmKdComPort;
|
|
|
|
//
|
|
// This overlapped structure will be used for all serial read
|
|
// operations. We only need one structure since the code is
|
|
// designed so that no more than one serial read operation is
|
|
// outstanding at any one time.
|
|
//
|
|
OVERLAPPED ReadOverlapped;
|
|
|
|
//
|
|
// This overlapped structure will be used for all serial write
|
|
// operations. We only need one structure since the code is
|
|
// designed so that no more than one serial write operation is
|
|
// outstanding at any one time.
|
|
//
|
|
OVERLAPPED WriteOverlapped;
|
|
|
|
//
|
|
// This overlapped structure will be used for all event operations.
|
|
// We only need one structure since the code is designed so that no more
|
|
// than one serial event operation is outstanding at any one time.
|
|
//
|
|
OVERLAPPED EventOverlapped;
|
|
|
|
|
|
//
|
|
// Global to watch changes in event status. (used for carrier detection)
|
|
//
|
|
DWORD DmKdComEvent;
|
|
|
|
|
|
CRITICAL_SECTION csComPort;
|
|
CRITICAL_SECTION csPacket;
|
|
|
|
|
|
BOOLEAN
|
|
DmKdInitComPort(
|
|
BOOLEAN KdModemControl
|
|
)
|
|
{
|
|
char ComPortName[16];
|
|
ULONG Baud;
|
|
DCB LocalDcb;
|
|
COMMTIMEOUTS To;
|
|
DWORD mask;
|
|
|
|
|
|
Baud = KdOptions[KDO_BAUDRATE].value;
|
|
sprintf( ComPortName, "\\\\.\\com%d", KdOptions[KDO_PORT].value );
|
|
|
|
//
|
|
// Open the device
|
|
//
|
|
DmKdComPort = CreateFile(
|
|
(PSZ)ComPortName,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
OPEN_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
|
NULL
|
|
);
|
|
|
|
if ( DmKdComPort == (HANDLE)-1 ) {
|
|
return FALSE;
|
|
}
|
|
|
|
SetupComm(DmKdComPort,(DWORD)4096,(DWORD)4096);
|
|
|
|
//
|
|
// Create the events used by the overlapped structures for the
|
|
// read and write.
|
|
//
|
|
|
|
ReadOverlapped.hEvent = CreateEvent(
|
|
NULL,
|
|
TRUE,
|
|
FALSE,NULL
|
|
);
|
|
|
|
if (!ReadOverlapped.hEvent) {
|
|
return FALSE;
|
|
}
|
|
|
|
WriteOverlapped.hEvent = CreateEvent(
|
|
NULL,
|
|
TRUE,
|
|
FALSE,NULL
|
|
);
|
|
|
|
if (!WriteOverlapped.hEvent) {
|
|
return FALSE;
|
|
}
|
|
|
|
ReadOverlapped.Offset = 0;
|
|
ReadOverlapped.OffsetHigh = 0;
|
|
|
|
WriteOverlapped.Offset = 0;
|
|
WriteOverlapped.OffsetHigh = 0;
|
|
|
|
//
|
|
// Set up the Comm port....
|
|
//
|
|
|
|
if (!GetCommState(
|
|
DmKdComPort,
|
|
&LocalDcb
|
|
)) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
LocalDcb.BaudRate = Baud;
|
|
LocalDcb.ByteSize = 8;
|
|
LocalDcb.Parity = NOPARITY;
|
|
LocalDcb.StopBits = ONESTOPBIT;
|
|
LocalDcb.fDtrControl = DTR_CONTROL_ENABLE;
|
|
LocalDcb.fRtsControl = RTS_CONTROL_ENABLE;
|
|
LocalDcb.fBinary = TRUE;
|
|
LocalDcb.fOutxCtsFlow = FALSE;
|
|
LocalDcb.fOutxDsrFlow = FALSE;
|
|
LocalDcb.fOutX = FALSE;
|
|
LocalDcb.fInX = FALSE;
|
|
|
|
if (!SetCommState(
|
|
DmKdComPort,
|
|
&LocalDcb
|
|
)) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Set the normal read and write timeout time.
|
|
// The symbols are 10 millisecond intervals.
|
|
//
|
|
|
|
To.ReadIntervalTimeout = 0;
|
|
To.ReadTotalTimeoutMultiplier = 0;
|
|
To.ReadTotalTimeoutConstant = 4 * 1000;
|
|
To.WriteTotalTimeoutMultiplier = 0;
|
|
To.WriteTotalTimeoutConstant = 4 * 1000;
|
|
|
|
if (!SetCommTimeouts(
|
|
DmKdComPort,
|
|
&To
|
|
)) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
DmKdComEvent = 0;
|
|
if (KdModemControl) {
|
|
|
|
//
|
|
// Debugger is being run over a modem. Set event to watch
|
|
// carrier detect.
|
|
//
|
|
|
|
GetCommMask (DmKdComPort, &mask);
|
|
mask = mask | EV_ERR; // | EV_RLSD;
|
|
if (!SetCommMask (DmKdComPort, mask)) {
|
|
return FALSE;
|
|
}
|
|
|
|
EventOverlapped.hEvent = CreateEvent(
|
|
NULL,
|
|
TRUE,
|
|
FALSE,NULL
|
|
);
|
|
|
|
if (!EventOverlapped.hEvent) {
|
|
return FALSE;
|
|
}
|
|
|
|
EventOverlapped.Offset = 0;
|
|
EventOverlapped.OffsetHigh = 0;
|
|
|
|
DmKdComEvent = 1; // Fake an event, so modem status will be checked
|
|
}
|
|
|
|
InitializeCriticalSection(&csComPort);
|
|
InitializeCriticalSection(&csPacket);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
DmKdWriteComPort(
|
|
IN PUCHAR Buffer,
|
|
IN ULONG SizeOfBuffer,
|
|
IN PULONG BytesWritten
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Writes the supplied bytes to the COM port. Handles overlapped
|
|
IO requirements and other common com port maintanance.
|
|
|
|
--*/
|
|
{
|
|
BOOLEAN rc;
|
|
DWORD TrashErr;
|
|
COMSTAT TrashStat;
|
|
|
|
|
|
EnterCriticalSection(&csComPort);
|
|
|
|
// if (DmKdComEvent) {
|
|
// DmKdCheckComStatus ( );
|
|
// }
|
|
|
|
rc = WriteFile(
|
|
DmKdComPort,
|
|
Buffer,
|
|
SizeOfBuffer,
|
|
BytesWritten,
|
|
&WriteOverlapped
|
|
);
|
|
|
|
if (!rc) {
|
|
|
|
if (GetLastError() == ERROR_IO_PENDING) {
|
|
|
|
rc = GetOverlappedResult(
|
|
DmKdComPort,
|
|
&WriteOverlapped,
|
|
BytesWritten,
|
|
TRUE
|
|
);
|
|
|
|
} else {
|
|
|
|
//
|
|
// Device could be locked up. Clear it just in case.
|
|
//
|
|
ClearCommError( DmKdComPort, &TrashErr, &TrashStat );
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// this is here for digiboards
|
|
//
|
|
FlushFileBuffers( DmKdComPort );
|
|
|
|
LeaveCriticalSection(&csComPort);
|
|
|
|
return rc;
|
|
}
|
|
|
|
BOOLEAN
|
|
DmKdReadComPort(
|
|
IN PUCHAR Buffer,
|
|
IN ULONG SizeOfBuffer,
|
|
IN PULONG BytesRead
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads bytes from the COM port. Handles overlapped
|
|
IO requirements and other common com port maintanance.
|
|
|
|
--*/
|
|
{
|
|
BOOLEAN rc;
|
|
DWORD TrashErr;
|
|
COMSTAT TrashStat;
|
|
|
|
|
|
EnterCriticalSection(&csComPort);
|
|
|
|
// if (DmKdComEvent) {
|
|
// DmKdCheckComStatus ( );
|
|
// }
|
|
|
|
rc = ReadFile(
|
|
DmKdComPort,
|
|
Buffer,
|
|
SizeOfBuffer,
|
|
BytesRead,
|
|
&ReadOverlapped
|
|
);
|
|
|
|
if (!rc) {
|
|
|
|
if (GetLastError() == ERROR_IO_PENDING) {
|
|
|
|
rc = GetOverlappedResult(
|
|
DmKdComPort,
|
|
&ReadOverlapped,
|
|
BytesRead,
|
|
TRUE
|
|
);
|
|
|
|
} else {
|
|
|
|
//
|
|
// Device could be locked up. Clear it just in case.
|
|
//
|
|
ClearCommError( DmKdComPort, &TrashErr, &TrashStat );
|
|
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&csComPort);
|
|
|
|
return rc;
|
|
}
|
|
|
|
VOID
|
|
DmKdCheckComStatus (
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called when the com port status trigger signals a change.
|
|
This function handles the change in status.
|
|
|
|
Note: status is only monitored when being used over the modem.
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
DWORD CommErr;
|
|
COMSTAT CommStat;
|
|
#if 0
|
|
BOOLEAN rc;
|
|
ULONG br;
|
|
UCHAR buf[20];
|
|
#endif
|
|
|
|
if (!DmKdComEvent) {
|
|
//
|
|
// Not triggered, just return
|
|
//
|
|
|
|
return ;
|
|
}
|
|
DmKdComEvent = 0;
|
|
|
|
GetCommModemStatus (DmKdComPort, &status);
|
|
#if 0
|
|
if (!(status & MS_RLSD_ON)) {
|
|
DEBUG_PRINT ("KD: No carrier detect - in terminal mode\n");
|
|
|
|
//
|
|
// Send any keystrokes to the ComPort
|
|
//
|
|
|
|
KdPollThreadMode = OUT_TERMINAL;
|
|
|
|
//
|
|
// Loop and read any com input
|
|
//
|
|
|
|
while (!(status & 0x80)) {
|
|
GetCommModemStatus (DmKdComPort, &status);
|
|
rc = DmKdReadComPort(buf, sizeof buf, &br);
|
|
if (rc != TRUE || br == 0)
|
|
continue;
|
|
|
|
DMPrintShellMsg( "%s", buf );
|
|
|
|
}
|
|
|
|
KdPollThreadMode = OUT_NORMAL;
|
|
DEBUG_PRINT ("KD: Carrier detect - returning to debugger\n");
|
|
|
|
ClearCommError (
|
|
DmKdComPort,
|
|
&CommErr,
|
|
&CommStat
|
|
);
|
|
|
|
} else {
|
|
#endif
|
|
|
|
CommErr = 0;
|
|
ClearCommError (
|
|
DmKdComPort,
|
|
&CommErr,
|
|
&CommStat
|
|
);
|
|
|
|
if (CommErr) {
|
|
DEBUG_PRINT( "Comm Error: " );
|
|
}
|
|
|
|
if (CommErr & CE_OVERRUN) {
|
|
DEBUG_PRINT (" [overrun err] ");
|
|
}
|
|
|
|
if (CommErr & CE_RXOVER) {
|
|
DEBUG_PRINT (" [overflow err] ");
|
|
}
|
|
|
|
if (CommErr & CE_RXPARITY) {
|
|
DEBUG_PRINT (" [parify err] ");
|
|
}
|
|
|
|
if (CommErr & CE_BREAK) {
|
|
DEBUG_PRINT (" [break err] ");
|
|
}
|
|
|
|
if (CommErr & CE_FRAME) {
|
|
DEBUG_PRINT (" [frame err] ");
|
|
}
|
|
|
|
if (CommErr & CE_TXFULL) {
|
|
DEBUG_PRINT (" [txfull err] ");
|
|
}
|
|
|
|
if (CommErr) {
|
|
DEBUG_PRINT( "\n" );
|
|
}
|
|
#if 0
|
|
}
|
|
#endif
|
|
|
|
|
|
//
|
|
// Reset trigger
|
|
//
|
|
|
|
WaitCommEvent (DmKdComPort, &DmKdComEvent, &EventOverlapped);
|
|
}
|