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.
632 lines
20 KiB
632 lines
20 KiB
|
|
#include "precomp.h" // Precompiled header
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Title : Specialix Generic Dispatch Functions. */
|
|
/* */
|
|
/* Author : N.P.Vassallo */
|
|
/* */
|
|
/* Creation : 29th September 1998 */
|
|
/* */
|
|
/* Version : 1.0.0 */
|
|
/* */
|
|
/* Description : Dispatch entry points are routed here */
|
|
/* for PnP/Power filtering before being */
|
|
/* passed to the main functions: */
|
|
/* Spx_Flush */
|
|
/* Spx_Write */
|
|
/* Spx_Read */
|
|
/* Spx_IoControl */
|
|
/* Spx_InternalIoControl */
|
|
/* Spx_CreateOpen */
|
|
/* Spx_Close */
|
|
/* Spx_Cleanup */
|
|
/* Spx_QueryInformationFile */
|
|
/* Spx_SetInformationFile */
|
|
/* */
|
|
/* Spx_UnstallIRPs */
|
|
/* Spx_KillStalledIRPs */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
/* History...
|
|
|
|
1.0.0 29/09/98 NPV Creation.
|
|
|
|
*/
|
|
|
|
#define FILE_ID SPX_DISP_C // File ID for Event Logging see SPX_DEFS.H for values.
|
|
|
|
/*****************************************************************************
|
|
******************************* *******************************
|
|
******************************* Prototypes *******************************
|
|
******************************* *******************************
|
|
*****************************************************************************/
|
|
|
|
NTSTATUS Spx_FilterIRPs(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp);
|
|
VOID Spx_FilterCancelQueued(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp);
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
******************************** Spx_Flush *******************************
|
|
*****************************************************************************/
|
|
|
|
NTSTATUS Spx_Flush(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
|
|
{
|
|
pIrp->IoStatus.Status = status;
|
|
|
|
if(status != STATUS_PENDING)
|
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
|
|
if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
|
|
ClearUnstallingFlag(pDevObject->DeviceExtension);
|
|
}
|
|
else
|
|
status = SerialFlush(pDevObject,pIrp);
|
|
|
|
return(status);
|
|
|
|
} // End Spx_Flush
|
|
|
|
/*****************************************************************************
|
|
******************************** Spx_Write *******************************
|
|
*****************************************************************************/
|
|
|
|
NTSTATUS Spx_Write(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
|
|
{
|
|
PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension;
|
|
NTSTATUS status;
|
|
|
|
if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
|
|
{
|
|
pIrp->IoStatus.Status = status;
|
|
|
|
if(status != STATUS_PENDING)
|
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
|
|
if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
|
|
ClearUnstallingFlag(pDevObject->DeviceExtension);
|
|
}
|
|
else
|
|
status = SerialWrite(pDevObject,pIrp);
|
|
|
|
return(status);
|
|
|
|
} // End Spx_Write
|
|
|
|
/*****************************************************************************
|
|
******************************** Spx_Read ********************************
|
|
*****************************************************************************/
|
|
|
|
NTSTATUS Spx_Read(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
|
|
{
|
|
pIrp->IoStatus.Status = status;
|
|
|
|
if(status != STATUS_PENDING)
|
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
|
|
if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
|
|
ClearUnstallingFlag(pDevObject->DeviceExtension);
|
|
}
|
|
else
|
|
status = SerialRead(pDevObject,pIrp);
|
|
|
|
return(status);
|
|
|
|
} // End Spx_Read
|
|
|
|
/*****************************************************************************
|
|
****************************** Spx_IoControl *****************************
|
|
*****************************************************************************/
|
|
|
|
NTSTATUS Spx_IoControl(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
|
|
{
|
|
pIrp->IoStatus.Status = status;
|
|
|
|
if(status != STATUS_PENDING)
|
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
|
|
if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
|
|
ClearUnstallingFlag(pDevObject->DeviceExtension);
|
|
}
|
|
else
|
|
status = SerialIoControl(pDevObject,pIrp);
|
|
|
|
return(status);
|
|
|
|
} // End Spx_IoControl
|
|
|
|
/*****************************************************************************
|
|
************************** Spx_InternalIoControl *************************
|
|
*****************************************************************************/
|
|
|
|
NTSTATUS Spx_InternalIoControl(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
|
|
{
|
|
pIrp->IoStatus.Status = status;
|
|
|
|
if(status != STATUS_PENDING)
|
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
|
|
if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
|
|
ClearUnstallingFlag(pDevObject->DeviceExtension);
|
|
}
|
|
else
|
|
status = Spx_SerialInternalIoControl(pDevObject,pIrp);
|
|
|
|
return(status);
|
|
|
|
} // Spx_InternalIoControl
|
|
|
|
/*****************************************************************************
|
|
***************************** Spx_CreateOpen *****************************
|
|
*****************************************************************************/
|
|
|
|
NTSTATUS Spx_CreateOpen(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
|
|
{
|
|
PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension;
|
|
NTSTATUS status;
|
|
|
|
|
|
if(pDevObject->DeviceType != FILE_DEVICE_SERIAL_PORT)
|
|
{
|
|
pIrp->IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
pIrp->IoStatus.Information = 0;
|
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
return(STATUS_ACCESS_DENIED);
|
|
}
|
|
|
|
|
|
// Lock out state Query stop and Query remove IRPs from changing the state
|
|
// of the port part way through openening the port.
|
|
ExAcquireFastMutex(&pPort->OpenMutex);
|
|
|
|
if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
|
|
{
|
|
pIrp->IoStatus.Status = status;
|
|
|
|
if(status != STATUS_PENDING)
|
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
|
|
if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
|
|
ClearUnstallingFlag(pDevObject->DeviceExtension);
|
|
}
|
|
else
|
|
{
|
|
if(pPort->DeviceIsOpen) // Is port already open?
|
|
{
|
|
status = STATUS_ACCESS_DENIED; // Yes, deny access
|
|
pIrp->IoStatus.Status = status;
|
|
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
|
|
}
|
|
else
|
|
status = SerialCreateOpen(pDevObject,pIrp);
|
|
|
|
}
|
|
|
|
ExReleaseFastMutex(&pPort->OpenMutex);
|
|
|
|
return(status);
|
|
|
|
} // End Spx_CreateOpen
|
|
|
|
/*****************************************************************************
|
|
******************************** Spx_Close *******************************
|
|
*****************************************************************************/
|
|
|
|
NTSTATUS Spx_Close(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
|
|
{
|
|
PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension;
|
|
NTSTATUS status;
|
|
|
|
if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
|
|
{
|
|
if(status == STATUS_DELETE_PENDING) // Successful close if device is removed
|
|
{
|
|
pPort->BufferSize = 0;
|
|
SpxFreeMem(pPort->InterruptReadBuffer);
|
|
pPort->InterruptReadBuffer = NULL;
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
pIrp->IoStatus.Status = status;
|
|
|
|
if(status != STATUS_PENDING)
|
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
|
|
if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
|
|
ClearUnstallingFlag(pDevObject->DeviceExtension);
|
|
}
|
|
else
|
|
status = SerialClose(pDevObject,pIrp);
|
|
|
|
return(status);
|
|
|
|
} // End Spx_Close
|
|
|
|
/*****************************************************************************
|
|
******************************* Spx_Cleanup ******************************
|
|
*****************************************************************************/
|
|
|
|
NTSTATUS Spx_Cleanup(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
|
|
{
|
|
if(status == STATUS_DELETE_PENDING)
|
|
{
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
pIrp->IoStatus.Status = status;
|
|
|
|
if(status != STATUS_PENDING)
|
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
|
|
if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
|
|
ClearUnstallingFlag(pDevObject->DeviceExtension);
|
|
}
|
|
else
|
|
{
|
|
Spx_KillStalledIRPs(pDevObject);
|
|
status = SerialCleanup(pDevObject,pIrp);
|
|
}
|
|
|
|
return(status);
|
|
|
|
} // End Spx_Cleanup
|
|
|
|
/*****************************************************************************
|
|
************************ Spx_QueryInformationFile ************************
|
|
*****************************************************************************/
|
|
|
|
NTSTATUS Spx_QueryInformationFile(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
|
|
{
|
|
pIrp->IoStatus.Status = status;
|
|
|
|
if(status != STATUS_PENDING)
|
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
|
|
if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
|
|
ClearUnstallingFlag(pDevObject->DeviceExtension);
|
|
}
|
|
else status = SerialQueryInformationFile(pDevObject,pIrp);
|
|
|
|
return(status);
|
|
|
|
} // End Spx_QueryInformationFile
|
|
|
|
/*****************************************************************************
|
|
************************* Spx_SetInformationFile *************************
|
|
*****************************************************************************/
|
|
|
|
NTSTATUS Spx_SetInformationFile(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
if(!SPX_SUCCESS(status = Spx_FilterIRPs(pDevObject,pIrp)))
|
|
{
|
|
pIrp->IoStatus.Status = status;
|
|
|
|
if(status != STATUS_PENDING)
|
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
|
|
if((status == STATUS_PENDING) || (status == STATUS_CANCELLED))
|
|
ClearUnstallingFlag(pDevObject->DeviceExtension);
|
|
}
|
|
else
|
|
status = SerialSetInformationFile(pDevObject,pIrp);
|
|
|
|
return(status);
|
|
|
|
} // End Spx_SetInformationFile
|
|
|
|
/*****************************************************************************
|
|
***************************** *****************************
|
|
***************************** Spx_FilterIRPs *****************************
|
|
***************************** *****************************
|
|
******************************************************************************
|
|
|
|
prototype: NTSTATUS Spx_FilterIRPs(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
|
|
|
|
description: Filter incoming SERIAL IRPs (except PNP and POWER) to check
|
|
the current PNP/POWER states and return an NT status code to
|
|
just complete the IRP if device is blocked for the following reasons:
|
|
|
|
parameters: pDevObject points to the device object for this IRP
|
|
pIrp points to the IRP to filter
|
|
|
|
returns: NT Status Code
|
|
|
|
*/
|
|
|
|
NTSTATUS Spx_FilterIRPs(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
|
|
{
|
|
PPORT_DEVICE_EXTENSION pPort = pDevObject->DeviceExtension;
|
|
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
|
|
KIRQL oldIrqlFlags;
|
|
KIRQL StalledOldIrql;
|
|
LARGE_INTEGER delay;
|
|
|
|
if(pIrpStack->MajorFunction == IRP_MJ_PNP) // Don't filter Plug and Play IRPs
|
|
return(STATUS_SUCCESS);
|
|
|
|
if(pIrpStack->MajorFunction == IRP_MJ_POWER) // Don't filter Plug and Play IRPs
|
|
return(STATUS_SUCCESS);
|
|
|
|
if(pIrpStack->MajorFunction == IRP_MJ_SYSTEM_CONTROL) // Don't filter WMI IRPs
|
|
return(STATUS_SUCCESS);
|
|
|
|
|
|
if(pPort->IsFDO) // Don't filter card IRPs
|
|
return(STATUS_SUCCESS);
|
|
|
|
if(pIrpStack->MajorFunction != IRP_MJ_PNP)
|
|
{
|
|
SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_FilterIRPs for Major %02X, Minor %02X\n",
|
|
PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber,pIrpStack->MajorFunction,pIrpStack->MinorFunction));
|
|
}
|
|
|
|
|
|
KeAcquireSpinLock(&pPort->PnpPowerFlagsLock, &oldIrqlFlags);
|
|
|
|
if(pPort->PnpPowerFlags & PPF_REMOVED) // Has this object been "removed"?
|
|
{
|
|
KeReleaseSpinLock(&pPort->PnpPowerFlagsLock,oldIrqlFlags);
|
|
SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_FilterIRPs for Major %02X, Minor %02X STATUS_SUCCESS\n",
|
|
PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber,pIrpStack->MajorFunction,pIrpStack->MinorFunction));
|
|
|
|
return(STATUS_NO_SUCH_DEVICE);
|
|
}
|
|
|
|
if(pPort->PnpPowerFlags & PPF_REMOVE_PENDING) // Removing the device?
|
|
{
|
|
KeReleaseSpinLock(&pPort->PnpPowerFlagsLock,oldIrqlFlags);
|
|
SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_FilterIRPs for Major %02X, Minor %02X STATUS_DELETE_PENDING\n",
|
|
PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber,pIrpStack->MajorFunction,pIrpStack->MinorFunction));
|
|
|
|
return(STATUS_DELETE_PENDING);
|
|
}
|
|
|
|
|
|
if((pPort->PnpPowerFlags & PPF_STOP_PENDING) // Device stopping?
|
|
||(!(pPort->PnpPowerFlags & PPF_POWERED)) // Device not powered?
|
|
||(!(pPort->PnpPowerFlags & PPF_STARTED))) // Device not started?
|
|
{
|
|
KIRQL oldIrql;
|
|
|
|
KeReleaseSpinLock(&pPort->PnpPowerFlagsLock,oldIrqlFlags);
|
|
|
|
|
|
KeAcquireSpinLock(&pPort->StalledIrpLock, &StalledOldIrql);
|
|
|
|
while(pPort->UnstallingFlag) // We do not wish to add any more IRPs to the queue if have started unstalling those currently queued.
|
|
{
|
|
KeReleaseSpinLock(&pPort->StalledIrpLock, StalledOldIrql);
|
|
|
|
delay = RtlLargeIntegerNegate(RtlConvertUlongToLargeInteger(1000000)); // 1mS
|
|
|
|
KeDelayExecutionThread(KernelMode, FALSE, &delay);
|
|
|
|
KeAcquireSpinLock(&pPort->StalledIrpLock, &StalledOldIrql);
|
|
}
|
|
|
|
pPort->UnstallingFlag = TRUE;
|
|
|
|
KeReleaseSpinLock(&pPort->StalledIrpLock, StalledOldIrql);
|
|
|
|
|
|
IoAcquireCancelSpinLock(&oldIrql);
|
|
|
|
if(pIrp->Cancel) // Has IRP been cancelled?
|
|
{ // Yes
|
|
IoReleaseCancelSpinLock(oldIrql);
|
|
SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_FilterIRPs for Major %02X, Minor %02X STATUS_CANCELLED\n",
|
|
PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber,pIrpStack->MajorFunction,pIrpStack->MinorFunction));
|
|
|
|
return(STATUS_CANCELLED);
|
|
}
|
|
|
|
// Mark the IRP as pending and queue on the stalled list...
|
|
pIrp->IoStatus.Status = STATUS_PENDING; // Mark IRP as pending
|
|
IoMarkIrpPending(pIrp);
|
|
InsertTailList(&pPort->StalledIrpQueue,&pIrp->Tail.Overlay.ListEntry);
|
|
IoSetCancelRoutine(pIrp,Spx_FilterCancelQueued);
|
|
IoReleaseCancelSpinLock(oldIrql);
|
|
SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_FilterIRPs for Major %02X, Minor %02X STATUS_PENDING\n",
|
|
PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber,pIrpStack->MajorFunction,pIrpStack->MinorFunction));
|
|
|
|
return(STATUS_PENDING);
|
|
}
|
|
|
|
KeReleaseSpinLock(&pPort->PnpPowerFlagsLock,oldIrqlFlags);
|
|
SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_FilterIRPs for Major %02X, Minor %02X STATUS_SUCCESS\n",
|
|
PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber,pIrpStack->MajorFunction,pIrpStack->MinorFunction));
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
} // End Spx_FilterIRPs
|
|
|
|
/*****************************************************************************
|
|
***************************** ****************************
|
|
***************************** Spx_UnstallIRPs ****************************
|
|
***************************** ****************************
|
|
******************************************************************************
|
|
|
|
prototype: VOID Spx_UnstallIrps(IN PPORT_DEVICE_EXTENSION pPort)
|
|
|
|
description: Restart all IRPs stored on the temporary stalled list.
|
|
|
|
parameters: pPort points to the device extension to unstall
|
|
|
|
returns: None
|
|
|
|
*/
|
|
|
|
VOID Spx_UnstallIrps(IN PPORT_DEVICE_EXTENSION pPort)
|
|
{
|
|
PLIST_ENTRY pIrpLink;
|
|
PIRP pIrp;
|
|
PIO_STACK_LOCATION pIrpStack;
|
|
PDEVICE_OBJECT pDevObj;
|
|
PDRIVER_OBJECT pDrvObj;
|
|
KIRQL oldIrql;
|
|
KIRQL StalledOldIrql;
|
|
LARGE_INTEGER delay;
|
|
|
|
SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_UnstallIRPs Entry\n",
|
|
PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber));
|
|
|
|
|
|
KeAcquireSpinLock(&pPort->StalledIrpLock, &StalledOldIrql);
|
|
|
|
while(pPort->UnstallingFlag) // We do not unstall any queued IRPs if some one is just about to be added to the queue.
|
|
{
|
|
KeReleaseSpinLock(&pPort->StalledIrpLock, StalledOldIrql);
|
|
|
|
delay = RtlLargeIntegerNegate(RtlConvertUlongToLargeInteger(1000000)); // 1mS
|
|
|
|
KeDelayExecutionThread(KernelMode, FALSE, &delay);
|
|
|
|
KeAcquireSpinLock(&pPort->StalledIrpLock, &StalledOldIrql);
|
|
}
|
|
|
|
pPort->UnstallingFlag = TRUE;
|
|
|
|
KeReleaseSpinLock(&pPort->StalledIrpLock, StalledOldIrql);
|
|
|
|
|
|
|
|
|
|
|
|
IoAcquireCancelSpinLock(&oldIrql);
|
|
pIrpLink = pPort->StalledIrpQueue.Flink;
|
|
|
|
// Restart each waiting IRP on the stalled list...
|
|
|
|
while(pIrpLink != &pPort->StalledIrpQueue)
|
|
{
|
|
pIrp = CONTAINING_RECORD(pIrpLink,IRP,Tail.Overlay.ListEntry);
|
|
pIrpLink = pIrp->Tail.Overlay.ListEntry.Flink;
|
|
RemoveEntryList(&pIrp->Tail.Overlay.ListEntry);
|
|
|
|
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
|
|
pDevObj = pIrpStack->DeviceObject;
|
|
pDrvObj = pDevObj->DriverObject;
|
|
IoSetCancelRoutine(pIrp,NULL);
|
|
IoReleaseCancelSpinLock(oldIrql);
|
|
|
|
SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Unstalling IRP 0x%X, Major %02X, Minor %02X\n",
|
|
PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber,
|
|
pIrp,pIrpStack->MajorFunction,pIrpStack->MinorFunction));
|
|
|
|
pDrvObj->MajorFunction[pIrpStack->MajorFunction](pDevObj,pIrp);
|
|
IoAcquireCancelSpinLock(&oldIrql);
|
|
}
|
|
|
|
IoReleaseCancelSpinLock(oldIrql);
|
|
|
|
ClearUnstallingFlag(pPort);
|
|
|
|
SpxDbgMsg(SPX_TRACE_FILTER_IRPS,("%s[card=%d,port=%d]: Spx_UnstallIRPs Exit\n",
|
|
PRODUCT_NAME,pPort->pParentCardExt->CardNumber,pPort->PortNumber));
|
|
|
|
} // End Spx_UnstallIRPs
|
|
|
|
/*****************************************************************************
|
|
************************* *************************
|
|
************************* Spx_FilterCancelQueued *************************
|
|
************************* *************************
|
|
******************************************************************************
|
|
|
|
prototype: VOID Spx_FilterCancelQueued(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp)
|
|
|
|
description: Routine to cancel IRPs queued on the stalled list
|
|
|
|
parameters: pDevObj the device object containing the queue
|
|
pIrp points to the IRP to cancel
|
|
|
|
returns: None
|
|
|
|
*/
|
|
|
|
VOID Spx_FilterCancelQueued(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp)
|
|
{
|
|
PPORT_DEVICE_EXTENSION pPort = pDevObj->DeviceExtension;
|
|
PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
|
|
|
|
pIrp->IoStatus.Status = STATUS_CANCELLED;
|
|
pIrp->IoStatus.Information = 0;
|
|
|
|
RemoveEntryList(&pIrp->Tail.Overlay.ListEntry);
|
|
IoReleaseCancelSpinLock(pIrp->CancelIrql);
|
|
|
|
} // End Spx_FilterCancelQueued
|
|
|
|
|
|
/*****************************************************************************
|
|
*************************** **************************
|
|
*************************** Spx_KillStalledIRPs **************************
|
|
*************************** **************************
|
|
******************************************************************************
|
|
|
|
prototype: VOID Spx_KillStalledIRPs(IN PDEVICE_OBJECT pDevObj)
|
|
|
|
description: Kill all IRPs queued on the stalled list
|
|
|
|
parameters: pDevObj the device object containing the queue
|
|
|
|
returns: None
|
|
|
|
*/
|
|
|
|
VOID Spx_KillStalledIRPs(IN PDEVICE_OBJECT pDevObj)
|
|
{
|
|
PPORT_DEVICE_EXTENSION pPort = pDevObj->DeviceExtension;
|
|
PDRIVER_CANCEL cancelRoutine;
|
|
KIRQL cancelIrql;
|
|
|
|
IoAcquireCancelSpinLock(&cancelIrql);
|
|
|
|
// Call the cancel routine of all IRPs queued on the stalled list...
|
|
|
|
while(!IsListEmpty(&pPort->StalledIrpQueue))
|
|
{
|
|
PIRP pIrp = CONTAINING_RECORD(pPort->StalledIrpQueue.Blink, IRP, Tail.Overlay.ListEntry);
|
|
|
|
RemoveEntryList(pPort->StalledIrpQueue.Blink);
|
|
cancelRoutine = pIrp->CancelRoutine; // Get the cancel routine for this IRP
|
|
pIrp->CancelIrql = cancelIrql;
|
|
pIrp->CancelRoutine = NULL;
|
|
pIrp->Cancel = TRUE;
|
|
|
|
cancelRoutine(pDevObj,pIrp); // Call the cancel routine
|
|
|
|
IoAcquireCancelSpinLock(&cancelIrql);
|
|
}
|
|
|
|
IoReleaseCancelSpinLock(cancelIrql);
|
|
|
|
} // End Spx_KillStalledIRPs
|
|
|
|
// End of SPX_DISP.C
|