Leaked source code of windows server 2003
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.
 
 
 
 
 
 

705 lines
18 KiB

/*++
Module Name:
openclos.c
Environment:
Kernel mode
Revision History :
--*/
#include "precomp.h"
NTSTATUS
MoxaGetPortPropertyFromRegistry(IN PMOXA_DEVICE_EXTENSION extension)
{
NTSTATUS status;
HANDLE keyHandle;
ULONG data=0,dataLen;
extension->RxFifoTrigger = 3; // for 550C UART
extension->TxFifoAmount = 16; // for 550C UART
extension->PortFlag = 0;
status = IoOpenDeviceRegistryKey(extension->Pdo, PLUGPLAY_REGKEY_DEVICE,
STANDARD_RIGHTS_READ, &keyHandle);
if (!NT_SUCCESS(status)) {
//
// This is a fatal error. If we can't get to our registry key,
// we are sunk.
//
return (status);
}
status = MoxaGetRegistryKeyValue(
keyHandle,
L"DisableFiFo",
sizeof(L"DisableFiFo"),
&data,
sizeof(ULONG),
&dataLen);
if (NT_SUCCESS(status)) {
if (data) {
extension->RxFifoTrigger = 0;
extension->TxFifoAmount = 1;
}
}
MoxaKdPrint(MX_DBG_TRACE,
("TxFifoSize/RxFifoTrig=%x/%x\n", extension->TxFifoAmount ,extension->RxFifoTrigger ));
status = MoxaGetRegistryKeyValue(
keyHandle,
L"TxMode",
sizeof(L"TxMode"),
&data,
sizeof(ULONG),
&dataLen);
if (NT_SUCCESS(status) && data )
extension->PortFlag = NORMAL_TX_MODE;
MoxaKdPrint(MX_DBG_TRACE,
("TxMode=%x/%x\n", extension->PortFlag ,status));
ZwClose(keyHandle);
return (status);
}
NTSTATUS
MoxaCreateOpen(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PMOXA_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
NTSTATUS status;
MoxaKdPrint(MX_DBG_TRACE,("MoxaCreateOpen\n"));
if (IoGetCurrentIrpStackLocation(Irp)->Parameters.Create.Options &
FILE_DIRECTORY_FILE) {
Irp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
Irp->IoStatus.Information = 0;
IoCompleteRequest(
Irp,
IO_NO_INCREMENT
);
MoxaKdPrint(MX_DBG_TRACE,("Is a directory,open failed\n"));
return STATUS_NOT_A_DIRECTORY;
}
if (extension->ControlDevice) {
extension->ErrorWord = 0;
extension->DeviceIsOpened = TRUE;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(
Irp,
IO_NO_INCREMENT
);
return STATUS_SUCCESS;
}
if (!extension->PortExist) {
Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
Irp->IoStatus.Information = 0;
IoCompleteRequest(
Irp,
IO_NO_INCREMENT
);
MoxaKdPrint(MX_DBG_TRACE,("No such device,open failed\n"));
return STATUS_NO_SUCH_DEVICE;
}
if (extension->PNPState != SERIAL_PNP_STARTED) {
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
MoxaKdPrint(MX_DBG_TRACE,("Device is not started,open failed\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Lock out changes to PnP state until we have our open state decided
//
ExAcquireFastMutex(&extension->OpenMutex);
if ((status = MoxaIRPPrologue(Irp, extension)) != STATUS_SUCCESS) {
ExReleaseFastMutex(&extension->OpenMutex);
MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
MoxaKdPrint(MX_DBG_TRACE,("MoxaIRPPrologue status=%x,open failed\n",status));
return status;
}
if (InterlockedIncrement(&extension->OpenCount) != 1) {
ExReleaseFastMutex(&extension->OpenMutex);
InterlockedDecrement(&extension->OpenCount);
Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
MoxaKdPrint(MX_DBG_TRACE,("Open count greater than 1,open failed\n",status));
return STATUS_ACCESS_DENIED;
}
//
// Ok, it looks like we really are going to open. Lock down the
// driver.
//
// MoxaLockPagableSectionByHandle(MoxaGlobalsData->PAGESER_Handle);
//
// Retreive the properties of port
//
MoxaGetPortPropertyFromRegistry(extension);
//
// Power up the stack
//
// (void)MoxaGotoPowerState(DeviceObject, extension, PowerDeviceD0);
if ((extension->PowerState != PowerDeviceD0)||
(MoxaGlobalData->BoardReady[extension->BoardNo] == FALSE)) {
MoxaKdPrint(MX_DBG_TRACE,("Board is not ready,open failed\n"));
ExReleaseFastMutex(&extension->OpenMutex);
InterlockedDecrement(&extension->OpenCount);
Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
return STATUS_ACCESS_DENIED;
}
MoxaKdPrint(MX_DBG_TRACE,("Device Opened,TxFiFo=%d,RxFiFo=%d,PortFlag=%x\n",
extension->TxFifoAmount,extension->RxFifoTrigger,extension->PortFlag));
//
// Not currently waiting for wake up
//
extension->SendWaitWake = FALSE;
extension->HandFlow.XoffLimit = extension->RxBufferSize >> 3;
extension->HandFlow.XonLimit = extension->RxBufferSize >> 1;
extension->BufferSizePt8 = ((3*(extension->RxBufferSize>>2))+
(extension->RxBufferSize>>4));
extension->WriteLength = 0;
extension->ReadLength = 0;
extension->TotalCharsQueued = 0;
extension->IrpMaskLocation = NULL;
extension->HistoryMask = 0;
extension->IsrWaitMask = 0;
extension->WmiCommData.XoffXmitThreshold = extension->HandFlow.XoffLimit;
extension->WmiCommData.XonXmitThreshold = extension->HandFlow.XonLimit;
//
// Clear out the statistics.
//
KeSynchronizeExecution(
extension->Interrupt,
MoxaClearStats,
extension
);
extension->EscapeChar = 0;
extension->ErrorWord = 0;
MoxaReset(extension);
MoxaFuncWithLock(extension, FC_SetTxFIFOCnt, extension->TxFifoAmount);
MoxaFuncWithLock(extension, FC_SetRxFIFOTrig,extension->RxFifoTrigger);
MoxaFuncWithLock(extension, FC_EnableCH, Magic_code);
/* 6-1-1998 by William */
/* 4-26-99 by William */
MoxaFuncWithLock(extension, FC_SetLineIrq,Magic_code);
/* 5-31-1998 by William
MoxaFuncWithLock(extension, FC_GetAll, 0);
extension->ModemStatus = *(PUSHORT)(extension->PortOfs + FuncArg + 2);
*/
extension->ModemStatus = *(PUSHORT)(extension->PortOfs + FlagStat) >> 4;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0L;
extension->DeviceIsOpened = TRUE;
//
// Mark the device as busy for WMI
//
extension->WmiCommData.IsBusy = TRUE;
//
// 7-20-01 by William
//
MoxaAddTimeOutProc(extension);
ExReleaseFastMutex(&extension->OpenMutex);
MoxaCompleteRequest(
extension,
Irp,
IO_NO_INCREMENT
);
return STATUS_SUCCESS;
}
VOID
MoxaReset(
IN PMOXA_DEVICE_EXTENSION Extension
)
{
SHORT divisor;
PUCHAR ofs;
MOXA_IOCTL_SYNC S;
ofs = Extension->PortOfs;
MoxaKdPrint (MX_DBG_TRACE, ("Enter MoxaReset\n"));
MoxaFuncWithLock(Extension, FC_ChannelReset, Magic_code);
MoxaFuncWithLock(Extension, FC_SetDataMode, Extension->DataMode);
MoxaGetDivisorFromBaud(
Extension->ClockType,
Extension->CurrentBaud,
&divisor
);
MoxaFuncWithLock(Extension, FC_SetBaud, divisor);
S.Extension = Extension;
S.Data = &Extension->HandFlow;
MoxaSetupNewHandFlow(
&S
);
*(PUSHORT)(ofs + Tx_trigger) = (USHORT)MoxaTxLowWater;
}
NTSTATUS
MoxaClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PMOXA_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
LARGE_INTEGER allSentDelay;
LARGE_INTEGER charTime;
PUCHAR ofs;
LONG count,count1;
ULONG openCount,pendingDPCs;
NTSTATUS status;
// MoxaKdPrint(MX_DBG_TRACE,("%ws,Closing ...\n",extension->DosName));
if (extension->ControlDevice) {
MoxaKdPrint(MX_DBG_TRACE,("Control Device Closed\n"));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information=0L;
extension->DeviceIsOpened = FALSE;
IoCompleteRequest(
Irp,
IO_NO_INCREMENT
);
return STATUS_SUCCESS;
}
//
// Grab a mutex
//
ExAcquireFastMutex(&extension->CloseMutex);
//
// We succeed a close on a removing device
//
//
// 7-20-01 by William
//
MoxaDelTimeOutProc(extension);
if ((status = MoxaIRPPrologue(Irp, extension)) != STATUS_SUCCESS) {
MoxaKdPrint (MX_DBG_ERROR,("Close prologue failed for: %x\n",Irp));
if (status == STATUS_DELETE_PENDING) {
status = Irp->IoStatus.Status = STATUS_SUCCESS;
}
MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
openCount = InterlockedDecrement(&extension->OpenCount);
// ASSERT(openCount == 0);
ExReleaseFastMutex(&extension->CloseMutex);
return status;
}
//ASSERT(extension->OpenCount == 1);
if (extension->OpenCount != 1) {
MoxaKdPrint (MX_DBG_ERROR,("Close open count bad for: 0x%x\n",Irp));
MoxaKdPrint (MX_DBG_ERROR,("------: Count: %x Addr: 0x%x\n",
extension->OpenCount, &extension->OpenCount));
ExReleaseFastMutex(&extension->CloseMutex);
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
return STATUS_INVALID_DEVICE_REQUEST;
}
charTime = RtlLargeIntegerNegate(MoxaGetCharTime(extension));
extension->DeviceIsOpened = FALSE;
//
// Mark device as not busy for WMI
//
extension->WmiCommData.IsBusy = FALSE;
ofs = extension->PortOfs;
if (extension->SendBreak) {
MoxaFuncWithLock(extension, FC_StopBreak, Magic_code);
extension->SendBreak = FALSE;
}
if (*(ofs + FlagStat) & Rx_xoff)
MoxaFuncWithLock(extension, FC_SendXon, 0);
/* 7-21-99 by William
count = GetDeviceTxQueueWithLock(extension);
count += extension->TotalCharsQueued;
//
// Wait data all sent
//
count += 10;
allSentDelay = RtlExtendedIntegerMultiply(
charTime,
count
);
KeDelayExecutionThread(
KernelMode,
TRUE,
&allSentDelay
);
*/
//
// Wait data all sent
//
count1 = 0;
while (TRUE) {
count = GetDeviceTxQueueWithLock(extension);
count += extension->TotalCharsQueued;
if (count == count1)
break;
else
count1 = count;
allSentDelay = RtlExtendedIntegerMultiply(
charTime,
count + 10
);
KeDelayExecutionThread(
KernelMode,
TRUE,
&allSentDelay
);
}
MoxaFuncWithLock(extension, FC_SetFlowCtl, 0);
MoxaFuncWithLock(extension, FC_DTRcontrol, 0); /* clear DTR */
MoxaFuncWithLock(extension, FC_RTScontrol, 0); /* clear RTS */
MoxaFuncWithLock(extension, FC_ClrLineIrq, Magic_code);
MoxaFlagBit[extension->PortNo] &= 0xFC;
*(PUSHORT)(ofs + HostStat) = 0;
MoxaFuncWithLock(extension, FC_DisableCH, Magic_code);
//
// Stop waiting for wakeup
//
extension->SendWaitWake = FALSE;
if (extension->PendingWakeIrp != NULL) {
IoCancelIrp(extension->PendingWakeIrp);
}
//
// Power down our device stack
//
// (void)MoxaGotoPowerState(DeviceObject, extension, PowerDeviceD3);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information=0L;
MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
//
// Unlock the pages. If this is the last reference to the section
// then the driver code will be flushed out.
//
//
// First, we have to let the DPC's drain. No more should be queued
// since we aren't taking interrupts now....
//
pendingDPCs = InterlockedDecrement(&extension->DpcCount);
if (pendingDPCs) {
MoxaKdPrint(MX_DBG_TRACE,("DpcCount = %d\n",extension->DpcCount));
MoxaKdPrint(MX_DBG_TRACE,("Drainging DPC's: %x\n",Irp));
KeWaitForSingleObject(&extension->PendingDpcEvent, Executive,
KernelMode, FALSE, NULL);
}
//
// Pages must be locked to release the mutex, so don't unlock
// them until after we release the mutex
//
ExReleaseFastMutex(&extension->CloseMutex);
//
// Reset for next open
//
InterlockedIncrement(&extension->DpcCount);
openCount = InterlockedDecrement(&extension->OpenCount);
//ASSERT(openCount == 0);
// MoxaKdPrint(MX_DBG_TRACE,("%ws,close completed.\n",extension->DosName));
// MoxaUnlockPagableImageSection(MoxaGlobalsData->PAGESER_Handle);
return STATUS_SUCCESS;
}
LARGE_INTEGER
MoxaGetCharTime(
IN PMOXA_DEVICE_EXTENSION Extension
)
{
ULONG dataSize;
ULONG paritySize;
ULONG stopSize;
ULONG charTime;
ULONG bitTime;
if ((Extension->DataMode & MOXA_DATA_MASK)
== MOXA_5_DATA) {
dataSize = 5;
} else if ((Extension->DataMode & MOXA_DATA_MASK)
== MOXA_6_DATA) {
dataSize = 6;
} else if ((Extension->DataMode & MOXA_DATA_MASK)
== MOXA_7_DATA) {
dataSize = 7;
} else if ((Extension->DataMode & MOXA_DATA_MASK)
== MOXA_8_DATA) {
dataSize = 8;
} else {
dataSize = 8;
}
paritySize = 1;
if ((Extension->DataMode & MOXA_PARITY_MASK)
== MOXA_NONE_PARITY) {
paritySize = 0;
}
if (Extension->DataMode & MOXA_STOP_MASK) {
//
// Even if it is 1.5, for sanities sake were going
// to say 2.
//
stopSize = 2;
} else {
stopSize = 1;
}
//
// First we calculate the number of 100 nanosecond intervals
// are in a single bit time (Approximately).
//
bitTime = (10000000+(Extension->CurrentBaud-1))/Extension->CurrentBaud;
charTime = bitTime + ((dataSize+paritySize+stopSize)*bitTime);
return RtlConvertUlongToLargeInteger(charTime);
}
NTSTATUS
MoxaCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PMOXA_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
KIRQL oldIrql;
NTSTATUS status;
if ((!extension->ControlDevice)&&(extension->DeviceIsOpened == TRUE)) {
//
// We succeed a cleanup on a removing device
//
if ((status = MoxaIRPPrologue(Irp, extension)) != STATUS_SUCCESS) {
if (status == STATUS_DELETE_PENDING) {
status = Irp->IoStatus.Status = STATUS_SUCCESS;
}
MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
return status;
}
//
// First kill all the reads and writes.
//
MoxaKillAllReadsOrWrites(
DeviceObject,
&extension->WriteQueue,
&extension->CurrentWriteIrp
);
MoxaKillAllReadsOrWrites(
DeviceObject,
&extension->ReadQueue,
&extension->CurrentReadIrp
);
//
// Next get rid of purges.
//
MoxaKillAllReadsOrWrites(
DeviceObject,
&extension->PurgeQueue,
&extension->CurrentPurgeIrp
);
//
// Get rid of any mask operations.
//
MoxaKillAllReadsOrWrites(
DeviceObject,
&extension->MaskQueue,
&extension->CurrentMaskIrp
);
//
// Now get rid a pending wait mask irp.
//
IoAcquireCancelSpinLock(&oldIrql);
if (extension->CurrentWaitIrp) {
PDRIVER_CANCEL cancelRoutine;
cancelRoutine = extension->CurrentWaitIrp->CancelRoutine;
extension->CurrentWaitIrp->Cancel = TRUE;
if (cancelRoutine) {
extension->CurrentWaitIrp->CancelIrql = oldIrql;
extension->CurrentWaitIrp->CancelRoutine = NULL;
cancelRoutine(
DeviceObject,
extension->CurrentWaitIrp
);
}
/* 8-30-01 by William */
else
IoReleaseCancelSpinLock(oldIrql);
}
else
IoReleaseCancelSpinLock(oldIrql);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information=0L;
MoxaCompleteRequest(extension, Irp, IO_NO_INCREMENT);
}
else {
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information=0L;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
return STATUS_SUCCESS;
}