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
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;
|
|
|
|
}
|
|
|