📄 mdd.c
字号:
}
return(TRUE);
}
// ****************************************************************
//
// @doc EXTERNAL
// @func HANDLE | COM_INIT | Serial device initialization.
//
// @parm ULONG | Identifier | Port identifier. The device loader
// passes in the registry key that contains information
// about the active device.
//
// @remark This routine is called at device load time in order
// to perform any initialization. Typically the init
// routine does as little as possible, postponing memory
// allocation and device power-on to Open time.
//
// @rdesc Returns a pointer to the serial head which is passed into
// the COM_OPEN and COM_DEINIT entry points as a device handle.
//
HANDLE
COM_Init(
ULONG Identifier
)
{
PVOID pHWHead = NULL;
PHW_INDEP_INFO pSerialHead = NULL;
ULONG HWBufferSize;
DWORD DevIndex;
HKEY hKey;
ULONG kreserved = 0, kvaluetype;
ULONG datasize = sizeof(ULONG);
/*
* INTERNAL: this routine initializes the hardware abstraction interface
* via HWInit(). It allocates a data structure representing this
* instantiation of the device. It also creates an event and initializes
* a critical section for receiving as well as registering the logical
* interrupt dwIntID with NK via InterruptInitialize. This call
* requires that the hardware dependent portion export apis that return
* the physical address of the receive buffer and the size of that buffer.
* Finally, it creates a buffer to act as an intermediate
* buffer when receiving.
*/
DEBUGMSG (ZONE_INIT | ZONE_FUNCTION, (TEXT("+COM_Init\r\n")));
// Allocate our control structure.
pSerialHead = (PHW_INDEP_INFO)LocalAlloc(LPTR, sizeof(HW_INDEP_INFO));
// Check that LocalAlloc did stuff ok too.
if ( !pSerialHead ) {
DEBUGMSG(ZONE_INIT | ZONE_ERROR,
(TEXT("Error allocating memory for pSerialHead, COM_Init failed\n\r")));
return(NULL);
}
// Initially, open list is empty.
InitializeListHead( &pSerialHead->OpenList );
InitializeCriticalSection(&(pSerialHead->OpenCS));
pSerialHead->pAccessOwner = NULL;
pSerialHead->fEventMask = 0;
// Init CommTimeouts.
pSerialHead->CommTimeouts.ReadIntervalTimeout = READ_TIMEOUT;
pSerialHead->CommTimeouts.ReadTotalTimeoutMultiplier =
READ_TIMEOUT_MULTIPLIER;
pSerialHead->CommTimeouts.ReadTotalTimeoutConstant =
READ_TIMEOUT_CONSTANT;
pSerialHead->CommTimeouts.WriteTotalTimeoutMultiplier= 0;
pSerialHead->CommTimeouts.WriteTotalTimeoutConstant = 0;
/* Create tx and rx events and stash in global struct field. Check return.
*/
pSerialHead->hSerialEvent = CreateEvent(0,FALSE,FALSE,NULL);
pSerialHead->hKillDispatchThread = CreateEvent(0, FALSE, FALSE, NULL);
pSerialHead->hTransmitEvent = CreateEvent(0, FALSE, FALSE, NULL);
pSerialHead->hReadEvent = CreateEvent(0, FALSE, FALSE, NULL);
if ( !pSerialHead->hSerialEvent || !pSerialHead->hKillDispatchThread ||
!pSerialHead->hTransmitEvent || !pSerialHead->hReadEvent ) {
DEBUGMSG(ZONE_ERROR | ZONE_INIT,
(TEXT("Error creating event, COM_Init failed\n\r")));
LocalFree(pSerialHead);
return(NULL);
}
/* Initialize the critical sections that will guard the parts of
* the receive and transmit buffers.
*/
InitializeCriticalSection(&(pSerialHead->ReceiveCritSec1));
InitializeCriticalSection(&(pSerialHead->TransmitCritSec1));
/* Want to use the Identifier to do RegOpenKey and RegQueryValue (?)
* to get the index to be passed to GetHWObj.
* The HWObj will also have a flag denoting whether to start the
* listening thread or provide the callback.
*/
DEBUGMSG (ZONE_INIT,(TEXT("Try to open %s\r\n"), (LPCTSTR)Identifier));
hKey = OpenDeviceKey((LPCTSTR)Identifier);
if ( !hKey ) {
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Failed to open devkeypath, COM_Init failed\r\n")));
LocalFree(pSerialHead);
return(NULL);
}
datasize = sizeof(DWORD);
if ( RegQueryValueEx(hKey, L"DeviceArrayIndex", NULL, &kvaluetype,
(LPBYTE)&DevIndex, &datasize) ) {
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Failed to get DeviceArrayIndex value, COM_Init failed\r\n")));
RegCloseKey (hKey);
LocalFree(pSerialHead);
return(NULL);
}
datasize = sizeof(DWORD);
if ( RegQueryValueEx(hKey, L"Priority256", NULL, &kvaluetype,
(LPBYTE)&pSerialHead->Priority256, &datasize) ) {
pSerialHead->Priority256 = DEFAULT_CE_THREAD_PRIORITY;
DEBUGMSG (ZONE_INIT | ZONE_WARN,
(TEXT("Failed to get Priority256 value, defaulting to %d\r\n"), pSerialHead->Priority256));
}
RegCloseKey (hKey);
DEBUGMSG (ZONE_INIT,
(TEXT("DevIndex %X\r\n"), DevIndex));
// Initialize hardware dependent data.
pSerialHead->pHWObj = GetSerialObject( DevIndex );
if ( !pSerialHead->pHWObj ) {
DEBUGMSG(ZONE_ERROR | ZONE_INIT,
(TEXT("Error in GetSerialObject, COM_Init failed\n\r")));
LocalFree(pSerialHead);
return(NULL);
}
DEBUGMSG (ZONE_INIT, (TEXT("About to call HWInit(%s,0x%X)\r\n"),
Identifier, pSerialHead));
pHWHead = pSerialHead->pHWObj->pFuncTbl->HWInit(Identifier, pSerialHead, pSerialHead->pHWObj);
pSerialHead->pHWHead = pHWHead;
/* Check that HWInit did stuff ok. From here on out, call Deinit function
* when things fail.
*/
if ( !pHWHead ) {
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Hardware doesn't init correctly, COM_Init failed\r\n")));
COM_Deinit(pSerialHead);
return(NULL);
}
DEBUGMSG (ZONE_INIT,
(TEXT("Back from hardware init\r\n")));
// Allocate at least twice the hardware buffer size so we have headroom
HWBufferSize = 2 * pSerialHead->pHWObj->pFuncTbl->HWGetRxBufferSize(pHWHead);
// Init rx buffer and buffer length here.
pSerialHead->RxBufferInfo.Length =
HWBufferSize > RX_BUFFER_SIZE ? HWBufferSize:RX_BUFFER_SIZE;
pSerialHead->RxBufferInfo.RxCharBuffer =
LocalAlloc(LPTR, pSerialHead->RxBufferInfo.Length);
if ( !pSerialHead->RxBufferInfo.RxCharBuffer ) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("Error allocating receive buffer, COM_Init failed\n\r")));
COM_Deinit(pSerialHead);
return(NULL);
}
DEBUGMSG (ZONE_INIT, (TEXT("RxHead init'ed\r\n")));
RxResetFifo(pSerialHead);
InitializeCriticalSection(&(pSerialHead->RxBufferInfo.CS));
InitializeCriticalSection(&(pSerialHead->TxBufferInfo.CS));
DEBUGMSG (ZONE_INIT, (TEXT("RxBuffer init'ed with start at %x\r\n"),
pSerialHead->RxBufferInfo.RxCharBuffer));
if ( pSerialHead->pHWObj->BindFlags & THREAD_AT_INIT ) {
// Hook the interrupt and start the associated thread.
if ( ! StartDispatchThread( pSerialHead ) ) {
// Failed on InterruptInitialize or CreateThread. Bail.
COM_Deinit(pSerialHead);
return(NULL);
}
}
// OK, now that everything is ready on our end, give the PDD
// one last chance to init interrupts, etc.
(void) pSerialHead->pHWObj->pFuncTbl->HWPostInit( pHWHead );
DEBUGMSG (ZONE_INIT | ZONE_FUNCTION, (TEXT("-COM_Init\r\n")));
return(pSerialHead);
}
/*
@doc EXTERNAL
@func HANDLE | COM_Open | Serial port driver initialization.
* Description: This routine must be called by the user to open the
* serial device. The HANDLE returned must be used by the application in
* all subsequent calls to the serial driver. This routine starts the thread
* which handles the serial events.
* Exported to users.
*
@rdesc This routine returns a HANDLE representing the device.
*/
HANDLE
COM_Open(
HANDLE pHead, // @parm Handle returned by COM_Init.
DWORD AccessCode, // @parm access code.
DWORD ShareMode // @parm share mode - Not used in this driver.
)
{
PHW_INDEP_INFO pSerialHead = (PHW_INDEP_INFO)pHead;
PHW_OPEN_INFO pOpenHead;
PHWOBJ pHWObj = pSerialHead->pHWObj;
DEBUGMSG (ZONE_OPEN|ZONE_FUNCTION, (TEXT("+COM_Open handle x%X, access x%X, share x%X\r\n"),
pHead, AccessCode, ShareMode));
// Return NULL if SerialInit failed.
if ( !pSerialHead ) {
DEBUGMSG (ZONE_OPEN|ZONE_ERROR,
(TEXT("Open attempted on uninited device!\r\n")));
SetLastError(ERROR_INVALID_HANDLE);
return(NULL);
}
// Return NULL if opening with access & someone else already has
if ( (AccessCode & (GENERIC_READ | GENERIC_WRITE)) &&
pSerialHead->pAccessOwner ) {
DEBUGMSG (ZONE_OPEN|ZONE_ERROR,
(TEXT("Open requested access %x, handle x%X already has x%X!\r\n"),
AccessCode, pSerialHead->pAccessOwner,
pSerialHead->pAccessOwner->AccessCode));
SetLastError(ERROR_INVALID_ACCESS);
return(NULL);
}
// OK, lets allocate an open structure
pOpenHead = (PHW_OPEN_INFO)LocalAlloc(LPTR, sizeof(HW_OPEN_INFO));
if ( !pOpenHead ) {
DEBUGMSG(ZONE_INIT | ZONE_ERROR,
(TEXT("Error allocating memory for pOpenHead, COM_Open failed\n\r")));
return(NULL);
}
// Init the structure
pOpenHead->pSerialHead = pSerialHead; // pointer back to our parent
pOpenHead->StructUsers = 0;
pOpenHead->AccessCode = AccessCode;
pOpenHead->ShareMode = ShareMode;
pOpenHead->CommEvents.hCommEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
pOpenHead->CommEvents.fEventMask = 0;
pOpenHead->CommEvents.fEventData = 0;
pOpenHead->CommEvents.fAbort = 0;
InitializeCriticalSection(&(pOpenHead->CommEvents.EventCS));
// if we have access permissions, note it in pSerialhead
if ( AccessCode & (GENERIC_READ | GENERIC_WRITE) ) {
DEBUGMSG(ZONE_INIT|ZONE_CLOSE,
(TEXT("COM_Open: Access permission handle granted x%X\n\r"),
pOpenHead));
pSerialHead->pAccessOwner = pOpenHead;
}
// add this open entry to list of open entries.
// Note that we hold the open CS for the duration of the routine since
// all of our state info is in flux during this time. In particular,
// without the CS is would be possible for an open & close to be going on
// simultaneously and have bad things happen like spinning a new event
// thread before the old one was gone, etc.
EnterCriticalSection(&(pSerialHead->OpenCS));
InsertHeadList(&pSerialHead->OpenList,
&pOpenHead->llist);
// If port not yet opened, we need to do some init
if ( ! pSerialHead->OpenCnt ) {
DEBUGMSG(ZONE_INIT|ZONE_OPEN,
(TEXT("COM_Open: First open : Do Init x%X\n\r"),
pOpenHead));
if ( pSerialHead->pHWObj->BindFlags & THREAD_AT_OPEN ) {
DEBUGMSG(ZONE_INIT|ZONE_OPEN,
(TEXT("COM_Open: Starting DispatchThread x%X\n\r"),
pOpenHead));
// Hook the interrupt and start the associated thread.
if ( ! StartDispatchThread( pSerialHead ) ) {
// Failed on InterruptInitialize or CreateThread. Bail.
DEBUGMSG(ZONE_INIT|ZONE_OPEN,
(TEXT("COM_Open: Failed StartDispatchThread x%X\n\r"),
pOpenHead));
goto OpenFail;
}
}
pSerialHead->RxBytes = 0;
pSerialHead->TxBytes = 0;
pSerialHead->TxBytesPending = 0;
pSerialHead->DroppedBytesMDD = 0;
pSerialHead->DroppedBytesPDD = 0;
pSerialHead->DCB.DCBlength = sizeof(DCB);
pSerialHead->DCB.BaudRate = 9600;
pSerialHead->DCB.fBinary = TRUE;
pSerialHead->DCB.fParity = FALSE;
pSerialHead->DCB.fOutxCtsFlow = FALSE;
pSerialHead->DCB.fOutxDsrFlow = FALSE;
// pSerialHead->DCB.fDtrControl = FALSE; //DTR_CONTROL_ENABLE; -by HMSEO
pSerialHead->DCB.fDtrControl = DTR_CONTROL_ENABLE; //-by HMSEO
pSerialHead->DCB.fDsrSensitivity = FALSE;
pSerialHead->DCB.fTXContinueOnXoff = FALSE;
pSerialHead->DCB.fOutX = FALSE;
pSerialHead->DCB.fInX = FALSE;
pSerialHead->DCB.fErrorChar = FALSE; //NOTE: ignored
pSerialHead->DCB.fNull = FALSE; //NOTE: ignored
pSerialHead->DCB.fRtsControl = FALSE; //RTS_CONTROL_ENABLE; -by HMSEO
pSerialHead->DCB.fAbortOnError = FALSE; //NOTE: ignored
pSerialHead->DCB.XonLim = 512;
pSerialHead->DCB.XoffLim = 128;
pSerialHead->DCB.ByteSize = 8;
pSerialHead->DCB.Parity = NOPARITY;
pSerialHead->DCB.StopBits = ONESTOPBIT;
pSerialHead->DCB.XonChar = X_ON_CHAR;
pSerialHead->DCB.XoffChar = X_OFF_CHAR;
pSerialHead->DCB.ErrorChar = ERROR_CHAR;
pSerialHead->DCB.EofChar = E_OF_CHAR;
pSerialHead->DCB.EvtChar = EVENT_CHAR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -